@pellux/goodvibes-tui 1.9.1 → 1.9.2

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 (75) hide show
  1. package/CHANGELOG.md +16 -5
  2. package/README.md +1 -1
  3. package/package.json +1 -1
  4. package/src/audio/player.ts +91 -5
  5. package/src/audio/spoken-turn-controller.ts +30 -2
  6. package/src/audio/spoken-turn-wiring.ts +3 -0
  7. package/src/config/credential-availability.ts +1 -1
  8. package/src/config/index.ts +1 -1
  9. package/src/core/turn-cancellation.ts +1 -1
  10. package/src/daemon/cli.ts +4 -4
  11. package/src/daemon/service-commands.ts +8 -8
  12. package/src/input/command-registry.ts +5 -5
  13. package/src/input/commands/config.ts +1 -1
  14. package/src/input/commands/memory.ts +1 -1
  15. package/src/input/commands/planning-runtime.ts +1 -1
  16. package/src/input/commands/recall-review.ts +2 -2
  17. package/src/input/commands/session-content.ts +1 -1
  18. package/src/input/feed-context-factory.ts +1 -1
  19. package/src/input/handler-content-actions.ts +2 -2
  20. package/src/input/handler-feed-routes.ts +2 -2
  21. package/src/input/handler-feed.ts +1 -1
  22. package/src/input/handler-onboarding-daemon-adopt.ts +3 -3
  23. package/src/input/handler-picker-routes.ts +2 -2
  24. package/src/input/handler-shortcuts.ts +1 -1
  25. package/src/input/model-picker.ts +2 -2
  26. package/src/input/onboarding/onboarding-wizard-apply.ts +3 -3
  27. package/src/input/onboarding/onboarding-wizard-network-adopt.ts +3 -3
  28. package/src/input/onboarding/onboarding-wizard-steps.ts +1 -1
  29. package/src/input/session-picker-modal.ts +1 -1
  30. package/src/input/settings-modal-data.ts +2 -2
  31. package/src/main.ts +5 -4
  32. package/src/panels/base-panel.ts +1 -1
  33. package/src/panels/builtin/operations.ts +4 -4
  34. package/src/panels/builtin/shared.ts +1 -1
  35. package/src/panels/fleet-panel-format.ts +1 -1
  36. package/src/panels/fleet-panel.ts +15 -15
  37. package/src/panels/fleet-read-model.ts +11 -11
  38. package/src/panels/fleet-steer.ts +2 -2
  39. package/src/panels/fleet-stop.ts +2 -2
  40. package/src/panels/fleet-tabs.ts +4 -4
  41. package/src/panels/fleet-transcript.ts +5 -5
  42. package/src/panels/types.ts +1 -1
  43. package/src/renderer/compaction-quality.ts +1 -1
  44. package/src/renderer/fleet-tab-strip.ts +2 -2
  45. package/src/renderer/footer-tips.ts +1 -1
  46. package/src/renderer/model-workspace.ts +1 -1
  47. package/src/renderer/session-picker-modal.ts +4 -4
  48. package/src/renderer/shell-surface.ts +1 -1
  49. package/src/renderer/status-glyphs.ts +3 -3
  50. package/src/renderer/terminal-bg-probe.ts +1 -1
  51. package/src/renderer/theme.ts +2 -2
  52. package/src/renderer/turn-injection.ts +3 -3
  53. package/src/renderer/ui-factory.ts +7 -7
  54. package/src/renderer/ui-primitives.ts +3 -3
  55. package/src/runtime/bootstrap-core.ts +3 -3
  56. package/src/runtime/bootstrap-hook-bridge.ts +2 -2
  57. package/src/runtime/bootstrap-shell.ts +3 -3
  58. package/src/runtime/bootstrap.ts +5 -5
  59. package/src/runtime/code-index-services.ts +2 -2
  60. package/src/runtime/index.ts +11 -3
  61. package/src/runtime/legacy-daemon-migration.ts +9 -9
  62. package/src/runtime/memory-fold.ts +1 -1
  63. package/src/runtime/onboarding/snapshot.ts +3 -3
  64. package/src/runtime/onboarding/types.ts +2 -2
  65. package/src/runtime/operator-token-cleanup.ts +2 -2
  66. package/src/runtime/orchestrator-core-services.ts +2 -2
  67. package/src/runtime/process-lifecycle.ts +19 -5
  68. package/src/runtime/services.ts +14 -14
  69. package/src/runtime/session-inbound-inputs.ts +1 -1
  70. package/src/runtime/session-spine-transport.ts +2 -2
  71. package/src/runtime/ui-services.ts +1 -1
  72. package/src/runtime/workstream-services.ts +1 -1
  73. package/src/runtime/wrfc-persistence.ts +2 -2
  74. package/src/shell/ui-openers.ts +2 -2
  75. package/src/version.ts +1 -1
@@ -86,13 +86,13 @@ export function buildOnboardingApplyRequest(controller: OnboardingWizardControll
86
86
  setConfig('service.autostart', hasServers);
87
87
  setConfig('service.restartOnFailure', true);
88
88
  // One-Platform daemon-by-default (SDK docs/decisions/2026-07-05-daemon-by-default.md):
89
- // the loopback-only cross-surface session daemon is safe-by-design (Wave 1:
90
- // loopback bind, auth-gated, rate-limited) and runs regardless of whether
89
+ // the loopback-only cross-surface session daemon is safe-by-design
90
+ // (loopback bind, auth-gated, rate-limited) and runs regardless of whether
91
91
  // browser/LAN/webhook/external-app capabilities are selected here — it is no
92
92
  // longer bundled with those network-exposing surfaces, so onboarding leaves
93
93
  // daemon.enabled untouched and lets the SDK's own default-true (or an existing
94
94
  // explicit user override) govern. (The deprecated danger.daemon alias this
95
- // comment used to also name was removed in Wave 6.)
95
+ // comment used to also name was later removed.)
96
96
  setConfig('controlPlane.enabled', hasServers);
97
97
  setConfig('danger.httpListener', httpListener);
98
98
  setConfig('web.enabled', browserAccess);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * F1 (One-Platform Wave 2 friction fix): the Network step's daemon-source choice
2
+ * Friction fix: the Network step's daemon-source choice
3
3
  * — start a new daemon owned by this TUI (default) vs connect to one that is
4
4
  * already running elsewhere with a known token. Extracted from
5
5
  * onboarding-wizard-steps.ts to keep that file under the architecture line cap.
@@ -78,7 +78,7 @@ export function pushDaemonAdoptionFields(
78
78
  }
79
79
 
80
80
  /**
81
- * W4-D1: the guided, visible entry point for migrating a detected legacy
81
+ * The guided, visible entry point for migrating a detected legacy
82
82
  * `goodvibes-daemon.service` unit — closes the fast-follow-up flagged when
83
83
  * `handleMigrateLegacyDaemonServiceForHandler` (handler-onboarding-daemon-adopt.ts)
84
84
  * shipped fully built but not wired to any onboarding control. Independent of
@@ -107,7 +107,7 @@ export function pushLegacyDaemonMigrationFields(
107
107
  kind: 'status',
108
108
  id: 'network.migrate-legacy-daemon-detected',
109
109
  label: 'Legacy daemon service detected',
110
- // F2 follow-up: name the unit this host actually resolves (carried on the
110
+ // Follow-up: name the unit this host actually resolves (carried on the
111
111
  // snapshot from `resolveConfiguredServiceName` at collection time) — the
112
112
  // MANAGED_SERVICE_NAME fallback only covers snapshots built without it.
113
113
  hint: legacyUnitNote(legacy, legacy.trackedServiceName ?? MANAGED_SERVICE_NAME),
@@ -533,7 +533,7 @@ export function buildNetworkStep(controller: OnboardingWizardControllerLike): On
533
533
  },
534
534
  ];
535
535
 
536
- // F1: recognize an adoptable already-running daemon (see onboarding-wizard-network-adopt.ts).
536
+ // Recognize an adoptable already-running daemon (see onboarding-wizard-network-adopt.ts).
537
537
  const daemonSource = getDaemonSource(controller);
538
538
  pushDaemonAdoptionFields(fields, controller, daemonSource, bindSettings);
539
539
  pushLegacyDaemonMigrationFields(fields, controller);
@@ -6,7 +6,7 @@
6
6
  * control-plane session, see below), tracks selected index, and handles
7
7
  * load/delete actions.
8
8
  *
9
- * W3-T2 (union-sessions surface): additionally surfaces the cross-surface
9
+ * Union-sessions surface: additionally surfaces the cross-surface
10
10
  * session union from `sessionBroker` (a SessionReadFacade — normally
11
11
  * `uiServices.sessions.sessionBroker`, the SessionUnionCache) so a user can
12
12
  * SEE what sessions are live/closed across every surface sharing this
@@ -156,7 +156,7 @@ export function buildSettingGroups(
156
156
  }
157
157
  }
158
158
 
159
- // Wave 5 (wo804): inject the storage.codeIndexEnabled toggle into the
159
+ // Inject the storage.codeIndexEnabled toggle into the
160
160
  // storage category. TUI-local synthetic setting (not in the SDK ConfigKey
161
161
  // union — see code-index-services.ts), same rationale as
162
162
  // notifyAfterSeconds above: opt-in, default off, states its own bounds.
@@ -342,7 +342,7 @@ export function buildNotifyAlertSyntheticEntries(configManager: Pick<ConfigManag
342
342
  }
343
343
 
344
344
  // ---------------------------------------------------------------------------
345
- // Wave 5 (wo804) — storage.codeIndexEnabled synthetic setting
345
+ // storage.codeIndexEnabled synthetic setting
346
346
  // ---------------------------------------------------------------------------
347
347
 
348
348
  /**
package/src/main.ts CHANGED
@@ -202,7 +202,7 @@ async function main() {
202
202
 
203
203
  const unsubs: Array<() => void> = [];
204
204
  let recoveryInterval: ReturnType<typeof setInterval> | null = null;
205
- let stopSpokenOutputForExit: (() => void) | null = null;
205
+ let stopSpokenOutputForExit: (() => Promise<void>) | null = null;
206
206
  let recoveryPending = false;
207
207
  // Which file the current recovery prompt should load/delete from (see recovery-input-helpers.ts).
208
208
  let recoverySource: 'live' | 'preserved' = 'live';
@@ -240,7 +240,8 @@ async function main() {
240
240
  events: uiServices.events,
241
241
  notify: (message) => { systemMessageRouter.high(message); render(); },
242
242
  });
243
- stopSpokenOutputForExit = () => spokenTurns.stop();
243
+ // Exit-path stop: bounded drain of the audio already playing (see stopForExit).
244
+ stopSpokenOutputForExit = () => spokenTurns.stopForExit();
244
245
  unsubs.push(...spokenTurns.unsubs);
245
246
  unsubs.push(attachSpokenTurnModelRouting({
246
247
  orchestrator,
@@ -497,7 +498,7 @@ async function main() {
497
498
  lastInputTokens: orchestrator.lastInputTokens,
498
499
  commandArgsHint,
499
500
  hitlMode: modeManager.getHITLMode(),
500
- // S3d: cross-surface spine posture segment (adopted-daemon mode only).
501
+ // Cross-surface spine posture segment (adopted-daemon mode only).
501
502
  sessionSpineStatus: (() => { const s = uiServices.platform.externalServices?.inspect(); return s?.sessionSpineActive && s.sessionSpineStatus && s.sessionSpineStatus !== 'unknown' ? s.sessionSpineStatus : undefined; })(), runningAgentCount, runningProcessCount,
502
503
  // Composer must not read as focused while the panel/process indicator owns keyboard focus.
503
504
  promptFocused: !input.panelFocused && !input.indicatorFocused,
@@ -646,7 +647,7 @@ async function main() {
646
647
  const terminalOutputGuard = installTuiTerminalOutputGuard({ stdout, stderr: process.stderr, onCapture: (total) => { commandContext.session.runtime.terminalWritesIntercepted = total; render(); } });
647
648
 
648
649
  setRenderRequest(renderNow); // bootstrap's 16ms coalescer calls the composite directly
649
- setPanelFrameRequester(render); // live panels repaint when idle (Wave-6 replay: fleet sat stale until keypress)
650
+ setPanelFrameRequester(render); // live panels repaint when idle (a replay finding: fleet sat stale until keypress)
650
651
  orchestratorRefs.requestRender = render;
651
652
  commandContext.renderRequest = render;
652
653
  wireShellUiOpeners({
@@ -14,7 +14,7 @@ const ERROR_FG = '#ef4444';
14
14
  * markDirty() only sets a flag the compositor reads when a frame is ALREADY
15
15
  * being composed for another reason (input, streaming) — so a live panel
16
16
  * (fleet ticks, registry subscriptions) sat visibly stale while the app was
17
- * idle until the next keypress (Wave-6 replay finding). The scheduler
17
+ * idle until the next keypress (a replay finding). The scheduler
18
18
  * coalesces same-tick requests, so this stays cheap.
19
19
  */
20
20
  let panelFrameRequester: (() => void) | null = null;
@@ -38,7 +38,7 @@ export function registerOperationsPanels(manager: PanelManager, deps: ResolvedBu
38
38
  // process registry constructed once in runtime/services.ts (shared with
39
39
  // every other consumer rather than duplicated here; the registry owns its
40
40
  // own coalesced tick, so no manual lifecycle-event wiring is needed).
41
- // Wave-3 (W3.2): runtimeBus is also passed so the read model can subscribe
41
+ // runtimeBus is also passed so the read model can subscribe
42
42
  // to the honest COMMUNICATION_CONSUMED steer-ack signal (fleet-read-model.ts).
43
43
  const fleetReadModel = createFleetReadModel(ui.runtime.processRegistry, ui.runtime.runtimeBus);
44
44
 
@@ -51,16 +51,16 @@ export function registerOperationsPanels(manager: PanelManager, deps: ResolvedBu
51
51
  description: 'Live unified process tree: agents, WRFC chains, workflows, watchers, and background processes, with interrupt/kill/steer controls',
52
52
  factory: () => new FleetPanel(fleetReadModel, {
53
53
  interrupt: (id: string) => fleetReadModel.interrupt(id),
54
- // Wave-6 (wo-F item d2): re-arm a paused trigger/schedule/automation job.
54
+ // Re-arm a paused trigger/schedule/automation job.
55
55
  resume: (id: string) => fleetReadModel.resume(id),
56
56
  kill: (id: string, opts: { cascade: boolean }) => fleetReadModel.kill(id, opts),
57
- // Wave-3 (C6): full-fidelity transcript source for an attached agent
57
+ // Full-fidelity transcript source for an attached agent
58
58
  // tab — live while the agent runs, frozen briefly after it completes
59
59
  // (AgentManager's bounded retention ring), empty once evicted (the
60
60
  // panel degrades to the on-disk ledger fallback in that case).
61
61
  getConversationSnapshot: (agentId: string) => ui.agents.agentManager.getConversationSnapshot(agentId),
62
62
  resolveSessionLogPath: (agentId: string) => ui.environment.shellPaths.resolveProjectPath('tui', 'sessions', `${agentId}.jsonl`),
63
- // Wave-3 (W3.2): queue a message for a live in-process agent/wrfc-subtask member.
63
+ // Queue a message for a live in-process agent/wrfc-subtask member.
64
64
  steer: (id: string, text: string) => fleetReadModel.steer(id, text),
65
65
  }, deps.configManager),
66
66
  });
@@ -86,7 +86,7 @@ export interface BuiltinPanelDeps {
86
86
  /** Approval broker for control-plane/operator panels. */
87
87
  approvalBroker?: ApprovalBroker;
88
88
  /**
89
- * S3d: cross-surface session READ facade for control-plane/operator panels.
89
+ * Cross-surface session READ facade for control-plane/operator panels.
90
90
  * Sync listSessions()/getSession() shape preserved; in adopted-daemon mode it
91
91
  * serves the daemon-hosted union (with an honest offline note when the wire is
92
92
  * down) instead of only this process's local broker. See session-union-cache.ts.
@@ -2,7 +2,7 @@
2
2
  // fleet-panel-format.ts
3
3
  //
4
4
  // Pure column-layout + cell-formatting helpers for FleetPanel's tree rows.
5
- // Extracted from fleet-panel.ts (S3b hygiene) to hold that file under the
5
+ // Extracted from fleet-panel.ts (file-size hygiene) to hold that file under the
6
6
  // 800-line architecture cap; these are stateless functions the panel's
7
7
  // renderItem/renderDetail call, with no `this` dependency.
8
8
  // ---------------------------------------------------------------------------
@@ -58,21 +58,21 @@ const C = DEFAULT_PANEL_PALETTE;
58
58
  export interface FleetActionCallbacks {
59
59
  /** Graceful interruption (AgentManager.cancel / trigger-schedule disable, via the registry). */
60
60
  readonly interrupt: (id: string) => boolean;
61
- /** Wave-6 (wo-F item d2): re-arm a `paused` node (disabled trigger/schedule or automation job) — interrupt()'s inverse. Honest false when not paused / non-resumable. */
61
+ /** Re-arm a `paused` node (disabled trigger/schedule or automation job) — interrupt()'s inverse. Honest false when not paused / non-resumable. */
62
62
  readonly resume: (id: string) => boolean;
63
63
  /** Hard stop, optionally cascading to killable descendants. Returns the node ids acted on. */
64
64
  readonly kill: (id: string, opts: { readonly cascade: boolean }) => readonly string[];
65
65
  /**
66
- * Wave-3 (C6): fetch an agent's conversation history — live (running) or
66
+ * Fetch an agent's conversation history — live (running) or
67
67
  * frozen (just-completed, still in the SDK's retention ring). Empty array
68
68
  * means "unavailable" (evicted, or never registered) — FleetPanel degrades
69
69
  * to the on-disk ledger fallback in that case, never fabricating content.
70
70
  */
71
71
  readonly getConversationSnapshot: (agentId: string) => readonly ConversationMessageSnapshot[];
72
- /** Wave-3 (C6): resolve the on-disk `<agentId>.jsonl` event-ledger path for the degraded fallback view. */
72
+ /** Resolve the on-disk `<agentId>.jsonl` event-ledger path for the degraded fallback view. */
73
73
  readonly resolveSessionLogPath: (agentId: string) => string;
74
74
  /**
75
- * Wave-3 (W3.2): queue a human message for a live in-process agent (or a
75
+ * Queue a human message for a live in-process agent (or a
76
76
  * wrfc-subtask's current live member agent), delivered at the target's
77
77
  * next turn boundary — never mid-token. Honest refusal
78
78
  * (`{queued:false,reason}`) for anything that cannot take mid-run input
@@ -128,7 +128,7 @@ export class FleetPanel extends ScrollableListPanel<FleetTreeRow> {
128
128
  this.reconcileSteerBadges();
129
129
  this.markDirty();
130
130
  });
131
- // Wave-3 (W3.2): the honest "the agent actually consumed this steer at
131
+ // The honest "the agent actually consumed this steer at
132
132
  // its turn boundary" signal — see fleet-tabs.ts's SteerBadgeStatus doc.
133
133
  // A read-model without a runtimeBus dep never invokes this (graceful
134
134
  // no-op), same degrade as steer()/steerable without a messageBus dep.
@@ -179,13 +179,13 @@ export class FleetPanel extends ScrollableListPanel<FleetTreeRow> {
179
179
  for (const tab of this.tabsState.tabs) tab.lineCache.clear();
180
180
  }
181
181
 
182
- /** True while a session tab (not the root tree) is focused. Replaces the old Wave-2 isDetailFocused() seam. */
182
+ /** True while a session tab (not the root tree) is focused. Replaces the old isDetailFocused() seam. */
183
183
  public isTabActive(): boolean {
184
184
  return this.tabsState.activeTabIndex > 0;
185
185
  }
186
186
 
187
187
  /**
188
- * Wave-3 (W3.2): true while the steer composer on the active tab is open —
188
+ * True while the steer composer on the active tab is open —
189
189
  * every character of a burst (paste, or several fast-typed chars in one
190
190
  * stdin chunk) must land in the draft one at a time rather than being
191
191
  * routed away as panel hotkeys or exploded to the main composer. See
@@ -207,7 +207,7 @@ export class FleetPanel extends ScrollableListPanel<FleetTreeRow> {
207
207
  }
208
208
 
209
209
  /**
210
- * Ctrl+X (panel-close) collision resolution (Wave-3 Part C4): the global
210
+ * Ctrl+X (panel-close) collision resolution: the global
211
211
  * shortcut route (handler-shortcuts.ts) calls this BEFORE closing the
212
212
  * panel. Detaching the active tab consumes the key; on the root tree tab
213
213
  * there is nothing to detach, so this returns false and Ctrl+X falls
@@ -317,7 +317,7 @@ export class FleetPanel extends ScrollableListPanel<FleetTreeRow> {
317
317
  }
318
318
 
319
319
  /**
320
- * Wave-3 (W3.2, risk #2 — "dropped inference"): called on every read-model
320
+ * The "dropped inference" reconciliation: called on every read-model
321
321
  * snapshot update and on the panel's 1s tick. See fleet-steer.ts's
322
322
  * reconcileSteerBadges doc for why this is needed (the SDK emits no
323
323
  * cancelled/expired signal for a queued steer).
@@ -350,7 +350,7 @@ export class FleetPanel extends ScrollableListPanel<FleetTreeRow> {
350
350
  // Confirm overlay owns input first (K-armed kill confirm).
351
351
  if (this.confirmOverlay.handleInput(key)) return true;
352
352
 
353
- // Wave-3 (W3.2): once the steer composer is open on the active tab, it
353
+ // Once the steer composer is open on the active tab, it
354
354
  // owns EVERY key (same full-priority-while-composing contract as
355
355
  // git-panel.ts's commitMessage entry) until Enter (submit) or Esc
356
356
  // (cancel) — a burst/paste and single hotkeys like 'j'/'s'/'[' all land
@@ -458,7 +458,7 @@ export class FleetPanel extends ScrollableListPanel<FleetTreeRow> {
458
458
  }
459
459
 
460
460
  if (key === 's') {
461
- // Batch replay D4: 's' from the TREE was silently dead — steering
461
+ // An earlier replay fix: 's' from the TREE was silently dead — steering
462
462
  // required an undiscoverable Enter-attach first. Attach-and-steer in
463
463
  // one press for a steerable node; honest refusal otherwise.
464
464
  if (!selected) return false;
@@ -485,7 +485,7 @@ export class FleetPanel extends ScrollableListPanel<FleetTreeRow> {
485
485
  }
486
486
 
487
487
  /**
488
- * Wave-3 (W3.2): the `s` gate — mirrors the i/K capability-gating template
488
+ * The `s` gate — mirrors the i/K capability-gating template
489
489
  * exactly (guard on the live node existing, non-terminal, and the specific
490
490
  * capability; consume the key and say so rather than silently no-op-ing).
491
491
  */
@@ -649,13 +649,13 @@ export class FleetPanel extends ScrollableListPanel<FleetTreeRow> {
649
649
 
650
650
  const snapshotRows = this.readModel.getSnapshot().rows;
651
651
  const liveNode = snapshotRows.find((row) => row.node.id === tab.nodeId)?.node ?? null;
652
- // Wave-3 (W3.2): the steer composer only ever applies to 'agent' tabs
652
+ // The steer composer only ever applies to 'agent' tabs
653
653
  // (wrfc-chain has no conversation loop of its own — see
654
654
  // fleet-tabs.ts's FleetAttachableKind doc); the live-node lookup is
655
655
  // shared with the isTerminal computation below either way.
656
656
  const canSteer = liveNode !== null && !isTerminalProcessState(liveNode.state) && liveNode.capabilities.steerable;
657
657
 
658
- // Wave-3 (W3.2): while composing, Enter/Esc replace the tab-switch/detach
658
+ // While composing, Enter/Esc replace the tab-switch/detach
659
659
  // hints (mirrors git-panel.ts's renderCommitCompose footer) so the
660
660
  // footer never advertises a key the composer itself has absorbed.
661
661
  const hints: Array<{ keys: string; label: string }> = tab.steerDraft !== null
@@ -739,7 +739,7 @@ export class FleetPanel extends ScrollableListPanel<FleetTreeRow> {
739
739
  const hints = buildFleetTreeHints(selected?.node, this.follow, this.tabsState.tabs.length > 0);
740
740
 
741
741
  // Tab strip renders only when tabs exist — omitting it entirely with no
742
- // tabs attached keeps the pre-Wave-3 root-tree rendering byte-identical.
742
+ // tabs attached keeps the pre-session-tab root-tree rendering byte-identical.
743
743
  const stripLine = renderFleetTabStrip(this.tabsState, width);
744
744
  const header = stripLine ? [stripLine] : undefined;
745
745
 
@@ -71,7 +71,7 @@ export interface FleetSnapshot {
71
71
 
72
72
  export type FleetStateTone = 'active' | 'success' | 'failure' | 'warn' | 'muted';
73
73
 
74
- // W6-P1 ruling: this is a DIFFERENT table from the SDK presentation
74
+ // Design ruling: this is a DIFFERENT table from the SDK presentation
75
75
  // contract's STATE_GLYPHS (@pellux/goodvibes-sdk/platform/presentation) — that
76
76
  // one is a 4-state semantic alias (good/warn/bad/info) shared by the TUI and
77
77
  // agent renderers; this one is a 12-state ProcessNode taxonomy specific to the
@@ -90,16 +90,16 @@ const STATE_GLYPHS: Record<ProcessState, string> = {
90
90
  done: '✓',
91
91
  failed: '✗',
92
92
  killed: '⊘',
93
- // Wave-3 verb formalization: a distinct TERMINAL outcome from 'killed' —
93
+ // A distinct TERMINAL outcome from 'killed' —
94
94
  // both come from AgentManager.cancel(), but a graceful interrupt request
95
95
  // ('the operator asked nicely') is display-distinguishable from a hard
96
96
  // kill. '◌' verified free against every other glyph in this table.
97
97
  interrupted: '◌',
98
98
  idle: '·',
99
99
  queued: '…',
100
- // Wave-6 SDK: schedules/triggers/automation jobs report 'paused' when
100
+ // SDK behavior: schedules/triggers/automation jobs report 'paused' when
101
101
  // disabled (previously mislabeled 'killed'). NOT terminal — resumable via
102
- // ProcessRegistry.resume() (W6.2 d2 wires the full pause/resume UI in
102
+ // ProcessRegistry.resume() (the full pause/resume UI lives in
103
103
  // fleet-stop.ts). '❚' verified free against every other glyph in this table.
104
104
  paused: '❚',
105
105
  };
@@ -140,11 +140,11 @@ const KIND_TAGS: Record<ProcessKind, string> = {
140
140
  schedule: 'sched',
141
141
  watcher: 'watch',
142
142
  'background-process': 'exec',
143
- // Wave 4 (wo703): orchestration-engine kinds (adapters/orchestration.ts).
143
+ // Orchestration-engine kinds (adapters/orchestration.ts).
144
144
  workstream: 'stream',
145
145
  phase: 'phase',
146
146
  'work-item': 'item',
147
- // Wave 5 (wo804): the repo source-tree code index (adapters/code-index.ts).
147
+ // The repo source-tree code index (adapters/code-index.ts).
148
148
  // A single leaf node — never a rollup of other flat-list nodes (see
149
149
  // ROLLUP_KINDS below) — so no other list in this module needs updating.
150
150
  'code-index': 'index',
@@ -288,7 +288,7 @@ export function buildFleetRows(nodes: readonly ProcessNode[]): FleetTreeRow[] {
288
288
  * nonzero cost/token reading (defense in depth against a future adapter
289
289
  * change, not load-bearing).
290
290
  *
291
- * Wave 4 (wo703) additions — verified against adapters/orchestration.ts:
291
+ * Orchestration-engine additions — verified against adapters/orchestration.ts:
292
292
  * - 'workstream': adaptWorkstream SUMS every work-item's usage/costUsd
293
293
  * exactly once (sumWorkItemUsage/aggregateWorkItemCost), the same
294
294
  * "rollup of nodes that also appear individually" shape as adaptChain —
@@ -308,7 +308,7 @@ export function buildFleetRows(nodes: readonly ProcessNode[]): FleetTreeRow[] {
308
308
  * 'wrfc-subtask'-for-capabilities analogue but the 'agent'-for-usage
309
309
  * analogue. Excluding it would silently zero out real cost/token totals.
310
310
  *
311
- * Wave 5 (wo804): 'code-index' is deliberately NOT in this set either —
311
+ * 'code-index' is deliberately NOT in this set either —
312
312
  * adaptCodeIndex yields exactly one standalone ProcessNode per registry
313
313
  * (never a parent whose children ALSO appear individually in the flat
314
314
  * list), so it is a leaf like 'agent'/'work-item', not a grouping construct.
@@ -435,7 +435,7 @@ export interface FleetReadModel {
435
435
  /** Graceful interruption where the source supports one. Returns true when accepted. */
436
436
  interrupt(id: string): boolean;
437
437
  /**
438
- * Wave-6 (wo-F item d2): re-arm a `paused` node (a disabled trigger/schedule,
438
+ * Re-arm a `paused` node (a disabled trigger/schedule,
439
439
  * or an automation job). The inverse of interrupt()'s pause. Returns true when
440
440
  * accepted; false for a node that is not currently `paused` or whose kind has
441
441
  * no resume path (honest refusal).
@@ -444,14 +444,14 @@ export interface FleetReadModel {
444
444
  /** Hard stop, optionally cascading to descendants. Returns the node ids acted on. */
445
445
  kill(id: string, opts?: { readonly cascade?: boolean }): readonly string[];
446
446
  /**
447
- * Wave-3 (W3.2): queue a human message for a live in-process agent (or a
447
+ * Queue a human message for a live in-process agent (or a
448
448
  * wrfc-subtask's current live member), delivered at its next turn
449
449
  * boundary. Honest refusal (`{queued:false,reason}`) for anything that
450
450
  * cannot take mid-run input — see ProcessRegistry.steer's doc comment.
451
451
  */
452
452
  steer(id: string, text: string): SteerResult;
453
453
  /**
454
- * Wave-3 (W3.2): subscribe to the honest "the agent actually consumed this
454
+ * Subscribe to the honest "the agent actually consumed this
455
455
  * steer at its turn boundary" signal (COMMUNICATION_CONSUMED on the
456
456
  * runtime bus's 'communication' domain). Returns an unsubscribe function.
457
457
  * A read-model constructed without a runtimeBus (e.g. the static factory,
@@ -1,7 +1,7 @@
1
1
  // ---------------------------------------------------------------------------
2
2
  // fleet-steer.ts
3
3
  //
4
- // Wave-3 (W3.2) — steer-badge rendering helpers and the "dropped inference"
4
+ // Steer-badge rendering helpers and the "dropped inference"
5
5
  // reconciliation pass, split out of fleet-panel.ts to keep that file under
6
6
  // the architecture line cap (see check-architecture.ts's 800-line gate).
7
7
  // Pure functions only; FleetPanel still owns the mutable FleetTab.steerBadge
@@ -67,7 +67,7 @@ export function renderSteerBadgeLine(badge: SteerBadge, width: number, palette:
67
67
  }
68
68
 
69
69
  /**
70
- * Wave-3 (W3.2, risk #2 — "dropped inference"): the SDK emits no
70
+ * The "dropped inference" risk: the SDK emits no
71
71
  * cancelled/expired signal for a queued steer, so a badge left `queued`
72
72
  * after its target node goes terminal (done/failed/killed/interrupted)
73
73
  * would hang forever with no honest resolution. Resolves any such badge to
@@ -115,7 +115,7 @@ export function buildFleetTreeHints(
115
115
  { keys: 'j/k', label: 'navigate' },
116
116
  { keys: 'Enter', label: 'attach' },
117
117
  ];
118
- if (live && selected.capabilities.steerable) hints.push({ keys: 's', label: 'steer' }); // D4: discoverable from the tree (attach-and-steer)
118
+ if (live && selected.capabilities.steerable) hints.push({ keys: 's', label: 'steer' }); // discoverable from the tree (attach-and-steer)
119
119
  if (live && selected.capabilities.interruptible) hints.push({ keys: 'i', label: 'interrupt' });
120
120
  if (live && selected.capabilities.killable) hints.push({ keys: 'K', label: 'kill' });
121
121
  if (live && !isPaused && selected.capabilities.pausable) hints.push({ keys: 'p', label: 'pause' });
@@ -125,7 +125,7 @@ export function buildFleetTreeHints(
125
125
  return hints;
126
126
  }
127
127
 
128
- /** K-confirm descendant stats (UX-C item 6): total = every non-terminal descendant (what a cascade kill takes down); active = the individually-killable subset. Was "active only" (Wave-3 C7), undercounting a mixed subtree. */
128
+ /** K-confirm descendant stats (UX-C item 6): total = every non-terminal descendant (what a cascade kill takes down); active = the individually-killable subset. Was "active only" in an earlier version, undercounting a mixed subtree. */
129
129
  export function countDescendantStats(rows: readonly FleetTreeRow[], nodeId: string): { total: number; active: number } {
130
130
  const byParent = new Map<string, string[]>();
131
131
  for (const row of rows) {
@@ -1,7 +1,7 @@
1
1
  // ---------------------------------------------------------------------------
2
2
  // fleet-tabs.ts
3
3
  //
4
- // Wave-3 (W3.1 Part C) — pure, testable tab-state model for FleetPanel's
4
+ // Pure, testable tab-state model for FleetPanel's
5
5
  // session tabs. No BasePanel/rendering dependency, mirroring the
6
6
  // fleet-read-model.ts convention: this module owns attach/detach/switch as
7
7
  // pure state transitions over a small immutable FleetTabsState, so the tab
@@ -32,7 +32,7 @@ export function isAttachableFleetKind(kind: ProcessKind): kind is FleetAttachabl
32
32
  }
33
33
 
34
34
  /**
35
- * Wave-3 (W3.2 steering) — lifecycle of a queued steer message, tracked
35
+ * Lifecycle of a queued steer message, tracked
36
36
  * per-tab. `queued` means `ProcessRegistry.steer()` accepted the message
37
37
  * onto the target's inbox, NOT that the agent has seen it — that is the
38
38
  * later, honest `consumed` transition (a `COMMUNICATION_CONSUMED` runtime-bus
@@ -119,14 +119,14 @@ export interface FleetTab {
119
119
  ledgerEntries: Record<string, unknown>[] | null;
120
120
  ledgerLoadStarted: boolean;
121
121
  /**
122
- * Wave-3 (W3.2): the one-line steer composer's in-progress text, or `null`
122
+ * The one-line steer composer's in-progress text, or `null`
123
123
  * when not composing. Mirrors git-panel.ts's `commitMessage` mutable-slot
124
124
  * convention (FleetPanel.isCapturingTextBurst() gates on this being
125
125
  * non-null so a burst/paste lands here char-by-char, never as tree/tab
126
126
  * hotkeys — see FleetPanel.handleSteerInput).
127
127
  */
128
128
  steerDraft: string | null;
129
- /** Wave-3 (W3.2): this tab's most recent steer message's lifecycle, or null. */
129
+ /** This tab's most recent steer message's lifecycle, or null. */
130
130
  steerBadge: SteerBadge | null;
131
131
  }
132
132
 
@@ -1,9 +1,9 @@
1
1
  // ---------------------------------------------------------------------------
2
2
  // fleet-transcript.ts
3
3
  //
4
- // Wave-3 (W3.1 Part C6) — renders the content of an attached FleetPanel
4
+ // Renders the content of an attached FleetPanel
5
5
  // session tab. Three sources, chosen by what the SDK can actually provide
6
- // (see the W3.1 brief's "central reality check" — a full-fidelity live
6
+ // (see the design brief's "central reality check" — a full-fidelity live
7
7
  // transcript needs a ConversationMessageSnapshot[] history source, which
8
8
  // only exists for a RUNNING agent or a just-completed one still inside the
9
9
  // SDK's bounded retention ring):
@@ -163,8 +163,8 @@ export function renderFleetAgentTranscript(
163
163
  /**
164
164
  * Render a live one-line-per-member summary for an attached wrfc-chain tab.
165
165
  *
166
- * `chainDoneOrAbsent` disambiguates an empty member list (d3, W6.2): a completed
167
- * chain prunes its wrapper node (Wave-3 reap), so zero members can mean the
166
+ * `chainDoneOrAbsent` disambiguates an empty member list: a completed
167
+ * chain prunes its wrapper node (zombie reap), so zero members can mean the
168
168
  * chain FINISHED, not that it has not started. When the chain node is absent
169
169
  * (pruned) or terminal, say so honestly instead of the "(no member agents yet)"
170
170
  * not-started wording.
@@ -284,7 +284,7 @@ function renderLedgerEntry(width: number, entry: Record<string, unknown>, palett
284
284
  { text: `${status}${formatLedgerDuration(entry['durationMs'])}`, fg: tone },
285
285
  ]);
286
286
  }
287
- // W5.2 (wo803) — Wave-5 wo801 per-turn passive knowledge injection
287
+ // Per-turn passive knowledge injection
288
288
  // records, appended to this same JSONL ledger as
289
289
  // `{type:'knowledge_injection', turn, ...record}` (orchestrator-runner.ts).
290
290
  // Without this case these fell through to the generic 'event' default
@@ -142,7 +142,7 @@ export interface Panel {
142
142
  /**
143
143
  * Optional: called by the global Ctrl+X (`panel-close`) shortcut BEFORE it
144
144
  * closes this panel (handler-shortcuts.ts). Return `true` to consume
145
- * Ctrl+X for an in-panel action instead — e.g. FleetPanel (Wave-3 session
145
+ * Ctrl+X for an in-panel action instead — e.g. FleetPanel (session
146
146
  * tabs) detaches its active tab and leaves the panel open. Return `false`
147
147
  * (or omit this hook) to fall through to the ordinary close behavior.
148
148
  * Ctrl+X never reaches a panel's own `handleInput` (ctrl/meta combos are
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Compaction quality-score bridging (Wave-5 W5.4 / B28).
2
+ * Compaction quality-score bridging.
3
3
  *
4
4
  * Reality check (wo803): the SDK's `computeQualityScore()`
5
5
  * (platform/runtime/compaction/quality-score.ts) is only ever called from a
@@ -1,7 +1,7 @@
1
1
  // ---------------------------------------------------------------------------
2
2
  // fleet-tab-strip.ts
3
3
  //
4
- // Wave-3 (W3.1 Part C3) — renders FleetPanel's session-tab strip by reusing
4
+ // Renders FleetPanel's session-tab strip by reusing
5
5
  // renderTabStrip exactly as panel-workspace-bar.ts does for the workspace
6
6
  // tab bar. Deliberately a SEPARATE, visually distinct strip from the
7
7
  // workspace bar: workspace tabs switch PANELS, fleet session tabs switch
@@ -23,7 +23,7 @@ const LABEL_FG = UI_TONES.fg.secondary;
23
23
  /**
24
24
  * Render the fleet session-tab strip, or `null` when there are no attached
25
25
  * tabs — the panel omits the strip entirely in that case (root-tab-only),
26
- * which is what keeps the pre-Wave-3 fleet-panel goldens byte-identical.
26
+ * which is what keeps the pre-session-tab fleet-panel goldens byte-identical.
27
27
  */
28
28
  export function renderFleetTabStrip(
29
29
  state: FleetTabsState,
@@ -29,7 +29,7 @@ export function isAgentActive(composerStatus: string | undefined): boolean {
29
29
  // shell/ui-openers.ts). The bare noun 'panels' undersold that; naming the verb
30
30
  // keeps the tip honest about what the chord actually does.
31
31
  const TIP_PANELS = 'Ctrl+P toggle panels';
32
- // W6.2 e: F2 now opens the Fleet panel (the process modal was retired), so the
32
+ // F2 now opens the Fleet panel (the process modal was retired), so the
33
33
  // tip names 'fleet', not 'processes'.
34
34
  const TIP_PROCESSES = 'F2 fleet';
35
35
  const TIP_HELP = '? help';
@@ -189,7 +189,7 @@ function detailLines(picker: ModelPickerModal, width: number): string[] {
189
189
  } else {
190
190
  lines.push(`Context cap overrides the detected local-model context window for this selection.`);
191
191
  }
192
- // W3-T2: a visible cursor glyph on the query itself when search is focused —
192
+ // A visible cursor glyph on the query itself when search is focused —
193
193
  // the only prior affordance was a footer-hint text swap ('/ search' vs.
194
194
  // 'Typing filters search...'), buried at the end of a long hint line and
195
195
  // easy to miss (confirmed via live tmux repro). This puts the "you are
@@ -6,7 +6,7 @@
6
6
  * - name, timestamp (formatted), message count
7
7
  * Footer hints: [Enter] Load [d] Delete [Esc] Close
8
8
  *
9
- * W3-T2: when the modal was wired with a cross-surface session union
9
+ * When the modal was wired with a cross-surface session union
10
10
  * (`modal.crossSurfaceView.mode !== 'local'`), an additional read-only
11
11
  * "Cross-surface sessions" section is appended, badged kind/status/project
12
12
  * (parity with the webui SessionsView) with one of three honest states —
@@ -66,7 +66,7 @@ function isReapedRecord(record: SharedSessionRecord): boolean {
66
66
  }
67
67
 
68
68
  /**
69
- * Wave-4 UX-lens note: 'reaped' names a mechanism (the idle-session sweep),
69
+ * UX-lens note: 'reaped' names a mechanism (the idle-session sweep),
70
70
  * not a state a first-time reader can guess — the webui pairs its own
71
71
  * 'reaped' badge with a tooltip explaining it
72
72
  * (SessionsView.tsx: "Closed by the idle-session sweep — reopens
@@ -96,7 +96,7 @@ const MAX_CROSS_SURFACE_ROWS = 5;
96
96
  /**
97
97
  * The exact honest note for the current state, or null when the union view
98
98
  * needs no caveat (fresh/embedded with rows). Precedence: offline > stale >
99
- * true-empty — the three states from the W3-T2 brief, never collapsed into
99
+ * true-empty — the three designed states, never collapsed into
100
100
  * each other (an offline view never silently renders as "no sessions yet").
101
101
  */
102
102
  function crossSurfaceNote(view: SessionPickerModal['crossSurfaceView'], rowCount: number): string | null {
@@ -238,7 +238,7 @@ export function renderSessionPickerModal(
238
238
  }
239
239
  }
240
240
 
241
- // W3-T2: cross-surface session union — visible only when a sessionBroker
241
+ // Cross-surface session union — visible only when a sessionBroker
242
242
  // was wired (mode !== 'local'); absent entirely otherwise, so the box size
243
243
  // and content of every pre-existing (local-only) caller is unaffected.
244
244
  if (modal.crossSurfaceView.mode !== 'local') {
@@ -48,7 +48,7 @@ export interface ShellFooterBuildOptions {
48
48
  */
49
49
  readonly compact?: boolean;
50
50
  /**
51
- * S3d: cross-surface session-spine posture for the context-info segment.
51
+ * Cross-surface session-spine posture for the context-info segment.
52
52
  * Set ONLY in adopted-daemon mode ('online'/'offline'); left undefined in
53
53
  * embedded/local mode so no segment renders.
54
54
  */
@@ -4,9 +4,9 @@
4
4
  // Extracted as a neutral module so both status-token.ts and polish.ts can
5
5
  // import from here without creating a circular ESM dependency.
6
6
  //
7
- // W6-P1: STATE_GLYPHS is no longer hardcoded here. It is the SDK presentation
8
- // contract (@pellux/goodvibes-sdk/platform/presentation, landed by W4-S1 and
9
- // already adopted by the agent in W4-R4), aliased to GLYPHS.status so the
7
+ // STATE_GLYPHS is no longer hardcoded here. It is the SDK presentation
8
+ // contract (@pellux/goodvibes-sdk/platform/presentation, and
9
+ // already adopted by the agent), aliased to GLYPHS.status so the
10
10
  // four semantic glyphs are spelled out in exactly one place and can never
11
11
  // drift from the registry again. Re-exported under the historical name so
12
12
  // status-token.ts and polish.ts import unchanged.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * terminal-bg-probe — OSC 11 terminal-background detection for `auto` theme mode.
3
3
  *
4
- * DEBT-2 / F5. On startup, when appearance is `auto` and stdout is a TTY, we ask
4
+ * DEBT-2. On startup, when appearance is `auto` and stdout is a TTY, we ask
5
5
  * the terminal for its background colour with an OSC 11 query and classify the
6
6
  * reply as light or dark. Everything about this is best-effort and conservative:
7
7
  * any timeout, any unparseable reply, any ambiguity resolves to DARK, which is