@mu-crew/mu 3.3.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +45 -31
  2. package/dist/cli.js +812 -429
  3. package/dist/cli.js.map +1 -1
  4. package/dist/extension/mu-pi.js +221 -55
  5. package/dist/extension/mu-pi.js.map +1 -1
  6. package/dist/index.d.ts +33 -4
  7. package/dist/index.js +76 -5
  8. package/dist/index.js.map +1 -1
  9. package/docs/VISION.md +5 -1
  10. package/docs/VOCABULARY.md +4 -1
  11. package/docs/architecture/dag.md +3 -3
  12. package/docs/architecture/ops-log.md +26 -7
  13. package/docs/guide/cleanup.md +19 -0
  14. package/docs/guide/delegate.md +43 -4
  15. package/docs/reference/env.md +1 -0
  16. package/docs/reference/naming.md +18 -0
  17. package/docs/specs/2026-09-29-task-substates.md +1 -1
  18. package/package.json +1 -1
  19. package/prompts/mu-debug.md +8 -0
  20. package/prompts/mu-sweep.md +8 -0
  21. package/prompts/mu-until.md +8 -0
  22. package/prompts/ultrathink.md +2 -1
  23. package/skills/mu/SKILL.md +70 -31
  24. package/skills/mu/recipes/adversarial-review.md +27 -19
  25. package/skills/mu/recipes/{triage.md → backlog-triage.md} +9 -4
  26. package/skills/mu/recipes/codemode-driver.md +68 -20
  27. package/skills/mu/recipes/deep-research.md +23 -8
  28. package/skills/mu/recipes/fan-out.md +15 -11
  29. package/skills/mu/recipes/findings.md +103 -0
  30. package/skills/mu/recipes/hypothesis-panel.md +18 -13
  31. package/skills/mu/recipes/long-run.md +4 -4
  32. package/skills/mu/recipes/loop-until-done.md +7 -3
  33. package/skills/mu/recipes/orchestrator-loop.md +44 -27
  34. package/skills/mu/recipes/plan.md +8 -3
  35. package/skills/mu/recipes/recovery.md +5 -0
  36. package/skills/mu/recipes/refute.md +38 -36
  37. package/skills/mu/recipes/remote-workers.md +7 -2
  38. package/skills/mu/recipes/review-panel.md +36 -31
  39. package/skills/mu/recipes/rules-audit.md +30 -17
  40. package/skills/mu/recipes/tasks-or-calls.md +71 -0
  41. package/skills/mu/recipes/tournament.md +13 -10
  42. package/skills/mu/recipes/ultrathink.md +20 -11
  43. package/skills/mu/recipes/watcher.md +4 -1
  44. package/skills/mu/recipes/waves.md +6 -5
  45. package/skills/mu/recipes/worker.md +3 -1
@@ -1,54 +1,102 @@
1
1
  # Codemode driver
2
2
 
3
- Use when a pi orchestrator with the `codemode` tool runs a recipe with
4
- many parallel units, and one tool call per spawn, send, and wait is
5
- slow. A script can issue those calls in parallel. It stays a driver:
6
- the plan, the state, and the results live in the DB.
3
+ Use when a pi orchestrator with the `codemode` tool has one step that
4
+ dispatches many workers, or many [delegate calls](tasks-or-calls.md#delegate-call)
5
+ whose verdicts you want back as one table. A script issues those calls
6
+ in parallel. It stays a driver: the script is the agent's, not mu's,
7
+ and the plan, the state, and the results live in the DB.
7
8
 
8
9
  ## The rule
9
10
 
10
11
  **Delete the script mid-run and nothing is lost.** That holds when:
11
12
 
12
- - The script calls only `mu` verbs, through `tools.bash`. It reads
13
- state with `mu state --json` / `mu task notes`, never from its own
14
- variables across calls.
13
+ - The script calls only `mu` verbs, through `tools.bash` (or
14
+ `tools.mu_delegate`, below). It reads state with `mu state --json` /
15
+ `mu task notes`, never from its own variables across calls.
15
16
  - Every task it dispatches exists in the DAG before the script starts.
16
17
  The script adds no tasks the orchestrator has not planned, except the
17
- ones a recipe step names (the next round, a `fix_` task).
18
+ ones a recipe step names (the next round, a finding).
18
19
  - `store()` / `load()` hold nothing a re-run needs. The DAG is the
19
20
  cursor.
20
- - The script's source goes into the log before it runs:
21
- `mu log -w <ws> --kind driver '<what it does, which tasks>'`.
21
+ - Before it runs, log a one-line summary and the task ids it touches:
22
+ `mu log -w <ws> --kind driver 'dispatch wave 2: sweep_a sweep_b'`.
22
23
 
23
- ## Shape
24
+ ## Workers
24
25
 
25
26
  ```js
26
27
  // @options: {"timeout_ms": 1800000}
27
28
  const ws = "audit";
29
+ const workers = ["worker-1", "worker-2", "worker-3", "worker-4"]; // within the ceiling
28
30
  const sh = async (c) => {
29
31
  const r = await tools.bash({ command: c });
30
32
  if (r.exit_code !== 0) throw new Error(`${c}: ${r.output}`);
31
33
  return r.output;
32
34
  };
33
- const ready = JSON.parse(await sh(`mu task next -w ${ws} -n 0 --json`)).items;
34
- await Promise.allSettled(ready.slice(0, 4).map(async (t, i) => {
35
- const w = `worker-${i + 1}`;
36
- await sh(`mu task claim ${t.name} -w ${ws} --for ${w} --evidence 'driver dispatch'`);
37
- await sh(`mu agent send ${w} -w ${ws} --fresh 'Work on ${t.name}. Read: mu task notes ${t.name} -w ${ws}'`);
35
+ const ready = JSON.parse(await sh(`mu task next -w ${ws} -n 0 --json`)).items.slice(0, workers.length);
36
+ await Promise.allSettled(ready.map(async (t, i) => {
37
+ await sh(`mu task claim ${t.name} -w ${ws} --for ${workers[i]} --evidence 'driver dispatch'`);
38
+ await sh(`mu workspace refresh ${workers[i]} -w ${ws}`);
39
+ await sh(`mu agent send ${workers[i]} -w ${ws} --fresh 'Work on ${t.name}. Read: mu task notes ${t.name} -w ${ws}'`);
38
40
  }));
39
- const wait = await tools.bash({ command: `mu task wait -w ${ws} ${ready.slice(0, 4).map((t) => t.name).join(" ")} --first --on-stall exit --json` });
41
+ const wait = await tools.bash({ command: `mu task wait -w ${ws} ${ready.map((t) => t.name).join(" ")} --first --on-stall exit --json` });
40
42
  return wait.output;
41
43
  ```
42
44
 
43
- Check field names against `--json` output before relying on them; the
44
- script above is a shape, not an API.
45
+ Size the worker list from the ceiling on the umbrella
46
+ ([orchestrator-loop § Concurrency](orchestrator-loop.md#concurrency)),
47
+ one per ready track. Merge and verify outside the script
48
+ ([orchestrator-loop § Merging](orchestrator-loop.md#merging)). Check
49
+ field names against `--json` output; the script is a shape, not an API.
50
+
51
+ ## Delegate calls
52
+
53
+ `tools.mu_delegate` works from a script, but it returns at once and the
54
+ answers arrive after the script, as follow-up messages: the script
55
+ gains nothing over issuing the calls in one turn. Use it from a script
56
+ only when `codemode.mode` is `only` and the tool is not offered
57
+ directly. Check `Promise.allSettled` results for rejections: past the
58
+ cap, `mu_delegate` refuses.
59
+
60
+ To get the verdicts back as one table instead of one message each, use
61
+ the `scratch` form through `tools.bash`:
62
+
63
+ ```js
64
+ // @options: {"timeout_ms": 1800000}
65
+ const findings = ["f_auth_put", "f_sql_order"]; // finding task ids, at most the cap per script
66
+ const sh = async (c) => (await tools.bash({ command: c })).output;
67
+ const rows = await Promise.all(findings.map(async (id, i) => {
68
+ const a = `refuter-${i + 1}`;
69
+ await sh(`mu agent spawn ${a} -w scratch`);
70
+ await sh(`mu agent send ${a} -w scratch --fresh '<brief for ${id}: ... end with VERDICT: ...>'`);
71
+ const w = JSON.parse(await sh(`mu agent wait ${a} -w scratch --json --timeout 1200`));
72
+ const text = w.agents?.[0]?.lastText ?? "";
73
+ await sh(`mu agent close ${a} -w scratch`);
74
+ return `${id}\t${(text.match(/VERDICT:.*$/m) ?? ["VERDICT: UNVERIFIED no verdict line"])[0]}`;
75
+ }));
76
+ return rows.join("\n");
77
+ ```
78
+
79
+ What the tool did for you, the script now owns:
80
+
81
+ - **The cap.** `MU_DELEGATE_MAX` does not apply to bash spawns: keep
82
+ each script's list at or under it.
83
+ - **Cleanup.** Close each scratch pane; a timed-out one stays, readable
84
+ with `mu agent read <a> -w scratch`.
85
+ - **Recording.** The table is not the record. Record each verdict on its
86
+ finding (`mu task accept`, `close --as rejected --why`), from the
87
+ script or after it returns.
45
88
 
46
89
  ## Traps
47
90
 
48
91
  - **One wave per script.** A script that loops forever hides progress
49
92
  from you and from the human. Dispatch, wait for the first close,
50
- return; merge and verify outside the script, then run it again.
93
+ return; merge and verify outside the script, then run it again. A
94
+ tournament runs one round per script.
51
95
  - **A script timeout cancels the waits, not the workers.** Workers keep
52
96
  running and their tasks stay claimed. Re-read `mu state` and carry on.
53
97
  - **Exit codes are data.** `mu task wait` exit 7 means a worker needs
54
98
  you; return it to the model instead of retrying.
99
+
100
+ Done when the script returned, `mu state` shows the dispatched tasks
101
+ claimed (workers) or every verdict is recorded on its finding (delegate
102
+ calls), and no scratch pane the script opened is left running.
@@ -7,13 +7,21 @@ a claim in a draft holds. This is [refute](refute.md) applied to
7
7
  sources. Workers need a web search tool (pi's `brave_search`, or
8
8
  `curl` on docs) or the code they research.
9
9
 
10
+ **Mode:** delegates by default: the report is the result, and claims
11
+ need no permanent record. Use a workstream for a long run that must
12
+ survive compaction or feeds a tracked decision; then each claim the
13
+ answer rests on is an `OPEN/triage` task, decided like a finding
14
+ ([findings](findings.md)).
15
+
10
16
  ## Steps
11
17
 
12
- 1. **Write the question and the bar** on an umbrella task: the exact
18
+ 1. **Write the question and the bar**, into every searcher's brief
19
+ (delegate mode) or on an umbrella task (workstream mode): the exact
13
20
  question, what a good answer contains (a recommendation, a
14
21
  comparison table, a yes/no with conditions), and how fresh sources
15
22
  must be.
16
- 2. **Split by angle**, one search task per angle: official docs,
23
+ 2. **Split by angle**, one searcher per angle (delegates; tasks only in
24
+ workstream mode): official docs,
17
25
  changelogs and release notes, issue trackers, independent write-ups,
18
26
  the code itself. Each searcher reads, fetches, and writes claims to
19
27
  its note, one per line:
@@ -24,16 +32,23 @@ sources. Workers need a web search tool (pi's `brave_search`, or
24
32
 
25
33
  A claim without a source and a quote is not a claim. Searchers can
26
34
  run on a cheap model.
27
- 3. **Dedupe claims** in one task: merge the same fact from several
28
- sources (keep every source), and flag claims that contradict each
29
- other.
30
- 4. **One check task per claim** that the answer depends on. The checker
35
+ 3. **Dedupe claims**: merge the same fact from several sources (keep
36
+ every source), and flag claims that contradict each other. In
37
+ workstream mode, each surviving claim becomes an `OPEN/triage` task
38
+ titled with the claim, its sources and quotes in the note.
39
+ 4. **One checker per claim** that the answer depends on, as a
40
+ [delegate call](tasks-or-calls.md#delegate-call) in both modes. The checker
31
41
  gets the claim and its sources, not the searcher's reasoning, fetches
32
42
  the source itself, and tries to break the claim: is the quote there,
33
43
  does it say that, is it current, does another source disagree? It
34
44
  ends with `VERDICT: c4 CONFIRMED | REFUTED | UNVERIFIED <evidence>`.
35
- For contradicted claims, one checker per side.
36
- 5. **Synthesize** in a task blocked by every check: answer the question
45
+ For contradicted claims, one checker per side. Batch under the cap
46
+ ([orchestrator-loop § Concurrency](orchestrator-loop.md#concurrency)). In workstream mode the
47
+ verdict is the claim task's state: `accept` for confirmed,
48
+ `close --as rejected` for refuted, an `UNVERIFIED:` note in triage
49
+ otherwise.
50
+ 5. **Synthesize** once every checker has answered (in workstream mode,
51
+ when no claim task is left undecided): answer the question
37
52
  from confirmed claims only, each with its source URL. List
38
53
  unverified claims separately. Note what the sources disagree on and
39
54
  which side the evidence favours.
@@ -6,7 +6,7 @@ some and calls the job done; one task per unit cannot.
6
6
 
7
7
  ## Steps
8
8
 
9
- 1. **Enumerate first, as its own task.** A scout lists the units and
9
+ 1. **Enumerate first.** A scout (a [delegate call](tasks-or-calls.md#delegate-call)) lists the units and
10
10
  writes them to the umbrella's note, one per line. The list is done
11
11
  when it matches a command the scout ran (`rg -l`, a test listing),
12
12
  not when it looks complete. Record the command and the count.
@@ -18,19 +18,23 @@ some and calls the job done; one task per unit cannot.
18
18
  mu task block sweep -w <ws> --by sweep_auth_ts
19
19
  ```
20
20
 
21
- Put the shared brief and acceptance criteria on the umbrella; each
22
- unit task's note holds only what differs.
23
- 3. **Cap concurrency.** Spawn at most one agent per ready track, and no
24
- more than the machine can build and test at once. Tell workers to
25
- avoid repo-wide commands so more can run.
26
- 4. **Pipeline.** Dispatch, wait `--first`, merge, dispatch the next unit
27
- to the freed worker with `--fresh`. Units that touch the same files
21
+ Put the shared [brief](brief.md) and acceptance criteria on the
22
+ umbrella; each unit task's note holds only what differs. A sweep that
23
+ only checks (no commits) makes each unit a delegate call instead
24
+ ([tasks-or-calls](tasks-or-calls.md)).
25
+ 3. **Cap concurrency** ([orchestrator-loop § Concurrency](orchestrator-loop.md#concurrency)).
26
+ Spawn at most one agent per ready track. Tell workers to avoid
27
+ repo-wide commands so more can run.
28
+ 4. **Pipeline.** Dispatch, wait `--first`, merge
29
+ ([orchestrator-loop § Merging](orchestrator-loop.md#merging)), dispatch
30
+ the next unit to the freed worker with `--fresh`. With `codemode`, a
31
+ [driver](codemode-driver.md) can dispatch each batch. Units that touch the same files
28
32
  go on one track (see [waves](waves.md)).
29
33
  5. **Review per unit** when a wrong unit is costly: add a review task
30
34
  per unit ([adversarial-review](adversarial-review.md)).
31
- 6. **Synthesize** when the output is a report, not commits: a final
32
- task blocked by every unit reads their notes and writes one result.
33
- It reads notes, not transcripts.
35
+ 6. **Synthesize** when the output is a report, not commits: one
36
+ delegate call reads the unit notes (not transcripts) and writes one
37
+ result into the umbrella's note.
34
38
 
35
39
  Done when `mu task close sweep --if-ready` closes the umbrella: every
36
40
  unit is closed, and the closed count matches the step 1 count.
@@ -0,0 +1,103 @@
1
+ # Findings
2
+
3
+ Use whenever an agent reviews, audits, checks, or researches something
4
+ and reports problems: every recipe that produces findings follows this
5
+ one. It decides where findings live, and how they become work.
6
+
7
+ ## Pick the mode first
8
+
9
+ Ask: **will anyone act on these findings through the DAG?**
10
+
11
+ | Situation | Mode | Findings live in |
12
+ | --- | --- | --- |
13
+ | The result is read once and acted on directly: PR comments, doc edits, a go/no-go, a draft fact-check | **Delegate** | the delegate's answer |
14
+ | Findings become work agents fix, or must be tracked to closure | **Workstream** | one `OPEN/triage` task per finding |
15
+
16
+ Delegate mode keeps reviews of other people's PRs and docs out of the
17
+ ops log, which is permanent and syncs to every machine. Workstream mode
18
+ is the mu way for your own work: the graph shows every finding, who
19
+ decided it, and the fix.
20
+
21
+ ## Delegate mode
22
+
23
+ 1. Run reviewers as [delegate calls](tasks-or-calls.md#delegate-call):
24
+ one per angle or slice, all in one turn so they run in parallel,
25
+ under the cap ([orchestrator-loop § Concurrency](orchestrator-loop.md#concurrency)).
26
+ 2. Each delegate ends its answer with one line per finding:
27
+
28
+ ```text
29
+ FINDING: high src/api/user.ts:88 PUT handler skips the auth check EVIDENCE: curl -X PUT ... returned 200
30
+ ```
31
+
32
+ 3. You read the answers, merge duplicates, and act: post the comments,
33
+ edit the doc, give the verdict.
34
+ 4. **Promote** when the findings turn out to be work: create one
35
+ `OPEN/triage` task per line (below) and continue in workstream mode.
36
+
37
+ Done when every delegate answered and every finding line was acted on
38
+ or dropped with a reason.
39
+
40
+ ## Workstream mode
41
+
42
+ ### Record
43
+
44
+ The reviewer records each finding as a task in triage, blocking the
45
+ review's umbrella so the umbrella cannot close while findings are
46
+ undecided:
47
+
48
+ ```bash
49
+ mu task add -w <ws> --triage \
50
+ -t "high: PUT /user skips the auth check" -i 70 -e 0.5 \
51
+ --note 'FINDING: high src/api/user.ts:88 PUT skips the auth check EVIDENCE: curl -X PUT ... returned 200 without a token'
52
+ mu task block <umbrella> -w <ws> --by <finding-id>
53
+ ```
54
+
55
+ The title starts with the severity. The note is one `FINDING:` line,
56
+ the same shape everywhere: `FINDING: <severity> <file:line> <what>
57
+ EVIDENCE: <command + output>`. `OPEN/triage` keeps the finding out of `mu task next`, and
58
+ `claim` refuses it, so no worker starts on an undecided finding.
59
+
60
+ **More than 5 findings from one reviewer:** the reviewer writes them as
61
+ `FINDING:` lines in its own task note instead. Before that reviewer
62
+ task closes, the orchestrator adds `triage_<umbrella>` blocking the
63
+ umbrella; the triage agent ([Triage](#triage) step 1) merges duplicates
64
+ across reviewers and creates one task per real problem.
65
+
66
+ ### Triage
67
+
68
+ 1. **Who:** a handful of findings, the orchestrator triages itself. Many,
69
+ or several reviewers on one change: a `triage_<umbrella>` task, run
70
+ by a fresh agent, so the orchestrator reads only its result.
71
+ 2. **Refute** each finding before accepting it with a
72
+ [delegate call](tasks-or-calls.md#delegate-call): a fresh agent tries
73
+ to prove it false and ends with
74
+ `VERDICT: <id> CONFIRMED | REFUTED | UNVERIFIED <evidence>`. Skip this
75
+ for low-severity style findings. High severity: three refuters,
76
+ accept only if at least two say CONFIRMED.
77
+ 3. **Decide** each one; the decision is the task's state:
78
+
79
+ | Decision | Command |
80
+ | --- | --- |
81
+ | real work | `mu task accept <id> --evidence '<what confirmed it>'` |
82
+ | false | `mu task close <id> --as rejected --why '<evidence>'` |
83
+ | same as another | `mu task close <id> --as duplicate --why 'same as <id>'` |
84
+ | valid, not worth it | `mu task close <id> --as wontfix --why '<reason>'` |
85
+ | could not check | stays in triage, with an `UNVERIFIED: <why>` note |
86
+
87
+ 4. **Group** accepted findings that touch the same files into one fix
88
+ task when separate workers would collide; close the grouped findings
89
+ `--as superseded --why 'fixed in <fix-task>'`.
90
+
91
+ Done when `mu task list --substate triage -w <ws>` lists only findings
92
+ with an `UNVERIFIED` note, and each of those is reported to the human.
93
+
94
+ ### Fix and close
95
+
96
+ Accepted findings are ordinary tasks: dispatch them, review the fix
97
+ ([adversarial-review](adversarial-review.md)), merge. The umbrella
98
+ closes with `mu task close <umbrella> --if-ready` once every finding is
99
+ `CLOSED/*`. A plain `close` would succeed with findings still open.
100
+
101
+ The report is a query, not a document: `mu task list -w <ws>
102
+ --substate rejected`, `--substate duplicate`, `--status OPEN`, and the
103
+ notes on each task.
@@ -9,19 +9,23 @@ form independent theories; separate agents then try to kill them.
9
9
 
10
10
  1. **Write the symptom** on the umbrella: what happens, how often, the
11
11
  repro command, and what would count as fixed.
12
- 2. **One hypothesis task per evidence source**: logs, the code path,
13
- recent commits, data, environment. Each agent sees only its source,
14
- so the theories do not anchor on each other. Each ends with:
15
-
16
- ```text
17
- HYPOTHESIS: h2 <cause>
18
- PREDICTS: <an observation that is true if h2 is the cause, false otherwise>
12
+ 2. **One reader per evidence source** (a [delegate call](tasks-or-calls.md#delegate-call)): logs, the
13
+ code path, recent commits, data, environment. Each sees only its
14
+ source, so the theories do not anchor on each other. Record each
15
+ theory as an `OPEN/triage` task blocking the umbrella, decided like
16
+ a finding ([findings § Triage](findings.md#triage)):
17
+
18
+ ```bash
19
+ mu task add -w <ws> --triage -t "h: <cause>" -i 60 -e 0.5 \
20
+ --note 'PREDICTS: <an observation true if this is the cause, false otherwise>'
19
21
  ```
20
22
 
21
- 3. **One test task per hypothesis**, in its own workspace. The tester
22
- builds the experiment that would kill the hypothesis (force the race,
23
- revert the commit, feed the data) and reports
24
- `VERDICT: h2 SURVIVES | KILLED <evidence>`.
23
+ 3. **Test each hypothesis.** An experiment that changes code (force the
24
+ race, revert the commit) needs a workspace: `mu task accept` the
25
+ hypothesis and dispatch it as a task. One that only reads (feed the
26
+ data, grep the logs) is a delegate call. A killed hypothesis closes
27
+ `--as rejected --why '<evidence>'`; a survivor gets a
28
+ `SURVIVED: <evidence>` note.
25
29
  4. **If one survives**, add a fix task for it, then a review task
26
30
  ([adversarial-review](adversarial-review.md)). The fix is accepted
27
31
  only if the step 1 repro stops reproducing.
@@ -29,12 +33,13 @@ form independent theories; separate agents then try to kill them.
29
33
  ([loop-until-done](loop-until-done.md)): the new hypothesis tasks get
30
34
  the killed hypotheses and their evidence as input.
31
35
 
32
- Done when a fix closed `ACCEPT` and the repro from step 1 no longer
36
+ Done when the fix's review task is `CLOSED/done` (ACCEPT) and the
37
+ repro from step 1 no longer
33
38
  reproduces at the rate step 1 recorded.
34
39
 
35
40
  ## Traps
36
41
 
37
42
  - **Two survivors** usually means the experiments were too weak. Design
38
43
  one experiment that separates them before you fix either.
39
- - **Flaky repros need counts.** "Passed once" proves nothing for a 1 in
44
+ - **Flaky repros need counts** ([long-run](long-run.md) step 1). "Passed once" proves nothing for a 1 in
40
45
  50 failure. Put the run count in step 1.
@@ -3,18 +3,18 @@
3
3
  Use when a task or proof runs for hours, crosses context compaction,
4
4
  or may hit flakes.
5
5
 
6
- 1. **Fix done first.** Before dispatch, write the completion criterion
6
+ 1. **Define done first.** Before dispatch, write the completion criterion
7
7
  into the task note: the checks, how many runs must agree, the
8
8
  allowed variance. A worker that finds the bar in the note stops at
9
9
  the bar, not at the first green.
10
- 2. **Split into independent units.** Shard a long proof into tasks
10
+ 2. **Split into independent units** ([fan-out](fan-out.md)). Shard a long proof into tasks
11
11
  that run in parallel, so one flake restarts only its unit. Each unit
12
12
  carries its own criterion.
13
13
  3. **Keep state in the DB.** Progress lives in task notes, not in the
14
14
  orchestrator's context. After a compaction, `mu state` and
15
15
  `mu task notes <id>` are the whole picture.
16
- 4. **Accept evidence, not close notes.** Re-run the key measurement
17
- from a clean checkout before you count a unit as done.
16
+ 4. **Accept evidence, not close notes**
17
+ ([orchestrator-loop § Merging](orchestrator-loop.md#merging)).
18
18
 
19
19
  Done when every unit is `CLOSED/done` and the criterion from step 1
20
20
  holds on the merged tree.
@@ -15,14 +15,18 @@ written down first does neither.
15
15
  NO-PROGRESS: two rounds in a row reduce the error count by zero
16
16
  ```
17
17
 
18
- 2. **Each round is a task**, blocked by the previous one:
18
+ 2. **Each round is a task** that blocks the umbrella and is blocked by
19
+ the previous round:
19
20
  `round_1`, `round_2`, .... Add the next round only when the current
20
- one closes; never pre-create rounds.
21
+ one closes; never pre-create rounds. Dispatch each per
22
+ [orchestrator-loop](orchestrator-loop.md); multi-hour loops follow
23
+ [long-run](long-run.md).
21
24
  3. **Each round ends with its measurement** in the note:
22
25
  `MEASURE: 14 errors (was 31)`, or `NEW: 0 flaky tests`.
23
26
  4. **After each round, check the rule** yourself, from the measurement
24
27
  command, not from the worker's note.
25
- - Rule met: close the umbrella.
28
+ - Rule met: `mu task close <umbrella> --if-ready --evidence '<stop
29
+ command + result>'` (each round blocks the umbrella).
26
30
  - No progress: stop the loop and decide. Change the approach, split
27
31
  the work, or park the umbrella with
28
32
  `mu task park <umbrella> --why '<what is stuck>'` and tell the human.
@@ -8,42 +8,59 @@ the loop and the reasons behind them.
8
8
 
9
9
  1. `mu state -w <ws>` — read agents, IN_PROGRESS, ready tasks,
10
10
  parallel tracks.
11
- 2. Spawn at most one agent per independent ready track.
11
+ 2. Spawn at most one agent per independent ready track ([waves](waves.md)
12
+ when workers share files).
12
13
  3. **Claim before sending — even one-shot reviewers/scouts.**
13
14
  `mu task claim <id> -w <ws> --for <agent> --evidence "..."`.
14
15
  If no task exists, `mu task add` first (`--note 'REPRO: ...'` when
15
16
  the title is not enough). Ownership is durable and waitable; agent
16
- state is not.
17
- 4. Send each new task with `mu agent send <w> --fresh '...'` (new
18
- session + prompt in one step; refuses while busy): task id,
19
- files/notes to read, workspace path, validation command, scope
20
- guards, task note contract. Follow the `Next:` block; it picks
21
- `--fresh` vs `--steer` for you.
22
- 5. End with a loud final-action block:
23
-
24
- ```text
25
- ⚠️ FINAL ACTION
26
- git commit -am '...' THEN
27
- mu task close <id> -w <ws> --evidence '...'
28
- ```
29
-
30
- 6. `mu task wait ... --first --on-stall exit --json`.
31
- 7. Cherry-pick the closed worker's **new** commit(s), verify the MERGE,
17
+ state is not. Review tasks: [adversarial-review](adversarial-review.md).
18
+ 4. Run `mu workspace refresh <w>`, then send a [brief](brief.md) with
19
+ `mu agent send <w> --fresh '...'` (new session + prompt in one step;
20
+ refuses while busy). The brief ends with its final-action block.
21
+ 5. `mu task wait ... --first --on-stall exit --json`.
22
+ 6. Cherry-pick the closed worker's **new** commit(s), verify the MERGE,
32
23
  then continue the loop in the same turn. Do not barrier or loop in
33
24
  shell.
34
25
  Only `CLOSED/done` ships; other closes: read the reason note.
35
- 8. Repeat from `mu state`.
26
+ 7. Repeat from `mu state`.
27
+
28
+ ## Concurrency
29
+
30
+ Write the ceiling on the umbrella before the first wave
31
+ (`CONCURRENCY: delegates 12, workers 4`) so a resumed orchestrator
32
+ keeps it.
33
+
34
+ - **[Delegate calls](tasks-or-calls.md#delegate-call)** (read-only): 10 to 20 at once is reasonable.
35
+ Token spend and provider rate limits bind first; start near 8 and
36
+ raise after a clean wave. `mu_delegate` runs at most
37
+ `MU_DELEGATE_MAX` (default 16) and queues up to four times that
38
+ (`queued-N`, started as slots free); past that it refuses.
39
+ - **Answers arrive when you stop**, as pi follow-up messages, never
40
+ mid-turn. pi's `followUpMode: "all"` delivers every waiting answer in
41
+ one turn instead of one turn each; each answer names its delegate and
42
+ ends with its `VERDICT: <id>` line, so a batch still maps back. Record
43
+ every verdict in the batch before acting on any.
44
+ - **Workers with workspaces** build and test: about one per CPU core,
45
+ fewer when each runs the full suite. A remote host has its own
46
+ session cap ([remote-workers](remote-workers.md)).
47
+ - **Stream, do not batch.** Keep the pool full: dispatch the next unit
48
+ when one closes, rather than waiting for a whole wave. With the
49
+ `codemode` tool, a [driver](codemode-driver.md) can dispatch a batch
50
+ of workers in one script.
36
51
 
37
52
  ## Waiting
38
53
 
39
54
  Use `--first --on-stall exit`: `--first` populates `.firing`, and
40
55
  `--on-stall exit` stops an unattended wait when a worker needs attention.
41
- Exit 6 is a dead pane; exit 7 is an owner in `needs_input`. Read that
56
+ Exit 6: the owner's pane died and the reaper reopened the task; exit 7:
57
+ the owner sat in `needs_input`. Read that
42
58
  pane (`mu agent read <owner>`) and answer: the worker may be waiting on
43
- you. Questions are cheaper than rework.
59
+ you.
44
60
 
45
61
  For an idle worker, read the pane, then answer, retry, or release its
46
- task. `MU_IDLE_THRESHOLD_MS` defaults to 5m.
62
+ task. `MU_IDLE_THRESHOLD_MS` defaults to 5m. A remote owner: poll once
63
+ per turn ([remote-workers](remote-workers.md#step-5-poll-once-per-turn)).
47
64
 
48
65
  ## Merging
49
66
 
@@ -51,10 +68,10 @@ task. `MU_IDLE_THRESHOLD_MS` defaults to 5m.
51
68
  new commits, verify, dispatch the next. An umbrella wait hides progress;
52
69
  merging stale branches can restore reverted code.
53
70
  - **Verify the merge, not the worker's rerun.** Only the combination
54
- with moved main is new; that found three breaks rerunning found none
55
- of. Remote hosts: [run the merged gate there](remote-workers.md#run-the-merged-gate-on-the-host).
56
- - **Push only from a green gate.** Make `git push` the last line under
57
- `set -e`. Check the gate runs what it claims: an env-gated randomized
71
+ with moved main is new, and it breaks in ways the worker's own run
72
+ cannot show. Remote hosts: [run the merged gate there](remote-workers.md#run-the-merged-gate-on-the-host).
73
+ - **Push only when the gate command passes.** Make `git push` the last
74
+ line under `set -e`. Check the gate command runs what it claims: an env-gated randomized
58
75
  test once passed with zero cases.
59
76
  - **Accept evidence, not close notes.** Re-run the key measurement from
60
77
  a clean checkout; close notes have claimed unpushed commits. A
@@ -63,8 +80,6 @@ task. `MU_IDLE_THRESHOLD_MS` defaults to 5m.
63
80
  no is not evidence: a test filtered to zero cases, a script you wrote
64
81
  agreeing with itself, a fixture you tuned on. A nonzero diff is a
65
82
  failure even when the command exited 0.
66
- - **Dispatch from current main.** Reset the worker's worktree to main
67
- before each task.
68
83
 
69
84
  ## Sending
70
85
 
@@ -85,3 +100,5 @@ task. `MU_IDLE_THRESHOLD_MS` defaults to 5m.
85
100
  context, waits for idle; exit 5 = still busy; queued follow-ups return
86
101
  to the editor unsent). Then `mu agent kick` (pi unresponsive, or
87
102
  non-pi; local panes only), then `mu agent close`.
103
+
104
+ Done when every task is closed, or a decision only a human can make blocks all progress (SKILL.md § Orchestrator rules).
@@ -17,9 +17,12 @@ human asks for a file.
17
17
  in two or three sentences, and the global constraints copied
18
18
  verbatim from the spec. Every other task is blocked by it; close it
19
19
  at once. It carries notes, not work.
20
- 4. **Write each task's note** as a [brief](brief.md):
20
+ 4. **Write each task's note** as a [brief](brief.md): its Shape, plus
21
+ INTERFACES and STEPS:
21
22
 
22
23
  ```text
24
+ GOAL: one sentence
25
+ DONE WHEN: checkable, exhaustive criterion
23
26
  FILES: Create/Modify/Test with exact paths (line ranges if known)
24
27
  INTERFACES: Consumes: <exact signatures from earlier tasks>
25
28
  Produces: <exact names and types later tasks use>
@@ -35,14 +38,16 @@ human asks for a file.
35
38
  of order.
36
39
  6. **Add edges for dependencies only.** `mu task block A --by B` when A
37
40
  consumes what B produces. Plan order is not a dependency: an extra
38
- edge serialises tracks that could run in parallel.
41
+ edge serialises tracks that could run in parallel. The exception:
42
+ tasks that edit the same files share a track ([waves](waves.md)).
39
43
  7. **Self-review before dispatch.** Walk each spec requirement and name
40
44
  the task that implements it. Grep the notes for placeholders. Check
41
45
  that names in INTERFACES match across tasks. Then read the graph back
42
46
  with `mu task tree task_0 -w <ws> --down`, or `mu state -w <ws>` for the tracks.
43
47
 
44
48
  Done when every spec requirement maps to a task, no note holds a
45
- placeholder, and `mu state` shows the intended parallel tracks.
49
+ placeholder, and `mu state` shows the intended parallel tracks. Then
50
+ dispatch per [orchestrator-loop](orchestrator-loop.md).
46
51
 
47
52
  ## Notes
48
53
 
@@ -19,8 +19,13 @@ when done in the wrong order.
19
19
  mu never runs ssh or rsync; `mu sync` prints the line.
20
20
  `--repair <peer>` is always safe. Agents, workspaces, and task
21
21
  ownership never travel.
22
+ - **`mu db forget <ws...>`** deletes torn-down workstreams' ops for
23
+ good (no undo); `mu db compact` only blanks redundant tombstones. Both
24
+ back up beside the DB first. Forget only what the human named.
22
25
  - **`mu doctor --deep` DRIFT** (exit 5) is a capture bug: back up and
23
26
  report it. Do not rebuild; the live rows may hold work the log missed.
24
27
  - The `doctor` `disk` section is report-only: an orphan dir may hold the
25
28
  only copy of uncommitted work, so mu prints cleanup commands and runs
26
29
  none. Read before you run them.
30
+
31
+ Done when `mu doctor` reports no DRIFT and every cleanup command you ran was read first.