prjct-cli 0.18.1 → 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 (245) hide show
  1. package/CHANGELOG.md +53 -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/agentic/subagent-generation.md +8 -6
  11. package/templates/commands/done.md +57 -258
  12. package/templates/commands/now.md +72 -277
  13. package/templates/commands/ship.md +55 -261
  14. package/templates/commands/sync.md +7 -7
  15. package/templates/commands/test.md +328 -21
  16. package/templates/global/CLAUDE.md +40 -205
  17. package/templates/global/docs/agents.md +88 -0
  18. package/templates/global/docs/architecture.md +103 -0
  19. package/templates/global/docs/commands.md +98 -0
  20. package/templates/global/docs/validation.md +95 -0
  21. package/templates/mcp-config.json +36 -0
  22. package/bin/dev.js +0 -216
  23. package/bin/serve.js +0 -361
  24. package/packages/web/README.md +0 -36
  25. package/packages/web/app/api/claude/sessions/route.ts +0 -44
  26. package/packages/web/app/api/claude/status/route.ts +0 -34
  27. package/packages/web/app/api/projects/[id]/icon/route.ts +0 -33
  28. package/packages/web/app/api/projects/[id]/momentum/route.ts +0 -257
  29. package/packages/web/app/api/projects/[id]/route.ts +0 -29
  30. package/packages/web/app/api/projects/[id]/stats/route.ts +0 -41
  31. package/packages/web/app/api/projects/[id]/status/route.ts +0 -21
  32. package/packages/web/app/api/projects/route.ts +0 -16
  33. package/packages/web/app/api/sessions/current/route.ts +0 -132
  34. package/packages/web/app/api/sessions/history/route.ts +0 -204
  35. package/packages/web/app/error.tsx +0 -34
  36. package/packages/web/app/favicon.ico +0 -0
  37. package/packages/web/app/globals.css +0 -198
  38. package/packages/web/app/layout.tsx +0 -53
  39. package/packages/web/app/loading.tsx +0 -7
  40. package/packages/web/app/not-found.tsx +0 -25
  41. package/packages/web/app/page.tsx +0 -12
  42. package/packages/web/app/project/[id]/code/layout.tsx +0 -18
  43. package/packages/web/app/project/[id]/code/page.tsx +0 -408
  44. package/packages/web/app/project/[id]/error.tsx +0 -41
  45. package/packages/web/app/project/[id]/loading.tsx +0 -9
  46. package/packages/web/app/project/[id]/not-found.tsx +0 -27
  47. package/packages/web/app/project/[id]/page.tsx +0 -384
  48. package/packages/web/app/project/[id]/reports/page.tsx +0 -59
  49. package/packages/web/app/project/[id]/reports/print/page.tsx +0 -58
  50. package/packages/web/app/sessions/page.tsx +0 -165
  51. package/packages/web/app/settings/page.tsx +0 -151
  52. package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +0 -2
  53. package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +0 -49
  54. package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +0 -8
  55. package/packages/web/components/ActivityTimeline/hooks/index.ts +0 -2
  56. package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +0 -9
  57. package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +0 -23
  58. package/packages/web/components/ActivityTimeline/index.ts +0 -2
  59. package/packages/web/components/AgentsCard/AgentsCard.tsx +0 -93
  60. package/packages/web/components/AgentsCard/AgentsCard.types.ts +0 -14
  61. package/packages/web/components/AgentsCard/index.ts +0 -2
  62. package/packages/web/components/AppSidebar/AppSidebar.tsx +0 -316
  63. package/packages/web/components/AppSidebar/index.ts +0 -1
  64. package/packages/web/components/BackLink/BackLink.tsx +0 -18
  65. package/packages/web/components/BackLink/BackLink.types.ts +0 -5
  66. package/packages/web/components/BackLink/index.ts +0 -2
  67. package/packages/web/components/BentoCard/BentoCard.constants.ts +0 -16
  68. package/packages/web/components/BentoCard/BentoCard.tsx +0 -48
  69. package/packages/web/components/BentoCard/BentoCard.types.ts +0 -15
  70. package/packages/web/components/BentoCard/index.ts +0 -2
  71. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +0 -9
  72. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +0 -18
  73. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +0 -5
  74. package/packages/web/components/BentoCardSkeleton/index.ts +0 -2
  75. package/packages/web/components/BentoGrid/BentoGrid.tsx +0 -18
  76. package/packages/web/components/BentoGrid/BentoGrid.types.ts +0 -4
  77. package/packages/web/components/BentoGrid/index.ts +0 -2
  78. package/packages/web/components/BlockersCard/BlockersCard.tsx +0 -75
  79. package/packages/web/components/BlockersCard/BlockersCard.types.ts +0 -12
  80. package/packages/web/components/BlockersCard/index.ts +0 -2
  81. package/packages/web/components/CommandBar/CommandBar.tsx +0 -67
  82. package/packages/web/components/CommandBar/index.ts +0 -1
  83. package/packages/web/components/CommandButton/CommandButton.tsx +0 -46
  84. package/packages/web/components/CommandButton/index.ts +0 -1
  85. package/packages/web/components/ConnectionStatus/ConnectionStatus.tsx +0 -29
  86. package/packages/web/components/ConnectionStatus/index.ts +0 -1
  87. package/packages/web/components/DashboardContent/DashboardContent.tsx +0 -284
  88. package/packages/web/components/DashboardContent/index.ts +0 -1
  89. package/packages/web/components/DateGroup/DateGroup.tsx +0 -18
  90. package/packages/web/components/DateGroup/DateGroup.types.ts +0 -6
  91. package/packages/web/components/DateGroup/DateGroup.utils.ts +0 -11
  92. package/packages/web/components/DateGroup/index.ts +0 -2
  93. package/packages/web/components/EmptyState/EmptyState.tsx +0 -76
  94. package/packages/web/components/EmptyState/EmptyState.types.ts +0 -11
  95. package/packages/web/components/EmptyState/index.ts +0 -2
  96. package/packages/web/components/EventRow/EventRow.constants.ts +0 -10
  97. package/packages/web/components/EventRow/EventRow.tsx +0 -49
  98. package/packages/web/components/EventRow/EventRow.types.ts +0 -7
  99. package/packages/web/components/EventRow/EventRow.utils.ts +0 -49
  100. package/packages/web/components/EventRow/index.ts +0 -2
  101. package/packages/web/components/ExpandButton/ExpandButton.tsx +0 -18
  102. package/packages/web/components/ExpandButton/ExpandButton.types.ts +0 -6
  103. package/packages/web/components/ExpandButton/index.ts +0 -2
  104. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +0 -14
  105. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +0 -5
  106. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +0 -13
  107. package/packages/web/components/HealthGradientBackground/index.ts +0 -2
  108. package/packages/web/components/HeroSection/HeroSection.tsx +0 -92
  109. package/packages/web/components/HeroSection/HeroSection.types.ts +0 -14
  110. package/packages/web/components/HeroSection/HeroSection.utils.ts +0 -11
  111. package/packages/web/components/HeroSection/hooks/index.ts +0 -2
  112. package/packages/web/components/HeroSection/hooks/useCountUp.ts +0 -45
  113. package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +0 -18
  114. package/packages/web/components/HeroSection/index.ts +0 -2
  115. package/packages/web/components/IdeasCard/IdeasCard.tsx +0 -115
  116. package/packages/web/components/IdeasCard/IdeasCard.types.ts +0 -10
  117. package/packages/web/components/IdeasCard/index.ts +0 -2
  118. package/packages/web/components/InsightMessage/InsightMessage.tsx +0 -9
  119. package/packages/web/components/InsightMessage/InsightMessage.types.ts +0 -3
  120. package/packages/web/components/InsightMessage/index.ts +0 -2
  121. package/packages/web/components/Logo/Logo.tsx +0 -65
  122. package/packages/web/components/Logo/index.ts +0 -1
  123. package/packages/web/components/MarkdownContent/MarkdownContent.tsx +0 -123
  124. package/packages/web/components/MarkdownContent/index.ts +0 -1
  125. package/packages/web/components/MasonryGrid/MasonryGrid.tsx +0 -18
  126. package/packages/web/components/MasonryGrid/index.ts +0 -1
  127. package/packages/web/components/MomentumWidget/MomentumWidget.tsx +0 -119
  128. package/packages/web/components/MomentumWidget/MomentumWidget.types.ts +0 -16
  129. package/packages/web/components/MomentumWidget/index.ts +0 -2
  130. package/packages/web/components/NowCard/NowCard.tsx +0 -118
  131. package/packages/web/components/NowCard/NowCard.types.ts +0 -16
  132. package/packages/web/components/NowCard/index.ts +0 -2
  133. package/packages/web/components/PageHeader/PageHeader.tsx +0 -24
  134. package/packages/web/components/PageHeader/index.ts +0 -1
  135. package/packages/web/components/ProgressRing/ProgressRing.constants.ts +0 -20
  136. package/packages/web/components/ProgressRing/ProgressRing.tsx +0 -51
  137. package/packages/web/components/ProgressRing/ProgressRing.types.ts +0 -11
  138. package/packages/web/components/ProgressRing/index.ts +0 -2
  139. package/packages/web/components/ProjectAvatar/ProjectAvatar.tsx +0 -54
  140. package/packages/web/components/ProjectAvatar/index.ts +0 -1
  141. package/packages/web/components/ProjectColorDot/ProjectColorDot.tsx +0 -37
  142. package/packages/web/components/ProjectColorDot/index.ts +0 -1
  143. package/packages/web/components/ProjectSelectorModal/ProjectSelectorModal.tsx +0 -104
  144. package/packages/web/components/ProjectSelectorModal/index.ts +0 -1
  145. package/packages/web/components/Providers/Providers.tsx +0 -48
  146. package/packages/web/components/Providers/index.ts +0 -1
  147. package/packages/web/components/QueueCard/QueueCard.tsx +0 -125
  148. package/packages/web/components/QueueCard/QueueCard.types.ts +0 -12
  149. package/packages/web/components/QueueCard/QueueCard.utils.ts +0 -12
  150. package/packages/web/components/QueueCard/index.ts +0 -2
  151. package/packages/web/components/RecoverCard/RecoverCard.tsx +0 -72
  152. package/packages/web/components/RecoverCard/RecoverCard.types.ts +0 -16
  153. package/packages/web/components/RecoverCard/index.ts +0 -2
  154. package/packages/web/components/RoadmapCard/RoadmapCard.tsx +0 -145
  155. package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +0 -16
  156. package/packages/web/components/RoadmapCard/index.ts +0 -2
  157. package/packages/web/components/ShipsCard/ShipsCard.tsx +0 -95
  158. package/packages/web/components/ShipsCard/ShipsCard.types.ts +0 -14
  159. package/packages/web/components/ShipsCard/ShipsCard.utils.ts +0 -4
  160. package/packages/web/components/ShipsCard/index.ts +0 -2
  161. package/packages/web/components/SparklineChart/SparklineChart.tsx +0 -40
  162. package/packages/web/components/SparklineChart/SparklineChart.types.ts +0 -6
  163. package/packages/web/components/SparklineChart/index.ts +0 -2
  164. package/packages/web/components/StatsMasonry/StatsMasonry.tsx +0 -95
  165. package/packages/web/components/StatsMasonry/index.ts +0 -1
  166. package/packages/web/components/StreakCard/StreakCard.constants.ts +0 -2
  167. package/packages/web/components/StreakCard/StreakCard.tsx +0 -55
  168. package/packages/web/components/StreakCard/StreakCard.types.ts +0 -4
  169. package/packages/web/components/StreakCard/index.ts +0 -2
  170. package/packages/web/components/TasksCounter/TasksCounter.tsx +0 -14
  171. package/packages/web/components/TasksCounter/TasksCounter.types.ts +0 -3
  172. package/packages/web/components/TasksCounter/index.ts +0 -2
  173. package/packages/web/components/TechStackBadges/TechStackBadges.tsx +0 -28
  174. package/packages/web/components/TechStackBadges/index.ts +0 -1
  175. package/packages/web/components/TerminalDock/DockToggleTab.tsx +0 -29
  176. package/packages/web/components/TerminalDock/TerminalDock.tsx +0 -386
  177. package/packages/web/components/TerminalDock/TerminalDockTab.tsx +0 -130
  178. package/packages/web/components/TerminalDock/TerminalTabBar.tsx +0 -142
  179. package/packages/web/components/TerminalDock/index.ts +0 -2
  180. package/packages/web/components/TerminalTabs/TerminalTab.tsx +0 -95
  181. package/packages/web/components/TerminalTabs/TerminalTabs.tsx +0 -211
  182. package/packages/web/components/TerminalTabs/index.ts +0 -1
  183. package/packages/web/components/VelocityBadge/VelocityBadge.tsx +0 -32
  184. package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +0 -3
  185. package/packages/web/components/VelocityBadge/index.ts +0 -2
  186. package/packages/web/components/VelocityCard/VelocityCard.tsx +0 -73
  187. package/packages/web/components/VelocityCard/VelocityCard.types.ts +0 -7
  188. package/packages/web/components/VelocityCard/index.ts +0 -2
  189. package/packages/web/components/WeeklyReports/PrintableReport.tsx +0 -259
  190. package/packages/web/components/WeeklyReports/ReportPreviewCard.tsx +0 -187
  191. package/packages/web/components/WeeklyReports/WeekCalendar.tsx +0 -288
  192. package/packages/web/components/WeeklyReports/WeeklyReports.tsx +0 -149
  193. package/packages/web/components/WeeklyReports/index.ts +0 -4
  194. package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +0 -25
  195. package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +0 -4
  196. package/packages/web/components/WeeklySparkline/index.ts +0 -2
  197. package/packages/web/components/charts/SessionsChart.tsx +0 -175
  198. package/packages/web/components/ui/alert-dialog.tsx +0 -157
  199. package/packages/web/components/ui/badge.tsx +0 -46
  200. package/packages/web/components/ui/button.tsx +0 -60
  201. package/packages/web/components/ui/card.tsx +0 -92
  202. package/packages/web/components/ui/chart.tsx +0 -385
  203. package/packages/web/components/ui/dialog.tsx +0 -143
  204. package/packages/web/components/ui/drawer.tsx +0 -135
  205. package/packages/web/components/ui/dropdown-menu.tsx +0 -257
  206. package/packages/web/components/ui/input.tsx +0 -21
  207. package/packages/web/components/ui/scroll-area.tsx +0 -58
  208. package/packages/web/components/ui/select.tsx +0 -187
  209. package/packages/web/components/ui/sheet.tsx +0 -139
  210. package/packages/web/components/ui/tabs.tsx +0 -66
  211. package/packages/web/components/ui/tooltip.tsx +0 -61
  212. package/packages/web/components.json +0 -22
  213. package/packages/web/context/GlobalTerminalContext.tsx +0 -538
  214. package/packages/web/context/TerminalContext.tsx +0 -45
  215. package/packages/web/context/TerminalTabsContext.tsx +0 -181
  216. package/packages/web/eslint.config.mjs +0 -18
  217. package/packages/web/hooks/useClaudeTerminal.ts +0 -425
  218. package/packages/web/hooks/useProjectStats.ts +0 -93
  219. package/packages/web/hooks/useProjects.ts +0 -73
  220. package/packages/web/lib/actions/projects.ts +0 -15
  221. package/packages/web/lib/commands.ts +0 -81
  222. package/packages/web/lib/format.ts +0 -23
  223. package/packages/web/lib/generate-week-report.ts +0 -285
  224. package/packages/web/lib/parse-prjct-files.ts +0 -1123
  225. package/packages/web/lib/project-colors.ts +0 -58
  226. package/packages/web/lib/projects.ts +0 -506
  227. package/packages/web/lib/pty.ts +0 -101
  228. package/packages/web/lib/query-config.ts +0 -44
  229. package/packages/web/lib/services/index.ts +0 -9
  230. package/packages/web/lib/services/projects.server.ts +0 -66
  231. package/packages/web/lib/services/stats.server.ts +0 -562
  232. package/packages/web/lib/unified-loader.ts +0 -396
  233. package/packages/web/lib/utils.ts +0 -6
  234. package/packages/web/next-env.d.ts +0 -6
  235. package/packages/web/next.config.ts +0 -7
  236. package/packages/web/package.json +0 -57
  237. package/packages/web/postcss.config.mjs +0 -7
  238. package/packages/web/public/file.svg +0 -1
  239. package/packages/web/public/globe.svg +0 -1
  240. package/packages/web/public/next.svg +0 -1
  241. package/packages/web/public/vercel.svg +0 -1
  242. package/packages/web/public/window.svg +0 -1
  243. package/packages/web/server.ts +0 -312
  244. package/packages/web/tsconfig.json +0 -34
  245. 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'