prjct-cli 0.11.4 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (385) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +81 -25
  3. package/bin/dev.js +1 -1
  4. package/bin/generate-views.js +209 -0
  5. package/bin/migrate-to-json.js +742 -0
  6. package/bin/prjct +5 -5
  7. package/bin/serve.js +246 -54
  8. package/core/__tests__/agentic/{memory-system.test.js → memory-system.test.ts} +12 -23
  9. package/core/__tests__/agentic/{plan-mode.test.js → plan-mode.test.ts} +26 -24
  10. package/core/__tests__/agentic/{prompt-builder.test.js → prompt-builder.test.ts} +3 -8
  11. package/core/__tests__/utils/date-helper.test.ts +405 -0
  12. package/core/__tests__/utils/{output.test.js → output.test.ts} +12 -24
  13. package/core/agentic/agent-router.ts +137 -0
  14. package/core/agentic/chain-of-thought.ts +228 -0
  15. package/core/agentic/command-executor/command-executor.ts +384 -0
  16. package/core/agentic/command-executor/index.ts +16 -0
  17. package/core/agentic/command-executor/status-signal.ts +38 -0
  18. package/core/agentic/command-executor/types.ts +79 -0
  19. package/core/agentic/command-executor.ts +8 -0
  20. package/core/agentic/{context-builder.js → context-builder.ts} +99 -89
  21. package/core/agentic/context-filter.ts +365 -0
  22. package/core/agentic/ground-truth/index.ts +76 -0
  23. package/core/agentic/ground-truth/types.ts +33 -0
  24. package/core/agentic/ground-truth/utils.ts +48 -0
  25. package/core/agentic/ground-truth/verifiers/analyze.ts +54 -0
  26. package/core/agentic/ground-truth/verifiers/done.ts +75 -0
  27. package/core/agentic/ground-truth/verifiers/feature.ts +70 -0
  28. package/core/agentic/ground-truth/verifiers/index.ts +37 -0
  29. package/core/agentic/ground-truth/verifiers/init.ts +52 -0
  30. package/core/agentic/ground-truth/verifiers/now.ts +57 -0
  31. package/core/agentic/ground-truth/verifiers/ship.ts +85 -0
  32. package/core/agentic/ground-truth/verifiers/spec.ts +45 -0
  33. package/core/agentic/ground-truth/verifiers/sync.ts +47 -0
  34. package/core/agentic/ground-truth/verifiers.ts +6 -0
  35. package/core/agentic/ground-truth.ts +8 -0
  36. package/core/agentic/loop-detector/error-analysis.ts +97 -0
  37. package/core/agentic/loop-detector/hallucination.ts +71 -0
  38. package/core/agentic/loop-detector/index.ts +41 -0
  39. package/core/agentic/loop-detector/loop-detector.ts +222 -0
  40. package/core/agentic/loop-detector/types.ts +66 -0
  41. package/core/agentic/loop-detector.ts +8 -0
  42. package/core/agentic/memory-system/history.ts +53 -0
  43. package/core/agentic/memory-system/index.ts +192 -0
  44. package/core/agentic/memory-system/patterns.ts +156 -0
  45. package/core/agentic/memory-system/semantic-memories.ts +277 -0
  46. package/core/agentic/memory-system/session.ts +21 -0
  47. package/core/agentic/memory-system/types.ts +159 -0
  48. package/core/agentic/memory-system.ts +8 -0
  49. package/core/agentic/parallel-tools.ts +165 -0
  50. package/core/agentic/plan-mode/approval.ts +57 -0
  51. package/core/agentic/plan-mode/constants.ts +44 -0
  52. package/core/agentic/plan-mode/index.ts +28 -0
  53. package/core/agentic/plan-mode/plan-mode.ts +406 -0
  54. package/core/agentic/plan-mode/types.ts +193 -0
  55. package/core/agentic/plan-mode.ts +8 -0
  56. package/core/agentic/prompt-builder.ts +566 -0
  57. package/core/agentic/response-templates.ts +164 -0
  58. package/core/agentic/semantic-compression.ts +273 -0
  59. package/core/agentic/services.ts +206 -0
  60. package/core/agentic/smart-context.ts +476 -0
  61. package/core/agentic/{template-loader.js → template-loader.ts} +35 -18
  62. package/core/agentic/think-blocks.ts +202 -0
  63. package/core/agentic/tool-registry.ts +119 -0
  64. package/core/agentic/validation-rules.ts +313 -0
  65. package/core/agents/index.ts +28 -0
  66. package/core/agents/performance.ts +444 -0
  67. package/core/agents/types.ts +126 -0
  68. package/core/bus/{index.js → index.ts} +57 -61
  69. package/core/command-registry/categories.ts +23 -0
  70. package/core/command-registry/commands.ts +15 -0
  71. package/core/command-registry/core-commands.ts +319 -0
  72. package/core/command-registry/index.ts +158 -0
  73. package/core/command-registry/optional-commands.ts +119 -0
  74. package/core/command-registry/setup-commands.ts +53 -0
  75. package/core/command-registry/types.ts +59 -0
  76. package/core/command-registry.ts +9 -0
  77. package/core/commands/analysis.ts +298 -0
  78. package/core/commands/analytics.ts +288 -0
  79. package/core/commands/base.ts +273 -0
  80. package/core/commands/index.ts +211 -0
  81. package/core/commands/maintenance.ts +226 -0
  82. package/core/commands/planning.ts +311 -0
  83. package/core/commands/setup.ts +309 -0
  84. package/core/commands/shipping.ts +188 -0
  85. package/core/commands/types.ts +183 -0
  86. package/core/commands/workflow.ts +226 -0
  87. package/core/commands.ts +11 -0
  88. package/core/constants/formats.ts +187 -0
  89. package/core/constants/index.ts +7 -0
  90. package/core/{context-sync.js → context-sync.ts} +59 -26
  91. package/core/data/agents-manager.ts +76 -0
  92. package/core/data/analysis-manager.ts +83 -0
  93. package/core/data/base-manager.ts +156 -0
  94. package/core/data/ideas-manager.ts +81 -0
  95. package/core/data/index.ts +32 -0
  96. package/core/data/outcomes-manager.ts +96 -0
  97. package/core/data/project-manager.ts +75 -0
  98. package/core/data/roadmap-manager.ts +118 -0
  99. package/core/data/shipped-manager.ts +65 -0
  100. package/core/data/state-manager.ts +214 -0
  101. package/core/domain/{agent-generator.js → agent-generator.ts} +77 -57
  102. package/core/domain/{agent-loader.js → agent-loader.ts} +65 -56
  103. package/core/domain/{agent-matcher.js → agent-matcher.ts} +51 -24
  104. package/core/domain/{agent-validator.js → agent-validator.ts} +70 -37
  105. package/core/domain/{analyzer.js → analyzer.ts} +91 -85
  106. package/core/domain/{architect-session.js → architect-session.ts} +49 -34
  107. package/core/domain/{architecture-generator.js → architecture-generator.ts} +25 -13
  108. package/core/domain/{context-estimator.js → context-estimator.ts} +57 -36
  109. package/core/domain/{product-standards.js → product-standards.ts} +40 -26
  110. package/core/domain/{smart-cache.js → smart-cache.ts} +39 -30
  111. package/core/domain/{snapshot-manager.js → snapshot-manager.ts} +103 -100
  112. package/core/domain/{task-analyzer.js → task-analyzer.ts} +82 -43
  113. package/core/domain/task-stack/index.ts +19 -0
  114. package/core/domain/task-stack/parser.ts +86 -0
  115. package/core/domain/task-stack/storage.ts +123 -0
  116. package/core/domain/task-stack/task-stack.ts +340 -0
  117. package/core/domain/task-stack/types.ts +51 -0
  118. package/core/domain/task-stack.ts +8 -0
  119. package/core/{index.js → index.ts} +61 -18
  120. package/core/infrastructure/{agent-detector.js → agent-detector.ts} +62 -23
  121. package/core/infrastructure/agents/{claude-agent.js → claude-agent.ts} +61 -21
  122. package/core/infrastructure/{author-detector.js → author-detector.ts} +42 -49
  123. package/core/infrastructure/{capability-installer.js → capability-installer.ts} +51 -27
  124. package/core/infrastructure/{command-installer.js → command-installer/command-installer.ts} +43 -144
  125. package/core/infrastructure/command-installer/global-config.ts +106 -0
  126. package/core/infrastructure/command-installer/index.ts +25 -0
  127. package/core/infrastructure/command-installer/types.ts +41 -0
  128. package/core/infrastructure/command-installer.ts +8 -0
  129. package/core/infrastructure/{config-manager.js → config-manager.ts} +60 -80
  130. package/core/infrastructure/{editors-config.js → editors-config.ts} +33 -31
  131. package/core/infrastructure/legacy-installer-detector/cleanup.ts +216 -0
  132. package/core/infrastructure/legacy-installer-detector/detection.ts +95 -0
  133. package/core/infrastructure/legacy-installer-detector/index.ts +171 -0
  134. package/core/infrastructure/legacy-installer-detector/migration.ts +87 -0
  135. package/core/infrastructure/legacy-installer-detector/types.ts +42 -0
  136. package/core/infrastructure/legacy-installer-detector.ts +7 -0
  137. package/core/infrastructure/migrator/file-operations.ts +125 -0
  138. package/core/infrastructure/migrator/index.ts +288 -0
  139. package/core/infrastructure/migrator/project-scanner.ts +89 -0
  140. package/core/infrastructure/migrator/reports.ts +117 -0
  141. package/core/infrastructure/migrator/types.ts +124 -0
  142. package/core/infrastructure/migrator/validation.ts +94 -0
  143. package/core/infrastructure/migrator/version-migration.ts +117 -0
  144. package/core/infrastructure/migrator.ts +10 -0
  145. package/core/infrastructure/{path-manager.js → path-manager.ts} +51 -91
  146. package/core/infrastructure/session-manager/index.ts +23 -0
  147. package/core/infrastructure/session-manager/migration.ts +88 -0
  148. package/core/infrastructure/session-manager/session-manager.ts +307 -0
  149. package/core/infrastructure/session-manager/types.ts +45 -0
  150. package/core/infrastructure/session-manager.ts +8 -0
  151. package/core/infrastructure/{setup.js → setup.ts} +29 -21
  152. package/core/infrastructure/{update-checker.js → update-checker.ts} +40 -18
  153. package/core/outcomes/analyzer.ts +333 -0
  154. package/core/outcomes/index.ts +34 -0
  155. package/core/outcomes/recorder.ts +194 -0
  156. package/core/outcomes/types.ts +145 -0
  157. package/core/plugin/{hooks.js → hooks.ts} +56 -58
  158. package/core/plugin/{index.js → index.ts} +19 -8
  159. package/core/plugin/{loader.js → loader.ts} +87 -69
  160. package/core/plugin/{registry.js → registry.ts} +49 -45
  161. package/core/plugins/{webhook.js → webhook.ts} +43 -27
  162. package/core/schemas/agents.ts +27 -0
  163. package/core/schemas/analysis.ts +41 -0
  164. package/core/schemas/ideas.ts +83 -0
  165. package/core/schemas/index.ts +73 -0
  166. package/core/schemas/outcomes.ts +22 -0
  167. package/core/schemas/project.ts +26 -0
  168. package/core/schemas/roadmap.ts +90 -0
  169. package/core/schemas/shipped.ts +82 -0
  170. package/core/schemas/state.ts +107 -0
  171. package/core/session/index.ts +17 -0
  172. package/core/session/{metrics.js → metrics.ts} +64 -46
  173. package/core/session/{index.js → session-manager.ts} +51 -117
  174. package/core/session/types.ts +29 -0
  175. package/core/session/utils.ts +57 -0
  176. package/core/state/index.ts +25 -0
  177. package/core/state/manager.ts +376 -0
  178. package/core/state/types.ts +185 -0
  179. package/core/tsconfig.json +22 -0
  180. package/core/types/index.ts +506 -0
  181. package/core/utils/{animations.js → animations.ts} +74 -28
  182. package/core/utils/{branding.js → branding.ts} +29 -4
  183. package/core/utils/{date-helper.js → date-helper.ts} +31 -74
  184. package/core/utils/file-helper.ts +262 -0
  185. package/core/utils/{jsonl-helper.js → jsonl-helper.ts} +71 -107
  186. package/core/utils/{logger.js → logger.ts} +24 -12
  187. package/core/utils/{output.js → output.ts} +25 -13
  188. package/core/utils/{project-capabilities.js → project-capabilities.ts} +31 -18
  189. package/core/utils/{session-helper.js → session-helper.ts} +79 -66
  190. package/core/utils/{version.js → version.ts} +23 -31
  191. package/core/view-generator.ts +536 -0
  192. package/package.json +23 -17
  193. package/packages/shared/.turbo/turbo-build.log +14 -0
  194. package/packages/shared/dist/index.d.ts +8 -613
  195. package/packages/shared/dist/index.d.ts.map +1 -0
  196. package/packages/shared/dist/index.js +4110 -118
  197. package/packages/shared/dist/schemas.d.ts +408 -0
  198. package/packages/shared/dist/schemas.d.ts.map +1 -0
  199. package/packages/shared/dist/types.d.ts +144 -0
  200. package/packages/shared/dist/types.d.ts.map +1 -0
  201. package/packages/shared/dist/unified.d.ts +139 -0
  202. package/packages/shared/dist/unified.d.ts.map +1 -0
  203. package/packages/shared/dist/utils.d.ts +60 -0
  204. package/packages/shared/dist/utils.d.ts.map +1 -0
  205. package/packages/shared/package.json +4 -4
  206. package/packages/shared/src/index.ts +1 -0
  207. package/packages/shared/src/unified.ts +174 -0
  208. package/packages/web/app/api/claude/sessions/route.ts +1 -1
  209. package/packages/web/app/api/claude/status/route.ts +1 -1
  210. package/packages/web/app/api/migrate/route.ts +46 -0
  211. package/packages/web/app/api/projects/[id]/route.ts +1 -1
  212. package/packages/web/app/api/projects/[id]/stats/route.ts +30 -2
  213. package/packages/web/app/api/projects/[id]/status/route.ts +1 -1
  214. package/packages/web/app/api/projects/route.ts +1 -1
  215. package/packages/web/app/api/settings/route.ts +97 -0
  216. package/packages/web/app/api/v2/projects/[id]/unified/route.ts +57 -0
  217. package/packages/web/app/globals.css +38 -0
  218. package/packages/web/app/layout.tsx +10 -2
  219. package/packages/web/app/page.tsx +9 -224
  220. package/packages/web/app/project/[id]/page.tsx +191 -63
  221. package/packages/web/app/project/[id]/stats/loading.tsx +43 -0
  222. package/packages/web/app/project/[id]/stats/page.tsx +203 -403
  223. package/packages/web/app/settings/page.tsx +222 -2
  224. package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +2 -0
  225. package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +50 -0
  226. package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +8 -0
  227. package/packages/web/components/ActivityTimeline/hooks/index.ts +2 -0
  228. package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +9 -0
  229. package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +23 -0
  230. package/packages/web/components/ActivityTimeline/index.ts +2 -0
  231. package/packages/web/components/AgentsCard/AgentsCard.tsx +63 -0
  232. package/packages/web/components/AgentsCard/AgentsCard.types.ts +13 -0
  233. package/packages/web/components/AgentsCard/index.ts +2 -0
  234. package/packages/web/components/AppSidebar/AppSidebar.tsx +134 -0
  235. package/packages/web/components/AppSidebar/index.ts +1 -0
  236. package/packages/web/components/BackLink/BackLink.tsx +18 -0
  237. package/packages/web/components/BackLink/BackLink.types.ts +5 -0
  238. package/packages/web/components/BackLink/index.ts +2 -0
  239. package/packages/web/components/BentoCard/BentoCard.constants.ts +16 -0
  240. package/packages/web/components/BentoCard/BentoCard.tsx +47 -0
  241. package/packages/web/components/BentoCard/BentoCard.types.ts +15 -0
  242. package/packages/web/components/BentoCard/index.ts +2 -0
  243. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +9 -0
  244. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +18 -0
  245. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +5 -0
  246. package/packages/web/components/BentoCardSkeleton/index.ts +2 -0
  247. package/packages/web/components/BentoGrid/BentoGrid.tsx +18 -0
  248. package/packages/web/components/BentoGrid/BentoGrid.types.ts +4 -0
  249. package/packages/web/components/BentoGrid/index.ts +2 -0
  250. package/packages/web/components/CommandButton/index.ts +1 -0
  251. package/packages/web/components/ConnectionStatus/index.ts +1 -0
  252. package/packages/web/components/DashboardContent/DashboardContent.tsx +254 -0
  253. package/packages/web/components/DashboardContent/index.ts +1 -0
  254. package/packages/web/components/DateGroup/DateGroup.tsx +18 -0
  255. package/packages/web/components/DateGroup/DateGroup.types.ts +6 -0
  256. package/packages/web/components/DateGroup/DateGroup.utils.ts +11 -0
  257. package/packages/web/components/DateGroup/index.ts +2 -0
  258. package/packages/web/components/EmptyState/EmptyState.tsx +58 -0
  259. package/packages/web/components/EmptyState/EmptyState.types.ts +10 -0
  260. package/packages/web/components/EmptyState/index.ts +2 -0
  261. package/packages/web/components/EventRow/EventRow.constants.ts +10 -0
  262. package/packages/web/components/EventRow/EventRow.tsx +49 -0
  263. package/packages/web/components/EventRow/EventRow.types.ts +7 -0
  264. package/packages/web/components/EventRow/EventRow.utils.ts +49 -0
  265. package/packages/web/components/EventRow/index.ts +2 -0
  266. package/packages/web/components/ExpandButton/ExpandButton.tsx +18 -0
  267. package/packages/web/components/ExpandButton/ExpandButton.types.ts +6 -0
  268. package/packages/web/components/ExpandButton/index.ts +2 -0
  269. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +14 -0
  270. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +5 -0
  271. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +13 -0
  272. package/packages/web/components/HealthGradientBackground/index.ts +2 -0
  273. package/packages/web/components/HeroSection/HeroSection.tsx +55 -0
  274. package/packages/web/components/HeroSection/HeroSection.types.ts +14 -0
  275. package/packages/web/components/HeroSection/HeroSection.utils.ts +7 -0
  276. package/packages/web/components/HeroSection/hooks/index.ts +2 -0
  277. package/packages/web/components/HeroSection/hooks/useCountUp.ts +45 -0
  278. package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +18 -0
  279. package/packages/web/components/HeroSection/index.ts +2 -0
  280. package/packages/web/components/IdeasCard/IdeasCard.tsx +48 -0
  281. package/packages/web/components/IdeasCard/IdeasCard.types.ts +9 -0
  282. package/packages/web/components/IdeasCard/index.ts +2 -0
  283. package/packages/web/components/InsightMessage/InsightMessage.tsx +9 -0
  284. package/packages/web/components/InsightMessage/InsightMessage.types.ts +3 -0
  285. package/packages/web/components/InsightMessage/index.ts +2 -0
  286. package/packages/web/components/Logo/index.ts +1 -0
  287. package/packages/web/components/MarkdownContent/index.ts +1 -0
  288. package/packages/web/components/NowCard/NowCard.tsx +93 -0
  289. package/packages/web/components/NowCard/NowCard.types.ts +15 -0
  290. package/packages/web/components/NowCard/index.ts +2 -0
  291. package/packages/web/components/ProgressRing/ProgressRing.constants.ts +20 -0
  292. package/packages/web/components/ProgressRing/ProgressRing.tsx +51 -0
  293. package/packages/web/components/ProgressRing/ProgressRing.types.ts +11 -0
  294. package/packages/web/components/ProgressRing/index.ts +2 -0
  295. package/packages/web/components/ProjectAvatar/index.ts +1 -0
  296. package/packages/web/components/Providers/index.ts +1 -0
  297. package/packages/web/components/QueueCard/QueueCard.tsx +72 -0
  298. package/packages/web/components/QueueCard/QueueCard.types.ts +11 -0
  299. package/packages/web/components/QueueCard/QueueCard.utils.ts +12 -0
  300. package/packages/web/components/QueueCard/index.ts +2 -0
  301. package/packages/web/components/RoadmapCard/RoadmapCard.tsx +77 -0
  302. package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +15 -0
  303. package/packages/web/components/RoadmapCard/index.ts +2 -0
  304. package/packages/web/components/ShipsCard/ShipsCard.tsx +52 -0
  305. package/packages/web/components/ShipsCard/ShipsCard.types.ts +12 -0
  306. package/packages/web/components/ShipsCard/ShipsCard.utils.ts +4 -0
  307. package/packages/web/components/ShipsCard/index.ts +2 -0
  308. package/packages/web/components/SparklineChart/SparklineChart.tsx +38 -0
  309. package/packages/web/components/SparklineChart/SparklineChart.types.ts +6 -0
  310. package/packages/web/components/SparklineChart/index.ts +2 -0
  311. package/packages/web/components/StreakCard/StreakCard.constants.ts +2 -0
  312. package/packages/web/components/StreakCard/StreakCard.tsx +53 -0
  313. package/packages/web/components/StreakCard/StreakCard.types.ts +4 -0
  314. package/packages/web/components/StreakCard/index.ts +2 -0
  315. package/packages/web/components/TasksCounter/TasksCounter.tsx +14 -0
  316. package/packages/web/components/TasksCounter/TasksCounter.types.ts +3 -0
  317. package/packages/web/components/TasksCounter/index.ts +2 -0
  318. package/packages/web/components/TechStackBadges/index.ts +1 -0
  319. package/packages/web/components/{TerminalTab.tsx → TerminalTabs/TerminalTab.tsx} +11 -0
  320. package/packages/web/components/{TerminalTabs.tsx → TerminalTabs/TerminalTabs.tsx} +29 -28
  321. package/packages/web/components/TerminalTabs/index.ts +1 -0
  322. package/packages/web/components/VelocityBadge/VelocityBadge.tsx +27 -0
  323. package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +3 -0
  324. package/packages/web/components/VelocityBadge/index.ts +2 -0
  325. package/packages/web/components/VelocityCard/VelocityCard.tsx +71 -0
  326. package/packages/web/components/VelocityCard/VelocityCard.types.ts +7 -0
  327. package/packages/web/components/VelocityCard/index.ts +2 -0
  328. package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +13 -0
  329. package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +3 -0
  330. package/packages/web/components/WeeklySparkline/index.ts +2 -0
  331. package/packages/web/components/ui/input.tsx +21 -0
  332. package/packages/web/components/ui/tooltip.tsx +2 -2
  333. package/packages/web/context/TerminalTabsContext.tsx +46 -1
  334. package/packages/web/hooks/useClaudeTerminal.ts +71 -21
  335. package/packages/web/hooks/useProjectStats.ts +55 -0
  336. package/packages/web/hooks/useProjects.ts +6 -6
  337. package/packages/web/lib/actions/projects.ts +15 -0
  338. package/packages/web/lib/json-loader.ts +630 -0
  339. package/packages/web/lib/services/index.ts +9 -0
  340. package/packages/web/lib/services/migration.server.ts +598 -0
  341. package/packages/web/lib/services/projects.server.ts +52 -0
  342. package/packages/web/lib/services/stats.server.ts +264 -0
  343. package/packages/web/lib/unified-loader.ts +396 -0
  344. package/packages/web/next-env.d.ts +1 -1
  345. package/packages/web/package.json +10 -6
  346. package/packages/web/server.ts +36 -6
  347. package/templates/commands/done.md +76 -32
  348. package/templates/commands/feature.md +121 -47
  349. package/templates/commands/idea.md +81 -8
  350. package/templates/commands/now.md +41 -17
  351. package/templates/commands/ship.md +64 -25
  352. package/templates/commands/sync.md +28 -3
  353. package/core/agentic/agent-router.js +0 -128
  354. package/core/agentic/chain-of-thought.js +0 -578
  355. package/core/agentic/command-executor.js +0 -421
  356. package/core/agentic/context-filter.js +0 -354
  357. package/core/agentic/ground-truth.js +0 -591
  358. package/core/agentic/loop-detector.js +0 -406
  359. package/core/agentic/memory-system.js +0 -850
  360. package/core/agentic/parallel-tools.js +0 -366
  361. package/core/agentic/plan-mode.js +0 -572
  362. package/core/agentic/prompt-builder.js +0 -338
  363. package/core/agentic/response-templates.js +0 -290
  364. package/core/agentic/semantic-compression.js +0 -517
  365. package/core/agentic/think-blocks.js +0 -657
  366. package/core/agentic/tool-registry.js +0 -184
  367. package/core/agentic/validation-rules.js +0 -380
  368. package/core/command-registry.js +0 -698
  369. package/core/commands.js +0 -2237
  370. package/core/domain/task-stack.js +0 -497
  371. package/core/infrastructure/legacy-installer-detector.js +0 -546
  372. package/core/infrastructure/migrator.js +0 -799
  373. package/core/infrastructure/session-manager.js +0 -390
  374. package/core/utils/file-helper.js +0 -329
  375. package/packages/web/app/api/projects/[id]/delete/route.ts +0 -21
  376. package/packages/web/app/api/stats/route.ts +0 -38
  377. package/packages/web/components/AppSidebar.tsx +0 -113
  378. package/packages/web/hooks/useStats.ts +0 -28
  379. /package/packages/web/components/{CommandButton.tsx → CommandButton/CommandButton.tsx} +0 -0
  380. /package/packages/web/components/{ConnectionStatus.tsx → ConnectionStatus/ConnectionStatus.tsx} +0 -0
  381. /package/packages/web/components/{Logo.tsx → Logo/Logo.tsx} +0 -0
  382. /package/packages/web/components/{MarkdownContent.tsx → MarkdownContent/MarkdownContent.tsx} +0 -0
  383. /package/packages/web/components/{ProjectAvatar.tsx → ProjectAvatar/ProjectAvatar.tsx} +0 -0
  384. /package/packages/web/components/{providers.tsx → Providers/Providers.tsx} +0 -0
  385. /package/packages/web/components/{TechStackBadges.tsx → TechStackBadges/TechStackBadges.tsx} +0 -0
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Stats Service (Server-only)
3
+ *
4
+ * Direct data access for Server Components.
5
+ * No API calls needed - reads directly from filesystem.
6
+ */
7
+
8
+ import 'server-only'
9
+ import { cache } from 'react'
10
+ import { exec } from 'child_process'
11
+ import { promisify } from 'util'
12
+ import {
13
+ loadUnifiedJsonData,
14
+ hasJsonState,
15
+ type UnifiedJsonData,
16
+ type StateJson,
17
+ type QueueJson,
18
+ type MetricsJson,
19
+ type ProjectInsights,
20
+ } from '@/lib/json-loader'
21
+ import { getProjectStats as getLegacyStats, type ProjectStats } from '@/lib/parse-prjct-files'
22
+ import { getProjects } from './projects.server'
23
+
24
+ export type { UnifiedJsonData, StateJson, QueueJson, MetricsJson, ProjectInsights }
25
+
26
+ // Activity type for recent activity tracking
27
+ export interface RecentActivity {
28
+ timestamp: string
29
+ type: string
30
+ description?: string
31
+ duration?: string
32
+ }
33
+
34
+ const execAsync = promisify(exec)
35
+
36
+ /**
37
+ * Global stats for dashboard (userName, totalProjects)
38
+ */
39
+ export interface GlobalStats {
40
+ userName: string
41
+ totalProjects: number
42
+ }
43
+
44
+ async function getGitUserName(): Promise<string> {
45
+ try {
46
+ const { stdout } = await execAsync('git config user.name')
47
+ return stdout.trim() || 'Developer'
48
+ } catch {
49
+ return 'Developer'
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Get global stats for dashboard - cached per request
55
+ */
56
+ export const getGlobalStats = cache(async (): Promise<GlobalStats> => {
57
+ const [projects, userName] = await Promise.all([
58
+ getProjects(),
59
+ getGitUserName()
60
+ ])
61
+
62
+ return {
63
+ userName,
64
+ totalProjects: projects.length
65
+ }
66
+ })
67
+
68
+ /**
69
+ * Unified stats result that works with both JSON and legacy formats
70
+ */
71
+ export interface StatsResult {
72
+ state: StateJson | null
73
+ queue: QueueJson | null
74
+ metrics: MetricsJson | null
75
+ insights: ProjectInsights
76
+ agents: UnifiedJsonData['agents']
77
+ ideas: UnifiedJsonData['ideas']
78
+ roadmap: UnifiedJsonData['roadmap']
79
+ shipped: UnifiedJsonData['shipped']
80
+ outcomes: UnifiedJsonData['outcomes']
81
+ hasData: boolean
82
+ isLegacy: boolean
83
+ legacyStats?: ProjectStats
84
+ }
85
+
86
+ const DEFAULT_INSIGHTS: ProjectInsights = {
87
+ healthScore: 0,
88
+ estimateAccuracy: 0,
89
+ topBlockers: [],
90
+ patternsDetected: [],
91
+ recommendations: ['Run /p:sync to initialize project']
92
+ }
93
+
94
+ const EMPTY_STATS_RESULT: StatsResult = {
95
+ state: null,
96
+ queue: null,
97
+ metrics: null,
98
+ insights: DEFAULT_INSIGHTS,
99
+ agents: [],
100
+ ideas: null,
101
+ roadmap: null,
102
+ shipped: null,
103
+ outcomes: [],
104
+ hasData: false,
105
+ isLegacy: false
106
+ }
107
+
108
+ /**
109
+ * Get project stats - cached per request
110
+ */
111
+ export const getStats = cache(async (projectId: string): Promise<StatsResult> => {
112
+ const hasJson = await hasJsonState(projectId)
113
+
114
+ if (hasJson) {
115
+ const jsonData = await loadUnifiedJsonData(projectId)
116
+ return {
117
+ state: jsonData.state,
118
+ queue: jsonData.queue,
119
+ metrics: jsonData.metrics,
120
+ insights: jsonData.insights,
121
+ agents: jsonData.agents,
122
+ ideas: jsonData.ideas,
123
+ roadmap: jsonData.roadmap,
124
+ shipped: jsonData.shipped,
125
+ outcomes: jsonData.outcomes,
126
+ hasData: jsonData.hasJsonData,
127
+ isLegacy: false
128
+ }
129
+ }
130
+
131
+ // Fallback to legacy markdown parsing
132
+ try {
133
+ const legacyStats = await getLegacyStats(projectId)
134
+ return {
135
+ ...EMPTY_STATS_RESULT,
136
+ insights: {
137
+ ...DEFAULT_INSIGHTS,
138
+ healthScore: 50,
139
+ recommendations: ['Run /p:sync to enable JSON format']
140
+ },
141
+ hasData: true,
142
+ isLegacy: true,
143
+ legacyStats
144
+ }
145
+ } catch {
146
+ return EMPTY_STATS_RESULT
147
+ }
148
+ })
149
+
150
+ /**
151
+ * Calculate streak from metrics (pure function, no mutation)
152
+ */
153
+ export function calculateStreak(metrics: MetricsJson | null): number {
154
+ if (!metrics?.recentActivity?.length) return 0
155
+
156
+ const activityDates = new Set(
157
+ metrics.recentActivity.map((a: { timestamp: string }) => new Date(a.timestamp).toISOString().split('T')[0])
158
+ )
159
+
160
+ const today = new Date()
161
+ today.setHours(0, 0, 0, 0)
162
+
163
+ // Generate last 30 days as array
164
+ const days = Array.from({ length: 30 }, (_, i) => {
165
+ const date = new Date(today)
166
+ date.setDate(date.getDate() - i)
167
+ return date.toISOString().split('T')[0]
168
+ })
169
+
170
+ // Find first gap (day without activity)
171
+ const firstGapIndex = days.findIndex(date => !activityDates.has(date))
172
+
173
+ // If today has no activity, check if yesterday does
174
+ if (firstGapIndex === 0) {
175
+ const yesterdayHasActivity = activityDates.has(days[1])
176
+ if (!yesterdayHasActivity) return 0
177
+ // Start counting from yesterday
178
+ const remainingDays = days.slice(1)
179
+ const gapFromYesterday = remainingDays.findIndex(date => !activityDates.has(date))
180
+ return gapFromYesterday === -1 ? remainingDays.length : gapFromYesterday
181
+ }
182
+
183
+ return firstGapIndex === -1 ? days.length : firstGapIndex
184
+ }
185
+
186
+ /**
187
+ * Get health emoji based on score
188
+ */
189
+ export function getHealthEmoji(score: number): string {
190
+ if (score >= 80) return '🔥'
191
+ if (score >= 60) return '💪'
192
+ if (score >= 40) return '👍'
193
+ if (score >= 20) return '🌱'
194
+ return '💤'
195
+ }
196
+
197
+ /**
198
+ * Get insight message based on stats
199
+ */
200
+ export function getInsightMessage(stats: StatsResult, streak: number): string {
201
+ if (!stats.hasData) return 'Run /p:sync to get started'
202
+ if (stats.state?.currentTask) return `Working on: ${stats.state.currentTask.description}`
203
+ if (streak >= 7) return `${streak} day streak! You're on fire! 🔥`
204
+ if (streak >= 3) return `${streak} day streak - keep it going!`
205
+
206
+ const queueLength = stats.queue?.tasks?.filter(t => !t.completed).length ?? 0
207
+ if (queueLength > 0) return `${queueLength} tasks in queue`
208
+ return 'Ready to start working'
209
+ }
210
+
211
+ /**
212
+ * Calculate velocity change percentage
213
+ */
214
+ export function getVelocityChange(velocity: number): number {
215
+ if (velocity > 2) return 15
216
+ if (velocity > 1) return 5
217
+ if (velocity > 0) return 0
218
+ return -10
219
+ }
220
+
221
+ /**
222
+ * Get weekly velocity data from metrics (last 7 days)
223
+ */
224
+ export function getWeeklyVelocityData(metrics: MetricsJson | null): number[] {
225
+ if (!metrics?.recentActivity?.length) return []
226
+
227
+ const today = new Date()
228
+
229
+ return Array.from({ length: 7 }, (_, i) => {
230
+ const date = new Date(today)
231
+ date.setDate(date.getDate() - (6 - i))
232
+ const dateStr = date.toISOString().split('T')[0]
233
+
234
+ return metrics.recentActivity.filter((e: { timestamp: string }) =>
235
+ e.timestamp?.startsWith(dateStr)
236
+ ).length
237
+ })
238
+ }
239
+
240
+ /**
241
+ * Calculate health score from stats
242
+ */
243
+ export function calculateHealthScore(stats: StatsResult): number {
244
+ if (!stats.hasData) return 0
245
+ if (stats.insights.healthScore > 0) return stats.insights.healthScore
246
+
247
+ // Fallback for legacy
248
+ if (stats.isLegacy && stats.legacyStats) {
249
+ const { metrics, currentTask, queue, timeline } = stats.legacyStats
250
+ const velocity = metrics?.velocity?.tasksPerDay ?? 0
251
+ const hasCurrentTask = Boolean(currentTask)
252
+ const queueSize = queue?.length ?? 0
253
+ const recentActivity = timeline?.slice(0, 7).length ?? 0
254
+
255
+ const velocityScore = Math.min(30, velocity * 15)
256
+ const taskScore = hasCurrentTask ? 20 : 0
257
+ const queueScore = queueSize > 0 && queueSize < 15 ? 20 : queueSize === 0 ? 5 : 10
258
+ const activityScore = Math.min(30, recentActivity * 5)
259
+
260
+ return Math.min(100, Math.round(velocityScore + taskScore + queueScore + activityScore))
261
+ }
262
+
263
+ return 50
264
+ }
@@ -0,0 +1,396 @@
1
+ /**
2
+ * Unified Loader
3
+ *
4
+ * Loads project data from the new unified state modules.
5
+ * Provides faster access than parsing markdown files.
6
+ */
7
+
8
+ import { promises as fs } from 'fs'
9
+ import { join } from 'path'
10
+ import { homedir } from 'os'
11
+
12
+ const GLOBAL_STORAGE = join(homedir(), '.prjct-cli', 'projects')
13
+
14
+ /**
15
+ * Project state from state.json
16
+ */
17
+ export interface ProjectState {
18
+ projectId: string
19
+ currentTask: CurrentTask | null
20
+ queue: QueuedTask[]
21
+ activeFeature: ActiveFeature | null
22
+ stats: PerformanceStats
23
+ recentActivity: RecentActivity[]
24
+ lastSync: string
25
+ version: number
26
+ }
27
+
28
+ export interface CurrentTask {
29
+ id: string
30
+ description: string
31
+ startedAt: string
32
+ agent?: string
33
+ agentConfidence?: number
34
+ estimatedDuration?: string
35
+ featureId?: string
36
+ pausedAt?: string
37
+ pauseReason?: string
38
+ }
39
+
40
+ export interface QueuedTask {
41
+ id: string
42
+ description: string
43
+ priority: 'low' | 'medium' | 'high' | 'critical'
44
+ featureId?: string
45
+ estimatedDuration?: string
46
+ tags?: string[]
47
+ createdAt: string
48
+ blockedReason?: string
49
+ }
50
+
51
+ export interface ActiveFeature {
52
+ id: string
53
+ name: string
54
+ status: 'planned' | 'in_progress' | 'completed' | 'shipped'
55
+ tasksCompleted: number
56
+ tasksRemaining: number
57
+ estimatedEffort?: string
58
+ actualEffort?: string
59
+ startedAt: string
60
+ }
61
+
62
+ export interface PerformanceStats {
63
+ tasksToday: number
64
+ tasksThisWeek: number
65
+ avgDuration: string
66
+ velocity: string
67
+ estimateAccuracy: number
68
+ streak: number
69
+ }
70
+
71
+ export interface RecentActivity {
72
+ type: 'task_completed' | 'feature_shipped' | 'idea_captured' | 'session_started'
73
+ description: string
74
+ timestamp: string
75
+ duration?: string
76
+ }
77
+
78
+ /**
79
+ * Outcome summary from analyzer
80
+ */
81
+ export interface OutcomeSummary {
82
+ totalOutcomes: number
83
+ avgQualityScore: number
84
+ estimateAccuracy: number
85
+ topBlockers: string[]
86
+ topAgents: string[]
87
+ patternsDetected: string[]
88
+ }
89
+
90
+ /**
91
+ * Agent performance data
92
+ */
93
+ export interface AgentPerformance {
94
+ agentName: string
95
+ taskType: string
96
+ tasksCompleted: number
97
+ successRate: number
98
+ avgDuration: string
99
+ estimateAccuracy: number
100
+ improving: boolean
101
+ lastUpdated: string
102
+ bestFor: string[]
103
+ avoidFor: string[]
104
+ }
105
+
106
+ /**
107
+ * Insights computed from all data
108
+ */
109
+ export interface ProjectInsights {
110
+ healthScore: number
111
+ estimateAccuracy: number
112
+ topBlockers: string[]
113
+ patternsDetected: string[]
114
+ recommendations: string[]
115
+ }
116
+
117
+ /**
118
+ * Unified response combining all data
119
+ */
120
+ export interface UnifiedProjectData {
121
+ state: ProjectState | null
122
+ outcomes: OutcomeSummary | null
123
+ agentPerformance: AgentPerformance[]
124
+ insights: ProjectInsights
125
+ // Legacy fallback data
126
+ legacyFallback: boolean
127
+ }
128
+
129
+ const DEFAULT_STATE: ProjectState = {
130
+ projectId: '',
131
+ currentTask: null,
132
+ queue: [],
133
+ activeFeature: null,
134
+ stats: {
135
+ tasksToday: 0,
136
+ tasksThisWeek: 0,
137
+ avgDuration: '0h',
138
+ velocity: '0',
139
+ estimateAccuracy: 0,
140
+ streak: 0,
141
+ },
142
+ recentActivity: [],
143
+ lastSync: new Date().toISOString(),
144
+ version: 1,
145
+ }
146
+
147
+ /**
148
+ * Read state.json for a project
149
+ */
150
+ async function readState(projectId: string): Promise<ProjectState | null> {
151
+ const statePath = join(GLOBAL_STORAGE, projectId, 'core', 'state.json')
152
+ try {
153
+ const content = await fs.readFile(statePath, 'utf-8')
154
+ return JSON.parse(content) as ProjectState
155
+ } catch {
156
+ return null
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Read outcomes summary
162
+ */
163
+ async function readOutcomes(projectId: string): Promise<OutcomeSummary | null> {
164
+ const outcomesPath = join(GLOBAL_STORAGE, projectId, 'outcomes', 'outcomes.jsonl')
165
+ try {
166
+ const content = await fs.readFile(outcomesPath, 'utf-8')
167
+ const outcomes = content
168
+ .trim()
169
+ .split('\n')
170
+ .filter(line => line.trim())
171
+ .map(line => JSON.parse(line))
172
+
173
+ if (outcomes.length === 0) return null
174
+
175
+ // Calculate summary
176
+ const avgQuality = outcomes.reduce((sum: number, o: { qualityScore: number }) =>
177
+ sum + o.qualityScore, 0) / outcomes.length
178
+
179
+ // Count accurate estimates (within 20%)
180
+ const accurateCount = outcomes.filter((o: { variance: string; estimatedDuration: string }) => {
181
+ if (!o.variance) return false
182
+ const variance = parseVariance(o.variance)
183
+ const estimated = parseDuration(o.estimatedDuration)
184
+ if (estimated === 0) return false
185
+ return Math.abs(variance) / estimated <= 0.2
186
+ }).length
187
+
188
+ // Count blockers
189
+ const blockerCounts = new Map<string, number>()
190
+ for (const outcome of outcomes) {
191
+ for (const blocker of outcome.blockers || []) {
192
+ blockerCounts.set(blocker, (blockerCounts.get(blocker) || 0) + 1)
193
+ }
194
+ }
195
+ const topBlockers = [...blockerCounts.entries()]
196
+ .sort((a, b) => b[1] - a[1])
197
+ .slice(0, 5)
198
+ .map(([blocker]) => blocker)
199
+
200
+ // Count agents
201
+ const agentCounts = new Map<string, number>()
202
+ for (const outcome of outcomes) {
203
+ if (outcome.agentUsed) {
204
+ agentCounts.set(outcome.agentUsed, (agentCounts.get(outcome.agentUsed) || 0) + 1)
205
+ }
206
+ }
207
+ const topAgents = [...agentCounts.entries()]
208
+ .sort((a, b) => b[1] - a[1])
209
+ .slice(0, 3)
210
+ .map(([agent]) => agent)
211
+
212
+ // Detect patterns
213
+ const patterns: string[] = []
214
+ const underestimated = outcomes.filter((o: { variance: string }) => {
215
+ const variance = parseVariance(o.variance)
216
+ return variance > 0
217
+ })
218
+ if (underestimated.length / outcomes.length > 0.6) {
219
+ patterns.push('Tasks consistently take longer than estimated')
220
+ }
221
+
222
+ return {
223
+ totalOutcomes: outcomes.length,
224
+ avgQualityScore: Math.round(avgQuality * 10) / 10,
225
+ estimateAccuracy: Math.round((accurateCount / outcomes.length) * 100),
226
+ topBlockers,
227
+ topAgents,
228
+ patternsDetected: patterns,
229
+ }
230
+ } catch {
231
+ return null
232
+ }
233
+ }
234
+
235
+ /**
236
+ * Read agent performance data
237
+ */
238
+ async function readAgentPerformance(projectId: string): Promise<AgentPerformance[]> {
239
+ const perfPath = join(GLOBAL_STORAGE, projectId, 'analysis', 'agent-performance.json')
240
+ try {
241
+ const content = await fs.readFile(perfPath, 'utf-8')
242
+ const data = JSON.parse(content)
243
+ return data.agents || []
244
+ } catch {
245
+ return []
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Compute insights from all data
251
+ */
252
+ function computeInsights(
253
+ state: ProjectState | null,
254
+ outcomes: OutcomeSummary | null,
255
+ agentPerformance: AgentPerformance[]
256
+ ): ProjectInsights {
257
+ let healthScore = 50 // Base score
258
+
259
+ // Adjust for state
260
+ if (state) {
261
+ // Has current task = +10
262
+ if (state.currentTask) healthScore += 10
263
+
264
+ // Velocity bonus (max +20)
265
+ const velocity = parseFloat(state.stats.velocity) || 0
266
+ healthScore += Math.min(20, velocity * 5)
267
+
268
+ // Streak bonus (max +15)
269
+ healthScore += Math.min(15, state.stats.streak * 3)
270
+
271
+ // Queue size penalty (too many = -5)
272
+ if (state.queue.length > 15) healthScore -= 5
273
+ }
274
+
275
+ // Adjust for outcomes
276
+ if (outcomes) {
277
+ // Estimate accuracy bonus (max +15)
278
+ healthScore += Math.round(outcomes.estimateAccuracy * 0.15)
279
+
280
+ // Quality score bonus (max +10)
281
+ healthScore += Math.round(outcomes.avgQualityScore * 2)
282
+
283
+ // Blockers penalty
284
+ healthScore -= outcomes.topBlockers.length * 2
285
+ }
286
+
287
+ // Adjust for agent performance
288
+ if (agentPerformance.length > 0) {
289
+ const avgSuccess = agentPerformance.reduce((sum, a) => sum + a.successRate, 0) / agentPerformance.length
290
+ healthScore += Math.round(avgSuccess * 0.1)
291
+ }
292
+
293
+ // Clamp to 0-100
294
+ healthScore = Math.max(0, Math.min(100, healthScore))
295
+
296
+ // Build recommendations
297
+ const recommendations: string[] = []
298
+
299
+ if (!state?.currentTask) {
300
+ recommendations.push('Start a task with /p:now to maintain momentum')
301
+ }
302
+
303
+ if (state && state.queue.length > 10) {
304
+ recommendations.push('Queue is large - consider prioritizing or archiving tasks')
305
+ }
306
+
307
+ if (outcomes && outcomes.estimateAccuracy < 50) {
308
+ recommendations.push('Estimate accuracy is low - try adding 30% buffer to estimates')
309
+ }
310
+
311
+ if (agentPerformance.length === 0) {
312
+ recommendations.push('No agent performance data yet - track outcomes with /p:done')
313
+ }
314
+
315
+ const improving = agentPerformance.filter(a => a.improving)
316
+ if (improving.length > 0) {
317
+ recommendations.push(`${improving.map(a => a.agentName).join(', ')} improving - great progress!`)
318
+ }
319
+
320
+ return {
321
+ healthScore,
322
+ estimateAccuracy: outcomes?.estimateAccuracy || 0,
323
+ topBlockers: outcomes?.topBlockers || [],
324
+ patternsDetected: outcomes?.patternsDetected || [],
325
+ recommendations: recommendations.slice(0, 4),
326
+ }
327
+ }
328
+
329
+ /**
330
+ * Parse variance string to minutes
331
+ */
332
+ function parseVariance(variance: string): number {
333
+ const match = variance.match(/^([+-])(\d+)([mh])$/)
334
+ if (!match) return 0
335
+
336
+ const sign = match[1] === '-' ? -1 : 1
337
+ const value = parseInt(match[2], 10)
338
+ const unit = match[3]
339
+
340
+ return sign * (unit === 'h' ? value * 60 : value)
341
+ }
342
+
343
+ /**
344
+ * Parse duration string to minutes
345
+ */
346
+ function parseDuration(duration: string): number {
347
+ let minutes = 0
348
+
349
+ const hourMatch = duration.match(/(\d+)h/)
350
+ if (hourMatch) {
351
+ minutes += parseInt(hourMatch[1], 10) * 60
352
+ }
353
+
354
+ const minMatch = duration.match(/(\d+)m/)
355
+ if (minMatch) {
356
+ minutes += parseInt(minMatch[1], 10)
357
+ }
358
+
359
+ return minutes
360
+ }
361
+
362
+ /**
363
+ * Load unified project data
364
+ */
365
+ export async function loadUnifiedProjectData(projectId: string): Promise<UnifiedProjectData> {
366
+ // Try to read from new unified state
367
+ const [state, outcomes, agentPerformance] = await Promise.all([
368
+ readState(projectId),
369
+ readOutcomes(projectId),
370
+ readAgentPerformance(projectId),
371
+ ])
372
+
373
+ // Compute insights
374
+ const insights = computeInsights(state, outcomes, agentPerformance)
375
+
376
+ return {
377
+ state,
378
+ outcomes,
379
+ agentPerformance,
380
+ insights,
381
+ legacyFallback: state === null,
382
+ }
383
+ }
384
+
385
+ /**
386
+ * Check if unified state exists for a project
387
+ */
388
+ export async function hasUnifiedState(projectId: string): Promise<boolean> {
389
+ const statePath = join(GLOBAL_STORAGE, projectId, 'core', 'state.json')
390
+ try {
391
+ await fs.access(statePath)
392
+ return true
393
+ } catch {
394
+ return false
395
+ }
396
+ }
@@ -1,6 +1,6 @@
1
1
  /// <reference types="next" />
2
2
  /// <reference types="next/image-types/global" />
3
- import "./.next/dev/types/routes.d.ts";
3
+ import "./.next/types/routes.d.ts";
4
4
 
5
5
  // NOTE: This file should not be edited
6
6
  // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -3,13 +3,15 @@
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
5
  "scripts": {
6
- "dev": "tsx server.ts",
7
- "dev:next": "next dev",
8
- "build": "next build",
9
- "start": "node server.js",
6
+ "dev": "NODE_ENV=development PORT=9471 bun server.ts",
7
+ "dev:next": "bun next dev",
8
+ "build": "bun next build",
9
+ "start": "NODE_ENV=production PORT=9472 bun server.ts",
10
+ "start:prod": "NODE_ENV=production PORT=9472 bun server.ts",
10
11
  "lint": "eslint"
11
12
  },
12
13
  "dependencies": {
14
+ "@ai-sdk/openai": "^2.0.80",
13
15
  "@radix-ui/react-alert-dialog": "^1.1.15",
14
16
  "@radix-ui/react-dialog": "^1.1.15",
15
17
  "@radix-ui/react-dropdown-menu": "^2.1.16",
@@ -22,6 +24,7 @@
22
24
  "@xterm/addon-fit": "^0.10.0",
23
25
  "@xterm/addon-web-links": "^0.11.0",
24
26
  "@xterm/xterm": "^5.5.0",
27
+ "ai": "^5.0.108",
25
28
  "class-variance-authority": "^0.7.1",
26
29
  "clsx": "^2.1.1",
27
30
  "lucide-react": "^0.556.0",
@@ -35,10 +38,12 @@
35
38
  "recharts": "^3.5.1",
36
39
  "remark-gfm": "^4.0.1",
37
40
  "tailwind-merge": "^3.4.0",
38
- "ws": "^8.18.3"
41
+ "ws": "^8.18.3",
42
+ "zod": "^4.1.13"
39
43
  },
40
44
  "devDependencies": {
41
45
  "@tailwindcss/postcss": "^4",
46
+ "@types/bun": "latest",
42
47
  "@types/node": "^20",
43
48
  "@types/react": "^19",
44
49
  "@types/react-dom": "^19",
@@ -46,7 +51,6 @@
46
51
  "eslint": "^9",
47
52
  "eslint-config-next": "16.0.7",
48
53
  "tailwindcss": "^4",
49
- "tsx": "^4.19.2",
50
54
  "tw-animate-css": "^1.4.0",
51
55
  "typescript": "^5"
52
56
  }