prjct-cli 0.11.5 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +81 -25
  3. package/bin/dev.js +1 -1
  4. package/bin/generate-views.js +209 -0
  5. package/bin/migrate-to-json.js +742 -0
  6. package/bin/prjct +5 -5
  7. package/bin/serve.js +226 -50
  8. package/core/__tests__/agentic/{memory-system.test.js → memory-system.test.ts} +12 -23
  9. package/core/__tests__/agentic/{plan-mode.test.js → plan-mode.test.ts} +26 -24
  10. package/core/__tests__/agentic/{prompt-builder.test.js → prompt-builder.test.ts} +3 -8
  11. package/core/__tests__/utils/{date-helper.test.js → date-helper.test.ts} +19 -30
  12. package/core/__tests__/utils/{output.test.js → output.test.ts} +12 -24
  13. package/core/agentic/agent-router.ts +137 -0
  14. package/core/agentic/chain-of-thought.ts +228 -0
  15. package/core/agentic/command-executor/command-executor.ts +384 -0
  16. package/core/agentic/command-executor/index.ts +16 -0
  17. package/core/agentic/command-executor/status-signal.ts +38 -0
  18. package/core/agentic/command-executor/types.ts +79 -0
  19. package/core/agentic/command-executor.ts +8 -0
  20. package/core/agentic/{context-builder.js → context-builder.ts} +92 -81
  21. package/core/agentic/context-filter.ts +365 -0
  22. package/core/agentic/ground-truth/index.ts +76 -0
  23. package/core/agentic/ground-truth/types.ts +33 -0
  24. package/core/agentic/ground-truth/utils.ts +48 -0
  25. package/core/agentic/ground-truth/verifiers/analyze.ts +54 -0
  26. package/core/agentic/ground-truth/verifiers/done.ts +75 -0
  27. package/core/agentic/ground-truth/verifiers/feature.ts +70 -0
  28. package/core/agentic/ground-truth/verifiers/index.ts +37 -0
  29. package/core/agentic/ground-truth/verifiers/init.ts +52 -0
  30. package/core/agentic/ground-truth/verifiers/now.ts +57 -0
  31. package/core/agentic/ground-truth/verifiers/ship.ts +85 -0
  32. package/core/agentic/ground-truth/verifiers/spec.ts +45 -0
  33. package/core/agentic/ground-truth/verifiers/sync.ts +47 -0
  34. package/core/agentic/ground-truth/verifiers.ts +6 -0
  35. package/core/agentic/ground-truth.ts +8 -0
  36. package/core/agentic/loop-detector/error-analysis.ts +97 -0
  37. package/core/agentic/loop-detector/hallucination.ts +71 -0
  38. package/core/agentic/loop-detector/index.ts +41 -0
  39. package/core/agentic/loop-detector/loop-detector.ts +222 -0
  40. package/core/agentic/loop-detector/types.ts +66 -0
  41. package/core/agentic/loop-detector.ts +8 -0
  42. package/core/agentic/memory-system/history.ts +53 -0
  43. package/core/agentic/memory-system/index.ts +192 -0
  44. package/core/agentic/memory-system/patterns.ts +156 -0
  45. package/core/agentic/memory-system/semantic-memories.ts +277 -0
  46. package/core/agentic/memory-system/session.ts +21 -0
  47. package/core/agentic/memory-system/types.ts +159 -0
  48. package/core/agentic/memory-system.ts +8 -0
  49. package/core/agentic/parallel-tools.ts +165 -0
  50. package/core/agentic/plan-mode/approval.ts +57 -0
  51. package/core/agentic/plan-mode/constants.ts +44 -0
  52. package/core/agentic/plan-mode/index.ts +28 -0
  53. package/core/agentic/plan-mode/plan-mode.ts +406 -0
  54. package/core/agentic/plan-mode/types.ts +193 -0
  55. package/core/agentic/plan-mode.ts +8 -0
  56. package/core/agentic/prompt-builder.ts +566 -0
  57. package/core/agentic/response-templates.ts +164 -0
  58. package/core/agentic/semantic-compression.ts +273 -0
  59. package/core/agentic/services.ts +206 -0
  60. package/core/agentic/smart-context.ts +476 -0
  61. package/core/agentic/{template-loader.js → template-loader.ts} +27 -16
  62. package/core/agentic/think-blocks.ts +202 -0
  63. package/core/agentic/tool-registry.ts +119 -0
  64. package/core/agentic/validation-rules.ts +313 -0
  65. package/core/agents/index.ts +28 -0
  66. package/core/agents/performance.ts +444 -0
  67. package/core/agents/types.ts +126 -0
  68. package/core/bus/{index.js → index.ts} +57 -61
  69. package/core/command-registry/categories.ts +23 -0
  70. package/core/command-registry/commands.ts +15 -0
  71. package/core/command-registry/core-commands.ts +319 -0
  72. package/core/command-registry/index.ts +158 -0
  73. package/core/command-registry/optional-commands.ts +119 -0
  74. package/core/command-registry/setup-commands.ts +53 -0
  75. package/core/command-registry/types.ts +59 -0
  76. package/core/command-registry.ts +9 -0
  77. package/core/commands/analysis.ts +298 -0
  78. package/core/commands/analytics.ts +288 -0
  79. package/core/commands/base.ts +273 -0
  80. package/core/commands/index.ts +211 -0
  81. package/core/commands/maintenance.ts +226 -0
  82. package/core/commands/planning.ts +311 -0
  83. package/core/commands/setup.ts +309 -0
  84. package/core/commands/shipping.ts +188 -0
  85. package/core/commands/types.ts +183 -0
  86. package/core/commands/workflow.ts +226 -0
  87. package/core/commands.ts +11 -0
  88. package/core/constants/formats.ts +187 -0
  89. package/core/constants/index.ts +7 -0
  90. package/core/{context-sync.js → context-sync.ts} +59 -26
  91. package/core/data/agents-manager.ts +76 -0
  92. package/core/data/analysis-manager.ts +83 -0
  93. package/core/data/base-manager.ts +156 -0
  94. package/core/data/ideas-manager.ts +81 -0
  95. package/core/data/index.ts +32 -0
  96. package/core/data/outcomes-manager.ts +96 -0
  97. package/core/data/project-manager.ts +75 -0
  98. package/core/data/roadmap-manager.ts +118 -0
  99. package/core/data/shipped-manager.ts +65 -0
  100. package/core/data/state-manager.ts +214 -0
  101. package/core/domain/{agent-generator.js → agent-generator.ts} +77 -57
  102. package/core/domain/{agent-loader.js → agent-loader.ts} +65 -56
  103. package/core/domain/{agent-matcher.js → agent-matcher.ts} +51 -24
  104. package/core/domain/{agent-validator.js → agent-validator.ts} +70 -37
  105. package/core/domain/{analyzer.js → analyzer.ts} +91 -85
  106. package/core/domain/{architect-session.js → architect-session.ts} +49 -34
  107. package/core/domain/{architecture-generator.js → architecture-generator.ts} +25 -13
  108. package/core/domain/{context-estimator.js → context-estimator.ts} +57 -36
  109. package/core/domain/{product-standards.js → product-standards.ts} +40 -26
  110. package/core/domain/{smart-cache.js → smart-cache.ts} +39 -30
  111. package/core/domain/{snapshot-manager.js → snapshot-manager.ts} +103 -100
  112. package/core/domain/{task-analyzer.js → task-analyzer.ts} +82 -43
  113. package/core/domain/task-stack/index.ts +19 -0
  114. package/core/domain/task-stack/parser.ts +86 -0
  115. package/core/domain/task-stack/storage.ts +123 -0
  116. package/core/domain/task-stack/task-stack.ts +340 -0
  117. package/core/domain/task-stack/types.ts +51 -0
  118. package/core/domain/task-stack.ts +8 -0
  119. package/core/{index.js → index.ts} +61 -18
  120. package/core/infrastructure/{agent-detector.js → agent-detector.ts} +55 -19
  121. package/core/infrastructure/agents/{claude-agent.js → claude-agent.ts} +61 -21
  122. package/core/infrastructure/{author-detector.js → author-detector.ts} +42 -49
  123. package/core/infrastructure/{capability-installer.js → capability-installer.ts} +51 -27
  124. package/core/infrastructure/{command-installer.js → command-installer/command-installer.ts} +43 -144
  125. package/core/infrastructure/command-installer/global-config.ts +106 -0
  126. package/core/infrastructure/command-installer/index.ts +25 -0
  127. package/core/infrastructure/command-installer/types.ts +41 -0
  128. package/core/infrastructure/command-installer.ts +8 -0
  129. package/core/infrastructure/{config-manager.js → config-manager.ts} +60 -80
  130. package/core/infrastructure/{editors-config.js → editors-config.ts} +33 -31
  131. package/core/infrastructure/legacy-installer-detector/cleanup.ts +216 -0
  132. package/core/infrastructure/legacy-installer-detector/detection.ts +95 -0
  133. package/core/infrastructure/legacy-installer-detector/index.ts +171 -0
  134. package/core/infrastructure/legacy-installer-detector/migration.ts +87 -0
  135. package/core/infrastructure/legacy-installer-detector/types.ts +42 -0
  136. package/core/infrastructure/legacy-installer-detector.ts +7 -0
  137. package/core/infrastructure/migrator/file-operations.ts +125 -0
  138. package/core/infrastructure/migrator/index.ts +288 -0
  139. package/core/infrastructure/migrator/project-scanner.ts +89 -0
  140. package/core/infrastructure/migrator/reports.ts +117 -0
  141. package/core/infrastructure/migrator/types.ts +124 -0
  142. package/core/infrastructure/migrator/validation.ts +94 -0
  143. package/core/infrastructure/migrator/version-migration.ts +117 -0
  144. package/core/infrastructure/migrator.ts +10 -0
  145. package/core/infrastructure/{path-manager.js → path-manager.ts} +51 -91
  146. package/core/infrastructure/session-manager/index.ts +23 -0
  147. package/core/infrastructure/session-manager/migration.ts +88 -0
  148. package/core/infrastructure/session-manager/session-manager.ts +307 -0
  149. package/core/infrastructure/session-manager/types.ts +45 -0
  150. package/core/infrastructure/session-manager.ts +8 -0
  151. package/core/infrastructure/{setup.js → setup.ts} +29 -21
  152. package/core/infrastructure/{update-checker.js → update-checker.ts} +40 -18
  153. package/core/outcomes/analyzer.ts +333 -0
  154. package/core/outcomes/index.ts +34 -0
  155. package/core/outcomes/recorder.ts +194 -0
  156. package/core/outcomes/types.ts +145 -0
  157. package/core/plugin/{hooks.js → hooks.ts} +56 -58
  158. package/core/plugin/{index.js → index.ts} +19 -8
  159. package/core/plugin/{loader.js → loader.ts} +87 -69
  160. package/core/plugin/{registry.js → registry.ts} +49 -45
  161. package/core/plugins/{webhook.js → webhook.ts} +43 -27
  162. package/core/schemas/agents.ts +27 -0
  163. package/core/schemas/analysis.ts +41 -0
  164. package/core/schemas/ideas.ts +83 -0
  165. package/core/schemas/index.ts +73 -0
  166. package/core/schemas/outcomes.ts +22 -0
  167. package/core/schemas/project.ts +26 -0
  168. package/core/schemas/roadmap.ts +90 -0
  169. package/core/schemas/shipped.ts +82 -0
  170. package/core/schemas/state.ts +107 -0
  171. package/core/session/index.ts +17 -0
  172. package/core/session/{metrics.js → metrics.ts} +64 -46
  173. package/core/session/{index.js → session-manager.ts} +51 -117
  174. package/core/session/types.ts +29 -0
  175. package/core/session/utils.ts +57 -0
  176. package/core/state/index.ts +25 -0
  177. package/core/state/manager.ts +376 -0
  178. package/core/state/types.ts +185 -0
  179. package/core/tsconfig.json +22 -0
  180. package/core/types/index.ts +506 -0
  181. package/core/utils/{animations.js → animations.ts} +74 -28
  182. package/core/utils/{branding.js → branding.ts} +29 -4
  183. package/core/utils/{date-helper.js → date-helper.ts} +31 -74
  184. package/core/utils/file-helper.ts +262 -0
  185. package/core/utils/{jsonl-helper.js → jsonl-helper.ts} +71 -107
  186. package/core/utils/{logger.js → logger.ts} +24 -12
  187. package/core/utils/{output.js → output.ts} +25 -13
  188. package/core/utils/{project-capabilities.js → project-capabilities.ts} +31 -18
  189. package/core/utils/{session-helper.js → session-helper.ts} +79 -66
  190. package/core/utils/{version.js → version.ts} +23 -31
  191. package/core/view-generator.ts +536 -0
  192. package/package.json +23 -17
  193. package/packages/shared/.turbo/turbo-build.log +14 -0
  194. package/packages/shared/dist/index.d.ts +8 -613
  195. package/packages/shared/dist/index.d.ts.map +1 -0
  196. package/packages/shared/dist/index.js +4110 -118
  197. package/packages/shared/dist/schemas.d.ts +408 -0
  198. package/packages/shared/dist/schemas.d.ts.map +1 -0
  199. package/packages/shared/dist/types.d.ts +144 -0
  200. package/packages/shared/dist/types.d.ts.map +1 -0
  201. package/packages/shared/dist/unified.d.ts +139 -0
  202. package/packages/shared/dist/unified.d.ts.map +1 -0
  203. package/packages/shared/dist/utils.d.ts +60 -0
  204. package/packages/shared/dist/utils.d.ts.map +1 -0
  205. package/packages/shared/package.json +4 -4
  206. package/packages/shared/src/index.ts +1 -0
  207. package/packages/shared/src/unified.ts +174 -0
  208. package/packages/web/app/api/claude/sessions/route.ts +1 -1
  209. package/packages/web/app/api/claude/status/route.ts +1 -1
  210. package/packages/web/app/api/migrate/route.ts +46 -0
  211. package/packages/web/app/api/projects/[id]/route.ts +1 -1
  212. package/packages/web/app/api/projects/[id]/stats/route.ts +30 -2
  213. package/packages/web/app/api/projects/[id]/status/route.ts +1 -1
  214. package/packages/web/app/api/projects/route.ts +1 -1
  215. package/packages/web/app/api/settings/route.ts +97 -0
  216. package/packages/web/app/api/v2/projects/[id]/unified/route.ts +57 -0
  217. package/packages/web/app/globals.css +38 -0
  218. package/packages/web/app/layout.tsx +10 -2
  219. package/packages/web/app/page.tsx +9 -224
  220. package/packages/web/app/project/[id]/page.tsx +191 -63
  221. package/packages/web/app/project/[id]/stats/loading.tsx +43 -0
  222. package/packages/web/app/project/[id]/stats/page.tsx +204 -163
  223. package/packages/web/app/settings/page.tsx +222 -2
  224. package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +2 -0
  225. package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +50 -0
  226. package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +8 -0
  227. package/packages/web/components/ActivityTimeline/hooks/index.ts +2 -0
  228. package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +9 -0
  229. package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +23 -0
  230. package/packages/web/components/ActivityTimeline/index.ts +2 -0
  231. package/packages/web/components/AgentsCard/AgentsCard.tsx +63 -0
  232. package/packages/web/components/AgentsCard/AgentsCard.types.ts +13 -0
  233. package/packages/web/components/AgentsCard/index.ts +2 -0
  234. package/packages/web/components/AppSidebar/AppSidebar.tsx +190 -0
  235. package/packages/web/components/AppSidebar/index.ts +1 -0
  236. package/packages/web/components/BackLink/BackLink.tsx +18 -0
  237. package/packages/web/components/BackLink/BackLink.types.ts +5 -0
  238. package/packages/web/components/BackLink/index.ts +2 -0
  239. package/packages/web/components/BentoCard/BentoCard.constants.ts +16 -0
  240. package/packages/web/components/BentoCard/BentoCard.tsx +47 -0
  241. package/packages/web/components/BentoCard/BentoCard.types.ts +15 -0
  242. package/packages/web/components/BentoCard/index.ts +2 -0
  243. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +9 -0
  244. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +18 -0
  245. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +5 -0
  246. package/packages/web/components/BentoCardSkeleton/index.ts +2 -0
  247. package/packages/web/components/{stats → BentoGrid}/BentoGrid.tsx +4 -8
  248. package/packages/web/components/BentoGrid/BentoGrid.types.ts +4 -0
  249. package/packages/web/components/BentoGrid/index.ts +2 -0
  250. package/packages/web/components/CommandButton/index.ts +1 -0
  251. package/packages/web/components/ConnectionStatus/index.ts +1 -0
  252. package/packages/web/components/DashboardContent/DashboardContent.tsx +254 -0
  253. package/packages/web/components/DashboardContent/index.ts +1 -0
  254. package/packages/web/components/DateGroup/DateGroup.tsx +18 -0
  255. package/packages/web/components/DateGroup/DateGroup.types.ts +6 -0
  256. package/packages/web/components/DateGroup/DateGroup.utils.ts +11 -0
  257. package/packages/web/components/DateGroup/index.ts +2 -0
  258. package/packages/web/components/{stats → EmptyState}/EmptyState.tsx +1 -10
  259. package/packages/web/components/EmptyState/EmptyState.types.ts +10 -0
  260. package/packages/web/components/EmptyState/index.ts +2 -0
  261. package/packages/web/components/EventRow/EventRow.constants.ts +10 -0
  262. package/packages/web/components/EventRow/EventRow.tsx +49 -0
  263. package/packages/web/components/EventRow/EventRow.types.ts +7 -0
  264. package/packages/web/components/EventRow/EventRow.utils.ts +49 -0
  265. package/packages/web/components/EventRow/index.ts +2 -0
  266. package/packages/web/components/ExpandButton/ExpandButton.tsx +18 -0
  267. package/packages/web/components/ExpandButton/ExpandButton.types.ts +6 -0
  268. package/packages/web/components/ExpandButton/index.ts +2 -0
  269. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +14 -0
  270. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +5 -0
  271. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +13 -0
  272. package/packages/web/components/HealthGradientBackground/index.ts +2 -0
  273. package/packages/web/components/HeroSection/HeroSection.tsx +55 -0
  274. package/packages/web/components/HeroSection/HeroSection.types.ts +14 -0
  275. package/packages/web/components/HeroSection/HeroSection.utils.ts +7 -0
  276. package/packages/web/components/HeroSection/hooks/index.ts +2 -0
  277. package/packages/web/components/HeroSection/hooks/useCountUp.ts +45 -0
  278. package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +18 -0
  279. package/packages/web/components/HeroSection/index.ts +2 -0
  280. package/packages/web/components/{stats → IdeasCard}/IdeasCard.tsx +3 -14
  281. package/packages/web/components/IdeasCard/IdeasCard.types.ts +9 -0
  282. package/packages/web/components/IdeasCard/index.ts +2 -0
  283. package/packages/web/components/InsightMessage/InsightMessage.tsx +9 -0
  284. package/packages/web/components/InsightMessage/InsightMessage.types.ts +3 -0
  285. package/packages/web/components/InsightMessage/index.ts +2 -0
  286. package/packages/web/components/Logo/index.ts +1 -0
  287. package/packages/web/components/MarkdownContent/index.ts +1 -0
  288. package/packages/web/components/NowCard/NowCard.tsx +93 -0
  289. package/packages/web/components/NowCard/NowCard.types.ts +15 -0
  290. package/packages/web/components/NowCard/index.ts +2 -0
  291. package/packages/web/components/ProgressRing/ProgressRing.constants.ts +20 -0
  292. package/packages/web/components/{stats → ProgressRing}/ProgressRing.tsx +4 -27
  293. package/packages/web/components/ProgressRing/ProgressRing.types.ts +11 -0
  294. package/packages/web/components/ProgressRing/index.ts +2 -0
  295. package/packages/web/components/ProjectAvatar/index.ts +1 -0
  296. package/packages/web/components/Providers/index.ts +1 -0
  297. package/packages/web/components/QueueCard/QueueCard.tsx +72 -0
  298. package/packages/web/components/QueueCard/QueueCard.types.ts +11 -0
  299. package/packages/web/components/QueueCard/QueueCard.utils.ts +12 -0
  300. package/packages/web/components/QueueCard/index.ts +2 -0
  301. package/packages/web/components/{stats → RoadmapCard}/RoadmapCard.tsx +3 -23
  302. package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +15 -0
  303. package/packages/web/components/RoadmapCard/index.ts +2 -0
  304. package/packages/web/components/{stats → ShipsCard}/ShipsCard.tsx +4 -22
  305. package/packages/web/components/ShipsCard/ShipsCard.types.ts +12 -0
  306. package/packages/web/components/ShipsCard/ShipsCard.utils.ts +4 -0
  307. package/packages/web/components/ShipsCard/index.ts +2 -0
  308. package/packages/web/components/{stats → SparklineChart}/SparklineChart.tsx +1 -7
  309. package/packages/web/components/SparklineChart/SparklineChart.types.ts +6 -0
  310. package/packages/web/components/SparklineChart/index.ts +2 -0
  311. package/packages/web/components/StreakCard/StreakCard.constants.ts +2 -0
  312. package/packages/web/components/{stats → StreakCard}/StreakCard.tsx +5 -11
  313. package/packages/web/components/StreakCard/StreakCard.types.ts +4 -0
  314. package/packages/web/components/StreakCard/index.ts +2 -0
  315. package/packages/web/components/TasksCounter/TasksCounter.tsx +14 -0
  316. package/packages/web/components/TasksCounter/TasksCounter.types.ts +3 -0
  317. package/packages/web/components/TasksCounter/index.ts +2 -0
  318. package/packages/web/components/TechStackBadges/index.ts +1 -0
  319. package/packages/web/components/{TerminalTab.tsx → TerminalTabs/TerminalTab.tsx} +11 -0
  320. package/packages/web/components/{TerminalTabs.tsx → TerminalTabs/TerminalTabs.tsx} +29 -28
  321. package/packages/web/components/TerminalTabs/index.ts +1 -0
  322. package/packages/web/components/VelocityBadge/VelocityBadge.tsx +27 -0
  323. package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +3 -0
  324. package/packages/web/components/VelocityBadge/index.ts +2 -0
  325. package/packages/web/components/VelocityCard/VelocityCard.tsx +71 -0
  326. package/packages/web/components/VelocityCard/VelocityCard.types.ts +7 -0
  327. package/packages/web/components/VelocityCard/index.ts +2 -0
  328. package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +13 -0
  329. package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +3 -0
  330. package/packages/web/components/WeeklySparkline/index.ts +2 -0
  331. package/packages/web/components/ui/input.tsx +21 -0
  332. package/packages/web/context/TerminalTabsContext.tsx +46 -1
  333. package/packages/web/hooks/useClaudeTerminal.ts +71 -21
  334. package/packages/web/hooks/useProjectStats.ts +55 -0
  335. package/packages/web/hooks/useProjects.ts +6 -6
  336. package/packages/web/lib/actions/projects.ts +15 -0
  337. package/packages/web/lib/json-loader.ts +630 -0
  338. package/packages/web/lib/services/index.ts +9 -0
  339. package/packages/web/lib/services/migration.server.ts +600 -0
  340. package/packages/web/lib/services/projects.server.ts +52 -0
  341. package/packages/web/lib/services/stats.server.ts +264 -0
  342. package/packages/web/lib/unified-loader.ts +396 -0
  343. package/packages/web/package.json +10 -7
  344. package/packages/web/server.ts +58 -8
  345. package/templates/commands/done.md +76 -32
  346. package/templates/commands/feature.md +121 -47
  347. package/templates/commands/idea.md +81 -8
  348. package/templates/commands/now.md +41 -17
  349. package/templates/commands/ship.md +64 -25
  350. package/templates/commands/sync.md +28 -3
  351. package/core/agentic/agent-router.js +0 -140
  352. package/core/agentic/chain-of-thought.js +0 -578
  353. package/core/agentic/command-executor.js +0 -417
  354. package/core/agentic/context-filter.js +0 -354
  355. package/core/agentic/ground-truth.js +0 -591
  356. package/core/agentic/loop-detector.js +0 -406
  357. package/core/agentic/memory-system.js +0 -845
  358. package/core/agentic/parallel-tools.js +0 -366
  359. package/core/agentic/plan-mode.js +0 -572
  360. package/core/agentic/prompt-builder.js +0 -352
  361. package/core/agentic/response-templates.js +0 -290
  362. package/core/agentic/semantic-compression.js +0 -517
  363. package/core/agentic/think-blocks.js +0 -657
  364. package/core/agentic/tool-registry.js +0 -184
  365. package/core/agentic/validation-rules.js +0 -380
  366. package/core/command-registry.js +0 -698
  367. package/core/commands.js +0 -2237
  368. package/core/domain/task-stack.js +0 -497
  369. package/core/infrastructure/legacy-installer-detector.js +0 -546
  370. package/core/infrastructure/migrator.js +0 -796
  371. package/core/infrastructure/session-manager.js +0 -390
  372. package/core/utils/file-helper.js +0 -329
  373. package/packages/web/app/api/projects/[id]/delete/route.ts +0 -21
  374. package/packages/web/app/api/stats/route.ts +0 -38
  375. package/packages/web/components/AppSidebar.tsx +0 -113
  376. package/packages/web/components/stats/ActivityTimeline.tsx +0 -201
  377. package/packages/web/components/stats/AgentsCard.tsx +0 -56
  378. package/packages/web/components/stats/BentoCard.tsx +0 -88
  379. package/packages/web/components/stats/HeroSection.tsx +0 -172
  380. package/packages/web/components/stats/NowCard.tsx +0 -71
  381. package/packages/web/components/stats/QueueCard.tsx +0 -58
  382. package/packages/web/components/stats/VelocityCard.tsx +0 -60
  383. package/packages/web/components/stats/index.ts +0 -17
  384. package/packages/web/hooks/useStats.ts +0 -28
  385. /package/packages/web/components/{CommandButton.tsx → CommandButton/CommandButton.tsx} +0 -0
  386. /package/packages/web/components/{ConnectionStatus.tsx → ConnectionStatus/ConnectionStatus.tsx} +0 -0
  387. /package/packages/web/components/{Logo.tsx → Logo/Logo.tsx} +0 -0
  388. /package/packages/web/components/{MarkdownContent.tsx → MarkdownContent/MarkdownContent.tsx} +0 -0
  389. /package/packages/web/components/{ProjectAvatar.tsx → ProjectAvatar/ProjectAvatar.tsx} +0 -0
  390. /package/packages/web/components/{providers.tsx → Providers/Providers.tsx} +0 -0
  391. /package/packages/web/components/{TechStackBadges.tsx → TechStackBadges/TechStackBadges.tsx} +0 -0
@@ -1,21 +0,0 @@
1
- import { NextResponse } from 'next/server'
2
- import { moveToTrash } from '@/lib/projects'
3
-
4
- export const dynamic = 'force-dynamic'
5
-
6
- export async function POST(
7
- request: Request,
8
- { params }: { params: Promise<{ id: string }> }
9
- ) {
10
- try {
11
- const { id } = await params
12
- const result = await moveToTrash(id)
13
- return NextResponse.json({ success: true, ...result })
14
- } catch (error) {
15
- const message = error instanceof Error ? error.message : 'Failed to delete project'
16
- return NextResponse.json(
17
- { success: false, error: message },
18
- { status: 500 }
19
- )
20
- }
21
- }
@@ -1,38 +0,0 @@
1
- import { NextResponse } from 'next/server'
2
- import { getProjects } from '@/lib/projects'
3
- import { exec } from 'child_process'
4
- import { promisify } from 'util'
5
-
6
- const execAsync = promisify(exec)
7
-
8
- export const dynamic = 'force-dynamic'
9
-
10
- async function getGitUserName(): Promise<string> {
11
- try {
12
- const { stdout } = await execAsync('git config user.name')
13
- return stdout.trim() || 'Developer'
14
- } catch {
15
- return 'Developer'
16
- }
17
- }
18
-
19
- export async function GET() {
20
- try {
21
- const [projects, userName] = await Promise.all([
22
- getProjects(),
23
- getGitUserName()
24
- ])
25
-
26
- const stats = {
27
- userName,
28
- totalProjects: projects.length
29
- }
30
-
31
- return NextResponse.json({ success: true, data: stats })
32
- } catch {
33
- return NextResponse.json(
34
- { success: false, error: 'Failed to get stats' },
35
- { status: 500 }
36
- )
37
- }
38
- }
@@ -1,113 +0,0 @@
1
- 'use client'
2
-
3
- import Link from 'next/link'
4
- import { usePathname } from 'next/navigation'
5
- import {
6
- LayoutDashboard,
7
- Settings,
8
- HelpCircle,
9
- PanelLeft
10
- } from 'lucide-react'
11
- import { Logo } from './Logo'
12
- import { cn } from '@/lib/utils'
13
- import { useState } from 'react'
14
-
15
- const navItems = [
16
- { href: '/', icon: LayoutDashboard, label: 'Dashboard' },
17
- ]
18
-
19
- export function AppSidebar() {
20
- const pathname = usePathname()
21
- const [isCollapsed, setIsCollapsed] = useState(false)
22
-
23
- return (
24
- <aside
25
- className={cn(
26
- 'flex h-full flex-col border-r border-border bg-card transition-all duration-200',
27
- isCollapsed ? 'w-14' : 'w-60'
28
- )}
29
- >
30
- {/* Header */}
31
- <div className={cn(
32
- 'flex h-14 items-center border-b border-border',
33
- isCollapsed ? 'justify-center' : 'justify-between px-3'
34
- )}>
35
- {!isCollapsed && (
36
- <Link href="/">
37
- <Logo size="xs" showText rounded />
38
- </Link>
39
- )}
40
- <button
41
- onClick={() => setIsCollapsed(!isCollapsed)}
42
- className="h-8 w-8 rounded-md flex items-center justify-center text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors"
43
- >
44
- <PanelLeft className="h-4 w-4" />
45
- </button>
46
- </div>
47
-
48
- {/* Nav */}
49
- <nav className={cn(
50
- 'flex-1 overflow-y-auto py-4',
51
- isCollapsed ? 'px-2' : 'px-3'
52
- )}>
53
- <div className="space-y-1">
54
- {navItems.map(({ href, icon: Icon, label }) => {
55
- const isActive = pathname === href || (href !== '/' && pathname.startsWith(href))
56
- return (
57
- <Link
58
- key={href}
59
- href={href}
60
- className={cn(
61
- 'flex items-center gap-3 rounded-md px-3 py-2 transition-colors',
62
- isCollapsed && 'justify-center px-2',
63
- isActive
64
- ? 'bg-accent text-accent-foreground'
65
- : 'text-muted-foreground hover:bg-accent hover:text-accent-foreground'
66
- )}
67
- title={isCollapsed ? label : undefined}
68
- >
69
- <Icon className="h-4 w-4 shrink-0" />
70
- {!isCollapsed && <span>{label}</span>}
71
- </Link>
72
- )
73
- })}
74
- </div>
75
- </nav>
76
-
77
- {/* Footer */}
78
- <div className={cn(
79
- 'border-t border-border p-3 space-y-1',
80
- isCollapsed && 'px-2'
81
- )}>
82
- <Link
83
- href="/settings"
84
- className={cn(
85
- 'flex items-center gap-3 rounded-md px-3 py-2 transition-colors',
86
- isCollapsed && 'justify-center px-2',
87
- pathname === '/settings'
88
- ? 'bg-accent text-accent-foreground'
89
- : 'text-muted-foreground hover:bg-accent hover:text-accent-foreground'
90
- )}
91
- title={isCollapsed ? 'Settings' : undefined}
92
- >
93
- <Settings className="h-4 w-4 shrink-0" />
94
- {!isCollapsed && <span>Settings</span>}
95
- </Link>
96
- <Link
97
- href="/help"
98
- className={cn(
99
- 'flex items-center gap-3 rounded-md px-3 py-2 transition-colors',
100
- isCollapsed && 'justify-center px-2',
101
- pathname === '/help'
102
- ? 'bg-accent text-accent-foreground'
103
- : 'text-muted-foreground hover:bg-accent hover:text-accent-foreground'
104
- )}
105
- title={isCollapsed ? 'Help' : undefined}
106
- >
107
- <HelpCircle className="h-4 w-4 shrink-0" />
108
- {!isCollapsed && <span>Need help?</span>}
109
- </Link>
110
- </div>
111
- </aside>
112
- )
113
- }
@@ -1,201 +0,0 @@
1
- 'use client'
2
-
3
- import { useMemo, useState } from 'react'
4
- import { BentoCard } from './BentoCard'
5
- import { EmptyState } from './EmptyState'
6
- import { Activity, CheckCircle2, Rocket, Target, RefreshCw, ChevronDown } from 'lucide-react'
7
- import { cn } from '@/lib/utils'
8
- import { Button } from '@/components/ui/button'
9
- import type { TimelineEvent } from '@/lib/parse-prjct-files'
10
-
11
- interface ActivityTimelineProps {
12
- timeline: TimelineEvent[]
13
- className?: string
14
- }
15
-
16
- function getEventIcon(type: string) {
17
- switch (type) {
18
- case 'task_complete':
19
- return CheckCircle2
20
- case 'task_start':
21
- return Target
22
- case 'feature_ship':
23
- return Rocket
24
- case 'sync':
25
- return RefreshCw
26
- default:
27
- return Activity
28
- }
29
- }
30
-
31
- function getEventColor(type: string) {
32
- switch (type) {
33
- case 'task_complete':
34
- return 'text-emerald-500'
35
- case 'task_start':
36
- return 'text-amber-500'
37
- case 'feature_ship':
38
- return 'text-blue-500'
39
- case 'sync':
40
- return 'text-muted-foreground'
41
- default:
42
- return 'text-muted-foreground'
43
- }
44
- }
45
-
46
- function getEventLabel(event: TimelineEvent): string {
47
- const e = event as Record<string, unknown>
48
- switch (event.type) {
49
- case 'task_complete':
50
- return (e.task as string) || 'Task completed'
51
- case 'task_start':
52
- return (e.task as string) || 'Task started'
53
- case 'feature_ship':
54
- return (e.name as string) || 'Feature shipped'
55
- case 'sync':
56
- return 'Project synced'
57
- default:
58
- return event.type
59
- }
60
- }
61
-
62
- function getEventBadge(type: string): string {
63
- switch (type) {
64
- case 'task_complete':
65
- return 'DONE'
66
- case 'task_start':
67
- return 'START'
68
- case 'feature_ship':
69
- return 'SHIP'
70
- case 'sync':
71
- return 'SYNC'
72
- default:
73
- return type.toUpperCase()
74
- }
75
- }
76
-
77
- function formatTime(dateString: string): string {
78
- const date = new Date(dateString)
79
- return date.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true })
80
- }
81
-
82
- function formatDate(dateString: string): string {
83
- const date = new Date(dateString)
84
- const today = new Date()
85
- const yesterday = new Date(today)
86
- yesterday.setDate(yesterday.getDate() - 1)
87
-
88
- if (date.toDateString() === today.toDateString()) return 'Today'
89
- if (date.toDateString() === yesterday.toDateString()) return 'Yesterday'
90
-
91
- return date.toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric' })
92
- }
93
-
94
- // Group events by date
95
- function groupEventsByDate(events: TimelineEvent[]): Map<string, TimelineEvent[]> {
96
- const groups = new Map<string, TimelineEvent[]>()
97
-
98
- events.forEach(event => {
99
- if (!event.ts) return
100
- const dateKey = event.ts.split('T')[0]
101
- const existing = groups.get(dateKey) || []
102
- groups.set(dateKey, [...existing, event])
103
- })
104
-
105
- return groups
106
- }
107
-
108
- export function ActivityTimeline({ timeline, className }: ActivityTimelineProps) {
109
- const [showAll, setShowAll] = useState(false)
110
-
111
- const displayEvents = showAll ? timeline.slice(0, 20) : timeline.slice(0, 8)
112
- const groupedEvents = useMemo(() => groupEventsByDate(displayEvents), [displayEvents])
113
- const hasMore = timeline.length > displayEvents.length
114
-
115
- return (
116
- <BentoCard
117
- size="full"
118
- title="Recent Activity"
119
- icon={Activity}
120
- count={timeline.length > 0 ? `${timeline.length} events` : undefined}
121
- className={className}
122
- >
123
- {timeline.length === 0 ? (
124
- <EmptyState
125
- icon={Activity}
126
- title="No recent activity"
127
- description="Activity will appear as you work"
128
- compact
129
- />
130
- ) : (
131
- <div className="space-y-4">
132
- {Array.from(groupedEvents.entries()).map(([dateKey, events]) => (
133
- <div key={dateKey}>
134
- {/* Date header */}
135
- <p className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground mb-2">
136
- {formatDate(dateKey + 'T00:00:00')}
137
- </p>
138
-
139
- {/* Events for this date */}
140
- <div className="space-y-1">
141
- {events.map((event, i) => {
142
- const Icon = getEventIcon(event.type)
143
- const e = event as Record<string, unknown>
144
-
145
- const duration = typeof e.duration === 'string' ? e.duration : null
146
-
147
- return (
148
- <div
149
- key={i}
150
- className="flex items-center gap-3 py-1.5 px-2 -mx-2 rounded-md hover:bg-muted/50 transition-colors group"
151
- >
152
- {/* Time */}
153
- {event.ts && (
154
- <span className="text-[10px] text-muted-foreground w-14 shrink-0 tabular-nums">
155
- {formatTime(event.ts)}
156
- </span>
157
- )}
158
-
159
- {/* Icon */}
160
- <Icon className={cn('h-3.5 w-3.5 shrink-0', getEventColor(event.type))} />
161
-
162
- {/* Label */}
163
- <span className="text-sm truncate flex-1 group-hover:text-foreground transition-colors">
164
- {getEventLabel(event)}
165
- </span>
166
-
167
- {/* Badge */}
168
- <span className="text-[9px] font-bold tracking-wider text-muted-foreground shrink-0">
169
- {getEventBadge(event.type)}
170
- </span>
171
-
172
- {/* Duration if available */}
173
- {duration && (
174
- <span className="text-[10px] text-muted-foreground shrink-0">
175
- {duration}
176
- </span>
177
- )}
178
- </div>
179
- )
180
- })}
181
- </div>
182
- </div>
183
- ))}
184
-
185
- {/* Load more button */}
186
- {hasMore && (
187
- <Button
188
- variant="ghost"
189
- size="sm"
190
- onClick={() => setShowAll(!showAll)}
191
- className="w-full text-muted-foreground"
192
- >
193
- <ChevronDown className={cn('h-4 w-4 mr-1 transition-transform', showAll && 'rotate-180')} />
194
- {showAll ? 'Show less' : `Show ${timeline.length - 8} more`}
195
- </Button>
196
- )}
197
- </div>
198
- )}
199
- </BentoCard>
200
- )
201
- }
@@ -1,56 +0,0 @@
1
- 'use client'
2
-
3
- import { BentoCard } from './BentoCard'
4
- import { EmptyState } from './EmptyState'
5
- import { Bot } from 'lucide-react'
6
- import { Badge } from '@/components/ui/badge'
7
-
8
- interface Agent {
9
- name: string
10
- description?: string
11
- }
12
-
13
- interface AgentsCardProps {
14
- agents: Agent[]
15
- className?: string
16
- }
17
-
18
- export function AgentsCard({ agents, className }: AgentsCardProps) {
19
- const displayAgents = agents.slice(0, 8)
20
-
21
- return (
22
- <BentoCard
23
- size="1x1"
24
- title="Agents"
25
- icon={Bot}
26
- count={agents.length}
27
- className={className}
28
- >
29
- {agents.length === 0 ? (
30
- <EmptyState
31
- icon={Bot}
32
- title="No agents"
33
- description="Run /p:sync to generate"
34
- compact
35
- />
36
- ) : (
37
- <div className="flex flex-wrap gap-1.5">
38
- {displayAgents.map((agent) => (
39
- <Badge
40
- key={agent.name}
41
- variant="secondary"
42
- className="text-xs px-2 py-0.5 font-mono"
43
- >
44
- @{agent.name}
45
- </Badge>
46
- ))}
47
- {agents.length > 8 && (
48
- <Badge variant="outline" className="text-xs px-2 py-0.5">
49
- +{agents.length - 8}
50
- </Badge>
51
- )}
52
- </div>
53
- )}
54
- </BentoCard>
55
- )
56
- }
@@ -1,88 +0,0 @@
1
- import * as React from 'react'
2
- import { cn } from '@/lib/utils'
3
- import type { LucideIcon } from 'lucide-react'
4
-
5
- export type BentoSize = '1x1' | '1x2' | '2x1' | '2x2' | 'full'
6
-
7
- const sizeClasses: Record<BentoSize, string> = {
8
- '1x1': 'col-span-1 row-span-1',
9
- '1x2': 'col-span-1 row-span-2',
10
- '2x1': 'col-span-2 row-span-1',
11
- '2x2': 'col-span-2 row-span-2',
12
- 'full': 'col-span-full',
13
- }
14
-
15
- export interface BentoCardProps {
16
- size?: BentoSize
17
- title?: string
18
- count?: number | string
19
- icon?: LucideIcon
20
- accentColor?: 'default' | 'success' | 'warning' | 'destructive'
21
- className?: string
22
- headerClassName?: string
23
- children: React.ReactNode
24
- }
25
-
26
- const accentStyles: Record<NonNullable<BentoCardProps['accentColor']>, string> = {
27
- default: '',
28
- success: 'border-emerald-500/20 bg-emerald-500/5',
29
- warning: 'border-amber-500/20 bg-amber-500/5',
30
- destructive: 'border-destructive/20 bg-destructive/5',
31
- }
32
-
33
- export function BentoCard({
34
- size = '1x1',
35
- title,
36
- count,
37
- icon: Icon,
38
- accentColor = 'default',
39
- className,
40
- headerClassName,
41
- children,
42
- }: BentoCardProps) {
43
- return (
44
- <div
45
- className={cn(
46
- 'relative overflow-hidden rounded-xl border bg-card p-4 transition-all duration-200',
47
- 'hover:shadow-md hover:border-foreground/20',
48
- sizeClasses[size],
49
- accentStyles[accentColor],
50
- className
51
- )}
52
- >
53
- {(title || count !== undefined || Icon) && (
54
- <div className={cn('flex items-center justify-between mb-3', headerClassName)}>
55
- <div className="flex items-center gap-2">
56
- {Icon && <Icon className="h-3.5 w-3.5 text-muted-foreground" />}
57
- {title && (
58
- <span className="text-[10px] font-bold uppercase tracking-[0.15em] text-muted-foreground">
59
- {title}
60
- </span>
61
- )}
62
- </div>
63
- {count !== undefined && (
64
- <span className="text-xs font-medium text-muted-foreground tabular-nums">
65
- {count}
66
- </span>
67
- )}
68
- </div>
69
- )}
70
- {children}
71
- </div>
72
- )
73
- }
74
-
75
- export function BentoCardSkeleton({ size = '1x1' }: { size?: BentoSize }) {
76
- return (
77
- <div
78
- className={cn(
79
- 'rounded-xl border bg-card p-4 animate-pulse',
80
- sizeClasses[size]
81
- )}
82
- >
83
- <div className="h-3 w-16 bg-muted rounded mb-3" />
84
- <div className="h-6 w-24 bg-muted rounded mb-2" />
85
- <div className="h-3 w-full bg-muted rounded" />
86
- </div>
87
- )
88
- }
@@ -1,172 +0,0 @@
1
- 'use client'
2
-
3
- import { useEffect, useState, useMemo } from 'react'
4
- import Link from 'next/link'
5
- import { cn } from '@/lib/utils'
6
- import { ArrowLeft, TrendingUp, TrendingDown } from 'lucide-react'
7
- import { ProgressRing } from './ProgressRing'
8
- import { SparklineChart } from './SparklineChart'
9
- import type { TimelineEvent } from '@/lib/parse-prjct-files'
10
-
11
- interface HeroSectionProps {
12
- projectId: string
13
- projectName: string
14
- tasksCompleted: number
15
- healthScore: number
16
- velocity: number
17
- velocityChange: number
18
- insightMessage: string
19
- timeline?: TimelineEvent[]
20
- }
21
-
22
- // Animated count-up hook
23
- function useCountUp(target: number, duration: number = 800) {
24
- const [count, setCount] = useState(0)
25
-
26
- useEffect(() => {
27
- if (target === 0) {
28
- setCount(0)
29
- return
30
- }
31
-
32
- let start = 0
33
- const startTime = performance.now()
34
-
35
- const animate = (currentTime: number) => {
36
- const elapsed = currentTime - startTime
37
- const progress = Math.min(elapsed / duration, 1)
38
-
39
- // Easing function (ease-out cubic)
40
- const easeOut = 1 - Math.pow(1 - progress, 3)
41
- const current = Math.floor(easeOut * target)
42
-
43
- setCount(current)
44
-
45
- if (progress < 1) {
46
- requestAnimationFrame(animate)
47
- } else {
48
- setCount(target)
49
- }
50
- }
51
-
52
- requestAnimationFrame(animate)
53
- }, [target, duration])
54
-
55
- return count
56
- }
57
-
58
- // Calculate 7-day activity data from timeline
59
- function getWeeklyActivityData(timeline: TimelineEvent[]): number[] {
60
- const today = new Date()
61
- const counts: number[] = []
62
-
63
- for (let i = 6; i >= 0; i--) {
64
- const date = new Date(today)
65
- date.setDate(date.getDate() - i)
66
- const dateStr = date.toISOString().split('T')[0]
67
-
68
- const count = timeline.filter(e => {
69
- if (!e.ts) return false
70
- return e.ts.startsWith(dateStr)
71
- }).length
72
-
73
- counts.push(count)
74
- }
75
-
76
- return counts
77
- }
78
-
79
- export function HeroSection({
80
- projectId,
81
- projectName,
82
- tasksCompleted,
83
- healthScore,
84
- velocity,
85
- velocityChange,
86
- insightMessage,
87
- timeline = [],
88
- }: HeroSectionProps) {
89
- const animatedCount = useCountUp(tasksCompleted)
90
- const weeklyData = useMemo(() => getWeeklyActivityData(timeline), [timeline])
91
-
92
- const healthColor = healthScore >= 70 ? 'success' : healthScore >= 40 ? 'warning' : 'destructive'
93
-
94
- return (
95
- <div className="relative mb-8">
96
- {/* Background gradient based on health */}
97
- <div
98
- className={cn(
99
- 'absolute inset-0 -m-8 rounded-2xl opacity-30 blur-3xl transition-colors duration-1000',
100
- healthScore >= 70 && 'bg-gradient-to-br from-emerald-500/20 to-transparent',
101
- healthScore >= 40 && healthScore < 70 && 'bg-gradient-to-br from-amber-500/20 to-transparent',
102
- healthScore < 40 && 'bg-gradient-to-br from-destructive/20 to-transparent'
103
- )}
104
- />
105
-
106
- <div className="relative flex items-start justify-between">
107
- {/* Left: Health ring + Main metric */}
108
- <div className="flex items-start gap-6">
109
- <ProgressRing
110
- value={healthScore}
111
- size="xl"
112
- accentColor={healthColor}
113
- />
114
-
115
- <div>
116
- {/* Tasks completed - big number */}
117
- <div className="flex items-baseline gap-3">
118
- <span className="text-7xl font-bold tracking-tighter tabular-nums">
119
- {animatedCount}
120
- </span>
121
- <span className="text-lg text-muted-foreground">tasks completed</span>
122
- </div>
123
-
124
- {/* Velocity trend */}
125
- {velocityChange !== 0 && (
126
- <div className="flex items-center gap-2 mt-2">
127
- <span
128
- className={cn(
129
- 'inline-flex items-center gap-1 text-sm font-medium px-2 py-0.5 rounded-md',
130
- velocityChange >= 0
131
- ? 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400'
132
- : 'bg-muted text-muted-foreground'
133
- )}
134
- >
135
- {velocityChange >= 0 ? (
136
- <TrendingUp className="h-3.5 w-3.5" />
137
- ) : (
138
- <TrendingDown className="h-3.5 w-3.5" />
139
- )}
140
- {velocityChange >= 0 ? '+' : ''}{velocityChange}%
141
- </span>
142
- <span className="text-sm text-muted-foreground">vs last week</span>
143
- </div>
144
- )}
145
-
146
- {/* Insight message */}
147
- <p className="text-muted-foreground mt-3 max-w-md">{insightMessage}</p>
148
- </div>
149
- </div>
150
-
151
- {/* Right: Sparkline + Navigation */}
152
- <div className="flex flex-col items-end gap-4">
153
- <Link
154
- href={`/project/${projectId}`}
155
- className="flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors"
156
- >
157
- <ArrowLeft className="w-4 h-4" />
158
- {projectName}
159
- </Link>
160
-
161
- {/* 7-day sparkline */}
162
- <div className="w-32">
163
- <p className="text-[10px] uppercase tracking-wider text-muted-foreground mb-1 text-right">
164
- 7-day activity
165
- </p>
166
- <SparklineChart data={weeklyData} height={40} />
167
- </div>
168
- </div>
169
- </div>
170
- </div>
171
- )
172
- }