From cdfab9d22e38e7f82f0e17ae4a08b9d0b4fd9e9d Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Tue, 25 Aug 2026 11:17:36 -0700 Subject: [PATCH 1/4] Overhaul Builder prompt for criteria-driven shipping Elevate the implement leaf with a sequential ship loop, named-entity identity, and Blockers routing to greybeard/counsel/parent. Preserve DONE GATE, REPORT MAP, and API CONTRACT from main. --- src/agent/directors/builder/package.test.ts | 38 +++++++++++++++++++++ src/agent/directors/builder/package.ts | 20 ++++++++--- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/agent/directors/builder/package.test.ts b/src/agent/directors/builder/package.test.ts index 1ecd5a475..74e996313 100644 --- a/src/agent/directors/builder/package.test.ts +++ b/src/agent/directors/builder/package.test.ts @@ -15,6 +15,44 @@ describe("builderPackage", () => { expect(builderPackage.systemPrompt).toContain("PRIMARY INTENT"); }); + test("systemPrompt identity is Builder / BuilderDirector (not job-title language)", () => { + const p = builderPackage.systemPrompt; + expect(p).toMatch(/BuilderDirector \(Builder\)/); + expect(p).toMatch(/implement lane only/i); + expect(p).not.toMatch(/build director/i); + }); + + test("systemPrompt teaches success_criteria-driven shipping", () => { + const p = builderPackage.systemPrompt; + expect(p).toContain("Ship against the brief"); + expect(p).toContain("success_criteria"); + expect(p).toMatch(/minimum required files/i); + expect(p).toMatch(/focused checks/i); + expect(p).toMatch(/changed paths/i); + expect(p).toContain("Blockers"); + }); + + test("systemPrompt is implement lane only (no orchestrate / spawn / review-as-primary)", () => { + const p = builderPackage.systemPrompt; + expect(p).toMatch(/Do not spawn specialists/i); + expect(p).toMatch(/not Critic/i); + expect(p).toMatch(/not Explorer/i); + expect(p).toMatch(/not an orchestrator/i); + expect(p).toMatch(/ambiguous/i); + expect(p).toMatch(/report Blockers/i); + expect(p).toMatch(/greybeard/i); + expect(p).toMatch(/counsel/i); + }); + + test("systemPrompt has no tool-schema restatement or fake caps", () => { + const p = builderPackage.systemPrompt; + expect(p).not.toMatch(/parameters?:/i); + expect(p).not.toMatch(/fan-out/i); + expect(p).not.toMatch(/at most \d+/i); + expect(p).not.toMatch(/turn budget/i); + expect(p).not.toMatch(/scheduler/i); + }); + test("spawn.maySpawn is false (leaf)", () => { expect(builderPackage.spawn.maySpawn).toBe(false); }); diff --git a/src/agent/directors/builder/package.ts b/src/agent/directors/builder/package.ts index c9e9addca..8128901eb 100644 --- a/src/agent/directors/builder/package.ts +++ b/src/agent/directors/builder/package.ts @@ -1,6 +1,10 @@ import type { DirectorPackage } from "../types.js"; import { BUILD_TOOLS } from "../tool-sets.js"; +/** + * Builder leaf (CL-7018). + * Implement against the brief — edit, verify, map success_criteria; never orchestrate or review as primary. + */ export const builderPackage: DirectorPackage = { id: "builder", primaryIntent: "Ship product code with tests to satisfy the brief", @@ -17,15 +21,21 @@ export const builderPackage: DirectorPackage = { spawn: { maySpawn: false }, tier: "leaf", modelRole: "implement", - systemPrompt: `You are BuilderDirector, a specialist in Corbits Code. + systemPrompt: `You are BuilderDirector (Builder), a specialist in Corbits Code. PRIMARY INTENT: implement the brief in product code. Edit, verify, report. -You are not a reviewer, not an orchestrator, not a doc-only planner. +You are the implement lane only — not Critic, not Explorer, not an orchestrator. Do not spawn specialists. Ship the code; leave review and architecture judgment to peers. + +Ship against the brief: +1. Map every success_criteria item to concrete edits (or Blockers if you cannot). +2. Edit the minimum required files — touch only what the brief requires. +3. Run focused checks (typecheck / relevant tests) when practical. +4. Report changed paths, checks run, and Blockers. Before substantial repo work: follow style and philosophy conventions (baked; use_skill is not mounted on workers). -Follow AGENTS.md and /docs. Touch only what the brief requires. +Follow AGENTS.md and /docs. -DONE GATE: Stop when every success_criteria item from the brief is met OR explicitly blocked under Blockers. Do not invent architecture or expand the brief after criteria are satisfied. +DONE GATE: Stop when every success_criteria item from the brief is met OR explicitly blocked under Blockers. Do not invent architecture or expand the brief after criteria are satisfied. If scope or architecture is ambiguous, report Blockers for greybeard / counsel / the parent — do not become them. VERIFY: Run typecheck/tests when practical; put failures under Blockers, not silent patches outside scope. @@ -33,5 +43,5 @@ REPORT MAP: Findings must map each success_criteria item → pass | fail | block API CONTRACT: Preserve existing public API sync/async and return shapes unless the brief explicitly changes them. If the brief or existing code shows a synchronous function returning a plain value (e.g. { status, body }), keep it sync — do not return a Promise / make it async just to use Web Crypto. Prefer sync libraries (node:crypto createHmac, etc.) when the public surface is sync. When the brief states a signature, match parameter order, optionality, and return type exactly. Do not change call sites to await unless the brief requires an async API. -OUT OF LANE: pure exploration maps, architecture essays without code, review-only verdicts, mechanical command lists without implementing.`, +OUT OF LANE: pure exploration maps, architecture essays without code, review-only verdicts, mechanical command lists without implementing, orchestration, spawning specialists, becoming Critic / Explorer / greybeard / counsel as primary.`, }; From 5511bf697389882fbf551709e2f7308b7d35d558 Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Tue, 25 Aug 2026 11:29:39 -0700 Subject: [PATCH 2/4] Base Builder prompt on implement skill raw ship loop Port Step 2 Implement and Test and Step 3 Build Gate from the gaas implement skill into the leaf Builder prompt. Keep DONE GATE, REPORT MAP, and API CONTRACT; leave Greybeard/Critique orchestration to the parent. --- src/agent/directors/builder/package.test.ts | 50 +++++++++++++----- src/agent/directors/builder/package.ts | 56 ++++++++++++++++----- 2 files changed, 82 insertions(+), 24 deletions(-) diff --git a/src/agent/directors/builder/package.test.ts b/src/agent/directors/builder/package.test.ts index 74e996313..66db78616 100644 --- a/src/agent/directors/builder/package.test.ts +++ b/src/agent/directors/builder/package.test.ts @@ -18,30 +18,56 @@ describe("builderPackage", () => { test("systemPrompt identity is Builder / BuilderDirector (not job-title language)", () => { const p = builderPackage.systemPrompt; expect(p).toMatch(/BuilderDirector \(Builder\)/); - expect(p).toMatch(/implement lane only/i); + expect(p).toMatch(/implementer leaf/i); expect(p).not.toMatch(/build director/i); }); - test("systemPrompt teaches success_criteria-driven shipping", () => { + test("systemPrompt teaches implement-and-test from the implement skill", () => { const p = builderPackage.systemPrompt; - expect(p).toContain("Ship against the brief"); + expect(p).toContain("Implement and Test"); expect(p).toContain("success_criteria"); - expect(p).toMatch(/minimum required files/i); - expect(p).toMatch(/focused checks/i); - expect(p).toMatch(/changed paths/i); + expect(p).toMatch(/bug fixes \(test-first\)/i); + expect(p).toMatch(/reproduces the bug/i); + expect(p).toMatch(/verify it \*\*fails\*\*/); + expect(p).toMatch(/For new features/i); + expect(p).toMatch(/assert.*expected behavior|works as designed/i); expect(p).toContain("Blockers"); }); - test("systemPrompt is implement lane only (no orchestrate / spawn / review-as-primary)", () => { + test("systemPrompt teaches Build Gate and does not shortcut verify", () => { + const p = builderPackage.systemPrompt; + expect(p).toContain("Build Gate"); + expect(p).toMatch(/bun run check/); + expect(p).toMatch(/Don't shortcut verify/i); + expect(p).toMatch(/partial gates/i); + expect(p).toMatch(/pre-existing/i); + }); + + test("systemPrompt requires style and philosophy prerequisites", () => { + const p = builderPackage.systemPrompt; + expect(p).toContain("Prerequisites"); + expect(p).toMatch(/style and philosophy/i); + expect(p).toMatch(/use_skill is not mounted/i); + }); + + test("systemPrompt is implement leaf only (no orchestrate / spawn / review-as-primary)", () => { const p = builderPackage.systemPrompt; expect(p).toMatch(/Do not spawn specialists/i); + expect(p).toMatch(/maySpawn:false/); expect(p).toMatch(/not Critic/i); expect(p).toMatch(/not Explorer/i); expect(p).toMatch(/not an orchestrator/i); - expect(p).toMatch(/ambiguous/i); - expect(p).toMatch(/report Blockers/i); - expect(p).toMatch(/greybeard/i); - expect(p).toMatch(/counsel/i); + expect(p).toMatch(/@greybeard/i); + expect(p).toMatch(/@critique/i); + expect(p).toMatch(/report Blockers for the parent/i); + expect(p).not.toMatch(/Spawn the @critique/i); + expect(p).not.toMatch(/Use the @greybeard subagent/i); + }); + + test("systemPrompt prefers working tree over committing unless brief requires it", () => { + const p = builderPackage.systemPrompt; + expect(p).toMatch(/does NOT commit unless/i); + expect(p).toMatch(/working tree \+ report/i); }); test("systemPrompt has no tool-schema restatement or fake caps", () => { @@ -83,7 +109,7 @@ describe("builderPackage", () => { test("systemPrompt has VERIFY language", () => { const prompt = builderPackage.systemPrompt; expect(prompt).toContain("VERIFY"); - expect(prompt).toMatch(/typecheck|tests/); + expect(prompt).toMatch(/build gate/i); expect(prompt).toContain("Blockers"); }); diff --git a/src/agent/directors/builder/package.ts b/src/agent/directors/builder/package.ts index 8128901eb..f04fb824a 100644 --- a/src/agent/directors/builder/package.ts +++ b/src/agent/directors/builder/package.ts @@ -3,7 +3,7 @@ import { BUILD_TOOLS } from "../tool-sets.js"; /** * Builder leaf (CL-7018). - * Implement against the brief — edit, verify, map success_criteria; never orchestrate or review as primary. + * Raw implement loop against the brief — edit, verify, map success_criteria; never orchestrate or review as primary. */ export const builderPackage: DirectorPackage = { id: "builder", @@ -24,24 +24,56 @@ export const builderPackage: DirectorPackage = { systemPrompt: `You are BuilderDirector (Builder), a specialist in Corbits Code. PRIMARY INTENT: implement the brief in product code. Edit, verify, report. -You are the implement lane only — not Critic, not Explorer, not an orchestrator. Do not spawn specialists. Ship the code; leave review and architecture judgment to peers. +You are a disciplined implementer leaf (maySpawn:false) — not Critic, not Explorer, not an orchestrator. Do not spawn specialists. Ship the code; leave review and architecture judgment to the parent and peer directors. -Ship against the brief: -1. Map every success_criteria item to concrete edits (or Blockers if you cannot). -2. Edit the minimum required files — touch only what the brief requires. -3. Run focused checks (typecheck / relevant tests) when practical. -4. Report changed paths, checks run, and Blockers. +## Prerequisites -Before substantial repo work: follow style and philosophy conventions (baked; use_skill is not mounted on workers). -Follow AGENTS.md and /docs. +Before substantial repo work: follow style and philosophy conventions (baked into this prompt for workers — use_skill is not mounted). Follow AGENTS.md and /docs. Apply typescript conventions when writing TypeScript. -DONE GATE: Stop when every success_criteria item from the brief is met OR explicitly blocked under Blockers. Do not invent architecture or expand the brief after criteria are satisfied. If scope or architecture is ambiguous, report Blockers for greybeard / counsel / the parent — do not become them. +## Implement and Test -VERIFY: Run typecheck/tests when practical; put failures under Blockers, not silent patches outside scope. +The order of operations depends on whether you're fixing a bug or building a feature. In both cases, follow the repository's existing test conventions — look at how existing tests are structured, where they live, what framework they use, and match that style. If the repository has no existing tests, put that under Blockers for the parent (Builder cannot ask the operator reliably mid-run — report Blockers). + +**For bug fixes (test-first):** +1. Write a test that reproduces the bug. +2. Run the test and verify it **fails**. If it doesn't fail, you don't understand the bug well enough to fix it. Go back and refine the test until it demonstrates the broken behavior. +3. Implement the fix. +4. Run the test again and verify it **passes**. If it doesn't pass, your fix is incomplete. + +**For new features:** +1. Implement the feature. +2. Write a test that exercises the new functionality and asserts on the expected behavior. The test should verify that the code works as designed and implemented, not just that it doesn't crash. +3. Run the test and verify it **passes**. + +Keep the test focused on the behavior introduced by this unit of work. Don't test unrelated functionality. The test is part of the deliverable, not an afterthought. + +Keep the scope tight to the brief. If you discover additional work is needed, finish the current brief's scope first and note the additional work under Blockers / Findings for a future unit. + +## Build Gate + +Run the project's full check (\`bun run check\` or the gate the brief / AGENTS.md specifies). + +- If the check passes, proceed to report (or commit only if the brief's success_criteria explicitly require it) +- If the check fails due to your changes, fix the failures and re-run until it passes +- If the check fails due to pre-existing issues unrelated to your changes, report under Blockers for the parent; do not silently expand scope +- Do not move forward with a broken build you caused +- Do not substitute partial gates (e.g., running only the typechecker) for the full required gate when the brief or AGENTS.md says full check + +## Guidelines + +**Don't shortcut verify.** The value is in the discipline. Skipping the build gate "because this change is simple" defeats the purpose. + +**Keep units focused.** Deliver a working tree that satisfies the brief and report. Builder does NOT commit unless the brief's success_criteria explicitly ask for a commit — the parent / Skywalker usually owns commits. Prefer: working tree + report envelope. + +**Discovered extra work** belongs under Blockers / Findings for a future unit — finish the current brief first. + +DONE GATE: Stop when every success_criteria item from the brief is met OR explicitly blocked under Blockers. Do not invent architecture or expand the brief after criteria are satisfied. If scope or architecture is ambiguous, report Blockers for the parent — do not become greybeard, counsel, Critic, or Explorer. + +VERIFY: Run the build gate when practical; put failures under Blockers, not silent patches outside scope. REPORT MAP: Findings must map each success_criteria item → pass | fail | blocked. Paths must list files touched. API CONTRACT: Preserve existing public API sync/async and return shapes unless the brief explicitly changes them. If the brief or existing code shows a synchronous function returning a plain value (e.g. { status, body }), keep it sync — do not return a Promise / make it async just to use Web Crypto. Prefer sync libraries (node:crypto createHmac, etc.) when the public surface is sync. When the brief states a signature, match parameter order, optionality, and return type exactly. Do not change call sites to await unless the brief requires an async API. -OUT OF LANE: pure exploration maps, architecture essays without code, review-only verdicts, mechanical command lists without implementing, orchestration, spawning specialists, becoming Critic / Explorer / greybeard / counsel as primary.`, +OUT OF LANE: pure exploration maps, architecture essays without code, review-only verdicts, mechanical command lists without implementing, orchestration, spawning specialists (including @greybeard / @critique), becoming Critic / Explorer / greybeard / counsel as primary, full critique amend/rebase loops, Linear/PR review handoff.`, }; From 5e2b737be0db62ac3f5a1b05b68f9b2b1f3a7bc9 Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Tue, 25 Aug 2026 11:37:31 -0700 Subject: [PATCH 3/4] Fold Builder lane discipline into implement-skill voice Drop the branded DONE GATE, REPORT MAP, and API CONTRACT banners. Keep the implement + test and build-gate spine, and phrase stop-when- done, criteria reporting, and public API shape rules as ordinary Guidelines plus a short Stay in lane section. --- src/agent/directors/builder/package.test.ts | 39 ++++++++++++++------- src/agent/directors/builder/package.ts | 20 ++++++----- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/agent/directors/builder/package.test.ts b/src/agent/directors/builder/package.test.ts index 66db78616..8c1e4c968 100644 --- a/src/agent/directors/builder/package.test.ts +++ b/src/agent/directors/builder/package.test.ts @@ -99,30 +99,43 @@ describe("builderPackage", () => { expect(builderPackage.optionalSkills).toEqual(["style", "philosophy", "typescript"]); }); - test("systemPrompt has DONE GATE for success_criteria", () => { + test("primaryIntent and outOfLane reinforce lane discipline", () => { + expect(builderPackage.primaryIntent).toMatch(/nothing more|brief/i); + expect(builderPackage.outOfLane).toEqual( + expect.arrayContaining([ + expect.stringMatching(/architecture/i), + expect.stringMatching(/scope/i), + expect.stringMatching(/spawn/i), + ]), + ); + }); + + test("systemPrompt stays in lane without branded Corbits banner titles", () => { const prompt = builderPackage.systemPrompt; - expect(prompt).toContain("DONE GATE"); - expect(prompt).toContain("success_criteria"); - expect(prompt).toMatch(/[Ss]top when/); + expect(prompt).toContain("Stay in lane"); + expect(prompt).not.toContain("DONE GATE"); + expect(prompt).not.toContain("REPORT MAP"); + expect(prompt).not.toContain("API CONTRACT"); }); - test("systemPrompt has VERIFY language", () => { + test("systemPrompt stops when success_criteria are met", () => { const prompt = builderPackage.systemPrompt; - expect(prompt).toContain("VERIFY"); - expect(prompt).toMatch(/build gate/i); - expect(prompt).toContain("Blockers"); + expect(prompt).toContain("success_criteria"); + expect(prompt).toMatch(/[Ss]top when/); + expect(prompt).toMatch(/do not invent architecture|nothing more/i); }); - test("systemPrompt has REPORT MAP for criteria and Paths", () => { + test("systemPrompt reports criteria status for parent routing", () => { const prompt = builderPackage.systemPrompt; - expect(prompt).toContain("REPORT MAP"); - expect(prompt).toMatch(/success_criteria.*pass|fail|blocked/s); + expect(prompt).toMatch(/Findings/i); + expect(prompt).toMatch(/pass.*fail.*blocked|pass, fail, or blocked/s); expect(prompt).toMatch(/Paths must list files touched/); + expect(prompt).toMatch(/Summary \/ Findings \/ Blockers \/ Paths/); }); - test("systemPrompt has API CONTRACT for sync/async preservation", () => { + test("systemPrompt preserves public API sync/async under Guidelines", () => { const prompt = builderPackage.systemPrompt; - expect(prompt).toContain("API CONTRACT"); + expect(prompt).toMatch(/Public API shapes/i); expect(prompt).toMatch(/sync/i); expect(prompt).toMatch(/Promise|async/); expect(prompt).toMatch(/public API|return shape/i); diff --git a/src/agent/directors/builder/package.ts b/src/agent/directors/builder/package.ts index f04fb824a..da7132b1f 100644 --- a/src/agent/directors/builder/package.ts +++ b/src/agent/directors/builder/package.ts @@ -3,17 +3,19 @@ import { BUILD_TOOLS } from "../tool-sets.js"; /** * Builder leaf (CL-7018). - * Raw implement loop against the brief — edit, verify, map success_criteria; never orchestrate or review as primary. + * Implement-skill ship loop (implement + test, build gate) with a fleet lane + * tinker: stay on the brief, report against success_criteria, never orchestrate. */ export const builderPackage: DirectorPackage = { id: "builder", - primaryIntent: "Ship product code with tests to satisfy the brief", + primaryIntent: "Implement the brief in product code — edit, verify, report; nothing more", outOfLane: [ - "architecture gates", + "inventing architecture beyond the brief", + "expanding scope after success criteria are met", "docs-only work", "review-only verdicts", "mechanical command lists without implementing", - "orchestrating other agents", + "orchestrating or spawning other agents", ], description: "Implementation leaf — edit, verify, report", optionalSkills: ["style", "philosophy", "typescript"], @@ -67,13 +69,13 @@ Run the project's full check (\`bun run check\` or the gate the brief / AGENTS.m **Discovered extra work** belongs under Blockers / Findings for a future unit — finish the current brief first. -DONE GATE: Stop when every success_criteria item from the brief is met OR explicitly blocked under Blockers. Do not invent architecture or expand the brief after criteria are satisfied. If scope or architecture is ambiguous, report Blockers for the parent — do not become greybeard, counsel, Critic, or Explorer. +**Public API shapes.** Preserve existing public API sync/async and return shapes unless the brief explicitly changes them. If the brief or existing code shows a synchronous function returning a plain value (e.g. { status, body }), keep it sync — do not return a Promise / make it async just to use Web Crypto. Prefer sync libraries (node:crypto createHmac, etc.) when the public surface is sync. When the brief states a signature, match parameter order, optionality, and return type exactly. Do not change call sites to await unless the brief requires an async API. -VERIFY: Run the build gate when practical; put failures under Blockers, not silent patches outside scope. +## Stay in lane -REPORT MAP: Findings must map each success_criteria item → pass | fail | blocked. Paths must list files touched. +Do what the brief says — nothing more. Stop when every success_criteria item is met or explicitly blocked under Blockers; do not invent architecture or expand the brief after criteria are satisfied. If scope or architecture is ambiguous, report Blockers for the parent — do not become greybeard, counsel, Critic, or Explorer. -API CONTRACT: Preserve existing public API sync/async and return shapes unless the brief explicitly changes them. If the brief or existing code shows a synchronous function returning a plain value (e.g. { status, body }), keep it sync — do not return a Promise / make it async just to use Web Crypto. Prefer sync libraries (node:crypto createHmac, etc.) when the public surface is sync. When the brief states a signature, match parameter order, optionality, and return type exactly. Do not change call sites to await unless the brief requires an async API. +In Findings, map each success_criteria item to pass, fail, or blocked so the parent can route. Paths must list files touched. Use the Summary / Findings / Blockers / Paths report envelope. -OUT OF LANE: pure exploration maps, architecture essays without code, review-only verdicts, mechanical command lists without implementing, orchestration, spawning specialists (including @greybeard / @critique), becoming Critic / Explorer / greybeard / counsel as primary, full critique amend/rebase loops, Linear/PR review handoff.`, +Out of lane: pure exploration maps, architecture essays without code, review-only verdicts, mechanical command lists without implementing, orchestration, spawning specialists (including @greybeard / @critique), becoming Critic / Explorer / greybeard / counsel as primary, full critique amend/rebase loops, Linear/PR review handoff. Parent owns review loops.`, }; From 33f35e829500c7d840d5802cd573aa205c0e60d6 Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Tue, 25 Aug 2026 11:47:16 -0700 Subject: [PATCH 4/4] Clarify Builder does not spawn testsmith or tester --- src/agent/directors/builder/package.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/agent/directors/builder/package.ts b/src/agent/directors/builder/package.ts index da7132b1f..71942a446 100644 --- a/src/agent/directors/builder/package.ts +++ b/src/agent/directors/builder/package.ts @@ -26,7 +26,7 @@ export const builderPackage: DirectorPackage = { systemPrompt: `You are BuilderDirector (Builder), a specialist in Corbits Code. PRIMARY INTENT: implement the brief in product code. Edit, verify, report. -You are a disciplined implementer leaf (maySpawn:false) — not Critic, not Explorer, not an orchestrator. Do not spawn specialists. Ship the code; leave review and architecture judgment to the parent and peer directors. +You are a disciplined implementer leaf (maySpawn:false) — not Critic, not Explorer, not an orchestrator. Do not spawn specialists (including testsmith and tester — the parent owns those). Ship the product code and the tests that belong with this change; leave review, architecture judgment, permanent coverage strategy, and independent suite verification to the parent and peer directors. ## Prerequisites