prjct-cli 0.11.4 → 0.12.0

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