@pellux/goodvibes-tui 2.0.21 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/CHANGELOG.md +65 -1
  2. package/README.md +30 -29
  3. package/docs/README.md +8 -5
  4. package/docs/foundation-artifacts/operator-contract.json +1 -1
  5. package/package.json +28 -19
  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-reference.ts +2 -2
  52. package/src/input/command-registry.ts +77 -35
  53. package/src/input/commands/acp-runtime.ts +19 -9
  54. package/src/input/commands/channel-runtime.ts +2 -2
  55. package/src/input/commands/ci-runtime.ts +1 -1
  56. package/src/input/commands/codebase-runtime.ts +1 -1
  57. package/src/input/commands/config.ts +7 -1
  58. package/src/input/commands/context-window.ts +25 -19
  59. package/src/input/commands/control-room-runtime.ts +18 -18
  60. package/src/input/commands/conversation-runtime.ts +0 -1
  61. package/src/input/commands/cost-runtime.ts +29 -20
  62. package/src/input/commands/diff-runtime.ts +35 -181
  63. package/src/input/commands/eval.ts +1 -1
  64. package/src/input/commands/experience-runtime.ts +3 -7
  65. package/src/input/commands/fresh-conversation.ts +86 -0
  66. package/src/input/commands/git-runtime.ts +5 -22
  67. package/src/input/commands/graph-runtime.ts +1 -1
  68. package/src/input/commands/guidance-runtime.ts +1 -1
  69. package/src/input/commands/health-runtime.ts +8 -9
  70. package/src/input/commands/hooks-runtime.ts +2 -2
  71. package/src/input/commands/hosted-runtime.ts +3 -3
  72. package/src/input/commands/incident-runtime.ts +3 -3
  73. package/src/input/commands/intelligence-runtime.ts +6 -9
  74. package/src/input/commands/knowledge.ts +2 -2
  75. package/src/input/commands/legacy-panel-command.ts +57 -0
  76. package/src/input/commands/local-auth-runtime.ts +8 -9
  77. package/src/input/commands/local-provider-runtime.ts +7 -4
  78. package/src/input/commands/local-runtime.ts +12 -15
  79. package/src/input/commands/local-setup-review.ts +1 -1
  80. package/src/input/commands/local-setup.ts +13 -19
  81. package/src/input/commands/memory.ts +1 -1
  82. package/src/input/commands/notify-runtime.ts +9 -0
  83. package/src/input/commands/operator-runtime.ts +10 -12
  84. package/src/input/commands/permissions-provenance.ts +3 -3
  85. package/src/input/commands/planning-runtime.ts +7 -7
  86. package/src/input/commands/platform-sandbox-runtime.ts +2 -2
  87. package/src/input/commands/platform-services-runtime.ts +1 -1
  88. package/src/input/commands/policy-dispatch.ts +2 -2
  89. package/src/input/commands/policy.ts +3 -3
  90. package/src/input/commands/provider.ts +1 -1
  91. package/src/input/commands/remote-runtime.ts +1 -1
  92. package/src/input/commands/review-runtime.ts +39 -94
  93. package/src/input/commands/rewind-runtime.ts +81 -108
  94. package/src/input/commands/runtime-services.ts +15 -17
  95. package/src/input/commands/services-runtime.ts +2 -2
  96. package/src/input/commands/session-content.ts +21 -5
  97. package/src/input/commands/session-workflow.ts +13 -38
  98. package/src/input/commands/settings-sync-runtime.ts +2 -2
  99. package/src/input/commands/shell-core.ts +19 -4
  100. package/src/input/commands/skills-runtime.ts +2 -2
  101. package/src/input/commands/status-runtime.ts +13 -0
  102. package/src/input/commands/subscription-runtime.ts +1 -1
  103. package/src/input/commands/tasks-runtime.ts +2 -8
  104. package/src/input/commands/work-plan-runtime.ts +4 -4
  105. package/src/input/commands/workstream-attempts.ts +24 -47
  106. package/src/input/commands/workstream-runtime.ts +2 -2
  107. package/src/input/commands/worktree-runtime.ts +3 -3
  108. package/src/input/commands.ts +3 -1
  109. package/src/input/composer-editor.ts +44 -0
  110. package/src/input/concealed-input.ts +1 -1
  111. package/src/input/config-modal-types.ts +20 -8
  112. package/src/input/config-modal.ts +106 -105
  113. package/src/input/confirm-dialog-types.ts +28 -0
  114. package/src/input/confirm-dialog.ts +70 -0
  115. package/src/input/delete-key-policy.ts +3 -3
  116. package/src/input/feed-context-factory.ts +15 -16
  117. package/src/input/handler-command-route.ts +7 -42
  118. package/src/input/handler-content-actions.ts +16 -15
  119. package/src/input/handler-feed-routes.ts +26 -211
  120. package/src/input/handler-feed.ts +68 -95
  121. package/src/input/handler-interactions.ts +5 -3
  122. package/src/input/handler-modal-routes.ts +215 -216
  123. package/src/input/handler-modal-stack.ts +81 -11
  124. package/src/input/handler-modal-token-routes.ts +4 -0
  125. package/src/input/handler-onboarding.ts +0 -1
  126. package/src/input/handler-picker-routes.ts +65 -107
  127. package/src/input/handler-session-view-route.ts +149 -0
  128. package/src/input/handler-shortcuts.ts +16 -154
  129. package/src/input/handler-types.ts +4 -2
  130. package/src/input/handler-ui-state.ts +45 -15
  131. package/src/input/handler-work-tree-route.ts +123 -0
  132. package/src/input/handler.ts +25 -70
  133. package/src/input/keybindings.ts +16 -71
  134. package/src/input/masked-entry-modal.ts +117 -0
  135. package/src/input/mcp-workspace.ts +48 -17
  136. package/src/input/model-picker-filter.ts +8 -0
  137. package/src/input/model-picker-open.ts +99 -0
  138. package/src/input/model-picker-types.ts +1 -1
  139. package/src/input/model-picker.ts +92 -9
  140. package/src/input/notifications-modal.ts +123 -0
  141. package/src/input/overlay-filter.ts +26 -0
  142. package/src/input/profile-picker-modal.ts +37 -8
  143. package/src/input/search.ts +3 -3
  144. package/src/input/selection-modal-queue.ts +2 -0
  145. package/src/input/selection-modal.ts +28 -16
  146. package/src/input/session-picker-modal.ts +33 -8
  147. package/src/input/settings-modal-activation.ts +7 -2
  148. package/src/input/settings-modal-data.ts +11 -6
  149. package/src/input/settings-modal-types.ts +1 -1
  150. package/src/input/settings-modal.ts +20 -20
  151. package/src/input/submission-intent.ts +1 -1
  152. package/src/input/submission-router.ts +4 -9
  153. package/src/input/surface-modal-host.ts +110 -0
  154. package/src/input/theme-settings-actions.ts +82 -0
  155. package/src/input/usage-modal.ts +183 -0
  156. package/src/input/views.ts +97 -0
  157. package/src/main.ts +175 -165
  158. package/src/permissions/hunk-selection.ts +1 -1
  159. package/src/permissions/prompt-card.ts +511 -0
  160. package/src/permissions/prompt.ts +59 -622
  161. package/src/renderer/agents-modal.ts +310 -0
  162. package/src/renderer/autocomplete-overlay.ts +42 -220
  163. package/src/renderer/back-to-bottom.ts +80 -0
  164. package/src/renderer/block-actions-overlay.ts +30 -48
  165. package/src/renderer/bookmark-modal.ts +48 -79
  166. package/src/renderer/changes-modal.ts +325 -0
  167. package/src/renderer/code-block.ts +184 -106
  168. package/src/renderer/command-palette.ts +93 -0
  169. package/src/renderer/composer-fragments.ts +4 -4
  170. package/src/renderer/composer.ts +146 -0
  171. package/src/renderer/compositor.ts +26 -160
  172. package/src/renderer/config-modal.ts +185 -81
  173. package/src/renderer/confirm-dialog.ts +50 -0
  174. package/src/renderer/context-inspector.ts +116 -154
  175. package/src/renderer/context-status-hint.ts +4 -4
  176. package/src/renderer/conversation-layout.ts +20 -0
  177. package/src/renderer/conversation-overlays.ts +94 -84
  178. package/src/renderer/conversation-surface.ts +19 -38
  179. package/src/renderer/diff-tint.ts +98 -0
  180. package/src/renderer/file-picker-overlay.ts +63 -90
  181. package/src/renderer/footer-targets.ts +38 -0
  182. package/src/renderer/git-status.ts +3 -4
  183. package/src/renderer/header-line.ts +140 -117
  184. package/src/renderer/help-overlay.ts +133 -219
  185. package/src/renderer/history-search-overlay.ts +15 -12
  186. package/src/renderer/lane-graph/bead.ts +800 -0
  187. package/src/renderer/lane-graph/glyphs.ts +134 -0
  188. package/src/renderer/lane-graph/layout.ts +248 -0
  189. package/src/renderer/lane-graph/paint.ts +537 -0
  190. package/src/renderer/lane-graph/semantic-memo.ts +77 -0
  191. package/src/renderer/layout-engine.ts +2 -57
  192. package/src/renderer/layout.ts +7 -13
  193. package/src/renderer/markdown-inline.ts +2 -1
  194. package/src/renderer/markdown-table.ts +17 -12
  195. package/src/renderer/markdown.ts +92 -34
  196. package/src/renderer/masked-entry-modal.ts +78 -0
  197. package/src/renderer/mcp-workspace.ts +166 -203
  198. package/src/renderer/model-workspace.ts +381 -436
  199. package/src/renderer/notifications-modal.ts +116 -0
  200. package/src/renderer/onboarding/onboarding-wizard.ts +178 -588
  201. package/src/renderer/process-view.ts +192 -0
  202. package/src/renderer/profile-picker-modal.ts +58 -110
  203. package/src/renderer/search-overlay.ts +6 -3
  204. package/src/renderer/selection-modal-overlay.ts +87 -327
  205. package/src/renderer/semantic-diff.ts +2 -2
  206. package/src/renderer/session-chips.ts +102 -0
  207. package/src/renderer/session-picker-modal.ts +177 -297
  208. package/src/renderer/settings-modal-connections.ts +14 -23
  209. package/src/renderer/settings-modal-context.ts +367 -0
  210. package/src/renderer/settings-modal-helpers.ts +6 -11
  211. package/src/renderer/settings-modal.ts +322 -726
  212. package/src/renderer/shell-surface.ts +277 -175
  213. package/src/renderer/shortcuts-overlay.ts +217 -0
  214. package/src/renderer/status-line.ts +475 -0
  215. package/src/renderer/surface-compose.ts +174 -0
  216. package/src/renderer/surface-kit-extra.ts +303 -0
  217. package/src/renderer/surface-kit-list.ts +366 -0
  218. package/src/renderer/surface-kit-parts.ts +360 -0
  219. package/src/renderer/surface-kit.ts +568 -0
  220. package/src/renderer/syntax-highlighter.ts +280 -197
  221. package/src/renderer/syntax-theme.ts +51 -0
  222. package/src/renderer/system-message.ts +0 -1
  223. package/src/renderer/term-caps.ts +42 -1
  224. package/src/renderer/terminal-bg-probe.ts +116 -19
  225. package/src/renderer/terminal-palette-probe.ts +322 -0
  226. package/src/renderer/terminal-palette-reader.ts +183 -0
  227. package/src/renderer/terminal-palette.ts +58 -0
  228. package/src/renderer/theme-mode-config.ts +16 -1
  229. package/src/renderer/theme.ts +234 -207
  230. package/src/renderer/thinking.ts +0 -1
  231. package/src/renderer/throbber.ts +188 -0
  232. package/src/renderer/toast-center.ts +119 -0
  233. package/src/renderer/ui-factory.ts +39 -602
  234. package/src/renderer/ui-primitives.ts +8 -25
  235. package/src/renderer/usage-modal.ts +353 -0
  236. package/src/renderer/user-message.ts +58 -0
  237. package/src/renderer/voice-capture-chip.ts +53 -0
  238. package/src/runtime/bootstrap-command-context.ts +0 -5
  239. package/src/runtime/bootstrap-command-parts.ts +38 -89
  240. package/src/runtime/bootstrap-core.ts +13 -15
  241. package/src/runtime/bootstrap-hook-bridge.ts +12 -21
  242. package/src/runtime/bootstrap-notifier-sync.ts +17 -1
  243. package/src/runtime/bootstrap-shell.ts +16 -50
  244. package/src/runtime/bootstrap.ts +14 -14
  245. package/src/runtime/client/fleet-union.ts +5 -5
  246. package/src/runtime/client/hosted-exit.ts +2 -2
  247. package/src/runtime/client/hosted-sessions.ts +1 -1
  248. package/src/runtime/client/spine-adoption.ts +1 -1
  249. package/src/runtime/context-accounting-source.ts +5 -4
  250. package/src/runtime/index.ts +1 -0
  251. package/src/runtime/notification-dispatch.ts +102 -29
  252. package/src/runtime/recovery-offer-wiring.ts +4 -1
  253. package/src/runtime/recovery-prompt.ts +31 -15
  254. package/src/runtime/runtime-services-types.ts +10 -6
  255. package/src/runtime/services.ts +17 -12
  256. package/src/runtime/session-continuity-hints.ts +2 -5
  257. package/src/runtime/session-inbound-inputs.ts +1 -1
  258. package/src/runtime/session-resume-liveness-confirm.ts +14 -2
  259. package/src/runtime/startup-typeahead-gate.ts +103 -0
  260. package/src/runtime/store/domains/domain-read-matrix.ts +0 -1
  261. package/src/runtime/store/domains/index.ts +0 -8
  262. package/src/runtime/store/selectors/index.ts +0 -28
  263. package/src/runtime/store/state.ts +0 -8
  264. package/src/runtime/ui-services.ts +4 -6
  265. package/src/runtime/usage-tracker.ts +348 -0
  266. package/src/runtime/wrfc-persistence.ts +4 -4
  267. package/src/shell/blocking-input.ts +92 -2
  268. package/src/shell/recovery-input-helpers.ts +1 -1
  269. package/src/shell/session-views.ts +539 -0
  270. package/src/shell/status-report.ts +86 -0
  271. package/src/shell/transcript-scroll.ts +68 -0
  272. package/src/shell/ui-openers.ts +84 -172
  273. package/src/shell/view-openers.ts +205 -0
  274. package/src/tools/wrfc-agent-guard.ts +22 -2
  275. package/src/utils/format-duration.ts +4 -8
  276. package/src/utils/splash-lines.ts +9 -1
  277. package/src/utils/terminal-width.ts +56 -0
  278. package/src/verification/live-verifier.ts +0 -10
  279. package/src/version.ts +1 -1
  280. package/src/{panels → views}/agent-inspector-shared.ts +2 -2
  281. package/src/{panels → views}/builtin-modals.ts +22 -21
  282. package/src/views/builtin-views.ts +135 -0
  283. package/src/{panels → views}/confirm-state.ts +9 -9
  284. package/src/{panels → views}/diff-review-model.ts +10 -3
  285. package/src/{panels → views}/eval-registry.ts +1 -1
  286. package/src/{panels → views}/fleet-acts.ts +49 -85
  287. package/src/{panels/fleet-panel-format.ts → views/fleet-format.ts} +40 -40
  288. package/src/{panels → views}/fleet-gateway.ts +5 -5
  289. package/src/{panels → views}/fleet-observed-render.ts +16 -16
  290. package/src/{panels → views}/fleet-read-model.ts +9 -9
  291. package/src/{panels/fleet-tabs.ts → views/fleet-session-tabs.ts} +13 -13
  292. package/src/{panels → views}/fleet-spawn.ts +33 -49
  293. package/src/{panels → views}/fleet-steer.ts +12 -12
  294. package/src/{panels → views}/fleet-stop.ts +4 -4
  295. package/src/{panels → views}/fleet-transcript.ts +26 -27
  296. package/src/{panels/fleet-panel-worktree-detail.ts → views/fleet-worktree-detail.ts} +7 -7
  297. package/src/{panels → views}/hosted-session-feed.ts +6 -6
  298. package/src/views/modal-surface-registry.ts +41 -0
  299. package/src/{panels → views}/modals/devices-modal.ts +2 -2
  300. package/src/{panels → views}/modals/hooks-modal.ts +13 -13
  301. package/src/{panels → views}/modals/keybindings-modal.ts +19 -27
  302. package/src/{panels → views}/modals/knowledge-modal.ts +6 -5
  303. package/src/{panels → views}/modals/local-auth-modal.ts +22 -21
  304. package/src/{panels → views}/modals/marketplace-modal.ts +11 -11
  305. package/src/{panels → views}/modals/memory-modal.ts +8 -8
  306. package/src/{panels → views}/modals/modal-surface-helpers.ts +15 -5
  307. package/src/{panels → views}/modals/pairing-modal.ts +9 -9
  308. package/src/{panels → views}/modals/planning-modal.ts +15 -20
  309. package/src/{panels → views}/modals/plugins-modal.ts +6 -6
  310. package/src/{panels → views}/modals/policy-modal.ts +13 -5
  311. package/src/{panels → views}/modals/provider-health-modal.ts +4 -4
  312. package/src/{panels → views}/modals/remote-modal.ts +3 -3
  313. package/src/{panels → views}/modals/sandbox-modal.ts +4 -4
  314. package/src/{panels → views}/modals/security-modal.ts +22 -16
  315. package/src/{panels → views}/modals/services-modal.ts +3 -3
  316. package/src/{panels → views}/modals/settings-sync-modal.ts +4 -4
  317. package/src/{panels → views}/modals/skills-modal.ts +9 -9
  318. package/src/{panels → views}/modals/subscription-modal.ts +3 -3
  319. package/src/{panels → views}/modals/work-plan-modal.ts +10 -13
  320. package/src/views/notifications-feed.ts +314 -0
  321. package/src/{panels → views}/polish-core.ts +38 -36
  322. package/src/{panels → views}/polish-tables.ts +35 -26
  323. package/src/{panels → views}/polish.ts +101 -95
  324. package/src/{panels → views}/project-planning-answer-actions.ts +3 -3
  325. package/src/{panels → views}/provider-health-routes.ts +14 -14
  326. package/src/{panels → views}/search-focus.ts +8 -8
  327. package/src/{panels → views}/session-maintenance.ts +11 -11
  328. package/src/views/skills-discovery.ts +159 -0
  329. package/src/views/view-deps.ts +80 -0
  330. package/src/views/view-panel-adapter.ts +53 -0
  331. package/src/{panels → views}/workstream-graph-render.ts +1 -1
  332. package/src/core/conversation-fold.ts +0 -101
  333. package/src/core/conversation-turn-structure.ts +0 -464
  334. package/src/core/conversation-user-receipts.ts +0 -42
  335. package/src/input/commands/operator-panel-runtime.ts +0 -186
  336. package/src/input/panel-integration-actions.ts +0 -33
  337. package/src/input/panel-mouse-geometry.ts +0 -97
  338. package/src/input/panel-paste-flood-guard.ts +0 -86
  339. package/src/panels/base-panel.ts +0 -301
  340. package/src/panels/builtin/agent.ts +0 -27
  341. package/src/panels/builtin/development.ts +0 -92
  342. package/src/panels/builtin/knowledge.ts +0 -12
  343. package/src/panels/builtin/operations.ts +0 -177
  344. package/src/panels/builtin/session.ts +0 -81
  345. package/src/panels/builtin/shared.ts +0 -357
  346. package/src/panels/builtin-panels.ts +0 -28
  347. package/src/panels/cost-tracker-panel.ts +0 -746
  348. package/src/panels/diff-panel.ts +0 -797
  349. package/src/panels/diff-review-panel.ts +0 -395
  350. package/src/panels/expandable-list-panel.ts +0 -189
  351. package/src/panels/fleet-deep-link.ts +0 -31
  352. package/src/panels/fleet-panel.ts +0 -799
  353. package/src/panels/git-panel.ts +0 -800
  354. package/src/panels/hosted-session-panel.ts +0 -221
  355. package/src/panels/index.ts +0 -21
  356. package/src/panels/local-auth-panel.ts +0 -478
  357. package/src/panels/notifications-feed.ts +0 -127
  358. package/src/panels/notifications-panel.ts +0 -160
  359. package/src/panels/panel-confirm-overlay.ts +0 -72
  360. package/src/panels/panel-manager.ts +0 -791
  361. package/src/panels/plugins-panel.ts +0 -371
  362. package/src/panels/scrollable-list-panel.ts +0 -498
  363. package/src/panels/skills-panel.ts +0 -454
  364. package/src/panels/token-budget-panel.ts +0 -688
  365. package/src/panels/types.ts +0 -191
  366. package/src/panels/wrfc-panel-format.ts +0 -133
  367. package/src/renderer/diff-view.ts +0 -134
  368. package/src/renderer/fleet-tab-strip.ts +0 -56
  369. package/src/renderer/footer-tips.ts +0 -53
  370. package/src/renderer/fullscreen-primitives.ts +0 -146
  371. package/src/renderer/fullscreen-workspace.ts +0 -194
  372. package/src/renderer/hint-grammar.ts +0 -52
  373. package/src/renderer/modal-factory.ts +0 -480
  374. package/src/renderer/overlay-box.ts +0 -154
  375. package/src/renderer/overlay-viewport.ts +0 -104
  376. package/src/renderer/panel-composite.ts +0 -145
  377. package/src/renderer/panel-workspace-bar.ts +0 -54
  378. package/src/renderer/process-indicator.ts +0 -163
  379. package/src/renderer/tab-strip.ts +0 -222
  380. package/src/renderer/text-layout.ts +0 -31
  381. package/src/renderer/tool-call.ts +0 -276
  382. package/src/renderer/tool-result-expanded-lines.ts +0 -48
  383. package/src/renderer/tool-result-summary.ts +0 -219
  384. package/src/runtime/diagnostics/panels/index.ts +0 -21
  385. package/src/runtime/diagnostics/panels/ops.ts +0 -156
  386. package/src/runtime/perf/panel-contracts.ts +0 -32
  387. package/src/runtime/store/domains/panels.ts +0 -117
  388. package/src/verification/verification-ledger.ts +0 -707
  389. /package/src/{panels → views}/memory-consolidation-gateway.ts +0 -0
  390. /package/src/{panels → views}/modals/modal-theme.ts +0 -0
  391. /package/src/{panels → views}/provider-health-domains.ts +0 -0
@@ -1,707 +0,0 @@
1
- import { readFileSync, readdirSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import { CONFIG_SCHEMA } from '@pellux/goodvibes-sdk/platform/config';
4
- import { FEATURE_SETTINGS } from '@pellux/goodvibes-sdk/platform/runtime/state';
5
- import { featureEnablementWrite, GOODVIBES_CLI_CATALOG } from '@pellux/goodvibes-terminal-shell';
6
- import { CommandRegistry } from '../input/command-registry.ts';
7
- import { registerBuiltinCommands } from '../input/commands.ts';
8
-
9
- export interface VerificationLedgerArea {
10
- readonly area: string;
11
- readonly total: number;
12
- readonly localSignalVerified: number;
13
- readonly localBehaviorVerified: number;
14
- readonly externalOutcomeRequired: number;
15
- readonly notes: string;
16
- }
17
-
18
- export interface VerificationLedger {
19
- readonly generatedAt: string;
20
- readonly areas: readonly VerificationLedgerArea[];
21
- readonly totals: {
22
- readonly total: number;
23
- readonly localSignalVerified: number;
24
- readonly localBehaviorVerified: number;
25
- readonly externalOutcomeRequired: number;
26
- readonly localSignalPercent: number;
27
- readonly localBehaviorPercent: number;
28
- };
29
- }
30
-
31
- /**
32
- * Baseline count of `Settings schema and persistence` items with real local
33
- * behavior verification, as measured when this ledger was first authored. New
34
- * schema keys added since then are accounted for explicitly (see
35
- * FEATURE_KNOB_LOCAL_SETTINGS) rather than folded into this number, so the
36
- * baseline stays an auditable fixed point.
37
- */
38
- const SETTINGS_BEHAVIOR_BASELINE = 184;
39
-
40
- /**
41
- * Config keys promoted into CONFIG_SCHEMA for the flag-gated feature knobs
42
- * (SDK commit f5c4af31, "config: add schema keys for flag-gated feature
43
- * knobs"). Adding these 28 keys raised the settings inventory `total` without a
44
- * matching rise in behavior-verified coverage, which dropped
45
- * `localBehaviorPercent` below its floor. Each key is a local, non-external
46
- * setting whose full persistence behavior, schema default, set → write →
47
- * reload round-trip, and reset-to-default, is exercised by
48
- * `src/test/verification/feature-knob-settings-persistence.test.ts`. They are
49
- * therefore genuinely behavior-verified locally and counted as such here.
50
- */
51
- /**
52
- * The daemon's own mailbox and calendar keys (`surfaces.email.*`,
53
- * `surfaces.calendar.*`), promoted into CONFIG_SCHEMA so the settings modal,
54
- * which renders from that schema, can actually show them. Before, the
55
- * daemon's handlers named these keys in their own error messages
56
- * ("Set surfaces.calendar.caldavUrl and surfaces.calendar.caldavUser") while
57
- * the UI that told an operator to set them could not display one of them.
58
- *
59
- * Declaring 25 keys raised the settings inventory `total` with no matching
60
- * behavior coverage, which dropped `localBehaviorPercent` below its floor,
61
- * the same arrival shape as the two lists above.
62
- *
63
- * THIS CONSTANT IS NOT A DIAL. Every key below is counted because
64
- * `src/test/verification/daemon-mailbox-settings-persistence.test.ts` runs the
65
- * same four-part persistence contract the other counted sets are counted for:
66
- * schema default exposure, `set()` through the key's own validator to disk,
67
- * reload into a fresh ConfigManager with read-back equality, and
68
- * reset-to-default that also survives reload. That test also asserts this list
69
- * is exactly the `surfaces.email.*` + `surfaces.calendar.*` schema key set and
70
- * overlaps neither other counted set, so nothing is double-counted and nothing
71
- * drifts in uncounted.
72
- *
73
- * PER-KEY EVIDENCE. All 42 are read by a LIVE consumer, which is why they were
74
- * declared at all: the SDK's mail and calendar gateway compositions
75
- * (platform/email/surface-config.ts and platform/calendar/caldav-gateway-config.ts)
76
- * resolve every one of them when the daemon serves `email.*` and `calendar.*`,
77
- * and the `surfaces.email.inbound.*` block is read by the daemon's inbound mail
78
- * reader, the poller/IDLE path that makes incoming mail visible at all.
79
- * The five password keys (email.password, email.imapPassword,
80
- * email.imap.password, email.smtp.password, calendar.caldavPassword)
81
- * additionally resolve through the daemon secret tier rather than from config,
82
- * and carry no secret value in config themselves. That is now enforced on the
83
- * write side too: all five are in `config/secret-config.ts`'s
84
- * SECRET_CONFIG_KEYS, so the settings modal and `/config set` route an entered
85
- * value into the secret store and leave only a `goodvibes://` reference in
86
- * config, rather than writing the password itself into a settings file.
87
- */
88
- export const DAEMON_MAILBOX_LOCAL_SETTINGS = [
89
- 'surfaces.email.host',
90
- 'surfaces.email.user',
91
- 'surfaces.email.username',
92
- 'surfaces.email.from',
93
- 'surfaces.email.password',
94
- 'surfaces.email.imapHost',
95
- 'surfaces.email.imapPort',
96
- 'surfaces.email.imapUser',
97
- 'surfaces.email.imapPassword',
98
- 'surfaces.email.imap.host',
99
- 'surfaces.email.imap.port',
100
- 'surfaces.email.imap.user',
101
- 'surfaces.email.imap.password',
102
- 'surfaces.email.imap.secure',
103
- 'surfaces.email.imap.mailbox',
104
- 'surfaces.email.imap.draftsMailbox',
105
- 'surfaces.email.smtp.host',
106
- 'surfaces.email.smtp.port',
107
- 'surfaces.email.smtp.password',
108
- 'surfaces.email.smtp.secure',
109
- // Inbound mail, the poller/IDLE reader the daemon runs to actually READ mail,
110
- // which arrived with the platform runtime. These are counted for exactly the
111
- // reason the keys above are: the same four-part persistence contract runs over
112
- // every one of them in
113
- // src/test/verification/daemon-mailbox-settings-persistence.test.ts, and the
114
- // list is asserted there to be the complete surfaces.email.*/surfaces.calendar.*
115
- // schema set. Arriving uncounted is what dropped localBehaviorPercent through
116
- // its floor when the schema grew.
117
- 'surfaces.email.inbound.enabled',
118
- 'surfaces.email.inbound.accounts',
119
- 'surfaces.email.inbound.source',
120
- 'surfaces.email.inbound.gmailPollSecondsExpecting',
121
- 'surfaces.email.inbound.gmailPollSecondsIdle',
122
- 'surfaces.email.inbound.mode',
123
- 'surfaces.email.inbound.pollIntervalSeconds',
124
- 'surfaces.email.inbound.idleReissueMinutes',
125
- 'surfaces.email.inbound.reconnect.maxBackoffSeconds',
126
- 'surfaces.email.inbound.notice.route',
127
- 'surfaces.email.inbound.notice.mode',
128
- 'surfaces.email.inbound.expectationWindowMinutes',
129
- 'surfaces.email.inbound.dedupTtlMinutes',
130
- 'surfaces.email.inbound.retentionDays',
131
- 'surfaces.email.inbound.maxRecords',
132
- 'surfaces.email.inbound.capabilityRecheckMinutes',
133
- 'surfaces.email.inbound.onInsufficientCapability',
134
- 'surfaces.calendar.caldavUrl',
135
- 'surfaces.calendar.caldavUser',
136
- 'surfaces.calendar.caldavPassword',
137
- 'surfaces.calendar.defaultCalendarId',
138
- 'surfaces.calendar.calendars',
139
- ] as const;
140
-
141
- export const FEATURE_KNOB_LOCAL_SETTINGS = [
142
- 'provider.optimizerMode',
143
- 'provider.optimizerPinnedModel',
144
- 'permissions.divergenceThreshold',
145
- 'permissions.maxDivergenceRecords',
146
- 'tools.overflowSpillBackend',
147
- 'notifications.burstWindowMs',
148
- 'notifications.burstThreshold',
149
- 'notifications.burstCooldownMs',
150
- 'fetch.sanitizeMode',
151
- 'fetch.trustedHosts',
152
- 'fetch.blockedHosts',
153
- 'security.tokenAudit.rotationCadenceDays',
154
- 'security.tokenAudit.rotationWarningDays',
155
- 'security.tokenAudit.managed',
156
- 'integrations.delivery.maxRetries',
157
- 'integrations.delivery.initialDelayMs',
158
- 'integrations.delivery.maxDelayMs',
159
- 'integrations.delivery.maxDlqSize',
160
- 'integrations.delivery.sloEnforced',
161
- 'policy.bundleSource',
162
- 'policy.bundlePath',
163
- 'agents.passiveInjection.budgetTokens',
164
- 'agents.passiveInjection.relevanceFloor',
165
- 'agents.passiveInjection.codeLimit',
166
- 'agents.contextCompactThreshold',
167
- 'runtime.toolBudget.maxMs',
168
- 'runtime.toolBudget.maxTokens',
169
- 'runtime.toolBudget.maxCostUsd',
170
- ] as const;
171
-
172
- /**
173
- * Config keys added by the paired-device and trigger-family domains in SDK
174
- * 1.14.0. Like FEATURE_KNOB_LOCAL_SETTINGS above, these arrived as new
175
- * CONFIG_SCHEMA entries that raised the settings inventory `total` with no
176
- * matching behavior coverage, dropping `localBehaviorPercent` below its floor.
177
- *
178
- * THIS CONSTANT IS NOT A DIAL. Each key below is counted because a test that
179
- * exercises it was actually written:
180
- * `src/test/verification/device-and-trigger-settings-persistence.test.ts` runs,
181
- * for every key in this list, the same four-part persistence contract the
182
- * feature-knob keys are counted for, schema default exposure, `set()` through
183
- * the key's own validator to disk, reload into a fresh ConfigManager with
184
- * read-back equality, and reset-to-default that also survives reload. That test
185
- * additionally asserts this list is exactly the non-enablement key set of both
186
- * domains and overlaps neither of the other counted sets, so nothing here is
187
- * double-counted and nothing drifts in uncounted.
188
- *
189
- * PER-KEY EVIDENCE, what is verified, and how live the key is TODAY.
190
- * "persistence" below means the four-part contract above; the second column
191
- * records whether anything in this tree (TUI or the pinned SDK) reads the key,
192
- * audited by tracing each key to its consumers.
193
- *
194
- * watchers.triggers.backoffLadderMs persistence · live (trigger supervisor retry ladder)
195
- * watchers.triggers.breakerStrikes persistence · live (strike breaker)
196
- * watchers.triggers.defaultCheckIntervalMs persistence · live (condition-check scheduler)
197
- * watchers.triggers.probeTimeoutMs persistence · live (probe execution)
198
- * watchers.triggers.maxConcurrentChecks persistence · live (check concurrency cap)
199
- * watchers.triggers.observationRingSize persistence · live (observation ring)
200
- * watchers.triggers.runHistoryLimit persistence · live (run history retention)
201
- * watchers.triggers.runHistoryTtlHours persistence · live (run history sweep)
202
- * watchers.triggers.eventLogLimit persistence · live (event log retention)
203
- * watchers.triggers.eventLogTtlHours persistence · live (event log sweep)
204
- * watchers.triggers.sweepIntervalMs persistence · live (housekeeping cadence)
205
- * watchers.triggers.supervisionTickMs persistence · live (supervision loop tick)
206
- * watchers.triggers.streamQueueLimit persistence · live (stream watcher queue)
207
- * watchers.triggers.streamBatchLines persistence · live (stream batching)
208
- * watchers.triggers.streamBatchIntervalMs persistence · live (stream batching)
209
- * watchers.triggers.onExitMaxDurationMs persistence · live (on-exit trigger duration cap)
210
- * watchers.triggers.onExitStdin persistence · live (on-exit stdin posture)
211
- * watchers.triggers.outputTailBytes persistence · live (captured output tail)
212
- * device.capabilities.allowAlwaysOffer persistence · behavior (durable-grant offer by sensitivity)
213
- * device.capabilities.requestTimeoutSeconds persistence · behavior (dispatch, wire payload and prompt deadline)
214
- * device.location.precision persistence · behavior (precise fix refused / never granted)
215
- * device.clipboard.readMode persistence · behavior (clipboard read refused / never granted)
216
- * device.capture.retentionHours persistence · behavior (capture TTL, swept off disk at expiry)
217
- * device.capture.maxArtifacts persistence · behavior (capture count cap at the sweep)
218
- * device.capture.sweepIntervalMinutes persistence · behavior (period of the sweep that reaps)
219
- * device.grants.expiryDays persistence · behavior (grant TTL, then asks again)
220
- * device.grants.maxPerNode persistence · behavior (per-node grant cap at the sweep)
221
- * device.grants.auditRetentionDays persistence · behavior (grant ledger retention)
222
- * device.nodes.maxPaired persistence · live (enforced at the pairing path)
223
- *
224
- * On `device.nodes.maxPaired`: the SDK enforces it where a device pairs,
225
- * PairingTokenManager.mint refuses a NEW node at the cap with
226
- * PairingLimitReachedError (code DEVICE_NODES_MAX_PAIRED, carrying the setting
227
- * name, the cap and the live count), mapped to HTTP 409 by the pairing and
228
- * pairing-handoff routes. An already-paired node supersedes its own record
229
- * instead of being refused, migration mints off the legacy shared token are
230
- * deliberately exempt, lowering the cap unpairs nobody, and a non-positive or
231
- * non-finite value reads as no cap so a broken setting cannot lock the owner
232
- * out. The cap is read per mint, so a change applies without a restart. What is
233
- * counted HERE is still only the persistence contract this repo's test
234
- * exercises, the enforcement itself is SDK-side and SDK-tested, and is recorded
235
- * in this column so the "how live is it" audit stays accurate, not to claim
236
- * coverage this repo did not write.
237
- *
238
- * On the other ten `device.*` rows: they are live now. This app composes the
239
- * platform's device posture runtime (src/runtime/device-posture-composition.ts)
240
- * on the same distributed runtime phones pair onto and the same approval broker
241
- * every other confirmation rides, registers the `phone` tool on it, and binds the
242
- * devices.* verbs to it, so each of these keys is read, per request and per
243
- * sweep, by the DeviceCapabilityService / DeviceGrantStore /
244
- * DeviceCaptureArtifactStore / DeviceHousekeeper that serve them. They were dark
245
- * before that: the policy struct carried matching defaults and named the keys in
246
- * its refusal messages, but nothing mapped configuration into it in either tree.
247
- * The mapping now lives in the SDK, so every daemon host honours it rather than
248
- * only whichever consumer had written its own.
249
- *
250
- * The second column above is upgraded to "behavior" on the strength of
251
- * `src/test/verification/device-posture-behavior.test.ts`, which drives THIS
252
- * app's composition with a real ConfigManager over a temp home and the platform's
253
- * real stores, stubs only the peer transport and the approval bridge, and asserts
254
- * per key at two values that the observable outcome differs, refusal code, how
255
- * authority was established, what reached the transport, what the prompt was
256
- * given, and what survives on disk after a sweep. It also invokes the `phone`
257
- * tool and the devices.* verbs off the composed runtime graph, because a mapping
258
- * nothing composes is the same defect in a different place.
259
- *
260
- * STILL NOT COUNTED, FOR A DIFFERENT REASON NOW: the 24 non-enablement
261
- * `voice.wake.*` keys from the same release. When this list was written they were
262
- * excluded because nothing captured audio at all. That is no longer true, this
263
- * terminal opens a recorder subprocess (src/audio/capture.ts), runs the SDK
264
- * detector over it through onnxruntime-web (src/audio/wake-inference.ts), and
265
- * hands both a confirmed wake's utterance and a push-to-talk recording to the
266
- * daemon's `voice.stt` verb. Every one of those rows is read by
267
- * resolveWakeRuntimeSettings and reaches this surface's runtime.
268
- *
269
- * They stay out of the NUMERATOR here because this constant counts exactly one
270
- * thing, keys whose four-part PERSISTENCE contract is exercised by
271
- * device-and-trigger-settings-persistence.test.ts, and that test does not cover
272
- * them. The behaviour they now drive is covered instead by the capture and wake
273
- * tests under src/test/audio/, which assert the frame path, the detection
274
- * chain, the disabled-means-no-capture rule, the supervisor's restart and latch,
275
- * and the recorder argv. Counting them in both places would double-count; adding
276
- * them here without writing their persistence round-trip would overclaim. So the
277
- * number this list raises coverage by is unchanged, and the reason it excludes
278
- * them is recorded above rather than left reading as "the feature does nothing".
279
- *
280
- * Every wake row is now in force on this surface, with one condition stated at
281
- * every surfacing: `voice.wake.vadThreshold` above 0 needs the speech gate's own
282
- * pinned artifact provisioned (`/voice wake setup` fetches it with the models),
283
- * and until it is, startup BLOCKS with that reason rather than scoring frames
284
- * ungated behind a row that says they are screened. `voice.wake.noiseSuppression:
285
- * speex` runs here: the filter is a WebAssembly module the SDK carries, applied
286
- * by the wrapper the listener and the push-to-talk session put around this
287
- * surface's capture opener.
288
- */
289
- export const DEVICE_AND_TRIGGER_LOCAL_SETTINGS = [
290
- 'watchers.triggers.backoffLadderMs',
291
- 'watchers.triggers.breakerStrikes',
292
- 'watchers.triggers.defaultCheckIntervalMs',
293
- 'watchers.triggers.probeTimeoutMs',
294
- 'watchers.triggers.maxConcurrentChecks',
295
- 'watchers.triggers.observationRingSize',
296
- 'watchers.triggers.runHistoryLimit',
297
- 'watchers.triggers.runHistoryTtlHours',
298
- 'watchers.triggers.eventLogLimit',
299
- 'watchers.triggers.eventLogTtlHours',
300
- 'watchers.triggers.sweepIntervalMs',
301
- 'watchers.triggers.supervisionTickMs',
302
- 'watchers.triggers.streamQueueLimit',
303
- 'watchers.triggers.streamBatchLines',
304
- 'watchers.triggers.streamBatchIntervalMs',
305
- 'watchers.triggers.onExitMaxDurationMs',
306
- 'watchers.triggers.onExitStdin',
307
- 'watchers.triggers.outputTailBytes',
308
- 'device.capabilities.allowAlwaysOffer',
309
- 'device.capabilities.requestTimeoutSeconds',
310
- 'device.location.precision',
311
- 'device.clipboard.readMode',
312
- 'device.capture.retentionHours',
313
- 'device.capture.maxArtifacts',
314
- 'device.capture.sweepIntervalMinutes',
315
- 'device.grants.expiryDays',
316
- 'device.grants.maxPerNode',
317
- 'device.grants.auditRetentionDays',
318
- 'device.nodes.maxPaired',
319
- ] as const;
320
-
321
- /**
322
- * Every feature's enablement settings key whose on/off writes round-trip
323
- * through a REAL on-disk ConfigManager in
324
- * `src/test/verification/../input/settings-modal-flag-persistence.test.ts`
325
- * ("every feature with an off position round-trips both directions"). These
326
- * are first-class schema keys under the dissolved feature model, so they are
327
- * genuinely behavior-verified locally. Keys already counted in the
328
- * feature-knob list are excluded to keep the sum honest.
329
- */
330
- const ENABLEMENT_KEYS_BEHAVIOR_VERIFIED = new Set(
331
- FEATURE_SETTINGS
332
- .filter((feature) => featureEnablementWrite(feature.id, true) !== null && featureEnablementWrite(feature.id, false) !== null)
333
- .map((feature) => feature.enablement.key)
334
- .filter((key) => !(FEATURE_KNOB_LOCAL_SETTINGS as readonly string[]).includes(key)),
335
- ).size;
336
-
337
- /** Settings with real local behavior verification: the authored baseline plus the persistence-tested feature-knob, device/trigger, and enablement keys. */
338
- /**
339
- * Config keys added by the LAN group-key layer: the automatic group-key
340
- * rotation interval, the dual-generation acceptance window around a rotation,
341
- * the discovery beacon interval, and the roster gossip interval.
342
- *
343
- * THIS CONSTANT IS NOT A DIAL, for the same reason as the two above. Each key
344
- * is counted because a test that exercises it was actually written:
345
- * `src/test/verification/cluster-group-settings-persistence.test.ts` runs the
346
- * same four-part persistence contract, schema default exposure, `set()`
347
- * through the key's own validator to disk, reload into a fresh ConfigManager
348
- * with read-back equality, and reset-to-default that survives reload.
349
- *
350
- * PER-KEY EVIDENCE. All four have a LIVE consumer in this build, which is more
351
- * than several of the keys counted above can claim:
352
- * cluster.keyRotationHours , read by resolveClusterGroupSettings and
353
- * compared against the current key's age in
354
- * the group runtime's rotation check.
355
- * cluster.keyRotationGraceMinutes, sets how long the previous generation
356
- * stays accepted after a scheduled
357
- * rotation; drives the keyring's accepted
358
- * generation set.
359
- * cluster.beaconSeconds , the discovery beacon timer interval, and
360
- * the basis of the "recently heard from"
361
- * window that decides which member mints a
362
- * rotation.
363
- * cluster.rosterGossipSeconds , how often the member list is shared.
364
- *
365
- * `cluster.enabled` is NOT here: it is a feature enablement key and the ledger
366
- * counts those in its own set.
367
- */
368
- export const CLUSTER_GROUP_LOCAL_SETTINGS = [
369
- 'cluster.keyRotationHours',
370
- 'cluster.keyRotationGraceMinutes',
371
- 'cluster.beaconSeconds',
372
- 'cluster.rosterGossipSeconds',
373
- ] as const;
374
-
375
- /**
376
- * Config keys for the daemon's payment capability: the master switch, which
377
- * card to use by default, the settlement currency, CVV handling, the six
378
- * budget knobs, the shipping-tier preference, the fourteen billing/shipping
379
- * address sub-fields, the two approval/veto windows, and the notify-channel
380
- * list. Card MATERIAL (number, expiry, CVV, cardholder name) is intentionally
381
- * NOT here, see the SDK's schema-domain-payments.ts header and this repo's
382
- * own input/payments-config.ts: that material lives write-only in the daemon
383
- * secret store, never in CONFIG_SCHEMA, so there is nothing for a persistence
384
- * contract to count.
385
- *
386
- * THIS CONSTANT IS NOT A DIAL, for the same reason as the sets above. Every
387
- * key below is counted because
388
- * `src/test/verification/payments-settings-persistence.test.ts` runs the same
389
- * four-part persistence contract the other counted sets are counted for:
390
- * schema default exposure, `set()` through the key's own validator to disk,
391
- * reload into a fresh ConfigManager with read-back equality, and
392
- * reset-to-default that also survives reload. That test also asserts this
393
- * list is exactly the CONFIG_SCHEMA's `payments.*` key set, so a future SDK
394
- * addition under this domain is caught (fails the inventory-integrity test)
395
- * rather than silently uncounted.
396
- *
397
- * PER-KEY EVIDENCE. All 28 are read by the daemon's own payment capability
398
- * (platform/payments, platform/control-plane/routes/payments.ts): the budget
399
- * keys size the daily/overage/tolerance pools, the window keys size the
400
- * veto/approval timers, cvvHandling and shipping.preferredTier select the
401
- * enum behaviors `platform/payments` documents, and the address sub-fields
402
- * are read directly by the daemon's shipping-address-required refusal and the
403
- * card-issuer address-verification path. `enabled` and `defaultCardId` gate
404
- * and select, respectively, whether/which card a purchase uses.
405
- */
406
- export const PAYMENTS_LOCAL_SETTINGS = [
407
- 'payments.enabled',
408
- 'payments.defaultCardId',
409
- 'payments.currency',
410
- 'payments.cvvHandling',
411
- 'payments.budget.dailyItem',
412
- 'payments.budget.dailyOverage',
413
- 'payments.budget.perPurchaseCeilingEnabled',
414
- 'payments.budget.perPurchaseCeiling',
415
- 'payments.budget.overageToleranceEnabled',
416
- 'payments.budget.overageToleranceDailyAllowance',
417
- 'payments.shipping.preferredTier',
418
- 'payments.billingAddress.name',
419
- 'payments.billingAddress.line1',
420
- 'payments.billingAddress.line2',
421
- 'payments.billingAddress.city',
422
- 'payments.billingAddress.region',
423
- 'payments.billingAddress.postalCode',
424
- 'payments.billingAddress.country',
425
- 'payments.shippingAddress.name',
426
- 'payments.shippingAddress.line1',
427
- 'payments.shippingAddress.line2',
428
- 'payments.shippingAddress.city',
429
- 'payments.shippingAddress.region',
430
- 'payments.shippingAddress.postalCode',
431
- 'payments.shippingAddress.country',
432
- 'payments.windows.vetoMinutes',
433
- 'payments.windows.approvalMinutes',
434
- 'payments.majorRetailersAdditional',
435
- 'payments.majorRetailersExcluded',
436
- 'payments.ebayMinSellerFeedbackCount',
437
- 'payments.ebayMinSellerPositivePercent',
438
- 'payments.notifyChannels',
439
- ] as const;
440
-
441
- /**
442
- * Connector settings, the daemon's Google-backed mail/calendar keys plus the
443
- * connected-host dial switch and the hosted-turn routing switch, declared as
444
- * described schema rows by platform runtime 2.0.8 (before that the connector
445
- * keys were cast onto the live config invisibly and the settings surface
446
- * answered "Unknown setting" for keys the daemon really reads). Counted for
447
- * exactly the reason DAEMON_MAILBOX_LOCAL_SETTINGS is: the same four-part
448
- * persistence contract runs over every one of them in
449
- * src/test/verification/connector-settings-persistence.test.ts, and that test
450
- * asserts this list is the complete schema set for the email, calendar and
451
- * google prefixes
452
- * plus the two switches. Arriving uncounted is what dropped
453
- * localBehaviorPercent through its floor when the schema grew. The three
454
- * secret-valued keys hold goodvibes://secrets/ references, never values,
455
- * same note as the mailbox passwords above.
456
- */
457
- export const CONNECTOR_LOCAL_SETTINGS = [
458
- 'email.enabled',
459
- 'email.imapHost',
460
- 'email.imapPort',
461
- 'email.imapSecurity',
462
- 'email.smtpHost',
463
- 'email.smtpPort',
464
- 'email.smtpSecurity',
465
- 'email.username',
466
- 'email.passwordRef',
467
- 'email.smtpPasswordRef',
468
- 'email.fromAddress',
469
- 'email.mailbox',
470
- 'email.draftsMailbox',
471
- 'calendar.google.clientId',
472
- 'calendar.google.clientSecretRef',
473
- 'calendar.google.icsUrl',
474
- 'calendar.microsoft.clientId',
475
- 'calendar.microsoft.clientSecretRef',
476
- 'google.oauth.projectId',
477
- 'google.oauth.publishingStatus',
478
- 'google.oauth.refreshToken',
479
- 'google.credentials.migratedFrom',
480
- 'daemon.connectedHost.enabled',
481
- 'hostedSessions.routeConversationTurns',
482
- ] as const;
483
-
484
- const SETTINGS_BEHAVIOR_VERIFIED = SETTINGS_BEHAVIOR_BASELINE
485
- + FEATURE_KNOB_LOCAL_SETTINGS.length
486
- + DEVICE_AND_TRIGGER_LOCAL_SETTINGS.length
487
- + CLUSTER_GROUP_LOCAL_SETTINGS.length
488
- + DAEMON_MAILBOX_LOCAL_SETTINGS.length
489
- + PAYMENTS_LOCAL_SETTINGS.length
490
- + CONNECTOR_LOCAL_SETTINGS.length
491
- + ENABLEMENT_KEYS_BEHAVIOR_VERIFIED;
492
-
493
- const EXTERNAL_SLASH_COMMANDS = new Set([
494
- 'auth',
495
- 'bridge',
496
- 'cloudflare',
497
- 'health',
498
- 'listener',
499
- 'login',
500
- 'logout',
501
- 'mcp',
502
- 'notify',
503
- 'pair',
504
- 'qrcode',
505
- 'remote',
506
- 'remote-env',
507
- 'remote-setup',
508
- 'runner-pool',
509
- 'scan',
510
- 'secrets',
511
- 'services',
512
- 'subscription',
513
- 'teleport',
514
- 'tts',
515
- 'tunnel',
516
- 'voice',
517
- ]);
518
-
519
- const EXTERNAL_CLI_COMMANDS = new Set([
520
- 'bridge',
521
- 'listener',
522
- 'pair',
523
- 'remote',
524
- 'run',
525
- 'serve',
526
- 'service',
527
- 'tui',
528
- 'web',
529
- ]);
530
-
531
- const ONBOARDING_CAPABILITIES = [
532
- 'local-tui-only',
533
- 'browser-access',
534
- 'network-access',
535
- 'webhook-events',
536
- 'external-integrations',
537
- 'cloudflare-batch',
538
- ] as const;
539
-
540
- const EXTERNAL_SURFACES = [
541
- 'bluebubbles',
542
- 'discord',
543
- 'googleChat',
544
- 'homeassistant',
545
- 'imessage',
546
- 'matrix',
547
- 'mattermost',
548
- 'msteams',
549
- 'ntfy',
550
- 'signal',
551
- 'slack',
552
- 'telegram',
553
- 'webhook',
554
- 'whatsapp',
555
- ] as const;
556
-
557
- function percent(numerator: number, denominator: number): number {
558
- return denominator === 0 ? 0 : Math.round((numerator / denominator) * 1000) / 10;
559
- }
560
-
561
- function listSlashCommands(): string[] {
562
- const registry = new CommandRegistry();
563
- registerBuiltinCommands(registry);
564
- return registry.getAll().map((command) => command.name);
565
- }
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;
576
- }
577
-
578
- /**
579
- * The CLI command words this terminal actually accepts, read off the catalog
580
- * the parser is driven by rather than scraped out of a source file, the
581
- * ledger counts what ships, and a catalog entry IS what ships.
582
- */
583
- function listCliCommands(): string[] {
584
- return GOODVIBES_CLI_CATALOG.commands
585
- .map((spec) => spec.name as string)
586
- .filter((command) => command !== 'unknown');
587
- }
588
-
589
- export function buildVerificationLedger(root: string): VerificationLedger {
590
- const slashCommandNames = listSlashCommands();
591
- const cliCommandNames = listCliCommands();
592
- const slashCommands = slashCommandNames.length;
593
- const panels = countBuiltinPanels(root);
594
- const cliCommands = cliCommandNames.length;
595
- const featureFlags = FEATURE_SETTINGS.length;
596
- const settings = CONFIG_SCHEMA.length;
597
- const externalSlashCommands = slashCommandNames.filter((command) => EXTERNAL_SLASH_COMMANDS.has(command)).length;
598
- const externalCliCommands = cliCommandNames.filter((command) => EXTERNAL_CLI_COMMANDS.has(command)).length;
599
-
600
- const areas: VerificationLedgerArea[] = [
601
- {
602
- area: 'Settings schema and persistence',
603
- total: settings,
604
- localSignalVerified: settings,
605
- localBehaviorVerified: SETTINGS_BEHAVIOR_VERIFIED,
606
- externalOutcomeRequired: settings - SETTINGS_BEHAVIOR_VERIFIED,
607
- notes: 'Every schema setting can be validated for schema/default/load/write/location; external side effects remain separate.',
608
- },
609
- {
610
- area: 'Feature flags',
611
- total: featureFlags,
612
- localSignalVerified: featureFlags,
613
- localBehaviorVerified: featureFlags - 4,
614
- externalOutcomeRequired: 4,
615
- notes: 'All flags can be loaded/toggled; a small surface/service subset still requires live external behavior.',
616
- },
617
- {
618
- area: 'Slash commands',
619
- total: slashCommands,
620
- localSignalVerified: slashCommands,
621
- localBehaviorVerified: slashCommands - externalSlashCommands,
622
- externalOutcomeRequired: externalSlashCommands,
623
- notes: 'Every command can be routed and invoked with a fake context; external/provider/device commands need live outcome checks.',
624
- },
625
- {
626
- area: 'Built-in panels',
627
- total: panels,
628
- localSignalVerified: panels,
629
- localBehaviorVerified: panels,
630
- externalOutcomeRequired: 0,
631
- notes: 'Panels can be rendered and input-tested against fake read models and real cached state.',
632
- },
633
- {
634
- area: 'Top-level CLI commands',
635
- total: cliCommands,
636
- localSignalVerified: cliCommands,
637
- localBehaviorVerified: cliCommands - externalCliCommands,
638
- externalOutcomeRequired: externalCliCommands,
639
- notes: 'Parser/help/status/package behavior is local; long-running TUI/service/remote flows require process or external checks.',
640
- },
641
- {
642
- area: 'External surfaces',
643
- total: EXTERNAL_SURFACES.length,
644
- localSignalVerified: EXTERNAL_SURFACES.length,
645
- localBehaviorVerified: 2,
646
- externalOutcomeRequired: EXTERNAL_SURFACES.length - 2,
647
- notes: 'Config/readiness can be local for all surfaces; real message delivery is external for most surfaces.',
648
- },
649
- {
650
- area: 'Onboarding capability bundles',
651
- total: ONBOARDING_CAPABILITIES.length,
652
- localSignalVerified: ONBOARDING_CAPABILITIES.length,
653
- localBehaviorVerified: 5,
654
- externalOutcomeRequired: 1,
655
- notes: 'Wizard state derivation/apply can be local; Cloudflare provisioning remains external.',
656
- },
657
- ];
658
-
659
- const total = areas.reduce((sum, area) => sum + area.total, 0);
660
- const localSignalVerified = areas.reduce((sum, area) => sum + area.localSignalVerified, 0);
661
- const localBehaviorVerified = areas.reduce((sum, area) => sum + area.localBehaviorVerified, 0);
662
- const externalOutcomeRequired = areas.reduce((sum, area) => sum + area.externalOutcomeRequired, 0);
663
-
664
- return {
665
- generatedAt: new Date().toISOString(),
666
- areas,
667
- totals: {
668
- total,
669
- localSignalVerified,
670
- localBehaviorVerified,
671
- externalOutcomeRequired,
672
- localSignalPercent: percent(localSignalVerified, total),
673
- localBehaviorPercent: percent(localBehaviorVerified, total),
674
- },
675
- };
676
- }
677
-
678
- export function renderVerificationLedgerMarkdown(ledger: VerificationLedger): string {
679
- const lines = [
680
- '# GoodVibes Verification Ledger',
681
- '',
682
- `Generated: ${ledger.generatedAt}`,
683
- '',
684
- '| Area | Total | Local verification signal | Local behavior | External outcome required | Notes |',
685
- '|---|---:|---:|---:|---:|---|',
686
- ...ledger.areas.map((area) => [
687
- `| ${area.area}`,
688
- area.total,
689
- area.localSignalVerified,
690
- area.localBehaviorVerified,
691
- area.externalOutcomeRequired,
692
- area.notes,
693
- ].join(' | ') + ' |'),
694
- '',
695
- '## Totals',
696
- '',
697
- `- Total inventory items: ${ledger.totals.total}`,
698
- `- Local verification signal: ${ledger.totals.localSignalVerified} (${ledger.totals.localSignalPercent}%)`,
699
- `- Local behavior verified: ${ledger.totals.localBehaviorVerified} (${ledger.totals.localBehaviorPercent}%)`,
700
- `- External outcome required: ${ledger.totals.externalOutcomeRequired}`,
701
- '',
702
- 'Local verification signal means the item can be exercised through schema, routing, persistence, render, readiness, daemon, CLI, or real-state checks without relying on an external SaaS/device outcome.',
703
- 'Local behavior verified means the behavior can be completed locally with in-process, CLI, daemon, tmux, or real persisted state.',
704
- '',
705
- ];
706
- return `${lines.join('\n')}\n`;
707
- }