prjct-cli 0.18.2 → 0.19.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 (243) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/CLAUDE.md +74 -211
  3. package/core/agentic/prompt-builder.ts +3 -7
  4. package/core/command-registry/optional-commands.ts +0 -20
  5. package/core/infrastructure/command-installer/command-installer.ts +8 -1
  6. package/core/infrastructure/command-installer/global-config.ts +31 -1
  7. package/core/infrastructure/command-installer/index.ts +1 -1
  8. package/core/infrastructure/setup.ts +3 -0
  9. package/package.json +3 -17
  10. package/templates/commands/done.md +57 -258
  11. package/templates/commands/now.md +72 -277
  12. package/templates/commands/ship.md +55 -261
  13. package/templates/commands/test.md +328 -21
  14. package/templates/global/CLAUDE.md +40 -205
  15. package/templates/global/docs/agents.md +88 -0
  16. package/templates/global/docs/architecture.md +103 -0
  17. package/templates/global/docs/commands.md +98 -0
  18. package/templates/global/docs/validation.md +95 -0
  19. package/templates/mcp-config.json +36 -0
  20. package/bin/dev.js +0 -216
  21. package/bin/serve.js +0 -361
  22. package/packages/web/README.md +0 -36
  23. package/packages/web/app/api/claude/sessions/route.ts +0 -44
  24. package/packages/web/app/api/claude/status/route.ts +0 -34
  25. package/packages/web/app/api/projects/[id]/icon/route.ts +0 -33
  26. package/packages/web/app/api/projects/[id]/momentum/route.ts +0 -257
  27. package/packages/web/app/api/projects/[id]/route.ts +0 -29
  28. package/packages/web/app/api/projects/[id]/stats/route.ts +0 -41
  29. package/packages/web/app/api/projects/[id]/status/route.ts +0 -21
  30. package/packages/web/app/api/projects/route.ts +0 -16
  31. package/packages/web/app/api/sessions/current/route.ts +0 -132
  32. package/packages/web/app/api/sessions/history/route.ts +0 -204
  33. package/packages/web/app/error.tsx +0 -34
  34. package/packages/web/app/favicon.ico +0 -0
  35. package/packages/web/app/globals.css +0 -198
  36. package/packages/web/app/layout.tsx +0 -53
  37. package/packages/web/app/loading.tsx +0 -7
  38. package/packages/web/app/not-found.tsx +0 -25
  39. package/packages/web/app/page.tsx +0 -12
  40. package/packages/web/app/project/[id]/code/layout.tsx +0 -18
  41. package/packages/web/app/project/[id]/code/page.tsx +0 -408
  42. package/packages/web/app/project/[id]/error.tsx +0 -41
  43. package/packages/web/app/project/[id]/loading.tsx +0 -9
  44. package/packages/web/app/project/[id]/not-found.tsx +0 -27
  45. package/packages/web/app/project/[id]/page.tsx +0 -384
  46. package/packages/web/app/project/[id]/reports/page.tsx +0 -59
  47. package/packages/web/app/project/[id]/reports/print/page.tsx +0 -58
  48. package/packages/web/app/sessions/page.tsx +0 -165
  49. package/packages/web/app/settings/page.tsx +0 -151
  50. package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +0 -2
  51. package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +0 -49
  52. package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +0 -8
  53. package/packages/web/components/ActivityTimeline/hooks/index.ts +0 -2
  54. package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +0 -9
  55. package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +0 -23
  56. package/packages/web/components/ActivityTimeline/index.ts +0 -2
  57. package/packages/web/components/AgentsCard/AgentsCard.tsx +0 -93
  58. package/packages/web/components/AgentsCard/AgentsCard.types.ts +0 -14
  59. package/packages/web/components/AgentsCard/index.ts +0 -2
  60. package/packages/web/components/AppSidebar/AppSidebar.tsx +0 -316
  61. package/packages/web/components/AppSidebar/index.ts +0 -1
  62. package/packages/web/components/BackLink/BackLink.tsx +0 -18
  63. package/packages/web/components/BackLink/BackLink.types.ts +0 -5
  64. package/packages/web/components/BackLink/index.ts +0 -2
  65. package/packages/web/components/BentoCard/BentoCard.constants.ts +0 -16
  66. package/packages/web/components/BentoCard/BentoCard.tsx +0 -48
  67. package/packages/web/components/BentoCard/BentoCard.types.ts +0 -15
  68. package/packages/web/components/BentoCard/index.ts +0 -2
  69. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +0 -9
  70. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +0 -18
  71. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +0 -5
  72. package/packages/web/components/BentoCardSkeleton/index.ts +0 -2
  73. package/packages/web/components/BentoGrid/BentoGrid.tsx +0 -18
  74. package/packages/web/components/BentoGrid/BentoGrid.types.ts +0 -4
  75. package/packages/web/components/BentoGrid/index.ts +0 -2
  76. package/packages/web/components/BlockersCard/BlockersCard.tsx +0 -75
  77. package/packages/web/components/BlockersCard/BlockersCard.types.ts +0 -12
  78. package/packages/web/components/BlockersCard/index.ts +0 -2
  79. package/packages/web/components/CommandBar/CommandBar.tsx +0 -67
  80. package/packages/web/components/CommandBar/index.ts +0 -1
  81. package/packages/web/components/CommandButton/CommandButton.tsx +0 -46
  82. package/packages/web/components/CommandButton/index.ts +0 -1
  83. package/packages/web/components/ConnectionStatus/ConnectionStatus.tsx +0 -29
  84. package/packages/web/components/ConnectionStatus/index.ts +0 -1
  85. package/packages/web/components/DashboardContent/DashboardContent.tsx +0 -284
  86. package/packages/web/components/DashboardContent/index.ts +0 -1
  87. package/packages/web/components/DateGroup/DateGroup.tsx +0 -18
  88. package/packages/web/components/DateGroup/DateGroup.types.ts +0 -6
  89. package/packages/web/components/DateGroup/DateGroup.utils.ts +0 -11
  90. package/packages/web/components/DateGroup/index.ts +0 -2
  91. package/packages/web/components/EmptyState/EmptyState.tsx +0 -76
  92. package/packages/web/components/EmptyState/EmptyState.types.ts +0 -11
  93. package/packages/web/components/EmptyState/index.ts +0 -2
  94. package/packages/web/components/EventRow/EventRow.constants.ts +0 -10
  95. package/packages/web/components/EventRow/EventRow.tsx +0 -49
  96. package/packages/web/components/EventRow/EventRow.types.ts +0 -7
  97. package/packages/web/components/EventRow/EventRow.utils.ts +0 -49
  98. package/packages/web/components/EventRow/index.ts +0 -2
  99. package/packages/web/components/ExpandButton/ExpandButton.tsx +0 -18
  100. package/packages/web/components/ExpandButton/ExpandButton.types.ts +0 -6
  101. package/packages/web/components/ExpandButton/index.ts +0 -2
  102. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +0 -14
  103. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +0 -5
  104. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +0 -13
  105. package/packages/web/components/HealthGradientBackground/index.ts +0 -2
  106. package/packages/web/components/HeroSection/HeroSection.tsx +0 -92
  107. package/packages/web/components/HeroSection/HeroSection.types.ts +0 -14
  108. package/packages/web/components/HeroSection/HeroSection.utils.ts +0 -11
  109. package/packages/web/components/HeroSection/hooks/index.ts +0 -2
  110. package/packages/web/components/HeroSection/hooks/useCountUp.ts +0 -45
  111. package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +0 -18
  112. package/packages/web/components/HeroSection/index.ts +0 -2
  113. package/packages/web/components/IdeasCard/IdeasCard.tsx +0 -115
  114. package/packages/web/components/IdeasCard/IdeasCard.types.ts +0 -10
  115. package/packages/web/components/IdeasCard/index.ts +0 -2
  116. package/packages/web/components/InsightMessage/InsightMessage.tsx +0 -9
  117. package/packages/web/components/InsightMessage/InsightMessage.types.ts +0 -3
  118. package/packages/web/components/InsightMessage/index.ts +0 -2
  119. package/packages/web/components/Logo/Logo.tsx +0 -65
  120. package/packages/web/components/Logo/index.ts +0 -1
  121. package/packages/web/components/MarkdownContent/MarkdownContent.tsx +0 -123
  122. package/packages/web/components/MarkdownContent/index.ts +0 -1
  123. package/packages/web/components/MasonryGrid/MasonryGrid.tsx +0 -18
  124. package/packages/web/components/MasonryGrid/index.ts +0 -1
  125. package/packages/web/components/MomentumWidget/MomentumWidget.tsx +0 -119
  126. package/packages/web/components/MomentumWidget/MomentumWidget.types.ts +0 -16
  127. package/packages/web/components/MomentumWidget/index.ts +0 -2
  128. package/packages/web/components/NowCard/NowCard.tsx +0 -118
  129. package/packages/web/components/NowCard/NowCard.types.ts +0 -16
  130. package/packages/web/components/NowCard/index.ts +0 -2
  131. package/packages/web/components/PageHeader/PageHeader.tsx +0 -24
  132. package/packages/web/components/PageHeader/index.ts +0 -1
  133. package/packages/web/components/ProgressRing/ProgressRing.constants.ts +0 -20
  134. package/packages/web/components/ProgressRing/ProgressRing.tsx +0 -51
  135. package/packages/web/components/ProgressRing/ProgressRing.types.ts +0 -11
  136. package/packages/web/components/ProgressRing/index.ts +0 -2
  137. package/packages/web/components/ProjectAvatar/ProjectAvatar.tsx +0 -54
  138. package/packages/web/components/ProjectAvatar/index.ts +0 -1
  139. package/packages/web/components/ProjectColorDot/ProjectColorDot.tsx +0 -37
  140. package/packages/web/components/ProjectColorDot/index.ts +0 -1
  141. package/packages/web/components/ProjectSelectorModal/ProjectSelectorModal.tsx +0 -104
  142. package/packages/web/components/ProjectSelectorModal/index.ts +0 -1
  143. package/packages/web/components/Providers/Providers.tsx +0 -48
  144. package/packages/web/components/Providers/index.ts +0 -1
  145. package/packages/web/components/QueueCard/QueueCard.tsx +0 -125
  146. package/packages/web/components/QueueCard/QueueCard.types.ts +0 -12
  147. package/packages/web/components/QueueCard/QueueCard.utils.ts +0 -12
  148. package/packages/web/components/QueueCard/index.ts +0 -2
  149. package/packages/web/components/RecoverCard/RecoverCard.tsx +0 -72
  150. package/packages/web/components/RecoverCard/RecoverCard.types.ts +0 -16
  151. package/packages/web/components/RecoverCard/index.ts +0 -2
  152. package/packages/web/components/RoadmapCard/RoadmapCard.tsx +0 -145
  153. package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +0 -16
  154. package/packages/web/components/RoadmapCard/index.ts +0 -2
  155. package/packages/web/components/ShipsCard/ShipsCard.tsx +0 -95
  156. package/packages/web/components/ShipsCard/ShipsCard.types.ts +0 -14
  157. package/packages/web/components/ShipsCard/ShipsCard.utils.ts +0 -4
  158. package/packages/web/components/ShipsCard/index.ts +0 -2
  159. package/packages/web/components/SparklineChart/SparklineChart.tsx +0 -40
  160. package/packages/web/components/SparklineChart/SparklineChart.types.ts +0 -6
  161. package/packages/web/components/SparklineChart/index.ts +0 -2
  162. package/packages/web/components/StatsMasonry/StatsMasonry.tsx +0 -95
  163. package/packages/web/components/StatsMasonry/index.ts +0 -1
  164. package/packages/web/components/StreakCard/StreakCard.constants.ts +0 -2
  165. package/packages/web/components/StreakCard/StreakCard.tsx +0 -55
  166. package/packages/web/components/StreakCard/StreakCard.types.ts +0 -4
  167. package/packages/web/components/StreakCard/index.ts +0 -2
  168. package/packages/web/components/TasksCounter/TasksCounter.tsx +0 -14
  169. package/packages/web/components/TasksCounter/TasksCounter.types.ts +0 -3
  170. package/packages/web/components/TasksCounter/index.ts +0 -2
  171. package/packages/web/components/TechStackBadges/TechStackBadges.tsx +0 -28
  172. package/packages/web/components/TechStackBadges/index.ts +0 -1
  173. package/packages/web/components/TerminalDock/DockToggleTab.tsx +0 -29
  174. package/packages/web/components/TerminalDock/TerminalDock.tsx +0 -386
  175. package/packages/web/components/TerminalDock/TerminalDockTab.tsx +0 -130
  176. package/packages/web/components/TerminalDock/TerminalTabBar.tsx +0 -142
  177. package/packages/web/components/TerminalDock/index.ts +0 -2
  178. package/packages/web/components/TerminalTabs/TerminalTab.tsx +0 -95
  179. package/packages/web/components/TerminalTabs/TerminalTabs.tsx +0 -211
  180. package/packages/web/components/TerminalTabs/index.ts +0 -1
  181. package/packages/web/components/VelocityBadge/VelocityBadge.tsx +0 -32
  182. package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +0 -3
  183. package/packages/web/components/VelocityBadge/index.ts +0 -2
  184. package/packages/web/components/VelocityCard/VelocityCard.tsx +0 -73
  185. package/packages/web/components/VelocityCard/VelocityCard.types.ts +0 -7
  186. package/packages/web/components/VelocityCard/index.ts +0 -2
  187. package/packages/web/components/WeeklyReports/PrintableReport.tsx +0 -259
  188. package/packages/web/components/WeeklyReports/ReportPreviewCard.tsx +0 -187
  189. package/packages/web/components/WeeklyReports/WeekCalendar.tsx +0 -288
  190. package/packages/web/components/WeeklyReports/WeeklyReports.tsx +0 -149
  191. package/packages/web/components/WeeklyReports/index.ts +0 -4
  192. package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +0 -25
  193. package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +0 -4
  194. package/packages/web/components/WeeklySparkline/index.ts +0 -2
  195. package/packages/web/components/charts/SessionsChart.tsx +0 -175
  196. package/packages/web/components/ui/alert-dialog.tsx +0 -157
  197. package/packages/web/components/ui/badge.tsx +0 -46
  198. package/packages/web/components/ui/button.tsx +0 -60
  199. package/packages/web/components/ui/card.tsx +0 -92
  200. package/packages/web/components/ui/chart.tsx +0 -385
  201. package/packages/web/components/ui/dialog.tsx +0 -143
  202. package/packages/web/components/ui/drawer.tsx +0 -135
  203. package/packages/web/components/ui/dropdown-menu.tsx +0 -257
  204. package/packages/web/components/ui/input.tsx +0 -21
  205. package/packages/web/components/ui/scroll-area.tsx +0 -58
  206. package/packages/web/components/ui/select.tsx +0 -187
  207. package/packages/web/components/ui/sheet.tsx +0 -139
  208. package/packages/web/components/ui/tabs.tsx +0 -66
  209. package/packages/web/components/ui/tooltip.tsx +0 -61
  210. package/packages/web/components.json +0 -22
  211. package/packages/web/context/GlobalTerminalContext.tsx +0 -538
  212. package/packages/web/context/TerminalContext.tsx +0 -45
  213. package/packages/web/context/TerminalTabsContext.tsx +0 -181
  214. package/packages/web/eslint.config.mjs +0 -18
  215. package/packages/web/hooks/useClaudeTerminal.ts +0 -425
  216. package/packages/web/hooks/useProjectStats.ts +0 -93
  217. package/packages/web/hooks/useProjects.ts +0 -73
  218. package/packages/web/lib/actions/projects.ts +0 -15
  219. package/packages/web/lib/commands.ts +0 -81
  220. package/packages/web/lib/format.ts +0 -23
  221. package/packages/web/lib/generate-week-report.ts +0 -285
  222. package/packages/web/lib/parse-prjct-files.ts +0 -1123
  223. package/packages/web/lib/project-colors.ts +0 -58
  224. package/packages/web/lib/projects.ts +0 -506
  225. package/packages/web/lib/pty.ts +0 -101
  226. package/packages/web/lib/query-config.ts +0 -44
  227. package/packages/web/lib/services/index.ts +0 -9
  228. package/packages/web/lib/services/projects.server.ts +0 -66
  229. package/packages/web/lib/services/stats.server.ts +0 -562
  230. package/packages/web/lib/unified-loader.ts +0 -396
  231. package/packages/web/lib/utils.ts +0 -6
  232. package/packages/web/next-env.d.ts +0 -6
  233. package/packages/web/next.config.ts +0 -7
  234. package/packages/web/package.json +0 -57
  235. package/packages/web/postcss.config.mjs +0 -7
  236. package/packages/web/public/file.svg +0 -1
  237. package/packages/web/public/globe.svg +0 -1
  238. package/packages/web/public/next.svg +0 -1
  239. package/packages/web/public/vercel.svg +0 -1
  240. package/packages/web/public/window.svg +0 -1
  241. package/packages/web/server.ts +0 -312
  242. package/packages/web/tsconfig.json +0 -34
  243. package/templates/commands/serve.md +0 -121
@@ -1,12 +0,0 @@
1
- export function getPriorityColor(priority?: 'low' | 'medium' | 'high' | 'critical' | number): string {
2
- if (typeof priority === 'string') {
3
- const colors: Record<string, string> = {
4
- critical: 'text-foreground font-bold',
5
- high: 'text-foreground',
6
- medium: 'text-muted-foreground',
7
- low: 'text-muted-foreground',
8
- }
9
- return colors[priority] ?? 'text-muted-foreground'
10
- }
11
- return 'text-muted-foreground'
12
- }
@@ -1,2 +0,0 @@
1
- export { QueueCard } from './QueueCard'
2
- export type { QueueCardProps } from './QueueCard.types'
@@ -1,72 +0,0 @@
1
- 'use client'
2
-
3
- import Link from 'next/link'
4
- import { AlertCircle, ChevronRight, Clock, MessageSquare } from 'lucide-react'
5
- import { Badge } from '@/components/ui/badge'
6
- import { cn } from '@/lib/utils'
7
- import type { RecoverCardProps } from './RecoverCard.types'
8
-
9
- export function RecoverCard({ abandonedSessions, codeHref, className }: RecoverCardProps) {
10
- if (abandonedSessions.length === 0) return null
11
-
12
- return (
13
- <div className={cn(
14
- 'relative overflow-hidden rounded-xl border border-yellow-500/30 bg-yellow-500/5 p-4 min-w-0 max-w-full',
15
- className
16
- )}>
17
- <div className="flex items-center justify-between mb-3 min-w-0">
18
- <div className="flex items-center gap-2 min-w-0">
19
- <AlertCircle className="h-4 w-4 text-yellow-500 shrink-0" />
20
- <span className="text-xs font-bold uppercase tracking-[0.15em] text-yellow-600 dark:text-yellow-500 truncate">
21
- Recover
22
- </span>
23
- </div>
24
- <Badge variant="outline" className="text-yellow-600 dark:text-yellow-500 border-yellow-500/50 shrink-0">
25
- {abandonedSessions.length}
26
- </Badge>
27
- </div>
28
-
29
- <div className="space-y-2 min-w-0 max-w-full">
30
- {abandonedSessions.slice(0, 3).map((session) => (
31
- <Link
32
- key={session.id}
33
- href={`${codeHref}?cmd=p.%20recover`}
34
- className="block py-2 px-2 -mx-2 hover:bg-yellow-500/10 rounded-lg transition-colors group"
35
- >
36
- <div className="flex items-start justify-between gap-2">
37
- <div className="flex-1 min-w-0">
38
- <p className="text-sm font-medium leading-tight truncate group-hover:text-foreground transition-colors">
39
- {session.task}
40
- </p>
41
- <div className="flex items-center gap-2 mt-1 text-xs text-muted-foreground">
42
- <Clock className="h-3 w-3 shrink-0" />
43
- <span>{session.hoursAgo}h ago</span>
44
- {session.projectName && (
45
- <>
46
- <span className="text-muted-foreground/50">|</span>
47
- <span className="truncate">{session.projectName}</span>
48
- </>
49
- )}
50
- </div>
51
- {session.prompt && (
52
- <div className="flex items-start gap-1.5 mt-1.5">
53
- <MessageSquare className="h-3 w-3 text-muted-foreground/70 shrink-0 mt-0.5" />
54
- <p className="text-xs text-muted-foreground/70 italic line-clamp-2">
55
- &quot;{session.prompt.slice(0, 80)}{session.prompt.length > 80 ? '...' : ''}&quot;
56
- </p>
57
- </div>
58
- )}
59
- </div>
60
- <ChevronRight className="h-4 w-4 text-muted-foreground/50 opacity-0 group-hover:opacity-100 transition-opacity shrink-0 mt-1" />
61
- </div>
62
- </Link>
63
- ))}
64
- {abandonedSessions.length > 3 && (
65
- <p className="text-xs text-yellow-600/70 dark:text-yellow-500/70 text-center pt-1">
66
- +{abandonedSessions.length - 3} more abandoned sessions
67
- </p>
68
- )}
69
- </div>
70
- </div>
71
- )
72
- }
@@ -1,16 +0,0 @@
1
- export interface AbandonedSession {
2
- id: string
3
- task: string
4
- projectId: string
5
- projectName?: string
6
- startedAt: string
7
- lastActivity?: string
8
- hoursAgo: number
9
- prompt?: string
10
- }
11
-
12
- export interface RecoverCardProps {
13
- abandonedSessions: AbandonedSession[]
14
- codeHref: string
15
- className?: string
16
- }
@@ -1,2 +0,0 @@
1
- export { RecoverCard } from './RecoverCard'
2
- export type { RecoverCardProps, AbandonedSession } from './RecoverCard.types'
@@ -1,145 +0,0 @@
1
- 'use client'
2
-
3
- import Link from 'next/link'
4
- import { EmptyState } from '@/components/EmptyState'
5
- import { Map, ChevronRight, CheckCircle2, Circle } from 'lucide-react'
6
- import { cn } from '@/lib/utils'
7
- import type { RoadmapCardProps } from './RoadmapCard.types'
8
-
9
- // Traffic light colors for progress: green=100%, yellow=50-99%, red=<50%
10
- function getProgressColor(progress: number): string {
11
- if (progress >= 100) return 'bg-emerald-500'
12
- if (progress >= 50) return 'bg-amber-500'
13
- return 'bg-red-500'
14
- }
15
-
16
- export function RoadmapCard({ roadmap, codeHref, className }: RoadmapCardProps) {
17
- const hasPhases = roadmap?.phases && roadmap.phases.length > 0
18
-
19
- return (
20
- <div className={cn(
21
- 'relative overflow-hidden rounded-xl border bg-card p-4',
22
- className
23
- )}>
24
- <div className="flex items-center justify-between mb-3">
25
- <div className="flex items-center gap-2">
26
- <Map className="h-4 w-4 text-muted-foreground" />
27
- <span className="text-xs font-bold uppercase tracking-[0.15em] text-muted-foreground">
28
- Roadmap
29
- </span>
30
- </div>
31
- {hasPhases && (
32
- <span className="text-xs font-bold tabular-nums">
33
- {roadmap.progress}%
34
- </span>
35
- )}
36
- </div>
37
-
38
- {!hasPhases ? (
39
- <EmptyState
40
- icon={Map}
41
- title="No roadmap yet"
42
- description="Plan your features"
43
- command="/p:feature"
44
- href={codeHref}
45
- />
46
- ) : (
47
- <div className="space-y-4">
48
- {/* Overall progress */}
49
- <div>
50
- <div className="flex items-center justify-between mb-2">
51
- <span className="text-xs text-muted-foreground">Overall progress</span>
52
- <span className="text-sm font-bold tabular-nums">{roadmap.progress}%</span>
53
- </div>
54
- <div className="h-3 bg-muted rounded-full overflow-hidden">
55
- <div
56
- className={cn("h-full rounded-full transition-all duration-500", getProgressColor(roadmap.progress))}
57
- style={{ width: `${roadmap.progress}%` }}
58
- />
59
- </div>
60
- </div>
61
-
62
- {/* Phases with features */}
63
- <div className="space-y-4">
64
- {roadmap.phases
65
- .filter(p => (p.features || []).length > 0)
66
- .slice(0, 6)
67
- .map((phase) => (
68
- <div key={phase.name} className="group">
69
- <div className="flex items-center justify-between mb-2">
70
- <div className="flex items-center gap-2">
71
- {phase.progress === 100 ? (
72
- <CheckCircle2 className="h-4 w-4 text-muted-foreground" />
73
- ) : (
74
- <Circle className="h-4 w-4 text-muted-foreground" />
75
- )}
76
- <span className="text-sm font-medium">
77
- {phase.name}
78
- </span>
79
- </div>
80
- <span className="text-xs font-bold tabular-nums shrink-0 ml-2 text-muted-foreground">
81
- {phase.progress}%
82
- </span>
83
- </div>
84
- <div className="h-2 bg-muted rounded-full overflow-hidden ml-6">
85
- <div
86
- className={cn("h-full rounded-full transition-all duration-300", getProgressColor(phase.progress))}
87
- style={{ width: `${phase.progress}%` }}
88
- />
89
- </div>
90
- {/* Show features under each phase */}
91
- {phase.features && phase.features.length > 0 && (
92
- <div className="ml-6 mt-2 space-y-1">
93
- {phase.features.slice(0, 3).map((feature, i) => {
94
- const isCompleted = feature.status === 'completed'
95
- const cmdHref = codeHref && !isCompleted
96
- ? `${codeHref}?cmd=${encodeURIComponent(`p. work "${feature.name}"`)}`
97
- : undefined
98
-
99
- const content = (
100
- <>
101
- <ChevronRight className="h-3 w-3 shrink-0" />
102
- <span className={cn(
103
- 'truncate',
104
- isCompleted && 'line-through opacity-60'
105
- )}>
106
- {feature.name}
107
- </span>
108
- </>
109
- )
110
-
111
- return cmdHref ? (
112
- <Link
113
- key={i}
114
- href={cmdHref}
115
- className="flex items-center gap-2 text-xs text-muted-foreground hover:text-foreground hover:bg-muted/50 rounded px-1 -mx-1 py-0.5 transition-colors cursor-pointer"
116
- >
117
- {content}
118
- </Link>
119
- ) : (
120
- <div key={i} className="flex items-center gap-2 text-xs text-muted-foreground">
121
- {content}
122
- </div>
123
- )
124
- })}
125
- {phase.features.length > 3 && (
126
- <span className="text-xs text-muted-foreground/70 ml-5">
127
- +{phase.features.length - 3} more
128
- </span>
129
- )}
130
- </div>
131
- )}
132
- </div>
133
- ))}
134
- </div>
135
-
136
- {roadmap.phases.length > 0 && (
137
- <p className="text-xs text-muted-foreground border-t pt-3 mt-3">
138
- {roadmap.phases.reduce((acc, p) => acc + (p.features?.length || 0), 0)} features across {roadmap.phases.length} phases
139
- </p>
140
- )}
141
- </div>
142
- )}
143
- </div>
144
- )
145
- }
@@ -1,16 +0,0 @@
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
- codeHref?: string
15
- className?: string
16
- }
@@ -1,2 +0,0 @@
1
- export { RoadmapCard } from './RoadmapCard'
2
- export type { RoadmapCardProps } from './RoadmapCard.types'
@@ -1,95 +0,0 @@
1
- 'use client'
2
-
3
- import { useState } from 'react'
4
- import { EmptyState } from '@/components/EmptyState'
5
- import { ExpandButton } from '@/components/ExpandButton'
6
- import { Rocket, Clock, FileCode, Check } from 'lucide-react'
7
- import { Badge } from '@/components/ui/badge'
8
- import { cn } from '@/lib/utils'
9
- import { formatShipDate } from './ShipsCard.utils'
10
- import type { ShipsCardProps } from './ShipsCard.types'
11
-
12
- const COLLAPSED_LIMIT = 10
13
-
14
- export function ShipsCard({ ships, totalShips = 0, codeHref, className }: ShipsCardProps) {
15
- const [expanded, setExpanded] = useState(false)
16
- const displayShips = expanded ? ships : ships.slice(0, COLLAPSED_LIMIT)
17
- const hasMore = ships.length > COLLAPSED_LIMIT
18
-
19
- return (
20
- <div className={cn(
21
- 'relative overflow-hidden rounded-xl border bg-card p-4',
22
- className
23
- )}>
24
- <div className="flex items-center justify-between mb-3">
25
- <div className="flex items-center gap-2">
26
- <Rocket className="h-4 w-4 text-muted-foreground" />
27
- <span className="text-xs font-bold uppercase tracking-[0.15em] text-muted-foreground">
28
- Shipped
29
- </span>
30
- </div>
31
- <span className="text-xs font-medium text-muted-foreground tabular-nums">
32
- {totalShips} total
33
- </span>
34
- </div>
35
-
36
- {ships.length === 0 ? (
37
- <EmptyState
38
- icon={Rocket}
39
- title="Nothing shipped yet"
40
- description="Ship your first feature"
41
- command="/p:ship"
42
- href={codeHref}
43
- compact
44
- />
45
- ) : (
46
- <div className="space-y-2">
47
- {displayShips.map((ship, i) => (
48
- <div key={i} className="group py-1.5 hover:bg-muted/50 rounded px-2 -mx-2 border-l-2 border-transparent hover:border-foreground/20">
49
- <div className="flex items-start justify-between gap-2">
50
- <div className="flex-1 min-w-0">
51
- <div className="flex items-center gap-2">
52
- <Check className="h-3 w-3 text-muted-foreground shrink-0" />
53
- <p className="text-sm font-medium truncate">
54
- {ship.name}
55
- </p>
56
- {ship.version && (
57
- <Badge variant="outline" className="text-xs px-1 py-0 font-mono shrink-0 h-4">
58
- {ship.version}
59
- </Badge>
60
- )}
61
- </div>
62
- <div className="flex items-center gap-3 mt-1 ml-5">
63
- <span className="text-xs text-muted-foreground">
64
- {formatShipDate(ship.date)}
65
- </span>
66
- {ship.duration && (
67
- <span className="inline-flex items-center gap-0.5 text-xs text-muted-foreground">
68
- <Clock className="h-2.5 w-2.5" />
69
- {ship.duration}
70
- </span>
71
- )}
72
- {ship.filesChanged && (
73
- <span className="inline-flex items-center gap-0.5 text-xs text-muted-foreground">
74
- <FileCode className="h-2.5 w-2.5" />
75
- {ship.filesChanged} files
76
- </span>
77
- )}
78
- </div>
79
- </div>
80
- </div>
81
- </div>
82
- ))}
83
- {hasMore && (
84
- <ExpandButton
85
- expanded={expanded}
86
- totalCount={ships.length}
87
- collapsedLimit={COLLAPSED_LIMIT}
88
- onToggle={() => setExpanded(!expanded)}
89
- />
90
- )}
91
- </div>
92
- )}
93
- </div>
94
- )
95
- }
@@ -1,14 +0,0 @@
1
- export interface Ship {
2
- name: string
3
- date: string
4
- version?: string
5
- duration?: string
6
- filesChanged?: number
7
- }
8
-
9
- export interface ShipsCardProps {
10
- ships: Ship[]
11
- totalShips?: number
12
- codeHref?: string
13
- className?: string
14
- }
@@ -1,4 +0,0 @@
1
- export function formatShipDate(dateString: string): string {
2
- const date = new Date(dateString)
3
- return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })
4
- }
@@ -1,2 +0,0 @@
1
- export { ShipsCard } from './ShipsCard'
2
- export type { ShipsCardProps } from './ShipsCard.types'
@@ -1,40 +0,0 @@
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
- <div className="w-full min-w-0" style={{ height }}>
20
- <ResponsiveContainer width="100%" height="100%">
21
- <AreaChart data={chartData} margin={{ top: 0, right: 0, bottom: 0, left: 0 }}>
22
- <defs>
23
- <linearGradient id="sparklineGradient" x1="0" y1="0" x2="0" y2="1">
24
- <stop offset="0%" stopColor={color} stopOpacity={0.3} />
25
- <stop offset="100%" stopColor={color} stopOpacity={0} />
26
- </linearGradient>
27
- </defs>
28
- <Area
29
- type="monotone"
30
- dataKey="value"
31
- stroke={color}
32
- strokeWidth={1.5}
33
- fill={showArea ? 'url(#sparklineGradient)' : 'none'}
34
- isAnimationActive={false}
35
- />
36
- </AreaChart>
37
- </ResponsiveContainer>
38
- </div>
39
- )
40
- }
@@ -1,6 +0,0 @@
1
- export interface SparklineChartProps {
2
- data: number[]
3
- color?: string
4
- height?: number
5
- showArea?: boolean
6
- }
@@ -1,2 +0,0 @@
1
- export { SparklineChart } from './SparklineChart'
2
- export type { SparklineChartProps } from './SparklineChart.types'
@@ -1,95 +0,0 @@
1
- 'use client'
2
-
3
- import { useEffect, useState } from 'react'
4
- import { MasonryGrid } from '@/components/MasonryGrid'
5
- import { NowCard } from '@/components/NowCard'
6
- import { VelocityCard } from '@/components/VelocityCard'
7
- import { StreakCard } from '@/components/StreakCard'
8
- import { QueueCard } from '@/components/QueueCard'
9
- import { ShipsCard } from '@/components/ShipsCard'
10
- import { IdeasCard } from '@/components/IdeasCard'
11
- import { AgentsCard } from '@/components/AgentsCard'
12
- import { RoadmapCard } from '@/components/RoadmapCard'
13
- import { BlockersCard } from '@/components/BlockersCard'
14
- import { RecoverCard, type AbandonedSession } from '@/components/RecoverCard'
15
- import { ActivityTimeline } from '@/components/ActivityTimeline'
16
- import type { TimelineEvent } from '@/lib/parse-prjct-files'
17
-
18
- interface StatsMasonryProps {
19
- projectId: string
20
- currentTask: any
21
- velocity: number
22
- weeklyVelocityData: number[]
23
- velocityChange: number
24
- estimateAccuracy?: number
25
- roadmap: any
26
- queue: any[]
27
- shipped: any[]
28
- totalShips: number
29
- streak: number
30
- blockers: any[]
31
- ideas: any[]
32
- agents: any[]
33
- timeline: TimelineEvent[]
34
- }
35
-
36
- export function StatsMasonry({
37
- projectId,
38
- currentTask,
39
- velocity,
40
- weeklyVelocityData,
41
- velocityChange,
42
- estimateAccuracy,
43
- roadmap,
44
- queue,
45
- shipped,
46
- totalShips,
47
- streak,
48
- blockers,
49
- ideas,
50
- agents,
51
- timeline,
52
- }: StatsMasonryProps) {
53
- const codeHref = `/project/${projectId}/code`
54
- const [abandonedSessions, setAbandonedSessions] = useState<AbandonedSession[]>([])
55
-
56
- // Fetch abandoned sessions from API
57
- useEffect(() => {
58
- async function fetchAbandonedSessions() {
59
- try {
60
- const res = await fetch(`/api/sessions/current?projectId=${projectId}`)
61
- const data = await res.json()
62
- if (data.success && data.data.abandonedSessions) {
63
- setAbandonedSessions(data.data.abandonedSessions)
64
- }
65
- } catch {
66
- // Silently fail - abandoned sessions are not critical
67
- }
68
- }
69
- fetchAbandonedSessions()
70
- }, [projectId])
71
-
72
- return (
73
- <MasonryGrid>
74
- {/* Show RecoverCard first if there are abandoned sessions */}
75
- {abandonedSessions.length > 0 && (
76
- <RecoverCard abandonedSessions={abandonedSessions} codeHref={codeHref} />
77
- )}
78
- <NowCard currentTask={currentTask} codeHref={codeHref} />
79
- <VelocityCard
80
- tasksPerDay={velocity}
81
- weeklyData={weeklyVelocityData}
82
- change={velocityChange}
83
- estimateAccuracy={estimateAccuracy}
84
- />
85
- <RoadmapCard roadmap={roadmap} codeHref={codeHref} />
86
- <QueueCard queue={queue} codeHref={codeHref} />
87
- <ShipsCard ships={shipped} totalShips={totalShips} codeHref={codeHref} />
88
- <StreakCard streak={streak} />
89
- <BlockersCard blockers={blockers} codeHref={codeHref} />
90
- <IdeasCard ideas={ideas} codeHref={codeHref} />
91
- <AgentsCard agents={agents} codeHref={codeHref} />
92
- <ActivityTimeline timeline={timeline} />
93
- </MasonryGrid>
94
- )
95
- }
@@ -1 +0,0 @@
1
- export { StatsMasonry } from './StatsMasonry'
@@ -1,2 +0,0 @@
1
- export const STREAK_HOT_THRESHOLD = 3
2
- export const STREAK_ON_FIRE_THRESHOLD = 7
@@ -1,55 +0,0 @@
1
- 'use client'
2
-
3
- import { Flame, Calendar } from 'lucide-react'
4
- import { cn } from '@/lib/utils'
5
- import type { StreakCardProps } from './StreakCard.types'
6
-
7
- function getStreakColor(streak: number): string {
8
- if (streak >= 7) return 'text-emerald-600 dark:text-emerald-400'
9
- if (streak >= 3) return 'text-amber-600 dark:text-amber-400'
10
- return 'text-red-600 dark:text-red-400'
11
- }
12
-
13
- export function StreakCard({ streak, className }: StreakCardProps) {
14
- return (
15
- <div className={cn(
16
- 'relative overflow-hidden rounded-xl border bg-card p-4',
17
- className
18
- )}>
19
- <div className="flex items-center justify-between mb-3">
20
- <div className="flex items-center gap-2">
21
- <Flame className="h-4 w-4 text-muted-foreground" />
22
- <span className="text-xs font-bold uppercase tracking-[0.15em] text-muted-foreground">
23
- Streak
24
- </span>
25
- </div>
26
- </div>
27
-
28
- <div className="flex items-center gap-4">
29
- <Flame className={cn("h-10 w-10", getStreakColor(streak))} />
30
- <div>
31
- <p className="text-3xl font-bold tabular-nums">{streak}</p>
32
- <p className="text-xs text-muted-foreground">consecutive day{streak !== 1 ? 's' : ''}</p>
33
- </div>
34
- </div>
35
-
36
- <div className="mt-4">
37
- <div className="flex items-center gap-1.5 mb-2">
38
- <Calendar className="h-3 w-3 text-muted-foreground" />
39
- <span className="text-xs text-muted-foreground">Last 7 days</span>
40
- </div>
41
- <div className="flex gap-1">
42
- {Array.from({ length: 7 }).map((_, i) => (
43
- <div
44
- key={i}
45
- className={cn(
46
- 'h-2 flex-1 rounded-full transition-colors',
47
- i < streak ? 'bg-foreground' : 'bg-muted'
48
- )}
49
- />
50
- ))}
51
- </div>
52
- </div>
53
- </div>
54
- )
55
- }
@@ -1,4 +0,0 @@
1
- export interface StreakCardProps {
2
- streak: number
3
- className?: string
4
- }
@@ -1,2 +0,0 @@
1
- export { StreakCard } from './StreakCard'
2
- export type { StreakCardProps } from './StreakCard.types'
@@ -1,14 +0,0 @@
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
- shipped
11
- </span>
12
- </div>
13
- )
14
- }
@@ -1,3 +0,0 @@
1
- export interface TasksCounterProps {
2
- count: number
3
- }
@@ -1,2 +0,0 @@
1
- export { TasksCounter } from './TasksCounter'
2
- export type { TasksCounterProps } from './TasksCounter.types'