prjct-cli 0.11.4 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (385) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +81 -25
  3. package/bin/dev.js +1 -1
  4. package/bin/generate-views.js +209 -0
  5. package/bin/migrate-to-json.js +742 -0
  6. package/bin/prjct +5 -5
  7. package/bin/serve.js +246 -54
  8. package/core/__tests__/agentic/{memory-system.test.js → memory-system.test.ts} +12 -23
  9. package/core/__tests__/agentic/{plan-mode.test.js → plan-mode.test.ts} +26 -24
  10. package/core/__tests__/agentic/{prompt-builder.test.js → prompt-builder.test.ts} +3 -8
  11. package/core/__tests__/utils/date-helper.test.ts +405 -0
  12. package/core/__tests__/utils/{output.test.js → output.test.ts} +12 -24
  13. package/core/agentic/agent-router.ts +137 -0
  14. package/core/agentic/chain-of-thought.ts +228 -0
  15. package/core/agentic/command-executor/command-executor.ts +384 -0
  16. package/core/agentic/command-executor/index.ts +16 -0
  17. package/core/agentic/command-executor/status-signal.ts +38 -0
  18. package/core/agentic/command-executor/types.ts +79 -0
  19. package/core/agentic/command-executor.ts +8 -0
  20. package/core/agentic/{context-builder.js → context-builder.ts} +99 -89
  21. package/core/agentic/context-filter.ts +365 -0
  22. package/core/agentic/ground-truth/index.ts +76 -0
  23. package/core/agentic/ground-truth/types.ts +33 -0
  24. package/core/agentic/ground-truth/utils.ts +48 -0
  25. package/core/agentic/ground-truth/verifiers/analyze.ts +54 -0
  26. package/core/agentic/ground-truth/verifiers/done.ts +75 -0
  27. package/core/agentic/ground-truth/verifiers/feature.ts +70 -0
  28. package/core/agentic/ground-truth/verifiers/index.ts +37 -0
  29. package/core/agentic/ground-truth/verifiers/init.ts +52 -0
  30. package/core/agentic/ground-truth/verifiers/now.ts +57 -0
  31. package/core/agentic/ground-truth/verifiers/ship.ts +85 -0
  32. package/core/agentic/ground-truth/verifiers/spec.ts +45 -0
  33. package/core/agentic/ground-truth/verifiers/sync.ts +47 -0
  34. package/core/agentic/ground-truth/verifiers.ts +6 -0
  35. package/core/agentic/ground-truth.ts +8 -0
  36. package/core/agentic/loop-detector/error-analysis.ts +97 -0
  37. package/core/agentic/loop-detector/hallucination.ts +71 -0
  38. package/core/agentic/loop-detector/index.ts +41 -0
  39. package/core/agentic/loop-detector/loop-detector.ts +222 -0
  40. package/core/agentic/loop-detector/types.ts +66 -0
  41. package/core/agentic/loop-detector.ts +8 -0
  42. package/core/agentic/memory-system/history.ts +53 -0
  43. package/core/agentic/memory-system/index.ts +192 -0
  44. package/core/agentic/memory-system/patterns.ts +156 -0
  45. package/core/agentic/memory-system/semantic-memories.ts +277 -0
  46. package/core/agentic/memory-system/session.ts +21 -0
  47. package/core/agentic/memory-system/types.ts +159 -0
  48. package/core/agentic/memory-system.ts +8 -0
  49. package/core/agentic/parallel-tools.ts +165 -0
  50. package/core/agentic/plan-mode/approval.ts +57 -0
  51. package/core/agentic/plan-mode/constants.ts +44 -0
  52. package/core/agentic/plan-mode/index.ts +28 -0
  53. package/core/agentic/plan-mode/plan-mode.ts +406 -0
  54. package/core/agentic/plan-mode/types.ts +193 -0
  55. package/core/agentic/plan-mode.ts +8 -0
  56. package/core/agentic/prompt-builder.ts +566 -0
  57. package/core/agentic/response-templates.ts +164 -0
  58. package/core/agentic/semantic-compression.ts +273 -0
  59. package/core/agentic/services.ts +206 -0
  60. package/core/agentic/smart-context.ts +476 -0
  61. package/core/agentic/{template-loader.js → template-loader.ts} +35 -18
  62. package/core/agentic/think-blocks.ts +202 -0
  63. package/core/agentic/tool-registry.ts +119 -0
  64. package/core/agentic/validation-rules.ts +313 -0
  65. package/core/agents/index.ts +28 -0
  66. package/core/agents/performance.ts +444 -0
  67. package/core/agents/types.ts +126 -0
  68. package/core/bus/{index.js → index.ts} +57 -61
  69. package/core/command-registry/categories.ts +23 -0
  70. package/core/command-registry/commands.ts +15 -0
  71. package/core/command-registry/core-commands.ts +319 -0
  72. package/core/command-registry/index.ts +158 -0
  73. package/core/command-registry/optional-commands.ts +119 -0
  74. package/core/command-registry/setup-commands.ts +53 -0
  75. package/core/command-registry/types.ts +59 -0
  76. package/core/command-registry.ts +9 -0
  77. package/core/commands/analysis.ts +298 -0
  78. package/core/commands/analytics.ts +288 -0
  79. package/core/commands/base.ts +273 -0
  80. package/core/commands/index.ts +211 -0
  81. package/core/commands/maintenance.ts +226 -0
  82. package/core/commands/planning.ts +311 -0
  83. package/core/commands/setup.ts +309 -0
  84. package/core/commands/shipping.ts +188 -0
  85. package/core/commands/types.ts +183 -0
  86. package/core/commands/workflow.ts +226 -0
  87. package/core/commands.ts +11 -0
  88. package/core/constants/formats.ts +187 -0
  89. package/core/constants/index.ts +7 -0
  90. package/core/{context-sync.js → context-sync.ts} +59 -26
  91. package/core/data/agents-manager.ts +76 -0
  92. package/core/data/analysis-manager.ts +83 -0
  93. package/core/data/base-manager.ts +156 -0
  94. package/core/data/ideas-manager.ts +81 -0
  95. package/core/data/index.ts +32 -0
  96. package/core/data/outcomes-manager.ts +96 -0
  97. package/core/data/project-manager.ts +75 -0
  98. package/core/data/roadmap-manager.ts +118 -0
  99. package/core/data/shipped-manager.ts +65 -0
  100. package/core/data/state-manager.ts +214 -0
  101. package/core/domain/{agent-generator.js → agent-generator.ts} +77 -57
  102. package/core/domain/{agent-loader.js → agent-loader.ts} +65 -56
  103. package/core/domain/{agent-matcher.js → agent-matcher.ts} +51 -24
  104. package/core/domain/{agent-validator.js → agent-validator.ts} +70 -37
  105. package/core/domain/{analyzer.js → analyzer.ts} +91 -85
  106. package/core/domain/{architect-session.js → architect-session.ts} +49 -34
  107. package/core/domain/{architecture-generator.js → architecture-generator.ts} +25 -13
  108. package/core/domain/{context-estimator.js → context-estimator.ts} +57 -36
  109. package/core/domain/{product-standards.js → product-standards.ts} +40 -26
  110. package/core/domain/{smart-cache.js → smart-cache.ts} +39 -30
  111. package/core/domain/{snapshot-manager.js → snapshot-manager.ts} +103 -100
  112. package/core/domain/{task-analyzer.js → task-analyzer.ts} +82 -43
  113. package/core/domain/task-stack/index.ts +19 -0
  114. package/core/domain/task-stack/parser.ts +86 -0
  115. package/core/domain/task-stack/storage.ts +123 -0
  116. package/core/domain/task-stack/task-stack.ts +340 -0
  117. package/core/domain/task-stack/types.ts +51 -0
  118. package/core/domain/task-stack.ts +8 -0
  119. package/core/{index.js → index.ts} +61 -18
  120. package/core/infrastructure/{agent-detector.js → agent-detector.ts} +62 -23
  121. package/core/infrastructure/agents/{claude-agent.js → claude-agent.ts} +61 -21
  122. package/core/infrastructure/{author-detector.js → author-detector.ts} +42 -49
  123. package/core/infrastructure/{capability-installer.js → capability-installer.ts} +51 -27
  124. package/core/infrastructure/{command-installer.js → command-installer/command-installer.ts} +43 -144
  125. package/core/infrastructure/command-installer/global-config.ts +106 -0
  126. package/core/infrastructure/command-installer/index.ts +25 -0
  127. package/core/infrastructure/command-installer/types.ts +41 -0
  128. package/core/infrastructure/command-installer.ts +8 -0
  129. package/core/infrastructure/{config-manager.js → config-manager.ts} +60 -80
  130. package/core/infrastructure/{editors-config.js → editors-config.ts} +33 -31
  131. package/core/infrastructure/legacy-installer-detector/cleanup.ts +216 -0
  132. package/core/infrastructure/legacy-installer-detector/detection.ts +95 -0
  133. package/core/infrastructure/legacy-installer-detector/index.ts +171 -0
  134. package/core/infrastructure/legacy-installer-detector/migration.ts +87 -0
  135. package/core/infrastructure/legacy-installer-detector/types.ts +42 -0
  136. package/core/infrastructure/legacy-installer-detector.ts +7 -0
  137. package/core/infrastructure/migrator/file-operations.ts +125 -0
  138. package/core/infrastructure/migrator/index.ts +288 -0
  139. package/core/infrastructure/migrator/project-scanner.ts +89 -0
  140. package/core/infrastructure/migrator/reports.ts +117 -0
  141. package/core/infrastructure/migrator/types.ts +124 -0
  142. package/core/infrastructure/migrator/validation.ts +94 -0
  143. package/core/infrastructure/migrator/version-migration.ts +117 -0
  144. package/core/infrastructure/migrator.ts +10 -0
  145. package/core/infrastructure/{path-manager.js → path-manager.ts} +51 -91
  146. package/core/infrastructure/session-manager/index.ts +23 -0
  147. package/core/infrastructure/session-manager/migration.ts +88 -0
  148. package/core/infrastructure/session-manager/session-manager.ts +307 -0
  149. package/core/infrastructure/session-manager/types.ts +45 -0
  150. package/core/infrastructure/session-manager.ts +8 -0
  151. package/core/infrastructure/{setup.js → setup.ts} +29 -21
  152. package/core/infrastructure/{update-checker.js → update-checker.ts} +40 -18
  153. package/core/outcomes/analyzer.ts +333 -0
  154. package/core/outcomes/index.ts +34 -0
  155. package/core/outcomes/recorder.ts +194 -0
  156. package/core/outcomes/types.ts +145 -0
  157. package/core/plugin/{hooks.js → hooks.ts} +56 -58
  158. package/core/plugin/{index.js → index.ts} +19 -8
  159. package/core/plugin/{loader.js → loader.ts} +87 -69
  160. package/core/plugin/{registry.js → registry.ts} +49 -45
  161. package/core/plugins/{webhook.js → webhook.ts} +43 -27
  162. package/core/schemas/agents.ts +27 -0
  163. package/core/schemas/analysis.ts +41 -0
  164. package/core/schemas/ideas.ts +83 -0
  165. package/core/schemas/index.ts +73 -0
  166. package/core/schemas/outcomes.ts +22 -0
  167. package/core/schemas/project.ts +26 -0
  168. package/core/schemas/roadmap.ts +90 -0
  169. package/core/schemas/shipped.ts +82 -0
  170. package/core/schemas/state.ts +107 -0
  171. package/core/session/index.ts +17 -0
  172. package/core/session/{metrics.js → metrics.ts} +64 -46
  173. package/core/session/{index.js → session-manager.ts} +51 -117
  174. package/core/session/types.ts +29 -0
  175. package/core/session/utils.ts +57 -0
  176. package/core/state/index.ts +25 -0
  177. package/core/state/manager.ts +376 -0
  178. package/core/state/types.ts +185 -0
  179. package/core/tsconfig.json +22 -0
  180. package/core/types/index.ts +506 -0
  181. package/core/utils/{animations.js → animations.ts} +74 -28
  182. package/core/utils/{branding.js → branding.ts} +29 -4
  183. package/core/utils/{date-helper.js → date-helper.ts} +31 -74
  184. package/core/utils/file-helper.ts +262 -0
  185. package/core/utils/{jsonl-helper.js → jsonl-helper.ts} +71 -107
  186. package/core/utils/{logger.js → logger.ts} +24 -12
  187. package/core/utils/{output.js → output.ts} +25 -13
  188. package/core/utils/{project-capabilities.js → project-capabilities.ts} +31 -18
  189. package/core/utils/{session-helper.js → session-helper.ts} +79 -66
  190. package/core/utils/{version.js → version.ts} +23 -31
  191. package/core/view-generator.ts +536 -0
  192. package/package.json +23 -17
  193. package/packages/shared/.turbo/turbo-build.log +14 -0
  194. package/packages/shared/dist/index.d.ts +8 -613
  195. package/packages/shared/dist/index.d.ts.map +1 -0
  196. package/packages/shared/dist/index.js +4110 -118
  197. package/packages/shared/dist/schemas.d.ts +408 -0
  198. package/packages/shared/dist/schemas.d.ts.map +1 -0
  199. package/packages/shared/dist/types.d.ts +144 -0
  200. package/packages/shared/dist/types.d.ts.map +1 -0
  201. package/packages/shared/dist/unified.d.ts +139 -0
  202. package/packages/shared/dist/unified.d.ts.map +1 -0
  203. package/packages/shared/dist/utils.d.ts +60 -0
  204. package/packages/shared/dist/utils.d.ts.map +1 -0
  205. package/packages/shared/package.json +4 -4
  206. package/packages/shared/src/index.ts +1 -0
  207. package/packages/shared/src/unified.ts +174 -0
  208. package/packages/web/app/api/claude/sessions/route.ts +1 -1
  209. package/packages/web/app/api/claude/status/route.ts +1 -1
  210. package/packages/web/app/api/migrate/route.ts +46 -0
  211. package/packages/web/app/api/projects/[id]/route.ts +1 -1
  212. package/packages/web/app/api/projects/[id]/stats/route.ts +30 -2
  213. package/packages/web/app/api/projects/[id]/status/route.ts +1 -1
  214. package/packages/web/app/api/projects/route.ts +1 -1
  215. package/packages/web/app/api/settings/route.ts +97 -0
  216. package/packages/web/app/api/v2/projects/[id]/unified/route.ts +57 -0
  217. package/packages/web/app/globals.css +38 -0
  218. package/packages/web/app/layout.tsx +10 -2
  219. package/packages/web/app/page.tsx +9 -224
  220. package/packages/web/app/project/[id]/page.tsx +191 -63
  221. package/packages/web/app/project/[id]/stats/loading.tsx +43 -0
  222. package/packages/web/app/project/[id]/stats/page.tsx +203 -403
  223. package/packages/web/app/settings/page.tsx +222 -2
  224. package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +2 -0
  225. package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +50 -0
  226. package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +8 -0
  227. package/packages/web/components/ActivityTimeline/hooks/index.ts +2 -0
  228. package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +9 -0
  229. package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +23 -0
  230. package/packages/web/components/ActivityTimeline/index.ts +2 -0
  231. package/packages/web/components/AgentsCard/AgentsCard.tsx +63 -0
  232. package/packages/web/components/AgentsCard/AgentsCard.types.ts +13 -0
  233. package/packages/web/components/AgentsCard/index.ts +2 -0
  234. package/packages/web/components/AppSidebar/AppSidebar.tsx +134 -0
  235. package/packages/web/components/AppSidebar/index.ts +1 -0
  236. package/packages/web/components/BackLink/BackLink.tsx +18 -0
  237. package/packages/web/components/BackLink/BackLink.types.ts +5 -0
  238. package/packages/web/components/BackLink/index.ts +2 -0
  239. package/packages/web/components/BentoCard/BentoCard.constants.ts +16 -0
  240. package/packages/web/components/BentoCard/BentoCard.tsx +47 -0
  241. package/packages/web/components/BentoCard/BentoCard.types.ts +15 -0
  242. package/packages/web/components/BentoCard/index.ts +2 -0
  243. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +9 -0
  244. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +18 -0
  245. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +5 -0
  246. package/packages/web/components/BentoCardSkeleton/index.ts +2 -0
  247. package/packages/web/components/BentoGrid/BentoGrid.tsx +18 -0
  248. package/packages/web/components/BentoGrid/BentoGrid.types.ts +4 -0
  249. package/packages/web/components/BentoGrid/index.ts +2 -0
  250. package/packages/web/components/CommandButton/index.ts +1 -0
  251. package/packages/web/components/ConnectionStatus/index.ts +1 -0
  252. package/packages/web/components/DashboardContent/DashboardContent.tsx +254 -0
  253. package/packages/web/components/DashboardContent/index.ts +1 -0
  254. package/packages/web/components/DateGroup/DateGroup.tsx +18 -0
  255. package/packages/web/components/DateGroup/DateGroup.types.ts +6 -0
  256. package/packages/web/components/DateGroup/DateGroup.utils.ts +11 -0
  257. package/packages/web/components/DateGroup/index.ts +2 -0
  258. package/packages/web/components/EmptyState/EmptyState.tsx +58 -0
  259. package/packages/web/components/EmptyState/EmptyState.types.ts +10 -0
  260. package/packages/web/components/EmptyState/index.ts +2 -0
  261. package/packages/web/components/EventRow/EventRow.constants.ts +10 -0
  262. package/packages/web/components/EventRow/EventRow.tsx +49 -0
  263. package/packages/web/components/EventRow/EventRow.types.ts +7 -0
  264. package/packages/web/components/EventRow/EventRow.utils.ts +49 -0
  265. package/packages/web/components/EventRow/index.ts +2 -0
  266. package/packages/web/components/ExpandButton/ExpandButton.tsx +18 -0
  267. package/packages/web/components/ExpandButton/ExpandButton.types.ts +6 -0
  268. package/packages/web/components/ExpandButton/index.ts +2 -0
  269. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +14 -0
  270. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +5 -0
  271. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +13 -0
  272. package/packages/web/components/HealthGradientBackground/index.ts +2 -0
  273. package/packages/web/components/HeroSection/HeroSection.tsx +55 -0
  274. package/packages/web/components/HeroSection/HeroSection.types.ts +14 -0
  275. package/packages/web/components/HeroSection/HeroSection.utils.ts +7 -0
  276. package/packages/web/components/HeroSection/hooks/index.ts +2 -0
  277. package/packages/web/components/HeroSection/hooks/useCountUp.ts +45 -0
  278. package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +18 -0
  279. package/packages/web/components/HeroSection/index.ts +2 -0
  280. package/packages/web/components/IdeasCard/IdeasCard.tsx +48 -0
  281. package/packages/web/components/IdeasCard/IdeasCard.types.ts +9 -0
  282. package/packages/web/components/IdeasCard/index.ts +2 -0
  283. package/packages/web/components/InsightMessage/InsightMessage.tsx +9 -0
  284. package/packages/web/components/InsightMessage/InsightMessage.types.ts +3 -0
  285. package/packages/web/components/InsightMessage/index.ts +2 -0
  286. package/packages/web/components/Logo/index.ts +1 -0
  287. package/packages/web/components/MarkdownContent/index.ts +1 -0
  288. package/packages/web/components/NowCard/NowCard.tsx +93 -0
  289. package/packages/web/components/NowCard/NowCard.types.ts +15 -0
  290. package/packages/web/components/NowCard/index.ts +2 -0
  291. package/packages/web/components/ProgressRing/ProgressRing.constants.ts +20 -0
  292. package/packages/web/components/ProgressRing/ProgressRing.tsx +51 -0
  293. package/packages/web/components/ProgressRing/ProgressRing.types.ts +11 -0
  294. package/packages/web/components/ProgressRing/index.ts +2 -0
  295. package/packages/web/components/ProjectAvatar/index.ts +1 -0
  296. package/packages/web/components/Providers/index.ts +1 -0
  297. package/packages/web/components/QueueCard/QueueCard.tsx +72 -0
  298. package/packages/web/components/QueueCard/QueueCard.types.ts +11 -0
  299. package/packages/web/components/QueueCard/QueueCard.utils.ts +12 -0
  300. package/packages/web/components/QueueCard/index.ts +2 -0
  301. package/packages/web/components/RoadmapCard/RoadmapCard.tsx +77 -0
  302. package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +15 -0
  303. package/packages/web/components/RoadmapCard/index.ts +2 -0
  304. package/packages/web/components/ShipsCard/ShipsCard.tsx +52 -0
  305. package/packages/web/components/ShipsCard/ShipsCard.types.ts +12 -0
  306. package/packages/web/components/ShipsCard/ShipsCard.utils.ts +4 -0
  307. package/packages/web/components/ShipsCard/index.ts +2 -0
  308. package/packages/web/components/SparklineChart/SparklineChart.tsx +38 -0
  309. package/packages/web/components/SparklineChart/SparklineChart.types.ts +6 -0
  310. package/packages/web/components/SparklineChart/index.ts +2 -0
  311. package/packages/web/components/StreakCard/StreakCard.constants.ts +2 -0
  312. package/packages/web/components/StreakCard/StreakCard.tsx +53 -0
  313. package/packages/web/components/StreakCard/StreakCard.types.ts +4 -0
  314. package/packages/web/components/StreakCard/index.ts +2 -0
  315. package/packages/web/components/TasksCounter/TasksCounter.tsx +14 -0
  316. package/packages/web/components/TasksCounter/TasksCounter.types.ts +3 -0
  317. package/packages/web/components/TasksCounter/index.ts +2 -0
  318. package/packages/web/components/TechStackBadges/index.ts +1 -0
  319. package/packages/web/components/{TerminalTab.tsx → TerminalTabs/TerminalTab.tsx} +11 -0
  320. package/packages/web/components/{TerminalTabs.tsx → TerminalTabs/TerminalTabs.tsx} +29 -28
  321. package/packages/web/components/TerminalTabs/index.ts +1 -0
  322. package/packages/web/components/VelocityBadge/VelocityBadge.tsx +27 -0
  323. package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +3 -0
  324. package/packages/web/components/VelocityBadge/index.ts +2 -0
  325. package/packages/web/components/VelocityCard/VelocityCard.tsx +71 -0
  326. package/packages/web/components/VelocityCard/VelocityCard.types.ts +7 -0
  327. package/packages/web/components/VelocityCard/index.ts +2 -0
  328. package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +13 -0
  329. package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +3 -0
  330. package/packages/web/components/WeeklySparkline/index.ts +2 -0
  331. package/packages/web/components/ui/input.tsx +21 -0
  332. package/packages/web/components/ui/tooltip.tsx +2 -2
  333. package/packages/web/context/TerminalTabsContext.tsx +46 -1
  334. package/packages/web/hooks/useClaudeTerminal.ts +71 -21
  335. package/packages/web/hooks/useProjectStats.ts +55 -0
  336. package/packages/web/hooks/useProjects.ts +6 -6
  337. package/packages/web/lib/actions/projects.ts +15 -0
  338. package/packages/web/lib/json-loader.ts +630 -0
  339. package/packages/web/lib/services/index.ts +9 -0
  340. package/packages/web/lib/services/migration.server.ts +598 -0
  341. package/packages/web/lib/services/projects.server.ts +52 -0
  342. package/packages/web/lib/services/stats.server.ts +264 -0
  343. package/packages/web/lib/unified-loader.ts +396 -0
  344. package/packages/web/next-env.d.ts +1 -1
  345. package/packages/web/package.json +10 -6
  346. package/packages/web/server.ts +36 -6
  347. package/templates/commands/done.md +76 -32
  348. package/templates/commands/feature.md +121 -47
  349. package/templates/commands/idea.md +81 -8
  350. package/templates/commands/now.md +41 -17
  351. package/templates/commands/ship.md +64 -25
  352. package/templates/commands/sync.md +28 -3
  353. package/core/agentic/agent-router.js +0 -128
  354. package/core/agentic/chain-of-thought.js +0 -578
  355. package/core/agentic/command-executor.js +0 -421
  356. package/core/agentic/context-filter.js +0 -354
  357. package/core/agentic/ground-truth.js +0 -591
  358. package/core/agentic/loop-detector.js +0 -406
  359. package/core/agentic/memory-system.js +0 -850
  360. package/core/agentic/parallel-tools.js +0 -366
  361. package/core/agentic/plan-mode.js +0 -572
  362. package/core/agentic/prompt-builder.js +0 -338
  363. package/core/agentic/response-templates.js +0 -290
  364. package/core/agentic/semantic-compression.js +0 -517
  365. package/core/agentic/think-blocks.js +0 -657
  366. package/core/agentic/tool-registry.js +0 -184
  367. package/core/agentic/validation-rules.js +0 -380
  368. package/core/command-registry.js +0 -698
  369. package/core/commands.js +0 -2237
  370. package/core/domain/task-stack.js +0 -497
  371. package/core/infrastructure/legacy-installer-detector.js +0 -546
  372. package/core/infrastructure/migrator.js +0 -799
  373. package/core/infrastructure/session-manager.js +0 -390
  374. package/core/utils/file-helper.js +0 -329
  375. package/packages/web/app/api/projects/[id]/delete/route.ts +0 -21
  376. package/packages/web/app/api/stats/route.ts +0 -38
  377. package/packages/web/components/AppSidebar.tsx +0 -113
  378. package/packages/web/hooks/useStats.ts +0 -28
  379. /package/packages/web/components/{CommandButton.tsx → CommandButton/CommandButton.tsx} +0 -0
  380. /package/packages/web/components/{ConnectionStatus.tsx → ConnectionStatus/ConnectionStatus.tsx} +0 -0
  381. /package/packages/web/components/{Logo.tsx → Logo/Logo.tsx} +0 -0
  382. /package/packages/web/components/{MarkdownContent.tsx → MarkdownContent/MarkdownContent.tsx} +0 -0
  383. /package/packages/web/components/{ProjectAvatar.tsx → ProjectAvatar/ProjectAvatar.tsx} +0 -0
  384. /package/packages/web/components/{providers.tsx → Providers/Providers.tsx} +0 -0
  385. /package/packages/web/components/{TechStackBadges.tsx → TechStackBadges/TechStackBadges.tsx} +0 -0
@@ -1,447 +1,247 @@
1
- 'use client'
2
-
3
- import { use, useMemo, useState } from 'react'
4
- import { useRouter } from 'next/navigation'
5
- import Link from 'next/link'
6
- import { useProject } from '@/hooks/useProjects'
7
- import { useProjectStats } from '@/hooks/useProjectStats'
8
- import { Button } from '@/components/ui/button'
1
+ import { notFound } from 'next/navigation'
9
2
  import {
10
- ArrowLeft,
11
- Zap,
12
- TrendingUp,
13
- TrendingDown,
14
- Lightbulb,
15
- AlertTriangle,
16
- CheckCircle2,
17
- Bot,
18
- Rocket,
19
- Flame,
20
- Play,
21
- Copy,
22
- FileText,
23
- Target,
24
- Clock
25
- } from 'lucide-react'
26
- import { cn } from '@/lib/utils'
3
+ getStats,
4
+ getInsightMessage,
5
+ calculateStreak,
6
+ calculateHealthScore,
7
+ getVelocityChange,
8
+ getWeeklyVelocityData,
9
+ type StatsResult
10
+ } from '@/lib/services/stats.server'
11
+ import { getProject } from '@/lib/services/projects.server'
27
12
  import type { TimelineEvent } from '@/lib/parse-prjct-files'
28
13
 
29
- // Calculate streak
30
- function calculateStreak(timeline: TimelineEvent[]): number {
31
- if (!timeline.length) return 0
32
- const dates = new Set(timeline.map(e => e.ts?.split('T')[0]).filter(Boolean))
33
- let streak = 0
34
- const today = new Date()
35
- for (let i = 0; i < 30; i++) {
36
- const date = new Date(today)
37
- date.setDate(date.getDate() - i)
38
- const dateStr = date.toISOString().split('T')[0]
39
- if (dates.has(dateStr)) streak++
40
- else if (i > 0) break
41
- }
42
- return streak
14
+ import { BentoGrid } from '@/components/BentoGrid'
15
+ import { HeroSection } from '@/components/HeroSection'
16
+ import { NowCard } from '@/components/NowCard'
17
+ import { VelocityCard } from '@/components/VelocityCard'
18
+ import { StreakCard } from '@/components/StreakCard'
19
+ import { QueueCard } from '@/components/QueueCard'
20
+ import { ShipsCard } from '@/components/ShipsCard'
21
+ import { IdeasCard } from '@/components/IdeasCard'
22
+ import { AgentsCard } from '@/components/AgentsCard'
23
+ import { RoadmapCard } from '@/components/RoadmapCard'
24
+ import { ActivityTimeline } from '@/components/ActivityTimeline'
25
+
26
+ // Types for normalized component data
27
+ interface NormalizedCurrentTask {
28
+ task: string
29
+ startedAt?: string
30
+ agent?: string
31
+ estimatedDuration?: string
32
+ pausedAt?: string
33
+ pauseReason?: string
43
34
  }
44
35
 
45
- // Health score (0-100)
46
- function getHealthScore(stats: any): number {
47
- if (!stats) return 0
48
- const velocity = stats?.metrics?.velocity?.tasksPerDay || 0
49
- const hasCurrentTask = !!stats?.currentTask
50
- const queueSize = stats?.queue?.length || 0
51
- const recentActivity = stats?.timeline?.slice(0, 7).length || 0
52
-
53
- let score = 0
54
- score += Math.min(30, velocity * 15) // Up to 30 for velocity
55
- score += hasCurrentTask ? 20 : 0 // 20 for active work
56
- score += queueSize > 0 && queueSize < 15 ? 20 : queueSize === 0 ? 5 : 10 // Queue health
57
- score += Math.min(30, recentActivity * 5) // Recent activity
58
-
59
- return Math.min(100, Math.round(score))
36
+ interface NormalizedQueueItem {
37
+ task: string
38
+ priority?: 'low' | 'medium' | 'high' | 'critical' | number
39
+ estimatedDuration?: string
60
40
  }
61
41
 
62
- // Copy to clipboard
63
- function copyCommand(cmd: string) {
64
- navigator.clipboard.writeText(cmd)
42
+ interface NormalizedShip {
43
+ name: string
44
+ date: string
45
+ duration?: string
65
46
  }
66
47
 
67
- // Format relative time
68
- function formatRelativeTime(dateString: string): string {
69
- const date = new Date(dateString)
70
- const now = new Date()
71
- const diffMs = now.getTime() - date.getTime()
72
- const diffMins = Math.floor(diffMs / 60000)
73
- const diffHours = Math.floor(diffMs / 3600000)
74
- const diffDays = Math.floor(diffMs / 86400000)
75
-
76
- if (diffMins < 1) return 'NOW'
77
- if (diffMins < 60) return `${diffMins}M`
78
- if (diffHours < 24) return `${diffHours}H`
79
- if (diffDays === 1) return '1D'
80
- if (diffDays < 7) return `${diffDays}D`
81
- return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }).toUpperCase()
48
+ interface NormalizedIdea {
49
+ title: string
50
+ impact?: string
82
51
  }
83
52
 
84
- // Contextual insight message
85
- function getInsightMessage(stats: any, streak: number): string {
86
- if (!stats) return ''
53
+ interface NormalizedAgent {
54
+ name: string
55
+ description?: string
56
+ successRate?: number
57
+ tasksCompleted?: number
58
+ bestFor?: string[]
59
+ }
87
60
 
88
- const velocity = stats?.metrics?.velocity?.tasksPerDay || 0
89
- const hasCurrentTask = !!stats?.currentTask
90
- const queueSize = stats?.queue?.length || 0
91
- const shipsCount = stats?.summary?.totalShipsEver || 0
61
+ interface NormalizedRoadmap {
62
+ phases: Array<{
63
+ name: string
64
+ progress: number
65
+ features?: Array<{ name: string; status: string }>
66
+ }>
67
+ progress: number
68
+ }
92
69
 
93
- if (hasCurrentTask && streak > 3) return 'Killing it. Keep the momentum.'
94
- if (hasCurrentTask) return 'Good focus. Ship when ready.'
95
- if (queueSize === 0) return 'Queue empty. Time to plan the next feature.'
96
- if (velocity > 2) return 'Fast pace. Watch for burnout.'
97
- if (shipsCount === 0) return 'No ships yet. Start small, ship fast.'
98
- if (streak === 0) return 'Get back in the flow. Start something.'
99
- return 'Steady progress. Pick the next task.'
70
+ // Data normalization functions
71
+ function normalizeCurrentTask(stats: StatsResult): NormalizedCurrentTask | null {
72
+ if (stats.state?.currentTask) {
73
+ return {
74
+ task: stats.state.currentTask.description,
75
+ startedAt: stats.state.currentTask.startedAt,
76
+ // Simplified - removed legacy fields not in new schema
77
+ }
78
+ }
79
+ return stats.legacyStats?.currentTask ?? null
100
80
  }
101
81
 
102
- // Section label component
103
- function SectionLabel({ children, className }: { children: React.ReactNode; className?: string }) {
104
- return (
105
- <p className={cn("text-[9px] font-bold uppercase tracking-[0.2em] text-foreground/40", className)}>
106
- {children}
107
- </p>
108
- )
82
+ function normalizeQueue(stats: StatsResult): NormalizedQueueItem[] {
83
+ if (stats.queue?.tasks) {
84
+ return stats.queue.tasks
85
+ .filter(t => !t.completed)
86
+ .map(q => ({
87
+ task: q.description,
88
+ priority: q.priority,
89
+ }))
90
+ }
91
+ return stats.legacyStats?.queue ?? []
109
92
  }
110
93
 
111
- // Health ring component
112
- function HealthRing({ score, size = 'md' }: { score: number; size?: 'sm' | 'md' | 'lg' }) {
113
- const sizes = {
114
- sm: { container: 'h-8 w-8', text: 'text-[10px]' },
115
- md: { container: 'h-12 w-12', text: 'text-xs' },
116
- lg: { container: 'h-16 w-16', text: 'text-sm' },
94
+ function normalizeRoadmap(stats: StatsResult): NormalizedRoadmap | null {
95
+ const features = stats.roadmap?.features ?? []
96
+ if (features.length > 0) {
97
+ const completed = features.filter(f =>
98
+ f.status === 'shipped' || f.status === 'completed'
99
+ ).length
100
+
101
+ return {
102
+ phases: features.map(f => ({
103
+ name: f.name,
104
+ progress: f.status === 'shipped' || f.status === 'completed' ? 100 :
105
+ f.status === 'active' ? 50 : 0,
106
+ features: f.tasks.map(t => ({
107
+ name: t.description,
108
+ status: t.completed ? 'completed' : 'pending'
109
+ }))
110
+ })),
111
+ progress: Math.round((completed / features.length) * 100)
112
+ }
117
113
  }
118
- const { container, text } = sizes[size]
114
+ return stats.legacyStats?.roadmap ?? null
115
+ }
119
116
 
120
- return (
121
- <div className={cn('relative', container)}>
122
- <svg className="h-full w-full -rotate-90" viewBox="0 0 36 36">
123
- <circle cx="18" cy="18" r="15" fill="none" stroke="currentColor" strokeWidth="3" className="text-foreground/10" />
124
- <circle
125
- cx="18" cy="18" r="15" fill="none" stroke="currentColor" strokeWidth="3"
126
- strokeDasharray={`${score} 100`}
127
- strokeLinecap="round"
128
- className="text-foreground transition-all duration-700"
129
- />
130
- </svg>
131
- <span className={cn('absolute inset-0 flex items-center justify-center font-bold', text)}>
132
- {score}
133
- </span>
134
- </div>
135
- )
117
+ function normalizeShipped(stats: StatsResult): NormalizedShip[] {
118
+ const items = stats.shipped?.items ?? []
119
+ return items.map(s => ({
120
+ name: s.name,
121
+ date: s.shippedAt,
122
+ }))
136
123
  }
137
124
 
138
- // Stat card component
139
- function StatCard({ value, label, suffix, size = 'md' }: {
140
- value: string | number
141
- label: string
142
- suffix?: string
143
- size?: 'sm' | 'md' | 'lg'
144
- }) {
145
- const sizeClasses = {
146
- sm: { value: 'text-lg font-bold', label: 'text-[9px] font-bold uppercase tracking-[0.2em] text-foreground/40' },
147
- md: { value: 'text-2xl font-bold', label: 'text-xs text-muted-foreground' },
148
- lg: { value: 'text-3xl font-black tracking-tight tabular-nums', label: 'text-[9px] font-bold uppercase tracking-[0.2em] text-foreground/40 mt-1' },
149
- }
150
- const styles = sizeClasses[size]
125
+ function normalizeIdeas(stats: StatsResult): NormalizedIdea[] {
126
+ const ideas = stats.ideas?.ideas ?? []
127
+ return ideas
128
+ .filter(i => i.status === 'pending')
129
+ .map(i => ({
130
+ title: i.text,
131
+ impact: i.priority.toUpperCase()
132
+ }))
133
+ }
151
134
 
152
- return (
153
- <div>
154
- <p className={cn(styles.value, 'text-foreground')}>
155
- {value}
156
- {suffix && <span className="text-foreground/50 font-normal text-sm ml-1">{suffix}</span>}
157
- </p>
158
- <p className={styles.label}>{label}</p>
159
- </div>
160
- )
135
+ function normalizeAgents(stats: StatsResult): NormalizedAgent[] {
136
+ return stats.agents.map(a => ({
137
+ name: a.name,
138
+ description: a.description,
139
+ successRate: a.successRate,
140
+ tasksCompleted: a.tasksCompleted,
141
+ bestFor: a.bestFor,
142
+ }))
161
143
  }
162
144
 
163
- // Stats row component - minimal divider
164
- function StatsRow({ children, className }: { children: React.ReactNode; className?: string }) {
165
- return (
166
- <div className={cn('flex flex-wrap gap-x-10 gap-y-4', className)}>
167
- {children}
168
- </div>
169
- )
145
+ function normalizeTimeline(stats: StatsResult): TimelineEvent[] {
146
+ if (stats.metrics?.recentActivity?.length) {
147
+ return stats.metrics.recentActivity.map((a: { timestamp: string; description: string; action?: string }) => ({
148
+ ts: a.timestamp,
149
+ type: a.action || 'task_completed',
150
+ task: a.description,
151
+ }))
152
+ }
153
+ return stats.legacyStats?.timeline ?? []
170
154
  }
171
155
 
172
- export default function ProjectStatsPage({ params }: { params: Promise<{ id: string }> }) {
173
- const { id: projectId } = use(params)
174
- const router = useRouter()
175
- const [expandedSection, setExpandedSection] = useState<string | null>(null)
156
+ function getVelocity(stats: StatsResult): number {
157
+ if (stats.metrics?.velocity?.tasksPerDay) {
158
+ return stats.metrics.velocity.tasksPerDay
159
+ }
160
+ return stats.legacyStats?.metrics?.velocity?.tasksPerDay ?? 0
161
+ }
176
162
 
177
- const { data: project, isLoading: projectLoading } = useProject(projectId)
178
- const { data, isLoading: statsLoading } = useProjectStats(projectId)
179
- const stats = data?.stats
163
+ function getTotalShips(stats: StatsResult): number {
164
+ return stats.shipped?.items?.length ?? stats.legacyStats?.summary?.totalShipsEver ?? 0
165
+ }
180
166
 
181
- const streak = useMemo(() => calculateStreak(stats?.timeline || []), [stats?.timeline])
182
- const healthScore = useMemo(() => getHealthScore(stats), [stats])
183
- const insightMessage = useMemo(() => getInsightMessage(stats, streak), [stats, streak])
167
+ function getTasksCompleted(stats: StatsResult): number {
168
+ return stats.metrics?.currentSprint?.tasksCompleted ?? stats.legacyStats?.metrics?.tasksCompleted ?? 0
169
+ }
184
170
 
185
- const completionRate = useMemo(() => {
186
- if (!stats?.metrics) return 0
187
- const { tasksStarted, tasksCompleted } = stats.metrics
188
- return tasksStarted > 0 ? Math.round((tasksCompleted / tasksStarted) * 100) : 0
189
- }, [stats?.metrics])
171
+ interface PageProps {
172
+ params: Promise<{ id: string }>
173
+ }
190
174
 
191
- const velocityChange = useMemo(() => {
192
- // Simulated - in reality would compare to previous period
193
- const velocity = stats?.metrics?.velocity?.tasksPerDay || 0
194
- return velocity > 2 ? 15 : velocity > 1 ? 5 : -10
195
- }, [stats?.metrics?.velocity?.tasksPerDay])
175
+ export default async function ProjectStatsPage({ params }: PageProps) {
176
+ const { id: projectId } = await params
196
177
 
197
- // Recent activity - last 5 for chips
198
- const recentActivity = useMemo(() => {
199
- if (!stats?.timeline) return []
200
- return stats.timeline.slice(0, 5)
201
- }, [stats?.timeline])
178
+ // Fetch data directly on server - no API calls
179
+ const [project, stats] = await Promise.all([
180
+ getProject(projectId),
181
+ getStats(projectId)
182
+ ])
202
183
 
203
- if (projectLoading || statsLoading) {
204
- return <div className="flex items-center justify-center h-full"><div className="animate-pulse text-muted-foreground">Loading...</div></div>
184
+ if (!stats.hasData) {
185
+ notFound()
205
186
  }
206
187
 
207
- if (!project || !stats) {
208
- return (
209
- <div className="flex items-center justify-center h-full">
210
- <div className="text-center space-y-4">
211
- <p className="text-4xl text-muted-foreground">404</p>
212
- <Button variant="ghost" onClick={() => router.back()}><ArrowLeft className="w-4 h-4 mr-2" />Back</Button>
213
- </div>
214
- </div>
215
- )
216
- }
188
+ // Compute derived values using service functions
189
+ const streak = calculateStreak(stats.metrics)
190
+ const healthScore = calculateHealthScore(stats)
191
+ const velocity = getVelocity(stats)
192
+ const velocityChange = getVelocityChange(velocity)
193
+ const insightMessage = getInsightMessage(stats, streak)
194
+ const weeklyVelocityData = getWeeklyVelocityData(stats.metrics)
195
+
196
+ // Normalize data for components
197
+ const currentTask = normalizeCurrentTask(stats)
198
+ const queue = normalizeQueue(stats)
199
+ const roadmap = normalizeRoadmap(stats)
200
+ const shipped = normalizeShipped(stats)
201
+ const ideas = normalizeIdeas(stats)
202
+ const agents = normalizeAgents(stats)
203
+ const timeline = normalizeTimeline(stats)
204
+ const totalShips = getTotalShips(stats)
205
+ const tasksCompleted = getTasksCompleted(stats)
217
206
 
218
207
  return (
219
- <div className="flex h-full flex-col p-8 overflow-auto">
220
- {/* Hero Section - Big number + insight */}
221
- <div className="flex items-start justify-between mb-2">
222
- <div>
223
- {/* Big Number - Tasks Completed */}
224
- <h1 className="text-8xl font-bold tracking-tighter text-foreground tabular-nums">
225
- {stats.metrics.tasksCompleted}
226
- </h1>
227
- <p className="text-lg text-muted-foreground mt-2">{insightMessage}</p>
228
- </div>
229
-
230
- {/* Navigation back */}
231
- <Link href={`/project/${projectId}`} className="flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground">
232
- <ArrowLeft className="w-4 h-4" />{project.name}
233
- </Link>
208
+ <div className="flex h-full flex-col p-4 md:p-8 overflow-auto">
209
+ {/* Mobile: Add padding for hamburger menu */}
210
+ <div className="pl-10 md:pl-0">
211
+ <HeroSection
212
+ projectId={projectId}
213
+ projectName={project?.name ?? projectId}
214
+ tasksCompleted={tasksCompleted}
215
+ healthScore={healthScore}
216
+ velocity={velocity}
217
+ velocityChange={velocityChange}
218
+ insightMessage={insightMessage}
219
+ timeline={timeline}
220
+ />
234
221
  </div>
235
222
 
236
- {/* Trend indicator */}
237
- {velocityChange !== 0 && (
238
- <div className="flex items-center gap-2 mt-4">
239
- <span className={cn(
240
- 'flex items-center gap-1 text-sm font-medium px-2 py-1 rounded-md',
241
- velocityChange >= 0 ? 'bg-foreground/5 text-foreground' : 'bg-muted text-muted-foreground'
242
- )}>
243
- {velocityChange >= 0 ? <TrendingUp className="h-3.5 w-3.5" /> : <TrendingDown className="h-3.5 w-3.5" />}
244
- {velocityChange >= 0 ? '+' : ''}{velocityChange}%
245
- </span>
246
- <span className="text-sm text-muted-foreground">velocity vs last week</span>
247
- </div>
248
- )}
249
-
250
- {/* Secondary KPIs Row */}
251
- <StatsRow className="mt-8">
252
- <div className="flex items-center gap-3">
253
- <HealthRing score={healthScore} />
254
- <div>
255
- <p className="text-sm font-medium">Health</p>
256
- <p className="text-xs text-muted-foreground">Project score</p>
257
- </div>
258
- </div>
259
-
260
- <StatCard value={`${completionRate}%`} label="Completion" />
261
- <StatCard value={stats.summary.totalShipsEver} label="Ships" />
262
- <StatCard value={stats.metrics.velocity.tasksPerDay} label="Tasks/day" />
263
- <StatCard
264
- value={<>{stats.queue.length} / {stats.ideas.pending.length}</>}
265
- label="Queue / Ideas"
223
+ {/* Bento Grid - Server Components */}
224
+ <BentoGrid className="mt-6 md:mt-8">
225
+ <NowCard currentTask={currentTask} />
226
+ <VelocityCard
227
+ tasksPerDay={velocity}
228
+ weeklyData={weeklyVelocityData}
229
+ change={velocityChange}
266
230
  />
267
- {streak > 0 && (
268
- <div className="flex items-center gap-2">
269
- <Flame className={cn('w-5 h-5', streak > 3 ? 'text-orange-500' : 'text-foreground/40')} />
270
- <StatCard value={streak} label="Day streak" />
271
- </div>
272
- )}
273
- </StatsRow>
274
-
275
- {/* Recent Activity - Chips style */}
276
- {recentActivity.length > 0 && (
277
- <div className="mt-8">
278
- <SectionLabel className="mb-4">RECENT</SectionLabel>
279
- <div className="flex flex-wrap gap-3">
280
- {recentActivity.map((event: TimelineEvent, i: number) => {
281
- const e = event as Record<string, unknown>
282
- const label = event.type === 'feature_ship' ? (e.name as string) :
283
- event.type === 'task_complete' ? (e.task as string) :
284
- event.type === 'task_start' ? (e.task as string) :
285
- event.type === 'sync' ? 'Sync' : event.type
286
- const status = event.type === 'feature_ship' ? 'SHIP' :
287
- event.type === 'task_complete' ? 'DONE' :
288
- event.type === 'task_start' ? 'START' :
289
- event.type === 'sync' ? 'SYNC' : event.type.toUpperCase()
290
- return (
291
- <div
292
- key={i}
293
- className="group flex items-center gap-3 rounded-lg border-2 border-foreground/10 px-4 py-2 transition-all hover:border-foreground hover:bg-foreground hover:text-background cursor-default"
294
- >
295
- <span className="text-sm font-bold text-foreground group-hover:text-background truncate max-w-[150px]">
296
- {label}
297
- </span>
298
- <span className="text-[9px] font-bold tracking-wider text-foreground/40 group-hover:text-background/60">
299
- {status}
300
- </span>
301
- {event.ts && (
302
- <span className="text-[9px] font-bold tracking-wider text-foreground/30 group-hover:text-background/40">
303
- {formatRelativeTime(event.ts)}
304
- </span>
305
- )}
306
- </div>
307
- )
308
- })}
309
- </div>
310
- </div>
311
- )}
312
-
313
- {/* Masonry Grid Layout */}
314
- <div className="columns-1 md:columns-2 lg:columns-3 gap-8 mt-10 [column-fill:_balance]">
315
- {/* Current Task */}
316
- <div className="break-inside-avoid mb-8">
317
- <SectionLabel className="mb-3">NOW</SectionLabel>
318
- {stats.currentTask ? (
319
- <div>
320
- <div className="flex items-center gap-2 mb-2">
321
- <div className="w-1.5 h-1.5 rounded-full bg-amber-500 animate-pulse" />
322
- <span className="text-[10px] font-medium text-amber-600 uppercase tracking-wider">Working</span>
323
- </div>
324
- <p className="text-lg font-semibold leading-tight">{stats.currentTask.task}</p>
325
- {stats.currentTask.duration && (
326
- <p className="text-xs text-muted-foreground mt-2">{stats.currentTask.duration}</p>
327
- )}
328
- </div>
329
- ) : (
330
- <p className="text-sm text-muted-foreground">No active task</p>
331
- )}
332
- </div>
333
-
334
- {/* Queue */}
335
- {stats.queue.length > 0 && (
336
- <div className="break-inside-avoid mb-8">
337
- <div className="flex items-center gap-2 mb-3">
338
- <SectionLabel>QUEUE</SectionLabel>
339
- <span className="text-xs text-muted-foreground">{stats.queue.length}</span>
340
- </div>
341
- <div className="space-y-1.5">
342
- {stats.queue.slice(0, 6).map((task: any, i: number) => (
343
- <div key={i} className="flex items-center gap-2 group">
344
- <span className="text-[10px] text-muted-foreground w-3">{i + 1}</span>
345
- <p className="flex-1 text-sm truncate">{task.task}</p>
346
- </div>
347
- ))}
348
- {stats.queue.length > 6 && (
349
- <p className="text-[10px] text-muted-foreground">+{stats.queue.length - 6} more</p>
350
- )}
351
- </div>
352
- </div>
353
- )}
354
-
355
- {/* Ships */}
356
- {stats.shipped.length > 0 && (
357
- <div className="break-inside-avoid mb-8">
358
- <SectionLabel className="mb-3">SHIPS</SectionLabel>
359
- <div className="space-y-3">
360
- {stats.shipped.slice(0, 5).map((ship: any, i: number) => (
361
- <div key={i}>
362
- <p className="text-sm font-medium">{ship.name}</p>
363
- <p className="text-[10px] text-muted-foreground">
364
- {new Date(ship.date).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}
365
- {ship.version && ` · ${ship.version}`}
366
- </p>
367
- </div>
368
- ))}
369
- </div>
370
- </div>
371
- )}
372
-
373
- {/* Agents */}
374
- {stats.agents.length > 0 && (
375
- <div className="break-inside-avoid mb-8">
376
- <div className="flex items-center gap-2 mb-3">
377
- <SectionLabel>AGENTS</SectionLabel>
378
- <span className="text-xs text-muted-foreground">{stats.agents.length}</span>
379
- </div>
380
- <div className="flex flex-wrap gap-1.5">
381
- {stats.agents.slice(0, 10).map((agent: any) => (
382
- <span
383
- key={agent.name}
384
- className="text-xs px-2 py-0.5 bg-foreground/5 rounded"
385
- >
386
- {agent.name}
387
- </span>
388
- ))}
389
- </div>
390
- </div>
391
- )}
392
-
393
- {/* Ideas */}
394
- {stats.ideas.pending.length > 0 && (
395
- <div className="break-inside-avoid mb-8">
396
- <div className="flex items-center gap-2 mb-3">
397
- <SectionLabel>IDEAS</SectionLabel>
398
- <span className="text-xs text-muted-foreground">{stats.ideas.pending.length}</span>
399
- </div>
400
- <div className="space-y-2">
401
- {stats.ideas.pending.slice(0, 5).map((idea: any, i: number) => (
402
- <div key={i} className="flex items-start gap-2">
403
- <Lightbulb className={cn(
404
- 'w-3 h-3 mt-0.5 shrink-0',
405
- idea.impact === 'HIGH' ? 'text-foreground' : 'text-muted-foreground'
406
- )} />
407
- <p className="text-sm">{idea.title}</p>
408
- </div>
409
- ))}
410
- </div>
411
- </div>
412
- )}
413
-
414
- {/* Roadmap */}
415
- {stats.roadmap?.phases?.length > 0 && (
416
- <div className="break-inside-avoid mb-8">
417
- <div className="flex items-center justify-between mb-3">
418
- <SectionLabel>ROADMAP</SectionLabel>
419
- <span className="text-lg font-bold">{stats.roadmap.progress}%</span>
420
- </div>
421
- <div className="space-y-2">
422
- {stats.roadmap.phases.filter((p: any) => (p.features || []).length > 0).slice(0, 4).map((phase: any) => (
423
- <div key={phase.name}>
424
- <div className="flex items-center justify-between text-xs mb-1">
425
- <span>{phase.name}</span>
426
- <span className="text-muted-foreground">{phase.progress}%</span>
427
- </div>
428
- <div className="h-1 bg-muted rounded-full overflow-hidden">
429
- <div
430
- className={cn(
431
- 'h-full rounded-full',
432
- phase.progress === 100 ? 'bg-emerald-500' : 'bg-foreground'
433
- )}
434
- style={{ width: `${phase.progress}%` }}
435
- />
436
- </div>
437
- </div>
438
- ))}
439
- </div>
440
- </div>
441
- )}
231
+ <RoadmapCard roadmap={roadmap} />
232
+ <StreakCard streak={streak} />
233
+ <QueueCard queue={queue} />
234
+ <ShipsCard ships={shipped} totalShips={totalShips} />
235
+ <IdeasCard ideas={ideas} />
236
+ <AgentsCard agents={agents} />
237
+ </BentoGrid>
238
+
239
+ {/* Activity Timeline - Client Component */}
240
+ <div className="mt-6 md:mt-8">
241
+ <ActivityTimeline timeline={timeline} />
442
242
  </div>
443
243
 
444
- <div className="h-8" />
244
+ <div className="h-6 md:h-8" />
445
245
  </div>
446
246
  )
447
247
  }