@pellux/goodvibes-tui 2.0.20 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (388) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/README.md +16 -16
  3. package/docs/README.md +4 -4
  4. package/docs/foundation-artifacts/operator-contract.json +59 -4
  5. package/package.json +16 -6
  6. package/src/cli/management.ts +5 -2
  7. package/src/cli/tui-startup.ts +34 -39
  8. package/src/core/agent-view-render.ts +157 -0
  9. package/src/core/approval-alert.ts +49 -11
  10. package/src/core/bookmark-navigation.ts +7 -1
  11. package/src/core/budget-breach-notifier.ts +27 -8
  12. package/src/core/compaction-receipt.ts +1 -1
  13. package/src/core/context-usage.ts +1 -1
  14. package/src/core/conversation-compaction-render.ts +3 -3
  15. package/src/core/conversation-display-only.ts +86 -0
  16. package/src/core/conversation-event-navigation.ts +27 -0
  17. package/src/core/conversation-line-cache.ts +216 -447
  18. package/src/core/conversation-render-context.ts +20 -27
  19. package/src/core/conversation-rendering.ts +157 -575
  20. package/src/core/conversation-splash-state.ts +6 -1
  21. package/src/core/conversation-types.ts +35 -0
  22. package/src/core/conversation-usage.ts +12 -0
  23. package/src/core/conversation.ts +130 -131
  24. package/src/core/long-task-notifier.ts +100 -31
  25. package/src/core/notices.ts +75 -0
  26. package/src/core/pairing-tailscale-gateway.ts +1 -1
  27. package/src/core/process-output-log.ts +143 -0
  28. package/src/core/rewind-receipt.ts +1 -1
  29. package/src/core/session-focus.ts +190 -0
  30. package/src/core/session-resume-core.ts +23 -81
  31. package/src/core/stream-event-wiring.ts +31 -5
  32. package/src/core/system-message-noise.ts +2 -2
  33. package/src/core/system-message-router.ts +16 -18
  34. package/src/core/turn-event-wiring.ts +272 -33
  35. package/src/core/work-tree-focus.ts +290 -0
  36. package/src/core/work-tree-fold-store.ts +143 -0
  37. package/src/core/work-tree-model.ts +799 -0
  38. package/src/core/work-tree-render.ts +384 -0
  39. package/src/core/work-tree-sources.ts +184 -0
  40. package/src/core/work-tree-wiring.ts +176 -0
  41. package/src/core/workstream-notification.ts +36 -6
  42. package/src/core/wrfc-notice-titles.ts +37 -0
  43. package/src/input/agents-modal-text.ts +119 -0
  44. package/src/input/agents-modal.ts +699 -0
  45. package/src/input/bookmark-modal.ts +33 -9
  46. package/src/input/changes-git.ts +251 -0
  47. package/src/input/changes-modal.ts +629 -0
  48. package/src/input/changes-model.ts +125 -0
  49. package/src/input/command-palette-types.ts +41 -0
  50. package/src/input/command-palette.ts +272 -0
  51. package/src/input/command-registry.ts +77 -35
  52. package/src/input/commands/acp-runtime.ts +19 -9
  53. package/src/input/commands/channel-runtime.ts +2 -2
  54. package/src/input/commands/ci-runtime.ts +1 -1
  55. package/src/input/commands/codebase-runtime.ts +1 -1
  56. package/src/input/commands/config.ts +7 -1
  57. package/src/input/commands/context-window.ts +25 -19
  58. package/src/input/commands/control-room-runtime.ts +18 -18
  59. package/src/input/commands/conversation-runtime.ts +0 -1
  60. package/src/input/commands/cost-runtime.ts +29 -20
  61. package/src/input/commands/diff-runtime.ts +35 -181
  62. package/src/input/commands/eval.ts +1 -1
  63. package/src/input/commands/experience-runtime.ts +3 -7
  64. package/src/input/commands/fresh-conversation.ts +86 -0
  65. package/src/input/commands/git-runtime.ts +5 -22
  66. package/src/input/commands/graph-runtime.ts +1 -1
  67. package/src/input/commands/guidance-runtime.ts +1 -1
  68. package/src/input/commands/health-runtime.ts +8 -9
  69. package/src/input/commands/hooks-runtime.ts +2 -2
  70. package/src/input/commands/hosted-runtime.ts +3 -3
  71. package/src/input/commands/incident-runtime.ts +3 -3
  72. package/src/input/commands/intelligence-runtime.ts +6 -9
  73. package/src/input/commands/knowledge.ts +2 -2
  74. package/src/input/commands/legacy-panel-command.ts +57 -0
  75. package/src/input/commands/local-auth-runtime.ts +8 -9
  76. package/src/input/commands/local-provider-runtime.ts +7 -4
  77. package/src/input/commands/local-runtime.ts +12 -15
  78. package/src/input/commands/local-setup-review.ts +1 -1
  79. package/src/input/commands/local-setup.ts +13 -19
  80. package/src/input/commands/memory.ts +1 -1
  81. package/src/input/commands/notify-runtime.ts +9 -0
  82. package/src/input/commands/operator-runtime.ts +10 -12
  83. package/src/input/commands/permissions-provenance.ts +3 -3
  84. package/src/input/commands/planning-runtime.ts +7 -7
  85. package/src/input/commands/platform-sandbox-runtime.ts +2 -2
  86. package/src/input/commands/platform-services-runtime.ts +1 -1
  87. package/src/input/commands/policy-dispatch.ts +2 -2
  88. package/src/input/commands/policy.ts +3 -3
  89. package/src/input/commands/provider.ts +1 -1
  90. package/src/input/commands/remote-runtime.ts +1 -1
  91. package/src/input/commands/review-runtime.ts +39 -94
  92. package/src/input/commands/rewind-runtime.ts +81 -108
  93. package/src/input/commands/runtime-services.ts +15 -17
  94. package/src/input/commands/services-runtime.ts +2 -2
  95. package/src/input/commands/session-content.ts +21 -5
  96. package/src/input/commands/session-workflow.ts +13 -38
  97. package/src/input/commands/settings-sync-runtime.ts +2 -2
  98. package/src/input/commands/shell-core.ts +19 -4
  99. package/src/input/commands/skills-runtime.ts +2 -2
  100. package/src/input/commands/status-runtime.ts +13 -0
  101. package/src/input/commands/subscription-runtime.ts +1 -1
  102. package/src/input/commands/tasks-runtime.ts +2 -8
  103. package/src/input/commands/work-plan-runtime.ts +4 -4
  104. package/src/input/commands/workstream-attempts.ts +24 -47
  105. package/src/input/commands/workstream-runtime.ts +2 -2
  106. package/src/input/commands/worktree-runtime.ts +3 -3
  107. package/src/input/commands.ts +3 -1
  108. package/src/input/composer-editor.ts +44 -0
  109. package/src/input/concealed-input.ts +1 -1
  110. package/src/input/config-modal-types.ts +20 -8
  111. package/src/input/config-modal.ts +106 -105
  112. package/src/input/confirm-dialog-types.ts +28 -0
  113. package/src/input/confirm-dialog.ts +70 -0
  114. package/src/input/delete-key-policy.ts +3 -3
  115. package/src/input/feed-context-factory.ts +15 -16
  116. package/src/input/handler-command-route.ts +7 -42
  117. package/src/input/handler-content-actions.ts +16 -15
  118. package/src/input/handler-feed-routes.ts +26 -211
  119. package/src/input/handler-feed.ts +68 -95
  120. package/src/input/handler-interactions.ts +5 -3
  121. package/src/input/handler-modal-routes.ts +215 -216
  122. package/src/input/handler-modal-stack.ts +81 -11
  123. package/src/input/handler-modal-token-routes.ts +4 -0
  124. package/src/input/handler-onboarding.ts +0 -1
  125. package/src/input/handler-picker-routes.ts +65 -107
  126. package/src/input/handler-session-view-route.ts +149 -0
  127. package/src/input/handler-shortcuts.ts +16 -154
  128. package/src/input/handler-types.ts +4 -2
  129. package/src/input/handler-ui-state.ts +45 -15
  130. package/src/input/handler-work-tree-route.ts +123 -0
  131. package/src/input/handler.ts +25 -70
  132. package/src/input/keybindings.ts +16 -71
  133. package/src/input/masked-entry-modal.ts +117 -0
  134. package/src/input/mcp-workspace.ts +48 -17
  135. package/src/input/model-picker-filter.ts +8 -0
  136. package/src/input/model-picker-open.ts +99 -0
  137. package/src/input/model-picker-types.ts +1 -1
  138. package/src/input/model-picker.ts +92 -9
  139. package/src/input/notifications-modal.ts +123 -0
  140. package/src/input/overlay-filter.ts +26 -0
  141. package/src/input/profile-picker-modal.ts +37 -8
  142. package/src/input/search.ts +3 -3
  143. package/src/input/selection-modal-queue.ts +2 -0
  144. package/src/input/selection-modal.ts +28 -16
  145. package/src/input/session-picker-modal.ts +33 -8
  146. package/src/input/settings-modal-activation.ts +7 -2
  147. package/src/input/settings-modal-data.ts +11 -6
  148. package/src/input/settings-modal-types.ts +1 -1
  149. package/src/input/settings-modal.ts +20 -20
  150. package/src/input/submission-intent.ts +1 -1
  151. package/src/input/submission-router.ts +4 -9
  152. package/src/input/surface-modal-host.ts +110 -0
  153. package/src/input/theme-settings-actions.ts +82 -0
  154. package/src/input/usage-modal.ts +183 -0
  155. package/src/input/views.ts +97 -0
  156. package/src/main.ts +175 -165
  157. package/src/permissions/hunk-selection.ts +1 -1
  158. package/src/permissions/prompt-card.ts +511 -0
  159. package/src/permissions/prompt.ts +59 -622
  160. package/src/renderer/agents-modal.ts +310 -0
  161. package/src/renderer/autocomplete-overlay.ts +42 -220
  162. package/src/renderer/back-to-bottom.ts +80 -0
  163. package/src/renderer/block-actions-overlay.ts +30 -48
  164. package/src/renderer/bookmark-modal.ts +48 -79
  165. package/src/renderer/changes-modal.ts +325 -0
  166. package/src/renderer/code-block.ts +184 -106
  167. package/src/renderer/command-palette.ts +93 -0
  168. package/src/renderer/composer-fragments.ts +4 -4
  169. package/src/renderer/composer.ts +146 -0
  170. package/src/renderer/compositor.ts +26 -160
  171. package/src/renderer/config-modal.ts +185 -81
  172. package/src/renderer/confirm-dialog.ts +50 -0
  173. package/src/renderer/context-inspector.ts +116 -154
  174. package/src/renderer/context-status-hint.ts +4 -4
  175. package/src/renderer/conversation-layout.ts +20 -0
  176. package/src/renderer/conversation-overlays.ts +94 -84
  177. package/src/renderer/conversation-surface.ts +19 -38
  178. package/src/renderer/diff-tint.ts +98 -0
  179. package/src/renderer/file-picker-overlay.ts +63 -90
  180. package/src/renderer/footer-targets.ts +38 -0
  181. package/src/renderer/git-status.ts +3 -4
  182. package/src/renderer/header-line.ts +140 -117
  183. package/src/renderer/help-overlay.ts +133 -219
  184. package/src/renderer/history-search-overlay.ts +15 -12
  185. package/src/renderer/lane-graph/bead.ts +800 -0
  186. package/src/renderer/lane-graph/glyphs.ts +134 -0
  187. package/src/renderer/lane-graph/layout.ts +248 -0
  188. package/src/renderer/lane-graph/paint.ts +537 -0
  189. package/src/renderer/lane-graph/semantic-memo.ts +77 -0
  190. package/src/renderer/layout-engine.ts +2 -57
  191. package/src/renderer/layout.ts +7 -13
  192. package/src/renderer/markdown-inline.ts +2 -1
  193. package/src/renderer/markdown-table.ts +17 -12
  194. package/src/renderer/markdown.ts +92 -34
  195. package/src/renderer/masked-entry-modal.ts +78 -0
  196. package/src/renderer/mcp-workspace.ts +166 -203
  197. package/src/renderer/model-workspace.ts +381 -436
  198. package/src/renderer/notifications-modal.ts +116 -0
  199. package/src/renderer/onboarding/onboarding-wizard.ts +178 -588
  200. package/src/renderer/process-view.ts +192 -0
  201. package/src/renderer/profile-picker-modal.ts +58 -110
  202. package/src/renderer/search-overlay.ts +6 -3
  203. package/src/renderer/selection-modal-overlay.ts +87 -327
  204. package/src/renderer/semantic-diff.ts +2 -2
  205. package/src/renderer/session-chips.ts +102 -0
  206. package/src/renderer/session-picker-modal.ts +177 -297
  207. package/src/renderer/settings-modal-connections.ts +14 -23
  208. package/src/renderer/settings-modal-context.ts +367 -0
  209. package/src/renderer/settings-modal-helpers.ts +6 -11
  210. package/src/renderer/settings-modal.ts +322 -726
  211. package/src/renderer/shell-surface.ts +277 -175
  212. package/src/renderer/shortcuts-overlay.ts +217 -0
  213. package/src/renderer/status-line.ts +475 -0
  214. package/src/renderer/surface-compose.ts +174 -0
  215. package/src/renderer/surface-kit-extra.ts +303 -0
  216. package/src/renderer/surface-kit-list.ts +366 -0
  217. package/src/renderer/surface-kit-parts.ts +360 -0
  218. package/src/renderer/surface-kit.ts +568 -0
  219. package/src/renderer/syntax-highlighter.ts +280 -197
  220. package/src/renderer/syntax-theme.ts +51 -0
  221. package/src/renderer/system-message.ts +0 -1
  222. package/src/renderer/term-caps.ts +42 -1
  223. package/src/renderer/terminal-bg-probe.ts +116 -19
  224. package/src/renderer/terminal-palette-probe.ts +322 -0
  225. package/src/renderer/terminal-palette-reader.ts +183 -0
  226. package/src/renderer/terminal-palette.ts +58 -0
  227. package/src/renderer/theme-mode-config.ts +16 -1
  228. package/src/renderer/theme.ts +234 -207
  229. package/src/renderer/thinking.ts +0 -1
  230. package/src/renderer/throbber.ts +188 -0
  231. package/src/renderer/toast-center.ts +119 -0
  232. package/src/renderer/ui-factory.ts +39 -602
  233. package/src/renderer/ui-primitives.ts +8 -25
  234. package/src/renderer/usage-modal.ts +353 -0
  235. package/src/renderer/user-message.ts +58 -0
  236. package/src/renderer/voice-capture-chip.ts +53 -0
  237. package/src/runtime/bootstrap-command-context.ts +0 -5
  238. package/src/runtime/bootstrap-command-parts.ts +38 -89
  239. package/src/runtime/bootstrap-core.ts +13 -15
  240. package/src/runtime/bootstrap-hook-bridge.ts +12 -21
  241. package/src/runtime/bootstrap-notifier-sync.ts +17 -1
  242. package/src/runtime/bootstrap-shell.ts +16 -50
  243. package/src/runtime/bootstrap.ts +14 -14
  244. package/src/runtime/client/fleet-union.ts +5 -5
  245. package/src/runtime/client/hosted-exit.ts +2 -2
  246. package/src/runtime/client/hosted-sessions.ts +1 -1
  247. package/src/runtime/client/spine-adoption.ts +1 -1
  248. package/src/runtime/context-accounting-source.ts +5 -4
  249. package/src/runtime/index.ts +1 -0
  250. package/src/runtime/notification-dispatch.ts +102 -29
  251. package/src/runtime/recovery-offer-wiring.ts +4 -1
  252. package/src/runtime/recovery-prompt.ts +31 -15
  253. package/src/runtime/runtime-services-types.ts +10 -6
  254. package/src/runtime/services.ts +17 -12
  255. package/src/runtime/session-continuity-hints.ts +2 -5
  256. package/src/runtime/session-inbound-inputs.ts +1 -1
  257. package/src/runtime/session-resume-liveness-confirm.ts +14 -2
  258. package/src/runtime/startup-typeahead-gate.ts +103 -0
  259. package/src/runtime/store/domains/domain-read-matrix.ts +0 -1
  260. package/src/runtime/store/domains/index.ts +0 -8
  261. package/src/runtime/store/selectors/index.ts +0 -28
  262. package/src/runtime/store/state.ts +0 -8
  263. package/src/runtime/ui-services.ts +4 -6
  264. package/src/runtime/usage-tracker.ts +348 -0
  265. package/src/runtime/wrfc-persistence.ts +4 -4
  266. package/src/shell/blocking-input.ts +92 -2
  267. package/src/shell/recovery-input-helpers.ts +1 -1
  268. package/src/shell/session-views.ts +539 -0
  269. package/src/shell/status-report.ts +86 -0
  270. package/src/shell/transcript-scroll.ts +68 -0
  271. package/src/shell/ui-openers.ts +84 -172
  272. package/src/shell/view-openers.ts +205 -0
  273. package/src/tools/wrfc-agent-guard.ts +22 -2
  274. package/src/utils/format-duration.ts +4 -8
  275. package/src/utils/splash-lines.ts +9 -1
  276. package/src/utils/terminal-width.ts +56 -0
  277. package/src/verification/verification-ledger.ts +18 -16
  278. package/src/{panels → views}/agent-inspector-shared.ts +2 -2
  279. package/src/{panels → views}/builtin-modals.ts +22 -21
  280. package/src/views/builtin-views.ts +135 -0
  281. package/src/{panels → views}/confirm-state.ts +9 -9
  282. package/src/{panels → views}/diff-review-model.ts +10 -3
  283. package/src/{panels → views}/eval-registry.ts +1 -1
  284. package/src/{panels → views}/fleet-acts.ts +49 -85
  285. package/src/{panels/fleet-panel-format.ts → views/fleet-format.ts} +40 -40
  286. package/src/{panels → views}/fleet-gateway.ts +5 -5
  287. package/src/{panels → views}/fleet-observed-render.ts +16 -16
  288. package/src/{panels → views}/fleet-read-model.ts +9 -9
  289. package/src/{panels/fleet-tabs.ts → views/fleet-session-tabs.ts} +13 -13
  290. package/src/{panels → views}/fleet-spawn.ts +33 -49
  291. package/src/{panels → views}/fleet-steer.ts +12 -12
  292. package/src/{panels → views}/fleet-stop.ts +4 -4
  293. package/src/{panels → views}/fleet-transcript.ts +26 -27
  294. package/src/{panels/fleet-panel-worktree-detail.ts → views/fleet-worktree-detail.ts} +7 -7
  295. package/src/{panels → views}/hosted-session-feed.ts +6 -6
  296. package/src/views/modal-surface-registry.ts +41 -0
  297. package/src/{panels → views}/modals/devices-modal.ts +2 -2
  298. package/src/{panels → views}/modals/hooks-modal.ts +13 -13
  299. package/src/{panels → views}/modals/keybindings-modal.ts +19 -27
  300. package/src/{panels → views}/modals/knowledge-modal.ts +6 -5
  301. package/src/{panels → views}/modals/local-auth-modal.ts +22 -21
  302. package/src/{panels → views}/modals/marketplace-modal.ts +11 -11
  303. package/src/{panels → views}/modals/memory-modal.ts +8 -8
  304. package/src/{panels → views}/modals/modal-surface-helpers.ts +15 -5
  305. package/src/{panels → views}/modals/pairing-modal.ts +9 -9
  306. package/src/{panels → views}/modals/planning-modal.ts +15 -20
  307. package/src/{panels → views}/modals/plugins-modal.ts +6 -6
  308. package/src/{panels → views}/modals/policy-modal.ts +13 -5
  309. package/src/{panels → views}/modals/provider-health-modal.ts +4 -4
  310. package/src/{panels → views}/modals/remote-modal.ts +3 -3
  311. package/src/{panels → views}/modals/sandbox-modal.ts +4 -4
  312. package/src/{panels → views}/modals/security-modal.ts +22 -16
  313. package/src/{panels → views}/modals/services-modal.ts +3 -3
  314. package/src/{panels → views}/modals/settings-sync-modal.ts +4 -4
  315. package/src/{panels → views}/modals/skills-modal.ts +9 -9
  316. package/src/{panels → views}/modals/subscription-modal.ts +3 -3
  317. package/src/{panels → views}/modals/work-plan-modal.ts +10 -13
  318. package/src/views/notifications-feed.ts +314 -0
  319. package/src/{panels → views}/polish-core.ts +38 -36
  320. package/src/{panels → views}/polish-tables.ts +35 -26
  321. package/src/{panels → views}/polish.ts +101 -95
  322. package/src/{panels → views}/project-planning-answer-actions.ts +3 -3
  323. package/src/{panels → views}/provider-health-routes.ts +14 -14
  324. package/src/{panels → views}/search-focus.ts +8 -8
  325. package/src/{panels → views}/session-maintenance.ts +11 -11
  326. package/src/views/skills-discovery.ts +159 -0
  327. package/src/views/view-deps.ts +80 -0
  328. package/src/views/view-panel-adapter.ts +53 -0
  329. package/src/{panels → views}/workstream-graph-render.ts +1 -1
  330. package/src/core/conversation-fold.ts +0 -101
  331. package/src/core/conversation-turn-structure.ts +0 -464
  332. package/src/core/conversation-user-receipts.ts +0 -42
  333. package/src/input/commands/operator-panel-runtime.ts +0 -186
  334. package/src/input/panel-integration-actions.ts +0 -33
  335. package/src/input/panel-mouse-geometry.ts +0 -97
  336. package/src/input/panel-paste-flood-guard.ts +0 -86
  337. package/src/panels/base-panel.ts +0 -301
  338. package/src/panels/builtin/agent.ts +0 -27
  339. package/src/panels/builtin/development.ts +0 -92
  340. package/src/panels/builtin/knowledge.ts +0 -12
  341. package/src/panels/builtin/operations.ts +0 -177
  342. package/src/panels/builtin/session.ts +0 -81
  343. package/src/panels/builtin/shared.ts +0 -357
  344. package/src/panels/builtin-panels.ts +0 -28
  345. package/src/panels/cost-tracker-panel.ts +0 -746
  346. package/src/panels/diff-panel.ts +0 -797
  347. package/src/panels/diff-review-panel.ts +0 -395
  348. package/src/panels/expandable-list-panel.ts +0 -189
  349. package/src/panels/fleet-deep-link.ts +0 -31
  350. package/src/panels/fleet-panel.ts +0 -799
  351. package/src/panels/git-panel.ts +0 -800
  352. package/src/panels/hosted-session-panel.ts +0 -221
  353. package/src/panels/index.ts +0 -21
  354. package/src/panels/local-auth-panel.ts +0 -478
  355. package/src/panels/notifications-feed.ts +0 -127
  356. package/src/panels/notifications-panel.ts +0 -160
  357. package/src/panels/panel-confirm-overlay.ts +0 -72
  358. package/src/panels/panel-manager.ts +0 -791
  359. package/src/panels/plugins-panel.ts +0 -371
  360. package/src/panels/scrollable-list-panel.ts +0 -498
  361. package/src/panels/skills-panel.ts +0 -454
  362. package/src/panels/token-budget-panel.ts +0 -688
  363. package/src/panels/types.ts +0 -191
  364. package/src/panels/wrfc-panel-format.ts +0 -133
  365. package/src/renderer/diff-view.ts +0 -134
  366. package/src/renderer/fleet-tab-strip.ts +0 -56
  367. package/src/renderer/footer-tips.ts +0 -53
  368. package/src/renderer/fullscreen-primitives.ts +0 -146
  369. package/src/renderer/fullscreen-workspace.ts +0 -194
  370. package/src/renderer/hint-grammar.ts +0 -52
  371. package/src/renderer/modal-factory.ts +0 -480
  372. package/src/renderer/overlay-box.ts +0 -154
  373. package/src/renderer/overlay-viewport.ts +0 -104
  374. package/src/renderer/panel-composite.ts +0 -145
  375. package/src/renderer/panel-workspace-bar.ts +0 -54
  376. package/src/renderer/process-indicator.ts +0 -163
  377. package/src/renderer/tab-strip.ts +0 -222
  378. package/src/renderer/text-layout.ts +0 -31
  379. package/src/renderer/tool-call.ts +0 -276
  380. package/src/renderer/tool-result-expanded-lines.ts +0 -48
  381. package/src/renderer/tool-result-summary.ts +0 -219
  382. package/src/runtime/diagnostics/panels/index.ts +0 -21
  383. package/src/runtime/diagnostics/panels/ops.ts +0 -156
  384. package/src/runtime/perf/panel-contracts.ts +0 -32
  385. package/src/runtime/store/domains/panels.ts +0 -117
  386. /package/src/{panels → views}/memory-consolidation-gateway.ts +0 -0
  387. /package/src/{panels → views}/modals/modal-theme.ts +0 -0
  388. /package/src/{panels → views}/provider-health-domains.ts +0 -0
@@ -1,3 +1,4 @@
1
+ import { activeTokens } from '../renderer/theme.ts';
1
2
  import { getConfigSnapshot } from '@pellux/goodvibes-sdk/platform/config';
2
3
  import {
3
4
  describeServingEffort,
@@ -12,7 +13,6 @@ import type { KnowledgeApi } from '@pellux/goodvibes-sdk/platform/knowledge';
12
13
  import type { MemorySpineClient } from '@pellux/goodvibes-sdk/platform/runtime/memory-spine';
13
14
  import type { HookApi } from '@pellux/goodvibes-sdk/platform/hooks';
14
15
  import type { McpApi } from '@pellux/goodvibes-sdk/platform/mcp';
15
- import type { PanelManager, PanelDeepLinkTarget } from '../panels/panel-manager.ts';
16
16
  import type { ProviderApi } from '@pellux/goodvibes-sdk/platform/providers';
17
17
  import type { OpsApi } from '@/runtime/index.ts';
18
18
  import type { FeatureFlagManager } from '@/runtime/index.ts';
@@ -54,7 +54,6 @@ import type { PeerClient } from '@/runtime/index.ts';
54
54
  import type { DirectTransport } from '@/runtime/index.ts';
55
55
  import type { VoiceProviderRegistry, VoiceService } from '@pellux/goodvibes-sdk/platform/voice';
56
56
  import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
57
- import { LocalAuthPanel } from '../panels/local-auth-panel.ts';
58
57
 
59
58
  export type BootstrapCommandSessionSection = CommandContext['session'];
60
59
  export type BootstrapCommandProviderSection = CommandContext['provider'];
@@ -70,7 +69,6 @@ export interface BootstrapCommandActionOptions {
70
69
  readonly conversation: ConversationManager;
71
70
  readonly runtime: MutableRuntimeState;
72
71
  readonly requestRender: () => void;
73
- readonly panelManager: PanelManager;
74
72
  readonly loadSystemPrompt: () => string;
75
73
  readonly activatePlan: (planId: string, task: string) => void;
76
74
  readonly requestPermission: PermissionRequestHandler;
@@ -86,7 +84,6 @@ export interface BootstrapCommandSectionOptions {
86
84
  readonly conversation: ConversationManager;
87
85
  readonly runtime: MutableRuntimeState;
88
86
  readonly keybindingsManager?: KeybindingsManager;
89
- readonly panelManager: PanelManager;
90
87
  readonly requestRender: () => void;
91
88
  readonly requestPermission: PermissionRequestHandler;
92
89
  readonly toolRegistry: ToolRegistry;
@@ -182,20 +179,19 @@ export function createBootstrapCommandActions(
182
179
  | 'print'
183
180
  | 'exit'
184
181
  | 'reloadSystemPrompt'
185
- | 'showPanel'
186
- | 'openForensicsPanel'
187
- | 'openIncidentPanel'
188
- | 'openPolicyPanel'
189
- | 'openHooksPanel'
190
- | 'openCommunicationPanel'
191
- | 'openOrchestrationPanel'
192
- | 'openCockpitPanel'
182
+ | 'openForensicsView'
183
+ | 'openIncidentView'
184
+ | 'openPolicyView'
185
+ | 'openHooksView'
186
+ | 'openCommunicationView'
187
+ | 'openOrchestrationView'
188
+ | 'openCockpitView'
193
189
  | 'openMcpWorkspace'
194
- | 'openSecurityPanel'
195
- | 'openKnowledgePanel'
196
- | 'openMemoryPanel'
197
- | 'openRemotePanel'
198
- | 'openSubscriptionPanel'
190
+ | 'openSecurityView'
191
+ | 'openKnowledgeView'
192
+ | 'openMemoryView'
193
+ | 'openRemoteView'
194
+ | 'openSubscriptionView'
199
195
  | 'openLocalAuthMaskedEntry'
200
196
  > {
201
197
  const {
@@ -204,24 +200,16 @@ export function createBootstrapCommandActions(
204
200
  conversation,
205
201
  runtime,
206
202
  requestRender,
207
- panelManager,
208
203
  loadSystemPrompt,
209
204
  activatePlan,
210
205
  requestPermission,
211
206
  completeModelSelectionSideEffect,
212
- localUserAuthManager,
213
207
  } = options;
214
208
 
215
- const showPanel = (panelId: string, pane?: 'top' | 'bottom', target?: PanelDeepLinkTarget) => {
216
- // (the purge): a MIGRATE-TO-MODAL id resolves to a modal, not a panel.
217
- // panelManager.open() fires the injected openModal callback and returns a
218
- // no-op sentinel, so skip panelManager.show() (which would reveal an empty
219
- // panel workspace behind the modal) when this id redirects. Keeps every
220
- // showPanel-based front-door (openHooksPanel/openSecurityPanel/… and the
221
- // migrated command runtimes) opening the modal cleanly.
222
- const redirected = panelManager.getModalRedirect(panelId) !== undefined;
223
- panelManager.open(panelId, pane, target);
224
- if (!redirected) panelManager.show();
209
+ // The views these open are kit modals, which exist once the shell attaches
210
+ // (shell/ui-openers.ts replaces every one of these with the real opener).
211
+ const viewNotAttached = (what: string) => (): void => {
212
+ conversation.log(`${what} opens once the terminal UI is attached.`, { fg: activeTokens().textMuted });
225
213
  requestRender();
226
214
  };
227
215
 
@@ -244,17 +232,17 @@ export function createBootstrapCommandActions(
244
232
  configManager.set('helper.globalProvider', def.provider);
245
233
  configManager.set('helper.globalModel', key);
246
234
  configManager.set('helper.enabled', true);
247
- conversation.log(`Helper model set to: ${def.displayName} (${def.provider})`, { fg: '135' });
235
+ conversation.log(`Helper model set to: ${def.displayName} (${def.provider})`, { fg: activeTokens().secondary });
248
236
  } else if (resolvedTarget === 'tool') {
249
237
  // Write to tool LLM config keys and enable the tool LLM
250
238
  configManager.set('tools.llmProvider', def.provider);
251
239
  configManager.set('tools.llmModel', key);
252
240
  configManager.setDynamic('tools.llmEnabled' as never, true);
253
- conversation.log(`Tool LLM set to: ${def.displayName} (${def.provider})`, { fg: '135' });
241
+ conversation.log(`Tool LLM set to: ${def.displayName} (${def.provider})`, { fg: activeTokens().secondary });
254
242
  } else if (resolvedTarget === 'tts') {
255
243
  configManager.set('tts.llmProvider', def.provider);
256
244
  configManager.set('tts.llmModel', key);
257
- conversation.log(`TTS LLM set to: ${def.displayName} (${def.provider})`, { fg: '135' });
245
+ conversation.log(`TTS LLM set to: ${def.displayName} (${def.provider})`, { fg: activeTokens().secondary });
258
246
  } else {
259
247
  // Default: main provider/model
260
248
  if (contextCap != null && contextCap > 0) {
@@ -292,13 +280,13 @@ export function createBootstrapCommandActions(
292
280
  const ctxNote = contextCap != null && contextCap > 0
293
281
  ? `, context cap: ${contextCap.toLocaleString()}`
294
282
  : '';
295
- conversation.log(`Switched to model: ${def.displayName} (${def.provider}), effort: ${describeServingEffort(serving, effortModel)}${ctxNote}`, { fg: '135' });
283
+ conversation.log(`Switched to model: ${def.displayName} (${def.provider}), effort: ${describeServingEffort(serving, effortModel)}${ctxNote}`, { fg: activeTokens().secondary });
296
284
  // The SDK's own sentence, printed verbatim so the explanation cannot
297
285
  // drift from the resolution that produced it.
298
- if (serving.note) conversation.log(serving.note, { fg: '214' });
286
+ if (serving.note) conversation.log(serving.note, { fg: activeTokens().warning });
299
287
  }
300
288
  } catch (e) {
301
- conversation.log(`Error switching model: ${summarizeError(e)}`, { fg: '#ef4444' });
289
+ conversation.log(`Error switching model: ${summarizeError(e)}`, { fg: activeTokens().error });
302
290
  }
303
291
  completeModelSelectionSideEffect?.();
304
292
  requestRender();
@@ -306,63 +294,25 @@ export function createBootstrapCommandActions(
306
294
  jumpToBookmark: () => unwiredShellAction('jumpToBookmark'),
307
295
  scrollToLine: () => unwiredShellAction('scrollToLine'),
308
296
  print: (text: string) => {
309
- conversation.log(text, { fg: '252' });
297
+ conversation.log(text, { fg: activeTokens().text });
310
298
  requestRender();
311
299
  },
312
300
  exit: () => unwiredShellAction('exit'),
313
301
  reloadSystemPrompt: loadSystemPrompt,
314
- showPanel,
315
- openForensicsPanel: () => {
316
- showPanel('forensics');
317
- },
318
- openIncidentPanel: () => {
319
- showPanel('incident');
320
- },
321
- openPolicyPanel: () => {
322
- showPanel('policy');
323
- },
324
- openHooksPanel: () => {
325
- showPanel('hooks');
326
- },
327
- openCommunicationPanel: () => {
328
- showPanel('communication');
329
- },
330
- openOrchestrationPanel: () => {
331
- showPanel('orchestration');
332
- },
333
- openCockpitPanel: () => {
334
- showPanel('cockpit');
335
- },
302
+ openForensicsView: viewNotAttached('Agents'),
303
+ openIncidentView: viewNotAttached('Agents'),
304
+ openPolicyView: viewNotAttached('Policy'),
305
+ openHooksView: viewNotAttached('Hooks'),
306
+ openCommunicationView: viewNotAttached('Agents'),
307
+ openOrchestrationView: viewNotAttached('Agents'),
308
+ openCockpitView: viewNotAttached('Agents'),
336
309
  openMcpWorkspace: () => unwiredShellAction('openMcpWorkspace'),
337
- openSecurityPanel: () => {
338
- showPanel('security');
339
- },
340
- openKnowledgePanel: () => {
341
- showPanel('knowledge');
342
- },
343
- openMemoryPanel: () => {
344
- showPanel('memory');
345
- },
346
- // remote/subscription migrated to config-modal surfaces. open() hits
347
- // the modal redirect and invokes the openModal callback, do NOT go through
348
- // showPanel here, which would additionally reveal + focus an (empty) panel
349
- // workspace behind the fullscreen modal.
350
- openRemotePanel: () => {
351
- panelManager.open('remote');
352
- },
353
- openSubscriptionPanel: () => {
354
- panelManager.open('subscription');
355
- },
356
- openLocalAuthMaskedEntry: (kind, username) => {
357
- showPanel('local-auth');
358
- const panel = panelManager.getPanel('local-auth');
359
- if (panel instanceof LocalAuthPanel && localUserAuthManager) {
360
- panel.openMaskedEntry(kind, username, localUserAuthManager);
361
- } else {
362
- conversation.log('Masked entry unavailable: local auth is not configured in this session.', { fg: '#ef4444' });
363
- requestRender();
364
- }
365
- },
310
+ openSecurityView: viewNotAttached('Security'),
311
+ openKnowledgeView: viewNotAttached('Knowledge'),
312
+ openMemoryView: viewNotAttached('Memory'),
313
+ openRemoteView: viewNotAttached('Remote'),
314
+ openSubscriptionView: viewNotAttached('Subscriptions'),
315
+ openLocalAuthMaskedEntry: viewNotAttached('The password prompt'),
366
316
  };
367
317
  }
368
318
 
@@ -406,7 +356,7 @@ export function createBootstrapCommandProviderSection(
406
356
  export function createBootstrapCommandWorkspaceSection(
407
357
  options: Pick<
408
358
  BootstrapCommandSectionOptions,
409
- 'surface' | 'keybindingsManager' | 'fileUndoManager' | 'workspaceCheckpointManager' | 'gatewayMethods' | 'workspaceTrustManager' | 'workspaceRegistrationManager' | 'panelManager' | 'profileManager' | 'bookmarkManager'
359
+ 'surface' | 'keybindingsManager' | 'fileUndoManager' | 'workspaceCheckpointManager' | 'gatewayMethods' | 'workspaceTrustManager' | 'workspaceRegistrationManager' | 'profileManager' | 'bookmarkManager'
410
360
  | 'projectPlanningService' | 'projectPlanningProjectId' | 'workPlanStore'
411
361
  >,
412
362
  shellServices: BootstrapCommandShellServices,
@@ -419,7 +369,6 @@ export function createBootstrapCommandWorkspaceSection(
419
369
  gatewayMethods: options.gatewayMethods,
420
370
  workspaceTrustManager: options.workspaceTrustManager,
421
371
  workspaceRegistrationManager: options.workspaceRegistrationManager,
422
- panelManager: options.panelManager,
423
372
  profileManager: options.profileManager,
424
373
  bookmarkManager: options.bookmarkManager,
425
374
  projectPlanningService: options.projectPlanningService,
@@ -1,4 +1,6 @@
1
1
  import { ConversationManager } from '../core/conversation';
2
+ import { createShellNoticeSink } from './notification-dispatch.ts';
3
+ import { getSharedNotificationFeed } from '../views/notifications-feed.ts';
2
4
  import { registerSessionConversation } from './conversation-rewind-port.ts';
3
5
  import { SelectionManager } from '@pellux/goodvibes-terminal-shell';
4
6
  import { logger } from '@pellux/goodvibes-sdk/platform/utils';
@@ -8,8 +10,7 @@ import { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
8
10
  import { registerAllTools } from '@pellux/goodvibes-sdk/platform/tools';
9
11
  import { createSandboxContainmentNotice } from './daemon-attach-notices.ts';
10
12
  import { PermissionManager, createPermissionConfigReader } from '@pellux/goodvibes-sdk/platform/permissions';
11
- import { Notifier } from '@pellux/goodvibes-sdk/platform/integrations';
12
- import { Compositor } from '../renderer/compositor.ts';
13
+ import { Compositor } from '../renderer/compositor.ts'; import { activeTokens } from '../renderer/theme.ts';
13
14
  import type { PermissionRequestHandler } from '@pellux/goodvibes-sdk/platform/permissions';
14
15
  import type { SystemMessageRouter } from '../core/system-message-router.ts';
15
16
  import type { ConversationFollowUpItem } from '@pellux/goodvibes-sdk/platform/core';
@@ -37,7 +38,7 @@ import type { SystemMessagePriority } from '../core/system-message-router.ts';
37
38
  import { SessionSpineClient, SessionUnionCache, TUI_SPINE_PARTICIPANT } from '@pellux/goodvibes-sdk/platform/runtime/session-spine';
38
39
  import { SessionInboundInputPoller, createBootstrapInboundInputPoller } from './session-inbound-inputs.ts';
39
40
  import { trustGatedAsk, type WorkspaceTrustLevel } from '@pellux/goodvibes-sdk/platform/runtime/operations';
40
- import { syncNotifierQueueIntegrations } from './bootstrap-notifier-sync.ts';
41
+ import { createRuntimeNotifier, syncNotifierQueueIntegrations } from './bootstrap-notifier-sync.ts';
41
42
 
42
43
  // --- Pre-router buffer ---
43
44
 
@@ -290,7 +291,6 @@ export async function initializeBootstrapCore(
290
291
  hookDispatcher,
291
292
  hookWorkbench,
292
293
  memoryStore,
293
- panelManager,
294
294
  routeBindings,
295
295
  sessionBroker: sharedSessionBroker,
296
296
  surfaceRegistry,
@@ -337,14 +337,12 @@ export async function initializeBootstrapCore(
337
337
  sessionUnionCache,
338
338
  });
339
339
 
340
- const conversation = new ConversationManager(() => {
341
- const width = stdout.columns || 80;
342
- if (panelManager.isVisible() && panelManager.getAllOpen().length > 0) {
343
- return Math.max(1, panelManager.getLeftWidth(width) - 1);
344
- }
345
- return width;
346
- });
340
+ const conversation = new ConversationManager(() => stdout.columns || 80);
347
341
  conversation.setConfigManager(configManager);
342
+ // Every system notice is a toast and a notification-history entry, full
343
+ // text (core/notices.ts); the transcript draws none of them.
344
+ // One history entry per event: see createShellNoticeSink.
345
+ conversation.setNoticeSink(createShellNoticeSink(getSharedNotificationFeed()));
348
346
  getConversationTitle = () => conversation.title;
349
347
 
350
348
  const compositor = new Compositor(stdout);
@@ -382,7 +380,7 @@ export async function initializeBootstrapCore(
382
380
  // Register context_accounting against OUR holder (the Orchestrator-backed source bound at bootstrap.ts). See runtime/context-accounting-source.ts.
383
381
  contextAccountingHolder: services.contextAccountingHolder,
384
382
  // First contained (sandboxed) command run announces "commands now run contained" once, recorded and surfaced now.
385
- onSandboxedRun: createSandboxContainmentNotice({ configManager, notify: (text) => conversation.log(`[Sandbox] ${text}`, { fg: '135' }) }),
383
+ onSandboxedRun: createSandboxContainmentNotice({ configManager, notify: (text) => conversation.log(`[Sandbox] ${text}`, { fg: activeTokens().secondary }) }),
386
384
  }); registerClientPhoneTool(toolRegistry, services.devices); // the `phone` tool follows the LOOP, so it is registered here; the posture runtime it used to call is the daemon's now and this tool reaches it over the devices.* verbs (see the SDK's client/phone-tool.ts)
387
385
  // Note: installWrfcAgentToolGuard is called after routeOrBuffer is defined (further below) so the onTrace callback routes guard decisions through the pre-router buffer.
388
386
  services.agentOrchestrator.setDependencies({
@@ -523,7 +521,7 @@ export async function initializeBootstrapCore(
523
521
  // core WORKFLOW_REVIEW_COMPLETED / WORKFLOW_CHAIN_CREATED messages.
524
522
  // The SDK does not surface constraint-specific system messages; the TUI layer
525
523
  // adds them here so operators can observe constraint enumeration and violations
526
- // in the SystemMessagesPanel and main conversation.
524
+ // in the main conversation.
527
525
  //
528
526
  // Pre-router buffering: events that arrive before the SystemMessageRouter is
529
527
  // attached are held in wrfcBuffer (bounded, 100 entries). When the router is
@@ -542,7 +540,7 @@ export async function initializeBootstrapCore(
542
540
  // Startup TLS banner, emitted via wrfcBuffer.push() because the
543
541
  // SystemMessageRouter is not attached yet at this point in bootstrap. The
544
542
  // smart-ref setter on systemMessageRouterRef auto-flushes the buffer when
545
- // the router attaches, so the message will appear in the WRFC panel on startup.
543
+ // the router attaches, so the message will appear in the conversation on startup.
546
544
  {
547
545
  const cpEnabled = Boolean(configManager.get('controlPlane.enabled'));
548
546
  const cpHostMode = String(configManager.get('controlPlane.hostMode') ?? 'local');
@@ -695,7 +693,7 @@ export async function initializeBootstrapCore(
695
693
  }
696
694
  services.webhookNotifier.attachToRuntimeBus(runtimeBus);
697
695
 
698
- const notifier = await Notifier.fromConfig(services.serviceRegistry);
696
+ const notifier = await createRuntimeNotifier(services.serviceRegistry, (key) => configManager.get(key as Parameters<typeof configManager.get>[0]));
699
697
  syncNotifierQueueIntegrations(notifier, runtimeBus, domainDispatch);
700
698
 
701
699
  await syncConfiguredServices(domainDispatch.syncIntegration, services.serviceRegistry);
@@ -1,3 +1,4 @@
1
+ import { activeTokens } from '../renderer/theme.ts';
1
2
  import type { ConversationManager } from '../core/conversation';
2
3
  import type { HookDispatcher } from '@pellux/goodvibes-sdk/platform/hooks';
3
4
  import type { MutableRuntimeState } from '@/runtime/index.ts';
@@ -11,7 +12,6 @@ import { formatReturnContextForDisplay, getReturnContextMode, maybeAssistReturnC
11
12
  import type { SharedSessionBroker } from '@pellux/goodvibes-sdk/platform/control-plane';
12
13
  import type { SessionSpineClient } from '@pellux/goodvibes-sdk/platform/runtime/session-spine';
13
14
  import type { SessionManager } from '@pellux/goodvibes-sdk/platform/sessions';
14
- import type { PanelManager } from '../panels/panel-manager.ts';
15
15
  import type { ProviderRegistry } from '@pellux/goodvibes-sdk/platform/providers';
16
16
  import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
17
17
  import { resumeSessionCore } from '../core/session-resume-core.ts';
@@ -31,7 +31,6 @@ export interface ResumeSessionOptions {
31
31
  readonly writeLastSessionPointer: (sessionId: string) => void;
32
32
  readonly hookDispatcher: HookDispatcher;
33
33
  readonly sessionManager: SessionManager;
34
- readonly panelManager: PanelManager;
35
34
  /** The app's declare-once session-storage handle, the same one /session resume threads. */
36
35
  readonly surface: SessionSurface;
37
36
  /**
@@ -58,7 +57,7 @@ export interface ResumeSessionOptions {
58
57
  * Delegates the mechanical resume sequence to resumeSessionCore (the same
59
58
  * routine session-workflow.ts's `/session resume` calls) so the two seams
60
59
  * cannot diverge on restoreTurnAnchors, resetAll-before-fromJSON, model
61
- * reselection, or the modal-redirect panel-reopen skip, see
60
+ * reselection, see
62
61
  * core/session-resume-core.ts's header doc for the full list of divergences
63
62
  * this closes. Everything below the resumeSessionCore call is plumbing only
64
63
  * this seam performs (hook fire, session-spine mirror, shared-broker
@@ -71,7 +70,7 @@ export function createResumeSessionHandler(options: ResumeSessionOptions): (sess
71
70
  // for the text path: never fork a session another terminal is holding
72
71
  // open without the operator saying so.
73
72
  if (options.confirmLiveResume && !(await options.confirmLiveResume(sessionId))) {
74
- options.conversation.log('Resume cancelled: the session is still open in another terminal.', { fg: '244' });
73
+ options.conversation.log('Resume cancelled: the session is still open in another terminal.', { fg: activeTokens().textMuted });
75
74
  options.requestRender();
76
75
  return;
77
76
  }
@@ -95,37 +94,29 @@ export function createResumeSessionHandler(options: ResumeSessionOptions): (sess
95
94
  conversation: options.conversation,
96
95
  runtime: options.runtime,
97
96
  surface: options.surface,
98
- panelManager: options.panelManager,
99
97
  selectModel: options.selectModel,
100
98
  hydrateSessionUsage: options.hydrateSessionUsage,
101
99
  });
102
- const { meta, panels } = outcome;
100
+ const { meta } = outcome;
103
101
 
104
102
  options.onSessionIdChanged?.(sessionId);
105
103
  options.writeLastSessionPointer(sessionId);
106
104
  void options.sharedSessionBroker.reopenSession(sessionId).catch((err) => { logger.debug('session broker reopen session failed', { err }); });
107
105
  // Fire-and-forget spine mirror (reopen:true, the user resume verb).
108
106
  options.sessionSpine.reopen({ sessionId, project: options.project, title: options.conversation.title || meta.title });
109
- options.conversation.log(`Resumed session: ${sessionId}`, { fg: '135' });
110
- if (panels.movedToModal.length > 0) {
111
- options.conversation.log(`Resume: ${panels.movedToModal.join(', ')} moved to a modal; reopen via its command instead of as a panel.`, { fg: '244' });
112
- }
113
- if (panels.notReopened.length > 0) {
114
- options.conversation.log(`Resume: …and ${panels.notReopened.length} more not reopened (/panels to open)`, { fg: '244' });
115
- }
107
+ options.conversation.log(`Resumed session: ${sessionId}`, { fg: activeTokens().secondary });
116
108
  const returnContextMode = getReturnContextMode(options.configManager);
117
109
  if (returnContextMode !== 'off' && meta.returnContext) {
110
+ // The SDK's session loader already dropped any legacy open-views list from a
111
+ // session saved by an older TUI, so the loaded return context is shown as-is.
118
112
  for (const line of formatReturnContextForDisplay(meta.returnContext)) {
119
- options.conversation.log(`Resume: ${line}`, { fg: '244' });
120
- }
121
- if (panels.reopened.length > 0) {
122
- options.conversation.log(`Resume: Reopened panels: ${panels.reopened.join(', ')}`, { fg: '244' });
113
+ options.conversation.log(`Resume: ${line}`, { fg: activeTokens().textMuted });
123
114
  }
124
115
  if ((meta.returnContext.remoteRunners?.length ?? 0) > 0) {
125
- options.conversation.log(`Resume: Remote re-entry -> /remote recover ${meta.returnContext.remoteRunners![0]}`, { fg: '244' });
116
+ options.conversation.log(`Resume: Remote re-entry -> /remote recover ${meta.returnContext.remoteRunners![0]}`, { fg: activeTokens().textMuted });
126
117
  }
127
118
  if ((meta.returnContext.worktreePaths?.length ?? 0) > 0) {
128
- options.conversation.log('Resume: Worktree re-entry -> /worktree review', { fg: '244' });
119
+ options.conversation.log('Resume: Worktree re-entry -> /worktree review', { fg: activeTokens().textMuted });
129
120
  }
130
121
  if (returnContextMode === 'assisted') {
131
122
  const helperModel = new HelperModel({
@@ -134,7 +125,7 @@ export function createResumeSessionHandler(options: ResumeSessionOptions): (sess
134
125
  });
135
126
  void maybeAssistReturnContextSummary(options.configManager, helperModel, meta.returnContext).then((assisted) => {
136
127
  if (!assisted.assistedNarrative) return;
137
- options.conversation.log(`Resume: ${assisted.assistedNarrative}`, { fg: '244' });
128
+ options.conversation.log(`Resume: ${assisted.assistedNarrative}`, { fg: activeTokens().textMuted });
138
129
  options.requestRender();
139
130
  });
140
131
  }
@@ -153,7 +144,7 @@ export function createResumeSessionHandler(options: ResumeSessionOptions): (sess
153
144
  }));
154
145
  } catch (error) {
155
146
  logger.debug('resumeSession failed', { error: summarizeError(error) });
156
- options.conversation.log('Failed to resume session.', { fg: '#ef4444' });
147
+ options.conversation.log('Failed to resume session.', { fg: activeTokens().error });
157
148
  }
158
149
  options.requestRender();
159
150
  };
@@ -1,4 +1,5 @@
1
- import type { Notifier } from '@pellux/goodvibes-sdk/platform/integrations';
1
+ import { Notifier } from '@pellux/goodvibes-sdk/platform/integrations';
2
+ import { readNotificationsMetadataOnly } from '@pellux/goodvibes-sdk/platform/runtime/operations';
2
3
  import type { RuntimeEventBus } from '@/runtime/index.ts';
3
4
  import type { createDomainDispatch } from './store/index.ts';
4
5
 
@@ -39,3 +40,18 @@ export function syncNotifierQueueIntegrations(
39
40
  }, 'bootstrap.notifier');
40
41
  }
41
42
  }
43
+
44
+ /**
45
+ * The Slack and Discord notifier, built from the configured services. Its
46
+ * agent and workstream notices name the task unless
47
+ * behavior.notificationsMetadataOnly is on; the setting is read at send time,
48
+ * so a change applies without a restart.
49
+ */
50
+ export function createRuntimeNotifier(
51
+ serviceRegistry: Parameters<typeof Notifier.fromConfig>[0],
52
+ configGet: (key: string) => unknown,
53
+ ): Promise<Notifier> {
54
+ return Notifier.fromConfig(serviceRegistry, {
55
+ metadataOnly: () => readNotificationsMetadataOnly(configGet),
56
+ });
57
+ }
@@ -16,7 +16,7 @@ import { InputHistory } from '../input/input-history.ts';
16
16
  import { GitStatusProvider } from '../renderer/git-status.ts';
17
17
  import type { GitHeaderInfo } from '../renderer/git-status.ts';
18
18
  import type { PermissionRequestHandler } from '@pellux/goodvibes-sdk/platform/permissions';
19
- import { registerBuiltinPanels } from '../panels/builtin-panels.ts';
19
+ import { createShellViews, type ShellViews } from '../views/builtin-views.ts';
20
20
  import { WorkspaceRegistrationManager } from '@pellux/goodvibes-sdk/platform/runtime/operations';
21
21
  import { createSystemMessageRouter, type SystemMessageRouter } from '../core/system-message-router.ts';
22
22
  import { getConfigSnapshot } from '@pellux/goodvibes-sdk/platform/config';
@@ -28,7 +28,6 @@ import { loadBootstrapSystemPrompt } from '@/runtime/index.ts';
28
28
  import { createShellPlanRuntime, createShellRemoteCommandService } from '@/runtime/index.ts';
29
29
  import { createRuntimeFoundationClients } from '@/runtime/index.ts';
30
30
  import type { ControlPlaneRecentEvent } from '@pellux/goodvibes-sdk/platform/control-plane';
31
- import type { BuiltinPanelDeps } from '../panels/builtin/shared.ts';
32
31
  import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
33
32
  import type { ForensicsRegistry } from '@/runtime/index.ts';
34
33
  import type { PolicyRuntimeState } from '@/runtime/index.ts';
@@ -44,6 +43,8 @@ export interface BootstrapShellState {
44
43
  readonly lastGitInfoRef: { value: GitHeaderInfo | undefined };
45
44
  readonly inputHistory: InputHistory;
46
45
  readonly systemMessageRouter: SystemMessageRouter;
46
+ /** The always-on read models and config-modal surfaces behind the built-in modals. */
47
+ readonly views: ShellViews;
47
48
  }
48
49
 
49
50
  export interface BootstrapShellOptions {
@@ -133,7 +134,6 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
133
134
  writeLastSessionPointer,
134
135
  hookDispatcher: services.hookDispatcher,
135
136
  sessionManager: services.sessionManager,
136
- panelManager: services.panelManager,
137
137
  surface: services.surface,
138
138
  // Read lazily on purpose. The selection modal lives on the command
139
139
  // context, which is composed further down this function (and whose
@@ -143,6 +143,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
143
143
  confirmLiveResume: (sessionId) => confirmLiveResume(sessionId, {
144
144
  surface: services.surface,
145
145
  openSelection: () => commandContext.openSelection,
146
+ confirm: () => commandContext.confirm,
146
147
  }),
147
148
  configManager,
148
149
  providerRegistry: services.providerRegistry,
@@ -155,11 +156,9 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
155
156
  });
156
157
 
157
158
  // initial cost-budget alert threshold (USD; 0/unset = disabled).
158
- // Once the session starts, the real control surface is the CostTrackerPanel
159
- // itself, the in-panel 'b' key and /cost budget <usd> both call
160
- // CostTrackerPanel.setBudgetThreshold() directly on the live panel instance,
161
- // which now writes through to the behavior.budgetAlertUsd config key
162
- // so the background budget-breach notifier reads the same value. The env
159
+ // Once the session starts, the Usage modal's 'b' key and /cost budget <usd>
160
+ // both write the behavior.budgetAlertUsd config key (runtime/usage-tracker.ts),
161
+ // the same key the background budget-breach notifier reads. The env
163
162
  // var remains a first-run convenience only: it seeds the config key when
164
163
  // that key has never been set, so it doesn't silently override a value the
165
164
  // user has already configured in a prior session.
@@ -172,54 +171,22 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
172
171
  }
173
172
 
174
173
  let commandContextRef: CommandContext | null = null;
175
- registerBuiltinPanels(services.panelManager, {
176
- configManager,
177
- getOrchestratorUsage: () => orchestrator.usage as { input: number; output: number; cacheRead: number; cacheWrite: number; model?: string },
178
- budgetThreshold: initialCostBudgetThreshold,
179
- toolRegistry,
174
+ const views = createShellViews({
180
175
  providerRegistry: services.providerRegistry,
181
- contextWindow: services.providerRegistry.getContextWindowForModel(services.providerRegistry.getCurrentModel()),
176
+ uiServices,
177
+ toolRegistry,
182
178
  orchestrator,
183
- getCtxWindow: () => services.providerRegistry.getContextWindowForModel(services.providerRegistry.getCurrentModel()),
184
- resumeSession,
179
+ getCtxWindow: () => services.providerRegistry.getKnownContextWindowForModel(services.providerRegistry.getCurrentModel()) ?? 0,
185
180
  requestRender,
186
- submitPlanningAnswer: (answer) => {
187
- if (!commandContextRef?.submitInput) {
188
- throw new Error('Planning answer submission is not wired yet.');
189
- }
190
- commandContextRef.submitInput(answer);
191
- },
192
- dismissPlanning: () => {
193
- services.panelManager.close('project-planning');
194
- commandContextRef?.focusPrompt?.();
195
- requestRender();
196
- },
197
- forensicsRegistry,
198
- policyRuntimeState,
199
- approvalBroker: services.approvalBroker,
200
- // Panels read the cross-surface union facade, not the raw local broker.
201
- sessionBroker: uiServices.sessions.sessionBroker,
202
- automationManager: services.automationManager,
203
- getControlPlaneRecentEvents,
204
- tokenAuditor: services.tokenAuditor,
205
- componentHealthMonitor: services.componentHealthMonitor,
206
- worktreeRegistry: services.worktreeRegistry,
207
181
  sandboxSessionRegistry: services.sandboxSessionRegistry,
208
- // Memory modal reads via the spine client, not the raw registry (see builtin/shared.ts).
182
+ // Memory modal reads via the spine client, not the raw registry.
209
183
  memoryRegistry: services.memorySpine,
210
- uiServices,
211
184
  pluginManager: services.pluginManager,
212
185
  hookDispatcher: services.hookDispatcher,
213
186
  hookActivityTracker: services.hookActivityTracker,
214
187
  hookWorkbench: services.hookWorkbench,
215
- mcpRegistry: services.mcpRegistry,
216
- daemonHomeDir: join(services.homeDirectory, '.goodvibes', 'daemon'),
217
- opsApi,
218
- planRuntime,
219
- watcherRegistry: services.watcherRegistry,
220
- runtimeStore,
221
- openPanel: (panelId: string) => { services.panelManager.open(panelId); },
222
188
  knowledgeApi,
189
+ sessionChangeTracker: services.sessionChangeTracker,
223
190
  // Fleet acts (pick / conflict / discard) surface receipts through the command
224
191
  // context's print and reuse its one-key jump affordance, both late-bound
225
192
  // (the command context is assigned to commandContextRef after bootstrap, and
@@ -227,7 +194,6 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
227
194
  fleetActsNotify: (message: string) => { commandContextRef?.print?.(message); requestRender(); },
228
195
  armFixSessionAttach: (sessionId: string) => { commandContextRef?.armFixSessionAttach?.(sessionId); },
229
196
  });
230
- services.panelManager.prewarmRegistered();
231
197
 
232
198
  const systemMessageRouter = createSystemMessageRouter(
233
199
  conversation,
@@ -340,7 +306,6 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
340
306
  mcpApi,
341
307
  opsApi,
342
308
  directTransport,
343
- panelManager: services.panelManager,
344
309
  worktreeRegistry: services.worktreeRegistry,
345
310
  sandboxSessionRegistry: services.sandboxSessionRegistry,
346
311
  loadSystemPrompt: () => loadBootstrapSystemPrompt(configManager),
@@ -372,8 +337,8 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
372
337
  // TURN_COMPLETED/TOOL_SUCCEEDED/TOOL_FAILED (see turn-event-wiring.ts's
373
338
  // refreshGit()), if the user runs `git init` externally and never submits
374
339
  // another turn, the header stays stuck on the startup-time fallback
375
- // indefinitely. Poll at the same 5s cadence GitPanel already uses for its
376
- // own self-poll (git-panel.ts) so the two mechanisms are cadence-consistent.
340
+ // indefinitely. Poll at the same 5s cadence the other live modals use for
341
+ // their own self-polls so the mechanisms are cadence-consistent.
377
342
  gitStatusProvider.startPolling(5_000, (info) => {
378
343
  lastGitInfoRef.value = info;
379
344
  requestRender();
@@ -392,5 +357,6 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
392
357
  lastGitInfoRef,
393
358
  inputHistory,
394
359
  systemMessageRouter,
360
+ views,
395
361
  };
396
362
  }