@martintrojer/mu 0.3.2 → 0.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 +181 -42
- package/README.md +63 -22
- package/dist/cli.js +13348 -5236
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1428 -1369
- package/dist/index.js +4002 -3110
- package/dist/index.js.map +1 -1
- package/docs/ARCHITECTURE.md +296 -56
- package/docs/HANDOVER.md +461 -0
- package/docs/ROADMAP.md +120 -498
- package/docs/USAGE_GUIDE.md +445 -143
- package/docs/VISION.md +48 -4
- package/docs/VOCABULARY.md +18 -5
- package/docs/img/tui-dashboard.png +0 -0
- package/package.json +12 -6
- package/skills/mu/SKILL.md +273 -469
package/docs/USAGE_GUIDE.md
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
# mu — Usage Guide
|
|
2
2
|
|
|
3
|
-
A practical, copy-pasteable tour of mu (current main; v0.
|
|
3
|
+
A practical, copy-pasteable tour of mu (current main; v0.4-track).
|
|
4
4
|
Everything below works against the built CLI. Terms are canonical
|
|
5
5
|
— see [VOCABULARY.md](VOCABULARY.md) for definitions; the complete
|
|
6
6
|
current verb list is in `## CLI — complete verb list` of
|
|
7
7
|
[skills/mu/SKILL.md](../skills/mu/SKILL.md).
|
|
8
8
|
|
|
9
|
-
> **Status:** v0.
|
|
9
|
+
> **Status:** v0.4 wave (pre-1.0). ~60 typed verbs across 8
|
|
10
10
|
> namespaces (`workstream`, `agent`, `task`, `workspace`, `log`,
|
|
11
11
|
> `snapshot`, `archive`, `me`) plus bare top-level verbs
|
|
12
12
|
> (`state`, `doctor`, `sql`, `undo`, `adopt`). Every verb accepts
|
|
13
13
|
> `--json` (one allow-listed exception, `mu agent attach`),
|
|
14
14
|
> per-agent VCS workspaces (jj/sl/git/none), activity log with
|
|
15
|
-
> `--tail` subscription,
|
|
16
|
-
>
|
|
15
|
+
> `--tail` subscription, bare `mu` TTY dashboard, canonical static
|
|
16
|
+
> state card (`mu state` default / `--tui` render modes), whole-DB
|
|
17
17
|
> snapshots auto-captured before destructive verbs +
|
|
18
18
|
> `mu undo` / `mu snapshot {list,show}`, evidence on lifecycle
|
|
19
19
|
> verbs, schema v7 (v5 surrogate INTEGER PKs + per-workstream
|
|
20
20
|
> UNIQUE on operator-facing names; v6 added the `archive_*`
|
|
21
21
|
> family additively; v7 dropped the dead `approvals` table).
|
|
22
22
|
> See [CHANGELOG.md](../CHANGELOG.md) for the release entry,
|
|
23
|
-
> and [§ Not in 0.
|
|
23
|
+
> and [§ Not in 0.4.0](#whats-not-in-040-and-how-to-work-around-it)
|
|
24
24
|
> at the bottom for the gaps that still need workarounds.
|
|
25
25
|
|
|
26
26
|
*If anything below disagrees with `mu --help`, trust `mu --help`.*
|
|
@@ -33,7 +33,8 @@ current verb list is in `## CLI — complete verb list` of
|
|
|
33
33
|
2. [Get oriented (`mu doctor`)](#2-get-oriented)
|
|
34
34
|
3. [Create a workstream (`mu workstream init`)](#3-create-a-workstream)
|
|
35
35
|
4. [Plan some work as a DAG (`mu task add`)](#4-plan-some-work-as-a-dag)
|
|
36
|
-
5. [See the graph (
|
|
36
|
+
5. [See the graph (dashboard + state API)](#5-see-the-graph-dashboard--state-api)
|
|
37
|
+
5b. [The TUI dashboard (interactive)](#5b-the-tui-dashboard-interactive)
|
|
37
38
|
6. [Spawn a crew (`mu agent spawn`)](#6-spawn-a-crew)
|
|
38
39
|
7. [Watch the crew live (`tmux attach`)](#7-watch-the-crew-live)
|
|
39
40
|
8. [Send work to an agent (`mu agent send`)](#8-send-work-to-an-agent)
|
|
@@ -47,7 +48,7 @@ current verb list is in `## CLI — complete verb list` of
|
|
|
47
48
|
15.5. [Archives — cross-workstream preservation](#155-archives--cross-workstream-preservation-of-task-graphs)
|
|
48
49
|
16. [One-shot demo script](#16-one-shot-demo-script)
|
|
49
50
|
17. [Mental model in three sentences](#mental-model-in-three-sentences)
|
|
50
|
-
18. [What's NOT in 0.
|
|
51
|
+
18. [What's NOT in 0.4.0](#whats-not-in-040-and-how-to-work-around-it)
|
|
51
52
|
19. [Where to go from here](#where-to-go-from-here)
|
|
52
53
|
|
|
53
54
|
---
|
|
@@ -140,6 +141,32 @@ tmux # if you're not already in one
|
|
|
140
141
|
|
|
141
142
|
## 2. Get oriented
|
|
142
143
|
|
|
144
|
+
For a human at an interactive terminal, bare `mu` is the home base:
|
|
145
|
+
it launches the read-only TUI with every workstream on the machine
|
|
146
|
+
loaded as tabs. Initial tab focus uses this ladder: `$MU_SESSION` when
|
|
147
|
+
it names a loaded workstream; then the current tmux session name when
|
|
148
|
+
it is `mu-<workstream>`; then best-effort cwd detection against
|
|
149
|
+
registered workspace paths; then cwd equal to the VCS-derived project
|
|
150
|
+
root of any loaded workstream's workspaces (ties broken by most-recent
|
|
151
|
+
workstream activity); then tab 0. If no workstream exists yet, it
|
|
152
|
+
prints help plus the one-paste start command:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
mu
|
|
156
|
+
# Get started: mu workstream init <name>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
For scripts, agents, CI, and pipes, bare `mu` deliberately does NOT
|
|
160
|
+
enter the TUI: when stdout is not a TTY it prints `mu --help`. Use
|
|
161
|
+
explicit typed verbs and `--json` for the API surface:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
mu state -w <workstream> --json
|
|
165
|
+
MU_NO_TUI=1 mu # force the non-TTY/help path even in a terminal
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Run the diagnostic once to check tmux + DB health:
|
|
169
|
+
|
|
143
170
|
```bash
|
|
144
171
|
mu doctor
|
|
145
172
|
```
|
|
@@ -222,9 +249,10 @@ $ mu task list -w foo --json
|
|
|
222
249
|
```
|
|
223
250
|
|
|
224
251
|
`count` is `items.length` pre-computed so `jq '.count'` is one less
|
|
225
|
-
hop than `jq '.items | length'`. Future siblings
|
|
226
|
-
|
|
227
|
-
|
|
252
|
+
hop than `jq '.items | length'`. Future siblings layer on without
|
|
253
|
+
breaking the existing two fields. Today `mu workspace commits --json`
|
|
254
|
+
also includes `vcs`, `baseRef`, and `workspacePath` siblings because
|
|
255
|
+
that verb already computes the workspace's fork metadata.
|
|
228
256
|
|
|
229
257
|
Applies to: `mu task list / next / owned-by / notes`,
|
|
230
258
|
`mu workstream list`, `mu workstream destroy --empty` (dry-run),
|
|
@@ -329,8 +357,8 @@ Tasks have **mandatory** `impact` (1–100) and `effort-days` (>0).
|
|
|
329
357
|
Edges are blocks-relationships, modelled as **`--blocked-by`** on `mu
|
|
330
358
|
task add` (and `mu task reparent`): `--blocked-by design` means "this
|
|
331
359
|
task is blocked by `design`; it can't start until `design` closes."
|
|
332
|
-
Tasks are **scoped to a workstream** —
|
|
333
|
-
tasks for the workstream you're
|
|
360
|
+
Tasks are **scoped to a workstream** — the dashboard and state views only show
|
|
361
|
+
tasks for the workstream you're viewing.
|
|
334
362
|
|
|
335
363
|
```bash
|
|
336
364
|
# --workstream can be omitted if you're inside the workstream's tmux
|
|
@@ -357,112 +385,299 @@ Each task validates its id (`/^[a-z][a-z0-9_-]{0,63}$/`) and rejects
|
|
|
357
385
|
duplicates. If you tried `mu task add x --blocked-by y` while `y`
|
|
358
386
|
already transitively depended on `x`, mu would refuse with a `CycleError`.
|
|
359
387
|
|
|
360
|
-
**Task ids are
|
|
361
|
-
|
|
362
|
-
|
|
388
|
+
**Task ids are per-workstream unique.** The same local id can exist in
|
|
389
|
+
multiple workstreams, so cross-workstream references use the qualified
|
|
390
|
+
form `<workstream>/<id>` when a global scope is needed. Blocks-edges
|
|
391
|
+
are always same-workstream — if a blocker resolves outside the target
|
|
363
392
|
workstream, mu refuses with a `CrossWorkstreamEdgeError`.
|
|
364
393
|
|
|
365
394
|
---
|
|
366
395
|
|
|
367
|
-
## 5. See the graph (
|
|
396
|
+
## 5. See the graph (dashboard + state API)
|
|
368
397
|
|
|
369
|
-
|
|
370
|
-
mu --workstream auth-refactor
|
|
371
|
-
# or, if your tmux session is mu-auth-refactor:
|
|
372
|
-
mu
|
|
373
|
-
```
|
|
398
|
+
`mu` exposes one logical "what's going on?" view with two renderers:
|
|
374
399
|
|
|
375
|
-
|
|
376
|
-
|
|
400
|
+
| Surface | Use it for |
|
|
401
|
+
| -------------------- | --------------------------------------------------------------- |
|
|
402
|
+
| **bare `mu`** | A human at a terminal — launches the interactive TUI dashboard. |
|
|
403
|
+
| **`mu state --tui`** | Same TUI, explicitly opt-in. Useful in scripts / aliases. |
|
|
404
|
+
| **`mu state`** | Static text card. JSON-friendly; pipeable; `watch`-able. |
|
|
405
|
+
| **`mu state --json`** | The canonical full snapshot. Agents and scripts read this. |
|
|
377
406
|
|
|
378
|
-
|
|
379
|
-
|
|
407
|
+
The interactive surface is large enough to deserve its own section —
|
|
408
|
+
see [§ 5b. The TUI dashboard](#5b-the-tui-dashboard-interactive)
|
|
409
|
+
immediately below. The rest of this section is the static / JSON
|
|
410
|
+
contract.
|
|
380
411
|
|
|
381
|
-
|
|
382
|
-
Track 1: review (3 tasks, 1 ready, track)
|
|
412
|
+
### Static state card (`mu state`)
|
|
383
413
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
found. When two goals share a prerequisite, mu collapses them into
|
|
399
|
-
ONE track ("merged") so two agents are never assigned tasks that
|
|
400
|
-
share a dependency
|
|
401
|
-
- **Ready** — actionable now, sorted by ROI (impact / effort)
|
|
402
|
-
|
|
403
|
-
### `mu state` render modes (default, `--hud`, `--mission`)
|
|
404
|
-
|
|
405
|
-
`mu state` is one verb with three render modes — same data set,
|
|
406
|
-
different presentation strategy. The flag picks the renderer; the
|
|
407
|
-
JSON shape (`--json`) follows render mode (full vs stripped).
|
|
408
|
-
|
|
409
|
-
```bash
|
|
410
|
-
mu state # default: full top-to-bottom card
|
|
411
|
-
mu state --hud # dynamic-fit budget renderer (watch / popup / status-bar)
|
|
412
|
-
mu state --mission # stripped 5-col glance card
|
|
413
|
-
mu # bare alias for `mu state --mission`
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
- **default (full card)** — every section: agents + orphans + tracks +
|
|
417
|
-
ready / in-progress / blocked / recent-closed + workspaces + recent
|
|
418
|
-
events. JSON-first by design (per Ilya's council critique: state
|
|
419
|
-
cards as the default attention surface; SQL/raw verbs as the
|
|
420
|
-
escape hatch underneath).
|
|
421
|
-
|
|
422
|
-
- **`--hud`** — dynamic table layout that fills the terminal (or tmux
|
|
423
|
-
pane) height + width with as much useful data as fits.
|
|
424
|
-
`watch -n 5 mu state --hud -w X` for a refreshing pane;
|
|
425
|
-
`tmux display-popup -E 'mu state --hud -w X'` for an on-demand
|
|
426
|
-
popup; `#(mu state --hud -w X --json) | jq ...` for tmux
|
|
427
|
-
status-bar interpolation. Sections (priority order):
|
|
428
|
-
header / agents / ready / in-progress / tracks / recent-events.
|
|
429
|
-
Truncated tables get a `… +N more (<verb>)` footer; lower-priority
|
|
430
|
-
sections that can't fit are skipped entirely. Drops blocked /
|
|
431
|
-
recent-closed / workspaces (not glanceable); operator drops
|
|
432
|
-
`--hud` to see them.
|
|
433
|
-
|
|
434
|
-
- **`--mission`** — stripped 5-col glance card (agents + orphans +
|
|
435
|
-
tracks + ready). The bare-`mu` muscle-memory orient call
|
|
436
|
-
("what's going on?"). The full card with blocked / recent-closed /
|
|
437
|
-
workspaces is too much for that intent; `--mission` is the
|
|
438
|
-
intentional minimum-viable orient view.
|
|
439
|
-
|
|
440
|
-
`--hud` and `--mission` are mutually exclusive.
|
|
441
|
-
|
|
442
|
-
Multi-workstream: pass `-w` multiple values to render N workstreams
|
|
443
|
-
in one card. `-w a,b,c`, `-w a -w b`, or any mix all work — see
|
|
444
|
-
[CLI conventions](#cli-conventions-multi-value-flags). `--all` is
|
|
445
|
-
sugar for "every workstream on this machine" (mutually exclusive with
|
|
446
|
-
`-w`). N≥2 in `--hud` mode unions the per-ws sections with a leading
|
|
447
|
-
`workstream` column; in default + `--mission` modes N≥2 stacks one
|
|
448
|
-
per-workstream card after another. The `--json` envelope wraps in
|
|
449
|
-
`{ workstreams: [...] }` when N≥2.
|
|
450
|
-
|
|
451
|
-
JSON shapes (per render mode):
|
|
414
|
+
For an agent/script or a static capture, use explicit `mu state`:
|
|
415
|
+
|
|
416
|
+
```bash
|
|
417
|
+
mu state -w auth-refactor # human-readable card
|
|
418
|
+
mu state -w auth-refactor --json # full snapshot
|
|
419
|
+
mu state --all --json # every workstream on this machine
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
The static card includes every section the TUI cards summarize:
|
|
423
|
+
agents + orphans + tracks + ready / in-progress / blocked /
|
|
424
|
+
recent-closed tasks + workspaces + recent events. `--json` emits the
|
|
425
|
+
same full snapshot shape regardless of `--tui`.
|
|
426
|
+
|
|
427
|
+
**JSON shapes**
|
|
452
428
|
|
|
453
429
|
- `mu state --json` (single-ws): flat `{ workstreamName, agents,
|
|
454
430
|
orphans, tracks, ready, blocked, inProgress, recentClosed,
|
|
455
431
|
workspaces, recent }`.
|
|
456
|
-
- `mu state --
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
432
|
+
- `mu state --json` (multi-ws): wrapped `{ workstreams: [{...}, ...] }`.
|
|
433
|
+
- bare `mu --json`: prints `--help` rather than entering the TUI;
|
|
434
|
+
use `mu state --json` for the full snapshot.
|
|
435
|
+
- `--tui` is render-only and incompatible with `--json` (the TUI
|
|
436
|
+
has no JSON shape).
|
|
437
|
+
|
|
438
|
+
**Multi-workstream**: pass `-w` multiple values, or `--all`. See
|
|
439
|
+
[CLI conventions](#cli-conventions-multi-value-flags). In static
|
|
440
|
+
mode N≥2 stacks one per-workstream card after another.
|
|
441
|
+
|
|
442
|
+
> **Migrating from old state surfaces**: `mu state --hud` and
|
|
443
|
+
> `mu state --mission` were removed in v0.4; use `mu state --tui`
|
|
444
|
+
> for the interactive surface and `mu state --json` for the full
|
|
445
|
+
> snapshot. `tmux display-popup -E 'mu state -w X'` keeps working
|
|
446
|
+
> unchanged for popup-card use.
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## 5b. The TUI dashboard (interactive)
|
|
451
|
+
|
|
452
|
+
The interactive TUI is mu's flagship human surface. It is **read-only
|
|
453
|
+
by design** — every act-intent `y`anks the canonical `mu` command to
|
|
454
|
+
your clipboard so you run mutations from your shell, with one
|
|
455
|
+
documented escape (`t` in git-show drills runs `tuicr` in the project
|
|
456
|
+
root, see below).
|
|
457
|
+
|
|
458
|
+
### Launch
|
|
461
459
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
460
|
+
```bash
|
|
461
|
+
mu # bare; opens the TUI when stdout is a TTY
|
|
462
|
+
mu state --tui # explicit; same surface
|
|
463
|
+
mu state --tui -w a,b # restrict to specific workstreams
|
|
464
|
+
mu state --tui --all # all workstreams (default for bare `mu`)
|
|
465
|
+
MU_NO_TUI=1 mu # force the help path even in a TTY
|
|
466
|
+
mu --json # also forces help; pipe `mu state --json`
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
Quit with `q` or `Ctrl-C`. The dashboard restores your scrollback
|
|
470
|
+
on exit (alt-screen).
|
|
471
|
+
|
|
472
|
+
**Initial active tab** is picked from this ladder:
|
|
473
|
+
`$MU_SESSION` → current tmux session name (`mu-<ws>`) → cwd inside a
|
|
474
|
+
registered workspace → cwd at the VCS-derived project root of any
|
|
475
|
+
workstream (newest activity wins ties) → tab 0.
|
|
476
|
+
|
|
477
|
+
### Layout: 10 cards, responsive columns
|
|
478
|
+
|
|
479
|
+
The dashboard renders 10 toggleable cards with rounded borders and
|
|
480
|
+
section headers inset into the top border line (lazygit / btop / k9s
|
|
481
|
+
convention):
|
|
482
|
+
|
|
483
|
+
| Slot | Card | Toggle | Popup | Content |
|
|
484
|
+
| ---- | ------------- | ------ | --------- | ---------------------------------------------------- |
|
|
485
|
+
| 0 | Commits | `0` | `Shift+0` | Recent project-root commits (git / jj / sl) |
|
|
486
|
+
| 1 | Agents | `1` | `Shift+1` | Active agents + status + cli + role |
|
|
487
|
+
| 2 | Tracks | `2` | `Shift+2` | Parallel tracks (union-find clusters) |
|
|
488
|
+
| 3 | Ready (Tasks) | `3` | `Shift+3` | Ready-to-claim tasks (no open blockers) |
|
|
489
|
+
| 4 | Activity log | `4` | `Shift+4` | Recent `agent_logs` events |
|
|
490
|
+
| 5 | Workspaces | `5` | `Shift+5` | Per-agent VCS workspaces + behind/dirty status |
|
|
491
|
+
| 6 | In-progress | `6` | `Shift+6` | IN_PROGRESS tasks owned by agents |
|
|
492
|
+
| 7 | Blocked | `7` | `Shift+7` | Tasks with at least one open blocker |
|
|
493
|
+
| 8 | Recent | `8` | `Shift+8` | Recently CLOSED tasks |
|
|
494
|
+
| 9 | Doctor | `9` | `Shift+9` | Cheap health checks (schema, ghosts, orphans, …) |
|
|
495
|
+
| — | DAG | — | `g` | Full task DAG forest (keybind-only) |
|
|
496
|
+
| — | All tasks | — | `t` | Sortable / filterable list of every task |
|
|
497
|
+
|
|
498
|
+
Digit toggles HIDE / SHOW the card on the dashboard; `Shift+digit`
|
|
499
|
+
opens the matching fullscreen popup. **Single-popup invariant**: only
|
|
500
|
+
one popup is visible at a time; `Esc` / `q` returns to the dashboard
|
|
501
|
+
with all toggles + tick rate preserved.
|
|
502
|
+
|
|
503
|
+
**Responsive layout**: cards stack below 120 cols, then reflow into
|
|
504
|
+
pair-aware 2 / 3 / 4-column layouts at 120 / 180 / 240 cols. Each
|
|
505
|
+
visible card gets a dynamic row budget so a noisy list cannot crowd
|
|
506
|
+
out its siblings; overflow shows as `+N more · Shift+N` inset into
|
|
507
|
+
the bottom border. On very short panes, the dashboard culls
|
|
508
|
+
low-priority cards (Doctor → Recent → Workspaces → …) and shows
|
|
509
|
+
`+N cards hidden · resize taller` until the surviving cards fit.
|
|
510
|
+
|
|
511
|
+
Dashboard ordering is slot-stable: within each rendered column,
|
|
512
|
+
non-stream cards are ordered by toggle digit ascending; stream cards
|
|
513
|
+
(Commits, Activity log) sit as natural trailers, with slot 0 trailing
|
|
514
|
+
last.
|
|
515
|
+
|
|
516
|
+
### Multi-workstream tabs
|
|
517
|
+
|
|
518
|
+
When the TUI is launched with N≥2 workstreams (e.g. bare `mu` on a
|
|
519
|
+
machine with multiple workstreams, or `mu state --tui -w a,b,c`),
|
|
520
|
+
a compact tab strip renders above the cards:
|
|
521
|
+
|
|
522
|
+
```
|
|
523
|
+
workstreams: ▸ auth-refactor · ui-rewrite · demo (Tab / Shift-Tab)
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
- `Tab` cycles forward, `Shift-Tab` backward (suppressed inside
|
|
527
|
+
popups so the same key still navigates inside popups that bind
|
|
528
|
+
it locally).
|
|
529
|
+
- The active tab name appears in the status bar's right zone next
|
|
530
|
+
to the tick rate.
|
|
531
|
+
- Cards / popups always operate on the active tab — there's no
|
|
532
|
+
per-row workstream column.
|
|
533
|
+
- For N=1 the strip renders nothing (frame is byte-identical to
|
|
534
|
+
single-ws TUI).
|
|
535
|
+
- When the workstream set is wider than the terminal, the strip
|
|
536
|
+
windows around the active tab and shows `‹N` / `›N` counters
|
|
537
|
+
for hidden workstreams.
|
|
538
|
+
|
|
539
|
+
### Popup drills
|
|
540
|
+
|
|
541
|
+
`Enter` in any list popup drills into the focused row. Where the
|
|
542
|
+
row is itself an entity (a task), a further `Enter` chains into the
|
|
543
|
+
shared read-only task-detail leaf (notes timeline):
|
|
544
|
+
|
|
545
|
+
- **Tracks popup (`Shift+2`)**: list of tracks → `Enter` opens the
|
|
546
|
+
track's task list → `Enter` opens that task's notes timeline.
|
|
547
|
+
- **Ready / In-progress / Blocked / Recent / All-tasks**:
|
|
548
|
+
list of tasks → `Enter` opens notes; `y` yanks `mu task show <id>`
|
|
549
|
+
(or `mu task claim` / `mu task close` / `mu task tree` depending
|
|
550
|
+
on popup).
|
|
551
|
+
- **Activity log popup (`Shift+4`)**: list of events → `Enter`
|
|
552
|
+
drills into the full untruncated payload of the focused event;
|
|
553
|
+
`y` yanks `mu log --since <seq-1> -n 1 -w <ws>`.
|
|
554
|
+
- **Workspaces popup (`Shift+5`)**: list of workspaces → `Enter`
|
|
555
|
+
opens the commits-since-fork list → `Enter` on a commit opens
|
|
556
|
+
the inline `git show <sha> --stat -p` view; `y` yanks `git show
|
|
557
|
+
<sha>`; `t` launches `tuicr -r <sha>`.
|
|
558
|
+
- **Commits popup (`Shift+0`)**: project-root recent commits →
|
|
559
|
+
`Enter` opens the backend's show view; `y` yanks the show
|
|
560
|
+
command; `t` launches `tuicr`.
|
|
561
|
+
- **Doctor popup (`Shift+9`)**: list of checks → `Enter` opens
|
|
562
|
+
the remediation paragraph for the focused check.
|
|
563
|
+
- **DAG popup (`g`)**: keybind-only; renders the active workstream's
|
|
564
|
+
full task DAG forest (one ASCII subtree per root, diamond-collapse
|
|
565
|
+
marker on repeated nodes).
|
|
566
|
+
|
|
567
|
+
One `Esc` / `q` backs out per recursion level. Drills auto-refresh
|
|
568
|
+
in step with the dashboard tick (fast 1s for SQL-derived bodies
|
|
569
|
+
like notes, slow 10s for subprocess git-show / scrollback). Scroll
|
|
570
|
+
position is preserved across refreshes; subprocess loaders keep the
|
|
571
|
+
prior body visible until the new one arrives so there's no
|
|
572
|
+
blank-flash mid-refetch.
|
|
573
|
+
|
|
574
|
+
### Search / filter
|
|
575
|
+
|
|
576
|
+
`/` inside any list popup enters an incremental case-insensitive
|
|
577
|
+
substring filter (lazygit / k9s convention):
|
|
578
|
+
|
|
579
|
+
- Every printable character appends to the query; `Backspace` pops
|
|
580
|
+
one.
|
|
581
|
+
- `Esc` cancels (clears the query); `Enter` commits (keeps the
|
|
582
|
+
filter applied while letting `j/k` resume normal navigation).
|
|
583
|
+
- Press `/` again on a committed filter to refine.
|
|
584
|
+
- The filter blob is per-popup: agent name + status + cli + role;
|
|
585
|
+
track head id + title; task name + title + status + owner; log
|
|
586
|
+
verb + payload + source.
|
|
587
|
+
- Filter state is per-popup and dies with the popup.
|
|
588
|
+
|
|
589
|
+
Task-list popups also expose **per-status toggles** (`o` / `i` / `c`
|
|
590
|
+
/ `r` / `d` toggle OPEN / IN_PROGRESS / CLOSED / REJECTED / DEFERRED
|
|
591
|
+
visibility; default all-on).
|
|
592
|
+
|
|
593
|
+
The All-tasks popup adds **sort cycle** on `s`: `roi` → `recency`
|
|
594
|
+
→ `age` → `id`.
|
|
595
|
+
|
|
596
|
+
### Mouse
|
|
597
|
+
|
|
598
|
+
Navigation-in only:
|
|
599
|
+
|
|
600
|
+
- Double-click a dashboard card → opens its popup.
|
|
601
|
+
- Scroll-wheel inside a popup list / drill body → moves the focused
|
|
602
|
+
cursor / scrolls the body.
|
|
603
|
+
- Double-click a popup row → drills one level deeper.
|
|
604
|
+
|
|
605
|
+
There is intentionally **no mouse back binding** — use `Esc` / `q`
|
|
606
|
+
to back out predictably.
|
|
607
|
+
|
|
608
|
+
### Yank contract (`y`) and the `tuicr` escape (`t`)
|
|
609
|
+
|
|
610
|
+
Every popup row exposes one canonical `mu` command via `y`. The
|
|
611
|
+
command goes to your system clipboard (pbcopy / wl-copy / xclip /
|
|
612
|
+
xsel / clip.exe with OSC-52 fallback). You run it in your shell.
|
|
613
|
+
The TUI never executes a mutation.
|
|
614
|
+
|
|
615
|
+
The one user-driven escape from the read-only pledge is **`t`**
|
|
616
|
+
inside any `git show` drill (Workspaces popup or Commits popup):
|
|
617
|
+
mu suspends its alt-screen, runs `tuicr -r <sha>` in the project
|
|
618
|
+
root / workspace cwd, then restores the dashboard when tuicr exits.
|
|
619
|
+
This is a deliberate handoff — the operator drives another TUI
|
|
620
|
+
tool, not mu performing the mutation.
|
|
621
|
+
|
|
622
|
+
Task-list cards and popups colour-code status cells consistently
|
|
623
|
+
with the static CLI tables: OPEN cyan, IN_PROGRESS yellow, CLOSED
|
|
624
|
+
green, REJECTED red, DEFERRED dim/gray.
|
|
625
|
+
|
|
626
|
+
### Polling tiers
|
|
627
|
+
|
|
628
|
+
The dashboard has two refresh tiers:
|
|
629
|
+
|
|
630
|
+
- **Fast tick** (default 1s, adjustable with `+` / `-` / `=` /
|
|
631
|
+
`0`): SQL-only. Refreshes tasks, tracks, workspace registry rows,
|
|
632
|
+
and the activity log.
|
|
633
|
+
- **Slow tick** (10s, fixed): subprocess-backed. Refreshes
|
|
634
|
+
tmux-derived agent liveness / orphans, workspace dirty flags,
|
|
635
|
+
recent project commits, and the Doctor summary.
|
|
636
|
+
|
|
637
|
+
The last slow-tier result is merged into every fast render so cards
|
|
638
|
+
do not flicker through a loading state. `r` / F5 refreshes both
|
|
639
|
+
tiers immediately. Tab / Shift-Tab triggers an eager slow refresh
|
|
640
|
+
for the newly active workstream.
|
|
641
|
+
|
|
642
|
+
### Keymap reference
|
|
643
|
+
|
|
644
|
+
| Mode | Keys | Action |
|
|
645
|
+
| --------- | ---------------------------- | -------------------------------------------------------------- |
|
|
646
|
+
| dashboard | `0`-`9` | toggle card visibility |
|
|
647
|
+
| dashboard | `Shift+0`-`Shift+9` | open the matching popup |
|
|
648
|
+
| dashboard | `g` | open DAG popup (keybind-only) |
|
|
649
|
+
| dashboard | `t` | open All-tasks popup (keybind-only) |
|
|
650
|
+
| dashboard | `Tab` / `Shift-Tab` | cycle workstream tabs (N≥2) |
|
|
651
|
+
| dashboard | `+` / `-` / `=` / `0` | adjust fast tick rate (faster / slower / default / pause) |
|
|
652
|
+
| dashboard | `r` / `F5` | force refresh both tiers |
|
|
653
|
+
| dashboard | `?` / `F1` | open help overlay |
|
|
654
|
+
| any | `q` / `Ctrl-C` | quit (or back out of popup; quits at dashboard) |
|
|
655
|
+
| popup | `j` / `k` | move cursor / scroll |
|
|
656
|
+
| popup | `g` / `G` | jump top / bottom |
|
|
657
|
+
| popup | `Ctrl-D` / `Ctrl-U` | half-page down / up |
|
|
658
|
+
| popup | `PgDn` / `PgUp` | full page |
|
|
659
|
+
| popup | `Enter` | drill into focused row |
|
|
660
|
+
| popup | `Esc` / `q` | back out one level |
|
|
661
|
+
| popup | `y` | yank canonical `mu` command for focused row |
|
|
662
|
+
| popup | `/` | enter filter mode |
|
|
663
|
+
| filter | (printable) / `Backspace` | edit query |
|
|
664
|
+
| filter | `Esc` | cancel (clear query) |
|
|
665
|
+
| filter | `Enter` | commit (keep filter, return to nav) |
|
|
666
|
+
| task popup| `o` / `i` / `c` / `r` / `d` | toggle OPEN / IN_PROGRESS / CLOSED / REJECTED / DEFERRED |
|
|
667
|
+
| All-tasks | `s` | cycle sort key (roi → recency → age → id) |
|
|
668
|
+
| git-show | `t` | launch `tuicr -r <sha>` (alt-screen handoff) |
|
|
669
|
+
|
|
670
|
+
`?` shows the same table as a scrollable overlay (j/k/Ctrl-D/U/g/G
|
|
671
|
+
also work inside the overlay).
|
|
672
|
+
|
|
673
|
+
### Read-only invariant
|
|
674
|
+
|
|
675
|
+
The TUI never executes a mutation. This is not a feature of the
|
|
676
|
+
implementation; it's a load-bearing pledge in `docs/ROADMAP.md`. If
|
|
677
|
+
a future TUI gesture tempts you to call into the SDK to mutate
|
|
678
|
+
state, file a roadmap entry first — the yank-and-run pattern is the
|
|
679
|
+
intentional cost we pay to keep the TUI inspectable, scriptable, and
|
|
680
|
+
recoverable from any shell.
|
|
466
681
|
|
|
467
682
|
---
|
|
468
683
|
|
|
@@ -630,6 +845,28 @@ MU_SEND_DELAY_MS=300 mu agent send worker-1 "..." # faster, less safe
|
|
|
630
845
|
MU_SEND_DELAY_MS=1000 mu agent send worker-1 "..." # slow remote
|
|
631
846
|
```
|
|
632
847
|
|
|
848
|
+
If the target agent has a workspace that is **stale** (≥10 commits
|
|
849
|
+
behind main — the same red bucket shown in `mu workspace list` and the
|
|
850
|
+
TUI Workspaces card), `mu agent send` prints a yellow stderr warning
|
|
851
|
+
but still sends by default:
|
|
852
|
+
|
|
853
|
+
```bash
|
|
854
|
+
WARN: worker-1 workspace is 14 commits behind main (≥10 = stale)
|
|
855
|
+
Next:
|
|
856
|
+
Refresh first : mu workspace refresh worker-1 -w auth-refactor
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
Use `--strict-staleness` when a wrapper should refuse instead of
|
|
860
|
+
warning:
|
|
861
|
+
|
|
862
|
+
```bash
|
|
863
|
+
mu agent send worker-1 "..." -w auth-refactor --strict-staleness
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
Agents without workspaces are skipped (common for read-only roles).
|
|
867
|
+
`--json` output includes `staleness: null` or `{agentName,
|
|
868
|
+
workstreamName, commitsBehindMain, isStale}`.
|
|
869
|
+
|
|
633
870
|
---
|
|
634
871
|
|
|
635
872
|
## 9. Read what an agent did
|
|
@@ -714,6 +951,29 @@ workstream prefix, `AgentNotFoundError` (exit 3, message names the
|
|
|
714
951
|
workstream) when the named worker doesn't live there. Nothing is
|
|
715
952
|
written on either failure.
|
|
716
953
|
|
|
954
|
+
When `--for` targets an agent with a stale workspace (≥10 commits
|
|
955
|
+
behind main), `mu task claim` warns on stderr and appends a refresh
|
|
956
|
+
hint, but the claim still succeeds by default:
|
|
957
|
+
|
|
958
|
+
```bash
|
|
959
|
+
mu task claim build -w auth-refactor --for worker-2
|
|
960
|
+
# stderr: WARN: worker-2 workspace is 14 commits behind main (≥10 = stale)
|
|
961
|
+
# Next: Refresh first : mu workspace refresh worker-2 -w auth-refactor
|
|
962
|
+
```
|
|
963
|
+
|
|
964
|
+
Pass `--strict-staleness` to refuse the claim instead with typed
|
|
965
|
+
`TaskClaimStaleWorkspaceError` (exit 4). This is useful for scripts
|
|
966
|
+
that should never dispatch work onto a stale parent:
|
|
967
|
+
|
|
968
|
+
```bash
|
|
969
|
+
mu task claim build -w auth-refactor --for worker-2 --strict-staleness
|
|
970
|
+
```
|
|
971
|
+
|
|
972
|
+
`--json` output includes `staleness: null` or `{agentName,
|
|
973
|
+
workstreamName, commitsBehindMain, isStale}`. Bare in-pane claims and
|
|
974
|
+
`--self` claims do not run this check because they do not assign work
|
|
975
|
+
to a named agent via `--for`.
|
|
976
|
+
|
|
717
977
|
### The orchestrator pattern: `--self`
|
|
718
978
|
|
|
719
979
|
Not every action comes from a registered worker pane. Often the
|
|
@@ -723,7 +983,7 @@ a worker pane just for a 5-minute job. Two patterns split here:
|
|
|
723
983
|
|
|
724
984
|
- **Worker** — a pane mu spawned (or you adopted). Has a row in the
|
|
725
985
|
`agents` table. Identity = pane title. Claims with bare
|
|
726
|
-
`mu task claim <id>`. `tasks.
|
|
986
|
+
`mu task claim <id>`. `tasks.owner_id` points at the worker row.
|
|
727
987
|
|
|
728
988
|
- **Actor** — anything that *causes* a state change. Includes
|
|
729
989
|
workers, but also includes the orchestrator. May or may not have
|
|
@@ -745,13 +1005,13 @@ Three actionable next steps. Pick one based on intent:
|
|
|
745
1005
|
```bash
|
|
746
1006
|
# Orchestrator does the work itself (most common):
|
|
747
1007
|
mu task claim some-task --self --evidence "trivial 5-line fix"
|
|
748
|
-
# -> tasks.
|
|
1008
|
+
# -> tasks.owner_id stays NULL
|
|
749
1009
|
# -> agent_logs records 'task claim some-task by pi-mu --self (anonymous)'
|
|
750
1010
|
# -> mu task show surfaces it as 'owner: (self: pi-mu)'
|
|
751
1011
|
|
|
752
1012
|
# Orchestrator dispatches to a worker:
|
|
753
1013
|
mu task claim some-task --for worker-1
|
|
754
|
-
# -> tasks.
|
|
1014
|
+
# -> tasks.owner_id points at worker-1
|
|
755
1015
|
|
|
756
1016
|
# Orchestrator wants to BE a registered worker (rare):
|
|
757
1017
|
mu agent adopt %6441 -w <ws> # only if pane is in mu-<ws> session
|
|
@@ -767,7 +1027,7 @@ to pane title, or `$USER`, or `unknown`):
|
|
|
767
1027
|
mu task claim deploy --self --actor deploy-bot --evidence "prod release"
|
|
768
1028
|
```
|
|
769
1029
|
|
|
770
|
-
When `tasks.
|
|
1030
|
+
When `tasks.owner_id IS NULL` because of `--self`, `mu task show` looks
|
|
771
1031
|
up the most recent `task claim` event for that task and surfaces it:
|
|
772
1032
|
|
|
773
1033
|
```
|
|
@@ -817,7 +1077,12 @@ verb stays useful on un-claimed tasks).
|
|
|
817
1077
|
Or, for ad-hoc shape, the SQL escape hatch:
|
|
818
1078
|
|
|
819
1079
|
```bash
|
|
820
|
-
mu sql "SELECT author, content, created_at
|
|
1080
|
+
mu sql "SELECT n.author, n.content, n.created_at
|
|
1081
|
+
FROM task_notes n
|
|
1082
|
+
JOIN tasks t ON t.id = n.task_id
|
|
1083
|
+
JOIN workstreams w ON w.id = t.workstream_id
|
|
1084
|
+
WHERE t.local_id='design' AND w.name='auth-refactor'
|
|
1085
|
+
ORDER BY n.id"
|
|
821
1086
|
```
|
|
822
1087
|
|
|
823
1088
|
Convention for note content: `KEY: value` lines. Common keys are
|
|
@@ -845,6 +1110,18 @@ task re-enters the ready set (the canonical "hand it back to the
|
|
|
845
1110
|
pool" workflow). `--reopen` is the escape hatch for forcing `OPEN`
|
|
846
1111
|
from `CLOSED` / `REJECTED` / `DEFERRED`.
|
|
847
1112
|
|
|
1113
|
+
When the closing actor has a per-agent workspace and that workspace
|
|
1114
|
+
has uncommitted edits, a successful close adds one extra `Next:` hint
|
|
1115
|
+
reminding the actor to commit before the next wave:
|
|
1116
|
+
|
|
1117
|
+
```bash
|
|
1118
|
+
cd $(mu workspace path worker-1 -w auth-refactor) && git commit -am 'Design auth module'
|
|
1119
|
+
```
|
|
1120
|
+
|
|
1121
|
+
The hint is best-effort: no workspace, a clean workspace, the `none`
|
|
1122
|
+
backend, or a failed VCS dirty check simply omit it. The same
|
|
1123
|
+
`nextSteps` entry is present in `--json` output.
|
|
1124
|
+
|
|
848
1125
|
`--if-ready` is the umbrella-on-wave-done shape: an orchestrator
|
|
849
1126
|
fires `mu task close <umbrella> --if-ready` after each wave-task
|
|
850
1127
|
finishes (or unconditionally as a final action). It's a no-op while
|
|
@@ -936,21 +1213,29 @@ one verify, one workspace recycle:
|
|
|
936
1213
|
# The dispatch-pipeline recipe: cycle until in_flight is empty.
|
|
937
1214
|
in_flight=( mufeedback-v03/foo mufeedback-v03/bar roadmap-v0-3/baz )
|
|
938
1215
|
while (( ${#in_flight[@]} > 0 )); do
|
|
939
|
-
|
|
940
|
-
|
|
1216
|
+
res=$(mu task wait "${in_flight[@]}" --first --timeout 90 --json)
|
|
1217
|
+
closed=$(jq -r '.firing.qualifiedId // empty' <<<"$res")
|
|
941
1218
|
if [[ -z "$closed" ]]; then break; fi # timeout or exit 6 — see below
|
|
942
1219
|
|
|
943
|
-
|
|
944
|
-
# nextSteps array — or use `mu task show` to look up).
|
|
945
|
-
worker=$(mu task show "${closed##*/}" -w "${closed%%/*}" --json | jq -r .ownerName)
|
|
1220
|
+
worker=$(jq -r '.firing.owner // empty' <<<"$res")
|
|
946
1221
|
ws=${closed%%/*}
|
|
947
|
-
|
|
948
|
-
#
|
|
949
|
-
|
|
950
|
-
git cherry-pick
|
|
1222
|
+
|
|
1223
|
+
# 1. Inspect, then run, the sha-pinned apply hint from nextSteps.
|
|
1224
|
+
# When the worker has commits since its fork point, the command is
|
|
1225
|
+
# `git cherry-pick <sha>` (or `<first>^..<last>` for multiple
|
|
1226
|
+
# commits). When the worker closed without committing, nextSteps
|
|
1227
|
+
# says so and points at manual `git diff` / `git apply` rescue.
|
|
1228
|
+
apply=$(jq -r '.nextSteps[0].command' <<<"$res")
|
|
1229
|
+
printf 'apply hint: %s\n' "$apply"
|
|
1230
|
+
if [[ "$apply" == git\ cherry-pick* ]]; then
|
|
1231
|
+
eval "$apply"
|
|
1232
|
+
else
|
|
1233
|
+
echo "manual rescue required; inspect the worker workspace before continuing"
|
|
1234
|
+
break
|
|
1235
|
+
fi
|
|
951
1236
|
|
|
952
1237
|
# 2. Verify
|
|
953
|
-
npm run typecheck && npm run lint && npm run test && npm run build
|
|
1238
|
+
npm run typecheck && npm run lint && npm run test:fast && npm run test && npm run build
|
|
954
1239
|
|
|
955
1240
|
# 3. Refresh the workspace for the next dispatch (rebases onto
|
|
956
1241
|
# fresh main WITHOUT killing the worker's LLM context). Default
|
|
@@ -1058,12 +1343,14 @@ mu sql "UPDATE tasks SET status='IN_PROGRESS'
|
|
|
1058
1343
|
|
|
1059
1344
|
# What's blocking what (open tasks only) — same data as `mu task tree`
|
|
1060
1345
|
# but as a flat join when you want a wider report. task_edges is keyed
|
|
1061
|
-
# by tasks.id, not local_id.
|
|
1346
|
+
# by tasks.id, not local_id; join workstreams to scope the report.
|
|
1062
1347
|
mu sql "SELECT b.local_id AS blocked, t.local_id AS by_task
|
|
1063
1348
|
FROM tasks b
|
|
1349
|
+
JOIN workstreams w ON w.id = b.workstream_id
|
|
1064
1350
|
JOIN task_edges e ON e.to_task_id = b.id
|
|
1065
1351
|
JOIN tasks t ON t.id = e.from_task_id
|
|
1066
|
-
WHERE
|
|
1352
|
+
WHERE w.name='mufeedback-v03'
|
|
1353
|
+
AND t.status != 'CLOSED' AND b.status = 'OPEN'"
|
|
1067
1354
|
|
|
1068
1355
|
# Recursive CTE: every task that transitively blocks `launch` in a
|
|
1069
1356
|
# given workstream (or use `mu task tree launch --json` for the same
|
|
@@ -1348,8 +1635,10 @@ failure leaves the registry intact (you can retry); if you only want
|
|
|
1348
1635
|
the DB cleared, use `mu sql` directly:
|
|
1349
1636
|
|
|
1350
1637
|
```bash
|
|
1351
|
-
mu sql "DELETE FROM tasks
|
|
1352
|
-
|
|
1638
|
+
mu sql "DELETE FROM tasks
|
|
1639
|
+
WHERE workstream_id=(SELECT id FROM workstreams WHERE name='auth-refactor')" # cascades
|
|
1640
|
+
mu sql "DELETE FROM agents
|
|
1641
|
+
WHERE workstream_id=(SELECT id FROM workstreams WHERE name='auth-refactor')"
|
|
1353
1642
|
```
|
|
1354
1643
|
|
|
1355
1644
|
Or nuke the entire DB:
|
|
@@ -1376,7 +1665,7 @@ subdirectory per source workstream:
|
|
|
1376
1665
|
<bucket>/
|
|
1377
1666
|
README.md # bucket-level summary (every source-ws + dates + totals)
|
|
1378
1667
|
INDEX.md # union of all task tables; first column = source-ws
|
|
1379
|
-
manifest.json # bucketVersion: 2
|
|
1668
|
+
manifest.json # bucketVersion: 2, manifest_version: 2, per-source-ws task summaries + sha256s
|
|
1380
1669
|
<source-ws>/
|
|
1381
1670
|
README.md # per-source-ws (counts)
|
|
1382
1671
|
INDEX.md # per-source-ws (table of every task)
|
|
@@ -1386,12 +1675,21 @@ subdirectory per source workstream:
|
|
|
1386
1675
|
Bucket exports are **additive**: `mu workstream export -w X --out
|
|
1387
1676
|
<bucket>` creates the bucket scaffolding plus `X/` on first use,
|
|
1388
1677
|
and a follow-up call with `-w Y --out <same-bucket>` appends a
|
|
1389
|
-
sibling `Y/` subdirectory without touching `X/`.
|
|
1678
|
+
sibling `Y/` subdirectory without touching `X/`. The top-level
|
|
1679
|
+
`INDEX.md` is always the union from `manifest.sources`, so a later
|
|
1680
|
+
single-workstream refresh does not drop sibling workstreams from the
|
|
1681
|
+
bucket-wide task table. Re-running with
|
|
1390
1682
|
the same `-w` is sha256-idempotent: only changed task files are
|
|
1391
1683
|
rewritten (mtime preserved on identical files); tasks added since
|
|
1392
1684
|
the previous export get fresh files; tasks deleted from the DB
|
|
1393
1685
|
STAY on disk with a `> **Deleted from DB on <ts>**` banner so you
|
|
1394
|
-
never lose context that may already be git-blamed.
|
|
1686
|
+
never lose context that may already be git-blamed. `manifest_version:
|
|
1687
|
+
2` stores compact task summaries (`name`/`title`/`status`/`impact`/
|
|
1688
|
+
`effortDays`) beside the per-file sha256s; older v1 manifests are
|
|
1689
|
+
accepted on re-export; mu infers the missing summaries from existing
|
|
1690
|
+
per-task markdown when possible, falling back to placeholder values
|
|
1691
|
+
only if a task file is missing or unreadable, so the bucket remains
|
|
1692
|
+
appendable.
|
|
1395
1693
|
|
|
1396
1694
|
```bash
|
|
1397
1695
|
# One-shot dump (bucket happens to contain just one source-ws)
|
|
@@ -1465,7 +1763,7 @@ Key properties:
|
|
|
1465
1763
|
imported in its own SQLite transaction. A failure in source A
|
|
1466
1764
|
rolls back A; sibling source B is unaffected.
|
|
1467
1765
|
- **Refuses silent merges.** If the target workstream already
|
|
1468
|
-
exists in the DB
|
|
1766
|
+
exists in the DB, the import errors with
|
|
1469
1767
|
`WorkstreamAlreadyExistsError`. Recourse:
|
|
1470
1768
|
`--workstream <new-name>` (single-source buckets only) or
|
|
1471
1769
|
destroy the existing workstream first.
|
|
@@ -1526,12 +1824,16 @@ Key properties:
|
|
|
1526
1824
|
- **Globally-unique labels.** Archive labels live in their own
|
|
1527
1825
|
namespace (separate from workstream names). Pick once, reuse
|
|
1528
1826
|
across years.
|
|
1529
|
-
- **
|
|
1530
|
-
idempotent at the (archive, source workstream) granularity
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1827
|
+
- **Snapshot-only accumulation.** `mu archive add <label> -w <ws>` is
|
|
1828
|
+
idempotent at the (archive, source workstream) granularity and is
|
|
1829
|
+
designed for end-of-milestone snapshot-and-destroy flows. Re-running
|
|
1830
|
+
on the same workstream is task-incremental: newly-created tasks are
|
|
1831
|
+
added, but notes and events for already-archived tasks stay pinned
|
|
1832
|
+
to the original snapshot and are NOT refreshed. If you need a full
|
|
1833
|
+
event-stream refresh for a source workstream, remove that source (or
|
|
1834
|
+
delete/re-create the archive label) and add it again. Two different
|
|
1835
|
+
workstreams under the same label coexist as separate
|
|
1836
|
+
`(source_workstream, original_local_id)` rows.
|
|
1535
1837
|
- **Outlives the source.** `archived_tasks.source_workstream` is
|
|
1536
1838
|
TEXT (not an FK), so the source workstream can be destroyed and
|
|
1537
1839
|
the archive's snapshot of it stays queryable forever.
|
|
@@ -1611,8 +1913,8 @@ mu agent spawn worker-1 --workstream demo --cli sh
|
|
|
1611
1913
|
mu agent spawn worker-2 --workstream demo --cli sh
|
|
1612
1914
|
|
|
1613
1915
|
# Assign + observe
|
|
1614
|
-
mu
|
|
1615
|
-
mu
|
|
1916
|
+
mu task claim design -w demo --for worker-1 --evidence "demo assignment"
|
|
1917
|
+
mu state -w demo
|
|
1616
1918
|
|
|
1617
1919
|
# Watch live (Ctrl+b d to detach)
|
|
1618
1920
|
tmux attach -t mu-demo
|
|
@@ -1638,8 +1940,8 @@ rm -f ~/.local/state/mu/mu.db
|
|
|
1638
1940
|
shared deps.
|
|
1639
1941
|
|
|
1640
1942
|
3. **Agents claim tasks via their pane title — zero config.**
|
|
1641
|
-
`mu task claim foo` from inside `worker-1`'s pane sets
|
|
1642
|
-
atomically. mu reads the pane title via
|
|
1943
|
+
`mu task claim foo` from inside `worker-1`'s pane sets the task's
|
|
1944
|
+
`owner_id` to the `worker-1` agent row atomically. mu reads the pane title via
|
|
1643
1945
|
`tmux display-message -t $TMUX_PANE -p '#{pane_title}'`, set on
|
|
1644
1946
|
spawn. Two agents cannot claim the same task.
|
|
1645
1947
|
|
|
@@ -1649,9 +1951,9 @@ service of those three.
|
|
|
1649
1951
|
|
|
1650
1952
|
---
|
|
1651
1953
|
|
|
1652
|
-
## What's NOT in 0.
|
|
1954
|
+
## What's NOT in 0.4.0 (and how to work around it)
|
|
1653
1955
|
|
|
1654
|
-
<a id="whats-not-in-
|
|
1956
|
+
<a id="whats-not-in-040-and-how-to-work-around-it"></a>
|
|
1655
1957
|
|
|
1656
1958
|
The full roadmap with promotion criteria lives in
|
|
1657
1959
|
[ROADMAP.md](ROADMAP.md). The short list of gaps you might hit
|
|
@@ -1660,13 +1962,13 @@ in real use:
|
|
|
1660
1962
|
| Want | Workaround | Status |
|
|
1661
1963
|
| --------------------------------------------- | ----------------------------------------------------------------------- | ------------- |
|
|
1662
1964
|
| Multi-CLI status detection (per-CLI prompts) | Braille spinner fallback (`f68838f`) covers pi/pi-meta + every TUI wrapper using standard spinner glyphs. Per-CLI permission-prompt patterns still pi-only. | partially shipped |
|
|
1663
|
-
| Pi extension (typed tools, HUD, wakeups) | `mu state --
|
|
1965
|
+
| Pi extension (typed tools, HUD, wakeups) | `mu state --tui` (interactive) covers the dashboard use-case; plain `mu state` (static) is the `watch` / `tmux display-popup` / `status-right` substrate. Other extension tools deferred. | partially shipped |
|
|
1664
1966
|
| Markdown agent-definition discovery | Spawn accepts `--cli` and `--command` directly; no template registry | dropped |
|
|
1665
1967
|
| `mu run script.ts` (JS DSL) | Use `--json` + bash + jq | rejected |
|
|
1666
1968
|
| Sync to GitHub Issues / Linear / Asana | Not in scope; explicitly rejected | — |
|
|
1667
|
-
| ~~`mu task blocked`~~ (removed; the `blocked` SQL view is the abstraction) | `mu sql "SELECT local_id, status, title FROM blocked WHERE
|
|
1668
|
-
| ~~`mu task goals`~~ (removed; same shape as `blocked` — view is the abstraction) | `mu sql "SELECT local_id, status, title FROM goals WHERE
|
|
1669
|
-
| ~~`mu task search <pat>`~~ (removed; case-insensitive LIKE is one SQL line) | `mu sql "SELECT local_id, status, title FROM tasks WHERE
|
|
1969
|
+
| ~~`mu task blocked`~~ (removed; the `blocked` SQL view is the abstraction) | `mu sql "SELECT b.local_id, b.status, b.title FROM blocked b JOIN workstreams w ON w.id=b.workstream_id WHERE w.name='X'"` | removed-with-recipe |
|
|
1970
|
+
| ~~`mu task goals`~~ (removed; same shape as `blocked` — view is the abstraction) | `mu sql "SELECT g.local_id, g.status, g.title FROM goals g JOIN workstreams w ON w.id=g.workstream_id WHERE w.name='X'"` | removed-with-recipe |
|
|
1971
|
+
| ~~`mu task search <pat>`~~ (removed; case-insensitive LIKE is one SQL line) | `mu sql "SELECT t.local_id, t.status, t.title FROM tasks t JOIN workstreams w ON w.id=t.workstream_id WHERE w.name='X' AND LOWER(t.title) LIKE '%pat%'"` (add `LEFT JOIN task_notes` for the old `--in-notes`; drop the workstream join/filter for the old `--all`) | removed-with-recipe |
|
|
1670
1972
|
|
|
1671
1973
|
Anything in this table that bites you in real use is a candidate
|
|
1672
1974
|
for **promotion**. Criteria: proven friction in ≥2 real workflows +
|