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
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Ground Truth Verification
3
+ * Verifies actual state before critical operations
4
+ *
5
+ * OPTIMIZATION (P1.3): Anti-Hallucination Pattern
6
+ * - Reads actual files before assuming state
7
+ * - Compares expected vs actual state
8
+ * - Provides specific warnings for mismatches
9
+ * - Logs verification results for debugging
10
+ *
11
+ * Source: Devin, Cursor, Augment Code patterns
12
+ */
13
+
14
+ import type { Context, VerificationResult } from './types'
15
+ import { verifiers } from './verifiers'
16
+ import { formatWarnings } from './utils'
17
+
18
+ export type { Context, VerificationResult, Verifier } from './types'
19
+ export { verifiers } from './verifiers'
20
+ export { formatDuration, escapeRegex, formatWarnings } from './utils'
21
+
22
+ /**
23
+ * Verify ground truth before command execution
24
+ */
25
+ async function verify(commandName: string, context: Context, state: unknown): Promise<VerificationResult> {
26
+ const verifier = verifiers[commandName]
27
+
28
+ if (!verifier) {
29
+ // No specific verification needed
30
+ return {
31
+ verified: true,
32
+ actual: {},
33
+ warnings: [],
34
+ recommendations: [],
35
+ }
36
+ }
37
+
38
+ try {
39
+ return await verifier(context, state)
40
+ } catch (error) {
41
+ return {
42
+ verified: false,
43
+ actual: {},
44
+ warnings: [`Verification error: ${(error as Error).message}`],
45
+ recommendations: ['Check file permissions and project configuration'],
46
+ }
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Prepare command by verifying ground truth
52
+ * Returns enhanced context with verification results
53
+ */
54
+ async function prepareCommand(commandName: string, context: Context, state: unknown) {
55
+ const verification = await verify(commandName, context, state)
56
+
57
+ return {
58
+ ...context,
59
+ groundTruth: {
60
+ ...verification,
61
+ verifiedAt: new Date().toISOString(),
62
+ command: commandName,
63
+ },
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Check if command requires ground truth verification
69
+ */
70
+ function requiresVerification(commandName: string): boolean {
71
+ // ANTI-HALLUCINATION: Expanded verification for more commands
72
+ return ['done', 'ship', 'feature', 'spec', 'now', 'init', 'sync', 'analyze'].includes(commandName)
73
+ }
74
+
75
+ export { verify, prepareCommand, requiresVerification }
76
+ export default { verify, prepareCommand, requiresVerification, formatWarnings, verifiers }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Ground Truth Types
3
+ */
4
+
5
+ export interface Context {
6
+ projectPath: string
7
+ projectId?: string | null
8
+ paths: {
9
+ now: string
10
+ next: string
11
+ metrics: string
12
+ shipped: string
13
+ roadmap: string
14
+ specs: string
15
+ [key: string]: string
16
+ }
17
+ params: {
18
+ feature?: string
19
+ description?: string
20
+ task?: string
21
+ name?: string
22
+ [key: string]: unknown
23
+ }
24
+ }
25
+
26
+ export interface VerificationResult {
27
+ verified: boolean
28
+ actual: Record<string, unknown>
29
+ warnings: string[]
30
+ recommendations: string[]
31
+ }
32
+
33
+ export type Verifier = (context: Context, state: unknown) => Promise<VerificationResult>
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Ground Truth Utilities
3
+ */
4
+
5
+ import type { VerificationResult } from './types'
6
+
7
+ /**
8
+ * Format duration from milliseconds to human-readable string
9
+ */
10
+ export function formatDuration(ms: number): string {
11
+ const hours = Math.floor(ms / (1000 * 60 * 60))
12
+ const minutes = Math.floor((ms % (1000 * 60 * 60)) / (1000 * 60))
13
+
14
+ if (hours > 0) {
15
+ return `${hours}h ${minutes}m`
16
+ }
17
+ return `${minutes}m`
18
+ }
19
+
20
+ /**
21
+ * Escape special regex characters in a string
22
+ */
23
+ export function escapeRegex(string: string): string {
24
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
25
+ }
26
+
27
+ /**
28
+ * Format verification warnings for display
29
+ */
30
+ export function formatWarnings(result: VerificationResult): string | null {
31
+ if (result.verified || result.warnings.length === 0) {
32
+ return null
33
+ }
34
+
35
+ let output = '⚠️ Ground Truth Warnings:\n'
36
+ result.warnings.forEach((w) => {
37
+ output += ` • ${w}\n`
38
+ })
39
+
40
+ if (result.recommendations.length > 0) {
41
+ output += '\nRecommendations:\n'
42
+ result.recommendations.forEach((r) => {
43
+ output += ` → ${r}\n`
44
+ })
45
+ }
46
+
47
+ return output
48
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Analyze Command Verifier
3
+ * Verify analysis can proceed
4
+ */
5
+
6
+ import fs from 'fs/promises'
7
+ import path from 'path'
8
+ import type { Context, VerificationResult } from '../types'
9
+
10
+ export async function verifyAnalyze(context: Context): Promise<VerificationResult> {
11
+ const warnings: string[] = []
12
+ const recommendations: string[] = []
13
+ const actual: Record<string, unknown> = {}
14
+
15
+ // 1. Check if project has recognizable structure
16
+ const files = ['package.json', 'Cargo.toml', 'go.mod', 'requirements.txt', 'Gemfile', 'pom.xml']
17
+ actual.detectedFiles = []
18
+
19
+ for (const file of files) {
20
+ try {
21
+ await fs.access(path.join(context.projectPath, file))
22
+ ;(actual.detectedFiles as string[]).push(file)
23
+ } catch {
24
+ // File doesn't exist
25
+ }
26
+ }
27
+
28
+ if ((actual.detectedFiles as string[]).length === 0) {
29
+ warnings.push('No recognizable project files detected')
30
+ recommendations.push('Analysis may be limited without package.json or similar')
31
+ }
32
+
33
+ // 2. Check for source directories
34
+ const srcDirs = ['src', 'lib', 'app', 'core', 'components']
35
+ actual.detectedSrcDirs = []
36
+
37
+ for (const dir of srcDirs) {
38
+ try {
39
+ const stat = await fs.stat(path.join(context.projectPath, dir))
40
+ if (stat.isDirectory()) {
41
+ ;(actual.detectedSrcDirs as string[]).push(dir)
42
+ }
43
+ } catch {
44
+ // Directory doesn't exist
45
+ }
46
+ }
47
+
48
+ return {
49
+ verified: true, // Analysis can always proceed, even with warnings
50
+ actual,
51
+ warnings,
52
+ recommendations,
53
+ }
54
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Done Command Verifier
3
+ * Verify task is actually complete-able
4
+ */
5
+
6
+ import fs from 'fs/promises'
7
+ import path from 'path'
8
+ import type { Context, VerificationResult } from '../types'
9
+ import { formatDuration } from '../utils'
10
+
11
+ export async function verifyDone(context: Context): Promise<VerificationResult> {
12
+ const warnings: string[] = []
13
+ const recommendations: string[] = []
14
+ const actual: Record<string, unknown> = {}
15
+
16
+ // 1. Verify now.md exists and has real content
17
+ const nowPath = context.paths.now
18
+ try {
19
+ const nowContent = await fs.readFile(nowPath, 'utf-8')
20
+ actual.nowExists = true
21
+ actual.nowContent = nowContent.trim()
22
+ actual.nowLength = nowContent.length
23
+
24
+ // Check for placeholder content
25
+ if (nowContent.includes('No current task') || nowContent.match(/^#\s*NOW\s*$/m)) {
26
+ warnings.push('now.md appears to be empty or placeholder')
27
+ recommendations.push('Start a task first with /p:now "task"')
28
+ }
29
+
30
+ // Check for task metadata (started time)
31
+ const startedMatch = nowContent.match(/Started:\s*(.+)/i)
32
+ if (startedMatch) {
33
+ actual.startedAt = startedMatch[1]
34
+ // Calculate duration
35
+ const startTime = new Date(startedMatch[1])
36
+ if (!isNaN(startTime.getTime())) {
37
+ actual.durationMs = Date.now() - startTime.getTime()
38
+ actual.durationFormatted = formatDuration(actual.durationMs as number)
39
+ }
40
+ }
41
+ } catch {
42
+ actual.nowExists = false
43
+ warnings.push('now.md does not exist')
44
+ recommendations.push('Create a task with /p:now "task"')
45
+ }
46
+
47
+ // 2. Verify next.md for auto-start
48
+ const nextPath = context.paths.next
49
+ try {
50
+ const nextContent = await fs.readFile(nextPath, 'utf-8')
51
+ actual.nextExists = true
52
+ const tasks = nextContent.match(/- \[ \]/g) || []
53
+ actual.pendingTasks = tasks.length
54
+ } catch {
55
+ actual.nextExists = false
56
+ actual.pendingTasks = 0
57
+ }
58
+
59
+ // 3. Verify metrics.md is writable
60
+ const metricsPath = context.paths.metrics
61
+ try {
62
+ await fs.access(path.dirname(metricsPath), fs.constants.W_OK)
63
+ actual.metricsWritable = true
64
+ } catch {
65
+ actual.metricsWritable = false
66
+ warnings.push('Cannot write to metrics directory')
67
+ }
68
+
69
+ return {
70
+ verified: warnings.length === 0,
71
+ actual,
72
+ warnings,
73
+ recommendations,
74
+ }
75
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Feature Command Verifier
3
+ * Verify feature can be added
4
+ */
5
+
6
+ import fs from 'fs/promises'
7
+ import type { Context, VerificationResult } from '../types'
8
+ import { escapeRegex } from '../utils'
9
+
10
+ export async function verifyFeature(context: Context): Promise<VerificationResult> {
11
+ const warnings: string[] = []
12
+ const recommendations: string[] = []
13
+ const actual: Record<string, unknown> = {}
14
+
15
+ // 1. Check next.md capacity
16
+ const nextPath = context.paths.next
17
+ try {
18
+ const nextContent = await fs.readFile(nextPath, 'utf-8')
19
+ actual.nextExists = true
20
+ const tasks = nextContent.match(/- \[[ x]\]/g) || []
21
+ actual.taskCount = tasks.length
22
+ actual.pendingTasks = (nextContent.match(/- \[ \]/g) || []).length
23
+
24
+ if ((actual.taskCount as number) >= 90) {
25
+ warnings.push(`Queue nearly full (${actual.taskCount}/100 tasks)`)
26
+ recommendations.push('Complete some tasks before adding more')
27
+ }
28
+ } catch {
29
+ actual.nextExists = false
30
+ actual.taskCount = 0
31
+ }
32
+
33
+ // 2. Check roadmap.md for duplicate features
34
+ const roadmapPath = context.paths.roadmap
35
+ try {
36
+ const roadmapContent = await fs.readFile(roadmapPath, 'utf-8')
37
+ actual.roadmapExists = true
38
+
39
+ const featureName = context.params.description || context.params.feature
40
+ if (featureName) {
41
+ const featurePattern = new RegExp(escapeRegex(featureName), 'i')
42
+ if (featurePattern.test(roadmapContent)) {
43
+ warnings.push(`Feature "${featureName}" may already exist in roadmap`)
44
+ recommendations.push('Check roadmap for duplicates with /p:roadmap')
45
+ }
46
+ }
47
+ } catch {
48
+ actual.roadmapExists = false
49
+ }
50
+
51
+ // 3. Check if there's an active task (should complete first?)
52
+ const nowPath = context.paths.now
53
+ try {
54
+ const nowContent = await fs.readFile(nowPath, 'utf-8')
55
+ actual.hasActiveTask = nowContent.trim().length > 0 && !nowContent.includes('No current task')
56
+
57
+ if (actual.hasActiveTask) {
58
+ recommendations.push('Consider completing current task first with /p:done')
59
+ }
60
+ } catch {
61
+ actual.hasActiveTask = false
62
+ }
63
+
64
+ return {
65
+ verified: warnings.length === 0,
66
+ actual,
67
+ warnings,
68
+ recommendations,
69
+ }
70
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Ground Truth Verifiers Index
3
+ * Re-exports all command verifiers
4
+ */
5
+
6
+ import type { Verifier } from '../types'
7
+ import { verifyDone } from './done'
8
+ import { verifyShip } from './ship'
9
+ import { verifyFeature } from './feature'
10
+ import { verifyNow } from './now'
11
+ import { verifyInit } from './init'
12
+ import { verifySync } from './sync'
13
+ import { verifyAnalyze } from './analyze'
14
+ import { verifySpec } from './spec'
15
+
16
+ /**
17
+ * Command-specific ground truth verifiers
18
+ */
19
+ export const verifiers: Record<string, Verifier> = {
20
+ done: verifyDone,
21
+ ship: verifyShip,
22
+ feature: verifyFeature,
23
+ now: verifyNow,
24
+ init: verifyInit,
25
+ sync: verifySync,
26
+ analyze: verifyAnalyze,
27
+ spec: verifySpec,
28
+ }
29
+
30
+ export { verifyDone } from './done'
31
+ export { verifyShip } from './ship'
32
+ export { verifyFeature } from './feature'
33
+ export { verifyNow } from './now'
34
+ export { verifyInit } from './init'
35
+ export { verifySync } from './sync'
36
+ export { verifyAnalyze } from './analyze'
37
+ export { verifySpec } from './spec'
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Init Command Verifier
3
+ * Verify project can be initialized
4
+ */
5
+
6
+ import fs from 'fs/promises'
7
+ import path from 'path'
8
+ import os from 'os'
9
+ import type { Context, VerificationResult } from '../types'
10
+
11
+ export async function verifyInit(context: Context): Promise<VerificationResult> {
12
+ const warnings: string[] = []
13
+ const recommendations: string[] = []
14
+ const actual: Record<string, unknown> = {}
15
+
16
+ // 1. Check if already initialized
17
+ const configPath = path.join(context.projectPath, '.prjct/prjct.config.json')
18
+ try {
19
+ const configContent = await fs.readFile(configPath, 'utf-8')
20
+ actual.alreadyInitialized = true
21
+ actual.existingConfig = JSON.parse(configContent)
22
+ warnings.push('Project already initialized')
23
+ recommendations.push('Use /p:analyze to refresh analysis or delete .prjct/ to reinitialize')
24
+ } catch {
25
+ actual.alreadyInitialized = false
26
+ }
27
+
28
+ // 2. Check if global storage path is writable
29
+ const globalPath = path.join(os.homedir(), '.prjct-cli')
30
+ try {
31
+ await fs.access(globalPath, fs.constants.W_OK)
32
+ actual.globalPathWritable = true
33
+ } catch {
34
+ try {
35
+ // Try to create it
36
+ await fs.mkdir(globalPath, { recursive: true })
37
+ actual.globalPathWritable = true
38
+ actual.globalPathCreated = true
39
+ } catch {
40
+ actual.globalPathWritable = false
41
+ warnings.push('Cannot write to ~/.prjct-cli')
42
+ recommendations.push('Check directory permissions')
43
+ }
44
+ }
45
+
46
+ return {
47
+ verified: warnings.length === 0,
48
+ actual,
49
+ warnings,
50
+ recommendations,
51
+ }
52
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Now Command Verifier
3
+ * Verify task can be set (anti-hallucination: warn if replacing)
4
+ */
5
+
6
+ import fs from 'fs/promises'
7
+ import type { Context, VerificationResult } from '../types'
8
+
9
+ export async function verifyNow(context: Context): Promise<VerificationResult> {
10
+ const warnings: string[] = []
11
+ const recommendations: string[] = []
12
+ const actual: Record<string, unknown> = {}
13
+
14
+ // 1. Check if there's already an active task
15
+ const nowPath = context.paths.now
16
+ try {
17
+ const nowContent = await fs.readFile(nowPath, 'utf-8')
18
+ actual.nowExists = true
19
+ actual.nowContent = nowContent.trim()
20
+
21
+ const hasRealTask =
22
+ nowContent.trim().length > 0 && !nowContent.includes('No current task') && !nowContent.match(/^#\s*NOW\s*$/m)
23
+
24
+ actual.hasActiveTask = hasRealTask
25
+
26
+ // ANTI-HALLUCINATION: Warn if replacing existing task
27
+ if (hasRealTask && context.params.task) {
28
+ const taskPreview = nowContent.substring(0, 50).replace(/\n/g, ' ')
29
+ warnings.push(`Replacing existing task: "${taskPreview}..."`)
30
+ recommendations.push('Use /p:done first to track completion')
31
+ }
32
+ } catch {
33
+ actual.nowExists = false
34
+ actual.hasActiveTask = false
35
+ }
36
+
37
+ // 2. Check next.md for available tasks
38
+ const nextPath = context.paths.next
39
+ try {
40
+ const nextContent = await fs.readFile(nextPath, 'utf-8')
41
+ const pendingTasks = (nextContent.match(/- \[ \]/g) || []).length
42
+ actual.pendingTasks = pendingTasks
43
+
44
+ if (!context.params.task && pendingTasks > 0) {
45
+ recommendations.push(`${pendingTasks} tasks available in queue`)
46
+ }
47
+ } catch {
48
+ actual.pendingTasks = 0
49
+ }
50
+
51
+ return {
52
+ verified: warnings.length === 0,
53
+ actual,
54
+ warnings,
55
+ recommendations,
56
+ }
57
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Ship Command Verifier
3
+ * Verify feature is ready to ship
4
+ */
5
+
6
+ import fs from 'fs/promises'
7
+ import path from 'path'
8
+ import { execSync } from 'child_process'
9
+ import type { Context, VerificationResult } from '../types'
10
+ import { escapeRegex } from '../utils'
11
+
12
+ export async function verifyShip(context: Context): Promise<VerificationResult> {
13
+ const warnings: string[] = []
14
+ const recommendations: string[] = []
15
+ const actual: Record<string, unknown> = {}
16
+
17
+ // 1. Check for uncommitted changes
18
+ try {
19
+ const gitStatus = execSync('git status --porcelain', {
20
+ cwd: context.projectPath,
21
+ encoding: 'utf-8',
22
+ })
23
+ actual.hasUncommittedChanges = gitStatus.trim().length > 0
24
+ actual.uncommittedFiles = gitStatus.trim().split('\n').filter(Boolean).length
25
+
26
+ if (actual.hasUncommittedChanges) {
27
+ warnings.push(`${actual.uncommittedFiles} uncommitted file(s)`)
28
+ recommendations.push('Commit changes before shipping')
29
+ }
30
+ } catch {
31
+ actual.gitAvailable = false
32
+ // Not a git repo or git not available - not a blocker
33
+ }
34
+
35
+ // 2. Check for package.json version (if exists)
36
+ const pkgPath = path.join(context.projectPath, 'package.json')
37
+ try {
38
+ const pkgContent = await fs.readFile(pkgPath, 'utf-8')
39
+ const pkg = JSON.parse(pkgContent)
40
+ actual.currentVersion = pkg.version
41
+ actual.hasPackageJson = true
42
+ } catch {
43
+ actual.hasPackageJson = false
44
+ }
45
+
46
+ // 3. Check shipped.md for duplicate feature names
47
+ const shippedPath = context.paths.shipped
48
+ try {
49
+ const shippedContent = await fs.readFile(shippedPath, 'utf-8')
50
+ actual.shippedExists = true
51
+
52
+ // Check if feature name already shipped today
53
+ const featureName = context.params.feature || context.params.description
54
+ if (featureName) {
55
+ const today = new Date().toISOString().split('T')[0]
56
+ const todayPattern = new RegExp(`${today}.*${escapeRegex(featureName)}`, 'i')
57
+ if (todayPattern.test(shippedContent)) {
58
+ warnings.push(`Feature "${featureName}" already shipped today`)
59
+ recommendations.push('Use a different feature name or skip /p:ship')
60
+ }
61
+ }
62
+ } catch {
63
+ actual.shippedExists = false
64
+ }
65
+
66
+ // 4. Check for test failures (if test script exists)
67
+ if (actual.hasPackageJson) {
68
+ try {
69
+ const pkgContent = await fs.readFile(pkgPath, 'utf-8')
70
+ const pkg = JSON.parse(pkgContent)
71
+ actual.hasTestScript = !!pkg.scripts?.test
72
+ // Note: We don't run tests here, just check if they exist
73
+ // Running tests is the user's responsibility
74
+ } catch {
75
+ actual.hasTestScript = false
76
+ }
77
+ }
78
+
79
+ return {
80
+ verified: warnings.length === 0,
81
+ actual,
82
+ warnings,
83
+ recommendations,
84
+ }
85
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Spec Command Verifier
3
+ * Verify spec can be created
4
+ */
5
+
6
+ import fs from 'fs/promises'
7
+ import type { Context, VerificationResult } from '../types'
8
+
9
+ export async function verifySpec(context: Context): Promise<VerificationResult> {
10
+ const warnings: string[] = []
11
+ const recommendations: string[] = []
12
+ const actual: Record<string, unknown> = {}
13
+
14
+ // 1. Check specs directory exists
15
+ const specsPath = context.paths.specs
16
+ try {
17
+ await fs.access(specsPath)
18
+ actual.specsExists = true
19
+
20
+ // List existing specs
21
+ const files = await fs.readdir(specsPath)
22
+ actual.existingSpecs = files.filter((f) => f.endsWith('.md'))
23
+ actual.specCount = (actual.existingSpecs as string[]).length
24
+ } catch {
25
+ actual.specsExists = false
26
+ actual.specCount = 0
27
+ }
28
+
29
+ // 2. Check for duplicate spec name
30
+ const featureName = context.params.feature || context.params.name || context.params.description
31
+ if (featureName && actual.existingSpecs) {
32
+ const slug = featureName.toLowerCase().replace(/\s+/g, '-')
33
+ if ((actual.existingSpecs as string[]).includes(`${slug}.md`)) {
34
+ warnings.push(`Spec "${featureName}" already exists`)
35
+ recommendations.push('Use a different name or edit existing spec')
36
+ }
37
+ }
38
+
39
+ return {
40
+ verified: warnings.length === 0,
41
+ actual,
42
+ warnings,
43
+ recommendations,
44
+ }
45
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Sync Command Verifier
3
+ * Verify sync can proceed
4
+ */
5
+
6
+ import fs from 'fs/promises'
7
+ import path from 'path'
8
+ import os from 'os'
9
+ import type { Context, VerificationResult } from '../types'
10
+
11
+ export async function verifySync(context: Context): Promise<VerificationResult> {
12
+ const warnings: string[] = []
13
+ const recommendations: string[] = []
14
+ const actual: Record<string, unknown> = {}
15
+
16
+ // 1. Check if project is initialized
17
+ const configPath = path.join(context.projectPath, '.prjct/prjct.config.json')
18
+ try {
19
+ const configContent = await fs.readFile(configPath, 'utf-8')
20
+ actual.hasConfig = true
21
+ actual.config = JSON.parse(configContent)
22
+ } catch {
23
+ actual.hasConfig = false
24
+ warnings.push('Project not initialized')
25
+ recommendations.push('Run /p:init first')
26
+ return { verified: false, actual, warnings, recommendations }
27
+ }
28
+
29
+ // 2. Check if global storage exists
30
+ const projectId = (actual.config as { projectId?: string })?.projectId
31
+ const globalProjectPath = path.join(os.homedir(), '.prjct-cli/projects', projectId || '')
32
+ try {
33
+ await fs.access(globalProjectPath)
34
+ actual.globalStorageExists = true
35
+ } catch {
36
+ actual.globalStorageExists = false
37
+ warnings.push('Global storage missing')
38
+ recommendations.push('Run /p:init to recreate')
39
+ }
40
+
41
+ return {
42
+ verified: warnings.length === 0,
43
+ actual,
44
+ warnings,
45
+ recommendations,
46
+ }
47
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Ground Truth Verifiers
3
+ * Re-exports from verifiers/index.ts for backwards compatibility.
4
+ */
5
+
6
+ export * from './verifiers/index'