@mu-crew/mu 3.6.2 → 3.8.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 (38) hide show
  1. package/dist/cli.js +12652 -12264
  2. package/dist/cli.js.map +1 -1
  3. package/dist/extension/mu-pi.js +302 -48
  4. package/dist/extension/mu-pi.js.map +1 -1
  5. package/dist/index.d.ts +59 -13
  6. package/dist/index.js +1376 -1205
  7. package/dist/index.js.map +1 -1
  8. package/docs/ARCHITECTURE.md +4 -3
  9. package/docs/architecture/control-socket.md +10 -5
  10. package/docs/architecture/mux.md +4 -1
  11. package/docs/guide/delegate.md +25 -3
  12. package/docs/guide/dispatch.md +22 -5
  13. package/docs/guide/getting-started.md +2 -2
  14. package/docs/guide/recovery.md +11 -6
  15. package/docs/guide/upgrade.md +4 -4
  16. package/docs/reference/env.md +2 -2
  17. package/docs/specs/2026-10-03-keep-driving-nudge.md +21 -0
  18. package/package.json +1 -1
  19. package/skills/mu/SKILL.md +40 -16
  20. package/skills/mu/recipes/adversarial-review.md +14 -6
  21. package/skills/mu/recipes/brief.md +29 -1
  22. package/skills/mu/recipes/codemode-driver.md +19 -9
  23. package/skills/mu/recipes/deep-research.md +6 -5
  24. package/skills/mu/recipes/drift-audit.md +72 -0
  25. package/skills/mu/recipes/findings.md +24 -15
  26. package/skills/mu/recipes/hypothesis-panel.md +5 -3
  27. package/skills/mu/recipes/long-run.md +13 -3
  28. package/skills/mu/recipes/loop-until-done.md +4 -3
  29. package/skills/mu/recipes/orchestrator-loop.md +29 -16
  30. package/skills/mu/recipes/plan.md +10 -6
  31. package/skills/mu/recipes/refute.md +3 -2
  32. package/skills/mu/recipes/remote-workers.md +23 -6
  33. package/skills/mu/recipes/review-panel.md +2 -2
  34. package/skills/mu/recipes/rules-audit.md +10 -5
  35. package/skills/mu/recipes/tasks-or-calls.md +40 -23
  36. package/skills/mu/recipes/tournament.md +4 -3
  37. package/skills/mu/recipes/ultrathink.md +2 -2
  38. package/skills/mu/recipes/worker.md +3 -2
@@ -0,0 +1,72 @@
1
+ # Drift audit
2
+
3
+ Use during a long run to catch a crew drifting from what you decided:
4
+ an instruction that never reached its worker, a batch run on stale
5
+ inputs, work continuing on a closed task. One read-only
6
+ [delegate call](tasks-or-calls.md#delegate-call); it edits nothing.
7
+
8
+ ## When
9
+
10
+ - every few hours of a long run;
11
+ - after each batch report of a chained task (sweep, campaign, soak);
12
+ - after a context compaction or a resume;
13
+ - before you declare a stop rule met.
14
+
15
+ ## Run
16
+
17
+ Issue one delegate call with `record: { task: "<ws>/<umbrella>" }` and
18
+ this brief, with `<ws>` filled in:
19
+
20
+ ```text
21
+ Read-only drift audit of mu workstream <ws>. Change nothing. Sources:
22
+ mu state -w <ws>; mu task list -w <ws> --json; mu task notes <id> -w <ws>;
23
+ mu sql (ops, tasks, task_notes, agents); git log in the repo and in each
24
+ owner's workspace. Never judge by a capped mu log -n window: the claim
25
+ or close you compare against is often older than it.
26
+ 1. Unsent notes: notes on IN_PROGRESS tasks, by someone other than the
27
+ owner, after the owner's last task.claim or agent.send op:
28
+ mu sql "select t.local_id task, a.name owner, n.created_at, substr(n.content,1,80) note from tasks t join workstreams w on w.id=t.workstream_id join agents a on a.id=t.owner_id join task_notes n on n.task_id=t.id where w.name='<ws>' and t.status='IN_PROGRESS' and coalesce(n.author,'')<>a.name and n.created_at > max(coalesce((select max(o.created_at) from ops o where o.intent='task.claim' and o.key='<ws>/'||t.local_id),''), coalesce((select max(o.created_at) from ops o where o.intent='agent.send' and o.key='<ws>' and o.payload like 'agent send '||a.name||' (%'),'')) order by n.created_at"
29
+ Quote each task's last claim (seq, time). For each instruction it
30
+ lists: did the owner act on it (later commits, notes, pane)? Also read
31
+ mu sql "select seq, created_at, payload from ops where intent='agent.send' and key='<ws>'"
32
+ and flag mode=plain or mode=steer with state=busy since=<t> long
33
+ before the send: it queued behind a long turn and may not have landed.
34
+ 2. Stale pins: for each build/binary sha or oracle commit named in an
35
+ IN_PROGRESS note, and each merged fix its task's findings depend on:
36
+ git merge-base --is-ancestor <fix> <pinned>. Exit 1 = pin is stale.
37
+ 3. Closed-task notes: notes added after the task's last task.close op.
38
+ Report each of the top 5 by count as its own finding with its count,
39
+ even when the notes look routine. A late note that reports the
40
+ closed bug again usually ran on a build without the closing fix:
41
+ check its sha with git merge-base --is-ancestor <fix> <sha>.
42
+ mu sql "select t.local_id name, count(*) late from tasks t join workstreams w on w.id=t.workstream_id join task_notes n on n.task_id=t.id where w.name='<ws>' and t.status='CLOSED' and n.created_at > (select max(o.created_at) from ops o where o.intent='task.close' and o.key='<ws>/'||t.local_id) group by t.local_id order by late desc"
43
+ 4. Thin decisions: an ACCEPT/REJECTED/CLOSE/SUPERSEDED note under 40
44
+ chars; a refuter tally with no REFUTER or VERDICT note; a review the
45
+ orchestrator closed with no FILES/COMMANDS note and no commit.
46
+ 5. Silent tasks: IN_PROGRESS with no note or commit for longer than
47
+ the cadence its notes state (default 2h).
48
+ 6. Missing work: a task or finding a note or log line says will be
49
+ filed that does not exist.
50
+ 7. Unrefuted briefs: IN_PROGRESS tasks with no note line starting
51
+ REFUTER , VERDICT: or REFUTE-EXEMPT:.
52
+ End with exactly this, one EVIDENCE line per finding (none when clean):
53
+ VERDICT: <ws> DRIFT-AUDIT CLEAN | FINDINGS <n>
54
+ EVIDENCE: FINDING <high|med|low> <file:line|task> <what> (check <1-7>)
55
+ ```
56
+
57
+ `record` keeps only the VERDICT line and the `EVIDENCE:` lines after
58
+ it, so each finding must be an `EVIDENCE: FINDING` line. The note
59
+ lands headed `REFUTER`, which the refute nudge and decision warnings
60
+ read as a recorded verdict; on an umbrella that is harmless.
61
+
62
+ ## Act
63
+
64
+ Each finding becomes one of:
65
+
66
+ - an `OPEN/triage` task blocking the umbrella ([findings § Record](findings.md#record));
67
+ - a send to the worker it names, per
68
+ [orchestrator-loop § Sending](orchestrator-loop.md#sending)
69
+ (`--interrupt` when its current work is wasted, as with a stale pin).
70
+
71
+ Done when the verdict is recorded on the umbrella and every finding
72
+ is a task or a delivered send.
@@ -69,24 +69,33 @@ across reviewers and creates one task per real problem.
69
69
  or several reviewers on one change: a `triage_<umbrella>` task, run
70
70
  by a fresh agent, so the orchestrator reads only its result.
71
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 |
72
+ [delegate call](tasks-or-calls.md#delegate-call) that passes
73
+ `record: { task: "<ws>/<id>" }`: a fresh agent tries to prove it
74
+ false, and its VERDICT block lands on the finding as a
75
+ `REFUTER <label> (<delegate>, <elapsed>):` note (VERDICT line, 3-6
76
+ EVIDENCE lines), or `REFUTER <label>: no verdict (<outcome>)` when
77
+ it times out or dies. Without `mu_delegate`, write that note yourself
78
+ before deciding
79
+ ([tasks-or-calls § Delegate call](tasks-or-calls.md#delegate-call)).
80
+ Skip this for low-severity style findings. High severity: three
81
+ refuters, accept only if at least two say CONFIRMED.
82
+ 3. **Decide** each one; the decision is the task's state. The reason
83
+ names the deciding evidence, not a tally or a judgement. mu warns
84
+ when a reason is under 40 chars and no note holds a `VERDICT:` line
85
+ or `REFUTER` note. Prose reasons go through a heredoc variable
86
+ ([brief § Quoting](brief.md#quoting)).
87
+
88
+ | Decision | Command | Bad reason |
89
+ | --- | --- | --- |
90
+ | real work | `mu task accept <id> --evidence "2/3 CONFIRMED: refuters 1 and 3 show the checklist:3 vs :33 cycle"` | `valid`, `orchestrator: valid`, `2/3 CONFIRMED` |
91
+ | false | `mu task close <id> --as rejected --why "<the guard or command that disproves it>"` | `refuter REFUTED` |
92
+ | same as another | `mu task close <id> --as duplicate --why "same as <id>"` | |
93
+ | valid, not worth it | `mu task close <id> --as wontfix --why "<cost vs impact>"` | `not worth it` |
94
+ | could not check | stays in triage, with an `UNVERIFIED: <why>` note | |
86
95
 
87
96
  4. **Group** accepted findings that touch the same files into one fix
88
97
  task when separate workers would collide; close the grouped findings
89
- `--as superseded --why 'fixed in <fix-task>'`.
98
+ `--as superseded --why "fixed in <fix-task>"`.
90
99
 
91
100
  Done when `mu task list --substate triage -w <ws>` lists only findings
92
101
  with an `UNVERIFIED` note, and each of those is reported to the human.
@@ -23,9 +23,11 @@ form independent theories; separate agents then try to kill them.
23
23
  3. **Test each hypothesis.** An experiment that changes code (force the
24
24
  race, revert the commit) needs a workspace: `mu task accept` the
25
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.
26
+ data, grep the logs) is a delegate call with `record` on the
27
+ hypothesis ([tasks-or-calls § Delegate call](tasks-or-calls.md#delegate-call)).
28
+ A killed hypothesis closes `--as rejected --why "<the observation
29
+ that contradicts PREDICTS>"`; a survivor gets a `SURVIVED: <evidence>`
30
+ note. Prose reasons: [brief § Quoting](brief.md#quoting).
29
31
  4. **If one survives**, add a fix task for it, then a review task
30
32
  ([adversarial-review](adversarial-review.md)). The fix is accepted
31
33
  only if the step 1 repro stops reproducing.
@@ -6,15 +6,25 @@ or may hit flakes.
6
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
- the bar, not at the first green.
9
+ the bar, not at the first green. For chained batches (sweeps,
10
+ campaigns, soaks) it also names the **inputs** each batch runs on
11
+ (build sha, oracle commit, config) and when to refresh them
12
+ ("rebuild from main before each batch"); each batch report states
13
+ the inputs it used, and the stop rule counts only batches on
14
+ current inputs.
10
15
  2. **Split into independent units** ([fan-out](fan-out.md)). Shard a long proof into tasks
11
16
  that run in parallel, so one flake restarts only its unit. Each unit
12
17
  carries its own criterion.
13
18
  3. **Keep state in the DB.** Progress lives in task notes, not in the
14
19
  orchestrator's context. After a compaction, `mu state` and
15
20
  `mu task notes <id>` are the whole picture.
16
- 4. **Accept evidence, not close notes**
17
- ([orchestrator-loop § Merging](orchestrator-loop.md#merging)).
21
+ 4. **Bound each tool call** to minutes: batches of ≤10 minutes,
22
+ `mu task wait --timeout` re-issued, no open-ended `sleep` loops.
23
+ A `--steer` lands only when the running tool returns.
24
+ 5. **Accept evidence, not close notes**
25
+ ([orchestrator-loop § Merging](orchestrator-loop.md#merging)), and
26
+ run a [drift-audit](drift-audit.md) after each batch report and
27
+ every few hours.
18
28
 
19
29
  Done when every unit is `CLOSED/done` and the criterion from step 1
20
30
  holds on the merged tree.
@@ -25,11 +25,12 @@ written down first does neither.
25
25
  `MEASURE: 14 errors (was 31)`, or `NEW: 0 flaky tests`.
26
26
  4. **After each round, check the rule** yourself, from the measurement
27
27
  command, not from the worker's note.
28
- - Rule met: `mu task close <umbrella> --if-ready --evidence '<stop
29
- command + result>'` (each round blocks the umbrella).
28
+ - Rule met: `mu task close <umbrella> --if-ready --evidence "<stop
29
+ command + result>"` (each round blocks the umbrella).
30
30
  - No progress: stop the loop and decide. Change the approach, split
31
31
  the work, or park the umbrella with
32
- `mu task park <umbrella> --why '<what is stuck>'` and tell the human.
32
+ `mu task park <umbrella> --why "<what is stuck>"` and tell the human.
33
+ Prose reasons: [brief § Quoting](brief.md#quoting).
33
34
  - Otherwise: add the next round and dispatch it.
34
35
 
35
36
  Done when the stop rule holds on the merged tree, run by you.
@@ -39,8 +39,8 @@ keeps it.
39
39
  - **Answers arrive when you stop**, as pi follow-up messages, never
40
40
  mid-turn. pi's `followUpMode: "all"` delivers every waiting answer in
41
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.
42
+ ends with its `VERDICT: <id>` block, so a batch still maps back. Read
43
+ every verdict in the batch before deciding any.
44
44
  - **Workers with workspaces** build and test: about one per CPU core,
45
45
  fewer when each runs the full suite. A remote host has its own
46
46
  session cap ([remote-workers](remote-workers.md)).
@@ -54,12 +54,16 @@ keeps it.
54
54
  Use `--first --on-stall exit`: `--first` populates `.firing`, and
55
55
  `--on-stall exit` stops an unattended wait when a worker needs attention.
56
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
58
- pane (`mu agent read <owner>`) and answer: the worker may be waiting on
59
- you.
60
-
61
- For an idle worker, read the pane, then answer, retry, or release its
62
- task. `MU_IDLE_THRESHOLD_MS` defaults to 5m. A remote owner: poll once
57
+ the owner sat in `needs_input`. Run the exit's `Next:` and answer: the
58
+ worker may be waiting on you. For a pi owner it leads with
59
+ `mu agent wait <owner> --after-runs <runs-1> --json`, which returns the
60
+ last answer at once. The pane read follows because dialogs and crashes
61
+ show only in the pane.
62
+
63
+ For an idle worker, read its last answer (the same `--after-runs`
64
+ wait for pi, else the pane), then answer, retry, or release its task.
65
+ `MU_IDLE_THRESHOLD_MS` defaults to 5m. A remote owner: for pi,
66
+ `mu agent wait --after-runs` first, then poll once; otherwise poll once
63
67
  per turn ([remote-workers](remote-workers.md#step-5-poll-once-per-turn)).
64
68
 
65
69
  ## Merging
@@ -75,7 +79,8 @@ per turn ([remote-workers](remote-workers.md#step-5-poll-once-per-turn)).
75
79
  test once passed with zero cases.
76
80
  - **Accept evidence, not close notes.** Re-run the key measurement from
77
81
  a clean checkout; close notes have claimed unpushed commits. A
78
- worker's "done" counts only once the diff shows the change.
82
+ worker's "done" counts only once the diff shows the change. Your own
83
+ accept and close notes name the check run and the commit.
79
84
  - **Ask whether the check could have failed.** A gate that cannot say
80
85
  no is not evidence: a test filtered to zero cases, a script you wrote
81
86
  agreeing with itself, a fixture you tuned on. A nonzero diff is a
@@ -83,16 +88,24 @@ per turn ([remote-workers](remote-workers.md#step-5-poll-once-per-turn)).
83
88
 
84
89
  ## Sending
85
90
 
86
- - A plain `mu agent send` appends to prior context; use it to steer or
87
- answer. Unrelated work to pi: `mu agent send worker-1 --fresh 'Claim
88
- task_x...'`.
91
+ A running worker sees what you send, never a new task note: deliver
92
+ an instruction for it with a send (or the next `--fresh` brief), and
93
+ keep the note as the durable copy. pi:
94
+
95
+ | `mu agent send` | busy pi acts | Use for |
96
+ | --- | --- | --- |
97
+ | plain | after the run ends | answers, same-task additions |
98
+ | `--steer` | after the current tool call | advice that can wait for the tool boundary |
99
+ | `--interrupt` | now: kills the running tool | a correction that wastes the current work (stale input, wrong target, changed stop rule) |
100
+ | `--fresh` | refused (`--force` drops the run) | unrelated work: new session + prompt |
101
+
89
102
  - claude-code/codex: send `/new` (codex: `/clear`), then the prompt; a
90
- send it cannot confirm prints a `warning:` on stderr. For pi,
91
- `--fresh` does both in one step.
92
- - Use `mu agent send`, not raw mux input. Single-quote prompts
93
- containing shell expansions, or use a quoted heredoc.
103
+ send it cannot confirm prints a `warning:` on stderr.
104
+ - Use `mu agent send`, not raw mux input. Quote prompts per
105
+ [brief](brief.md#quoting).
94
106
  - Cross-workstream wait and claim use qualified refs; only task
95
107
  ownership crosses.
108
+ - A long run drifts unseen: audit it per [drift-audit](drift-audit.md).
96
109
 
97
110
  ## Stopping a worker
98
111
 
@@ -40,14 +40,18 @@ human asks for a file.
40
40
  consumes what B produces. Plan order is not a dependency: an extra
41
41
  edge serialises tracks that could run in parallel. The exception:
42
42
  tasks that edit the same files share a track ([waves](waves.md)).
43
- 7. **Self-review before dispatch.** Walk each spec requirement and name
44
- the task that implements it. Grep the notes for placeholders. Check
45
- that names in INTERFACES match across tasks. Then read the graph back
46
- with `mu task tree task_0 -w <ws> --down`, or `mu state -w <ws>` for the tracks.
43
+ 7. **Self-review before dispatch.** Map each spec requirement to its
44
+ task, grep the notes for placeholders, match INTERFACES names across
45
+ tasks, and read the graph back (`mu task tree task_0 -w <ws> --down`).
46
+ Then refute each brief that makes claims ([call](tasks-or-calls.md#delegate-call),
47
+ all in one turn): "What in this brief is false about the code,
48
+ ambiguous, or would make a correct worker fail review? Cite
49
+ file:line." Rewrite each AMEND. Five of six briefs refuted in one run had
50
+ such a defect, e.g. a fallback test old extensions made unpassable.
47
51
 
48
52
  Done when every spec requirement maps to a task, no note holds a
49
- placeholder, and `mu state` shows the intended parallel tracks. Then
50
- dispatch per [orchestrator-loop](orchestrator-loop.md).
53
+ placeholder, every claim-making brief has a verdict, and `mu state`
54
+ shows the intended parallel tracks. Then dispatch per [orchestrator-loop](orchestrator-loop.md).
51
55
 
52
56
  ## Notes
53
57
 
@@ -27,8 +27,9 @@ fact-check nobody will track, use delegate mode from
27
27
  [delegate call](tasks-or-calls.md#delegate-call), not a task. The
28
28
  refuter gets the finding and the code, not the finder's reasoning,
29
29
  and tries to prove it false: run it, find the guard, read the caller.
30
- Record its verdict on the finding, and apply the skip and
31
- three-refuter rules, as in [findings § Triage](findings.md#triage).
30
+ Pass `record` so its verdict lands on the finding, and apply the
31
+ skip and three-refuter rules, as in
32
+ [findings § Triage](findings.md#triage).
32
33
  Many findings: issue the calls in batches under the cap ([orchestrator-loop § Concurrency](orchestrator-loop.md#concurrency)); to
33
34
  get the verdicts back as one table, see
34
35
  [codemode-driver § Delegate calls](codemode-driver.md#delegate-calls).
@@ -44,7 +44,8 @@ mu agent spawn worker-1 -w big --command \
44
44
  mu task claim t1 -w big --for worker-1 --evidence 'remote on dev'
45
45
  mu agent send worker-1 -w big --fresh '...'
46
46
 
47
- # 5. WAIT: run the claim's one-shot Next: command once per turn
47
+ # 5. WAIT: pi: mu agent wait worker-1 -w big --after-runs <send's runs> --json,
48
+ # then the claim's Next: once. non-pi: run the claim's Next: once per turn
48
49
 
49
50
  # 6. COLLECT: fetch straight from the remote worktree
50
51
  git fetch "ssh://dev/~/ws/worker-1" HEAD && git cherry-pick FETCH_HEAD
@@ -72,13 +73,13 @@ retry next turn, not progress.
72
73
 
73
74
  ### Step 3: the control-socket forward
74
75
 
75
- Spawn reports `ctl ok` when all of these hold (`mu doctor` has a ctl
76
+ Spawn reports `ctl: ok` when all of these hold (`mu doctor` has a ctl
76
77
  row per agent):
77
78
 
78
79
  - The host has the mu extension: run `mu link pi` there.
79
80
  - The ssh is direct. `$MU_SSH_ARGS` sets `ControlMaster=no
80
81
  ControlPath=none`; a multiplexed ssh never binds the forward and spawn
81
- reports `ctl missing`.
82
+ reports `ctl: missing`.
82
83
  - sshd allows the forward. A refused forward kills the pane at spawn
83
84
  (`ExitOnForwardFailure=yes`). Check `AllowStreamLocalForwarding`.
84
85
 
@@ -88,6 +89,16 @@ plus a 10 s cache.
88
89
 
89
90
  ### Step 5: poll once per turn
90
91
 
92
+ The claim's `Next:` mule poll is mandatory. It proves the commit is on
93
+ the host and closes the task. For a pi worker, first block on
94
+ `mu agent wait <name> --after-runs <runs> --json`, with `runs` from
95
+ `mu agent send --json`. It settles exactly over the forwarded socket.
96
+ Without `--after-runs`, a worker that is already idle blocks until
97
+ `--timeout`. If the worker may already be done, pass `<runs-1>`: the
98
+ wait then returns the last answer at once. Then run `Next:` once instead
99
+ of on every turn. On exit 5 (timeout), or on a wait that returns while
100
+ the worker asks a question, run `Next:` anyway.
101
+
91
102
  - Never `sleep` in a tool call. Aborting the loop can leave remote work
92
103
  and a capped channel running.
93
104
  - Set a deadline before dispatch. At expiry, read the pane, then release
@@ -123,14 +134,20 @@ the final gate before the push that matters.
123
134
 
124
135
  ## Traps
125
136
 
126
- ### A spawn on an auth prompt looks healthy
137
+ ### A non-pi spawn on an auth prompt looks healthy
127
138
 
128
139
  With the channel busy, the attach ssh stopped at `Enter a passcode:`.
129
140
  Spawn succeeded, the agent showed `needs_input`, and the prompt went
130
- into the passcode field. Confirm a remote agent got the work
131
- (`mu agent read <name> -n 20`) before trusting it. Send nothing
141
+ into the passcode field. This applies to non-pi CLIs and to
142
+ `--via mux`, which paste into the pane. Confirm such an agent got the
143
+ work (`mu agent read <name> -n 20`) before trusting it. Send nothing
132
144
  sensitive to an unconfirmed pane.
133
145
 
146
+ A pi agent does not paste. Spawn reports `ctl: ok` only when pi
147
+ answers on the socket; otherwise it warns `ctl: missing` or
148
+ `ctl: refused`, and `mu agent send` fails instead of typing into the
149
+ pane.
150
+
134
151
  ### Use the host's real CLI command
135
152
 
136
153
  If your local `$MU_PI_COMMAND` is a wrapper such as `pi-meta
@@ -56,7 +56,7 @@ triage and the umbrella closes with `--if-ready` (workstream mode).
56
56
 
57
57
  - **Reviewers padding the list.** A panel that always finds ten things
58
58
  is guessing.
59
- - **Use different models across angles** where you can; one model's
60
- blind spot repeated five times is still one blind spot.
59
+ - **Vary models across angles** ([Models](../SKILL.md#models-and-thinking-effort)); one model's blind spot
60
+ repeated five times is still one blind spot.
61
61
  - **The panel is not the gate command.** Merge verification still runs on the
62
62
  merged tree ([orchestrator-loop](orchestrator-loop.md#merging)).
@@ -37,7 +37,10 @@ rules are findings: [findings](findings.md) says where they live.
37
37
  line and the rule, and drops false positives (the rule does not
38
38
  apply here, the code already complies, the rule has a stated
39
39
  exception). In workstream mode, a dropped flag is
40
- `close --as rejected --why '<reason>'`; a confirmed one is accepted.
40
+ `close --as rejected --why "<why the rule does not bite here>"`; a
41
+ confirmed one is accepted with `--evidence` naming the flagged line
42
+ ([findings § Triage](findings.md#triage) step 3; quoting:
43
+ [brief § Quoting](brief.md#quoting)).
41
44
  5. **Report or fix** confirmed violations, as in review-panel step 5.
42
45
 
43
46
  Done when every rule from step 1 has a checker result, and every flag
@@ -62,10 +65,12 @@ is decided.
62
65
  corrections from different occasions; a one-off is not a rule.
63
66
  3. **One `OPEN/triage` task per candidate rule**, the rule as the
64
67
  title and its cluster of corrections in the note.
65
- 4. **Refute each candidate** with a [delegate call](tasks-or-calls.md#delegate-call): would it have
66
- prevented the real mistakes in its cluster? Does it contradict an
67
- existing rule? Is it already enforced by a linter or test (then it
68
- needs no prose)? Dropped candidates close `--as rejected`.
68
+ 4. **Refute each candidate** with a
69
+ [delegate call](tasks-or-calls.md#delegate-call) that passes
70
+ `record`: would it have prevented the real mistakes in its cluster?
71
+ Does it contradict an existing rule? Is it already enforced by a
72
+ linter or test (then it needs no prose)? Dropped candidates close
73
+ `--as rejected --why` naming the deciding answer.
69
74
  5. **Propose, don't commit.** The candidates left in triage are the
70
75
  proposal: write them as a diff to the rule file in the umbrella's
71
76
  note, worded per [brief](brief.md) (positive, specific, with the
@@ -7,30 +7,49 @@ hundreds of tasks and a workstream nobody wanted.
7
7
 
8
8
  ## Delegate call
9
9
 
10
- A **delegate call** is one `mu_delegate` tool call in pi. Without the
11
- tool (another harness, a script):
12
-
13
- ```bash
14
- mu agent spawn refuter-1 -w scratch
15
- mu agent send refuter-1 -w scratch --fresh '<brief>'
16
- mu agent wait refuter-1 -w scratch --json # answer in lastText
17
- ```
10
+ A **delegate call** is one `mu_delegate` tool call in pi.
18
11
 
19
12
  - **It starts empty.** The brief carries everything: the finding or
20
- claim, file paths, the criteria, and the answer line to end with
21
- (`VERDICT: ...`, `WINNER: ...`). See [brief](brief.md).
13
+ claim, file paths, the criteria, and the answer to end with. See
14
+ [brief](brief.md). A tournament judge ends with `WINNER: ...`
15
+ ([tournament](tournament.md)). A refuter or claim checker passes
16
+ `record: { task: "<ws>/<id>" }` and ends with:
17
+
18
+ ```text
19
+ VERDICT: <id> CONFIRMED|REFUTED|UNVERIFIED <one line>
20
+ EVIDENCE: <file:line or command + result> (3-6 lines)
21
+ ```
22
+
22
23
  - **Fan out in one turn.** Issue every call for a step together; in pi
23
24
  the answers arrive later as follow-up messages. Calling one, waiting,
24
25
  then the next runs them in series.
25
- - **It leaves no task.** Its `scratch` pane stays attachable while it
26
- runs. `mu_delegate` closes it after a clean finish and keeps it on a
27
- crash, timeout, or API error (`keep: true` always keeps it); the bash
28
- form needs `mu agent close <name> -w scratch`. You record its verdict
29
- on the task it judged.
26
+ - **Its `scratch` pane** stays attachable while it runs; `mu_delegate`
27
+ closes it after a clean finish and keeps it on a crash, timeout, or
28
+ API error (or always, with `keep: true`).
30
29
  - **An API error is yours to decide.** Re-issue the call, or record the
31
30
  check as `UNVERIFIED` on its task, then close the kept pane
32
31
  (`mu_delegate_cancel`, or `mu agent close`).
33
32
 
33
+ Without the tool, write the note `record` would, before deciding:
34
+
35
+ ```bash
36
+ mu agent spawn refuter-1 -w scratch
37
+ runs=$(mu agent send refuter-1 -w scratch --fresh - --json <<'EOF' | jq .runs
38
+ <brief, ending with the VERDICT block>
39
+ EOF
40
+ )
41
+ mu agent wait refuter-1 -w scratch --after-runs "$runs" --json # answer in lastText
42
+ mu task note <id> -w <ws> - <<'EOF'
43
+ REFUTER 1 (refuter-1, 4m 05s):
44
+ <the VERDICT line and EVIDENCE lines, verbatim>
45
+ EOF
46
+ mu agent close refuter-1 -w scratch
47
+ ```
48
+
49
+ A wait that times out or dies leaves `REFUTER 1: no verdict (<outcome>)`.
50
+ `--after-runs` counts a run that finished before the wait started; the
51
+ quoted heredocs keep the evidence verbatim ([brief § Quoting](brief.md#quoting)).
52
+
34
53
  ## The rule
35
54
 
36
55
  **A task is a thing the graph tracks. Checking a thing is a call.**
@@ -43,17 +62,15 @@ mu agent wait refuter-1 -w scratch --json # answer in lastText
43
62
  | the umbrella, and each round of a loop | a skeptic or dedupe pass |
44
63
  | anything that needs its own workspace | a reader or scout whose output feeds one step |
45
64
 
46
- A call writes nothing to mu. Its answer lands on the task it judged:
47
- the orchestrator records the verdict as a note and a state change
48
- (`mu task accept`, `close --as rejected --why '<evidence>'`). The graph
49
- keeps the decision and its evidence without a node per check.
65
+ A call adds no node: its note and your decision land on the task it
66
+ judged ([findings § Triage](findings.md#triage)).
50
67
 
51
68
  ## Examples
52
69
 
53
- - A refuter checks 30 findings: 30 delegate calls, 0 new tasks; each
54
- finding task gets the refuter's evidence and is accepted or closed.
55
- - A tournament over 16 names: 15 judge delegate calls; the winner goes
56
- in the umbrella's note.
70
+ - 30 findings to refute: 30 delegate calls, 0 new tasks; each finding
71
+ gets a `REFUTER` note, then your decision.
72
+ - A tournament over 16 names: 15 judge calls; each round's `WINNER:`
73
+ lines go on the umbrella.
57
74
  - A hypothesis test that reverts commits or forces a race needs a
58
75
  workspace: that one is a task.
59
76
 
@@ -20,8 +20,9 @@ reliable than scoring one.
20
20
  each, so no judge holds the whole field
21
21
  ([tasks-or-calls](tasks-or-calls.md)). The judge sees the two
22
22
  candidates and the rubric and ends with `WINNER: <a|b> <reason>`.
23
- Record each round's results in the umbrella's note; winners meet in
24
- the next round. A round wider than the cap runs in batches
23
+ A judge decides a pair, not a task: no `record`. Record each round
24
+ (pair, winner, reason) in the umbrella's note; winners meet in the
25
+ next round. A round wider than the cap runs in batches
25
26
  ([orchestrator-loop § Concurrency](orchestrator-loop.md#concurrency)).
26
27
  5. **Confirm the winner** with a final check against the rubric, then
27
28
  merge it. Free the losing workspaces.
@@ -35,6 +36,6 @@ final check passed.
35
36
  calls, judge the pair twice with the order swapped; a split decision
36
37
  goes to a third judge.
37
38
  - **Same model, same taste.** Vary the attempt models, and judge with a
38
- model that made no attempt.
39
+ model that made no attempt ([Models](../SKILL.md#models-and-thinking-effort)).
39
40
  - **Ranking many items** (tickets by severity): bucket them in parallel,
40
41
  then run pairwise comparisons only within and across bucket edges.
@@ -43,8 +43,8 @@ and check, skip it.
43
43
  [brief](brief.md) ([plan](plan.md) for a spec-driven build). Rounds
44
44
  of a loop are the one exception: add each when the last closes.
45
45
  5. **Review every unit that ships.** Each commit-producing task gets a
46
- review task ([adversarial-review](adversarial-review.md)), on a
47
- different model where you can. Every finding is a triage task,
46
+ review task ([adversarial-review](adversarial-review.md)) on a
47
+ [comparable model](../SKILL.md#models-and-thinking-effort). Every finding is a triage task,
48
48
  refuted before it is accepted ([findings](findings.md)).
49
49
  6. **Run the loop** ([orchestrator-loop](orchestrator-loop.md)): pipeline
50
50
  merges, verify each merge, keep workers busy
@@ -17,8 +17,9 @@ mu task note <id> "FILES: ...\nDECISION: ...\nVERIFIED: ..."
17
17
  mu task close <id> --evidence "tests pass: ..." # LAST action
18
18
  ```
19
19
 
20
- The note follows the task note contract in SKILL.md. Commit before you
21
- close: the orchestrator cherry-picks your commits, not your tree. A
20
+ The note follows the task note contract in SKILL.md. Keep each tool
21
+ call to minutes (short batches, waits with a timeout): steering reaches
22
+ you only between tool calls. Commit before you close: the orchestrator cherry-picks your commits, not your tree. A
22
23
  review or audit task records each problem per
23
24
  [findings § Record](findings.md#record).
24
25