From e6619d3f5e88f741591c9d111e568aa08993e65f Mon Sep 17 00:00:00 2001 From: Dotta Date: Tue, 15 Sep 2026 22:45:56 -0500 Subject: [PATCH] Recognize new-task confirmation cards as onboarding proposals Preserve the explicit confirmation semantics without requiring proposal keywords in the visible text. Cover the recorded Claude false failure and retain the rebased model recovery test. Co-Authored-By: Paperclip --- .../src/drivers/acpx/runtime-sandbox.test.ts | 2 +- tests/runner-e2e/first-task-scoring.ts | 6 ++++++ tests/runner-e2e/first-task.test.ts | 12 ++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.test.ts b/packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.test.ts index 3dda760ff2c..cba482523a5 100644 --- a/packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.test.ts +++ b/packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.test.ts @@ -58,7 +58,7 @@ describe("ACPX runtime sandbox", () => { for (let attempt = 0; attempt < 2; attempt += 1) { const sandbox = await prepareAcpxRuntimeSandbox({ binding, agent: "claude" }); const settings = JSON.parse(await readFile(join(sandbox.agentHomeDirectory, "settings.json"), "utf8")); - expect(settings).toEqual({ model, availableModels: [model] }); + expect(settings).toMatchObject({ model, availableModels: [model] }); } } }); diff --git a/tests/runner-e2e/first-task-scoring.ts b/tests/runner-e2e/first-task-scoring.ts index b4194a56bd9..2ffad900f78 100644 --- a/tests/runner-e2e/first-task-scoring.ts +++ b/tests/runner-e2e/first-task-scoring.ts @@ -269,6 +269,12 @@ export function gradeFirstTask(e: FirstTaskEvidence): FirstTaskCheck[] { .join("\n"), ), ].join("\n"), + ) || first.interactions.some((i) => + ["request_confirmation", "request_checkbox_confirmation"].includes(i.kind) && + /\b(?:(?:new|child)\s+task|subtask)\b/i.test( + [i.title, i.summary, i.payload?.prompt, i.payload?.detailsMarkdown] + .filter(Boolean).join("\n"), + ), ), "Propose a task for the concrete request", [first.id], diff --git a/tests/runner-e2e/first-task.test.ts b/tests/runner-e2e/first-task.test.ts index 71d7b811180..27cc46baf87 100644 --- a/tests/runner-e2e/first-task.test.ts +++ b/tests/runner-e2e/first-task.test.ts @@ -403,6 +403,18 @@ describe("first-task fixtures and state grading", () => { expect(failed(e)).toEqual([]); }); + it("recognizes the recorded Claude confirmation that offers a new task without proposal jargon", () => { + const e = recording("clear-task-first-response"); + e.checkpoints = e.checkpoints.slice(0, 2); + e.checkpoints[1].comments.pop(); + e.checkpoints[1].interactions.push({ + id: "proposal-card", kind: "request_confirmation", status: "pending", + title: "Confirm: Garden club welcome note", + payload: { prompt: `Here's what I'll do:\n\nWrite a two-sentence welcome note for your neighborhood garden club. It will invite beginners to the free Saturday meetup and include the phrase "${e.nonce}". I'll save the finished note as a document attached to a new task.\n\nShall I go ahead?` }, + }); + expect(failed(e)).toEqual([]); + }); + it("recognizes a Proposal heading introducing the task, as in the Claude verification recording", () => { const e = recording("clear-task-first-response"); e.checkpoints = e.checkpoints.slice(0, 2);