From 67658fb71770291f43637505a9487711fabbd060 Mon Sep 17 00:00:00 2001 From: Lukas May Date: Fri, 6 Mar 2026 15:35:11 +0100 Subject: [PATCH] fix: require signal.json for all errand agent exit scenarios Option A ("ask inline, session stays open") described a path where the errand agent could ask questions without writing signal.json, which broke the server's completion detection (checkAgentCompletionResult polls for done|questions|error status). Remove the Option A/B distinction and make signal.json with questions status the single mechanism for all user-input requests, consistent with how other agents handle blocking questions. Co-Authored-By: Claude Sonnet 4.6 --- apps/server/agent/file-io.test.ts | 15 +++++++++++++++ apps/server/agent/prompts/errand.ts | 18 +++++------------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/apps/server/agent/file-io.test.ts b/apps/server/agent/file-io.test.ts index 321ff8a..0e747fa 100644 --- a/apps/server/agent/file-io.test.ts +++ b/apps/server/agent/file-io.test.ts @@ -498,4 +498,19 @@ describe('buildErrandPrompt', () => { const result = buildErrandPrompt('some change'); expect(result).toMatch(/resume|end.*session|session.*end/i); }); + + it('does not present inline asking as an alternative that bypasses signal.json', () => { + const result = buildErrandPrompt('some change'); + // "session stays open" implied agents can skip signal.json — all exits must write it + expect(result).not.toMatch(/session stays open/i); + expect(result).not.toMatch(/Option A/i); + }); + + it('requires signal.json for all question-asking paths', () => { + const result = buildErrandPrompt('some change'); + // questions status must be the mechanism for all user-input requests + expect(result).toContain('"status": "questions"'); + // must not describe a path that skips signal.json + expect(result).not.toMatch(/session stays open/i); + }); }); diff --git a/apps/server/agent/prompts/errand.ts b/apps/server/agent/prompts/errand.ts index f7f2228..3c2ac91 100644 --- a/apps/server/agent/prompts/errand.ts +++ b/apps/server/agent/prompts/errand.ts @@ -7,23 +7,15 @@ Work interactively with the user. Make only the changes needed to fulfill the de ## Asking questions -### Option A — Ask inline (session stays open) - -Ask the user directly in your response and wait. The user can reply via the UI chat input on the Errands page or by running: - - cw errand chat "" - -Their reply will be delivered as the next message in this session. - -### Option B — End session with questions (then resume) - -If you need answers before you can start, end the session by writing .cw/output/signal.json with this format: +If you need clarification before or during the change, write .cw/output/signal.json with the questions format and end your session: { "status": "questions", "questions": [{ "id": "q1", "question": "What is the target file?" }] } -The session will end. The user will be shown your questions in the UI. When they answer (via UI or cw errand chat), the session resumes and you will receive their answers. Use this when blocking questions need to be resolved before any work can proceed. +The session will end. The user will be shown your questions in the UI or via: -Be explicit about what you need — don't make assumptions when the task is ambiguous. + cw errand chat "" + +Your session will then resume with their answers. Be explicit about what you need — don't make assumptions when the task is ambiguous. ## Finishing