@pellux/goodvibes-tui 1.27.1 → 2.0.1

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 (405) hide show
  1. package/CHANGELOG.md +116 -2
  2. package/README.md +7 -9
  3. package/bin/goodvibes +2 -2
  4. package/bin/launcher-support.js +8 -4
  5. package/docs/README.md +11 -2
  6. package/docs/foundation-artifacts/operator-contract.json +6403 -2347
  7. package/package.json +14 -25
  8. package/scripts/postinstall.js +35 -35
  9. package/src/audio/spoken-turn-model-routing.ts +1 -1
  10. package/src/cli/bundle-command.ts +5 -5
  11. package/src/cli/completions/generate.ts +1 -1
  12. package/src/cli/doctor.ts +3 -3
  13. package/src/cli/entrypoint.ts +12 -7
  14. package/src/cli/help.ts +4 -5
  15. package/src/cli/hooks-command.ts +1 -1
  16. package/src/cli/index.ts +1 -4
  17. package/src/cli/launch-auto-update.ts +59 -7
  18. package/src/cli/management-commands.ts +6 -6
  19. package/src/cli/management-utils.ts +5 -5
  20. package/src/cli/management.ts +7 -7
  21. package/src/cli/network-posture.ts +1 -1
  22. package/src/cli/package-verification.ts +7 -6
  23. package/src/cli/plugin-bundles-command.ts +1 -1
  24. package/src/cli/plugin-command.ts +2 -2
  25. package/src/cli/service-command.ts +2 -2
  26. package/src/cli/service-posture.ts +4 -4
  27. package/src/cli/status.ts +9 -8
  28. package/src/cli/surface-command.ts +4 -4
  29. package/src/cli/tui-startup.ts +3 -3
  30. package/src/cli-flags.ts +3 -3
  31. package/src/config/goodvibes-home-audit.ts +0 -2
  32. package/src/config/secret-config.ts +37 -5
  33. package/src/config/tui-extension-settings.ts +1 -1
  34. package/src/core/approval-alert.ts +2 -2
  35. package/src/core/budget-breach-notifier.ts +3 -3
  36. package/src/core/conversation-compaction-render.ts +1 -1
  37. package/src/core/conversation-line-cache.ts +1 -1
  38. package/src/core/conversation-render-context.ts +1 -1
  39. package/src/core/conversation-rendering.ts +2 -2
  40. package/src/core/conversation.ts +10 -10
  41. package/src/core/long-task-notifier.ts +2 -2
  42. package/src/core/memory-diagnostics-gateway.ts +1 -1
  43. package/src/core/scriptable-statusline.ts +1 -1
  44. package/src/core/session-auto-titler.ts +1 -1
  45. package/src/core/session-resume-core.ts +2 -2
  46. package/src/core/stream-event-wiring.ts +24 -44
  47. package/src/core/terminal-notifier.ts +3 -3
  48. package/src/core/turn-cancellation.ts +1 -1
  49. package/src/core/turn-event-wiring.ts +5 -5
  50. package/src/input/command-registry.ts +6 -6
  51. package/src/input/commands/channel-pairing.ts +1 -1
  52. package/src/input/commands/cluster-runtime.ts +1 -1
  53. package/src/input/commands/codebase-runtime.ts +1 -1
  54. package/src/input/commands/devices-runtime.ts +1 -1
  55. package/src/input/commands/hosted-runtime.ts +330 -0
  56. package/src/input/commands/local-setup-review.ts +1 -1
  57. package/src/input/commands/local-setup-transfer.ts +2 -2
  58. package/src/input/commands/local-setup.ts +3 -3
  59. package/src/input/commands/managed-runtime.ts +2 -2
  60. package/src/input/commands/operator-rpc.ts +24 -110
  61. package/src/input/commands/payment-card-intake.ts +1 -1
  62. package/src/input/commands/permissions-provenance.ts +2 -2
  63. package/src/input/commands/plugin-runtime.ts +1 -1
  64. package/src/input/commands/provider.ts +1 -1
  65. package/src/input/commands/relay-runtime.ts +18 -9
  66. package/src/input/commands/rewind-runtime.ts +1 -1
  67. package/src/input/commands/runtime-services.ts +1 -1
  68. package/src/input/commands/services-runtime.ts +1 -1
  69. package/src/input/commands/session-workflow.ts +1 -1
  70. package/src/input/commands/settings-sync-runtime.ts +2 -2
  71. package/src/input/commands/share-runtime.ts +1 -1
  72. package/src/input/commands/tasks-runtime.ts +145 -55
  73. package/src/input/commands/update-runtime.ts +31 -28
  74. package/src/input/commands/work-plan-runtime.ts +2 -2
  75. package/src/input/commands/workstream-attempts.ts +1 -1
  76. package/src/input/commands/workstream-runtime.ts +2 -2
  77. package/src/input/commands.ts +2 -0
  78. package/src/input/feature-unit-layout.ts +1 -1
  79. package/src/input/feed-context-factory.ts +3 -3
  80. package/src/input/handler-content-actions.ts +2 -2
  81. package/src/input/handler-feed-routes.ts +1 -1
  82. package/src/input/handler-feed.ts +3 -3
  83. package/src/input/handler-modal-token-routes.ts +1 -1
  84. package/src/input/handler-onboarding-daemon-adopt.ts +3 -2
  85. package/src/input/handler-onboarding.ts +1 -1
  86. package/src/input/handler-types.ts +2 -2
  87. package/src/input/handler-ui-state.ts +1 -1
  88. package/src/input/handler.ts +4 -4
  89. package/src/input/input-history.ts +1 -1
  90. package/src/input/onboarding/onboarding-feature-units.ts +2 -2
  91. package/src/input/onboarding/onboarding-runtime-status.ts +15 -1
  92. package/src/input/onboarding/onboarding-wizard-apply.ts +17 -8
  93. package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +5 -3
  94. package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +1 -1
  95. package/src/input/onboarding/onboarding-wizard-types.ts +1 -1
  96. package/src/input/payments-config.ts +6 -6
  97. package/src/input/search.ts +1 -1
  98. package/src/input/session-picker-modal.ts +46 -0
  99. package/src/input/settings-modal-activation.ts +1 -1
  100. package/src/input/settings-modal-behavior.ts +4 -4
  101. package/src/input/settings-modal-commit.ts +11 -0
  102. package/src/input/settings-modal-data.ts +13 -80
  103. package/src/input/settings-modal-mutations.ts +33 -0
  104. package/src/input/settings-modal-secrets.ts +34 -0
  105. package/src/input/settings-modal-subscriptions.ts +1 -1
  106. package/src/input/settings-modal-types.ts +15 -1
  107. package/src/input/settings-modal.ts +28 -3
  108. package/src/input/worktree-setup-config.ts +1 -1
  109. package/src/main.ts +11 -9
  110. package/src/panels/agent-inspector-shared.ts +2 -2
  111. package/src/panels/base-panel.ts +2 -2
  112. package/src/panels/builtin/operations.ts +6 -8
  113. package/src/panels/builtin/session.ts +17 -0
  114. package/src/panels/builtin/shared.ts +5 -5
  115. package/src/panels/builtin-modals.ts +3 -3
  116. package/src/panels/confirm-state.ts +1 -1
  117. package/src/panels/cost-tracker-panel.ts +4 -4
  118. package/src/panels/diff-panel.ts +2 -2
  119. package/src/panels/diff-review-panel.ts +2 -2
  120. package/src/panels/expandable-list-panel.ts +2 -2
  121. package/src/panels/fleet-acts.ts +1 -1
  122. package/src/panels/fleet-observed-render.ts +1 -1
  123. package/src/panels/fleet-panel-format.ts +1 -1
  124. package/src/panels/fleet-panel.ts +1 -1
  125. package/src/panels/fleet-spawn.ts +1 -1
  126. package/src/panels/fleet-steer.ts +1 -1
  127. package/src/panels/fleet-transcript.ts +1 -1
  128. package/src/panels/git-panel.ts +1 -1
  129. package/src/panels/hosted-session-feed.ts +352 -0
  130. package/src/panels/hosted-session-panel.ts +221 -0
  131. package/src/panels/local-auth-panel.ts +3 -3
  132. package/src/panels/modals/devices-modal.ts +1 -1
  133. package/src/panels/modals/local-auth-modal.ts +1 -1
  134. package/src/panels/modals/pairing-modal.ts +1 -1
  135. package/src/panels/modals/services-modal.ts +1 -1
  136. package/src/panels/modals/settings-sync-modal.ts +1 -1
  137. package/src/panels/modals/subscription-modal.ts +1 -1
  138. package/src/panels/modals/work-plan-modal.ts +1 -1
  139. package/src/panels/notifications-panel.ts +1 -1
  140. package/src/panels/panel-confirm-overlay.ts +1 -1
  141. package/src/panels/plugins-panel.ts +2 -2
  142. package/src/panels/polish-core.ts +2 -2
  143. package/src/panels/polish-tables.ts +1 -1
  144. package/src/panels/polish.ts +2 -2
  145. package/src/panels/scrollable-list-panel.ts +3 -3
  146. package/src/panels/skills-panel.ts +3 -3
  147. package/src/panels/token-budget-panel.ts +5 -5
  148. package/src/panels/types.ts +1 -2
  149. package/src/permissions/prompt.ts +1 -1
  150. package/src/renderer/autocomplete-overlay.ts +1 -1
  151. package/src/renderer/block-actions-overlay.ts +1 -1
  152. package/src/renderer/bookmark-modal.ts +1 -1
  153. package/src/renderer/buffer.ts +1 -1
  154. package/src/renderer/code-block.ts +1 -1
  155. package/src/renderer/composer-fragments.ts +1 -1
  156. package/src/renderer/compositor.ts +2 -2
  157. package/src/renderer/config-modal.ts +1 -1
  158. package/src/renderer/context-inspector.ts +1 -1
  159. package/src/renderer/conversation-layout.ts +2 -2
  160. package/src/renderer/conversation-overlays.ts +1 -1
  161. package/src/renderer/conversation-surface.ts +2 -2
  162. package/src/renderer/diff-view.ts +1 -1
  163. package/src/renderer/diff.ts +1 -1
  164. package/src/renderer/file-picker-overlay.ts +1 -1
  165. package/src/renderer/fleet-tab-strip.ts +1 -1
  166. package/src/renderer/fullscreen-primitives.ts +2 -2
  167. package/src/renderer/fullscreen-workspace.ts +1 -1
  168. package/src/renderer/header-line.ts +1 -1
  169. package/src/renderer/help-overlay.ts +1 -1
  170. package/src/renderer/history-search-overlay.ts +2 -2
  171. package/src/renderer/layout.ts +5 -8
  172. package/src/renderer/markdown-inline.ts +1 -1
  173. package/src/renderer/markdown-table.ts +1 -1
  174. package/src/renderer/markdown.ts +1 -1
  175. package/src/renderer/mcp-workspace.ts +1 -1
  176. package/src/renderer/modal-factory.ts +2 -2
  177. package/src/renderer/model-workspace.ts +2 -2
  178. package/src/renderer/onboarding/onboarding-wizard.ts +1 -1
  179. package/src/renderer/overlay-box.ts +1 -1
  180. package/src/renderer/panel-composite.ts +1 -1
  181. package/src/renderer/panel-workspace-bar.ts +1 -1
  182. package/src/renderer/process-indicator.ts +1 -1
  183. package/src/renderer/profile-picker-modal.ts +1 -1
  184. package/src/renderer/search-overlay.ts +2 -2
  185. package/src/renderer/selection-modal-overlay.ts +1 -1
  186. package/src/renderer/session-picker-modal.ts +124 -3
  187. package/src/renderer/settings-modal-helpers.ts +2 -0
  188. package/src/renderer/settings-modal.ts +2 -2
  189. package/src/renderer/shell-surface.ts +2 -2
  190. package/src/renderer/system-message.ts +1 -1
  191. package/src/renderer/tab-strip.ts +1 -1
  192. package/src/renderer/theme-mode-config.ts +1 -1
  193. package/src/renderer/theme.ts +11 -12
  194. package/src/renderer/thinking.ts +1 -1
  195. package/src/renderer/tool-call.ts +2 -2
  196. package/src/renderer/tool-result-expanded-lines.ts +1 -1
  197. package/src/renderer/turn-injection.ts +7 -8
  198. package/src/renderer/ui-factory.ts +3 -3
  199. package/src/runtime/bootstrap-command-context.ts +4 -4
  200. package/src/runtime/bootstrap-command-parts.ts +5 -5
  201. package/src/runtime/bootstrap-core.ts +30 -30
  202. package/src/runtime/bootstrap-shell.ts +4 -4
  203. package/src/runtime/bootstrap.ts +128 -157
  204. package/src/runtime/client/approval-updates.ts +82 -0
  205. package/src/runtime/client/build-floors.ts +167 -0
  206. package/src/runtime/client/daemon-attach-handshake.ts +115 -0
  207. package/src/runtime/client/fleet-union.ts +147 -0
  208. package/src/runtime/client/host-service-status.ts +71 -0
  209. package/src/runtime/client/hosted-exit.ts +86 -0
  210. package/src/runtime/client/hosted-roster.ts +110 -0
  211. package/src/runtime/client/hosted-session-stream.ts +178 -0
  212. package/src/runtime/client/hosted-sessions.ts +187 -0
  213. package/src/runtime/client/operator-endpoint.ts +213 -0
  214. package/src/runtime/client/spine-adoption.ts +99 -0
  215. package/src/runtime/cloudflare-control-plane.ts +1 -1
  216. package/src/runtime/context-accounting-source.ts +1 -1
  217. package/src/runtime/context.ts +2 -2
  218. package/src/runtime/conversation-rewind-port.ts +42 -14
  219. package/src/runtime/daemon-attach-notices.ts +55 -19
  220. package/src/runtime/diagnostics/panels/ops.ts +1 -1
  221. package/src/runtime/disposal-wiring.ts +4 -24
  222. package/src/runtime/index.ts +119 -105
  223. package/src/runtime/install-self-check-startup.ts +2 -2
  224. package/src/runtime/interaction-seams.ts +1 -1
  225. package/src/runtime/knowledge-services.ts +8 -2
  226. package/src/runtime/legacy-daemon-migration.ts +4 -3
  227. package/src/runtime/legacy-daemon-reconcile.ts +3 -2
  228. package/src/runtime/memory-spine-transport.ts +37 -267
  229. package/src/runtime/notification-dispatch.ts +2 -2
  230. package/src/runtime/onboarding/apply.ts +2 -2
  231. package/src/runtime/onboarding/derivation.ts +2 -2
  232. package/src/runtime/onboarding/markers.ts +2 -2
  233. package/src/runtime/onboarding/progress.ts +2 -2
  234. package/src/runtime/onboarding/snapshot.ts +1 -1
  235. package/src/runtime/onboarding/state.ts +2 -2
  236. package/src/runtime/onboarding/types.ts +2 -2
  237. package/src/runtime/orchestrator-core-services.ts +1 -1
  238. package/src/runtime/path-shadow-startup.ts +28 -221
  239. package/src/runtime/power-keepawake-remote.ts +3 -2
  240. package/src/runtime/process-lifecycle.ts +2 -2
  241. package/src/runtime/provider-fallback.ts +10 -66
  242. package/src/runtime/recovery-autosave.ts +1 -1
  243. package/src/runtime/recovery-offer-wiring.ts +39 -23
  244. package/src/runtime/recovery-prompt.ts +31 -17
  245. package/src/runtime/relay-reachability-bridge.ts +53 -42
  246. package/src/runtime/release-artifacts.ts +2 -1
  247. package/src/runtime/runtime-services-types.ts +82 -35
  248. package/src/runtime/services.ts +305 -300
  249. package/src/runtime/session-resume-liveness-confirm.ts +1 -1
  250. package/src/runtime/ui-services.ts +7 -6
  251. package/src/runtime/update-check.ts +23 -43
  252. package/src/runtime/workspace-checkpointing.ts +1 -1
  253. package/src/runtime/wrfc-persistence.ts +2 -2
  254. package/src/shell/ui-openers.ts +30 -7
  255. package/src/utils/clipboard.ts +1 -1
  256. package/src/verification/verification-ledger.ts +10 -8
  257. package/src/version.ts +1 -1
  258. package/bin/goodvibes-daemon +0 -90
  259. package/src/cli/config-overrides.ts +0 -267
  260. package/src/cli/endpoints.ts +0 -109
  261. package/src/cli/parser.ts +0 -395
  262. package/src/cli/redaction.ts +0 -170
  263. package/src/cli/types.ts +0 -84
  264. package/src/cluster/commands.ts +0 -382
  265. package/src/cluster/remote-daemon-target.ts +0 -225
  266. package/src/cluster/render.ts +0 -268
  267. package/src/config/atomic-write.ts +0 -70
  268. package/src/config/credential-availability.ts +0 -122
  269. package/src/config/goodvibes-home.ts +0 -149
  270. package/src/config/index.ts +0 -88
  271. package/src/config/provider-model.ts +0 -23
  272. package/src/config/read-versioned.ts +0 -228
  273. package/src/core/alert-gating.ts +0 -67
  274. package/src/core/consolidation-receipt.ts +0 -41
  275. package/src/core/focus-tracker.ts +0 -41
  276. package/src/core/history.ts +0 -45
  277. package/src/core/memory-status.ts +0 -118
  278. package/src/core/orchestrator.ts +0 -7
  279. package/src/core/pairing-devices.ts +0 -49
  280. package/src/core/pairing-handoff.ts +0 -101
  281. package/src/core/pairing-offers.ts +0 -83
  282. package/src/core/pairing-origin.ts +0 -78
  283. package/src/core/rewind-turn-anchors.ts +0 -311
  284. package/src/core/session-recovery.ts +0 -210
  285. package/src/core/stable-host.ts +0 -171
  286. package/src/core/transcript-journal.ts +0 -503
  287. package/src/daemon/cli.ts +0 -693
  288. package/src/daemon/fatal-boot-report.ts +0 -111
  289. package/src/daemon/handlers/context.ts +0 -29
  290. package/src/daemon/handlers/contracts.ts +0 -77
  291. package/src/daemon/handlers/credentials.ts +0 -139
  292. package/src/daemon/handlers/drafts/draft-store.ts +0 -427
  293. package/src/daemon/handlers/drafts/index.ts +0 -17
  294. package/src/daemon/handlers/drafts/register.ts +0 -331
  295. package/src/daemon/handlers/errors.ts +0 -18
  296. package/src/daemon/handlers/inbox/cursor-store.ts +0 -457
  297. package/src/daemon/handlers/inbox/index.ts +0 -284
  298. package/src/daemon/handlers/inbox/mapping.ts +0 -192
  299. package/src/daemon/handlers/inbox/poller.ts +0 -212
  300. package/src/daemon/handlers/inbox/provider-adapter.ts +0 -156
  301. package/src/daemon/handlers/inbox/providers/discord.ts +0 -252
  302. package/src/daemon/handlers/inbox/providers/email.ts +0 -152
  303. package/src/daemon/handlers/inbox/providers/imap-client.ts +0 -300
  304. package/src/daemon/handlers/inbox/providers/route-util.ts +0 -24
  305. package/src/daemon/handlers/inbox/providers/slack.ts +0 -263
  306. package/src/daemon/handlers/index.ts +0 -117
  307. package/src/daemon/handlers/register.ts +0 -168
  308. package/src/daemon/handlers/remote/backends/cloud-terminal.ts +0 -142
  309. package/src/daemon/handlers/remote/backends/docker.ts +0 -79
  310. package/src/daemon/handlers/remote/backends/index.ts +0 -40
  311. package/src/daemon/handlers/remote/backends/local-process.ts +0 -113
  312. package/src/daemon/handlers/remote/backends/process-runner.ts +0 -127
  313. package/src/daemon/handlers/remote/backends/ssh.ts +0 -125
  314. package/src/daemon/handlers/remote/backends/types.ts +0 -97
  315. package/src/daemon/handlers/remote/dispatcher.ts +0 -181
  316. package/src/daemon/handlers/remote/index.ts +0 -119
  317. package/src/daemon/handlers/remote/peer-registry.ts +0 -357
  318. package/src/daemon/handlers/remote/service.ts +0 -191
  319. package/src/daemon/handlers/routing/inbox-bridge.ts +0 -71
  320. package/src/daemon/handlers/routing/index.ts +0 -261
  321. package/src/daemon/handlers/routing/route-store.ts +0 -319
  322. package/src/daemon/handlers/routing/routing-resolver.ts +0 -75
  323. package/src/daemon/handlers/sqlite-store.ts +0 -278
  324. package/src/daemon/handlers/triage/index.ts +0 -57
  325. package/src/daemon/handlers/triage/integration.ts +0 -213
  326. package/src/daemon/handlers/triage/pipeline.ts +0 -274
  327. package/src/daemon/handlers/triage/scorer.ts +0 -287
  328. package/src/daemon/handlers/triage/tagger/discord.ts +0 -187
  329. package/src/daemon/handlers/triage/tagger/imap.ts +0 -384
  330. package/src/daemon/handlers/triage/tagger/index.ts +0 -184
  331. package/src/daemon/handlers/triage/tagger/shared.ts +0 -70
  332. package/src/daemon/handlers/triage/tagger/slack.ts +0 -69
  333. package/src/daemon/handlers/triage/types.ts +0 -50
  334. package/src/daemon/lifecycle.ts +0 -41
  335. package/src/daemon/provision-wake-model.ts +0 -81
  336. package/src/daemon/safe-serve.ts +0 -61
  337. package/src/daemon/send/channels.ts +0 -200
  338. package/src/daemon/send/command.ts +0 -332
  339. package/src/daemon/send/composition.ts +0 -99
  340. package/src/daemon/send/failure-text.ts +0 -93
  341. package/src/daemon/send/inert-text.ts +0 -225
  342. package/src/daemon/send/stdin.ts +0 -24
  343. package/src/daemon/service-commands.ts +0 -329
  344. package/src/export/cost-utils.ts +0 -319
  345. package/src/input/selection.ts +0 -135
  346. package/src/plugins/loader.ts +0 -15
  347. package/src/renderer/bottom-bar.ts +0 -58
  348. package/src/renderer/conversation-tree.ts +0 -228
  349. package/src/runtime/agent-graph-composition.ts +0 -78
  350. package/src/runtime/channel-composition.ts +0 -46
  351. package/src/runtime/cluster-composition.ts +0 -124
  352. package/src/runtime/cluster-group-composition.ts +0 -284
  353. package/src/runtime/code-index-services.ts +0 -167
  354. package/src/runtime/daemon-handler-composition.ts +0 -76
  355. package/src/runtime/device-posture-composition.ts +0 -110
  356. package/src/runtime/durability-housekeeping.ts +0 -183
  357. package/src/runtime/durability-services.ts +0 -155
  358. package/src/runtime/embedded-service-factories.ts +0 -74
  359. package/src/runtime/feature-settings.ts +0 -154
  360. package/src/runtime/fleet-needs-input-push.ts +0 -70
  361. package/src/runtime/fleet-services.ts +0 -41
  362. package/src/runtime/idle-power-services.ts +0 -85
  363. package/src/runtime/mail-composition.ts +0 -65
  364. package/src/runtime/memory-fold.ts +0 -55
  365. package/src/runtime/operator-token-cleanup.ts +0 -109
  366. package/src/runtime/path-shadow.ts +0 -418
  367. package/src/runtime/perf/panel-health-monitor.ts +0 -18
  368. package/src/runtime/provider-optimizer-wiring.ts +0 -55
  369. package/src/runtime/reachability-notice.ts +0 -100
  370. package/src/runtime/remote-execution-composition.ts +0 -62
  371. package/src/runtime/session-liveness-marker.ts +0 -257
  372. package/src/runtime/session-pointer-surface.ts +0 -22
  373. package/src/runtime/session-storage-services.ts +0 -41
  374. package/src/runtime/surface-feature-flags.ts +0 -96
  375. package/src/runtime/terminal-output-guard.ts +0 -235
  376. package/src/runtime/trust/workspace-registration.ts +0 -192
  377. package/src/runtime/trust/workspace-trust.ts +0 -229
  378. package/src/runtime/ui/index.ts +0 -39
  379. package/src/runtime/ui/model-picker/data-provider.ts +0 -182
  380. package/src/runtime/ui/model-picker/health-enrichment.ts +0 -231
  381. package/src/runtime/ui/model-picker/index.ts +0 -59
  382. package/src/runtime/ui/model-picker/types.ts +0 -153
  383. package/src/runtime/ui/provider-health/data-provider.ts +0 -244
  384. package/src/runtime/ui/provider-health/fallback-visualizer.ts +0 -71
  385. package/src/runtime/ui/provider-health/index.ts +0 -46
  386. package/src/runtime/ui/provider-health/types.ts +0 -146
  387. package/src/runtime/ui-events.ts +0 -1
  388. package/src/runtime/ui-read-model-helpers.ts +0 -1
  389. package/src/runtime/ui-read-models-observability-maintenance.ts +0 -1
  390. package/src/runtime/ui-read-models-observability-options.ts +0 -1
  391. package/src/runtime/ui-read-models-observability-remote.ts +0 -1
  392. package/src/runtime/ui-read-models-observability-security.ts +0 -1
  393. package/src/runtime/ui-read-models-observability-system.ts +0 -1
  394. package/src/runtime/ui-read-models-observability.ts +0 -1
  395. package/src/runtime/ui-service-queries.ts +0 -1
  396. package/src/runtime/voice-setup-services.ts +0 -98
  397. package/src/runtime/workstream-attempts-validation.ts +0 -77
  398. package/src/runtime/workstream-draft-edits.ts +0 -95
  399. package/src/runtime/workstream-draft-store.ts +0 -274
  400. package/src/runtime/workstream-draft-types.ts +0 -42
  401. package/src/runtime/workstream-services.ts +0 -373
  402. package/src/tools/index.ts +0 -1
  403. package/src/types/grid.ts +0 -48
  404. package/src/types/sql-js.d.ts +0 -15
  405. package/src/work-plans/work-plan-store.ts +0 -702
@@ -1,503 +0,0 @@
1
- /**
2
- * transcript-journal.ts — WAL-style append-only transcript journal.
3
- *
4
- * Purpose
5
- * ───────
6
- * Between full snapshots (written by persistConversation / writeRecoveryFile),
7
- * a SIGKILL loses every conversation turn since the last snapshot. This module
8
- * provides an append-only journal that records each durable conversation event
9
- * (user message submitted, assistant turn finalised, tool results appended,
10
- * compaction performed) so that a kill at any moment loses at most the
11
- * in-flight append — never a full turn.
12
- *
13
- * File format (NDJSON)
14
- * ────────────────────
15
- * Line 0 — header: { version: 1, sessionId: "...", createdAt: <epochMs> }
16
- * Line 1+ — records: { type, seq, ts, messages: ConversationMessageSnapshot[] }
17
- *
18
- * The header carries the schemaVersion so that a reader from a future process
19
- * can gate on it (readVersioned convention: unknown version → quarantine).
20
- *
21
- * Durability / performance tradeoff
22
- * ──────────────────────────────────
23
- * appendRecord() performs one appendFileSync + one fsyncSync per call.
24
- * This means one fsync per durable conversation event (user message,
25
- * assistant turn, tool result batch, compaction). It does NOT fsync per
26
- * streaming token — the streaming path never calls appendRecord().
27
- *
28
- * At typical usage (a few events per user turn), this is 2–6 fsyncs/min,
29
- * well within the durability/throughput envelope of any modern filesystem.
30
- * The tradeoff is explicit: we accept per-event write amplification in
31
- * exchange for at-most-one-record loss on SIGKILL.
32
- *
33
- * Recovery semantics
34
- * ──────────────────
35
- * 1. Read the header line. Gate on version — quarantine if unrecognised.
36
- * 2. Read subsequent lines until EOF. Stop at the first line that is not
37
- * valid JSON or lacks the expected shape. Quarantine the remainder of
38
- * the file from that point onward (rename to .unrecognized). Never crash.
39
- * 3. Return only records whose `ts` is strictly greater than the provided
40
- * `snapshotTimestamp` (i.e. events that occurred after the last snapshot).
41
- * 4. Caller replays the returned records in `seq` order atop the snapshot
42
- * to reconstruct the conversation, then writes a fresh snapshot and
43
- * calls `journal.rotate()` to truncate the journal.
44
- *
45
- * Rotation
46
- * ────────
47
- * After a fresh snapshot is written, call journal.rotate() which deletes the
48
- * journal file. The next append will recreate it with a fresh header.
49
- *
50
- * Journal path convention
51
- * ───────────────────────
52
- * <homeDirectory>/.goodvibes/tui/transcript-<sessionId>.journal
53
- * This mirrors the recovery-file location (homeDirectory-scoped, not
54
- * workingDir-scoped) so all per-session durability artefacts live together.
55
- */
56
-
57
- import {
58
- appendFileSync,
59
- closeSync,
60
- existsSync,
61
- fsyncSync,
62
- mkdirSync,
63
- openSync,
64
- readFileSync,
65
- readdirSync,
66
- renameSync,
67
- statSync,
68
- unlinkSync,
69
- } from 'node:fs';
70
- import { dirname, join } from 'node:path';
71
- import type { ConversationMessageSnapshot } from '@pellux/goodvibes-sdk/platform/core';
72
- import { UNRECOGNIZED_SUFFIX } from '@/config/read-versioned.ts';
73
- import type { SessionSurface } from '@/runtime/index.ts';
74
-
75
- // ─── Constants ──────────────────────────────────────────────────────────────
76
-
77
- export const JOURNAL_SCHEMA_VERSION = 1;
78
-
79
- // ─── Types ──────────────────────────────────────────────────────────────────
80
-
81
- export interface JournalHeader {
82
- readonly version: typeof JOURNAL_SCHEMA_VERSION;
83
- readonly sessionId: string;
84
- readonly createdAt: number;
85
- }
86
-
87
- export type JournalEventType =
88
- | 'user_message'
89
- | 'assistant_turn'
90
- | 'tool_results'
91
- | 'compaction';
92
-
93
- export interface JournalRecord {
94
- /** Discriminator for the kind of durable event. */
95
- readonly type: JournalEventType;
96
- /** Monotonically increasing sequence number (0-based, per journal file). */
97
- readonly seq: number;
98
- /** Wall-clock timestamp (Date.now()) when the record was appended. */
99
- readonly ts: number;
100
- /** Full conversation message snapshot at the time of the event. */
101
- readonly messages: ConversationMessageSnapshot[];
102
- }
103
-
104
- export interface ReplayResult {
105
- /** Records whose ts is strictly after snapshotTimestamp, in seq order. */
106
- readonly records: JournalRecord[];
107
- /**
108
- * True if the journal tail was corrupt (a partial write from a kill).
109
- * The corrupt tail has been quarantined; replay stopped at the last
110
- * good record.
111
- */
112
- readonly hadCorruptTail: boolean;
113
- }
114
-
115
- // ─── Public API ─────────────────────────────────────────────────────────────
116
-
117
- export interface TranscriptJournal {
118
- /**
119
- * Append one durable event record and fsync it to disk.
120
- *
121
- * Best-effort: if the write fails (e.g. disk full), the error is swallowed
122
- * — the journal is durability-enhancing, never a hard requirement.
123
- */
124
- appendRecord(type: JournalEventType, messages: ConversationMessageSnapshot[]): void;
125
-
126
- /**
127
- * Delete the journal file (called after a fresh snapshot is written).
128
- * The next appendRecord() will recreate the file with a fresh header.
129
- * Best-effort — silently swallows errors.
130
- */
131
- rotate(): void;
132
-
133
- /** Absolute path to the journal file. */
134
- readonly path: string;
135
-
136
- /**
137
- * Point this journal at a different session's file, resetting the sequence
138
- * counter and initialization flag. Used when the session a journal was
139
- * opened for is switched out from under it (e.g. `/session resume` or
140
- * `/session fork` reassigning `runtime.sessionId`) — without this, the
141
- * journal keeps appending the NEW session's records into the OLD session's
142
- * file. Does not touch the old file on disk; it is simply no longer
143
- * written to.
144
- */
145
- rebind(journalPath: string, sessionId: string): void;
146
- }
147
-
148
- // ─── Factory ────────────────────────────────────────────────────────────────
149
-
150
- /**
151
- * Create a TranscriptJournal for the given session.
152
- *
153
- * The journal file is created lazily on the first appendRecord() call.
154
- * Calling openTranscriptJournal() does not perform any I/O.
155
- */
156
- export function openTranscriptJournal(
157
- journalPath: string,
158
- sessionId: string,
159
- ): TranscriptJournal {
160
- return new TranscriptJournalImpl(journalPath, sessionId);
161
- }
162
-
163
- /**
164
- * Build the canonical journal path for a session.
165
- *
166
- * Both the home directory and the scope segment come off the caller's
167
- * SessionSurface, so the journal lands beside the sessions and recovery
168
- * snapshots it fills gaps for rather than under a separately-spelled scope.
169
- *
170
- * @param surface The app's declare-once session-storage handle.
171
- * @param sessionId The session identifier.
172
- */
173
- export function journalPathFor(surface: SessionSurface, sessionId: string): string {
174
- return join(surface.homeDirectory, '.goodvibes', surface.surfaceRoot, `transcript-${sessionId}.journal`);
175
- }
176
-
177
- /**
178
- * Replay journal records that post-date `snapshotTimestamp`.
179
- *
180
- * Returns an empty result if the journal file does not exist.
181
- * Corrupt tail lines (partial write from a kill) are quarantined; replay
182
- * stops at the first unparseable line.
183
- *
184
- * @param journalPath Absolute path to the journal file.
185
- * @param snapshotTimestamp The `writtenAt` / `timestamp` of the last known
186
- * good snapshot. Only records with ts > this value
187
- * are returned.
188
- */
189
- export function replayJournal(
190
- journalPath: string,
191
- snapshotTimestamp: number,
192
- ): ReplayResult {
193
- if (!existsSync(journalPath)) {
194
- return { records: [], hadCorruptTail: false };
195
- }
196
-
197
- let raw: string;
198
- try {
199
- raw = readFileSync(journalPath, 'utf-8');
200
- } catch {
201
- return { records: [], hadCorruptTail: false };
202
- }
203
-
204
- const lines = raw.split('\n').filter((l) => l.trim().length > 0);
205
- if (lines.length === 0) {
206
- return { records: [], hadCorruptTail: false };
207
- }
208
-
209
- // ── Validate header ─────────────────────────────────────────────────────
210
- let header: unknown;
211
- try {
212
- header = JSON.parse(lines[0]);
213
- } catch {
214
- quarantineJournal(journalPath);
215
- return { records: [], hadCorruptTail: true };
216
- }
217
-
218
- if (
219
- !isPlainObject(header) ||
220
- typeof header['version'] !== 'number' ||
221
- header['version'] !== JOURNAL_SCHEMA_VERSION
222
- ) {
223
- quarantineJournal(journalPath);
224
- return { records: [], hadCorruptTail: true };
225
- }
226
-
227
- // ── Read records ────────────────────────────────────────────────────────
228
- const records: JournalRecord[] = [];
229
- let firstBadLine = -1;
230
-
231
- for (let i = 1; i < lines.length; i++) {
232
- let parsed: unknown;
233
- try {
234
- parsed = JSON.parse(lines[i]);
235
- } catch {
236
- firstBadLine = i;
237
- break;
238
- }
239
-
240
- if (!isValidRecord(parsed)) {
241
- firstBadLine = i;
242
- break;
243
- }
244
-
245
- if (parsed.ts > snapshotTimestamp) {
246
- records.push(parsed);
247
- }
248
- }
249
-
250
- // ── Quarantine corrupt tail ──────────────────────────────────────────────
251
- let hadCorruptTail = false;
252
- if (firstBadLine !== -1) {
253
- hadCorruptTail = true;
254
- // Quarantine the remainder: rename the file. Caller will rotate after
255
- // replay anyway, but we quarantine now so the original file is not
256
- // accidentally replayed again if the process is killed during recovery.
257
- quarantineJournal(journalPath);
258
- }
259
-
260
- // Sort by seq to guarantee ordering in case lines were reordered (they
261
- // should not be, but be defensive).
262
- records.sort((a, b) => a.seq - b.seq);
263
-
264
- return { records, hadCorruptTail };
265
- }
266
-
267
- // ─── Implementation ─────────────────────────────────────────────────────────
268
-
269
- class TranscriptJournalImpl implements TranscriptJournal {
270
- // Not `readonly` at the class level (unlike the public interface) so
271
- // rebind() can repoint it; external callers only ever see it through the
272
- // `TranscriptJournal` interface, which keeps it read-only for them.
273
- path: string;
274
- private _sessionId: string;
275
- private _seq = 0;
276
- private _initialised = false;
277
-
278
- constructor(journalPath: string, sessionId: string) {
279
- this.path = journalPath;
280
- this._sessionId = sessionId;
281
- }
282
-
283
- rebind(journalPath: string, sessionId: string): void {
284
- this.path = journalPath;
285
- this._sessionId = sessionId;
286
- this._seq = 0;
287
- this._initialised = false;
288
- }
289
-
290
- appendRecord(type: JournalEventType, messages: ConversationMessageSnapshot[]): void {
291
- try {
292
- this._ensureInitialised();
293
- const record: JournalRecord = {
294
- type,
295
- seq: this._seq++,
296
- ts: Date.now(),
297
- messages,
298
- };
299
- const line = JSON.stringify(record) + '\n';
300
- appendFileSync(this.path, line, { mode: 0o600 });
301
- // fsync to flush the append to durable storage before returning.
302
- const fd = openSync(this.path, 'r+');
303
- try {
304
- fsyncSync(fd);
305
- } finally {
306
- closeSync(fd);
307
- }
308
- } catch {
309
- // Best-effort — never crash the TUI over a journal failure.
310
- }
311
- }
312
-
313
- rotate(): void {
314
- try {
315
- if (existsSync(this.path)) {
316
- unlinkSync(this.path);
317
- }
318
- this._initialised = false;
319
- this._seq = 0;
320
- } catch {
321
- // Best-effort.
322
- }
323
- }
324
-
325
- private _ensureInitialised(): void {
326
- if (this._initialised && journalHasContent(this.path)) return;
327
-
328
- mkdirSync(dirname(this.path), { recursive: true });
329
- const header: JournalHeader = {
330
- version: JOURNAL_SCHEMA_VERSION,
331
- sessionId: this._sessionId,
332
- createdAt: Date.now(),
333
- };
334
- // Append the header as the first line. If the file already exists with
335
- // content (e.g. process restarted mid-session), we start appending records
336
- // after whatever is already there — the replay function handles seq
337
- // ordering.
338
- //
339
- // The guard is `journalHasContent`, not `existsSync`: a crash between
340
- // creating the file and writing the header leaves a zero-byte journal, and
341
- // an existence-only check would then skip the header forever. Every record
342
- // appended after that would sit in a header-less file, so the next replay
343
- // would read record 0 where the header belongs, fail the version gate, and
344
- // quarantine the entire journal — losing exactly the turns this module
345
- // exists to preserve. Deciding on content instead means a zero-byte
346
- // journal is re-headered and stays replayable.
347
- if (!journalHasContent(this.path)) {
348
- appendFileSync(this.path, JSON.stringify(header) + '\n', { mode: 0o600 });
349
- }
350
- this._initialised = true;
351
- }
352
- }
353
-
354
- // ─── Internal helpers ────────────────────────────────────────────────────────
355
-
356
- function isPlainObject(value: unknown): value is Record<string, unknown> {
357
- return typeof value === 'object' && value !== null && !Array.isArray(value);
358
- }
359
-
360
- function isValidRecord(value: unknown): value is JournalRecord {
361
- if (!isPlainObject(value)) return false;
362
- const v = value as Record<string, unknown>;
363
- return (
364
- typeof v['type'] === 'string' &&
365
- typeof v['seq'] === 'number' &&
366
- typeof v['ts'] === 'number' &&
367
- Array.isArray(v['messages'])
368
- );
369
- }
370
-
371
- function quarantineJournal(journalPath: string): void {
372
- try {
373
- renameSync(journalPath, `${journalPath}${UNRECOGNIZED_SUFFIX}`);
374
- } catch {
375
- // Best-effort — if rename fails, proceed silently.
376
- }
377
- }
378
-
379
- /** True when the journal file exists AND holds at least one byte. */
380
- function journalHasContent(journalPath: string): boolean {
381
- try {
382
- return statSync(journalPath).size > 0;
383
- } catch {
384
- return false;
385
- }
386
- }
387
-
388
- // ─── Reaping orphaned journals ──────────────────────────────────────────────
389
- //
390
- // `rotate()` deletes a journal once its records have been folded into a
391
- // snapshot or replayed. A session that crashes and is never resumed never
392
- // reaches either, so its journal stays on disk forever — one file per
393
- // abandoned session. The SDK's registered append-only retention sweep does not
394
- // cover this home-scoped path, so the reclaim happens here.
395
-
396
- const JOURNAL_PREFIX = 'transcript-';
397
- const JOURNAL_SUFFIX = '.journal';
398
-
399
- /** How long an untouched journal for a non-live session is kept: 7 days. */
400
- export const JOURNAL_ORPHAN_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
401
-
402
- /**
403
- * Hard ceiling on reapable journals kept after the age rule, newest kept.
404
- * A burst of crashes inside the age window is still bounded.
405
- */
406
- export const JOURNAL_ORPHAN_MAX_FILES = 50;
407
-
408
- export interface JournalReapResult {
409
- /** Journal files examined this sweep. */
410
- readonly scanned: number;
411
- /** Journal files deleted this sweep. */
412
- readonly reaped: number;
413
- }
414
-
415
- export interface JournalReapOptions {
416
- /**
417
- * Is this session open in a still-running process? Injected rather than
418
- * imported so this module keeps no dependency on the liveness marker — the
419
- * composition point (runtime/durability-housekeeping.ts) supplies the real
420
- * check, and tests supply their own.
421
- */
422
- readonly isSessionLive: (sessionId: string) => boolean;
423
- /** The session this process is writing right now; never reaped. */
424
- readonly currentSessionId?: string | null;
425
- readonly now?: () => number;
426
- /** Override the age window (tests). */
427
- readonly maxAgeMs?: number;
428
- /** Override the count cap (tests). */
429
- readonly maxFiles?: number;
430
- }
431
-
432
- /**
433
- * Delete transcript journals belonging to sessions that crashed and were never
434
- * resumed.
435
- *
436
- * A journal is reapable only when it is neither the current session's nor
437
- * apparently open in another running process. Of those, one is deleted when it
438
- * is empty (a zero-byte file holds no records, so nothing can be lost) or
439
- * untouched for longer than the age window; whatever survives both rules is
440
- * then capped by count, newest kept.
441
- *
442
- * The rules are deliberately mtime- and liveness-based, never parse-based: an
443
- * unparseable TAIL is the normal, expected shape of a journal killed
444
- * mid-append and is exactly the data replay is there to salvage, so a parse
445
- * failure must never make a journal reapable.
446
- *
447
- * Idempotent and concurrency-safe: a journal another sweeper unlinked between
448
- * the listing and this unlink (ENOENT) counts as reaped, not as an error.
449
- */
450
- export function reapOrphanedJournals(surface: SessionSurface, options: JournalReapOptions): JournalReapResult {
451
- const dir = join(surface.homeDirectory, '.goodvibes', surface.surfaceRoot);
452
- let names: string[];
453
- try {
454
- names = readdirSync(dir).filter((n) => n.startsWith(JOURNAL_PREFIX) && n.endsWith(JOURNAL_SUFFIX));
455
- } catch {
456
- return { scanned: 0, reaped: 0 };
457
- }
458
-
459
- const now = options.now?.() ?? Date.now();
460
- const maxAgeMs = options.maxAgeMs ?? JOURNAL_ORPHAN_MAX_AGE_MS;
461
- const maxFiles = options.maxFiles ?? JOURNAL_ORPHAN_MAX_FILES;
462
-
463
- let reaped = 0;
464
- const survivors: { readonly path: string; readonly mtimeMs: number }[] = [];
465
-
466
- for (const name of names) {
467
- const sessionId = name.slice(JOURNAL_PREFIX.length, name.length - JOURNAL_SUFFIX.length);
468
- if (sessionId.length === 0) continue;
469
- if (options.currentSessionId && sessionId === options.currentSessionId) continue;
470
- if (options.isSessionLive(sessionId)) continue;
471
-
472
- const path = join(dir, name);
473
- let stats: { size: number; mtimeMs: number };
474
- try {
475
- stats = statSync(path);
476
- } catch {
477
- continue; // vanished under us
478
- }
479
- if (stats.size === 0 || now - stats.mtimeMs > maxAgeMs) {
480
- if (unlinkJournalIfPresent(path)) reaped++;
481
- continue;
482
- }
483
- survivors.push({ path, mtimeMs: stats.mtimeMs });
484
- }
485
-
486
- if (survivors.length > maxFiles) {
487
- survivors.sort((a, b) => a.mtimeMs - b.mtimeMs); // oldest first
488
- for (const victim of survivors.slice(0, survivors.length - maxFiles)) {
489
- if (unlinkJournalIfPresent(victim.path)) reaped++;
490
- }
491
- }
492
-
493
- return { scanned: names.length, reaped };
494
- }
495
-
496
- function unlinkJournalIfPresent(path: string): boolean {
497
- try {
498
- unlinkSync(path);
499
- return true;
500
- } catch (err) {
501
- return (err as NodeJS.ErrnoException | undefined)?.code === 'ENOENT';
502
- }
503
- }