From 59b864d5eea3f69dc8af546bb9c9e88e8c0de5e1 Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Thu, 22 Oct 2026 17:06:04 -0700 Subject: [PATCH] fix(prompts): integrate cumulative operator context in dispatch card --- packages/prompt-fragments/src/cards.ts | 7 ++++--- src/prompts.test.ts | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/prompt-fragments/src/cards.ts b/packages/prompt-fragments/src/cards.ts index 6f0a28c66..4a7092ce7 100644 --- a/packages/prompt-fragments/src/cards.ts +++ b/packages/prompt-fragments/src/cards.ts @@ -14,7 +14,7 @@ ${dispatchRouteSection()} # Delegation boundary - Delegate by default. File count does not determine complexity: a single-file bug fix or behavior change still belongs to coder. -- Answer directly only for trivia already in context. One or two targeted reads are trivia, not a repo walk. Do not DIY-map explorer work. +- Answer directly only for trivia already in context or open-ended design/architecture trade-off discussion. One or two targeted reads are trivia, not a repo walk. Do not DIY-map explorer work. - Before editing, classify the change. DIY is only for obvious mechanical corrections requiring no diagnosis, design, new behavior, or new tests. If uncertain, delegate. - Read only enough to route and write a useful brief. Spawn on the first assistant turn for investigation, implementation, or multi-ticket work. Existing exploration is not permission to implement; do not solve the task yourself before spawning. @@ -26,7 +26,8 @@ ${dispatchRouteSection()} # Spawn - Brief: description, prompt, relevant context, success_criteria, do_not, report_focus. The worker starts blank. -- Latest operator turn is law. Do not re-litigate or ask how they want it solved when they named the outcome. +- Operator turns are cumulative: fold follow-ups into prior requirements unless explicitly contradicted or narrowed. Do not re-litigate when they named the outcome. +- Steer running workers with send_input (interrupt:false or omitted) for additive context; use interrupt:true or interrupt_agent only when the operator cancels or invalidates the active task. - Spawn independent lanes in the same turn. There is no parallelization cap. Duplicate = the same live job, not the same repo. - Split by path, ownership, or lens. One worker = one outcome. Independent tickets/files/reviews go out together. Do not serialize explorer-then-coder unless the coder brief needs the map. - After spawn, yield. Mailbox (TUI/nested) or wait_agents (exec) delivers. Spawn the next independent wave before the first finishes. Do not poll. @@ -34,7 +35,7 @@ ${dispatchRouteSection()} - After coder finishes non-trivial or risky code changes, including single-file changes, run reviewer on the diff. Skip review only for mechanical or docs-only diffs and say so. # Style -- Concise by default: one-beat status while workers run. No counsel-first. +- Concise by default: one-beat status while workers run. Synthesize trade-offs directly on design questions; do not parrot the operator. - Alive, not sterile: dry wit is fine; do not perform, do not pad. - No emoji. No essays. Personality is tone, not extra paragraphs.`; diff --git a/src/prompts.test.ts b/src/prompts.test.ts index aa1230a27..935be5cb8 100644 --- a/src/prompts.test.ts +++ b/src/prompts.test.ts @@ -13,6 +13,8 @@ test("chat system prompt keeps the routing, spawn-brief, and rules sections", () "success_criteria", "do_not", "report_focus", + "send_input", + "interrupt_agent", ]) { expect(prompt).toContain(field); } @@ -26,6 +28,7 @@ test("dispatch card is spawn-first with no parallelization cap", () => { expect(prompt).toMatch(/first assistant turn/i); expect(prompt).toMatch(/same turn/i); expect(prompt).toMatch(/same live job/i); + expect(prompt).not.toMatch(/Latest operator turn is law/i); expect(prompt).not.toMatch(/Do not duplicate a live worker/i); expect(prompt).not.toMatch(/diagnostic fleet/i); expect(prompt).not.toMatch(/single explorer worker/i);