@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,394 @@
1
+ import { resolve } from 'path';
2
+ import type { PluginStatus } from '@pellux/goodvibes-sdk/platform/plugins';
3
+ import { getPluginDirectories, getUserPluginDirectory } from '../../plugins/loader';
4
+ import type { CommandRegistry } from '../command-registry.ts';
5
+ import {
6
+ installEcosystemCatalogEntry,
7
+ listInstalledEcosystemEntries,
8
+ loadEcosystemCatalog,
9
+ removeEcosystemCatalogEntry,
10
+ reviewEcosystemCatalogEntry,
11
+ searchEcosystemCatalog,
12
+ updateInstalledEcosystemEntry,
13
+ upsertEcosystemCatalogEntry,
14
+ uninstallEcosystemCatalogEntry,
15
+ } from '@/runtime/index.ts';
16
+ import { requireEcosystemCatalogPaths, requirePluginPathOptions } from './runtime-services.ts';
17
+
18
+ export function registerIntegrationRuntimeCommands(registry: CommandRegistry): void {
19
+ registry.register({
20
+ name: 'plugin',
21
+ aliases: [],
22
+ description: 'Manage plugins, trust, review, and ecosystem paths',
23
+ usage: 'list | dirs | inspect <name> | review | installed | catalog-review <id> | publish-local <id> <path> <summary...> | unpublish <id> | install <id> [project|user] | update <id> [project|user] | uninstall <id> [project|user] | enable <name> | disable <name> | reload',
24
+ argsHint: 'list | dirs | inspect | review | installed | catalog-review | publish-local | unpublish | install | update | uninstall | enable | disable | reload',
25
+ async handler(args, ctx) {
26
+ const pluginManager = ctx.extensions.pluginManager;
27
+ const ecosystemPaths = requireEcosystemCatalogPaths(ctx);
28
+ const pluginPaths = requirePluginPathOptions(ctx);
29
+ if (!pluginManager) {
30
+ ctx.print('Plugin manager is not available in this runtime.');
31
+ return;
32
+ }
33
+ const sub = args[0];
34
+
35
+ if (!sub || sub === 'open' || sub === 'panel') {
36
+ if (ctx.showPanel) ctx.showPanel('plugins');
37
+ return;
38
+ }
39
+
40
+ if (sub === 'list') {
41
+ const plugins = pluginManager.list() as PluginStatus[];
42
+ if (plugins.length === 0) {
43
+ const directories = getPluginDirectories(pluginPaths)
44
+ .map((dir) => ` ${dir}`)
45
+ .join('\n');
46
+ ctx.print(
47
+ `No plugins installed.\nPlugin search directories:\n${directories}\nPlace a plugin folder in one of those locations with manifest.json and index.ts.`
48
+ );
49
+ return;
50
+ }
51
+ const lines: string[] = ['Installed plugins:'];
52
+ for (const p of plugins) {
53
+ const statusIcon = p.active ? '[active] ' : p.enabled ? '[loading] ' : '[disabled]';
54
+ lines.push(` ${statusIcon} ${p.name.padEnd(24)} v${p.version} — ${p.description}`);
55
+ if (p.author) lines.push(` by ${p.author}`);
56
+ }
57
+ lines.push('');
58
+ lines.push('Use /plugin enable <name> or /plugin disable <name> to toggle plugins.');
59
+ ctx.print(lines.join('\n'));
60
+ return;
61
+ }
62
+ if (sub === 'dirs') {
63
+ const directories = getPluginDirectories(pluginPaths);
64
+ ctx.print([
65
+ 'Plugin Search Directories',
66
+ ...directories.map((dir) => ` ${dir}`),
67
+ '',
68
+ `User plugin directory: ${getUserPluginDirectory(pluginPaths)}`,
69
+ ].join('\n'));
70
+ return;
71
+ }
72
+ if (sub === 'inspect') {
73
+ const name = args[1];
74
+ if (!name) {
75
+ ctx.print('Usage: /plugin inspect <name>');
76
+ return;
77
+ }
78
+ const status = pluginManager.list().find((plugin) => plugin.name === name);
79
+ if (!status) {
80
+ ctx.print(`Error: Plugin '${name}' not found.`);
81
+ return;
82
+ }
83
+ const capabilities = pluginManager.capabilities(name);
84
+ const trust = pluginManager.getTrustRecord(name);
85
+ const quarantine = pluginManager.getQuarantineRecord(name);
86
+ ctx.print([
87
+ `Plugin ${name}`,
88
+ ` version: ${status.version}`,
89
+ ` state: ${status.active ? 'active' : status.enabled ? 'enabled' : 'disabled'}`,
90
+ ` trustTier: ${status.trustTier}`,
91
+ ` quarantined: ${status.quarantined ? 'yes' : 'no'}`,
92
+ ` requestedCapabilities: ${capabilities?.requested.length ?? 0}`,
93
+ ` highRiskCapabilities: ${capabilities?.highRisk.length ?? 0}`,
94
+ ` blockedCapabilities: ${capabilities?.blocked.length ?? 0}`,
95
+ ` signedFingerprint: ${trust?.signatureFingerprint ?? 'n/a'}`,
96
+ ` quarantineReason: ${quarantine?.reason ?? 'n/a'}`,
97
+ ].join('\n'));
98
+ return;
99
+ }
100
+ if (sub === 'review') {
101
+ const plugins = pluginManager.list();
102
+ ctx.print([
103
+ 'Plugin Security Review',
104
+ ` total: ${plugins.length}`,
105
+ ` active: ${plugins.filter((plugin) => plugin.active).length}`,
106
+ ` trusted: ${plugins.filter((plugin) => plugin.trustTier === 'trusted').length}`,
107
+ ` limited: ${plugins.filter((plugin) => plugin.trustTier === 'limited').length}`,
108
+ ` untrusted: ${plugins.filter((plugin) => plugin.trustTier === 'untrusted').length}`,
109
+ ` quarantined: ${plugins.filter((plugin) => plugin.quarantined).length}`,
110
+ ].join('\n'));
111
+ return;
112
+ }
113
+ if (sub === 'browse' || sub === 'catalog') {
114
+ const query = args.slice(1).join(' ');
115
+ const entries = query
116
+ ? searchEcosystemCatalog('plugin', query, ecosystemPaths)
117
+ : loadEcosystemCatalog('plugin', ecosystemPaths);
118
+ if (entries.length === 0) {
119
+ ctx.print(query
120
+ ? `No curated plugin catalog entries matched "${query}".`
121
+ : 'No curated plugin catalog entries found. Add .goodvibes/agent/ecosystem/plugins.json to publish a local-first plugin catalog.');
122
+ return;
123
+ }
124
+ ctx.print([
125
+ `Curated Plugin Catalog (${entries.length})`,
126
+ ...entries.map((entry) => ` ${entry.id} ${entry.name} [${entry.tags.join(', ') || 'untagged'}] ${entry.summary}`),
127
+ ].join('\n'));
128
+ return;
129
+ }
130
+ if (sub === 'installed') {
131
+ const receipts = listInstalledEcosystemEntries('plugin', ecosystemPaths);
132
+ if (receipts.length === 0) {
133
+ ctx.print('No curated plugins installed from local catalogs yet.');
134
+ return;
135
+ }
136
+ ctx.print([
137
+ `Installed Curated Plugins (${receipts.length})`,
138
+ ...receipts.map((receipt) => ` ${receipt.entry.id} ${receipt.scope} ${receipt.targetPath}`),
139
+ ].join('\n'));
140
+ return;
141
+ }
142
+ if (sub === 'catalog-review') {
143
+ const entryId = args[1];
144
+ if (!entryId) {
145
+ ctx.print('Usage: /plugin catalog-review <catalog-id>');
146
+ return;
147
+ }
148
+ const entry = loadEcosystemCatalog('plugin', ecosystemPaths).find((candidate) => candidate.id === entryId);
149
+ if (!entry) {
150
+ ctx.print(`Unknown curated plugin entry: ${entryId}`);
151
+ return;
152
+ }
153
+ const review = reviewEcosystemCatalogEntry(entry, ecosystemPaths);
154
+ ctx.print([
155
+ `Plugin Catalog Review: ${entry.name}`,
156
+ ` id: ${entry.id}`,
157
+ ` source: ${entry.source}`,
158
+ ` sourceKind: ${review.sourceKind}`,
159
+ ` sourceExists: ${review.sourceExists ? 'yes' : 'no'}`,
160
+ ` recommendedScope: ${review.recommendedScope}`,
161
+ ` risk: ${review.riskLevel}`,
162
+ ` trust notes: ${entry.trustNotes ?? '(none)'}`,
163
+ ` provenance: ${entry.provenance ?? '(none)'}`,
164
+ ` update hint: ${entry.updateHint ?? '(none)'}`,
165
+ ].join('\n'));
166
+ return;
167
+ }
168
+ if (sub === 'install-hint') {
169
+ const entryId = args[1];
170
+ if (!entryId) {
171
+ ctx.print('Usage: /plugin install-hint <catalog-id>');
172
+ return;
173
+ }
174
+ const entry = loadEcosystemCatalog('plugin', ecosystemPaths).find((candidate) => candidate.id === entryId);
175
+ if (!entry) {
176
+ ctx.print(`Unknown curated plugin entry: ${entryId}`);
177
+ return;
178
+ }
179
+ ctx.print([
180
+ `Plugin Install Guidance: ${entry.name}`,
181
+ ` id: ${entry.id}`,
182
+ ` source: ${entry.source}`,
183
+ ` tags: ${entry.tags.join(', ') || '(none)'}`,
184
+ ` trust notes: ${entry.trustNotes ?? '(none)'}`,
185
+ ` install hint: ${entry.installHint ?? 'Place the plugin under a configured plugin search directory and use /plugin reload.'}`,
186
+ ].join('\n'));
187
+ return;
188
+ }
189
+ if (sub === 'publish-local') {
190
+ const entryId = args[1];
191
+ const sourcePath = args[2];
192
+ const summary = args.slice(3).join(' ').trim();
193
+ if (!entryId || !sourcePath || !summary) {
194
+ ctx.print('Usage: /plugin publish-local <catalog-id> <path> <summary...>');
195
+ return;
196
+ }
197
+ const result = upsertEcosystemCatalogEntry({
198
+ id: entryId,
199
+ kind: 'plugin',
200
+ name: entryId.replace(/[-_]/g, ' ').replace(/\b\w/g, (char) => char.toUpperCase()),
201
+ summary,
202
+ source: sourcePath,
203
+ tags: ['local-first', 'published'],
204
+ provenance: 'operator-published',
205
+ updateHint: 'Use /plugin publish-local again to refresh catalog metadata after edits.',
206
+ }, ecosystemPaths);
207
+ ctx.print(result.ok
208
+ ? `Published curated plugin ${entryId} into ${result.path}`
209
+ : `Error: ${result.error}`);
210
+ return;
211
+ }
212
+ if (sub === 'unpublish') {
213
+ const entryId = args[1];
214
+ if (!entryId) {
215
+ ctx.print('Usage: /plugin unpublish <catalog-id>');
216
+ return;
217
+ }
218
+ const result = removeEcosystemCatalogEntry('plugin', entryId, ecosystemPaths);
219
+ ctx.print(result.ok
220
+ ? `Removed curated plugin ${entryId} from ${result.path}`
221
+ : `Error: ${result.error}`);
222
+ return;
223
+ }
224
+ if (sub === 'install') {
225
+ const entryId = args[1];
226
+ const scopeArg = args[2];
227
+ if (!entryId) {
228
+ ctx.print('Usage: /plugin install <catalog-id> [project|user]');
229
+ return;
230
+ }
231
+ const scope = scopeArg === 'user' ? 'user' : 'project';
232
+ const result = installEcosystemCatalogEntry('plugin', entryId, { ...ecosystemPaths, scope });
233
+ ctx.print(result.ok
234
+ ? `Installed curated plugin ${entryId} into ${result.receipt.targetPath}`
235
+ : `Error: ${result.error}`);
236
+ return;
237
+ }
238
+ if (sub === 'update') {
239
+ const entryId = args[1];
240
+ const scopeArg = args[2];
241
+ if (!entryId) {
242
+ ctx.print('Usage: /plugin update <catalog-id> [project|user]');
243
+ return;
244
+ }
245
+ const scope = scopeArg === 'user' ? 'user' : 'project';
246
+ const result = updateInstalledEcosystemEntry('plugin', entryId, { ...ecosystemPaths, scope });
247
+ ctx.print(result.ok
248
+ ? `Updated curated plugin ${entryId} in ${result.receipt.targetPath}`
249
+ : `Error: ${result.error}`);
250
+ return;
251
+ }
252
+ if (sub === 'uninstall') {
253
+ const entryId = args[1];
254
+ const scopeArg = args[2];
255
+ if (!entryId) {
256
+ ctx.print('Usage: /plugin uninstall <catalog-id> [project|user]');
257
+ return;
258
+ }
259
+ const scope = scopeArg === 'user' ? 'user' : 'project';
260
+ const result = uninstallEcosystemCatalogEntry('plugin', entryId, { ...ecosystemPaths, scope });
261
+ ctx.print(result.ok
262
+ ? `Uninstalled curated plugin ${entryId} from ${result.removedPath}`
263
+ : `Error: ${result.error}`);
264
+ return;
265
+ }
266
+ if (sub === 'enable') {
267
+ const name = args[1];
268
+ if (!name) { ctx.print('Usage: /plugin enable <name>'); return; }
269
+ const result = await pluginManager.enable(name);
270
+ ctx.print(result.ok ? `Plugin '${name}' enabled and activated.` : `Error: ${result.error}`);
271
+ return;
272
+ }
273
+ if (sub === 'disable') {
274
+ const name = args[1];
275
+ if (!name) { ctx.print('Usage: /plugin disable <name>'); return; }
276
+ const result = await pluginManager.disable(name);
277
+ ctx.print(result.ok ? `Plugin '${name}' disabled.` : `Error: ${result.error}`);
278
+ return;
279
+ }
280
+ if (sub === 'reload') {
281
+ ctx.print('Reloading plugins...');
282
+ const { reloaded, failed } = await pluginManager.reload();
283
+ ctx.print(`Done. ${reloaded} plugin(s) reloaded${failed > 0 ? `, ${failed} failed` : ''}.`);
284
+ return;
285
+ }
286
+ if (sub === 'trust') {
287
+ const name = args[1];
288
+ const rawTier = args[2];
289
+ if (!name || !rawTier) {
290
+ ctx.print('Usage: /plugin trust <name> <untrusted|limited|trusted> [note]');
291
+ return;
292
+ }
293
+ if (rawTier !== 'untrusted' && rawTier !== 'limited' && rawTier !== 'trusted') {
294
+ ctx.print(`Error: Invalid trust tier '${rawTier}'. Must be: untrusted, limited, or trusted.`);
295
+ return;
296
+ }
297
+ const tier = rawTier as 'untrusted' | 'limited' | 'trusted';
298
+ const note = args.slice(3).join(' ') || undefined;
299
+ if (tier === 'trusted') {
300
+ const sigResult = pluginManager.trustSigned(name);
301
+ if (sigResult.ok) {
302
+ ctx.print(`Plugin '${name}' elevated to 'trusted' via signed manifest${sigResult.fingerprint ? ` (fingerprint: ${sigResult.fingerprint})` : ''}.\nReload the plugin to apply updated capability grants.`);
303
+ return;
304
+ }
305
+ ctx.print(`Warning: Signature validation failed (${sigResult.error}).\nGranting 'trusted' tier by operator override. High-risk capabilities will be available on next reload.`);
306
+ }
307
+ const result = pluginManager.trust(name, tier, note);
308
+ ctx.print(result.ok
309
+ ? `Plugin '${name}' trust tier set to '${tier}'.${tier === 'trusted' ? '\nReload the plugin to apply high-risk capability grants.' : ''}`
310
+ : `Error: ${result.error}`);
311
+ return;
312
+ }
313
+ if (sub === 'verify') {
314
+ const name = args[1];
315
+ if (!name) { ctx.print('Usage: /plugin verify <name>'); return; }
316
+ const result = pluginManager.verify(name);
317
+ if (!result.ok && result.reason?.includes('not found')) {
318
+ ctx.print(`Error: ${result.reason}`);
319
+ return;
320
+ }
321
+ ctx.print(result.valid
322
+ ? `Plugin '${name}' manifest signature is VALID.${result.fingerprint ? `\nFingerprint: ${result.fingerprint}` : ''}`
323
+ : `Plugin '${name}' manifest signature is INVALID.\nReason: ${result.reason ?? 'Unknown'}`);
324
+ return;
325
+ }
326
+ if (sub === 'capabilities') {
327
+ const name = args[1];
328
+ if (!name) { ctx.print('Usage: /plugin capabilities <name>'); return; }
329
+ const info = pluginManager.capabilities(name);
330
+ if (!info) {
331
+ ctx.print(`Error: Plugin '${name}' not found.`);
332
+ return;
333
+ }
334
+ const lines: string[] = [`Plugin: ${name}`, `Trust tier: ${info.tier}`, '', `Requested capabilities (${info.requested.length}):`];
335
+ if (info.requested.length === 0) lines.push(' (none)');
336
+ else {
337
+ for (const cap of info.requested) {
338
+ const tag = info.blocked.includes(cap)
339
+ ? '[BLOCKED - requires trusted tier]'
340
+ : info.highRisk.includes(cap) ? '[high-risk, granted]' : '[safe]';
341
+ lines.push(` ${cap.padEnd(32)} ${tag}`);
342
+ }
343
+ }
344
+ if (info.blocked.length > 0) {
345
+ lines.push('');
346
+ lines.push(`${info.blocked.length} high-risk capability/capabilities blocked by trust tier '${info.tier}'.`);
347
+ lines.push(`Use /plugin trust ${name} trusted to escalate.`);
348
+ }
349
+ ctx.print(lines.join('\n'));
350
+ return;
351
+ }
352
+ if (sub === 'quarantine') {
353
+ const name = args[1];
354
+ const action = args[2] ?? 'add';
355
+ if (!name) {
356
+ ctx.print('Usage: /plugin quarantine <name> [add|lift] [reason]');
357
+ return;
358
+ }
359
+ if (action === 'lift') {
360
+ const result = pluginManager.liftQuarantine(name);
361
+ ctx.print(result.ok ? `Plugin '${name}' quarantine lifted. Reload to restore safe capabilities.` : `Error: ${result.error}`);
362
+ return;
363
+ }
364
+ const reason = args.slice(2).join(' ') || 'quarantined by operator';
365
+ const result = pluginManager.quarantine(name, reason);
366
+ ctx.print(result.ok
367
+ ? `Plugin '${name}' quarantined.\nReason: ${reason}\nHigh-risk capabilities revoked. Reload to fully apply. Use /plugin quarantine <name> lift to restore.`
368
+ : `Error: ${result.error}`);
369
+ return;
370
+ }
371
+
372
+ ctx.print(
373
+ 'Usage: /plugin <subcommand>\n'
374
+ + ' list — show installed plugins and their status\n'
375
+ + ' enable <name> — enable a plugin\n'
376
+ + ' disable <name> — disable a plugin\n'
377
+ + ' reload — reload all enabled plugins\n'
378
+ + ' trust <name> <tier> [note] — set trust tier (untrusted|limited|trusted)\n'
379
+ + ' verify <name> — inspect a plugin manifest signature\n'
380
+ + ' capabilities <name> — show capability grants and blocks\n'
381
+ + ' browse [query] — browse curated local-first plugin catalog entries\n'
382
+ + ' installed — list curated catalog installs with provenance receipts\n'
383
+ + ' catalog-review <id> — review source, provenance, and risk for a curated plugin\n'
384
+ + ' publish-local <id> <path> <summary...> — publish a local plugin directory into the curated catalog\n'
385
+ + ' unpublish <id> — remove a local curated plugin catalog entry\n'
386
+ + ' install-hint <catalog-id> — show install guidance for a curated plugin entry\n'
387
+ + ' install <catalog-id> [scope] — install a local-path curated plugin into project|user scope\n'
388
+ + ' uninstall <catalog-id> [scope] — remove a curated plugin install receipt and target path\n'
389
+ + ' quarantine <name> [reason] — quarantine a plugin (revoke high-risk caps)\n'
390
+ + ' quarantine <name> lift — lift quarantine from a plugin'
391
+ );
392
+ },
393
+ });
394
+ }
@@ -0,0 +1,223 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import type { CommandContext, CommandRegistry } from '../command-registry.ts';
4
+ import { CodeIntelligence } from '@pellux/goodvibes-sdk/platform/intelligence';
5
+ import type { DocumentSymbol } from '@pellux/goodvibes-sdk/platform/intelligence';
6
+ import type { SymbolInfo } from '@pellux/goodvibes-sdk/platform/intelligence';
7
+ import { openCommandPanel, requireReadModels, requireShellPaths } from './runtime-services.ts';
8
+
9
+ function resolveTargetPath(pathArg: string, ctx: CommandContext): string {
10
+ return requireShellPaths(ctx).resolveWorkspacePath(pathArg);
11
+ }
12
+
13
+ function parsePosition(lineArg: string | undefined, columnArg: string | undefined): { line: number; column: number } | null {
14
+ const line = Number.parseInt(lineArg ?? '', 10);
15
+ const column = Number.parseInt(columnArg ?? '', 10);
16
+ if (!Number.isFinite(line) || line < 1 || !Number.isFinite(column) || column < 1) return null;
17
+ return { line: line - 1, column: column - 1 };
18
+ }
19
+
20
+ function formatSymbolKind(kind: number | string | undefined): string {
21
+ if (typeof kind === 'number') return `kind=${kind}`;
22
+ if (typeof kind === 'string' && kind.trim().length > 0) return kind;
23
+ return 'symbol';
24
+ }
25
+
26
+ function formatDocumentSymbol(symbol: DocumentSymbol): string {
27
+ const line = (symbol.selectionRange?.start.line ?? symbol.range.start.line) + 1;
28
+ const column = (symbol.selectionRange?.start.character ?? symbol.range.start.character) + 1;
29
+ return ` ${symbol.name} ${formatSymbolKind(symbol.kind)} ${line}:${column}`;
30
+ }
31
+
32
+ function formatTreeSitterSymbol(symbol: SymbolInfo): string {
33
+ return ` ${symbol.name} ${formatSymbolKind(symbol.kind)} ${symbol.line + 1}:${symbol.column + 1}`;
34
+ }
35
+
36
+ function ensureExistingFile(pathArg: string | undefined, ctx: CommandContext): string | null {
37
+ if (!pathArg) {
38
+ ctx.print('Intelligence Review\n Missing file path.');
39
+ return null;
40
+ }
41
+ const targetPath = resolveTargetPath(pathArg, ctx);
42
+ if (!existsSync(targetPath)) {
43
+ ctx.print(`Intelligence Review\n File not found: ${targetPath}`);
44
+ return null;
45
+ }
46
+ return targetPath;
47
+ }
48
+
49
+ export function registerIntelligenceRuntimeCommands(registry: CommandRegistry): void {
50
+ registry.register({
51
+ name: 'intelligence',
52
+ aliases: ['intel'],
53
+ description: 'Review workspace intelligence readiness, diagnostics posture, and symbol search availability',
54
+ usage: '[review|panel|diagnostics [file]|symbols <file>|outline <file>|definition <file> <line> <column>|references <file> <line> <column>|hover <file> <line> <column>|repair]',
55
+ async handler(args, ctx) {
56
+ const sub = (args[0] ?? 'review').toLowerCase();
57
+ if (sub === 'panel' || sub === 'open') {
58
+ openCommandPanel(ctx, 'intelligence');
59
+ return;
60
+ }
61
+
62
+ const intelligence = new CodeIntelligence();
63
+ const state = requireReadModels(ctx).intelligence.getSnapshot();
64
+
65
+ if (sub === 'symbols' || sub === 'outline') {
66
+ const targetPath = ensureExistingFile(args[1], ctx);
67
+ if (!targetPath) return;
68
+ const content = readFileSync(targetPath, 'utf-8');
69
+ if (sub === 'symbols') {
70
+ const symbols = await intelligence.getDocumentSymbols(targetPath, content);
71
+ const entries = symbols.slice(0, 12).map((symbol) => ('selectionRange' in symbol ? formatDocumentSymbol(symbol) : formatTreeSitterSymbol(symbol)));
72
+ ctx.print([
73
+ `Intelligence Symbols: ${targetPath}`,
74
+ ` source: ${state.symbolSearchStatus === 'ready' ? 'LSP/tree-sitter' : 'best-effort tree-sitter/LSP fallback'}`,
75
+ ` status: ${state.symbolSearchStatus}`,
76
+ ` results: ${symbols.length}`,
77
+ ...(entries.length > 0 ? entries : [' No symbols available for this file.']),
78
+ ' next: /health intelligence',
79
+ ].join('\n'));
80
+ return;
81
+ }
82
+
83
+ const outline = await intelligence.getOutline(targetPath, content);
84
+ ctx.print([
85
+ `Intelligence Outline: ${targetPath}`,
86
+ ` source: tree-sitter outline extraction`,
87
+ ` language ready: ${intelligence.hasTreeSitter(targetPath) ? 'yes' : 'no'}`,
88
+ ` results: ${outline.length}`,
89
+ ...(outline.slice(0, 12).map((entry) => ` ${entry.signature || entry.name} line ${entry.line}`)),
90
+ ...(outline.length === 0 ? [' No outline entries available for this file.'] : []),
91
+ ' next: /intelligence symbols ' + targetPath,
92
+ ].join('\n'));
93
+ return;
94
+ }
95
+
96
+ if (sub === 'definition' || sub === 'references' || sub === 'hover') {
97
+ const targetPath = ensureExistingFile(args[1], ctx);
98
+ if (!targetPath) return;
99
+ const position = parsePosition(args[2], args[3]);
100
+ if (!position) {
101
+ ctx.print(`Intelligence ${sub[0]!.toUpperCase()}${sub.slice(1)}\n Usage: /intelligence ${sub} <file> <line> <column>`);
102
+ return;
103
+ }
104
+
105
+ if (sub === 'definition') {
106
+ const definition = await intelligence.getDefinition(targetPath, position.line, position.column);
107
+ ctx.print([
108
+ `Intelligence Definition: ${targetPath}:${position.line + 1}:${position.column + 1}`,
109
+ ` status: ${state.hoverStatus === 'ready' || state.symbolSearchStatus === 'ready' ? 'available' : 'best-effort'}`,
110
+ ...(definition
111
+ ? [
112
+ ` target: ${definition.uri}`,
113
+ ` line: ${definition.range.start.line + 1}`,
114
+ ` column: ${definition.range.start.character + 1}`,
115
+ ' next: open the target file or use /intelligence references on the same symbol',
116
+ ]
117
+ : [' No definition was returned for that position.', ' next: /health intelligence']),
118
+ ].join('\n'));
119
+ return;
120
+ }
121
+
122
+ if (sub === 'references') {
123
+ const references = await intelligence.getReferences(targetPath, position.line, position.column);
124
+ ctx.print([
125
+ `Intelligence References: ${targetPath}:${position.line + 1}:${position.column + 1}`,
126
+ ` status: ${state.symbolSearchStatus}`,
127
+ ` results: ${references.length}`,
128
+ ...(references.slice(0, 12).map((reference) => ` ${reference.uri} ${reference.range.start.line + 1}:${reference.range.start.character + 1}`)),
129
+ ...(references.length === 0 ? [' No references were returned for that position.'] : []),
130
+ ' next: /intelligence definition ' + `${targetPath} ${position.line + 1} ${position.column + 1}`,
131
+ ].join('\n'));
132
+ return;
133
+ }
134
+
135
+ const hover = await intelligence.getHover(targetPath, position.line, position.column);
136
+ const hoverLines = typeof hover?.contents === 'string'
137
+ ? hover.contents.split('\n')
138
+ : Array.isArray(hover?.contents)
139
+ ? hover.contents.flatMap((entry) => typeof entry === 'string' ? entry : entry.value.split('\n'))
140
+ : hover?.contents && 'value' in hover.contents
141
+ ? hover.contents.value.split('\n')
142
+ : [];
143
+ ctx.print([
144
+ `Intelligence Hover: ${targetPath}:${position.line + 1}:${position.column + 1}`,
145
+ ` status: ${state.hoverStatus}`,
146
+ ...(hoverLines.length > 0 ? hoverLines.slice(0, 8).map((line) => ` ${line}`) : [' No hover information was returned for that position.']),
147
+ ' next: /health intelligence',
148
+ ].join('\n'));
149
+ return;
150
+ }
151
+
152
+ if (sub === 'diagnostics') {
153
+ const file = args[1];
154
+ const entries = [...state.diagnostics.entries()]
155
+ .map(([filePath, diagnostics]) => ({
156
+ filePath,
157
+ diagnostics,
158
+ errors: diagnostics.filter((entry) => entry.severity === 'error').length,
159
+ warnings: diagnostics.filter((entry) => entry.severity === 'warning').length,
160
+ }))
161
+ .sort((a, b) => (b.errors - a.errors) || (b.warnings - a.warnings) || a.filePath.localeCompare(b.filePath));
162
+ const selected = file
163
+ ? entries.find((entry) => entry.filePath === file)
164
+ : entries[0];
165
+ if (!selected) {
166
+ ctx.print('Intelligence Diagnostics\n No diagnostics are currently tracked.');
167
+ return;
168
+ }
169
+ ctx.print([
170
+ `Intelligence Diagnostics: ${selected.filePath}`,
171
+ ` errors: ${selected.errors}`,
172
+ ` warnings: ${selected.warnings}`,
173
+ ...selected.diagnostics.slice(0, 8).map((diagnostic) => (
174
+ ` [${diagnostic.severity}] ${diagnostic.line + 1}:${diagnostic.column + 1} ${diagnostic.message}`
175
+ )),
176
+ ...(entries.length > 1 ? [` next: /intelligence diagnostics ${entries[1]!.filePath}`] : []),
177
+ ].join('\n'));
178
+ return;
179
+ }
180
+
181
+ if (sub === 'repair') {
182
+ const lines = [
183
+ 'Intelligence Repair',
184
+ ' verify: /health intelligence',
185
+ ...(state.diagnosticsStatus !== 'ready' ? [' /setup review', ' /health intelligence'] : []),
186
+ ...(state.symbolSearchStatus !== 'ready' ? [' /symbols', ' /intelligence symbols <file>', ' /health intelligence'] : []),
187
+ ...(state.completionsStatus !== 'ready' || state.hoverStatus !== 'ready'
188
+ ? [' /intelligence review', ' /intelligence hover <file> <line> <column>', ' /setup onboarding']
189
+ : []),
190
+ ];
191
+ ctx.print(lines.length > 1 ? lines.join('\n') : 'Intelligence Repair\n No active repair actions suggested.');
192
+ return;
193
+ }
194
+
195
+ const issues: string[] = [];
196
+ if (state.diagnosticsStatus !== 'ready') issues.push(`diagnostics=${state.diagnosticsStatus}`);
197
+ if (state.symbolSearchStatus !== 'ready') issues.push(`symbols=${state.symbolSearchStatus}`);
198
+ if (state.completionsStatus !== 'ready') issues.push(`completions=${state.completionsStatus}`);
199
+ if (state.hoverStatus !== 'ready') issues.push(`hover=${state.hoverStatus}`);
200
+
201
+ ctx.print([
202
+ 'Intelligence Review',
203
+ ` diagnostics: ${state.diagnosticsStatus}`,
204
+ ` symbols: ${state.symbolSearchStatus}`,
205
+ ` completions: ${state.completionsStatus}`,
206
+ ` hover: ${state.hoverStatus}`,
207
+ ` errors: ${state.errorCount}`,
208
+ ` warnings: ${state.warningCount}`,
209
+ ` requests: ${state.totalRequests}`,
210
+ ` avg latency: ${Math.round(state.avgLatencyMs)}ms`,
211
+ ...(issues.length > 0 ? [` issues: ${issues.join(', ')}`] : [' issues: none']),
212
+ ` diagnostic files: ${state.diagnostics.size}`,
213
+ ...(state.diagnostics.size > 0 ? [' next: /intelligence diagnostics'] : []),
214
+ ' next: /intelligence symbols <file>',
215
+ ' next: /intelligence outline <file>',
216
+ ' next: /intelligence references <file> <line> <column>',
217
+ ' next: /intelligence definition <file> <line> <column>',
218
+ ' next: /intelligence hover <file> <line> <column>',
219
+ ' next: /intelligence repair',
220
+ ].join('\n'));
221
+ },
222
+ });
223
+ }