@mu-crew/mu 4.0.0 → 4.1.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.
Files changed (34) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-5HECDBK3.js → chunk-4ULY3ZKO.js} +16 -16
  3. package/dist/{chunk-AW2NONYU.js → chunk-7M634JMD.js} +81 -7
  4. package/dist/chunk-7M634JMD.js.map +1 -0
  5. package/dist/{chunk-GQNHIPJN.js → chunk-SS7NQSSZ.js} +21 -421
  6. package/dist/chunk-SS7NQSSZ.js.map +1 -0
  7. package/dist/{chunk-S424D5EP.js → chunk-UCZPJX7K.js} +628 -141
  8. package/dist/chunk-UCZPJX7K.js.map +1 -0
  9. package/dist/{cli-GB2CAVVW.js → cli-TV3N47AZ.js} +340 -42
  10. package/dist/cli-TV3N47AZ.js.map +1 -0
  11. package/dist/cli.js +1 -1
  12. package/dist/{errors-KHOYKD7D.js → errors-GRONKWFS.js} +2 -2
  13. package/dist/extension/mu-pi.js +28 -14
  14. package/dist/extension/mu-pi.js.map +1 -1
  15. package/dist/index.d.ts +63 -11
  16. package/dist/index.js +15 -15
  17. package/dist/{tui-ALPHYTA2.js → tui-FUBQ326D.js} +102 -27
  18. package/dist/tui-FUBQ326D.js.map +1 -0
  19. package/docs/ARCHITECTURE.md +5 -4
  20. package/docs/VOCABULARY.md +6 -5
  21. package/docs/guide/cleanup.md +8 -0
  22. package/docs/guide/delegate.md +11 -3
  23. package/docs/guide/remote.md +19 -12
  24. package/docs/reference/env.md +1 -0
  25. package/docs/reference/naming.md +2 -0
  26. package/package.json +1 -1
  27. package/skills/mu/recipes/remote-workers.md +7 -6
  28. package/dist/chunk-AW2NONYU.js.map +0 -1
  29. package/dist/chunk-GQNHIPJN.js.map +0 -1
  30. package/dist/chunk-S424D5EP.js.map +0 -1
  31. package/dist/cli-GB2CAVVW.js.map +0 -1
  32. package/dist/tui-ALPHYTA2.js.map +0 -1
  33. /package/dist/{chunk-5HECDBK3.js.map → chunk-4ULY3ZKO.js.map} +0 -0
  34. /package/dist/{errors-KHOYKD7D.js.map → errors-GRONKWFS.js.map} +0 -0
package/README.md CHANGED
@@ -83,7 +83,7 @@ package), or spawn into the reserved `scratch` workstream:
83
83
  Run `mu` with no arguments for the read-only dashboard. It has five tabs
84
84
  (Overview, Tasks, DAG, Agents, Log), with what needs a human on top: a
85
85
  dead or stalled worker, one waiting on a permission or on input, a
86
- `human-needed` task.
86
+ `human-needed` task, a refused or failed delegate call.
87
87
 
88
88
  ![The mu dashboard: a payments workstream with a dead worker, one waiting on a permission, one stalled on a tool, and a human-needed task.](docs/img/tui-dashboard.png)
89
89
 
@@ -1,10 +1,6 @@
1
1
  import { createRequire as __muCreateRequire } from "node:module"; const require = __muCreateRequire(import.meta.url);
2
2
  import {
3
- DelegateCallConflictError,
4
- DelegateNotFoundError,
5
- DelegateStateError,
6
3
  IN_FLIGHT_STATES,
7
- TERMINAL_DELEGATE_STATES,
8
4
  ambientFlush,
9
5
  ambientIngest,
10
6
  authorisedReady,
@@ -13,15 +9,10 @@ import {
13
9
  currentCallers,
14
10
  deliveredOf,
15
11
  endAttempt,
16
- finishDelegate,
17
12
  foreignVersionMessage,
18
13
  getAutoConfig,
19
- getDelegateCall,
20
- listDelegates,
21
- listDelegatesOf,
22
14
  liveAgentToOutput,
23
15
  localMachineId,
24
- markDelegate,
25
16
  openHumanNeeds,
26
17
  ownSegmentForeignLine,
27
18
  pendingAttempts,
@@ -30,12 +21,9 @@ import {
30
21
  projectLog,
31
22
  readAttempt,
32
23
  recordHumanNeeded,
33
- registerDelegateCall,
34
24
  reserveAttempt,
35
- reserveRetry,
36
- tallyCalls,
37
- verdictTally
38
- } from "./chunk-GQNHIPJN.js";
25
+ reserveRetry
26
+ } from "./chunk-SS7NQSSZ.js";
39
27
  import {
40
28
  AgentLockBusyError,
41
29
  AgentNotFoundError,
@@ -46,11 +34,15 @@ import {
46
34
  CtlWriteVetoedError,
47
35
  DEFAULT_SUBSTATE,
48
36
  DELEGATE_TOKEN,
37
+ DelegateCallConflictError,
38
+ DelegateNotFoundError,
39
+ DelegateStateError,
49
40
  NoMultiplexerError,
50
41
  RemoteRecoveryRefusedError,
51
42
  SYNCED_ENTITIES,
52
43
  SpawnAttemptBusyError,
53
44
  SpawnAttemptGuardError,
45
+ TERMINAL_DELEGATE_STATES,
54
46
  TaskNotFoundError,
55
47
  WorkstreamNotFoundError,
56
48
  activeMux,
@@ -77,7 +69,9 @@ import {
77
69
  endWait,
78
70
  expectsCtl,
79
71
  fenceAgentRef,
72
+ finishDelegate,
80
73
  getAgent,
74
+ getDelegateCall,
81
75
  getReceipt,
82
76
  getTask,
83
77
  getTaskNote,
@@ -87,6 +81,8 @@ import {
87
81
  isConsumed,
88
82
  isValidTaskId,
89
83
  listBlocked,
84
+ listDelegates,
85
+ listDelegatesOf,
90
86
  listInProgress,
91
87
  listReady,
92
88
  listTasks,
@@ -94,6 +90,7 @@ import {
94
90
  localPaneAlive,
95
91
  locksDir,
96
92
  logStallOnce,
93
+ markDelegate,
97
94
  newMsgId,
98
95
  observeAgentStates,
99
96
  openDb,
@@ -106,6 +103,7 @@ import {
106
103
  recordSend,
107
104
  recoveryGone,
108
105
  recoveryHolds,
106
+ registerDelegateCall,
109
107
  registerOwnedWait,
110
108
  releaseTask,
111
109
  resolveCliCommand,
@@ -120,16 +118,18 @@ import {
120
118
  spawnAutoAttempt,
121
119
  spawnForTask,
122
120
  speaksMuCtl,
121
+ tallyCalls,
123
122
  taskIdFor,
124
123
  taskRevision,
125
124
  tryResolveLiveWorkstreamId,
125
+ verdictTally,
126
126
  watchAgentRun,
127
127
  withAgentLock,
128
128
  withCaptureSuppressed,
129
129
  withFileLock,
130
130
  withHostChannel,
131
131
  withOpContext
132
- } from "./chunk-S424D5EP.js";
132
+ } from "./chunk-UCZPJX7K.js";
133
133
 
134
134
  // src/rebuild.ts
135
135
  import { existsSync, mkdirSync, rmSync, statSync } from "fs";
@@ -4479,4 +4479,4 @@ export {
4479
4479
  saveResume,
4480
4480
  loadResume
4481
4481
  };
4482
- //# sourceMappingURL=chunk-5HECDBK3.js.map
4482
+ //# sourceMappingURL=chunk-4ULY3ZKO.js.map
@@ -1,29 +1,64 @@
1
1
  import { createRequire as __muCreateRequire } from "node:module"; const require = __muCreateRequire(import.meta.url);
2
2
  import {
3
3
  computeNext,
4
- listDelegates,
5
4
  liveAgentToOutput,
6
5
  loadOpenTaskFrontier,
7
6
  logItem,
8
7
  openHumanNeeds,
9
8
  parseOpKey
10
- } from "./chunk-GQNHIPJN.js";
9
+ } from "./chunk-SS7NQSSZ.js";
11
10
  import {
12
11
  UNKNOWN_REASON,
13
12
  WorkstreamNotFoundError,
14
13
  isScratchWorkstream,
15
14
  latestSeq,
15
+ listDelegates,
16
16
  listLogs,
17
17
  listTasks,
18
18
  readLiveAgents,
19
+ tallyCalls,
19
20
  tryResolveLiveWorkstreamId
20
- } from "./chunk-S424D5EP.js";
21
+ } from "./chunk-UCZPJX7K.js";
21
22
 
22
23
  // src/dashboard-data.ts
23
24
  var DEFAULT_STATUS = ["OPEN", "IN_PROGRESS"];
24
25
  var DEFAULT_LOG_LIMIT = 100;
25
26
  var STALLED_TOOL_MS = 15 * 6e4;
26
27
  var FINISHED_CALL = ["done", "failed", "cancelled"];
28
+ var FAILED_CALL_MS = 24 * 60 * 6e4;
29
+ var WAVE_MAX = 5;
30
+ var callOf = (c) => ({
31
+ call_id: c.callId,
32
+ state: c.state,
33
+ verdict: c.verdict,
34
+ judges: c.record ? `${c.record.workstream}/${c.record.task}` : null,
35
+ wave: c.wave
36
+ });
37
+ function wavesOf(db, workstream) {
38
+ const names = db.prepare(
39
+ `SELECT t.wave AS wave, MAX(d.updated_at) AS at FROM delegate_calls d
40
+ JOIN tasks t ON t.id = d.task_id JOIN workstreams w ON w.id = t.workstream_id
41
+ WHERE w.name = ? AND t.wave IS NOT NULL
42
+ GROUP BY t.wave ORDER BY at DESC, t.wave LIMIT ?`
43
+ ).all(workstream, WAVE_MAX).map((r) => r.wave);
44
+ return names.map((wave) => {
45
+ const rows = listDelegates(db, void 0, workstream, { wave });
46
+ const t = tallyCalls(rows);
47
+ const sum = (k) => t.findings.reduce((n, f) => n + f[k], 0);
48
+ return {
49
+ key: keyOf(workstream, wave),
50
+ workstream,
51
+ wave,
52
+ calls: rows.length,
53
+ confirmed: sum("confirmed"),
54
+ refuted: sum("refuted"),
55
+ unverified: sum("unverified"),
56
+ pending: sum("pending"),
57
+ refused: t.refused.length,
58
+ updated_at: rows.reduce((m, r) => r.updatedAt > m ? r.updatedAt : m, "")
59
+ };
60
+ });
61
+ }
27
62
  function taskActivity(db, workstream) {
28
63
  const prefix = `${workstream}/`;
29
64
  const rows = db.prepare(
@@ -59,7 +94,8 @@ function toolOf(tool, now) {
59
94
  return { tool: tool === null ? null : { ...tool, elapsed_ms: Math.max(0, now - tool.since) } };
60
95
  }
61
96
  var keyOf = (workstream, id) => `${workstream}/${id}`;
62
- function dashboardTask(row, activity, agentsById) {
97
+ function dashboardTask(row, activity, agentsById, calls) {
98
+ const call = row.kind === "delegate" ? calls.get(row.name) : void 0;
63
99
  const inProgress = row.status === "IN_PROGRESS";
64
100
  const owner = inProgress && row.ownerId !== null ? agentsById.get(row.ownerId) : void 0;
65
101
  return {
@@ -78,7 +114,8 @@ function dashboardTask(row, activity, agentsById) {
78
114
  wave: row.wave,
79
115
  created_at: row.createdAt,
80
116
  updated_at: row.updatedAt,
81
- activity_seq: activity.get(row.name) ?? 0
117
+ activity_seq: activity.get(row.name) ?? 0,
118
+ ...call ? { call: callOf(call) } : {}
82
119
  };
83
120
  }
84
121
  function byActivityDesc(a, b) {
@@ -103,6 +140,7 @@ var ATTENTION_ORDER = [
103
140
  "permission",
104
141
  "stalled",
105
142
  "input",
143
+ "delegate",
106
144
  "human",
107
145
  "next_unavailable",
108
146
  "sync"
@@ -157,11 +195,26 @@ async function loadDashboard(db, opts) {
157
195
  const edges = [];
158
196
  const frontier = [];
159
197
  const agents = [];
198
+ const waves = [];
160
199
  const now = Date.now();
161
200
  for (const ws of readFrom) {
162
201
  const activity = taskActivity(db, ws.name);
202
+ const calls = listDelegates(db, void 0, ws.name, { taskStatuses: statuses });
203
+ const callByTask = new Map(calls.map((c) => [c.task, c]));
204
+ waves.push(...wavesOf(db, ws.name));
163
205
  tasks.push(
164
- ...listTasks(db, ws.name, { status: statuses }).map((r) => dashboardTask(r, activity, agentsById)).filter((t) => matches(opts.text, t.key, t.title, t.owner, t.substate))
206
+ ...listTasks(db, ws.name, { status: statuses }).map((r) => dashboardTask(r, activity, agentsById, callByTask)).filter(
207
+ (t) => matches(
208
+ opts.text,
209
+ t.key,
210
+ t.title,
211
+ t.owner,
212
+ t.substate,
213
+ t.call?.state,
214
+ t.call?.verdict,
215
+ t.call?.judges
216
+ )
217
+ )
165
218
  );
166
219
  const front = loadOpenTaskFrontier(db, ws.name);
167
220
  frontier.push({
@@ -239,6 +292,26 @@ async function loadDashboard(db, opts) {
239
292
  updated_at: c.updatedAt
240
293
  })) : [];
241
294
  const attention = everyAgent.flatMap((a) => agentAttention(a, now));
295
+ const liveNames = new Set(live.map((w) => w.name));
296
+ const troubled = [
297
+ ...listDelegates(db, void 0, void 0, { states: ["refused"] }),
298
+ ...listDelegates(db, void 0, void 0, {
299
+ states: ["failed"],
300
+ updatedAfter: new Date(now - FAILED_CALL_MS).toISOString()
301
+ })
302
+ ];
303
+ troubled.sort((a, b) => keyOf(a.workstream, a.task).localeCompare(keyOf(b.workstream, b.task)));
304
+ for (const c of troubled) {
305
+ if (!liveNames.has(c.workstream)) continue;
306
+ const how = c.state === "refused" ? " (reissue or cancel it from pi)" : "";
307
+ attention.push({
308
+ key: `delegate:${keyOf(c.workstream, c.task)}`,
309
+ workstream: c.workstream,
310
+ kind: "delegate",
311
+ text: `delegate ${c.state}: ${c.request.label ?? c.task}${how}`,
312
+ target: keyOf(c.workstream, c.task)
313
+ });
314
+ }
242
315
  for (const t of db.prepare(
243
316
  `SELECT ws.name AS ws, t.local_id AS id, t.title AS title FROM tasks t
244
317
  JOIN workstreams ws ON ws.id = t.workstream_id AND ws.torn_down_at IS NULL
@@ -288,6 +361,7 @@ async function loadDashboard(db, opts) {
288
361
  next_source: next.source,
289
362
  human_needs,
290
363
  delegates,
364
+ waves,
291
365
  attention
292
366
  };
293
367
  }
@@ -298,4 +372,4 @@ export {
298
372
  matches,
299
373
  loadDashboard
300
374
  };
301
- //# sourceMappingURL=chunk-AW2NONYU.js.map
375
+ //# sourceMappingURL=chunk-7M634JMD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/dashboard-data.ts"],"sourcesContent":["// SDK seam for the dashboard: ONE read-only projection of everything its tabs\n// show (workstreams, tasks with a delegate task's `call`, frontier, agents, log,\n// human needs, the caller's delegates, delegate `waves`, attention).\n//\n// READ-ONLY by construction: it never reconciles, reaps, ingests or writes, and\n// runs on a `readonly: true` connection. The only I/O beyond SQL is the\n// best-effort ctl probe `readLiveAgents` does (a socket read). It composes the\n// merged readers (`listTasks`, `loadOpenTaskFrontier`, `readLiveAgents`,\n// `listLogs`/`logItem`, `openHumanNeeds`, `listDelegates`, `tallyCalls`) rather than\n// re-deriving them, so a dashboard row equals the CLI's. `stateSnapshot` is NOT\n// the source of the task list: it omits OPEN/parked rows and caps closed ones.\n//\n// `next` is `computeNext` (the CLI's one rule set) with no outcome: it only reads.\n// A failed computation stays `next_source: \"unavailable\"` (never \"no authorised\n// work\"). An agent's `tool` comes from the ctl status the agent read already did:\n// an object while a tool runs, null when none, absent for an extension that\n// predates the field (unknown). Elapsed is `now - since`, calculated at read.\n//\n// Two delegate reads, on purpose: `delegates` is the caller's own unfinished calls\n// (caller-scoped like `human_needs`, empty for a human shell), while a task's\n// `call`, `waves` and the `delegate` attention items read every caller's, because\n// they describe tasks and waves anyone can see. Each delegate read is bounded in\n// SQL (shown task statuses, the newest waves, the failed-call window), so a tick\n// does not grow with the delegate history in `scratch`.\n\nimport { type AgentOutput, liveAgentToOutput } from \"./agent-output.js\";\nimport type { StateReading } from \"./agent-state.js\";\nimport { UNKNOWN_REASON } from \"./agent-state.js\";\nimport { readLiveAgents } from \"./agents.js\";\nimport { type LogItem, logItem } from \"./cli/log-records.js\";\nimport type { CtlTool } from \"./ctl/protocol.js\";\nimport { loadOpenTaskFrontier } from \"./dag.js\";\nimport { type Db, tryResolveLiveWorkstreamId, WorkstreamNotFoundError } from \"./db.js\";\nimport { type DelegateRow, listDelegates, tallyCalls } from \"./delegates.js\";\nimport { openHumanNeeds } from \"./human-needed.js\";\nimport { parseOpKey } from \"./log-render.js\";\nimport { latestSeq, listLogs } from \"./logs.js\";\nimport { computeNext } from \"./next-hints.js\";\nimport type { NextPlan } from \"./output-contract.js\";\nimport type { TaskStatus } from \"./tasks/status.js\";\nimport { listTasks, type TaskRow } from \"./tasks.js\";\nimport { isScratchWorkstream } from \"./workstream.js\";\n\n/** A running tool of a pi agent (from the ctl status). */\nexport interface AgentTool {\n name: string;\n /** Epoch ms the tool started. */\n since: number;\n /** Calculated at read time (`now - since`), when known. */\n elapsed_ms?: number;\n}\n\nexport interface DashboardWorkstream {\n name: string;\n scratch: boolean;\n /** Newest visible op seq in the workstream; 0 when it has none, or when `activity: false` skipped the read. */\n latest_seq: number;\n}\n\n/** One task, SQL column names, `key` = `<workstream>/<id>` (unique across workstreams). */\nexport interface DashboardTask {\n key: string;\n workstream: string;\n id: string;\n title: string;\n status: string;\n substate: string;\n impact: number;\n effort_days: number;\n /** Owner's name; only while IN_PROGRESS. */\n owner: string | null;\n /** The owner's registry id (`tasks.owner_id`; the identity: names repeat across workstreams). */\n owner_id: number | null;\n /** The owner's OWN workstream, which can differ from the task's; null when unowned. */\n owner_workstream: string | null;\n kind: string;\n wave: string | null;\n created_at: string;\n updated_at: string;\n /** `MAX(ops.seq)` over the task's own ops, its notes' and its edges' (raw log, db/sql writes included); 0 when none. */\n activity_seq: number;\n /** The call behind a `kind=delegate` task, whoever made it; absent for any other task. */\n call?: DashboardCall;\n}\n\n/** A delegate call as a task row shows it: machine-wide, never narrowed to a caller. */\nexport interface DashboardCall {\n call_id: string;\n state: string;\n /** The parsed label of a done answer; null otherwise. */\n verdict: string | null;\n /** `<workstream>/<task>` the call judges; null with no record target. */\n judges: string | null;\n wave: string | null;\n}\n\n/**\n * One wave of delegate calls in a workstream, tallied as `verdictTally` counts it\n * (one result per call), over every caller. `pending` includes `refused`.\n */\nexport interface DashboardWave {\n /** `<workstream>/<wave>`. */\n key: string;\n workstream: string;\n wave: string;\n calls: number;\n confirmed: number;\n refuted: number;\n unverified: number;\n pending: number;\n refused: number;\n /** The newest `updated_at` of its calls. */\n updated_at: string;\n}\n\n/** One line of the open DAG (`loadOpenTaskFrontier`, preorder, per workstream). */\nexport interface DashboardEdge {\n key: string;\n workstream: string;\n id: string;\n title: string;\n status: string;\n substate: string;\n depth: number;\n /** Qualified key of the entry it is listed under; null for a root. */\n parent: string | null;\n /** Already listed above (a diamond): not expanded again. */\n again: boolean;\n /** Open neighbours not listed under this entry. */\n kids: number;\n /** CLOSED neighbours collapsed into this count. */\n closed: number;\n cap_cut: number;\n}\n\n/** What the frontier cap left out of one workstream's DAG (per-entry `cap_cut` cannot say it). */\nexport interface DashboardFrontierCut {\n workstream: string;\n /** Open start tasks the node cap left out: open work absent from `edges`. */\n roots_cut: number;\n /** Recurrence (diamond) lines the cap left out; each such task is listed elsewhere. */\n again_cut: number;\n}\n\n/** A registry agent with its computed state; unknown stays unknown. */\nexport interface DashboardAgent extends AgentOutput {\n /** `<workstream>/<name>`. */\n key: string;\n /** Qualified keys of the IN_PROGRESS tasks it owns (empty when none). */\n tasks: string[];\n /** The first of `tasks`; null when none. */\n task: string | null;\n /** The running tool; null = none running; absent = unknown (old extension, no ctl): never read as \"none\". */\n tool?: AgentTool | null;\n}\n\n/** An op of the canonical log, rendered by the one formatter (`logItem`), plus its workstream. */\nexport interface DashboardLogItem extends LogItem {\n /** The workstream the op belongs to; null for a machine-wide op. */\n scope: string | null;\n}\n\n/** An OPEN `human` task of the caller. */\nexport interface DashboardHumanNeed {\n key: string;\n workstream: string;\n id: string;\n reason: string;\n}\n\n/** An unfinished delegate call of the caller. */\nexport interface DashboardDelegate {\n call_id: string;\n workstream: string;\n /** The delegate task's local id. */\n task: string;\n state: string;\n wave: string | null;\n judges: string | null;\n agent: string | null;\n verdict: string | null;\n error: string | null;\n updated_at: string;\n}\n\n/**\n * Something a human has to look at. Read over EVERY live workstream and blind\n * to the status/text filters and the workstream scope, so each surface (the\n * strip under the tabs, the Overview card) agrees.\n *\n * - `dead`: the agent's pane (or gate process) is gone.\n * - `permission`: `needs_permission`; `text` carries how long.\n * - `stalled`: one tool has run over `STALLED_TOOL_MS`.\n * - `input`: `needs_input` past the idle threshold on an agent that owns work\n * (the registry's `idle` flag; `MU_IDLE_THRESHOLD_MS`, 0 disables).\n * - `delegate`: a delegate call that is `refused` (parked until its pi session\n * reissues it) or `failed` within `FAILED_CALL_MS`, whoever made it.\n * - `human`: an OPEN `kind=human` task, whoever recorded it (`human_needs`\n * is caller-scoped and empty for a human shell).\n * - `next_unavailable`: `computeNext` failed.\n * - `sync`: a warning the caller passed as `syncWarnings`.\n */\nexport type AttentionKind =\n | \"dead\"\n | \"permission\"\n | \"input\"\n | \"stalled\"\n | \"delegate\"\n | \"human\"\n | \"next_unavailable\"\n | \"sync\";\n\nexport interface DashboardAttention {\n /** Unique within a snapshot (`<kind>:<target>`). */\n key: string;\n /** The workstream it belongs to; null for a machine-wide item (`next_unavailable`, `sync`). */\n workstream: string | null;\n kind: AttentionKind;\n /** One short line, age at read (\"worker-3 permission 20m\"; a human task: its title); bare names, the UI qualifies. */\n text: string;\n /** Qualified key to drill into: the agent (dead/permission/input/stalled) or the task (delegate, human); null otherwise. */\n target: string | null;\n}\n\nexport interface DashboardSnapshot {\n /** The identity the caller-scoped panels were read for; null = a human shell. */\n caller: string | null;\n /** `none`: no identity, so `human_needs` and `delegates` are empty BY DESIGN (never another caller's); `call`, `waves` and attention are every caller's. */\n caller_scope: \"caller\" | \"none\";\n /** Every live workstream, scratch included; never narrowed by a filter (it is the switcher). */\n workstreams: DashboardWorkstream[];\n tasks: DashboardTask[];\n edges: DashboardEdge[];\n /** One per in-scope workstream: the frontier's root/recurrence cuts, passed through. */\n frontier: DashboardFrontierCut[];\n agents: DashboardAgent[];\n /** The newest ops, oldest first. */\n log: DashboardLogItem[];\n /** `computeNext` for the caller set and the workstream filter; null when `next_source` is `unavailable`, or computed and nothing is authorised. */\n next: NextPlan;\n /** `unavailable`: the computation failed; the UI must not read null as \"no work\". */\n next_source: \"unavailable\" | \"computed\";\n human_needs: DashboardHumanNeed[];\n delegates: DashboardDelegate[];\n /** Per read workstream (tasks scope), its `WAVE_MAX` most recently updated waves, newest first, any caller. */\n waves: DashboardWave[];\n /** Trouble across every workstream, filters ignored, most urgent first (see `AttentionKind`). */\n attention: DashboardAttention[];\n}\n\nexport interface DashboardOptions {\n /** Narrow tasks, frontier, agents, log and caller panels to one live workstream. */\n workstream?: string;\n /**\n * Read tasks, edges and frontier of this workstream ONLY (a name that is not live,\n * or null: none), leaving agents, log, caller panels and attention machine-wide:\n * the dashboard shows one workstream, and reading every other one's tasks and DAG\n * each tick is what made it costly. Absent: every live workstream. `workstream`, when\n * set, wins.\n */\n scopeWorkstream?: string | null;\n /** Statuses to list; default OPEN + IN_PROGRESS (CLOSED is hidden). */\n status?: readonly TaskStatus[];\n /** Case-insensitive substring over a task's key/title/owner/substate and an agent's key/name/state/task keys. */\n text?: string;\n /** `spawnerFromEnv()`; null = a human shell (caller-scoped panels stay empty). */\n caller: string | null;\n /** Who `next` is computed for (`currentCallers()`); default: `caller` alone, none for a human shell. */\n callers?: readonly string[];\n /** Log tail size (default 100). */\n logLimit?: number;\n /** Read the log tail of this workstream only, leaving every other panel unscoped (not checked: a name that is not live reads an empty log). */\n logWorkstream?: string;\n /**\n * Read each workstream's `latest_seq` (default true). It only ranks the starting\n * pick and costs one log scan per workstream, so the dashboard's poll passes false\n * once the set of live workstreams is known (every `latest_seq` is then 0).\n */\n activity?: boolean;\n /** Sync warnings the caller holds (`ambientIngest`); each becomes a `sync` attention item. */\n syncWarnings?: readonly string[];\n /**\n * The agent-state cache (the dashboard's slow tier, see `readLiveAgents`): with\n * `probe: false` the read is SQL only for every cached agent. Absent: probe all.\n */\n agentStates?: { cache: Map<string, StateReading>; probe: boolean };\n}\n\nconst DEFAULT_STATUS: readonly TaskStatus[] = [\"OPEN\", \"IN_PROGRESS\"];\nconst DEFAULT_LOG_LIMIT = 100;\n/** A tool running this long counts as stalled. */\nexport const STALLED_TOOL_MS = 15 * 60_000;\nconst FINISHED_CALL: readonly string[] = [\"done\", \"failed\", \"cancelled\"];\n/** A failed call is an attention item this long after it failed. */\nexport const FAILED_CALL_MS = 24 * 60 * 60_000;\n/** Waves kept per workstream. */\nexport const WAVE_MAX = 5;\n\nconst callOf = (c: DelegateRow): DashboardCall => ({\n call_id: c.callId,\n state: c.state,\n verdict: c.verdict,\n judges: c.record ? `${c.record.workstream}/${c.record.task}` : null,\n wave: c.wave,\n});\n\n/** The `WAVE_MAX` most recently updated waves of `calls` (one workstream's), newest first. */\nfunction wavesOf(db: Db, workstream: string): DashboardWave[] {\n // The newest waves by name first (no request parse), then only their calls.\n const names = (\n db\n .prepare(\n `SELECT t.wave AS wave, MAX(d.updated_at) AS at FROM delegate_calls d\n JOIN tasks t ON t.id = d.task_id JOIN workstreams w ON w.id = t.workstream_id\n WHERE w.name = ? AND t.wave IS NOT NULL\n GROUP BY t.wave ORDER BY at DESC, t.wave LIMIT ?`,\n )\n .all(workstream, WAVE_MAX) as { wave: string }[]\n ).map((r) => r.wave);\n return names.map((wave): DashboardWave => {\n const rows = listDelegates(db, undefined, workstream, { wave });\n const t = tallyCalls(rows);\n const sum = (k: \"confirmed\" | \"refuted\" | \"unverified\" | \"pending\"): number =>\n t.findings.reduce((n, f) => n + f[k], 0);\n return {\n key: keyOf(workstream, wave),\n workstream,\n wave,\n calls: rows.length,\n confirmed: sum(\"confirmed\"),\n refuted: sum(\"refuted\"),\n unverified: sum(\"unverified\"),\n pending: sum(\"pending\"),\n refused: t.refused.length,\n updated_at: rows.reduce((m, r) => (r.updatedAt > m ? r.updatedAt : m), \"\"),\n };\n });\n}\n\n/** `MAX(ops.seq)` per task id of one workstream over its task, note and edge ops. */\nfunction taskActivity(db: Db, workstream: string): Map<string, number> {\n const prefix = `${workstream}/`;\n const rows = db\n .prepare(\n `SELECT entity, key, MAX(seq) AS seq FROM ops\n WHERE entity IN ('task', 'note', 'edge') AND key >= ? AND key < ?\n GROUP BY entity, key`,\n )\n .all(prefix, `${workstream}0`) as { entity: string; key: string; seq: number }[];\n const out = new Map<string, number>();\n const bump = (id: string | undefined, seq: number): void => {\n if (id !== undefined && seq > (out.get(id) ?? 0)) out.set(id, seq);\n };\n for (const r of rows) {\n if (r.entity === \"task\") bump(r.key.slice(prefix.length), r.seq);\n else if (r.entity === \"note\") bump(r.key.slice(prefix.length).split(\"#\")[0], r.seq);\n else {\n const parsed = parseOpKey(r.key);\n bump(parsed.local, r.seq);\n bump(parsed.to, r.seq);\n }\n }\n return out;\n}\n\nfunction nextOf(\n db: Db,\n callers: readonly string[],\n workstream: string | undefined,\n): { plan: NextPlan; source: DashboardSnapshot[\"next_source\"] } {\n try {\n const plan = computeNext(db, { callers, ...(workstream !== undefined ? { workstream } : {}) });\n return { plan, source: \"computed\" };\n } catch {\n return { plan: null, source: \"unavailable\" };\n }\n}\n\n/** The tool as the dashboard shows it, `elapsed_ms` calculated now; unknown stays absent. */\nfunction toolOf(tool: CtlTool | null | undefined, now: number): { tool?: AgentTool | null } {\n if (tool === undefined) return {};\n return { tool: tool === null ? null : { ...tool, elapsed_ms: Math.max(0, now - tool.since) } };\n}\n\nconst keyOf = (workstream: string, id: string): string => `${workstream}/${id}`;\n\ninterface AgentIdentity {\n name: string;\n workstream: string;\n}\n\nfunction dashboardTask(\n row: TaskRow,\n activity: ReadonlyMap<string, number>,\n agentsById: ReadonlyMap<number, AgentIdentity>,\n calls: ReadonlyMap<string, DelegateRow>,\n): DashboardTask {\n const call = row.kind === \"delegate\" ? calls.get(row.name) : undefined;\n const inProgress = row.status === \"IN_PROGRESS\";\n const owner = inProgress && row.ownerId !== null ? agentsById.get(row.ownerId) : undefined;\n return {\n key: keyOf(row.workstreamName, row.name),\n workstream: row.workstreamName,\n id: row.name,\n title: row.title,\n status: row.status,\n substate: row.substate,\n impact: row.impact,\n effort_days: row.effortDays,\n owner: inProgress ? row.ownerName : null,\n owner_id: inProgress ? row.ownerId : null,\n owner_workstream: owner?.workstream ?? null,\n kind: row.kind,\n wave: row.wave,\n created_at: row.createdAt,\n updated_at: row.updatedAt,\n activity_seq: activity.get(row.name) ?? 0,\n ...(call ? { call: callOf(call) } : {}),\n };\n}\n\n/** Newest activity first; no ops (capture suppressed) falls back to `updated_at`, then key. */\nfunction byActivityDesc(a: DashboardTask, b: DashboardTask): number {\n if (a.activity_seq !== b.activity_seq) return b.activity_seq - a.activity_seq;\n if (a.updated_at !== b.updated_at) return a.updated_at < b.updated_at ? 1 : -1;\n return a.key < b.key ? -1 : a.key > b.key ? 1 : 0;\n}\n\n/** `45s`, `1m05s`, `1h05m`: the ONE duration format of the dashboard (strip and tool column). */\nexport function formatElapsed(ms: number): string {\n const s = Math.max(0, Math.floor(ms / 1000));\n if (s < 60) return `${s}s`;\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m${String(s % 60).padStart(2, \"0\")}s`;\n return `${Math.floor(m / 60)}h${String(m % 60).padStart(2, \"0\")}m`;\n}\n\n/** The pane (or a gate's process) is gone, as opposed to a state source that merely cannot say. */\nfunction isDead(a: DashboardAgent): boolean {\n if (a.state !== \"unknown\") return false;\n if (a.reason === UNKNOWN_REASON.paneGone) return true;\n return a.gate_token !== null && /^(exited \\d+|killed by signal)/.test(a.reason ?? \"\");\n}\n\nconst ATTENTION_ORDER: readonly AttentionKind[] = [\n \"dead\",\n \"permission\",\n \"stalled\",\n \"input\",\n \"delegate\",\n \"human\",\n \"next_unavailable\",\n \"sync\",\n];\n\nfunction agentAttention(a: DashboardAgent, now: number): DashboardAttention[] {\n const item = (kind: AttentionKind, text: string): DashboardAttention => ({\n key: `${kind}:${a.key}`,\n workstream: a.workstream,\n kind,\n text: `${a.name} ${text}`,\n target: a.key,\n });\n const since = a.since == null ? Number.NaN : Date.parse(a.since);\n const waited = Number.isFinite(since) ? ` ${formatElapsed(now - since)}` : \"\";\n const out: DashboardAttention[] = [];\n if (isDead(a)) out.push(item(\"dead\", \"dead\"));\n if (a.state === \"needs_permission\") out.push(item(\"permission\", `permission${waited}`));\n if (a.idle === true) out.push(item(\"input\", `input${waited}`));\n const ran = a.tool?.elapsed_ms;\n if (a.tool != null && ran !== undefined && ran >= STALLED_TOOL_MS) {\n out.push(item(\"stalled\", `${a.tool.name} ${formatElapsed(ran)}`));\n }\n return out;\n}\n\nexport function matches(\n text: string | undefined,\n ...fields: (string | null | undefined)[]\n): boolean {\n if (text === undefined || text === \"\") return true;\n const needle = text.toLowerCase();\n return fields.some((f) => f?.toLowerCase().includes(needle) === true);\n}\n\n/**\n * Load the dashboard's whole read model in one pass. Read-only (see the file\n * header); async only for the ctl probes. Throws `WorkstreamNotFoundError` for\n * a `workstream` filter that is not a live workstream.\n */\nexport async function loadDashboard(db: Db, opts: DashboardOptions): Promise<DashboardSnapshot> {\n const live = (\n db\n .prepare(\"SELECT name, id FROM workstreams WHERE torn_down_at IS NULL ORDER BY name\")\n .all() as { name: string; id: number }[]\n ).map((w) => ({ ...w, scratch: isScratchWorkstream(w.name) }));\n if (opts.workstream !== undefined && tryResolveLiveWorkstreamId(db, opts.workstream) === null) {\n throw new WorkstreamNotFoundError(opts.workstream);\n }\n const scoped = live.filter((w) => opts.workstream === undefined || w.name === opts.workstream);\n // Whose tasks, edges and frontier are read (`scopeWorkstream`; `workstream` wins).\n const readFrom =\n opts.workstream !== undefined || opts.scopeWorkstream === undefined\n ? scoped\n : live.filter((w) => w.name === opts.scopeWorkstream);\n const statuses =\n opts.status === undefined || opts.status.length === 0 ? DEFAULT_STATUS : opts.status;\n\n const agentsById = new Map<number, AgentIdentity>(\n (\n db\n .prepare(\n \"SELECT a.id, a.name, w.name AS workstream FROM agents a JOIN workstreams w ON w.id = a.workstream_id\",\n )\n .all() as { id: number; name: string; workstream: string }[]\n ).map((a) => [a.id, { name: a.name, workstream: a.workstream }]),\n );\n // IN_PROGRESS tasks by owner registry id, over EVERY live workstream: a task can be\n // claimed by an agent of another workstream, and a filtered read must still show it.\n const owned = new Map<number, string[]>();\n for (const t of db\n .prepare(\n `SELECT ws.name AS ws, t.local_id AS id, t.owner_id AS owner FROM tasks t\n JOIN workstreams ws ON ws.id = t.workstream_id AND ws.torn_down_at IS NULL\n WHERE t.status = 'IN_PROGRESS' AND t.owner_id IS NOT NULL ORDER BY ws.name, t.local_id`,\n )\n .all() as { ws: string; id: string; owner: number }[]) {\n owned.set(t.owner, [...(owned.get(t.owner) ?? []), keyOf(t.ws, t.id)]);\n }\n\n const tasks: DashboardTask[] = [];\n const edges: DashboardEdge[] = [];\n const frontier: DashboardFrontierCut[] = [];\n const agents: DashboardAgent[] = [];\n const waves: DashboardWave[] = [];\n const now = Date.now();\n for (const ws of readFrom) {\n const activity = taskActivity(db, ws.name);\n const calls = listDelegates(db, undefined, ws.name, { taskStatuses: statuses });\n const callByTask = new Map(calls.map((c) => [c.task, c]));\n waves.push(...wavesOf(db, ws.name));\n tasks.push(\n ...listTasks(db, ws.name, { status: statuses })\n .map((r) => dashboardTask(r, activity, agentsById, callByTask))\n .filter((t) =>\n matches(\n opts.text,\n t.key,\n t.title,\n t.owner,\n t.substate,\n t.call?.state,\n t.call?.verdict,\n t.call?.judges,\n ),\n ),\n );\n const front = loadOpenTaskFrontier(db, ws.name);\n frontier.push({\n workstream: ws.name,\n roots_cut: front.rootsCut,\n again_cut: front.againCut,\n });\n for (const e of front.entries) {\n edges.push({\n key: keyOf(ws.name, e.task.name),\n workstream: ws.name,\n id: e.task.name,\n title: e.task.title,\n status: e.task.status,\n substate: e.task.substate,\n depth: e.depth,\n parent: e.parent === null ? null : keyOf(ws.name, e.parent),\n again: e.again,\n kids: e.kids,\n closed: e.closed,\n cap_cut: e.capCut,\n });\n }\n }\n tasks.sort(byActivityDesc);\n\n // Every live workstream's agents, whatever the scope or text: Attention reads them all.\n const everyAgent: DashboardAgent[] = [];\n for (const ws of live) {\n for (const a of await readLiveAgents(db, ws.name, undefined, opts.agentStates)) {\n const mine = owned.get(a.incarnation) ?? [];\n everyAgent.push({\n ...liveAgentToOutput(a, ws.id),\n key: keyOf(ws.name, a.name),\n tasks: mine,\n task: mine[0] ?? null,\n ...toolOf(a.tool, now),\n });\n }\n }\n const inScope = new Set(scoped.map((w) => w.name));\n agents.push(\n ...everyAgent.filter(\n (a) => inScope.has(a.workstream) && matches(opts.text, a.key, a.state ?? null, ...a.tasks),\n ),\n );\n\n const next = nextOf(\n db,\n opts.callers ?? (opts.caller === null ? [] : [opts.caller]),\n opts.workstream,\n );\n const logWs = opts.logWorkstream ?? opts.workstream;\n const log = listLogs(db, {\n ...(logWs !== undefined ? { workstream: logWs } : {}),\n limit: opts.logLimit ?? DEFAULT_LOG_LIMIT,\n }).map((row) => ({\n ...logItem(row, true).item,\n scope: parseOpKey(row.workstreamName).workstream ?? null,\n }));\n\n const callerOwn = opts.caller !== null;\n const human_needs = callerOwn\n ? openHumanNeeds(db, opts.caller as string)\n .filter((h) => inScope.has(h.workstream))\n .map((h) => ({\n key: keyOf(h.workstream, h.id),\n workstream: h.workstream,\n id: h.id,\n reason: h.reason,\n }))\n : [];\n const delegates = callerOwn\n ? listDelegates(db, opts.caller as string)\n .filter((c) => inScope.has(c.workstream) && !FINISHED_CALL.includes(c.state))\n .map((c) => ({\n call_id: c.callId,\n workstream: c.workstream,\n task: c.task,\n state: c.state,\n wave: c.wave,\n judges: c.record ? `${c.record.workstream}/${c.record.task}` : null,\n agent: c.agent,\n verdict: c.verdict,\n error: c.error,\n updated_at: c.updatedAt,\n }))\n : [];\n\n const attention: DashboardAttention[] = everyAgent.flatMap((a) => agentAttention(a, now));\n const liveNames = new Set(live.map((w) => w.name));\n const troubled = [\n ...listDelegates(db, undefined, undefined, { states: [\"refused\"] }),\n ...listDelegates(db, undefined, undefined, {\n states: [\"failed\"],\n updatedAfter: new Date(now - FAILED_CALL_MS).toISOString(),\n }),\n ];\n // Workstream, then task id, like the human items.\n troubled.sort((a, b) => keyOf(a.workstream, a.task).localeCompare(keyOf(b.workstream, b.task)));\n for (const c of troubled) {\n if (!liveNames.has(c.workstream)) continue;\n // A refused call has no expiry: say how to clear it.\n const how = c.state === \"refused\" ? \" (reissue or cancel it from pi)\" : \"\";\n attention.push({\n key: `delegate:${keyOf(c.workstream, c.task)}`,\n workstream: c.workstream,\n kind: \"delegate\",\n text: `delegate ${c.state}: ${c.request.label ?? c.task}${how}`,\n target: keyOf(c.workstream, c.task),\n });\n }\n for (const t of db\n .prepare(\n `SELECT ws.name AS ws, t.local_id AS id, t.title AS title FROM tasks t\n JOIN workstreams ws ON ws.id = t.workstream_id AND ws.torn_down_at IS NULL\n WHERE t.status = 'OPEN' AND t.kind = 'human' ORDER BY ws.name, t.local_id`,\n )\n .all() as { ws: string; id: string; title: string }[]) {\n attention.push({\n key: `human:${keyOf(t.ws, t.id)}`,\n workstream: t.ws,\n kind: \"human\",\n text: t.title,\n target: keyOf(t.ws, t.id),\n });\n }\n if (next.source === \"unavailable\") {\n attention.push({\n key: \"next_unavailable\",\n workstream: null,\n kind: \"next_unavailable\",\n text: \"next unavailable\",\n target: null,\n });\n }\n (opts.syncWarnings ?? []).forEach((w, i) => {\n attention.push({\n key: `sync:${i}`,\n workstream: null,\n kind: \"sync\",\n text: `sync: ${w}`,\n target: null,\n });\n });\n // Most urgent kind first; within a kind the order read holds (agents, delegate and\n // human items: workstream, then name).\n attention.sort((a, b) => ATTENTION_ORDER.indexOf(a.kind) - ATTENTION_ORDER.indexOf(b.kind));\n\n return {\n caller: opts.caller,\n caller_scope: callerOwn ? \"caller\" : \"none\",\n workstreams: live.map((w) => ({\n name: w.name,\n scratch: w.scratch,\n latest_seq: opts.activity === false ? 0 : latestSeq(db, w.name),\n })),\n tasks,\n edges,\n frontier,\n agents,\n log,\n next: next.plan,\n next_source: next.source,\n human_needs,\n delegates,\n waves,\n attention,\n };\n}\n"],"mappings":"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","names":[]}