prjct-cli 0.11.4 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (385) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +81 -25
  3. package/bin/dev.js +1 -1
  4. package/bin/generate-views.js +209 -0
  5. package/bin/migrate-to-json.js +742 -0
  6. package/bin/prjct +5 -5
  7. package/bin/serve.js +246 -54
  8. package/core/__tests__/agentic/{memory-system.test.js → memory-system.test.ts} +12 -23
  9. package/core/__tests__/agentic/{plan-mode.test.js → plan-mode.test.ts} +26 -24
  10. package/core/__tests__/agentic/{prompt-builder.test.js → prompt-builder.test.ts} +3 -8
  11. package/core/__tests__/utils/date-helper.test.ts +405 -0
  12. package/core/__tests__/utils/{output.test.js → output.test.ts} +12 -24
  13. package/core/agentic/agent-router.ts +137 -0
  14. package/core/agentic/chain-of-thought.ts +228 -0
  15. package/core/agentic/command-executor/command-executor.ts +384 -0
  16. package/core/agentic/command-executor/index.ts +16 -0
  17. package/core/agentic/command-executor/status-signal.ts +38 -0
  18. package/core/agentic/command-executor/types.ts +79 -0
  19. package/core/agentic/command-executor.ts +8 -0
  20. package/core/agentic/{context-builder.js → context-builder.ts} +99 -89
  21. package/core/agentic/context-filter.ts +365 -0
  22. package/core/agentic/ground-truth/index.ts +76 -0
  23. package/core/agentic/ground-truth/types.ts +33 -0
  24. package/core/agentic/ground-truth/utils.ts +48 -0
  25. package/core/agentic/ground-truth/verifiers/analyze.ts +54 -0
  26. package/core/agentic/ground-truth/verifiers/done.ts +75 -0
  27. package/core/agentic/ground-truth/verifiers/feature.ts +70 -0
  28. package/core/agentic/ground-truth/verifiers/index.ts +37 -0
  29. package/core/agentic/ground-truth/verifiers/init.ts +52 -0
  30. package/core/agentic/ground-truth/verifiers/now.ts +57 -0
  31. package/core/agentic/ground-truth/verifiers/ship.ts +85 -0
  32. package/core/agentic/ground-truth/verifiers/spec.ts +45 -0
  33. package/core/agentic/ground-truth/verifiers/sync.ts +47 -0
  34. package/core/agentic/ground-truth/verifiers.ts +6 -0
  35. package/core/agentic/ground-truth.ts +8 -0
  36. package/core/agentic/loop-detector/error-analysis.ts +97 -0
  37. package/core/agentic/loop-detector/hallucination.ts +71 -0
  38. package/core/agentic/loop-detector/index.ts +41 -0
  39. package/core/agentic/loop-detector/loop-detector.ts +222 -0
  40. package/core/agentic/loop-detector/types.ts +66 -0
  41. package/core/agentic/loop-detector.ts +8 -0
  42. package/core/agentic/memory-system/history.ts +53 -0
  43. package/core/agentic/memory-system/index.ts +192 -0
  44. package/core/agentic/memory-system/patterns.ts +156 -0
  45. package/core/agentic/memory-system/semantic-memories.ts +277 -0
  46. package/core/agentic/memory-system/session.ts +21 -0
  47. package/core/agentic/memory-system/types.ts +159 -0
  48. package/core/agentic/memory-system.ts +8 -0
  49. package/core/agentic/parallel-tools.ts +165 -0
  50. package/core/agentic/plan-mode/approval.ts +57 -0
  51. package/core/agentic/plan-mode/constants.ts +44 -0
  52. package/core/agentic/plan-mode/index.ts +28 -0
  53. package/core/agentic/plan-mode/plan-mode.ts +406 -0
  54. package/core/agentic/plan-mode/types.ts +193 -0
  55. package/core/agentic/plan-mode.ts +8 -0
  56. package/core/agentic/prompt-builder.ts +566 -0
  57. package/core/agentic/response-templates.ts +164 -0
  58. package/core/agentic/semantic-compression.ts +273 -0
  59. package/core/agentic/services.ts +206 -0
  60. package/core/agentic/smart-context.ts +476 -0
  61. package/core/agentic/{template-loader.js → template-loader.ts} +35 -18
  62. package/core/agentic/think-blocks.ts +202 -0
  63. package/core/agentic/tool-registry.ts +119 -0
  64. package/core/agentic/validation-rules.ts +313 -0
  65. package/core/agents/index.ts +28 -0
  66. package/core/agents/performance.ts +444 -0
  67. package/core/agents/types.ts +126 -0
  68. package/core/bus/{index.js → index.ts} +57 -61
  69. package/core/command-registry/categories.ts +23 -0
  70. package/core/command-registry/commands.ts +15 -0
  71. package/core/command-registry/core-commands.ts +319 -0
  72. package/core/command-registry/index.ts +158 -0
  73. package/core/command-registry/optional-commands.ts +119 -0
  74. package/core/command-registry/setup-commands.ts +53 -0
  75. package/core/command-registry/types.ts +59 -0
  76. package/core/command-registry.ts +9 -0
  77. package/core/commands/analysis.ts +298 -0
  78. package/core/commands/analytics.ts +288 -0
  79. package/core/commands/base.ts +273 -0
  80. package/core/commands/index.ts +211 -0
  81. package/core/commands/maintenance.ts +226 -0
  82. package/core/commands/planning.ts +311 -0
  83. package/core/commands/setup.ts +309 -0
  84. package/core/commands/shipping.ts +188 -0
  85. package/core/commands/types.ts +183 -0
  86. package/core/commands/workflow.ts +226 -0
  87. package/core/commands.ts +11 -0
  88. package/core/constants/formats.ts +187 -0
  89. package/core/constants/index.ts +7 -0
  90. package/core/{context-sync.js → context-sync.ts} +59 -26
  91. package/core/data/agents-manager.ts +76 -0
  92. package/core/data/analysis-manager.ts +83 -0
  93. package/core/data/base-manager.ts +156 -0
  94. package/core/data/ideas-manager.ts +81 -0
  95. package/core/data/index.ts +32 -0
  96. package/core/data/outcomes-manager.ts +96 -0
  97. package/core/data/project-manager.ts +75 -0
  98. package/core/data/roadmap-manager.ts +118 -0
  99. package/core/data/shipped-manager.ts +65 -0
  100. package/core/data/state-manager.ts +214 -0
  101. package/core/domain/{agent-generator.js → agent-generator.ts} +77 -57
  102. package/core/domain/{agent-loader.js → agent-loader.ts} +65 -56
  103. package/core/domain/{agent-matcher.js → agent-matcher.ts} +51 -24
  104. package/core/domain/{agent-validator.js → agent-validator.ts} +70 -37
  105. package/core/domain/{analyzer.js → analyzer.ts} +91 -85
  106. package/core/domain/{architect-session.js → architect-session.ts} +49 -34
  107. package/core/domain/{architecture-generator.js → architecture-generator.ts} +25 -13
  108. package/core/domain/{context-estimator.js → context-estimator.ts} +57 -36
  109. package/core/domain/{product-standards.js → product-standards.ts} +40 -26
  110. package/core/domain/{smart-cache.js → smart-cache.ts} +39 -30
  111. package/core/domain/{snapshot-manager.js → snapshot-manager.ts} +103 -100
  112. package/core/domain/{task-analyzer.js → task-analyzer.ts} +82 -43
  113. package/core/domain/task-stack/index.ts +19 -0
  114. package/core/domain/task-stack/parser.ts +86 -0
  115. package/core/domain/task-stack/storage.ts +123 -0
  116. package/core/domain/task-stack/task-stack.ts +340 -0
  117. package/core/domain/task-stack/types.ts +51 -0
  118. package/core/domain/task-stack.ts +8 -0
  119. package/core/{index.js → index.ts} +61 -18
  120. package/core/infrastructure/{agent-detector.js → agent-detector.ts} +62 -23
  121. package/core/infrastructure/agents/{claude-agent.js → claude-agent.ts} +61 -21
  122. package/core/infrastructure/{author-detector.js → author-detector.ts} +42 -49
  123. package/core/infrastructure/{capability-installer.js → capability-installer.ts} +51 -27
  124. package/core/infrastructure/{command-installer.js → command-installer/command-installer.ts} +43 -144
  125. package/core/infrastructure/command-installer/global-config.ts +106 -0
  126. package/core/infrastructure/command-installer/index.ts +25 -0
  127. package/core/infrastructure/command-installer/types.ts +41 -0
  128. package/core/infrastructure/command-installer.ts +8 -0
  129. package/core/infrastructure/{config-manager.js → config-manager.ts} +60 -80
  130. package/core/infrastructure/{editors-config.js → editors-config.ts} +33 -31
  131. package/core/infrastructure/legacy-installer-detector/cleanup.ts +216 -0
  132. package/core/infrastructure/legacy-installer-detector/detection.ts +95 -0
  133. package/core/infrastructure/legacy-installer-detector/index.ts +171 -0
  134. package/core/infrastructure/legacy-installer-detector/migration.ts +87 -0
  135. package/core/infrastructure/legacy-installer-detector/types.ts +42 -0
  136. package/core/infrastructure/legacy-installer-detector.ts +7 -0
  137. package/core/infrastructure/migrator/file-operations.ts +125 -0
  138. package/core/infrastructure/migrator/index.ts +288 -0
  139. package/core/infrastructure/migrator/project-scanner.ts +89 -0
  140. package/core/infrastructure/migrator/reports.ts +117 -0
  141. package/core/infrastructure/migrator/types.ts +124 -0
  142. package/core/infrastructure/migrator/validation.ts +94 -0
  143. package/core/infrastructure/migrator/version-migration.ts +117 -0
  144. package/core/infrastructure/migrator.ts +10 -0
  145. package/core/infrastructure/{path-manager.js → path-manager.ts} +51 -91
  146. package/core/infrastructure/session-manager/index.ts +23 -0
  147. package/core/infrastructure/session-manager/migration.ts +88 -0
  148. package/core/infrastructure/session-manager/session-manager.ts +307 -0
  149. package/core/infrastructure/session-manager/types.ts +45 -0
  150. package/core/infrastructure/session-manager.ts +8 -0
  151. package/core/infrastructure/{setup.js → setup.ts} +29 -21
  152. package/core/infrastructure/{update-checker.js → update-checker.ts} +40 -18
  153. package/core/outcomes/analyzer.ts +333 -0
  154. package/core/outcomes/index.ts +34 -0
  155. package/core/outcomes/recorder.ts +194 -0
  156. package/core/outcomes/types.ts +145 -0
  157. package/core/plugin/{hooks.js → hooks.ts} +56 -58
  158. package/core/plugin/{index.js → index.ts} +19 -8
  159. package/core/plugin/{loader.js → loader.ts} +87 -69
  160. package/core/plugin/{registry.js → registry.ts} +49 -45
  161. package/core/plugins/{webhook.js → webhook.ts} +43 -27
  162. package/core/schemas/agents.ts +27 -0
  163. package/core/schemas/analysis.ts +41 -0
  164. package/core/schemas/ideas.ts +83 -0
  165. package/core/schemas/index.ts +73 -0
  166. package/core/schemas/outcomes.ts +22 -0
  167. package/core/schemas/project.ts +26 -0
  168. package/core/schemas/roadmap.ts +90 -0
  169. package/core/schemas/shipped.ts +82 -0
  170. package/core/schemas/state.ts +107 -0
  171. package/core/session/index.ts +17 -0
  172. package/core/session/{metrics.js → metrics.ts} +64 -46
  173. package/core/session/{index.js → session-manager.ts} +51 -117
  174. package/core/session/types.ts +29 -0
  175. package/core/session/utils.ts +57 -0
  176. package/core/state/index.ts +25 -0
  177. package/core/state/manager.ts +376 -0
  178. package/core/state/types.ts +185 -0
  179. package/core/tsconfig.json +22 -0
  180. package/core/types/index.ts +506 -0
  181. package/core/utils/{animations.js → animations.ts} +74 -28
  182. package/core/utils/{branding.js → branding.ts} +29 -4
  183. package/core/utils/{date-helper.js → date-helper.ts} +31 -74
  184. package/core/utils/file-helper.ts +262 -0
  185. package/core/utils/{jsonl-helper.js → jsonl-helper.ts} +71 -107
  186. package/core/utils/{logger.js → logger.ts} +24 -12
  187. package/core/utils/{output.js → output.ts} +25 -13
  188. package/core/utils/{project-capabilities.js → project-capabilities.ts} +31 -18
  189. package/core/utils/{session-helper.js → session-helper.ts} +79 -66
  190. package/core/utils/{version.js → version.ts} +23 -31
  191. package/core/view-generator.ts +536 -0
  192. package/package.json +23 -17
  193. package/packages/shared/.turbo/turbo-build.log +14 -0
  194. package/packages/shared/dist/index.d.ts +8 -613
  195. package/packages/shared/dist/index.d.ts.map +1 -0
  196. package/packages/shared/dist/index.js +4110 -118
  197. package/packages/shared/dist/schemas.d.ts +408 -0
  198. package/packages/shared/dist/schemas.d.ts.map +1 -0
  199. package/packages/shared/dist/types.d.ts +144 -0
  200. package/packages/shared/dist/types.d.ts.map +1 -0
  201. package/packages/shared/dist/unified.d.ts +139 -0
  202. package/packages/shared/dist/unified.d.ts.map +1 -0
  203. package/packages/shared/dist/utils.d.ts +60 -0
  204. package/packages/shared/dist/utils.d.ts.map +1 -0
  205. package/packages/shared/package.json +4 -4
  206. package/packages/shared/src/index.ts +1 -0
  207. package/packages/shared/src/unified.ts +174 -0
  208. package/packages/web/app/api/claude/sessions/route.ts +1 -1
  209. package/packages/web/app/api/claude/status/route.ts +1 -1
  210. package/packages/web/app/api/migrate/route.ts +46 -0
  211. package/packages/web/app/api/projects/[id]/route.ts +1 -1
  212. package/packages/web/app/api/projects/[id]/stats/route.ts +30 -2
  213. package/packages/web/app/api/projects/[id]/status/route.ts +1 -1
  214. package/packages/web/app/api/projects/route.ts +1 -1
  215. package/packages/web/app/api/settings/route.ts +97 -0
  216. package/packages/web/app/api/v2/projects/[id]/unified/route.ts +57 -0
  217. package/packages/web/app/globals.css +38 -0
  218. package/packages/web/app/layout.tsx +10 -2
  219. package/packages/web/app/page.tsx +9 -224
  220. package/packages/web/app/project/[id]/page.tsx +191 -63
  221. package/packages/web/app/project/[id]/stats/loading.tsx +43 -0
  222. package/packages/web/app/project/[id]/stats/page.tsx +203 -403
  223. package/packages/web/app/settings/page.tsx +222 -2
  224. package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +2 -0
  225. package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +50 -0
  226. package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +8 -0
  227. package/packages/web/components/ActivityTimeline/hooks/index.ts +2 -0
  228. package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +9 -0
  229. package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +23 -0
  230. package/packages/web/components/ActivityTimeline/index.ts +2 -0
  231. package/packages/web/components/AgentsCard/AgentsCard.tsx +63 -0
  232. package/packages/web/components/AgentsCard/AgentsCard.types.ts +13 -0
  233. package/packages/web/components/AgentsCard/index.ts +2 -0
  234. package/packages/web/components/AppSidebar/AppSidebar.tsx +134 -0
  235. package/packages/web/components/AppSidebar/index.ts +1 -0
  236. package/packages/web/components/BackLink/BackLink.tsx +18 -0
  237. package/packages/web/components/BackLink/BackLink.types.ts +5 -0
  238. package/packages/web/components/BackLink/index.ts +2 -0
  239. package/packages/web/components/BentoCard/BentoCard.constants.ts +16 -0
  240. package/packages/web/components/BentoCard/BentoCard.tsx +47 -0
  241. package/packages/web/components/BentoCard/BentoCard.types.ts +15 -0
  242. package/packages/web/components/BentoCard/index.ts +2 -0
  243. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +9 -0
  244. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +18 -0
  245. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +5 -0
  246. package/packages/web/components/BentoCardSkeleton/index.ts +2 -0
  247. package/packages/web/components/BentoGrid/BentoGrid.tsx +18 -0
  248. package/packages/web/components/BentoGrid/BentoGrid.types.ts +4 -0
  249. package/packages/web/components/BentoGrid/index.ts +2 -0
  250. package/packages/web/components/CommandButton/index.ts +1 -0
  251. package/packages/web/components/ConnectionStatus/index.ts +1 -0
  252. package/packages/web/components/DashboardContent/DashboardContent.tsx +254 -0
  253. package/packages/web/components/DashboardContent/index.ts +1 -0
  254. package/packages/web/components/DateGroup/DateGroup.tsx +18 -0
  255. package/packages/web/components/DateGroup/DateGroup.types.ts +6 -0
  256. package/packages/web/components/DateGroup/DateGroup.utils.ts +11 -0
  257. package/packages/web/components/DateGroup/index.ts +2 -0
  258. package/packages/web/components/EmptyState/EmptyState.tsx +58 -0
  259. package/packages/web/components/EmptyState/EmptyState.types.ts +10 -0
  260. package/packages/web/components/EmptyState/index.ts +2 -0
  261. package/packages/web/components/EventRow/EventRow.constants.ts +10 -0
  262. package/packages/web/components/EventRow/EventRow.tsx +49 -0
  263. package/packages/web/components/EventRow/EventRow.types.ts +7 -0
  264. package/packages/web/components/EventRow/EventRow.utils.ts +49 -0
  265. package/packages/web/components/EventRow/index.ts +2 -0
  266. package/packages/web/components/ExpandButton/ExpandButton.tsx +18 -0
  267. package/packages/web/components/ExpandButton/ExpandButton.types.ts +6 -0
  268. package/packages/web/components/ExpandButton/index.ts +2 -0
  269. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +14 -0
  270. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +5 -0
  271. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +13 -0
  272. package/packages/web/components/HealthGradientBackground/index.ts +2 -0
  273. package/packages/web/components/HeroSection/HeroSection.tsx +55 -0
  274. package/packages/web/components/HeroSection/HeroSection.types.ts +14 -0
  275. package/packages/web/components/HeroSection/HeroSection.utils.ts +7 -0
  276. package/packages/web/components/HeroSection/hooks/index.ts +2 -0
  277. package/packages/web/components/HeroSection/hooks/useCountUp.ts +45 -0
  278. package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +18 -0
  279. package/packages/web/components/HeroSection/index.ts +2 -0
  280. package/packages/web/components/IdeasCard/IdeasCard.tsx +48 -0
  281. package/packages/web/components/IdeasCard/IdeasCard.types.ts +9 -0
  282. package/packages/web/components/IdeasCard/index.ts +2 -0
  283. package/packages/web/components/InsightMessage/InsightMessage.tsx +9 -0
  284. package/packages/web/components/InsightMessage/InsightMessage.types.ts +3 -0
  285. package/packages/web/components/InsightMessage/index.ts +2 -0
  286. package/packages/web/components/Logo/index.ts +1 -0
  287. package/packages/web/components/MarkdownContent/index.ts +1 -0
  288. package/packages/web/components/NowCard/NowCard.tsx +93 -0
  289. package/packages/web/components/NowCard/NowCard.types.ts +15 -0
  290. package/packages/web/components/NowCard/index.ts +2 -0
  291. package/packages/web/components/ProgressRing/ProgressRing.constants.ts +20 -0
  292. package/packages/web/components/ProgressRing/ProgressRing.tsx +51 -0
  293. package/packages/web/components/ProgressRing/ProgressRing.types.ts +11 -0
  294. package/packages/web/components/ProgressRing/index.ts +2 -0
  295. package/packages/web/components/ProjectAvatar/index.ts +1 -0
  296. package/packages/web/components/Providers/index.ts +1 -0
  297. package/packages/web/components/QueueCard/QueueCard.tsx +72 -0
  298. package/packages/web/components/QueueCard/QueueCard.types.ts +11 -0
  299. package/packages/web/components/QueueCard/QueueCard.utils.ts +12 -0
  300. package/packages/web/components/QueueCard/index.ts +2 -0
  301. package/packages/web/components/RoadmapCard/RoadmapCard.tsx +77 -0
  302. package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +15 -0
  303. package/packages/web/components/RoadmapCard/index.ts +2 -0
  304. package/packages/web/components/ShipsCard/ShipsCard.tsx +52 -0
  305. package/packages/web/components/ShipsCard/ShipsCard.types.ts +12 -0
  306. package/packages/web/components/ShipsCard/ShipsCard.utils.ts +4 -0
  307. package/packages/web/components/ShipsCard/index.ts +2 -0
  308. package/packages/web/components/SparklineChart/SparklineChart.tsx +38 -0
  309. package/packages/web/components/SparklineChart/SparklineChart.types.ts +6 -0
  310. package/packages/web/components/SparklineChart/index.ts +2 -0
  311. package/packages/web/components/StreakCard/StreakCard.constants.ts +2 -0
  312. package/packages/web/components/StreakCard/StreakCard.tsx +53 -0
  313. package/packages/web/components/StreakCard/StreakCard.types.ts +4 -0
  314. package/packages/web/components/StreakCard/index.ts +2 -0
  315. package/packages/web/components/TasksCounter/TasksCounter.tsx +14 -0
  316. package/packages/web/components/TasksCounter/TasksCounter.types.ts +3 -0
  317. package/packages/web/components/TasksCounter/index.ts +2 -0
  318. package/packages/web/components/TechStackBadges/index.ts +1 -0
  319. package/packages/web/components/{TerminalTab.tsx → TerminalTabs/TerminalTab.tsx} +11 -0
  320. package/packages/web/components/{TerminalTabs.tsx → TerminalTabs/TerminalTabs.tsx} +29 -28
  321. package/packages/web/components/TerminalTabs/index.ts +1 -0
  322. package/packages/web/components/VelocityBadge/VelocityBadge.tsx +27 -0
  323. package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +3 -0
  324. package/packages/web/components/VelocityBadge/index.ts +2 -0
  325. package/packages/web/components/VelocityCard/VelocityCard.tsx +71 -0
  326. package/packages/web/components/VelocityCard/VelocityCard.types.ts +7 -0
  327. package/packages/web/components/VelocityCard/index.ts +2 -0
  328. package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +13 -0
  329. package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +3 -0
  330. package/packages/web/components/WeeklySparkline/index.ts +2 -0
  331. package/packages/web/components/ui/input.tsx +21 -0
  332. package/packages/web/components/ui/tooltip.tsx +2 -2
  333. package/packages/web/context/TerminalTabsContext.tsx +46 -1
  334. package/packages/web/hooks/useClaudeTerminal.ts +71 -21
  335. package/packages/web/hooks/useProjectStats.ts +55 -0
  336. package/packages/web/hooks/useProjects.ts +6 -6
  337. package/packages/web/lib/actions/projects.ts +15 -0
  338. package/packages/web/lib/json-loader.ts +630 -0
  339. package/packages/web/lib/services/index.ts +9 -0
  340. package/packages/web/lib/services/migration.server.ts +598 -0
  341. package/packages/web/lib/services/projects.server.ts +52 -0
  342. package/packages/web/lib/services/stats.server.ts +264 -0
  343. package/packages/web/lib/unified-loader.ts +396 -0
  344. package/packages/web/next-env.d.ts +1 -1
  345. package/packages/web/package.json +10 -6
  346. package/packages/web/server.ts +36 -6
  347. package/templates/commands/done.md +76 -32
  348. package/templates/commands/feature.md +121 -47
  349. package/templates/commands/idea.md +81 -8
  350. package/templates/commands/now.md +41 -17
  351. package/templates/commands/ship.md +64 -25
  352. package/templates/commands/sync.md +28 -3
  353. package/core/agentic/agent-router.js +0 -128
  354. package/core/agentic/chain-of-thought.js +0 -578
  355. package/core/agentic/command-executor.js +0 -421
  356. package/core/agentic/context-filter.js +0 -354
  357. package/core/agentic/ground-truth.js +0 -591
  358. package/core/agentic/loop-detector.js +0 -406
  359. package/core/agentic/memory-system.js +0 -850
  360. package/core/agentic/parallel-tools.js +0 -366
  361. package/core/agentic/plan-mode.js +0 -572
  362. package/core/agentic/prompt-builder.js +0 -338
  363. package/core/agentic/response-templates.js +0 -290
  364. package/core/agentic/semantic-compression.js +0 -517
  365. package/core/agentic/think-blocks.js +0 -657
  366. package/core/agentic/tool-registry.js +0 -184
  367. package/core/agentic/validation-rules.js +0 -380
  368. package/core/command-registry.js +0 -698
  369. package/core/commands.js +0 -2237
  370. package/core/domain/task-stack.js +0 -497
  371. package/core/infrastructure/legacy-installer-detector.js +0 -546
  372. package/core/infrastructure/migrator.js +0 -799
  373. package/core/infrastructure/session-manager.js +0 -390
  374. package/core/utils/file-helper.js +0 -329
  375. package/packages/web/app/api/projects/[id]/delete/route.ts +0 -21
  376. package/packages/web/app/api/stats/route.ts +0 -38
  377. package/packages/web/components/AppSidebar.tsx +0 -113
  378. package/packages/web/hooks/useStats.ts +0 -28
  379. /package/packages/web/components/{CommandButton.tsx → CommandButton/CommandButton.tsx} +0 -0
  380. /package/packages/web/components/{ConnectionStatus.tsx → ConnectionStatus/ConnectionStatus.tsx} +0 -0
  381. /package/packages/web/components/{Logo.tsx → Logo/Logo.tsx} +0 -0
  382. /package/packages/web/components/{MarkdownContent.tsx → MarkdownContent/MarkdownContent.tsx} +0 -0
  383. /package/packages/web/components/{ProjectAvatar.tsx → ProjectAvatar/ProjectAvatar.tsx} +0 -0
  384. /package/packages/web/components/{providers.tsx → Providers/Providers.tsx} +0 -0
  385. /package/packages/web/components/{TechStackBadges.tsx → TechStackBadges/TechStackBadges.tsx} +0 -0
@@ -0,0 +1,15 @@
1
+ export interface RoadmapPhase {
2
+ name: string
3
+ progress: number
4
+ features?: Array<{ name: string; status: string }>
5
+ }
6
+
7
+ export interface RoadmapData {
8
+ phases: RoadmapPhase[]
9
+ progress: number
10
+ }
11
+
12
+ export interface RoadmapCardProps {
13
+ roadmap: RoadmapData | null
14
+ className?: string
15
+ }
@@ -0,0 +1,2 @@
1
+ export { RoadmapCard } from './RoadmapCard'
2
+ export type { RoadmapCardProps } from './RoadmapCard.types'
@@ -0,0 +1,52 @@
1
+ import { BentoCard } from '@/components/BentoCard'
2
+ import { EmptyState } from '@/components/EmptyState'
3
+ import { Rocket } from 'lucide-react'
4
+ import { Badge } from '@/components/ui/badge'
5
+ import { formatShipDate } from './ShipsCard.utils'
6
+ import type { ShipsCardProps } from './ShipsCard.types'
7
+
8
+ export function ShipsCard({ ships, totalShips = 0, className }: ShipsCardProps) {
9
+ const displayShips = ships.slice(0, 4)
10
+
11
+ return (
12
+ <BentoCard
13
+ size="1x2"
14
+ title="Ships"
15
+ icon={Rocket}
16
+ count={totalShips}
17
+ accentColor={ships.length > 0 ? 'success' : 'default'}
18
+ className={className}
19
+ >
20
+ {ships.length === 0 ? (
21
+ <EmptyState
22
+ icon={Rocket}
23
+ title="Nothing shipped yet"
24
+ description="Ship your first feature"
25
+ command="/p:ship"
26
+ compact
27
+ />
28
+ ) : (
29
+ <div className="space-y-3">
30
+ {displayShips.map((ship, i) => (
31
+ <div key={i} className="group">
32
+ <div className="flex items-center gap-2">
33
+ {ship.version && (
34
+ <Badge variant="outline" className="text-[10px] px-1.5 py-0 font-mono shrink-0">
35
+ {ship.version}
36
+ </Badge>
37
+ )}
38
+ <p className="text-sm font-medium truncate group-hover:text-foreground transition-colors">
39
+ {ship.name}
40
+ </p>
41
+ </div>
42
+ <p className="text-[10px] text-muted-foreground mt-0.5">
43
+ {formatShipDate(ship.date)}
44
+ {ship.duration && ` · ${ship.duration}`}
45
+ </p>
46
+ </div>
47
+ ))}
48
+ </div>
49
+ )}
50
+ </BentoCard>
51
+ )
52
+ }
@@ -0,0 +1,12 @@
1
+ export interface Ship {
2
+ name: string
3
+ date: string
4
+ version?: string
5
+ duration?: string
6
+ }
7
+
8
+ export interface ShipsCardProps {
9
+ ships: Ship[]
10
+ totalShips?: number
11
+ className?: string
12
+ }
@@ -0,0 +1,4 @@
1
+ export function formatShipDate(dateString: string): string {
2
+ const date = new Date(dateString)
3
+ return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })
4
+ }
@@ -0,0 +1,2 @@
1
+ export { ShipsCard } from './ShipsCard'
2
+ export type { ShipsCardProps } from './ShipsCard.types'
@@ -0,0 +1,38 @@
1
+ 'use client'
2
+
3
+ import { Area, AreaChart, ResponsiveContainer } from 'recharts'
4
+ import type { SparklineChartProps } from './SparklineChart.types'
5
+
6
+ export function SparklineChart({
7
+ data,
8
+ color = 'currentColor',
9
+ height = 32,
10
+ showArea = true,
11
+ }: SparklineChartProps) {
12
+ const chartData = data.map((value, index) => ({ index, value }))
13
+
14
+ if (data.length === 0) {
15
+ return <div style={{ height }} className="w-full" />
16
+ }
17
+
18
+ return (
19
+ <ResponsiveContainer width="100%" height={height}>
20
+ <AreaChart data={chartData} margin={{ top: 0, right: 0, bottom: 0, left: 0 }}>
21
+ <defs>
22
+ <linearGradient id="sparklineGradient" x1="0" y1="0" x2="0" y2="1">
23
+ <stop offset="0%" stopColor={color} stopOpacity={0.3} />
24
+ <stop offset="100%" stopColor={color} stopOpacity={0} />
25
+ </linearGradient>
26
+ </defs>
27
+ <Area
28
+ type="monotone"
29
+ dataKey="value"
30
+ stroke={color}
31
+ strokeWidth={1.5}
32
+ fill={showArea ? 'url(#sparklineGradient)' : 'none'}
33
+ isAnimationActive={false}
34
+ />
35
+ </AreaChart>
36
+ </ResponsiveContainer>
37
+ )
38
+ }
@@ -0,0 +1,6 @@
1
+ export interface SparklineChartProps {
2
+ data: number[]
3
+ color?: string
4
+ height?: number
5
+ showArea?: boolean
6
+ }
@@ -0,0 +1,2 @@
1
+ export { SparklineChart } from './SparklineChart'
2
+ export type { SparklineChartProps } from './SparklineChart.types'
@@ -0,0 +1,2 @@
1
+ export const STREAK_HOT_THRESHOLD = 3
2
+ export const STREAK_ON_FIRE_THRESHOLD = 7
@@ -0,0 +1,53 @@
1
+ import { BentoCard } from '@/components/BentoCard'
2
+ import { Flame } from 'lucide-react'
3
+ import { cn } from '@/lib/utils'
4
+ import { STREAK_HOT_THRESHOLD, STREAK_ON_FIRE_THRESHOLD } from './StreakCard.constants'
5
+ import type { StreakCardProps } from './StreakCard.types'
6
+
7
+ export function StreakCard({ streak, className }: StreakCardProps) {
8
+ const isHot = streak >= STREAK_HOT_THRESHOLD
9
+ const isOnFire = streak >= STREAK_ON_FIRE_THRESHOLD
10
+
11
+ return (
12
+ <BentoCard
13
+ size="1x1"
14
+ title="Streak"
15
+ icon={Flame}
16
+ accentColor={isOnFire ? 'warning' : 'default'}
17
+ className={className}
18
+ >
19
+ <div className="flex flex-col h-full justify-between">
20
+ <div className="flex items-center gap-3">
21
+ <Flame
22
+ className={cn(
23
+ 'h-8 w-8 transition-colors',
24
+ isOnFire ? 'text-orange-500' : isHot ? 'text-amber-500' : 'text-muted-foreground'
25
+ )}
26
+ />
27
+ <div>
28
+ <p className="text-3xl font-bold tabular-nums">{streak}</p>
29
+ <p className="text-xs text-muted-foreground">day{streak !== 1 ? 's' : ''}</p>
30
+ </div>
31
+ </div>
32
+
33
+ <div className="flex gap-1 mt-3">
34
+ {Array.from({ length: 7 }).map((_, i) => (
35
+ <div
36
+ key={i}
37
+ className={cn(
38
+ 'h-1.5 flex-1 rounded-full transition-colors',
39
+ i < streak
40
+ ? isOnFire
41
+ ? 'bg-orange-500'
42
+ : isHot
43
+ ? 'bg-amber-500'
44
+ : 'bg-foreground'
45
+ : 'bg-muted'
46
+ )}
47
+ />
48
+ ))}
49
+ </div>
50
+ </div>
51
+ </BentoCard>
52
+ )
53
+ }
@@ -0,0 +1,4 @@
1
+ export interface StreakCardProps {
2
+ streak: number
3
+ className?: string
4
+ }
@@ -0,0 +1,2 @@
1
+ export { StreakCard } from './StreakCard'
2
+ export type { StreakCardProps } from './StreakCard.types'
@@ -0,0 +1,14 @@
1
+ import type { TasksCounterProps } from './TasksCounter.types'
2
+
3
+ export function TasksCounter({ count }: TasksCounterProps) {
4
+ return (
5
+ <div className="flex flex-col sm:flex-row sm:items-baseline gap-1 sm:gap-3">
6
+ <span className="text-5xl sm:text-6xl md:text-7xl font-bold tracking-tighter tabular-nums">
7
+ {count}
8
+ </span>
9
+ <span className="text-sm sm:text-base md:text-lg text-muted-foreground">
10
+ tasks completed
11
+ </span>
12
+ </div>
13
+ )
14
+ }
@@ -0,0 +1,3 @@
1
+ export interface TasksCounterProps {
2
+ count: number
3
+ }
@@ -0,0 +1,2 @@
1
+ export { TasksCounter } from './TasksCounter'
2
+ export type { TasksCounterProps } from './TasksCounter.types'
@@ -0,0 +1 @@
1
+ export { TechStackBadges } from './TechStackBadges'
@@ -35,6 +35,7 @@ export function TerminalTab({ session, projectDir, isActive }: TerminalTabProps)
35
35
  disconnect,
36
36
  sendInput,
37
37
  focusTerminal,
38
+ fit,
38
39
  } = useClaudeTerminal({
39
40
  sessionId: session.id,
40
41
  projectDir,
@@ -57,6 +58,16 @@ export function TerminalTab({ session, projectDir, isActive }: TerminalTabProps)
57
58
  }
58
59
  }, []) // Empty deps - run only on mount
59
60
 
61
+ // Re-fit terminal when tab becomes active (fixes resize issues when tab was hidden)
62
+ useEffect(() => {
63
+ if (isActive && hasInitializedRef.current) {
64
+ // Use requestAnimationFrame to ensure container is fully visible
65
+ requestAnimationFrame(() => {
66
+ fit()
67
+ })
68
+ }
69
+ }, [isActive, fit])
70
+
60
71
  // Register sendInput and focusTerminal for this session
61
72
  useEffect(() => {
62
73
  registerSendInput(session.id, sendInput)
@@ -90,8 +90,8 @@ export function TerminalTabs({ projectDir }: TerminalTabsProps) {
90
90
 
91
91
  return (
92
92
  <div className="flex flex-col h-full">
93
- {/* Tab bar */}
94
- <div className="flex items-center gap-1 px-2 py-1 bg-card border-b border-border min-h-[40px]">
93
+ {/* Tab bar - scrollable on mobile */}
94
+ <div className="flex items-center gap-1 px-2 py-1.5 bg-card border-b border-border min-h-[44px] md:min-h-[40px] overflow-x-auto scrollbar-hide">
95
95
  {sessions.map(session => (
96
96
  <div
97
97
  key={session.id}
@@ -101,22 +101,23 @@ export function TerminalTabs({ projectDir }: TerminalTabsProps) {
101
101
  tabIndex={0}
102
102
  onKeyDown={(e) => e.key === 'Enter' && setActiveSession(session.id)}
103
103
  className={cn(
104
- 'flex items-center gap-2 px-3 py-1.5 rounded-md text-sm transition-colors cursor-pointer',
105
- 'hover:bg-muted',
104
+ 'flex items-center gap-2 px-3 py-2 md:py-1.5 rounded-md text-sm transition-colors cursor-pointer shrink-0',
105
+ 'hover:bg-muted active:bg-muted/80',
106
+ 'min-h-[36px] md:min-h-0', // Touch-friendly height on mobile
106
107
  session.id === activeSessionId
107
108
  ? 'bg-muted text-foreground'
108
109
  : 'text-muted-foreground'
109
110
  )}
110
111
  >
111
112
  {session.isLoading ? (
112
- <Loader2 className="w-3.5 h-3.5 animate-spin" />
113
+ <Loader2 className="w-3.5 h-3.5 animate-spin shrink-0" />
113
114
  ) : session.isConnected ? (
114
- <span className="relative flex h-2 w-2">
115
+ <span className="relative flex h-2.5 w-2.5 shrink-0">
115
116
  <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" />
116
- <span className="relative inline-flex rounded-full h-2 w-2 bg-green-500" />
117
+ <span className="relative inline-flex rounded-full h-2.5 w-2.5 bg-green-500" />
117
118
  </span>
118
119
  ) : (
119
- <span className="h-2 w-2 rounded-full bg-muted-foreground/50" />
120
+ <span className="h-2.5 w-2.5 rounded-full bg-muted-foreground/50 shrink-0" />
120
121
  )}
121
122
  {editingSessionId === session.id ? (
122
123
  <input
@@ -130,41 +131,41 @@ export function TerminalTabs({ projectDir }: TerminalTabsProps) {
130
131
  className="w-[100px] bg-background border border-border rounded px-1 py-0.5 text-sm outline-none focus:ring-1 focus:ring-ring"
131
132
  />
132
133
  ) : (
133
- <span className="truncate max-w-[100px]">{session.label}</span>
134
+ <span className="truncate max-w-[80px] md:max-w-[100px]">{session.label}</span>
134
135
  )}
135
136
  <button
136
137
  onClick={(e) => handleCloseTab(session.id, e)}
137
- className="p-0.5 rounded hover:bg-background/50 text-muted-foreground hover:text-foreground"
138
+ className="p-1 md:p-0.5 rounded hover:bg-background/50 text-muted-foreground hover:text-foreground shrink-0"
138
139
  >
139
- <X className="w-3 h-3" />
140
+ <X className="w-4 h-4 md:w-3 md:h-3" />
140
141
  </button>
141
142
  </div>
142
143
  ))}
143
144
 
144
- {/* New tab button */}
145
+ {/* New tab button - larger touch target on mobile */}
145
146
  <Button
146
147
  variant="ghost"
147
148
  size="icon"
148
- className="h-7 w-7 ml-1"
149
+ className="h-9 w-9 md:h-7 md:w-7 ml-1 shrink-0"
149
150
  onClick={createSession}
150
151
  >
151
- <Plus className="w-4 h-4" />
152
+ <Plus className="w-5 h-5 md:w-4 md:h-4" />
152
153
  </Button>
153
154
  </div>
154
155
 
155
156
  {/* Terminal area */}
156
157
  <div className="flex-1 relative">
157
158
  {hasNoSessions ? (
158
- <div className="absolute inset-0 flex items-center justify-center bg-background">
159
- <div className="text-center">
160
- <div className="w-16 h-16 rounded-full bg-muted flex items-center justify-center mx-auto mb-4">
161
- <TerminalIcon className="w-8 h-8 text-muted-foreground" />
159
+ <div className="absolute inset-0 flex items-center justify-center bg-background p-4">
160
+ <div className="text-center max-w-xs">
161
+ <div className="w-14 h-14 md:w-16 md:h-16 rounded-full bg-muted flex items-center justify-center mx-auto mb-3 md:mb-4">
162
+ <TerminalIcon className="w-7 h-7 md:w-8 md:h-8 text-muted-foreground" />
162
163
  </div>
163
- <h2 className="text-lg font-medium mb-2">No active sessions</h2>
164
- <p className="text-muted-foreground text-sm mb-4">
165
- Click + or press Start to create a new terminal
164
+ <h2 className="text-base md:text-lg font-medium mb-1.5 md:mb-2">No active sessions</h2>
165
+ <p className="text-muted-foreground text-sm mb-3 md:mb-4">
166
+ Tap + to create a new terminal
166
167
  </p>
167
- <Button onClick={createSession}>
168
+ <Button onClick={createSession} className="min-h-[44px]">
168
169
  <Plus className="w-4 h-4 mr-2" />
169
170
  New Terminal
170
171
  </Button>
@@ -182,23 +183,23 @@ export function TerminalTabs({ projectDir }: TerminalTabsProps) {
182
183
  )}
183
184
  </div>
184
185
 
185
- {/* Close confirmation dialog */}
186
+ {/* Close confirmation dialog - responsive */}
186
187
  <AlertDialog open={!!sessionToClose} onOpenChange={(open: boolean) => !open && setSessionToClose(null)}>
187
- <AlertDialogContent>
188
+ <AlertDialogContent className="max-w-[calc(100vw-2rem)] sm:max-w-lg">
188
189
  <AlertDialogHeader>
189
190
  <AlertDialogTitle className="flex items-center gap-2">
190
- <AlertTriangle className="w-5 h-5 text-destructive" />
191
+ <AlertTriangle className="w-5 h-5 text-destructive shrink-0" />
191
192
  Close Terminal?
192
193
  </AlertDialogTitle>
193
194
  <AlertDialogDescription>
194
195
  This terminal has an active session. Closing it will terminate the connection.
195
196
  </AlertDialogDescription>
196
197
  </AlertDialogHeader>
197
- <AlertDialogFooter>
198
- <AlertDialogCancel>Cancel</AlertDialogCancel>
198
+ <AlertDialogFooter className="flex-col sm:flex-row gap-2">
199
+ <AlertDialogCancel className="w-full sm:w-auto">Cancel</AlertDialogCancel>
199
200
  <AlertDialogAction
200
201
  onClick={handleConfirmClose}
201
- className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
202
+ className="bg-destructive text-destructive-foreground hover:bg-destructive/90 w-full sm:w-auto"
202
203
  >
203
204
  Close Terminal
204
205
  </AlertDialogAction>
@@ -0,0 +1 @@
1
+ export { TerminalTabs } from './TerminalTabs'
@@ -0,0 +1,27 @@
1
+ import { TrendingUp, TrendingDown } from 'lucide-react'
2
+ import { cn } from '@/lib/utils'
3
+ import type { VelocityBadgeProps } from './VelocityBadge.types'
4
+
5
+ export function VelocityBadge({ change }: VelocityBadgeProps) {
6
+ if (change === 0) return null
7
+
8
+ const isPositive = change >= 0
9
+ const Icon = isPositive ? TrendingUp : TrendingDown
10
+
11
+ return (
12
+ <div className="flex items-center gap-2 mt-2">
13
+ <span
14
+ className={cn(
15
+ 'inline-flex items-center gap-1 text-xs sm:text-sm font-medium px-2 py-0.5 rounded-md',
16
+ isPositive
17
+ ? 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400'
18
+ : 'bg-muted text-muted-foreground'
19
+ )}
20
+ >
21
+ <Icon className="h-3 w-3 sm:h-3.5 sm:w-3.5" />
22
+ {isPositive ? '+' : ''}{change}%
23
+ </span>
24
+ <span className="text-xs sm:text-sm text-muted-foreground">vs last week</span>
25
+ </div>
26
+ )
27
+ }
@@ -0,0 +1,3 @@
1
+ export interface VelocityBadgeProps {
2
+ change: number
3
+ }
@@ -0,0 +1,2 @@
1
+ export { VelocityBadge } from './VelocityBadge'
2
+ export type { VelocityBadgeProps } from './VelocityBadge.types'
@@ -0,0 +1,71 @@
1
+ import { BentoCard } from '@/components/BentoCard'
2
+ import { SparklineChart } from '@/components/SparklineChart'
3
+ import { Zap, TrendingUp, TrendingDown, Target } from 'lucide-react'
4
+ import { cn } from '@/lib/utils'
5
+ import type { VelocityCardProps } from './VelocityCard.types'
6
+
7
+ export function VelocityCard({
8
+ tasksPerDay,
9
+ weeklyData = [],
10
+ change = 0,
11
+ estimateAccuracy,
12
+ className,
13
+ }: VelocityCardProps) {
14
+ return (
15
+ <BentoCard
16
+ size="1x1"
17
+ title="Velocity"
18
+ icon={Zap}
19
+ className={className}
20
+ >
21
+ <div className="flex flex-col h-full justify-between">
22
+ <div>
23
+ <p className="text-3xl font-bold tabular-nums">{tasksPerDay}</p>
24
+ <p className="text-xs text-muted-foreground">tasks/day</p>
25
+ </div>
26
+
27
+ {weeklyData.length > 0 && (
28
+ <div className="mt-2">
29
+ <SparklineChart data={weeklyData} height={28} />
30
+ </div>
31
+ )}
32
+
33
+ <div className="flex items-center justify-between mt-2">
34
+ {change !== 0 && (
35
+ <div className="flex items-center gap-1">
36
+ {change >= 0 ? (
37
+ <TrendingUp className="h-3 w-3 text-emerald-500" />
38
+ ) : (
39
+ <TrendingDown className="h-3 w-3 text-muted-foreground" />
40
+ )}
41
+ <span
42
+ className={cn(
43
+ 'text-xs font-medium',
44
+ change >= 0 ? 'text-emerald-600 dark:text-emerald-400' : 'text-muted-foreground'
45
+ )}
46
+ >
47
+ {change >= 0 ? '+' : ''}{change}%
48
+ </span>
49
+ </div>
50
+ )}
51
+
52
+ {estimateAccuracy !== undefined && estimateAccuracy > 0 && (
53
+ <div className="flex items-center gap-1">
54
+ <Target className="h-3 w-3 text-muted-foreground" />
55
+ <span
56
+ className={cn(
57
+ 'text-xs font-medium',
58
+ estimateAccuracy >= 70 ? 'text-emerald-600 dark:text-emerald-400' :
59
+ estimateAccuracy >= 40 ? 'text-amber-600 dark:text-amber-400' :
60
+ 'text-muted-foreground'
61
+ )}
62
+ >
63
+ {estimateAccuracy}% acc
64
+ </span>
65
+ </div>
66
+ )}
67
+ </div>
68
+ </div>
69
+ </BentoCard>
70
+ )
71
+ }
@@ -0,0 +1,7 @@
1
+ export interface VelocityCardProps {
2
+ tasksPerDay: number
3
+ weeklyData?: number[]
4
+ change?: number
5
+ estimateAccuracy?: number
6
+ className?: string
7
+ }
@@ -0,0 +1,2 @@
1
+ export { VelocityCard } from './VelocityCard'
2
+ export type { VelocityCardProps } from './VelocityCard.types'
@@ -0,0 +1,13 @@
1
+ import { SparklineChart } from '@/components/SparklineChart'
2
+ import type { WeeklySparklineProps } from './WeeklySparkline.types'
3
+
4
+ export function WeeklySparkline({ data }: WeeklySparklineProps) {
5
+ return (
6
+ <div className="w-full sm:w-32">
7
+ <p className="text-[10px] uppercase tracking-wider text-muted-foreground mb-1 md:text-right">
8
+ 7-day activity
9
+ </p>
10
+ <SparklineChart data={data} height={40} />
11
+ </div>
12
+ )
13
+ }
@@ -0,0 +1,3 @@
1
+ export interface WeeklySparklineProps {
2
+ data: number[]
3
+ }
@@ -0,0 +1,2 @@
1
+ export { WeeklySparkline } from './WeeklySparkline'
2
+ export type { WeeklySparklineProps } from './WeeklySparkline.types'
@@ -0,0 +1,21 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
6
+ return (
7
+ <input
8
+ type={type}
9
+ data-slot="input"
10
+ className={cn(
11
+ "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
12
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
13
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
14
+ className
15
+ )}
16
+ {...props}
17
+ />
18
+ )
19
+ }
20
+
21
+ export { Input }
@@ -46,13 +46,13 @@ function TooltipContent({
46
46
  data-slot="tooltip-content"
47
47
  sideOffset={sideOffset}
48
48
  className={cn(
49
- "bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
49
+ "bg-popover text-popover-foreground border shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
50
50
  className
51
51
  )}
52
52
  {...props}
53
53
  >
54
54
  {children}
55
- <TooltipPrimitive.Arrow className="bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
55
+ <TooltipPrimitive.Arrow className="bg-popover fill-popover z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
56
56
  </TooltipPrimitive.Content>
57
57
  </TooltipPrimitive.Portal>
58
58
  )
@@ -4,7 +4,7 @@
4
4
  * Terminal Tabs Context - Manage multiple terminal sessions
5
5
  */
6
6
 
7
- import { createContext, useContext, useCallback, useState, useRef, ReactNode } from 'react'
7
+ import { createContext, useContext, useCallback, useState, useRef, useEffect, ReactNode } from 'react'
8
8
 
9
9
  export interface TerminalSession {
10
10
  id: string
@@ -108,6 +108,51 @@ export function TerminalTabsProvider({ children, projectId }: { children: ReactN
108
108
  }
109
109
  }, [activeSessionId, sessions])
110
110
 
111
+ // Check if any session is connected
112
+ const hasConnectedSessions = sessions.some(s => s.isConnected)
113
+
114
+ // Prevent page unload when terminal sessions are active
115
+ useEffect(() => {
116
+ if (!hasConnectedSessions) return
117
+
118
+ const handleBeforeUnload = (e: BeforeUnloadEvent) => {
119
+ e.preventDefault()
120
+ // Modern browsers require returnValue to be set
121
+ e.returnValue = 'You have active terminal sessions. Are you sure you want to leave?'
122
+ return e.returnValue
123
+ }
124
+
125
+ window.addEventListener('beforeunload', handleBeforeUnload)
126
+ return () => window.removeEventListener('beforeunload', handleBeforeUnload)
127
+ }, [hasConnectedSessions])
128
+
129
+ // Prevent back/forward navigation when terminal sessions are active
130
+ useEffect(() => {
131
+ if (!hasConnectedSessions) return
132
+
133
+ // Push a state to history so we can intercept back navigation
134
+ const currentPath = window.location.pathname + window.location.search
135
+ window.history.pushState({ terminalActive: true }, '', currentPath)
136
+
137
+ const handlePopState = (e: PopStateEvent) => {
138
+ // User pressed back/forward
139
+ const confirmLeave = window.confirm(
140
+ 'You have active terminal sessions. Leaving will terminate them. Are you sure?'
141
+ )
142
+
143
+ if (!confirmLeave) {
144
+ // Cancel navigation by pushing state back
145
+ window.history.pushState({ terminalActive: true }, '', currentPath)
146
+ }
147
+ // If confirmed, let the navigation happen naturally
148
+ }
149
+
150
+ window.addEventListener('popstate', handlePopState)
151
+ return () => {
152
+ window.removeEventListener('popstate', handlePopState)
153
+ }
154
+ }, [hasConnectedSessions])
155
+
111
156
  return (
112
157
  <TerminalTabsContext.Provider value={{
113
158
  sessions,