@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,5 +1,5 @@
1
1
  import type { Tool } from '@pellux/goodvibes-sdk/platform/types';
2
- import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
2
+ import { askDelegatesToAgent, askForbidsWrites, type ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
3
3
 
4
4
  type AgentToolArgs = {
5
5
  readonly mode?: unknown;
@@ -92,6 +92,18 @@ export function normalizeWrfcAgentToolInvocation(args: AgentToolArgs, options: W
92
92
  const lastUserMessage = cleanText(options.getLastUserMessage?.() ?? null);
93
93
  const trace = options.onTrace;
94
94
  if (args.mode === 'spawn') {
95
+ // The user's own "do not modify files" outranks every promotion below: a
96
+ // write-review-fix chain's fix phase writes files, so a read-only ask
97
+ // (a review, an audit) runs as a plain agent with the task the model
98
+ // delegated. The SDK applies the same rule (rootSpawnIsReadOnlyAsk).
99
+ if (askForbidsWrites(lastUserMessage || cleanText(args.task))) {
100
+ trace?.({
101
+ kind: 'spawn-suppressed-wrfc',
102
+ reason: 'the request forbids writing files',
103
+ task: cleanText(args.task) || '(no task)',
104
+ });
105
+ return { ...args, reviewMode: 'none', dangerously_disable_wrfc: true };
106
+ }
95
107
  if (shouldRouteSpawnToWrfc(args)) {
96
108
  const reason = resolveSpawnWrfcReason(args);
97
109
  trace?.({
@@ -264,8 +276,16 @@ function isReadOnlyTask(text: string): boolean {
264
276
  return /^\s*(?:inspect|research|read|find|list|summarize|analy[sz]e|explain|report|investigate|document|describe|audit|evaluate|assess|check|compare|tell|show)\b/i.test(text);
265
277
  }
266
278
 
279
+ /**
280
+ * The chain's task: the user's own words, unless those words are an
281
+ * instruction to delegate ("Spawn one agent to …"). The agent being spawned
282
+ * IS that delegation, so its task is the work the model extracted; handed the
283
+ * delegation instruction itself, an agent without the agent tool can only fail.
284
+ */
267
285
  function selectAuthoritativeTask(candidate: unknown, lastUserMessage: string): string {
268
- return lastUserMessage || cleanText(candidate);
286
+ const delegated = cleanText(candidate);
287
+ if (lastUserMessage && askDelegatesToAgent(lastUserMessage) && delegated) return delegated;
288
+ return lastUserMessage || delegated;
269
289
  }
270
290
 
271
291
  function uniqueStrings(groups: readonly unknown[]): string[] | undefined {
@@ -1,22 +1,18 @@
1
1
  /**
2
- * Shared ms-duration formatters for the panel layer.
2
+ * Shared ms-duration formatters for the view layer.
3
3
  *
4
4
  * Two families are exported, each matching a distinct behavior cluster.
5
5
  * DO NOT replace these with formatElapsed from utils/format-elapsed.ts,
6
6
  * formatElapsed floors to integer seconds and lacks the null/'?ms' guards
7
- * that the latency panels require.
7
+ * that the latency views require.
8
8
  *
9
- * (the purge): formatShortDuration (used only by incident-review-panel
10
- * and eval-panel, both removed, RETIRE-INTO-FLEET and DELETE respectively)
11
- * was removed as a genuinely orphaned export, no remaining caller anywhere
12
- * in src/.
9
+ * formatShortDuration was removed as a genuinely orphaned export, with no
10
+ * remaining caller anywhere in src/.
13
11
  */
14
12
 
15
13
  /**
16
14
  * Format a latency value in milliseconds with sub-second precision.
17
15
  *
18
- * Used by: provider-health-panel
19
- *
20
16
  * ms <= 0 → 'n/a'
21
17
  * ms >= 10000 → '12.3s' (one decimal)
22
18
  * ms >= 1000 → '1.23s' (two decimals)
@@ -23,8 +23,16 @@ const TAGLINE = '[ good vibes ・ A I ・ いい雰囲気
23
23
  const versionLine = (version: string) =>
24
24
  ` ✦ v${version} █ terminal AI assistant █ 自動コード  ✦`;
25
25
 
26
+ /**
27
+ * The splash wordmark gradient, protected: it is part of the GoodVibes mark,
28
+ * identical under every theme and mode, and must never be routed through the
29
+ * theme tokens. conversation-rendering.ts interpolates start to end across
30
+ * each wordmark row.
31
+ */
32
+ export const SPLASH_GRADIENT = Object.freeze({ start: '#00ffff', end: '#d000ff' } as const);
33
+
26
34
  /** Fixed hint line, the three primary shell entry points. */
27
- const HINT_LINE = 'Ctrl+P panels / ? help / F2 fleet';
35
+ const HINT_LINE = 'Ctrl+P commands / ? help / F2 agents';
28
36
 
29
37
  export interface SplashOptions {
30
38
  workingDir?: string;
@@ -93,6 +93,13 @@ export function getDisplayWidth(text: string): number {
93
93
  // corrupting the following text (the "✕t" glitch on the steer error line).
94
94
  code === 0x2715 ||
95
95
  code === 0x2716 ||
96
+ // ✦ (0x2726, the splash star and the modal group marker), ⏎ (0x23ce)
97
+ // and ⌫ (0x232b, keycap glyphs) have no emoji presentation, so
98
+ // terminals draw them one cell wide too; the block rules below would
99
+ // otherwise count them as 2 and shift everything after them.
100
+ code === 0x2726 ||
101
+ code === 0x23ce ||
102
+ code === 0x232b ||
96
103
  code === 0x2022 ||
97
104
  code === 0x258d ||
98
105
  (code >= 0x2500 && code <= 0x257f)
@@ -272,6 +279,55 @@ export function wrapText(text: string, width: number): string[] {
272
279
  return lines;
273
280
  }
274
281
 
282
+ /** Columns one tab takes in a drawn body; the same two spaces a diff body uses (changes-modal.ts wrapTokens). */
283
+ export const BODY_TAB_WIDTH = 2;
284
+
285
+ /** Replace every tab with BODY_TAB_WIDTH spaces, so width math and drawing agree. */
286
+ export function expandTabs(text: string): string {
287
+ return text.includes('\t') ? text.replace(/\t/g, ' '.repeat(BODY_TAB_WIDTH)) : text;
288
+ }
289
+
290
+ /**
291
+ * Wrap one body line (a file line, command output) to `width` cells without
292
+ * losing its layout: tabs expand to spaces, a line that fits is returned
293
+ * exactly as it is (leading indentation and inner runs of spaces kept), and a
294
+ * longer line wraps at spaces with every continuation row indented like the
295
+ * first. A word wider than the room left is cut hard. Every returned row is
296
+ * at most `width` cells.
297
+ */
298
+ export function wrapPreservingIndent(text: string, width: number): string[] {
299
+ const out: string[] = [];
300
+ for (const raw of expandTabs(text).split('\n')) {
301
+ const line = raw.replace(/\s+$/, '');
302
+ if (getDisplayWidth(line) <= width) { out.push(line); continue; }
303
+ const indentText = /^ */.exec(line)![0];
304
+ // Deep indentation leaves no room: continuation rows start at the left edge.
305
+ const indent = indentText.length <= Math.floor(width / 2) ? indentText : '';
306
+ let rest = Array.from(line.slice(indentText.length));
307
+ let prefix = indentText.length <= width - 1 ? indentText : '';
308
+ while (rest.length > 0) {
309
+ const avail = Math.max(1, width - prefix.length);
310
+ // Longest run of `rest` that fits, preferring to break after a space.
311
+ let cut = 0;
312
+ let used = 0;
313
+ let lastSpace = -1;
314
+ for (let i = 0; i < rest.length; i++) {
315
+ const w = getDisplayWidth(rest[i]!);
316
+ if (used + w > avail) break;
317
+ used += w;
318
+ cut = i + 1;
319
+ if (rest[i] === ' ') lastSpace = i + 1;
320
+ }
321
+ const at = cut === rest.length ? cut : lastSpace > 0 ? lastSpace : Math.max(1, cut);
322
+ out.push((prefix + rest.slice(0, at).join('')).replace(/\s+$/, ''));
323
+ rest = rest.slice(at);
324
+ while (rest[0] === ' ') rest.shift();
325
+ prefix = indent;
326
+ }
327
+ }
328
+ return out;
329
+ }
330
+
275
331
  export function interpolateColor(startHex: string, endHex: string, factor: number): string {
276
332
  const parse = (hex: string) => {
277
333
  const r = parseInt(hex.slice(1, 3), 16);
@@ -1,4 +1,4 @@
1
- import { readFileSync, readdirSync } from 'node:fs';
1
+ import { readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { CONFIG_SCHEMA } from '@pellux/goodvibes-sdk/platform/config';
4
4
  import { FEATURE_SETTINGS } from '@pellux/goodvibes-sdk/platform/runtime/state';
@@ -564,15 +564,17 @@ function listSlashCommands(): string[] {
564
564
  return registry.getAll().map((command) => command.name);
565
565
  }
566
566
 
567
- function countBuiltinPanels(root: string): number {
568
- const builtinDir = join(root, 'src', 'panels', 'builtin');
569
- let count = 0;
570
- for (const file of readdirSync(builtinDir)) {
571
- if (!file.endsWith('.ts')) continue;
572
- const text = readFileSync(join(builtinDir, file), 'utf8');
573
- count += [...text.matchAll(/registerType\(\s*\{\s*id:\s*['"][^'"]+['"]/g)].length;
574
- }
575
- return count;
567
+ /**
568
+ * Built-in modals and views: every config-modal surface builtin-modals.ts
569
+ * registers, plus every kit view modal the shell's view openers construct
570
+ * (Agents, Usage, Changes, Notifications, the masked password prompt).
571
+ */
572
+ function countBuiltinModals(root: string): number {
573
+ const surfaces = readFileSync(join(root, 'src', 'views', 'builtin-modals.ts'), 'utf8');
574
+ const openers = readFileSync(join(root, 'src', 'shell', 'view-openers.ts'), 'utf8');
575
+ const surfaceCount = [...surfaces.matchAll(/registerModalSurface\(/g)].length;
576
+ const viewModals = new Set([...openers.matchAll(/new ([A-Za-z]+Modal)\(/g)].map((m) => m[1]));
577
+ return surfaceCount + viewModals.size;
576
578
  }
577
579
 
578
580
  /**
@@ -590,7 +592,7 @@ export function buildVerificationLedger(root: string): VerificationLedger {
590
592
  const slashCommandNames = listSlashCommands();
591
593
  const cliCommandNames = listCliCommands();
592
594
  const slashCommands = slashCommandNames.length;
593
- const panels = countBuiltinPanels(root);
595
+ const modals = countBuiltinModals(root);
594
596
  const cliCommands = cliCommandNames.length;
595
597
  const featureFlags = FEATURE_SETTINGS.length;
596
598
  const settings = CONFIG_SCHEMA.length;
@@ -623,12 +625,12 @@ export function buildVerificationLedger(root: string): VerificationLedger {
623
625
  notes: 'Every command can be routed and invoked with a fake context; external/provider/device commands need live outcome checks.',
624
626
  },
625
627
  {
626
- area: 'Built-in panels',
627
- total: panels,
628
- localSignalVerified: panels,
629
- localBehaviorVerified: panels,
628
+ area: 'Built-in modals and views',
629
+ total: modals,
630
+ localSignalVerified: modals,
631
+ localBehaviorVerified: modals,
630
632
  externalOutcomeRequired: 0,
631
- notes: 'Panels can be rendered and input-tested against fake read models and real cached state.',
633
+ notes: 'Modals and views can be rendered and input-tested against fake read models and real cached state.',
632
634
  },
633
635
  {
634
636
  area: 'Top-level CLI commands',
@@ -7,7 +7,7 @@ export type AgentInspectorEntryKind = 'user' | 'assistant' | 'tool_call' | 'tool
7
7
 
8
8
  // ---------------------------------------------------------------------------
9
9
  // Shared agent status / stall constants
10
- // Used by the Fleet panel's agent views and read-model consumers (formerly also
10
+ // Used by the Agents modal's agent views and read-model consumers (formerly also
11
11
  // AgentDetailModal, which was retired in).
12
12
  // ---------------------------------------------------------------------------
13
13
 
@@ -22,7 +22,7 @@ export const AGENT_STALL_THRESHOLD_MS = 5 * 60 * 1000;
22
22
  * An agent is stalled when it is non-terminal and has been running for at
23
23
  * least AGENT_STALL_THRESHOLD_MS without completing.
24
24
  *
25
- * Extracted as a standalone export so read-models and panels can share the
25
+ * Extracted as a standalone export so read-models and views can share the
26
26
  * canonical stall-count logic (TASK-046).
27
27
  */
28
28
  export function countStalledAgents(
@@ -1,5 +1,5 @@
1
- import type { PanelManager } from './panel-manager.ts';
2
- import { requireUiServices, type ResolvedBuiltinPanelDeps } from './builtin/shared.ts';
1
+ import type { ModalSurfaceRegistry } from './modal-surface-registry.ts';
2
+ import type { ResolvedBuiltinViewDeps } from './view-deps.ts';
3
3
  import type { ConfigModalSurface, ConfigModalView } from '../input/config-modal-types.ts';
4
4
  import { createProviderRuntimeInspectionQuery } from '@/runtime/index.ts';
5
5
  import { createRuntimeProviderApi } from '@/runtime/index.ts';
@@ -32,20 +32,23 @@ import { createDevicesModalSurface } from './modals/devices-modal.ts';
32
32
  import { createPlanningModalSurface } from './modals/planning-modal.ts';
33
33
 
34
34
  /**
35
- * Register the config-modal surfaces + their panel-id redirects, from a prior
36
- * panel-consolidation cleanup. Called once at startup from registerBuiltinPanels, AFTER the panels'
37
- * deps are resolved (the surfaces close over the same read-models the retired
38
- * panels used). For each surface migrated from a standalone panel this does two things:
35
+ * Register the config-modal surfaces and the old names that open them. Called
36
+ * once at startup from createShellViews (builtin-views.ts). For each surface
37
+ * this does two things:
39
38
  * 1. registerModalSurface, the data + actions the config-modal host renders.
40
- * 2. registerModalRedirect, so `/panel open <old-id>`, saved layouts, and any
41
- * alias still resolve to the modal.
39
+ * 2. registerModalRedirect, so `/panel open <old-id>`, notifications and any
40
+ * alias still resolve to the modal (views.ts consults these).
42
41
  *
43
- * The Providers & Connectivity + Security subset is registered first, followed by the
44
- * Ecosystem & Governance set, the 12 ported config-modal
45
- * surfaces plus the `sessions` fold into the existing session-picker modal.
42
+ * `openMaskedEntry` opens the local-auth password prompt (a kit modal), which
43
+ * is how the Local Auth modal's add-user and rotate-password actions keep the
44
+ * password out of argv, history and the transcript.
46
45
  */
47
- export function registerBuiltinModals(manager: PanelManager, deps: ResolvedBuiltinPanelDeps): void {
48
- const ui = requireUiServices(deps);
46
+ export function registerBuiltinModals(
47
+ manager: ModalSurfaceRegistry,
48
+ deps: ResolvedBuiltinViewDeps,
49
+ openMaskedEntry: (kind: 'add-user' | 'rotate-password', username?: string) => void,
50
+ ): void {
51
+ const ui = deps.uiServices;
49
52
 
50
53
  // ── Providers & Connectivity ─────────────────────────────────────────────────
51
54
  manager.registerModalSurface(createServicesModalSurface(deps.serviceRegistry, deps.subscriptionManager));
@@ -71,10 +74,8 @@ export function registerBuiltinModals(manager: PanelManager, deps: ResolvedBuilt
71
74
  manager.registerModalSurface(createSettingsSyncModalSurface(deps.configManager));
72
75
  manager.registerModalRedirect('settings-sync', 'settings-sync-modal');
73
76
 
74
- // local-auth-modal is reached via the /local-auth front-door only; no
75
- // redirect (the 'local-auth' panel id must keep resolving to LocalAuthPanel
76
- // for the masked password-entry path). See builtin/operations.ts.
77
- manager.registerModalSurface(createLocalAuthModalSurface(deps.localUserAuthManager));
77
+ manager.registerModalSurface(createLocalAuthModalSurface(deps.localUserAuthManager, openMaskedEntry));
78
+ manager.registerModalRedirect('local-auth', 'local-auth-modal');
78
79
 
79
80
  manager.registerModalSurface(createSandboxModalSurface(deps.configManager, deps.sandboxSessionRegistry, deps.requestRender));
80
81
  manager.registerModalRedirect('sandbox', 'sandbox-modal');
@@ -178,7 +179,7 @@ export function registerBuiltinModals(manager: PanelManager, deps: ResolvedBuilt
178
179
  }));
179
180
  manager.registerModalRedirect('project-planning', 'planning-modal');
180
181
 
181
- // The retired 'sessions' panel folds into the EXISTING session-picker modal
182
+ // The retired 'sessions' view folds into the EXISTING session-picker modal
182
183
  // (no new config-modal surface); the redirect is a plain hand-off, moved here
183
184
  // from the deleted ecosystem bridge.
184
185
  manager.registerModalRedirect('sessions', 'sessionPicker');
@@ -188,11 +189,11 @@ export function registerBuiltinModals(manager: PanelManager, deps: ResolvedBuilt
188
189
  * Build the companion-pairing connection info lazily (called from the pairing
189
190
  * surface's first render, not at registration time) so a missing daemon home
190
191
  * degrades to an honest "unavailable" modal instead of throwing at startup.
191
- * Mirrors the retired QrPanel factory's construction.
192
+ * Mirrors the retired Qr view factory's construction.
192
193
  */
193
- function buildPairingConnectionInfo(deps: ResolvedBuiltinPanelDeps): PairingModalConnectionInfo | null {
194
+ function buildPairingConnectionInfo(deps: ResolvedBuiltinViewDeps): PairingModalConnectionInfo | null {
194
195
  try {
195
- const ui = requireUiServices(deps);
196
+ const ui = deps.uiServices;
196
197
  const configManager = deps.configManager;
197
198
  // Freeze a stable web origin once (never clobbering a user-set value).
198
199
  const webOrigin = ensurePublicBaseUrl(configManager);
@@ -0,0 +1,135 @@
1
+ /**
2
+ * builtin-views.ts, the always-on pieces behind the built-in modals.
3
+ *
4
+ * Built once at startup (runtime/bootstrap-shell.ts):
5
+ * - the UsageTracker, collecting per-turn history and costs from the first
6
+ * turn whether or not the Usage modal is ever opened;
7
+ * - the fleet's action callbacks, acts (pick / conflict / discard) and the
8
+ * ACP spawn controller the Agents modal drives;
9
+ * - every config-modal surface, registered on the ModalSurfaceRegistry with
10
+ * the old names that open it.
11
+ *
12
+ * Two things only exist once the input handler does (the kit modal host): the
13
+ * Changes preview the fleet acts show candidate diffs in, and the local-auth
14
+ * password prompt. They are late-bound through `bridge`, which the shell fills
15
+ * in (shell/ui-openers.ts) before any of them can be used.
16
+ */
17
+
18
+ import type { UserAuthManager } from '@pellux/goodvibes-sdk/platform/security';
19
+ import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
20
+ import { GOODVIBES_TUI_SURFACE_ROOT } from '../config/surface.ts';
21
+ import { UsageTracker } from '../runtime/usage-tracker.ts';
22
+ import type { FleetActionCallbacks } from '../input/agents-modal.ts';
23
+ import { ModalSurfaceRegistry } from './modal-surface-registry.ts';
24
+ import { registerBuiltinModals } from './builtin-modals.ts';
25
+ import { resolveBuiltinViewDeps, type BuiltinViewDeps } from './view-deps.ts';
26
+ import type { FleetReadModel } from './fleet-read-model.ts';
27
+ import { FleetActs, type FleetDiffSurface } from './fleet-acts.ts';
28
+ import { createFleetGateway } from './fleet-gateway.ts';
29
+ import { FleetSpawn, createAcpSpawnGateway } from './fleet-spawn.ts';
30
+
31
+ export type MaskedEntryOpener = (kind: 'add-user' | 'rotate-password', username?: string) => void;
32
+
33
+ export interface ShellViewBridge {
34
+ /** Show candidate diffs and ask over them (the Changes preview). */
35
+ diffSurface: FleetDiffSurface | null;
36
+ /** Open the local-auth password prompt. */
37
+ openMaskedEntry: MaskedEntryOpener | null;
38
+ }
39
+
40
+ export interface ShellViews {
41
+ readonly modalSurfaces: ModalSurfaceRegistry;
42
+ readonly usage: UsageTracker;
43
+ readonly fleet: {
44
+ readonly readModel: FleetReadModel;
45
+ readonly actions: FleetActionCallbacks;
46
+ readonly acts: FleetActs;
47
+ readonly spawn: FleetSpawn;
48
+ };
49
+ readonly configManager: ConfigManager;
50
+ readonly workingDirectory: string;
51
+ /** Files this session edited. */
52
+ readonly getSessionFiles: () => string[];
53
+ readonly localUserAuthManager: UserAuthManager;
54
+ readonly bridge: ShellViewBridge;
55
+ dispose(): void;
56
+ }
57
+
58
+ export function createShellViews(deps: BuiltinViewDeps): ShellViews {
59
+ const resolved = resolveBuiltinViewDeps(deps);
60
+ const ui = deps.uiServices;
61
+ const requestRender = deps.requestRender ?? (() => {});
62
+ const bridge: ShellViewBridge = { diffSurface: null, openMaskedEntry: null };
63
+ const fleetReadModel = ui.runtime.fleetReadModel;
64
+ const notify = deps.fleetActsNotify ?? (() => {});
65
+
66
+ const usage = new UsageTracker({
67
+ turnEvents: ui.events.turns,
68
+ agentEvents: ui.events.agents,
69
+ getUsage: () => (deps.orchestrator?.usage ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }) as { input: number; output: number; cacheRead: number; cacheWrite: number; model?: string },
70
+ getContextTokens: () => deps.orchestrator?.lastInputTokens ?? 0,
71
+ getContextWindow: () => deps.getCtxWindow?.() ?? 0,
72
+ getModelId: () => deps.providerRegistry.getCurrentModel().id,
73
+ getAgentStatus: (id) => ui.agents.agentManager.getStatus(id),
74
+ getFleetCost: () => fleetReadModel.getSnapshot().totalCost,
75
+ configManager: resolved.configManager,
76
+ sessionMemoryStore: resolved.sessionMemoryStore,
77
+ sessionReadModel: ui.readModels.session,
78
+ requestRender,
79
+ });
80
+
81
+ const diffSurface: FleetDiffSurface = {
82
+ show: (title, diff) => bridge.diffSurface?.show(title, diff),
83
+ armConfirm: (opts) => {
84
+ if (bridge.diffSurface) bridge.diffSurface.armConfirm(opts);
85
+ else opts.onCancel?.();
86
+ },
87
+ close: () => bridge.diffSurface?.close(),
88
+ };
89
+
90
+ const acts = new FleetActs({
91
+ resolveGateway: () => createFleetGateway({
92
+ configManager: resolved.configManager,
93
+ homeDirectory: ui.environment.shellPaths.homeDirectory,
94
+ armFixSessionAttach: deps.armFixSessionAttach ?? (() => {}),
95
+ }),
96
+ diffSurface,
97
+ notify,
98
+ markDirty: requestRender,
99
+ findNode: (nodeId: string) => fleetReadModel.getSnapshot().rows.find((r) => r.node.id === nodeId)?.node ?? null,
100
+ });
101
+
102
+ const spawn = new FleetSpawn({
103
+ resolveGateway: () => createAcpSpawnGateway({
104
+ configManager: resolved.configManager,
105
+ homeDirectory: ui.environment.shellPaths.homeDirectory,
106
+ }),
107
+ currentDirectory: () => ui.environment.shellPaths.workingDirectory,
108
+ notify,
109
+ markDirty: requestRender,
110
+ });
111
+
112
+ const actions: FleetActionCallbacks = {
113
+ interrupt: (id) => fleetReadModel.interrupt(id),
114
+ resume: (id) => fleetReadModel.resume(id),
115
+ kill: (id, opts) => fleetReadModel.kill(id, opts),
116
+ getConversationSnapshot: (agentId) => ui.agents.agentManager.getConversationSnapshot(agentId),
117
+ resolveSessionLogPath: (agentId) => ui.environment.shellPaths.resolveProjectPath(GOODVIBES_TUI_SURFACE_ROOT, 'sessions', `${agentId}.jsonl`),
118
+ steer: (id, text) => fleetReadModel.steer(id, text),
119
+ };
120
+
121
+ const modalSurfaces = new ModalSurfaceRegistry();
122
+ registerBuiltinModals(modalSurfaces, resolved, (kind, username) => bridge.openMaskedEntry?.(kind, username));
123
+
124
+ return {
125
+ modalSurfaces,
126
+ usage,
127
+ fleet: { readModel: fleetReadModel, actions, acts, spawn },
128
+ configManager: resolved.configManager,
129
+ workingDirectory: ui.environment.workingDirectory,
130
+ getSessionFiles: () => deps.sessionChangeTracker?.getChangedFiles() ?? [],
131
+ localUserAuthManager: resolved.localUserAuthManager,
132
+ bridge,
133
+ dispose: () => usage.dispose(),
134
+ };
135
+ }
@@ -1,27 +1,27 @@
1
1
  // ---------------------------------------------------------------------------
2
2
  // useConfirmState<T>, reusable inline confirm/cancel helper
3
3
  //
4
- // ── Project-standard confirm contract (all panels must match) ──────────────
4
+ // ── Project-standard confirm contract (all views must match) ──────────────
5
5
  //
6
6
  // CONFIRM: Enter, Return, or y
7
7
  // CANCEL: Esc or n
8
8
  // ABSORBED: any other key while confirm is active (keeps confirm pending)
9
9
  //
10
10
  // Implementation:
11
- // - Composable: any panel holds a ConfirmState<T> field; no new base class
11
+ // - Composable: any view holds a ConfirmState<T> field; no new base class
12
12
  // - Call handleConfirmInput(confirm, key) BEFORE normal key dispatch.
13
13
  // It handles all four outcomes and returns one of the four result tokens.
14
14
  // - Call renderConfirmLines(width, state) to render the two-line overlay
15
15
  // that replaces normal content while a confirm is pending.
16
16
  //
17
17
  // ── This file is the canonical contract for all confirm flows ─────────────
18
- // Any new panel confirm flow must use ConfirmState<T> and handleConfirmInput;
18
+ // Any new view confirm flow must use ConfirmState<T> and handleConfirmInput;
19
19
  // do not implement a bespoke two-press or Enter-only variant.
20
20
  // ---------------------------------------------------------------------------
21
21
 
22
22
  import type { Line } from '@pellux/goodvibes-sdk/platform/types';
23
- import { buildPanelLine } from './polish.ts';
24
- import { DEFAULT_PANEL_PALETTE } from './polish.ts';
23
+ import { buildViewLine } from './polish.ts';
24
+ import { DEFAULT_VIEW_PALETTE } from './polish.ts';
25
25
 
26
26
  export interface ConfirmState<T = string> {
27
27
  /** The subject of the confirmation (e.g. item name or id). */
@@ -37,7 +37,7 @@ export interface ConfirmState<T = string> {
37
37
  }
38
38
 
39
39
  /**
40
- * Call this from a panel's handleInput() BEFORE any other key handling.
40
+ * Call this from a view's handleInput() BEFORE any other key handling.
41
41
  *
42
42
  * Project-standard confirm contract:
43
43
  * - CONFIRM: Enter, Return, or y
@@ -66,14 +66,14 @@ export function handleConfirmInput<T = string>(
66
66
  * Callers embed these lines in a workspace section titled 'Confirmation'.
67
67
  */
68
68
  export function renderConfirmLines<T = string>(width: number, state: ConfirmState<T>): Line[] {
69
- const palette = DEFAULT_PANEL_PALETTE;
69
+ const palette = DEFAULT_VIEW_PALETTE;
70
70
  const verb = state.verb ?? 'Delete';
71
71
  return [
72
- buildPanelLine(width, [[
72
+ buildViewLine(width, [[
73
73
  ` ${verb} "${state.label}"?`,
74
74
  palette.warn,
75
75
  ]]),
76
- buildPanelLine(width, [
76
+ buildViewLine(width, [
77
77
  [' Enter / y', palette.info],
78
78
  [' confirm', palette.dim],
79
79
  [' n / Esc', palette.info],
@@ -1,11 +1,11 @@
1
1
  // ---------------------------------------------------------------------------
2
2
  // Diff review model, pure parsing + steering-payload helpers for the
3
- // comment-on-hunk review loop (see diff-review-panel.ts).
3
+ // comment-on-hunk review loop (see the diff review view).
4
4
  //
5
5
  // The diff this operates on is the git working tree vs a base ref (HEAD),
6
6
  // filtered to the files the current session actually edited (the SDK's
7
7
  // SessionChangeTracker). That is the honest source: it is CURRENT working-tree
8
- // content, not a turn-start snapshot, the panel labels it exactly that way.
8
+ // content, not a turn-start snapshot, the diff review view labels it exactly that way.
9
9
  // ---------------------------------------------------------------------------
10
10
 
11
11
  /** One hunk of one file's diff, with enough structure to steer a comment at it. */
@@ -169,13 +169,20 @@ export interface HunkComment {
169
169
  * patch excerpt so the model knows exactly what the comment targets. The
170
170
  * `sourceLabel` states the honest provenance of the diff (working tree vs base).
171
171
  */
172
- export function buildSteerMessage(items: readonly HunkComment[], sourceLabel: string): string {
172
+ export function buildSteerMessage(
173
+ items: readonly HunkComment[],
174
+ sourceLabel: string,
175
+ /** One-line semantic summaries (functions, classes, imports changed) by file path, when known. */
176
+ semanticByFile?: ReadonlyMap<string, string>,
177
+ ): string {
173
178
  const blocks = items.map(({ hunk, comment }) => {
174
179
  const range = hunkLineRange(hunk);
180
+ const semantic = semanticByFile?.get(hunk.filePath);
175
181
  return [
176
182
  `Review comment on ${hunk.filePath} (lines ${range.start}-${range.end}, new file):`,
177
183
  comment,
178
184
  '',
185
+ ...(semantic ? [`Structure of this file's change: ${semantic}`, ''] : []),
179
186
  'Referenced change:',
180
187
  '```diff',
181
188
  hunkExcerpt(hunk),
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * EvalRegistry, holds the latest evaluation harness run state.
3
3
  *
4
- * (the purge): extracted out of eval-panel.ts. 'eval' was
4
+ * (the purge): extracted out of the eval view. 'eval' was
5
5
  * DELETE-disposition (no surviving human surface, the evaluation harness
6
6
  * is driven and reviewed via the `/eval` CLI command, input/commands/eval.ts)
7
7
  * but this registry is still a live consumer of `/eval run` output, so it