@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,339 @@
1
+ import type { CommandRegistry, CommandContext } from '../command-registry.ts';
2
+ import { join } from 'node:path';
3
+ import { AGENT_TEMPLATES } from '@pellux/goodvibes-sdk/platform/tools';
4
+ import { ArchetypeLoader, type AgentArchetype } from '@pellux/goodvibes-sdk/platform/agents';
5
+ import { requireReadModels, requireShellPaths } from './runtime-services.ts';
6
+
7
+ type TeamworkModeId =
8
+ | 'local-engineer'
9
+ | 'local-shell'
10
+ | 'remote-engineer'
11
+ | 'teammate'
12
+ | 'research'
13
+ | 'dream'
14
+ | 'review'
15
+ | 'verifier'
16
+ | 'integration';
17
+
18
+ interface TeamworkMode {
19
+ readonly id: TeamworkModeId;
20
+ readonly label: string;
21
+ readonly taskKind: 'agent' | 'exec' | 'acp' | 'integration';
22
+ readonly owner: string;
23
+ readonly template?: keyof typeof AGENT_TEMPLATES;
24
+ readonly reviewMode: 'none' | 'wrfc';
25
+ readonly executionProtocol: 'direct' | 'gather-plan-apply';
26
+ }
27
+
28
+ interface TeamworkRecipe {
29
+ readonly id: string;
30
+ readonly summary: string;
31
+ readonly steps: readonly string[];
32
+ }
33
+
34
+ interface ResolvedArchetypeMode {
35
+ readonly id: string;
36
+ readonly label: string;
37
+ readonly owner: string;
38
+ readonly taskKind: 'agent' | 'exec' | 'acp' | 'integration';
39
+ readonly template?: string;
40
+ readonly reviewMode: 'none' | 'wrfc';
41
+ readonly executionProtocol: 'direct' | 'gather-plan-apply';
42
+ readonly source: 'builtin' | 'custom';
43
+ readonly family: 'implement' | 'review' | 'test' | 'research' | 'general';
44
+ readonly sourcePath?: string;
45
+ readonly validationIssues: readonly string[];
46
+ readonly tools: readonly string[];
47
+ }
48
+
49
+ interface TeamworkReviewSnapshot {
50
+ readonly builtinArchetypes: number;
51
+ readonly customArchetypes: number;
52
+ readonly archetypesWithIssues: number;
53
+ readonly implementArchetypes: number;
54
+ readonly reviewArchetypes: number;
55
+ readonly researchArchetypes: number;
56
+ readonly activeTaskCount: number;
57
+ readonly blockedTaskCount: number;
58
+ readonly reviewTaskCount: number;
59
+ }
60
+
61
+ const TEAMWORK_MODES: readonly TeamworkMode[] = [
62
+ { id: 'local-engineer', label: 'Local engineer task', taskKind: 'agent', owner: 'local-engineer', template: 'engineer', reviewMode: 'wrfc', executionProtocol: 'gather-plan-apply' },
63
+ { id: 'local-shell', label: 'Local shell task', taskKind: 'exec', owner: 'local-shell', reviewMode: 'none', executionProtocol: 'direct' },
64
+ { id: 'remote-engineer', label: 'Remote engineer task', taskKind: 'acp', owner: 'remote-engineer', template: 'engineer', reviewMode: 'wrfc', executionProtocol: 'gather-plan-apply' },
65
+ { id: 'teammate', label: 'In-process teammate task', taskKind: 'agent', owner: 'teammate', template: 'general', reviewMode: 'wrfc', executionProtocol: 'gather-plan-apply' },
66
+ { id: 'research', label: 'Research task', taskKind: 'agent', owner: 'research', template: 'researcher', reviewMode: 'none', executionProtocol: 'gather-plan-apply' },
67
+ { id: 'dream', label: 'Speculative dream task', taskKind: 'agent', owner: 'dream', template: 'researcher', reviewMode: 'none', executionProtocol: 'gather-plan-apply' },
68
+ { id: 'review', label: 'Review-only task', taskKind: 'agent', owner: 'review', template: 'reviewer', reviewMode: 'wrfc', executionProtocol: 'gather-plan-apply' },
69
+ { id: 'verifier', label: 'Verifier task', taskKind: 'agent', owner: 'verifier', template: 'reviewer', reviewMode: 'wrfc', executionProtocol: 'gather-plan-apply' },
70
+ { id: 'integration', label: 'Integration task', taskKind: 'integration', owner: 'integration', template: 'engineer', reviewMode: 'wrfc', executionProtocol: 'gather-plan-apply' },
71
+ ];
72
+
73
+ const TEAMWORK_RECIPES: readonly TeamworkRecipe[] = [
74
+ {
75
+ id: 'research-implement-review',
76
+ summary: 'Research first, implement second, certify with WRFC review.',
77
+ steps: ['research', 'local-engineer', 'review', 'verifier'],
78
+ },
79
+ {
80
+ id: 'remote-certification',
81
+ summary: 'Remote engineer execution with local review and integration.',
82
+ steps: ['remote-engineer', 'review', 'integration'],
83
+ },
84
+ {
85
+ id: 'triage-delegate-integrate',
86
+ summary: 'Triage locally, delegate focused teammate work, then integrate.',
87
+ steps: ['teammate', 'review', 'integration'],
88
+ },
89
+ {
90
+ id: 'dream-then-certify',
91
+ summary: 'Run a speculative research pass, then ground it through engineer, review, and verifier steps.',
92
+ steps: ['dream', 'local-engineer', 'review', 'verifier'],
93
+ },
94
+ ];
95
+
96
+ function formatMode(mode: TeamworkMode): string {
97
+ return ` ${mode.id.padEnd(18)} ${mode.taskKind.padEnd(11)} ${mode.owner.padEnd(16)} ${mode.reviewMode.padEnd(4)} ${mode.executionProtocol}${mode.template ? ` template=${mode.template}` : ''}`;
98
+ }
99
+
100
+ function classifyArchetype(archetype: AgentArchetype): ResolvedArchetypeMode['family'] {
101
+ const haystack = `${archetype.name} ${archetype.description}`.toLowerCase();
102
+ const tools = new Set(archetype.tools.map((tool) => tool.toLowerCase()));
103
+ if (haystack.includes('review') || haystack.includes('audit')) return 'review';
104
+ if (haystack.includes('test') || tools.has('exec') && tools.has('write') && !tools.has('edit')) return 'test';
105
+ if (haystack.includes('research') || haystack.includes('analysis') || (tools.has('find') && tools.has('analyze') && !tools.has('write') && !tools.has('edit'))) return 'research';
106
+ if (tools.has('write') || tools.has('edit')) return 'implement';
107
+ return 'general';
108
+ }
109
+
110
+ function buildArchetypeMode(archetype: AgentArchetype): ResolvedArchetypeMode {
111
+ const family = classifyArchetype(archetype);
112
+ const source = archetype.isCustom ? 'custom' : 'builtin';
113
+ return {
114
+ id: archetype.name,
115
+ label: archetype.description || `${archetype.name} archetype`,
116
+ owner: source === 'custom' ? `custom:${archetype.name}` : archetype.name,
117
+ taskKind: 'agent',
118
+ template: archetype.name,
119
+ reviewMode: family === 'review' ? 'wrfc' : 'none',
120
+ executionProtocol: family === 'research' ? 'gather-plan-apply' : family === 'implement' ? 'gather-plan-apply' : 'direct',
121
+ source,
122
+ family,
123
+ sourcePath: archetype.sourcePath,
124
+ validationIssues: archetype.validationIssues ?? [],
125
+ tools: archetype.tools,
126
+ };
127
+ }
128
+
129
+ function listArchetypeModes(projectRoot: string): ResolvedArchetypeMode[] {
130
+ const loader = new ArchetypeLoader(join(projectRoot, '.goodvibes', 'agents'));
131
+ return loader.listArchetypes()
132
+ .map(buildArchetypeMode)
133
+ .sort((a, b) => a.id.localeCompare(b.id));
134
+ }
135
+
136
+ function buildTeamworkReviewSnapshot(ctx: CommandContext): TeamworkReviewSnapshot {
137
+ const projectRoot = requireShellPaths(ctx).workingDirectory;
138
+ const archetypes = listArchetypeModes(projectRoot);
139
+ const tasks = [...requireReadModels(ctx).tasks.getSnapshot().tasks];
140
+ return {
141
+ builtinArchetypes: archetypes.filter((entry) => entry.source === 'builtin').length,
142
+ customArchetypes: archetypes.filter((entry) => entry.source === 'custom').length,
143
+ archetypesWithIssues: archetypes.filter((entry) => entry.validationIssues.length > 0).length,
144
+ implementArchetypes: archetypes.filter((entry) => entry.family === 'implement').length,
145
+ reviewArchetypes: archetypes.filter((entry) => entry.family === 'review').length,
146
+ researchArchetypes: archetypes.filter((entry) => entry.family === 'research').length,
147
+ activeTaskCount: tasks.filter((task) => task.status === 'running' || task.status === 'queued').length,
148
+ blockedTaskCount: tasks.filter((task) => task.status === 'blocked').length,
149
+ reviewTaskCount: tasks.filter((task) => task.owner === 'review' || task.owner === 'verifier').length,
150
+ };
151
+ }
152
+
153
+ function printAgentDelegationBoundary(ctx: CommandContext, requestedAction: string): void {
154
+ ctx.print([
155
+ 'GoodVibes Agent does not create local teamwork, Engineer, Reviewer, Tester, Verifier, or WRFC-owned tasks.',
156
+ ` requested: ${requestedAction}`,
157
+ ' policy: keep ordinary work serial in the main assistant conversation',
158
+ ' build/fix/review: delegate one request to GoodVibes TUI through the public shared-session/build-delegation contract',
159
+ ' preserve: full original user ask and executionIntent; let TUI own WRFC when explicitly requested',
160
+ ].join('\n'));
161
+ }
162
+
163
+ export function registerTeamworkRuntimeCommands(registry: CommandRegistry): void {
164
+ registry.register({
165
+ name: 'teamwork',
166
+ aliases: ['teammates'],
167
+ description: 'Packaged task modes, teammate templates, and orchestration recipes',
168
+ usage: '[review|modes|mode <id>|create-mode <id> <title...>|recipes|recipe <id>|templates|archetypes|validate|archetype <name>|create-archetype <name> <title...>]',
169
+ handler(args, ctx) {
170
+ const sub = args[0]?.toLowerCase() ?? 'review';
171
+
172
+ if (sub === 'review') {
173
+ const snapshot = buildTeamworkReviewSnapshot(ctx);
174
+ ctx.print([
175
+ 'Teamwork Review',
176
+ ` modes: ${TEAMWORK_MODES.length}`,
177
+ ` recipes: ${TEAMWORK_RECIPES.length}`,
178
+ ` builtin archetypes: ${snapshot.builtinArchetypes}`,
179
+ ` custom archetypes: ${snapshot.customArchetypes}`,
180
+ ` archetypes with issues: ${snapshot.archetypesWithIssues}`,
181
+ ` implement/review/research: ${snapshot.implementArchetypes}/${snapshot.reviewArchetypes}/${snapshot.researchArchetypes}`,
182
+ ` active tasks: ${snapshot.activeTaskCount}`,
183
+ ` blocked tasks: ${snapshot.blockedTaskCount}`,
184
+ ` review tasks: ${snapshot.reviewTaskCount}`,
185
+ ' next: /teamwork archetypes',
186
+ ' next: /teamwork validate',
187
+ ' next: /tasks',
188
+ ].join('\n'));
189
+ return;
190
+ }
191
+
192
+ if (sub === 'modes') {
193
+ ctx.print([
194
+ 'Teamwork Modes',
195
+ ...TEAMWORK_MODES.map(formatMode),
196
+ ].join('\n'));
197
+ return;
198
+ }
199
+
200
+ if (sub === 'mode') {
201
+ const modeId = args[1] as TeamworkModeId | undefined;
202
+ const mode = TEAMWORK_MODES.find((entry) => entry.id === modeId);
203
+ if (!mode) {
204
+ ctx.print('Usage: /teamwork mode <local-engineer|local-shell|remote-engineer|teammate|research|dream|review|verifier|integration>');
205
+ return;
206
+ }
207
+ ctx.print([
208
+ `Teamwork Mode ${mode.id}`,
209
+ ` label: ${mode.label}`,
210
+ ` taskKind: ${mode.taskKind}`,
211
+ ` owner: ${mode.owner}`,
212
+ ` template: ${mode.template ?? '(none)'}`,
213
+ ` reviewMode: ${mode.reviewMode}`,
214
+ ` executionProtocol: ${mode.executionProtocol}`,
215
+ ].join('\n'));
216
+ return;
217
+ }
218
+
219
+ if (sub === 'create-mode') {
220
+ const modeId = args[1] as TeamworkModeId | undefined;
221
+ const title = args.slice(2).join(' ').trim();
222
+ const mode = TEAMWORK_MODES.find((entry) => entry.id === modeId);
223
+ if (!mode || !title) {
224
+ ctx.print('Usage: /teamwork create-mode <local-engineer|local-shell|remote-engineer|teammate|research|dream|review|verifier|integration> <title...>');
225
+ return;
226
+ }
227
+ printAgentDelegationBoundary(ctx, `/teamwork create-mode ${mode.id} ${title}`);
228
+ return;
229
+ }
230
+
231
+ if (sub === 'recipes') {
232
+ ctx.print([
233
+ 'Teamwork Recipes',
234
+ ...TEAMWORK_RECIPES.map((recipe) => ` ${recipe.id.padEnd(26)} ${recipe.summary}`),
235
+ ].join('\n'));
236
+ return;
237
+ }
238
+
239
+ if (sub === 'recipe') {
240
+ const recipeId = args[1];
241
+ const recipe = TEAMWORK_RECIPES.find((entry) => entry.id === recipeId);
242
+ if (!recipe) {
243
+ ctx.print('Usage: /teamwork recipe <id>');
244
+ return;
245
+ }
246
+ ctx.print([
247
+ `Teamwork Recipe ${recipe.id}`,
248
+ ` summary: ${recipe.summary}`,
249
+ ` steps: ${recipe.steps.join(' -> ')}`,
250
+ ].join('\n'));
251
+ return;
252
+ }
253
+
254
+ if (sub === 'templates') {
255
+ const archetypes = listArchetypeModes(requireShellPaths(ctx).workingDirectory);
256
+ ctx.print([
257
+ 'Teamwork Templates',
258
+ ...Object.entries(AGENT_TEMPLATES).map(([name, template]) => (
259
+ ` ${name.padEnd(12)} ${template.description}`
260
+ )),
261
+ '',
262
+ 'Discovered Archetypes',
263
+ ...archetypes.map((entry) => ` ${entry.id.padEnd(12)} ${entry.family.padEnd(10)} ${entry.source.padEnd(7)} ${entry.label}`),
264
+ ].join('\n'));
265
+ return;
266
+ }
267
+
268
+ if (sub === 'archetypes') {
269
+ const archetypes = listArchetypeModes(requireShellPaths(ctx).workingDirectory);
270
+ ctx.print([
271
+ 'Teamwork Archetypes',
272
+ ...archetypes.map((entry) => ` ${entry.id.padEnd(18)} ${entry.family.padEnd(10)} ${entry.source.padEnd(7)} ${entry.reviewMode.padEnd(4)} ${entry.executionProtocol}${entry.validationIssues.length > 0 ? ' issues' : ''}`),
273
+ ].join('\n'));
274
+ return;
275
+ }
276
+
277
+ if (sub === 'validate') {
278
+ const archetypes = listArchetypeModes(requireShellPaths(ctx).workingDirectory);
279
+ const invalid = archetypes.filter((entry) => entry.validationIssues.length > 0);
280
+ ctx.print(invalid.length > 0
281
+ ? [
282
+ 'Teamwork Archetype Validation',
283
+ ...invalid.flatMap((entry) => [
284
+ ` ${entry.id} (${entry.source})`,
285
+ ...entry.validationIssues.map((issue) => ` issue: ${issue}`),
286
+ ]),
287
+ ].join('\n')
288
+ : 'Teamwork Archetype Validation\n All discovered archetypes are currently valid.');
289
+ return;
290
+ }
291
+
292
+ if (sub === 'archetype') {
293
+ const archetypeName = args[1];
294
+ if (!archetypeName) {
295
+ ctx.print('Usage: /teamwork archetype <name>');
296
+ return;
297
+ }
298
+ const mode = listArchetypeModes(requireShellPaths(ctx).workingDirectory).find((entry) => entry.id === archetypeName);
299
+ if (!mode) {
300
+ ctx.print(`Unknown archetype: ${archetypeName}`);
301
+ return;
302
+ }
303
+ ctx.print([
304
+ `Teamwork Archetype ${mode.id}`,
305
+ ` label: ${mode.label}`,
306
+ ` family: ${mode.family}`,
307
+ ` source: ${mode.source}`,
308
+ ` owner: ${mode.owner}`,
309
+ ` reviewMode: ${mode.reviewMode}`,
310
+ ` executionProtocol: ${mode.executionProtocol}`,
311
+ ` tools: ${mode.tools.join(', ') || '(none)'}`,
312
+ ` sourcePath: ${mode.sourcePath ?? '(builtin)'}`,
313
+ ...(mode.validationIssues.length > 0
314
+ ? mode.validationIssues.map((issue) => ` issue: ${issue}`)
315
+ : [' validation: clean']),
316
+ ].join('\n'));
317
+ return;
318
+ }
319
+
320
+ if (sub === 'create-archetype') {
321
+ const archetypeName = args[1];
322
+ const title = args.slice(2).join(' ').trim();
323
+ if (!archetypeName || !title) {
324
+ ctx.print('Usage: /teamwork create-archetype <name> <title...>');
325
+ return;
326
+ }
327
+ const mode = listArchetypeModes(requireShellPaths(ctx).workingDirectory).find((entry) => entry.id === archetypeName);
328
+ if (!mode) {
329
+ ctx.print(`Unknown archetype: ${archetypeName}`);
330
+ return;
331
+ }
332
+ printAgentDelegationBoundary(ctx, `/teamwork create-archetype ${mode.id} ${title}`);
333
+ return;
334
+ }
335
+
336
+ ctx.print('Usage: /teamwork [review|modes|mode <id>|create-mode <id> <title...>|recipes|recipe <id>|templates|archetypes|validate|archetype <name>|create-archetype <name> <title...>]');
337
+ },
338
+ });
339
+ }
@@ -0,0 +1,57 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import type { CommandRegistry } from '../command-registry.ts';
3
+ import type { RemoteSessionBundle } from '@/runtime/index.ts';
4
+ import { requirePeerClient, requireShellPaths } from './runtime-services.ts';
5
+
6
+ function inspectRemoteSessionBundle(bundle: RemoteSessionBundle): string {
7
+ return [
8
+ 'Teleport Bundle Review',
9
+ ` session: ${bundle.sessionId}`,
10
+ ` exportedAt: ${new Date(bundle.exportedAt).toISOString()}`,
11
+ ` active connections: ${bundle.activeConnectionIds.length}`,
12
+ ` pools: ${bundle.pools.length}`,
13
+ ` contracts: ${bundle.contracts.length}`,
14
+ ` artifacts: ${bundle.artifacts.length}`,
15
+ ].join('\n');
16
+ }
17
+
18
+ export function registerTeleportRuntimeCommands(registry: CommandRegistry): void {
19
+ registry.register({
20
+ name: 'teleport',
21
+ description: 'Package, inspect, and import portable remote-session handoff bundles',
22
+ usage: '[export <path>|inspect <path>|import <path>]',
23
+ async handler(args, ctx) {
24
+ const shellPaths = requireShellPaths(ctx);
25
+ const mode = (args[0] ?? 'export').toLowerCase();
26
+ const pathArg = args[1];
27
+ if (!pathArg) {
28
+ ctx.print('Usage: /teleport [export <path>|inspect <path>|import <path>]');
29
+ return;
30
+ }
31
+ let peerClient;
32
+ try {
33
+ peerClient = requirePeerClient(ctx);
34
+ } catch {
35
+ ctx.print('Remote runner registry is not available in this runtime.');
36
+ return;
37
+ }
38
+ const targetPath = shellPaths.resolveWorkspacePath(pathArg);
39
+ if (mode === 'export') {
40
+ const exported = await peerClient.runners.exportSessionBundle(targetPath);
41
+ ctx.print(`Teleport bundle exported for session ${exported.bundle.sessionId} to ${exported.path}`);
42
+ return;
43
+ }
44
+ if (mode === 'inspect') {
45
+ const bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as RemoteSessionBundle;
46
+ ctx.print(inspectRemoteSessionBundle(bundle));
47
+ return;
48
+ }
49
+ if (mode === 'import') {
50
+ const bundle = await peerClient.runners.importSessionBundle(targetPath);
51
+ ctx.print(`Imported teleport bundle ${bundle.sessionId} with ${bundle.contracts.length} contracts.`);
52
+ return;
53
+ }
54
+ ctx.print('Usage: /teleport [export <path>|inspect <path>|import <path>]');
55
+ },
56
+ });
57
+ }
@@ -0,0 +1,29 @@
1
+ import type { CommandRegistry } from '../command-registry.ts';
2
+
3
+ export function registerTtsRuntimeCommands(registry: CommandRegistry): void {
4
+ registry.register({
5
+ name: 'tts',
6
+ description: 'Submit a normal prompt and play the assistant response through live TTS',
7
+ usage: '<prompt>|stop',
8
+ handler(args, ctx) {
9
+ const first = (args[0] ?? '').toLowerCase();
10
+ if (first === 'stop' || first === 'cancel') {
11
+ ctx.stopSpokenOutput?.();
12
+ ctx.print('Live TTS playback stopped.');
13
+ return;
14
+ }
15
+
16
+ const prompt = args.join(' ').trim();
17
+ if (!prompt) {
18
+ ctx.print('Usage: /tts <prompt> or /tts stop');
19
+ return;
20
+ }
21
+ if (!ctx.submitSpokenInput) {
22
+ ctx.print('Live TTS is not available in this runtime.');
23
+ return;
24
+ }
25
+ ctx.submitSpokenInput(prompt);
26
+ },
27
+ });
28
+
29
+ }
@@ -0,0 +1,169 @@
1
+ import type { CommandRegistry } from '../command-registry.ts';
2
+ import type { WorkPlanItemStatus, WorkPlanStore } from '../../work-plans/work-plan-store.ts';
3
+ import { WORK_PLAN_STATUSES } from '../../work-plans/work-plan-store.ts';
4
+ import { requirePanelManager } from './runtime-services.ts';
5
+ import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
6
+
7
+ const STATUS_COMMANDS: Record<string, WorkPlanItemStatus> = {
8
+ pending: 'pending',
9
+ todo: 'pending',
10
+ start: 'in_progress',
11
+ active: 'in_progress',
12
+ progress: 'in_progress',
13
+ block: 'blocked',
14
+ blocked: 'blocked',
15
+ done: 'done',
16
+ complete: 'done',
17
+ fail: 'failed',
18
+ failed: 'failed',
19
+ cancel: 'cancelled',
20
+ cancelled: 'cancelled',
21
+ };
22
+
23
+ function getStore(ctx: import('../command-registry.ts').CommandContext): WorkPlanStore | null {
24
+ return ctx.workspace.workPlanStore ?? null;
25
+ }
26
+
27
+ function openPanel(ctx: import('../command-registry.ts').CommandContext): void {
28
+ if (ctx.showPanel) {
29
+ ctx.showPanel('work-plan');
30
+ return;
31
+ }
32
+ const panelManager = requirePanelManager(ctx);
33
+ panelManager.open('work-plan');
34
+ panelManager.show();
35
+ ctx.renderRequest();
36
+ }
37
+
38
+ function formatList(store: WorkPlanStore): string {
39
+ const items = store.listItems();
40
+ if (items.length === 0) return 'Work plan is empty. Add one with /workplan add <title>.';
41
+ return [
42
+ `Work Plan (${items.length})`,
43
+ ...items.map((item) => {
44
+ const owner = item.owner ? ` @${item.owner}` : '';
45
+ return ` ${item.id} ${item.status.padEnd(11)} ${item.title}${owner}`;
46
+ }),
47
+ ].join('\n');
48
+ }
49
+
50
+ function parseAddArgs(args: string[]): { title: string; owner?: string; source?: string; notes?: string } {
51
+ const titleParts: string[] = [];
52
+ let owner: string | undefined;
53
+ let source: string | undefined;
54
+ let notes: string | undefined;
55
+ for (let i = 0; i < args.length; i++) {
56
+ const part = args[i] ?? '';
57
+ if (part === '--owner' && args[i + 1]) {
58
+ owner = args[++i];
59
+ continue;
60
+ }
61
+ if (part === '--source' && args[i + 1]) {
62
+ source = args[++i];
63
+ continue;
64
+ }
65
+ if (part === '--notes' && args[i + 1]) {
66
+ notes = args.slice(i + 1).join(' ').trim();
67
+ break;
68
+ }
69
+ titleParts.push(part);
70
+ }
71
+ return {
72
+ title: titleParts.join(' ').trim(),
73
+ ...(owner ? { owner } : {}),
74
+ ...(source ? { source } : {}),
75
+ ...(notes ? { notes } : {}),
76
+ };
77
+ }
78
+
79
+ export function registerWorkPlanRuntimeCommands(registry: CommandRegistry): void {
80
+ registry.register({
81
+ name: 'workplan',
82
+ aliases: ['wp', 'todo'],
83
+ description: 'Track a persistent workspace-scoped work plan',
84
+ usage: '[panel|list|show|add <title> [--owner name] [--source label] [--notes text]|done <id>|start <id>|block <id>|fail <id>|cancel <id>|pending <id>|remove <id>|clear-done]',
85
+ argsHint: '[panel|add|list|done]',
86
+ handler(args, ctx) {
87
+ const store = getStore(ctx);
88
+ if (!store) {
89
+ ctx.print('Work plan store is not available in this runtime.');
90
+ return;
91
+ }
92
+ const subcommand = (args[0] ?? 'panel').toLowerCase();
93
+ try {
94
+ if (subcommand === 'panel' || subcommand === 'open') {
95
+ openPanel(ctx);
96
+ ctx.print('Opened work plan panel.');
97
+ return;
98
+ }
99
+ if (subcommand === 'list') {
100
+ ctx.print(formatList(store));
101
+ return;
102
+ }
103
+ if (subcommand === 'show' || subcommand === 'markdown') {
104
+ ctx.print(store.toMarkdown());
105
+ return;
106
+ }
107
+ if (subcommand === 'add') {
108
+ const parsed = parseAddArgs(args.slice(1));
109
+ if (!parsed.title) {
110
+ ctx.print('Usage: /workplan add <title> [--owner name] [--source label] [--notes text]');
111
+ return;
112
+ }
113
+ const addOptions = {
114
+ ...(parsed.owner ? { owner: parsed.owner } : {}),
115
+ source: parsed.source ?? 'manual',
116
+ ...(parsed.notes ? { notes: parsed.notes } : {}),
117
+ };
118
+ const item = store.addItem(parsed.title, addOptions);
119
+ openPanel(ctx);
120
+ ctx.print(`Added work plan item ${item.id}.`);
121
+ return;
122
+ }
123
+ if (subcommand === 'remove' || subcommand === 'delete' || subcommand === 'rm') {
124
+ const id = args[1];
125
+ if (!id) {
126
+ ctx.print(`Usage: /workplan ${subcommand} <id>`);
127
+ return;
128
+ }
129
+ const item = store.removeItem(id);
130
+ ctx.print(`Removed work plan item ${item.id}: ${item.title}`);
131
+ return;
132
+ }
133
+ if (subcommand === 'clear-done' || subcommand === 'clear-completed') {
134
+ const count = store.clearCompleted();
135
+ ctx.print(`Cleared ${count} completed/cancelled work plan item${count === 1 ? '' : 's'}.`);
136
+ return;
137
+ }
138
+ if (subcommand === 'cycle' || subcommand === 'toggle') {
139
+ const id = args[1];
140
+ if (!id) {
141
+ ctx.print(`Usage: /workplan ${subcommand} <id>`);
142
+ return;
143
+ }
144
+ const item = store.cycleItemStatus(id);
145
+ ctx.print(`Updated ${item.id}: ${item.status}.`);
146
+ return;
147
+ }
148
+ const status = STATUS_COMMANDS[subcommand];
149
+ if (status) {
150
+ const id = args[1];
151
+ if (!id) {
152
+ ctx.print(`Usage: /workplan ${subcommand} <id>`);
153
+ return;
154
+ }
155
+ const item = store.setItemStatus(id, status);
156
+ ctx.print(`Updated ${item.id}: ${item.status}.`);
157
+ return;
158
+ }
159
+ if (WORK_PLAN_STATUSES.includes(subcommand as WorkPlanItemStatus)) {
160
+ ctx.print(`Usage: /workplan ${subcommand} <id>`);
161
+ return;
162
+ }
163
+ ctx.print(`Unknown workplan subcommand: ${subcommand}`);
164
+ } catch (error) {
165
+ ctx.print(summarizeError(error));
166
+ }
167
+ },
168
+ });
169
+ }