@mu-crew/mu 3.10.1 → 3.11.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.
- package/dist/{chunk-7OQNJWBY.js → chunk-2FJK6OOZ.js} +3 -3
- package/dist/{chunk-XXK7FR37.js → chunk-DXKJY3NT.js} +3 -3
- package/dist/{chunk-WT7IN2OD.js → chunk-JYZUNPPO.js} +44 -3
- package/dist/chunk-JYZUNPPO.js.map +1 -0
- package/dist/{chunk-YIF3X32A.js → chunk-WYBOR4FX.js} +2 -2
- package/dist/{chunk-YIF3X32A.js.map → chunk-WYBOR4FX.js.map} +1 -1
- package/dist/{cli-KJGVEZW5.js → cli-GRAPF5VC.js} +14 -9
- package/dist/cli-GRAPF5VC.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/extension/mu-pi.js +2 -2
- package/dist/extension/mu-pi.js.map +1 -1
- package/dist/index.d.ts +22 -2
- package/dist/index.js +5 -3
- package/dist/{tui-X2XICJTN.js → tui-DGDEH4JX.js} +5 -5
- package/dist/{tui-X2XICJTN.js.map → tui-DGDEH4JX.js.map} +1 -1
- package/dist/tui-sync-worker.js +1 -1
- package/docs/VISION.md +3 -0
- package/docs/guide/delegate.md +1 -1
- package/package.json +1 -1
- package/skills/mu/SKILL.md +29 -37
- package/skills/mu/recipes/adversarial-review.md +26 -21
- package/skills/mu/recipes/brief.md +3 -2
- package/skills/mu/recipes/codemode-driver.md +9 -6
- package/skills/mu/recipes/deep-research.md +2 -1
- package/skills/mu/recipes/drift-audit.md +5 -4
- package/skills/mu/recipes/fan-out.md +5 -3
- package/skills/mu/recipes/findings.md +7 -3
- package/skills/mu/recipes/hypothesis-panel.md +2 -1
- package/skills/mu/recipes/models.md +102 -0
- package/skills/mu/recipes/orchestrator-loop.md +6 -8
- package/skills/mu/recipes/plan.md +5 -5
- package/skills/mu/recipes/recovery.md +9 -8
- package/skills/mu/recipes/refute.md +7 -4
- package/skills/mu/recipes/remote-workers.md +22 -14
- package/skills/mu/recipes/review-panel.md +4 -3
- package/skills/mu/recipes/rules-audit.md +7 -6
- package/skills/mu/recipes/tasks-or-calls.md +6 -5
- package/skills/mu/recipes/tournament.md +5 -2
- package/skills/mu/recipes/ultrathink.md +6 -4
- package/skills/mu/recipes/watcher.md +4 -0
- package/skills/mu/recipes/waves.md +5 -4
- package/skills/mu/recipes/worker.md +2 -2
- package/dist/chunk-WT7IN2OD.js.map +0 -1
- package/dist/cli-KJGVEZW5.js.map +0 -1
- /package/dist/{chunk-7OQNJWBY.js.map → chunk-2FJK6OOZ.js.map} +0 -0
- /package/dist/{chunk-XXK7FR37.js.map → chunk-DXKJY3NT.js.map} +0 -0
package/dist/tui-sync-worker.js
CHANGED
package/docs/VISION.md
CHANGED
|
@@ -201,6 +201,9 @@ mu agent spawn worker-1 --cli pi_mini
|
|
|
201
201
|
mu agent spawn reviewer-1 --cli pi_big
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
+
The skill's [model tiers](../skills/mu/recipes/models.md) are advice to
|
|
205
|
+
the agent choosing; mu reads none of it.
|
|
206
|
+
|
|
204
207
|
## What it enables
|
|
205
208
|
|
|
206
209
|
- **Visible crews.** Spawn agents once and send them work all day. Each
|
package/docs/guide/delegate.md
CHANGED
|
@@ -22,7 +22,7 @@ Delegates called in one turn run in parallel.
|
|
|
22
22
|
| `timeout` | Seconds to wait for the answer (default 3600). After it, the answer does not come back; the follow-up gives the `mu agent wait` command. |
|
|
23
23
|
| `workspace` | Own VCS checkout, for delegates that edit files. The follow-up names its path. It isolates repository edits only. |
|
|
24
24
|
| `cli` | Key for `$MU_<CLI>_COMMAND` (default `pi`). Only keys set in pi's environment exist. |
|
|
25
|
-
| `model` | pi `--model` value, appended to the cli's command (`sonnet`, `
|
|
25
|
+
| `model` | pi `--model` value, appended to the cli's command (`sonnet`, `<provider>/<model>:high`, copied from `pi --list-models`). Varies models across a panel. tmux only: herdr refuses a command override. |
|
|
26
26
|
| `keep` | Keep the pane after it finishes, to talk to it again. |
|
|
27
27
|
| `record` | `{ task, workstream? }` (or `task: "<ws>/<task>"`): write the answer's verdict onto that task as a note. See [Record a verdict](#record-a-verdict). |
|
|
28
28
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mu-crew/mu",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.11.0",
|
|
4
4
|
"description": "A persistent, observable crew of pi agents running in one tmux or herdr session per workstream, coordinated through a built-in task DAG.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
package/skills/mu/SKILL.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mu
|
|
3
3
|
description: >-
|
|
4
|
-
Fresh-context
|
|
4
|
+
Fresh-context delegates (mu's counterpart to hidden subagents) and crews
|
|
5
|
+
in tmux/herdr panes. Check before you
|
|
5
6
|
commit: before acting on a claim, root cause, plan, fix or brief, have a
|
|
6
7
|
`mu_delegate` call refute it. Also for a fresh delegate's second look at
|
|
7
8
|
your own work or diff; parallel read-only research, investigation or fan-out
|
|
@@ -24,14 +25,14 @@ not in `--help` do not exist.
|
|
|
24
25
|
Default output is a card on stdout plus a `Next:` block. Read both.
|
|
25
26
|
Every verb takes `--json`: one stdout object; collections are
|
|
26
27
|
`{items, count}`, except `mu agent list` (`{agents, orphans}`); `mu sql --json` is bare rows; `mu log --tail` is
|
|
27
|
-
NDJSON
|
|
28
|
+
NDJSON; `mu log` writes print text even with `--json`. Errors are `{error,message,nextSteps,exitCode}` on stderr
|
|
28
29
|
(validation errors add `usage`). **`nextSteps` survives in JSON.**
|
|
29
30
|
|
|
30
31
|
## Vocabulary
|
|
31
32
|
|
|
32
33
|
- **workstream** — one **mux session** `mu-<name>` (tmux session or
|
|
33
34
|
herdr workspace) and one DB partition.
|
|
34
|
-
- **agent** — named
|
|
35
|
+
- **agent** — named process in a pane (you may be one); a **worker** is an agent claiming tasks.
|
|
35
36
|
- **mux** — tmux or herdr, one per invocation. `mu doctor` names it;
|
|
36
37
|
`MU_MUX` forces it. `mu agent kick` is Linux-only on herdr.
|
|
37
38
|
- **control socket (ctl)** — how mu drives a pi agent: the mu pi
|
|
@@ -44,7 +45,8 @@ NDJSON. Errors are `{error,message,nextSteps,exitCode}` on stderr
|
|
|
44
45
|
- **claim / release** — atomic take/clear of `tasks.owner`.
|
|
45
46
|
- **note** — append-only task context; survives sessions.
|
|
46
47
|
- **track** — tasks connected by `block` edges (`mu task block B --by A`
|
|
47
|
-
puts B on A's track)
|
|
48
|
+
puts B on A's track). Spawn one agent per ready task, not per track:
|
|
49
|
+
an umbrella puts all its units on one track.
|
|
48
50
|
- **workspace** — per-agent VCS copy under
|
|
49
51
|
`<state-dir>/workspaces/<workstream>/<agent>/`.
|
|
50
52
|
|
|
@@ -62,7 +64,7 @@ Recipe words, the same in every recipe:
|
|
|
62
64
|
- **finding** — one reported problem, recorded as an `OPEN/triage` task.
|
|
63
65
|
- **verdict** — a check's answer: `VERDICT: <id> CONFIRMED | REFUTED |
|
|
64
66
|
UNVERIFIED <one line>` plus `EVIDENCE:` lines (or ACCEPT | REJECT for
|
|
65
|
-
a review gate).
|
|
67
|
+
a review gate). REFUTED on a brief means it holds a false claim: rewrite it.
|
|
66
68
|
- **stop rule** — the command and condition that end a loop, written on
|
|
67
69
|
the umbrella first ([loop-until-done](recipes/loop-until-done.md)).
|
|
68
70
|
|
|
@@ -76,12 +78,12 @@ or inspection.
|
|
|
76
78
|
|
|
77
79
|
Before you act on a claim, root cause, plan, fix or brief, or to get a second
|
|
78
80
|
look at your own work or diff, make a [delegate call](recipes/tasks-or-calls.md#delegate-call)
|
|
79
|
-
that tries to refute it
|
|
81
|
+
that tries to refute it, on another model family ([models](recipes/models.md#checkers); briefs: see
|
|
82
|
+
Orchestrator rules; many claims: [refute](recipes/refute.md)).
|
|
80
83
|
|
|
81
84
|
For one-shot work inside pi, call `mu_delegate` (installed by `mu link pi`). Outside pi: spawn
|
|
82
|
-
into the reserved `scratch` workstream (no task DAG, auto-created),
|
|
83
|
-
|
|
84
|
-
ends first hangs the wait. Recipes call either form a **delegate call**. A check judging a mu
|
|
85
|
+
into the reserved `scratch` workstream (no task DAG, auto-created), as in
|
|
86
|
+
[delegate call](recipes/tasks-or-calls.md#delegate-call). Recipes call either form a **delegate call**. A check judging a mu
|
|
85
87
|
task lands its verdict there: `record: { task: "<ws>/<id>" }` on `mu_delegate`, a hand-written
|
|
86
88
|
`REFUTER` note on the spawn path; with no task, skip both.
|
|
87
89
|
|
|
@@ -102,8 +104,10 @@ wrapper whose argv0 is not `pi`/`pi-meta` it shows `needs_input`): add
|
|
|
102
104
|
### Workstreams, DAGs, tracks
|
|
103
105
|
|
|
104
106
|
The DAG has one edge: `mu task block A --by B` means **B blocks A**.
|
|
105
|
-
Tracks sharing a prerequisite collapse into one, so
|
|
106
|
-
|
|
107
|
+
Tracks sharing a prerequisite collapse into one, so an umbrella every
|
|
108
|
+
unit blocks makes the whole job one track. Parallelism is the ready
|
|
109
|
+
set: tasks that edit the same files get a `block` edge between them,
|
|
110
|
+
so only one is ready at a time.
|
|
107
111
|
|
|
108
112
|
### Workspaces prevent trampling
|
|
109
113
|
|
|
@@ -112,9 +116,9 @@ repo, spawn with `--workspace`. Two builds in one checkout corrupt each
|
|
|
112
116
|
other; keep the main checkout for orchestration.
|
|
113
117
|
|
|
114
118
|
Workspaces auto-detect jj, sl, or git (else `cp -a`). `mu agent close`
|
|
115
|
-
frees one **only if clean
|
|
116
|
-
|
|
117
|
-
|
|
119
|
+
frees one **only if clean**; otherwise it fails with
|
|
120
|
+
`WorkspacePreservedError`. A `cp -a` copy is never clean. Cherry-pick what
|
|
121
|
+
to keep, and pass `--discard-workspace` only to throw the rest away.
|
|
118
122
|
Before each `--fresh` send, `mu workspace refresh <agent>` rebases onto
|
|
119
123
|
main and keeps LLM context ([waves](recipes/waves.md) when workers share
|
|
120
124
|
files). Claim and send warn at ≥10 commits behind
|
|
@@ -190,7 +194,7 @@ rules hold even when you skip it:
|
|
|
190
194
|
- **Send, don't note, a running worker**: it never sees new notes. The note is the durable copy
|
|
191
195
|
([how to send](recipes/orchestrator-loop.md#sending)).
|
|
192
196
|
- **Refute a brief claiming a cause, fix, threshold or code fact** before dispatch:
|
|
193
|
-
one `record`ed refuter call; rewrite on
|
|
197
|
+
one `record`ed refuter call; rewrite on REFUTED. Others get a `REFUTE-EXEMPT: <why>` note.
|
|
194
198
|
- **Checks are calls, not tasks.** Refuters, claim checkers, judges and
|
|
195
199
|
skeptics are [delegate calls](recipes/tasks-or-calls.md#delegate-call)
|
|
196
200
|
(`mu_delegate`, or a `scratch` spawn without it), all issued in one
|
|
@@ -205,13 +209,9 @@ rules hold even when you skip it:
|
|
|
205
209
|
|
|
206
210
|
## CLI gotchas
|
|
207
211
|
|
|
208
|
-
- **`task close --if-ready`** no-ops until every blocker is CLOSED; bare
|
|
209
|
-
`task release` reopens IN_PROGRESS.
|
|
210
212
|
- **`task close --as rejected|wontfix --why ...`** unblocks dependents
|
|
211
213
|
(listed in the output). `rejected` = the claim is false; `wontfix` =
|
|
212
|
-
true, not worth doing. To keep dependents waiting, `task park --why` instead
|
|
213
|
-
leaves `next`, and `claim` refuses it without `--force`. Park refuses
|
|
214
|
-
IN_PROGRESS — `task release` first.
|
|
214
|
+
true, not worth doing. To keep dependents waiting, `task park --why` instead.
|
|
215
215
|
- **For waits use `task wait`, not `log --tail`.** `mu log --kind <k>`
|
|
216
216
|
entries are your own durable state (a ledger); `--intent` filters what
|
|
217
217
|
mu recorded.
|
|
@@ -225,23 +225,14 @@ rules hold even when you skip it:
|
|
|
225
225
|
|
|
226
226
|
## Models and thinking effort
|
|
227
227
|
|
|
228
|
-
mu
|
|
228
|
+
mu passes the model through; you pick it. Before you choose one for a
|
|
229
|
+
spawn or a delegate call, read [recipes/models.md](recipes/models.md):
|
|
230
|
+
tiers, which roles need which, and local models as a last resort.
|
|
229
231
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
`pi_mini` scouts and finds, `pi` builds and refactors, `pi_big` designs and
|
|
237
|
-
handles incidents. A reviewer, refuter,
|
|
238
|
-
judge or auditor checks level or up, never down: at least the worker's
|
|
239
|
-
capability, from another family if one exists (provider or model-id prefix in
|
|
240
|
-
`pi --list-models`). Small-model signs: a local runtime (ollama, lmstudio,
|
|
241
|
-
llama.cpp), a size (`4b`, `27b`), mini/haiku/flash/nano/lite, thinking `no`,
|
|
242
|
-
context or max-out far below the worker's. No such peer: same model, fresh
|
|
243
|
-
context, higher thinking unless at max. Probe an unused model first
|
|
244
|
-
(`pi --model <provider/model> -p "say ok"`); `ctl: ok` does not test it.
|
|
232
|
+
- `mu_delegate` takes `model`; a spawn takes `--command "pi --model <id>"`.
|
|
233
|
+
- A checker (reviewer, refuter, judge, auditor) runs at the author's tier
|
|
234
|
+
or higher, from another family when one exists. A delegate with no
|
|
235
|
+
`model` runs the cli's default model; pass `model` when it matters.
|
|
245
236
|
|
|
246
237
|
## Reaper and agent state
|
|
247
238
|
|
|
@@ -264,7 +255,7 @@ Close the task as your last action, or the orchestrator's wait hangs.
|
|
|
264
255
|
## Guardrails
|
|
265
256
|
|
|
266
257
|
Task ownership outranks agent state. Coordinate through task notes and
|
|
267
|
-
the
|
|
258
|
+
the ops log (`mu log`). Keep edges within one workstream. Give workers
|
|
268
259
|
bounded paths and commands.
|
|
269
260
|
|
|
270
261
|
## Recipes
|
|
@@ -287,6 +278,7 @@ risky job that needs several of them, start with
|
|
|
287
278
|
| [drift-audit](recipes/drift-audit.md) | hours into a long run, after a batch, compaction or resume, before a stop rule |
|
|
288
279
|
| [watcher](recipes/watcher.md) | a helper polls a PR, CI, or log for change |
|
|
289
280
|
| [findings](recipes/findings.md) | any review, audit, or check reports problems: where they live, how they are triaged |
|
|
281
|
+
| [models](recipes/models.md) | you pick a model for a spawn or delegate call |
|
|
290
282
|
| [tasks-or-calls](recipes/tasks-or-calls.md) | a recipe step spawns an agent: DAG task or delegate call |
|
|
291
283
|
| [adversarial-review](recipes/adversarial-review.md) | gate each unit you dispatch before it merges (a review task per unit) |
|
|
292
284
|
| [fan-out](recipes/fan-out.md) | a sweep or migration: the same change over many files or call sites |
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# Adversarial review
|
|
2
2
|
|
|
3
3
|
Use when a unit of work must be checked by someone other than its
|
|
4
|
-
author before it counts: a
|
|
4
|
+
author before it counts: a unit that produces commits (a fix, a feature).
|
|
5
|
+
Checking a finding or claim is a delegate call
|
|
6
|
+
([findings § Triage](findings.md#triage), [refute](refute.md)). The author
|
|
5
7
|
grades its own work generously; a fresh agent told to refute it does
|
|
6
8
|
not. Every other review-shaped recipe builds on this one.
|
|
7
9
|
|
|
8
10
|
The review is a task in the DAG, not a step inside the worker's
|
|
9
|
-
session. Its verdict, its evidence, and every
|
|
10
|
-
DB: each
|
|
11
|
+
session. Its verdict, its evidence, and every finding it makes stay in the
|
|
12
|
+
DB: each is a finding task ([findings](findings.md)). For a one-off
|
|
11
13
|
check outside any workstream, one
|
|
12
14
|
[delegate call](tasks-or-calls.md#delegate-call) is enough; to review a
|
|
13
15
|
PR or diff from several angles, use [review-panel](review-panel.md).
|
|
@@ -22,27 +24,29 @@ PR or diff from several angles, use [review-panel](review-panel.md).
|
|
|
22
24
|
|
|
23
25
|
```bash
|
|
24
26
|
mu task add review_x -w <ws> -t "Review x" -i 50 -e 0.5 --blocked-by x \
|
|
25
|
-
--note 'ACCEPTANCE: see x notes. Refute; report
|
|
27
|
+
--note 'ACCEPTANCE: see x notes. Refute; report findings, not style.'
|
|
26
28
|
```
|
|
27
29
|
|
|
28
30
|
3. **Dispatch the work** as usual. When `x` closes, `review_x` becomes
|
|
29
31
|
ready.
|
|
30
32
|
4. **Spawn a fresh reviewer.** A new agent, or `--fresh` on an idle one,
|
|
31
|
-
so it has none of the author's reasoning,
|
|
32
|
-
[
|
|
33
|
+
so it has none of the author's reasoning, at the worker's tier or
|
|
34
|
+
higher and from another family ([models](models.md#checkers)). Give it the worker's workspace path
|
|
33
35
|
and commits read-only by instruction; it edits nothing.
|
|
34
36
|
5. **Claim `review_x` for the reviewer**, send the brief (below), wait.
|
|
35
37
|
6. **Act on the verdict:**
|
|
36
38
|
The review's state is the verdict: `CLOSED/done` for ACCEPT,
|
|
37
39
|
`CLOSED/rejected` for REJECT.
|
|
38
40
|
- `ACCEPT`: cherry-pick `x`'s commits and verify the merge.
|
|
39
|
-
- `REJECT`: the reviewer recorded each
|
|
40
|
-
Add `review_x_2` and block it on every
|
|
41
|
-
(`mu task block review_x_2 --by <
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
- `REJECT`: the reviewer recorded each finding as an `OPEN/triage` task.
|
|
42
|
+
Add `review_x_2` and block it on every finding
|
|
43
|
+
(`mu task block review_x_2 --by <finding>`). Closing `review_x`
|
|
44
|
+
`--as rejected` unblocked its dependents, so re-block each task
|
|
45
|
+
downstream of `x` on `review_x_2`
|
|
46
|
+
(`mu task block <downstream> --by review_x_2`). Decide each
|
|
47
|
+
finding ([findings § Triage](findings.md#triage)), then
|
|
48
|
+
dispatch the accepted ones to the original worker, whose context
|
|
49
|
+
still holds the work. Repeat from step 4 when the findings are closed.
|
|
46
50
|
The DAG grows; nothing is rewritten.
|
|
47
51
|
7. **Cap the rounds.** After two rejections on the same unit, stop the
|
|
48
52
|
loop and decide yourself: split the unit, change the criteria, or
|
|
@@ -60,24 +64,25 @@ You are reviewing task <x>. You did not write it. Your job is to find
|
|
|
60
64
|
where it fails the acceptance criteria in `mu task notes <x>`.
|
|
61
65
|
|
|
62
66
|
- Read the diff (<range>) and the criteria. Run the tests that cover it.
|
|
63
|
-
- Report
|
|
67
|
+
- Report findings against the criteria: a requirement not met, an edge case
|
|
64
68
|
without a test, a change outside scope, a claim the evidence does not
|
|
65
69
|
support. Not style, not preferences.
|
|
66
|
-
- Record each
|
|
67
|
-
mu task add -w <ws> --triage -t "<severity>: <
|
|
68
|
-
--note 'FINDING: <severity> <file:line> <
|
|
70
|
+
- Record each as a finding, per findings.md § Record:
|
|
71
|
+
mu task add -w <ws> --triage -t "<severity>: <title>" -i <n> -e <days> \
|
|
72
|
+
--note 'FINDING: <severity> <file:line> <what fails> EVIDENCE: <command + output>'
|
|
69
73
|
- If you could not check something (tool failed, no access), say
|
|
70
74
|
UNVERIFIED for it. Unverified is not a pass and not a fail.
|
|
71
|
-
-
|
|
75
|
+
- Your only writes are `mu task add` (findings), the verdict note, and
|
|
76
|
+
the close; leave the workspace as you found it.
|
|
72
77
|
|
|
73
78
|
Write the verdict note (FILES/COMMANDS/FINDINGS/VERIFIED), then close
|
|
74
79
|
(long reasons: a heredoc variable, brief.md § Quoting):
|
|
75
80
|
ACCEPT: mu task close review_<x> --evidence "<key command>: <result>"
|
|
76
81
|
REJECT: mu task close review_<x> --as rejected \
|
|
77
|
-
--why "<n>
|
|
82
|
+
--why "<n> findings: <id> (<why it fails, one clause>), ..."
|
|
78
83
|
```
|
|
79
84
|
|
|
80
|
-
mu adds each named
|
|
85
|
+
mu adds each named finding's title to the REJECTED note.
|
|
81
86
|
|
|
82
87
|
**Closing a review yourself** (you fixed a finding, or accept without a
|
|
83
88
|
fresh reviewer): write the reviewer's note plus `COMMIT: <sha> fixes
|
|
@@ -93,7 +98,7 @@ by orchestrator`.
|
|
|
93
98
|
reviewer ran. A review with no evidence is a
|
|
94
99
|
rejected review: re-send it.
|
|
95
100
|
- **Reviewers drift into fixing.** A reviewer that edits the code is now
|
|
96
|
-
an author nobody reviews. The fix belongs to the
|
|
101
|
+
an author nobody reviews. The fix belongs to the finding tasks.
|
|
97
102
|
- **Review is not merge verification.** An accepted unit can still
|
|
98
103
|
break once merged with moved main. Verify the merge as in
|
|
99
104
|
[orchestrator-loop](orchestrator-loop.md#merging).
|
|
@@ -77,5 +77,6 @@ mu task close <id> -w <ws> --evidence "$v"
|
|
|
77
77
|
Chain batched adds with `&&`, then `mu task list`, so one
|
|
78
78
|
quoting failure cannot half-apply the batch unseen.
|
|
79
79
|
|
|
80
|
-
Done when
|
|
81
|
-
|
|
80
|
+
Done when the brief has GOAL, FILES, DONE WHEN, VERIFY and the
|
|
81
|
+
final-action block, every shared fact is a `Read:` pointer, and the task
|
|
82
|
+
holds a refuter verdict or a `REFUTE-EXEMPT:` note.
|
|
@@ -44,7 +44,7 @@ return wait.output;
|
|
|
44
44
|
|
|
45
45
|
Size the worker list from the ceiling on the umbrella
|
|
46
46
|
([orchestrator-loop § Concurrency](orchestrator-loop.md#concurrency)),
|
|
47
|
-
one per ready
|
|
47
|
+
one per ready task. Merge and verify outside the script
|
|
48
48
|
([orchestrator-loop § Merging](orchestrator-loop.md#merging)). Check
|
|
49
49
|
field names against `--json` output; the script is a shape, not an API.
|
|
50
50
|
|
|
@@ -54,8 +54,8 @@ field names against `--json` output; the script is a shape, not an API.
|
|
|
54
54
|
answers arrive after the script, as follow-up messages: the script
|
|
55
55
|
gains nothing over issuing the calls in one turn. Use it from a script
|
|
56
56
|
only when `codemode.mode` is `only` and the tool is not offered
|
|
57
|
-
directly. Check `Promise.allSettled` results for rejections
|
|
58
|
-
|
|
57
|
+
directly. Check `Promise.allSettled` results for rejections; the cap is in
|
|
58
|
+
[orchestrator-loop § Concurrency](orchestrator-loop.md#concurrency).
|
|
59
59
|
|
|
60
60
|
To get the verdicts back as one table instead of one message each, use
|
|
61
61
|
the `scratch` form through `tools.bash`:
|
|
@@ -63,8 +63,9 @@ the `scratch` form through `tools.bash`:
|
|
|
63
63
|
```js
|
|
64
64
|
// @options: {"timeout_ms": 1800000}
|
|
65
65
|
const ws = "audit";
|
|
66
|
-
const findings = ["f_auth_put", "f_sql_order"]; // finding task ids,
|
|
66
|
+
const findings = ["f_auth_put", "f_sql_order"]; // finding task ids, within the cap
|
|
67
67
|
const sh = async (c) => (await tools.bash({ command: c })).output;
|
|
68
|
+
const dir = `${(await sh("echo $HOME")).trim()}/.local/state/mu`;
|
|
68
69
|
const json = (s) => { try { return JSON.parse(s); } catch { return {}; } };
|
|
69
70
|
const el = (ms) => { const t = Math.round(ms / 1000); return t < 60 ? `${t}s` : `${Math.floor(t / 60)}m ${String(t % 60).padStart(2, "0")}s`; };
|
|
70
71
|
const rows = await Promise.all(findings.map(async (id, i) => {
|
|
@@ -77,7 +78,8 @@ const rows = await Promise.all(findings.map(async (id, i) => {
|
|
|
77
78
|
const note = w.outcome !== "done" ? `REFUTER ${i + 1}: no verdict (${w.outcome ?? "no result"})`
|
|
78
79
|
: `REFUTER ${i + 1} (${a}, ${el(Date.now() - t0)}):\n` + (at < 0 ? `NO VERDICT LINE: ${(w.lastText ?? "").slice(-1500)}`
|
|
79
80
|
: [lines[at], ...lines.slice(at + 1).filter((l) => /^[\s>*_`-]*EVIDENCE:/.test(l))].join("\n"));
|
|
80
|
-
await
|
|
81
|
+
await tools.write({ path: `${dir}/note-${a}.txt`, content: note }); // answer text never touches a shell
|
|
82
|
+
await sh(`mu task note ${id} -w ${ws} - < ${dir}/note-${a}.txt && rm ${dir}/note-${a}.txt`);
|
|
81
83
|
if (w.outcome === "done") await sh(`mu agent close ${a} -w scratch`);
|
|
82
84
|
return `${id}\t${note.split("\n")[1] ?? note}`;
|
|
83
85
|
}));
|
|
@@ -87,7 +89,8 @@ return rows.join("\n");
|
|
|
87
89
|
What the tool did for you, the script now owns:
|
|
88
90
|
|
|
89
91
|
- **The cap.** `MU_DELEGATE_MAX` does not apply to bash spawns: keep
|
|
90
|
-
each script's list
|
|
92
|
+
each script's list within
|
|
93
|
+
[orchestrator-loop § Concurrency](orchestrator-loop.md#concurrency).
|
|
91
94
|
- **Cleanup.** Close each scratch pane; a timed-out one stays, readable
|
|
92
95
|
with `mu agent read <a> -w scratch`.
|
|
93
96
|
- **Recording.** The script writes each `REFUTER` note in `record`'s
|
|
@@ -31,7 +31,8 @@ answer rests on is an `OPEN/triage` task, decided like a finding
|
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
A claim without a source and a quote is not a claim. Searchers can
|
|
34
|
-
run
|
|
34
|
+
run cheap (hosted, not local: [models](models.md#local-models-are-a-last-resort));
|
|
35
|
+
the checkers in step 4 run mid or higher.
|
|
35
36
|
3. **Dedupe claims**: merge the same fact from several sources (keep
|
|
36
37
|
every source), and flag claims that contradict each other. In
|
|
37
38
|
workstream mode, each surviving claim becomes an `OPEN/triage` task
|
|
@@ -35,13 +35,14 @@ or close you compare against is often older than it.
|
|
|
35
35
|
IN_PROGRESS note, and each merged fix its task's findings depend on:
|
|
36
36
|
git merge-base --is-ancestor <fix> <pinned>. Exit 1 = pin is stale.
|
|
37
37
|
3. Closed-task notes: notes added after the task's last task.close op,
|
|
38
|
-
minus the
|
|
39
|
-
|
|
40
|
-
prefix. Report each of the top 5 by
|
|
38
|
+
minus those the close verb writes in its own transaction
|
|
39
|
+
(`--evidence`, `--why`: timestamp within 50ms of the close op); any
|
|
40
|
+
other note counts, whatever its prefix. Report each of the top 5 by
|
|
41
|
+
count as its own finding with its count,
|
|
41
42
|
even when the notes look routine. A late note that reports the
|
|
42
43
|
closed bug again usually ran on a build without the closing fix:
|
|
43
44
|
check its sha with git merge-base --is-ancestor <fix> <sha>.
|
|
44
|
-
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 join (select key, max(
|
|
45
|
+
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 join (select key, max(created_at) at from ops where intent='task.close' and entity='task' group by key) c on c.key='<ws>/'||t.local_id where w.name='<ws>' and t.status='CLOSED' and (julianday(n.created_at)-julianday(c.at))*86400 > 0.05 group by t.local_id order by late desc"
|
|
45
46
|
4. Thin decisions: an ACCEPT/REJECTED/CLOSE/SUPERSEDED note under 40
|
|
46
47
|
chars; a refuter tally with no REFUTER or VERDICT note; a review the
|
|
47
48
|
orchestrator closed with no FILES/COMMANDS note and no commit.
|
|
@@ -9,7 +9,9 @@ some and calls the job done; one task per unit cannot.
|
|
|
9
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
|
-
not when it looks complete. Record the command and the count.
|
|
12
|
+
not when it looks complete. Record the command and the count. The
|
|
13
|
+
scout runs cheap; the units run mid, or strong when each is a
|
|
14
|
+
judgement call ([models](models.md#roles)).
|
|
13
15
|
2. **One task per unit**, blocked into an umbrella:
|
|
14
16
|
|
|
15
17
|
```bash
|
|
@@ -23,13 +25,13 @@ some and calls the job done; one task per unit cannot.
|
|
|
23
25
|
only checks (no commits) makes each unit a delegate call instead
|
|
24
26
|
([tasks-or-calls](tasks-or-calls.md)).
|
|
25
27
|
3. **Cap concurrency** ([orchestrator-loop § Concurrency](orchestrator-loop.md#concurrency)).
|
|
26
|
-
|
|
28
|
+
One agent per ready unit, up to the ceiling. Tell workers to avoid
|
|
27
29
|
repo-wide commands so more can run.
|
|
28
30
|
4. **Pipeline.** Dispatch, wait `--first`, merge
|
|
29
31
|
([orchestrator-loop § Merging](orchestrator-loop.md#merging)), dispatch
|
|
30
32
|
the next unit to the freed worker with `--fresh`. With `codemode`, a
|
|
31
33
|
[driver](codemode-driver.md) can dispatch each batch. Units that touch the same files
|
|
32
|
-
|
|
34
|
+
are chained with `block` (see [waves](waves.md)).
|
|
33
35
|
5. **Review per unit** when a wrong unit is costly: add a review task
|
|
34
36
|
per unit ([adversarial-review](adversarial-review.md)).
|
|
35
37
|
6. **Synthesize** when the output is a report, not commits: one
|
|
@@ -94,8 +94,10 @@ across reviewers and creates one task per real problem.
|
|
|
94
94
|
| could not check | stays in triage, with an `UNVERIFIED: <why>` note | |
|
|
95
95
|
|
|
96
96
|
4. **Group** accepted findings that touch the same files into one fix
|
|
97
|
-
task when separate workers would collide
|
|
98
|
-
|
|
97
|
+
task when separate workers would collide. Block the umbrella on the
|
|
98
|
+
fix task (`mu task block <umbrella> --by <fix-task>`), then close the
|
|
99
|
+
grouped findings `--as superseded --why "fixed in <fix-task>"`:
|
|
100
|
+
superseding unblocks the umbrella.
|
|
99
101
|
|
|
100
102
|
Done when `mu task list --substate triage -w <ws>` lists only findings
|
|
101
103
|
with an `UNVERIFIED` note, and each of those is reported to the human.
|
|
@@ -105,7 +107,9 @@ with an `UNVERIFIED` note, and each of those is reported to the human.
|
|
|
105
107
|
Accepted findings are ordinary tasks: dispatch them, review the fix
|
|
106
108
|
([adversarial-review](adversarial-review.md)), merge. The umbrella
|
|
107
109
|
closes with `mu task close <umbrella> --if-ready` once every finding is
|
|
108
|
-
`CLOSED/*`. A plain `close` would succeed with findings still open
|
|
110
|
+
`CLOSED/*`. A plain `close` would succeed with findings still open; an
|
|
111
|
+
`UNVERIFIED` finding blocks `--if-ready`, so the umbrella stays open
|
|
112
|
+
until the human decides it.
|
|
109
113
|
|
|
110
114
|
The report is a query, not a document: `mu task list -w <ws>
|
|
111
115
|
--substate rejected`, `--substate duplicate`, `--status OPEN`, and the
|
|
@@ -9,7 +9,8 @@ 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 reader per evidence source** (a [delegate call](tasks-or-calls.md#delegate-call)
|
|
12
|
+
2. **One reader per evidence source** (a [delegate call](tasks-or-calls.md#delegate-call), strong tier:
|
|
13
|
+
root cause is judgement, [models](models.md#roles)): logs, the
|
|
13
14
|
code path, recent commits, data, environment. Each sees only its
|
|
14
15
|
source, so the theories do not anchor on each other. Record each
|
|
15
16
|
theory as an `OPEN/triage` task blocking the umbrella, decided like
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Model tiers
|
|
2
|
+
|
|
3
|
+
Read when you pick a model for a spawn or a delegate call. mu passes the
|
|
4
|
+
model through and never picks one; the choice is yours. Recipes name a
|
|
5
|
+
tier (cheap, mid, strong, frontier) and say which one their roles need;
|
|
6
|
+
this file says how to tell a model's tier.
|
|
7
|
+
|
|
8
|
+
## Tiers
|
|
9
|
+
|
|
10
|
+
Rank a model within its own family. The model-id prefix in
|
|
11
|
+
`pi --list-models` (`anthropic/`, `openai/`, `google/`) names the family
|
|
12
|
+
when it names a lab; the provider column is often one shared gateway, so
|
|
13
|
+
it does not tell families apart.
|
|
14
|
+
|
|
15
|
+
| Tier | Where it sits in its family | Names as of 2026-10 |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| **frontier** | an exceptional tier above the lab's normal flagship, priced well above it, often gated | fable, astra |
|
|
18
|
+
| **strong** | the lab's normal flagship | opus, sol |
|
|
19
|
+
| **mid** | the everyday default | sonnet, terra |
|
|
20
|
+
| **cheap** | the lab's small, fast hosted model | haiku, luna, flash, mini, nano, lite |
|
|
21
|
+
| **local** | runs on this machine (ollama, lmstudio, llama.cpp) | qwen, gemma, gpt-oss |
|
|
22
|
+
|
|
23
|
+
Names go stale within months; the position in the family does not. Rank
|
|
24
|
+
a model you cannot place by the lab's own description of its lineup
|
|
25
|
+
(flagship, balanced, fast). `pi --list-models` shows context and max
|
|
26
|
+
output, not price or quality, and siblings often share both. Still
|
|
27
|
+
unsure: run it on a small slice of the real work and compare it with a
|
|
28
|
+
model you can place. Until then, pick conservatively: a model you know
|
|
29
|
+
is strong enough for the work, and for a checker never one that might
|
|
30
|
+
sit below the author.
|
|
31
|
+
|
|
32
|
+
Thinking effort strengthens a model within its tier. It does not change
|
|
33
|
+
the tier, and it does not stand in for another family.
|
|
34
|
+
|
|
35
|
+
## Local models are a last resort
|
|
36
|
+
|
|
37
|
+
A hosted cheap model beats a small local one at agent work: tool calls,
|
|
38
|
+
long briefs, multi-step edits. Small local models lose the thread of a
|
|
39
|
+
brief and fake tool results; in `pi --list-models` they tend to show
|
|
40
|
+
thinking `no` and small context and output limits. Use one only when no
|
|
41
|
+
hosted model is available, or the work must stay on the machine, and
|
|
42
|
+
then only for cheap-tier work whose output something stronger checks. A
|
|
43
|
+
local model never reviews, refutes or judges.
|
|
44
|
+
|
|
45
|
+
## Roles
|
|
46
|
+
|
|
47
|
+
| Work | Tier |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| fan-out scouting (listing units), searchers collecting quoted claims, watchers, first-pass finders | cheap |
|
|
50
|
+
| building, refactoring, tests, routine fixes | mid |
|
|
51
|
+
| review, refute, judge, audit, synthesize | the tier of whoever wrote the thing being checked, or higher; another family when one exists |
|
|
52
|
+
| design, plans, incidents, root cause, final synthesis of a large run | strong |
|
|
53
|
+
| a strong attempt failed, or the final judge of a close call | frontier; none available: the strongest model, from a family not yet used on the job |
|
|
54
|
+
|
|
55
|
+
Cheap work suits bounded tasks whose output can be checked: a searcher's
|
|
56
|
+
claim carries a quote a checker verifies. A cheap finder's misses stay
|
|
57
|
+
missed, since refuters only test what was reported. When an omission is
|
|
58
|
+
costly (a security audit, a coverage sweep), run the finders mid or
|
|
59
|
+
strong, or add a second finder from another family.
|
|
60
|
+
|
|
61
|
+
## Checkers
|
|
62
|
+
|
|
63
|
+
A checker (reviewer, refuter, judge, auditor) must not share the
|
|
64
|
+
author's blind spots. The author is whoever wrote the thing being
|
|
65
|
+
checked: the worker for a diff, the planner for a brief, the finder for
|
|
66
|
+
a finding.
|
|
67
|
+
|
|
68
|
+
- **Level or up.** At least the author's tier; never down.
|
|
69
|
+
- **Another family when one exists**, at that tier. One model's blind
|
|
70
|
+
spot repeated is still one blind spot.
|
|
71
|
+
- **No peer in another family**: the same model, fresh context, higher
|
|
72
|
+
thinking unless at max.
|
|
73
|
+
|
|
74
|
+
A delegate with no `model` runs the cli's configured default, which is
|
|
75
|
+
your own model only if you are on that default. When the tier or family
|
|
76
|
+
matters, pass `model`.
|
|
77
|
+
|
|
78
|
+
## How to pass a model and effort level
|
|
79
|
+
|
|
80
|
+
pi takes both in one `--model` value: `<provider/id>:<level>`, where the
|
|
81
|
+
thinking (effort) level is one of `off`, `minimal`, `low`, `medium`,
|
|
82
|
+
`high`, `xhigh`, `max`. Leave `:<level>` off to keep the model's default. With `:<level>`, pi
|
|
83
|
+
reads the first segment as the provider, so copy `<provider>/<model>`
|
|
84
|
+
exactly from `pi --list-models`. Through a gateway that is
|
|
85
|
+
`modelbridge/anthropic/claude-sonnet-5-5:high`; `anthropic/…:high` fails
|
|
86
|
+
with "No API key".
|
|
87
|
+
|
|
88
|
+
- `mu_delegate`: `model: "<provider>/<model>:high"`.
|
|
89
|
+
- Spawn: `mu agent spawn r -w <ws> --command "pi --model <provider>/<model>:high"`.
|
|
90
|
+
- A `cli` key (`--cli pi_big`) works only if `$MU_<KEY>_COMMAND` is set
|
|
91
|
+
in the environment; check before you rely on one.
|
|
92
|
+
- herdr refuses a command override, so neither model nor level can be
|
|
93
|
+
set per agent there: every helper runs the cli's default. The only
|
|
94
|
+
independence left is fresh context; say so in the verdict.
|
|
95
|
+
|
|
96
|
+
Probe a model you have not used this session
|
|
97
|
+
(`pi --model <id> -p "say ok"`); `ctl: ok` after spawn does not test the
|
|
98
|
+
model.
|
|
99
|
+
|
|
100
|
+
Done when the chosen `model` is placed in a tier, a checker is at the
|
|
101
|
+
author's tier or higher and from another family (or the verdict says why
|
|
102
|
+
not), and a model new this session answered `pi --model <id> -p "say ok"`.
|
|
@@ -6,10 +6,10 @@ the loop and the reasons behind them.
|
|
|
6
6
|
|
|
7
7
|
## Every turn
|
|
8
8
|
|
|
9
|
-
1. `mu state -w <ws>` — read agents, IN_PROGRESS, ready tasks
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
1. `mu state -w <ws>` — read agents, IN_PROGRESS, ready tasks.
|
|
10
|
+
2. Spawn one agent per ready task, up to the ceiling below. Tasks that
|
|
11
|
+
edit the same files are chained with `block`, so only one is ready
|
|
12
|
+
([waves](waves.md)).
|
|
13
13
|
3. **Claim before sending — even one-shot reviewers/scouts.**
|
|
14
14
|
`mu task claim <id> -w <ws> --for <agent> --evidence "..."`.
|
|
15
15
|
If no task exists, `mu task add` first (`--note 'REPRO: ...'` when
|
|
@@ -109,9 +109,7 @@ keep the note as the durable copy. pi:
|
|
|
109
109
|
|
|
110
110
|
## Stopping a worker
|
|
111
111
|
|
|
112
|
-
`mu agent abort <w>` first for pi
|
|
113
|
-
|
|
114
|
-
to the editor unsent). Then `mu agent kick` (pi unresponsive, or
|
|
115
|
-
non-pi; local panes only), then `mu agent close`.
|
|
112
|
+
`mu agent abort <w>` first for pi, then `mu agent kick` (pi
|
|
113
|
+
unresponsive, or non-pi), then `mu agent close`.
|
|
116
114
|
|
|
117
115
|
Done when every task is closed, or a decision only a human can make blocks all progress (SKILL.md § Orchestrator rules).
|
|
@@ -38,20 +38,20 @@ human asks for a file.
|
|
|
38
38
|
of order.
|
|
39
39
|
6. **Add edges for dependencies only.** `mu task block A --by B` when A
|
|
40
40
|
consumes what B produces. Plan order is not a dependency: an extra
|
|
41
|
-
edge serialises
|
|
42
|
-
tasks that edit the same files
|
|
41
|
+
edge serialises tasks that could run in parallel. The exception:
|
|
42
|
+
tasks that edit the same files are chained ([waves](waves.md)).
|
|
43
43
|
7. **Self-review before dispatch.** Map each spec requirement to its
|
|
44
44
|
task, grep the notes for placeholders, match INTERFACES names across
|
|
45
45
|
tasks, and read the graph back (`mu task tree task_0 -w <ws> --down`).
|
|
46
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,
|
|
47
|
+
all in one turn, at your tier from another family: [models](models.md#checkers)): "What in this brief is false about the code,
|
|
48
48
|
ambiguous, or would make a correct worker fail review? Cite
|
|
49
|
-
file:line." Rewrite each
|
|
49
|
+
file:line." Rewrite each REFUTED brief. Five of six briefs refuted in one run had
|
|
50
50
|
such a defect, e.g. a fallback test old extensions made unpassable.
|
|
51
51
|
|
|
52
52
|
Done when every spec requirement maps to a task, no note holds a
|
|
53
53
|
placeholder, every claim-making brief has a verdict, and `mu state`
|
|
54
|
-
|
|
54
|
+
lists the tasks you meant to run in parallel as Ready together. Then dispatch per [orchestrator-loop](orchestrator-loop.md).
|
|
55
55
|
|
|
56
56
|
## Notes
|
|
57
57
|
|