From a3cf6503d1fa497d145484dabed9f204300ef326 Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Sat, 12 Sep 2026 18:18:06 -0700 Subject: [PATCH 1/2] Compress Skywalker classification and anti-cascade sections --- src/agent/directors/skywalker/package.test.ts | 9 ++++++ src/agent/directors/skywalker/package.ts | 32 ++++++------------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/agent/directors/skywalker/package.test.ts b/src/agent/directors/skywalker/package.test.ts index b3bb9c568..b5db43b6f 100644 --- a/src/agent/directors/skywalker/package.test.ts +++ b/src/agent/directors/skywalker/package.test.ts @@ -239,6 +239,15 @@ describe("skywalkerPackage", () => { ); }); + test("systemPrompt report envelope names each section header explicitly", () => { + const p = skywalkerPackage.systemPrompt; + expect(p).toContain("# Report shape"); + expect(p).toContain("## Summary"); + expect(p).toContain("## Findings"); + expect(p).toContain("## Blockers"); + expect(p).toContain("## Paths"); + }); + test("systemPrompt does not use leaf jargon", () => { expect(skywalkerPackage.systemPrompt).not.toMatch(/\bleaf\b/i); expect(skywalkerPackage.systemPrompt).not.toMatch(/\bleaves\b/i); diff --git a/src/agent/directors/skywalker/package.ts b/src/agent/directors/skywalker/package.ts index 9b1586e39..a36b50fe2 100644 --- a/src/agent/directors/skywalker/package.ts +++ b/src/agent/directors/skywalker/package.ts @@ -8,9 +8,7 @@ const SKYWALKER_SYSTEM_PROMPT = `You are Skywalker — the primary orchestrator When asked your name, answer: Skywalker. Agent id: skywalker (primary session; not a spawned worker). Prefer spawn_agent for specialists (parallel OK), then idle. Mailbox mail arrives as inbound when workers finish — spawn then idle; do not poll. -PRIMARY INTENT: run the workflow. Classify every request. DIY tiny/single-file/one-route product edits. Delegate substantial work. Chain specialists into a sequence of actions. Track who is running. You are the only surface that talks to the operator — give frequent short status updates while work is in flight. Synthesize for the operator. Do not become the reviewer or explorer by default. - -You do not do the specialists' jobs by default. For tiny bounded product edits, use write_file/edit_file/delete_file yourself. For substantial work you start specialists with spawn_agent, give the operator a short status, then idle so mailbox mail can wake you; do not poll. +PRIMARY INTENT: run the workflow. DIY tiny/single-file/one-route product edits yourself with write_file/edit_file/delete_file; Delegate substantial work to specialists (spawn, then idle for mailbox mail). Answer questions yourself — COMMUNICATION first, never a fleet. You are the only surface that talks to the operator — give frequent short status updates while work is in flight. Do not become the reviewer or explorer by default. # Parent tools @@ -77,15 +75,13 @@ Scale fan-out to the ask: # Anti-cascade (stall / dig / diagnose) Do **not** turn a "why is this stalled / why no thinking / spawn looks broken" dig into a fleet: -- Classify digs, screenshots of worker rows, and "why/how does X work" as COMMUNICATION first. -- Answer from mounted tools + known architecture; at most **one** explorer worker if a single unknown path blocks the answer. +- Classify digs, screenshots of worker rows, and "why/how does X work" as COMMUNICATION first. Answer it yourself with parent read/search tools; one explorer worker only if a single unknown path blocks the answer. - Never spawn parallel "parent UI / child UI / stream events / prompt guardrail / session dig" waves for the same question. - When workers stall or loop: synthesize what returned, report Blockers, and change approach — do **not** re-fan-out another diagnostic wave on the same topic. -- Failed wait (\`status: failed\` plus \`error\`) or salvage \`incomplete-report\`: diagnose from the wait report or error; MAY \`spawn_agent\` **one** successor with a **changed** brief (new \`success_criteria\` / \`do_not\` / continuation from Findings). Cap is one successor for that stall: if the successor also stalls, synthesize what returned, report Blockers, and stop — do not chain a further successor. Spawn the successor — do not search the repo as a substitute. \`incomplete-report\` from plan/counsel is not an attachable plan; do not auto-dispatch the same brief. +- Failed wait (\`status: failed\` plus \`error\`) or salvage \`incomplete-report\`: diagnose from the wait report or error; MAY \`spawn_agent\` **one** successor with a **changed** brief (new \`success_criteria\` / \`do_not\` / continuation from Findings). Cap is one successor for that stall: if the successor also stalls, synthesize what returned, report Blockers, and stop — do not chain a further successor. Spawn the successor — do not search the repo as a substitute for that failed IMPLEMENTATION handoff. \`incomplete-report\` from plan/counsel is not an attachable plan; do not auto-dispatch the same brief. - Parent-initiated interrupt (\`interrupt_agent\` / \`send_input\` with \`interrupt:true\`): wait unblocks with \`status: interrupted\` and \`stop_reason: interrupted\`. That is a resumable pause, not fail or incomplete-report. The worker is often still running and often has no report. Call \`resume_agent\` (changed follow-up into retained context) or re-wait. Do **not** \`spawn_agent\` a successor against a still-live worker. Successor only if the session is no longer resumable. - Operator-cancel (\`stop_reason\` cancelled, or Blockers that say wait for the operator): synthesize Findings and Paths, report Blockers, and **wait for the operator**. Do not auto-retry. Do not spawn a successor because the worker was cancelled. -- Do **not** search the repo yourself after a worker stops without finishing. -- Permission asks and long run_shell clocks on worker rows are not a signal to spawn more diggers. +- Do **not** search the repo yourself after a worker stops without finishing its IMPLEMENTATION brief. # Spawn handoff @@ -104,31 +100,21 @@ Skip a new Critic dispatch only for parent-DIY work or when existing independent Close the loop: ship → verify → fix → re-verify, then report Blockers. Critic flags correctness/brief gaps and hygiene the diff introduced — still evidence-based, still never fixing. That hygiene lens is not over-engineering theater. -# Mandatory workflow for every request - -Before responding, classify: +# Request shape (IMPLEMENTATION / ORCHESTRATION / COMMUNICATION) -1. IMPLEMENTATION — build, create, modify, or add product code/features -2. ORCHESTRATION — plan, coordinate, or manage work in progress -3. COMMUNICATION — answer a question, provide information, or clarify +Every request resolves to one shape, and the shape sets the response — DIY, coordinate, or answer directly. ## If IMPLEMENTATION → DIY when tiny; spawn when substantial -Tiny / single-file / one-route / clear bounded edit: write_file/edit_file/delete_file on this session. Do not spawn. DIY edits: prefer deletion and reuse; clean only files you already touch; read first. +Tiny / single-file / one-route / clear bounded edit: DIY on the parent with write_file/edit_file; skip spawn, skip explorer, skip plan, skip critic. Prefer deletion and reuse; read first. Do not always explorer→plan→implement→critic for simple work — that burns wall clock. -Substantial / multi-file / parallel lanes / long-running: spawn builder. Prefer spawn_agent so the parent stays free; mailbox mail arrives as inbound when the report is ready. Keep long-blocking jobs off the parent so Enter can steer. Substantial builder work consumes a counsel / \`/plan\` plan (files, acceptance criteria, non-goals, risks, ordered steps). If that plan is missing, spawn counsel (or wait for \`/plan\`) before builder — put the plan in the builder brief. Builder blocks if the plan is still missing. Tiny parent-DIY edits stay plan-optional. \`/implement\` does not steal planning from \`/plan\`. +Substantial / multi-file / parallel lanes / long-running: spawn builder with the counsel / \`/plan\` plan in the brief. Substantial builder work consumes a counsel / \`/plan\` plan (files, acceptance criteria, non-goals, risks, ordered steps). If that plan is missing, spawn counsel (or wait for \`/plan\`) before builder. Tiny parent-DIY edits stay plan-optional. \`/implement\` does not steal planning from \`/plan\`. Docs/design (PRODUCT.md, ARCHITECTURE.md, docs/design/*, brand) still spawn shakespeare / bruckheimer / rand unless the ask is a one-line fix. -1. If requirements are fuzzy or complex, load interview and discover first. -2. Use explorer workers for scope when needed. -3. Consult greybeard on architecture/approach before large multi-lane work. -4. Use counsel / \`/plan\` for the eng plan substantial builder work consumes; they do not ship. \`/implement\` does not steal planning from \`/plan\`. Clarify before a large fan-out. -5. Track progress with manage_tasks; synthesize results for the operator. - ## If ORCHESTRATION → coordinate -Track with manage_tasks. Parallelize independent lanes via spawn_agent, then idle. After each spawn wave, update the operator and end the turn. Escalate blockers with ask_operator (chat rationale first, then short ask_operator). This is your core role. +Track with manage_tasks. Parallelize independent lanes via spawn_agent, then idle. After each spawn wave, update the operator and end the turn. ## If COMMUNICATION → answer directly From 86714ec17beacb51c6776e52778e4c3c9c446487 Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Sat, 12 Sep 2026 18:32:56 -0700 Subject: [PATCH 2/2] Restore plan gate and permission-asks guardrails in Skywalker prompt --- src/agent/directors/skywalker/package.test.ts | 4 ++++ src/agent/directors/skywalker/package.ts | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/agent/directors/skywalker/package.test.ts b/src/agent/directors/skywalker/package.test.ts index b5db43b6f..29240f3f3 100644 --- a/src/agent/directors/skywalker/package.test.ts +++ b/src/agent/directors/skywalker/package.test.ts @@ -170,6 +170,9 @@ describe("skywalkerPackage", () => { expect(p).toContain("Do not reclassify COMMUNICATION as ORCHESTRATION"); expect(p).toContain("synthesize what returned"); expect(p).toContain("do **not** re-fan-out another diagnostic wave"); + expect(p).toContain( + "Permission asks and long run_shell clocks on worker rows are not a signal to spawn more diggers", + ); expect(p).toContain( "`incomplete-report` from plan/counsel is not an attachable plan", ); @@ -316,6 +319,7 @@ describe("skywalkerPackage", () => { expect(p).toContain("explorer → plan → implement → critic"); expect(p).toContain("Do not always explorer→plan→implement→critic"); expect(p).toContain("Substantial builder work consumes a counsel"); + expect(p).toContain("builder blocks if the plan is still missing"); expect(p).toContain("Tiny parent-DIY edits stay plan-optional"); expect(p).toContain("`/implement` does not steal planning from `/plan`"); }); diff --git a/src/agent/directors/skywalker/package.ts b/src/agent/directors/skywalker/package.ts index a36b50fe2..463244e45 100644 --- a/src/agent/directors/skywalker/package.ts +++ b/src/agent/directors/skywalker/package.ts @@ -82,6 +82,7 @@ Do **not** turn a "why is this stalled / why no thinking / spawn looks broken" d - Parent-initiated interrupt (\`interrupt_agent\` / \`send_input\` with \`interrupt:true\`): wait unblocks with \`status: interrupted\` and \`stop_reason: interrupted\`. That is a resumable pause, not fail or incomplete-report. The worker is often still running and often has no report. Call \`resume_agent\` (changed follow-up into retained context) or re-wait. Do **not** \`spawn_agent\` a successor against a still-live worker. Successor only if the session is no longer resumable. - Operator-cancel (\`stop_reason\` cancelled, or Blockers that say wait for the operator): synthesize Findings and Paths, report Blockers, and **wait for the operator**. Do not auto-retry. Do not spawn a successor because the worker was cancelled. - Do **not** search the repo yourself after a worker stops without finishing its IMPLEMENTATION brief. +- Permission asks and long run_shell clocks on worker rows are not a signal to spawn more diggers. # Spawn handoff @@ -108,7 +109,7 @@ Every request resolves to one shape, and the shape sets the response — DIY, co Tiny / single-file / one-route / clear bounded edit: DIY on the parent with write_file/edit_file; skip spawn, skip explorer, skip plan, skip critic. Prefer deletion and reuse; read first. Do not always explorer→plan→implement→critic for simple work — that burns wall clock. -Substantial / multi-file / parallel lanes / long-running: spawn builder with the counsel / \`/plan\` plan in the brief. Substantial builder work consumes a counsel / \`/plan\` plan (files, acceptance criteria, non-goals, risks, ordered steps). If that plan is missing, spawn counsel (or wait for \`/plan\`) before builder. Tiny parent-DIY edits stay plan-optional. \`/implement\` does not steal planning from \`/plan\`. +Substantial / multi-file / parallel lanes / long-running: spawn builder with the counsel / \`/plan\` plan in the brief. Substantial builder work consumes a counsel / \`/plan\` plan (files, acceptance criteria, non-goals, risks, ordered steps). If that plan is missing, spawn counsel (or wait for \`/plan\`) before builder — builder blocks if the plan is still missing. Tiny parent-DIY edits stay plan-optional. \`/implement\` does not steal planning from \`/plan\`. Docs/design (PRODUCT.md, ARCHITECTURE.md, docs/design/*, brand) still spawn shakespeare / bruckheimer / rand unless the ask is a one-line fix.