@mu-crew/mu 3.2.1 → 3.4.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 +83 -22
- package/dist/cli.js +294 -98
- package/dist/cli.js.map +1 -1
- package/dist/extension/mu-pi.js +346 -85
- package/dist/extension/mu-pi.js.map +1 -1
- package/dist/index.d.ts +68 -13
- package/dist/index.js +159 -71
- package/dist/index.js.map +1 -1
- package/docs/ARCHITECTURE.md +1 -0
- package/docs/VISION.md +3 -1
- package/docs/VOCABULARY.md +6 -1
- package/docs/architecture/control-socket.md +17 -3
- package/docs/architecture/dag.md +3 -3
- package/docs/architecture/mux.md +3 -4
- package/docs/guide/README.md +5 -0
- package/docs/guide/delegate.md +30 -3
- 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 +2 -1
- package/docs/reference/naming.md +18 -0
- 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-debug.md +8 -0
- 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-sweep.md +8 -0
- package/prompts/mu-tournament.md +9 -0
- package/prompts/mu-until.md +8 -0
- package/prompts/ultrathink.md +10 -0
- package/skills/mu/SKILL.md +124 -145
- package/skills/mu/recipes/adversarial-review.md +91 -0
- package/skills/mu/recipes/backlog-triage.md +43 -0
- package/skills/mu/recipes/brief.md +53 -0
- package/skills/mu/recipes/codemode-driver.md +102 -0
- package/skills/mu/recipes/deep-research.md +67 -0
- package/skills/mu/recipes/fan-out.md +40 -0
- package/skills/mu/recipes/findings.md +103 -0
- package/skills/mu/recipes/hypothesis-panel.md +45 -0
- package/skills/mu/recipes/long-run.md +20 -0
- package/skills/mu/recipes/loop-until-done.md +42 -0
- package/skills/mu/recipes/orchestrator-loop.md +98 -0
- package/skills/mu/recipes/plan.md +59 -0
- package/skills/mu/recipes/recovery.md +28 -0
- package/skills/mu/recipes/refute.md +51 -0
- package/skills/mu/{REMOTE_WORKERS.md → recipes/remote-workers.md} +7 -2
- package/skills/mu/recipes/review-panel.md +62 -0
- package/skills/mu/recipes/rules-audit.md +83 -0
- package/skills/mu/recipes/tasks-or-calls.md +67 -0
- package/skills/mu/recipes/tournament.md +40 -0
- package/skills/mu/recipes/ultrathink.md +82 -0
- package/skills/mu/recipes/watcher.md +19 -0
- package/skills/mu/recipes/waves.md +20 -0
- package/skills/mu/recipes/worker.md +26 -0
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -139,6 +139,7 @@ hub that re-exports them. `src/tasks.ts`, `src/agents.ts`, `src/mux.ts`,
|
|
|
139
139
|
| `src/ctl/client.ts` | `ctlRequest`, `ctlProbe`, version and unknown-op errors |
|
|
140
140
|
| `extension/mu-pi.ts` | pi extension, child side: serves `$MU_CTL_SOCK`; built to `dist/extension/mu-pi.js` |
|
|
141
141
|
| `extension/delegate.ts` | pi extension, parent side: `mu_delegate` / `mu_delegate_cancel`, which shell out to `mu` |
|
|
142
|
+
| `extension/nudge.ts` | pi extension: the keep-driving nudge. Arms on a `mu` dispatch, checks `mu state --json` at `agent_before_settle`, injects the SKILL.md rule once per prompt, logs `--kind nudge` |
|
|
142
143
|
| `src/link.ts` | `mu link pi`: extension shim, skill symlink, `inspectLinks` for doctor |
|
|
143
144
|
|
|
144
145
|
### Tasks, workspaces and workstreams
|
package/docs/VISION.md
CHANGED
|
@@ -224,7 +224,9 @@ mu agent spawn reviewer-1 --cli pi_big
|
|
|
224
224
|
visible pane: attach, steer, abort, or keep talking to it. It costs one
|
|
225
225
|
pane and one pi process. A hidden subagent is lighter for many tiny
|
|
226
226
|
calls. mu bets that visibility and steering are worth the cost. There
|
|
227
|
-
are no agent types: the brief is plain text.
|
|
227
|
+
are no agent types: the brief is plain text. A delegate's answer is
|
|
228
|
+
not recorded in mu; only what the caller writes back (a note, a state
|
|
229
|
+
change) is.
|
|
228
230
|
- **DB-undoable, not substrate-undoable.** `mu undo <group> --yes`
|
|
229
231
|
restores rows. It does not revive killed panes or freed workspace
|
|
230
232
|
directories. Reconciliation then reports ghosts and orphans.
|
package/docs/VOCABULARY.md
CHANGED
|
@@ -40,11 +40,14 @@ agent names, and file paths are in [reference/naming.md](reference/naming.md).
|
|
|
40
40
|
| **role** | The capability flag: `full-access` or `read-only`. | "permission", "tier" |
|
|
41
41
|
| **persistent** | An agent that stays alive across tasks. | "long-lived" (prose only) |
|
|
42
42
|
| **one-shot** | An agent that exists for one task. | "ephemeral", "transient" |
|
|
43
|
+
| **nudge** | The pi extension's one-shot keep-driving reminder: after a dispatch, if the orchestrator ends its turn with work IN_PROGRESS, it injects the SKILL.md rule once and continues. Logged as `--kind nudge`. | "goal", "loop" |
|
|
43
44
|
| **delegate** | A scratch agent started for one task; its answer returns when its control-socket `wait` resolves. The `mu_delegate` tool does it in one call; the pane stays attachable. | "subagent", "child agent" |
|
|
45
|
+
| **delegate call** | Using a delegate for one check (a refuter, judge, claim checker): one `mu_delegate` call, or `mu agent spawn -w scratch` + `send --fresh` + `wait --json` without the tool. Its verdict is recorded on the task it judged; the call itself adds no task. | "subtask" |
|
|
44
46
|
| **hidden subagent** | A child agent in other tools (pi-subagents, Claude Code and Codex task tools) with no pane to attach or steer. mu's counterpart is the **delegate**. | "subagent" (alone) |
|
|
45
47
|
| **agent state** | `busy`, `needs_input`, `needs_permission`, or `unknown`, from the **state source**. Not persisted; see [Agent state values](#agent-state-values). | "agent status", "lifecycle state" |
|
|
46
48
|
| **state source** | The **control socket** for pi agents; else herdr's `paneStatus()` or, on tmux, murmur. A silent pi socket gives `unknown` (`ctl missing`, `ctl refused`). | "scraper" |
|
|
47
49
|
| **control socket** / **ctl** | The per-agent unix socket (`$MU_CTL_SOCK`) the mu pi extension serves inside pi. **ctl state** is `ok`, `missing`, or `refused`. | "rpc", "daemon" |
|
|
50
|
+
| **session command** | `/new`, `/reload`, or `/compact [instructions]` sent to a pi agent. mu runs it inside pi through the ctl `command` op, never as a paste. Any other slash command to a pi agent is refused; `--via mux` types it into the pane. | "slash paste" |
|
|
48
51
|
| **outdated extension** | A running pi whose loaded extension is older than mu (exit 4 on a missing op). pi's `/reload` fixes it. | |
|
|
49
52
|
| **lastText** | A pi run's final assistant message, returned verbatim by `wait`. mu never interprets it. | "result", "output" (alone) |
|
|
50
53
|
| **ghost** | An `agents` row whose `pane_id` no longer exists. Pruned by **reconcile**. | "dead agent", "stale row" |
|
|
@@ -61,8 +64,10 @@ agent names, and file paths are in [reference/naming.md](reference/naming.md).
|
|
|
61
64
|
| --- | --- | --- |
|
|
62
65
|
| **task** | A node in the DAG with mandatory `impact` and `effort_days`, a **task status**, and a **substate**. | "issue", "ticket", "item" |
|
|
63
66
|
| **task status** | `OPEN`, `IN_PROGRESS`, or `CLOSED`. Any `CLOSED/*` satisfies a blocker. | "state" |
|
|
64
|
-
| **substate** | What the status means, shown as `STATUS/substate`; never null. `OPEN`: `todo`, `parked`. `IN_PROGRESS`: `active`. `CLOSED`: `done`, `rejected`, `wontfix`, `duplicate`, `superseded`. | "resolution", "reason" |
|
|
67
|
+
| **substate** | What the status means, shown as `STATUS/substate`; never null. `OPEN`: `todo`, `parked`, `triage`. `IN_PROGRESS`: `active`. `CLOSED`: `done`, `rejected`, `wontfix`, `duplicate`, `superseded`. | "resolution", "reason" |
|
|
65
68
|
| **park** / **unpark** | `OPEN/todo` ↔ `OPEN/parked` (park needs `--why`). Parked tasks leave **ready**. | "defer", "snooze" |
|
|
69
|
+
| **triage** / **accept** | `OPEN/triage` is a proposed task, usually a review **finding**, not yet accepted as work: out of **ready**, refused by `claim`, but it blocks its dependents. `mu task add --triage` creates one; `mu task accept` moves it to `OPEN/todo`; declining is `close --as rejected` or `--as duplicate`. | "inbox", "pending" |
|
|
70
|
+
| **finding** | One problem a reviewer, checker, or auditor reports. Recorded as an `OPEN/triage` task (the mu way), or as an answer line when a **delegate** reviews something nobody will track. | "issue", "comment" |
|
|
66
71
|
| **task DAG** / **graph** | The directed acyclic graph of tasks. | "task list", "tree" |
|
|
67
72
|
| **edge** | The single edge type: `A blocks B` means A must close before B starts. | "dependency" (prose only) |
|
|
68
73
|
| **subtree** / **scope** | Tasks reachable from a root via blocks-edges. | "subgraph" |
|
|
@@ -33,15 +33,23 @@ reply carries `v: 1`; the client (`src/ctl/client.ts`) throws
|
|
|
33
33
|
| `wait` | resolves on pi's `agent_settled` after `afterRuns`, with the run's `lastText` |
|
|
34
34
|
| `abort` | `ctx.abort()` (pi's Esc) |
|
|
35
35
|
| `fresh` | new session plus prompt as one operation, through the internal `/mu-fresh` command; replies once the new run starts; refused with `busy` unless `force` |
|
|
36
|
+
| `command` | `name` `new`, `reload` or `compact` (with optional `instructions`), through the internal `/mu-new`, `/mu-reload`, `/mu-compact` commands, which call `ctx.newSession()`, `ctx.reload()`, `ctx.compact()`. `new` replies once the session is replaced, `reload` after the `session_start` it causes, `compact` when compaction starts or with pi's error (`Nothing to compact ...`). Refused with `busy` unless `force` |
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
`pi.sendUserMessage` dispatches only extension commands, not pi's
|
|
39
|
+
built-in `/new`, `/reload`, `/compact`. Each internal command is an
|
|
40
|
+
extension command, triggered with `expandPromptTemplates: true`, and
|
|
41
|
+
its handler gets the command context that can replace or reload the
|
|
42
|
+
session.
|
|
43
|
+
|
|
44
|
+
These back `mu agent send` (`--fresh`, `--steer`, session commands), `mu agent wait`,
|
|
38
45
|
`mu agent abort`, the agent state reading, and `mu_delegate`.
|
|
39
46
|
|
|
40
47
|
## Version skew
|
|
41
48
|
|
|
42
49
|
An op the extension does not serve returns `unknown op: <op>` with its
|
|
43
50
|
`ops` list. mu raises `AgentExtensionOutdatedError` (exit 4), whose
|
|
44
|
-
next steps are `/reload` through the mux
|
|
51
|
+
next steps are `/reload` through the mux (an extension that lacks the
|
|
52
|
+
`command` op cannot run it over ctl) or a respawn. `mu doctor`
|
|
45
53
|
probes every pi agent's socket (the `ctl` row) and flags an
|
|
46
54
|
`extVersion` older than the installed mu or a missing op. Its extension
|
|
47
55
|
row reports whether `mu link pi` installed the extension.
|
|
@@ -90,9 +98,15 @@ The mux paste path (bracketed paste, `MU_SEND_DELAY_MS`,
|
|
|
90
98
|
|
|
91
99
|
- non-pi CLIs;
|
|
92
100
|
- adopted panes without ctl;
|
|
93
|
-
- slash commands, because `sendUserMessage` does not run them;
|
|
94
101
|
- an explicit `--via mux`.
|
|
95
102
|
|
|
103
|
+
A pi agent's `/new`, `/reload` and `/compact [instructions]` go
|
|
104
|
+
through the `command` op. Any other slash command to a pi agent raises
|
|
105
|
+
`AgentSlashCommandUnsupportedError` (exit 2), whose next step is the
|
|
106
|
+
same text with `--via mux`. Text such as `/tmp/x.log ...` is a plain
|
|
107
|
+
prompt, not a slash command. A pi agent therefore never reaches
|
|
108
|
+
`capturePane` or the paste timing in `src/mux/input-timing.ts`.
|
|
109
|
+
|
|
96
110
|
## Remote agents
|
|
97
111
|
|
|
98
112
|
The user's `ssh` command carries `-L <local derived path>:<remote path>`
|
package/docs/architecture/dag.md
CHANGED
|
@@ -14,11 +14,11 @@ it mu is only an agent runner. Overview:
|
|
|
14
14
|
- **Status lifecycle:** `OPEN → IN_PROGRESS → CLOSED`. Status alone
|
|
15
15
|
decides edge satisfaction: any `CLOSED` task satisfies its blockers.
|
|
16
16
|
- **Substate** qualifies status and never touches edges:
|
|
17
|
-
`OPEN/todo|parked`, `IN_PROGRESS/active`,
|
|
17
|
+
`OPEN/todo|parked|triage`, `IN_PROGRESS/active`,
|
|
18
18
|
`CLOSED/done|rejected|wontfix|duplicate|superseded`. The rule is
|
|
19
19
|
"store intent, derive graph facts": ready and blocked stay derived
|
|
20
|
-
from edges. `OPEN/parked`
|
|
21
|
-
`goals`.
|
|
20
|
+
from edges. `OPEN/parked` and `OPEN/triage` are excluded from `ready`
|
|
21
|
+
but stay in `goals`; `claim` refuses both without `--force`.
|
|
22
22
|
- **Notes** are append-only per task. They survive LLM context loss
|
|
23
23
|
and agent restarts, which fixes context loss at the task level
|
|
24
24
|
rather than the agent level.
|
package/docs/architecture/mux.md
CHANGED
|
@@ -97,15 +97,14 @@ as a capability, not a name check:
|
|
|
97
97
|
| --- | --- | --- |
|
|
98
98
|
| `NewWindowOptions.command` | carries the command | refused if non-empty |
|
|
99
99
|
| `startAgentInPane()` | absent | implemented |
|
|
100
|
-
| after start | mu checks pane life and startup errors
|
|
100
|
+
| after start | mu checks pane life and startup errors | the mux returns once the agent is ready |
|
|
101
101
|
|
|
102
102
|
`spawnAgent` branches on `mux.startAgentInPane !== undefined`.
|
|
103
103
|
|
|
104
104
|
- **tmux.** After `MU_SPAWN_LIVENESS_MS` (default 1500, `0` skips) mu
|
|
105
105
|
verifies the pane survived and scans its tail for provider or auth
|
|
106
|
-
startup errors.
|
|
107
|
-
|
|
108
|
-
murmur that poll is skipped.
|
|
106
|
+
startup errors. mu does not wait for murmur to claim the pane: state
|
|
107
|
+
reads before the first claim report `unknown`.
|
|
109
108
|
- **herdr.** mu creates a bare pane and calls `startAgentInPane`, which
|
|
110
109
|
subsumes both checks.
|
|
111
110
|
- **pi, either backend.** After the agent starts, mu polls its control
|
package/docs/guide/README.md
CHANGED
|
@@ -21,5 +21,10 @@ How-to guides:
|
|
|
21
21
|
- [Choose a multiplexer backend](backends.md)
|
|
22
22
|
- [Clean up](cleanup.md)
|
|
23
23
|
|
|
24
|
+
Agent-facing recipes (orchestrator loop, worker loop, recovery, waves,
|
|
25
|
+
long runs, watchers, remote workers) live
|
|
26
|
+
in [skills/mu/recipes/](../../skills/mu/recipes/). The skill's
|
|
27
|
+
[recipe index](../../skills/mu/SKILL.md#recipes) says when to read each.
|
|
28
|
+
|
|
24
29
|
For features mu does not have on purpose, see
|
|
25
30
|
[ROADMAP.md § Explicitly rejected](../ROADMAP.md#explicitly-rejected).
|
package/docs/guide/delegate.md
CHANGED
|
@@ -29,7 +29,9 @@ Delegates called in one turn run in parallel.
|
|
|
29
29
|
- The pane closes after a clean finish; died or timed-out panes stay
|
|
30
30
|
as evidence.
|
|
31
31
|
- pi's footer shows how many delegates this session is waiting on.
|
|
32
|
-
- Each delegate costs a pane and a pi process.
|
|
32
|
+
- Each delegate costs a pane and a pi process. A session runs at most
|
|
33
|
+
`MU_DELEGATE_MAX` at once (default 16); past that, the tool refuses
|
|
34
|
+
and the rest wait for answers.
|
|
33
35
|
|
|
34
36
|
`MU_DELEGATE=0` hides the tool ([env vars](../reference/env.md)).
|
|
35
37
|
|
|
@@ -79,9 +81,34 @@ mu log -w scratch --kind pr-state -n 1 --json
|
|
|
79
81
|
Act only on change. `--since <seq>` replays entries a dead watcher
|
|
80
82
|
missed.
|
|
81
83
|
|
|
84
|
+
## Delegates vs hidden subagents
|
|
85
|
+
|
|
86
|
+
Claude Code, Codex, and pi-subagents delegate to a hidden child process
|
|
87
|
+
and return only its result. A mu delegate is an ordinary agent in a
|
|
88
|
+
pane.
|
|
89
|
+
|
|
90
|
+
| | Hidden subagent | mu delegate |
|
|
91
|
+
| ----------------------- | ------------------------ | ----------- |
|
|
92
|
+
| Visibility | none while it runs | a pane; attach and watch |
|
|
93
|
+
| Steer mid-run | no | `mu agent send`; stop with `mu agent abort` |
|
|
94
|
+
| Keep talking after it answers | no | yes, with `keep: true` |
|
|
95
|
+
| Transcript | collapses into a result | a normal pi session log |
|
|
96
|
+
| If the work grows | re-brief a new agent | same task DAG and workspaces |
|
|
97
|
+
| Cost | light | one pane and one pi process |
|
|
98
|
+
|
|
99
|
+
For many tiny calls, a hidden subagent is lighter. mu bets that seeing
|
|
100
|
+
and steering agent work is worth a pane.
|
|
101
|
+
|
|
82
102
|
## When to stop delegating
|
|
83
103
|
|
|
84
|
-
|
|
104
|
+
Use delegates when you only need the answer: reviewing someone's PR or
|
|
105
|
+
a doc, a fact-check, a go/no-go. Nothing they find lands in the ops
|
|
106
|
+
log, which is permanent and syncs to every machine.
|
|
107
|
+
|
|
108
|
+
Move to a workstream when the findings become work agents will fix, or
|
|
109
|
+
the job has dependencies or several stages: see
|
|
85
110
|
[Getting started](getting-started.md) and
|
|
86
111
|
[How to dispatch work](dispatch.md). There, `mu task wait` keys on the
|
|
87
|
-
task and has `--on-stall`.
|
|
112
|
+
task and has `--on-stall`. The agent-facing rules for both are in
|
|
113
|
+
[recipes/findings.md](../../skills/mu/recipes/findings.md) and
|
|
114
|
+
[recipes/tasks-or-calls.md](../../skills/mu/recipes/tasks-or-calls.md).
|
package/docs/guide/dispatch.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# How to dispatch work to a worker
|
|
2
2
|
|
|
3
3
|
This guide assumes you finished [Getting started](getting-started.md).
|
|
4
|
-
The
|
|
5
|
-
[
|
|
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).
|
|
6
8
|
|
|
7
9
|
## Claim before you send
|
|
8
10
|
|
|
@@ -40,6 +42,10 @@ socket. Pick the mode by what the agent is doing:
|
|
|
40
42
|
- Never send `/new` and then the prompt as two sends to pi. The prompt
|
|
41
43
|
can land during the reset and vanish.
|
|
42
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.
|
|
43
49
|
- If the socket does not answer, the send fails with exit 1 and
|
|
44
50
|
pastes nothing. `--via mux` pastes into the pane on purpose.
|
|
45
51
|
|
|
@@ -86,8 +92,9 @@ context:
|
|
|
86
92
|
mu workspace refresh worker-1 -w auth
|
|
87
93
|
```
|
|
88
94
|
|
|
89
|
-
It
|
|
90
|
-
|
|
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
|
|
91
98
|
`mu workspace free worker-1 -w auth`.
|
|
92
99
|
|
|
93
100
|
Claim and send warn when the worker's workspace is 10 or more commits
|
|
@@ -147,6 +147,9 @@ The worker keeps its pi context:
|
|
|
147
147
|
mu workspace refresh worker-1 -w auth
|
|
148
148
|
```
|
|
149
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
|
+
|
|
150
153
|
## Check the graph
|
|
151
154
|
|
|
152
155
|
```bash
|
package/docs/guide/recovery.md
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Start with `mu doctor`. Each row that is not `ok` prints the command
|
|
4
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.
|
|
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).
|
|
6
8
|
|
|
7
9
|
```bash
|
|
8
10
|
mu doctor # exit 0 healthy, 5 on drift
|
package/docs/guide/remote.md
CHANGED
|
@@ -4,7 +4,7 @@ The pane is local and the pi process is remote. mu runs no ssh
|
|
|
4
4
|
itself. `mu agent remote-env` prints the ssh pieces, and you put them
|
|
5
5
|
in the spawn command. The full recipe, with recording, collecting,
|
|
6
6
|
and the traps, is in
|
|
7
|
-
[skills/mu/
|
|
7
|
+
[skills/mu/recipes/remote-workers.md](../../skills/mu/recipes/remote-workers.md).
|
|
8
8
|
Read it before your first remote spawn.
|
|
9
9
|
|
|
10
10
|
## Prepare the host
|
|
@@ -587,7 +587,7 @@ mu doctor # agent state : ok agent state from murmur 1.x
|
|
|
587
587
|
|
|
588
588
|
### Documentation
|
|
589
589
|
|
|
590
|
-
- **[skills/mu/REMOTE_WORKERS.md](../../skills/mu/
|
|
590
|
+
- **[skills/mu/REMOTE_WORKERS.md](../../skills/mu/recipes/remote-workers.md) (now `recipes/remote-workers.md`)** — running
|
|
591
591
|
agents on another machine. This already worked with no mu changes (the
|
|
592
592
|
pane is local, the process is remote, so send/read/status/reaper are
|
|
593
593
|
unaffected), but nothing said so and the failure modes are not
|
package/docs/reference/env.md
CHANGED
|
@@ -30,7 +30,6 @@ milliseconds; `0` disables a wait unless noted.
|
|
|
30
30
|
| `MU_<CLI>_COMMAND` | Executable for `--cli <cli>`; hyphens become underscores (`--cli pi-meta` reads `MU_PI_META_COMMAND`). May hold arguments. `--command` wins; the spawn line names the env var when it supplied the command. | the cli value |
|
|
31
31
|
| `MU_SPAWN_CTL_MS` | Budget for the control-socket handshake with a new pi agent, polled every 250ms. On timeout spawn still exits 0, reports `ctl: missing` or `ctl: refused`, and warns. `--no-ctl` skips it per spawn. | `30000` |
|
|
32
32
|
| `MU_SPAWN_LIVENESS_MS` | tmux only. Wait this long, then check the pane is alive and its scrollback has no startup error (auth failure, `command not found`). Failure rolls back the row and throws `AgentDiedOnSpawnError` or `AgentSpawnStartupError`. | `1500` |
|
|
33
|
-
| `MU_SPAWN_READINESS_MS` | tmux only, when murmur is installed. Budget to wait for murmur to claim the new pane. | `10000` |
|
|
34
33
|
| `MU_SPAWN_LOCK_TIMEOUT_MS` | How long a spawn waits for the per-workstream spawn lock. | `15000` |
|
|
35
34
|
|
|
36
35
|
## Send and state (tmux path)
|
|
@@ -68,6 +67,8 @@ pi agent's `--command`. mu never reads them back.
|
|
|
68
67
|
| Name | Effect | Default |
|
|
69
68
|
| --- | --- | --- |
|
|
70
69
|
| `MU_DELEGATE` | `0` hides the `mu_delegate` tool. `mu doctor` reports it. | unset: shown |
|
|
70
|
+
| `MU_DELEGATE_MAX` | Most delegates one pi session runs at once; `mu_delegate` refuses past it. A positive integer. | `16` |
|
|
71
|
+
| `MU_NUDGE` | `0` turns off the keep-driving nudge: one reminder when an orchestrator ends a turn with dispatched work still IN_PROGRESS. `mu doctor` reports it. | unset: on |
|
|
71
72
|
| `MU_PI_HOME` | Root under which `mu link pi` writes `.pi/` and `.agents/`. | `$HOME` |
|
|
72
73
|
| `PI_CODING_AGENT_DIR` | Read only. pi's agent dir, checked for a linked murmur extension. | `~/.pi/agent` |
|
|
73
74
|
| `MU_EXTENSION_ENTRY` | Test only. Built extension the `mu link pi` shim imports. | `dist/extension/mu-pi.js` |
|
package/docs/reference/naming.md
CHANGED
|
@@ -45,6 +45,24 @@ clears all blockers.
|
|
|
45
45
|
`mu agent spawn <name> -w scratch`, and `mu workstream init scratch`
|
|
46
46
|
is rejected. The `mu-` prefix is reserved too.
|
|
47
47
|
|
|
48
|
+
## Workstream names
|
|
49
|
+
|
|
50
|
+
Name a workstream `<project>-<purpose>`: `hail-auth`, `swayward-v2`,
|
|
51
|
+
`dotfiles-zsh`. The project is the repo or folder; the purpose is the
|
|
52
|
+
effort. Two repos then never share `auth`, and `mu workstream list`
|
|
53
|
+
groups by project. `workstream init` prints a hint for a name with no
|
|
54
|
+
`-`.
|
|
55
|
+
|
|
56
|
+
- **One workstream per effort.** Tear it down when the effort ships;
|
|
57
|
+
the ops log keeps the history and `mu undo` restores it. A long-lived
|
|
58
|
+
catch-all becomes a log nobody reads: `mu state` hints once a
|
|
59
|
+
workstream passes 300 tasks with fewer than 10% open.
|
|
60
|
+
- **Ultrathink runs** get their own: `<project>-ut-<topic>`.
|
|
61
|
+
- **Delegate-only work** (reviewing someone's PR or a doc) goes in
|
|
62
|
+
`scratch`, never a new workstream.
|
|
63
|
+
- `mu-` is reserved, so the mu repo's own workstreams use the purpose
|
|
64
|
+
alone or another prefix.
|
|
65
|
+
|
|
48
66
|
## Agent names
|
|
49
67
|
|
|
50
68
|
Name agents by role with a numeric suffix: `worker-1`, `reviewer-1`,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Task substates: classification without stranded dependents
|
|
2
2
|
|
|
3
|
-
Status: shipped in 3.0.0 (schema v11); `CLOSED/rejected` added in 3.1.0. Implemented 2026-09-29 (approved 2026-09-29; see [Deviations during implementation](#deviations-during-implementation))
|
|
3
|
+
Status: shipped in 3.0.0 (schema v11); `CLOSED/rejected` added in 3.1.0; `OPEN/triage` added in 3.4.0 (per D10, one seeded row). Implemented 2026-09-29 (approved 2026-09-29; see [Deviations during implementation](#deviations-during-implementation))
|
|
4
4
|
Date: 2026-09-29
|
|
5
5
|
Supersedes the notes-only convention from `9e3c47b` ("tasks: reduce lifecycle to three states").
|
|
6
6
|
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Keep-driving nudge: one prompt when an orchestrator stops early
|
|
2
|
+
|
|
3
|
+
Status: shipped (unreleased). Implemented 2026-10-03; see [Deviations](#deviations-during-implementation)
|
|
4
|
+
Date: 2026-10-03
|
|
5
|
+
|
|
6
|
+
## Problem
|
|
7
|
+
|
|
8
|
+
An orchestrator dispatches workers, then ends its turn to print a
|
|
9
|
+
status summary while those workers are still running. Nothing happens
|
|
10
|
+
until the human notices and types "carry on". The crew sits idle for
|
|
11
|
+
as long as the human is away. This is the most common way a long run
|
|
12
|
+
stalls, and a rule in the skill alone has not stopped it.
|
|
13
|
+
|
|
14
|
+
`skills/mu/SKILL.md` § Orchestrator rules now states the rule ("While
|
|
15
|
+
workers run, keep driving"). The pi extension can back it up at the one
|
|
16
|
+
moment it matters: when the orchestrator is about to stop.
|
|
17
|
+
|
|
18
|
+
## Approach
|
|
19
|
+
|
|
20
|
+
When a pi session that dispatched mu work is about to settle, and that
|
|
21
|
+
work is still running, the extension injects **one** message quoting
|
|
22
|
+
the skill's rule, and asks pi to continue. The model then either goes
|
|
23
|
+
back to `mu task wait`, or ends the turn again with a reason. The
|
|
24
|
+
second stop is final: the nudge fires at most once per user prompt.
|
|
25
|
+
|
|
26
|
+
This is not a goal loop. It does not re-check, re-inject, or count
|
|
27
|
+
continuations. One reminder, then the model's judgement stands.
|
|
28
|
+
|
|
29
|
+
## Behaviour
|
|
30
|
+
|
|
31
|
+
1. **Arm.** During a run, the extension watches `tool_call` events for
|
|
32
|
+
bash commands that dispatch mu work: `mu agent send`, `mu agent
|
|
33
|
+
spawn`, or `mu task claim ... --for`. It records the workstreams
|
|
34
|
+
they name (`-w`, `--workstream`, or a qualified `<ws>/<task>` ref),
|
|
35
|
+
falling back to the default resolution (`$MU_SESSION`, tmux session).
|
|
36
|
+
A run with no dispatch never arms. `mu_delegate` does not arm: its
|
|
37
|
+
answers already arrive as follow-ups.
|
|
38
|
+
2. **Check.** On `agent_before_settle`, if armed and not yet fired for
|
|
39
|
+
this prompt, run `mu state -w <ws...> --json` (about 1 s) and count
|
|
40
|
+
`inProgress` tasks across those workstreams. Zero means the work is
|
|
41
|
+
done or parked: let the turn end.
|
|
42
|
+
3. **Nudge.** Otherwise return one `custom_message` entry
|
|
43
|
+
(`customType: "mu-keep-driving"`, `display: true`) and
|
|
44
|
+
`continue: true`. The text is the skill paragraph verbatim, followed
|
|
45
|
+
by the live count and the wait command:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
[mu] <the skill paragraph>
|
|
49
|
+
|
|
50
|
+
3 tasks IN_PROGRESS in auth. Next: mu task wait -w auth --first --on-stall exit
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
4. **Record.** Write `mu log -w <ws> --kind nudge 'keep-driving: 3 in
|
|
54
|
+
progress'` so the push is visible in the activity log, next to the
|
|
55
|
+
orchestrator's own entries.
|
|
56
|
+
5. **Reset.** The fired flag and the armed set clear on the next
|
|
57
|
+
`input` event, i.e. the next human (or mu-sent) prompt.
|
|
58
|
+
|
|
59
|
+
`outcome: "aborted"` or `"error"` never nudges: the human pressed Esc,
|
|
60
|
+
or the run failed, and both should stop.
|
|
61
|
+
|
|
62
|
+
## Single source for the text
|
|
63
|
+
|
|
64
|
+
The paragraph lives in `SKILL.md` between
|
|
65
|
+
`<!-- mu:keep-driving -->` and `<!-- /mu:keep-driving -->`. The
|
|
66
|
+
extension reads it from the package's skill at load time. A test
|
|
67
|
+
asserts the markers exist and the extracted text is non-empty, so
|
|
68
|
+
editing the skill edits the nudge, and deleting the markers fails the
|
|
69
|
+
gate rather than silently sending nothing.
|
|
70
|
+
|
|
71
|
+
## Opt-out
|
|
72
|
+
|
|
73
|
+
`MU_NUDGE=0` disables it. `mu doctor` reports it next to `MU_DELEGATE`.
|
|
74
|
+
|
|
75
|
+
## Fit with the pillars
|
|
76
|
+
|
|
77
|
+
- **The CLI is the product.** The nudge adds no state and no logic the
|
|
78
|
+
CLI lacks: its only data is `mu state --json`, and its only write is
|
|
79
|
+
`mu log`. Without the extension, the same rule is in the skill. Like
|
|
80
|
+
`mu_delegate`'s follow-up callback, it is harness glue, not a feature.
|
|
81
|
+
- **One DB is canonical.** The armed set and fired flag are per-prompt
|
|
82
|
+
scratch, never persisted. Losing them loses one reminder.
|
|
83
|
+
- **Nothing hidden.** The message is displayed in the transcript and
|
|
84
|
+
logged in the DB.
|
|
85
|
+
- **ROADMAP.** No daemon, watcher, or loop: one hook, one check, one
|
|
86
|
+
message. Estimated under 150 LOC plus tests.
|
|
87
|
+
|
|
88
|
+
## Key decisions
|
|
89
|
+
|
|
90
|
+
| # | Decision | Why |
|
|
91
|
+
|---|---|---|
|
|
92
|
+
| D1 | At most once per user prompt. | A loop overrides the model's judgement on real human decisions; one reminder corrects the common mistake and then defers. |
|
|
93
|
+
| D2 | Arm only on observed dispatch. | A session that never dispatched is not orchestrating; nudging it would be noise. |
|
|
94
|
+
| D3 | Gate on `inProgress > 0`, not ready tasks. | Ready-but-unclaimed work may be waiting on the human's go-ahead. Running workers are the clear case. |
|
|
95
|
+
| D4 | Quote the skill paragraph, read at load. | One source of truth; the model sees the exact rule it was taught. |
|
|
96
|
+
| D5 | `agent_before_settle` + `continue: true`, not `sendUserMessage`. | The boundary hook is pi's designed point for one continuation, and the entry is a visible custom message, not fake user input. |
|
|
97
|
+
| D6 | Log every nudge with `--kind nudge`. | The push is part of the run's record; `mu log --kind nudge` shows how often orchestrators stop early. |
|
|
98
|
+
|
|
99
|
+
## Out of scope
|
|
100
|
+
|
|
101
|
+
- A worker that stops without closing its task. Same shape (check
|
|
102
|
+
`mu me` for an owned IN_PROGRESS task, nudge once), but a separate
|
|
103
|
+
decision.
|
|
104
|
+
- Non-pi harnesses. They get the skill rule only.
|
|
105
|
+
- Any repeat, backoff, or goal condition.
|
|
106
|
+
|
|
107
|
+
## Test plan
|
|
108
|
+
|
|
109
|
+
- Unit, with a fake pi API (as `delegate.ts` tests do):
|
|
110
|
+
- no dispatch in the run → no nudge;
|
|
111
|
+
- dispatch + `inProgress: 0` → no nudge;
|
|
112
|
+
- dispatch + `inProgress: 2` → one entry, `continue: true`, one
|
|
113
|
+
`mu log` call;
|
|
114
|
+
- a second settle in the same prompt → no nudge;
|
|
115
|
+
- a new `input` event → armed again;
|
|
116
|
+
- `outcome: "aborted"` → no nudge;
|
|
117
|
+
- `MU_NUDGE=0` → no nudge.
|
|
118
|
+
- Marker test: `SKILL.md` contains the markers; extracted text matches
|
|
119
|
+
the paragraph.
|
|
120
|
+
- Manual: real orchestrator session, dispatch two workers, ask for a
|
|
121
|
+
status summary; confirm one `[mu]` message, the model resumes
|
|
122
|
+
waiting, and `mu log --kind nudge` shows the entry.
|
|
123
|
+
|
|
124
|
+
## Deviations during implementation
|
|
125
|
+
|
|
126
|
+
- **Wait hint names tasks.** `mu task wait` takes task ids, so the
|
|
127
|
+
message lists up to eight `<ws>/<task>` refs and counts the rest,
|
|
128
|
+
instead of a `-w <ws>` form that does not exist.
|
|
129
|
+
- **Both `mu state --json` shapes.** One `-w` prints a bare card; several
|
|
130
|
+
print `{ workstreams: [...] }`. The unit tests first mocked only the
|
|
131
|
+
second; the live run used the first and stayed silent. Both are read
|
|
132
|
+
and tested now.
|
|
133
|
+
- **`scratch` never arms.** Dispatches into the reserved delegate
|
|
134
|
+
workstream are `mu_delegate`'s, whose answers return as follow-ups.
|
|
135
|
+
- **The check runs once per prompt even when it fails.** A failing
|
|
136
|
+
`mu state` does not retry on the next settle.
|
|
137
|
+
|
|
138
|
+
Live verification: a real pi orchestrator against a throwaway DB
|
|
139
|
+
claimed a task for a worker, ended its turn, received one
|
|
140
|
+
`[mu-keep-driving]` message with `mu task wait nudgeprobe/slow ...`, and
|
|
141
|
+
`mu log --kind nudge` held one entry. With nothing IN_PROGRESS, no
|
|
142
|
+
nudge fired.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mu-crew/mu",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.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"
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"files": [
|
|
45
45
|
"dist",
|
|
46
46
|
"skills",
|
|
47
|
+
"prompts",
|
|
47
48
|
"docs",
|
|
48
49
|
"README.md",
|
|
49
50
|
"AGENTS.md"
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Debug with mu: independent hypotheses from separate evidence, each attacked, fix verified"
|
|
3
|
+
argument-hint: "<symptom>"
|
|
4
|
+
---
|
|
5
|
+
Debug this with mu. Load the mu skill, then read its
|
|
6
|
+
`recipes/hypothesis-panel.md` in full and follow it.
|
|
7
|
+
|
|
8
|
+
Symptom: $@
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Find, refute, synthesize with mu: audit or fact-check with a refuter per finding"
|
|
3
|
+
argument-hint: "<what to audit or check>"
|
|
4
|
+
---
|
|
5
|
+
Run a find-refute-synthesize pass with mu. Load the mu skill, then read
|
|
6
|
+
its `recipes/refute.md` in full and follow it.
|
|
7
|
+
|
|
8
|
+
Scope: $@
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Review panel with mu: parallel focused reviewers, refuted findings, one report"
|
|
3
|
+
argument-hint: "[diff, PR, branch, or path]"
|
|
4
|
+
---
|
|
5
|
+
Run a review panel with mu. Load the mu skill, then read its
|
|
6
|
+
`recipes/review-panel.md` in full and follow it.
|
|
7
|
+
|
|
8
|
+
Target: ${@:-the uncommitted changes in this repo}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Rules audit with mu: check a change against AGENTS.md rule by rule, or mine missing rules"
|
|
3
|
+
argument-hint: "[check <target> | mine]"
|
|
4
|
+
---
|
|
5
|
+
Run a rules audit with mu. Load the mu skill, then read its
|
|
6
|
+
`recipes/rules-audit.md` in full and follow it.
|
|
7
|
+
|
|
8
|
+
Mode and target: ${@:-check the uncommitted changes in this repo}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Tournament with mu: competing attempts judged in pairs against a rubric"
|
|
3
|
+
argument-hint: "<what to choose or build>"
|
|
4
|
+
---
|
|
5
|
+
Run a tournament with mu. Load the mu skill, then read its
|
|
6
|
+
`recipes/tournament.md` in full and follow it. Ask me for the rubric
|
|
7
|
+
first if the task does not imply one.
|
|
8
|
+
|
|
9
|
+
Task: $@
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Loop with mu until a check is clean (tsc, lint, tests), with a stop rule written first"
|
|
3
|
+
argument-hint: "<stop rule, e.g. npx tsc --noEmit exits 0>"
|
|
4
|
+
---
|
|
5
|
+
Loop with mu until this holds. Load the mu skill, then read its
|
|
6
|
+
`recipes/loop-until-done.md` in full and follow it.
|
|
7
|
+
|
|
8
|
+
Stop rule: $@
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Run a large or risky job the mu way: DAG, fan-out, adversarial review"
|
|
3
|
+
argument-hint: "<job>"
|
|
4
|
+
---
|
|
5
|
+
Ultrathink this job with mu. Load the mu skill, then read its
|
|
6
|
+
`recipes/ultrathink.md` in full and follow it. Every unit, review, and
|
|
7
|
+
round goes in the task DAG; checks (refuters, judges, skeptics) are
|
|
8
|
+
delegate calls. Keep driving until the stop rule holds.
|
|
9
|
+
|
|
10
|
+
Job: $@
|