pantheon-opencode 1.5.0-beta.15 → 1.5.0-beta.17

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 (54) hide show
  1. package/AGENTS.md +14 -63
  2. package/CHANGELOG.md +55 -0
  3. package/README.md +14 -27
  4. package/README.pt-BR.md +5 -6
  5. package/commands/pantheon.md +1 -35
  6. package/package.json +1 -1
  7. package/plugin.json +1 -1
  8. package/pyproject.toml +1 -1
  9. package/scripts/mcp_persistence_server.py +1 -1
  10. package/src/agents/apollo.md +1 -0
  11. package/src/agents/gaia.md +1 -0
  12. package/src/agents/zeus.md +8 -29
  13. package/src/instructions/memory-protocol.instructions.md +6 -3
  14. package/src/instructions/zeus-anti-stall.instructions.md +2 -4
  15. package/src/instructions/zeus-council-synthesis.instructions.md +3 -28
  16. package/src/instructions/zeus-timeout-retry.instructions.md +3 -28
  17. package/src/mcp/mcp_persistence_server.py +1 -1
  18. package/src/mcp/toon_codec.py +2 -4
  19. package/src/pantheon/{delegation-compaction.ts → compaction-context.ts} +10 -100
  20. package/src/pantheon/cost-command.ts +1 -2
  21. package/src/pantheon/delegation-enforce.ts +59 -14
  22. package/src/pantheon/goal-loop.ts +1 -1
  23. package/src/pantheon/goal-store.ts +1 -1
  24. package/src/pantheon/idle-continuation.ts +4 -6
  25. package/src/pantheon/model-command.ts +1 -2
  26. package/src/pantheon/native-task-status.ts +2 -2
  27. package/src/pantheon/session-id.ts +30 -0
  28. package/src/pantheon/task-result-guard.ts +2 -3
  29. package/src/pantheon/todo-enforcer.ts +3 -3
  30. package/src/pantheon/tool-context.ts +23 -0
  31. package/src/pantheon/v2-bridge.ts +1 -4
  32. package/src/plugin-v2.ts +4 -15
  33. package/src/plugin.ts +61 -245
  34. package/src/plugins/tui/dist/tui.d.ts +33 -64
  35. package/src/plugins/tui/dist/tui.d.ts.map +1 -1
  36. package/src/plugins/tui/dist/tui.js +30 -177
  37. package/src/plugins/tui/package-lock.json +2 -2
  38. package/src/plugins/tui/package.json +1 -1
  39. package/src/plugins/tui/src/index.tsx +67 -277
  40. package/src/skills/context-compression/SKILL.md +1 -1
  41. package/scripts/dev-tui.sh +0 -48
  42. package/scripts/generate-preset-docs.mjs +0 -300
  43. package/scripts/generate-prompts.sh +0 -222
  44. package/scripts/install/component.mjs +0 -24
  45. package/scripts/install/migrate-config.mjs +0 -302
  46. package/src/pantheon/delegate-manager.ts +0 -851
  47. package/src/pantheon/delegation-classifier.ts +0 -306
  48. package/src/pantheon/delegation-finalize.ts +0 -468
  49. package/src/pantheon/delegation-notify.ts +0 -212
  50. package/src/pantheon/delegation-toast.ts +0 -73
  51. package/src/pantheon/delegation.ts +0 -1349
  52. package/src/pantheon/native-probe.ts +0 -234
  53. package/src/pantheon/step-cap.ts +0 -110
  54. package/src/pantheon/toon-codec.ts +0 -481
@@ -5,7 +5,7 @@ type DelegationEntry = {
5
5
  alias: string;
6
6
  /** Parent session the job was launched from (dir name under .pantheon/delegations). */
7
7
  sessionID: string;
8
- /** Child session id (= board task id, from the `Task ID` header). The
8
+ /** Child session id (= task id, from the `Task ID` header). The
9
9
  * children channel always sets it from the child session itself; the md
10
10
  * channel parses it so child↔md matching works by taskID. */
11
11
  taskID?: string;
@@ -21,10 +21,11 @@ type DelegationEntry = {
21
21
  /** True while the panel is waiting for pantheon_delegation_read. */
22
22
  read?: boolean;
23
23
  /** Internal provenance used to keep a finalized md report authoritative.
24
- * 'children-only' = a native task() child session with NO board report
25
- * (a native child row); 'md' = board report wins;
26
- * 'board' = read from .pantheon/board/state.json (cross-session FSM). */
27
- source?: 'child' | 'live' | 'md' | 'children-only' | 'board';
24
+ * 'children-only' = a native task() child session with NO delegate report
25
+ * (a native child row); 'md' = the child has a matching report;
26
+ * 'child' = the plain children channel; 'live' = the optimistic tool-event
27
+ * channel. */
28
+ source?: 'child' | 'live' | 'md' | 'children-only';
28
29
  };
29
30
  /** Parse one delegation report md header into a structured entry.
30
31
  * Returns null (skip) when the file is not a recognizable report:
@@ -51,38 +52,18 @@ declare function readDelegationEntries(dir: string): Promise<DelegationEntry[]>;
51
52
  * running first, Finalized desc (the sort applied by readDelegationEntries).
52
53
  * Fail-open: a missing/unreadable directory yields []. */
53
54
  declare function readAllDelegationEntries(root: string): Promise<DelegationEntry[]>;
54
- /** The persisted subset of BackgroundJobRecord the panel consumes. Duck-typed
55
- * so a corrupt/older record never breaks parsing. */
56
- type BoardJobRecord = {
57
- taskID: string;
58
- parentSessionID: string;
59
- agent: string;
60
- description?: string;
61
- state: string;
62
- alias: string;
63
- launchedAt?: number;
64
- completedAt?: number;
65
- updatedAt?: number;
66
- timedOut?: boolean;
67
- };
68
- /** The FilePersistence state path: `<root>/.pantheon/board/state.json`. */
69
- declare function boardStatePath(root: string): string;
70
- /** Read `.pantheon/board/state.json` (the cross-session job board snapshot).
71
- * Fail-open: missing file, corrupt JSON, non-array payload or an unreadable
72
- * path all yield [] — the panel keeps rendering from the other channels. */
73
- declare function readBoardState(root: string): Promise<BoardJobRecord[]>;
74
55
  /** Resolve the PROJECT ROOT used by every pantheon file channel. `directory`
75
56
  * wins over `worktree` (the old `resolveDelegationsDir` already did this);
76
57
  * an absent/empty root or `/` (no git — e.g. the sandbox test project) falls
77
- * back to cwd. Standardised here so the delegations md, the board state file
78
- * and the panel logger all read the SAME root (audit finding: the channels
58
+ * back to cwd. Standardised here so the delegations md and the panel logger
59
+ * all read the SAME root (audit finding: the channels
79
60
  * resolved the root independently). Pure — no I/O. */
80
61
  declare function resolvePantheonRoot(state: {
81
62
  directory?: string;
82
63
  worktree?: string;
83
64
  } | undefined, cwd?: string): string;
84
- /** Resolve the directory where the job board writes delegation md reports.
85
- * The board writes `.pantheon/delegations` RELATIVE to the server cwd,
65
+ /** Resolve the directory where delegation md reports are written.
66
+ * The finalizer writes `.pantheon/delegations` RELATIVE to the server cwd,
86
67
  * which the TUI exposes as `TuiState.path.directory`. */
87
68
  declare function resolveDelegationsDir(state: {
88
69
  directory?: string;
@@ -119,11 +100,11 @@ declare const STALE_RUNNING_THRESHOLD_MS: number;
119
100
  * considered stale. Combined with the stale-running threshold to produce the
120
101
  * display-only `stale-running` state. */
121
102
  declare const IDLE_SILENCE_MS: number;
122
- /** Visual-only terminal retention windows. Reports remain on disk and in the
123
- * board; these constants only control which rows enter the TUI window. */
103
+ /** Visual-only terminal retention windows. Reports remain on disk; these
104
+ * constants only control which rows enter the TUI window. */
124
105
  declare const DELEGATION_DONE_RETENTION_MS: number;
125
106
  declare const DELEGATION_FAILED_RETENTION_MS: number;
126
- /** Alias-less NATIVE task() live entries never receive a board alias (the
107
+ /** Alias-less NATIVE task() live entries never receive a report alias (the
127
108
  * task tool output carries none), so the 30s alias-less prune in
128
109
  * mergeChildDelegationSources must not apply to them — 5 minutes covers a
129
110
  * slow child listing while still bounding the live map. */
@@ -131,7 +112,7 @@ declare const NATIVE_LIVE_ALIASLESS_TTL_MS: number;
131
112
  /**
132
113
  * Mark a running entry as `stale-running` if it has been running longer than
133
114
  * the threshold AND has no recent activity (no `updatedAt` change in the last
134
- * `IDLE_SILENCE_MS`). This is DISPLAY-ONLY — the board state is unchanged.
115
+ * `IDLE_SILENCE_MS`). This is DISPLAY-ONLY — the persisted state is unchanged.
135
116
  *
136
117
  * A `stale-running` entry renders with a warning indicator but the underlying
137
118
  * delegation is still treated as running by the backend.
@@ -152,9 +133,10 @@ declare function delegationActivityLabel(entry: DelegationEntry): string;
152
133
  /** Return a deterministic spinner frame. The View ticks this every 1000ms
153
134
  * (not 140ms — the fast tick flickered without adding information). */
154
135
  declare function delegationSpinnerFrame(now: number): string;
155
- /** Every state the row knows how to draw: the real BackgroundJobBoard FSM
156
- * (src/pantheon/background-job-board.ts) plus the TUI display-only states
157
- * (`retry`, `stale-running`). Fase 1 deliberately omits speculative
136
+ /** Every state the row knows how to draw: the delegation lifecycle states
137
+ * derived from the children status + md reports (`completed`, `error`,
138
+ * `cancelled`, `startup_failed`, `startup_unknown`) plus the TUI-only
139
+ * states (`retry`, `stale-running`). Fase 1 deliberately omits speculative
158
140
  * blocked/paused/scheduled/skipped. There is no `pending` display state: a
159
141
  * pre-dispatch tool part maps to `running` in {@link reduceDelegationToolPart}. */
160
142
  type DelegationDisplayState = DelegationEntry['state'];
@@ -291,31 +273,18 @@ declare function toDelegationEntry(live: LiveDelegationEntry): DelegationEntry;
291
273
  * terminal md entry is authoritative over a live running entry for the
292
274
  * same job (it carries Finalized/timedOut/cancelled from finalize). */
293
275
  declare function mergeDelegationSources(live: readonly LiveDelegationEntry[], md: readonly DelegationEntry[]): DelegationEntry[];
294
- /** Map one persisted board record into the display shape. Returns null for
295
- * states the panel does not render (reconciled / unknown). Pure. */
296
- declare function boardRecordToDelegationEntry(record: BoardJobRecord): DelegationEntry | null;
297
- /** Map a whole board snapshot, dropping unrenderable states. Sorted like every
298
- * other channel (running first, then most recent). Pure. */
299
- declare function boardRecordsToDelegationEntries(records: readonly BoardJobRecord[]): DelegationEntry[];
300
- /** Merge the board over any other channel. The board is AUTHORITATIVE for
301
- * state/alias/agent (it is the persisted FSM). This merge is intentionally
302
- * UNSCOPED so the board can enrich an active-session row (dedup by taskID);
303
- * the caller scopes the merged list with {@link filterDelegationsToSession},
304
- * which is what keeps other-session board jobs out of the panel. Dedup by
305
- * taskID first, then by (sessionID, alias) — aliases are per parent session. Pure. */
306
- declare function mergeBoardDelegationSources(base: readonly DelegationEntry[], board: readonly DelegationEntry[]): DelegationEntry[];
307
276
  /** Scope a fully-merged display list to the ACTIVE session only.
308
277
  *
309
- * The panel is session-scoped: rows from other sessions (board snapshot, md
310
- * history under `.pantheon/delegations/<other-session>/`) and rows with no
278
+ * The panel is session-scoped: rows from other sessions (md history under
279
+ * `.pantheon/delegations/<other-session>/`) and rows with no
311
280
  * attributable session (empty sessionID) are DROPPED. The previous
312
281
  * cross-session behavior rendered those rows and clicking them led to
313
282
  * "Session not found" — there is no cross-session channel anymore.
314
283
  *
315
- * The board/md channels still feed the merge UNFILTERED so the board can
316
- * ENRICH an active-session row with state/alias/agent (dedup by taskID), but
317
- * they can never introduce a row for another session: this filter is applied
318
- * ONCE, after every merge (children + live + md + board).
284
+ * The md channel still feeds the merge UNFILTERED so it can ENRICH an
285
+ * active-session row with state/alias/agent (dedup by taskID), but it can
286
+ * never introduce a row for another session: this filter is applied
287
+ * ONCE, after every merge (children + live + md).
319
288
  *
320
289
  * Returns [] when no active session resolves (null/placeholder) — there is no
321
290
  * scope to show. Native children always carry the active session id (stamped
@@ -379,12 +348,12 @@ declare function buildChildrenPath(id: string | null | undefined): {
379
348
  } | null;
380
349
  /** Duck-typed subset of a child Session (+ its live status type). */
381
350
  type ChildDelegationLike = {
382
- /** Child session id (= board task id). */
351
+ /** Child session id (= task id). */
383
352
  id: string;
384
353
  /** Session title — the delegate's description or prompt prefix. */
385
354
  title?: string;
386
355
  /** Agent name when the child session carries one (duck-typed; native
387
- * task() children may expose it, board reports always do). */
356
+ * task() children may expose it, md reports always do). */
388
357
  agent?: string;
389
358
  /** Status type from api.state.session.status: 'busy' | 'retry' | 'idle',
390
359
  * or undefined when the status API is unavailable. */
@@ -403,11 +372,11 @@ declare function childStatusToState(status: string | undefined): 'running' | 'co
403
372
  *
404
373
  * A row is
405
374
  * `{glyph} {alias:7} {elapsed:>5}` plus a muted description line. The short
406
- * alias (`apo-1`) is the single identity; rows without a board alias show
375
+ * alias (`apo-1`) is the single identity; rows without a report alias show
407
376
  * the agent instead (never both). */
408
377
  type DelegationRowStatus = 'active' | 'done' | 'failed' | 'retry';
409
378
  /** Map every FSM/display state to one of the 4 row kinds. reconciled never
410
- * reaches the panel (the board parser drops it) but reads as done;
379
+ * reaches the panel (the md parser drops it) but reads as done;
411
380
  * cancelled reads as done; startup_failed reads as failed while
412
381
  * startup_unknown (no error known) reads as retry. Pure. */
413
382
  declare function delegationRowStatus(state: DelegationDisplayState): DelegationRowStatus;
@@ -419,8 +388,8 @@ declare function delegationRowGlyph(status: DelegationRowStatus): string;
419
388
  * through the 1s spinner for the given tick; every other kind is static.
420
389
  * Pure. */
421
390
  declare function delegationRowMarker(state: DelegationDisplayState, now?: number): string;
422
- /** ONE identity per row: the short board alias (`apo-1`); a row without a
423
- * board alias (native task() child `native-task` / `native-<id>`, or an
391
+ /** ONE identity per row: the short report alias (`apo-1`); a row without a
392
+ * report alias (native task() child `native-task` / `native-<id>`, or an
424
393
  * alias-less native live row `live-<callID>` kept as children-only) shows
425
394
  * the agent instead — never alias + agent stacked. Pure. */
426
395
  declare function delegationRowIdentity(entry: DelegationEntry): string;
@@ -463,7 +432,7 @@ declare function ceilingDelegationList(all: readonly DelegationEntry[], maxVisib
463
432
  hiddenTerminal: number;
464
433
  };
465
434
  /** Split a display list into native task() rows vs pantheon_delegate rows.
466
- * Native = source 'children-only' (no board report); everything else counts
435
+ * Native = source 'children-only' (no delegate report); everything else counts
467
436
  * as pantheon. Pure — powers the hooks.log line. */
468
437
  declare function countDelegationSources(entries: readonly DelegationEntry[]): {
469
438
  native: number;
@@ -471,7 +440,7 @@ declare function countDelegationSources(entries: readonly DelegationEntry[]): {
471
440
  total: number;
472
441
  };
473
442
  /** Diagnostic hooks.log line for a panel re-fetch, with the children
474
- * breakdown (pantheon = children WITH a board report, native = children
443
+ * breakdown (pantheon = children WITH a delegate report, native = children
475
444
  * WITHOUT one). Pure — the View logs the returned string verbatim. */
476
445
  declare function formatPanelLogLine(children: number, pantheon: number, native: number, md: number, events: number): string;
477
446
  declare function childrenToDelegationEntries(children: readonly ChildDelegationLike[] | undefined, md: readonly DelegationEntry[], now?: number, parentSessionID?: string): DelegationEntry[];
@@ -503,5 +472,5 @@ declare const plugin: TuiPluginModule & {
503
472
  setup: () => Promise<void>;
504
473
  };
505
474
  //#endregion
506
- export { BoardJobRecord, ChildDelegationLike, DELEGATION_ALIAS_WIDTH, DELEGATION_DESCRIPTION_MAX, DELEGATION_DONE_RETENTION_MS, DELEGATION_ELAPSED_WIDTH, DELEGATION_FAILED_RETENTION_MS, DELEGATION_ROW_GLYPHS, DELEGATION_VISIBLE_CEILING, DelegationActivity, DelegationDisplayState, DelegationEntry, DelegationRowStatus, DelegationStateTone, DelegationToolPart, IDLE_SILENCE_MS, LiveDelegationEntry, LiveDelegationStore, NATIVE_LIVE_ALIASLESS_TTL_MS, ParsedDelegationToolPart, STALE_RUNNING_THRESHOLD_MS, ToolActivity, TuiSessionSources, boardRecordToDelegationEntry, boardRecordsToDelegationEntries, boardStatePath, buildChildrenPath, ceilingDelegationList, childStatusToState, childrenToDelegationEntries, collectDelegationToolParts, compareDelegationEntries, countDelegationSources, createDelegationRowOpenHandler, plugin as default, delegationActivity, delegationActivityLabel, delegationElapsed, delegationRowGlyph, delegationRowIdentity, delegationRowMarker, delegationRowStatus, delegationSpinnerFrame, delegationStateTone, extractToolActivity, filterDelegationsToSession, fmtElapsed, formatDelegationAlias, formatDelegationElapsed, formatDelegationHeader, formatDelegationRowLead, formatPanelLogLine, isValidSessionId, latestToolActivityFor, markStaleIfRunning, mergeBoardDelegationSources, mergeChildDelegationSources, mergeDelegationSources, navigateToDelegationSession, panelLogDir, parseDelegationMarkdown, parseDelegationToolPart, readAllDelegationEntries, readBoardState, readDelegationEntries, reduceDelegationToolPart, removeDelegationEntry, resolveCurrentSessionID, resolveDelegationsDir, resolvePantheonRoot, safeSessionPath, seedLiveDelegationMap, splitDelegationList, toDelegationEntry, trackToolActivity, truncateDelegationDescription, tuiLogPath, visibleDelegationList };
475
+ export { ChildDelegationLike, DELEGATION_ALIAS_WIDTH, DELEGATION_DESCRIPTION_MAX, DELEGATION_DONE_RETENTION_MS, DELEGATION_ELAPSED_WIDTH, DELEGATION_FAILED_RETENTION_MS, DELEGATION_ROW_GLYPHS, DELEGATION_VISIBLE_CEILING, DelegationActivity, DelegationDisplayState, DelegationEntry, DelegationRowStatus, DelegationStateTone, DelegationToolPart, IDLE_SILENCE_MS, LiveDelegationEntry, LiveDelegationStore, NATIVE_LIVE_ALIASLESS_TTL_MS, ParsedDelegationToolPart, STALE_RUNNING_THRESHOLD_MS, ToolActivity, TuiSessionSources, buildChildrenPath, ceilingDelegationList, childStatusToState, childrenToDelegationEntries, collectDelegationToolParts, compareDelegationEntries, countDelegationSources, createDelegationRowOpenHandler, plugin as default, delegationActivity, delegationActivityLabel, delegationElapsed, delegationRowGlyph, delegationRowIdentity, delegationRowMarker, delegationRowStatus, delegationSpinnerFrame, delegationStateTone, extractToolActivity, filterDelegationsToSession, fmtElapsed, formatDelegationAlias, formatDelegationElapsed, formatDelegationHeader, formatDelegationRowLead, formatPanelLogLine, isValidSessionId, latestToolActivityFor, markStaleIfRunning, mergeChildDelegationSources, mergeDelegationSources, navigateToDelegationSession, panelLogDir, parseDelegationMarkdown, parseDelegationToolPart, readAllDelegationEntries, readDelegationEntries, reduceDelegationToolPart, removeDelegationEntry, resolveCurrentSessionID, resolveDelegationsDir, resolvePantheonRoot, safeSessionPath, seedLiveDelegationMap, splitDelegationList, toDelegationEntry, trackToolActivity, truncateDelegationDescription, tuiLogPath, visibleDelegationList };
507
476
  //# sourceMappingURL=tui.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tui.d.ts","names":[],"sources":["../src/index.tsx"],"mappings":"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"}
1
+ {"version":3,"file":"tui.d.ts","names":[],"sources":["../src/index.tsx"],"mappings":"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"}
@@ -165,7 +165,7 @@ async function detectVersion(api) {
165
165
  if (ver) return ver;
166
166
  }
167
167
  } catch {}
168
- return "1.5.0-beta.15";
168
+ return "1.5.0-beta.17";
169
169
  }
170
170
  /**
171
171
  * usage-bar — AI subscription usage gauge for the opencode TUI.
@@ -841,71 +841,19 @@ async function readDelegationEntries(dir) {
841
841
  async function readAllDelegationEntries(root) {
842
842
  return readDelegationEntries(join(root, ".pantheon", "delegations"));
843
843
  }
844
- /** The persisted subset of BackgroundJobRecord the panel consumes. Duck-typed
845
- * so a corrupt/older record never breaks parsing. */
846
- /** The FilePersistence state path: `<root>/.pantheon/board/state.json`. */
847
- function boardStatePath(root) {
848
- return join(root, ".pantheon", "board", "state.json");
849
- }
850
- /** Validate one parsed record, keeping only the fields the panel uses.
851
- * Returns null for anything without a taskID/state (a corrupt entry is
852
- * skipped individually — the rest of the snapshot still loads). */
853
- function normalizeBoardRecord(item) {
854
- if (typeof item !== "object" || item === null) return null;
855
- const rec = item;
856
- if (typeof rec.taskID !== "string" || rec.taskID === "") return null;
857
- if (typeof rec.state !== "string" || rec.state === "") return null;
858
- const record = {
859
- taskID: rec.taskID,
860
- parentSessionID: typeof rec.parentSessionID === "string" ? rec.parentSessionID : "",
861
- agent: typeof rec.agent === "string" && rec.agent !== "" ? rec.agent : "agent",
862
- state: rec.state,
863
- alias: typeof rec.alias === "string" ? rec.alias : ""
864
- };
865
- if (typeof rec.description === "string") record.description = rec.description;
866
- if (typeof rec.launchedAt === "number" && Number.isFinite(rec.launchedAt)) record.launchedAt = rec.launchedAt;
867
- if (typeof rec.completedAt === "number" && Number.isFinite(rec.completedAt)) record.completedAt = rec.completedAt;
868
- if (typeof rec.updatedAt === "number" && Number.isFinite(rec.updatedAt)) record.updatedAt = rec.updatedAt;
869
- if (typeof rec.timedOut === "boolean") record.timedOut = rec.timedOut;
870
- return record;
871
- }
872
- /** Read `.pantheon/board/state.json` (the cross-session job board snapshot).
873
- * Fail-open: missing file, corrupt JSON, non-array payload or an unreadable
874
- * path all yield [] — the panel keeps rendering from the other channels. */
875
- async function readBoardState(root) {
876
- let raw;
877
- try {
878
- raw = await readFile(boardStatePath(root), "utf8");
879
- } catch {
880
- return [];
881
- }
882
- let parsed;
883
- try {
884
- parsed = JSON.parse(raw);
885
- } catch {
886
- return [];
887
- }
888
- if (!Array.isArray(parsed)) return [];
889
- const records = [];
890
- for (const item of parsed) {
891
- const record = normalizeBoardRecord(item);
892
- if (record !== null) records.push(record);
893
- }
894
- return records;
895
- }
896
844
  /** Resolve the PROJECT ROOT used by every pantheon file channel. `directory`
897
845
  * wins over `worktree` (the old `resolveDelegationsDir` already did this);
898
846
  * an absent/empty root or `/` (no git — e.g. the sandbox test project) falls
899
- * back to cwd. Standardised here so the delegations md, the board state file
900
- * and the panel logger all read the SAME root (audit finding: the channels
847
+ * back to cwd. Standardised here so the delegations md and the panel logger
848
+ * all read the SAME root (audit finding: the channels
901
849
  * resolved the root independently). Pure — no I/O. */
902
850
  function resolvePantheonRoot(state, cwd = process.cwd()) {
903
851
  const root = state?.directory ?? state?.worktree ?? "";
904
852
  if (root === "" || root === "/") return cwd;
905
853
  return root;
906
854
  }
907
- /** Resolve the directory where the job board writes delegation md reports.
908
- * The board writes `.pantheon/delegations` RELATIVE to the server cwd,
855
+ /** Resolve the directory where delegation md reports are written.
856
+ * The finalizer writes `.pantheon/delegations` RELATIVE to the server cwd,
909
857
  * which the TUI exposes as `TuiState.path.directory`. */
910
858
  function resolveDelegationsDir(state, cwd = process.cwd()) {
911
859
  return join(resolvePantheonRoot(state, cwd), ".pantheon", "delegations");
@@ -962,11 +910,11 @@ const STALE_RUNNING_THRESHOLD_MS = 1800 * 1e3;
962
910
  * considered stale. Combined with the stale-running threshold to produce the
963
911
  * display-only `stale-running` state. */
964
912
  const IDLE_SILENCE_MS = 60 * 1e3;
965
- /** Visual-only terminal retention windows. Reports remain on disk and in the
966
- * board; these constants only control which rows enter the TUI window. */
913
+ /** Visual-only terminal retention windows. Reports remain on disk; these
914
+ * constants only control which rows enter the TUI window. */
967
915
  const DELEGATION_DONE_RETENTION_MS = 120 * 1e3;
968
916
  const DELEGATION_FAILED_RETENTION_MS = 600 * 1e3;
969
- /** Alias-less NATIVE task() live entries never receive a board alias (the
917
+ /** Alias-less NATIVE task() live entries never receive a report alias (the
970
918
  * task tool output carries none), so the 30s alias-less prune in
971
919
  * mergeChildDelegationSources must not apply to them — 5 minutes covers a
972
920
  * slow child listing while still bounding the live map. */
@@ -974,7 +922,7 @@ const NATIVE_LIVE_ALIASLESS_TTL_MS = 300 * 1e3;
974
922
  /**
975
923
  * Mark a running entry as `stale-running` if it has been running longer than
976
924
  * the threshold AND has no recent activity (no `updatedAt` change in the last
977
- * `IDLE_SILENCE_MS`). This is DISPLAY-ONLY — the board state is unchanged.
925
+ * `IDLE_SILENCE_MS`). This is DISPLAY-ONLY — the persisted state is unchanged.
978
926
  *
979
927
  * A `stale-running` entry renders with a warning indicator but the underlying
980
928
  * delegation is still treated as running by the backend.
@@ -1047,9 +995,10 @@ function delegationSpinnerFrame(now) {
1047
995
  const index = Math.floor(Math.max(0, now) / 1e3) % DELEGATION_SPINNER_FRAMES.length;
1048
996
  return DELEGATION_SPINNER_FRAMES[index] ?? DELEGATION_SPINNER_FRAMES[0];
1049
997
  }
1050
- /** Every state the row knows how to draw: the real BackgroundJobBoard FSM
1051
- * (src/pantheon/background-job-board.ts) plus the TUI display-only states
1052
- * (`retry`, `stale-running`). Fase 1 deliberately omits speculative
998
+ /** Every state the row knows how to draw: the delegation lifecycle states
999
+ * derived from the children status + md reports (`completed`, `error`,
1000
+ * `cancelled`, `startup_failed`, `startup_unknown`) plus the TUI-only
1001
+ * states (`retry`, `stale-running`). Fase 1 deliberately omits speculative
1053
1002
  * blocked/paused/scheduled/skipped. There is no `pending` display state: a
1054
1003
  * pre-dispatch tool part maps to `running` in {@link reduceDelegationToolPart}. */
1055
1004
  /** Semantic tone mapped to the TUI theme at the row ({@link DelegationRow}).
@@ -1430,108 +1379,18 @@ function mergeDelegationSources(live, md) {
1430
1379
  all.sort(compareDelegationEntries);
1431
1380
  return all;
1432
1381
  }
1433
- /** Job-board FSM → panel display state. `reconciled` is intentionally absent:
1434
- * the panel parser rejects it (a reconciled job is done and folded away). */
1435
- const BOARD_STATE_TO_DISPLAY = {
1436
- running: "running",
1437
- completed: "completed",
1438
- error: "error",
1439
- startup_failed: "startup_failed",
1440
- startup_unknown: "startup_unknown",
1441
- cancelled: "cancelled"
1442
- };
1443
- /** Map one persisted board record into the display shape. Returns null for
1444
- * states the panel does not render (reconciled / unknown). Pure. */
1445
- function boardRecordToDelegationEntry(record) {
1446
- const state = BOARD_STATE_TO_DISPLAY[record.state];
1447
- if (state === void 0) return null;
1448
- const running = state === "running";
1449
- return {
1450
- alias: record.alias !== "" ? record.alias : `job-${record.taskID.slice(0, 8)}`,
1451
- sessionID: record.parentSessionID,
1452
- taskID: record.taskID,
1453
- agent: record.agent,
1454
- state,
1455
- startedAt: record.launchedAt ?? record.updatedAt ?? 0,
1456
- updatedAt: running ? null : record.completedAt ?? record.updatedAt ?? null,
1457
- timedOut: record.timedOut === true,
1458
- description: record.description ?? "",
1459
- source: "board"
1460
- };
1461
- }
1462
- /** Map a whole board snapshot, dropping unrenderable states. Sorted like every
1463
- * other channel (running first, then most recent). Pure. */
1464
- function boardRecordsToDelegationEntries(records) {
1465
- const out = [];
1466
- for (const record of records) {
1467
- const entry = boardRecordToDelegationEntry(record);
1468
- if (entry !== null) out.push(entry);
1469
- }
1470
- out.sort(compareDelegationEntries);
1471
- return out;
1472
- }
1473
- /** Active (non-terminal) display states — a job in one of these is still live. */
1474
- function isActiveDelegationState(state) {
1475
- return state === "running" || state === "retry" || state === "stale-running";
1476
- }
1477
- /** Temporal guard for the board merge (recycled-alias regression): board
1478
- * aliases recycle across jobs (apo-1 of a previous job), so a board
1479
- * terminal record only closes a running entry when its Finalized timestamp
1480
- * is STRICTLY NEWER than the entry it would close. Older/equal/missing
1481
- * keeps the live entry — when in doubt the live job wins. Pure. */
1482
- function shouldKeepRunningOverBoardTerminal(existing, incoming) {
1483
- if (existing === void 0) return false;
1484
- if (!isActiveDelegationState(existing.state)) return false;
1485
- if (isActiveDelegationState(incoming.state)) return false;
1486
- const incomingTs = incoming.updatedAt;
1487
- if (incomingTs === null) return true;
1488
- return incomingTs <= (existing.updatedAt ?? existing.startedAt);
1489
- }
1490
- /** Merge the board over any other channel. The board is AUTHORITATIVE for
1491
- * state/alias/agent (it is the persisted FSM). This merge is intentionally
1492
- * UNSCOPED so the board can enrich an active-session row (dedup by taskID);
1493
- * the caller scopes the merged list with {@link filterDelegationsToSession},
1494
- * which is what keeps other-session board jobs out of the panel. Dedup by
1495
- * taskID first, then by (sessionID, alias) — aliases are per parent session. Pure. */
1496
- function mergeBoardDelegationSources(base, board) {
1497
- const key = (sessionID, alias) => `${sessionID}\u0000${alias}`;
1498
- const byTaskID = /* @__PURE__ */ new Map();
1499
- const bySessionAlias = /* @__PURE__ */ new Map();
1500
- const out = [...base];
1501
- out.forEach((entry, index) => {
1502
- if (entry.taskID !== void 0) byTaskID.set(entry.taskID, index);
1503
- bySessionAlias.set(key(entry.sessionID, entry.alias), index);
1504
- });
1505
- for (const incoming of board) {
1506
- const index = (incoming.taskID !== void 0 ? byTaskID.get(incoming.taskID) : void 0) ?? bySessionAlias.get(key(incoming.sessionID, incoming.alias));
1507
- if (index === void 0) {
1508
- out.push(incoming);
1509
- const next = out.length - 1;
1510
- if (incoming.taskID !== void 0) byTaskID.set(incoming.taskID, next);
1511
- bySessionAlias.set(key(incoming.sessionID, incoming.alias), next);
1512
- continue;
1513
- }
1514
- if (shouldKeepRunningOverBoardTerminal(out[index], incoming)) continue;
1515
- out[index] = {
1516
- ...incoming,
1517
- sessionID: incoming.sessionID !== "" ? incoming.sessionID : out[index]?.sessionID ?? ""
1518
- };
1519
- }
1520
- out.sort(compareDelegationEntries);
1521
- return out;
1522
- }
1523
1382
  /** Scope a fully-merged display list to the ACTIVE session only.
1524
1383
  *
1525
- * The panel is session-scoped: rows from other sessions (board snapshot, md
1526
- * history under `.pantheon/delegations/<other-session>/`) and rows with no
1384
+ * The panel is session-scoped: rows from other sessions (md history under
1385
+ * `.pantheon/delegations/<other-session>/`) and rows with no
1527
1386
  * attributable session (empty sessionID) are DROPPED. The previous
1528
1387
  * cross-session behavior rendered those rows and clicking them led to
1529
1388
  * "Session not found" — there is no cross-session channel anymore.
1530
1389
  *
1531
- * The board/md channels still feed the merge UNFILTERED so the board can
1532
- * ENRICH an active-session row with state/alias/agent (dedup by taskID), but
1533
- * they can never introduce a row for another session: this filter is applied
1534
- * ONCE, after every merge (children + live + md + board).
1390
+ * The md channel still feeds the merge UNFILTERED so it can ENRICH an
1391
+ * active-session row with state/alias/agent (dedup by taskID), but it can
1392
+ * never introduce a row for another session: this filter is applied
1393
+ * ONCE, after every merge (children + live + md).
1535
1394
  *
1536
1395
  * Returns [] when no active session resolves (null/placeholder) — there is no
1537
1396
  * scope to show. Native children always carry the active session id (stamped
@@ -1600,10 +1459,10 @@ function childStatusToState(status) {
1600
1459
  *
1601
1460
  * A row is
1602
1461
  * `{glyph} {alias:7} {elapsed:>5}` plus a muted description line. The short
1603
- * alias (`apo-1`) is the single identity; rows without a board alias show
1462
+ * alias (`apo-1`) is the single identity; rows without a report alias show
1604
1463
  * the agent instead (never both). */
1605
1464
  /** Map every FSM/display state to one of the 4 row kinds. reconciled never
1606
- * reaches the panel (the board parser drops it) but reads as done;
1465
+ * reaches the panel (the md parser drops it) but reads as done;
1607
1466
  * cancelled reads as done; startup_failed reads as failed while
1608
1467
  * startup_unknown (no error known) reads as retry. Pure. */
1609
1468
  function delegationRowStatus(state) {
@@ -1636,8 +1495,8 @@ function delegationRowMarker(state, now = Date.now()) {
1636
1495
  const status = delegationRowStatus(state);
1637
1496
  return `${status === "active" ? delegationSpinnerFrame(now) : delegationRowGlyph(status)} `;
1638
1497
  }
1639
- /** ONE identity per row: the short board alias (`apo-1`); a row without a
1640
- * board alias (native task() child `native-task` / `native-<id>`, or an
1498
+ /** ONE identity per row: the short report alias (`apo-1`); a row without a
1499
+ * report alias (native task() child `native-task` / `native-<id>`, or an
1641
1500
  * alias-less native live row `live-<callID>` kept as children-only) shows
1642
1501
  * the agent instead — never alias + agent stacked. Pure. */
1643
1502
  function delegationRowIdentity(entry) {
@@ -1736,7 +1595,7 @@ function ceilingDelegationList(all, maxVisible = 8, now = Date.now()) {
1736
1595
  };
1737
1596
  }
1738
1597
  /** Split a display list into native task() rows vs pantheon_delegate rows.
1739
- * Native = source 'children-only' (no board report); everything else counts
1598
+ * Native = source 'children-only' (no delegate report); everything else counts
1740
1599
  * as pantheon. Pure — powers the hooks.log line. */
1741
1600
  function countDelegationSources(entries) {
1742
1601
  let native = 0;
@@ -1748,7 +1607,7 @@ function countDelegationSources(entries) {
1748
1607
  };
1749
1608
  }
1750
1609
  /** Diagnostic hooks.log line for a panel re-fetch, with the children
1751
- * breakdown (pantheon = children WITH a board report, native = children
1610
+ * breakdown (pantheon = children WITH a delegate report, native = children
1752
1611
  * WITHOUT one). Pure — the View logs the returned string verbatim. */
1753
1612
  function formatPanelLogLine(children, pantheon, native, md, events) {
1754
1613
  return `panel: children=${children}(pantheon=${pantheon} native=${native}) md=${md} events=${events}`;
@@ -1763,7 +1622,7 @@ function formatPanelLogLine(children, pantheon, native, md, events) {
1763
1622
  * child of the current session — pantheon_delegate OR the native `task()`
1764
1623
  * tool — carries parentID = caller), so it gets source 'children-only', a
1765
1624
  * per-child alias 'native-<last4 of the child id>' (one identity per native
1766
- * row) instead of a board alias. The 'task nativa' description fallback
1625
+ * row) instead of a report alias. The 'task nativa' description fallback
1767
1626
  * keeps the row non-empty when the child carries no title.
1768
1627
  * A FRESH terminal md state wins over the derived state (a stale md report
1769
1628
  * from a previous incarnation never flips a live child — see
@@ -1776,7 +1635,7 @@ function formatPanelLogLine(children, pantheon, native, md, events) {
1776
1635
  * Sorted running-first (compareDelegationEntries).
1777
1636
  * Pure — no I/O. */
1778
1637
  /** Temporal guard for the children channel (same recycled-alias class as the
1779
- * board merge): an md terminal report matched by taskID may still belong to
1638
+ * md merge): an md terminal report matched by taskID may still belong to
1780
1639
  * a PREVIOUS job incarnation. Accept it only when its Finalized timestamp
1781
1640
  * covers the child's latest activity, when either side has no timestamp to
1782
1641
  * compare, or when both startedAt agree on a single job incarnation.
@@ -2028,18 +1887,12 @@ function View(props) {
2028
1887
  } catch {
2029
1888
  md = [];
2030
1889
  }
2031
- let board = [];
2032
- try {
2033
- board = boardRecordsToDelegationEntries(await readBoardState(projectRoot()));
2034
- } catch {
2035
- board = [];
2036
- }
2037
1890
  const sessionID = resolveCurrentSessionID({
2038
1891
  sessionID: props.sessionID,
2039
1892
  api: props.api
2040
1893
  });
2041
1894
  if (sessionID === null) {
2042
- setChildDelegations(filterDelegationsToSession(mergeBoardDelegationSources(md, board), sessionID));
1895
+ setChildDelegations([]);
2043
1896
  panelLog.info(`${formatPanelLogLine(0, 0, 0, md.length, eventRefreshCount)} (no sessionID — inactive panel)`);
2044
1897
  return;
2045
1898
  }
@@ -2066,7 +1919,7 @@ function View(props) {
2066
1919
  })), md, now(), sessionID);
2067
1920
  for (const [k, v] of props.liveStore.map) if (v.alias === null && v.taskID === null && Date.now() - v.startedAt > 3e4) props.liveStore.map.delete(k);
2068
1921
  const liveEntries = [...props.liveStore.map.values()].filter((entry) => entry.sessionID === sessionID);
2069
- setChildDelegations(filterDelegationsToSession(mergeBoardDelegationSources(mergeChildDelegationSources(childEntries, liveEntries), board), sessionID));
1922
+ setChildDelegations(filterDelegationsToSession(mergeChildDelegationSources(childEntries, liveEntries), sessionID));
2070
1923
  const counts = countDelegationSources(childEntries);
2071
1924
  panelLog.info(formatPanelLogLine(children.length, counts.pantheon, counts.native, md.length, eventRefreshCount));
2072
1925
  } finally {
@@ -2378,6 +2231,6 @@ const plugin = {
2378
2231
  setup: async () => {}
2379
2232
  };
2380
2233
  //#endregion
2381
- export { DELEGATION_ALIAS_WIDTH, DELEGATION_DESCRIPTION_MAX, DELEGATION_DONE_RETENTION_MS, DELEGATION_ELAPSED_WIDTH, DELEGATION_FAILED_RETENTION_MS, DELEGATION_ROW_GLYPHS, DELEGATION_VISIBLE_CEILING, IDLE_SILENCE_MS, NATIVE_LIVE_ALIASLESS_TTL_MS, STALE_RUNNING_THRESHOLD_MS, boardRecordToDelegationEntry, boardRecordsToDelegationEntries, boardStatePath, buildChildrenPath, ceilingDelegationList, childStatusToState, childrenToDelegationEntries, collectDelegationToolParts, compareDelegationEntries, countDelegationSources, createDelegationRowOpenHandler, plugin as default, delegationActivity, delegationActivityLabel, delegationElapsed, delegationRowGlyph, delegationRowIdentity, delegationRowMarker, delegationRowStatus, delegationSpinnerFrame, delegationStateTone, extractToolActivity, filterDelegationsToSession, fmtElapsed, formatDelegationAlias, formatDelegationElapsed, formatDelegationHeader, formatDelegationRowLead, formatPanelLogLine, isValidSessionId, latestToolActivityFor, markStaleIfRunning, mergeBoardDelegationSources, mergeChildDelegationSources, mergeDelegationSources, navigateToDelegationSession, panelLogDir, parseDelegationMarkdown, parseDelegationToolPart, readAllDelegationEntries, readBoardState, readDelegationEntries, reduceDelegationToolPart, removeDelegationEntry, resolveCurrentSessionID, resolveDelegationsDir, resolvePantheonRoot, safeSessionPath, seedLiveDelegationMap, splitDelegationList, toDelegationEntry, trackToolActivity, truncateDelegationDescription, tuiLogPath, visibleDelegationList };
2234
+ export { DELEGATION_ALIAS_WIDTH, DELEGATION_DESCRIPTION_MAX, DELEGATION_DONE_RETENTION_MS, DELEGATION_ELAPSED_WIDTH, DELEGATION_FAILED_RETENTION_MS, DELEGATION_ROW_GLYPHS, DELEGATION_VISIBLE_CEILING, IDLE_SILENCE_MS, NATIVE_LIVE_ALIASLESS_TTL_MS, STALE_RUNNING_THRESHOLD_MS, buildChildrenPath, ceilingDelegationList, childStatusToState, childrenToDelegationEntries, collectDelegationToolParts, compareDelegationEntries, countDelegationSources, createDelegationRowOpenHandler, plugin as default, delegationActivity, delegationActivityLabel, delegationElapsed, delegationRowGlyph, delegationRowIdentity, delegationRowMarker, delegationRowStatus, delegationSpinnerFrame, delegationStateTone, extractToolActivity, filterDelegationsToSession, fmtElapsed, formatDelegationAlias, formatDelegationElapsed, formatDelegationHeader, formatDelegationRowLead, formatPanelLogLine, isValidSessionId, latestToolActivityFor, markStaleIfRunning, mergeChildDelegationSources, mergeDelegationSources, navigateToDelegationSession, panelLogDir, parseDelegationMarkdown, parseDelegationToolPart, readAllDelegationEntries, readDelegationEntries, reduceDelegationToolPart, removeDelegationEntry, resolveCurrentSessionID, resolveDelegationsDir, resolvePantheonRoot, safeSessionPath, seedLiveDelegationMap, splitDelegationList, toDelegationEntry, trackToolActivity, truncateDelegationDescription, tuiLogPath, visibleDelegationList };
2382
2235
 
2383
2236
  //# sourceMappingURL=tui.js.map
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pantheon-tui",
3
- "version": "1.5.0-beta.15",
3
+ "version": "1.5.0-beta.17",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pantheon-tui",
9
- "version": "1.5.0-beta.15",
9
+ "version": "1.5.0-beta.17",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@opencode-ai/plugin": ">=1.14.0",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pantheon-tui",
3
3
  "type": "module",
4
- "version": "1.5.0-beta.15",
4
+ "version": "1.5.0-beta.17",
5
5
  "description": "Pantheon TUI plugin — sidebar (version, preset, sessions, real-time delegations) + AI subscription usage gauges incl. OpenCode Go/Zen dollar limits (vendored, MIT)",
6
6
  "license": "MIT",
7
7
  "exports": {