@mu-crew/mu 3.2.1 → 3.3.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/AGENTS.md +10 -5
- package/README.md +49 -2
- package/dist/cli.js +108 -78
- package/dist/cli.js.map +1 -1
- package/dist/extension/mu-pi.js +244 -12
- package/dist/extension/mu-pi.js.map +1 -1
- package/dist/index.d.ts +36 -10
- package/dist/index.js +89 -67
- package/dist/index.js.map +1 -1
- package/docs/ARCHITECTURE.md +1 -0
- package/docs/VOCABULARY.md +2 -0
- package/docs/architecture/control-socket.md +17 -3
- package/docs/architecture/mux.md +3 -4
- package/docs/guide/README.md +5 -0
- package/docs/guide/dispatch.md +11 -4
- package/docs/guide/getting-started.md +3 -0
- package/docs/guide/recovery.md +3 -1
- package/docs/guide/remote.md +1 -1
- package/docs/history/CHANGELOG-pre-3.md +1 -1
- package/docs/reference/env.md +1 -1
- package/docs/specs/2026-10-03-keep-driving-nudge.md +142 -0
- package/package.json +2 -1
- package/prompts/mu-refute.md +8 -0
- package/prompts/mu-research.md +8 -0
- package/prompts/mu-review.md +8 -0
- package/prompts/mu-rules-audit.md +8 -0
- package/prompts/mu-tournament.md +9 -0
- package/prompts/ultrathink.md +9 -0
- package/skills/mu/SKILL.md +71 -131
- package/skills/mu/recipes/adversarial-review.md +83 -0
- package/skills/mu/recipes/brief.md +53 -0
- package/skills/mu/recipes/codemode-driver.md +54 -0
- package/skills/mu/recipes/deep-research.md +52 -0
- package/skills/mu/recipes/fan-out.md +36 -0
- package/skills/mu/recipes/hypothesis-panel.md +40 -0
- package/skills/mu/recipes/long-run.md +20 -0
- package/skills/mu/recipes/loop-until-done.md +38 -0
- package/skills/mu/recipes/orchestrator-loop.md +87 -0
- package/skills/mu/recipes/plan.md +54 -0
- package/skills/mu/recipes/recovery.md +26 -0
- package/skills/mu/recipes/refute.md +49 -0
- package/skills/mu/recipes/review-panel.md +57 -0
- package/skills/mu/recipes/rules-audit.md +70 -0
- package/skills/mu/recipes/tournament.md +37 -0
- package/skills/mu/recipes/triage.md +38 -0
- package/skills/mu/recipes/ultrathink.md +73 -0
- package/skills/mu/recipes/watcher.md +16 -0
- package/skills/mu/recipes/waves.md +19 -0
- package/skills/mu/recipes/worker.md +24 -0
- /package/skills/mu/{REMOTE_WORKERS.md → recipes/remote-workers.md} +0 -0
package/skills/mu/SKILL.md
CHANGED
|
@@ -55,9 +55,7 @@ auto-created), `send --fresh`, then `mu agent wait --json` (`lastText`).
|
|
|
55
55
|
|
|
56
56
|
- `mu agent wait <names...> --first` waits for busy → idle instead of a
|
|
57
57
|
`sleep` loop; exit 0 met, 5 timeout, 6 pane died.
|
|
58
|
-
- For a watcher,
|
|
59
|
-
scratch --kind pr-state 'pr=1234 sha=abc ci=red'`, then read `mu log -w
|
|
60
|
-
scratch --kind pr-state -n 1 --json`. Act only on change.
|
|
58
|
+
- For a watcher (PR, CI, a log), follow [recipes/watcher.md](recipes/watcher.md).
|
|
61
59
|
- One agent per independent unit; `--workspace` for any helper that may edit,
|
|
62
60
|
build, or test the shared repo.
|
|
63
61
|
|
|
@@ -89,16 +87,10 @@ keeps LLM context. Claim and send warn at ≥10 commits behind
|
|
|
89
87
|
|
|
90
88
|
### Remote agents
|
|
91
89
|
|
|
92
|
-
The PANE is local, the PROCESS is remote
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
**Read [REMOTE_WORKERS.md](REMOTE_WORKERS.md) before spawning your first
|
|
98
|
-
remote agent, and again before waiting on one.** Poll once per turn with
|
|
99
|
-
the claim's one-shot `Next:` command. On a session-capped host, route
|
|
100
|
-
long commands and polls through [mule](https://github.com/mu-crew/mule):
|
|
101
|
-
a refused bare ssh returns an empty sha that looks like progress.
|
|
90
|
+
The PANE is local, the PROCESS is remote. **One orchestrator DB**: never
|
|
91
|
+
run a second mu on the host. **Read
|
|
92
|
+
[recipes/remote-workers.md](recipes/remote-workers.md) before spawning
|
|
93
|
+
your first remote agent, and again before waiting on one.**
|
|
102
94
|
**`mule` exit 3 is a HANDBACK** to the operator (hardware-key touch):
|
|
103
95
|
never retry or open `ssh -MNf` yourself.
|
|
104
96
|
|
|
@@ -124,78 +116,37 @@ ODDITIES: weird things not acted on
|
|
|
124
116
|
Then close with grounding:
|
|
125
117
|
`mu task close <id> -w <ws> --evidence "tests pass: cargo test exit 0"`.
|
|
126
118
|
|
|
127
|
-
## Orchestrator
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
(see below), return control. Do not barrier or loop in shell.
|
|
155
|
-
Only `CLOSED/done` ships; other closes: read the reason note.
|
|
156
|
-
8. Repeat from `mu state`.
|
|
157
|
-
|
|
158
|
-
## Dispatch rules that prevent real failures
|
|
159
|
-
|
|
160
|
-
- **Pipeline; don't barrier.** Wait for one task, cherry-pick only its
|
|
161
|
-
new commits, verify, return control. An umbrella wait hides progress;
|
|
162
|
-
merging stale branches can restore reverted code.
|
|
163
|
-
- **Verify the merge, not the worker's rerun.** Only the combination
|
|
164
|
-
with moved main is new; that found three breaks rerunning found none
|
|
165
|
-
of. Run a remote merge gate on the host (see REMOTE_WORKERS.md).
|
|
166
|
-
- **Push only from a green gate.** Make `git push` the last line under
|
|
167
|
-
`set -e`. Check the gate runs what it claims: an env-gated randomized
|
|
168
|
-
test once passed with zero cases.
|
|
169
|
-
- **Dispatch from current main.** Reset the worker's worktree to main
|
|
170
|
-
before each task.
|
|
171
|
-
- **Accept evidence, not close notes.** Re-run the key measurement from
|
|
172
|
-
a clean checkout; close notes have claimed unpushed commits.
|
|
173
|
-
- **Freeze only what conflicts.** Give idle workers tasks that avoid
|
|
174
|
-
shared files; a blanket freeze idled four of five workers for a day.
|
|
175
|
-
- **Fix done before a long run.** Put the completion criterion (checks,
|
|
176
|
-
agreeing runs, allowed variance) in the task note first.
|
|
177
|
-
- **Split long proofs into independent units**, sharded and parallel,
|
|
178
|
-
so one flake restarts only its unit.
|
|
179
|
-
- Bucket waves by file cluster, not severity; two agents editing one file
|
|
180
|
-
conflict. Refresh workspaces between waves.
|
|
181
|
-
- Cross-workstream wait and claim use qualified refs; only task
|
|
182
|
-
ownership crosses.
|
|
183
|
-
- For an idle worker, read the pane, then answer, retry, or release its
|
|
184
|
-
task. `MU_IDLE_THRESHOLD_MS` defaults to 5m.
|
|
185
|
-
- **Never chain `/new` and a prompt as two sends to a pi agent:** the prompt
|
|
186
|
-
can land mid-reset and vanish (it did, twice). `--fresh` does both inside pi.
|
|
187
|
-
- **Stop a worker:** `mu agent abort <w>` first for pi (exact, local or
|
|
188
|
-
remote, keeps context, waits for idle; exit 5 = still busy; queued
|
|
189
|
-
follow-ups return to the editor unsent). Then `mu agent kick` (pi
|
|
190
|
-
unresponsive, or non-pi; local panes only), then `mu agent close`.
|
|
191
|
-
- Use `mu agent send`, not raw mux input. Single-quote prompts containing shell
|
|
192
|
-
expansions, or use a quoted heredoc.
|
|
119
|
+
## Orchestrator rules
|
|
120
|
+
|
|
121
|
+
<!-- mu:keep-driving -->
|
|
122
|
+
**While workers run, keep driving.** Your turn ends only when every
|
|
123
|
+
task is closed, or when a decision only a human can make blocks all
|
|
124
|
+
progress (scope, spend, irreversible or external actions, a hardware-key
|
|
125
|
+
handback). A status summary is a log line, not a stopping point: write
|
|
126
|
+
it with `mu log`, then go straight back to `mu task wait`. Ending a
|
|
127
|
+
turn to report progress while workers are busy stalls the whole crew.
|
|
128
|
+
<!-- /mu:keep-driving -->
|
|
129
|
+
|
|
130
|
+
Before you dispatch, read [recipes/orchestrator-loop.md](recipes/orchestrator-loop.md):
|
|
131
|
+
the every-turn loop, waiting, merging, and stopping workers. These
|
|
132
|
+
rules hold even when you skip it:
|
|
133
|
+
|
|
134
|
+
- **Claim before sending**, even one-shot reviewers. Ownership is
|
|
135
|
+
durable and waitable; agent state is not.
|
|
136
|
+
- **Pipeline; don't barrier.** Merge each task as it closes.
|
|
137
|
+
- **Verify the merge, not the worker's rerun.** Only `CLOSED/done` ships.
|
|
138
|
+
- **Push only from a green gate.**
|
|
139
|
+
- **Fix done before a long run**: the completion criterion goes in the
|
|
140
|
+
task note first.
|
|
141
|
+
- **New work to pi is `mu agent send --fresh`.** Never chain `/new` and
|
|
142
|
+
a prompt as two sends: the prompt can land mid-reset and vanish.
|
|
143
|
+
- **`mu task wait --first --on-stall exit`**; exit 7 means read the
|
|
144
|
+
owner's pane and answer it.
|
|
145
|
+
- **Stop a worker gently**: `mu agent abort`, then `kick`, then `close`.
|
|
193
146
|
|
|
194
147
|
## CLI gotchas
|
|
195
148
|
|
|
196
|
-
- **`workstream teardown`** is dry-run without `--yes`.
|
|
197
|
-
TOMBSTONE ops, so `mu undo <group> --yes` reverses it; the log is the
|
|
198
|
-
backup. `workstream list --torn-down` lists group ids to undo.
|
|
149
|
+
- **`workstream teardown`** is dry-run without `--yes`.
|
|
199
150
|
- **`task close --if-ready`** no-ops until every blocker is CLOSED; bare
|
|
200
151
|
`task release` reopens IN_PROGRESS.
|
|
201
152
|
- **`task close --as rejected|wontfix --why ...`** (declined | valid, not worth it) unblocks dependents (listed in
|
|
@@ -204,32 +155,12 @@ Every turn:
|
|
|
204
155
|
IN_PROGRESS — `task release` first.
|
|
205
156
|
- **For waits use `task wait`, not `log --tail`.** `--kind` is the operator's
|
|
206
157
|
log-ledger channel; `--intent` is what mu recorded.
|
|
207
|
-
- **`mu undo`** bare lists groups; `<group>` previews; `<group> --yes`
|
|
208
|
-
emits inverse ops for that group only (redo = undo the undo). Exit 4
|
|
209
|
-
if a later action changed the same fields (`--force` discards it).
|
|
210
|
-
Rows only: killed panes and freed workspace dirs do not come back.
|
|
211
|
-
- **`mu rebuild <file>`** writes a new DB from the ops log, without
|
|
212
|
-
agents or workspaces; re-spawn after the swap. Recovery is
|
|
213
|
-
`mu rebuild`, not `mu db backup`.
|
|
214
158
|
- **`mu sql`** skips ambient sync.
|
|
215
|
-
- **
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
ownership never travel.
|
|
221
|
-
- **`mu doctor --deep` DRIFT** (exit 5) is a capture bug: back up and
|
|
222
|
-
report it. Do not rebuild; the live rows may hold work the log missed.
|
|
223
|
-
The `disk` section is report-only: an orphan dir may hold the only copy
|
|
224
|
-
of uncommitted work, so mu prints cleanup commands and runs none.
|
|
225
|
-
|
|
226
|
-
## `mu task wait`
|
|
227
|
-
|
|
228
|
-
Use `--first --on-stall exit`: `--first` populates `.firing`, and
|
|
229
|
-
`--on-stall exit` stops an unattended wait when a worker needs attention.
|
|
230
|
-
Exit 6 is a dead pane; exit 7 is an owner in `needs_input`. Read that
|
|
231
|
-
pane (`mu agent read <owner>`) and answer: the worker may be waiting on
|
|
232
|
-
you. Questions are cheaper than rework.
|
|
159
|
+
- **Never put `MU_DB_PATH` inside `MU_SYNC_DIR`**: it corrupts the DB.
|
|
160
|
+
- **`mu doctor --deep` DRIFT** (exit 5): back up and report it; do not
|
|
161
|
+
rebuild.
|
|
162
|
+
- Before undo, rebuild, teardown, sync setup, or acting on `doctor`
|
|
163
|
+
cleanup output, read [recipes/recovery.md](recipes/recovery.md).
|
|
233
164
|
|
|
234
165
|
## Models and thinking effort
|
|
235
166
|
|
|
@@ -258,31 +189,10 @@ says why. Before a high-stakes decision, read the pane
|
|
|
258
189
|
(`mu agent read worker-1 -n 100`), `mu log -w <ws> --tail`, and
|
|
259
190
|
`mu task notes <id>`.
|
|
260
191
|
|
|
261
|
-
##
|
|
262
|
-
|
|
263
|
-
`$MU_AGENT_NAME` (injected at spawn) resolves identity; adopted panes
|
|
264
|
-
fall back to the pane title. In a worker pane, bare `mu task claim <id>`
|
|
265
|
-
works. In the unregistered orchestrator pane it errors; use `--self`,
|
|
266
|
-
`--for <worker>`, or `mu agent adopt <pane>`.
|
|
267
|
-
|
|
268
|
-
```bash
|
|
269
|
-
mu me
|
|
270
|
-
mu me next
|
|
271
|
-
mu task show <id>; mu task notes <id>
|
|
272
|
-
mu task claim <id> --evidence "starting; read notes"
|
|
273
|
-
mu task note <id> "FILES: ...\nDECISION: ...\nVERIFIED: ..."
|
|
274
|
-
mu task close <id> --evidence "tests pass: ..." # LAST action
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
Skipping close makes the orchestrator's wait hang. Won't do it:
|
|
278
|
-
`close --as wontfix --why "..."`.
|
|
192
|
+
## You are a worker
|
|
279
193
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
A plain `mu agent send` appends to prior context; use it to steer or
|
|
283
|
-
answer. Unrelated work to pi: `mu agent send worker-1 --fresh 'Claim
|
|
284
|
-
task_x...'`. claude-code/codex: send `/new` (codex: `/clear`), then the
|
|
285
|
-
prompt; a send it cannot confirm prints a `warning:` on stderr.
|
|
194
|
+
If a task was claimed for you, follow [recipes/worker.md](recipes/worker.md).
|
|
195
|
+
Close the task as your last action, or the orchestrator's wait hangs.
|
|
286
196
|
|
|
287
197
|
## Guardrails
|
|
288
198
|
|
|
@@ -290,6 +200,36 @@ Task ownership outranks agent state. Coordinate through task notes and
|
|
|
290
200
|
the activity log. Keep edges within one workstream and reserve the `mu_`
|
|
291
201
|
task-id prefix. Give workers bounded paths and commands.
|
|
292
202
|
|
|
203
|
+
## Recipes
|
|
204
|
+
|
|
205
|
+
Read the recipe before starting the shape it names. For a large or
|
|
206
|
+
risky job that needs several of them, start with
|
|
207
|
+
[ultrathink](recipes/ultrathink.md).
|
|
208
|
+
|
|
209
|
+
| Recipe | Read when |
|
|
210
|
+
| --- | --- |
|
|
211
|
+
| [ultrathink](recipes/ultrathink.md) | a job is too large or risky for one context; composes the rest |
|
|
212
|
+
| [orchestrator-loop](recipes/orchestrator-loop.md) | you dispatch tasks and merge results |
|
|
213
|
+
| [brief](recipes/brief.md) | you write a task note or prompt a worker will read |
|
|
214
|
+
| [plan](recipes/plan.md) | you turn a spec or requirements into a task DAG |
|
|
215
|
+
| [worker](recipes/worker.md) | a task was claimed for you |
|
|
216
|
+
| [recovery](recipes/recovery.md) | undo, rebuild, teardown, sync setup, `doctor` cleanup |
|
|
217
|
+
| [remote-workers](recipes/remote-workers.md) | an agent runs on another machine |
|
|
218
|
+
| [waves](recipes/waves.md) | more than one worker edits the same repo at once |
|
|
219
|
+
| [long-run](recipes/long-run.md) | a task or proof runs for hours, or must survive flakes |
|
|
220
|
+
| [watcher](recipes/watcher.md) | a helper polls a PR, CI, or log for change |
|
|
221
|
+
| [adversarial-review](recipes/adversarial-review.md) | work must be checked by someone other than its author before it counts |
|
|
222
|
+
| [fan-out](recipes/fan-out.md) | the same change or check applies to many units |
|
|
223
|
+
| [refute](recipes/refute.md) | an audit, sweep, or fact-check produces findings |
|
|
224
|
+
| [hypothesis-panel](recipes/hypothesis-panel.md) | a root cause is unknown (flaky test, intermittent bug) |
|
|
225
|
+
| [tournament](recipes/tournament.md) | several answers are possible and the best is a judgement call |
|
|
226
|
+
| [loop-until-done](recipes/loop-until-done.md) | the amount of work is unknown until a check passes |
|
|
227
|
+
| [triage](recipes/triage.md) | a backlog of external items needs classifying and acting on |
|
|
228
|
+
| [deep-research](recipes/deep-research.md) | a question needs many sources read and cross-checked |
|
|
229
|
+
| [review-panel](recipes/review-panel.md) | one diff or PR needs review from several angles |
|
|
230
|
+
| [rules-audit](recipes/rules-audit.md) | a change must follow AGENTS.md rule by rule, or rules keep being restated |
|
|
231
|
+
| [codemode-driver](recipes/codemode-driver.md) | a codemode script would dispatch a wave in parallel |
|
|
232
|
+
|
|
293
233
|
## See also
|
|
294
234
|
|
|
295
235
|
- `mu --help`, `mu <verb> --help` — canonical CLI reference.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Adversarial review
|
|
2
|
+
|
|
3
|
+
Use when a unit of work must be checked by someone other than its
|
|
4
|
+
author before it counts: a fix, a finding, a claim, a plan. The author
|
|
5
|
+
grades its own work generously; a fresh agent told to refute it does
|
|
6
|
+
not. Every other review-shaped recipe builds on this one.
|
|
7
|
+
|
|
8
|
+
The review is a task in the DAG, not a step inside the worker's
|
|
9
|
+
session. Its verdict, its evidence, and every rejection stay in the DB.
|
|
10
|
+
|
|
11
|
+
## Steps
|
|
12
|
+
|
|
13
|
+
1. **Write the criteria first.** Before dispatching the work, note on
|
|
14
|
+
the work task what "accepted" means: the requirements, the edge
|
|
15
|
+
cases that need tests, the files that must not change. The reviewer
|
|
16
|
+
judges against this note, not against its own taste.
|
|
17
|
+
2. **Add the review task, blocked by the work:**
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
mu task add review_x -w <ws> -t "Review x" -i 50 -e 0.5 --blocked-by x \
|
|
21
|
+
--note 'ACCEPTANCE: see x notes. Refute; report gaps, not style.'
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
3. **Dispatch the work** as usual. When `x` closes, `review_x` becomes
|
|
25
|
+
ready.
|
|
26
|
+
4. **Spawn a fresh reviewer.** A new agent, or `--fresh` on an idle one,
|
|
27
|
+
so it has none of the author's reasoning. Use a different model from
|
|
28
|
+
the worker where you can (`--cli pi_big` reviewing `pi`): a second
|
|
29
|
+
model has different blind spots. Give it the worker's workspace path
|
|
30
|
+
and commits read-only by instruction; it edits nothing.
|
|
31
|
+
5. **Send the reviewer brief** (below), claim `review_x` for it, wait.
|
|
32
|
+
6. **Act on the verdict:**
|
|
33
|
+
- `ACCEPT`: cherry-pick `x`'s commits and verify the merge.
|
|
34
|
+
- `REJECT`: add `fix_x` (blocked by `review_x`, note = the gaps) and
|
|
35
|
+
`review_x_2` (blocked by `fix_x`). Dispatch `fix_x` to the original
|
|
36
|
+
worker, whose context still holds the work. Repeat from step 4.
|
|
37
|
+
The DAG grows; nothing is rewritten.
|
|
38
|
+
- The `fix_x` brief tells the author to check each gap before fixing
|
|
39
|
+
it: reproduce it, then fix it, or answer it with evidence in the
|
|
40
|
+
note (`GAP 2: not reproducible, <command + output>`). A gap the
|
|
41
|
+
author disputes goes to the next reviewer as a claim to check,
|
|
42
|
+
not as settled.
|
|
43
|
+
7. **Cap the rounds.** After two rejections on the same unit, stop the
|
|
44
|
+
loop and decide yourself: split the unit, change the criteria, or
|
|
45
|
+
ask the human. A third round of the same argument rarely converges.
|
|
46
|
+
|
|
47
|
+
Done when the latest review task closed with `VERDICT: ACCEPT`, and the
|
|
48
|
+
accepted commits are merged and the merged tree passes the gate.
|
|
49
|
+
|
|
50
|
+
## Reviewer brief
|
|
51
|
+
|
|
52
|
+
Send this with the task id, the workspace path, and the commit range:
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
You are reviewing task <x>. You did not write it. Your job is to find
|
|
56
|
+
where it fails the acceptance criteria in `mu task notes <x>`.
|
|
57
|
+
|
|
58
|
+
- Read the diff (<range>) and the criteria. Run the tests that cover it.
|
|
59
|
+
- Report gaps against the criteria: a requirement not met, an edge case
|
|
60
|
+
without a test, a change outside scope, a claim the evidence does not
|
|
61
|
+
support. Not style, not preferences.
|
|
62
|
+
- Each gap cites a file:line or a command and its output.
|
|
63
|
+
- If you could not check something (tool failed, no access), say
|
|
64
|
+
UNVERIFIED for it. Unverified is not a pass and not a fail.
|
|
65
|
+
- Do not edit files.
|
|
66
|
+
|
|
67
|
+
End with a note in the task note contract, plus one line:
|
|
68
|
+
VERDICT: ACCEPT | REJECT
|
|
69
|
+
Then close: mu task close review_<x> --evidence '<verdict + key check>'
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Traps
|
|
73
|
+
|
|
74
|
+
- **A reviewer that sees the author's reasoning agrees with it.** Send
|
|
75
|
+
the diff and the criteria, not the worker's transcript or close note.
|
|
76
|
+
- **"Looks good" is not a verdict.** Require the `VERDICT:` line and at
|
|
77
|
+
least one command the reviewer ran. A review with no evidence is a
|
|
78
|
+
rejected review: re-send it.
|
|
79
|
+
- **Reviewers drift into fixing.** A reviewer that edits the code is now
|
|
80
|
+
an author nobody reviews. Keep the fix in `fix_x`.
|
|
81
|
+
- **Review is not merge verification.** An accepted unit can still
|
|
82
|
+
break once merged with moved main. Verify the merge as in
|
|
83
|
+
[orchestrator-loop](orchestrator-loop.md#merging).
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Writing a brief
|
|
2
|
+
|
|
3
|
+
Use when you write anything a worker reads: a task note, a `--fresh`
|
|
4
|
+
prompt, a reviewer brief. The worker starts with no context. What is
|
|
5
|
+
not in the brief, or one pointer away, does not exist for it.
|
|
6
|
+
|
|
7
|
+
<!-- Ideas adapted from mattpocock/skills `writing-for-agents` (MIT). -->
|
|
8
|
+
|
|
9
|
+
## Rules
|
|
10
|
+
|
|
11
|
+
1. **End on a completion criterion.** The brief says how the worker
|
|
12
|
+
tells done from not done, and the criterion is both checkable and
|
|
13
|
+
exhaustive: "every file in the UNITS list compiles under
|
|
14
|
+
`npm run typecheck`", not "update the call sites". A vague bound
|
|
15
|
+
invites the worker to stop at the first plausible point.
|
|
16
|
+
2. **Inline what every path needs; point to the rest.** Files, the
|
|
17
|
+
verify command, scope, and the final action go in the brief. Shared
|
|
18
|
+
context goes in one place (an umbrella's note) and the brief points
|
|
19
|
+
at it: `Read: mu task notes sweep -w audit`. Repeating it per task
|
|
20
|
+
copies it into every worker's context and lets the copies drift.
|
|
21
|
+
3. **State the target, not the ban.** "Edit only files under
|
|
22
|
+
`src/auth/`" works; "don't touch other files" puts other files in
|
|
23
|
+
the worker's head. Keep a prohibition only for a hard guardrail
|
|
24
|
+
with no positive form, and pair it with the positive target.
|
|
25
|
+
4. **Reuse the recipe words.** *Unit*, *stop rule*, *verdict*,
|
|
26
|
+
*finding*, *umbrella* mean the same thing in every recipe. Use them
|
|
27
|
+
as written; a worker that read one recipe brief reads the next
|
|
28
|
+
faster.
|
|
29
|
+
5. **Cut the default.** A sentence the worker would obey anyway
|
|
30
|
+
("be careful", "write clean code") costs attention and changes
|
|
31
|
+
nothing. Delete the whole sentence.
|
|
32
|
+
6. **Ask for evidence, not reassurance.** The final note names the
|
|
33
|
+
commands run and their exit codes (the task note contract). "Done,
|
|
34
|
+
all good" is not a result.
|
|
35
|
+
|
|
36
|
+
## Shape
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
Task <id> in <ws>. Workspace: <path>.
|
|
40
|
+
Read: mu task notes <id> -w <ws> (and the umbrella's, if any)
|
|
41
|
+
|
|
42
|
+
GOAL: <one sentence>
|
|
43
|
+
FILES: <paths it may change>
|
|
44
|
+
DONE WHEN: <checkable, exhaustive criterion>
|
|
45
|
+
VERIFY: <exact command>
|
|
46
|
+
|
|
47
|
+
⚠️ FINAL ACTION
|
|
48
|
+
git commit -am '<msg>' THEN
|
|
49
|
+
mu task close <id> -w <ws> --evidence '<command + result>'
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Done when a worker with no other context could finish the task from
|
|
53
|
+
the brief and the notes it points at, and could tell when it is done.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Codemode driver
|
|
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.
|
|
7
|
+
|
|
8
|
+
## The rule
|
|
9
|
+
|
|
10
|
+
**Delete the script mid-run and nothing is lost.** That holds when:
|
|
11
|
+
|
|
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.
|
|
15
|
+
- Every task it dispatches exists in the DAG before the script starts.
|
|
16
|
+
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
|
+
- `store()` / `load()` hold nothing a re-run needs. The DAG is the
|
|
19
|
+
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>'`.
|
|
22
|
+
|
|
23
|
+
## Shape
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
// @options: {"timeout_ms": 1800000}
|
|
27
|
+
const ws = "audit";
|
|
28
|
+
const sh = async (c) => {
|
|
29
|
+
const r = await tools.bash({ command: c });
|
|
30
|
+
if (r.exit_code !== 0) throw new Error(`${c}: ${r.output}`);
|
|
31
|
+
return r.output;
|
|
32
|
+
};
|
|
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}'`);
|
|
38
|
+
}));
|
|
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` });
|
|
40
|
+
return wait.output;
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Check field names against `--json` output before relying on them; the
|
|
44
|
+
script above is a shape, not an API.
|
|
45
|
+
|
|
46
|
+
## Traps
|
|
47
|
+
|
|
48
|
+
- **One wave per script.** A script that loops forever hides progress
|
|
49
|
+
from you and from the human. Dispatch, wait for the first close,
|
|
50
|
+
return; merge and verify outside the script, then run it again.
|
|
51
|
+
- **A script timeout cancels the waits, not the workers.** Workers keep
|
|
52
|
+
running and their tasks stay claimed. Re-read `mu state` and carry on.
|
|
53
|
+
- **Exit codes are data.** `mu task wait` exit 7 means a worker needs
|
|
54
|
+
you; return it to the model instead of retrying.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Deep research
|
|
2
|
+
|
|
3
|
+
Use when a question needs more sources than one context can read and
|
|
4
|
+
checking them against each other: how a library or protocol behaves,
|
|
5
|
+
what changed between versions, how competitors solve a problem, whether
|
|
6
|
+
a claim in a draft holds. This is [refute](refute.md) applied to
|
|
7
|
+
sources. Workers need a web search tool (pi's `brave_search`, or
|
|
8
|
+
`curl` on docs) or the code they research.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
1. **Write the question and the bar** on an umbrella task: the exact
|
|
13
|
+
question, what a good answer contains (a recommendation, a
|
|
14
|
+
comparison table, a yes/no with conditions), and how fresh sources
|
|
15
|
+
must be.
|
|
16
|
+
2. **Split by angle**, one search task per angle: official docs,
|
|
17
|
+
changelogs and release notes, issue trackers, independent write-ups,
|
|
18
|
+
the code itself. Each searcher reads, fetches, and writes claims to
|
|
19
|
+
its note, one per line:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
CLAIM: c4 "Node 22 enables the permission model by default" SOURCE: <url> QUOTE: "<exact words>"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
A claim without a source and a quote is not a claim. Searchers can
|
|
26
|
+
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
|
|
31
|
+
gets the claim and its sources, not the searcher's reasoning, fetches
|
|
32
|
+
the source itself, and tries to break the claim: is the quote there,
|
|
33
|
+
does it say that, is it current, does another source disagree? It
|
|
34
|
+
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
|
|
37
|
+
from confirmed claims only, each with its source URL. List
|
|
38
|
+
unverified claims separately. Note what the sources disagree on and
|
|
39
|
+
which side the evidence favours.
|
|
40
|
+
|
|
41
|
+
Done when every claim the answer uses has a `CONFIRMED` verdict line,
|
|
42
|
+
every sentence of fact in the report cites a URL, and the report meets
|
|
43
|
+
the bar from step 1.
|
|
44
|
+
|
|
45
|
+
## Traps
|
|
46
|
+
|
|
47
|
+
- **A fetch failure is UNVERIFIED, not REFUTED.** Rate limits and
|
|
48
|
+
paywalls block checkers; say so, do not drop the claim silently.
|
|
49
|
+
- **Secondary sources copy each other.** Three blog posts repeating one
|
|
50
|
+
changelog are one source. Prefer the primary source in the dedupe.
|
|
51
|
+
- **Version drift.** A claim true for v2 can be false for v3. Checkers
|
|
52
|
+
confirm the version the question asks about.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Fan-out
|
|
2
|
+
|
|
3
|
+
Use when the same treatment applies to many units: files, call sites,
|
|
4
|
+
failing tests, findings, modules. One context holding 50 units drops
|
|
5
|
+
some and calls the job done; one task per unit cannot.
|
|
6
|
+
|
|
7
|
+
## Steps
|
|
8
|
+
|
|
9
|
+
1. **Enumerate first, as its own task.** A scout lists the units and
|
|
10
|
+
writes them to the umbrella's note, one per line. The list is done
|
|
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.
|
|
13
|
+
2. **One task per unit**, blocked into an umbrella:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
mu task add sweep -w <ws> -t "Sweep: <goal>" -i 60 -e 1 --note 'UNITS: 37 (rg -l ... | wc -l)'
|
|
17
|
+
mu task add sweep_auth_ts -w <ws> -t "Sweep src/auth.ts" -i 50 -e 0.2
|
|
18
|
+
mu task block sweep -w <ws> --by sweep_auth_ts
|
|
19
|
+
```
|
|
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
|
|
28
|
+
go on one track (see [waves](waves.md)).
|
|
29
|
+
5. **Review per unit** when a wrong unit is costly: add a review task
|
|
30
|
+
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.
|
|
34
|
+
|
|
35
|
+
Done when `mu task close sweep --if-ready` closes the umbrella: every
|
|
36
|
+
unit is closed, and the closed count matches the step 1 count.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Hypothesis panel
|
|
2
|
+
|
|
3
|
+
Use for root-cause work: a flaky test, an intermittent bug, a metric
|
|
4
|
+
that moved. One agent that forms a theory then tests its own theory
|
|
5
|
+
finds evidence for it. Separate agents, each given different evidence,
|
|
6
|
+
form independent theories; separate agents then try to kill them.
|
|
7
|
+
|
|
8
|
+
## Steps
|
|
9
|
+
|
|
10
|
+
1. **Write the symptom** on the umbrella: what happens, how often, the
|
|
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>
|
|
19
|
+
```
|
|
20
|
+
|
|
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>`.
|
|
25
|
+
4. **If one survives**, add a fix task for it, then a review task
|
|
26
|
+
([adversarial-review](adversarial-review.md)). The fix is accepted
|
|
27
|
+
only if the step 1 repro stops reproducing.
|
|
28
|
+
5. **If none survives**, start another round
|
|
29
|
+
([loop-until-done](loop-until-done.md)): the new hypothesis tasks get
|
|
30
|
+
the killed hypotheses and their evidence as input.
|
|
31
|
+
|
|
32
|
+
Done when a fix closed `ACCEPT` and the repro from step 1 no longer
|
|
33
|
+
reproduces at the rate step 1 recorded.
|
|
34
|
+
|
|
35
|
+
## Traps
|
|
36
|
+
|
|
37
|
+
- **Two survivors** usually means the experiments were too weak. Design
|
|
38
|
+
one experiment that separates them before you fix either.
|
|
39
|
+
- **Flaky repros need counts.** "Passed once" proves nothing for a 1 in
|
|
40
|
+
50 failure. Put the run count in step 1.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Long runs
|
|
2
|
+
|
|
3
|
+
Use when a task or proof runs for hours, crosses context compaction,
|
|
4
|
+
or may hit flakes.
|
|
5
|
+
|
|
6
|
+
1. **Fix done first.** Before dispatch, write the completion criterion
|
|
7
|
+
into the task note: the checks, how many runs must agree, the
|
|
8
|
+
allowed variance. A worker that finds the bar in the note stops at
|
|
9
|
+
the bar, not at the first green.
|
|
10
|
+
2. **Split into independent units.** Shard a long proof into tasks
|
|
11
|
+
that run in parallel, so one flake restarts only its unit. Each unit
|
|
12
|
+
carries its own criterion.
|
|
13
|
+
3. **Keep state in the DB.** Progress lives in task notes, not in the
|
|
14
|
+
orchestrator's context. After a compaction, `mu state` and
|
|
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.
|
|
18
|
+
|
|
19
|
+
Done when every unit is `CLOSED/done` and the criterion from step 1
|
|
20
|
+
holds on the merged tree.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Loop until done
|
|
2
|
+
|
|
3
|
+
Use when the amount of work is unknown: fix type errors until clean,
|
|
4
|
+
find flaky tests until none are new, search until nothing new turns up.
|
|
5
|
+
A fixed number of passes stops too early or runs too long; a stop rule
|
|
6
|
+
written down first does neither.
|
|
7
|
+
|
|
8
|
+
## Steps
|
|
9
|
+
|
|
10
|
+
1. **Write the stop rule** on the umbrella before the first round. It
|
|
11
|
+
names a command and a condition, plus a no-progress rule:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
STOP: `npx tsc --noEmit` exits 0
|
|
15
|
+
NO-PROGRESS: two rounds in a row reduce the error count by zero
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
2. **Each round is a task**, blocked by the previous one:
|
|
19
|
+
`round_1`, `round_2`, .... Add the next round only when the current
|
|
20
|
+
one closes; never pre-create rounds.
|
|
21
|
+
3. **Each round ends with its measurement** in the note:
|
|
22
|
+
`MEASURE: 14 errors (was 31)`, or `NEW: 0 flaky tests`.
|
|
23
|
+
4. **After each round, check the rule** yourself, from the measurement
|
|
24
|
+
command, not from the worker's note.
|
|
25
|
+
- Rule met: close the umbrella.
|
|
26
|
+
- No progress: stop the loop and decide. Change the approach, split
|
|
27
|
+
the work, or park the umbrella with
|
|
28
|
+
`mu task park <umbrella> --why '<what is stuck>'` and tell the human.
|
|
29
|
+
- Otherwise: add the next round and dispatch it.
|
|
30
|
+
|
|
31
|
+
Done when the stop rule holds on the merged tree, run by you.
|
|
32
|
+
|
|
33
|
+
## Traps
|
|
34
|
+
|
|
35
|
+
- **A round that only reports is not progress.** Each round must change
|
|
36
|
+
something (fix, new search slice) or produce a new measurement.
|
|
37
|
+
- **Moving goalposts.** Edit the stop rule only with a note saying why;
|
|
38
|
+
the old rule stays in the history.
|