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,81 @@
1
+ /**
2
+ * Ideas Manager
3
+ *
4
+ * Manages ideas.json - idea backlog.
5
+ */
6
+
7
+ import { ArrayManager } from './base-manager'
8
+ import type { IdeaSchema, IdeasSchema, IdeaPriority } from '../schemas'
9
+ import { DEFAULT_IDEA } from '../schemas'
10
+
11
+ class IdeasManager extends ArrayManager<IdeaSchema> {
12
+ constructor() {
13
+ super('ideas.json')
14
+ }
15
+
16
+ async getIdeas(projectId: string): Promise<IdeasSchema> {
17
+ return this.read(projectId)
18
+ }
19
+
20
+ async getPendingIdeas(projectId: string): Promise<IdeasSchema> {
21
+ const ideas = await this.read(projectId)
22
+ return ideas.filter((idea) => idea.status === 'pending')
23
+ }
24
+
25
+ async getIdea(projectId: string, id: string): Promise<IdeaSchema | undefined> {
26
+ return this.find(projectId, (idea) => idea.id === id)
27
+ }
28
+
29
+ async addIdea(
30
+ projectId: string,
31
+ content: string,
32
+ options?: Partial<Omit<IdeaSchema, 'id' | 'content' | 'createdAt'>>
33
+ ): Promise<IdeasSchema> {
34
+ const idea: IdeaSchema = {
35
+ ...DEFAULT_IDEA,
36
+ ...options,
37
+ id: `idea_${Date.now()}`,
38
+ content,
39
+ createdAt: new Date().toISOString()
40
+ }
41
+ return this.add(projectId, idea)
42
+ }
43
+
44
+ async updateIdea(
45
+ projectId: string,
46
+ id: string,
47
+ updates: Partial<Omit<IdeaSchema, 'id' | 'createdAt'>>
48
+ ): Promise<IdeasSchema> {
49
+ return this.updateItem(
50
+ projectId,
51
+ (idea) => idea.id === id,
52
+ (idea) => ({ ...idea, ...updates })
53
+ )
54
+ }
55
+
56
+ async archiveIdea(projectId: string, id: string): Promise<IdeasSchema> {
57
+ return this.updateIdea(projectId, id, {
58
+ status: 'archived',
59
+ archivedAt: new Date().toISOString()
60
+ })
61
+ }
62
+
63
+ async convertToFeature(projectId: string, id: string): Promise<IdeasSchema> {
64
+ return this.updateIdea(projectId, id, { status: 'converted' })
65
+ }
66
+
67
+ async setPriority(
68
+ projectId: string,
69
+ id: string,
70
+ priority: IdeaPriority
71
+ ): Promise<IdeasSchema> {
72
+ return this.updateIdea(projectId, id, { priority })
73
+ }
74
+
75
+ async removeIdea(projectId: string, id: string): Promise<IdeasSchema> {
76
+ return this.remove(projectId, (idea) => idea.id === id)
77
+ }
78
+ }
79
+
80
+ export const ideasManager = new IdeasManager()
81
+ export default ideasManager
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Data Module
3
+ *
4
+ * JSON file managers for all project data types.
5
+ */
6
+
7
+ // Base
8
+ export { BaseManager, ArrayManager } from './base-manager'
9
+
10
+ // Managers
11
+ export { stateManager, default as stateManagerDefault } from './state-manager'
12
+ export { projectManager, default as projectManagerDefault } from './project-manager'
13
+ export { agentsManager, default as agentsManagerDefault } from './agents-manager'
14
+ export { ideasManager, default as ideasManagerDefault } from './ideas-manager'
15
+ export { roadmapManager, default as roadmapManagerDefault } from './roadmap-manager'
16
+ export { shippedManager, default as shippedManagerDefault } from './shipped-manager'
17
+ export { analysisManager, default as analysisManagerDefault } from './analysis-manager'
18
+ export { outcomesManager, default as outcomesManagerDefault } from './outcomes-manager'
19
+
20
+ // Convenience object with all managers
21
+ export const dataManagers = {
22
+ state: require('./state-manager').stateManager,
23
+ project: require('./project-manager').projectManager,
24
+ agents: require('./agents-manager').agentsManager,
25
+ ideas: require('./ideas-manager').ideasManager,
26
+ roadmap: require('./roadmap-manager').roadmapManager,
27
+ shipped: require('./shipped-manager').shippedManager,
28
+ analysis: require('./analysis-manager').analysisManager,
29
+ outcomes: require('./outcomes-manager').outcomesManager
30
+ }
31
+
32
+ export default dataManagers
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Outcomes Manager
3
+ *
4
+ * Manages outcomes.json - task completion metrics and history.
5
+ */
6
+
7
+ import { ArrayManager } from './base-manager'
8
+ import type { OutcomeSchema, OutcomesSchema, QualityScore } from '../schemas'
9
+
10
+ class OutcomesManager extends ArrayManager<OutcomeSchema> {
11
+ constructor() {
12
+ super('outcomes.json')
13
+ }
14
+
15
+ async getOutcomes(projectId: string): Promise<OutcomesSchema> {
16
+ return this.read(projectId)
17
+ }
18
+
19
+ async getRecentOutcomes(projectId: string, limit = 20): Promise<OutcomesSchema> {
20
+ const outcomes = await this.read(projectId)
21
+ return outcomes
22
+ .sort((a, b) => new Date(b.completedAt).getTime() - new Date(a.completedAt).getTime())
23
+ .slice(0, limit)
24
+ }
25
+
26
+ async addOutcome(
27
+ projectId: string,
28
+ outcome: Omit<OutcomeSchema, 'id' | 'completedAt'>
29
+ ): Promise<OutcomesSchema> {
30
+ const fullOutcome: OutcomeSchema = {
31
+ ...outcome,
32
+ id: `outcome_${Date.now()}`,
33
+ completedAt: new Date().toISOString()
34
+ }
35
+ return this.add(projectId, fullOutcome)
36
+ }
37
+
38
+ async getByAgent(projectId: string, agentName: string): Promise<OutcomesSchema> {
39
+ const outcomes = await this.read(projectId)
40
+ return outcomes.filter((o) => o.agentUsed === agentName)
41
+ }
42
+
43
+ async getAverageQuality(projectId: string): Promise<number> {
44
+ const outcomes = await this.read(projectId)
45
+ if (outcomes.length === 0) return 0
46
+ const sum = outcomes.reduce((acc, o) => acc + o.qualityScore, 0)
47
+ return Math.round((sum / outcomes.length) * 10) / 10
48
+ }
49
+
50
+ async getCompletionRate(projectId: string): Promise<number> {
51
+ const outcomes = await this.read(projectId)
52
+ if (outcomes.length === 0) return 0
53
+ const completed = outcomes.filter((o) => o.completedAsPlanned).length
54
+ return Math.round((completed / outcomes.length) * 100)
55
+ }
56
+
57
+ async getTopBlockers(projectId: string, limit = 5): Promise<string[]> {
58
+ const outcomes = await this.read(projectId)
59
+ const blockerCounts = new Map<string, number>()
60
+
61
+ for (const outcome of outcomes) {
62
+ for (const blocker of outcome.blockers) {
63
+ blockerCounts.set(blocker, (blockerCounts.get(blocker) || 0) + 1)
64
+ }
65
+ }
66
+
67
+ return Array.from(blockerCounts.entries())
68
+ .sort((a, b) => b[1] - a[1])
69
+ .slice(0, limit)
70
+ .map(([blocker]) => blocker)
71
+ }
72
+
73
+ async getAgentStats(
74
+ projectId: string,
75
+ agentName: string
76
+ ): Promise<{ count: number; avgQuality: number; successRate: number }> {
77
+ const agentOutcomes = await this.getByAgent(projectId, agentName)
78
+ if (agentOutcomes.length === 0) {
79
+ return { count: 0, avgQuality: 0, successRate: 0 }
80
+ }
81
+
82
+ const avgQuality =
83
+ agentOutcomes.reduce((acc, o) => acc + o.qualityScore, 0) / agentOutcomes.length
84
+ const successRate =
85
+ (agentOutcomes.filter((o) => o.completedAsPlanned).length / agentOutcomes.length) * 100
86
+
87
+ return {
88
+ count: agentOutcomes.length,
89
+ avgQuality: Math.round(avgQuality * 10) / 10,
90
+ successRate: Math.round(successRate)
91
+ }
92
+ }
93
+ }
94
+
95
+ export const outcomesManager = new OutcomesManager()
96
+ export default outcomesManager
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Project Manager
3
+ *
4
+ * Manages project.json - project metadata.
5
+ */
6
+
7
+ import { BaseManager } from './base-manager'
8
+ import type { ProjectSchema } from '../schemas'
9
+ import { DEFAULT_PROJECT } from '../schemas'
10
+
11
+ class ProjectManager extends BaseManager<ProjectSchema> {
12
+ constructor() {
13
+ super('project.json')
14
+ }
15
+
16
+ protected getDefault(projectId: string): ProjectSchema {
17
+ return {
18
+ ...DEFAULT_PROJECT,
19
+ projectId,
20
+ name: '',
21
+ repoPath: '',
22
+ createdAt: new Date().toISOString(),
23
+ lastSync: new Date().toISOString()
24
+ }
25
+ }
26
+
27
+ async getProject(projectId: string): Promise<ProjectSchema> {
28
+ return this.read(projectId)
29
+ }
30
+
31
+ async updateProject(
32
+ projectId: string,
33
+ updates: Partial<Omit<ProjectSchema, 'projectId'>>
34
+ ): Promise<ProjectSchema> {
35
+ return this.update(projectId, (project) => ({
36
+ ...project,
37
+ ...updates,
38
+ lastSync: new Date().toISOString()
39
+ }))
40
+ }
41
+
42
+ async setTechStack(projectId: string, techStack: string[]): Promise<ProjectSchema> {
43
+ return this.updateProject(projectId, { techStack })
44
+ }
45
+
46
+ async setFileCount(projectId: string, fileCount: number): Promise<ProjectSchema> {
47
+ return this.updateProject(projectId, { fileCount })
48
+ }
49
+
50
+ async setCommitCount(projectId: string, commitCount: number): Promise<ProjectSchema> {
51
+ return this.updateProject(projectId, { commitCount })
52
+ }
53
+
54
+ async initializeProject(
55
+ projectId: string,
56
+ name: string,
57
+ repoPath: string,
58
+ options?: Partial<ProjectSchema>
59
+ ): Promise<ProjectSchema> {
60
+ const project: ProjectSchema = {
61
+ ...DEFAULT_PROJECT,
62
+ ...options,
63
+ projectId,
64
+ name,
65
+ repoPath,
66
+ createdAt: new Date().toISOString(),
67
+ lastSync: new Date().toISOString()
68
+ }
69
+ await this.write(projectId, project)
70
+ return project
71
+ }
72
+ }
73
+
74
+ export const projectManager = new ProjectManager()
75
+ export default projectManager
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Roadmap Manager
3
+ *
4
+ * Manages roadmap.json - feature roadmap.
5
+ */
6
+
7
+ import { ArrayManager } from './base-manager'
8
+ import type {
9
+ FeatureSchema,
10
+ RoadmapSchema,
11
+ FeatureStatus,
12
+ FeatureTask
13
+ } from '../schemas'
14
+ import { DEFAULT_FEATURE } from '../schemas'
15
+
16
+ class RoadmapManager extends ArrayManager<FeatureSchema> {
17
+ constructor() {
18
+ super('roadmap.json')
19
+ }
20
+
21
+ async getFeatures(projectId: string): Promise<RoadmapSchema> {
22
+ return this.read(projectId)
23
+ }
24
+
25
+ async getActiveFeatures(projectId: string): Promise<RoadmapSchema> {
26
+ const features = await this.read(projectId)
27
+ return features.filter((f) => f.status === 'in_progress')
28
+ }
29
+
30
+ async getFeature(projectId: string, id: string): Promise<FeatureSchema | undefined> {
31
+ return this.find(projectId, (feature) => feature.id === id)
32
+ }
33
+
34
+ async addFeature(
35
+ projectId: string,
36
+ name: string,
37
+ options?: Partial<Omit<FeatureSchema, 'id' | 'name' | 'createdAt'>>
38
+ ): Promise<RoadmapSchema> {
39
+ const feature: FeatureSchema = {
40
+ ...DEFAULT_FEATURE,
41
+ ...options,
42
+ id: `feature_${Date.now()}`,
43
+ name,
44
+ createdAt: new Date().toISOString()
45
+ }
46
+ return this.add(projectId, feature)
47
+ }
48
+
49
+ async updateFeature(
50
+ projectId: string,
51
+ id: string,
52
+ updates: Partial<Omit<FeatureSchema, 'id' | 'createdAt'>>
53
+ ): Promise<RoadmapSchema> {
54
+ return this.updateItem(
55
+ projectId,
56
+ (feature) => feature.id === id,
57
+ (feature) => ({ ...feature, ...updates })
58
+ )
59
+ }
60
+
61
+ async setStatus(
62
+ projectId: string,
63
+ id: string,
64
+ status: FeatureStatus
65
+ ): Promise<RoadmapSchema> {
66
+ const updates: Partial<FeatureSchema> = { status }
67
+ if (status === 'completed' || status === 'shipped') {
68
+ updates.completedAt = new Date().toISOString()
69
+ }
70
+ return this.updateFeature(projectId, id, updates)
71
+ }
72
+
73
+ async addTask(
74
+ projectId: string,
75
+ featureId: string,
76
+ task: FeatureTask
77
+ ): Promise<RoadmapSchema> {
78
+ return this.updateItem(
79
+ projectId,
80
+ (feature) => feature.id === featureId,
81
+ (feature) => ({
82
+ ...feature,
83
+ tasks: [...feature.tasks, task]
84
+ })
85
+ )
86
+ }
87
+
88
+ async completeTask(
89
+ projectId: string,
90
+ featureId: string,
91
+ taskIndex: number
92
+ ): Promise<RoadmapSchema> {
93
+ return this.updateItem(
94
+ projectId,
95
+ (feature) => feature.id === featureId,
96
+ (feature) => ({
97
+ ...feature,
98
+ tasks: feature.tasks.map((task, i) =>
99
+ i === taskIndex ? { ...task, completed: true } : task
100
+ )
101
+ })
102
+ )
103
+ }
104
+
105
+ async removeFeature(projectId: string, id: string): Promise<RoadmapSchema> {
106
+ return this.remove(projectId, (feature) => feature.id === id)
107
+ }
108
+
109
+ async getProgress(projectId: string, featureId: string): Promise<number> {
110
+ const feature = await this.getFeature(projectId, featureId)
111
+ if (!feature || feature.tasks.length === 0) return 0
112
+ const completed = feature.tasks.filter((t) => t.completed).length
113
+ return Math.round((completed / feature.tasks.length) * 100)
114
+ }
115
+ }
116
+
117
+ export const roadmapManager = new RoadmapManager()
118
+ export default roadmapManager
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Shipped Manager
3
+ *
4
+ * Manages shipped.json - completed/shipped items history.
5
+ */
6
+
7
+ import { ArrayManager } from './base-manager'
8
+ import type { ShippedItemSchema, ShippedSchema } from '../schemas'
9
+
10
+ class ShippedManager extends ArrayManager<ShippedItemSchema> {
11
+ constructor() {
12
+ super('shipped.json')
13
+ }
14
+
15
+ async getShipped(projectId: string): Promise<ShippedSchema> {
16
+ return this.read(projectId)
17
+ }
18
+
19
+ async getRecentShipped(projectId: string, limit = 10): Promise<ShippedSchema> {
20
+ const shipped = await this.read(projectId)
21
+ return shipped
22
+ .sort((a, b) => new Date(b.shippedAt).getTime() - new Date(a.shippedAt).getTime())
23
+ .slice(0, limit)
24
+ }
25
+
26
+ async addShipped(
27
+ projectId: string,
28
+ item: Omit<ShippedItemSchema, 'id' | 'shippedAt'>
29
+ ): Promise<ShippedSchema> {
30
+ const shippedItem: ShippedItemSchema = {
31
+ ...item,
32
+ id: `shipped_${Date.now()}`,
33
+ shippedAt: new Date().toISOString()
34
+ }
35
+ return this.add(projectId, shippedItem)
36
+ }
37
+
38
+ async getByFeature(projectId: string, featureId: string): Promise<ShippedSchema> {
39
+ const shipped = await this.read(projectId)
40
+ return shipped.filter((item) => item.featureId === featureId)
41
+ }
42
+
43
+ async getTotalDuration(projectId: string): Promise<string> {
44
+ const shipped = await this.read(projectId)
45
+ // Parse durations and sum (simplified - assumes format like "2h 30m")
46
+ let totalMinutes = 0
47
+ for (const item of shipped) {
48
+ const hours = item.duration.match(/(\d+)h/)
49
+ const minutes = item.duration.match(/(\d+)m/)
50
+ if (hours) totalMinutes += parseInt(hours[1]) * 60
51
+ if (minutes) totalMinutes += parseInt(minutes[1])
52
+ }
53
+ const h = Math.floor(totalMinutes / 60)
54
+ const m = totalMinutes % 60
55
+ return h > 0 ? `${h}h ${m}m` : `${m}m`
56
+ }
57
+
58
+ async getCount(projectId: string): Promise<number> {
59
+ const shipped = await this.read(projectId)
60
+ return shipped.length
61
+ }
62
+ }
63
+
64
+ export const shippedManager = new ShippedManager()
65
+ export default shippedManager
@@ -0,0 +1,214 @@
1
+ /**
2
+ * State Manager
3
+ *
4
+ * Manages state.json - the unified project state.
5
+ */
6
+
7
+ import { BaseManager } from './base-manager'
8
+ import type {
9
+ StateSchema,
10
+ CurrentTask,
11
+ QueuedTask,
12
+ RecentActivity,
13
+ Stats
14
+ } from '../schemas'
15
+ import { DEFAULT_STATE, DEFAULT_STATS } from '../schemas'
16
+
17
+ const MAX_RECENT_ACTIVITY = 10
18
+
19
+ class StateManager extends BaseManager<StateSchema> {
20
+ constructor() {
21
+ super('state.json')
22
+ }
23
+
24
+ protected getDefault(projectId: string): StateSchema {
25
+ return {
26
+ ...DEFAULT_STATE,
27
+ projectId,
28
+ lastSync: new Date().toISOString()
29
+ }
30
+ }
31
+
32
+ // =========== Current Task ===========
33
+
34
+ async getCurrentTask(projectId: string): Promise<CurrentTask | null> {
35
+ const state = await this.read(projectId)
36
+ return state.currentTask
37
+ }
38
+
39
+ async setCurrentTask(projectId: string, task: CurrentTask | null): Promise<StateSchema> {
40
+ return this.update(projectId, (state) => ({
41
+ ...state,
42
+ currentTask: task,
43
+ lastSync: new Date().toISOString()
44
+ }))
45
+ }
46
+
47
+ async startTask(
48
+ projectId: string,
49
+ task: Omit<CurrentTask, 'startedAt'>
50
+ ): Promise<StateSchema> {
51
+ const currentTask: CurrentTask = {
52
+ ...task,
53
+ startedAt: new Date().toISOString()
54
+ }
55
+
56
+ return this.update(projectId, (state) => ({
57
+ ...state,
58
+ currentTask,
59
+ recentActivity: [
60
+ {
61
+ type: 'session_started' as const,
62
+ description: task.description,
63
+ timestamp: new Date().toISOString()
64
+ },
65
+ ...state.recentActivity
66
+ ].slice(0, MAX_RECENT_ACTIVITY),
67
+ lastSync: new Date().toISOString()
68
+ }))
69
+ }
70
+
71
+ async completeTask(projectId: string, duration: string): Promise<StateSchema> {
72
+ const state = await this.read(projectId)
73
+ if (!state.currentTask) {
74
+ throw new Error('No active task to complete')
75
+ }
76
+
77
+ const activity: RecentActivity = {
78
+ type: 'task_completed',
79
+ description: state.currentTask.description,
80
+ timestamp: new Date().toISOString(),
81
+ duration
82
+ }
83
+
84
+ return this.update(projectId, (s) => ({
85
+ ...s,
86
+ currentTask: null,
87
+ recentActivity: [activity, ...s.recentActivity].slice(0, MAX_RECENT_ACTIVITY),
88
+ stats: {
89
+ ...s.stats,
90
+ tasksToday: s.stats.tasksToday + 1
91
+ },
92
+ lastSync: new Date().toISOString()
93
+ }))
94
+ }
95
+
96
+ async pauseTask(projectId: string, reason?: string): Promise<StateSchema> {
97
+ const state = await this.read(projectId)
98
+ if (!state.currentTask) {
99
+ throw new Error('No active task to pause')
100
+ }
101
+
102
+ return this.update(projectId, (s) => ({
103
+ ...s,
104
+ currentTask: s.currentTask
105
+ ? {
106
+ ...s.currentTask,
107
+ pausedAt: new Date().toISOString(),
108
+ pauseReason: reason
109
+ }
110
+ : null,
111
+ lastSync: new Date().toISOString()
112
+ }))
113
+ }
114
+
115
+ async resumeTask(projectId: string): Promise<StateSchema> {
116
+ const state = await this.read(projectId)
117
+ if (!state.currentTask?.pausedAt) {
118
+ throw new Error('No paused task to resume')
119
+ }
120
+
121
+ return this.update(projectId, (s) => ({
122
+ ...s,
123
+ currentTask: s.currentTask
124
+ ? {
125
+ ...s.currentTask,
126
+ pausedAt: undefined,
127
+ pauseReason: undefined
128
+ }
129
+ : null,
130
+ lastSync: new Date().toISOString()
131
+ }))
132
+ }
133
+
134
+ // =========== Queue ===========
135
+
136
+ async getQueue(projectId: string): Promise<QueuedTask[]> {
137
+ const state = await this.read(projectId)
138
+ return state.queue
139
+ }
140
+
141
+ async addToQueue(
142
+ projectId: string,
143
+ task: Omit<QueuedTask, 'id' | 'createdAt'>
144
+ ): Promise<StateSchema> {
145
+ const queuedTask: QueuedTask = {
146
+ ...task,
147
+ id: `task_${Date.now()}`,
148
+ createdAt: new Date().toISOString()
149
+ }
150
+
151
+ return this.update(projectId, (state) => ({
152
+ ...state,
153
+ queue: [...state.queue, queuedTask].sort((a, b) => {
154
+ const priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 }
155
+ return priorityOrder[a.priority] - priorityOrder[b.priority]
156
+ }),
157
+ lastSync: new Date().toISOString()
158
+ }))
159
+ }
160
+
161
+ async removeFromQueue(projectId: string, taskId: string): Promise<StateSchema> {
162
+ return this.update(projectId, (state) => ({
163
+ ...state,
164
+ queue: state.queue.filter((t) => t.id !== taskId),
165
+ lastSync: new Date().toISOString()
166
+ }))
167
+ }
168
+
169
+ async getNextTask(projectId: string): Promise<QueuedTask | null> {
170
+ const state = await this.read(projectId)
171
+ return state.queue.find((t) => !t.blockedReason) || null
172
+ }
173
+
174
+ // =========== Stats ===========
175
+
176
+ async getStats(projectId: string): Promise<Stats> {
177
+ const state = await this.read(projectId)
178
+ return state.stats
179
+ }
180
+
181
+ async updateStats(projectId: string, stats: Partial<Stats>): Promise<StateSchema> {
182
+ return this.update(projectId, (state) => ({
183
+ ...state,
184
+ stats: { ...state.stats, ...stats },
185
+ lastSync: new Date().toISOString()
186
+ }))
187
+ }
188
+
189
+ async resetDailyStats(projectId: string): Promise<StateSchema> {
190
+ return this.update(projectId, (state) => ({
191
+ ...state,
192
+ stats: { ...state.stats, tasksToday: 0 },
193
+ lastSync: new Date().toISOString()
194
+ }))
195
+ }
196
+
197
+ // =========== Activity ===========
198
+
199
+ async addActivity(projectId: string, activity: RecentActivity): Promise<StateSchema> {
200
+ return this.update(projectId, (state) => ({
201
+ ...state,
202
+ recentActivity: [activity, ...state.recentActivity].slice(0, MAX_RECENT_ACTIVITY),
203
+ lastSync: new Date().toISOString()
204
+ }))
205
+ }
206
+
207
+ async getRecentActivity(projectId: string): Promise<RecentActivity[]> {
208
+ const state = await this.read(projectId)
209
+ return state.recentActivity
210
+ }
211
+ }
212
+
213
+ export const stateManager = new StateManager()
214
+ export default stateManager