@mu-crew/mu 3.2.0 → 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 +208 -599
- package/README.md +125 -329
- package/dist/cli.js +108 -78
- package/dist/cli.js.map +1 -1
- package/dist/extension/mu-pi.js +421 -56
- 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 +176 -1072
- package/docs/ROADMAP.md +88 -169
- package/docs/VISION.md +205 -415
- package/docs/VOCABULARY.md +204 -466
- package/docs/architecture/control-socket.md +133 -0
- package/docs/architecture/dag.md +113 -0
- package/docs/architecture/mux.md +162 -0
- package/docs/architecture/ops-log.md +140 -0
- package/docs/architecture/sdk.md +185 -0
- package/docs/architecture/sync.md +129 -0
- package/docs/architecture/tui.md +146 -0
- package/docs/guide/README.md +30 -0
- package/docs/guide/backends.md +61 -0
- package/docs/guide/cleanup.md +74 -0
- package/docs/guide/delegate.md +87 -0
- package/docs/guide/dispatch.md +144 -0
- package/docs/guide/getting-started.md +180 -0
- package/docs/guide/recovery.md +135 -0
- package/docs/guide/remote.md +74 -0
- package/docs/guide/sql.md +76 -0
- package/docs/guide/stop-a-worker.md +64 -0
- package/docs/guide/sync.md +78 -0
- package/docs/guide/tui.md +98 -0
- package/docs/guide/upgrade.md +76 -0
- package/docs/history/CHANGELOG-pre-3.md +4866 -0
- package/docs/reference/env.md +87 -0
- package/docs/reference/naming.md +82 -0
- package/docs/specs/2026-09-28-agent-state-from-murmur.md +1 -1
- package/docs/specs/2026-09-29-task-substates.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 +126 -255
- 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/remote-workers.md +292 -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/docs/HANDOVER.md +0 -486
- package/docs/USAGE_GUIDE.md +0 -2738
- package/skills/mu/REMOTE_WORKERS.md +0 -617
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# How to delegate a one-off task
|
|
2
|
+
|
|
3
|
+
## Delegate from pi
|
|
4
|
+
|
|
5
|
+
`mu link pi` installs the `mu_delegate` and `mu_delegate_cancel` tools
|
|
6
|
+
in every pi session. Ask pi in plain words:
|
|
7
|
+
|
|
8
|
+
- "Delegate a review of src/x.ts to a helper."
|
|
9
|
+
- "Have three helpers investigate A, B, and C."
|
|
10
|
+
|
|
11
|
+
pi calls `mu_delegate`. It spawns a pi agent in the reserved `scratch`
|
|
12
|
+
workstream and returns at once with the delegate's name and attach
|
|
13
|
+
command. The answer arrives later as a follow-up message; do not poll.
|
|
14
|
+
Delegates called in one turn run in parallel.
|
|
15
|
+
|
|
16
|
+
| Option | Meaning |
|
|
17
|
+
| ------ | ------- |
|
|
18
|
+
| `task` (required) | All the context. The delegate starts empty. |
|
|
19
|
+
| `label` | Names the delegate: `review` gives `delegate-review`. |
|
|
20
|
+
| `brief` | Ad hoc persona or ground rules, sent first. Not enforced. |
|
|
21
|
+
| `cwd` | Start directory. Default: the caller's. Must exist. |
|
|
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
|
+
| `workspace` | Own VCS checkout, for delegates that edit files. The follow-up names its path. It isolates repository edits only. |
|
|
24
|
+
| `cli` | Key for `$MU_<CLI>_COMMAND` (default `pi`), e.g. a cheaper model. |
|
|
25
|
+
| `keep` | Keep the pane after it finishes, to talk to it again. |
|
|
26
|
+
|
|
27
|
+
- Watch or steer: run the attach command.
|
|
28
|
+
- Stop: `mu_delegate_cancel`, or `mu agent abort <name> -w scratch`.
|
|
29
|
+
- The pane closes after a clean finish; died or timed-out panes stay
|
|
30
|
+
as evidence.
|
|
31
|
+
- pi's footer shows how many delegates this session is waiting on.
|
|
32
|
+
- Each delegate costs a pane and a pi process.
|
|
33
|
+
|
|
34
|
+
`MU_DELEGATE=0` hides the tool ([env vars](../reference/env.md)).
|
|
35
|
+
|
|
36
|
+
## Delegate without pi
|
|
37
|
+
|
|
38
|
+
From a script or other shell, run what the tool runs:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
mu agent spawn helper-1 -w scratch
|
|
42
|
+
mu agent send helper-1 -w scratch --fresh 'Investigate why foo.spec.ts fails. Report the cause.'
|
|
43
|
+
mu agent wait helper-1 -w scratch --json
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Use `--fresh`: a plain send to a reused agent carries the previous
|
|
47
|
+
task's context.
|
|
48
|
+
|
|
49
|
+
`mu agent wait` fires when the agent leaves busy (including to
|
|
50
|
+
`needs_input`), never on an already idle agent. For pi, the `--json`
|
|
51
|
+
row carries:
|
|
52
|
+
|
|
53
|
+
- `outcome`: `done`, `empty`, `died`, `timeout`, or `pending`.
|
|
54
|
+
- `lastText`: the final message, capped at 64 KiB.
|
|
55
|
+
|
|
56
|
+
Exit codes: `0` met, `5` timeout, `6` pane died. Non-pi agents have no
|
|
57
|
+
`lastText`; read the pane with `mu agent read helper-1 -w scratch -n 80`.
|
|
58
|
+
|
|
59
|
+
## Keep a helper
|
|
60
|
+
|
|
61
|
+
Pass `keep: true`, or spawn a named agent in `scratch`. It is created
|
|
62
|
+
on first spawn, needs no tasks, and cannot be `init`ed.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
mu agent spawn helper -w scratch
|
|
66
|
+
mu agent send helper -w scratch 'Watch CI on PR 1234 and tell me when it is green'
|
|
67
|
+
mu agent read helper -w scratch -n 50
|
|
68
|
+
mu agent close helper -w scratch
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
A watcher's chat context does not survive compaction. Log each tick
|
|
72
|
+
under your own `--kind`; read the latest entry on the next:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
mu log -w scratch --kind pr-state 'pr=1234 sha=abc ci=red -> spawned fixer-1'
|
|
76
|
+
mu log -w scratch --kind pr-state -n 1 --json
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Act only on change. `--since <seq>` replays entries a dead watcher
|
|
80
|
+
missed.
|
|
81
|
+
|
|
82
|
+
## When to stop delegating
|
|
83
|
+
|
|
84
|
+
Dependencies, several agents, or review need a real workstream: see
|
|
85
|
+
[Getting started](getting-started.md) and
|
|
86
|
+
[How to dispatch work](dispatch.md). There, `mu task wait` keys on the
|
|
87
|
+
task and has `--on-stall`.
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# How to dispatch work to a worker
|
|
2
|
+
|
|
3
|
+
This guide assumes you finished [Getting started](getting-started.md).
|
|
4
|
+
The agent-facing loop and its traps are in
|
|
5
|
+
[recipes/orchestrator-loop.md](../../skills/mu/recipes/orchestrator-loop.md). For several workers in
|
|
6
|
+
one repo, see [waves](../../skills/mu/recipes/waves.md); for runs that
|
|
7
|
+
last hours, see [long runs](../../skills/mu/recipes/long-run.md).
|
|
8
|
+
|
|
9
|
+
## Claim before you send
|
|
10
|
+
|
|
11
|
+
Always claim the task for the worker before the first send, even for a
|
|
12
|
+
one-shot reviewer:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
mu task claim build -w auth --for worker-1
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`mu task wait` watches tasks, and the reaper returns a claimed task to
|
|
19
|
+
`OPEN` when its pane dies. An unclaimed task gets neither. If no task
|
|
20
|
+
exists, create one with `mu task add --note '<brief>'`.
|
|
21
|
+
|
|
22
|
+
- `--for` takes a worker name or a qualified `<workstream>/<name>`.
|
|
23
|
+
The worker stays in its own workstream. Only the ownership crosses.
|
|
24
|
+
- Inside a worker's pane, bare `mu task claim <id>` uses the pane
|
|
25
|
+
title as the worker name.
|
|
26
|
+
- To do the task yourself, use `mu task claim <id> --self`.
|
|
27
|
+
|
|
28
|
+
## Pick the send mode
|
|
29
|
+
|
|
30
|
+
For a pi agent, `mu agent send` goes through the agent's control
|
|
31
|
+
socket. Pick the mode by what the agent is doing:
|
|
32
|
+
|
|
33
|
+
| Situation | Command |
|
|
34
|
+
| --------- | ------- |
|
|
35
|
+
| New task, any state | `mu agent send worker-1 --fresh '<brief>'` |
|
|
36
|
+
| Busy, and you want to interrupt the current run | `mu agent send worker-1 --steer '<text>'` |
|
|
37
|
+
| Answering a question, or adding to the same task | `mu agent send worker-1 '<text>'` |
|
|
38
|
+
|
|
39
|
+
- `--fresh` starts a new pi session and sends the prompt into it as
|
|
40
|
+
one operation. It refuses with exit 4 while pi is busy. Run
|
|
41
|
+
`mu agent abort` first, or pass `--force` to drop the running turn.
|
|
42
|
+
- Never send `/new` and then the prompt as two sends to pi. The prompt
|
|
43
|
+
can land during the reset and vanish.
|
|
44
|
+
- A plain send to a busy agent queues as a follow-up.
|
|
45
|
+
- `/new`, `/reload` and `/compact [instructions]` run inside pi through
|
|
46
|
+
the socket and report pi's answer (for example `Nothing to compact`).
|
|
47
|
+
They refuse with exit 4 while pi is busy; `--force` overrides. Any
|
|
48
|
+
other slash command exits 2; add `--via mux` to type it into the pane.
|
|
49
|
+
- If the socket does not answer, the send fails with exit 1 and
|
|
50
|
+
pastes nothing. `--via mux` pastes into the pane on purpose.
|
|
51
|
+
|
|
52
|
+
After a claim, spawn, or wait, the `Next:` block prints the right send.
|
|
53
|
+
|
|
54
|
+
### Non-pi agents
|
|
55
|
+
|
|
56
|
+
Agents other than pi have no control socket, so mu pastes the text
|
|
57
|
+
into the pane. To start a new session, send `/new` (codex: `/clear`),
|
|
58
|
+
then the prompt. If mu prints `warning: ... was NOT submitted`, the
|
|
59
|
+
agent has not seen the text. Read the pane before you wait. On a slow
|
|
60
|
+
tmux link, raise `MU_SEND_DELAY_MS` (default 500 ms).
|
|
61
|
+
|
|
62
|
+
## Write the brief
|
|
63
|
+
|
|
64
|
+
Put the full brief in a task note, so it survives context compaction
|
|
65
|
+
and the next agent can read it. Send a short prompt that points at it:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
mu task note build -w auth 'FILES: src/auth/\nVERIFY: npm test\nSCOPE: no schema changes'
|
|
69
|
+
mu agent send worker-1 -w auth --fresh 'Work on build. Read: mu task notes build -w auth'
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
End the brief with the exact final action, for example:
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
⚠️ FINAL ACTION
|
|
76
|
+
git commit -am '...' THEN
|
|
77
|
+
mu task close build -w auth --evidence '...'
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Single-quote prompts that contain `$` or backticks. To see only what the worker wrote after the claim, run
|
|
81
|
+
`mu task notes build -w auth --since-claim`.
|
|
82
|
+
|
|
83
|
+
## Give each worker a workspace
|
|
84
|
+
|
|
85
|
+
`mu agent spawn --workspace` creates a jj, sl, or git worktree for the
|
|
86
|
+
agent (`cp -a` outside a repo). You cherry-pick from it.
|
|
87
|
+
|
|
88
|
+
Refresh the workspace between tasks. The rebase keeps the agent's pi
|
|
89
|
+
context:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
mu workspace refresh worker-1 -w auth
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
It rebases onto the remote's main (`origin/HEAD`); without a remote,
|
|
96
|
+
pass `--from main`. It refuses on a dirty tree. On a conflict it exits 5
|
|
97
|
+
with a `cd` hint. To throw the workspace away instead, run
|
|
98
|
+
`mu workspace free worker-1 -w auth`.
|
|
99
|
+
|
|
100
|
+
Claim and send warn when the worker's workspace is 10 or more commits
|
|
101
|
+
behind main. `--strict-staleness` makes that a refusal (exit 4).
|
|
102
|
+
|
|
103
|
+
## Wait for the first task to close
|
|
104
|
+
|
|
105
|
+
Wait on every in-flight task and handle the first one that closes:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
mu task wait auth/build auth/docs --first --on-stall exit --json
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
- `--first` prints the closed ref and fills `firing` in `--json`.
|
|
112
|
+
`--any` leaves `firing` null even on success.
|
|
113
|
+
- `nextSteps[0]` is the cherry-pick command for the worker's new
|
|
114
|
+
commits. If the worker closed without committing, it says so.
|
|
115
|
+
- Exit codes: `0` met, `5` timeout, `6` the owner's pane died,
|
|
116
|
+
`7` the owner sat in `needs_input` for `--stuck-after` seconds
|
|
117
|
+
(default 300).
|
|
118
|
+
|
|
119
|
+
Exit 7 has several causes: the worker finished but did not close, it
|
|
120
|
+
asked a question, or it hit a prompt. In each case, run
|
|
121
|
+
`mu agent read <owner>` first.
|
|
122
|
+
|
|
123
|
+
Pipeline the work: merge one task, run your tests on the merged tree,
|
|
124
|
+
then dispatch the next task. Waiting for a whole wave hides partial
|
|
125
|
+
progress.
|
|
126
|
+
|
|
127
|
+
## Close and park tasks
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
mu task close spike -w auth --as wontfix --why "superseded by v2"
|
|
131
|
+
mu task close umbrella -w auth --if-ready
|
|
132
|
+
mu task park polish -w auth --why "after the release"
|
|
133
|
+
mu task release build -w auth
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- Closed substates other than `done` need `--why`. Every `CLOSED`
|
|
137
|
+
substate satisfies a blocker.
|
|
138
|
+
- `--if-ready` closes only when every blocker is closed. Otherwise it
|
|
139
|
+
lists the open blockers and exits 0.
|
|
140
|
+
- A parked task leaves the ready set, and its dependents keep waiting.
|
|
141
|
+
- `release` clears the owner and returns `IN_PROGRESS` to `OPEN`.
|
|
142
|
+
|
|
143
|
+
To wait on something outside the repo, such as an upstream release,
|
|
144
|
+
block on a placeholder task and close it when the thing lands.
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Getting started
|
|
2
|
+
|
|
3
|
+
In this tutorial we install mu, plan two tasks where one blocks the
|
|
4
|
+
other, hand the first task to a pi worker, and merge its commit. It
|
|
5
|
+
takes about ten minutes.
|
|
6
|
+
|
|
7
|
+
You need Node.js, the pi coding agent, tmux 3.0
|
|
8
|
+
or later, and a git repository to work in. Run every command from
|
|
9
|
+
inside a tmux session, in the root of that repository.
|
|
10
|
+
|
|
11
|
+
## Install mu and link pi
|
|
12
|
+
|
|
13
|
+
First, install mu and connect it to pi:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm i -g @mu-crew/mu
|
|
17
|
+
mu link pi
|
|
18
|
+
mu doctor
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`mu link pi` installs the mu pi extension and the mu skill. In the
|
|
22
|
+
output of `mu doctor`, the extension, skill, and `ctl` rows say `ok`.
|
|
23
|
+
If pi was already running, restart it so it loads the extension.
|
|
24
|
+
|
|
25
|
+
## Create a workstream
|
|
26
|
+
|
|
27
|
+
A workstream is one project: one tmux session, its agents, and its
|
|
28
|
+
task graph.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
mu workstream init auth
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
Created workstream auth (mux session mu-auth)
|
|
36
|
+
Next:
|
|
37
|
+
Attach the session : tmux attach -t mu-auth
|
|
38
|
+
...
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Every verb ends with a `Next:` block of follow-up commands. We use
|
|
42
|
+
them as we go.
|
|
43
|
+
|
|
44
|
+
## Plan two tasks
|
|
45
|
+
|
|
46
|
+
Now add two tasks. Each needs an impact (1–100) and an effort in
|
|
47
|
+
days. `--blocked-by` makes `build` wait for `design`:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
mu task add design -w auth -t "Design the auth module" -i 80 -e 2
|
|
51
|
+
mu task add build -w auth -t "Build the auth module" -i 80 -e 5 --blocked-by design
|
|
52
|
+
mu task next -w auth
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
┌────────┬────────┬────────────────────────┬────────┬────────┬──────┬───────┐
|
|
57
|
+
│ name │ status │ title │ impact │ effort │ ROI │ owner │
|
|
58
|
+
├────────┼────────┼────────────────────────┼────────┼────────┼──────┼───────┤
|
|
59
|
+
│ design │ OPEN │ Design the auth module │ 80 │ 2 │ 40.0 │ — │
|
|
60
|
+
└────────┴────────┴────────────────────────┴────────┴────────┴──────┴───────┘
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Only `design` is ready. `build` appears when `design` closes.
|
|
64
|
+
|
|
65
|
+
## Spawn a worker
|
|
66
|
+
|
|
67
|
+
Spawn a pi agent with its own git worktree:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
mu agent spawn worker-1 -w auth --workspace
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
Spawned worker-1 (pi) in window worker-1 of mu-auth, pane %15 with auto-workspace
|
|
75
|
+
workspace: ~/.local/state/mu/workspaces/auth/worker-1 (git)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The worker runs in a new window of the `mu-auth` session. To watch
|
|
79
|
+
it, run `tmux attach -t mu-auth`. Detach with `Ctrl+b d`.
|
|
80
|
+
|
|
81
|
+
## Claim the task for the worker
|
|
82
|
+
|
|
83
|
+
Assign the task before you send any text. The claim is what
|
|
84
|
+
`mu task wait` watches.
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
mu task note design -w auth 'SCOPE: write docs/auth.md with the token design'
|
|
88
|
+
mu task claim design -w auth --for worker-1
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
Claimed design for worker-1 (OPEN → IN_PROGRESS)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Send the task
|
|
96
|
+
|
|
97
|
+
`--fresh` starts a new pi session and sends the prompt into it in
|
|
98
|
+
one step:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
mu agent send worker-1 -w auth --fresh 'Work on task design. Read: mu task notes design -w auth.
|
|
102
|
+
When done: git commit -am "Design auth", then mu task close design -w auth --evidence "<what you verified>"'
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The worker reads its notes, does the work, commits in its worktree,
|
|
106
|
+
and closes the task.
|
|
107
|
+
|
|
108
|
+
## Wait for the task to close
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
mu task wait design -w auth --first --on-stall exit
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
auth/design
|
|
116
|
+
any-of 1 reached CLOSED in 41094ms
|
|
117
|
+
Next:
|
|
118
|
+
Cherry-pick worker-1's commit onto your branch : git cherry-pick 26278f1...
|
|
119
|
+
Refresh worker-1's workspace onto current main : mu workspace refresh worker-1 -w auth
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The exit code tells you what happened:
|
|
123
|
+
|
|
124
|
+
| Exit | Meaning | Next move |
|
|
125
|
+
| ---- | ------- | --------- |
|
|
126
|
+
| `0` | the task closed | merge the work |
|
|
127
|
+
| `5` | `--timeout` expired (default 600 s) | wait again |
|
|
128
|
+
| `6` | the worker's pane died and the task went back to `OPEN` | spawn and claim again |
|
|
129
|
+
| `7` | the worker sat in `needs_input` for 5 minutes | `mu agent read worker-1 -w auth`, then answer it |
|
|
130
|
+
|
|
131
|
+
Without `--on-stall exit`, a stalled worker only prints a warning and
|
|
132
|
+
the wait keeps running.
|
|
133
|
+
|
|
134
|
+
## Merge the commit
|
|
135
|
+
|
|
136
|
+
Run the cherry-pick command from the `Next:` block, then run your
|
|
137
|
+
tests on the result:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
git cherry-pick 26278f1
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Before the next task, rebase the worker's worktree onto the new main.
|
|
144
|
+
The worker keeps its pi context:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
mu workspace refresh worker-1 -w auth
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The default target is the remote's main branch (`origin/HEAD`). In a
|
|
151
|
+
repository without a remote, name the branch: `--from main`.
|
|
152
|
+
|
|
153
|
+
## Check the graph
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
mu task next -w auth
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
`build` is ready now. You can claim it for `worker-1` and repeat the
|
|
160
|
+
claim, send, wait, and merge steps.
|
|
161
|
+
|
|
162
|
+
## Close the worker
|
|
163
|
+
|
|
164
|
+
When you are done, free the worktree and close the agent:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
mu workspace free worker-1 -w auth
|
|
168
|
+
mu agent close worker-1 -w auth
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
`mu agent close` refuses while the worktree has commits or edits that
|
|
172
|
+
mu has not freed. That protects work you have not merged.
|
|
173
|
+
|
|
174
|
+
## Next steps
|
|
175
|
+
|
|
176
|
+
- [Dispatch work to a worker](dispatch.md) covers more than one
|
|
177
|
+
worker and the `--fresh`, `--steer`, and plain send choices.
|
|
178
|
+
- [Use the TUI dashboard](tui.md): run bare `mu` to see every
|
|
179
|
+
workstream at once.
|
|
180
|
+
- [Clean up](cleanup.md) when the workstream is finished.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# How to recover from a broken state
|
|
2
|
+
|
|
3
|
+
Start with `mu doctor`. Each row that is not `ok` prints the command
|
|
4
|
+
that fixes it. mu reports and never cleans up for you, because an
|
|
5
|
+
orphan directory can hold the only copy of uncommitted work. Agents
|
|
6
|
+
read the same rules in
|
|
7
|
+
[recipes/recovery.md](../../skills/mu/recipes/recovery.md).
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
mu doctor # exit 0 healthy, 5 on drift
|
|
11
|
+
mu doctor --deep # rebuild the ops log and diff every field
|
|
12
|
+
mu doctor --disk # add per-workspace byte usage
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## An agent's pane died
|
|
16
|
+
|
|
17
|
+
Run `mu agent list` or `mu state`. Each run reconciles the registry
|
|
18
|
+
with the multiplexer:
|
|
19
|
+
|
|
20
|
+
- An agent row whose pane is gone is a ghost. mu deletes the row, and
|
|
21
|
+
its `IN_PROGRESS` task returns to `OPEN`. A `mu task wait` on that
|
|
22
|
+
task exits 6.
|
|
23
|
+
- A pane in the session that runs an agent CLI but has no row is an
|
|
24
|
+
orphan. mu lists it with an adopt hint and does not adopt it.
|
|
25
|
+
|
|
26
|
+
To register an orphan pane, or a pi you started by hand:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
mu agent adopt %15 -w auth
|
|
30
|
+
mu agent adopt %15 -w auth --name investigator
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The pane title becomes the agent name. The pane must be in the
|
|
34
|
+
`mu-<workstream>` session. An adopted pi has no control socket until
|
|
35
|
+
you restart it with the `MU_CTL_SOCK` path that `adopt` prints.
|
|
36
|
+
|
|
37
|
+
## A pi agent shows `ctl missing` or `ctl refused`
|
|
38
|
+
|
|
39
|
+
mu reaches pi agents only through the control socket, and never falls
|
|
40
|
+
back to pasting.
|
|
41
|
+
|
|
42
|
+
| State | Means | Fix |
|
|
43
|
+
| ----- | ----- | --- |
|
|
44
|
+
| `ctl missing` | no socket: the extension is not loaded | run `mu link pi`, then respawn the agent |
|
|
45
|
+
| `ctl refused` | the socket exists but does not answer | respawn the agent; for a remote agent, check the ssh forward |
|
|
46
|
+
| `extension X older than installed Y` | pi loaded an older mu build | type `/reload` in the pane, or respawn |
|
|
47
|
+
|
|
48
|
+
To send `/reload` without attaching:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
mu agent send worker-1 -w auth '/reload' --via mux
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`/reload` keeps the pi session. A `send --fresh` or `abort` against an
|
|
55
|
+
outdated extension fails with exit 4 and prints the same two fixes.
|
|
56
|
+
|
|
57
|
+
## A new pi agent is stuck at `needs_input`
|
|
58
|
+
|
|
59
|
+
pi asks whether to trust a project folder on first start. Run
|
|
60
|
+
`/trust` in the pane once, or spawn with
|
|
61
|
+
`--command 'pi --approve'`. `--approve` trusts every directory,
|
|
62
|
+
including workspace forks, so use it only on your own code.
|
|
63
|
+
|
|
64
|
+
## You closed your terminal
|
|
65
|
+
|
|
66
|
+
The tmux session keeps running. Reattach with `tmux attach -t mu-auth`.
|
|
67
|
+
Every `mu` command is a short process that reads the DB, so nothing
|
|
68
|
+
needs restarting.
|
|
69
|
+
|
|
70
|
+
## You ran the wrong command
|
|
71
|
+
|
|
72
|
+
Every action is one group of ops. Find it, preview the inverse, then
|
|
73
|
+
apply:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
mu undo # list recent groups
|
|
77
|
+
mu undo 6380dd3d # preview
|
|
78
|
+
mu undo 6380dd3d --yes # apply
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
- Any unique prefix of a group id works.
|
|
82
|
+
- The undo is its own group, so undoing it again is redo.
|
|
83
|
+
- If later work changed the same fields, undo exits 4 and names the
|
|
84
|
+
conflict. `--force --yes` overrides and discards the newer work.
|
|
85
|
+
- Undo restores rows only. Killed panes and freed workspace
|
|
86
|
+
directories do not come back.
|
|
87
|
+
|
|
88
|
+
## `mu doctor` reports drift
|
|
89
|
+
|
|
90
|
+
Drift means the ops log and the live tables disagree. `--deep` names
|
|
91
|
+
the table, key, and field. Do not rebuild by reflex: if capture missed
|
|
92
|
+
a write, the live table holds real work that a rebuild would discard.
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
mu db backup /tmp/mu-drift-evidence.db # 1. keep the evidence
|
|
96
|
+
mu rebuild /tmp/mu-rebuilt.db # 2. replay the log into a new file
|
|
97
|
+
MU_DB_PATH=/tmp/mu-rebuilt.db mu sql "SELECT local_id, title FROM tasks" # 3. compare
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Decide which side is right, then report the drift as a bug with the
|
|
101
|
+
named field. `mu rebuild` never writes in place. It prints the swap
|
|
102
|
+
command.
|
|
103
|
+
|
|
104
|
+
## The `disk` section of `mu doctor` warns
|
|
105
|
+
|
|
106
|
+
| Row | Means |
|
|
107
|
+
| --- | ----- |
|
|
108
|
+
| `ws-rows` | a workspace row whose directory is gone; the next send fails in the VCS |
|
|
109
|
+
| `ws-dirs` | a workspace directory with no row; it blocks the next `--workspace` spawn with that name |
|
|
110
|
+
| `ws-empty` | a workstream directory with no checkouts |
|
|
111
|
+
| `db-copies` | stray `mu.db*` files that nothing reads |
|
|
112
|
+
| `exports` | output left by the removed export verb |
|
|
113
|
+
| `locks` | lock directories older than one hour, from a spawn or flush that died |
|
|
114
|
+
|
|
115
|
+
To list workspace orphans with cleanup commands, run
|
|
116
|
+
`mu workspace orphans -w auth`. Remove a git-backed orphan with
|
|
117
|
+
`git worktree remove --force <path>` from the project root.
|
|
118
|
+
|
|
119
|
+
## Rename a workstream
|
|
120
|
+
|
|
121
|
+
There is no rename verb. Every child table cascades on the name:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
mu sql "UPDATE workstreams SET name='auth-refactor' WHERE name='auth-refator'"
|
|
125
|
+
tmux rename-session -t mu-auth-refator mu-auth-refactor
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Names start with a lowercase letter, use letters, digits, `_`, or
|
|
129
|
+
`-`, are at most 32 characters, and do not start with `mu-`.
|
|
130
|
+
|
|
131
|
+
## Report a bug
|
|
132
|
+
|
|
133
|
+
Include the exact command, its full output, the `environment` block of
|
|
134
|
+
`mu doctor`, and your platform. To reproduce without your real data,
|
|
135
|
+
set `MU_DB_PATH=/tmp/mu-debug.db` and `MU_SYNC_DIR=` (empty).
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# How to run a worker on another machine
|
|
2
|
+
|
|
3
|
+
The pane is local and the pi process is remote. mu runs no ssh
|
|
4
|
+
itself. `mu agent remote-env` prints the ssh pieces, and you put them
|
|
5
|
+
in the spawn command. The full recipe, with recording, collecting,
|
|
6
|
+
and the traps, is in
|
|
7
|
+
[skills/mu/recipes/remote-workers.md](../../skills/mu/recipes/remote-workers.md).
|
|
8
|
+
Read it before your first remote spawn.
|
|
9
|
+
|
|
10
|
+
## Prepare the host
|
|
11
|
+
|
|
12
|
+
On the remote host:
|
|
13
|
+
|
|
14
|
+
1. Install mu and run `mu link pi`, so the remote pi loads the mu
|
|
15
|
+
extension.
|
|
16
|
+
2. Allow unix-socket forwards in the host's sshd:
|
|
17
|
+
`AllowStreamLocalForwarding yes`.
|
|
18
|
+
3. Create the worker's checkout yourself. `--workspace` works only
|
|
19
|
+
for local agents:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
ssh dev 'git -C ~/repo worktree add ~/ws/worker-1'
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Use one orchestrator DB on your machine. Do not run a second mu on the
|
|
26
|
+
host for the same work: task ownership points into your local
|
|
27
|
+
`agents` table.
|
|
28
|
+
|
|
29
|
+
## Spawn the agent
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
eval "$(mu agent remote-env worker-1 -w auth --shell)" # sets MU_SSH_ARGS, MU_REMOTE_ENV
|
|
33
|
+
mu agent spawn worker-1 -w auth --command \
|
|
34
|
+
"ssh $MU_SSH_ARGS dev -t 'cd ~/ws/worker-1 && $MU_REMOTE_ENV \$SHELL -ilc \"pi --approve\"'"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
What each part does:
|
|
38
|
+
|
|
39
|
+
- `MU_SSH_ARGS` forwards the remote pi's control socket to the local
|
|
40
|
+
path mu connects to. It includes `-o ControlMaster=no -o
|
|
41
|
+
ControlPath=none`, because a multiplexed ssh connection never binds
|
|
42
|
+
the local end of the forward.
|
|
43
|
+
- `MU_REMOTE_ENV` sets the agent's identity inside the remote shell.
|
|
44
|
+
tmux `-e` variables do not cross the ssh hop.
|
|
45
|
+
- `$SHELL -ilc` starts pi in an interactive login shell, so the
|
|
46
|
+
remote `~/.zshrc` or `~/.bashrc` loads PATH and provider keys.
|
|
47
|
+
Without it, ssh's non-interactive shell skips them and pi can die at
|
|
48
|
+
startup.
|
|
49
|
+
- `pi --approve` skips pi's project-trust prompt. It trusts whatever
|
|
50
|
+
directory the pane starts in, so use it only on your own code.
|
|
51
|
+
|
|
52
|
+
If the spawn reports `ctl refused`, check `AllowStreamLocalForwarding`
|
|
53
|
+
on the host.
|
|
54
|
+
|
|
55
|
+
## Drive it like a local agent
|
|
56
|
+
|
|
57
|
+
Claim, `mu agent send --fresh`, `mu agent wait`, and `mu agent abort`
|
|
58
|
+
all go through the forwarded socket and behave as they do locally:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
mu task note build -w auth 'REMOTE: dev:~/ws/worker-1'
|
|
62
|
+
mu task claim build -w auth --for worker-1
|
|
63
|
+
mu agent send worker-1 -w auth --fresh 'Work on build. Read: mu task notes build -w auth'
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The `REMOTE: <host>:<path>` note line is how `mu state` lists remote
|
|
67
|
+
workers. Collect the work by fetching from the remote checkout:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
git fetch "ssh://dev/~/ws/worker-1" HEAD && git cherry-pick FETCH_HEAD
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`mu agent kick` does not reach a remote process. Use `mu agent abort`,
|
|
74
|
+
or close the pane.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# How to query and script mu
|
|
2
|
+
|
|
3
|
+
Use typed verbs with `--json` first. Use `mu sql` for ad-hoc joins,
|
|
4
|
+
reports, and repairs that no verb covers.
|
|
5
|
+
|
|
6
|
+
## Script with `--json`
|
|
7
|
+
|
|
8
|
+
Every verb takes `--json`.
|
|
9
|
+
|
|
10
|
+
- Collection reads print `{"items": [...], "count": N}`.
|
|
11
|
+
- Single objects, such as `mu task show`, print an object with named
|
|
12
|
+
fields.
|
|
13
|
+
- `mu sql --json` prints a bare array of rows.
|
|
14
|
+
- `mu log --tail --json` prints one JSON object per line.
|
|
15
|
+
- Errors go to stderr as `{error, message, nextSteps, exitCode}`.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
mu state -w auth --json
|
|
19
|
+
mu task list -w auth --json | jq '.count'
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Exit codes: `2` usage error, `3` not found, `4` conflict, `5`
|
|
23
|
+
timeout or a multiplexer, VCS, or drift failure, `6` reaped pane,
|
|
24
|
+
`7` stall.
|
|
25
|
+
|
|
26
|
+
## Read the schema
|
|
27
|
+
|
|
28
|
+
The schema has 11 tables and 3 views (`ready`, `blocked`, `goals`).
|
|
29
|
+
Four tables travel between machines: `workstreams`, `tasks`,
|
|
30
|
+
`task_edges`, and `task_notes`. List them all:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
mu sql "SELECT type, name FROM sqlite_master WHERE type IN ('table','view') ORDER BY type, name"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Task ids (`local_id`) are unique per workstream only. Join
|
|
37
|
+
`workstreams` in every query, or you hit a same-named task elsewhere.
|
|
38
|
+
Edges and notes reference `tasks.id`, not `local_id`.
|
|
39
|
+
|
|
40
|
+
## Run common queries
|
|
41
|
+
|
|
42
|
+
Blocked tasks and the goals view, which replaced removed verbs:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
mu sql "SELECT b.local_id, b.title FROM blocked b JOIN workstreams w ON w.id = b.workstream_id WHERE w.name = 'auth'"
|
|
46
|
+
mu sql "SELECT g.local_id, g.title FROM goals g JOIN workstreams w ON w.id = g.workstream_id WHERE w.name = 'auth'"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Search task titles:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
mu sql "SELECT t.local_id, t.status, t.title FROM tasks t JOIN workstreams w ON w.id = t.workstream_id
|
|
53
|
+
WHERE w.name = 'auth' AND LOWER(t.title) LIKE '%token%'"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Every task that blocks `launch`, directly or not:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
mu sql "WITH RECURSIVE prereqs(id) AS (
|
|
60
|
+
SELECT t.id FROM tasks t JOIN workstreams w ON w.id = t.workstream_id
|
|
61
|
+
WHERE t.local_id = 'launch' AND w.name = 'auth'
|
|
62
|
+
UNION
|
|
63
|
+
SELECT e.from_task_id FROM task_edges e JOIN prereqs ON e.to_task_id = prereqs.id
|
|
64
|
+
)
|
|
65
|
+
SELECT t.local_id, t.title, t.status FROM prereqs JOIN tasks t ON t.id = prereqs.id"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`mu sql` runs writes too and prints the number of rows changed. Writes
|
|
69
|
+
are captured as ops, so `mu undo` can revert them.
|
|
70
|
+
|
|
71
|
+
## Pass list flags
|
|
72
|
+
|
|
73
|
+
A flag with `<value...>` in its help takes repeats, commas, or both:
|
|
74
|
+
`--blocked-by a,b` equals `--blocked-by a --blocked-by b`. An empty
|
|
75
|
+
fragment from a stray comma is dropped. A blank fragment such as
|
|
76
|
+
`" "` is a usage error.
|