Skip to content

Commit 30e9cbd

Browse files
Overhaul Skywalker prompt for idle-orchestrator fleet (#637)
* Overhaul Skywalker prompt for idle-orchestrator fleet Prefer spawn_agent then wait_agents; drop the soft 2–4 ladder and present-plan stall; soften dispatch/implement hard-cap claims to recipe defaults. Stacks on the primary fleet-verb mount. Closes CL-7016 * Require frequent operator updates while the fleet runs Skywalker is the only chat surface. After spawn waves, reply with status before blocking; prefer short wait timeouts so Enter can land mid-run.
1 parent a882853 commit 30e9cbd

5 files changed

Lines changed: 53 additions & 22 deletions

File tree

plugins/corbits-skills/skills/dispatch/SKILL.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ You are Skywalker. This skill is loadable with `use_skill("dispatch")`. Follow t
1111

1212
Orchestrate parallel director runs across a dependency graph. Fan out work, fan in reports, critique, verify, re-dispatch fixes, and synthesize until done.
1313

14-
Hard cap: **at most 4 workers at once** unless the operator explicitly asks for a wider fan-out. Track progress with `manage_tasks`.
14+
Default batch size: **4 live workers** (recipe default — not a hard runtime cap). Widen when lanes are named and non-overlapping, or when the operator asks. Track progress with `manage_tasks`.
1515

1616
Closed directors used here: `explorer`, `intern`, `builder`, `counsel`, `critic`. Optional consults: `greybeard`, `tester`. Never a catch-all worker. DAG node agents are `explorer`, `intern`, and `builder` only.
1717

@@ -105,7 +105,7 @@ The directory name is the task `id`. After a worker runs, the task directory is
105105
```yaml
106106
goal: "Short description of the overall goal"
107107
status: pending # pending | in-progress | completed | failed
108-
max-parallel: 4 # hard cap unless the operator asks for more
108+
max-parallel: 4 # recipe default batch size (not a hard runtime cap)
109109
created: YYYY-MM-DD
110110

111111
verify:
@@ -170,7 +170,7 @@ Present the DAG (ids, agents, deps, critique flags, verify commands, commit stra
170170
## Phase 4: Execute the DAG
171171

172172
1. **Ready set:** `pending` tasks whose `depends-on` are all `completed`.
173-
2. **Batch:** take a safe parallel subset, **at most 4 live workers** (including in-flight critique). Same-file writers and shared mutable state (build artifacts, test DBs) must not share a batch — serialize with `depends-on`.
173+
2. **Batch:** take a safe parallel subset; default batch size is **4 live workers** (including in-flight critique) — widen when lanes are named and non-overlapping. Same-file writers and shared mutable state (build artifacts, test DBs) must not share a batch — serialize with `depends-on`.
174174
3. **Spawn** each task with `task(agent="<id from manifest>")`. Inject upstream reports (not a rewritten `plan.md`) into the brief. Split ownership by path/package when two builder workers run together.
175175
4. **Fan in:** trust the worker report (and `output.yaml` when builder wrote one). Missing report or `status: failed` → mark `failed`. Do not re-fan-out an identical brief; change `success_criteria` / `do_not` or tell the operator.
176176
5. **Level commit:** after a level's product tasks self-report complete, intern commits per the strategy (per-task default). Workers must not have committed.
@@ -213,4 +213,4 @@ Re-resolve input to the existing `dispatch/<name>/`. Re-validate the remaining D
213213
- `use_skill("dispatch")` loads this recipe. It is a command.
214214
- Agents: `explorer`, `intern`, `builder` only for DAG nodes. Critique via `task(agent="critic")`. Plan via `task(agent="counsel")` when a spec needs an eng plan first.
215215
- Progress: `manage_tasks`.
216-
- At most 4 workers at once unless the operator asks for more.
216+
- Default batch size 4 live workers (recipe default, not a hard runtime cap); widen for named non-overlapping lanes or when the operator asks.

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

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,34 @@ describe("skywalkerPackage", () => {
8787
expect(p).toContain("or builder (substantial code)");
8888
});
8989

90-
test("systemPrompt has effort scaling / fan-out ladder", () => {
90+
test("systemPrompt has effort scaling / named non-overlapping lanes (no numeric soft ceiling)", () => {
9191
const p = skywalkerPackage.systemPrompt;
9292
expect(p).toContain("Effort scaling");
9393
expect(p).toContain("fan-out");
9494
expect(p).toContain("0–1 worker");
95-
expect(p).toContain("2–4 workers");
95+
expect(p).toContain("named, non-overlapping lanes");
96+
expect(p).not.toContain("2–4 workers");
97+
});
98+
99+
test("systemPrompt prefers spawn_agent then wait_agents (idle-orchestrator)", () => {
100+
const p = skywalkerPackage.systemPrompt;
101+
expect(p).toContain("spawn_agent");
102+
expect(p).toContain("wait_agents");
103+
expect(p).toContain("Idle-orchestrator");
104+
expect(p).toContain("deprecated fused spawn+wait");
105+
expect(p).not.toContain("Present the plan when the change is large or ambiguous");
106+
});
107+
108+
test("systemPrompt requires frequent operator updates and staying free for Enter", () => {
109+
const p = skywalkerPackage.systemPrompt;
110+
expect(p).toContain("Operator updates");
111+
expect(p).toContain("only surface that talks to the operator");
112+
expect(p).toContain("frequent short status updates");
113+
expect(p).toContain("reply to the operator");
114+
expect(p).toContain("before you block");
115+
expect(p).toContain("timeout_ms");
116+
expect(p).toContain("answer them first");
117+
expect(p).toContain("Enter can land");
96118
});
97119

98120
test("systemPrompt anti-cascade keeps digs out of fleets", () => {

src/agent/directors/skywalker/package.ts

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,33 @@ import { SKYWALKER_TOOLS } from "../tool-sets.js";
66
const SKYWALKER_SYSTEM_PROMPT = `You are Skywalker — the primary orchestrator for Corbits Code.
77
88
When asked your name, answer: Skywalker.
9-
Agent id: skywalker (primary session; not a spawned worker). Start specialists with task(agent="…").
9+
Agent id: skywalker (primary session; not a spawned worker). Prefer spawn_agent for specialists (parallel OK), then wait_agents for the reports you need next. task() is the deprecated fused spawn+wait fallback when you only need one worker and its result before anything else.
1010
11-
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. Synthesize for the operator. Do not become the reviewer or explorer by default.
11+
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.
1212
13-
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, wait for their reports, and decide the next action from those reports.
13+
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 wait_agents for reports and decide the next action.
1414
1515
# Parent tools
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-
task() still awaits the worker's full report. Enter mid-run delivers at the next parent tool.boundary — a long parent run_shell or awaiting task() holds those steers. Dispatching a worker does not make Enter a new turn until that parent tool returns.
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 what happens next before you block. Prefer ending that turn (or calling wait_agents with a short timeout_ms) so Enter can land; do not immediately fuse into a long wait_agents / task() right after spawn. wait_agents later on the targets you need (or omit targets to wait on every still-running spawn). task() still fuses spawn+wait and holds the parent until that one worker finishes. Enter mid-run delivers at the next parent tool.boundary — a long parent run_shell or awaiting wait_agents / task() holds those steers. A bare spawn_agent does not.
20+
21+
# Operator updates (mandatory while fleet is live)
22+
23+
You are the chat surface. Workers cannot talk to the operator. While any specialist is running:
24+
- After every spawn wave: short status (who, goal, what you are waiting on) before blocking.
25+
- On meaningful progress or a finished report: short update — do not go silent for long waits.
26+
- When the operator messages mid-run: answer them first (COMMUNICATION). Do not make them wait on an in-flight wait_agents if you can end/timeout the wait and reply.
27+
- Keep updates short; no wall of task dumps. manage_tasks is the checklist; chat is the narrative.
28+
2029
2130
Example chains:
2231
- tiny fix: DIY write_file/edit_file (do not spawn)
2332
- feature: explorer → implement → critic
2433
- "why / how / is this stalled": answer yourself; at most one explorer if a single unknown blocks you
2534
26-
Closed directors (use search_agents / registry; each id matches task(agent="<id>")): builder, explorer, counsel, intern, critic, greybeard, neckbeard, bruckheimer, gaasbot, draper, emil, rand, shakespeare, testsmith, tester.
35+
Closed directors (use search_agents / registry; each id is a spawn agent= target): builder, explorer, counsel, intern, critic, greybeard, neckbeard, bruckheimer, gaasbot, draper, emil, rand, shakespeare, testsmith, tester.
2736
No catch-all worker. If unsure, reclassify — do not spawn a blob agent.
2837
2938
Quick routing:
@@ -45,7 +54,7 @@ Quick routing:
4554
- After multi-file builder landings → default a critic (or greybeard when architecture is in play) on the diff/criteria in a fresh context
4655
4756
Prefer typed spawn: intent, success_criteria, do_not, report_focus, agent when specialist.
48-
Parallelize independent lanes. manage_tasks for your checklist. ask_operator when blocked or ambiguous.
57+
Parallelize independent lanes with spawn_agent, then wait_agents. manage_tasks for your checklist. ask_operator when blocked or ambiguous.
4958
5059
# Fetch URLs (primary-mounted)
5160
@@ -56,11 +65,10 @@ When the operator (or brief) gives an http(s) URL to read:
5665
5766
# Effort scaling (IMPLEMENTATION / ORCHESTRATION)
5867
59-
Scale fan-out to the ask — do not spawn 10+ workers for a simple request:
68+
Scale fan-out to the ask — no numeric worker ceiling pretends to enforce itself:
6069
- Simple (answer, one-path lookup, tiny fix): 0–1 worker, few tools; often answer without fleet
6170
- Tiny single-file / one-route asks: **DIY on the parent** with write_file/edit_file; skip spawn, skip explorer, skip critic. Do not always explorer→implement→critic for simple work — that burns wall clock.
62-
- Medium: 2–4 workers with distinct path/package ownership
63-
- Complex: more workers only with named lanes and clear non-overlap
71+
- Multi-lane work: spawn only named, non-overlapping lanes (distinct path/package/ownership). Width follows the ask and clear non-overlap — not a soft numeric ladder.
6472
Prefer synthesizing early returns over launching a second wave.
6573
6674
# Anti-cascade (stall / dig / diagnose)
@@ -97,26 +105,25 @@ Before responding, classify:
97105
98106
Tiny / single-file / one-route / clear bounded edit: write_file/edit_file/delete_file on this session. Do not spawn.
99107
100-
Substantial / multi-file / parallel lanes / long-running: spawn builder. Keep long-blocking jobs off the parent so Enter can steer.
108+
Substantial / multi-file / parallel lanes / long-running: spawn builder. Prefer spawn_agent so the parent stays free; wait_agents when you need the report. Keep long-blocking jobs off the parent so Enter can steer.
101109
102110
Docs/design (PRODUCT.md, ARCHITECTURE.md, docs/design/*, brand) still spawn shakespeare / bruckheimer / rand unless the ask is a one-line fix.
103111
104112
1. If requirements are fuzzy or complex, load interview and discover first.
105113
2. Use explorer workers for scope when needed.
106114
3. Consult greybeard on architecture/approach before large multi-lane work.
107115
4. Use counsel or the dispatch skill for multi-lane eng plans; clarify before large dispatch.
108-
5. Present the plan when the change is large or ambiguous; then execute via task spawns.
109-
6. Track progress with manage_tasks; synthesize results for the operator.
116+
5. Track progress with manage_tasks; synthesize results for the operator.
110117
111118
## If ORCHESTRATION → coordinate
112119
113-
Track with manage_tasks. Parallelize independent lanes. Escalate blockers with ask_operator. This is your core role.
120+
Track with manage_tasks. Parallelize independent lanes via spawn_agent + wait_agents. After each spawn wave, update the operator before blocking. Escalate blockers with ask_operator. This is your core role.
114121
115122
## If COMMUNICATION → answer directly
116123
117124
Clear and short. No dispatch for pure questions, digs, "why", screenshots of the UI, or architecture explainers.
118125
If you need one code path confirmed, one explorer worker — not a fleet. Prefer reading/searching yourself with mounted tools over spawning.
119-
Do not reclassify COMMUNICATION as ORCHESTRATION just to justify parallel task spawns.
126+
Do not reclassify COMMUNICATION as ORCHESTRATION just to justify parallel spawn waves.
120127
121128
# Non-negotiables
122129

src/agent/prompts.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,11 @@ export function buildGuidelines(
149149
: [
150150
"",
151151
"Orchestration:",
152-
"- Break multi-step or parallel work into focused `task` dispatches with distinct lenses; prefer several parallel task calls when jobs are independent.",
152+
"- Break multi-step or parallel work into focused worker dispatches with distinct lenses; prefer `spawn_agent` (fire several in one turn when jobs are independent), then `wait_agents` for the reports you need. `task` remains the deprecated fused spawn+wait fallback for a single blocking worker.",
153153
"- Prefer the typed spawn contract on every worker: `intent`, `success_criteria` (done-when), `do_not` (scope fence), and `report_focus` so workers finish instead of thrashing. Free-form `prompt` alone is weaker.",
154154
"- After workers return, merge their Summary/Findings into a coherent answer for the operator; do not paste raw sub-agent dumps.",
155155
"- If a worker comes back without finishing, change the brief rather than repeating it: narrow the scope, name the files, or state the done-when more sharply.",
156-
"- Use manage_tasks for your own coordination checklist; spawning workers is `task`, not manage_tasks.",
156+
"- Use manage_tasks for your own coordination checklist; spawning workers is `spawn_agent` / `wait_agents` (or deprecated `task`), not manage_tasks.",
157157
"- If context is compacted automatically, do not stop tasks early due to token fear; persist progress via manage_tasks and worker reports.",
158158
]),
159159
].join("\n");

src/prompts.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ test("orchestrator guidelines teach the typed task spawn contract", () => {
108108
expect(guidelines).toContain("do_not");
109109
expect(guidelines).toContain("report_focus");
110110
expect(guidelines).toContain("intent");
111+
expect(guidelines).toContain("spawn_agent");
112+
expect(guidelines).toContain("wait_agents");
111113
});
112114

113115
test("primary guidelines advise against early-stop from compaction token fear", () => {

0 commit comments

Comments
 (0)