From 93381e5141559e9f4fb2d0e902b4a4b136ea1412 Mon Sep 17 00:00:00 2001 From: Dotta Date: Sun, 8 Nov 2026 23:11:48 -0600 Subject: [PATCH] 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 --- .../integrator-plugin-routine-context.test.ts | 6 ++++++ .../chat-catalog-domains/integrator-plugin-routine.ts | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/runner-e2e/chat-catalog-domains/integrator-plugin-routine-context.test.ts b/tests/runner-e2e/chat-catalog-domains/integrator-plugin-routine-context.test.ts index 69585c27310..d28c617b51c 100644 --- a/tests/runner-e2e/chat-catalog-domains/integrator-plugin-routine-context.test.ts +++ b/tests/runner-e2e/chat-catalog-domains/integrator-plugin-routine-context.test.ts @@ -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 }); +}); diff --git a/tests/runner-e2e/chat-catalog-domains/integrator-plugin-routine.ts b/tests/runner-e2e/chat-catalog-domains/integrator-plugin-routine.ts index 63bd3648b1f..59c79e129f2 100644 --- a/tests/runner-e2e/chat-catalog-domains/integrator-plugin-routine.ts +++ b/tests/runner-e2e/chat-catalog-domains/integrator-plugin-routine.ts @@ -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"); }