diff --git a/tests/runner-e2e/catalog.test.ts b/tests/runner-e2e/catalog.test.ts index 25c099a2e35..ccf44672e71 100644 --- a/tests/runner-e2e/catalog.test.ts +++ b/tests/runner-e2e/catalog.test.ts @@ -64,6 +64,38 @@ describe("runner E2E catalog", () => { } }); + it("gives legacy planning agents a direct bounded API recipe", () => { + const task = runnerTasks.find( + (candidate) => candidate.id === "plan-revise-accept", + ); + const execution = runnerMatrix.find( + (candidate) => + candidate.profile.id === "legacy-claude" && + candidate.environment.id === "local" && + candidate.task.id === "plan-revise-accept", + ); + expect(task).toBeDefined(); + expect(execution).toBeDefined(); + const agent = execution!.profile.buildAgent({ + environmentId: "11111111-1111-4111-8111-111111111111", + environmentFixtureId: "local", + workspacePath: "/tmp/runner-e2e-workspace", + secretRefs: { + ANTHROPIC_API_KEY: { + type: "secret_ref", + secretId: "22222222-2222-4222-8222-222222222222", + version: "latest", + }, + }, + executionId: execution!.id, + }); + expect(agent.adapterConfig).toMatchObject({ maxTurnsPerRun: 24 }); + expect(agent.instructionsBundle).toMatchObject({ + files: { "AGENTS.md": expect.stringContaining("/interactions") }, + }); + expect(task!.buildPrompt("nonce")).toContain("request_confirmation"); + }); + it("accepts only complete immutable Daytona digests", () => { expect( isImmutableDaytonaImage( diff --git a/tests/runner-e2e/catalog.ts b/tests/runner-e2e/catalog.ts index 7fcecede623..ea2a1be1d89 100644 --- a/tests/runner-e2e/catalog.ts +++ b/tests/runner-e2e/catalog.ts @@ -58,6 +58,11 @@ function commonAgent( "For planning tasks, publish or revise the canonical Plan document and its revision-bound request_confirmation, then wait. Only implement after that exact plan is accepted.", "Invoke assigned tools only through the runtime's real tool-call channel. Never print XML, DSML, JSON, or other tool-call markup as assistant text.", "Legacy adapters must use the public Paperclip API and the injected PAPERCLIP_API_URL, PAPERCLIP_API_KEY, PAPERCLIP_TASK_ID, and PAPERCLIP_RUN_ID values for comments, documents, interactions, and status changes.", + ...(adapterType === "paperclip_runner" + ? [] + : [ + "For a planning task, do not inspect the OpenAPI schema. PUT /api/issues/$PAPERCLIP_TASK_ID/documents/plan with {title:\"Plan\",format:\"markdown\",body,changeSummary}; read latestRevisionId and latestRevisionNumber from that response. Then POST /api/issues/$PAPERCLIP_TASK_ID/interactions with {kind:\"request_confirmation\",continuationPolicy:\"wake_assignee\",payload:{version:1,prompt,acceptLabel:\"Approve\",rejectLabel:\"Reject\",rejectRequiresReason:true,target:{type:\"issue_document\",key:\"plan\",revisionId,revisionNumber}}}, and PATCH the issue to {status:\"in_review\"}. Include Authorization and X-Paperclip-Run-Id on every write.", + ]), "Never print, persist, or expose credential values, and never create unrelated work.", ].join("\n"), }, @@ -193,7 +198,7 @@ export const runnerProfiles: readonly RunnerProfileFixture[] = [ // canonical Plan document, and request confirmation. Four turns caused // the Claude CLI to terminate correctly but prematurely with // `max_turns_exhausted` during the revision flow. - maxTurnsPerRun: 12, + maxTurnsPerRun: 24, }, }), legacyProfile({