test(evals): ignore the reader-only canChangeResponsibleUser flag in the managed-routine prequery check

plugin-managed-routine setup compared the CEO's read of the routine to the
board's read with a deep-equality check. GET /api/routines/:id now adds
canChangeResponsibleUser, which is true for the board and false for an
agent, so setup always failed ("CEO could not independently read the
unchanged selected routine") before the person's message was sent.
Compare the routine without that reader-specific flag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
DottaandClaude Opus 5.5 committed 2026-11-09 00:12:15 -06:00
1 parent 7c7de99480
commit 93381e5141
2 files changed
+13 -1

No files matched your search

@@ -54,3 +54,9 @@ it.each(["foreign-reader", "denied-reader", "changed-routine", "new-run", "wrong
if (kind === "existing-description") c.source.description = "Prior context";
await expect(prepareManagedRoutineContext(c.ctx, r.plugin, r.routine)).rejects.toThrow(); expect(c.evidence).not.toHaveBeenCalled();
});
it("accepts the CEO's read when only the reader-specific canChangeResponsibleUser flag differs", async () => {
const r = resources(), c = context();
const boardRead = { ...r.routine, canChangeResponsibleUser: true } as RoutineDetail;
reads.routine = { ...r.routine, canChangeResponsibleUser: false };
await expect(prepareManagedRoutineContext(c.ctx, r.plugin, boardRead)).resolves.toMatchObject({ ceoRoutineStatus: 200 });
});
@@ -61,6 +61,12 @@ export function managedRoutineContext(companyId: string, issuePrefix: string, pl
plugin: { id: plugin.id, key: plugin.manifestJson.id, name: plugin.manifestJson.displayName, url: `/${issuePrefix}/plugins/${plugin.id}` },
}, null, 2)}`;
}
/** The routine as every viewer sees it: `canChangeResponsibleUser` answers for
* the reader (true for the board, false for an agent), not for the routine. */
export function viewerIndependentRoutine(routine: RoutineDetail) {
const { canChangeResponsibleUser: _viewer, ...rest } = routine as RoutineDetail & { canChangeResponsibleUser?: unknown };
return rest;
}
export async function prepareManagedRoutineContext(ctx: ChatCatalogContext, plugin: PluginRecord, routine: RoutineDetail) {
const company = ctx.input.fixtures.company;
const prefix = company.issuePrefix;
@@ -82,7 +88,7 @@ export async function prepareManagedRoutineContext(ctx: ChatCatalogContext, plug
if (visibleSource.status !== 200 || readSource?.id !== source.id || readSource.companyId !== company.id
|| readSource.assigneeAgentId !== ctx.input.fixtures.agent.id || readSource.description !== description
|| visibleRoutine.status !== 200 || !readRoutine || managedRoutineContext(company.id, prefix, plugin, readRoutine) !== description
|| !isDeepStrictEqual(readRoutine, routine)
|| !isDeepStrictEqual(viewerIndependentRoutine(readRoutine), viewerIndependentRoutine(routine))
|| (await comments()).length !== 0 || (await ctx.allRuns()).length !== 0) {
throw new Error("CEO could not independently read the unchanged selected routine and source context before work");
}