@mu-crew/mu 3.9.0 → 3.10.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.
@@ -0,0 +1,16 @@
1
+ import {
2
+ ambientSyncPass,
3
+ openDb
4
+ } from "./chunk-YIF3X32A.js";
5
+ import "./chunk-4PACTXAB.js";
6
+ import "./chunk-PZ5AY32C.js";
7
+
8
+ // src/cli/tui/sync-worker.ts
9
+ import { parentPort, workerData } from "worker_threads";
10
+ var port = parentPort;
11
+ if (port === null) throw new Error("tui-sync-worker must run as a worker_thread");
12
+ var db = openDb({ path: workerData.dbPath });
13
+ port.on("message", () => {
14
+ void ambientSyncPass(db, { quiet: true }).catch(() => null).then((result) => port.postMessage(result));
15
+ });
16
+ //# sourceMappingURL=tui-sync-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/tui/sync-worker.ts"],"sourcesContent":["// worker_thread entry for the TUI's ambient sync pass (built to\n// dist/tui-sync-worker.js). ingest and flush are synchronous SQLite and\n// file work (seconds on a first read, hundreds of ms per peer append on\n// a 40 MB segment), so on ink's thread they froze input and repaints.\n// Here they block only this thread. The worker owns its own connection\n// to the same DB file: WAL serves the TUI's reads meanwhile, and the\n// TUI sees the result on its next read.\n//\n// Protocol: the parent posts any message to start one pass, and the\n// worker replies with the pass's result (`null` if it threw) when the\n// pass is over. ambientSyncPass is total, and `quiet` keeps stderr off\n// the alternate screen.\n\nimport { parentPort, workerData } from \"node:worker_threads\";\nimport { openDb } from \"../../db.js\";\nimport { ambientSyncPass } from \"../../sync.js\";\n\nconst port = parentPort;\nif (port === null) throw new Error(\"tui-sync-worker must run as a worker_thread\");\nconst db = openDb({ path: (workerData as { dbPath: string }).dbPath });\nport.on(\"message\", () => {\n void ambientSyncPass(db, { quiet: true })\n .catch(() => null)\n .then((result) => port.postMessage(result));\n});\n"],"mappings":";;;;;;;;AAaA,SAAS,YAAY,kBAAkB;AAIvC,IAAM,OAAO;AACb,IAAI,SAAS,KAAM,OAAM,IAAI,MAAM,6CAA6C;AAChF,IAAM,KAAK,OAAO,EAAE,MAAO,WAAkC,OAAO,CAAC;AACrE,KAAK,GAAG,WAAW,MAAM;AACvB,OAAK,gBAAgB,IAAI,EAAE,OAAO,KAAK,CAAC,EACrC,MAAM,MAAM,IAAI,EAChB,KAAK,CAAC,WAAW,KAAK,YAAY,MAAM,CAAC;AAC9C,CAAC;","names":[]}
@@ -0,0 +1,12 @@
1
+ import {
2
+ osc52Sequence,
3
+ probeClipboardBackend,
4
+ yank
5
+ } from "./chunk-77GBZ2KR.js";
6
+ import "./chunk-PZ5AY32C.js";
7
+ export {
8
+ osc52Sequence,
9
+ probeClipboardBackend,
10
+ yank
11
+ };
12
+ //# sourceMappingURL=yank-T3AYQTVR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -88,7 +88,7 @@ hub that re-exports them. `src/tasks.ts`, `src/agents.ts`, `src/mux.ts`,
88
88
 
89
89
  | Module | Responsibility |
90
90
  | --- | --- |
91
- | `src/db.ts` | better-sqlite3 connection (WAL); schema v11 (11 tables, 3 views) in `applySchema`; installs capture; owns `SYNCED_ENTITIES`, `PORTABLE_TABLES`, `MACHINE_LOCAL_TABLES`; refuses older (`SchemaTooOldError`) or newer (`SchemaTooNewError`) DBs, exit 4 |
91
+ | `src/db.ts` | better-sqlite3 connection (WAL); schema v11 (12 tables, 3 views) in `applySchema`; installs capture; owns `SYNCED_ENTITIES`, `PORTABLE_TABLES`, `MACHINE_LOCAL_TABLES`; refuses older (`SchemaTooOldError`) or newer (`SchemaTooNewError`) DBs, exit 4 |
92
92
  | `src/hlc.ts` | hybrid logical clock, serialized as sortable TEXT |
93
93
  | `src/capture.ts` | TEMP triggers recording each portable write as an op, and refusing natural-key changes |
94
94
  | `src/op-context.ts` | `withOpContext` (intent, actor, group); `withCaptureSuppressed` echo guard |
@@ -106,6 +106,8 @@ hub that re-exports them. `src/tasks.ts`, `src/agents.ts`, `src/mux.ts`,
106
106
  | Module | Responsibility |
107
107
  | --- | --- |
108
108
  | `src/segments.ts` | JSONL segments: flush own ops, ingest peers from a watermark |
109
+ | `src/segment-manifest.ts` | segment `.manifest` sidecar: read, write, seal, and the self-consistency check the owner's flush runs before trusting it |
110
+ | `src/sha256-resumable.ts` | SHA-256 with a serialisable running state, so the segment manifest hashes only appended bytes |
109
111
  | `src/sync.ts` | peer status, the ambient hook, `--from`, `--repair` |
110
112
  | `src/file-lock.ts` | cross-process advisory lock through atomic `fs.mkdir` |
111
113
  | `src/fleet-hazards.ts` | mixed-fleet checks: DB inside `MU_SYNC_DIR`, network mount, case collisions |
@@ -141,7 +143,7 @@ hub that re-exports them. `src/tasks.ts`, `src/agents.ts`, `src/mux.ts`,
141
143
  | `src/ctl/client.ts` | `ctlRequest`, `ctlProbe`, version and unknown-op errors |
142
144
  | `extension/mu-pi.ts` | pi extension, child side: serves `$MU_CTL_SOCK`; built to `dist/extension/mu-pi.js` |
143
145
  | `extension/delegate.ts` | pi extension, parent side: `mu_delegate` / `mu_delegate_cancel`, which shell out to `mu` |
144
- | `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`. Also the close nudge (worker settles owning a task) and the refute nudge (`task claim --for` on a task with no refute decision in `mu task notes --json`; one notice, no continuation) |
146
+ | `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`. Also the close nudge (worker settles owning a task) and the refute nudge (`task claim --for` on a task with no refute decision in `mu task notes --json`; one notice, no continuation). `parallelSettle` runs the three settle checks in parallel behind one `agent_before_settle` handler and merges their entries; `mu log` breadcrumbs are not awaited |
145
147
  | `src/link.ts` | `mu link pi`: extension shim, skill symlink, `inspectLinks` for doctor |
146
148
 
147
149
  ### Tasks, workspaces and workstreams
@@ -167,14 +169,18 @@ hub that re-exports them. `src/tasks.ts`, `src/agents.ts`, `src/mux.ts`,
167
169
 
168
170
  | Module | Responsibility |
169
171
  | --- | --- |
170
- | `src/cli.ts` | Commander wiring (`buildProgram`) |
172
+ | `src/main.ts` | the `mu` bin (`dist/cli.js`): enables the compile cache, then `import()`s `src/cli.ts` |
173
+ | `src/compile-cache.ts`, `src/state-dir.ts` | best-effort V8 compile cache under `<state>/compile-cache`; builtins-only state-dir resolution |
174
+ | `src/cli.ts` | Commander wiring (`buildProgram`, `runCli`) |
171
175
  | `src/cli/*.ts` | one file per verb namespace, thin wrappers over the SDK; `format.ts` renders tables, `handle.ts` maps errors to exit codes and runs ambient sync |
172
176
  | `src/cli/tasks/*.ts` | the `mu task` namespace, including `mu me tasks` / `mu me next` |
173
177
  | `src/cli/dispatch-hints.ts` | dispatch-time `Next:` hints for pi agents (`--fresh`, `--interrupt`, abort) |
174
178
  | `src/cli/stdin.ts` | `-` as a text argument: reads note / send text from stdin (heredoc prose) |
175
179
  | `src/cli/agents-remote.ts` | `mu agent remote-env`: prints the ssh forward and env, runs nothing |
176
180
  | `src/cli/tui-launch-focus.ts` | initial-tab focus ladder for bare `mu` and `mu state --tui` |
181
+ | `src/cli/tui-load.ts` | lazy `import()` of the TUI with `NODE_ENV` defaulted to `production` (React prod build) |
177
182
  | `src/cli/tui/` | the ink TUI; the only place ink and react are imported |
183
+ | `src/cli/tui/sync-worker.ts` | worker_thread (`dist/tui-sync-worker.js`) running the TUI's slow-tick sync pass off ink's thread |
178
184
  | `src/output.ts`, `src/shell-quote.ts` | `printNextSteps` / `errorNextSteps`; POSIX quoting for hints |
179
185
  | `src/glyphs.ts` | the one glyph vocabulary (single-cell Nerd Font codepoints) |
180
186
  | `src/index.ts` | SDK entry point |
@@ -132,7 +132,11 @@ probes `refused`, and `mu agent close` or the reaper deletes it.
132
132
  when `MU_MANAGED_AGENT` is set (inside a mu-spawned pane) or
133
133
  `MU_DELEGATE=0`. The tools shell out to the `mu` CLI (spawn, send,
134
134
  `wait --json`, read, abort, close) and only format the CLI's
135
- `outcome` into a follow-up message. `delegateOutcome`
135
+ `outcome` into a follow-up message. A call runs one
136
+ `mu agent spawn --next-free --send <task> --json` (mu picks the free
137
+ name under its spawn lock and returns the send's `runs`), then one
138
+ `mu agent wait --after-runs <runs>` in the background; with `record`,
139
+ a `mu task show` comes first. `delegateOutcome`
136
140
  (`src/agents/delegate.ts`) maps one wait result to `done`, `empty`,
137
141
  `error`, `died`, `timeout` or `pending`. The extension imports nothing from pi;
138
142
  it types pi's API structurally.
@@ -15,7 +15,12 @@ Litestream, cr-sqlite or a peer list, and why the DB must never sit in
15
15
  - `flushSegment` appends this machine's unflushed ops to
16
16
  `<MU_SYNC_DIR>/<machine_id>.jsonl`.
17
17
  - `ingestSegment` reads a peer segment from its watermark into
18
- `applyOp`.
18
+ `applyOp`. Ambient ingest skips a peer that is caught up: the manifest
19
+ counts the watermark, and the segment's size, exact mtime and
20
+ manifest sha256 equal what the last clean read to the end recorded
21
+ (in `sync_fingerprints`). Any change, including a rewrite with a
22
+ backdated mtime, fails that check, so the full read hashes the file
23
+ and reports the mismatch. `mu sync` always reads every line.
19
24
  - Peer discovery is implicit: every non-self `*.jsonl` is a peer. A
20
25
  peer disappears only when its segment is deleted.
21
26
  - A Syncthing conflict copy (`<machine>.sync-conflict-….jsonl`) is
@@ -25,7 +30,11 @@ Litestream, cr-sqlite or a peer list, and why the DB must never sit in
25
30
  **Single writer per file.** A machine appends only to its own segment,
26
31
  so nothing is contended and any folder syncer is adequate. Segments
27
32
  are regenerable, so there is no fsync. `src/file-lock.ts` stops two
28
- local `mu` processes from interleaving partial lines.
33
+ local `mu` processes from interleaving partial lines. A flush never
34
+ appends without that lock: if another process still holds it after
35
+ 2 s (15 s for `mu sync`), the flush writes nothing, the ops stay
36
+ pending in `ops`, and the next invocation appends them. A stale lock
37
+ (holder crashed, older than 30 s) is broken as before.
29
38
 
30
39
  **Only `SYNCED_ENTITIES` and only this machine's ops are flushed.**
31
40
  Pane ids and absolute paths never leave the machine, and peers never
@@ -118,8 +127,13 @@ edge puts that are resolvable now but unprojected. It skips ops whose
118
127
  parent task is gone and keys with a newer `del`, so a deleted edge is
119
128
  never resurrected and an orphan is not retried forever. It runs once
120
129
  per ingest pass, not per peer, because an edge in one segment may name
121
- a task in another. On a healthy DB it is two indexed queries returning
122
- zero rows.
130
+ a task in another. Ambient ingest runs it only while SQLite's
131
+ `user_version` is 1. `applyIncomingOp` sets that marker in the same
132
+ transaction whenever an op changes a row or defers (`absent`), whether
133
+ it came from a segment, `--from`, or an SDK caller; the repair clears
134
+ it. A process that dies between
135
+ the two leaves the marker set, so the next invocation runs the repair.
136
+ `mu sync` and `--from` always run it.
123
137
 
124
138
  There is no retry queue. A queue would be a second source of truth and
125
139
  would not survive a short-lived `mu` process when the parent arrives
@@ -58,6 +58,10 @@ socket. Pick the mode by what the agent is doing:
58
58
  pastes nothing. `--via mux` pastes into the pane on purpose.
59
59
 
60
60
  After a claim, spawn, or wait, the `Next:` block prints the right send.
61
+ `mu agent spawn --send <text>` spawns and sends the first prompt in one
62
+ call; `--next-free` takes the next free name when `<name>` is taken
63
+ (`worker-1` → `worker-2`; the stem is cut to keep the name within 32
64
+ chars, and it gives up with exit 4 when no free name is near).
61
65
 
62
66
  ### Non-pi agents
63
67
 
package/docs/guide/sql.md CHANGED
@@ -25,7 +25,7 @@ FAIL-row failure, `6` reaped pane, `7` stall.
25
25
 
26
26
  ## Read the schema
27
27
 
28
- The schema has 11 tables and 3 views (`ready`, `blocked`, `goals`).
28
+ The schema has 12 tables and 3 views (`ready`, `blocked`, `goals`).
29
29
  Four tables travel between machines: `workstreams`, `tasks`,
30
30
  `task_edges`, and `task_notes`. List them all:
31
31
 
@@ -10,7 +10,7 @@ milliseconds; `0` disables a wait unless noted.
10
10
  | Name | Effect | Default |
11
11
  | --- | --- | --- |
12
12
  | `MU_DB_PATH` | SQLite file path. Wins over the state dir. | `<state-dir>/mu.db` |
13
- | `MU_STATE_DIR` | State directory. | `$XDG_STATE_HOME/mu` |
13
+ | `MU_STATE_DIR` | State directory. Also holds `compile-cache/` (V8 code cache for the CLI; `NODE_DISABLE_COMPILE_CACHE=1` turns it off). | `$XDG_STATE_HOME/mu` |
14
14
  | `XDG_STATE_HOME` | XDG state base; mu appends `mu/`. An empty or relative value is ignored. | `~/.local/state` |
15
15
  | `MU_SESSION` | Active workstream when `-w` is absent. | current `mu-<name>` mux session |
16
16
  | `MU_SYNC_DIR` | Folder holding one segment per machine. This is the whole sync setup; there is no peer list. | unset: sync off |
@@ -86,6 +86,7 @@ pi agent's `--command`. mu never reads them back.
86
86
  | `MU_FORCE_COLOR` | Truthy forces colour on. `""`, `0`, and `false` opt out. Checked before `FORCE_COLOR`. | unset |
87
87
  | `MU_NO_TUI` | `1` makes bare `mu` print help instead of opening the TUI. | unset |
88
88
  | `MU_TUI_DEBUG_MOUSE` | `1` logs mouse hit-tests to stderr. | unset |
89
+ | `NODE_ENV` | Unset: the TUI loads React's production build. Set it (e.g. `development`) to get React's dev build and warnings. | unset |
89
90
 
90
91
  ## Tests
91
92
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mu-crew/mu",
3
- "version": "3.9.0",
3
+ "version": "3.10.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"