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
package/bin/prjct CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env bun
2
2
 
3
3
  /**
4
4
  * prjct CLI entry point
@@ -6,8 +6,8 @@
6
6
  * Auto-setup on first use (like Astro, Vite, etc.)
7
7
  */
8
8
 
9
- const { VERSION } = require('../core/utils/version')
10
- const editorsConfig = require('../core/infrastructure/editors-config')
9
+ const { VERSION } = require('../core/utils/version.ts')
10
+ const editorsConfig = require('../core/infrastructure/editors-config.ts').default
11
11
 
12
12
  // Check for special subcommands that bypass normal CLI
13
13
  const args = process.argv.slice(2)
@@ -31,7 +31,7 @@ if (args[0] === 'dev') {
31
31
  console.log('🔧 One-time setup (v' + VERSION + ')...')
32
32
  console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n')
33
33
 
34
- const setup = require('../core/infrastructure/setup')
34
+ const setup = require('../core/infrastructure/setup.ts').default
35
35
  await setup.run()
36
36
 
37
37
  console.log('✓ Setup complete!\n')
@@ -42,7 +42,7 @@ if (args[0] === 'dev') {
42
42
  }
43
43
 
44
44
  // Continue to main CLI logic
45
- require('../core/index')
45
+ require('../core/index.ts')
46
46
  })()
47
47
 
48
48
  } // end else
package/bin/serve.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env bun
2
2
 
3
3
  /**
4
4
  * prjct serve - Start the web server
@@ -6,21 +6,26 @@
6
6
  * Launches the prjct web interface with Claude Code CLI integration.
7
7
  * Uses your existing Claude subscription via PTY - no API costs!
8
8
  *
9
- * Auto-installs dependencies on first run.
9
+ * Smart dependency management:
10
+ * - Tracks installed version in .prjct-web-state.json
11
+ * - Only installs when version changes or node_modules missing
12
+ * - Reuses existing prjct-web server if already running on port
10
13
  */
11
14
 
12
- const { spawn, spawnSync } = require('child_process')
15
+ const { spawn, spawnSync, execSync } = require('child_process')
13
16
  const path = require('path')
14
17
  const fs = require('fs')
15
18
 
16
19
  const packagesDir = path.join(__dirname, '..', 'packages')
17
20
  const sharedDir = path.join(packagesDir, 'shared')
18
21
  const webDir = path.join(packagesDir, 'web')
22
+ const prjctDir = path.join(require('os').homedir(), '.prjct-cli')
23
+ const stateFile = path.join(prjctDir, '.prjct-web-state.json')
19
24
 
20
25
  // Parse arguments
21
26
  const args = process.argv.slice(2)
22
27
  const portArg = args.find((a) => a.startsWith('--port='))
23
- const port = portArg ? portArg.split('=')[1] : '3000'
28
+ const port = portArg ? portArg.split('=')[1] : '9472'
24
29
 
25
30
  // Check if web package exists
26
31
  if (!fs.existsSync(webDir)) {
@@ -30,26 +35,123 @@ if (!fs.existsSync(webDir)) {
30
35
  process.exit(1)
31
36
  }
32
37
 
33
- // Check if dependencies are installed
34
- const sharedNodeModules = path.join(sharedDir, 'node_modules')
35
- const webNodeModules = path.join(webDir, 'node_modules')
36
- const needsSharedInstall = fs.existsSync(sharedDir) && !fs.existsSync(sharedNodeModules)
37
- const needsWebInstall = !fs.existsSync(webNodeModules)
38
+ /**
39
+ * Read the current state file
40
+ */
41
+ function readState() {
42
+ try {
43
+ if (fs.existsSync(stateFile)) {
44
+ return JSON.parse(fs.readFileSync(stateFile, 'utf8'))
45
+ }
46
+ } catch {
47
+ // Ignore errors, return empty state
48
+ }
49
+ return {}
50
+ }
51
+
52
+ /**
53
+ * Write state file
54
+ */
55
+ function writeState(state) {
56
+ try {
57
+ // Ensure ~/.prjct-cli directory exists
58
+ if (!fs.existsSync(prjctDir)) {
59
+ fs.mkdirSync(prjctDir, { recursive: true })
60
+ }
61
+ fs.writeFileSync(stateFile, JSON.stringify(state, null, 2))
62
+ } catch {
63
+ // Ignore write errors
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Get package.json version and hash of dependencies
69
+ */
70
+ function getPackageInfo(pkgPath) {
71
+ try {
72
+ const pkg = JSON.parse(fs.readFileSync(path.join(pkgPath, 'package.json'), 'utf8'))
73
+ const deps = JSON.stringify(pkg.dependencies || {}) + JSON.stringify(pkg.devDependencies || {})
74
+ // Simple hash of dependencies
75
+ let hash = 0
76
+ for (let i = 0; i < deps.length; i++) {
77
+ const char = deps.charCodeAt(i)
78
+ hash = ((hash << 5) - hash) + char
79
+ hash = hash & hash // Convert to 32bit integer
80
+ }
81
+ return { version: pkg.version, depsHash: hash.toString(16) }
82
+ } catch {
83
+ return { version: '0.0.0', depsHash: '0' }
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Check if dependencies need to be installed
89
+ */
90
+ function needsInstall(pkgDir, stateKey) {
91
+ const nodeModules = path.join(pkgDir, 'node_modules')
92
+
93
+ // If node_modules doesn't exist, definitely need install
94
+ if (!fs.existsSync(nodeModules)) {
95
+ return { needed: true, reason: 'node_modules not found' }
96
+ }
97
+
98
+ const state = readState()
99
+ const pkgInfo = getPackageInfo(pkgDir)
100
+ const savedInfo = state[stateKey]
101
+
102
+ // If no saved state, need install to track
103
+ if (!savedInfo) {
104
+ return { needed: true, reason: 'first time tracking' }
105
+ }
106
+
107
+ // If version changed, need install
108
+ if (savedInfo.version !== pkgInfo.version) {
109
+ return { needed: true, reason: `version changed: ${savedInfo.version} → ${pkgInfo.version}` }
110
+ }
111
+
112
+ // If dependencies hash changed, need install
113
+ if (savedInfo.depsHash !== pkgInfo.depsHash) {
114
+ return { needed: true, reason: 'dependencies changed' }
115
+ }
116
+
117
+ return { needed: false }
118
+ }
119
+
120
+ /**
121
+ * Update state after successful install
122
+ */
123
+ function markInstalled(pkgDir, stateKey) {
124
+ const state = readState()
125
+ const pkgInfo = getPackageInfo(pkgDir)
126
+ state[stateKey] = {
127
+ version: pkgInfo.version,
128
+ depsHash: pkgInfo.depsHash,
129
+ installedAt: new Date().toISOString()
130
+ }
131
+ writeState(state)
132
+ }
133
+
134
+ // Check if dependencies need installation
135
+ const sharedCheck = fs.existsSync(sharedDir) ? needsInstall(sharedDir, 'shared') : { needed: false }
136
+ const webCheck = needsInstall(webDir, 'web')
137
+
138
+ if (sharedCheck.needed || webCheck.needed) {
139
+ const reasons = []
140
+ if (sharedCheck.needed) reasons.push(`shared: ${sharedCheck.reason}`)
141
+ if (webCheck.needed) reasons.push(`web: ${webCheck.reason}`)
38
142
 
39
- if (needsSharedInstall || needsWebInstall) {
40
143
  console.log(`
41
144
  ╔═══════════════════════════════════════════════════════════╗
42
145
  ║ ║
43
- ║ ⚡ prjct - First Time Setup
146
+ ║ ⚡ prjct - Dependency Update
44
147
  ║ ║
45
- Installing web dependencies...
46
- ║ This only happens once. ║
148
+ ${reasons.join(', ').substring(0, 45).padEnd(45)}
47
149
  ║ ║
48
150
  ╚═══════════════════════════════════════════════════════════╝
49
151
  `)
50
152
 
51
- // Install shared dependencies first (if exists)
52
- if (needsSharedInstall) {
153
+ // Install shared dependencies first (if needed)
154
+ if (sharedCheck.needed) {
53
155
  console.log('📦 Installing packages/shared dependencies...')
54
156
  const sharedInstall = spawnSync('npm', ['install'], {
55
157
  cwd: sharedDir,
@@ -73,10 +175,12 @@ if (needsSharedInstall || needsWebInstall) {
73
175
  if (sharedBuild.status !== 0) {
74
176
  console.error('⚠️ Warning: Failed to build shared package')
75
177
  }
178
+
179
+ markInstalled(sharedDir, 'shared')
76
180
  }
77
181
 
78
- // Install web dependencies
79
- if (needsWebInstall) {
182
+ // Install web dependencies (if needed)
183
+ if (webCheck.needed) {
80
184
  console.log('📦 Installing packages/web dependencies...')
81
185
  const webInstall = spawnSync('npm', ['install'], {
82
186
  cwd: webDir,
@@ -88,55 +192,133 @@ if (needsSharedInstall || needsWebInstall) {
88
192
  console.error('❌ Failed to install web dependencies')
89
193
  process.exit(1)
90
194
  }
195
+
196
+ markInstalled(webDir, 'web')
91
197
  }
92
198
 
93
- console.log('✅ Dependencies installed!\n')
199
+ console.log('✅ Dependencies ready!\n')
200
+ } else {
201
+ console.log('✅ Dependencies up to date\n')
202
+ }
203
+
204
+ /**
205
+ * Check if process on port is a prjct-web server
206
+ */
207
+ function isPrjctWebProcess(pid) {
208
+ try {
209
+ if (process.platform === 'win32') {
210
+ const result = spawnSync('wmic', ['process', 'where', `processid=${pid}`, 'get', 'commandline'], {
211
+ shell: true,
212
+ encoding: 'utf8',
213
+ })
214
+ return result.stdout.includes('server.ts') || result.stdout.includes('prjct')
215
+ } else {
216
+ // macOS / Linux - check process command line
217
+ const result = spawnSync('ps', ['-p', pid, '-o', 'command='], {
218
+ shell: true,
219
+ encoding: 'utf8',
220
+ })
221
+ const cmd = result.stdout.trim()
222
+ return cmd.includes('server.ts') || cmd.includes('prjct') || cmd.includes('next')
223
+ }
224
+ } catch {
225
+ return false
226
+ }
94
227
  }
95
228
 
96
- // Kill any process using the port
97
- function killPort(portToKill) {
229
+ /**
230
+ * Get PIDs using a port
231
+ */
232
+ function getPortPids(portToCheck) {
98
233
  try {
99
234
  if (process.platform === 'win32') {
100
- // Windows
101
235
  const result = spawnSync('netstat', ['-ano'], { shell: true, encoding: 'utf8' })
236
+ const pids = []
102
237
  const lines = result.stdout.split('\n')
103
238
  for (const line of lines) {
104
- if (line.includes(`:${portToKill}`) && line.includes('LISTENING')) {
239
+ if (line.includes(`:${portToCheck}`) && line.includes('LISTENING')) {
105
240
  const parts = line.trim().split(/\s+/)
106
241
  const pid = parts[parts.length - 1]
107
- if (pid && pid !== '0') {
108
- spawnSync('taskkill', ['/F', '/PID', pid], { shell: true })
109
- }
242
+ if (pid && pid !== '0') pids.push(pid)
110
243
  }
111
244
  }
245
+ return pids
112
246
  } else {
113
- // macOS / Linux
114
- const result = spawnSync('lsof', ['-ti', `:${portToKill}`], {
247
+ const result = spawnSync('lsof', ['-ti', `:${portToCheck}`], {
115
248
  shell: true,
116
249
  encoding: 'utf8',
117
250
  })
118
- const pids = result.stdout.trim().split('\n').filter(Boolean)
119
- for (const pid of pids) {
251
+ return result.stdout.trim().split('\n').filter(Boolean)
252
+ }
253
+ } catch {
254
+ return []
255
+ }
256
+ }
257
+
258
+ /**
259
+ * Kill specific PIDs
260
+ */
261
+ function killPids(pids) {
262
+ for (const pid of pids) {
263
+ try {
264
+ if (process.platform === 'win32') {
265
+ spawnSync('taskkill', ['/F', '/PID', pid], { shell: true })
266
+ } else {
120
267
  spawnSync('kill', ['-9', pid], { shell: true })
121
268
  }
269
+ } catch {
270
+ // Ignore individual kill errors
122
271
  }
123
- } catch {
124
- // Ignore errors - port might not be in use
125
272
  }
126
273
  }
127
274
 
128
- // Kill port if occupied
129
- const checkPort = spawnSync('lsof', ['-ti', `:${port}`], {
130
- shell: true,
131
- encoding: 'utf8',
132
- })
275
+ /**
276
+ * Open URL in browser
277
+ */
278
+ function openBrowser(url) {
279
+ const openCmd =
280
+ process.platform === 'darwin'
281
+ ? 'open'
282
+ : process.platform === 'win32'
283
+ ? 'start'
284
+ : 'xdg-open'
285
+ spawn(openCmd, [url], { shell: true, detached: true }).unref()
286
+ }
287
+
288
+ // Check if port is in use and handle accordingly
289
+ const portPids = getPortPids(port)
290
+ let serverAlreadyRunning = false
291
+
292
+ if (portPids.length > 0) {
293
+ // Check if it's a prjct-web server
294
+ const isPrjctWeb = portPids.some(pid => isPrjctWebProcess(pid))
295
+
296
+ if (isPrjctWeb) {
297
+ console.log(`
298
+ ╔═══════════════════════════════════════════════════════════╗
299
+ ║ ║
300
+ ║ ⚡ prjct - Server Already Running ║
301
+ ║ ║
302
+ ║ Found existing prjct-web on port ${port} ║
303
+ ║ Opening browser... ║
304
+ ║ ║
305
+ ╚═══════════════════════════════════════════════════════════╝
306
+ `)
307
+ openBrowser(`http://localhost:${port}`)
308
+ serverAlreadyRunning = true
309
+ } else {
310
+ // Not a prjct-web process, ask before killing
311
+ console.log(`⚠️ Port ${port} is in use by another process.`)
312
+ console.log(` PIDs: ${portPids.join(', ')}`)
313
+ console.log(` Stopping to avoid killing unrelated processes.`)
314
+ console.log(` Use --port=XXXX to specify a different port.`)
315
+ process.exit(1)
316
+ }
317
+ }
133
318
 
134
- if (checkPort.stdout.trim()) {
135
- console.log(`⚠️ Port ${port} is in use. Killing existing process...`)
136
- killPort(port)
137
- // Small delay to ensure port is released
138
- spawnSync('sleep', ['1'], { shell: true })
139
- console.log(`✅ Port ${port} freed\n`)
319
+ // If server is already running, we're done - just opened browser above
320
+ if (serverAlreadyRunning) {
321
+ process.exit(0)
140
322
  }
141
323
 
142
324
  console.log(`
@@ -144,32 +326,42 @@ console.log(`
144
326
  ║ ║
145
327
  ║ ⚡ prjct - Developer Momentum ║
146
328
  ║ ║
147
- ║ Starting web server...
329
+ ║ Starting production server...
148
330
  ║ ║
149
- ║ Web: http://localhost:${port}
331
+ ║ Web: http://localhost:${port}
150
332
  ║ ║
151
333
  ║ Using your Claude subscription - $0 API costs ║
152
334
  ║ ║
153
335
  ╚═══════════════════════════════════════════════════════════╝
154
336
  `)
155
337
 
156
- // Start web dev server
157
- const web = spawn('npm', ['run', 'dev'], {
338
+ // Build for production if needed (first run or .next missing)
339
+ const nextDir = path.join(webDir, '.next')
340
+ if (!fs.existsSync(nextDir)) {
341
+ console.log('🔨 Building for production (first run)...\n')
342
+ const buildResult = spawnSync('npm', ['run', 'build'], {
343
+ cwd: webDir,
344
+ stdio: 'inherit',
345
+ shell: true,
346
+ })
347
+ if (buildResult.status !== 0) {
348
+ console.error('❌ Build failed')
349
+ process.exit(1)
350
+ }
351
+ console.log('✅ Build complete!\n')
352
+ }
353
+
354
+ // Start web server in production mode
355
+ const web = spawn('npm', ['run', 'start:prod'], {
158
356
  cwd: webDir,
159
357
  stdio: 'inherit',
160
358
  shell: true,
161
- env: { ...process.env, PORT: port },
359
+ env: { ...process.env, PORT: port, NODE_ENV: 'production' },
162
360
  })
163
361
 
164
362
  // Open browser after a short delay
165
363
  setTimeout(() => {
166
- const openCmd =
167
- process.platform === 'darwin'
168
- ? 'open'
169
- : process.platform === 'win32'
170
- ? 'start'
171
- : 'xdg-open'
172
- spawn(openCmd, [`http://localhost:${port}`], { shell: true })
364
+ openBrowser(`http://localhost:${port}`)
173
365
  }, 3000)
174
366
 
175
367
  // Handle shutdown
@@ -3,27 +3,21 @@
3
3
  * P3.3: Semantic Memory Database
4
4
  */
5
5
 
6
- const memorySystem = require('../../agentic/memory-system')
7
- const fs = require('fs').promises
8
- const path = require('path')
9
- const os = require('os')
6
+ import { describe, it, expect, beforeEach, afterEach } from 'bun:test'
7
+ import memorySystem from '../../agentic/memory-system'
8
+ import fs from 'fs/promises'
9
+ import path from 'path'
10
+ import os from 'os'
10
11
 
11
- // Generate unique project ID for each test run
12
12
  let testCounter = 0
13
13
  const getTestProjectId = () => `test-memory-${Date.now()}-${++testCounter}`
14
14
 
15
15
  describe('MemorySystem P3.3', () => {
16
- let TEST_PROJECT_ID
16
+ let TEST_PROJECT_ID: string
17
17
 
18
18
  beforeEach(() => {
19
- // Use unique project ID for each test to avoid data leakage
20
19
  TEST_PROJECT_ID = getTestProjectId()
21
- // Reset internal state
22
- memorySystem._memories = null
23
- memorySystem._memoriesLoaded = false
24
- memorySystem._patterns = null
25
- memorySystem._patternsLoaded = false
26
- memorySystem._sessionMemory.clear()
20
+ memorySystem.resetState()
27
21
  })
28
22
 
29
23
  describe('createMemory', () => {
@@ -64,10 +58,10 @@ describe('MemorySystem P3.3', () => {
64
58
  const memories = await memorySystem.getAllMemories(TEST_PROJECT_ID)
65
59
  const memory = memories.find(m => m.id === memoryId)
66
60
 
67
- expect(memory.title).toBe('Updated Title')
68
- expect(memory.content).toBe('Updated content')
69
- expect(memory.tags).toContain('architecture')
70
- expect(memory.tags).not.toContain('code_style')
61
+ expect(memory!.title).toBe('Updated Title')
62
+ expect(memory!.content).toBe('Updated content')
63
+ expect(memory!.tags).toContain('architecture')
64
+ expect(memory!.tags).not.toContain('code_style')
71
65
  })
72
66
 
73
67
  it('should return false for non-existent memory', async () => {
@@ -96,7 +90,6 @@ describe('MemorySystem P3.3', () => {
96
90
 
97
91
  describe('findByTags', () => {
98
92
  beforeEach(async () => {
99
- // Create test memories
100
93
  await memorySystem.createMemory(TEST_PROJECT_ID, {
101
94
  title: 'Memory 1',
102
95
  content: 'Content 1',
@@ -160,7 +153,6 @@ describe('MemorySystem P3.3', () => {
160
153
 
161
154
  describe('getRelevantMemories', () => {
162
155
  beforeEach(async () => {
163
- // Create memories with different relevance
164
156
  await memorySystem.createMemory(TEST_PROJECT_ID, {
165
157
  title: 'Commit Style',
166
158
  content: 'Use conventional commits',
@@ -184,7 +176,6 @@ describe('MemorySystem P3.3', () => {
184
176
  const results = await memorySystem.getRelevantMemories(TEST_PROJECT_ID, context, 5)
185
177
 
186
178
  expect(results.length).toBeGreaterThan(0)
187
- // Ship command should prioritize commit_style and ship_workflow tags
188
179
  const hasRelevantTags = results.some(m =>
189
180
  m.tags.includes('commit_style') || m.tags.includes('ship_workflow')
190
181
  )
@@ -195,9 +186,8 @@ describe('MemorySystem P3.3', () => {
195
186
  const context = { commandName: 'ship', params: {} }
196
187
  const results = await memorySystem.getRelevantMemories(TEST_PROJECT_ID, context, 5)
197
188
 
198
- // User triggered should be ranked higher
199
189
  const userTriggeredIndex = results.findIndex(m => m.userTriggered)
200
- expect(userTriggeredIndex).toBeLessThanOrEqual(1) // Should be in top 2
190
+ expect(userTriggeredIndex).toBeLessThanOrEqual(1)
201
191
  })
202
192
 
203
193
  it('should limit results', async () => {
@@ -251,7 +241,6 @@ describe('MemorySystem P3.3', () => {
251
241
  })
252
242
  })
253
243
 
254
- // Cleanup test directories after each test
255
244
  afterEach(async () => {
256
245
  try {
257
246
  const testPath = path.join(os.homedir(), '.prjct-cli', 'projects', TEST_PROJECT_ID)
@@ -3,14 +3,18 @@
3
3
  * P3.4: Plan Mode + Approval Flow
4
4
  */
5
5
 
6
- const planMode = require('../../agentic/plan-mode')
7
- const { PLAN_STATUS, PLAN_REQUIRED_COMMANDS, DESTRUCTIVE_COMMANDS, PLANNING_TOOLS } = require('../../agentic/plan-mode')
6
+ import { describe, it, expect, beforeEach } from 'bun:test'
7
+ import planMode, {
8
+ PLAN_STATUS,
9
+ PLAN_REQUIRED_COMMANDS,
10
+ DESTRUCTIVE_COMMANDS,
11
+ PLANNING_TOOLS
12
+ } from '../../agentic/plan-mode'
8
13
 
9
14
  describe('PlanMode P3.4', () => {
10
15
  const TEST_PROJECT_ID = 'test-plan-mode'
11
16
 
12
17
  beforeEach(() => {
13
- // Clear any active plans
14
18
  planMode.activePlans.clear()
15
19
  })
16
20
 
@@ -136,8 +140,8 @@ describe('PlanMode P3.4', () => {
136
140
  planMode.recordGatheredInfo(TEST_PROJECT_ID, { type: 'file', source: 'src/index.js', data: 'content' })
137
141
 
138
142
  const plan = planMode.getActivePlan(TEST_PROJECT_ID)
139
- expect(plan.gatheredInfo.length).toBe(1)
140
- expect(plan.gatheredInfo[0].type).toBe('file')
143
+ expect(plan!.gatheredInfo.length).toBe(1)
144
+ expect(plan!.gatheredInfo[0].type).toBe('file')
141
145
  })
142
146
  })
143
147
 
@@ -151,7 +155,7 @@ describe('PlanMode P3.4', () => {
151
155
  })
152
156
 
153
157
  const plan = planMode.getActivePlan(TEST_PROJECT_ID)
154
- expect(plan.status).toBe(PLAN_STATUS.PENDING_APPROVAL)
158
+ expect(plan!.status).toBe(PLAN_STATUS.PENDING_APPROVAL)
155
159
  })
156
160
 
157
161
  it('should return formatted plan for display', () => {
@@ -162,9 +166,9 @@ describe('PlanMode P3.4', () => {
162
166
  steps: [{ description: 'Step 1' }]
163
167
  })
164
168
 
165
- expect(formatted.summary).toBe('Test plan')
166
- expect(formatted.approach).toBe('Test approach')
167
- expect(formatted.requiresConfirmation).toBe(true)
169
+ expect(formatted!.summary).toBe('Test plan')
170
+ expect(formatted!.approach).toBe('Test approach')
171
+ expect(formatted!.requiresConfirmation).toBe(true)
168
172
  })
169
173
  })
170
174
 
@@ -174,9 +178,9 @@ describe('PlanMode P3.4', () => {
174
178
  planMode.proposePlan(TEST_PROJECT_ID, { steps: [{ description: 'Step 1' }] })
175
179
  const result = planMode.approvePlan(TEST_PROJECT_ID)
176
180
 
177
- expect(result.approved).toBe(true)
181
+ expect(result!.approved).toBe(true)
178
182
  const plan = planMode.getActivePlan(TEST_PROJECT_ID)
179
- expect(plan.status).toBe(PLAN_STATUS.APPROVED)
183
+ expect(plan!.status).toBe(PLAN_STATUS.APPROVED)
180
184
  })
181
185
 
182
186
  it('should convert proposed steps to executable steps', () => {
@@ -186,13 +190,12 @@ describe('PlanMode P3.4', () => {
186
190
  })
187
191
  const result = planMode.approvePlan(TEST_PROJECT_ID)
188
192
 
189
- expect(result.steps.length).toBe(2)
190
- expect(result.steps[0].status).toBe('pending')
193
+ expect(result!.steps.length).toBe(2)
194
+ expect(result!.steps[0].status).toBe('pending')
191
195
  })
192
196
 
193
197
  it('should return null if not pending approval', () => {
194
198
  planMode.startPlanning(TEST_PROJECT_ID, 'feature', {})
195
- // Not proposed yet, so should return null
196
199
  const result = planMode.approvePlan(TEST_PROJECT_ID)
197
200
 
198
201
  expect(result).toBeNull()
@@ -205,8 +208,8 @@ describe('PlanMode P3.4', () => {
205
208
  planMode.proposePlan(TEST_PROJECT_ID, { steps: [] })
206
209
  const result = planMode.rejectPlan(TEST_PROJECT_ID, 'Not the right approach')
207
210
 
208
- expect(result.rejected).toBe(true)
209
- expect(result.reason).toBe('Not the right approach')
211
+ expect(result!.rejected).toBe(true)
212
+ expect(result!.reason).toBe('Not the right approach')
210
213
  })
211
214
 
212
215
  it('should clear active plan after rejection', () => {
@@ -233,17 +236,17 @@ describe('PlanMode P3.4', () => {
233
236
  it('should start execution and return first step', () => {
234
237
  const step = planMode.startExecution(TEST_PROJECT_ID)
235
238
 
236
- expect(step.stepNumber).toBe(1)
237
- expect(step.totalSteps).toBe(2)
238
- expect(step.progress).toBe(0)
239
+ expect(step!.stepNumber).toBe(1)
240
+ expect(step!.totalSteps).toBe(2)
241
+ expect(step!.progress).toBe(0)
239
242
  })
240
243
 
241
244
  it('should advance to next step on completion', () => {
242
245
  planMode.startExecution(TEST_PROJECT_ID)
243
246
  const nextStep = planMode.completeStep(TEST_PROJECT_ID, { success: true })
244
247
 
245
- expect(nextStep.stepNumber).toBe(2)
246
- expect(nextStep.progress).toBe(50)
248
+ expect(nextStep!.stepNumber).toBe(2)
249
+ expect(nextStep!.progress).toBe(50)
247
250
  })
248
251
 
249
252
  it('should complete plan when all steps done', () => {
@@ -251,7 +254,6 @@ describe('PlanMode P3.4', () => {
251
254
  planMode.completeStep(TEST_PROJECT_ID)
252
255
  const result = planMode.completeStep(TEST_PROJECT_ID)
253
256
 
254
- // When all steps complete, getNextStep returns null and completePlan is called
255
257
  expect(result).toBeNull()
256
258
  expect(planMode.getActivePlan(TEST_PROJECT_ID)).toBeNull()
257
259
  })
@@ -266,8 +268,8 @@ describe('PlanMode P3.4', () => {
266
268
 
267
269
  const result = planMode.abortPlan(TEST_PROJECT_ID, 'User cancelled')
268
270
 
269
- expect(result.aborted).toBe(true)
270
- expect(result.reason).toBe('User cancelled')
271
+ expect(result!.aborted).toBe(true)
272
+ expect(result!.reason).toBe('User cancelled')
271
273
  expect(planMode.getActivePlan(TEST_PROJECT_ID)).toBeNull()
272
274
  })
273
275
  })