prjct-cli 0.11.5 → 0.12.1

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 (391) hide show
  1. package/CHANGELOG.md +58 -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 +226 -50
  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.js → date-helper.test.ts} +19 -30
  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} +92 -81
  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} +27 -16
  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} +55 -19
  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 +204 -163
  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 +190 -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/{stats → BentoGrid}/BentoGrid.tsx +4 -8
  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/{stats → EmptyState}/EmptyState.tsx +1 -10
  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/{stats → IdeasCard}/IdeasCard.tsx +3 -14
  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/{stats → ProgressRing}/ProgressRing.tsx +4 -27
  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/{stats → RoadmapCard}/RoadmapCard.tsx +3 -23
  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/{stats → ShipsCard}/ShipsCard.tsx +4 -22
  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/{stats → SparklineChart}/SparklineChart.tsx +1 -7
  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/{stats → StreakCard}/StreakCard.tsx +5 -11
  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/context/TerminalTabsContext.tsx +46 -1
  333. package/packages/web/hooks/useClaudeTerminal.ts +71 -21
  334. package/packages/web/hooks/useProjectStats.ts +55 -0
  335. package/packages/web/hooks/useProjects.ts +6 -6
  336. package/packages/web/lib/actions/projects.ts +15 -0
  337. package/packages/web/lib/json-loader.ts +630 -0
  338. package/packages/web/lib/services/index.ts +9 -0
  339. package/packages/web/lib/services/migration.server.ts +600 -0
  340. package/packages/web/lib/services/projects.server.ts +52 -0
  341. package/packages/web/lib/services/stats.server.ts +264 -0
  342. package/packages/web/lib/unified-loader.ts +396 -0
  343. package/packages/web/package.json +10 -7
  344. package/packages/web/server.ts +58 -8
  345. package/templates/commands/done.md +76 -32
  346. package/templates/commands/feature.md +121 -47
  347. package/templates/commands/idea.md +81 -8
  348. package/templates/commands/now.md +41 -17
  349. package/templates/commands/ship.md +64 -25
  350. package/templates/commands/sync.md +28 -3
  351. package/core/agentic/agent-router.js +0 -140
  352. package/core/agentic/chain-of-thought.js +0 -578
  353. package/core/agentic/command-executor.js +0 -417
  354. package/core/agentic/context-filter.js +0 -354
  355. package/core/agentic/ground-truth.js +0 -591
  356. package/core/agentic/loop-detector.js +0 -406
  357. package/core/agentic/memory-system.js +0 -845
  358. package/core/agentic/parallel-tools.js +0 -366
  359. package/core/agentic/plan-mode.js +0 -572
  360. package/core/agentic/prompt-builder.js +0 -352
  361. package/core/agentic/response-templates.js +0 -290
  362. package/core/agentic/semantic-compression.js +0 -517
  363. package/core/agentic/think-blocks.js +0 -657
  364. package/core/agentic/tool-registry.js +0 -184
  365. package/core/agentic/validation-rules.js +0 -380
  366. package/core/command-registry.js +0 -698
  367. package/core/commands.js +0 -2237
  368. package/core/domain/task-stack.js +0 -497
  369. package/core/infrastructure/legacy-installer-detector.js +0 -546
  370. package/core/infrastructure/migrator.js +0 -796
  371. package/core/infrastructure/session-manager.js +0 -390
  372. package/core/utils/file-helper.js +0 -329
  373. package/packages/web/app/api/projects/[id]/delete/route.ts +0 -21
  374. package/packages/web/app/api/stats/route.ts +0 -38
  375. package/packages/web/components/AppSidebar.tsx +0 -113
  376. package/packages/web/components/stats/ActivityTimeline.tsx +0 -201
  377. package/packages/web/components/stats/AgentsCard.tsx +0 -56
  378. package/packages/web/components/stats/BentoCard.tsx +0 -88
  379. package/packages/web/components/stats/HeroSection.tsx +0 -172
  380. package/packages/web/components/stats/NowCard.tsx +0 -71
  381. package/packages/web/components/stats/QueueCard.tsx +0 -58
  382. package/packages/web/components/stats/VelocityCard.tsx +0 -60
  383. package/packages/web/components/stats/index.ts +0 -17
  384. package/packages/web/hooks/useStats.ts +0 -28
  385. /package/packages/web/components/{CommandButton.tsx → CommandButton/CommandButton.tsx} +0 -0
  386. /package/packages/web/components/{ConnectionStatus.tsx → ConnectionStatus/ConnectionStatus.tsx} +0 -0
  387. /package/packages/web/components/{Logo.tsx → Logo/Logo.tsx} +0 -0
  388. /package/packages/web/components/{MarkdownContent.tsx → MarkdownContent/MarkdownContent.tsx} +0 -0
  389. /package/packages/web/components/{ProjectAvatar.tsx → ProjectAvatar/ProjectAvatar.tsx} +0 -0
  390. /package/packages/web/components/{providers.tsx → Providers/Providers.tsx} +0 -0
  391. /package/packages/web/components/{TechStackBadges.tsx → TechStackBadges/TechStackBadges.tsx} +0 -0
@@ -1,796 +0,0 @@
1
- /**
2
- * Migrator
3
- * Handles migrations between prjct versions and structures.
4
- *
5
- * @module infrastructure/migrator
6
- * @version 0.3.0
7
- */
8
-
9
- const fs = require('fs').promises
10
- const path = require('path')
11
- const pathManager = require('./path-manager')
12
- const configManager = require('./config-manager')
13
- const authorDetector = require('./author-detector')
14
-
15
- /**
16
- * Handles version migrations and project structure updates.
17
- * Supports legacy → global storage migration and config version upgrades.
18
- */
19
- class Migrator {
20
- /**
21
- * Check if a project needs migration
22
- *
23
- * @param {string} projectPath - Path to the project
24
- * @returns {Promise<boolean>} - True if migration needed
25
- */
26
- async needsMigration(projectPath) {
27
- const structureMigration = await configManager.needsMigration(projectPath)
28
- if (structureMigration) return true
29
-
30
- const config = await configManager.readConfig(projectPath)
31
- if (config && config.version && config.version.startsWith('0.2.')) {
32
- return true
33
- }
34
-
35
- return false
36
- }
37
-
38
- /**
39
- * Migrate config from 0.2.x to 0.3.0 (move authors to global config)
40
- *
41
- * @param {string} projectPath - Path to the project
42
- * @returns {Promise<Object>} - Migration result
43
- */
44
- async migrateConfigTo030(projectPath) {
45
- const result = {
46
- success: false,
47
- message: '',
48
- oldVersion: null,
49
- newVersion: '0.3.0',
50
- }
51
-
52
- try {
53
- const localConfig = await configManager.readConfig(projectPath)
54
- if (!localConfig) {
55
- result.message = 'No config found'
56
- return result
57
- }
58
-
59
- result.oldVersion = localConfig.version
60
- const projectId = localConfig.projectId
61
-
62
- const globalConfig = await configManager.readGlobalConfig(projectId)
63
- if (globalConfig && globalConfig.authors && globalConfig.authors.length > 0) {
64
- const needsCleanup =
65
- localConfig.authors ||
66
- localConfig.author ||
67
- localConfig.version ||
68
- localConfig.created ||
69
- localConfig.lastSync
70
-
71
- if (needsCleanup) {
72
- delete localConfig.authors
73
- delete localConfig.author
74
- delete localConfig.version
75
- delete localConfig.created
76
- delete localConfig.lastSync
77
- await configManager.writeConfig(projectPath, localConfig)
78
- }
79
- result.success = true
80
- result.message = 'Authors already in global config, cleaned up local config'
81
- return result
82
- }
83
-
84
- let authors = []
85
- const now = new Date().toISOString()
86
-
87
- if (localConfig.authors && Array.isArray(localConfig.authors)) {
88
- authors = localConfig.authors
89
- } else if (localConfig.author) {
90
- authors = [
91
- {
92
- name: localConfig.author.name || 'Unknown',
93
- email: localConfig.author.email || '',
94
- github: localConfig.author.github || '',
95
- firstContribution: localConfig.created || now,
96
- lastActivity: localConfig.lastSync || now,
97
- },
98
- ]
99
- } else {
100
- authors = [
101
- {
102
- name: 'Unknown',
103
- email: '',
104
- github: '',
105
- firstContribution: now,
106
- lastActivity: now,
107
- },
108
- ]
109
- }
110
-
111
- const newGlobalConfig = {
112
- projectId,
113
- authors,
114
- version: '0.3.0',
115
- created: localConfig.created || now,
116
- lastSync: now,
117
- }
118
- await configManager.writeGlobalConfig(projectId, newGlobalConfig)
119
-
120
- delete localConfig.authors
121
- delete localConfig.author
122
- delete localConfig.version
123
- delete localConfig.created
124
- delete localConfig.lastSync
125
- await configManager.writeConfig(projectPath, localConfig)
126
-
127
- result.success = true
128
- result.message = `Migrated ${authors.length} author(s) to global config`
129
- return result
130
- } catch (error) {
131
- result.message = `Migration failed: ${error.message}`
132
- return result
133
- }
134
- }
135
-
136
- /**
137
- * Copy a directory recursively
138
- *
139
- * @param {string} source - Source directory
140
- * @param {string} destination - Destination directory
141
- * @returns {Promise<number>} - Number of files copied
142
- * @private
143
- */
144
- async copyDirectory(source, destination) {
145
- let fileCount = 0
146
-
147
- await fs.mkdir(destination, { recursive: true })
148
-
149
- const entries = await fs.readdir(source, { withFileTypes: true })
150
-
151
- for (const entry of entries) {
152
- const sourcePath = path.join(source, entry.name)
153
- const destPath = path.join(destination, entry.name)
154
-
155
- if (entry.isDirectory()) {
156
- fileCount += await this.copyDirectory(sourcePath, destPath)
157
- } else {
158
- await fs.copyFile(sourcePath, destPath)
159
- fileCount++
160
- }
161
- }
162
-
163
- return fileCount
164
- }
165
-
166
- /**
167
- * Map legacy flat structure to new layered structure
168
- *
169
- * @param {string} filename - Name of the file
170
- * @returns {Object} - {layer, filename}
171
- * @private
172
- */
173
- mapLegacyFile(filename) {
174
- if (filename === 'now.md' || filename === 'next.md' || filename === 'context.md') {
175
- return { layer: 'core', filename }
176
- }
177
-
178
- if (filename === 'shipped.md' || filename === 'metrics.md') {
179
- return { layer: 'progress', filename }
180
- }
181
-
182
- if (filename === 'ideas.md' || filename === 'roadmap.md') {
183
- return { layer: 'planning', filename }
184
- }
185
-
186
- if (
187
- filename === 'memory.jsonl' ||
188
- filename === 'context.jsonl' ||
189
- filename === 'decisions.jsonl'
190
- ) {
191
- return { layer: 'memory', filename }
192
- }
193
-
194
- if (filename === 'repo-summary.md') {
195
- return { layer: 'analysis', filename }
196
- }
197
-
198
- return { layer: '.', filename }
199
- }
200
-
201
- /**
202
- * Migrate files from legacy structure to new layered structure
203
- *
204
- * @param {string} legacyPath - Path to legacy .prjct directory
205
- * @param {string} globalPath - Path to new global project directory
206
- * @returns {Promise<{fileCount: number, layerCounts: Object}>}
207
- * @private
208
- */
209
- async migrateFiles(legacyPath, globalPath) {
210
- let fileCount = 0
211
- const layerCounts = {
212
- core: 0,
213
- progress: 0,
214
- planning: 0,
215
- analysis: 0,
216
- memory: 0,
217
- other: 0,
218
- }
219
-
220
- const validLayers = ['core', 'progress', 'planning', 'analysis', 'memory', 'sessions']
221
- const entries = await fs.readdir(legacyPath, { withFileTypes: true })
222
-
223
- for (const entry of entries) {
224
- const sourcePath = path.join(legacyPath, entry.name)
225
-
226
- if (entry.name === 'prjct.config.json' || entry.name.endsWith('.old')) {
227
- continue
228
- }
229
-
230
- if (entry.isDirectory()) {
231
- if (validLayers.includes(entry.name)) {
232
- const destPath = path.join(globalPath, entry.name)
233
- const count = await this.copyDirectory(sourcePath, destPath)
234
- fileCount += count
235
- if (Object.prototype.hasOwnProperty.call(layerCounts, entry.name)) {
236
- layerCounts[entry.name] += count
237
- } else {
238
- layerCounts.other += count
239
- }
240
- } else {
241
- const destPath = path.join(globalPath, 'planning', entry.name)
242
- const count = await this.copyDirectory(sourcePath, destPath)
243
- fileCount += count
244
- layerCounts.planning += count
245
- }
246
- } else {
247
- const mapping = this.mapLegacyFile(entry.name)
248
- const destPath = path.join(globalPath, mapping.layer, mapping.filename)
249
-
250
- await fs.mkdir(path.dirname(destPath), { recursive: true })
251
-
252
- await fs.copyFile(sourcePath, destPath)
253
- fileCount++
254
-
255
- if (mapping.layer === '.') {
256
- layerCounts.other++
257
- } else {
258
- layerCounts[mapping.layer] = (layerCounts[mapping.layer] || 0) + 1
259
- }
260
- }
261
- }
262
-
263
- return { fileCount, layerCounts }
264
- }
265
-
266
- /**
267
- * Validate that migration was successful
268
- *
269
- * @param {string} projectId - Project ID
270
- * @returns {Promise<{valid: boolean, issues: string[]}>}
271
- * @private
272
- */
273
- async validateMigration(projectId) {
274
- const issues = []
275
-
276
- const exists = await pathManager.projectExists(projectId)
277
- if (!exists) {
278
- issues.push('Global project directory not found')
279
- return { valid: false, issues }
280
- }
281
-
282
- const globalPath = pathManager.getGlobalProjectPath(projectId)
283
- const requiredLayers = ['core', 'progress', 'planning', 'analysis', 'memory']
284
-
285
- for (const layer of requiredLayers) {
286
- try {
287
- await fs.access(path.join(globalPath, layer))
288
- } catch {
289
- issues.push(`Missing layer directory: ${layer}`)
290
- }
291
- }
292
-
293
- try {
294
- const coreFiles = await fs.readdir(path.join(globalPath, 'core'))
295
- if (coreFiles.length === 0) {
296
- issues.push('No files found in core directory')
297
- }
298
- } catch {
299
- issues.push('Cannot read core directory')
300
- }
301
-
302
- return {
303
- valid: issues.length === 0,
304
- issues,
305
- }
306
- }
307
-
308
- /**
309
- * Cleanup legacy directories while preserving config
310
- * Removes: analysis/, core/, memory/, planning/, progress/, sessions/
311
- * Keeps: prjct.config.json
312
- *
313
- * @param {string} projectPath - Path to the project
314
- * @returns {Promise<void>}
315
- * @private
316
- */
317
- async cleanupLegacyDirectories(projectPath) {
318
- const legacyPath = pathManager.getLegacyPrjctPath(projectPath)
319
- const layersToRemove = ['analysis', 'core', 'memory', 'planning', 'progress', 'sessions']
320
-
321
- for (const layer of layersToRemove) {
322
- const layerPath = path.join(legacyPath, layer)
323
- try {
324
- await fs.rm(layerPath, { recursive: true, force: true })
325
- } catch {}
326
- }
327
- }
328
-
329
- /**
330
- * Perform the complete migration process
331
- *
332
- * @param {string} projectPath - Path to the project
333
- * @param {Object} options - Migration options
334
- * @param {boolean} options.removeLegacy - Remove legacy .prjct after migration completely
335
- * @param {boolean} options.cleanupLegacy - Remove legacy directories but keep config
336
- * @param {boolean} options.dryRun - Simulate migration without making changes
337
- * @returns {Promise<Object>} - Migration result
338
- */
339
- async migrate(projectPath, options = {}) {
340
- const result = {
341
- success: false,
342
- projectId: null,
343
- filescopied: 0,
344
- layerCounts: {},
345
- config: null,
346
- author: null,
347
- issues: [],
348
- dryRun: options.dryRun || false,
349
- }
350
-
351
- try {
352
- const config = await configManager.readConfig(projectPath)
353
- if (config && config.version && config.version.startsWith('0.2.')) {
354
- const versionMigration = await this.migrateConfigTo030(projectPath)
355
- result.success = versionMigration.success
356
- result.projectId = config.projectId
357
- result.filesCopied = 0
358
- result.issues = versionMigration.success ? [] : [versionMigration.message]
359
- return result
360
- }
361
-
362
- const needsStructuralMigration = await configManager.needsMigration(projectPath)
363
- if (!needsStructuralMigration) {
364
- result.success = false
365
- result.issues.push('No migration needed - either no legacy structure or already migrated')
366
- return result
367
- }
368
-
369
- result.author = await authorDetector.detect()
370
-
371
- const projectId = pathManager.generateProjectId(projectPath)
372
- result.projectId = projectId
373
-
374
- if (options.dryRun) {
375
- result.success = true
376
- result.issues.push('DRY RUN - No changes were made')
377
- return result
378
- }
379
-
380
- await pathManager.ensureProjectStructure(projectId)
381
-
382
- result.config = await configManager.createConfig(projectPath, result.author)
383
-
384
- const legacyPath = pathManager.getLegacyPrjctPath(projectPath)
385
- const globalPath = pathManager.getGlobalProjectPath(projectId)
386
-
387
- const migrationStats = await this.migrateFiles(legacyPath, globalPath)
388
- result.filesCopied = migrationStats.fileCount
389
- result.layerCounts = migrationStats.layerCounts
390
-
391
- const validation = await this.validateMigration(projectId)
392
- result.issues = validation.issues
393
-
394
- if (!validation.valid) {
395
- result.success = false
396
- return result
397
- }
398
-
399
- if (options.removeLegacy) {
400
- await fs.rm(legacyPath, { recursive: true, force: true })
401
- result.legacyRemoved = true
402
- } else if (options.cleanupLegacy) {
403
- await this.cleanupLegacyDirectories(projectPath)
404
- result.legacyCleaned = true
405
- }
406
-
407
- result.success = true
408
- return result
409
- } catch (error) {
410
- result.success = false
411
- result.issues.push(`Migration error: ${error.message}`)
412
- return result
413
- }
414
- }
415
-
416
- /**
417
- * Generate a migration report
418
- *
419
- * @param {Object} result - Migration result
420
- * @returns {string} - Formatted report
421
- */
422
- generateReport(result) {
423
- const lines = []
424
-
425
- lines.push('📦 Migration Report')
426
- lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
427
-
428
- if (result.dryRun) {
429
- lines.push('⚠️ DRY RUN MODE - No changes were made')
430
- lines.push('')
431
- }
432
-
433
- if (result.success) {
434
- lines.push('✅ Migration successful!')
435
- lines.push('')
436
- lines.push(`📋 Project ID: ${result.projectId}`)
437
- lines.push(`👤 Author: ${authorDetector.formatAuthor(result.author)}`)
438
- lines.push(`📁 Files migrated: ${result.filesCopied}`)
439
- lines.push('')
440
- lines.push('📂 Files by layer:')
441
- for (const [layer, count] of Object.entries(result.layerCounts)) {
442
- if (count > 0) {
443
- lines.push(` • ${layer}: ${count} files`)
444
- }
445
- }
446
- lines.push('')
447
- lines.push(`📍 Data location: ${result.config.dataPath}`)
448
-
449
- if (result.legacyRemoved) {
450
- lines.push('')
451
- lines.push('🗑️ Legacy .prjct directory removed')
452
- }
453
- } else {
454
- lines.push('❌ Migration failed!')
455
- lines.push('')
456
- if (result.issues.length > 0) {
457
- lines.push('Issues:')
458
- for (const issue of result.issues) {
459
- lines.push(` • ${issue}`)
460
- }
461
- }
462
- }
463
-
464
- lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
465
-
466
- return lines.join('\n')
467
- }
468
-
469
- /**
470
- * Check migration status for a project
471
- *
472
- * @param {string} projectPath - Path to the project
473
- * @returns {Promise<Object>} - Status information
474
- */
475
- async checkStatus(projectPath) {
476
- const hasLegacy = await pathManager.hasLegacyStructure(projectPath)
477
- const hasConfig = await pathManager.hasConfig(projectPath)
478
- const needsMigration = hasLegacy && !hasConfig
479
-
480
- let status = 'unknown'
481
- if (!hasLegacy && !hasConfig) {
482
- status = 'new' // New project, not initialized
483
- } else if (!hasLegacy && hasConfig) {
484
- status = 'migrated' // Already migrated to v0.2.0
485
- } else if (hasLegacy && !hasConfig) {
486
- status = 'legacy' // v0.1.0, needs migration
487
- } else if (hasLegacy && hasConfig) {
488
- status = 'both' // Has both (migration incomplete or manual setup)
489
- }
490
-
491
- return {
492
- status,
493
- hasLegacy,
494
- hasConfig,
495
- needsMigration,
496
- version: hasConfig ? '0.2.0' : hasLegacy ? '0.1.0' : 'none',
497
- }
498
- }
499
-
500
- /**
501
- * Find all projects with .prjct directories on the user's machine
502
- *
503
- * @param {Object} options - Search options
504
- * @param {boolean} options.deepScan - Scan entire home directory (default: true for automatic migration)
505
- * @returns {Promise<Array<string>>} - Array of project paths
506
- */
507
- async findAllProjects(options = {}) {
508
- const { deepScan = true } = options
509
- const projectDirs = []
510
- const os = require('os')
511
-
512
- let searchPaths = []
513
- if (deepScan) {
514
- searchPaths = [os.homedir()]
515
- } else {
516
- const commonDirs = [
517
- 'Projects',
518
- 'Documents',
519
- 'Developer',
520
- 'Code',
521
- 'dev',
522
- 'workspace',
523
- 'repos',
524
- 'src',
525
- 'Apps',
526
- ]
527
- searchPaths = commonDirs
528
- .map((dir) => path.join(os.homedir(), dir))
529
- .filter((dirPath) => {
530
- try {
531
- fs.accessSync(dirPath)
532
- return true
533
- } catch {
534
- return false
535
- }
536
- })
537
- }
538
-
539
- const shouldSkip = (dirName) => {
540
- const skipDirs = [
541
- 'node_modules',
542
- '.git',
543
- '.next',
544
- 'dist',
545
- 'build',
546
- '.cache',
547
- 'coverage',
548
- '.vscode',
549
- '.idea',
550
- 'vendor',
551
- '__pycache__',
552
- ]
553
- return skipDirs.includes(dirName) || (dirName.startsWith('.') && dirName !== '.prjct')
554
- }
555
-
556
- const searchDirectory = async (dirPath, depth = 0) => {
557
- if (depth > 10) return
558
-
559
- try {
560
- const entries = await fs.readdir(dirPath, { withFileTypes: true })
561
-
562
- if (entries.some((entry) => entry.name === '.prjct' && entry.isDirectory())) {
563
- projectDirs.push(dirPath)
564
- return // Don't search subdirectories if we found a project
565
- }
566
-
567
- for (const entry of entries) {
568
- if (entry.isDirectory() && !shouldSkip(entry.name)) {
569
- const subPath = path.join(dirPath, entry.name)
570
- await searchDirectory(subPath, depth + 1)
571
- }
572
- }
573
- } catch (error) {}
574
- }
575
-
576
- for (const searchPath of searchPaths) {
577
- await searchDirectory(searchPath)
578
- }
579
-
580
- return projectDirs
581
- }
582
-
583
- /**
584
- * Migrate all projects with legacy .prjct directories
585
- *
586
- * @param {Object} options - Migration options
587
- * @param {boolean} options.deepScan - Scan entire home directory
588
- * @param {boolean} options.removeLegacy - Remove legacy .prjct after migration completely
589
- * @param {boolean} options.cleanupLegacy - Remove legacy directories but keep config
590
- * @param {boolean} options.dryRun - Simulate migration without making changes
591
- * @param {boolean} options.interactive - Ask for confirmation before each migration
592
- * @param {Function} options.onProgress - Callback for progress updates
593
- * @returns {Promise<Object>} - Migration summary
594
- */
595
- async migrateAll(options = {}) {
596
- const {
597
- deepScan = false,
598
- removeLegacy = false,
599
- cleanupLegacy = false,
600
- dryRun = false,
601
- interactive = false,
602
- onProgress = null,
603
- } = options
604
-
605
- const summary = {
606
- success: false,
607
- totalFound: 0,
608
- alreadyMigrated: 0,
609
- successfullyMigrated: 0,
610
- failed: 0,
611
- skipped: 0,
612
- projects: [],
613
- errors: [],
614
- dryRun,
615
- }
616
-
617
- try {
618
- if (onProgress) onProgress({ phase: 'scanning', message: 'Searching for projects...' })
619
- const projectPaths = await this.findAllProjects({ deepScan })
620
- summary.totalFound = projectPaths.length
621
-
622
- if (projectPaths.length === 0) {
623
- summary.success = true
624
- return summary
625
- }
626
-
627
- for (let i = 0; i < projectPaths.length; i++) {
628
- const projectPath = projectPaths[i]
629
- const projectName = path.basename(projectPath)
630
-
631
- if (onProgress) {
632
- onProgress({
633
- phase: 'checking',
634
- message: `Checking ${projectName} (${i + 1}/${projectPaths.length})`,
635
- current: i + 1,
636
- total: projectPaths.length,
637
- })
638
- }
639
-
640
- try {
641
- const status = await this.checkStatus(projectPath)
642
-
643
- const projectInfo = {
644
- path: projectPath,
645
- name: projectName,
646
- status: status.status,
647
- }
648
-
649
- if (status.status === 'migrated' || status.status === 'new') {
650
- projectInfo.result = 'skipped'
651
- projectInfo.reason =
652
- status.status === 'migrated' ? 'Already migrated' : 'Not initialized'
653
- summary.alreadyMigrated++
654
- } else if (status.needsMigration) {
655
- if (interactive && onProgress) {
656
- const shouldMigrate = await onProgress({
657
- phase: 'confirm',
658
- message: `Migrate ${projectName}?`,
659
- projectPath,
660
- })
661
- if (!shouldMigrate) {
662
- projectInfo.result = 'skipped'
663
- projectInfo.reason = 'User skipped'
664
- summary.skipped++
665
- summary.projects.push(projectInfo)
666
- continue
667
- }
668
- }
669
-
670
- if (onProgress) {
671
- onProgress({
672
- phase: 'migrating',
673
- message: `Migrating ${projectName}...`,
674
- current: i + 1,
675
- total: projectPaths.length,
676
- })
677
- }
678
-
679
- const migrationResult = await this.migrate(projectPath, {
680
- removeLegacy,
681
- cleanupLegacy,
682
- dryRun,
683
- })
684
-
685
- projectInfo.projectId = migrationResult.projectId
686
- projectInfo.filesCopied = migrationResult.filesCopied
687
- projectInfo.layerCounts = migrationResult.layerCounts
688
-
689
- if (migrationResult.success) {
690
- projectInfo.result = 'success'
691
- summary.successfullyMigrated++
692
- } else {
693
- projectInfo.result = 'failed'
694
- projectInfo.errors = migrationResult.issues
695
- summary.failed++
696
- summary.errors.push({
697
- project: projectName,
698
- path: projectPath,
699
- issues: migrationResult.issues,
700
- })
701
- }
702
- }
703
-
704
- summary.projects.push(projectInfo)
705
- } catch (error) {
706
- summary.failed++
707
- summary.errors.push({
708
- project: projectName,
709
- path: projectPath,
710
- issues: [error.message],
711
- })
712
- summary.projects.push({
713
- path: projectPath,
714
- name: projectName,
715
- result: 'failed',
716
- errors: [error.message],
717
- })
718
- }
719
- }
720
-
721
- summary.success = summary.failed === 0
722
- return summary
723
- } catch (error) {
724
- summary.success = false
725
- summary.errors.push({
726
- project: 'global',
727
- issues: [error.message],
728
- })
729
- return summary
730
- }
731
- }
732
-
733
- /**
734
- * Generate a summary report for migrateAll results
735
- *
736
- * @param {Object} summary - Migration summary from migrateAll
737
- * @returns {string} - Formatted report
738
- */
739
- generateMigrationSummary(summary) {
740
- const lines = []
741
-
742
- lines.push('📦 Global Migration Report')
743
- lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
744
-
745
- if (summary.dryRun) {
746
- lines.push('⚠️ DRY RUN MODE - No changes were made')
747
- lines.push('')
748
- }
749
-
750
- lines.push(`🔍 Found: ${summary.totalFound} projects`)
751
- lines.push(`✅ Successfully migrated: ${summary.successfullyMigrated}`)
752
- lines.push(`⏭️ Already migrated: ${summary.alreadyMigrated}`)
753
- if (summary.skipped > 0) {
754
- lines.push(`⏸️ Skipped: ${summary.skipped}`)
755
- }
756
- if (summary.failed > 0) {
757
- lines.push(`❌ Failed: ${summary.failed}`)
758
- }
759
- lines.push('')
760
-
761
- if (summary.successfullyMigrated > 0) {
762
- lines.push('✅ Successfully Migrated:')
763
- summary.projects
764
- .filter((p) => p.result === 'success')
765
- .forEach((project) => {
766
- lines.push(` • ${project.name}`)
767
- lines.push(` Files: ${project.filesCopied} | ID: ${project.projectId}`)
768
- })
769
- lines.push('')
770
- }
771
-
772
- if (summary.errors.length > 0) {
773
- lines.push('❌ Errors:')
774
- summary.errors.forEach((error) => {
775
- lines.push(` • ${error.project}`)
776
- error.issues.forEach((issue) => lines.push(` - ${issue}`))
777
- })
778
- lines.push('')
779
- }
780
-
781
- if (summary.success && summary.successfullyMigrated > 0) {
782
- lines.push('🎉 All projects migrated successfully!')
783
- lines.push(`📍 Global data location: ${pathManager.getGlobalBasePath()}`)
784
- } else if (summary.totalFound === 0) {
785
- lines.push('ℹ️ No legacy projects found')
786
- } else if (summary.alreadyMigrated === summary.totalFound) {
787
- lines.push('ℹ️ All projects already migrated')
788
- }
789
-
790
- lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
791
-
792
- return lines.join('\n')
793
- }
794
- }
795
-
796
- module.exports = new Migrator()