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,13 @@
1
+ import type { AccentColor } from './HealthGradientBackground.types'
2
+
3
+ export function getHealthColor(score: number): AccentColor {
4
+ if (score >= 70) return 'success'
5
+ if (score >= 40) return 'warning'
6
+ return 'destructive'
7
+ }
8
+
9
+ export function getHealthGradient(score: number): string {
10
+ if (score >= 70) return 'bg-gradient-to-br from-emerald-500/20 to-transparent'
11
+ if (score >= 40) return 'bg-gradient-to-br from-amber-500/20 to-transparent'
12
+ return 'bg-gradient-to-br from-destructive/20 to-transparent'
13
+ }
@@ -0,0 +1,2 @@
1
+ export { HealthGradientBackground } from './HealthGradientBackground'
2
+ export type { HealthGradientBackgroundProps } from './HealthGradientBackground.types'
@@ -0,0 +1,55 @@
1
+ 'use client'
2
+
3
+ import { ProgressRing } from '@/components/ProgressRing'
4
+ import { BackLink } from '@/components/BackLink'
5
+ import { TasksCounter } from '@/components/TasksCounter'
6
+ import { VelocityBadge } from '@/components/VelocityBadge'
7
+ import { InsightMessage } from '@/components/InsightMessage'
8
+ import { WeeklySparkline } from '@/components/WeeklySparkline'
9
+ import { HealthGradientBackground } from '@/components/HealthGradientBackground'
10
+ import { useCountUp, useWeeklyActivity } from './hooks'
11
+ import { getHealthColor } from './HeroSection.utils'
12
+ import type { HeroProps } from './HeroSection.types'
13
+
14
+ export function HeroSection({
15
+ projectId,
16
+ projectName,
17
+ tasksCompleted,
18
+ healthScore,
19
+ velocityChange,
20
+ insightMessage,
21
+ timeline = [],
22
+ }: HeroProps) {
23
+ const animatedCount = useCountUp(tasksCompleted)
24
+ const weeklyData = useWeeklyActivity(timeline)
25
+ const healthColor = getHealthColor(healthScore)
26
+
27
+ return (
28
+ <div className="relative mb-6 md:mb-8">
29
+ <HealthGradientBackground score={healthScore} />
30
+ <BackLink projectId={projectId} projectName={projectName} className="md:hidden mb-4" />
31
+
32
+ <div className="relative flex flex-col md:flex-row md:items-start md:justify-between gap-4 md:gap-0">
33
+ <div className="flex items-center md:items-start gap-4 md:gap-6">
34
+ <ProgressRing
35
+ value={healthScore}
36
+ size="xl"
37
+ accentColor={healthColor}
38
+ className="shrink-0"
39
+ />
40
+
41
+ <div className="flex-1 min-w-0">
42
+ <TasksCounter count={animatedCount} />
43
+ <VelocityBadge change={velocityChange} />
44
+ <InsightMessage message={insightMessage} />
45
+ </div>
46
+ </div>
47
+
48
+ <div className="flex flex-col items-start md:items-end gap-3 md:gap-4">
49
+ <BackLink projectId={projectId} projectName={projectName} className="hidden md:flex" />
50
+ <WeeklySparkline data={weeklyData} />
51
+ </div>
52
+ </div>
53
+ </div>
54
+ )
55
+ }
@@ -0,0 +1,14 @@
1
+ import type { TimelineEvent } from '@/lib/parse-prjct-files'
2
+
3
+ export type { TimelineEvent }
4
+
5
+ export interface HeroProps {
6
+ projectId: string
7
+ projectName: string
8
+ tasksCompleted: number
9
+ healthScore: number
10
+ velocity: number
11
+ velocityChange: number
12
+ insightMessage: string
13
+ timeline?: TimelineEvent[]
14
+ }
@@ -0,0 +1,7 @@
1
+ export type AccentColor = 'default' | 'success' | 'warning' | 'destructive'
2
+
3
+ export function getHealthColor(score: number): AccentColor {
4
+ if (score >= 70) return 'success'
5
+ if (score >= 40) return 'warning'
6
+ return 'destructive'
7
+ }
@@ -0,0 +1,2 @@
1
+ export { useCountUp } from './useCountUp'
2
+ export { useWeeklyActivity } from './useWeeklyActivity'
@@ -0,0 +1,45 @@
1
+ 'use client'
2
+
3
+ import { useEffect, useRef, useState } from 'react'
4
+
5
+ export function useCountUp(target: number, duration: number = 800): number {
6
+ const [count, setCount] = useState(0)
7
+ const prevTargetRef = useRef(target)
8
+
9
+ useEffect(() => {
10
+ if (target === 0) {
11
+ // Only reset if target changed to 0 (not if it was already 0)
12
+ if (prevTargetRef.current !== 0) {
13
+ // Defer state update to avoid synchronous setState in effect
14
+ const timeoutId = setTimeout(() => setCount(0), 0)
15
+ prevTargetRef.current = target
16
+ return () => clearTimeout(timeoutId)
17
+ }
18
+ prevTargetRef.current = target
19
+ return
20
+ }
21
+
22
+ prevTargetRef.current = target
23
+
24
+ const startTime = performance.now()
25
+
26
+ const animate = (currentTime: number) => {
27
+ const elapsed = currentTime - startTime
28
+ const progress = Math.min(elapsed / duration, 1)
29
+ const easeOut = 1 - Math.pow(1 - progress, 3)
30
+ const current = Math.floor(easeOut * target)
31
+
32
+ setCount(current)
33
+
34
+ if (progress < 1) {
35
+ requestAnimationFrame(animate)
36
+ } else {
37
+ setCount(target)
38
+ }
39
+ }
40
+
41
+ requestAnimationFrame(animate)
42
+ }, [target, duration])
43
+
44
+ return count
45
+ }
@@ -0,0 +1,18 @@
1
+ 'use client'
2
+
3
+ import { useMemo } from 'react'
4
+ import type { TimelineEvent } from '../HeroSection.types'
5
+
6
+ export function useWeeklyActivity(timeline: TimelineEvent[]): number[] {
7
+ return useMemo(() => {
8
+ const today = new Date()
9
+
10
+ return Array.from({ length: 7 }, (_, i) => {
11
+ const date = new Date(today)
12
+ date.setDate(date.getDate() - (6 - i))
13
+ const dateStr = date.toISOString().split('T')[0]
14
+
15
+ return timeline.filter(e => e.ts?.startsWith(dateStr)).length
16
+ })
17
+ }, [timeline])
18
+ }
@@ -0,0 +1,2 @@
1
+ export { HeroSection } from './HeroSection'
2
+ export type { HeroProps } from './HeroSection.types'
@@ -0,0 +1,48 @@
1
+ import { BentoCard } from '@/components/BentoCard'
2
+ import { EmptyState } from '@/components/EmptyState'
3
+ import { Lightbulb } from 'lucide-react'
4
+ import { cn } from '@/lib/utils'
5
+ import type { IdeasCardProps } from './IdeasCard.types'
6
+
7
+ export function IdeasCard({ ideas, className }: IdeasCardProps) {
8
+ const displayIdeas = ideas.slice(0, 4)
9
+ const highImpactCount = ideas.filter(i => i.impact === 'HIGH').length
10
+
11
+ return (
12
+ <BentoCard
13
+ size="1x1"
14
+ title="Ideas"
15
+ icon={Lightbulb}
16
+ count={ideas.length}
17
+ className={className}
18
+ >
19
+ {ideas.length === 0 ? (
20
+ <EmptyState
21
+ icon={Lightbulb}
22
+ title="No ideas yet"
23
+ command="/p:idea"
24
+ compact
25
+ />
26
+ ) : (
27
+ <div className="space-y-1.5">
28
+ {displayIdeas.map((idea, i) => (
29
+ <div key={i} className="flex items-start gap-2">
30
+ <Lightbulb
31
+ className={cn(
32
+ 'h-3 w-3 mt-0.5 shrink-0',
33
+ idea.impact === 'HIGH' ? 'text-amber-500' : 'text-muted-foreground'
34
+ )}
35
+ />
36
+ <p className="text-sm truncate">{idea.title}</p>
37
+ </div>
38
+ ))}
39
+ {highImpactCount > 0 && (
40
+ <p className="text-[10px] text-amber-600 dark:text-amber-400 mt-2 pl-5 font-medium">
41
+ {highImpactCount} high impact
42
+ </p>
43
+ )}
44
+ </div>
45
+ )}
46
+ </BentoCard>
47
+ )
48
+ }
@@ -0,0 +1,9 @@
1
+ export interface Idea {
2
+ title: string
3
+ impact?: string
4
+ }
5
+
6
+ export interface IdeasCardProps {
7
+ ideas: Idea[]
8
+ className?: string
9
+ }
@@ -0,0 +1,2 @@
1
+ export { IdeasCard } from './IdeasCard'
2
+ export type { IdeasCardProps } from './IdeasCard.types'
@@ -0,0 +1,9 @@
1
+ import type { InsightMessageProps } from './InsightMessage.types'
2
+
3
+ export function InsightMessage({ message }: InsightMessageProps) {
4
+ return (
5
+ <p className="text-sm md:text-base text-muted-foreground mt-2 md:mt-3 max-w-md">
6
+ {message}
7
+ </p>
8
+ )
9
+ }
@@ -0,0 +1,3 @@
1
+ export interface InsightMessageProps {
2
+ message: string
3
+ }
@@ -0,0 +1,2 @@
1
+ export { InsightMessage } from './InsightMessage'
2
+ export type { InsightMessageProps } from './InsightMessage.types'
@@ -0,0 +1 @@
1
+ export { Logo } from './Logo'
@@ -0,0 +1 @@
1
+ export { MarkdownContent } from './MarkdownContent'
@@ -0,0 +1,93 @@
1
+ import { BentoCard } from '@/components/BentoCard'
2
+ import { EmptyState } from '@/components/EmptyState'
3
+ import { Target, Clock, Bot, Pause } from 'lucide-react'
4
+ import { cn } from '@/lib/utils'
5
+ import type { NowCardProps } from './NowCard.types'
6
+
7
+ export function NowCard({ currentTask, className }: NowCardProps) {
8
+ return (
9
+ <BentoCard
10
+ size="2x2"
11
+ title="Now"
12
+ icon={Target}
13
+ accentColor={currentTask ? 'warning' : 'default'}
14
+ className={className}
15
+ >
16
+ {currentTask ? (
17
+ <div className="flex flex-col h-full">
18
+ <div className="flex items-center gap-2 mb-3">
19
+ {currentTask.pausedAt ? (
20
+ <>
21
+ <Pause className="w-3 h-3 text-muted-foreground" />
22
+ <span className="text-[10px] font-semibold text-muted-foreground uppercase tracking-wider">
23
+ Paused
24
+ </span>
25
+ </>
26
+ ) : (
27
+ <>
28
+ <div className="w-2 h-2 rounded-full bg-amber-500 animate-pulse" />
29
+ <span className="text-[10px] font-semibold text-amber-600 dark:text-amber-400 uppercase tracking-wider">
30
+ Working
31
+ </span>
32
+ </>
33
+ )}
34
+ </div>
35
+
36
+ <p className="text-xl font-semibold leading-tight flex-1">
37
+ {currentTask.task}
38
+ </p>
39
+
40
+ {currentTask.agent && (
41
+ <div className="flex items-center gap-2 mt-2 text-xs text-muted-foreground">
42
+ <Bot className="h-3 w-3" />
43
+ <span className="font-mono">{currentTask.agent}</span>
44
+ {currentTask.agentConfidence !== undefined && (
45
+ <span className={cn(
46
+ 'px-1.5 py-0.5 rounded text-[10px]',
47
+ currentTask.agentConfidence >= 0.8 ? 'bg-emerald-500/10 text-emerald-600' :
48
+ currentTask.agentConfidence >= 0.5 ? 'bg-amber-500/10 text-amber-600' :
49
+ 'bg-muted text-muted-foreground'
50
+ )}>
51
+ {Math.round(currentTask.agentConfidence * 100)}% confidence
52
+ </span>
53
+ )}
54
+ </div>
55
+ )}
56
+
57
+ <div className="flex items-center gap-4 mt-3 text-muted-foreground">
58
+ {currentTask.duration && (
59
+ <div className="flex items-center gap-1.5">
60
+ <Clock className="h-3.5 w-3.5" />
61
+ <span className="text-sm">{currentTask.duration}</span>
62
+ </div>
63
+ )}
64
+ {currentTask.estimatedDuration && (
65
+ <span className="text-xs">
66
+ / est. {currentTask.estimatedDuration}
67
+ </span>
68
+ )}
69
+ </div>
70
+
71
+ <div className="mt-4">
72
+ <div className="h-1.5 bg-muted rounded-full overflow-hidden">
73
+ <div
74
+ className={cn(
75
+ "h-full rounded-full",
76
+ currentTask.pausedAt ? "bg-muted-foreground" : "bg-amber-500 animate-pulse"
77
+ )}
78
+ style={{ width: '60%' }}
79
+ />
80
+ </div>
81
+ </div>
82
+ </div>
83
+ ) : (
84
+ <EmptyState
85
+ icon={Target}
86
+ title="No active task"
87
+ description="Start working on something"
88
+ command="/p:now"
89
+ />
90
+ )}
91
+ </BentoCard>
92
+ )
93
+ }
@@ -0,0 +1,15 @@
1
+ export interface CurrentTask {
2
+ task: string
3
+ startedAt?: string
4
+ agent?: string
5
+ agentConfidence?: number
6
+ estimatedDuration?: string
7
+ pausedAt?: string
8
+ pauseReason?: string
9
+ duration?: string
10
+ }
11
+
12
+ export interface NowCardProps {
13
+ currentTask: CurrentTask | null
14
+ className?: string
15
+ }
@@ -0,0 +1,2 @@
1
+ export { NowCard } from './NowCard'
2
+ export type { NowCardProps } from './NowCard.types'
@@ -0,0 +1,20 @@
1
+ import type { ProgressRingSize, AccentColor } from './ProgressRing.types'
2
+
3
+ export const PROGRESS_RING_SIZES: Record<ProgressRingSize, {
4
+ container: string
5
+ text: string
6
+ viewBox: number
7
+ radius: number
8
+ }> = {
9
+ sm: { container: 'h-8 w-8', text: 'text-[10px]', viewBox: 36, radius: 14 },
10
+ md: { container: 'h-12 w-12', text: 'text-xs', viewBox: 36, radius: 14 },
11
+ lg: { container: 'h-16 w-16', text: 'text-sm', viewBox: 36, radius: 14 },
12
+ xl: { container: 'h-20 w-20', text: 'text-base', viewBox: 36, radius: 14 },
13
+ }
14
+
15
+ export const PROGRESS_RING_COLOR_STYLES: Record<AccentColor, string> = {
16
+ default: 'text-foreground',
17
+ success: 'text-emerald-500',
18
+ warning: 'text-amber-500',
19
+ destructive: 'text-destructive',
20
+ }
@@ -0,0 +1,51 @@
1
+ 'use client'
2
+
3
+ import { cn } from '@/lib/utils'
4
+ import { PROGRESS_RING_SIZES, PROGRESS_RING_COLOR_STYLES } from './ProgressRing.constants'
5
+ import type { ProgressRingProps } from './ProgressRing.types'
6
+
7
+ export function ProgressRing({
8
+ value,
9
+ size = 'md',
10
+ showValue = true,
11
+ strokeWidth = 3,
12
+ className,
13
+ accentColor = 'default',
14
+ }: ProgressRingProps) {
15
+ const { container, text, viewBox, radius } = PROGRESS_RING_SIZES[size]
16
+ const circumference = 2 * Math.PI * radius
17
+ const strokeDashoffset = circumference - (value / 100) * circumference
18
+
19
+ return (
20
+ <div className={cn('relative', container, className)}>
21
+ <svg className="h-full w-full -rotate-90" viewBox={`0 0 ${viewBox} ${viewBox}`}>
22
+ <circle
23
+ cx={viewBox / 2}
24
+ cy={viewBox / 2}
25
+ r={radius}
26
+ fill="none"
27
+ stroke="currentColor"
28
+ strokeWidth={strokeWidth}
29
+ className="text-foreground/10"
30
+ />
31
+ <circle
32
+ cx={viewBox / 2}
33
+ cy={viewBox / 2}
34
+ r={radius}
35
+ fill="none"
36
+ stroke="currentColor"
37
+ strokeWidth={strokeWidth}
38
+ strokeDasharray={circumference}
39
+ strokeDashoffset={strokeDashoffset}
40
+ strokeLinecap="round"
41
+ className={cn('transition-all duration-700 ease-out', PROGRESS_RING_COLOR_STYLES[accentColor])}
42
+ />
43
+ </svg>
44
+ {showValue && (
45
+ <span className={cn('absolute inset-0 flex items-center justify-center font-bold tabular-nums', text)}>
46
+ {value}
47
+ </span>
48
+ )}
49
+ </div>
50
+ )
51
+ }
@@ -0,0 +1,11 @@
1
+ export type ProgressRingSize = 'sm' | 'md' | 'lg' | 'xl'
2
+ export type AccentColor = 'default' | 'success' | 'warning' | 'destructive'
3
+
4
+ export interface ProgressRingProps {
5
+ value: number
6
+ size?: ProgressRingSize
7
+ showValue?: boolean
8
+ strokeWidth?: number
9
+ className?: string
10
+ accentColor?: AccentColor
11
+ }
@@ -0,0 +1,2 @@
1
+ export { ProgressRing } from './ProgressRing'
2
+ export type { ProgressRingProps } from './ProgressRing.types'
@@ -0,0 +1 @@
1
+ export { ProjectAvatar } from './ProjectAvatar'
@@ -0,0 +1 @@
1
+ export { Providers } from './Providers'
@@ -0,0 +1,72 @@
1
+ import { BentoCard } from '@/components/BentoCard'
2
+ import { EmptyState } from '@/components/EmptyState'
3
+ import { ListTodo, Bot } from 'lucide-react'
4
+ import { cn } from '@/lib/utils'
5
+ import { getPriorityColor } from './QueueCard.utils'
6
+ import type { QueueCardProps } from './QueueCard.types'
7
+
8
+ export function QueueCard({ queue, className }: QueueCardProps) {
9
+ const displayItems = queue.slice(0, 5)
10
+ const remaining = queue.length - 5
11
+
12
+ return (
13
+ <BentoCard
14
+ size="1x2"
15
+ title="Queue"
16
+ icon={ListTodo}
17
+ count={queue.length}
18
+ className={className}
19
+ >
20
+ {queue.length === 0 ? (
21
+ <EmptyState
22
+ icon={ListTodo}
23
+ title="Queue empty"
24
+ description="Plan your next tasks"
25
+ command="/p:next"
26
+ compact
27
+ />
28
+ ) : (
29
+ <div className="space-y-2">
30
+ {displayItems.map((item, i) => {
31
+ const priorityColor = getPriorityColor(item.priority)
32
+ return (
33
+ <div key={i} className="flex items-start gap-2 group">
34
+ <span className={cn(
35
+ "text-[10px] font-medium w-4 shrink-0 pt-0.5 tabular-nums",
36
+ priorityColor
37
+ )}>
38
+ {i + 1}
39
+ </span>
40
+ <div className="flex-1 min-w-0">
41
+ <p className="text-sm leading-tight truncate group-hover:text-foreground transition-colors">
42
+ {item.task}
43
+ </p>
44
+ {(item.suggestedAgent || item.estimatedDuration) && (
45
+ <div className="flex items-center gap-2 mt-0.5">
46
+ {item.suggestedAgent && (
47
+ <span className="inline-flex items-center gap-0.5 text-[9px] text-muted-foreground">
48
+ <Bot className="h-2.5 w-2.5" />
49
+ {item.suggestedAgent}
50
+ </span>
51
+ )}
52
+ {item.estimatedDuration && (
53
+ <span className="text-[9px] text-muted-foreground">
54
+ ~{item.estimatedDuration}
55
+ </span>
56
+ )}
57
+ </div>
58
+ )}
59
+ </div>
60
+ </div>
61
+ )
62
+ })}
63
+ {remaining > 0 && (
64
+ <p className="text-[10px] text-muted-foreground mt-2 pl-6">
65
+ +{remaining} more
66
+ </p>
67
+ )}
68
+ </div>
69
+ )}
70
+ </BentoCard>
71
+ )
72
+ }
@@ -0,0 +1,11 @@
1
+ export interface QueueItem {
2
+ task: string
3
+ priority?: 'low' | 'medium' | 'high' | 'critical' | number
4
+ suggestedAgent?: string
5
+ estimatedDuration?: string
6
+ }
7
+
8
+ export interface QueueCardProps {
9
+ queue: QueueItem[]
10
+ className?: string
11
+ }
@@ -0,0 +1,12 @@
1
+ export function getPriorityColor(priority?: 'low' | 'medium' | 'high' | 'critical' | number): string {
2
+ if (typeof priority === 'string') {
3
+ const colors: Record<string, string> = {
4
+ critical: 'text-red-500',
5
+ high: 'text-amber-500',
6
+ medium: 'text-blue-500',
7
+ low: 'text-muted-foreground',
8
+ }
9
+ return colors[priority] ?? 'text-muted-foreground'
10
+ }
11
+ return 'text-muted-foreground'
12
+ }
@@ -0,0 +1,2 @@
1
+ export { QueueCard } from './QueueCard'
2
+ export type { QueueCardProps } from './QueueCard.types'
@@ -0,0 +1,77 @@
1
+ import { BentoCard } from '@/components/BentoCard'
2
+ import { EmptyState } from '@/components/EmptyState'
3
+ import { Map } from 'lucide-react'
4
+ import { cn } from '@/lib/utils'
5
+ import type { RoadmapCardProps } from './RoadmapCard.types'
6
+
7
+ export function RoadmapCard({ roadmap, className }: RoadmapCardProps) {
8
+ const hasPhases = roadmap?.phases && roadmap.phases.length > 0
9
+
10
+ return (
11
+ <BentoCard
12
+ size="2x2"
13
+ title="Roadmap"
14
+ icon={Map}
15
+ count={hasPhases ? `${roadmap.progress}%` : undefined}
16
+ className={className}
17
+ >
18
+ {!hasPhases ? (
19
+ <EmptyState
20
+ icon={Map}
21
+ title="No roadmap yet"
22
+ description="Plan your features"
23
+ command="/p:feature"
24
+ />
25
+ ) : (
26
+ <div className="flex flex-col h-full">
27
+ <div className="mb-4">
28
+ <div className="flex items-center justify-between text-xs mb-1.5">
29
+ <span className="text-muted-foreground">Overall progress</span>
30
+ <span className="font-bold tabular-nums">{roadmap.progress}%</span>
31
+ </div>
32
+ <div className="h-2 bg-muted rounded-full overflow-hidden">
33
+ <div
34
+ className={cn(
35
+ 'h-full rounded-full transition-all duration-500',
36
+ roadmap.progress === 100 ? 'bg-emerald-500' : 'bg-foreground'
37
+ )}
38
+ style={{ width: `${roadmap.progress}%` }}
39
+ />
40
+ </div>
41
+ </div>
42
+
43
+ <div className="space-y-3 flex-1">
44
+ {roadmap.phases
45
+ .filter(p => (p.features || []).length > 0)
46
+ .slice(0, 4)
47
+ .map((phase) => (
48
+ <div key={phase.name}>
49
+ <div className="flex items-center justify-between text-xs mb-1">
50
+ <span className="font-medium truncate">{phase.name}</span>
51
+ <span className="text-muted-foreground tabular-nums shrink-0 ml-2">
52
+ {phase.progress}%
53
+ </span>
54
+ </div>
55
+ <div className="h-1.5 bg-muted rounded-full overflow-hidden">
56
+ <div
57
+ className={cn(
58
+ 'h-full rounded-full transition-all duration-300',
59
+ phase.progress === 100 ? 'bg-emerald-500' : 'bg-foreground/70'
60
+ )}
61
+ style={{ width: `${phase.progress}%` }}
62
+ />
63
+ </div>
64
+ </div>
65
+ ))}
66
+ </div>
67
+
68
+ {roadmap.phases.length > 0 && (
69
+ <p className="text-[10px] text-muted-foreground mt-3">
70
+ {roadmap.phases.reduce((acc, p) => acc + (p.features?.length || 0), 0)} features across {roadmap.phases.length} phases
71
+ </p>
72
+ )}
73
+ </div>
74
+ )}
75
+ </BentoCard>
76
+ )
77
+ }