prjct-cli 0.11.4 → 0.12.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 (385) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +81 -25
  3. package/bin/dev.js +1 -1
  4. package/bin/generate-views.js +209 -0
  5. package/bin/migrate-to-json.js +742 -0
  6. package/bin/prjct +5 -5
  7. package/bin/serve.js +246 -54
  8. package/core/__tests__/agentic/{memory-system.test.js → memory-system.test.ts} +12 -23
  9. package/core/__tests__/agentic/{plan-mode.test.js → plan-mode.test.ts} +26 -24
  10. package/core/__tests__/agentic/{prompt-builder.test.js → prompt-builder.test.ts} +3 -8
  11. package/core/__tests__/utils/date-helper.test.ts +405 -0
  12. package/core/__tests__/utils/{output.test.js → output.test.ts} +12 -24
  13. package/core/agentic/agent-router.ts +137 -0
  14. package/core/agentic/chain-of-thought.ts +228 -0
  15. package/core/agentic/command-executor/command-executor.ts +384 -0
  16. package/core/agentic/command-executor/index.ts +16 -0
  17. package/core/agentic/command-executor/status-signal.ts +38 -0
  18. package/core/agentic/command-executor/types.ts +79 -0
  19. package/core/agentic/command-executor.ts +8 -0
  20. package/core/agentic/{context-builder.js → context-builder.ts} +99 -89
  21. package/core/agentic/context-filter.ts +365 -0
  22. package/core/agentic/ground-truth/index.ts +76 -0
  23. package/core/agentic/ground-truth/types.ts +33 -0
  24. package/core/agentic/ground-truth/utils.ts +48 -0
  25. package/core/agentic/ground-truth/verifiers/analyze.ts +54 -0
  26. package/core/agentic/ground-truth/verifiers/done.ts +75 -0
  27. package/core/agentic/ground-truth/verifiers/feature.ts +70 -0
  28. package/core/agentic/ground-truth/verifiers/index.ts +37 -0
  29. package/core/agentic/ground-truth/verifiers/init.ts +52 -0
  30. package/core/agentic/ground-truth/verifiers/now.ts +57 -0
  31. package/core/agentic/ground-truth/verifiers/ship.ts +85 -0
  32. package/core/agentic/ground-truth/verifiers/spec.ts +45 -0
  33. package/core/agentic/ground-truth/verifiers/sync.ts +47 -0
  34. package/core/agentic/ground-truth/verifiers.ts +6 -0
  35. package/core/agentic/ground-truth.ts +8 -0
  36. package/core/agentic/loop-detector/error-analysis.ts +97 -0
  37. package/core/agentic/loop-detector/hallucination.ts +71 -0
  38. package/core/agentic/loop-detector/index.ts +41 -0
  39. package/core/agentic/loop-detector/loop-detector.ts +222 -0
  40. package/core/agentic/loop-detector/types.ts +66 -0
  41. package/core/agentic/loop-detector.ts +8 -0
  42. package/core/agentic/memory-system/history.ts +53 -0
  43. package/core/agentic/memory-system/index.ts +192 -0
  44. package/core/agentic/memory-system/patterns.ts +156 -0
  45. package/core/agentic/memory-system/semantic-memories.ts +277 -0
  46. package/core/agentic/memory-system/session.ts +21 -0
  47. package/core/agentic/memory-system/types.ts +159 -0
  48. package/core/agentic/memory-system.ts +8 -0
  49. package/core/agentic/parallel-tools.ts +165 -0
  50. package/core/agentic/plan-mode/approval.ts +57 -0
  51. package/core/agentic/plan-mode/constants.ts +44 -0
  52. package/core/agentic/plan-mode/index.ts +28 -0
  53. package/core/agentic/plan-mode/plan-mode.ts +406 -0
  54. package/core/agentic/plan-mode/types.ts +193 -0
  55. package/core/agentic/plan-mode.ts +8 -0
  56. package/core/agentic/prompt-builder.ts +566 -0
  57. package/core/agentic/response-templates.ts +164 -0
  58. package/core/agentic/semantic-compression.ts +273 -0
  59. package/core/agentic/services.ts +206 -0
  60. package/core/agentic/smart-context.ts +476 -0
  61. package/core/agentic/{template-loader.js → template-loader.ts} +35 -18
  62. package/core/agentic/think-blocks.ts +202 -0
  63. package/core/agentic/tool-registry.ts +119 -0
  64. package/core/agentic/validation-rules.ts +313 -0
  65. package/core/agents/index.ts +28 -0
  66. package/core/agents/performance.ts +444 -0
  67. package/core/agents/types.ts +126 -0
  68. package/core/bus/{index.js → index.ts} +57 -61
  69. package/core/command-registry/categories.ts +23 -0
  70. package/core/command-registry/commands.ts +15 -0
  71. package/core/command-registry/core-commands.ts +319 -0
  72. package/core/command-registry/index.ts +158 -0
  73. package/core/command-registry/optional-commands.ts +119 -0
  74. package/core/command-registry/setup-commands.ts +53 -0
  75. package/core/command-registry/types.ts +59 -0
  76. package/core/command-registry.ts +9 -0
  77. package/core/commands/analysis.ts +298 -0
  78. package/core/commands/analytics.ts +288 -0
  79. package/core/commands/base.ts +273 -0
  80. package/core/commands/index.ts +211 -0
  81. package/core/commands/maintenance.ts +226 -0
  82. package/core/commands/planning.ts +311 -0
  83. package/core/commands/setup.ts +309 -0
  84. package/core/commands/shipping.ts +188 -0
  85. package/core/commands/types.ts +183 -0
  86. package/core/commands/workflow.ts +226 -0
  87. package/core/commands.ts +11 -0
  88. package/core/constants/formats.ts +187 -0
  89. package/core/constants/index.ts +7 -0
  90. package/core/{context-sync.js → context-sync.ts} +59 -26
  91. package/core/data/agents-manager.ts +76 -0
  92. package/core/data/analysis-manager.ts +83 -0
  93. package/core/data/base-manager.ts +156 -0
  94. package/core/data/ideas-manager.ts +81 -0
  95. package/core/data/index.ts +32 -0
  96. package/core/data/outcomes-manager.ts +96 -0
  97. package/core/data/project-manager.ts +75 -0
  98. package/core/data/roadmap-manager.ts +118 -0
  99. package/core/data/shipped-manager.ts +65 -0
  100. package/core/data/state-manager.ts +214 -0
  101. package/core/domain/{agent-generator.js → agent-generator.ts} +77 -57
  102. package/core/domain/{agent-loader.js → agent-loader.ts} +65 -56
  103. package/core/domain/{agent-matcher.js → agent-matcher.ts} +51 -24
  104. package/core/domain/{agent-validator.js → agent-validator.ts} +70 -37
  105. package/core/domain/{analyzer.js → analyzer.ts} +91 -85
  106. package/core/domain/{architect-session.js → architect-session.ts} +49 -34
  107. package/core/domain/{architecture-generator.js → architecture-generator.ts} +25 -13
  108. package/core/domain/{context-estimator.js → context-estimator.ts} +57 -36
  109. package/core/domain/{product-standards.js → product-standards.ts} +40 -26
  110. package/core/domain/{smart-cache.js → smart-cache.ts} +39 -30
  111. package/core/domain/{snapshot-manager.js → snapshot-manager.ts} +103 -100
  112. package/core/domain/{task-analyzer.js → task-analyzer.ts} +82 -43
  113. package/core/domain/task-stack/index.ts +19 -0
  114. package/core/domain/task-stack/parser.ts +86 -0
  115. package/core/domain/task-stack/storage.ts +123 -0
  116. package/core/domain/task-stack/task-stack.ts +340 -0
  117. package/core/domain/task-stack/types.ts +51 -0
  118. package/core/domain/task-stack.ts +8 -0
  119. package/core/{index.js → index.ts} +61 -18
  120. package/core/infrastructure/{agent-detector.js → agent-detector.ts} +62 -23
  121. package/core/infrastructure/agents/{claude-agent.js → claude-agent.ts} +61 -21
  122. package/core/infrastructure/{author-detector.js → author-detector.ts} +42 -49
  123. package/core/infrastructure/{capability-installer.js → capability-installer.ts} +51 -27
  124. package/core/infrastructure/{command-installer.js → command-installer/command-installer.ts} +43 -144
  125. package/core/infrastructure/command-installer/global-config.ts +106 -0
  126. package/core/infrastructure/command-installer/index.ts +25 -0
  127. package/core/infrastructure/command-installer/types.ts +41 -0
  128. package/core/infrastructure/command-installer.ts +8 -0
  129. package/core/infrastructure/{config-manager.js → config-manager.ts} +60 -80
  130. package/core/infrastructure/{editors-config.js → editors-config.ts} +33 -31
  131. package/core/infrastructure/legacy-installer-detector/cleanup.ts +216 -0
  132. package/core/infrastructure/legacy-installer-detector/detection.ts +95 -0
  133. package/core/infrastructure/legacy-installer-detector/index.ts +171 -0
  134. package/core/infrastructure/legacy-installer-detector/migration.ts +87 -0
  135. package/core/infrastructure/legacy-installer-detector/types.ts +42 -0
  136. package/core/infrastructure/legacy-installer-detector.ts +7 -0
  137. package/core/infrastructure/migrator/file-operations.ts +125 -0
  138. package/core/infrastructure/migrator/index.ts +288 -0
  139. package/core/infrastructure/migrator/project-scanner.ts +89 -0
  140. package/core/infrastructure/migrator/reports.ts +117 -0
  141. package/core/infrastructure/migrator/types.ts +124 -0
  142. package/core/infrastructure/migrator/validation.ts +94 -0
  143. package/core/infrastructure/migrator/version-migration.ts +117 -0
  144. package/core/infrastructure/migrator.ts +10 -0
  145. package/core/infrastructure/{path-manager.js → path-manager.ts} +51 -91
  146. package/core/infrastructure/session-manager/index.ts +23 -0
  147. package/core/infrastructure/session-manager/migration.ts +88 -0
  148. package/core/infrastructure/session-manager/session-manager.ts +307 -0
  149. package/core/infrastructure/session-manager/types.ts +45 -0
  150. package/core/infrastructure/session-manager.ts +8 -0
  151. package/core/infrastructure/{setup.js → setup.ts} +29 -21
  152. package/core/infrastructure/{update-checker.js → update-checker.ts} +40 -18
  153. package/core/outcomes/analyzer.ts +333 -0
  154. package/core/outcomes/index.ts +34 -0
  155. package/core/outcomes/recorder.ts +194 -0
  156. package/core/outcomes/types.ts +145 -0
  157. package/core/plugin/{hooks.js → hooks.ts} +56 -58
  158. package/core/plugin/{index.js → index.ts} +19 -8
  159. package/core/plugin/{loader.js → loader.ts} +87 -69
  160. package/core/plugin/{registry.js → registry.ts} +49 -45
  161. package/core/plugins/{webhook.js → webhook.ts} +43 -27
  162. package/core/schemas/agents.ts +27 -0
  163. package/core/schemas/analysis.ts +41 -0
  164. package/core/schemas/ideas.ts +83 -0
  165. package/core/schemas/index.ts +73 -0
  166. package/core/schemas/outcomes.ts +22 -0
  167. package/core/schemas/project.ts +26 -0
  168. package/core/schemas/roadmap.ts +90 -0
  169. package/core/schemas/shipped.ts +82 -0
  170. package/core/schemas/state.ts +107 -0
  171. package/core/session/index.ts +17 -0
  172. package/core/session/{metrics.js → metrics.ts} +64 -46
  173. package/core/session/{index.js → session-manager.ts} +51 -117
  174. package/core/session/types.ts +29 -0
  175. package/core/session/utils.ts +57 -0
  176. package/core/state/index.ts +25 -0
  177. package/core/state/manager.ts +376 -0
  178. package/core/state/types.ts +185 -0
  179. package/core/tsconfig.json +22 -0
  180. package/core/types/index.ts +506 -0
  181. package/core/utils/{animations.js → animations.ts} +74 -28
  182. package/core/utils/{branding.js → branding.ts} +29 -4
  183. package/core/utils/{date-helper.js → date-helper.ts} +31 -74
  184. package/core/utils/file-helper.ts +262 -0
  185. package/core/utils/{jsonl-helper.js → jsonl-helper.ts} +71 -107
  186. package/core/utils/{logger.js → logger.ts} +24 -12
  187. package/core/utils/{output.js → output.ts} +25 -13
  188. package/core/utils/{project-capabilities.js → project-capabilities.ts} +31 -18
  189. package/core/utils/{session-helper.js → session-helper.ts} +79 -66
  190. package/core/utils/{version.js → version.ts} +23 -31
  191. package/core/view-generator.ts +536 -0
  192. package/package.json +23 -17
  193. package/packages/shared/.turbo/turbo-build.log +14 -0
  194. package/packages/shared/dist/index.d.ts +8 -613
  195. package/packages/shared/dist/index.d.ts.map +1 -0
  196. package/packages/shared/dist/index.js +4110 -118
  197. package/packages/shared/dist/schemas.d.ts +408 -0
  198. package/packages/shared/dist/schemas.d.ts.map +1 -0
  199. package/packages/shared/dist/types.d.ts +144 -0
  200. package/packages/shared/dist/types.d.ts.map +1 -0
  201. package/packages/shared/dist/unified.d.ts +139 -0
  202. package/packages/shared/dist/unified.d.ts.map +1 -0
  203. package/packages/shared/dist/utils.d.ts +60 -0
  204. package/packages/shared/dist/utils.d.ts.map +1 -0
  205. package/packages/shared/package.json +4 -4
  206. package/packages/shared/src/index.ts +1 -0
  207. package/packages/shared/src/unified.ts +174 -0
  208. package/packages/web/app/api/claude/sessions/route.ts +1 -1
  209. package/packages/web/app/api/claude/status/route.ts +1 -1
  210. package/packages/web/app/api/migrate/route.ts +46 -0
  211. package/packages/web/app/api/projects/[id]/route.ts +1 -1
  212. package/packages/web/app/api/projects/[id]/stats/route.ts +30 -2
  213. package/packages/web/app/api/projects/[id]/status/route.ts +1 -1
  214. package/packages/web/app/api/projects/route.ts +1 -1
  215. package/packages/web/app/api/settings/route.ts +97 -0
  216. package/packages/web/app/api/v2/projects/[id]/unified/route.ts +57 -0
  217. package/packages/web/app/globals.css +38 -0
  218. package/packages/web/app/layout.tsx +10 -2
  219. package/packages/web/app/page.tsx +9 -224
  220. package/packages/web/app/project/[id]/page.tsx +191 -63
  221. package/packages/web/app/project/[id]/stats/loading.tsx +43 -0
  222. package/packages/web/app/project/[id]/stats/page.tsx +203 -403
  223. package/packages/web/app/settings/page.tsx +222 -2
  224. package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +2 -0
  225. package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +50 -0
  226. package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +8 -0
  227. package/packages/web/components/ActivityTimeline/hooks/index.ts +2 -0
  228. package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +9 -0
  229. package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +23 -0
  230. package/packages/web/components/ActivityTimeline/index.ts +2 -0
  231. package/packages/web/components/AgentsCard/AgentsCard.tsx +63 -0
  232. package/packages/web/components/AgentsCard/AgentsCard.types.ts +13 -0
  233. package/packages/web/components/AgentsCard/index.ts +2 -0
  234. package/packages/web/components/AppSidebar/AppSidebar.tsx +134 -0
  235. package/packages/web/components/AppSidebar/index.ts +1 -0
  236. package/packages/web/components/BackLink/BackLink.tsx +18 -0
  237. package/packages/web/components/BackLink/BackLink.types.ts +5 -0
  238. package/packages/web/components/BackLink/index.ts +2 -0
  239. package/packages/web/components/BentoCard/BentoCard.constants.ts +16 -0
  240. package/packages/web/components/BentoCard/BentoCard.tsx +47 -0
  241. package/packages/web/components/BentoCard/BentoCard.types.ts +15 -0
  242. package/packages/web/components/BentoCard/index.ts +2 -0
  243. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +9 -0
  244. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +18 -0
  245. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +5 -0
  246. package/packages/web/components/BentoCardSkeleton/index.ts +2 -0
  247. package/packages/web/components/BentoGrid/BentoGrid.tsx +18 -0
  248. package/packages/web/components/BentoGrid/BentoGrid.types.ts +4 -0
  249. package/packages/web/components/BentoGrid/index.ts +2 -0
  250. package/packages/web/components/CommandButton/index.ts +1 -0
  251. package/packages/web/components/ConnectionStatus/index.ts +1 -0
  252. package/packages/web/components/DashboardContent/DashboardContent.tsx +254 -0
  253. package/packages/web/components/DashboardContent/index.ts +1 -0
  254. package/packages/web/components/DateGroup/DateGroup.tsx +18 -0
  255. package/packages/web/components/DateGroup/DateGroup.types.ts +6 -0
  256. package/packages/web/components/DateGroup/DateGroup.utils.ts +11 -0
  257. package/packages/web/components/DateGroup/index.ts +2 -0
  258. package/packages/web/components/EmptyState/EmptyState.tsx +58 -0
  259. package/packages/web/components/EmptyState/EmptyState.types.ts +10 -0
  260. package/packages/web/components/EmptyState/index.ts +2 -0
  261. package/packages/web/components/EventRow/EventRow.constants.ts +10 -0
  262. package/packages/web/components/EventRow/EventRow.tsx +49 -0
  263. package/packages/web/components/EventRow/EventRow.types.ts +7 -0
  264. package/packages/web/components/EventRow/EventRow.utils.ts +49 -0
  265. package/packages/web/components/EventRow/index.ts +2 -0
  266. package/packages/web/components/ExpandButton/ExpandButton.tsx +18 -0
  267. package/packages/web/components/ExpandButton/ExpandButton.types.ts +6 -0
  268. package/packages/web/components/ExpandButton/index.ts +2 -0
  269. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +14 -0
  270. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +5 -0
  271. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +13 -0
  272. package/packages/web/components/HealthGradientBackground/index.ts +2 -0
  273. package/packages/web/components/HeroSection/HeroSection.tsx +55 -0
  274. package/packages/web/components/HeroSection/HeroSection.types.ts +14 -0
  275. package/packages/web/components/HeroSection/HeroSection.utils.ts +7 -0
  276. package/packages/web/components/HeroSection/hooks/index.ts +2 -0
  277. package/packages/web/components/HeroSection/hooks/useCountUp.ts +45 -0
  278. package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +18 -0
  279. package/packages/web/components/HeroSection/index.ts +2 -0
  280. package/packages/web/components/IdeasCard/IdeasCard.tsx +48 -0
  281. package/packages/web/components/IdeasCard/IdeasCard.types.ts +9 -0
  282. package/packages/web/components/IdeasCard/index.ts +2 -0
  283. package/packages/web/components/InsightMessage/InsightMessage.tsx +9 -0
  284. package/packages/web/components/InsightMessage/InsightMessage.types.ts +3 -0
  285. package/packages/web/components/InsightMessage/index.ts +2 -0
  286. package/packages/web/components/Logo/index.ts +1 -0
  287. package/packages/web/components/MarkdownContent/index.ts +1 -0
  288. package/packages/web/components/NowCard/NowCard.tsx +93 -0
  289. package/packages/web/components/NowCard/NowCard.types.ts +15 -0
  290. package/packages/web/components/NowCard/index.ts +2 -0
  291. package/packages/web/components/ProgressRing/ProgressRing.constants.ts +20 -0
  292. package/packages/web/components/ProgressRing/ProgressRing.tsx +51 -0
  293. package/packages/web/components/ProgressRing/ProgressRing.types.ts +11 -0
  294. package/packages/web/components/ProgressRing/index.ts +2 -0
  295. package/packages/web/components/ProjectAvatar/index.ts +1 -0
  296. package/packages/web/components/Providers/index.ts +1 -0
  297. package/packages/web/components/QueueCard/QueueCard.tsx +72 -0
  298. package/packages/web/components/QueueCard/QueueCard.types.ts +11 -0
  299. package/packages/web/components/QueueCard/QueueCard.utils.ts +12 -0
  300. package/packages/web/components/QueueCard/index.ts +2 -0
  301. package/packages/web/components/RoadmapCard/RoadmapCard.tsx +77 -0
  302. package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +15 -0
  303. package/packages/web/components/RoadmapCard/index.ts +2 -0
  304. package/packages/web/components/ShipsCard/ShipsCard.tsx +52 -0
  305. package/packages/web/components/ShipsCard/ShipsCard.types.ts +12 -0
  306. package/packages/web/components/ShipsCard/ShipsCard.utils.ts +4 -0
  307. package/packages/web/components/ShipsCard/index.ts +2 -0
  308. package/packages/web/components/SparklineChart/SparklineChart.tsx +38 -0
  309. package/packages/web/components/SparklineChart/SparklineChart.types.ts +6 -0
  310. package/packages/web/components/SparklineChart/index.ts +2 -0
  311. package/packages/web/components/StreakCard/StreakCard.constants.ts +2 -0
  312. package/packages/web/components/StreakCard/StreakCard.tsx +53 -0
  313. package/packages/web/components/StreakCard/StreakCard.types.ts +4 -0
  314. package/packages/web/components/StreakCard/index.ts +2 -0
  315. package/packages/web/components/TasksCounter/TasksCounter.tsx +14 -0
  316. package/packages/web/components/TasksCounter/TasksCounter.types.ts +3 -0
  317. package/packages/web/components/TasksCounter/index.ts +2 -0
  318. package/packages/web/components/TechStackBadges/index.ts +1 -0
  319. package/packages/web/components/{TerminalTab.tsx → TerminalTabs/TerminalTab.tsx} +11 -0
  320. package/packages/web/components/{TerminalTabs.tsx → TerminalTabs/TerminalTabs.tsx} +29 -28
  321. package/packages/web/components/TerminalTabs/index.ts +1 -0
  322. package/packages/web/components/VelocityBadge/VelocityBadge.tsx +27 -0
  323. package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +3 -0
  324. package/packages/web/components/VelocityBadge/index.ts +2 -0
  325. package/packages/web/components/VelocityCard/VelocityCard.tsx +71 -0
  326. package/packages/web/components/VelocityCard/VelocityCard.types.ts +7 -0
  327. package/packages/web/components/VelocityCard/index.ts +2 -0
  328. package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +13 -0
  329. package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +3 -0
  330. package/packages/web/components/WeeklySparkline/index.ts +2 -0
  331. package/packages/web/components/ui/input.tsx +21 -0
  332. package/packages/web/components/ui/tooltip.tsx +2 -2
  333. package/packages/web/context/TerminalTabsContext.tsx +46 -1
  334. package/packages/web/hooks/useClaudeTerminal.ts +71 -21
  335. package/packages/web/hooks/useProjectStats.ts +55 -0
  336. package/packages/web/hooks/useProjects.ts +6 -6
  337. package/packages/web/lib/actions/projects.ts +15 -0
  338. package/packages/web/lib/json-loader.ts +630 -0
  339. package/packages/web/lib/services/index.ts +9 -0
  340. package/packages/web/lib/services/migration.server.ts +598 -0
  341. package/packages/web/lib/services/projects.server.ts +52 -0
  342. package/packages/web/lib/services/stats.server.ts +264 -0
  343. package/packages/web/lib/unified-loader.ts +396 -0
  344. package/packages/web/next-env.d.ts +1 -1
  345. package/packages/web/package.json +10 -6
  346. package/packages/web/server.ts +36 -6
  347. package/templates/commands/done.md +76 -32
  348. package/templates/commands/feature.md +121 -47
  349. package/templates/commands/idea.md +81 -8
  350. package/templates/commands/now.md +41 -17
  351. package/templates/commands/ship.md +64 -25
  352. package/templates/commands/sync.md +28 -3
  353. package/core/agentic/agent-router.js +0 -128
  354. package/core/agentic/chain-of-thought.js +0 -578
  355. package/core/agentic/command-executor.js +0 -421
  356. package/core/agentic/context-filter.js +0 -354
  357. package/core/agentic/ground-truth.js +0 -591
  358. package/core/agentic/loop-detector.js +0 -406
  359. package/core/agentic/memory-system.js +0 -850
  360. package/core/agentic/parallel-tools.js +0 -366
  361. package/core/agentic/plan-mode.js +0 -572
  362. package/core/agentic/prompt-builder.js +0 -338
  363. package/core/agentic/response-templates.js +0 -290
  364. package/core/agentic/semantic-compression.js +0 -517
  365. package/core/agentic/think-blocks.js +0 -657
  366. package/core/agentic/tool-registry.js +0 -184
  367. package/core/agentic/validation-rules.js +0 -380
  368. package/core/command-registry.js +0 -698
  369. package/core/commands.js +0 -2237
  370. package/core/domain/task-stack.js +0 -497
  371. package/core/infrastructure/legacy-installer-detector.js +0 -546
  372. package/core/infrastructure/migrator.js +0 -799
  373. package/core/infrastructure/session-manager.js +0 -390
  374. package/core/utils/file-helper.js +0 -329
  375. package/packages/web/app/api/projects/[id]/delete/route.ts +0 -21
  376. package/packages/web/app/api/stats/route.ts +0 -38
  377. package/packages/web/components/AppSidebar.tsx +0 -113
  378. package/packages/web/hooks/useStats.ts +0 -28
  379. /package/packages/web/components/{CommandButton.tsx → CommandButton/CommandButton.tsx} +0 -0
  380. /package/packages/web/components/{ConnectionStatus.tsx → ConnectionStatus/ConnectionStatus.tsx} +0 -0
  381. /package/packages/web/components/{Logo.tsx → Logo/Logo.tsx} +0 -0
  382. /package/packages/web/components/{MarkdownContent.tsx → MarkdownContent/MarkdownContent.tsx} +0 -0
  383. /package/packages/web/components/{ProjectAvatar.tsx → ProjectAvatar/ProjectAvatar.tsx} +0 -0
  384. /package/packages/web/components/{providers.tsx → Providers/Providers.tsx} +0 -0
  385. /package/packages/web/components/{TechStackBadges.tsx → TechStackBadges/TechStackBadges.tsx} +0 -0
@@ -1,338 +0,0 @@
1
- /**
2
- * Prompt Builder
3
- * Builds prompts for Claude based on templates and context
4
- * Claude decides what to do - NO if/else logic here
5
- *
6
- * P1.1: Includes learned patterns from memory system
7
- * P3.1: Includes think blocks for anti-hallucination
8
- * P3.3: Includes relevant memories from semantic database
9
- * P3.4: Includes plan mode instructions
10
- * P4.1: Includes quality checklists (Claude decides which to apply)
11
- */
12
-
13
- const fs = require('fs')
14
- const path = require('path')
15
-
16
- class PromptBuilder {
17
- constructor() {
18
- this._checklistsCache = null
19
- this._checklistRoutingCache = null
20
- }
21
-
22
- /**
23
- * Load quality checklists from templates/checklists/
24
- * Returns checklist content - Claude decides which to apply
25
- * NO if/else logic here - just load and provide
26
- */
27
- loadChecklists() {
28
- if (this._checklistsCache) return this._checklistsCache
29
-
30
- const checklistsDir = path.join(__dirname, '..', '..', 'templates', 'checklists')
31
- const checklists = {}
32
-
33
- try {
34
- if (fs.existsSync(checklistsDir)) {
35
- const files = fs.readdirSync(checklistsDir).filter(f => f.endsWith('.md'))
36
- for (const file of files) {
37
- const name = file.replace('.md', '')
38
- const content = fs.readFileSync(path.join(checklistsDir, file), 'utf-8')
39
- checklists[name] = content
40
- }
41
- }
42
- } catch (err) {
43
- // Silent fail - checklists are optional enhancement
44
- }
45
-
46
- this._checklistsCache = checklists
47
- return checklists
48
- }
49
-
50
- /**
51
- * Load checklist routing template
52
- * Claude reads this to decide which checklists to apply
53
- */
54
- loadChecklistRouting() {
55
- if (this._checklistRoutingCache) return this._checklistRoutingCache
56
-
57
- const routingPath = path.join(__dirname, '..', '..', 'templates', 'agentic', 'checklist-routing.md')
58
-
59
- try {
60
- if (fs.existsSync(routingPath)) {
61
- this._checklistRoutingCache = fs.readFileSync(routingPath, 'utf-8')
62
- }
63
- } catch (err) {
64
- // Silent fail
65
- }
66
-
67
- return this._checklistRoutingCache || null
68
- }
69
- /**
70
- * Build concise prompt - only essentials
71
- * CRITICAL: Includes full agent content if agent is provided
72
- * P1.1: Includes learned patterns to avoid repetitive questions
73
- * P3.1: Includes think blocks for critical decisions
74
- * P3.3: Includes relevant memories from semantic database
75
- * P3.4: Includes plan mode status and constraints
76
- */
77
- build(template, context, state, agent = null, learnedPatterns = null, thinkBlock = null, relevantMemories = null, planInfo = null) {
78
- const parts = []
79
-
80
- // Store context for use in helper methods
81
- this._currentContext = context
82
-
83
- // Agent assignment (CONDITIONAL - only for code-modifying commands)
84
- // Commands like done, ship, recap, next don't need specialized agents
85
- const commandName = template.frontmatter?.name?.replace('p:', '') || ''
86
- const agentCommands = ['now', 'build', 'feature', 'design', 'fix', 'bug', 'test', 'work', 'cleanup', 'spec']
87
- const needsAgent = agentCommands.includes(commandName)
88
-
89
- if (agent && needsAgent) {
90
- // COMPRESSED: Only essential agent info (500 bytes vs 3-5KB)
91
- parts.push(`# AGENT: ${agent.name}\n`)
92
- if (agent.role) parts.push(`Role: ${agent.role}\n`)
93
- if (agent.skills?.length) parts.push(`Skills: ${agent.skills.join(', ')}\n`)
94
- parts.push(`\nApply specialized expertise. Read agent file for details if needed.\n\n`)
95
- }
96
-
97
- // Core instruction (concise)
98
- parts.push(`TASK: ${template.frontmatter.description}\n`)
99
-
100
- // Tools (inline)
101
- if (template.frontmatter['allowed-tools']) {
102
- parts.push(`TOOLS: ${template.frontmatter['allowed-tools'].join(', ')}\n`)
103
- }
104
-
105
- // Critical parameters only
106
- if (context.params?.task || context.params?.description) {
107
- parts.push(`INPUT: ${context.params.task || context.params.description}\n`)
108
- }
109
-
110
- parts.push('\n---\n')
111
-
112
- // Template (only the flow section, skip verbose explanations)
113
- const flowMatch = template.content.match(/## Flow([\s\S]*?)(?=##|$)/)
114
- if (flowMatch) {
115
- parts.push(flowMatch[0])
116
- } else {
117
- // Fallback to full template if no flow section
118
- parts.push(template.content)
119
- }
120
-
121
- // Current state (only if exists and relevant)
122
- const relevantState = this.filterRelevantState(state)
123
- if (relevantState) {
124
- parts.push('\n## PRJCT STATE (Project Management Data)\n')
125
- parts.push(relevantState)
126
- parts.push('\n')
127
- }
128
-
129
- // COMPRESSED: File list (5 files vs 20, saves ~400 bytes)
130
- if (context.files?.length > 0) {
131
- const top5 = context.files.slice(0, 5).join(', ')
132
- parts.push(`\n## FILES: ${context.files.length} available. Top: ${top5}\n`)
133
- parts.push('Read BEFORE modifying. Use Glob/Grep to find more.\n\n')
134
- } else if (context.projectPath) {
135
- parts.push(`\n## PROJECT: ${context.projectPath}\nRead files before modifying.\n\n`)
136
- }
137
-
138
- // OPTIMIZED: Only include patterns for code-modifying commands
139
- // Commands like done, ship, recap, next don't need full patterns
140
- const codeCommands = ['now', 'build', 'feature', 'design', 'cleanup', 'fix', 'bug', 'test', 'init', 'spec', 'work']
141
- const needsPatterns = codeCommands.includes(commandName)
142
-
143
- // Include code patterns analysis for code-modifying commands
144
- // COMPRESSED: Extract only conventions and anti-patterns (800 bytes max vs 6KB)
145
- const codePatternsContent = state?.codePatterns || ''
146
- if (needsPatterns && codePatternsContent && codePatternsContent.trim()) {
147
- const patternSummary = this.extractPatternSummary(codePatternsContent)
148
- if (patternSummary) {
149
- parts.push('\n## CODE PATTERNS\n')
150
- parts.push(patternSummary)
151
- parts.push('\nFull patterns: Read analysis/patterns.md\n')
152
- }
153
- }
154
-
155
- const analysisContent = state?.analysis || ''
156
- if (needsPatterns && analysisContent && analysisContent.trim()) {
157
- // Extract stack info compactly
158
- const stackMatch = analysisContent.match(/Stack[:\s]+([^\n]+)/i) ||
159
- analysisContent.match(/Technology[:\s]+([^\n]+)/i)
160
- const stack = stackMatch ? stackMatch[1].trim() : 'detected'
161
-
162
- parts.push(`\n## STACK\nStack: ${stack}\n`)
163
- if (!codePatternsContent) {
164
- parts.push('Read analysis/repo-summary.md + similar files before coding. Match patterns exactly.\n')
165
- }
166
- }
167
-
168
- // CRITICAL: Compressed rules (replaces 78 lines with 12)
169
- parts.push(this.buildCriticalRules());
170
-
171
- // P1.1: Learned Patterns (avoid asking user questions we already know)
172
- if (learnedPatterns && Object.keys(learnedPatterns).some(k => learnedPatterns[k])) {
173
- parts.push('\n## LEARNED PATTERNS (use these, do NOT ask user)\n')
174
- for (const [key, value] of Object.entries(learnedPatterns)) {
175
- if (value) {
176
- parts.push(`- ${key}: ${value}\n`)
177
- }
178
- }
179
- }
180
-
181
- // P3.1: Think Block (reasoning before action)
182
- if (thinkBlock && thinkBlock.plan && thinkBlock.plan.length > 0) {
183
- parts.push('\n## THINK FIRST (reasoning from analysis)\n')
184
- if (thinkBlock.conclusions && thinkBlock.conclusions.length > 0) {
185
- parts.push('Conclusions:\n')
186
- thinkBlock.conclusions.forEach(c => parts.push(` → ${c}\n`))
187
- }
188
- parts.push('Plan:\n')
189
- thinkBlock.plan.forEach((p, i) => parts.push(` ${i + 1}. ${p}\n`))
190
- parts.push(`Confidence: ${Math.round((thinkBlock.confidence || 0.5) * 100)}%\n`)
191
- }
192
-
193
- // P3.3: Relevant Memories (context from past decisions)
194
- if (relevantMemories && relevantMemories.length > 0) {
195
- parts.push('\n## RELEVANT MEMORIES (apply these learnings)\n')
196
- for (const memory of relevantMemories) {
197
- parts.push(`- **${memory.title}**: ${memory.content}\n`)
198
- if (memory.tags && memory.tags.length > 0) {
199
- parts.push(` Tags: ${memory.tags.join(', ')}\n`)
200
- }
201
- }
202
- }
203
-
204
- // P3.4: Plan Mode (OPTIMIZED: 30 lines → 5 lines)
205
- if (planInfo?.isPlanning) {
206
- parts.push(`\n## PLAN MODE\nRead-only. Gather info → Analyze → Propose plan → Wait for approval.\n`)
207
- if (planInfo.allowedTools) parts.push(`Tools: ${planInfo.allowedTools.join(', ')}\n`)
208
- }
209
- if (planInfo?.requiresApproval) {
210
- parts.push(`\n## APPROVAL REQUIRED\nShow changes, list affected files, ask for confirmation.\n`)
211
- }
212
-
213
- // P4.1: Quality Checklists (Claude decides which to apply)
214
- // Only for code-modifying commands that benefit from quality gates
215
- const checklistCommands = ['now', 'build', 'feature', 'design', 'fix', 'bug', 'cleanup', 'spec', 'work']
216
- if (checklistCommands.includes(commandName)) {
217
- const routing = this.loadChecklistRouting()
218
- const checklists = this.loadChecklists()
219
-
220
- if (routing && Object.keys(checklists).length > 0) {
221
- parts.push('\n## QUALITY CHECKLISTS\n')
222
- parts.push('Apply relevant checklists based on task. Read checklist-routing.md for guidance.\n')
223
- parts.push(`Available: ${Object.keys(checklists).join(', ')}\n`)
224
- parts.push('Path: templates/checklists/{name}.md\n')
225
- parts.push('Use Read tool to load checklists you determine are relevant.\n')
226
- }
227
- }
228
-
229
- // Simple execution directive
230
- parts.push('\nEXECUTE: Follow flow. Use tools. Decide.\n')
231
-
232
- return parts.join('')
233
- }
234
-
235
- /**
236
- * Filter only relevant state data
237
- * IMPROVED: Include more context, don't truncate critical info
238
- */
239
- filterRelevantState(state) {
240
- if (!state || Object.keys(state).length === 0) return null
241
-
242
- const relevant = []
243
- for (const [key, content] of Object.entries(state)) {
244
- if (content && content.trim()) {
245
- // Include full content for critical files (now, next, context, patterns)
246
- const criticalFiles = ['now', 'next', 'context', 'analysis', 'codePatterns']
247
- if (criticalFiles.includes(key)) {
248
- // Include full content for critical files (up to 2000 chars)
249
- const display = content.length > 2000
250
- ? content.substring(0, 2000) + '\n... (truncated)'
251
- : content
252
- relevant.push(`### ${key}\n${display}`)
253
- } else if (content.length < 1000) {
254
- // Include full content for small files
255
- relevant.push(`### ${key}\n${content}`)
256
- } else {
257
- // Truncate large files but show more context
258
- relevant.push(`### ${key}\n${content.substring(0, 500)}... (truncated, use Read tool for full content)`)
259
- }
260
- }
261
- }
262
-
263
- return relevant.length > 0 ? relevant.join('\n\n') : null
264
- }
265
-
266
- /**
267
- * Build analysis prompt
268
- * Used for tasks that need Claude to analyze before acting
269
- * @param {string} analysisType - Type of analysis
270
- * @param {Object} context - Context
271
- * @returns {string} Analysis prompt
272
- */
273
- buildAnalysis(analysisType, context) {
274
- const parts = []
275
-
276
- parts.push(`# Analyze: ${analysisType}\n\n`)
277
- parts.push('Read the project context and provide your analysis.\n')
278
- parts.push('No predetermined patterns - decide based on what you find.\n\n')
279
-
280
- parts.push('## Project Context\n')
281
- parts.push(`- Path: ${context.projectPath}\n`)
282
- parts.push(`- ID: ${context.projectId}\n\n`)
283
-
284
- return parts.join('')
285
- }
286
-
287
- /**
288
- * Extract pattern summary from full patterns content
289
- * OPTIMIZED: Returns only conventions + high-priority anti-patterns (800 bytes max)
290
- */
291
- extractPatternSummary(content) {
292
- if (!content) return null
293
-
294
- const parts = []
295
-
296
- // Extract conventions section
297
- const conventionsMatch = content.match(/## Conventions[\s\S]*?(?=##|$)/i)
298
- if (conventionsMatch) {
299
- // Compress to key lines only
300
- const conventions = conventionsMatch[0]
301
- .split('\n')
302
- .filter(line => line.includes(':') || line.startsWith('-'))
303
- .slice(0, 6)
304
- .join('\n')
305
- if (conventions) parts.push(conventions)
306
- }
307
-
308
- // Extract high priority anti-patterns only
309
- const antiPatternsMatch = content.match(/### High Priority[\s\S]*?(?=###|##|$)/i)
310
- if (antiPatternsMatch) {
311
- const antiPatterns = antiPatternsMatch[0].substring(0, 300)
312
- parts.push('\nAvoid:\n' + antiPatterns)
313
- }
314
-
315
- const result = parts.join('\n').substring(0, 800)
316
- return result || null
317
- }
318
-
319
- /**
320
- * Build critical rules - compressed anti-hallucination
321
- * OPTIMIZED: From 66 lines to 12 lines (~82% reduction)
322
- */
323
- buildCriticalRules() {
324
- const fileCount = this._currentContext?.files?.length || this._currentContext?.filteredSize || 0
325
- return `
326
- ## RULES (CRITICAL)
327
- 1. **READ FIRST**: Use Read tool BEFORE modifying any file. Never assume code structure.
328
- 2. **MATCH PATTERNS**: Follow existing style, architecture, naming, imports exactly.
329
- 3. **NO HALLUCINATIONS**: Don't invent files, functions, or paths. If unsure, READ first.
330
- 4. **GIT SAFETY**: Never use checkout/reset --hard/clean. Always check status first.
331
- 5. **VERIFY**: After writing, confirm code matches project patterns.
332
- Context: ${fileCount} files available. Read what you need.
333
- `;
334
- }
335
-
336
- }
337
-
338
- module.exports = new PromptBuilder()
@@ -1,290 +0,0 @@
1
- /**
2
- * Response Templates
3
- * Minimal output templates for all commands
4
- * Rule: < 4 lines, always actionable
5
- *
6
- * OPTIMIZATION (P0.3): Minimal Output
7
- * - Concise responses (< 4 lines)
8
- * - Always suggest next action
9
- * - Use symbols for status, not words
10
- *
11
- * Source: Claude Code, Kiro patterns
12
- */
13
-
14
- /**
15
- * Format duration from milliseconds or ISO strings
16
- * @param {number|string|Date} start - Start time
17
- * @param {number|string|Date} end - End time (defaults to now)
18
- * @returns {string} Human-readable duration
19
- */
20
- function formatDuration(start, end = new Date()) {
21
- const startMs = new Date(start).getTime()
22
- const endMs = new Date(end).getTime()
23
- const diffMs = endMs - startMs
24
-
25
- const hours = Math.floor(diffMs / (1000 * 60 * 60))
26
- const minutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60))
27
-
28
- if (hours > 0) {
29
- return `${hours}h ${minutes}m`
30
- }
31
- return `${minutes}m`
32
- }
33
-
34
- /**
35
- * Truncate text to max length with ellipsis
36
- * @param {string} text - Text to truncate
37
- * @param {number} maxLength - Maximum length
38
- * @returns {string}
39
- */
40
- function truncate(text, maxLength = 40) {
41
- if (!text) return ''
42
- if (text.length <= maxLength) return text
43
- return text.substring(0, maxLength - 3) + '...'
44
- }
45
-
46
- /**
47
- * Response templates for each command
48
- * Each template is a function that returns minimal formatted output
49
- */
50
- const templates = {
51
- /**
52
- * /p:done - Task completed
53
- */
54
- done: ({ task, duration, nextTask }) => {
55
- let output = `✓ '${truncate(task)}' (${duration})`
56
- if (nextTask) {
57
- output += `\n→ Next: '${truncate(nextTask)}'`
58
- }
59
- output += '\n\n/p:ship to release'
60
- return output
61
- },
62
-
63
- /**
64
- * /p:now - Current task set/shown
65
- */
66
- now: ({ task, started, isNew }) => {
67
- if (!task) {
68
- return `No active task\n→ /p:now "task" to start`
69
- }
70
- if (isNew) {
71
- return `🎯 Started: '${truncate(task)}'\n→ /p:done when complete`
72
- }
73
- return `🎯 Working on: '${truncate(task)}'\n⏱️ ${started || 'just now'}\n→ /p:done when complete`
74
- },
75
-
76
- /**
77
- * /p:next - Priority queue
78
- */
79
- next: ({ tasks, total }) => {
80
- if (!tasks || tasks.length === 0) {
81
- return `Queue empty\n→ /p:feature or /p:idea to add`
82
- }
83
- const top3 = tasks.slice(0, 3).map((t, i) =>
84
- `${i + 1}. ${truncate(t.name, 35)}`
85
- ).join('\n')
86
- const more = total > 3 ? `\n+${total - 3} more` : ''
87
- return `${top3}${more}\n\n/p:now 1 to start`
88
- },
89
-
90
- /**
91
- * /p:ship - Feature shipped
92
- */
93
- ship: ({ feature, agent, duration, version }) => {
94
- let output = `🚀 Shipped: '${truncate(feature)}'`
95
- if (agent) output += ` (${agent})`
96
- if (duration) output += ` | ${duration}`
97
- if (version) output += ` | v${version}`
98
- output += '\n→ /compact recommended'
99
- return output
100
- },
101
-
102
- /**
103
- * /p:idea - Idea captured
104
- */
105
- idea: ({ idea, addedToQueue }) => {
106
- let output = `💡 Captured: '${truncate(idea)}'`
107
- if (addedToQueue) {
108
- output += '\n→ Added to queue'
109
- }
110
- output += '\n\n/p:next to see queue'
111
- return output
112
- },
113
-
114
- /**
115
- * /p:feature - Feature added
116
- */
117
- feature: ({ feature, tasks, impact, effort }) => {
118
- let output = `📋 Feature: '${truncate(feature)}'`
119
- if (tasks) output += ` (${tasks} tasks)`
120
- if (impact) output += `\nImpact: ${impact}`
121
- if (effort) output += ` | Effort: ${effort}`
122
- output += '\n\n/p:now to start'
123
- return output
124
- },
125
-
126
- /**
127
- * /p:bug - Bug reported
128
- */
129
- bug: ({ description, priority, addedAt }) => {
130
- const priorityIcon = {
131
- 'critical': '🔴',
132
- 'high': '🟠',
133
- 'medium': '🟡',
134
- 'low': '🟢'
135
- }[priority] || '🟡'
136
-
137
- let output = `${priorityIcon} Bug: '${truncate(description)}'\nPriority: ${priority}`
138
- if (addedAt) {
139
- output += ` | Added: ${addedAt}`
140
- }
141
- output += '\n\n/p:now to fix'
142
- return output
143
- },
144
-
145
- /**
146
- * /p:pause - Task paused
147
- */
148
- pause: ({ task, duration }) => {
149
- return `⏸️ Paused: '${truncate(task)}' (${duration})\n→ /p:resume to continue`
150
- },
151
-
152
- /**
153
- * /p:resume - Task resumed
154
- */
155
- resume: ({ task, pausedFor }) => {
156
- return `▶️ Resumed: '${truncate(task)}'\nPaused for: ${pausedFor}\n→ /p:done when complete`
157
- },
158
-
159
- /**
160
- * /p:recap - Project overview
161
- */
162
- recap: ({ shipped, inProgress, queued, momentum }) => {
163
- const momentumIcon = {
164
- 'high': '🔥',
165
- 'medium': '✨',
166
- 'low': '💤'
167
- }[momentum] || '✨'
168
-
169
- return `${momentumIcon} ${shipped} shipped | ${inProgress ? '1 active' : '0 active'} | ${queued} queued`
170
- },
171
-
172
- /**
173
- * /p:progress - Progress metrics
174
- */
175
- progress: ({ period, shipped, velocity, trend }) => {
176
- const trendIcon = trend > 0 ? '↑' : trend < 0 ? '↓' : '→'
177
- return `📊 ${period}: ${shipped} shipped\nVelocity: ${velocity}/week ${trendIcon}`
178
- },
179
-
180
- /**
181
- * /p:analyze - Analysis complete
182
- */
183
- analyze: ({ stack, files, agents }) => {
184
- return `🔍 Analyzed: ${stack}\n${files} files | ${agents} agents generated\n\n/p:sync to update`
185
- },
186
-
187
- /**
188
- * /p:sync - Sync complete
189
- */
190
- sync: ({ updated, agents }) => {
191
- return `🔄 Synced: ${updated} files updated\n${agents} agents refreshed`
192
- },
193
-
194
- /**
195
- * /p:help - Help shown
196
- */
197
- help: ({ context, suggestions }) => {
198
- const sugs = suggestions.slice(0, 3).map(s => `• ${s}`).join('\n')
199
- return `📚 ${context}\n\n${sugs}`
200
- },
201
-
202
- /**
203
- * /p:suggest - Suggestions
204
- */
205
- suggest: ({ urgency, suggestion, command }) => {
206
- const urgencyIcon = {
207
- 'high': '🔥',
208
- 'medium': '💡',
209
- 'low': '✨'
210
- }[urgency] || '💡'
211
-
212
- return `${urgencyIcon} ${suggestion}\n→ ${command}`
213
- },
214
-
215
- /**
216
- * /p:spec - Spec created/updated
217
- */
218
- spec: ({ name, status, tasks, requirements, isNew }) => {
219
- let output = isNew
220
- ? `📋 Created spec: '${truncate(name)}'`
221
- : `📋 Updated spec: '${truncate(name)}'`
222
-
223
- if (requirements) output += `\n${requirements} requirements`
224
- if (tasks) output += ` | ${tasks} tasks`
225
- if (status) output += ` | Status: ${status}`
226
-
227
- output += '\n\n→ Review and approve to start'
228
- return output
229
- },
230
-
231
- /**
232
- * Generic success response
233
- */
234
- success: ({ message, nextAction }) => {
235
- let output = `✓ ${message}`
236
- if (nextAction) {
237
- output += `\n→ ${nextAction}`
238
- }
239
- return output
240
- },
241
-
242
- /**
243
- * Generic error response
244
- */
245
- error: ({ error, suggestion }) => {
246
- let output = `❌ ${error}`
247
- if (suggestion) {
248
- output += `\n→ ${suggestion}`
249
- }
250
- return output
251
- }
252
- }
253
-
254
- /**
255
- * Format a response using the appropriate template
256
- *
257
- * @param {string} commandName - Command name
258
- * @param {Object} data - Data for the template
259
- * @returns {string} Formatted response
260
- */
261
- function format(commandName, data) {
262
- const template = templates[commandName]
263
- if (!template) {
264
- // Fallback to generic success/error
265
- if (data.error) {
266
- return templates.error(data)
267
- }
268
- return templates.success(data)
269
- }
270
-
271
- return template(data)
272
- }
273
-
274
- /**
275
- * Check if response exceeds recommended length
276
- * @param {string} response - Response text
277
- * @returns {boolean} True if too long
278
- */
279
- function isTooLong(response) {
280
- const lines = response.split('\n').filter(l => l.trim())
281
- return lines.length > 4
282
- }
283
-
284
- module.exports = {
285
- format,
286
- templates,
287
- formatDuration,
288
- truncate,
289
- isTooLong
290
- }