prjct-cli 0.11.5 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +81 -25
  3. package/bin/dev.js +1 -1
  4. package/bin/generate-views.js +209 -0
  5. package/bin/migrate-to-json.js +742 -0
  6. package/bin/prjct +5 -5
  7. package/bin/serve.js +226 -50
  8. package/core/__tests__/agentic/{memory-system.test.js → memory-system.test.ts} +12 -23
  9. package/core/__tests__/agentic/{plan-mode.test.js → plan-mode.test.ts} +26 -24
  10. package/core/__tests__/agentic/{prompt-builder.test.js → prompt-builder.test.ts} +3 -8
  11. package/core/__tests__/utils/{date-helper.test.js → date-helper.test.ts} +19 -30
  12. package/core/__tests__/utils/{output.test.js → output.test.ts} +12 -24
  13. package/core/agentic/agent-router.ts +137 -0
  14. package/core/agentic/chain-of-thought.ts +228 -0
  15. package/core/agentic/command-executor/command-executor.ts +384 -0
  16. package/core/agentic/command-executor/index.ts +16 -0
  17. package/core/agentic/command-executor/status-signal.ts +38 -0
  18. package/core/agentic/command-executor/types.ts +79 -0
  19. package/core/agentic/command-executor.ts +8 -0
  20. package/core/agentic/{context-builder.js → context-builder.ts} +92 -81
  21. package/core/agentic/context-filter.ts +365 -0
  22. package/core/agentic/ground-truth/index.ts +76 -0
  23. package/core/agentic/ground-truth/types.ts +33 -0
  24. package/core/agentic/ground-truth/utils.ts +48 -0
  25. package/core/agentic/ground-truth/verifiers/analyze.ts +54 -0
  26. package/core/agentic/ground-truth/verifiers/done.ts +75 -0
  27. package/core/agentic/ground-truth/verifiers/feature.ts +70 -0
  28. package/core/agentic/ground-truth/verifiers/index.ts +37 -0
  29. package/core/agentic/ground-truth/verifiers/init.ts +52 -0
  30. package/core/agentic/ground-truth/verifiers/now.ts +57 -0
  31. package/core/agentic/ground-truth/verifiers/ship.ts +85 -0
  32. package/core/agentic/ground-truth/verifiers/spec.ts +45 -0
  33. package/core/agentic/ground-truth/verifiers/sync.ts +47 -0
  34. package/core/agentic/ground-truth/verifiers.ts +6 -0
  35. package/core/agentic/ground-truth.ts +8 -0
  36. package/core/agentic/loop-detector/error-analysis.ts +97 -0
  37. package/core/agentic/loop-detector/hallucination.ts +71 -0
  38. package/core/agentic/loop-detector/index.ts +41 -0
  39. package/core/agentic/loop-detector/loop-detector.ts +222 -0
  40. package/core/agentic/loop-detector/types.ts +66 -0
  41. package/core/agentic/loop-detector.ts +8 -0
  42. package/core/agentic/memory-system/history.ts +53 -0
  43. package/core/agentic/memory-system/index.ts +192 -0
  44. package/core/agentic/memory-system/patterns.ts +156 -0
  45. package/core/agentic/memory-system/semantic-memories.ts +277 -0
  46. package/core/agentic/memory-system/session.ts +21 -0
  47. package/core/agentic/memory-system/types.ts +159 -0
  48. package/core/agentic/memory-system.ts +8 -0
  49. package/core/agentic/parallel-tools.ts +165 -0
  50. package/core/agentic/plan-mode/approval.ts +57 -0
  51. package/core/agentic/plan-mode/constants.ts +44 -0
  52. package/core/agentic/plan-mode/index.ts +28 -0
  53. package/core/agentic/plan-mode/plan-mode.ts +406 -0
  54. package/core/agentic/plan-mode/types.ts +193 -0
  55. package/core/agentic/plan-mode.ts +8 -0
  56. package/core/agentic/prompt-builder.ts +566 -0
  57. package/core/agentic/response-templates.ts +164 -0
  58. package/core/agentic/semantic-compression.ts +273 -0
  59. package/core/agentic/services.ts +206 -0
  60. package/core/agentic/smart-context.ts +476 -0
  61. package/core/agentic/{template-loader.js → template-loader.ts} +27 -16
  62. package/core/agentic/think-blocks.ts +202 -0
  63. package/core/agentic/tool-registry.ts +119 -0
  64. package/core/agentic/validation-rules.ts +313 -0
  65. package/core/agents/index.ts +28 -0
  66. package/core/agents/performance.ts +444 -0
  67. package/core/agents/types.ts +126 -0
  68. package/core/bus/{index.js → index.ts} +57 -61
  69. package/core/command-registry/categories.ts +23 -0
  70. package/core/command-registry/commands.ts +15 -0
  71. package/core/command-registry/core-commands.ts +319 -0
  72. package/core/command-registry/index.ts +158 -0
  73. package/core/command-registry/optional-commands.ts +119 -0
  74. package/core/command-registry/setup-commands.ts +53 -0
  75. package/core/command-registry/types.ts +59 -0
  76. package/core/command-registry.ts +9 -0
  77. package/core/commands/analysis.ts +298 -0
  78. package/core/commands/analytics.ts +288 -0
  79. package/core/commands/base.ts +273 -0
  80. package/core/commands/index.ts +211 -0
  81. package/core/commands/maintenance.ts +226 -0
  82. package/core/commands/planning.ts +311 -0
  83. package/core/commands/setup.ts +309 -0
  84. package/core/commands/shipping.ts +188 -0
  85. package/core/commands/types.ts +183 -0
  86. package/core/commands/workflow.ts +226 -0
  87. package/core/commands.ts +11 -0
  88. package/core/constants/formats.ts +187 -0
  89. package/core/constants/index.ts +7 -0
  90. package/core/{context-sync.js → context-sync.ts} +59 -26
  91. package/core/data/agents-manager.ts +76 -0
  92. package/core/data/analysis-manager.ts +83 -0
  93. package/core/data/base-manager.ts +156 -0
  94. package/core/data/ideas-manager.ts +81 -0
  95. package/core/data/index.ts +32 -0
  96. package/core/data/outcomes-manager.ts +96 -0
  97. package/core/data/project-manager.ts +75 -0
  98. package/core/data/roadmap-manager.ts +118 -0
  99. package/core/data/shipped-manager.ts +65 -0
  100. package/core/data/state-manager.ts +214 -0
  101. package/core/domain/{agent-generator.js → agent-generator.ts} +77 -57
  102. package/core/domain/{agent-loader.js → agent-loader.ts} +65 -56
  103. package/core/domain/{agent-matcher.js → agent-matcher.ts} +51 -24
  104. package/core/domain/{agent-validator.js → agent-validator.ts} +70 -37
  105. package/core/domain/{analyzer.js → analyzer.ts} +91 -85
  106. package/core/domain/{architect-session.js → architect-session.ts} +49 -34
  107. package/core/domain/{architecture-generator.js → architecture-generator.ts} +25 -13
  108. package/core/domain/{context-estimator.js → context-estimator.ts} +57 -36
  109. package/core/domain/{product-standards.js → product-standards.ts} +40 -26
  110. package/core/domain/{smart-cache.js → smart-cache.ts} +39 -30
  111. package/core/domain/{snapshot-manager.js → snapshot-manager.ts} +103 -100
  112. package/core/domain/{task-analyzer.js → task-analyzer.ts} +82 -43
  113. package/core/domain/task-stack/index.ts +19 -0
  114. package/core/domain/task-stack/parser.ts +86 -0
  115. package/core/domain/task-stack/storage.ts +123 -0
  116. package/core/domain/task-stack/task-stack.ts +340 -0
  117. package/core/domain/task-stack/types.ts +51 -0
  118. package/core/domain/task-stack.ts +8 -0
  119. package/core/{index.js → index.ts} +61 -18
  120. package/core/infrastructure/{agent-detector.js → agent-detector.ts} +55 -19
  121. package/core/infrastructure/agents/{claude-agent.js → claude-agent.ts} +61 -21
  122. package/core/infrastructure/{author-detector.js → author-detector.ts} +42 -49
  123. package/core/infrastructure/{capability-installer.js → capability-installer.ts} +51 -27
  124. package/core/infrastructure/{command-installer.js → command-installer/command-installer.ts} +43 -144
  125. package/core/infrastructure/command-installer/global-config.ts +106 -0
  126. package/core/infrastructure/command-installer/index.ts +25 -0
  127. package/core/infrastructure/command-installer/types.ts +41 -0
  128. package/core/infrastructure/command-installer.ts +8 -0
  129. package/core/infrastructure/{config-manager.js → config-manager.ts} +60 -80
  130. package/core/infrastructure/{editors-config.js → editors-config.ts} +33 -31
  131. package/core/infrastructure/legacy-installer-detector/cleanup.ts +216 -0
  132. package/core/infrastructure/legacy-installer-detector/detection.ts +95 -0
  133. package/core/infrastructure/legacy-installer-detector/index.ts +171 -0
  134. package/core/infrastructure/legacy-installer-detector/migration.ts +87 -0
  135. package/core/infrastructure/legacy-installer-detector/types.ts +42 -0
  136. package/core/infrastructure/legacy-installer-detector.ts +7 -0
  137. package/core/infrastructure/migrator/file-operations.ts +125 -0
  138. package/core/infrastructure/migrator/index.ts +288 -0
  139. package/core/infrastructure/migrator/project-scanner.ts +89 -0
  140. package/core/infrastructure/migrator/reports.ts +117 -0
  141. package/core/infrastructure/migrator/types.ts +124 -0
  142. package/core/infrastructure/migrator/validation.ts +94 -0
  143. package/core/infrastructure/migrator/version-migration.ts +117 -0
  144. package/core/infrastructure/migrator.ts +10 -0
  145. package/core/infrastructure/{path-manager.js → path-manager.ts} +51 -91
  146. package/core/infrastructure/session-manager/index.ts +23 -0
  147. package/core/infrastructure/session-manager/migration.ts +88 -0
  148. package/core/infrastructure/session-manager/session-manager.ts +307 -0
  149. package/core/infrastructure/session-manager/types.ts +45 -0
  150. package/core/infrastructure/session-manager.ts +8 -0
  151. package/core/infrastructure/{setup.js → setup.ts} +29 -21
  152. package/core/infrastructure/{update-checker.js → update-checker.ts} +40 -18
  153. package/core/outcomes/analyzer.ts +333 -0
  154. package/core/outcomes/index.ts +34 -0
  155. package/core/outcomes/recorder.ts +194 -0
  156. package/core/outcomes/types.ts +145 -0
  157. package/core/plugin/{hooks.js → hooks.ts} +56 -58
  158. package/core/plugin/{index.js → index.ts} +19 -8
  159. package/core/plugin/{loader.js → loader.ts} +87 -69
  160. package/core/plugin/{registry.js → registry.ts} +49 -45
  161. package/core/plugins/{webhook.js → webhook.ts} +43 -27
  162. package/core/schemas/agents.ts +27 -0
  163. package/core/schemas/analysis.ts +41 -0
  164. package/core/schemas/ideas.ts +83 -0
  165. package/core/schemas/index.ts +73 -0
  166. package/core/schemas/outcomes.ts +22 -0
  167. package/core/schemas/project.ts +26 -0
  168. package/core/schemas/roadmap.ts +90 -0
  169. package/core/schemas/shipped.ts +82 -0
  170. package/core/schemas/state.ts +107 -0
  171. package/core/session/index.ts +17 -0
  172. package/core/session/{metrics.js → metrics.ts} +64 -46
  173. package/core/session/{index.js → session-manager.ts} +51 -117
  174. package/core/session/types.ts +29 -0
  175. package/core/session/utils.ts +57 -0
  176. package/core/state/index.ts +25 -0
  177. package/core/state/manager.ts +376 -0
  178. package/core/state/types.ts +185 -0
  179. package/core/tsconfig.json +22 -0
  180. package/core/types/index.ts +506 -0
  181. package/core/utils/{animations.js → animations.ts} +74 -28
  182. package/core/utils/{branding.js → branding.ts} +29 -4
  183. package/core/utils/{date-helper.js → date-helper.ts} +31 -74
  184. package/core/utils/file-helper.ts +262 -0
  185. package/core/utils/{jsonl-helper.js → jsonl-helper.ts} +71 -107
  186. package/core/utils/{logger.js → logger.ts} +24 -12
  187. package/core/utils/{output.js → output.ts} +25 -13
  188. package/core/utils/{project-capabilities.js → project-capabilities.ts} +31 -18
  189. package/core/utils/{session-helper.js → session-helper.ts} +79 -66
  190. package/core/utils/{version.js → version.ts} +23 -31
  191. package/core/view-generator.ts +536 -0
  192. package/package.json +23 -17
  193. package/packages/shared/.turbo/turbo-build.log +14 -0
  194. package/packages/shared/dist/index.d.ts +8 -613
  195. package/packages/shared/dist/index.d.ts.map +1 -0
  196. package/packages/shared/dist/index.js +4110 -118
  197. package/packages/shared/dist/schemas.d.ts +408 -0
  198. package/packages/shared/dist/schemas.d.ts.map +1 -0
  199. package/packages/shared/dist/types.d.ts +144 -0
  200. package/packages/shared/dist/types.d.ts.map +1 -0
  201. package/packages/shared/dist/unified.d.ts +139 -0
  202. package/packages/shared/dist/unified.d.ts.map +1 -0
  203. package/packages/shared/dist/utils.d.ts +60 -0
  204. package/packages/shared/dist/utils.d.ts.map +1 -0
  205. package/packages/shared/package.json +4 -4
  206. package/packages/shared/src/index.ts +1 -0
  207. package/packages/shared/src/unified.ts +174 -0
  208. package/packages/web/app/api/claude/sessions/route.ts +1 -1
  209. package/packages/web/app/api/claude/status/route.ts +1 -1
  210. package/packages/web/app/api/migrate/route.ts +46 -0
  211. package/packages/web/app/api/projects/[id]/route.ts +1 -1
  212. package/packages/web/app/api/projects/[id]/stats/route.ts +30 -2
  213. package/packages/web/app/api/projects/[id]/status/route.ts +1 -1
  214. package/packages/web/app/api/projects/route.ts +1 -1
  215. package/packages/web/app/api/settings/route.ts +97 -0
  216. package/packages/web/app/api/v2/projects/[id]/unified/route.ts +57 -0
  217. package/packages/web/app/globals.css +38 -0
  218. package/packages/web/app/layout.tsx +10 -2
  219. package/packages/web/app/page.tsx +9 -224
  220. package/packages/web/app/project/[id]/page.tsx +191 -63
  221. package/packages/web/app/project/[id]/stats/loading.tsx +43 -0
  222. package/packages/web/app/project/[id]/stats/page.tsx +204 -163
  223. package/packages/web/app/settings/page.tsx +222 -2
  224. package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +2 -0
  225. package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +50 -0
  226. package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +8 -0
  227. package/packages/web/components/ActivityTimeline/hooks/index.ts +2 -0
  228. package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +9 -0
  229. package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +23 -0
  230. package/packages/web/components/ActivityTimeline/index.ts +2 -0
  231. package/packages/web/components/AgentsCard/AgentsCard.tsx +63 -0
  232. package/packages/web/components/AgentsCard/AgentsCard.types.ts +13 -0
  233. package/packages/web/components/AgentsCard/index.ts +2 -0
  234. package/packages/web/components/AppSidebar/AppSidebar.tsx +190 -0
  235. package/packages/web/components/AppSidebar/index.ts +1 -0
  236. package/packages/web/components/BackLink/BackLink.tsx +18 -0
  237. package/packages/web/components/BackLink/BackLink.types.ts +5 -0
  238. package/packages/web/components/BackLink/index.ts +2 -0
  239. package/packages/web/components/BentoCard/BentoCard.constants.ts +16 -0
  240. package/packages/web/components/BentoCard/BentoCard.tsx +47 -0
  241. package/packages/web/components/BentoCard/BentoCard.types.ts +15 -0
  242. package/packages/web/components/BentoCard/index.ts +2 -0
  243. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +9 -0
  244. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +18 -0
  245. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +5 -0
  246. package/packages/web/components/BentoCardSkeleton/index.ts +2 -0
  247. package/packages/web/components/{stats → BentoGrid}/BentoGrid.tsx +4 -8
  248. package/packages/web/components/BentoGrid/BentoGrid.types.ts +4 -0
  249. package/packages/web/components/BentoGrid/index.ts +2 -0
  250. package/packages/web/components/CommandButton/index.ts +1 -0
  251. package/packages/web/components/ConnectionStatus/index.ts +1 -0
  252. package/packages/web/components/DashboardContent/DashboardContent.tsx +254 -0
  253. package/packages/web/components/DashboardContent/index.ts +1 -0
  254. package/packages/web/components/DateGroup/DateGroup.tsx +18 -0
  255. package/packages/web/components/DateGroup/DateGroup.types.ts +6 -0
  256. package/packages/web/components/DateGroup/DateGroup.utils.ts +11 -0
  257. package/packages/web/components/DateGroup/index.ts +2 -0
  258. package/packages/web/components/{stats → EmptyState}/EmptyState.tsx +1 -10
  259. package/packages/web/components/EmptyState/EmptyState.types.ts +10 -0
  260. package/packages/web/components/EmptyState/index.ts +2 -0
  261. package/packages/web/components/EventRow/EventRow.constants.ts +10 -0
  262. package/packages/web/components/EventRow/EventRow.tsx +49 -0
  263. package/packages/web/components/EventRow/EventRow.types.ts +7 -0
  264. package/packages/web/components/EventRow/EventRow.utils.ts +49 -0
  265. package/packages/web/components/EventRow/index.ts +2 -0
  266. package/packages/web/components/ExpandButton/ExpandButton.tsx +18 -0
  267. package/packages/web/components/ExpandButton/ExpandButton.types.ts +6 -0
  268. package/packages/web/components/ExpandButton/index.ts +2 -0
  269. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +14 -0
  270. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +5 -0
  271. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +13 -0
  272. package/packages/web/components/HealthGradientBackground/index.ts +2 -0
  273. package/packages/web/components/HeroSection/HeroSection.tsx +55 -0
  274. package/packages/web/components/HeroSection/HeroSection.types.ts +14 -0
  275. package/packages/web/components/HeroSection/HeroSection.utils.ts +7 -0
  276. package/packages/web/components/HeroSection/hooks/index.ts +2 -0
  277. package/packages/web/components/HeroSection/hooks/useCountUp.ts +45 -0
  278. package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +18 -0
  279. package/packages/web/components/HeroSection/index.ts +2 -0
  280. package/packages/web/components/{stats → IdeasCard}/IdeasCard.tsx +3 -14
  281. package/packages/web/components/IdeasCard/IdeasCard.types.ts +9 -0
  282. package/packages/web/components/IdeasCard/index.ts +2 -0
  283. package/packages/web/components/InsightMessage/InsightMessage.tsx +9 -0
  284. package/packages/web/components/InsightMessage/InsightMessage.types.ts +3 -0
  285. package/packages/web/components/InsightMessage/index.ts +2 -0
  286. package/packages/web/components/Logo/index.ts +1 -0
  287. package/packages/web/components/MarkdownContent/index.ts +1 -0
  288. package/packages/web/components/NowCard/NowCard.tsx +93 -0
  289. package/packages/web/components/NowCard/NowCard.types.ts +15 -0
  290. package/packages/web/components/NowCard/index.ts +2 -0
  291. package/packages/web/components/ProgressRing/ProgressRing.constants.ts +20 -0
  292. package/packages/web/components/{stats → ProgressRing}/ProgressRing.tsx +4 -27
  293. package/packages/web/components/ProgressRing/ProgressRing.types.ts +11 -0
  294. package/packages/web/components/ProgressRing/index.ts +2 -0
  295. package/packages/web/components/ProjectAvatar/index.ts +1 -0
  296. package/packages/web/components/Providers/index.ts +1 -0
  297. package/packages/web/components/QueueCard/QueueCard.tsx +72 -0
  298. package/packages/web/components/QueueCard/QueueCard.types.ts +11 -0
  299. package/packages/web/components/QueueCard/QueueCard.utils.ts +12 -0
  300. package/packages/web/components/QueueCard/index.ts +2 -0
  301. package/packages/web/components/{stats → RoadmapCard}/RoadmapCard.tsx +3 -23
  302. package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +15 -0
  303. package/packages/web/components/RoadmapCard/index.ts +2 -0
  304. package/packages/web/components/{stats → ShipsCard}/ShipsCard.tsx +4 -22
  305. package/packages/web/components/ShipsCard/ShipsCard.types.ts +12 -0
  306. package/packages/web/components/ShipsCard/ShipsCard.utils.ts +4 -0
  307. package/packages/web/components/ShipsCard/index.ts +2 -0
  308. package/packages/web/components/{stats → SparklineChart}/SparklineChart.tsx +1 -7
  309. package/packages/web/components/SparklineChart/SparklineChart.types.ts +6 -0
  310. package/packages/web/components/SparklineChart/index.ts +2 -0
  311. package/packages/web/components/StreakCard/StreakCard.constants.ts +2 -0
  312. package/packages/web/components/{stats → StreakCard}/StreakCard.tsx +5 -11
  313. package/packages/web/components/StreakCard/StreakCard.types.ts +4 -0
  314. package/packages/web/components/StreakCard/index.ts +2 -0
  315. package/packages/web/components/TasksCounter/TasksCounter.tsx +14 -0
  316. package/packages/web/components/TasksCounter/TasksCounter.types.ts +3 -0
  317. package/packages/web/components/TasksCounter/index.ts +2 -0
  318. package/packages/web/components/TechStackBadges/index.ts +1 -0
  319. package/packages/web/components/{TerminalTab.tsx → TerminalTabs/TerminalTab.tsx} +11 -0
  320. package/packages/web/components/{TerminalTabs.tsx → TerminalTabs/TerminalTabs.tsx} +29 -28
  321. package/packages/web/components/TerminalTabs/index.ts +1 -0
  322. package/packages/web/components/VelocityBadge/VelocityBadge.tsx +27 -0
  323. package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +3 -0
  324. package/packages/web/components/VelocityBadge/index.ts +2 -0
  325. package/packages/web/components/VelocityCard/VelocityCard.tsx +71 -0
  326. package/packages/web/components/VelocityCard/VelocityCard.types.ts +7 -0
  327. package/packages/web/components/VelocityCard/index.ts +2 -0
  328. package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +13 -0
  329. package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +3 -0
  330. package/packages/web/components/WeeklySparkline/index.ts +2 -0
  331. package/packages/web/components/ui/input.tsx +21 -0
  332. package/packages/web/context/TerminalTabsContext.tsx +46 -1
  333. package/packages/web/hooks/useClaudeTerminal.ts +71 -21
  334. package/packages/web/hooks/useProjectStats.ts +55 -0
  335. package/packages/web/hooks/useProjects.ts +6 -6
  336. package/packages/web/lib/actions/projects.ts +15 -0
  337. package/packages/web/lib/json-loader.ts +630 -0
  338. package/packages/web/lib/services/index.ts +9 -0
  339. package/packages/web/lib/services/migration.server.ts +600 -0
  340. package/packages/web/lib/services/projects.server.ts +52 -0
  341. package/packages/web/lib/services/stats.server.ts +264 -0
  342. package/packages/web/lib/unified-loader.ts +396 -0
  343. package/packages/web/package.json +10 -7
  344. package/packages/web/server.ts +58 -8
  345. package/templates/commands/done.md +76 -32
  346. package/templates/commands/feature.md +121 -47
  347. package/templates/commands/idea.md +81 -8
  348. package/templates/commands/now.md +41 -17
  349. package/templates/commands/ship.md +64 -25
  350. package/templates/commands/sync.md +28 -3
  351. package/core/agentic/agent-router.js +0 -140
  352. package/core/agentic/chain-of-thought.js +0 -578
  353. package/core/agentic/command-executor.js +0 -417
  354. package/core/agentic/context-filter.js +0 -354
  355. package/core/agentic/ground-truth.js +0 -591
  356. package/core/agentic/loop-detector.js +0 -406
  357. package/core/agentic/memory-system.js +0 -845
  358. package/core/agentic/parallel-tools.js +0 -366
  359. package/core/agentic/plan-mode.js +0 -572
  360. package/core/agentic/prompt-builder.js +0 -352
  361. package/core/agentic/response-templates.js +0 -290
  362. package/core/agentic/semantic-compression.js +0 -517
  363. package/core/agentic/think-blocks.js +0 -657
  364. package/core/agentic/tool-registry.js +0 -184
  365. package/core/agentic/validation-rules.js +0 -380
  366. package/core/command-registry.js +0 -698
  367. package/core/commands.js +0 -2237
  368. package/core/domain/task-stack.js +0 -497
  369. package/core/infrastructure/legacy-installer-detector.js +0 -546
  370. package/core/infrastructure/migrator.js +0 -796
  371. package/core/infrastructure/session-manager.js +0 -390
  372. package/core/utils/file-helper.js +0 -329
  373. package/packages/web/app/api/projects/[id]/delete/route.ts +0 -21
  374. package/packages/web/app/api/stats/route.ts +0 -38
  375. package/packages/web/components/AppSidebar.tsx +0 -113
  376. package/packages/web/components/stats/ActivityTimeline.tsx +0 -201
  377. package/packages/web/components/stats/AgentsCard.tsx +0 -56
  378. package/packages/web/components/stats/BentoCard.tsx +0 -88
  379. package/packages/web/components/stats/HeroSection.tsx +0 -172
  380. package/packages/web/components/stats/NowCard.tsx +0 -71
  381. package/packages/web/components/stats/QueueCard.tsx +0 -58
  382. package/packages/web/components/stats/VelocityCard.tsx +0 -60
  383. package/packages/web/components/stats/index.ts +0 -17
  384. package/packages/web/hooks/useStats.ts +0 -28
  385. /package/packages/web/components/{CommandButton.tsx → CommandButton/CommandButton.tsx} +0 -0
  386. /package/packages/web/components/{ConnectionStatus.tsx → ConnectionStatus/ConnectionStatus.tsx} +0 -0
  387. /package/packages/web/components/{Logo.tsx → Logo/Logo.tsx} +0 -0
  388. /package/packages/web/components/{MarkdownContent.tsx → MarkdownContent/MarkdownContent.tsx} +0 -0
  389. /package/packages/web/components/{ProjectAvatar.tsx → ProjectAvatar/ProjectAvatar.tsx} +0 -0
  390. /package/packages/web/components/{providers.tsx → Providers/Providers.tsx} +0 -0
  391. /package/packages/web/components/{TechStackBadges.tsx → TechStackBadges/TechStackBadges.tsx} +0 -0
@@ -1,41 +1,44 @@
1
- const fs = require('fs').promises
2
- const fsSync = require('fs')
3
- const readline = require('readline')
4
- const path = require('path')
1
+ import fs from 'fs/promises'
2
+ import fsSync from 'fs'
3
+ import readline from 'readline'
4
+ import path from 'path'
5
5
 
6
6
  /**
7
7
  * JSONL Helper - Centralized JSONL parsing and writing
8
8
  *
9
9
  * Eliminates duplicated JSONL logic across:
10
- * - session-manager.js (_parseJsonLines)
11
- * - commands.js (inline parsing)
12
- * - analyzer.js (inline parsing)
10
+ * - session-manager.ts (_parseJsonLines)
11
+ * - commands.ts (inline parsing)
12
+ * - analyzer.ts (inline parsing)
13
13
  *
14
14
  * JSONL Format: One JSON object per line, newline-separated
15
15
  * Example:
16
16
  * {"ts":"2025-10-04T14:30:00Z","type":"feature_add","name":"auth"}
17
17
  * {"ts":"2025-10-04T15:00:00Z","type":"task_start","task":"JWT"}
18
- *
19
- * @module jsonl-helper
20
18
  */
21
19
 
20
+ interface NodeError extends Error {
21
+ code?: string
22
+ }
23
+
24
+ interface FileSizeWarning {
25
+ sizeMB: number
26
+ isLarge: boolean
27
+ }
28
+
22
29
  /**
23
30
  * Parse JSONL content into array of objects
24
31
  * Handles malformed lines gracefully (skips them)
25
- *
26
- * @param {string} content - JSONL content
27
- * @returns {Array<Object>} - Array of parsed objects
28
32
  */
29
- function parseJsonLines(content) {
33
+ export function parseJsonLines<T = Record<string, unknown>>(content: string): T[] {
30
34
  const lines = content.split('\n').filter((line) => line.trim())
31
- const entries = []
35
+ const entries: T[] = []
32
36
 
33
37
  for (const line of lines) {
34
38
  try {
35
- entries.push(JSON.parse(line))
36
- } catch (error) {
39
+ entries.push(JSON.parse(line) as T)
40
+ } catch {
37
41
  // Skip malformed lines silently
38
- // Could optionally log warning
39
42
  }
40
43
  }
41
44
 
@@ -44,26 +47,20 @@ function parseJsonLines(content) {
44
47
 
45
48
  /**
46
49
  * Convert array of objects to JSONL string
47
- *
48
- * @param {Array<Object>} objects - Array of objects to stringify
49
- * @returns {string} - JSONL formatted string
50
50
  */
51
- function stringifyJsonLines(objects) {
51
+ export function stringifyJsonLines(objects: unknown[]): string {
52
52
  return objects.map((obj) => JSON.stringify(obj)).join('\n') + '\n'
53
53
  }
54
54
 
55
55
  /**
56
56
  * Read and parse JSONL file
57
- *
58
- * @param {string} filePath - Path to JSONL file
59
- * @returns {Promise<Array<Object>>} - Array of parsed objects
60
57
  */
61
- async function readJsonLines(filePath) {
58
+ export async function readJsonLines<T = Record<string, unknown>>(filePath: string): Promise<T[]> {
62
59
  try {
63
60
  const content = await fs.readFile(filePath, 'utf-8')
64
- return parseJsonLines(content)
61
+ return parseJsonLines<T>(content)
65
62
  } catch (error) {
66
- if (error.code === 'ENOENT') {
63
+ if ((error as NodeError).code === 'ENOENT') {
67
64
  return [] // File doesn't exist, return empty array
68
65
  }
69
66
  throw error
@@ -72,12 +69,8 @@ async function readJsonLines(filePath) {
72
69
 
73
70
  /**
74
71
  * Write array of objects to JSONL file (overwrites)
75
- *
76
- * @param {string} filePath - Path to JSONL file
77
- * @param {Array<Object>} objects - Array of objects to write
78
- * @returns {Promise<void>}
79
72
  */
80
- async function writeJsonLines(filePath, objects) {
73
+ export async function writeJsonLines(filePath: string, objects: unknown[]): Promise<void> {
81
74
  const content = stringifyJsonLines(objects)
82
75
  await fs.writeFile(filePath, content, 'utf-8')
83
76
  }
@@ -85,24 +78,16 @@ async function writeJsonLines(filePath, objects) {
85
78
  /**
86
79
  * Append a single object to JSONL file
87
80
  * Uses append mode for efficiency (no full file read/write)
88
- *
89
- * @param {string} filePath - Path to JSONL file
90
- * @param {Object} object - Object to append
91
- * @returns {Promise<void>}
92
81
  */
93
- async function appendJsonLine(filePath, object) {
82
+ export async function appendJsonLine(filePath: string, object: unknown): Promise<void> {
94
83
  const line = JSON.stringify(object) + '\n'
95
84
  await fs.appendFile(filePath, line, 'utf-8')
96
85
  }
97
86
 
98
87
  /**
99
88
  * Append multiple objects to JSONL file
100
- *
101
- * @param {string} filePath - Path to JSONL file
102
- * @param {Array<Object>} objects - Objects to append
103
- * @returns {Promise<void>}
104
89
  */
105
- async function appendJsonLines(filePath, objects) {
90
+ export async function appendJsonLines(filePath: string, objects: unknown[]): Promise<void> {
106
91
  const content = stringifyJsonLines(objects)
107
92
  await fs.appendFile(filePath, content, 'utf-8')
108
93
  }
@@ -110,29 +95,25 @@ async function appendJsonLines(filePath, objects) {
110
95
  /**
111
96
  * Filter JSONL file entries by predicate
112
97
  * Reads all entries, filters, returns matching ones
113
- *
114
- * @param {string} filePath - Path to JSONL file
115
- * @param {Function} predicate - Filter function (entry => boolean)
116
- * @returns {Promise<Array<Object>>} - Filtered entries
117
98
  */
118
- async function filterJsonLines(filePath, predicate) {
119
- const entries = await readJsonLines(filePath)
99
+ export async function filterJsonLines<T = Record<string, unknown>>(
100
+ filePath: string,
101
+ predicate: (entry: T) => boolean
102
+ ): Promise<T[]> {
103
+ const entries = await readJsonLines<T>(filePath)
120
104
  return entries.filter(predicate)
121
105
  }
122
106
 
123
107
  /**
124
108
  * Count lines in JSONL file (non-empty, parseable lines)
125
- *
126
- * @param {string} filePath - Path to JSONL file
127
- * @returns {Promise<number>} - Number of valid lines
128
109
  */
129
- async function countJsonLines(filePath) {
110
+ export async function countJsonLines(filePath: string): Promise<number> {
130
111
  try {
131
112
  const content = await fs.readFile(filePath, 'utf-8')
132
113
  const lines = content.split('\n').filter((line) => line.trim())
133
114
  return lines.length
134
115
  } catch (error) {
135
- if (error.code === 'ENOENT') {
116
+ if ((error as NodeError).code === 'ENOENT') {
136
117
  return 0
137
118
  }
138
119
  throw error
@@ -142,40 +123,35 @@ async function countJsonLines(filePath) {
142
123
  /**
143
124
  * Get last N entries from JSONL file
144
125
  * Efficient for large files (reads whole file but only returns last N)
145
- *
146
- * @param {string} filePath - Path to JSONL file
147
- * @param {number} n - Number of entries to return
148
- * @returns {Promise<Array<Object>>} - Last N entries
149
126
  */
150
- async function getLastJsonLines(filePath, n) {
151
- const entries = await readJsonLines(filePath)
127
+ export async function getLastJsonLines<T = Record<string, unknown>>(
128
+ filePath: string,
129
+ n: number
130
+ ): Promise<T[]> {
131
+ const entries = await readJsonLines<T>(filePath)
152
132
  return entries.slice(-n)
153
133
  }
154
134
 
155
135
  /**
156
136
  * Get first N entries from JSONL file
157
- *
158
- * @param {string} filePath - Path to JSONL file
159
- * @param {number} n - Number of entries to return
160
- * @returns {Promise<Array<Object>>} - First N entries
161
137
  */
162
- async function getFirstJsonLines(filePath, n) {
163
- const entries = await readJsonLines(filePath)
138
+ export async function getFirstJsonLines<T = Record<string, unknown>>(
139
+ filePath: string,
140
+ n: number
141
+ ): Promise<T[]> {
142
+ const entries = await readJsonLines<T>(filePath)
164
143
  return entries.slice(0, n)
165
144
  }
166
145
 
167
146
  /**
168
147
  * Merge multiple JSONL files into one array
169
148
  * Useful for reading multiple sessions
170
- *
171
- * @param {Array<string>} filePaths - Array of JSONL file paths
172
- * @returns {Promise<Array<Object>>} - Merged entries from all files
173
149
  */
174
- async function mergeJsonLines(filePaths) {
175
- const allEntries = []
150
+ export async function mergeJsonLines<T = Record<string, unknown>>(filePaths: string[]): Promise<T[]> {
151
+ const allEntries: T[] = []
176
152
 
177
153
  for (const filePath of filePaths) {
178
- const entries = await readJsonLines(filePath)
154
+ const entries = await readJsonLines<T>(filePath)
179
155
  allEntries.push(...entries)
180
156
  }
181
157
 
@@ -184,11 +160,8 @@ async function mergeJsonLines(filePaths) {
184
160
 
185
161
  /**
186
162
  * Check if JSONL file is empty or doesn't exist
187
- *
188
- * @param {string} filePath - Path to JSONL file
189
- * @returns {Promise<boolean>} - True if empty or non-existent
190
163
  */
191
- async function isJsonLinesEmpty(filePath) {
164
+ export async function isJsonLinesEmpty(filePath: string): Promise<boolean> {
192
165
  const count = await countJsonLines(filePath)
193
166
  return count === 0
194
167
  }
@@ -196,12 +169,11 @@ async function isJsonLinesEmpty(filePath) {
196
169
  /**
197
170
  * Read JSONL file with streaming (memory-efficient for large files)
198
171
  * Only reads last N lines instead of loading entire file
199
- *
200
- * @param {string} filePath - Path to JSONL file
201
- * @param {number} maxLines - Maximum lines to read (default: 1000)
202
- * @returns {Promise<Array<Object>>} - Array of parsed objects (last N lines)
203
172
  */
204
- async function readJsonLinesStreaming(filePath, maxLines = 1000) {
173
+ export async function readJsonLinesStreaming<T = Record<string, unknown>>(
174
+ filePath: string,
175
+ maxLines = 1000
176
+ ): Promise<T[]> {
205
177
  try {
206
178
  const fileStream = fsSync.createReadStream(filePath)
207
179
  const rl = readline.createInterface({
@@ -209,12 +181,12 @@ async function readJsonLinesStreaming(filePath, maxLines = 1000) {
209
181
  crlfDelay: Infinity,
210
182
  })
211
183
 
212
- const lines = []
184
+ const lines: T[] = []
213
185
 
214
186
  for await (const line of rl) {
215
187
  if (line.trim()) {
216
188
  try {
217
- lines.push(JSON.parse(line))
189
+ lines.push(JSON.parse(line) as T)
218
190
  } catch {
219
191
  // Skip malformed lines
220
192
  }
@@ -228,7 +200,7 @@ async function readJsonLinesStreaming(filePath, maxLines = 1000) {
228
200
 
229
201
  return lines
230
202
  } catch (error) {
231
- if (error.code === 'ENOENT') {
203
+ if ((error as NodeError).code === 'ENOENT') {
232
204
  return []
233
205
  }
234
206
  throw error
@@ -237,16 +209,13 @@ async function readJsonLinesStreaming(filePath, maxLines = 1000) {
237
209
 
238
210
  /**
239
211
  * Get file size in MB
240
- *
241
- * @param {string} filePath - Path to file
242
- * @returns {Promise<number>} - File size in MB
243
212
  */
244
- async function getFileSizeMB(filePath) {
213
+ export async function getFileSizeMB(filePath: string): Promise<number> {
245
214
  try {
246
215
  const stats = await fs.stat(filePath)
247
216
  return stats.size / (1024 * 1024)
248
217
  } catch (error) {
249
- if (error.code === 'ENOENT') {
218
+ if ((error as NodeError).code === 'ENOENT') {
250
219
  return 0
251
220
  }
252
221
  throw error
@@ -256,12 +225,8 @@ async function getFileSizeMB(filePath) {
256
225
  /**
257
226
  * Rotate JSONL file if it exceeds size limit
258
227
  * Moves large file to archive with timestamp
259
- *
260
- * @param {string} filePath - Path to JSONL file
261
- * @param {number} maxSizeMB - Maximum size in MB before rotation (default: 10)
262
- * @returns {Promise<boolean>} - True if rotated, false if not needed
263
228
  */
264
- async function rotateJsonLinesIfNeeded(filePath, maxSizeMB = 10) {
229
+ export async function rotateJsonLinesIfNeeded(filePath: string, maxSizeMB = 10): Promise<boolean> {
265
230
  const sizeMB = await getFileSizeMB(filePath)
266
231
 
267
232
  if (sizeMB < maxSizeMB) {
@@ -286,13 +251,12 @@ async function rotateJsonLinesIfNeeded(filePath, maxSizeMB = 10) {
286
251
  /**
287
252
  * Append JSON line with automatic rotation
288
253
  * Checks file size before append and rotates if needed
289
- *
290
- * @param {string} filePath - Path to JSONL file
291
- * @param {Object} object - Object to append
292
- * @param {number} maxSizeMB - Maximum size before rotation (default: 10)
293
- * @returns {Promise<void>}
294
254
  */
295
- async function appendJsonLineWithRotation(filePath, object, maxSizeMB = 10) {
255
+ export async function appendJsonLineWithRotation(
256
+ filePath: string,
257
+ object: unknown,
258
+ maxSizeMB = 10
259
+ ): Promise<void> {
296
260
  // Rotate if needed (before appending)
297
261
  await rotateJsonLinesIfNeeded(filePath, maxSizeMB)
298
262
 
@@ -303,12 +267,11 @@ async function appendJsonLineWithRotation(filePath, object, maxSizeMB = 10) {
303
267
  /**
304
268
  * Warn if file is large before reading
305
269
  * Returns size and whether it's considered large
306
- *
307
- * @param {string} filePath - Path to file
308
- * @param {number} warnThresholdMB - Threshold in MB to warn (default: 50)
309
- * @returns {Promise<{sizeMB: number, isLarge: boolean}>}
310
270
  */
311
- async function checkFileSizeWarning(filePath, warnThresholdMB = 50) {
271
+ export async function checkFileSizeWarning(
272
+ filePath: string,
273
+ warnThresholdMB = 50
274
+ ): Promise<FileSizeWarning> {
312
275
  const sizeMB = await getFileSizeMB(filePath)
313
276
  const isLarge = sizeMB > warnThresholdMB
314
277
 
@@ -321,7 +284,8 @@ async function checkFileSizeWarning(filePath, warnThresholdMB = 50) {
321
284
  return { sizeMB, isLarge }
322
285
  }
323
286
 
324
- module.exports = {
287
+ // Default export for CommonJS compatibility
288
+ export default {
325
289
  parseJsonLines,
326
290
  stringifyJsonLines,
327
291
  readJsonLines,
@@ -334,10 +298,10 @@ module.exports = {
334
298
  getFirstJsonLines,
335
299
  mergeJsonLines,
336
300
  isJsonLinesEmpty,
337
- // NEW: Memory-efficient functions
338
301
  readJsonLinesStreaming,
339
302
  getFileSizeMB,
340
303
  rotateJsonLinesIfNeeded,
341
304
  appendJsonLineWithRotation,
342
- checkFileSizeWarning,
305
+ checkFileSizeWarning
343
306
  }
307
+
@@ -9,14 +9,26 @@
9
9
  * PRJCT_DEBUG=debug (everything)
10
10
  *
11
11
  * Usage:
12
- * const log = require('./utils/logger')
12
+ * import log from './utils/logger'
13
13
  * log.debug('Processing files...')
14
14
  * log.info('Task started')
15
15
  * log.warn('Cache miss')
16
16
  * log.error('Failed to load', error.message)
17
17
  */
18
18
 
19
- const LEVELS = { error: 0, warn: 1, info: 2, debug: 3 }
19
+ type LogLevel = 'error' | 'warn' | 'info' | 'debug'
20
+ type LogFunction = (...args: unknown[]) => void
21
+
22
+ interface Logger {
23
+ error: LogFunction
24
+ warn: LogFunction
25
+ info: LogFunction
26
+ debug: LogFunction
27
+ isEnabled: () => boolean
28
+ level: () => LogLevel | 'disabled'
29
+ }
30
+
31
+ const LEVELS: Record<LogLevel, number> = { error: 0, warn: 1, info: 2, debug: 3 }
20
32
 
21
33
  const debugEnv = process.env.PRJCT_DEBUG || process.env.DEBUG || ''
22
34
  const isEnabled = debugEnv === '1' || debugEnv === 'true' || debugEnv.includes('prjct')
@@ -26,39 +38,39 @@ let currentLevel = -1 // disabled by default
26
38
  if (isEnabled) {
27
39
  if (debugEnv === '1' || debugEnv === 'true' || debugEnv === 'prjct') {
28
40
  currentLevel = LEVELS.debug // all logs
29
- } else if (LEVELS[debugEnv] !== undefined) {
30
- currentLevel = LEVELS[debugEnv]
41
+ } else if (LEVELS[debugEnv as LogLevel] !== undefined) {
42
+ currentLevel = LEVELS[debugEnv as LogLevel]
31
43
  } else {
32
44
  currentLevel = LEVELS.debug
33
45
  }
34
46
  }
35
47
 
36
48
  // No-op function for disabled logs
37
- const noop = () => {}
49
+ const noop: LogFunction = () => {}
38
50
 
39
51
  // Create logger methods
40
- const logger = {
52
+ const logger: Logger = {
41
53
  error: currentLevel >= LEVELS.error
42
- ? (...args) => console.error('[prjct:error]', ...args)
54
+ ? (...args: unknown[]) => console.error('[prjct:error]', ...args)
43
55
  : noop,
44
56
 
45
57
  warn: currentLevel >= LEVELS.warn
46
- ? (...args) => console.warn('[prjct:warn]', ...args)
58
+ ? (...args: unknown[]) => console.warn('[prjct:warn]', ...args)
47
59
  : noop,
48
60
 
49
61
  info: currentLevel >= LEVELS.info
50
- ? (...args) => console.log('[prjct:info]', ...args)
62
+ ? (...args: unknown[]) => console.log('[prjct:info]', ...args)
51
63
  : noop,
52
64
 
53
65
  debug: currentLevel >= LEVELS.debug
54
- ? (...args) => console.log('[prjct:debug]', ...args)
66
+ ? (...args: unknown[]) => console.log('[prjct:debug]', ...args)
55
67
  : noop,
56
68
 
57
69
  // Check if logging is enabled (useful for expensive log prep)
58
70
  isEnabled: () => currentLevel >= 0,
59
71
 
60
72
  // Get current level name
61
- level: () => Object.keys(LEVELS).find(k => LEVELS[k] === currentLevel) || 'disabled'
73
+ level: () => (Object.keys(LEVELS) as LogLevel[]).find(k => LEVELS[k] === currentLevel) || 'disabled'
62
74
  }
63
75
 
64
- module.exports = logger
76
+ export default logger
@@ -1,22 +1,34 @@
1
1
  /**
2
2
  * Minimal Output System for prjct-cli
3
3
  * Spinner while working → Single line result
4
- * With prjct branding
4
+ * With prjct branding
5
5
  */
6
6
 
7
- const chalk = require('chalk')
8
- const branding = require('./branding')
7
+ import chalk from 'chalk'
8
+ import branding from './branding'
9
9
 
10
10
  const FRAMES = branding.spinner.frames
11
11
  const SPEED = branding.spinner.speed
12
12
 
13
- let interval = null
13
+ let interval: ReturnType<typeof setInterval> | null = null
14
14
  let frame = 0
15
15
 
16
- const truncate = (s, max = 50) => (s && s.length > max ? s.slice(0, max - 1) + '…' : s || '')
17
- const clear = () => process.stdout.write('\r' + ' '.repeat(80) + '\r')
16
+ const truncate = (s: string | undefined | null, max = 50): string =>
17
+ s && s.length > max ? s.slice(0, max - 1) + '' : s || ''
18
18
 
19
- const out = {
19
+ const clear = (): boolean => process.stdout.write('\r' + ' '.repeat(80) + '\r')
20
+
21
+ interface Output {
22
+ start(): Output
23
+ end(): Output
24
+ spin(msg: string): Output
25
+ done(msg: string): Output
26
+ fail(msg: string): Output
27
+ warn(msg: string): Output
28
+ stop(): Output
29
+ }
30
+
31
+ const out: Output = {
20
32
  // Branding: Show header at start
21
33
  start() {
22
34
  console.log(branding.cli.header())
@@ -29,8 +41,8 @@ const out = {
29
41
  return this
30
42
  },
31
43
 
32
- // Branded spinner: prjct message...
33
- spin(msg) {
44
+ // Branded spinner: prjct message...
45
+ spin(msg: string) {
34
46
  this.stop()
35
47
  interval = setInterval(() => {
36
48
  process.stdout.write(`\r${branding.cli.spin(frame++, truncate(msg, 45))}`)
@@ -38,19 +50,19 @@ const out = {
38
50
  return this
39
51
  },
40
52
 
41
- done(msg) {
53
+ done(msg: string) {
42
54
  this.stop()
43
55
  console.log(`${chalk.green('✓')} ${truncate(msg, 65)}`)
44
56
  return this
45
57
  },
46
58
 
47
- fail(msg) {
59
+ fail(msg: string) {
48
60
  this.stop()
49
61
  console.log(`${chalk.red('✗')} ${truncate(msg, 65)}`)
50
62
  return this
51
63
  },
52
64
 
53
- warn(msg) {
65
+ warn(msg: string) {
54
66
  this.stop()
55
67
  console.log(`${chalk.yellow('⚠')} ${truncate(msg, 65)}`)
56
68
  return this
@@ -66,4 +78,4 @@ const out = {
66
78
  }
67
79
  }
68
80
 
69
- module.exports = out
81
+ export default out
@@ -3,16 +3,25 @@
3
3
  * Detects ONLY what exists - no assumptions, no hallucinations
4
4
  */
5
5
 
6
- const fs = require('fs').promises
7
- const path = require('path')
6
+ import fs from 'fs/promises'
7
+ import path from 'path'
8
+
9
+ interface Capabilities {
10
+ design: boolean
11
+ test: boolean
12
+ docs: boolean
13
+ }
14
+
15
+ interface PackageJson {
16
+ dependencies?: Record<string, string>
17
+ devDependencies?: Record<string, string>
18
+ }
8
19
 
9
20
  class ProjectCapabilities {
10
21
  /**
11
22
  * Detect project capabilities
12
- * @param {string} projectPath - Project root path
13
- * @returns {Promise<Object>} Capabilities object
14
23
  */
15
- async detect(projectPath = process.cwd()) {
24
+ async detect(projectPath = process.cwd()): Promise<Capabilities> {
16
25
  return {
17
26
  design: await this.hasDesign(projectPath),
18
27
  test: await this.hasTest(projectPath),
@@ -23,7 +32,7 @@ class ProjectCapabilities {
23
32
  /**
24
33
  * Check if project has design system
25
34
  */
26
- async hasDesign(projectPath) {
35
+ async hasDesign(projectPath: string): Promise<boolean> {
27
36
  return (
28
37
  (await this.hasFolder(projectPath, 'design')) ||
29
38
  (await this.hasFolder(projectPath, 'designs')) ||
@@ -37,7 +46,7 @@ class ProjectCapabilities {
37
46
  /**
38
47
  * Check if project has test framework
39
48
  */
40
- async hasTest(projectPath) {
49
+ async hasTest(projectPath: string): Promise<boolean> {
41
50
  return (
42
51
  (await this.hasDep(projectPath, 'jest')) ||
43
52
  (await this.hasDep(projectPath, 'vitest')) ||
@@ -52,7 +61,7 @@ class ProjectCapabilities {
52
61
  /**
53
62
  * Check if project has documentation system
54
63
  */
55
- async hasDocs(projectPath) {
64
+ async hasDocs(projectPath: string): Promise<boolean> {
56
65
  return (
57
66
  (await this.hasFolder(projectPath, 'docs')) ||
58
67
  (await this.hasFolder(projectPath, 'documentation')) ||
@@ -65,7 +74,7 @@ class ProjectCapabilities {
65
74
  /**
66
75
  * Check if folder exists
67
76
  */
68
- async hasFolder(projectPath, folderName) {
77
+ async hasFolder(projectPath: string, folderName: string): Promise<boolean> {
69
78
  try {
70
79
  const folderPath = path.join(projectPath, folderName)
71
80
  const stat = await fs.stat(folderPath)
@@ -78,7 +87,7 @@ class ProjectCapabilities {
78
87
  /**
79
88
  * Check if file exists
80
89
  */
81
- async hasFile(projectPath, fileName) {
90
+ async hasFile(projectPath: string, fileName: string): Promise<boolean> {
82
91
  try {
83
92
  const filePath = path.join(projectPath, fileName)
84
93
  await fs.access(filePath)
@@ -91,7 +100,7 @@ class ProjectCapabilities {
91
100
  /**
92
101
  * Check if files matching pattern exist
93
102
  */
94
- async hasFiles(projectPath, pattern) {
103
+ async hasFiles(projectPath: string, pattern: string): Promise<boolean> {
95
104
  try {
96
105
  // Convert glob pattern to regex
97
106
  const regex = this.globToRegex(pattern)
@@ -99,9 +108,12 @@ class ProjectCapabilities {
99
108
 
100
109
  // Filter by pattern and ignore node_modules, dist, build
101
110
  return files.some((file) => {
111
+ const fileName = typeof file === 'string' ? file : file.toString()
102
112
  const skip =
103
- file.includes('node_modules/') || file.includes('dist/') || file.includes('build/')
104
- return !skip && regex.test(file)
113
+ fileName.includes('node_modules/') ||
114
+ fileName.includes('dist/') ||
115
+ fileName.includes('build/')
116
+ return !skip && regex.test(fileName)
105
117
  })
106
118
  } catch {
107
119
  return false
@@ -111,24 +123,24 @@ class ProjectCapabilities {
111
123
  /**
112
124
  * Convert simple glob pattern to regex
113
125
  */
114
- globToRegex(pattern) {
126
+ globToRegex(pattern: string): RegExp {
115
127
  // Convert **/*.{test,spec}.{js,ts,jsx,tsx} to regex
116
128
  const escaped = pattern
117
129
  .replace(/\./g, '\\.')
118
130
  .replace(/\*\*/g, '.*')
119
131
  .replace(/\*/g, '[^/]*')
120
- .replace(/\{([^}]+)\}/g, (_, group) => `(${group.split(',').join('|')})`)
132
+ .replace(/\{([^}]+)\}/g, (_, group: string) => `(${group.split(',').join('|')})`)
121
133
  return new RegExp(escaped)
122
134
  }
123
135
 
124
136
  /**
125
137
  * Check if dependency exists in package.json
126
138
  */
127
- async hasDep(projectPath, depName) {
139
+ async hasDep(projectPath: string, depName: string): Promise<boolean> {
128
140
  try {
129
141
  const pkgPath = path.join(projectPath, 'package.json')
130
142
  const content = await fs.readFile(pkgPath, 'utf8')
131
- const pkg = JSON.parse(content)
143
+ const pkg: PackageJson = JSON.parse(content)
132
144
 
133
145
  return !!(
134
146
  (pkg.dependencies && pkg.dependencies[depName]) ||
@@ -140,4 +152,5 @@ class ProjectCapabilities {
140
152
  }
141
153
  }
142
154
 
143
- module.exports = new ProjectCapabilities()
155
+ const projectCapabilities = new ProjectCapabilities()
156
+ export default projectCapabilities