@mu-crew/mu 1.6.0 → 3.0.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
@@ -1,5 +1,36 @@
1
1
  import { Database } from 'better-sqlite3';
2
2
 
3
+ type RuntimeState = "busy" | "needs_input" | "needs_permission" | "unknown";
4
+ type StateSource = "murmur" | "herdr" | "none";
5
+ interface StateReading {
6
+ state: RuntimeState;
7
+ source: StateSource;
8
+ since: number | null;
9
+ alive: boolean;
10
+ reason?: string;
11
+ }
12
+ interface StateAgentRef {
13
+ name: string;
14
+ workstreamName: string;
15
+ paneId: string;
16
+ }
17
+ declare const UNKNOWN_REASON: {
18
+ readonly murmurMissing: "murmur not installed";
19
+ readonly extensionMissing: "murmur pi extension not linked";
20
+ readonly noRow: "murmur has no row";
21
+ readonly stale: "remote snapshot stale";
22
+ readonly herdrNone: "herdr reports no state";
23
+ readonly paneGone: "pane gone";
24
+ };
25
+ declare function agentKey(a: {
26
+ name: string;
27
+ workstreamName: string;
28
+ }): string;
29
+ declare function murmurAvailable(): boolean;
30
+ declare function readAgentStates(agents: readonly StateAgentRef[], opts?: {
31
+ now?: number;
32
+ }): Promise<Map<string, StateReading>>;
33
+
3
34
  /**
4
35
  * One actionable next step. The `intent` is human-prose ("Drop notes
5
36
  * as you work"); the `command` is a literal shell command the user (or
@@ -67,14 +98,14 @@ declare class SchemaTooOldError extends Error implements HasNextSteps {
67
98
  constructor(detectedVersion: number, requiredVersion: number);
68
99
  errorNextSteps(): NextStep[];
69
100
  }
70
- /** The schema version a fresh DB starts at. v10 drops the REJECTED
71
- * and DEFERRED task statuses (three-state lifecycle: OPEN,
72
- * IN_PROGRESS, CLOSED). See CHANGELOG.md. */
73
- declare const CURRENT_SCHEMA_VERSION = 10;
101
+ /** The schema version a fresh DB starts at. v11 adds tasks.substate
102
+ * and the task_substates lookup table on top of v10's three-state
103
+ * lifecycle (OPEN, IN_PROGRESS, CLOSED). See CHANGELOG.md. */
104
+ declare const CURRENT_SCHEMA_VERSION = 11;
74
105
  /** Tables a healthy DB must contain. Single source of truth so
75
106
  * `mu doctor` and any other consumer don't drift. Adding a new table
76
107
  * = one new entry here AND a CREATE TABLE in CURRENT_SCHEMA, plus a
77
- * CURRENT_SCHEMA_VERSION bump. Sorted; exactly 10 entries in v10. */
108
+ * CURRENT_SCHEMA_VERSION bump. Sorted; exactly 11 entries in v11. */
78
109
  declare const EXPECTED_TABLES: readonly string[];
79
110
  /** Op entities that cross machines. Everything else is machine-local.
80
111
  * Readonly tuple (not `string[]`) so `SyncedEntity` is a real union
@@ -118,6 +149,8 @@ type PortableTable = (typeof PORTABLE_TABLES)[number];
118
149
  * machine_identity IS the per-machine identity.
119
150
  * schema_version local bookkeeping.
120
151
  * sync_peers local bookkeeping (per-peer watermarks).
152
+ * task_substates seeded identically on every machine from
153
+ * TASK_SUBSTATE_ROWS; code, not data.
121
154
  * ops see below — the carrier, not cargo.
122
155
  *
123
156
  * `ops` is listed here deliberately rather than omitted. It is not
@@ -132,73 +165,13 @@ type PortableTable = (typeof PORTABLE_TABLES)[number];
132
165
  * is an FK into `agents`, and `agents` is machine-local. Therefore
133
166
  * OWNERSHIP DOES NOT SYNC. The deleted db-sync.ts reached the same
134
167
  * conclusion via an `includeOwners` flag; here it is structural. */
135
- declare const MACHINE_LOCAL_TABLES: readonly ["agents", "machine_identity", "ops", "schema_version", "sync_peers", "vcs_workspaces"];
168
+ declare const MACHINE_LOCAL_TABLES: readonly ["agents", "machine_identity", "ops", "schema_version", "sync_peers", "task_substates", "vcs_workspaces"];
136
169
  type MachineLocalTable = (typeof MACHINE_LOCAL_TABLES)[number];
137
170
 
138
- /**
139
- * The full agent lifecycle status. Most values are scrollback-derived
140
- * (`DetectedStatus`); the rest are set by the lifecycle layer.
141
- */
142
- type AgentStatus = "spawning" | "busy" | "needs_input" | "needs_permission" | "free" | "unreachable" | "terminated";
143
- /** Status that can be inferred from pane scrollback. */
144
- type DetectedStatus = "busy" | "needs_input" | "needs_permission";
145
- /**
146
- * Run the detector against pane scrollback and return the inferred
147
- * status. Permission overrides busy.
148
- */
149
- declare function detectPiStatus(scrollback: string): DetectedStatus;
150
- /**
151
- * Public for tests — extract the tail window the detector actually
152
- * inspects. Take last TAIL_WINDOW_LINES, strip trailing blanks, take
153
- * last TAIL_LINES.
154
- */
155
- declare function extractTail(scrollback: string): string;
156
-
157
- /**
158
- * Agent status → glyph, used by CLI and TUI status surfaces.
159
- */
160
- declare const AGENT_STATUS_GLYPH: Record<AgentStatus, string>;
161
- /**
162
- * Single rendering helper for agent status glyphs. Keep callers off
163
- * AGENT_STATUS_GLYPH indexing so the fallback policy stays in one place.
164
- */
165
- declare function agentStatusGlyph(status: AgentStatus): string;
166
- /**
167
- * Non-agent state glyphs, keyed by what they MEAN rather than what
168
- * they look like. A call site asks for `GLYPH.stale`, never for a
169
- * clock — so re-pointing the clock is a one-line edit here.
170
- *
171
- * `ok` / `fail` / `warn` deliberately reuse the same codepoints as the
172
- * agent statuses they rhyme with (`free`, `terminated`): a check-circle
173
- * means "fine" whether the row is an agent, a workspace or a doctor
174
- * check.
175
- */
176
- declare const GLYPH: {
177
- /** Healthy, clean, passing, closed-successfully. */
178
- readonly ok: "";
179
- /** Failed check. */
180
- readonly fail: "";
181
- /** Needs attention but not broken (idle-but-assigned, stale warning). */
182
- readonly warn: "";
183
- /** Workspace has uncommitted edits. */
184
- readonly dirty: "";
185
- /** Workspace is ≥ WORKSPACE_STALE_THRESHOLD commits behind main. */
186
- readonly stale: "";
187
- /** Task is blocked by an incoming edge. */
188
- readonly blocked: "";
189
- /** Track whose roots merged (diamond dependency). */
190
- readonly merge: "";
191
- /** Agent owns more than one task (pane-title multi-count slot). */
192
- readonly multi: "";
193
- /** Filter toggle: enabled / disabled. */
194
- readonly on: "";
195
- readonly off: "";
196
- /** Status outside the known enum. */
197
- readonly unknown: "";
198
- };
199
-
200
171
  /** The multiplexers mu can drive. */
201
172
  type MuxBackendName = "herdr" | "tmux";
173
+ /** Runtime states a mux backend can report directly for one pane. */
174
+ type MuxPaneStatus = "busy" | "needs_input" | "needs_permission";
202
175
  interface MuxSession {
203
176
  name: string;
204
177
  }
@@ -458,22 +431,11 @@ interface MuxBackend {
458
431
  sendToPane(paneId: string, text: string, opts?: SendOptions): Promise<void>;
459
432
  capturePane(paneId: string, opts?: CaptureOptions): Promise<string>;
460
433
  /**
461
- * The pane's lifecycle status AS THE MUX ITSELF CLASSIFIES IT, or
462
- * undefined when the pane is gone / unclassified.
463
- *
464
- * OPTIONAL by design, and the one place the two backends genuinely
465
- * differ in kind rather than in syntax. tmux knows nothing about what
466
- * runs inside a pane, so it omits this and mu falls back to scraping
467
- * scrollback with the per-CLI detector in `src/detect.ts`. herdr
468
- * watches the terminal continuously across every agent kind it
469
- * recognises, so it implements this and the detector is BYPASSED
470
- * entirely — guessing from a 100-line tail would be strictly worse
471
- * information than the substrate's own answer.
472
- *
473
- * Absent method ⇒ "ask the detector". Present-but-undefined result ⇒
474
- * "this pane has no status", NOT "free": no detector may mint `free`.
434
+ * The pane's runtime state as the mux itself reports it, or undefined
435
+ * when the pane is gone or unclassified. tmux omits this capability;
436
+ * herdr reports it directly.
475
437
  */
476
- paneStatus?(paneId: string): Promise<DetectedStatus | undefined>;
438
+ paneStatus?(paneId: string): Promise<MuxPaneStatus | undefined>;
477
439
  enableMuPaneBordersForSession(session: string): Promise<number>;
478
440
  enableMuPaneBordersForPane(paneId: string): Promise<void>;
479
441
  /** Copy-pasteable shell line that lands the user on `target`. */
@@ -570,9 +532,8 @@ declare class HerdrSyntaxError extends Error {
570
532
  *
571
533
  * A REFUSAL, not a fallback. herdr's `pane run <command>` would happily
572
534
  * start the binary, but herdr would then never classify that pane, and
573
- * on this backend herdr's classification IS mu's status source
574
- * (`paneStatus()` bypasses src/detect.ts entirely). A pane mu can start
575
- * but never observe is the same family of failure as a pane mu records
535
+ * on this backend herdr's report is mu's runtime state source. A pane
536
+ * mu can start but never observe is the same family of failure as a pane mu records
576
537
  * with nothing running in it: it looks fine and lies forever.
577
538
  *
578
539
  * Not a `MuxError`: the substrate is healthy and answered precisely.
@@ -955,9 +916,8 @@ declare function hasWorkMarker(scrollback: string): boolean;
955
916
  *
956
917
  * Because the blocker is a model call, no fixed sleep can be correct —
957
918
  * `sleep 2` is a coin flip, not a fix. The signal already existed: pi's
958
- * spinner is a Braille glyph and `detectPiStatus` calls Braille busy,
959
- * so this reuses the detector rather than adding a second readiness
960
- * mechanism, matching `awaitSpawnReadiness` in src/agents/spawn.ts.
919
+ * spinner is a Braille glyph, so the private input-timing helper can wait
920
+ * for it to clear before sending.
961
921
  *
962
922
  * `needs_permission` counts as ready: a pane sitting on a confirm
963
923
  * dialog is waiting for a keystroke, and refusing to send would break
@@ -1054,6 +1014,7 @@ type mux_MuxError = MuxError;
1054
1014
  declare const mux_MuxError: typeof MuxError;
1055
1015
  type mux_MuxHealth = MuxHealth;
1056
1016
  type mux_MuxPane = MuxPane;
1017
+ type mux_MuxPaneStatus = MuxPaneStatus;
1057
1018
  type mux_MuxSession = MuxSession;
1058
1019
  type mux_MuxWindow = MuxWindow;
1059
1020
  type mux_NewSessionOptions = NewSessionOptions;
@@ -1079,7 +1040,7 @@ declare const mux_setHerdrExecutor: typeof setHerdrExecutor;
1079
1040
  declare const mux_setMuxForTests: typeof setMuxForTests;
1080
1041
  declare const mux_tmuxBackend: typeof tmuxBackend;
1081
1042
  declare namespace mux {
1082
- export { type mux_AttachTarget as AttachTarget, type mux_CaptureOptions as CaptureOptions, mux_HerdrCommandOverrideError as HerdrCommandOverrideError, mux_HerdrError as HerdrError, mux_HerdrNotImplementedError as HerdrNotImplementedError, mux_HerdrSyntaxError as HerdrSyntaxError, mux_HerdrUnsupportedCliError as HerdrUnsupportedCliError, mux_HerdrWorkspaceGroupCloseError as HerdrWorkspaceGroupCloseError, type mux_MuxBackend as MuxBackend, type mux_MuxBackendName as MuxBackendName, type mux_MuxCommand as MuxCommand, type mux_MuxDiagnostics as MuxDiagnostics, mux_MuxError as MuxError, type mux_MuxHealth as MuxHealth, type mux_MuxPane as MuxPane, type mux_MuxSession as MuxSession, type mux_MuxWindow as MuxWindow, type mux_NewSessionOptions as NewSessionOptions, type mux_NewSessionWithPaneOptions as NewSessionWithPaneOptions, type mux_NewWindowOptions as NewWindowOptions, mux_NoMultiplexerError as NoMultiplexerError, mux_PaneNotFoundError as PaneNotFoundError, type mux_SendOptions as SendOptions, type mux_SendWarning as SendWarning, type mux_SplitWindowOptions as SplitWindowOptions, type mux_StartAgentInPaneOptions as StartAgentInPaneOptions, mux_activeMux as activeMux, mux_detectMux as detectMux, mux_herdrBackend as herdrBackend, mux_isHerdrStatusUsable as isHerdrStatusUsable, mux_muxByName as muxByName, mux_parseAgentNameFromTitle as parseAgentNameFromTitle, mux_resetHerdrExecutor as resetHerdrExecutor, mux_resetMux as resetMux, mux_setHerdrExecutor as setHerdrExecutor, mux_setMuxForTests as setMuxForTests, mux_tmuxBackend as tmuxBackend };
1043
+ export { type mux_AttachTarget as AttachTarget, type mux_CaptureOptions as CaptureOptions, mux_HerdrCommandOverrideError as HerdrCommandOverrideError, mux_HerdrError as HerdrError, mux_HerdrNotImplementedError as HerdrNotImplementedError, mux_HerdrSyntaxError as HerdrSyntaxError, mux_HerdrUnsupportedCliError as HerdrUnsupportedCliError, mux_HerdrWorkspaceGroupCloseError as HerdrWorkspaceGroupCloseError, type mux_MuxBackend as MuxBackend, type mux_MuxBackendName as MuxBackendName, type mux_MuxCommand as MuxCommand, type mux_MuxDiagnostics as MuxDiagnostics, mux_MuxError as MuxError, type mux_MuxHealth as MuxHealth, type mux_MuxPane as MuxPane, type mux_MuxPaneStatus as MuxPaneStatus, type mux_MuxSession as MuxSession, type mux_MuxWindow as MuxWindow, type mux_NewSessionOptions as NewSessionOptions, type mux_NewSessionWithPaneOptions as NewSessionWithPaneOptions, type mux_NewWindowOptions as NewWindowOptions, mux_NoMultiplexerError as NoMultiplexerError, mux_PaneNotFoundError as PaneNotFoundError, type mux_SendOptions as SendOptions, type mux_SendWarning as SendWarning, type mux_SplitWindowOptions as SplitWindowOptions, type mux_StartAgentInPaneOptions as StartAgentInPaneOptions, mux_activeMux as activeMux, mux_detectMux as detectMux, mux_herdrBackend as herdrBackend, mux_isHerdrStatusUsable as isHerdrStatusUsable, mux_muxByName as muxByName, mux_parseAgentNameFromTitle as parseAgentNameFromTitle, mux_resetHerdrExecutor as resetHerdrExecutor, mux_resetMux as resetMux, mux_setHerdrExecutor as setHerdrExecutor, mux_setMuxForTests as setMuxForTests, mux_tmuxBackend as tmuxBackend };
1083
1044
  }
1084
1045
 
1085
1046
  /**
@@ -1130,9 +1091,6 @@ interface ReconcileReport {
1130
1091
  * this is the count of rows that WOULD have been pruned; in `full`
1131
1092
  * mode it's the count actually deleted. */
1132
1093
  prunedGhosts: number;
1133
- /** Number of agents whose status was changed by scrollback detection.
1134
- * Always 0 in `report-only` mode (status detection is skipped). */
1135
- statusChanges: number;
1136
1094
  /** Panes in the workstream's tmux session that look like agents but
1137
1095
  * aren't in the registry. NOT auto-adopted. */
1138
1096
  orphans: MuxPane[];
@@ -1823,7 +1781,6 @@ interface AgentRow {
1823
1781
  workstreamName: string;
1824
1782
  cli: string;
1825
1783
  paneId: string;
1826
- status: AgentStatus;
1827
1784
  role: string;
1828
1785
  /** Window name; null when the agent has its own window named after itself. */
1829
1786
  tab: string | null;
@@ -1831,27 +1788,19 @@ interface AgentRow {
1831
1788
  createdAt: string;
1832
1789
  /** ISO 8601 timestamp. */
1833
1790
  updatedAt: string;
1834
- /**
1835
- * Derived 'idle but assigned' flag (idle_assigned_agent_detection).
1836
- * Set ONLY by `listLiveAgents` (and the helper `computeAgentIdle`);
1837
- * never stored in the DB. Predicate:
1838
- * status === 'needs_input'
1839
- * AND owns ≥1 IN_PROGRESS task in this workstream
1840
- * AND (now - updated_at) >= MU_IDLE_THRESHOLD_MS (default 300_000ms)
1841
- *
1842
- * Surfaces the third lifecycle state (alive but assigned, no recent
1843
- * progress) to `mu state` renders + `mu state --json`. Omitted (i.e.
1844
- * absent — NOT `false`) when the predicate doesn't fire, so JSON
1845
- * consumers can do a simple `if (agent.idle)` check and the field
1846
- * stays out of the way for callers that don't care.
1847
- */
1791
+ }
1792
+ interface LiveAgent extends AgentRow {
1793
+ state: RuntimeState;
1794
+ source: StateSource;
1795
+ /** ISO 8601 time when the source entered this state. */
1796
+ since: string | null;
1797
+ reason?: string;
1848
1798
  idle?: boolean;
1849
1799
  }
1850
1800
  interface InsertAgentInput {
1851
1801
  name: string;
1852
1802
  workstream: string;
1853
1803
  paneId: string;
1854
- status: AgentStatus;
1855
1804
  /** Defaults to "pi" via schema DEFAULT. */
1856
1805
  cli?: string;
1857
1806
  /** Defaults to "full-access" via schema DEFAULT. */
@@ -1875,19 +1824,6 @@ declare function getAgent(db: Db, name: string, workstream: string): AgentRow |
1875
1824
  declare function listAgents(db: Db, opts?: {
1876
1825
  workstream?: string;
1877
1826
  }): AgentRow[];
1878
- /**
1879
- * Update an agent's status. Returns true if a row was matched.
1880
- * Also bumps updated_at. Workstream is required (v5: agents.name is
1881
- * per-workstream unique).
1882
- */
1883
- declare function updateAgentStatus(db: Db, name: string, status: AgentStatus, workstream: string): boolean;
1884
- /** Back-compat alias for the agent status glyph map, which now lives
1885
- * with every other state glyph in src/glyphs.ts. New code should
1886
- * import AGENT_STATUS_GLYPH (or the agentStatusGlyph helper) from
1887
- * there; this name is kept because it is part of the SDK surface via
1888
- * src/index.ts. */
1889
- declare const STATUS_EMOJI: Record<AgentStatus, string>;
1890
-
1891
1827
  /** Build the pane title for `agent` based on current DB state.
1892
1828
  * Pure (no tmux side effect; no DB write). Read-only on the DB. */
1893
1829
  declare function composeAgentTitle(db: Db, agent: AgentRow): string;
@@ -2013,7 +1949,7 @@ interface ListLiveAgentsOptions {
2013
1949
  }
2014
1950
  interface LiveAgentsView {
2015
1951
  /** All registered agents in the workstream, post-reconcile. */
2016
- agents: AgentRow[];
1952
+ agents: LiveAgent[];
2017
1953
  /** Panes in the tmux session that look like agents but aren't registered. */
2018
1954
  orphans: MuxPane[];
2019
1955
  /** Diagnostic numbers from the reconcile pass; useful for `mu doctor`. */
@@ -2171,8 +2107,8 @@ interface CaptureDb {
2171
2107
  }
2172
2108
 
2173
2109
  type TaskStatus = "OPEN" | "IN_PROGRESS" | "CLOSED";
2174
- /** Every legal task status, in canonical order (matches the schema
2175
- * CHECK clause). Exported so CLI surfaces (`--status` validators,
2110
+ /** Every legal task status, in canonical order (matches the seeded
2111
+ * task_substates rows). Exported so CLI surfaces (`--status` validators,
2176
2112
  * --help text, error messages) name them all in one place; missing
2177
2113
  * one used to silently lie about the supported set. */
2178
2114
  declare const TASK_STATUSES: readonly TaskStatus[];
@@ -2182,15 +2118,50 @@ declare function isTaskStatus(s: string): s is TaskStatus;
2182
2118
  * --help text and error messages so adding a new status doesn't
2183
2119
  * leave stale lists rotting in the CLI surface. */
2184
2120
  declare const TASK_STATUS_LIST: string;
2121
+ /** Legal substates per status. `substate` qualifies `status` and never
2122
+ * touches edge semantics: only `status === "CLOSED"` satisfies a
2123
+ * `blocks` edge. */
2124
+ declare const TASK_SUBSTATES: {
2125
+ readonly OPEN: readonly ["todo", "parked"];
2126
+ readonly IN_PROGRESS: readonly ["active"];
2127
+ readonly CLOSED: readonly ["done", "wontfix", "duplicate", "superseded"];
2128
+ };
2129
+ type TaskSubstate = (typeof TASK_SUBSTATES)[TaskStatus][number];
2130
+ /** The substate a status takes when none is given. Never null: an
2131
+ * absent value must not carry meaning. */
2132
+ declare const DEFAULT_SUBSTATE: {
2133
+ readonly [S in TaskStatus]: (typeof TASK_SUBSTATES)[S][number];
2134
+ };
2135
+ interface TaskPair {
2136
+ status: TaskStatus;
2137
+ substate: TaskSubstate;
2138
+ }
2139
+ /** Rows for seeding task_substates: [status, substate, isDefault]. */
2140
+ declare const TASK_SUBSTATE_ROWS: ReadonlyArray<readonly [TaskStatus, TaskSubstate, 0 | 1]>;
2141
+ declare function isValidPair(status: string, substate: string): boolean;
2142
+ /** REJECTED -> {CLOSED, wontfix}; DEFERRED -> {OPEN, parked}; else null. */
2143
+ declare function mapLegacyStatus(value: string): TaskPair | null;
2144
+ /** Map a stored/remote pair onto a legal one. Legacy status -> mapped pair
2145
+ * (ignores substate arg). Unknown status -> null. Known status with
2146
+ * unknown/missing/mismatched substate -> {status, DEFAULT_SUBSTATE[status]}. */
2147
+ declare function resolvePair(status: string, substate: unknown): TaskPair | null;
2148
+ /** "OPEN" for default pairs, "OPEN/parked" otherwise. Shared by CLI + TUI. */
2149
+ declare function formatPair(pair: TaskPair): string;
2185
2150
 
2186
2151
  interface SetStatusResult {
2187
2152
  /** Status before the call. */
2188
2153
  previousStatus: TaskStatus;
2189
2154
  /** Status after the call (== requested status). */
2190
2155
  status: TaskStatus;
2191
- /** True iff the row actually changed. False on idempotent no-op. */
2156
+ /** Substate before the call. */
2157
+ previousSubstate: TaskSubstate;
2158
+ /** Substate after the call (== requested substate, or the status default). */
2159
+ substate: TaskSubstate;
2160
+ /** True iff status OR substate changed. False on idempotent no-op. */
2192
2161
  changed: boolean;
2193
2162
  }
2163
+ /** The substates a task can be closed as (`mu task close --as`). */
2164
+ type CloseSubstate = Extract<TaskSubstate, "done" | "wontfix" | "duplicate" | "superseded">;
2194
2165
  /**
2195
2166
  * Optional evidence string carried on lifecycle verbs (close / open /
2196
2167
  * claim / release). Lands in the auto-emitted `kind='event'` payload
@@ -2202,14 +2173,19 @@ interface SetStatusResult {
2202
2173
  interface EvidenceOption {
2203
2174
  evidence?: string;
2204
2175
  }
2176
+ interface SetStatusOptions extends EvidenceOption {
2177
+ workstream: string;
2178
+ /** Substate to land on; defaults to DEFAULT_SUBSTATE[status]. A pair
2179
+ * outside TASK_SUBSTATES throws InvalidSubstateError before any write. */
2180
+ substate?: TaskSubstate;
2181
+ }
2205
2182
  /**
2206
- * Flip a task's status to any of OPEN / IN_PROGRESS / CLOSED.
2207
- * Idempotent: setting a task to its current status is a no-op (returns
2183
+ * Flip a task's status to any of OPEN / IN_PROGRESS / CLOSED, writing
2184
+ * status and substate in ONE UPDATE (one op, one HLC — spec D7).
2185
+ * Idempotent: setting a task to its current pair is a no-op (returns
2208
2186
  * `changed: false`) rather than throwing. Owner is unchanged.
2209
2187
  */
2210
- declare function setTaskStatus(db: Db, localId: string, status: TaskStatus, opts: EvidenceOption & {
2211
- workstream: string;
2212
- }): SetStatusResult;
2188
+ declare function setTaskStatus(db: Db, localId: string, status: TaskStatus, opts: SetStatusOptions): SetStatusResult;
2213
2189
  /** Result of `closeTask` when called with `ifReady: true` and the
2214
2190
  * task is NOT yet ready to close (still has at least one OPEN /
2215
2191
  * IN_PROGRESS blocker). Distinguished from a regular `SetStatusResult`
@@ -2230,6 +2206,9 @@ interface CloseSkippedResult {
2230
2206
  previousStatus: TaskStatus;
2231
2207
  /** Status after the call (== previousStatus, since we no-op). */
2232
2208
  status: TaskStatus;
2209
+ /** Substate before (and after) the call. */
2210
+ previousSubstate: TaskSubstate;
2211
+ substate: TaskSubstate;
2233
2212
  /** Always false on a skip (no row mutated). */
2234
2213
  changed: false;
2235
2214
  /** Local ids of every blocker still in OPEN or IN_PROGRESS, sorted
@@ -2254,6 +2233,19 @@ interface CloseTaskOptions extends EvidenceOption {
2254
2233
  * as a bare `addNote` without `--author`). Surfaced in mufeedback
2255
2234
  * task_close_evidence_does_not_append_the. */
2256
2235
  author?: string;
2236
+ /** Closing substate; default "done". Any CLOSED/* satisfies edges. */
2237
+ as?: CloseSubstate;
2238
+ /** Required (non-empty) unless `as` is "done"; stored as a
2239
+ * `<AS>: <why>` note in the same op group. */
2240
+ why?: string;
2241
+ }
2242
+ /** Result of a close that ran (not skipped). */
2243
+ interface CloseTaskResult extends SetStatusResult {
2244
+ /** Direct same-workstream dependents that entered the `ready` view
2245
+ * because of this close, sorted. Computed only when `as` is not
2246
+ * "done" (spec D3: a non-done close must show what it released);
2247
+ * always [] for a done close. */
2248
+ unblocked: string[];
2257
2249
  }
2258
2250
  /** Convenience: setTaskStatus(db, id, "CLOSED"). Accepts evidence.
2259
2251
  * Skipped
@@ -2265,12 +2257,30 @@ interface CloseTaskOptions extends EvidenceOption {
2265
2257
  * `mu task close --if-ready` so an orchestrator can fire-and-forget
2266
2258
  * the umbrella close after every blocker resolves without first
2267
2259
  * re-querying the graph. */
2268
- declare function closeTask(db: Db, localId: string, opts: CloseTaskOptions): SetStatusResult | CloseSkippedResult;
2260
+ declare function closeTask(db: Db, localId: string, opts: CloseTaskOptions): CloseTaskResult | CloseSkippedResult;
2269
2261
  /** Convenience: setTaskStatus(db, id, "OPEN"). Owner intentionally NOT
2270
2262
  * cleared — use `releaseTask` for that. Accepts evidence. */
2271
2263
  declare function openTask(db: Db, localId: string, opts: EvidenceOption & {
2272
2264
  workstream: string;
2273
2265
  }): SetStatusResult;
2266
+ interface ParkTaskOptions extends EvidenceOption {
2267
+ workstream: string;
2268
+ /** Required, non-empty; stored as a `PARKED: <why>` note. */
2269
+ why: string;
2270
+ author?: string;
2271
+ }
2272
+ /**
2273
+ * OPEN/todo → OPEN/parked: keep the task out of `ready` / `next` and
2274
+ * make `claim` refuse it without `--force`. Its dependents stay blocked
2275
+ * (parked is still OPEN). Idempotent on OPEN/parked (no second note).
2276
+ * Refuses IN_PROGRESS (release first) and CLOSED (open first) — one
2277
+ * verb, one transition.
2278
+ */
2279
+ declare function parkTask(db: Db, localId: string, opts: ParkTaskOptions): SetStatusResult;
2280
+ /** OPEN/parked → OPEN/todo. A no-op (`changed: false`) on any other pair. */
2281
+ declare function unparkTask(db: Db, localId: string, opts: EvidenceOption & {
2282
+ workstream: string;
2283
+ }): SetStatusResult;
2274
2284
 
2275
2285
  interface ReleaseResult {
2276
2286
  /** The previous owner (null if the task was already unowned). */
@@ -2372,6 +2382,12 @@ interface ClaimTaskOptions extends EvidenceOption {
2372
2382
  * title (e.g. "deploy-bot" rather than "pi-mu").
2373
2383
  */
2374
2384
  actor?: string;
2385
+ /**
2386
+ * Claim an OPEN/parked task anyway. Without it, a parked task throws
2387
+ * TaskParkedError before any write: parking means "keep out of the
2388
+ * scheduler", so overriding it must be explicit.
2389
+ */
2390
+ force?: boolean;
2375
2391
  }
2376
2392
  interface ClaimResult {
2377
2393
  /** The agent now owning the task, or null when the claim was anonymous (--self). */
@@ -2440,6 +2456,8 @@ interface TaskRow {
2440
2456
  workstreamName: string;
2441
2457
  title: string;
2442
2458
  status: TaskStatus;
2459
+ /** Qualifies status (e.g. OPEN/parked, CLOSED/wontfix). Never null. */
2460
+ substate: TaskSubstate;
2443
2461
  impact: number;
2444
2462
  effortDays: number;
2445
2463
  /** Foreign-name reference to the owning agent (NULL when unowned). */
@@ -2466,6 +2484,7 @@ interface TaskEdges {
2466
2484
  interface TaskEdgeWithStatus {
2467
2485
  name: string;
2468
2486
  status: TaskStatus;
2487
+ substate: TaskSubstate;
2469
2488
  }
2470
2489
  interface TaskEdgesWithStatus {
2471
2490
  /** Tasks that must close before this one can start (blockers),
@@ -2931,6 +2950,56 @@ declare class CrossWorkstreamEdgeError extends Error implements HasNextSteps {
2931
2950
  constructor(blocker: string, blockerWorkstream: string, dependent: string, dependentWorkstream: string);
2932
2951
  errorNextSteps(): NextStep[];
2933
2952
  }
2953
+ /**
2954
+ * Thrown by `closeTask` (non-`done` `--as`) and `parkTask` when no
2955
+ * non-empty `--why` was given. The reason is stored as a note, so a
2956
+ * classification with no rationale is refused before any write.
2957
+ */
2958
+ declare class SubstateReasonRequiredError extends Error implements HasNextSteps {
2959
+ readonly verb: "close" | "park";
2960
+ readonly substate: TaskSubstate;
2961
+ readonly taskId: string;
2962
+ readonly name = "SubstateReasonRequiredError";
2963
+ constructor(verb: "close" | "park", substate: TaskSubstate, taskId: string);
2964
+ errorNextSteps(): NextStep[];
2965
+ }
2966
+ /**
2967
+ * Thrown by `parkTask` on an IN_PROGRESS or CLOSED task. Park is one
2968
+ * transition (OPEN/todo → OPEN/parked); the owner releases, or the task
2969
+ * is reopened, first.
2970
+ */
2971
+ declare class TaskParkStateError extends Error implements HasNextSteps {
2972
+ readonly taskId: string;
2973
+ readonly status: "IN_PROGRESS" | "CLOSED";
2974
+ readonly workstream: string;
2975
+ readonly name = "TaskParkStateError";
2976
+ constructor(taskId: string, status: "IN_PROGRESS" | "CLOSED", workstream: string);
2977
+ errorNextSteps(): NextStep[];
2978
+ }
2979
+ /**
2980
+ * Thrown by `claimTask` on an OPEN/parked task without `force`. Parked
2981
+ * means "keep out of the scheduler"; claiming it anyway is explicit.
2982
+ */
2983
+ declare class TaskParkedError extends Error implements HasNextSteps {
2984
+ readonly taskId: string;
2985
+ readonly workstream: string;
2986
+ readonly name = "TaskParkedError";
2987
+ constructor(taskId: string, workstream: string);
2988
+ errorNextSteps(): NextStep[];
2989
+ }
2990
+ /**
2991
+ * Thrown when a verb is asked for a (status, substate) pair that the
2992
+ * task_substates table does not allow, e.g. `close --as parked`.
2993
+ * Caught here rather than by the deferred FK, which would fail only at
2994
+ * commit with an opaque constraint message.
2995
+ */
2996
+ declare class InvalidSubstateError extends Error implements HasNextSteps {
2997
+ readonly status: TaskStatus;
2998
+ readonly substate: string;
2999
+ readonly name = "InvalidSubstateError";
3000
+ constructor(status: TaskStatus, substate: string);
3001
+ errorNextSteps(): NextStep[];
3002
+ }
2934
3003
 
2935
3004
  declare function isValidTaskId(id: string): boolean;
2936
3005
  /**
@@ -3035,6 +3104,8 @@ declare function getTask(db: Db, localId: string, workstream: string): TaskRow |
3035
3104
  interface ListTasksOptions {
3036
3105
  /** Filter to one or more lifecycle statuses. Omitted = all statuses. */
3037
3106
  status?: TaskStatus | readonly TaskStatus[];
3107
+ /** Filter to one or more substates (ANDed with `status`). */
3108
+ substate?: TaskSubstate | readonly TaskSubstate[];
3038
3109
  }
3039
3110
  declare function listTasks(db: Db, workstream?: string, opts?: ListTasksOptions): TaskRow[];
3040
3111
  /** Options for listReady. The optional `statuses` filter composes
@@ -3045,6 +3116,8 @@ declare function listTasks(db: Db, workstream?: string, opts?: ListTasksOptions)
3045
3116
  * shipped on `mu task list` (task_list_multi_status_union). */
3046
3117
  interface ListReadyOptions {
3047
3118
  status?: TaskStatus | readonly TaskStatus[];
3119
+ /** Substate filter; the `ready` view already excludes OPEN/parked. */
3120
+ substate?: TaskSubstate | readonly TaskSubstate[];
3048
3121
  }
3049
3122
  declare function listReady(db: Db, workstream: string, opts?: ListReadyOptions): TaskRow[];
3050
3123
  declare function listBlocked(db: Db, workstream: string): TaskRow[];
@@ -3177,6 +3250,12 @@ interface TaskWaitOptions {
3177
3250
  * needs_input might BE the success path. See
3178
3251
  * task_wait_stall_action_flag. */
3179
3252
  onStall?: "warn" | "exit";
3253
+ /** Read an owner's current runtime state for attention detection.
3254
+ * Without this hook, SDK waits never infer a stall from stored data. */
3255
+ readOwnerState?: (owner: {
3256
+ name: string;
3257
+ workstreamName: string;
3258
+ }) => Promise<StateReading | null>;
3180
3259
  /** Optional async hook run BEFORE every snapshot (initial + each
3181
3260
  * poll iteration). The CLI uses this to reconcile the workstream
3182
3261
  * each tick (reaper flips IN_PROGRESS → OPEN for dead-pane
@@ -3199,6 +3278,8 @@ interface TaskWaitTaskState {
3199
3278
  name: string;
3200
3279
  /** Current status (at the moment we exit). */
3201
3280
  status: TaskStatus;
3281
+ /** Current substate. A CLOSED ref that is not `done` has no deliverable. */
3282
+ substate: TaskSubstate;
3202
3283
  /** Owner at exit time (NULL when unowned, after release, or after
3203
3284
  * the reaper flipped IN_PROGRESS → OPEN due to a dead pane). */
3204
3285
  owner: string | null;
@@ -3252,6 +3333,9 @@ interface RenderTreeOptions {
3252
3333
  interface LoadFullDagOptions {
3253
3334
  /** Optional visible-status filter. Omitted = every task status. */
3254
3335
  statuses?: ReadonlySet<TaskStatus>;
3336
+ /** Optional row predicate, applied after `statuses` (e.g. the TUI's
3337
+ * substate toggles). Omitted = keep every row. */
3338
+ include?: (task: TaskRow) => boolean;
3255
3339
  }
3256
3340
  declare function loadFullDag(db: Db, workstream: string, opts?: LoadFullDagOptions): FullDag;
3257
3341
  /**
@@ -3390,6 +3474,9 @@ interface Track {
3390
3474
  taskIds: ReadonlySet<string>;
3391
3475
  /** Number of READY tasks (per the SQL view) within this track's subgraph. */
3392
3476
  readyCount: number;
3477
+ /** True when every non-CLOSED task in the track is OPEN/parked: the
3478
+ * track holds work, but none of it is schedulable. */
3479
+ parked: boolean;
3393
3480
  }
3394
3481
  /**
3395
3482
  * Identify independent task subtrees suitable for parallel assignment
@@ -3410,6 +3497,9 @@ interface WorkstreamSnapshot {
3410
3497
  inProgress: TaskRow[];
3411
3498
  blocked: TaskRow[];
3412
3499
  recentClosed: TaskRow[];
3500
+ /** OPEN/parked tasks in the workstream. The ready card names them
3501
+ * when nothing is ready, since parked work is otherwise invisible there. */
3502
+ parkedCount: number;
3413
3503
  /** Populated only when callers explicitly pass `withAllTasks: true`.
3414
3504
  * The TUI dashboard fast tick leaves this empty and the all-tasks
3415
3505
  * popup reads its exhaustive list directly from SQLite while open. */
@@ -3489,8 +3579,8 @@ declare function loadWorkstreamSnapshot(db: Db, workstream: string, opts?: LoadW
3489
3579
  */
3490
3580
  type RoiBucket = "high" | "mid" | "low" | "infinite";
3491
3581
  declare function roiBucket(impact: number, effortDays: number): RoiBucket;
3492
- /** Histogram of agents by status. Pure derivation (no colour render). */
3493
- declare function agentStatusHistogram(agents: readonly AgentRow[]): ReadonlyMap<AgentStatus, number>;
3582
+ /** Histogram of agents by runtime state. Pure derivation (no colour render). */
3583
+ declare function agentStateHistogram(agents: readonly LiveAgent[]): ReadonlyMap<RuntimeState, number>;
3494
3584
  interface OwnedTasksSummary {
3495
3585
  /** Display token: "—" (none), task id (one), or GLYPH.multi + count (many). */
3496
3586
  bit: string;
@@ -3535,7 +3625,7 @@ interface DoctorSummary {
3535
3625
  * snapshot-derived checks (ghosts / orphans / workspace-orphans) are
3536
3626
  * skipped in that case.
3537
3627
  */
3538
- declare function loadDoctorSummary(db: Db, snapshot: WorkstreamSnapshot | null): DoctorSummary;
3628
+ declare function loadDoctorSummary(db: Db, snapshot: WorkstreamSnapshot | null, agentStateSource?: "murmur" | "herdr"): DoctorSummary;
3539
3629
  /** Count of warn + fail rows. Pure; exported for unit tests. */
3540
3630
  declare function countProblems(checks: readonly DoctorCheck[]): number;
3541
3631
  /**
@@ -3821,6 +3911,44 @@ declare function checkFleetHazards(db: Db, opts?: {
3821
3911
  syncDir?: string | undefined;
3822
3912
  }): FleetHazard[];
3823
3913
 
3914
+ declare const AGENT_STATE_GLYPH: Record<RuntimeState, string>;
3915
+ declare function agentStateGlyph(state: RuntimeState): string;
3916
+ /**
3917
+ * Non-agent state glyphs, keyed by what they MEAN rather than what
3918
+ * they look like. A call site asks for `GLYPH.stale`, never for a
3919
+ * clock — so re-pointing the clock is a one-line edit here.
3920
+ *
3921
+ * `ok` / `fail` / `warn` deliberately reuse the same codepoints as the
3922
+ * agent statuses they rhyme with (`free`, `terminated`): a check-circle
3923
+ * means "fine" whether the row is an agent, a workspace or a doctor
3924
+ * check.
3925
+ */
3926
+ declare const GLYPH: {
3927
+ /** Healthy, clean, passing, closed-successfully. */
3928
+ readonly ok: "";
3929
+ /** Failed check. */
3930
+ readonly fail: "";
3931
+ /** Needs attention but not broken (idle-but-assigned, stale warning). */
3932
+ readonly warn: "";
3933
+ /** Workspace has uncommitted edits. */
3934
+ readonly dirty: "";
3935
+ /** Workspace is ≥ WORKSPACE_STALE_THRESHOLD commits behind main. */
3936
+ readonly stale: "";
3937
+ /** Task is blocked by an incoming edge. */
3938
+ readonly blocked: "";
3939
+ /** Task is parked (OPEN/parked): open, but set aside on purpose. */
3940
+ readonly parked: "";
3941
+ /** Track whose roots merged (diamond dependency). */
3942
+ readonly merge: "";
3943
+ /** Agent owns more than one task (pane-title multi-count slot). */
3944
+ readonly multi: "";
3945
+ /** Filter toggle: enabled / disabled. */
3946
+ readonly on: "";
3947
+ readonly off: "";
3948
+ /** Status outside the known enum. */
3949
+ readonly unknown: "";
3950
+ };
3951
+
3824
3952
  /** A parsed HLC. Never construct by hand — use `parseHlc` or `formatHlc`. */
3825
3953
  interface Hlc {
3826
3954
  /** Wall-clock hint, milliseconds since the epoch. */
@@ -3911,7 +4039,7 @@ declare function receiveHlc(db: Db, remoteHlc: string, now?: number): string;
3911
4039
  /** Every intent mu writes: the local ones (`emitEvent`, for changes no
3912
4040
  * trigger can see) plus the capture-trigger ones (set via
3913
4041
  * `withOpContext` around a portable-table mutation). */
3914
- type CaptureIntent = "task.add" | "task.update" | "task.note" | "task.delete" | "task.close" | "task.open" | "task.reject" | "task.defer" | "task.claim" | "task.release" | "task.reap" | "task.block" | "task.unblock" | "task.reparent" | "workstream.init" | "workstream.teardown" | "workstream.destroy";
4042
+ 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";
3915
4043
  type KnownIntent = CaptureIntent | LocalIntent;
3916
4044
  /** A log row, reduced to what rendering needs. Structural so both
3917
4045
  * `LogRow` (the SDK shape) and raw op rows satisfy it. */
@@ -4850,4 +4978,4 @@ declare function summarizeWorkstream(db: Db, opts: WorkstreamOptions): Promise<W
4850
4978
  */
4851
4979
  declare function teardownWorkstream(db: Db, opts: TeardownWorkstreamOptions): Promise<TeardownResult>;
4852
4980
 
4853
- export { AGENT_STATUS_GLYPH, type AddNoteOptions, type AddTaskOptions, type AdoptAgentOptions, type AdoptAgentResult, AgentDiedOnSpawnError, AgentExistsError, AgentNotFoundError, AgentNotInWorkstreamError, type AgentRow, AgentSpawnCliNotFoundError, AgentSpawnStartupError, type AgentStatus, 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 CommandResolutionResult, type CommandResolver, CrossWorkstreamEdgeError, CycleError, DRIFT_REPORT_CAP, type Db, type DeleteTaskResult, type DetectedStatus, 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, type InverseOp, KNOWN_INTENTS, KNOWN_VERBS, type KickAgentOptions, type KickAgentResult, type KickProcessExecutor, type KickSignal, type KnownIntent, type ListLiveAgentsOptions, type ListLogsOptions, type ListNotesOptions, type ListReadyOptions, type ListTasksOptions, type LiveAgentsView, type LoadFullDagOptions, type LoadWorkstreamSnapshotOptions, type LocalIntent, type LogKind, type LogRow, MACHINE_LOCAL_ENTITIES, MACHINE_LOCAL_TABLES, MachineIdentityMissingError, type MachineLocalEntity, type MachineLocalLoss, type MachineLocalTable, type MuxBackend, type MuxBackendName, MuxError, type MuxPane, 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 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, SEGMENT_FORMAT_VERSION, STATUS_EMOJI, SYNCED_ENTITIES, SchemaTooOldError, type SegmentDefect, type SegmentDefectKind, type SegmentLine, type SegmentManifest, type SendOptions, type SendWarning, type SetStatusResult, type SlugifyResult, type SpawnAgentOptions, type SplitWindowOptions, type StrandedWorkspaceOrphan, type SyncPassResult, SyncPeerNotFoundError, SyncPeerRefAmbiguousError, SyncSourceNotFoundError, type SyncedEntity, TASK_STATUSES, TASK_STATUS_LIST, TaskAlreadyOwnedError, type TaskEdgeWithStatus, type TaskEdges, type TaskEdgesWithStatus, TaskExistsError, TaskNotFoundError, TaskNotInWorkstreamError, type TaskNoteRow, type TaskRow, type TaskStatus, type TaskWaitOptions, type TaskWaitRef, type TaskWaitResult, type TaskWaitTaskState, type TeardownResult, TmuxError, type TmuxExecResult, type TmuxExecutor, type TmuxPane, type TmuxSession, type TmuxWindow, type Track, 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, activeMux, addBlockEdge, addNote, addTask, adoptAgent, agentStatusGlyph, agentStatusHistogram, 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, currentAgentName, currentOpContext, currentPaneTitle, decorateWithDirty, decorateWithStaleness, defaultDbPath, defaultSendDelayMs, defaultSendReadinessMs, defaultSpawnLivenessMs, defaultStateDir, deleteAgent, deleteTask, detectBackend, detectMux, detectPiStatus, discoverPeers, driftRemediation, emitEvent, ensureWorkstream, envVarNameForCli, extractTail, findCaseCollisions, flushSegment, foregroundPgid, formatDriftRecord, formatHlc, freeWorkspace, getAgent, getAgentByPane, getParallelTracks, getPrerequisites, getTask, getTaskEdges, getTaskEdgesWithStatus, getWaitPollCount, getWatermark, getWorkspaceForAgent, getWorkspaceStaleness, gitBackend, hasWorkMarker, idFromTitle, idFromTitleVerbose, ingestFromDb, ingestSegment, insertAgent, installCapture, isKickSignal, isPathInside, isTaskStatus, isValidAgentName, isValidPaneId, isValidTaskId, isValidWorkstreamName, isWorkspaceStale, jjBackend, kickAgent, killPane, killSession, latestSeq, 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, mergeSnapshotFastSlow, mostRecentGroup, mux, muxByName, newSession, newSessionWithPane, newWindow, nextHlc, noneBackend, opSubject, openDb, openTask, paneExists, paneTTY, parseAgentNameFromTitle, parseHlc, parseOpKey, parsePsTtyOutput, peerStatuses, planUndo, priorFieldValue, probeFilesystem, readAgent, 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, resolvePeerRef, roiBucket, segmentLineCount, segmentPath, selectLayout, sendToAgent, sendToPane, 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, updateAgentStatus, updateTask, verifyAgainstManifest, waitForTasks, withCaptureSuppressed, withFileLock, withOpContext, workspacePath, workspacesRoot, yankCommandForCheck };
4981
+ export { AGENT_STATE_GLYPH, type AddNoteOptions, type AddTaskOptions, type AdoptAgentOptions, type AdoptAgentResult, AgentDiedOnSpawnError, AgentExistsError, AgentNotFoundError, AgentNotInWorkstreamError, type AgentRow, 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, 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, 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, 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 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, 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, 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, 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, currentAgentName, currentOpContext, currentPaneTitle, decorateWithDirty, decorateWithStaleness, defaultDbPath, defaultSendDelayMs, defaultSendReadinessMs, defaultSpawnLivenessMs, defaultStateDir, deleteAgent, deleteTask, detectBackend, detectMux, discoverPeers, driftRemediation, emitEvent, ensureWorkstream, envVarNameForCli, 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, installCapture, isKickSignal, isPathInside, isTaskStatus, isValidAgentName, isValidPair, isValidPaneId, isValidTaskId, isValidWorkstreamName, isWorkspaceStale, jjBackend, kickAgent, killPane, killSession, latestSeq, 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, 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 };