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
@@ -0,0 +1,288 @@
1
+ /**
2
+ * Migrator
3
+ * Handles migrations between prjct versions and structures.
4
+ *
5
+ * @module infrastructure/migrator
6
+ * @version 0.3.0
7
+ */
8
+
9
+ import fs from 'fs/promises'
10
+ import path from 'path'
11
+ import pathManager from '../path-manager'
12
+ import configManager from '../config-manager'
13
+ import authorDetector from '../author-detector'
14
+
15
+ import type {
16
+ Author,
17
+ MigrationResult,
18
+ MigrationOptions,
19
+ MigrationSummary,
20
+ MigrateAllOptions,
21
+ ProjectInfo,
22
+ LayerCounts
23
+ } from './types'
24
+
25
+ import { needsMigration, migrateConfigTo030 } from './version-migration'
26
+ import { migrateFiles } from './file-operations'
27
+ import { validateMigration, cleanupLegacyDirectories, checkStatus } from './validation'
28
+ import { findAllProjects } from './project-scanner'
29
+ import { generateReport, generateMigrationSummary } from './reports'
30
+
31
+ /**
32
+ * Handles version migrations and project structure updates.
33
+ * Supports legacy -> global storage migration and config version upgrades.
34
+ */
35
+ class Migrator {
36
+ // Re-export helper methods
37
+ needsMigration = needsMigration
38
+ migrateConfigTo030 = migrateConfigTo030
39
+ validateMigration = validateMigration
40
+ cleanupLegacyDirectories = cleanupLegacyDirectories
41
+ checkStatus = checkStatus
42
+ findAllProjects = findAllProjects
43
+ generateReport = generateReport
44
+ generateMigrationSummary = generateMigrationSummary
45
+
46
+ /**
47
+ * Perform the complete migration process
48
+ */
49
+ async migrate(projectPath: string, options: MigrationOptions = {}): Promise<MigrationResult> {
50
+ const result: MigrationResult = {
51
+ success: false,
52
+ projectId: null,
53
+ filesCopied: 0,
54
+ layerCounts: {
55
+ core: 0,
56
+ progress: 0,
57
+ planning: 0,
58
+ analysis: 0,
59
+ memory: 0,
60
+ other: 0,
61
+ },
62
+ config: null,
63
+ author: null,
64
+ issues: [],
65
+ dryRun: options.dryRun || false,
66
+ }
67
+
68
+ try {
69
+ const config = await configManager.readConfig(projectPath)
70
+ if (config && config.version && config.version.startsWith('0.2.')) {
71
+ const versionMigration = await migrateConfigTo030(projectPath)
72
+ result.success = versionMigration.success
73
+ result.projectId = config.projectId
74
+ result.filesCopied = 0
75
+ result.issues = versionMigration.success ? [] : [versionMigration.message]
76
+ return result
77
+ }
78
+
79
+ const needsStructuralMigration = await configManager.needsMigration(projectPath)
80
+ if (!needsStructuralMigration) {
81
+ result.success = false
82
+ result.issues.push('No migration needed - either no legacy structure or already migrated')
83
+ return result
84
+ }
85
+
86
+ const detectedAuthor = await authorDetector.detect()
87
+ result.author = {
88
+ name: detectedAuthor.name,
89
+ email: detectedAuthor.email,
90
+ github: detectedAuthor.github
91
+ }
92
+
93
+ const projectId = pathManager.generateProjectId(projectPath)
94
+ result.projectId = projectId
95
+
96
+ if (options.dryRun) {
97
+ result.success = true
98
+ result.issues.push('DRY RUN - No changes were made')
99
+ return result
100
+ }
101
+
102
+ await pathManager.ensureProjectStructure(projectId)
103
+
104
+ // Convert null to undefined for createConfig
105
+ const authorForConfig = {
106
+ name: result.author.name || undefined,
107
+ email: result.author.email || undefined,
108
+ github: result.author.github || undefined
109
+ }
110
+ result.config = await configManager.createConfig(projectPath, authorForConfig)
111
+
112
+ const legacyPath = pathManager.getLegacyPrjctPath(projectPath)
113
+ const globalPath = pathManager.getGlobalProjectPath(projectId)
114
+
115
+ const migrationStats = await migrateFiles(legacyPath, globalPath)
116
+ result.filesCopied = migrationStats.fileCount
117
+ result.layerCounts = migrationStats.layerCounts
118
+
119
+ const validation = await validateMigration(projectId)
120
+ result.issues = validation.issues
121
+
122
+ if (!validation.valid) {
123
+ result.success = false
124
+ return result
125
+ }
126
+
127
+ if (options.removeLegacy) {
128
+ await fs.rm(legacyPath, { recursive: true, force: true })
129
+ result.legacyRemoved = true
130
+ } else if (options.cleanupLegacy) {
131
+ await cleanupLegacyDirectories(projectPath)
132
+ result.legacyCleaned = true
133
+ }
134
+
135
+ result.success = true
136
+ return result
137
+ } catch (error) {
138
+ result.success = false
139
+ result.issues.push(`Migration error: ${(error as Error).message}`)
140
+ return result
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Migrate all projects with legacy .prjct directories
146
+ */
147
+ async migrateAll(options: MigrateAllOptions = {}): Promise<MigrationSummary> {
148
+ const {
149
+ deepScan = false,
150
+ removeLegacy = false,
151
+ cleanupLegacy = false,
152
+ dryRun = false,
153
+ interactive = false,
154
+ onProgress = null,
155
+ } = options
156
+
157
+ const summary: MigrationSummary = {
158
+ success: false,
159
+ totalFound: 0,
160
+ alreadyMigrated: 0,
161
+ successfullyMigrated: 0,
162
+ failed: 0,
163
+ skipped: 0,
164
+ projects: [],
165
+ errors: [],
166
+ dryRun,
167
+ }
168
+
169
+ try {
170
+ if (onProgress) onProgress({ phase: 'scanning', message: 'Searching for projects...' })
171
+ const projectPaths = await findAllProjects({ deepScan })
172
+ summary.totalFound = projectPaths.length
173
+
174
+ if (projectPaths.length === 0) {
175
+ summary.success = true
176
+ return summary
177
+ }
178
+
179
+ for (let i = 0; i < projectPaths.length; i++) {
180
+ const projectPath = projectPaths[i]
181
+ const projectName = path.basename(projectPath)
182
+
183
+ if (onProgress) {
184
+ onProgress({
185
+ phase: 'checking',
186
+ message: `Checking ${projectName} (${i + 1}/${projectPaths.length})`,
187
+ current: i + 1,
188
+ total: projectPaths.length,
189
+ })
190
+ }
191
+
192
+ try {
193
+ const status = await checkStatus(projectPath)
194
+
195
+ const projectInfo: ProjectInfo = {
196
+ path: projectPath,
197
+ name: projectName,
198
+ status: status.status,
199
+ }
200
+
201
+ if (status.status === 'migrated' || status.status === 'new') {
202
+ projectInfo.result = 'skipped'
203
+ projectInfo.reason =
204
+ status.status === 'migrated' ? 'Already migrated' : 'Not initialized'
205
+ summary.alreadyMigrated++
206
+ } else if (status.needsMigration) {
207
+ if (interactive && onProgress) {
208
+ const shouldMigrate = await onProgress({
209
+ phase: 'confirm',
210
+ message: `Migrate ${projectName}?`,
211
+ projectPath,
212
+ })
213
+ if (!shouldMigrate) {
214
+ projectInfo.result = 'skipped'
215
+ projectInfo.reason = 'User skipped'
216
+ summary.skipped++
217
+ summary.projects.push(projectInfo)
218
+ continue
219
+ }
220
+ }
221
+
222
+ if (onProgress) {
223
+ onProgress({
224
+ phase: 'migrating',
225
+ message: `Migrating ${projectName}...`,
226
+ current: i + 1,
227
+ total: projectPaths.length,
228
+ })
229
+ }
230
+
231
+ const migrationResult = await this.migrate(projectPath, {
232
+ removeLegacy,
233
+ cleanupLegacy,
234
+ dryRun,
235
+ })
236
+
237
+ projectInfo.projectId = migrationResult.projectId || undefined
238
+ projectInfo.filesCopied = migrationResult.filesCopied
239
+ projectInfo.layerCounts = migrationResult.layerCounts
240
+
241
+ if (migrationResult.success) {
242
+ projectInfo.result = 'success'
243
+ summary.successfullyMigrated++
244
+ } else {
245
+ projectInfo.result = 'failed'
246
+ projectInfo.errors = migrationResult.issues
247
+ summary.failed++
248
+ summary.errors.push({
249
+ project: projectName,
250
+ path: projectPath,
251
+ issues: migrationResult.issues,
252
+ })
253
+ }
254
+ }
255
+
256
+ summary.projects.push(projectInfo)
257
+ } catch (error) {
258
+ summary.failed++
259
+ summary.errors.push({
260
+ project: projectName,
261
+ path: projectPath,
262
+ issues: [(error as Error).message],
263
+ })
264
+ summary.projects.push({
265
+ path: projectPath,
266
+ name: projectName,
267
+ result: 'failed',
268
+ errors: [(error as Error).message],
269
+ })
270
+ }
271
+ }
272
+
273
+ summary.success = summary.failed === 0
274
+ return summary
275
+ } catch (error) {
276
+ summary.success = false
277
+ summary.errors.push({
278
+ project: 'global',
279
+ issues: [(error as Error).message],
280
+ })
281
+ return summary
282
+ }
283
+ }
284
+ }
285
+
286
+ const migrator = new Migrator()
287
+ export default migrator
288
+ export * from './types'
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Project Scanner
3
+ * Finds projects with .prjct directories for migration.
4
+ */
5
+
6
+ import fs from 'fs/promises'
7
+ import path from 'path'
8
+ import os from 'os'
9
+ import type { FindProjectsOptions } from './types'
10
+
11
+ /**
12
+ * Find all projects with .prjct directories on the user's machine
13
+ */
14
+ export async function findAllProjects(options: FindProjectsOptions = {}): Promise<string[]> {
15
+ const { deepScan = true } = options
16
+ const projectDirs: string[] = []
17
+
18
+ let searchPaths: string[] = []
19
+ if (deepScan) {
20
+ searchPaths = [os.homedir()]
21
+ } else {
22
+ const commonDirs = [
23
+ 'Projects',
24
+ 'Documents',
25
+ 'Developer',
26
+ 'Code',
27
+ 'dev',
28
+ 'workspace',
29
+ 'repos',
30
+ 'src',
31
+ 'Apps',
32
+ ]
33
+ searchPaths = commonDirs
34
+ .map((dir) => path.join(os.homedir(), dir))
35
+ .filter((dirPath) => {
36
+ try {
37
+ require('fs').accessSync(dirPath)
38
+ return true
39
+ } catch {
40
+ return false
41
+ }
42
+ })
43
+ }
44
+
45
+ const shouldSkip = (dirName: string): boolean => {
46
+ const skipDirs = [
47
+ 'node_modules',
48
+ '.git',
49
+ '.next',
50
+ 'dist',
51
+ 'build',
52
+ '.cache',
53
+ 'coverage',
54
+ '.vscode',
55
+ '.idea',
56
+ 'vendor',
57
+ '__pycache__',
58
+ ]
59
+ return skipDirs.includes(dirName) || (dirName.startsWith('.') && dirName !== '.prjct')
60
+ }
61
+
62
+ const searchDirectory = async (dirPath: string, depth: number = 0): Promise<void> => {
63
+ if (depth > 10) return
64
+
65
+ try {
66
+ const entries = await fs.readdir(dirPath, { withFileTypes: true })
67
+
68
+ if (entries.some((entry) => entry.name === '.prjct' && entry.isDirectory())) {
69
+ projectDirs.push(dirPath)
70
+ return // Don't search subdirectories if we found a project
71
+ }
72
+
73
+ for (const entry of entries) {
74
+ if (entry.isDirectory() && !shouldSkip(entry.name)) {
75
+ const subPath = path.join(dirPath, entry.name)
76
+ await searchDirectory(subPath, depth + 1)
77
+ }
78
+ }
79
+ } catch {
80
+ // Ignore errors
81
+ }
82
+ }
83
+
84
+ for (const searchPath of searchPaths) {
85
+ await searchDirectory(searchPath)
86
+ }
87
+
88
+ return projectDirs
89
+ }
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Reports
3
+ * Generates migration reports.
4
+ */
5
+
6
+ import pathManager from '../path-manager'
7
+ import authorDetector from '../author-detector'
8
+ import type { MigrationResult, MigrationSummary } from './types'
9
+
10
+ /**
11
+ * Generate a migration report
12
+ */
13
+ export function generateReport(result: MigrationResult): string {
14
+ const lines: string[] = []
15
+
16
+ lines.push('Migration Report')
17
+ lines.push('---')
18
+
19
+ if (result.dryRun) {
20
+ lines.push('DRY RUN MODE - No changes were made')
21
+ lines.push('')
22
+ }
23
+
24
+ if (result.success) {
25
+ lines.push('Migration successful!')
26
+ lines.push('')
27
+ lines.push(`Project ID: ${result.projectId}`)
28
+ lines.push(`Author: ${authorDetector.formatAuthor(result.author!)}`)
29
+ lines.push(`Files migrated: ${result.filesCopied}`)
30
+ lines.push('')
31
+ lines.push('Files by layer:')
32
+ for (const [layer, count] of Object.entries(result.layerCounts)) {
33
+ if (count > 0) {
34
+ lines.push(` - ${layer}: ${count} files`)
35
+ }
36
+ }
37
+ lines.push('')
38
+ lines.push(`Data location: ${result.config?.dataPath}`)
39
+
40
+ if (result.legacyRemoved) {
41
+ lines.push('')
42
+ lines.push('Legacy .prjct directory removed')
43
+ }
44
+ } else {
45
+ lines.push('Migration failed!')
46
+ lines.push('')
47
+ if (result.issues.length > 0) {
48
+ lines.push('Issues:')
49
+ for (const issue of result.issues) {
50
+ lines.push(` - ${issue}`)
51
+ }
52
+ }
53
+ }
54
+
55
+ lines.push('---')
56
+
57
+ return lines.join('\n')
58
+ }
59
+
60
+ /**
61
+ * Generate a summary report for migrateAll results
62
+ */
63
+ export function generateMigrationSummary(summary: MigrationSummary): string {
64
+ const lines: string[] = []
65
+
66
+ lines.push('Global Migration Report')
67
+ lines.push('---')
68
+
69
+ if (summary.dryRun) {
70
+ lines.push('DRY RUN MODE - No changes were made')
71
+ lines.push('')
72
+ }
73
+
74
+ lines.push(`Found: ${summary.totalFound} projects`)
75
+ lines.push(`Successfully migrated: ${summary.successfullyMigrated}`)
76
+ lines.push(`Already migrated: ${summary.alreadyMigrated}`)
77
+ if (summary.skipped > 0) {
78
+ lines.push(`Skipped: ${summary.skipped}`)
79
+ }
80
+ if (summary.failed > 0) {
81
+ lines.push(`Failed: ${summary.failed}`)
82
+ }
83
+ lines.push('')
84
+
85
+ if (summary.successfullyMigrated > 0) {
86
+ lines.push('Successfully Migrated:')
87
+ summary.projects
88
+ .filter((p) => p.result === 'success')
89
+ .forEach((project) => {
90
+ lines.push(` - ${project.name}`)
91
+ lines.push(` Files: ${project.filesCopied} | ID: ${project.projectId}`)
92
+ })
93
+ lines.push('')
94
+ }
95
+
96
+ if (summary.errors.length > 0) {
97
+ lines.push('Errors:')
98
+ summary.errors.forEach((error) => {
99
+ lines.push(` - ${error.project}`)
100
+ error.issues.forEach((issue) => lines.push(` - ${issue}`))
101
+ })
102
+ lines.push('')
103
+ }
104
+
105
+ if (summary.success && summary.successfullyMigrated > 0) {
106
+ lines.push('All projects migrated successfully!')
107
+ lines.push(`Global data location: ${pathManager.getGlobalBasePath()}`)
108
+ } else if (summary.totalFound === 0) {
109
+ lines.push('No legacy projects found')
110
+ } else if (summary.alreadyMigrated === summary.totalFound) {
111
+ lines.push('All projects already migrated')
112
+ }
113
+
114
+ lines.push('---')
115
+
116
+ return lines.join('\n')
117
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Migrator Types
3
+ * Type definitions for migration operations.
4
+ */
5
+
6
+ export interface Author {
7
+ name: string | null
8
+ email: string | null
9
+ github?: string | null
10
+ firstContribution?: string
11
+ lastActivity?: string
12
+ }
13
+
14
+ export interface LocalConfig {
15
+ projectId: string
16
+ dataPath: string
17
+ authors?: Author[]
18
+ author?: Author
19
+ version?: string
20
+ created?: string
21
+ lastSync?: string
22
+ }
23
+
24
+ export interface LayerCounts {
25
+ core: number
26
+ progress: number
27
+ planning: number
28
+ analysis: number
29
+ memory: number
30
+ other: number
31
+ }
32
+
33
+ export interface MigrationResult {
34
+ success: boolean
35
+ projectId: string | null
36
+ filesCopied?: number
37
+ filescopied?: number
38
+ layerCounts: LayerCounts
39
+ config: LocalConfig | null
40
+ author: Author | null
41
+ issues: string[]
42
+ dryRun: boolean
43
+ legacyRemoved?: boolean
44
+ legacyCleaned?: boolean
45
+ }
46
+
47
+ export interface VersionMigrationResult {
48
+ success: boolean
49
+ message: string
50
+ oldVersion: string | null
51
+ newVersion: string
52
+ }
53
+
54
+ export interface ValidationResult {
55
+ valid: boolean
56
+ issues: string[]
57
+ }
58
+
59
+ export interface FileMapping {
60
+ layer: string
61
+ filename: string
62
+ }
63
+
64
+ export interface MigrationStats {
65
+ fileCount: number
66
+ layerCounts: LayerCounts
67
+ }
68
+
69
+ export interface MigrationOptions {
70
+ removeLegacy?: boolean
71
+ cleanupLegacy?: boolean
72
+ dryRun?: boolean
73
+ }
74
+
75
+ export interface StatusResult {
76
+ status: string
77
+ hasLegacy: boolean
78
+ hasConfig: boolean
79
+ needsMigration: boolean
80
+ version: string
81
+ }
82
+
83
+ export interface ProjectInfo {
84
+ path: string
85
+ name: string
86
+ status?: string
87
+ result?: string
88
+ reason?: string
89
+ projectId?: string
90
+ filesCopied?: number
91
+ layerCounts?: LayerCounts
92
+ errors?: string[]
93
+ }
94
+
95
+ export interface MigrationSummary {
96
+ success: boolean
97
+ totalFound: number
98
+ alreadyMigrated: number
99
+ successfullyMigrated: number
100
+ failed: number
101
+ skipped: number
102
+ projects: ProjectInfo[]
103
+ errors: Array<{ project: string; path?: string; issues: string[] }>
104
+ dryRun: boolean
105
+ }
106
+
107
+ export interface MigrateAllOptions {
108
+ deepScan?: boolean
109
+ removeLegacy?: boolean
110
+ cleanupLegacy?: boolean
111
+ dryRun?: boolean
112
+ interactive?: boolean
113
+ onProgress?: (progress: {
114
+ phase: string
115
+ message: string
116
+ current?: number
117
+ total?: number
118
+ projectPath?: string
119
+ }) => boolean | void | Promise<boolean | void>
120
+ }
121
+
122
+ export interface FindProjectsOptions {
123
+ deepScan?: boolean
124
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Validation
3
+ * Handles migration validation and legacy cleanup.
4
+ */
5
+
6
+ import fs from 'fs/promises'
7
+ import path from 'path'
8
+ import pathManager from '../path-manager'
9
+ import type { ValidationResult, StatusResult } from './types'
10
+
11
+ /**
12
+ * Validate that migration was successful
13
+ */
14
+ export async function validateMigration(projectId: string): Promise<ValidationResult> {
15
+ const issues: string[] = []
16
+
17
+ const exists = await pathManager.projectExists(projectId)
18
+ if (!exists) {
19
+ issues.push('Global project directory not found')
20
+ return { valid: false, issues }
21
+ }
22
+
23
+ const globalPath = pathManager.getGlobalProjectPath(projectId)
24
+ const requiredLayers = ['core', 'progress', 'planning', 'analysis', 'memory']
25
+
26
+ for (const layer of requiredLayers) {
27
+ try {
28
+ await fs.access(path.join(globalPath, layer))
29
+ } catch {
30
+ issues.push(`Missing layer directory: ${layer}`)
31
+ }
32
+ }
33
+
34
+ try {
35
+ const coreFiles = await fs.readdir(path.join(globalPath, 'core'))
36
+ if (coreFiles.length === 0) {
37
+ issues.push('No files found in core directory')
38
+ }
39
+ } catch {
40
+ issues.push('Cannot read core directory')
41
+ }
42
+
43
+ return {
44
+ valid: issues.length === 0,
45
+ issues,
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Cleanup legacy directories while preserving config
51
+ * Removes: analysis/, core/, memory/, planning/, progress/, sessions/
52
+ * Keeps: prjct.config.json
53
+ */
54
+ export async function cleanupLegacyDirectories(projectPath: string): Promise<void> {
55
+ const legacyPath = pathManager.getLegacyPrjctPath(projectPath)
56
+ const layersToRemove = ['analysis', 'core', 'memory', 'planning', 'progress', 'sessions']
57
+
58
+ for (const layer of layersToRemove) {
59
+ const layerPath = path.join(legacyPath, layer)
60
+ try {
61
+ await fs.rm(layerPath, { recursive: true, force: true })
62
+ } catch {
63
+ // Ignore errors
64
+ }
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Check migration status for a project
70
+ */
71
+ export async function checkStatus(projectPath: string): Promise<StatusResult> {
72
+ const hasLegacy = await pathManager.hasLegacyStructure(projectPath)
73
+ const hasConfig = await pathManager.hasConfig(projectPath)
74
+ const needsMigration = hasLegacy && !hasConfig
75
+
76
+ let status = 'unknown'
77
+ if (!hasLegacy && !hasConfig) {
78
+ status = 'new' // New project, not initialized
79
+ } else if (!hasLegacy && hasConfig) {
80
+ status = 'migrated' // Already migrated to v0.2.0
81
+ } else if (hasLegacy && !hasConfig) {
82
+ status = 'legacy' // v0.1.0, needs migration
83
+ } else if (hasLegacy && hasConfig) {
84
+ status = 'both' // Has both (migration incomplete or manual setup)
85
+ }
86
+
87
+ return {
88
+ status,
89
+ hasLegacy,
90
+ hasConfig,
91
+ needsMigration,
92
+ version: hasConfig ? '0.2.0' : hasLegacy ? '0.1.0' : 'none',
93
+ }
94
+ }