diff --git a/tests/runner-e2e/chat-catalog-descriptors.json b/tests/runner-e2e/chat-catalog-descriptors.json index d916535e351..148764768e3 100644 --- a/tests/runner-e2e/chat-catalog-descriptors.json +++ b/tests/runner-e2e/chat-catalog-descriptors.json @@ -5376,7 +5376,7 @@ "chat-catalog-domains/integrator-support.ts", "chat-scenarios/status-cards.yaml" ], - "oracleVersion": "paperclip.chat-catalog.status-card.required-work-failure.v3", + "oracleVersion": "paperclip.chat-catalog.status-card.required-work-failure.v4", "expectedRunCount": 7, "expectedHumanMessageCount": 4, "turnTimeoutMs": 120000, diff --git a/tests/runner-e2e/chat-catalog-domains/integrator-status-cards.test.ts b/tests/runner-e2e/chat-catalog-domains/integrator-status-cards.test.ts index 4c373626f43..ea7f64330f2 100644 --- a/tests/runner-e2e/chat-catalog-domains/integrator-status-cards.test.ts +++ b/tests/runner-e2e/chat-catalog-domains/integrator-status-cards.test.ts @@ -219,6 +219,11 @@ it("makes the genuine new blocker visible in the public task title used by bound expect(update).not.toHaveProperty("status"); // No task/card/native status fabricated. expect(JSON.stringify(update)).not.toMatch(/summari[sz]e|write|return|tool|generationIssueId|model/i); }); +it("allows the refresh lead one run per human message, as the four-turn case requires", async () => { + const { REFRESH_CARD_LEAD_TURNS } = await import("./integrator-status-cards.js"); + const definition = integratorStatusCardsCases.find(row => row.scenarioId === "status-cards.refresh-card")!; + expect(REFRESH_CARD_LEAD_TURNS).toBe(definition.expectedHumanMessageCount); +}); it("declares factual human attachments only for the two actual missing selected referents", () => { for (const id of ["status-cards.explain-card", "status-cards.archive-card"]) { const definition = integratorStatusCardsCases.find(row => row.scenarioId === id)!; diff --git a/tests/runner-e2e/chat-catalog-domains/integrator-status-cards.ts b/tests/runner-e2e/chat-catalog-domains/integrator-status-cards.ts index 1a38fdcea8d..79afe575588 100644 --- a/tests/runner-e2e/chat-catalog-domains/integrator-status-cards.ts +++ b/tests/runner-e2e/chat-catalog-domains/integrator-status-cards.ts @@ -229,6 +229,14 @@ export function selectedStatusCardReference(card: StatusCard, sources: Entity[], export function refreshedBlockerTaskInput() { return { title: "Mobile Safari checkout regression blocks launch", description: "Payment approval has been received. The remaining blocker is the mobile Safari checkout regression." }; } +/** refresh-card asks four questions, so its lead needs four runs; the shared chat fixture allows three a day. */ +export const REFRESH_CARD_LEAD_TURNS = 4; +async function allowLeadTurns(ctx: ChatCatalogContext, turns: number) { + const leadPath = `/api/agents/${ctx.input.fixtures.agent.id}`; + const lead = await ctx.input.api.get<{ runtimeConfig: { heartbeat?: Record; [key: string]: unknown } }>(leadPath); + await ctx.input.api.patch(leadPath, { runtimeConfig: { ...lead.runtimeConfig, heartbeat: { ...lead.runtimeConfig.heartbeat, maxDailyRuns: turns } } }); + if ((await ctx.input.api.get(leadPath)).runtimeConfig.heartbeat?.maxDailyRuns !== turns) throw new Error(`Card fixture requires its declared ${turns}-turn daily lead allowance`); +} const experiments = new WeakMap(); function define(id: string, seed: "none" | "ceo" | "morgan", extra: Partial = {}): ChatCatalogCase { return integratorDefinition("status-cards", id, async ctx => { @@ -242,6 +250,7 @@ function define(id: string, seed: "none" | "ceo" | "morgan", extra: Partial