@mu-crew/mu 3.8.0 → 3.9.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/dist/index.d.ts CHANGED
@@ -100,7 +100,7 @@ interface OpenDbOptions {
100
100
  }
101
101
  /**
102
102
  * Resolve the canonical mu state directory:
103
- * MU_STATE_DIR > $XDG_STATE_HOME/mu > ~/.local/state/mu
103
+ * MU_STATE_DIR > $XDG_STATE_HOME/mu (absolute only) > ~/.local/state/mu
104
104
  */
105
105
  declare function defaultStateDir(): string;
106
106
  /**
@@ -114,6 +114,12 @@ declare function defaultDbPath(): string;
114
114
  * concurrently — WAL mode handles cross-process writes.
115
115
  */
116
116
  declare function openDb(options?: OpenDbOptions): Db;
117
+ declare class WorkstreamNotFoundError extends Error implements HasNextSteps {
118
+ readonly workstream: string;
119
+ readonly name = "WorkstreamNotFoundError";
120
+ constructor(workstream: string);
121
+ errorNextSteps(): NextStep[];
122
+ }
117
123
  /**
118
124
  * Thrown by openDb when the on-disk DB is older than the current
119
125
  * schema. There is no in-place migration ladder; the old DB is left
@@ -126,6 +132,17 @@ declare class SchemaTooOldError extends Error implements HasNextSteps {
126
132
  constructor(detectedVersion: number, requiredVersion: number);
127
133
  errorNextSteps(): NextStep[];
128
134
  }
135
+ /**
136
+ * Thrown by openDb when the on-disk DB was written by a NEWER mu.
137
+ * The DB is left untouched. Maps to exit code 4 (conflict).
138
+ */
139
+ declare class SchemaTooNewError extends Error implements HasNextSteps {
140
+ readonly detectedVersion: number;
141
+ readonly supportedVersion: number;
142
+ readonly name = "SchemaTooNewError";
143
+ constructor(detectedVersion: number, supportedVersion: number);
144
+ errorNextSteps(): NextStep[];
145
+ }
129
146
  /** The schema version a fresh DB starts at. v11 adds tasks.substate
130
147
  * and the task_substates lookup table on top of v10's three-state
131
148
  * lifecycle (OPEN, IN_PROGRESS, CLOSED). See CHANGELOG.md. */
@@ -139,7 +156,7 @@ declare const EXPECTED_TABLES: readonly string[];
139
156
  * Readonly tuple (not `string[]`) so `SyncedEntity` is a real union
140
157
  * and downstream code gets compile-time checking, not raw strings. */
141
158
  declare const SYNCED_ENTITIES: readonly ["workstream", "task", "edge", "note", "message"];
142
- /** One of the six op entities that sync. Derived from the tuple, so
159
+ /** One of the op entities that sync. Derived from the tuple, so
143
160
  * adding an entity is a one-line change with no type to keep in step. */
144
161
  type SyncedEntity = (typeof SYNCED_ENTITIES)[number];
145
162
  /** Op entities this build KNOWS are machine-local: their payloads name
@@ -466,9 +483,9 @@ interface MuxBackend {
466
483
  enableMuPaneBordersForSession(session: string): Promise<number>;
467
484
  enableMuPaneBordersForPane(paneId: string): Promise<void>;
468
485
  /** Copy-pasteable shell line that lands the user on `target`. */
469
- attachHint(target: AttachTarget): string;
486
+ attachHint(target: AttachTarget): string | Promise<string>;
470
487
  /** The same attach, as argv steps to spawn in order. */
471
- attachCommands(target: AttachTarget): readonly MuxCommand[];
488
+ attachCommands(target: AttachTarget): readonly MuxCommand[] | Promise<readonly MuxCommand[]>;
472
489
  /** Backend-specific `PaneNotFoundError` remediation. */
473
490
  paneNotFoundNextSteps(paneId: string): NextStep[];
474
491
  /** Version + ambient facts for `mu doctor`. Never throws: an
@@ -632,11 +649,12 @@ declare class HerdrWorkspaceGroupCloseError extends Error {
632
649
  constructor(session: string, workspaceId: string, detail: string);
633
650
  errorNextSteps(): NextStep[];
634
651
  }
635
- /** A `MuxBackend` method whose herdr implementation is owned by another
636
- * task. Never thrown on any path mu currently drives on herdr. */
652
+ /** A creation verb was handed a command to run. herdr cannot do that
653
+ * in one step (see `rejectCommand`), so this is a bug in the caller:
654
+ * spawn passes no command on herdr and calls `startAgentInPane`. */
637
655
  declare class HerdrNotImplementedError extends Error {
638
656
  readonly name = "HerdrNotImplementedError";
639
- constructor(method: string, owner: string);
657
+ constructor(method: string);
640
658
  }
641
659
  interface HerdrExecResult {
642
660
  stdout: string;
@@ -762,7 +780,8 @@ declare function newSessionWithPane(name: string, opts: NewSessionWithPaneOption
762
780
  * Four swallowed shapes:
763
781
  * - "can't find session: <name>" — session never existed.
764
782
  * - "session not found" — alternate phrasing on some tmux builds.
765
- * - "no server running on <path>" — the tmux server itself has exited
783
+ * - "no server running on <path>" (or "error connecting to <path> (No
784
+ * such file or directory)", see NO_SERVER_RE) — the tmux server itself has exited
766
785
  * (typical when the test suite runs against a private `tmux -L
767
786
  * <socket>` server and the just-killed session was its last; tmux
768
787
  * quietly shuts the server down). Without this, killSession would
@@ -922,7 +941,10 @@ declare function defaultSendReadinessMs(): number;
922
941
  declare function hasWorkMarker(scrollback: string): boolean;
923
942
  /**
924
943
  * Block until the pane is ready to ACCEPT input, or the budget expires.
925
- * Returns true if the pane quiesced, false on timeout.
944
+ * Returns true if the pane quiesced, false on timeout. Throws the
945
+ * capture's TmuxError at once when the pane or the server is gone:
946
+ * a dead pane never quiesces, so polling it would only burn the whole
947
+ * budget before the send fails anyway.
926
948
  *
927
949
  * WHY THIS EXISTS (dogfood_send_after_new_dropped, reproduced 3/6 at
928
950
  * sleep=0.3s and 1/5 at sleep=2s against a real pi pane):
@@ -999,7 +1021,12 @@ declare function sendToPane(paneId: string, text: string, opts?: SendOptions): P
999
1021
  *
1000
1022
  * - No options: full scrollback (`-S - -E -`)
1001
1023
  * - `lines: 0`: visible pane only
1002
- * - `lines: N`: last N lines (`-S -N`)
1024
+ * - `lines: N`: last N lines, ending at the last non-blank row
1025
+ *
1026
+ * `-S -N` counts from the TOP of the visible screen, so tmux returns the
1027
+ * N rows above the screen plus every visible row, blank rows below the
1028
+ * cursor included. That range always holds the last N non-blank-ended
1029
+ * lines, so drop the trailing blank rows and keep the last N.
1003
1030
  */
1004
1031
  declare function capturePane(paneId: string, opts?: CaptureOptions): Promise<string>;
1005
1032
  declare function attachHint(target: AttachTarget): string;
@@ -1011,12 +1038,18 @@ declare function paneNotFoundNextSteps(paneId: string): NextStep[];
1011
1038
  * reporting different env vars needs no doctor change.
1012
1039
  */
1013
1040
  declare function healthCheck(): Promise<MuxHealth>;
1041
+ /** `MuxBackend` with tmux's synchronous attach methods: SDK callers of
1042
+ * `tmuxBackend.attachHint()` keep getting a string, not a Promise. */
1043
+ interface TmuxBackend extends MuxBackend {
1044
+ attachHint(target: AttachTarget): string;
1045
+ attachCommands(target: AttachTarget): readonly MuxCommand[];
1046
+ }
1014
1047
  /**
1015
1048
  * The tmux implementation of `MuxBackend`. A frozen record of the
1016
1049
  * module's functions — no state of its own, so swapping backends is a
1017
1050
  * pointer assignment (see ./detect.ts).
1018
1051
  */
1019
- declare const tmuxBackend: MuxBackend;
1052
+ declare const tmuxBackend: TmuxBackend;
1020
1053
 
1021
1054
  type mux_AttachTarget = AttachTarget;
1022
1055
  type mux_CaptureOptions = CaptureOptions;
@@ -1075,17 +1108,14 @@ declare namespace mux {
1075
1108
  * "full" Default for `mu state` and `mu agent list`. Prunes
1076
1109
  * ghosts (deleting the registry row, which fires the
1077
1110
  * deleteAgent reaper that flips IN_PROGRESS tasks back
1078
- * to OPEN with [reaper] notes), runs status detection
1079
- * against surviving panes, surfaces orphans.
1111
+ * to OPEN with [reaper] notes), refreshes pane titles
1112
+ * of surviving agents, surfaces orphans.
1080
1113
  *
1081
1114
  * "report-only" Pure observation. Counts would-be-pruned ghosts
1082
- * without deleting; skips status detection entirely
1083
- * (no DB writes, no tmux title writes); surfaces
1084
- * orphans (pure read). Used by `mu undo` (the
1085
- * post-restore pass MUST NOT delete rows the snapshot
1086
- * just restored — see
1087
- * snap_undo_reconcile_destroys_recovered_agents) and
1088
- * `mu doctor` (read-only diagnostic).
1115
+ * without deleting; skips the title refresh (no DB
1116
+ * writes, no tmux title writes); surfaces orphans
1117
+ * (pure read). Used by `mu doctor` (read-only
1118
+ * diagnostic).
1089
1119
  *
1090
1120
  * Mid-spawn placeholders are protected directly in the prune loop, so read
1091
1121
  * paths no longer need a separate mode just to avoid racing spawn's workspace
@@ -1175,6 +1205,14 @@ interface RebaseResult {
1175
1205
  * resolveGitMainRef() symbolic ref; for jj/sl it's the literal
1176
1206
  * `trunk()` revset (or whatever the operator passed via fromRef). */
1177
1207
  fromRef: string;
1208
+ /** Concrete commit id of the workspace's new fork point: fromRef's
1209
+ * commit, or the previous fork point when that already descends from
1210
+ * it (parent_ref never moves backward). The caller writes it to
1211
+ * `vcs_workspaces.parent_ref` so staleness, `mu workspace commits`
1212
+ * and the close-time clean check measure from the new base. Omitted
1213
+ * when the backend cannot resolve a single commit (e.g. a jj revset
1214
+ * naming several); the caller then keeps the old value. */
1215
+ parentRef?: string;
1178
1216
  /** Commit subjects (or descriptions) that got replayed, oldest-first.
1179
1217
  * Empty when the workspace was already at fromRef (no-op). */
1180
1218
  replayed: string[];
@@ -1206,6 +1244,56 @@ interface ShowCommitResult {
1206
1244
  /** Human-readable error message; omitted on success. */
1207
1245
  error?: string;
1208
1246
  }
1247
+ /**
1248
+ * Thrown by `rebaseTo` / `commitsSinceBase` on the `none` backend
1249
+ * (cp -a snapshots have no notion of a rebase target / fork point).
1250
+ * Maps to exit code 4.
1251
+ */
1252
+ declare class WorkspaceVcsRequiredError extends Error implements HasNextSteps {
1253
+ readonly verb: string;
1254
+ readonly workspacePath: string;
1255
+ readonly name = "WorkspaceVcsRequiredError";
1256
+ constructor(verb: string, workspacePath: string);
1257
+ errorNextSteps(): NextStep[];
1258
+ }
1259
+ /**
1260
+ * Thrown by `rebaseTo` when the workspace has uncommitted changes
1261
+ * the rebase would clobber. Carries the dirty file list so the operator
1262
+ * can decide between commit/stash/--force. Maps to exit code 4.
1263
+ */
1264
+ declare class WorkspaceDirtyError extends Error implements HasNextSteps {
1265
+ readonly workspacePath: string;
1266
+ readonly files: readonly string[];
1267
+ readonly name = "WorkspaceDirtyError";
1268
+ /** The verb that refused. Only `rebaseTo` refuses this way today,
1269
+ * but the field keeps the message + nextSteps self-describing. */
1270
+ readonly verb: string;
1271
+ constructor(workspacePath: string, files: readonly string[], verb?: string);
1272
+ errorNextSteps(): NextStep[];
1273
+ }
1274
+ /**
1275
+ * Thrown by `rebaseTo` when the rebase produced conflicts. Carries the
1276
+ * conflicting paths (git/sl) or commits (jj). Maps to exit code 5.
1277
+ *
1278
+ * git and sl abort the rebase before throwing, so the workspace is back
1279
+ * at its pre-rebase state (`aborted` is true). jj cannot abort: the
1280
+ * rebase is done and the conflicts are committed in place (`aborted` is
1281
+ * false). Either way the row's parent_ref is unchanged, so the hint
1282
+ * ends with re-running refresh: once the conflicts are resolved, that
1283
+ * rebase is clean and records the base the disk is on.
1284
+ */
1285
+ declare class WorkspaceConflictError extends Error implements HasNextSteps {
1286
+ readonly workspacePath: string;
1287
+ readonly fromRef: string;
1288
+ readonly conflicts: readonly string[];
1289
+ /** True when the backend aborted the rebase and the workspace is unchanged. */
1290
+ readonly aborted: boolean;
1291
+ readonly name = "WorkspaceConflictError";
1292
+ constructor(workspacePath: string, fromRef: string, conflicts: readonly string[],
1293
+ /** True when the backend aborted the rebase and the workspace is unchanged. */
1294
+ aborted?: boolean);
1295
+ errorNextSteps(): NextStep[];
1296
+ }
1209
1297
  interface CreateWorkspaceOptions$1 {
1210
1298
  /** The repository being branched from. Absolute path. */
1211
1299
  projectRoot: string;
@@ -1237,6 +1325,10 @@ interface FreeWorkspaceResult$1 {
1237
1325
  /** The commit id that captured the pending changes, when `commit` was
1238
1326
  * true and there was something to commit. Otherwise undefined. */
1239
1327
  committedRef?: string;
1328
+ /** Branch created to keep the workspace's commits reachable after the
1329
+ * worktree is removed (git with `commit`, when HEAD was on no branch,
1330
+ * remote or tag). Otherwise undefined. */
1331
+ branch?: string;
1240
1332
  /** True iff the on-disk path was actually removed (vs. already gone). */
1241
1333
  removed: boolean;
1242
1334
  }
@@ -1275,15 +1367,17 @@ interface VcsBackend {
1275
1367
  * Backend-specific behaviour:
1276
1368
  * - git: refuses on dirty WC (WorkspaceDirtyError); fetches first;
1277
1369
  * `git rebase <ref>`. On conflict, aborts the rebase and throws
1278
- * WorkspaceConflictError so the operator resolves manually.
1370
+ * WorkspaceConflictError (aborted); the workspace is unchanged.
1371
+ * Any other rebase failure is rethrown.
1279
1372
  * - jj: always-snapshotted, so dirty is never an issue. After
1280
1373
  * `jj rebase -d <ref>` the conflict-set is queried via
1281
1374
  * `jj log -r 'conflict()'`. Conflicts surface as
1282
1375
  * WorkspaceConflictError without an abort (jj's conflict markers
1283
1376
  * persist as commits; the operator resolves in-place).
1284
- * - sl: similar to jj. `sl rebase -d <ref>`; conflicts via
1285
- * `sl resolve -l`. On dirty WC sl errors itself; we wrap that
1286
- * into WorkspaceDirtyError.
1377
+ * - sl: like git. Refuses on dirty WC (WorkspaceDirtyError);
1378
+ * `sl rebase -d <ref>`; conflicts via `sl resolve --list`, then
1379
+ * aborts and throws WorkspaceConflictError (aborted). Any other
1380
+ * rebase failure is rethrown.
1287
1381
  * - none: throws WorkspaceVcsRequiredError unconditionally.
1288
1382
  *
1289
1383
  * Surfaced by fb_workspace_recycle_verb: dogfood between waves
@@ -1291,7 +1385,10 @@ interface VcsBackend {
1291
1385
  * main; that killed the worker's LLM context. `refresh` updates
1292
1386
  * the on-disk dir without touching the agent or pane.
1293
1387
  */
1294
- rebaseTo(workspacePath: string, fromRef?: string): Promise<RebaseResult>;
1388
+ rebaseTo(workspacePath: string, fromRef?: string,
1389
+ /** The row's current parent_ref. Kept as the result's parentRef
1390
+ * when it already descends from fromRef and is under the head. */
1391
+ previousParentRef?: string): Promise<RebaseResult>;
1295
1392
  /**
1296
1393
  * Cheap "is the working copy clean?" probe used by close-auto-free
1297
1394
  * (allow_mu_agent_close_without_discard). Definition: ZERO uncommitted
@@ -1434,9 +1531,9 @@ declare function checkCommandResolvable(command: string): Promise<CommandResolut
1434
1531
  interface SpawnAgentOptions {
1435
1532
  name: string;
1436
1533
  workstream: string;
1437
- /** Defaults to "pi". 0.1.0 only really supports "pi" but the column
1438
- * accepts any string for forward-compat with future multi-CLI support
1439
- * (claude/codex). */
1534
+ /** Defaults to "pi". Any CLI is accepted: pi is driven over its control
1535
+ * socket; others run `MU_<CLI>_COMMAND` (or the cli name) and get
1536
+ * text by mux paste. */
1440
1537
  cli?: string;
1441
1538
  /** The actual command to run in the pane. Defaults to the cli value. */
1442
1539
  command?: string;
@@ -1504,7 +1601,7 @@ declare function spawnAgent(db: Db, opts: SpawnAgentOptions): Promise<SpawnedAge
1504
1601
  declare function defaultSpawnLivenessMs(): number;
1505
1602
 
1506
1603
  interface AdoptAgentOptions {
1507
- /** tmux pane id (e.g. '%15'). Must already exist on the tmux server. */
1604
+ /** Mux pane id (tmux '%15', herdr 'w1:p2'). Must already exist. */
1508
1605
  paneId: string;
1509
1606
  /** Workstream to adopt the pane into. The pane MUST be in the
1510
1607
  * matching tmux session (`mu-<workstream>`); cross-session adopt is
@@ -1553,18 +1650,18 @@ interface AdoptAgentResult {
1553
1650
  * Validation order (matches the design in note #100):
1554
1651
  * 1. Pane id format -> assertValidPaneId via paneExists / setPaneTitle
1555
1652
  * 2. Pane exists -> PaneNotFoundError
1556
- * 3. Pane is in session -> AgentNotInWorkstreamError (cross-session)
1653
+ * 3. Pane is in session -> PaneNotInSessionError (cross-session)
1557
1654
  * 4. Resolved name OK -> isValidAgentName / Error('agent name invalid')
1558
1655
  * 5. Idempotent check -> if pane already owned by an agent of this
1559
1656
  * name, return alreadyAdopted=true
1560
1657
  * 6. Name not taken -> AgentExistsError (else)
1561
1658
  * 7. Insert + retitle.
1562
1659
  *
1563
- * Status starts at 'free' — reconcile/detect will update it on the next
1564
- * `mu agent list` based on actual pane content (the pi prompt yields
1565
- * 'free'; an agent mid-thought yields 'busy'; etc.). We don't run
1566
- * detection inline here because the caller may not have $TMUX, and
1567
- * adoption shouldn't depend on a captured-pane probe succeeding.
1660
+ * The row's `status` column is the deprecated constant 'spawning' (see
1661
+ * insertAgent); runtime state is read at display time by
1662
+ * src/agent-state.ts (control socket, murmur, or herdr), never from
1663
+ * pane text. Adoption runs no state probe, so it does not depend on
1664
+ * the agent's control socket or a captured pane answering.
1568
1665
  */
1569
1666
  declare function adoptAgent(db: Db, opts: AdoptAgentOptions): Promise<AdoptAgentResult>;
1570
1667
 
@@ -1656,6 +1753,20 @@ declare class AgentNotInWorkstreamError extends Error implements HasNextSteps {
1656
1753
  constructor(agentName: string, expectedWorkstream: string, actualWorkstream: string);
1657
1754
  errorNextSteps(): NextStep[];
1658
1755
  }
1756
+ /**
1757
+ * `mu agent adopt` of a pane that exists but is not in the workstream's
1758
+ * mux session. Distinct from AgentNotInWorkstreamError: the subject is a
1759
+ * pane, not an agent, and its owning session is not known without
1760
+ * another mux query. Maps to exit code 4 (conflict).
1761
+ */
1762
+ declare class PaneNotInSessionError extends Error implements HasNextSteps {
1763
+ readonly paneId: string;
1764
+ readonly workstream: string;
1765
+ readonly expectedSession: string;
1766
+ readonly name = "PaneNotInSessionError";
1767
+ constructor(paneId: string, workstream: string, expectedSession: string);
1768
+ errorNextSteps(): NextStep[];
1769
+ }
1659
1770
  /**
1660
1771
  * Thrown when an agent's pane is created and titled successfully but the
1661
1772
  * spawned process exits within the liveness window (default 1500ms;
@@ -1804,6 +1915,27 @@ declare class AgentFreshNeedsCtlError extends Error implements HasNextSteps {
1804
1915
  constructor(agentName: string, workstream: string, cli: string);
1805
1916
  errorNextSteps(): NextStep[];
1806
1917
  }
1918
+ /**
1919
+ * The agent's pi serves the control socket with an extension it loaded
1920
+ * before mu learned `op` (e.g. `fresh`): running pi processes keep the
1921
+ * extension code they started with. pi's `/reload` re-imports the
1922
+ * extension through the `mu link pi` shim and keeps the socket; a
1923
+ * respawn always works. An extension that serves op `command` takes
1924
+ * `/reload` over ctl; an older one needs it typed (`--via mux`).
1925
+ */
1926
+ declare class AgentExtensionOutdatedError extends Error implements HasNextSteps {
1927
+ readonly agentName: string;
1928
+ readonly workstream: string;
1929
+ readonly op: string;
1930
+ readonly extVersion?: string | undefined;
1931
+ /** Ops the extension serves (from its "unknown op" reply); absent from old extensions. */
1932
+ readonly ops?: readonly string[] | undefined;
1933
+ readonly name = "AgentExtensionOutdatedError";
1934
+ constructor(agentName: string, workstream: string, op: string, extVersion?: string | undefined,
1935
+ /** Ops the extension serves (from its "unknown op" reply); absent from old extensions. */
1936
+ ops?: readonly string[] | undefined);
1937
+ errorNextSteps(): NextStep[];
1938
+ }
1807
1939
  /**
1808
1940
  * `send --fresh` or a session command (`/new`, `/reload`, `/compact`)
1809
1941
  * refused: pi is mid-turn, and running it would abandon the turn.
@@ -2153,10 +2285,7 @@ interface ListLiveAgentsOptions {
2153
2285
  * documented mutating behaviour `mu agent list` has always had,
2154
2286
  * now also used by `mu state`).
2155
2287
  *
2156
- * `mu doctor` and `mu undo` pass `"report-only"`: count drift,
2157
- * mutate nothing. `mu undo` MUST use this so a post-restore
2158
- * reconcile doesn't delete the rows the snapshot just restored
2159
- * (snap_undo_reconcile_destroys_recovered_agents).
2288
+ * `mu doctor` passes `"report-only"`: count drift, mutate nothing.
2160
2289
  *
2161
2290
  * Mid-spawn placeholders (pane id `%pending-<name>`) are protected
2162
2291
  * directly in reconcile's prune loop, independent of mode
@@ -2179,9 +2308,8 @@ interface LiveAgentsView {
2179
2308
  /**
2180
2309
  * Return the live, reality-reconciled view of agents in a workstream.
2181
2310
  * `mu state` and `mu agent list` call this with the default `mode: "full"`
2182
- * (mutating); read-only diagnostic / restore paths
2183
- * (`mu doctor`, `mu undo`) call it with `mode: "report-only"` to mutate
2184
- * nothing at all.
2311
+ * (mutating); the read-only diagnostic (`mu doctor`) calls it with
2312
+ * `mode: "report-only"` to mutate nothing at all.
2185
2313
  */
2186
2314
  declare function listLiveAgents(db: Db, opts: ListLiveAgentsOptions): Promise<LiveAgentsView>;
2187
2315
 
@@ -2463,7 +2591,8 @@ interface CloseTaskOptions extends EvidenceOption {
2463
2591
  * as a bare `addNote` without `--author`). Surfaced in mufeedback
2464
2592
  * task_close_evidence_does_not_append_the. */
2465
2593
  author?: string;
2466
- /** Closing substate; default "done". Any CLOSED/* satisfies edges. */
2594
+ /** Closing substate; default "done" (or, for an already-CLOSED task,
2595
+ * its current substate). Any CLOSED/* satisfies edges. */
2467
2596
  as?: CloseSubstate;
2468
2597
  /** Required (non-empty) unless `as` is "done"; stored as a
2469
2598
  * `<AS>: <why>` note in the same op group. */
@@ -2478,9 +2607,9 @@ interface CloseTaskResult extends SetStatusResult {
2478
2607
  unblocked: string[];
2479
2608
  }
2480
2609
  /** Convenience: setTaskStatus(db, id, "CLOSED"). Accepts evidence.
2481
- * Skipped
2482
- * for the idempotent no-op (already CLOSED) so we don't accumulate
2483
- * empty-delta snapshots on retry loops.
2610
+ * Notes are skipped for the idempotent no-op (already CLOSED with the
2611
+ * same substate; a bare close without `as` keeps the current one) so
2612
+ * retry loops don't accumulate duplicates.
2484
2613
  *
2485
2614
  * With `ifReady: true`, returns a `CloseSkippedResult` (no mutation,
2486
2615
  * no snapshot) when any blocker is still OPEN / IN_PROGRESS. Used by
@@ -2593,7 +2722,7 @@ interface ClaimTaskOptions extends AttributedEvidence {
2593
2722
  */
2594
2723
  agentWorkstream?: string;
2595
2724
  /**
2596
- * Anonymous claim: write `owner = NULL` instead of resolving an agent
2725
+ * Anonymous claim: write `owner_id = NULL` instead of resolving an agent
2597
2726
  * name and checking the FK. Use when the actor is the orchestrator
2598
2727
  * (or a script, or a human) doing direct work in a workstream they
2599
2728
  * aren't a registered worker in.
@@ -2604,9 +2733,10 @@ interface ClaimTaskOptions extends AttributedEvidence {
2604
2733
  *
2605
2734
  * Resolution order for the actor name (used as the log source):
2606
2735
  * 1. `actor` if explicitly passed.
2607
- * 2. Current pane title (when `$TMUX_PANE` is set).
2608
- * 3. `$USER`.
2609
- * 4. The literal string 'unknown'.
2736
+ * 2. `$MU_AGENT_NAME`.
2737
+ * 3. The mux's current agent name (pane title on tmux).
2738
+ * 4. `$USER`.
2739
+ * 5. The literal string 'orchestrator'.
2610
2740
  *
2611
2741
  * Mutually exclusive with `agentName` (the two are alternative
2612
2742
  * answers to "who's the actor for this claim?"). Passing both is a
@@ -2644,14 +2774,15 @@ interface ClaimResult {
2644
2774
  * Claim a task. Two modes:
2645
2775
  *
2646
2776
  * Worker claim (default):
2647
- * Resolve an agent name from `opts.agentName` or from $TMUX_PANE's
2648
- * pane title. The name MUST exist in the agents table (FK on
2649
- * tasks.owner). Sets `owner = <name>`. This is what mu-spawned
2777
+ * Resolve an agent name from `opts.agentName`, else $MU_AGENT_NAME,
2778
+ * else the mux's current agent name (pane title on tmux). The name
2779
+ * MUST exist in the agents table (`tasks.owner_id` is an FK to
2780
+ * `agents.id`). Sets `owner_id` to that agent. This is what mu-spawned
2650
2781
  * workers do, and what `mu task claim --for <worker>` does for
2651
2782
  * orchestrator dispatch.
2652
2783
  *
2653
2784
  * Anonymous claim (--self):
2654
- * Skip the name -> agents FK lookup entirely. Sets `owner = NULL`.
2785
+ * Skip the name -> agents FK lookup entirely. Sets `owner_id = NULL`.
2655
2786
  * Records the actor in `agent_logs.source` instead. This is the
2656
2787
  * orchestrator-doing-direct-work path — the actor is logged but
2657
2788
  * not registered as a worker pane.
@@ -2867,12 +2998,15 @@ interface DeleteTaskResult {
2867
2998
  * found an existing task with zero edges and zero notes
2868
2999
  * (`present: true, deletedEdges: 0, deletedNotes: 0`). */
2869
3000
  present: boolean;
3001
+ /** The op group the delete wrote, for `mu undo <group> --yes`. Null
3002
+ * when nothing was deleted (dry-run or missing row). */
3003
+ group: string | null;
2870
3004
  }
2871
3005
  interface DeleteTaskOptions {
2872
3006
  /** When true, return the cascade preview (would-be edge / note
2873
- * counts) without mutating and without snapshotting. The CLI uses
2874
- * this to power the bare `mu task delete <id>` two-phase pattern
2875
- * (mirrors `mu workstream teardown` / `mu snapshot prune`). Surfaced
3007
+ * counts) without mutating. The CLI uses this to power the bare
3008
+ * `mu task delete <id>` two-phase pattern (mirrors
3009
+ * `mu workstream teardown` / `mu undo`). Surfaced
2876
3010
  * by feedback ws task
2877
3011
  * fb_task_delete_no_yes (impact=30): a dogfood report typed
2878
3012
  * `mu task delete X --yes` (mirroring workstream teardown) and got
@@ -2889,10 +3023,9 @@ interface DeleteTaskOptions {
2889
3023
  * `changes()` only reports rows directly affected by the DELETE.
2890
3024
  *
2891
3025
  * With `opts.dryRun: true`, returns the would-be counts without
2892
- * touching the DB and without taking a snapshot (no mutation = no
2893
- * snapshot — same reasoning that gates the closeTask snap on the
2894
- * idempotent no-op path). The CLI bare `mu task delete <id>` form
2895
- * uses this; `--yes` calls through with `dryRun: false`.
3026
+ * touching the DB (no mutation, so no op is written). The CLI bare
3027
+ * `mu task delete <id>` form uses this; `--yes` calls through with
3028
+ * `dryRun: false`.
2896
3029
  */
2897
3030
  declare function deleteTask(db: Db, localId: string, workstream: string, opts?: DeleteTaskOptions): DeleteTaskResult;
2898
3031
  interface UpdateTaskOptions {
@@ -3042,6 +3175,9 @@ interface FreeWorkspaceResult {
3042
3175
  /** The committed ref, when `commit` was true and there was something
3043
3176
  * to commit. */
3044
3177
  committedRef?: string;
3178
+ /** Branch mu created to keep the workspace's commits reachable after
3179
+ * removal (git `--commit` on a detached HEAD). */
3180
+ branch?: string;
3045
3181
  /** True iff the on-disk path was actually removed. */
3046
3182
  removed: boolean;
3047
3183
  /** True iff the DB row was actually deleted. */
@@ -3121,6 +3257,19 @@ declare class TaskNotFoundError extends Error implements HasNextSteps {
3121
3257
  constructor(taskId: string);
3122
3258
  errorNextSteps(): NextStep[];
3123
3259
  }
3260
+ /**
3261
+ * Thrown by `addTask` when `localId` violates the schema regex
3262
+ * `/^[a-z][a-z0-9_-]{0,63}$/`. Replaces a bare `TypeError` so the
3263
+ * CLI's `handle()` wrapper can map it to exit code 2 (usage, with the
3264
+ * verb's --help, like WorkstreamNameInvalidError) and surface a `--json` `nextSteps` block pointing at
3265
+ * the auto-derived-id workflow and a sanitised candidate.
3266
+ */
3267
+ declare class TaskIdInvalidError extends Error implements HasNextSteps {
3268
+ readonly attempted: string;
3269
+ readonly name = "TaskIdInvalidError";
3270
+ constructor(attempted: string);
3271
+ errorNextSteps(): NextStep[];
3272
+ }
3124
3273
  declare class TaskExistsError extends Error implements HasNextSteps {
3125
3274
  readonly taskId: string;
3126
3275
  readonly name = "TaskExistsError";
@@ -3153,7 +3302,7 @@ declare class TaskAlreadyOwnedError extends Error implements HasNextSteps {
3153
3302
  * Thrown when `mu task claim` resolves a claimer agent name (from the
3154
3303
  * pane title or --for) that has no matching row in the agents table.
3155
3304
  *
3156
- * The FK on `tasks.owner` references `agents.name`; without this guard
3305
+ * The FK on `tasks.owner_id` references `agents.id`; without this guard
3157
3306
  * the claim attempt would fail with the unhelpful 'FOREIGN KEY constraint
3158
3307
  * failed' from SQLite. This typed error gives the user actionable next
3159
3308
  * steps (run `mu agent adopt <pane-id>` to register, or use --for to pick a
@@ -3174,6 +3323,12 @@ declare class ClaimerNotRegisteredError extends Error implements HasNextSteps {
3174
3323
  */
3175
3324
  errorNextSteps(): NextStep[];
3176
3325
  }
3326
+ declare class TaskClaimStaleWorkspaceError extends Error implements HasNextSteps {
3327
+ readonly staleness: WorkspaceStaleness;
3328
+ readonly name = "TaskClaimStaleWorkspaceError";
3329
+ constructor(staleness: WorkspaceStaleness);
3330
+ errorNextSteps(): NextStep[];
3331
+ }
3177
3332
  declare class CycleError extends Error implements HasNextSteps {
3178
3333
  readonly from: string;
3179
3334
  readonly to: string;
@@ -3181,6 +3336,64 @@ declare class CycleError extends Error implements HasNextSteps {
3181
3336
  constructor(from: string, to: string);
3182
3337
  errorNextSteps(): NextStep[];
3183
3338
  }
3339
+ /**
3340
+ * Thrown by the `mu task wait` CLI wrapper when the per-poll
3341
+ * reconciler detects that a watched task transitioned
3342
+ * `IN_PROGRESS → OPEN` between polls (the reaper saw the owner's
3343
+ * pane was gone and flipped the task back). With `--status CLOSED`
3344
+ * (the default) the wait can never satisfy by progress — the worker
3345
+ * is dead — so we abort fast instead of running out the operator's
3346
+ * `--timeout`.
3347
+ *
3348
+ * Maps to exit code 6 (REAPER_DETECTED) via the cli.ts handler. The
3349
+ * suppression rule (only fire when target=CLOSED) lives in the
3350
+ * caller; this error type is a pure data carrier.
3351
+ *
3352
+ * Surfaced live by task_wait_reconcile_dead_panes (twice in one
3353
+ * v0.3 dispatch wave: tmux restart killed worker panes; `mu task
3354
+ * wait --timeout 1800` blocked silently for 25 min instead of
3355
+ * failing in seconds).
3356
+ */
3357
+ declare class ReaperDetectedDuringWaitError extends Error implements HasNextSteps {
3358
+ readonly taskId: string;
3359
+ readonly previousOwner: string | null;
3360
+ readonly workstream: string;
3361
+ readonly name = "ReaperDetectedDuringWaitError";
3362
+ constructor(taskId: string, previousOwner: string | null, workstream: string);
3363
+ errorNextSteps(): NextStep[];
3364
+ }
3365
+ declare class StallDetectedDuringWaitError extends Error implements HasNextSteps {
3366
+ readonly taskName: string;
3367
+ readonly owner: string | null;
3368
+ readonly workstream: string;
3369
+ readonly ageSecs: number;
3370
+ /** The owner runs pi (control socket): `mu agent abort` stops its turn. */
3371
+ readonly ownerExpectsCtl: boolean;
3372
+ /** The owner's ctl run count at the stall, when its socket answered. */
3373
+ readonly ownerRuns?: number | undefined;
3374
+ /** The owner's workstream when it differs from the task's
3375
+ * (`task claim --for <ws>/<agent>`). Agent commands use it. */
3376
+ readonly ownerWorkstream: string;
3377
+ readonly name = "StallDetectedDuringWaitError";
3378
+ constructor(taskName: string, owner: string | null, workstream: string, ageSecs: number,
3379
+ /** The owner runs pi (control socket): `mu agent abort` stops its turn. */
3380
+ ownerExpectsCtl?: boolean,
3381
+ /** The owner's ctl run count at the stall, when its socket answered. */
3382
+ ownerRuns?: number | undefined,
3383
+ /** The owner's workstream when it differs from the task's
3384
+ * (`task claim --for <ws>/<agent>`). Agent commands use it. */
3385
+ ownerWorkstream?: string);
3386
+ /**
3387
+ * Diagnose before acting. `mu agent read` comes FIRST because the
3388
+ * predicate that threw cannot tell the three causes of needs_input
3389
+ * apart, and the evidence is in the pane rather than the task row.
3390
+ * The earlier order led with "poke the worker", which is the right
3391
+ * move for only one of the three and actively wrong for a worker
3392
+ * waiting on an answer — a poke with no answer in it just restates
3393
+ * the question.
3394
+ */
3395
+ errorNextSteps(): NextStep[];
3396
+ }
3184
3397
  declare class CrossWorkstreamEdgeError extends Error implements HasNextSteps {
3185
3398
  readonly blocker: string;
3186
3399
  readonly blockerWorkstream: string;
@@ -3253,6 +3466,16 @@ declare class InvalidSubstateError extends Error implements HasNextSteps {
3253
3466
  errorNextSteps(): NextStep[];
3254
3467
  }
3255
3468
 
3469
+ /** Thrown when a title has no ASCII letter or digit, so no id can be
3470
+ * derived from it (any non-ASCII script, or pure punctuation). Exit 2
3471
+ * (usage) with the verb's --help; the fix is the `<id>` positional.
3472
+ * Lives here, not in errors.ts, because errors.ts imports this file. */
3473
+ declare class TaskTitleSlugEmptyError extends Error implements HasNextSteps {
3474
+ readonly title: string;
3475
+ readonly name = "TaskTitleSlugEmptyError";
3476
+ constructor(title: string);
3477
+ errorNextSteps(): NextStep[];
3478
+ }
3256
3479
  declare function isValidTaskId(id: string): boolean;
3257
3480
  /**
3258
3481
  * Lowercase title; collapse non-alnum runs into single `_`; trim
@@ -3262,7 +3485,7 @@ declare function isValidTaskId(id: string): boolean;
3262
3485
  * when one exists, else hard-truncate). Mirrors `tg`'s `id_from_title`
3263
3486
  * but adds the soft cap.
3264
3487
  *
3265
- * Throws if `title` yields an empty slug after stripping.
3488
+ * Throws `TaskTitleSlugEmptyError` if `title` yields an empty slug.
3266
3489
  */
3267
3490
  declare function slugifyTitle(title: string): string;
3268
3491
  /**
@@ -3379,8 +3602,11 @@ declare function listGoals(db: Db, workstream: string): TaskRow[];
3379
3602
  * named SDK helper so CLI renderers don't re-derive the row-shape
3380
3603
  * conversion (review_code_raw_task_state_duplicate). */
3381
3604
  declare function listInProgress(db: Db, workstream: string): TaskRow[];
3382
- /** Most-recently-closed tasks in a workstream, newest first, capped at
3383
- * `limit` (default 5). Used by `mu state` for its 'recent closed'
3605
+ /** CLOSED tasks in a workstream, most recently updated first, capped at
3606
+ * `limit` (default 5). `updated_at` is a proxy for close time: there is
3607
+ * no `closed_at` column, and a later note or edge change on a CLOSED
3608
+ * task bumps `updated_at` (touchTask), moving it up. Used by `mu state`
3609
+ * for its 'recent closed'
3384
3610
  * slice; exposed as a named SDK helper so the CLI no longer needs the
3385
3611
  * raw-row type that was duplicating RawTaskRow
3386
3612
  * (review_code_raw_task_state_duplicate). */
@@ -3406,8 +3632,9 @@ interface ListNotesOptions {
3406
3632
  * an error here — CLI-side validation rejects `--tail 0`. */
3407
3633
  tail?: number;
3408
3634
  /** ISO-8601 cutoff: only notes with `created_at > since` survive.
3409
- * Comparison is lexicographic on the ISO string (matches the way
3410
- * the rest of the codebase compares ISO timestamps). */
3635
+ * Any `Date.parse`-able value; it is normalised to `toISOString()`
3636
+ * form (the stored shape) before the text comparison, so offsets
3637
+ * and second-precision cutoffs compare as instants. */
3411
3638
  since?: string;
3412
3639
  /** When true and `since` is unset, look up the `created_at` of the
3413
3640
  * most recent `task claim` event for this task and use it as the
@@ -3631,9 +3858,12 @@ declare class LinkConflictError extends Error implements HasNextSteps {
3631
3858
  }
3632
3859
  /** Install the extension shim (or, with `copy`, an inlined copy pinned
3633
3860
  * to this version). `replacedCopy` is true when an existing file without
3634
- * the shim marker was overwritten. */
3861
+ * the shim marker was overwritten. A symlink at the destination (e.g. to
3862
+ * a dev checkout) is never written through: a live one needs `force`,
3863
+ * which replaces the link itself, never its target. */
3635
3864
  declare function linkPi(opts?: LinkOptions & {
3636
3865
  copy?: boolean;
3866
+ force?: boolean;
3637
3867
  }): {
3638
3868
  path: string;
3639
3869
  replacedCopy: boolean;
@@ -3664,7 +3894,7 @@ interface LogRow {
3664
3894
  * render as "system" rather than the string "null". */
3665
3895
  source: string;
3666
3896
  /** Structured intent ('task.close', 'agent.spawn', ...). Null only for
3667
- * operator-authored prose lines (`mu log write` / a `--kind` ledger),
3897
+ * operator-authored prose lines (`mu log "<text>"` / a `--kind` ledger),
3668
3898
  * which name no state change. The formatter in src/log-render.ts
3669
3899
  * renders from this — never from the payload text. */
3670
3900
  intent: string | null;
@@ -3683,6 +3913,15 @@ interface LogRow {
3683
3913
  /** ISO 8601 timestamp set at insert time. */
3684
3914
  createdAt: string;
3685
3915
  }
3916
+ /** Raised when a group-id prefix matches more than one group.
3917
+ * Astronomically unlikely with uuids, but silently picking one of two
3918
+ * candidate groups to UNDO is not an acceptable failure mode. */
3919
+ declare class GroupIdAmbiguousError extends Error implements HasNextSteps {
3920
+ readonly prefix: string;
3921
+ readonly candidates: readonly string[];
3922
+ constructor(prefix: string, candidates: readonly string[]);
3923
+ errorNextSteps(): NextStep[];
3924
+ }
3686
3925
  interface AppendLogOptions {
3687
3926
  /** Workstream this entry belongs to. `null` for machine-wide. */
3688
3927
  workstream: string | null;
@@ -3698,6 +3937,14 @@ interface AppendLogOptions {
3698
3937
  * to name. */
3699
3938
  intent?: string;
3700
3939
  }
3940
+ /** Raised by `appendLog` for a kind in RESERVED_LOG_KINDS. Usage lane
3941
+ * (exit 2): the operator picked a tag that names a projectable entity. */
3942
+ declare class LogKindReservedError extends Error implements HasNextSteps {
3943
+ readonly kind: string;
3944
+ readonly name = "LogKindReservedError";
3945
+ constructor(kind: string);
3946
+ errorNextSteps(): NextStep[];
3947
+ }
3701
3948
  /**
3702
3949
  * Append a log entry. Returns the inserted row (with assigned `seq`).
3703
3950
  * Constant-time. Single INSERT; safe to call from any state-changing
@@ -3865,6 +4112,11 @@ interface WorkstreamSnapshotSlowFields {
3865
4112
  commitsBackend?: VcsBackendName | null;
3866
4113
  doctor: DoctorSummary | null;
3867
4114
  }
4115
+ /**
4116
+ * Fast TUI/state snapshot tier: pure SQLite reads only. Subprocess-backed
4117
+ * fields are intentionally empty placeholders so callers can merge the last
4118
+ * slow-tier values without blocking a 1s render tick on tmux or VCS probes.
4119
+ */
3868
4120
  declare function loadWorkstreamSnapshotFast(db: Db, workstream: string, opts?: LoadWorkstreamSnapshotOptions): Promise<WorkstreamSnapshot>;
3869
4121
  /**
3870
4122
  * Slow snapshot tier: fields backed by tmux / VCS subprocess probes (plus
@@ -3927,6 +4179,10 @@ interface DoctorSummary {
3927
4179
  /** Convenience: how many rows are warn or fail. Card subtitle
3928
4180
  * reads this directly. Pure derivation from `checks`. */
3929
4181
  problemCount: number;
4182
+ /** Where the murmur row read agent state from. The slot-9 popup
4183
+ * re-derives the full check list and passes this back, so its
4184
+ * murmur row matches the card's (herdr on herdr). */
4185
+ agentStateSource?: "murmur" | "herdr";
3930
4186
  }
3931
4187
  /**
3932
4188
  * Compute the doctor summary for a workstream. Pure-ish: runs cheap
@@ -3951,7 +4207,7 @@ declare function countProblems(checks: readonly DoctorCheck[]): number;
3951
4207
  * just `.checks`. Pure-ish (same cheap synchronous DB reads as
3952
4208
  * `loadDoctorSummary`).
3953
4209
  */
3954
- declare function loadDoctorChecks(db: Db, snapshot: WorkstreamSnapshot | null): readonly DoctorCheck[];
4210
+ declare function loadDoctorChecks(db: Db, snapshot: WorkstreamSnapshot | null, agentStateSource?: "murmur" | "herdr"): readonly DoctorCheck[];
3955
4211
  /**
3956
4212
  * Map a check row to the most useful informational command the
3957
4213
  * operator might paste. Read-only by construction: `mu agent list`,
@@ -4113,6 +4369,17 @@ interface FleetHazard {
4113
4369
  /** Multi-line explanation + remediation, shown when non-ok. */
4114
4370
  remediation?: readonly string[];
4115
4371
  }
4372
+ /**
4373
+ * `mu doctor` found at least one `fail`-severity row. Thrown after the
4374
+ * whole report is printed (or the --json payload emitted) so scripts and
4375
+ * CI see a non-zero exit; maps to exit 5 like drift, because a `fail`
4376
+ * row means the substrate is unsafe, not that a hint is pending.
4377
+ */
4378
+ declare class HazardFailError extends Error {
4379
+ readonly failedRows: readonly string[];
4380
+ readonly name = "HazardFailError";
4381
+ constructor(failedRows: readonly string[]);
4382
+ }
4116
4383
  /**
4117
4384
  * True iff `child` is inside `parent` (or is `parent`).
4118
4385
  *
@@ -4330,7 +4597,7 @@ declare function nextHlc(db: Db, now?: number): string;
4330
4597
  *
4331
4598
  * wall = max(local_wall, remote_wall, now)
4332
4599
  *
4333
- * The counter has three explicit cases, by which of the three won:
4600
+ * The counter has four explicit cases, by which of the three won:
4334
4601
  * - `now` strictly won -> counter = 0 (fresh millisecond)
4335
4602
  * - local and remote tie at max -> counter = max(local_c, remote_c) + 1
4336
4603
  * - only local is at max -> counter = local_c + 1
@@ -4350,7 +4617,7 @@ declare function receiveHlc(db: Db, remoteHlc: string, now?: number): string;
4350
4617
  /** Every intent mu writes: the local ones (`emitEvent`, for changes no
4351
4618
  * trigger can see) plus the capture-trigger ones (set via
4352
4619
  * `withOpContext` around a portable-table mutation). */
4353
- type CaptureIntent = "task.add" | "task.update" | "task.note" | "task.delete" | "task.close" | "task.open" | "task.park" | "task.unpark" | "task.reject" | "task.defer" | "task.claim" | "task.release" | "task.reap" | "task.block" | "task.unblock" | "task.reparent" | "workstream.init" | "workstream.teardown" | "workstream.destroy";
4620
+ type CaptureIntent = "task.add" | "task.update" | "task.note" | "task.delete" | "task.close" | "task.open" | "task.park" | "task.unpark" | "task.accept" | "task.reject" | "task.defer" | "task.claim" | "task.release" | "task.reap" | "task.block" | "task.unblock" | "task.reparent" | "workstream.init" | "workstream.teardown" | "sql.write" | "workstream.destroy";
4354
4621
  type KnownIntent = CaptureIntent | LocalIntent;
4355
4622
  /** A log row, reduced to what rendering needs. Structural so both
4356
4623
  * `LogRow` (the SDK shape) and raw op rows satisfy it. */
@@ -4402,7 +4669,7 @@ declare const KNOWN_VERBS: readonly string[];
4402
4669
  * Render one op as prose.
4403
4670
  *
4404
4671
  * Returns null when the row is not a rendered op at all — operator prose
4405
- * from `mu log write` / a `--kind` ledger, which has no intent and
4672
+ * from `mu log "<text>"` / a `--kind` ledger, which has no intent and
4406
4673
  * should be shown verbatim. Callers print `payload` in that case.
4407
4674
  */
4408
4675
  declare function renderOp(row: RenderableOp): RenderedOp | null;
@@ -4521,8 +4788,9 @@ interface RebuildReport {
4521
4788
  /** Ops copied into the target's log. Every op, not just synced ones. */
4522
4789
  opsCopied: number;
4523
4790
  /** Ops that projected into a portable table. Always <= opsCopied:
4524
- * log-only entities (message / event / broadcast / marker) are
4525
- * copied but have no table to land in. */
4791
+ * log-only entities (message / event / broadcast), machine-local
4792
+ * agent / workspace ops and legacy log-only intents are copied but
4793
+ * have no table to land in. */
4526
4794
  opsProjected: number;
4527
4795
  /** Ops that changed a row when applied. Lower than opsProjected
4528
4796
  * whenever later ops superseded earlier ones — which is normal and
@@ -4674,6 +4942,13 @@ declare function verifyAgainstManifest(segment: string): {
4674
4942
  interface PeerSegment {
4675
4943
  /** Machine id the segment belongs to. */
4676
4944
  machineId: string;
4945
+ /** Key of this FILE's watermark in `sync_peers`: the machine id for
4946
+ * the peer's own segment, the full file stem for a conflict copy.
4947
+ * A copy diverges from its original, so line N of one says nothing
4948
+ * about line N of the other; sharing one watermark skipped every op
4949
+ * that existed only in the copy. Optional for SDK callers written
4950
+ * before it existed: absent means the machine id (`peerWatermarkKey`). */
4951
+ watermarkKey?: string;
4677
4952
  /** Path on disk. */
4678
4953
  path: string;
4679
4954
  /** True for a Syncthing-style conflict copy. */
@@ -4695,7 +4970,9 @@ interface PeerSegment {
4695
4970
  */
4696
4971
  declare function discoverPeers(dir: string, selfMachineId: string): PeerSegment[];
4697
4972
  /**
4698
- * How far into a peer's segment we have applied.
4973
+ * How far into one segment file we have applied, keyed by
4974
+ * `PeerSegment.watermarkKey` (the machine id, or a conflict copy's own
4975
+ * stem).
4699
4976
  *
4700
4977
  * ONE INTEGER SUFFICES because segments are append-only and ordered — a
4701
4978
  * set or a vector clock would be strictly more state for no more
@@ -4706,15 +4983,17 @@ declare function discoverPeers(dir: string, selfMachineId: string): PeerSegment[
4706
4983
  * `ops.seq` (which is a local-only cursor on their machine and means
4707
4984
  * nothing here).
4708
4985
  */
4709
- declare function getWatermark(db: Db, machineId: string): number;
4710
- declare function setWatermark(db: Db, machineId: string, value: number): void;
4986
+ declare function getWatermark(db: Db, watermarkKey: string): number;
4987
+ declare function setWatermark(db: Db, watermarkKey: string, value: number): void;
4711
4988
  /** Reset a peer's watermark so the next ingest re-reads from zero. The
4712
4989
  * universal repair, safe because ingest is idempotent. */
4713
- declare function resetWatermark(db: Db, machineId: string): void;
4990
+ declare function resetWatermark(db: Db, watermarkKey: string): void;
4714
4991
  interface IngestResult {
4715
4992
  machineId: string;
4716
4993
  path: string;
4717
- /** Lines read past the watermark. */
4994
+ /** Lines consumed past the starting watermark: applied plus skipped
4995
+ * (refused, re-delivered, historical log-only) lines. A line that
4996
+ * halted ingest is not counted. */
4718
4997
  read: number;
4719
4998
  /** Ops applied (some are no-ops: already present, or lost an LWW). */
4720
4999
  applied: number;
@@ -4750,11 +5029,38 @@ interface IngestResult {
4750
5029
  * lines, forever — so it is reported and SKIPPED. A non-monotonic line
4751
5030
  * we have NOT seen before is still real damage and still halts.
4752
5031
  *
5032
+ * A HISTORICAL log-only line (`isLegacyLogOnlyIntent`: a prose payload
5033
+ * under an otherwise projectable entity, written by a mu older than the
5034
+ * flush filter) is skipped silently, exactly as flush and `--from` skip
5035
+ * it. Applying it threw a JSON SyntaxError that rolled back the whole
5036
+ * segment on every invocation.
5037
+ *
5038
+ * A manifest mismatch (layer 4) is reported but does not halt: every
5039
+ * line still present is individually valid, so applying them is safe.
5040
+ *
4753
5041
  * Calls `receiveHlc` per op so the local clock advances past the peer's,
4754
5042
  * which is what makes "laptop edits after seeing the devserver's op" order
4755
5043
  * correctly rather than losing to it.
4756
5044
  */
4757
5045
  declare function ingestSegment(db: Db, peer: PeerSegment): IngestResult;
5046
+ /**
5047
+ * Apply ONE incoming op and record it in the local `ops` table.
5048
+ *
5049
+ * The shared tail of every ingest path — segment ingest above, and the
5050
+ * `mu sync --from <peer.db>` reader in `src/sync.ts`, which is a
5051
+ * different READER over the same apply semantics. Extracted so the two
5052
+ * cannot drift: a second copy of "advance the clock, apply, record" is
5053
+ * how one of them silently stops advancing the clock.
5054
+ *
5055
+ * Three steps, in this order:
5056
+ * 1. `receiveHlc` BEFORE applying, so anything we mint afterwards
5057
+ * sorts above the peer's op.
5058
+ * 2. `applyOp`, which is capture-suppressed (no echo op is minted).
5059
+ * 3. Record the op locally so it survives, participates in
5060
+ * provenance, and can be re-flushed by rebuild. INSERT OR IGNORE
5061
+ * makes this idempotent via UNIQUE (machine_id, hlc) — the
5062
+ * property that lets "re-read from zero" be the universal repair.
5063
+ */
4758
5064
  declare function applyIncomingOp(db: Db, op: Op): {
4759
5065
  changed: boolean;
4760
5066
  };
@@ -4767,7 +5073,7 @@ interface SyncPassResult {
4767
5073
  /**
4768
5074
  * One flush + one ingest of every discovered peer.
4769
5075
  *
4770
- * This is the SDK seam `mu sync` (v2-sync) will call; it deliberately
5076
+ * The SDK seam `mu sync` calls (src/cli/sync.ts); it deliberately
4771
5077
  * prints nothing and starts nothing. No daemon, no watcher, no polling
4772
5078
  * loop that outlives the command — the anti-feature pledges are firm, and
4773
5079
  * mu never moves files itself: the operator owns transport.
@@ -4818,7 +5124,12 @@ interface PeerStatus {
4818
5124
  path: string;
4819
5125
  /** True for a Syncthing-style `*.sync-conflict-*.jsonl` copy. */
4820
5126
  conflictCopy: boolean;
4821
- /** Lines of this peer's segment already applied. */
5127
+ /** `sync_peers` key of this file's watermark (see `PeerSegment`).
5128
+ * `peerStatuses` always sets it. Optional so SDK callers that build
5129
+ * the pre-watermarkKey shape still compile; absent means the machine
5130
+ * id (`peerWatermarkKey`). */
5131
+ watermarkKey?: string;
5132
+ /** Lines of this segment file already applied. */
4822
5133
  watermark: number;
4823
5134
  /** GOOD lines currently in the segment (a defect stops the count). */
4824
5135
  total: number;
@@ -4838,10 +5149,16 @@ declare function peerStatuses(db: Db, dir: string): PeerStatus[];
4838
5149
  /** Resolve an operator-typed peer reference (full machine id, or any
4839
5150
  * unique prefix) against the discovered peers. Ambiguity is a
4840
5151
  * UsageError, never a guess — repairing the wrong peer would re-read a
4841
- * whole segment for nothing and confuse the report. */
5152
+ * whole segment for nothing and confuse the report.
5153
+ *
5154
+ * A ref names a MACHINE, so a segment and its conflict copies (same
5155
+ * machine id) count as one match; the peer's own segment is returned
5156
+ * when present. Counting them separately made the short id `mu sync`
5157
+ * prints unresolvable. */
4842
5158
  declare function resolvePeerRef(peers: readonly PeerStatus[], ref: string): PeerStatus;
4843
- /** Reset a peer's watermark so the next ingest re-reads its segment from
4844
- * zero. Safe by construction: apply is idempotent and `ops` dedupes on
5159
+ /** Reset the watermark of every segment file a peer has (its own and
5160
+ * any conflict copies) so the next ingest re-reads them from zero. Safe
5161
+ * by construction: apply is idempotent and `ops` dedupes on
4845
5162
  * `UNIQUE (machine_id, hlc)`. */
4846
5163
  declare function repairPeer(db: Db, ref: string, dir: string): PeerStatus;
4847
5164
  /** Is sync configured at all? THE single `if` the no-sync case pays.
@@ -4960,6 +5277,7 @@ declare const tmux_PaneNotFoundError: typeof PaneNotFoundError;
4960
5277
  type tmux_SendOptions = SendOptions;
4961
5278
  type tmux_SendWarning = SendWarning;
4962
5279
  type tmux_SplitWindowOptions = SplitWindowOptions;
5280
+ type tmux_TmuxBackend = TmuxBackend;
4963
5281
  type tmux_TmuxError = TmuxError;
4964
5282
  declare const tmux_TmuxError: typeof TmuxError;
4965
5283
  type tmux_TmuxExecResult = TmuxExecResult;
@@ -5010,7 +5328,7 @@ declare const tmux_sleep: typeof sleep;
5010
5328
  declare const tmux_splitWindow: typeof splitWindow;
5011
5329
  declare const tmux_tmuxBackend: typeof tmuxBackend;
5012
5330
  declare namespace tmux {
5013
- export { type tmux_AttachTarget as AttachTarget, type tmux_CaptureOptions as CaptureOptions, type tmux_MuxCommand as MuxCommand, tmux_MuxError as MuxError, type tmux_MuxHealth as MuxHealth, type tmux_NewSessionOptions as NewSessionOptions, type tmux_NewSessionWithPaneOptions as NewSessionWithPaneOptions, type tmux_NewWindowOptions as NewWindowOptions, tmux_PANE_ID_RE as PANE_ID_RE, tmux_PaneNotFoundError as PaneNotFoundError, type tmux_SendOptions as SendOptions, type tmux_SendWarning as SendWarning, type tmux_SplitWindowOptions as SplitWindowOptions, tmux_TmuxError as TmuxError, type tmux_TmuxExecResult as TmuxExecResult, type tmux_TmuxExecutor as TmuxExecutor, type tmux_TmuxPane as TmuxPane, type tmux_TmuxSession as TmuxSession, type tmux_TmuxWindow as TmuxWindow, tmux_assertValidPaneId as assertValidPaneId, tmux_attachCommands as attachCommands, tmux_attachHint as attachHint, tmux_awaitPaneQuiescence as awaitPaneQuiescence, tmux_capturePane as capturePane, tmux_currentAgentName as currentAgentName, tmux_currentPaneTitle as currentPaneTitle, tmux_currentSessionName as currentSessionName, tmux_defaultSendDelayMs as defaultSendDelayMs, tmux_defaultSendReadinessMs as defaultSendReadinessMs, tmux_enableMuPaneBorders as enableMuPaneBorders, tmux_enableMuPaneBordersForPane as enableMuPaneBordersForPane, tmux_enableMuPaneBordersForSession as enableMuPaneBordersForSession, tmux_getPaneTitle as getPaneTitle, tmux_getWindowIdForPane as getWindowIdForPane, tmux_hasWorkMarker as hasWorkMarker, tmux_healthCheck as healthCheck, tmux_isValidPaneId as isValidPaneId, tmux_killPane as killPane, tmux_killSession as killSession, tmux_listPanes as listPanes, tmux_listPanesInSession as listPanesInSession, tmux_listSessions as listSessions, tmux_listWindows as listWindows, tmux_newSession as newSession, tmux_newSessionWithPane as newSessionWithPane, tmux_newWindow as newWindow, tmux_paneExists as paneExists, tmux_paneNotFoundNextSteps as paneNotFoundNextSteps, tmux_paneTTY as paneTTY, tmux_parseAgentNameFromTitle as parseAgentNameFromTitle, tmux_resetSleep as resetSleep, tmux_resetTmuxExecutor as resetTmuxExecutor, tmux_selectLayout as selectLayout, tmux_sendToPane as sendToPane, tmux_sessionExists as sessionExists, tmux_setPaneTitle as setPaneTitle, tmux_setSleepForTests as setSleepForTests, tmux_setTmuxExecutor as setTmuxExecutor, tmux_sleep as sleep, tmux_splitWindow as splitWindow, tmux$1 as tmux, tmux_tmuxBackend as tmuxBackend };
5331
+ export { type tmux_AttachTarget as AttachTarget, type tmux_CaptureOptions as CaptureOptions, type tmux_MuxCommand as MuxCommand, tmux_MuxError as MuxError, type tmux_MuxHealth as MuxHealth, type tmux_NewSessionOptions as NewSessionOptions, type tmux_NewSessionWithPaneOptions as NewSessionWithPaneOptions, type tmux_NewWindowOptions as NewWindowOptions, tmux_PANE_ID_RE as PANE_ID_RE, tmux_PaneNotFoundError as PaneNotFoundError, type tmux_SendOptions as SendOptions, type tmux_SendWarning as SendWarning, type tmux_SplitWindowOptions as SplitWindowOptions, type tmux_TmuxBackend as TmuxBackend, tmux_TmuxError as TmuxError, type tmux_TmuxExecResult as TmuxExecResult, type tmux_TmuxExecutor as TmuxExecutor, type tmux_TmuxPane as TmuxPane, type tmux_TmuxSession as TmuxSession, type tmux_TmuxWindow as TmuxWindow, tmux_assertValidPaneId as assertValidPaneId, tmux_attachCommands as attachCommands, tmux_attachHint as attachHint, tmux_awaitPaneQuiescence as awaitPaneQuiescence, tmux_capturePane as capturePane, tmux_currentAgentName as currentAgentName, tmux_currentPaneTitle as currentPaneTitle, tmux_currentSessionName as currentSessionName, tmux_defaultSendDelayMs as defaultSendDelayMs, tmux_defaultSendReadinessMs as defaultSendReadinessMs, tmux_enableMuPaneBorders as enableMuPaneBorders, tmux_enableMuPaneBordersForPane as enableMuPaneBordersForPane, tmux_enableMuPaneBordersForSession as enableMuPaneBordersForSession, tmux_getPaneTitle as getPaneTitle, tmux_getWindowIdForPane as getWindowIdForPane, tmux_hasWorkMarker as hasWorkMarker, tmux_healthCheck as healthCheck, tmux_isValidPaneId as isValidPaneId, tmux_killPane as killPane, tmux_killSession as killSession, tmux_listPanes as listPanes, tmux_listPanesInSession as listPanesInSession, tmux_listSessions as listSessions, tmux_listWindows as listWindows, tmux_newSession as newSession, tmux_newSessionWithPane as newSessionWithPane, tmux_newWindow as newWindow, tmux_paneExists as paneExists, tmux_paneNotFoundNextSteps as paneNotFoundNextSteps, tmux_paneTTY as paneTTY, tmux_parseAgentNameFromTitle as parseAgentNameFromTitle, tmux_resetSleep as resetSleep, tmux_resetTmuxExecutor as resetTmuxExecutor, tmux_selectLayout as selectLayout, tmux_sendToPane as sendToPane, tmux_sessionExists as sessionExists, tmux_setPaneTitle as setPaneTitle, tmux_setSleepForTests as setSleepForTests, tmux_setTmuxExecutor as setTmuxExecutor, tmux_sleep as sleep, tmux_splitWindow as splitWindow, tmux$1 as tmux, tmux_tmuxBackend as tmuxBackend };
5014
5332
  }
5015
5333
 
5016
5334
  /** What undoing one op will do. */
@@ -5052,8 +5370,9 @@ interface UndoPlan {
5052
5370
  interface UndoResult {
5053
5371
  plan: UndoPlan;
5054
5372
  /** Group id of the ops the UNDO itself wrote — pass this to
5055
- * `mu undo` to redo. */
5056
- undoGroupId: string;
5373
+ * `mu undo` to redo. Null when no inverse changed a row: the undo
5374
+ * wrote no ops, so there is no group to redo. */
5375
+ undoGroupId: string | null;
5057
5376
  /** Inverse ops that actually changed a row. */
5058
5377
  applied: number;
5059
5378
  }
@@ -5098,8 +5417,12 @@ declare class UndoSupersededError extends Error implements HasNextSteps {
5098
5417
  * Returns `{ found: false }` when no earlier op named the field, which
5099
5418
  * means the field had no value before this op — so there is nothing to
5100
5419
  * restore and the op must have been part of the row's creation.
5420
+ *
5421
+ * `machineId` limits the lookup to one machine's ops. Undo passes it for
5422
+ * `owner_id`, whose live value only this machine's ops ever wrote (apply
5423
+ * strips it from peers' ops).
5101
5424
  */
5102
- declare function priorFieldValue(db: Db, entity: string, key: string, hlc: string, field: string): {
5425
+ declare function priorFieldValue(db: Db, entity: string, key: string, hlc: string, field: string, machineId?: string): {
5103
5426
  found: true;
5104
5427
  value: string | number | null;
5105
5428
  } | {
@@ -5172,8 +5495,10 @@ interface UndoOptions {
5172
5495
  declare function undoGroup(db: Db, groupId: string, opts?: UndoOptions): UndoResult;
5173
5496
 
5174
5497
  declare function isValidWorkstreamName(name: string): boolean;
5175
- /** Thrown by `ensureWorkstream` and `mu workstream init` when the name
5176
- * doesn't match the rules. */
5498
+ /** A workstream name collision. Exported SDK error class mapped to exit
5499
+ * 4 (conflict) by `classifyError`; no mu verb throws it today
5500
+ * (`ensureWorkstream` is idempotent). Invalid names throw
5501
+ * `WorkstreamNameInvalidError`. */
5177
5502
  declare class WorkstreamExistsError extends Error implements HasNextSteps {
5178
5503
  readonly workstream: string;
5179
5504
  readonly name: string;
@@ -5186,6 +5511,15 @@ declare class WorkstreamNameInvalidError extends Error implements HasNextSteps {
5186
5511
  constructor(attempted: string);
5187
5512
  errorNextSteps(): NextStep[];
5188
5513
  }
5514
+ /** Thrown by `mu workstream init` when the operator tries to create a
5515
+ * reserved workstream (e.g. `scratch`) explicitly. The name is not
5516
+ * invalid — it auto-creates on spawn — it just can't be `init`ed. */
5517
+ declare class WorkstreamNameReservedError extends Error implements HasNextSteps {
5518
+ readonly attempted: string;
5519
+ readonly name = "WorkstreamNameReservedError";
5520
+ constructor(attempted: string);
5521
+ errorNextSteps(): NextStep[];
5522
+ }
5189
5523
  /**
5190
5524
  * Ensure a row exists in the `workstreams` table for `name`. Idempotent;
5191
5525
  * INSERT OR IGNORE so concurrent callers race safely. Called by
@@ -5276,6 +5610,18 @@ interface WorkstreamOptions {
5276
5610
  }
5277
5611
  interface TeardownWorkstreamOptions extends WorkstreamOptions {
5278
5612
  }
5613
+ /**
5614
+ * Discover every workstream visible on this machine. The union of:
5615
+ * - rows in the `workstreams` table (canonical DB source; populated by
5616
+ * `mu init` and auto-created by insertAgent / addTask)
5617
+ * - mux sessions named `mu-*` (with the prefix stripped) — catches
5618
+ * externally-created sessions (e.g. `tmux new-session -s mu-foo`)
5619
+ * that mu hasn't observed yet
5620
+ *
5621
+ * Returns one `WorkstreamSummary` per workstream, sorted by name.
5622
+ * Useful as a pre-flight before `mu init` ("is this name taken?") and
5623
+ * for `mu doctor`-style diagnostics.
5624
+ */
5279
5625
  declare function listWorkstreams(db: Db): Promise<WorkstreamSummary[]>;
5280
5626
  declare function summarizeWorkstream(db: Db, opts: WorkstreamOptions): Promise<WorkstreamSummary>;
5281
5627
  /**
@@ -5289,4 +5635,4 @@ declare function summarizeWorkstream(db: Db, opts: WorkstreamOptions): Promise<W
5289
5635
  */
5290
5636
  declare function teardownWorkstream(db: Db, opts: TeardownWorkstreamOptions): Promise<TeardownResult>;
5291
5637
 
5292
- export { AGENT_STATE_GLYPH, type AbortAgentOptions, type AbortResult, type AddNoteOptions, type AddTaskOptions, type AdoptAgentOptions, type AdoptAgentResult, AgentAbortNeedsCtlError, AgentAbortTimeoutError, AgentBusyError, AgentCtlUnreachableError, AgentDiedOnSpawnError, AgentExistsError, AgentFreshNeedsCtlError, AgentNotFoundError, AgentNotInWorkstreamError, type AgentRow, AgentSlashCommandUnsupportedError, AgentSpawnCliNotFoundError, AgentSpawnStartupError, type AmbientOptions, type AmbientResult, type AppendLogOptions, type ApplyResult, type BlockEdgeResult, CAPTURE_TRIGGER_DDL, CURRENT_SCHEMA_VERSION, type CaptureDb, type CaptureIntent, type CaptureOptions, type CaseCollision, type CheapDriftReport, type ClaimResult, type ClaimTaskOptions, ClaimerNotRegisteredError, type CloseAgentOptions, type CloseAgentResult, type CloseSubstate, type CloseTaskResult, type CommandResolutionResult, type CommandResolver, CrossWorkstreamEdgeError, type CtlLink, CycleError, DEFAULT_SUBSTATE, DRIFT_REPORT_CAP, type Db, type DeleteTaskResult, type DoctorCheck, type DoctorStatus, type DoctorSummary, DriftDetectedError, type DriftRecord, type DriftReport, EXPECTED_TABLES, type EvidenceOption, type FileLockOptions, type FleetHazard, type FlushResult, type FsProbe, type FullDag, GLYPH, type GroupSummary, type HazardSeverity, type Hlc, HlcOverflowError, HlcParseError, HomeDirAsProjectRootError, type IdFromTitleResult, type IngestFromDbResult, type IngestResult, type InsertAgentInput, InvalidSubstateError, type InverseOp, KNOWN_INTENTS, KNOWN_VERBS, type KickAgentOptions, type KickAgentResult, type KickProcessExecutor, type KickSignal, type KnownIntent, LinkConflictError, type LinkState, type LinkStatus, type ListLiveAgentsOptions, type ListLogsOptions, type ListNotesOptions, type ListReadyOptions, type ListTasksOptions, type LiveAgent, type LiveAgentsView, type LoadFullDagOptions, type LoadWorkstreamSnapshotOptions, type LocalIntent, type LogKind, type LogRow, MACHINE_LOCAL_ENTITIES, MACHINE_LOCAL_TABLES, MU_SHIM_MARKER, MachineIdentityMissingError, type MachineLocalEntity, type MachineLocalLoss, type MachineLocalTable, type MuxBackend, type MuxBackendName, MuxError, type MuxPane, type MuxPaneStatus, type MuxSession, type MuxWindow, type NewSessionOptions, type NewWindowOptions, NoForegroundProcessError, NoMultiplexerError, NothingToUndoError, OP_CTX_DDL, type Op, type OpContext, OpEntityNotSyncedError, OpKeyMalformedError, type OpenDbOptions, type OwnedTasksSummary, PANE_ID_RE, PEER_SHORT_LEN, PEER_STALE_MS, PORTABLE_TABLES, PaneNotFoundError, type ParkTaskOptions, type PeerSegment, type PeerStatus, type PortableTable, type RebuildOptions, type RebuildReport, RebuildTargetExistsError, RebuildTargetIsSourceError, type ReconcileMode, type ReconcileOptions, type ReconcileReport, type ReleaseResult, type ReleaseTaskOptions, type RemoveBlockEdgeResult, type RenderableOp, type RenderedOp, type ReparentTaskResult, type RoiBucket, type RuntimeState, SEGMENT_FORMAT_VERSION, SYNCED_ENTITIES, SchemaTooOldError, type SegmentDefect, type SegmentDefectKind, type SegmentLine, type SegmentManifest, type SendOptions, type SendResult, type SendWarning, type SetStatusOptions, type SetStatusResult, type SlugifyResult, type SpawnAgentOptions, type SplitWindowOptions, type StateReading, type StateSource, type StrandedWorkspaceOrphan, SubstateReasonRequiredError, type SyncPassResult, SyncPeerNotFoundError, SyncPeerRefAmbiguousError, SyncSourceNotFoundError, type SyncedEntity, TASK_STATUSES, TASK_STATUS_LIST, TASK_SUBSTATES, TASK_SUBSTATE_ROWS, TaskAlreadyOwnedError, type TaskEdgeWithStatus, type TaskEdges, type TaskEdgesWithStatus, TaskExistsError, TaskInTriageError, TaskNotFoundError, TaskNotInWorkstreamError, type TaskNoteRow, type TaskPair, TaskParkStateError, TaskParkedError, type TaskRow, type TaskStatus, type TaskSubstate, type TaskWaitOptions, type TaskWaitRef, type TaskWaitResult, type TaskWaitTaskState, type TeardownResult, TmuxError, type TmuxExecResult, type TmuxExecutor, type TmuxPane, type TmuxSession, type TmuxWindow, type Track, type Transport, UNKNOWN_REASON, UndoGroupNotFoundError, type UndoOptions, type UndoPlan, type UndoResult, UndoSupersededError, type UpdateTaskOptions, type UpdateTaskResult, type VcsBackend, type VcsBackendName, WORKSPACE_STALE_THRESHOLD, WorkspaceExistsError, type WorkspaceFailure, WorkspaceNotFoundError, type WorkspaceOrphan, WorkspacePathNotEmptyError, WorkspacePreservedError, type WorkspaceRow, type WorkspaceStaleness, WorkstreamExistsError, WorkstreamNameInvalidError, type WorkstreamOptions, type WorkstreamSnapshot, type WorkstreamSnapshotSlowFields, type WorkstreamSummary, abortAgent, acceptTask, activeMux, addBlockEdge, addNote, addTask, adoptAgent, agentKey, agentStateGlyph, agentStateHistogram, ambientFlush, ambientIngest, ambientSyncPass, appendLog, applyIncomingOp, applyOp, applyOps, assertValidPaneId, awaitPaneQuiescence, backendByName, capturePane, checkCaseCollisions, checkCheapDriftInvariant, checkCommandResolvable, checkDbInsideSyncDir, checkDrift, checkFleetHazards, checkNetworkMount, claimTask, classifyFsType, closeAgent, closeTask, compareHlc, composeAgentTitle, countProblems, createWorkspace, ctlRuntimeState, currentAgentName, currentOpContext, currentPaneTitle, decorateWithDirty, decorateWithStaleness, defaultDbPath, defaultSendDelayMs, defaultSendReadinessMs, defaultSpawnLivenessMs, defaultStateDir, deleteAgent, deleteTask, detectBackend, detectMux, discoverPeers, driftRemediation, emitEvent, ensureWorkstream, envVarNameForCli, expectsCtl, findCaseCollisions, flushSegment, foregroundPgid, formatDriftRecord, formatHlc, formatPair, freeWorkspace, getAgent, getAgentByPane, getParallelTracks, getPrerequisites, getTask, getTaskEdges, getTaskEdgesWithStatus, getWaitPollCount, getWatermark, getWorkspaceForAgent, getWorkspaceStaleness, gitBackend, hasWorkMarker, idFromTitle, idFromTitleVerbose, ingestFromDb, ingestSegment, insertAgent, inspectLinks, installCapture, interruptAgent, isKickSignal, isPathInside, isTaskStatus, isValidAgentName, isValidPair, isValidPaneId, isValidTaskId, isValidWorkstreamName, isWorkspaceStale, jjBackend, kickAgent, killPane, killSession, latestSeq, linkPi, linkSkill, listAgents, listAllOrphanWorkspaces, listBlocked, listGoals, listInProgress, listLiveAgents, listLogs, listNotes, listPanes, listPanesInSession, listReady, listRecentClosed, listRecentGroups, listSessions, listTasks, listTasksByOwner, listWindows, listWorkspaceOrphans, listWorkspaces, listWorkstreams, loadDoctorChecks, loadDoctorSummary, loadFullDag, loadWorkstreamSnapshot, loadWorkstreamSnapshotFast, loadWorkstreamSnapshotSlow, localMachineId, locksDir, mapLegacyStatus, mergeSnapshotFastSlow, mostRecentGroup, murmurAvailable, mux, muxByName, newSession, newSessionWithPane, newWindow, nextHlc, noneBackend, opSubject, openDb, openTask, paneExists, paneTTY, parkTask, parseAgentNameFromTitle, parseHlc, parseOpKey, parsePsTtyOutput, peerStatuses, planUndo, priorFieldValue, probeFilesystem, readAgent, readAgentStates, readFileLockMeta, readManifest, rebuildInto, receiveHlc, reconcile, refreshAgentTitle, releaseTask, remediationParagraph, removeBlockEdge, renderForest, renderOp, renderOpLine, renderTaskTree, repairPeer, reparentTask, resetCommandResolverForTests, resetKickProcessExecutor, resetMux, resetSleep, resetTmuxExecutor, resetWaitPollCount, resetWatermark, resolveActorIdentity, resolveCliCommand, resolveCliCommandWithSource, resolveGroupId, resolvePair, resolvePeerRef, roiBucket, segmentLineCount, segmentPath, selectLayout, sendToAgent, sendToPane, sendViaTransport, sessionExists, setCommandResolverForTests, setKickProcessExecutor, setMuxForTests, setPaneTitle, setSleepForTests, setTaskStatus, setTmuxExecutor, setWaitSleepForTests, setWaitStuckWarnForTests, setWatermark, slBackend, sleep, slugifyTitle, slugifyTitleVerbose, spawnAgent, splitWindow, summarizeOwnedTasks, summarizeWorkstream, syncDir, syncEnabled, syncPass, teardownWorkstream, tmux, tmuxBackend, transportNextSteps, undoGroup, unparkTask, updateTask, verifyAgainstManifest, waitForTasks, withCaptureSuppressed, withFileLock, withOpContext, workspacePath, workspacesRoot, yankCommandForCheck };
5638
+ export { AGENT_STATE_GLYPH, type AbortAgentOptions, type AbortResult, type AddNoteOptions, type AddTaskOptions, type AdoptAgentOptions, type AdoptAgentResult, AgentAbortNeedsCtlError, AgentAbortTimeoutError, AgentBusyError, AgentCtlUnreachableError, AgentDiedOnSpawnError, AgentExistsError, AgentExtensionOutdatedError, AgentFreshNeedsCtlError, AgentNotFoundError, AgentNotInWorkstreamError, type AgentRow, AgentSlashCommandUnsupportedError, AgentSpawnCliNotFoundError, AgentSpawnStartupError, type AmbientOptions, type AmbientResult, type AppendLogOptions, type ApplyResult, type BlockEdgeResult, CAPTURE_TRIGGER_DDL, CURRENT_SCHEMA_VERSION, type CaptureDb, type CaptureIntent, type CaptureOptions, type CaseCollision, type CheapDriftReport, type ClaimResult, type ClaimTaskOptions, ClaimerNotRegisteredError, type CloseAgentOptions, type CloseAgentResult, type CloseSubstate, type CloseTaskResult, type CommandResolutionResult, type CommandResolver, CrossWorkstreamEdgeError, type CtlLink, CycleError, DEFAULT_SUBSTATE, DRIFT_REPORT_CAP, type Db, type DeleteTaskResult, type DoctorCheck, type DoctorStatus, type DoctorSummary, DriftDetectedError, type DriftRecord, type DriftReport, EXPECTED_TABLES, type EvidenceOption, type FileLockOptions, type FleetHazard, type FlushResult, type FsProbe, type FullDag, GLYPH, GroupIdAmbiguousError, type GroupSummary, HazardFailError, type HazardSeverity, type Hlc, HlcOverflowError, HlcParseError, HomeDirAsProjectRootError, type IdFromTitleResult, type IngestFromDbResult, type IngestResult, type InsertAgentInput, InvalidSubstateError, type InverseOp, KNOWN_INTENTS, KNOWN_VERBS, type KickAgentOptions, type KickAgentResult, type KickProcessExecutor, type KickSignal, type KnownIntent, LinkConflictError, type LinkState, type LinkStatus, type ListLiveAgentsOptions, type ListLogsOptions, type ListNotesOptions, type ListReadyOptions, type ListTasksOptions, type LiveAgent, type LiveAgentsView, type LoadFullDagOptions, type LoadWorkstreamSnapshotOptions, type LocalIntent, type LogKind, LogKindReservedError, type LogRow, MACHINE_LOCAL_ENTITIES, MACHINE_LOCAL_TABLES, MU_SHIM_MARKER, MachineIdentityMissingError, type MachineLocalEntity, type MachineLocalLoss, type MachineLocalTable, type MuxBackend, type MuxBackendName, MuxError, type MuxPane, type MuxPaneStatus, type MuxSession, type MuxWindow, type NewSessionOptions, type NewWindowOptions, NoForegroundProcessError, NoMultiplexerError, NothingToUndoError, OP_CTX_DDL, type Op, type OpContext, OpEntityNotSyncedError, OpKeyMalformedError, type OpenDbOptions, type OwnedTasksSummary, PANE_ID_RE, PEER_SHORT_LEN, PEER_STALE_MS, PORTABLE_TABLES, PaneNotFoundError, PaneNotInSessionError, type ParkTaskOptions, type PeerSegment, type PeerStatus, type PortableTable, ReaperDetectedDuringWaitError, type RebuildOptions, type RebuildReport, RebuildTargetExistsError, RebuildTargetIsSourceError, type ReconcileMode, type ReconcileOptions, type ReconcileReport, type ReleaseResult, type ReleaseTaskOptions, type RemoveBlockEdgeResult, type RenderableOp, type RenderedOp, type ReparentTaskResult, type RoiBucket, type RuntimeState, SEGMENT_FORMAT_VERSION, SYNCED_ENTITIES, SchemaTooNewError, SchemaTooOldError, type SegmentDefect, type SegmentDefectKind, type SegmentLine, type SegmentManifest, type SendOptions, type SendResult, type SendWarning, type SetStatusOptions, type SetStatusResult, type SlugifyResult, type SpawnAgentOptions, type SplitWindowOptions, StallDetectedDuringWaitError, type StateReading, type StateSource, type StrandedWorkspaceOrphan, SubstateReasonRequiredError, type SyncPassResult, SyncPeerNotFoundError, SyncPeerRefAmbiguousError, SyncSourceNotFoundError, type SyncedEntity, TASK_STATUSES, TASK_STATUS_LIST, TASK_SUBSTATES, TASK_SUBSTATE_ROWS, TaskAlreadyOwnedError, TaskClaimStaleWorkspaceError, type TaskEdgeWithStatus, type TaskEdges, type TaskEdgesWithStatus, TaskExistsError, TaskIdInvalidError, TaskInTriageError, TaskNotFoundError, TaskNotInWorkstreamError, type TaskNoteRow, type TaskPair, TaskParkStateError, TaskParkedError, type TaskRow, type TaskStatus, type TaskSubstate, TaskTitleSlugEmptyError, type TaskWaitOptions, type TaskWaitRef, type TaskWaitResult, type TaskWaitTaskState, type TeardownResult, TmuxError, type TmuxExecResult, type TmuxExecutor, type TmuxPane, type TmuxSession, type TmuxWindow, type Track, type Transport, UNKNOWN_REASON, UndoGroupNotFoundError, type UndoOptions, type UndoPlan, type UndoResult, UndoSupersededError, type UpdateTaskOptions, type UpdateTaskResult, type VcsBackend, type VcsBackendName, WORKSPACE_STALE_THRESHOLD, WorkspaceConflictError, WorkspaceDirtyError, WorkspaceExistsError, type WorkspaceFailure, WorkspaceNotFoundError, type WorkspaceOrphan, WorkspacePathNotEmptyError, WorkspacePreservedError, type WorkspaceRow, type WorkspaceStaleness, WorkspaceVcsRequiredError, WorkstreamExistsError, WorkstreamNameInvalidError, WorkstreamNameReservedError, WorkstreamNotFoundError, type WorkstreamOptions, type WorkstreamSnapshot, type WorkstreamSnapshotSlowFields, type WorkstreamSummary, abortAgent, acceptTask, activeMux, addBlockEdge, addNote, addTask, adoptAgent, agentKey, agentStateGlyph, agentStateHistogram, ambientFlush, ambientIngest, ambientSyncPass, appendLog, applyIncomingOp, applyOp, applyOps, assertValidPaneId, awaitPaneQuiescence, backendByName, capturePane, checkCaseCollisions, checkCheapDriftInvariant, checkCommandResolvable, checkDbInsideSyncDir, checkDrift, checkFleetHazards, checkNetworkMount, claimTask, classifyFsType, closeAgent, closeTask, compareHlc, composeAgentTitle, countProblems, createWorkspace, ctlRuntimeState, currentAgentName, currentOpContext, currentPaneTitle, decorateWithDirty, decorateWithStaleness, defaultDbPath, defaultSendDelayMs, defaultSendReadinessMs, defaultSpawnLivenessMs, defaultStateDir, deleteAgent, deleteTask, detectBackend, detectMux, discoverPeers, driftRemediation, emitEvent, ensureWorkstream, envVarNameForCli, expectsCtl, findCaseCollisions, flushSegment, foregroundPgid, formatDriftRecord, formatHlc, formatPair, freeWorkspace, getAgent, getAgentByPane, getParallelTracks, getPrerequisites, getTask, getTaskEdges, getTaskEdgesWithStatus, getWaitPollCount, getWatermark, getWorkspaceForAgent, getWorkspaceStaleness, gitBackend, hasWorkMarker, idFromTitle, idFromTitleVerbose, ingestFromDb, ingestSegment, insertAgent, inspectLinks, installCapture, interruptAgent, isKickSignal, isPathInside, isTaskStatus, isValidAgentName, isValidPair, isValidPaneId, isValidTaskId, isValidWorkstreamName, isWorkspaceStale, jjBackend, kickAgent, killPane, killSession, latestSeq, linkPi, linkSkill, listAgents, listAllOrphanWorkspaces, listBlocked, listGoals, listInProgress, listLiveAgents, listLogs, listNotes, listPanes, listPanesInSession, listReady, listRecentClosed, listRecentGroups, listSessions, listTasks, listTasksByOwner, listWindows, listWorkspaceOrphans, listWorkspaces, listWorkstreams, loadDoctorChecks, loadDoctorSummary, loadFullDag, loadWorkstreamSnapshot, loadWorkstreamSnapshotFast, loadWorkstreamSnapshotSlow, localMachineId, locksDir, mapLegacyStatus, mergeSnapshotFastSlow, mostRecentGroup, murmurAvailable, mux, muxByName, newSession, newSessionWithPane, newWindow, nextHlc, noneBackend, opSubject, openDb, openTask, paneExists, paneTTY, parkTask, parseAgentNameFromTitle, parseHlc, parseOpKey, parsePsTtyOutput, peerStatuses, planUndo, priorFieldValue, probeFilesystem, readAgent, readAgentStates, readFileLockMeta, readManifest, rebuildInto, receiveHlc, reconcile, refreshAgentTitle, releaseTask, remediationParagraph, removeBlockEdge, renderForest, renderOp, renderOpLine, renderTaskTree, repairPeer, reparentTask, resetCommandResolverForTests, resetKickProcessExecutor, resetMux, resetSleep, resetTmuxExecutor, resetWaitPollCount, resetWatermark, resolveActorIdentity, resolveCliCommand, resolveCliCommandWithSource, resolveGroupId, resolvePair, resolvePeerRef, roiBucket, segmentLineCount, segmentPath, selectLayout, sendToAgent, sendToPane, sendViaTransport, sessionExists, setCommandResolverForTests, setKickProcessExecutor, setMuxForTests, setPaneTitle, setSleepForTests, setTaskStatus, setTmuxExecutor, setWaitSleepForTests, setWaitStuckWarnForTests, setWatermark, slBackend, sleep, slugifyTitle, slugifyTitleVerbose, spawnAgent, splitWindow, summarizeOwnedTasks, summarizeWorkstream, syncDir, syncEnabled, syncPass, teardownWorkstream, tmux, tmuxBackend, transportNextSteps, undoGroup, unparkTask, updateTask, verifyAgainstManifest, waitForTasks, withCaptureSuppressed, withFileLock, withOpContext, workspacePath, workspacesRoot, yankCommandForCheck };