Skip to content

Commit 334e8b8

Browse files
committed
Strip scheduler restatements from the Skywalker prompt
1 parent bf79cc0 commit 334e8b8

3 files changed

Lines changed: 25 additions & 12 deletions

File tree

‎src/agent/directors/skywalker/package.test.ts‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,19 +115,25 @@ describe("skywalkerPackage", () => {
115115
expect(p).not.toContain("2–4 workers");
116116
expect(p).not.toContain("at most 4");
117117
expect(p).not.toContain("Prefer synthesizing early returns");
118-
expect(p).toContain("queues excess");
118+
// CL-6953: admission queue owns queueing (src/subagent/admission.ts) —
119+
// the prompt keeps the fan-out judgment, not the mechanism restatement.
120+
expect(p).not.toContain("queues excess");
119121
expect(p).toContain("Do not invent a numeric cap");
120122
});
121123

122124
test("systemPrompt prefers spawn_agent then idle (idle-orchestrator)", () => {
123125
const p = skywalkerPackage.systemPrompt;
124126
expect(p).toContain("spawn_agent");
125-
expect(p).toContain("wait_agents");
127+
// CL-6953: collection path (wait_agents vs mailbox) lives in the runtime
128+
// mount + spawn_agent tool description — not the static prompt.
129+
expect(p).not.toContain("wait_agents");
126130
expect(p).toContain("Idle-orchestrator");
127131
expect(p).not.toContain("task()");
128132
expect(p).toContain("Spawn then idle; do not poll");
129133
expect(p).not.toContain("do not poll wait_agents");
130-
expect(p).toContain("wait_agents is mounted on exec-primary runs only");
134+
// CL-6953: wait_agents mounting lives in the runtime (exec/runner.ts) and
135+
// tool descriptions — the prompt keeps spawn-then-idle, not the mount fact.
136+
expect(p).not.toContain("wait_agents is mounted on exec-primary runs only");
131137
expect(p).toContain("mailbox mail arrives as inbound");
132138
expect(p).toContain(
133139
"When the fleet goes dry the runtime re-enters with collected reports",
@@ -218,6 +224,9 @@ describe("skywalkerPackage", () => {
218224
expect(p).toContain("clean-room");
219225
expect(p).toContain("no fork");
220226
expect(p).toContain("required for implement/review");
227+
// CL-6953 / CL-6807: single contract statement (spawn graph); the routing
228+
// and handoff restatements are gone.
229+
expect(p).not.toContain("Runtime requires success_criteria");
221230
expect(p).not.toContain("Brief completeness");
222231
expect(p).not.toContain("Prefer typed spawn");
223232
expect(p.indexOf("Critic stays clean-room")).toBeGreaterThan(
@@ -303,7 +312,9 @@ describe("skywalkerPackage", () => {
303312
expect(p).toContain("re-dispatch **builder**");
304313
expect(p).toMatch(/narrowed or changed follow-up brief/i);
305314
expect(p).toContain("ship → verify → fix → re-verify");
306-
expect(p).toContain("Cap re-fix rounds");
315+
// CL-6953: no runtime retry budget enforces a re-fix cap — keep the loop
316+
// judgment, not the number.
317+
expect(p).not.toContain("Cap re-fix rounds");
307318
});
308319

309320
test("systemPrompt Linear three-state: In Review at PR-open, never Done at PR-open", () => {

‎src/agent/directors/skywalker/package.ts‎

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ You do not do the specialists' jobs by default. For tiny bounded product edits,
1616
1717
Do not run long-blocking jobs on the parent (evals, full test suites, long installs, long-running implementation). Dispatch intern (mechanical shell), tester (suite / repro), or builder (substantial code). Path tools (write_file/edit_file/delete_file) are the DIY surface; shell file-writes stay denied.
1818
19-
Idle-orchestrator: fire one or more spawn_agent calls in a turn — each returns immediately with an agent_id and does not hold the parent. Then **reply to the operator** with who is running and **end the turn**. Workers keep running while you are idle; mailbox mail arrives as inbound when a worker finishes or fails — read it and decide the next action. Spawn then idle; do not poll. wait_agents is mounted on exec-primary runs only. list_agents shows the fleet without blocking; do not poll list_agents. interrupt_agent unblocks an in-flight wait immediately. Enter mid-run delivers at the next parent tool.boundary — a long parent foreground run_shell holds those steers (start long commands with run_shell background:true instead). A bare spawn_agent does not. When the fleet goes dry the runtime re-enters with collected reports.
19+
Idle-orchestrator: fire one or more spawn_agent calls in a turn — each returns immediately with an agent_id and does not hold the parent. Then **reply to the operator** with who is running and **end the turn**. Workers keep running while you are idle; mailbox mail arrives as inbound when a worker finishes or fails — read it and decide the next action. Spawn then idle; do not poll. list_agents shows the fleet without blocking; do not poll list_agents. Enter mid-run delivers at the next parent tool.boundary — a long parent foreground run_shell holds those steers (start long commands with run_shell background:true instead). A bare spawn_agent does not. When the fleet goes dry the runtime re-enters with collected reports.
2020
2121
# Operator updates (mandatory while fleet is live)
2222
@@ -52,7 +52,7 @@ Quick routing:
5252
- intern = exact shell / mechanical ops
5353
- After every delegated builder landing → run a critic on the diff/criteria in a fresh context; when architecture is in play, add greybeard for architecture judgment
5454
55-
success_criteria is required for implement/review and their default directors; recommended otherwise. Pass intent, do_not, report_focus, and agent when specialist.
55+
Pass intent, do_not, report_focus, and agent when specialist.
5656
Parallelize independent lanes with spawn_agent, then idle. manage_tasks for your checklist. ask_operator when blocked or ambiguous — put long rationale in a normal transcript reply first, then call ask_operator with a short question and short option labels only.
5757
5858
# Fetch URLs (primary-mounted)
@@ -64,7 +64,7 @@ When the operator (or brief) gives an http(s) URL to read:
6464
6565
# Effort scaling (IMPLEMENTATION / ORCHESTRATION)
6666
67-
Scale fan-out to the ask — the runtime queues excess rather than refusing:
67+
Scale fan-out to the ask:
6868
- Simple (answer, one-path lookup, tiny fix): 0–1 worker, few tools; often answer without fleet
6969
- Tiny single-file / one-route asks: **DIY on the parent** with write_file/edit_file; skip spawn, skip explorer, skip plan, skip critic. Do not always explorer→plan→implement→critic for simple work — that burns wall clock.
7070
- Multi-lane work: spawn only named, non-overlapping lanes (distinct path/package/ownership). Width follows independent lanes. Do not invent a numeric cap.
@@ -76,7 +76,7 @@ Do **not** turn a "why is this stalled / why no thinking / spawn looks broken" d
7676
- Answer from mounted tools + known architecture; at most **one** explorer worker if a single unknown path blocks the answer.
7777
- Never spawn parallel "parent UI / child UI / stream events / prompt guardrail / session dig" waves for the same question.
7878
- 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.
79-
- 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. 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.
79+
- 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). 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.
8080
- 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.
8181
- 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.
8282
- Do **not** search the repo yourself after a worker stops without finishing.
@@ -85,7 +85,6 @@ Do **not** turn a "why is this stalled / why no thinking / spawn looks broken" d
8585
# Spawn handoff
8686
8787
Child starts blank. Parent writes a complete packet: Goal, contracts copied verbatim, Scope/do_not, Done-when/success_criteria, What to report.
88-
Runtime requires success_criteria for implement/review and their default directors; recommended otherwise.
8988
Re-dispatch after a blocker is a new handoff (new criteria / new do_not), not a retry of the old one-liner.
9089
Identical re-dispatch of the same brief stays refused.
9190
Operator-cancel is not a re-dispatch — wait for the operator.
@@ -97,7 +96,7 @@ When the operator brief states a function signature or return shape, put that **
9796
Critic stays clean-room: brief + diff + public API; no fork.
9897
After every delegated **builder** implementation, run **critic** in a fresh context focused on the brief, resulting diff, and relevant public API contracts (sync/async, signatures). A substantial implementation limited to one internal file still requires Critic review. Builder self-report, even a green report with claimed test passes, is never sufficient to skip this independent critique.
9998
Skip a new Critic dispatch only for parent-DIY work or when existing independent review evidence already covers both the resulting diff and its success criteria. Use **tester** when you need independent suite evidence. If critic (or tester) reports **blocking** findings, re-dispatch **builder** with a narrowed or changed follow-up brief that carries those findings in success_criteria/do_not — do not declare done on a "ready" that ignored blockers.
100-
Close the loop: ship → verify → fix → re-verify. Cap re-fix rounds (e.g. 1–2) then report Blockers.
99+
Close the loop: ship → verify → fix → re-verify, then report Blockers.
101100
Critic flags correctness/brief gaps and hygiene the diff introduced — still evidence-based, still never fixing. That hygiene lens is not over-engineering theater.
102101
103102
# Mandatory workflow for every request

‎src/agent/prompts.test.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,13 @@ describe("wait_agents mount-gated prompt copy (CL-7678)", () => {
163163
it("tells an unmounted primary to spawn then idle on mailbox mail", () => {
164164
const prompt = chatPrompt(TUI_AVAILABILITY);
165165
expect(prompt).toContain("mailbox mail arrives as inbound");
166-
// No wait_agents tool ad on an unmounted primary — only the exec-only note.
166+
// No wait_agents tool ad on an unmounted primary — and no mount-fact
167+
// restatement either (CL-6953: the mount lives in the runtime toolset +
168+
// mount-gated guidelines copy, not the static prompt; naming an unmounted
169+
// tool is an impossible-tool ref per CL-6807 hygiene).
167170
expect(prompt).not.toContain("- wait_agents:");
168171
expect(prompt).not.toContain("collect with wait_agents");
169-
expect(prompt).toContain(
172+
expect(prompt).not.toContain(
170173
"wait_agents is mounted on exec-primary runs only",
171174
);
172175
});

0 commit comments

Comments
 (0)