@pellux/goodvibes-agent 0.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 (398) hide show
  1. package/.goodvibes/GOODVIBES.md +35 -0
  2. package/.goodvibes/agents/reviewer.md +48 -0
  3. package/.goodvibes/skills/add-provider/SKILL.md +199 -0
  4. package/CHANGELOG.md +25 -0
  5. package/README.md +74 -0
  6. package/bin/goodvibes-agent.ts +2 -0
  7. package/docs/README.md +23 -0
  8. package/docs/deployment-and-services.md +57 -0
  9. package/docs/getting-started.md +53 -0
  10. package/docs/release-and-publishing.md +46 -0
  11. package/package.json +134 -0
  12. package/scripts/check-bun.sh +20 -0
  13. package/src/audio/player.ts +156 -0
  14. package/src/audio/spoken-turn-controller.ts +203 -0
  15. package/src/audio/spoken-turn-model-routing.ts +117 -0
  16. package/src/audio/spoken-turn-wiring.ts +44 -0
  17. package/src/audio/text-chunker.ts +110 -0
  18. package/src/cli/bundle-command.ts +227 -0
  19. package/src/cli/completion.ts +90 -0
  20. package/src/cli/config-overrides.ts +159 -0
  21. package/src/cli/endpoints.ts +63 -0
  22. package/src/cli/entrypoint.ts +172 -0
  23. package/src/cli/help.ts +299 -0
  24. package/src/cli/index.ts +11 -0
  25. package/src/cli/management-commands.ts +426 -0
  26. package/src/cli/management.ts +744 -0
  27. package/src/cli/network-posture.ts +46 -0
  28. package/src/cli/package-verification.ts +123 -0
  29. package/src/cli/parser.ts +369 -0
  30. package/src/cli/provider-auth-routes.ts +22 -0
  31. package/src/cli/provider-classification.ts +107 -0
  32. package/src/cli/redaction.ts +105 -0
  33. package/src/cli/service-command.ts +26 -0
  34. package/src/cli/service-posture.ts +482 -0
  35. package/src/cli/status.ts +383 -0
  36. package/src/cli/surface-command.ts +247 -0
  37. package/src/cli/tui-startup.ts +32 -0
  38. package/src/cli/types.ts +69 -0
  39. package/src/cli-flags.ts +21 -0
  40. package/src/config/goodvibes-home-audit.ts +465 -0
  41. package/src/config/index.ts +57 -0
  42. package/src/config/provider-model.ts +23 -0
  43. package/src/config/secret-config.ts +119 -0
  44. package/src/config/secrets.ts +71 -0
  45. package/src/config/surface.ts +1 -0
  46. package/src/core/composer-state.ts +61 -0
  47. package/src/core/conversation-rendering.ts +359 -0
  48. package/src/core/conversation.ts +551 -0
  49. package/src/core/history.ts +45 -0
  50. package/src/core/orchestrator.ts +7 -0
  51. package/src/core/system-message-router.ts +171 -0
  52. package/src/daemon/cli.ts +55 -0
  53. package/src/daemon/safe-serve.ts +61 -0
  54. package/src/input/agent-workspace.ts +428 -0
  55. package/src/input/autocomplete.ts +96 -0
  56. package/src/input/bookmark-modal.ts +115 -0
  57. package/src/input/command-args-hint.ts +36 -0
  58. package/src/input/command-registry.ts +329 -0
  59. package/src/input/commands/agent-externalized-tui.ts +73 -0
  60. package/src/input/commands/agent-workspace-runtime.ts +17 -0
  61. package/src/input/commands/branch-runtime.ts +72 -0
  62. package/src/input/commands/cloudflare-runtime.ts +370 -0
  63. package/src/input/commands/config.ts +18 -0
  64. package/src/input/commands/control-room-runtime.ts +255 -0
  65. package/src/input/commands/conversation-runtime.ts +207 -0
  66. package/src/input/commands/discovery-runtime.ts +52 -0
  67. package/src/input/commands/eval.ts +204 -0
  68. package/src/input/commands/experience-runtime.ts +278 -0
  69. package/src/input/commands/guidance-runtime.ts +106 -0
  70. package/src/input/commands/health-runtime.ts +434 -0
  71. package/src/input/commands/hooks-runtime.ts +148 -0
  72. package/src/input/commands/incident-runtime.ts +95 -0
  73. package/src/input/commands/integration-runtime.ts +394 -0
  74. package/src/input/commands/intelligence-runtime.ts +223 -0
  75. package/src/input/commands/knowledge.ts +531 -0
  76. package/src/input/commands/local-auth-runtime.ts +105 -0
  77. package/src/input/commands/local-provider-runtime.ts +170 -0
  78. package/src/input/commands/local-runtime.ts +392 -0
  79. package/src/input/commands/local-setup-review.ts +199 -0
  80. package/src/input/commands/local-setup-transfer.ts +135 -0
  81. package/src/input/commands/local-setup.ts +282 -0
  82. package/src/input/commands/managed-runtime.ts +209 -0
  83. package/src/input/commands/marketplace-runtime.ts +290 -0
  84. package/src/input/commands/mcp-runtime.ts +432 -0
  85. package/src/input/commands/memory-product-runtime.ts +111 -0
  86. package/src/input/commands/memory.ts +151 -0
  87. package/src/input/commands/notify-runtime.ts +83 -0
  88. package/src/input/commands/onboarding-runtime.ts +14 -0
  89. package/src/input/commands/operator-panel-runtime.ts +146 -0
  90. package/src/input/commands/operator-runtime.ts +392 -0
  91. package/src/input/commands/planning-runtime.ts +205 -0
  92. package/src/input/commands/platform-access-runtime.ts +422 -0
  93. package/src/input/commands/platform-services-runtime.ts +246 -0
  94. package/src/input/commands/policy-dispatch.ts +339 -0
  95. package/src/input/commands/policy.ts +17 -0
  96. package/src/input/commands/product-runtime.ts +351 -0
  97. package/src/input/commands/profile-sync-runtime.ts +99 -0
  98. package/src/input/commands/provider-accounts-runtime.ts +113 -0
  99. package/src/input/commands/provider.ts +363 -0
  100. package/src/input/commands/qrcode-runtime.ts +20 -0
  101. package/src/input/commands/quit-shared.ts +162 -0
  102. package/src/input/commands/recall-bundle.ts +132 -0
  103. package/src/input/commands/recall-capture.ts +152 -0
  104. package/src/input/commands/recall-query.ts +229 -0
  105. package/src/input/commands/recall-review.ts +98 -0
  106. package/src/input/commands/recall-shared.ts +22 -0
  107. package/src/input/commands/remote-runtime-pool.ts +106 -0
  108. package/src/input/commands/remote-runtime-setup.ts +199 -0
  109. package/src/input/commands/remote-runtime.ts +431 -0
  110. package/src/input/commands/replay-runtime.ts +18 -0
  111. package/src/input/commands/runtime-services.ts +291 -0
  112. package/src/input/commands/schedule-runtime.ts +91 -0
  113. package/src/input/commands/services-runtime.ts +209 -0
  114. package/src/input/commands/session-content.ts +408 -0
  115. package/src/input/commands/session-workflow.ts +464 -0
  116. package/src/input/commands/session.ts +375 -0
  117. package/src/input/commands/settings-sync-runtime.ts +174 -0
  118. package/src/input/commands/share-runtime.ts +119 -0
  119. package/src/input/commands/shell-core.ts +307 -0
  120. package/src/input/commands/skills-runtime.ts +221 -0
  121. package/src/input/commands/subscription-runtime.ts +434 -0
  122. package/src/input/commands/tasks-runtime.ts +230 -0
  123. package/src/input/commands/teamwork-runtime.ts +339 -0
  124. package/src/input/commands/teleport-runtime.ts +57 -0
  125. package/src/input/commands/tts-runtime.ts +29 -0
  126. package/src/input/commands/work-plan-runtime.ts +169 -0
  127. package/src/input/commands.ts +131 -0
  128. package/src/input/feed-context-factory.ts +254 -0
  129. package/src/input/file-picker.ts +192 -0
  130. package/src/input/handler-command-route.ts +180 -0
  131. package/src/input/handler-content-actions.ts +497 -0
  132. package/src/input/handler-feed-routes.ts +648 -0
  133. package/src/input/handler-feed.ts +452 -0
  134. package/src/input/handler-interactions.ts +281 -0
  135. package/src/input/handler-modal-routes.ts +418 -0
  136. package/src/input/handler-modal-stack.ts +263 -0
  137. package/src/input/handler-modal-token-routes.ts +329 -0
  138. package/src/input/handler-onboarding-cloudflare.ts +391 -0
  139. package/src/input/handler-onboarding.ts +620 -0
  140. package/src/input/handler-picker-routes.ts +472 -0
  141. package/src/input/handler-prompt-buffer.ts +320 -0
  142. package/src/input/handler-shortcuts.ts +213 -0
  143. package/src/input/handler-ui-state.ts +372 -0
  144. package/src/input/handler.ts +729 -0
  145. package/src/input/input-history.ts +297 -0
  146. package/src/input/keybindings.ts +292 -0
  147. package/src/input/mcp-workspace.ts +554 -0
  148. package/src/input/model-picker-provider-filter.ts +28 -0
  149. package/src/input/model-picker-types.ts +137 -0
  150. package/src/input/model-picker.ts +797 -0
  151. package/src/input/onboarding/handler-onboarding-routes.ts +125 -0
  152. package/src/input/onboarding/onboarding-runtime-status.ts +87 -0
  153. package/src/input/onboarding/onboarding-wizard-apply.ts +277 -0
  154. package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +494 -0
  155. package/src/input/onboarding/onboarding-wizard-cloudflare.ts +204 -0
  156. package/src/input/onboarding/onboarding-wizard-constants.ts +158 -0
  157. package/src/input/onboarding/onboarding-wizard-external-surface-extra-specs.ts +130 -0
  158. package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +762 -0
  159. package/src/input/onboarding/onboarding-wizard-helpers.ts +167 -0
  160. package/src/input/onboarding/onboarding-wizard-rules.ts +256 -0
  161. package/src/input/onboarding/onboarding-wizard-state.ts +365 -0
  162. package/src/input/onboarding/onboarding-wizard-steps.ts +798 -0
  163. package/src/input/onboarding/onboarding-wizard-types.ts +195 -0
  164. package/src/input/onboarding/onboarding-wizard.ts +711 -0
  165. package/src/input/panel-integration-actions.ts +78 -0
  166. package/src/input/profile-picker-modal.ts +222 -0
  167. package/src/input/search.ts +100 -0
  168. package/src/input/selection-modal.ts +163 -0
  169. package/src/input/selection.ts +135 -0
  170. package/src/input/session-picker-modal.ts +136 -0
  171. package/src/input/settings-modal-behavior.ts +37 -0
  172. package/src/input/settings-modal-secrets.ts +41 -0
  173. package/src/input/settings-modal-subscriptions.ts +95 -0
  174. package/src/input/settings-modal-types.ts +91 -0
  175. package/src/input/settings-modal.ts +793 -0
  176. package/src/input/submission-intent.ts +17 -0
  177. package/src/input/submission-router.ts +59 -0
  178. package/src/input/tts-settings-actions.ts +100 -0
  179. package/src/main.ts +792 -0
  180. package/src/mcp/runtime-reload.ts +81 -0
  181. package/src/panels/agent-inspector-panel.ts +521 -0
  182. package/src/panels/agent-inspector-shared.ts +94 -0
  183. package/src/panels/agent-logs-panel.ts +559 -0
  184. package/src/panels/agent-logs-shared.ts +129 -0
  185. package/src/panels/approval-panel.ts +150 -0
  186. package/src/panels/automation-control-panel.ts +212 -0
  187. package/src/panels/base-panel.ts +254 -0
  188. package/src/panels/builtin/agent.ts +117 -0
  189. package/src/panels/builtin/development.ts +31 -0
  190. package/src/panels/builtin/knowledge.ts +26 -0
  191. package/src/panels/builtin/operations.ts +349 -0
  192. package/src/panels/builtin/session.ts +129 -0
  193. package/src/panels/builtin/shared.ts +274 -0
  194. package/src/panels/builtin-panels.ts +23 -0
  195. package/src/panels/cockpit-panel.ts +183 -0
  196. package/src/panels/communication-panel.ts +153 -0
  197. package/src/panels/confirm-state.ts +61 -0
  198. package/src/panels/context-visualizer-panel.ts +204 -0
  199. package/src/panels/control-plane-panel.ts +211 -0
  200. package/src/panels/cost-tracker-panel.ts +444 -0
  201. package/src/panels/debug-panel.ts +432 -0
  202. package/src/panels/diff-panel.ts +520 -0
  203. package/src/panels/docs-panel.ts +283 -0
  204. package/src/panels/eval-panel.ts +399 -0
  205. package/src/panels/file-explorer-panel.ts +584 -0
  206. package/src/panels/file-preview-panel.ts +434 -0
  207. package/src/panels/forensics-panel.ts +364 -0
  208. package/src/panels/git-panel.ts +638 -0
  209. package/src/panels/hooks-panel.ts +239 -0
  210. package/src/panels/incident-review-panel.ts +197 -0
  211. package/src/panels/index.ts +46 -0
  212. package/src/panels/intelligence-panel.ts +176 -0
  213. package/src/panels/knowledge-panel.ts +345 -0
  214. package/src/panels/local-auth-panel.ts +130 -0
  215. package/src/panels/marketplace-panel.ts +212 -0
  216. package/src/panels/memory-panel.ts +225 -0
  217. package/src/panels/ops-control-panel.ts +150 -0
  218. package/src/panels/ops-strategy-panel.ts +235 -0
  219. package/src/panels/orchestration-panel.ts +273 -0
  220. package/src/panels/panel-list-panel.ts +509 -0
  221. package/src/panels/panel-manager.ts +570 -0
  222. package/src/panels/panel-picker.ts +106 -0
  223. package/src/panels/plan-dashboard-panel.ts +274 -0
  224. package/src/panels/plugins-panel.ts +178 -0
  225. package/src/panels/policy-panel.ts +308 -0
  226. package/src/panels/polish.ts +717 -0
  227. package/src/panels/project-planning-panel.ts +711 -0
  228. package/src/panels/provider-account-snapshot.ts +259 -0
  229. package/src/panels/provider-accounts-panel.ts +218 -0
  230. package/src/panels/provider-health-domains.ts +215 -0
  231. package/src/panels/provider-health-panel.ts +727 -0
  232. package/src/panels/provider-health-tracker.ts +115 -0
  233. package/src/panels/provider-stats-panel.ts +366 -0
  234. package/src/panels/qr-panel.ts +182 -0
  235. package/src/panels/remote-panel.ts +449 -0
  236. package/src/panels/routes-panel.ts +178 -0
  237. package/src/panels/sandbox-panel.ts +283 -0
  238. package/src/panels/schedule-panel.ts +329 -0
  239. package/src/panels/scrollable-list-panel.ts +491 -0
  240. package/src/panels/search-focus.ts +32 -0
  241. package/src/panels/security-panel.ts +295 -0
  242. package/src/panels/services-panel.ts +231 -0
  243. package/src/panels/session-browser-panel.ts +400 -0
  244. package/src/panels/session-maintenance.ts +125 -0
  245. package/src/panels/settings-sync-panel.ts +120 -0
  246. package/src/panels/skills-panel.ts +431 -0
  247. package/src/panels/subscription-panel.ts +263 -0
  248. package/src/panels/symbol-outline-panel.ts +486 -0
  249. package/src/panels/system-messages-panel.ts +230 -0
  250. package/src/panels/tasks-panel.ts +399 -0
  251. package/src/panels/thinking-panel.ts +304 -0
  252. package/src/panels/token-budget-panel.ts +475 -0
  253. package/src/panels/tool-inspector-panel.ts +429 -0
  254. package/src/panels/types.ts +54 -0
  255. package/src/panels/watchers-panel.ts +193 -0
  256. package/src/panels/work-plan-panel.ts +175 -0
  257. package/src/panels/worktree-panel.ts +182 -0
  258. package/src/panels/wrfc-panel.ts +609 -0
  259. package/src/permissions/prompt.ts +165 -0
  260. package/src/planning/project-planning-coordinator.ts +543 -0
  261. package/src/plugins/loader.ts +15 -0
  262. package/src/renderer/agent-detail-modal.ts +331 -0
  263. package/src/renderer/agent-workspace.ts +238 -0
  264. package/src/renderer/ansi-sanitize.ts +76 -0
  265. package/src/renderer/autocomplete-overlay.ts +154 -0
  266. package/src/renderer/block-actions.ts +76 -0
  267. package/src/renderer/bookmark-modal.ts +101 -0
  268. package/src/renderer/bottom-bar.ts +58 -0
  269. package/src/renderer/buffer.ts +113 -0
  270. package/src/renderer/code-block.ts +373 -0
  271. package/src/renderer/compositor.ts +283 -0
  272. package/src/renderer/context-inspector.ts +219 -0
  273. package/src/renderer/conversation-layout.ts +67 -0
  274. package/src/renderer/conversation-overlays.ts +140 -0
  275. package/src/renderer/conversation-surface.ts +260 -0
  276. package/src/renderer/diff-view.ts +132 -0
  277. package/src/renderer/diff.ts +130 -0
  278. package/src/renderer/file-picker-overlay.ts +101 -0
  279. package/src/renderer/file-tree.ts +153 -0
  280. package/src/renderer/fullscreen-primitives.ts +130 -0
  281. package/src/renderer/fullscreen-workspace.ts +199 -0
  282. package/src/renderer/git-status.ts +89 -0
  283. package/src/renderer/help-overlay.ts +267 -0
  284. package/src/renderer/history-search-overlay.ts +73 -0
  285. package/src/renderer/layout-engine.ts +97 -0
  286. package/src/renderer/layout.ts +32 -0
  287. package/src/renderer/live-tail-modal.ts +156 -0
  288. package/src/renderer/markdown.ts +635 -0
  289. package/src/renderer/mcp-workspace.ts +237 -0
  290. package/src/renderer/modal-factory.ts +467 -0
  291. package/src/renderer/modal-utils.ts +24 -0
  292. package/src/renderer/model-picker-overlay.ts +473 -0
  293. package/src/renderer/model-workspace.ts +488 -0
  294. package/src/renderer/onboarding/onboarding-wizard.ts +615 -0
  295. package/src/renderer/overlay-box.ts +146 -0
  296. package/src/renderer/overlay-viewport.ts +104 -0
  297. package/src/renderer/panel-composite.ts +158 -0
  298. package/src/renderer/panel-picker-overlay.ts +202 -0
  299. package/src/renderer/panel-tab-bar.ts +69 -0
  300. package/src/renderer/panel-workspace-bar.ts +42 -0
  301. package/src/renderer/process-indicator.ts +96 -0
  302. package/src/renderer/process-modal.ts +656 -0
  303. package/src/renderer/process-summary.ts +67 -0
  304. package/src/renderer/profile-picker-modal.ts +129 -0
  305. package/src/renderer/progress.ts +98 -0
  306. package/src/renderer/qr-renderer.ts +120 -0
  307. package/src/renderer/search-overlay.ts +54 -0
  308. package/src/renderer/selection-modal-overlay.ts +214 -0
  309. package/src/renderer/semantic-diff.ts +369 -0
  310. package/src/renderer/session-picker-modal.ts +127 -0
  311. package/src/renderer/settings-modal-helpers.ts +193 -0
  312. package/src/renderer/settings-modal.ts +537 -0
  313. package/src/renderer/shell-surface.ts +88 -0
  314. package/src/renderer/status-glyphs.ts +21 -0
  315. package/src/renderer/status-token.ts +67 -0
  316. package/src/renderer/surface-layout.ts +101 -0
  317. package/src/renderer/syntax-highlighter.ts +542 -0
  318. package/src/renderer/system-message.ts +83 -0
  319. package/src/renderer/tab-strip.ts +108 -0
  320. package/src/renderer/text-layout.ts +31 -0
  321. package/src/renderer/thinking.ts +17 -0
  322. package/src/renderer/tool-call.ts +234 -0
  323. package/src/renderer/ui-factory.ts +524 -0
  324. package/src/renderer/ui-primitives.ts +96 -0
  325. package/src/runtime/bootstrap-command-context.ts +278 -0
  326. package/src/runtime/bootstrap-command-parts.ts +386 -0
  327. package/src/runtime/bootstrap-core.ts +540 -0
  328. package/src/runtime/bootstrap-hook-bridge.ts +112 -0
  329. package/src/runtime/bootstrap-shell.ts +283 -0
  330. package/src/runtime/bootstrap.ts +575 -0
  331. package/src/runtime/cloudflare-control-plane.ts +349 -0
  332. package/src/runtime/context.ts +142 -0
  333. package/src/runtime/diagnostics/panels/index.ts +24 -0
  334. package/src/runtime/diagnostics/panels/ops.ts +156 -0
  335. package/src/runtime/diagnostics/panels/panel-resources.ts +118 -0
  336. package/src/runtime/diagnostics/panels/policy.ts +177 -0
  337. package/src/runtime/index.ts +662 -0
  338. package/src/runtime/onboarding/apply.ts +642 -0
  339. package/src/runtime/onboarding/derivation.ts +534 -0
  340. package/src/runtime/onboarding/index.ts +7 -0
  341. package/src/runtime/onboarding/markers.ts +148 -0
  342. package/src/runtime/onboarding/snapshot.ts +406 -0
  343. package/src/runtime/onboarding/state.ts +141 -0
  344. package/src/runtime/onboarding/types.ts +404 -0
  345. package/src/runtime/onboarding/verify.ts +171 -0
  346. package/src/runtime/operator-token-cleanup.ts +27 -0
  347. package/src/runtime/perf/panel-contracts.ts +32 -0
  348. package/src/runtime/perf/panel-health-monitor.ts +18 -0
  349. package/src/runtime/sandbox-public-gaps.ts +358 -0
  350. package/src/runtime/services.ts +670 -0
  351. package/src/runtime/store/domains/domain-read-matrix.ts +15 -0
  352. package/src/runtime/store/domains/index.ts +222 -0
  353. package/src/runtime/store/domains/panels.ts +117 -0
  354. package/src/runtime/store/domains/ui-perf.ts +103 -0
  355. package/src/runtime/store/index.ts +305 -0
  356. package/src/runtime/store/selectors/index.ts +359 -0
  357. package/src/runtime/store/state.ts +145 -0
  358. package/src/runtime/surface-feature-flags.ts +65 -0
  359. package/src/runtime/terminal-output-guard.ts +228 -0
  360. package/src/runtime/ui/index.ts +39 -0
  361. package/src/runtime/ui/model-picker/data-provider.ts +182 -0
  362. package/src/runtime/ui/model-picker/health-enrichment.ts +228 -0
  363. package/src/runtime/ui/model-picker/index.ts +59 -0
  364. package/src/runtime/ui/model-picker/types.ts +149 -0
  365. package/src/runtime/ui/provider-health/data-provider.ts +244 -0
  366. package/src/runtime/ui/provider-health/fallback-visualizer.ts +71 -0
  367. package/src/runtime/ui/provider-health/index.ts +46 -0
  368. package/src/runtime/ui/provider-health/types.ts +146 -0
  369. package/src/runtime/ui-events.ts +1 -0
  370. package/src/runtime/ui-read-model-helpers.ts +1 -0
  371. package/src/runtime/ui-read-models-observability-maintenance.ts +1 -0
  372. package/src/runtime/ui-read-models-observability-options.ts +1 -0
  373. package/src/runtime/ui-read-models-observability-remote.ts +1 -0
  374. package/src/runtime/ui-read-models-observability-security.ts +1 -0
  375. package/src/runtime/ui-read-models-observability-system.ts +1 -0
  376. package/src/runtime/ui-read-models-observability.ts +1 -0
  377. package/src/runtime/ui-read-models.ts +61 -0
  378. package/src/runtime/ui-service-queries.ts +1 -0
  379. package/src/runtime/ui-services.ts +190 -0
  380. package/src/scripts/process-messages.ts +42 -0
  381. package/src/shell/blocking-input.ts +98 -0
  382. package/src/shell/service-settings-sync.ts +273 -0
  383. package/src/shell/ui-openers.ts +352 -0
  384. package/src/tools/index.ts +1 -0
  385. package/src/tools/wrfc-agent-guard.ts +49 -0
  386. package/src/types/grid.ts +48 -0
  387. package/src/types/sql-js.d.ts +15 -0
  388. package/src/utils/clipboard.ts +22 -0
  389. package/src/utils/splash-lines.ts +46 -0
  390. package/src/utils/terminal-width.ts +185 -0
  391. package/src/verification/live-verifier.ts +430 -0
  392. package/src/verification/verification-ledger.ts +242 -0
  393. package/src/version.ts +17 -0
  394. package/src/widget/index.ts +2 -0
  395. package/src/widget/types.ts +9 -0
  396. package/src/widget/widget.ts +8 -0
  397. package/src/work-plans/work-plan-store.ts +374 -0
  398. package/tsconfig.json +18 -0
@@ -0,0 +1,239 @@
1
+ import type { Line } from '../types/grid.ts';
2
+ import { ScrollableListPanel } from './scrollable-list-panel.ts';
3
+ import { listHookPointContracts } from '@pellux/goodvibes-sdk/platform/hooks';
4
+ import type { HookDispatcher } from '@pellux/goodvibes-sdk/platform/hooks';
5
+ import type { HookPointContract } from '@pellux/goodvibes-sdk/platform/hooks';
6
+ import type { HookActivityRecord, HookActivityTracker } from '@pellux/goodvibes-sdk/platform/hooks';
7
+ import type { HookAuthoringAction, HookSimulationResult } from '@pellux/goodvibes-sdk/platform/hooks';
8
+ import type { HookChain, HookDefinition } from '@pellux/goodvibes-sdk/platform/hooks';
9
+ import type { HookWorkbench } from '@pellux/goodvibes-sdk/platform/hooks';
10
+ import { truncateDisplay } from '../utils/terminal-width.ts';
11
+ import {
12
+ buildPanelLine,
13
+ buildStatusPill,
14
+ DEFAULT_PANEL_PALETTE,
15
+ } from './polish.ts';
16
+
17
+ const C = {
18
+ ...DEFAULT_PANEL_PALETTE,
19
+ header: '#94a3b8',
20
+ headerBg: '#1e293b',
21
+ ok: '#22c55e',
22
+ warn: '#eab308',
23
+ error: '#ef4444',
24
+ info: '#38bdf8',
25
+ selectBg: '#0f172a',
26
+ } as const;
27
+
28
+ export interface HooksPanelWorkbenchView {
29
+ listManagedHooks(): Array<{ pattern: string; hook: HookDefinition }>;
30
+ listManagedChains(): HookChain[];
31
+ listRecentActions(limit?: number): HookAuthoringAction[];
32
+ getLastSimulation(): HookSimulationResult | null;
33
+ getHooksFilePath(): string;
34
+ }
35
+
36
+ export interface HooksPanelDataSource {
37
+ listContracts(): HookPointContract[];
38
+ listHooks(): Array<{ pattern: string; hook: HookDefinition }>;
39
+ listChains(): HookChain[];
40
+ listRecentActivity(limit?: number): readonly HookActivityRecord[];
41
+ getWorkbench(): HooksPanelWorkbenchView;
42
+ }
43
+
44
+ function createDefaultDataSource(
45
+ hookDispatcher: Pick<HookDispatcher, 'listHooks' | 'getChains'>,
46
+ hookWorkbench: HookWorkbench,
47
+ hookActivityTracker: Pick<HookActivityTracker, 'listRecent'>,
48
+ ): HooksPanelDataSource {
49
+ return {
50
+ listContracts: () => listHookPointContracts(),
51
+ listHooks: () => hookDispatcher.listHooks(),
52
+ listChains: () => hookDispatcher.getChains(),
53
+ listRecentActivity: (limit = 3) => hookActivityTracker.listRecent(limit),
54
+ getWorkbench: () => hookWorkbench,
55
+ };
56
+ }
57
+
58
+ type HookEntry = { pattern: string; hook: HookDefinition };
59
+
60
+ export class HooksPanel extends ScrollableListPanel<HookEntry> {
61
+ private readonly dataSource: HooksPanelDataSource;
62
+
63
+ public constructor(
64
+ hookDispatcher: Pick<HookDispatcher, 'listHooks' | 'getChains'>,
65
+ hookWorkbench: HookWorkbench,
66
+ hookActivityTracker: Pick<HookActivityTracker, 'listRecent'>,
67
+ dataSource: HooksPanelDataSource = createDefaultDataSource(hookDispatcher, hookWorkbench, hookActivityTracker),
68
+ ) {
69
+ super('hooks', 'Hooks', 'H', 'monitoring');
70
+ this.showSelectionGutter = true; // I5: non-color selection affordance
71
+ this.dataSource = dataSource;
72
+ }
73
+
74
+ protected override getPalette() { return C; }
75
+ protected override getEmptyStateMessage() { return ' No hooks are currently registered.'; }
76
+ protected override getEmptyStateActions() {
77
+ return [
78
+ { command: '/hooks', summary: 'review hook contracts and managed authoring actions' },
79
+ { command: '/settings', summary: 'review hook/runtime behavior in the settings surface' },
80
+ ];
81
+ }
82
+
83
+ protected getItems(): readonly HookEntry[] {
84
+ return this.dataSource.listHooks();
85
+ }
86
+
87
+ protected renderItem(entry: HookEntry, index: number, selected: boolean, width: number): Line {
88
+ const bg = selected ? C.selectBg : undefined;
89
+ return buildPanelLine(width, [
90
+ [' ', C.label, bg],
91
+ [truncateDisplay(entry.hook.name ?? '(unnamed)', 20).padEnd(20), C.value, bg],
92
+ [` ${truncateDisplay(entry.pattern, 28).padEnd(28)}`, C.info, bg],
93
+ ...buildStatusPill(entry.hook.enabled === false ? 'warn' : 'good', ` ${(entry.hook.enabled === false ? 'DISABLED' : 'ENABLED').padEnd(8)}`, { bg }),
94
+ [` ${entry.hook.type}`, C.dim, bg],
95
+ ]);
96
+ }
97
+
98
+ public handleInput(key: string): boolean {
99
+ if (key === 'r') {
100
+ this.markDirty();
101
+ return true;
102
+ }
103
+ return super.handleInput(key);
104
+ }
105
+
106
+ public render(width: number, height: number): Line[] {
107
+ this.clampSelection();
108
+ const hooks = this.dataSource.listHooks();
109
+ const contracts = this.dataSource.listContracts();
110
+ const chains = this.dataSource.listChains();
111
+ const recentActivity = this.dataSource.listRecentActivity(3);
112
+ const workbench = this.dataSource.getWorkbench();
113
+ const managedHooks = workbench.listManagedHooks();
114
+ const managedChains = workbench.listManagedChains();
115
+ const recentAuthoring = workbench.listRecentActions(3);
116
+ const lastSimulation = workbench.getLastSimulation();
117
+ const intro = 'Hook contracts, active registrations, managed authoring, recent runtime activity, and simulation matches.';
118
+
119
+ const selected = hooks[this.selectedIndex];
120
+ const contract = selected ? contracts.find((c) => c.pattern === selected.pattern) : undefined;
121
+
122
+ const detailLines: Line[] = [];
123
+ if (selected) {
124
+ detailLines.push(buildPanelLine(width, [
125
+ [' Hook: ', C.label],
126
+ [selected.hook.name ?? '(unnamed)', C.value],
127
+ [' Type: ', C.label],
128
+ [selected.hook.type, C.info],
129
+ [' Match: ', C.label],
130
+ [selected.hook.matcher ?? selected.hook.match, C.value],
131
+ ]));
132
+ detailLines.push(buildPanelLine(width, [
133
+ [' Pattern: ', C.label],
134
+ [truncateDisplay(selected.pattern, Math.max(0, width - 12)), C.value],
135
+ ]));
136
+ if (contract) {
137
+ detailLines.push(buildPanelLine(width, [
138
+ [' Contract: ', C.label],
139
+ [`${contract.authority} / ${contract.executionMode}`, C.info],
140
+ [' Policy: ', C.label],
141
+ [contract.failurePolicy, C.value],
142
+ ]));
143
+ detailLines.push(buildPanelLine(width, [
144
+ [' Capabilities: ', C.label],
145
+ [`deny=${contract.canDeny ? 'yes' : 'no'} mutate=${contract.canMutateInput ? 'yes' : 'no'} inject=${contract.canInjectContext ? 'yes' : 'no'}`, C.dim],
146
+ ]));
147
+ } else {
148
+ detailLines.push(buildPanelLine(width, [[' Contract: No exact contract registered for this pattern.', C.warn]]));
149
+ }
150
+ detailLines.push(buildPanelLine(width, [
151
+ [' Summary: ', C.label],
152
+ [`hooks=${hooks.length} chains=${chains.length} contracts=${contracts.length} managed=${managedHooks.length}/${managedChains.length}`, C.dim],
153
+ ]));
154
+ detailLines.push(buildPanelLine(width, [
155
+ [' Hooks file: ', C.label],
156
+ [truncateDisplay(workbench.getHooksFilePath(), Math.max(0, width - 15)), C.dim],
157
+ ]));
158
+ }
159
+
160
+ const activityLines: Line[] = recentActivity.length === 0
161
+ ? [buildPanelLine(width, [[' No hook activity recorded yet.', C.empty]])]
162
+ : recentActivity.map((record) => {
163
+ const color = !record.ok ? C.error : record.decision === 'deny' ? C.warn : C.ok;
164
+ return buildPanelLine(width, [
165
+ [' ', C.label],
166
+ [truncateDisplay(record.hookName, 18).padEnd(18), C.value],
167
+ [' ', C.label],
168
+ [truncateDisplay(record.path, 26).padEnd(26), C.info],
169
+ [' ', C.label],
170
+ [record.ok ? (record.decision ?? 'ok') : 'error', color],
171
+ ]);
172
+ });
173
+
174
+ const authoringLines: Line[] = recentAuthoring.length === 0
175
+ ? [buildPanelLine(width, [[' No managed hook authoring actions recorded yet.', C.empty]])]
176
+ : recentAuthoring.map((action) => buildPanelLine(width, [
177
+ [' ', C.label],
178
+ [truncateDisplay(action.kind, 14).padEnd(14), C.info],
179
+ [' ', C.label],
180
+ [truncateDisplay(action.target, Math.max(0, width - 20)), C.dim],
181
+ ]));
182
+ if (lastSimulation) {
183
+ authoringLines.push(buildPanelLine(width, [
184
+ [' Last Simulation: ', C.label],
185
+ [truncateDisplay(lastSimulation.eventPath, Math.max(0, width - 20)), C.value],
186
+ ]));
187
+ authoringLines.push(buildPanelLine(width, [
188
+ [' Matches: ', C.label],
189
+ [`hooks=${lastSimulation.matchedHooks.length} chains=${lastSimulation.matchedChains.length}`, C.dim],
190
+ ]));
191
+ }
192
+
193
+ // Empty state: show extra context lines (hooks file, contracts, authoring) before base empty state
194
+ if (hooks.length === 0) {
195
+ const extraHeader: Line[] = [
196
+ buildPanelLine(width, [
197
+ [' Contracts: ', C.label],
198
+ [String(contracts.length), C.value],
199
+ [' Chains: ', C.label],
200
+ [String(chains.length), C.value],
201
+ [' Managed: ', C.label],
202
+ [String(managedHooks.length), C.info],
203
+ ]),
204
+ buildPanelLine(width, [
205
+ [' Hooks file: ', C.label],
206
+ [truncateDisplay(workbench.getHooksFilePath(), Math.max(0, width - 15)), C.dim],
207
+ ]),
208
+ ];
209
+ if (recentAuthoring.length > 0) {
210
+ extraHeader.push(buildPanelLine(width, [
211
+ [' Authoring: ', C.label],
212
+ [truncateDisplay(`${recentAuthoring[0]!.kind} ${recentAuthoring[0]!.target}`, Math.max(0, width - 14)), C.info],
213
+ ]));
214
+ }
215
+ if (lastSimulation) {
216
+ extraHeader.push(buildPanelLine(width, [
217
+ [' Last Simulation: ', C.label],
218
+ [truncateDisplay(lastSimulation.eventPath, Math.max(0, width - 20)), C.value],
219
+ ]));
220
+ }
221
+ return this.renderList(width, height, {
222
+ title: 'Hooks Control Room',
223
+ header: extraHeader,
224
+ });
225
+ }
226
+
227
+ return this.renderList(width, height, {
228
+ title: 'Hooks Control Room',
229
+ footer: [
230
+ ...detailLines,
231
+ buildPanelLine(width, [[' Recent Activity', C.label]]),
232
+ ...activityLines,
233
+ buildPanelLine(width, [[' Authoring', C.label]]),
234
+ ...authoringLines,
235
+ buildPanelLine(width, [[' Up/Down move r refresh /hooks for full contract listing', C.dim]]),
236
+ ],
237
+ });
238
+ }
239
+ }
@@ -0,0 +1,197 @@
1
+ import type { Line } from '../types/grid.ts';
2
+ import type { ForensicsRegistry } from '@/runtime/index.ts';
3
+ import { ScrollableListPanel } from './scrollable-list-panel.ts';
4
+ import {
5
+ buildBodyText,
6
+ buildEmptyState,
7
+ buildGuidanceLine,
8
+ buildKeyValueLine,
9
+ buildPanelLine,
10
+ buildPanelWorkspace,
11
+ buildStatusPill,
12
+ DEFAULT_PANEL_PALETTE,
13
+ type PanelPalette,
14
+ } from './polish.ts';
15
+ import type { FailureReport } from '@/runtime/index.ts';
16
+
17
+ const C = {
18
+ ...DEFAULT_PANEL_PALETTE,
19
+ header: '#cbd5e1',
20
+ headerBg: '#0f172a',
21
+ warn: '#f59e0b',
22
+ bad: '#ef4444',
23
+ selectBg: '#111827',
24
+ } as const;
25
+
26
+ function classificationColor(value: string): string {
27
+ switch (value) {
28
+ case 'cancelled':
29
+ return C.dim;
30
+ case 'max_tokens':
31
+ case 'unknown':
32
+ return C.warn;
33
+ default:
34
+ return C.bad;
35
+ }
36
+ }
37
+
38
+ export class IncidentReviewPanel extends ScrollableListPanel<FailureReport> {
39
+ private readonly registry?: ForensicsRegistry;
40
+ private readonly unsub: (() => void) | null;
41
+
42
+ public constructor(registry?: ForensicsRegistry) {
43
+ super('incident', 'Incident Review', 'N', 'monitoring');
44
+ this.showSelectionGutter = true; // I5: non-color selection affordance
45
+ this.registry = registry;
46
+ this.unsub = registry ? registry.subscribe(() => this.markDirty()) : null;
47
+ }
48
+
49
+ public override onDestroy(): void {
50
+ this.unsub?.();
51
+ }
52
+
53
+ protected override getPalette(): PanelPalette {
54
+ return C;
55
+ }
56
+
57
+ protected getItems(): readonly FailureReport[] {
58
+ return this.registry?.getAll() ?? [];
59
+ }
60
+
61
+ protected renderItem(report: FailureReport, index: number, selected: boolean, width: number): Line {
62
+ const bg = selected ? C.selectBg : undefined;
63
+ return buildPanelLine(width, [
64
+ [' ', C.label, bg],
65
+ [report.id.slice(0, 8).padEnd(9), C.dim, bg],
66
+ [report.classification.padEnd(20), classificationColor(report.classification), bg],
67
+ [report.summary.slice(0, Math.max(0, width - 31)), C.value, bg],
68
+ ]);
69
+ }
70
+
71
+ protected override getEmptyStateMessage(): string {
72
+ return ' No incidents recorded yet.';
73
+ }
74
+
75
+ protected override getEmptyStateActions(): Array<{ command: string; summary: string }> {
76
+ return [
77
+ { command: '/incident latest', summary: 'inspect the latest report once one exists' },
78
+ { command: '/recall capture incident latest', summary: 'promote incident evidence into project knowledge' },
79
+ ];
80
+ }
81
+
82
+ public render(width: number, height: number): Line[] {
83
+ const intro = 'Failure bundles, replay mismatches, permission fallout, and exportable review evidence.';
84
+
85
+ if (!this.registry) {
86
+ return buildPanelWorkspace(width, height, {
87
+ title: 'Incident Review Workspace',
88
+ intro,
89
+ sections: [{
90
+ lines: buildEmptyState(
91
+ width,
92
+ ' Forensics registry not wired into this panel yet.',
93
+ 'Incident review needs the live forensics registry so it can inspect failure bundles, replay mismatches, and causal evidence.',
94
+ [
95
+ { command: '/incident latest', summary: 'inspect the latest incident from the command surface' },
96
+ { command: '/security', summary: 'open the broader trust and incident posture control room' },
97
+ ],
98
+ C,
99
+ ),
100
+ }],
101
+ palette: C,
102
+ });
103
+ }
104
+
105
+ const reports = this.getItems();
106
+ if (reports.length === 0) {
107
+ return this.renderList(width, height, { title: 'Incident Review Workspace' });
108
+ }
109
+
110
+ this.clampSelection();
111
+ const selected = reports[this.selectedIndex]!;
112
+ const bundle = this.registry.buildBundle(selected.id);
113
+
114
+ const headerLines: Line[] = [
115
+ buildKeyValueLine(width, [
116
+ { label: 'incidents', value: String(reports.length), valueColor: C.value },
117
+ { label: 'selected', value: `${this.selectedIndex + 1}/${reports.length}`, valueColor: C.info },
118
+ { label: 'classification', value: selected.classification, valueColor: classificationColor(selected.classification) },
119
+ ], C),
120
+ buildPanelLine(width, [[' Up/Down move Home/End jump selected incident drives the action rail below', C.dim]]),
121
+ ];
122
+
123
+ const footerLines: Line[] = [];
124
+ if (bundle) {
125
+ footerLines.push(buildKeyValueLine(width, [
126
+ { label: 'id', value: selected.id, valueColor: C.dim },
127
+ { label: 'trace', value: selected.traceId, valueColor: C.dim },
128
+ ], C));
129
+ footerLines.push(...buildBodyText(width, `Root cause: ${bundle.evidence.rootCause ?? 'n/a'}`, C, C.value));
130
+ footerLines.push(buildKeyValueLine(width, [
131
+ { label: 'Permissions denied', value: String(bundle.evidence.deniedPermissionCount), valueColor: bundle.evidence.deniedPermissionCount > 0 ? C.warn : C.dim },
132
+ { label: 'Budget breaches', value: String(bundle.evidence.budgetBreachCount), valueColor: bundle.evidence.budgetBreachCount > 0 ? C.warn : C.dim },
133
+ { label: 'Replay mismatches', value: String(bundle.replay.mismatchCount), valueColor: bundle.replay.mismatchCount > 0 ? C.bad : C.dim },
134
+ ], C));
135
+ footerLines.push(buildPanelLine(width, [
136
+ [' Related IDs: ', C.label],
137
+ [`turn=${bundle.evidence.relatedIds.turnId ?? 'n/a'} task=${bundle.evidence.relatedIds.taskId ?? 'n/a'} agent=${bundle.evidence.relatedIds.agentId ?? 'n/a'}`.slice(0, Math.max(0, width - 14)), C.info],
138
+ ]));
139
+ if (bundle.evidence.slowPhases.length > 0) {
140
+ footerLines.push(buildPanelLine(width, [
141
+ [' Slow phases: ', C.label],
142
+ ...buildStatusPill('warn', bundle.evidence.slowPhases.join(', ').slice(0, Math.max(0, width - 15))),
143
+ ]));
144
+ }
145
+ const rootCause = selected.causalChain.find((entry) => entry.isRootCause);
146
+ if (rootCause) {
147
+ footerLines.push(buildPanelLine(width, [
148
+ [' Root event: ', C.label],
149
+ [`${rootCause.sourceEventType} - ${rootCause.description}`.slice(0, Math.max(0, width - 14)), C.dim],
150
+ ]));
151
+ }
152
+ const denied = selected.permissionEvidence.find((entry) => entry.approved === false);
153
+ if (denied) {
154
+ footerLines.push(buildPanelLine(width, [
155
+ [' Permission: ', C.label],
156
+ [`${denied.tool} denied${denied.riskLevel ? ` (${denied.riskLevel})` : ''}${denied.summary ? ` - ${denied.summary}` : ''}`.slice(0, Math.max(0, width - 14)), C.warn],
157
+ ]));
158
+ }
159
+ if (bundle.replay.relatedMismatches.length > 0) {
160
+ const mismatch = bundle.replay.relatedMismatches[0]!;
161
+ const ownerBreakdown = Object.entries(bundle.replay.mismatchBreakdown.byOwnerDomain)
162
+ .filter(([, count]) => count > 0)
163
+ .slice(0, 3)
164
+ .map(([domain, count]) => `${domain}:${count}`)
165
+ .join(', ');
166
+ const replayDetail = ownerBreakdown.length > 0
167
+ ? `Replay link: ${mismatch.kind}${mismatch.ownerDomain ? `/${mismatch.ownerDomain}` : ''} - ${mismatch.description} Replay owners: ${ownerBreakdown}`
168
+ : `Replay link: ${mismatch.kind}${mismatch.ownerDomain ? `/${mismatch.ownerDomain}` : ''} - ${mismatch.description}`;
169
+ footerLines.push(buildPanelLine(width, [
170
+ [' ', C.label],
171
+ ...buildStatusPill('bad', replayDetail.slice(0, Math.max(0, width - 2))),
172
+ ]));
173
+ } else {
174
+ const ownerBreakdown = Object.entries(bundle.replay.mismatchBreakdown.byOwnerDomain)
175
+ .filter(([, count]) => count > 0)
176
+ .slice(0, 3)
177
+ .map(([domain, count]) => `${domain}:${count}`)
178
+ .join(', ');
179
+ if (ownerBreakdown.length > 0) {
180
+ footerLines.push(buildPanelLine(width, [
181
+ [' Replay owners: ', C.label],
182
+ [ownerBreakdown.slice(0, Math.max(0, width - 17)), C.info],
183
+ ]));
184
+ }
185
+ }
186
+ }
187
+ footerLines.push(buildPanelLine(width, [[' Action Rail', C.label]]));
188
+ footerLines.push(buildPanelLine(width, [[` /incident latest /incident export ${selected.id} /recall capture incident ${selected.id}`, C.info]]));
189
+ footerLines.push(buildGuidanceLine(width, '/security', 'open the broader trust and incident posture control room', C));
190
+
191
+ return this.renderList(width, height, {
192
+ title: 'Incident Review Workspace',
193
+ header: headerLines,
194
+ footer: footerLines,
195
+ });
196
+ }
197
+ }
@@ -0,0 +1,46 @@
1
+ export type { Panel, PanelCategory, PanelRegistration } from './types.ts';
2
+ export type { Pane } from './panel-manager.ts';
3
+ export { BasePanel } from './base-panel.ts';
4
+ export { PanelManager } from './panel-manager.ts';
5
+ export { TokenBudgetPanel } from './token-budget-panel.ts';
6
+ export { CostTrackerPanel } from './cost-tracker-panel.ts';
7
+ export { AgentInspectorPanel } from './agent-inspector-panel.ts';
8
+ export { AgentLogsPanel } from './agent-logs-panel.ts';
9
+ export { WrfcPanel } from './wrfc-panel.ts';
10
+ export { ProviderHealthPanel } from './provider-health-panel.ts';
11
+ export { ProviderHealthTracker } from './provider-health-tracker.ts';
12
+ export type { ProviderHealth, ProviderStatus } from './provider-health-tracker.ts';
13
+ export { GitPanel } from './git-panel.ts';
14
+ export { SymbolOutlinePanel } from './symbol-outline-panel.ts';
15
+ export type { SymbolEntry, SymbolKind } from './symbol-outline-panel.ts';
16
+ export { ProviderStatsPanel } from './provider-stats-panel.ts';
17
+ export { SessionBrowserPanel } from './session-browser-panel.ts';
18
+ export { DocsPanel } from './docs-panel.ts';
19
+ export { ThinkingPanel } from './thinking-panel.ts';
20
+ export { ToolInspectorPanel } from './tool-inspector-panel.ts';
21
+ export { ContextVisualizerPanel } from './context-visualizer-panel.ts';
22
+ export { DebugPanel } from './debug-panel.ts';
23
+ export type { ApiCallEntry, ApiCallStatus } from './debug-panel.ts';
24
+ export { registerBuiltinPanels } from './builtin-panels.ts';
25
+ export type { BuiltinPanelDeps } from './builtin-panels.ts';
26
+ export { ForensicsPanel } from './forensics-panel.ts';
27
+ export { IncidentReviewPanel } from './incident-review-panel.ts';
28
+ export { PolicyPanel } from './policy-panel.ts';
29
+ export { PluginsPanel } from './plugins-panel.ts';
30
+ export { SkillsPanel } from './skills-panel.ts';
31
+ export { TasksPanel } from './tasks-panel.ts';
32
+ export { OrchestrationPanel } from './orchestration-panel.ts';
33
+ export { CommunicationPanel } from './communication-panel.ts';
34
+ export { CockpitPanel } from './cockpit-panel.ts';
35
+ export { RemotePanel } from './remote-panel.ts';
36
+ export { ServicesPanel } from './services-panel.ts';
37
+ export { SubscriptionPanel } from './subscription-panel.ts';
38
+ export { HooksPanel } from './hooks-panel.ts';
39
+ export { SecurityPanel } from './security-panel.ts';
40
+ export { MarketplacePanel } from './marketplace-panel.ts';
41
+ export { SandboxPanel } from './sandbox-panel.ts';
42
+ export { ApprovalPanel } from './approval-panel.ts';
43
+ export { KnowledgePanel } from './knowledge-panel.ts';
44
+ export { SystemMessagesPanel } from './system-messages-panel.ts';
45
+ export { PanelListPanel } from './panel-list-panel.ts';
46
+ export type { SystemMessageEntry, SystemMessagePriority } from './system-messages-panel.ts';
@@ -0,0 +1,176 @@
1
+ import type { Line } from '../types/grid.ts';
2
+ import { createEmptyLine } from '../types/grid.ts';
3
+ import { BasePanel } from './base-panel.ts';
4
+ import type { UiIntelligenceSnapshot, UiReadModel } from '../runtime/ui-read-models.ts';
5
+ import {
6
+ buildEmptyState,
7
+ buildGuidanceLine,
8
+ buildKeyValueLine,
9
+ buildPanelLine,
10
+ buildPanelWorkspace,
11
+ DEFAULT_PANEL_PALETTE,
12
+ type PanelWorkspaceSection,
13
+ } from './polish.ts';
14
+
15
+ const C = {
16
+ ...DEFAULT_PANEL_PALETTE,
17
+ good: '#22c55e',
18
+ warn: '#f59e0b',
19
+ bad: '#ef4444',
20
+ info: '#38bdf8',
21
+ headerBg: '#1e293b',
22
+ } as const;
23
+
24
+ function statusColor(status: string): string {
25
+ switch (status) {
26
+ case 'ready':
27
+ return C.good;
28
+ case 'loading':
29
+ return C.info;
30
+ case 'degraded':
31
+ return C.warn;
32
+ case 'unavailable':
33
+ default:
34
+ return C.bad;
35
+ }
36
+ }
37
+
38
+ export class IntelligencePanel extends BasePanel {
39
+ private readonly unsub: (() => void) | null;
40
+
41
+ public constructor(private readonly readModel?: UiReadModel<UiIntelligenceSnapshot>) {
42
+ super('intelligence', 'Intelligence', 'J', 'development');
43
+ this.unsub = readModel ? readModel.subscribe(() => this.markDirty()) : null;
44
+ }
45
+
46
+ public override onDestroy(): void {
47
+ this.unsub?.();
48
+ }
49
+
50
+ public render(width: number, height: number): Line[] {
51
+ this.needsRender = false;
52
+ if (!this.readModel) {
53
+ const lines = buildPanelWorkspace(width, height, {
54
+ title: 'Intelligence Control Room',
55
+ intro: 'Workspace intelligence posture across diagnostics, symbols, completions, and hover readiness.',
56
+ sections: [{
57
+ lines: buildEmptyState(
58
+ width,
59
+ ' Intelligence runtime store unavailable.',
60
+ 'This surface needs the live runtime store so it can show diagnostics, symbol readiness, and recovery guidance.',
61
+ [{ command: '/intelligence review', summary: 'review intelligence readiness from the command surface' }],
62
+ C,
63
+ ),
64
+ }],
65
+ palette: C,
66
+ });
67
+ while (lines.length < height) lines.push(createEmptyLine(width));
68
+ return lines.slice(0, height);
69
+ }
70
+
71
+ const state = this.readModel.getSnapshot();
72
+ const degraded = [
73
+ state.diagnosticsStatus,
74
+ state.completionsStatus,
75
+ state.symbolSearchStatus,
76
+ state.hoverStatus,
77
+ ].filter((status) => status !== 'ready').length;
78
+
79
+ const sections: PanelWorkspaceSection[] = [
80
+ {
81
+ title: 'Intelligence posture',
82
+ lines: [
83
+ buildKeyValueLine(width, [
84
+ { label: 'diagnostics', value: state.diagnosticsStatus, valueColor: statusColor(state.diagnosticsStatus) },
85
+ { label: 'symbols', value: state.symbolSearchStatus, valueColor: statusColor(state.symbolSearchStatus) },
86
+ { label: 'completions', value: state.completionsStatus, valueColor: statusColor(state.completionsStatus) },
87
+ { label: 'hover', value: state.hoverStatus, valueColor: statusColor(state.hoverStatus) },
88
+ ], C),
89
+ buildKeyValueLine(width, [
90
+ { label: 'errors', value: String(state.errorCount), valueColor: state.errorCount > 0 ? C.bad : C.dim },
91
+ { label: 'warnings', value: String(state.warningCount), valueColor: state.warningCount > 0 ? C.warn : C.dim },
92
+ { label: 'requests', value: String(state.totalRequests), valueColor: C.value },
93
+ { label: 'avg latency', value: `${Math.round(state.avgLatencyMs)}ms`, valueColor: C.info },
94
+ ], C),
95
+ ],
96
+ },
97
+ {
98
+ title: 'Next Actions',
99
+ lines: [
100
+ buildGuidanceLine(width, '/intelligence diagnostics', 'review readiness posture and current diagnostics activity', C),
101
+ buildGuidanceLine(width, '/intelligence repair', 'surface repair-oriented guidance when symbols, hover, or completions degrade', C),
102
+ ],
103
+ },
104
+ {
105
+ title: 'Readiness',
106
+ lines: [
107
+ buildPanelLine(width, [[` Diagnostics are ${state.diagnosticsStatus}. Symbol search is ${state.symbolSearchStatus}.`, state.diagnosticsStatus === 'ready' && state.symbolSearchStatus === 'ready' ? C.dim : C.warn]]),
108
+ buildPanelLine(width, [[` Hover is ${state.hoverStatus}. Completions are ${state.completionsStatus}.`, state.hoverStatus === 'ready' && state.completionsStatus === 'ready' ? C.dim : C.warn]]),
109
+ ...(state.hover.active && state.hover.filePath
110
+ ? [buildPanelLine(width, [[` Active hover: ${state.hover.filePath}`, C.info]])]
111
+ : []),
112
+ ],
113
+ },
114
+ ];
115
+
116
+ const diagnosticFiles = [...state.diagnostics.entries()]
117
+ .map(([filePath, diagnostics]) => ({
118
+ filePath,
119
+ errors: diagnostics.filter((entry) => entry.severity === 'error').length,
120
+ warnings: diagnostics.filter((entry) => entry.severity === 'warning').length,
121
+ }))
122
+ .sort((a, b) => (b.errors - a.errors) || (b.warnings - a.warnings) || a.filePath.localeCompare(b.filePath))
123
+ .slice(0, 4);
124
+ sections.push({
125
+ title: 'Diagnostics',
126
+ lines: diagnosticFiles.length > 0
127
+ ? diagnosticFiles.map((entry) => buildPanelLine(width, [[
128
+ ` ${entry.filePath} errors=${entry.errors} warnings=${entry.warnings}`,
129
+ entry.errors > 0 ? C.bad : entry.warnings > 0 ? C.warn : C.dim,
130
+ ]]))
131
+ : [buildPanelLine(width, [[' No tracked diagnostics yet.', C.dim]])],
132
+ });
133
+
134
+ sections.push({
135
+ title: 'Workflows',
136
+ lines: [
137
+ buildGuidanceLine(width, '/intelligence symbols <file>', 'inspect document symbols for a file and verify symbol-surface readiness', C),
138
+ buildGuidanceLine(width, '/intelligence outline <file>', 'review structural outline extraction without leaving the control room', C),
139
+ buildGuidanceLine(width, '/intelligence definition <file> <line> <column>', 'check definition lookup for an exact source position', C),
140
+ buildGuidanceLine(width, '/intelligence references <file> <line> <column>', 'review reference lookup for a symbol under the cursor', C),
141
+ buildGuidanceLine(width, '/intelligence hover <file> <line> <column>', 'inspect hover/details posture for a specific source position', C),
142
+ ],
143
+ });
144
+
145
+ if (degraded > 0) {
146
+ sections.push({
147
+ title: 'Recovery',
148
+ lines: [
149
+ buildPanelLine(width, [[' Workspace intelligence is not fully ready. Review LSP/tree-sitter setup and workspace language configuration.', C.warn]]),
150
+ buildGuidanceLine(width, '/health review', 'check setup and readiness failures that could block diagnostics and symbol search', C),
151
+ buildGuidanceLine(width, '/setup review', 'review startup and environment posture for intelligence dependencies', C),
152
+ buildGuidanceLine(width, '/intelligence repair', 'show repair-oriented commands for diagnostics, symbols, hover, and completions', C),
153
+ buildGuidanceLine(width, '/health repair intelligence', 'show repair commands plus post-repair verification for the intelligence domain', C),
154
+ ],
155
+ });
156
+ } else {
157
+ sections.push({
158
+ title: 'Recovery',
159
+ lines: [
160
+ buildPanelLine(width, [[' Intelligence surfaces are healthy and ready for code-aware workflows.', C.dim]]),
161
+ buildGuidanceLine(width, '/health intelligence', 'verify readiness posture after setup changes or dependency recovery', C),
162
+ ],
163
+ });
164
+ }
165
+
166
+ const lines = buildPanelWorkspace(width, height, {
167
+ title: 'Intelligence Control Room',
168
+ intro: 'Workspace intelligence posture across diagnostics, symbol search, hover, and completion readiness.',
169
+ sections,
170
+ footerLines: [buildPanelLine(width, [[' /symbols /intelligence diagnostics /intelligence symbols <file> /intelligence definition <file> <line> <column> ', C.dim]])],
171
+ palette: C,
172
+ });
173
+ while (lines.length < height) lines.push(createEmptyLine(width));
174
+ return lines.slice(0, height);
175
+ }
176
+ }