prjct-cli 0.11.5 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +81 -25
  3. package/bin/dev.js +1 -1
  4. package/bin/generate-views.js +209 -0
  5. package/bin/migrate-to-json.js +742 -0
  6. package/bin/prjct +5 -5
  7. package/bin/serve.js +226 -50
  8. package/core/__tests__/agentic/{memory-system.test.js → memory-system.test.ts} +12 -23
  9. package/core/__tests__/agentic/{plan-mode.test.js → plan-mode.test.ts} +26 -24
  10. package/core/__tests__/agentic/{prompt-builder.test.js → prompt-builder.test.ts} +3 -8
  11. package/core/__tests__/utils/{date-helper.test.js → date-helper.test.ts} +19 -30
  12. package/core/__tests__/utils/{output.test.js → output.test.ts} +12 -24
  13. package/core/agentic/agent-router.ts +137 -0
  14. package/core/agentic/chain-of-thought.ts +228 -0
  15. package/core/agentic/command-executor/command-executor.ts +384 -0
  16. package/core/agentic/command-executor/index.ts +16 -0
  17. package/core/agentic/command-executor/status-signal.ts +38 -0
  18. package/core/agentic/command-executor/types.ts +79 -0
  19. package/core/agentic/command-executor.ts +8 -0
  20. package/core/agentic/{context-builder.js → context-builder.ts} +92 -81
  21. package/core/agentic/context-filter.ts +365 -0
  22. package/core/agentic/ground-truth/index.ts +76 -0
  23. package/core/agentic/ground-truth/types.ts +33 -0
  24. package/core/agentic/ground-truth/utils.ts +48 -0
  25. package/core/agentic/ground-truth/verifiers/analyze.ts +54 -0
  26. package/core/agentic/ground-truth/verifiers/done.ts +75 -0
  27. package/core/agentic/ground-truth/verifiers/feature.ts +70 -0
  28. package/core/agentic/ground-truth/verifiers/index.ts +37 -0
  29. package/core/agentic/ground-truth/verifiers/init.ts +52 -0
  30. package/core/agentic/ground-truth/verifiers/now.ts +57 -0
  31. package/core/agentic/ground-truth/verifiers/ship.ts +85 -0
  32. package/core/agentic/ground-truth/verifiers/spec.ts +45 -0
  33. package/core/agentic/ground-truth/verifiers/sync.ts +47 -0
  34. package/core/agentic/ground-truth/verifiers.ts +6 -0
  35. package/core/agentic/ground-truth.ts +8 -0
  36. package/core/agentic/loop-detector/error-analysis.ts +97 -0
  37. package/core/agentic/loop-detector/hallucination.ts +71 -0
  38. package/core/agentic/loop-detector/index.ts +41 -0
  39. package/core/agentic/loop-detector/loop-detector.ts +222 -0
  40. package/core/agentic/loop-detector/types.ts +66 -0
  41. package/core/agentic/loop-detector.ts +8 -0
  42. package/core/agentic/memory-system/history.ts +53 -0
  43. package/core/agentic/memory-system/index.ts +192 -0
  44. package/core/agentic/memory-system/patterns.ts +156 -0
  45. package/core/agentic/memory-system/semantic-memories.ts +277 -0
  46. package/core/agentic/memory-system/session.ts +21 -0
  47. package/core/agentic/memory-system/types.ts +159 -0
  48. package/core/agentic/memory-system.ts +8 -0
  49. package/core/agentic/parallel-tools.ts +165 -0
  50. package/core/agentic/plan-mode/approval.ts +57 -0
  51. package/core/agentic/plan-mode/constants.ts +44 -0
  52. package/core/agentic/plan-mode/index.ts +28 -0
  53. package/core/agentic/plan-mode/plan-mode.ts +406 -0
  54. package/core/agentic/plan-mode/types.ts +193 -0
  55. package/core/agentic/plan-mode.ts +8 -0
  56. package/core/agentic/prompt-builder.ts +566 -0
  57. package/core/agentic/response-templates.ts +164 -0
  58. package/core/agentic/semantic-compression.ts +273 -0
  59. package/core/agentic/services.ts +206 -0
  60. package/core/agentic/smart-context.ts +476 -0
  61. package/core/agentic/{template-loader.js → template-loader.ts} +27 -16
  62. package/core/agentic/think-blocks.ts +202 -0
  63. package/core/agentic/tool-registry.ts +119 -0
  64. package/core/agentic/validation-rules.ts +313 -0
  65. package/core/agents/index.ts +28 -0
  66. package/core/agents/performance.ts +444 -0
  67. package/core/agents/types.ts +126 -0
  68. package/core/bus/{index.js → index.ts} +57 -61
  69. package/core/command-registry/categories.ts +23 -0
  70. package/core/command-registry/commands.ts +15 -0
  71. package/core/command-registry/core-commands.ts +319 -0
  72. package/core/command-registry/index.ts +158 -0
  73. package/core/command-registry/optional-commands.ts +119 -0
  74. package/core/command-registry/setup-commands.ts +53 -0
  75. package/core/command-registry/types.ts +59 -0
  76. package/core/command-registry.ts +9 -0
  77. package/core/commands/analysis.ts +298 -0
  78. package/core/commands/analytics.ts +288 -0
  79. package/core/commands/base.ts +273 -0
  80. package/core/commands/index.ts +211 -0
  81. package/core/commands/maintenance.ts +226 -0
  82. package/core/commands/planning.ts +311 -0
  83. package/core/commands/setup.ts +309 -0
  84. package/core/commands/shipping.ts +188 -0
  85. package/core/commands/types.ts +183 -0
  86. package/core/commands/workflow.ts +226 -0
  87. package/core/commands.ts +11 -0
  88. package/core/constants/formats.ts +187 -0
  89. package/core/constants/index.ts +7 -0
  90. package/core/{context-sync.js → context-sync.ts} +59 -26
  91. package/core/data/agents-manager.ts +76 -0
  92. package/core/data/analysis-manager.ts +83 -0
  93. package/core/data/base-manager.ts +156 -0
  94. package/core/data/ideas-manager.ts +81 -0
  95. package/core/data/index.ts +32 -0
  96. package/core/data/outcomes-manager.ts +96 -0
  97. package/core/data/project-manager.ts +75 -0
  98. package/core/data/roadmap-manager.ts +118 -0
  99. package/core/data/shipped-manager.ts +65 -0
  100. package/core/data/state-manager.ts +214 -0
  101. package/core/domain/{agent-generator.js → agent-generator.ts} +77 -57
  102. package/core/domain/{agent-loader.js → agent-loader.ts} +65 -56
  103. package/core/domain/{agent-matcher.js → agent-matcher.ts} +51 -24
  104. package/core/domain/{agent-validator.js → agent-validator.ts} +70 -37
  105. package/core/domain/{analyzer.js → analyzer.ts} +91 -85
  106. package/core/domain/{architect-session.js → architect-session.ts} +49 -34
  107. package/core/domain/{architecture-generator.js → architecture-generator.ts} +25 -13
  108. package/core/domain/{context-estimator.js → context-estimator.ts} +57 -36
  109. package/core/domain/{product-standards.js → product-standards.ts} +40 -26
  110. package/core/domain/{smart-cache.js → smart-cache.ts} +39 -30
  111. package/core/domain/{snapshot-manager.js → snapshot-manager.ts} +103 -100
  112. package/core/domain/{task-analyzer.js → task-analyzer.ts} +82 -43
  113. package/core/domain/task-stack/index.ts +19 -0
  114. package/core/domain/task-stack/parser.ts +86 -0
  115. package/core/domain/task-stack/storage.ts +123 -0
  116. package/core/domain/task-stack/task-stack.ts +340 -0
  117. package/core/domain/task-stack/types.ts +51 -0
  118. package/core/domain/task-stack.ts +8 -0
  119. package/core/{index.js → index.ts} +61 -18
  120. package/core/infrastructure/{agent-detector.js → agent-detector.ts} +55 -19
  121. package/core/infrastructure/agents/{claude-agent.js → claude-agent.ts} +61 -21
  122. package/core/infrastructure/{author-detector.js → author-detector.ts} +42 -49
  123. package/core/infrastructure/{capability-installer.js → capability-installer.ts} +51 -27
  124. package/core/infrastructure/{command-installer.js → command-installer/command-installer.ts} +43 -144
  125. package/core/infrastructure/command-installer/global-config.ts +106 -0
  126. package/core/infrastructure/command-installer/index.ts +25 -0
  127. package/core/infrastructure/command-installer/types.ts +41 -0
  128. package/core/infrastructure/command-installer.ts +8 -0
  129. package/core/infrastructure/{config-manager.js → config-manager.ts} +60 -80
  130. package/core/infrastructure/{editors-config.js → editors-config.ts} +33 -31
  131. package/core/infrastructure/legacy-installer-detector/cleanup.ts +216 -0
  132. package/core/infrastructure/legacy-installer-detector/detection.ts +95 -0
  133. package/core/infrastructure/legacy-installer-detector/index.ts +171 -0
  134. package/core/infrastructure/legacy-installer-detector/migration.ts +87 -0
  135. package/core/infrastructure/legacy-installer-detector/types.ts +42 -0
  136. package/core/infrastructure/legacy-installer-detector.ts +7 -0
  137. package/core/infrastructure/migrator/file-operations.ts +125 -0
  138. package/core/infrastructure/migrator/index.ts +288 -0
  139. package/core/infrastructure/migrator/project-scanner.ts +89 -0
  140. package/core/infrastructure/migrator/reports.ts +117 -0
  141. package/core/infrastructure/migrator/types.ts +124 -0
  142. package/core/infrastructure/migrator/validation.ts +94 -0
  143. package/core/infrastructure/migrator/version-migration.ts +117 -0
  144. package/core/infrastructure/migrator.ts +10 -0
  145. package/core/infrastructure/{path-manager.js → path-manager.ts} +51 -91
  146. package/core/infrastructure/session-manager/index.ts +23 -0
  147. package/core/infrastructure/session-manager/migration.ts +88 -0
  148. package/core/infrastructure/session-manager/session-manager.ts +307 -0
  149. package/core/infrastructure/session-manager/types.ts +45 -0
  150. package/core/infrastructure/session-manager.ts +8 -0
  151. package/core/infrastructure/{setup.js → setup.ts} +29 -21
  152. package/core/infrastructure/{update-checker.js → update-checker.ts} +40 -18
  153. package/core/outcomes/analyzer.ts +333 -0
  154. package/core/outcomes/index.ts +34 -0
  155. package/core/outcomes/recorder.ts +194 -0
  156. package/core/outcomes/types.ts +145 -0
  157. package/core/plugin/{hooks.js → hooks.ts} +56 -58
  158. package/core/plugin/{index.js → index.ts} +19 -8
  159. package/core/plugin/{loader.js → loader.ts} +87 -69
  160. package/core/plugin/{registry.js → registry.ts} +49 -45
  161. package/core/plugins/{webhook.js → webhook.ts} +43 -27
  162. package/core/schemas/agents.ts +27 -0
  163. package/core/schemas/analysis.ts +41 -0
  164. package/core/schemas/ideas.ts +83 -0
  165. package/core/schemas/index.ts +73 -0
  166. package/core/schemas/outcomes.ts +22 -0
  167. package/core/schemas/project.ts +26 -0
  168. package/core/schemas/roadmap.ts +90 -0
  169. package/core/schemas/shipped.ts +82 -0
  170. package/core/schemas/state.ts +107 -0
  171. package/core/session/index.ts +17 -0
  172. package/core/session/{metrics.js → metrics.ts} +64 -46
  173. package/core/session/{index.js → session-manager.ts} +51 -117
  174. package/core/session/types.ts +29 -0
  175. package/core/session/utils.ts +57 -0
  176. package/core/state/index.ts +25 -0
  177. package/core/state/manager.ts +376 -0
  178. package/core/state/types.ts +185 -0
  179. package/core/tsconfig.json +22 -0
  180. package/core/types/index.ts +506 -0
  181. package/core/utils/{animations.js → animations.ts} +74 -28
  182. package/core/utils/{branding.js → branding.ts} +29 -4
  183. package/core/utils/{date-helper.js → date-helper.ts} +31 -74
  184. package/core/utils/file-helper.ts +262 -0
  185. package/core/utils/{jsonl-helper.js → jsonl-helper.ts} +71 -107
  186. package/core/utils/{logger.js → logger.ts} +24 -12
  187. package/core/utils/{output.js → output.ts} +25 -13
  188. package/core/utils/{project-capabilities.js → project-capabilities.ts} +31 -18
  189. package/core/utils/{session-helper.js → session-helper.ts} +79 -66
  190. package/core/utils/{version.js → version.ts} +23 -31
  191. package/core/view-generator.ts +536 -0
  192. package/package.json +23 -17
  193. package/packages/shared/.turbo/turbo-build.log +14 -0
  194. package/packages/shared/dist/index.d.ts +8 -613
  195. package/packages/shared/dist/index.d.ts.map +1 -0
  196. package/packages/shared/dist/index.js +4110 -118
  197. package/packages/shared/dist/schemas.d.ts +408 -0
  198. package/packages/shared/dist/schemas.d.ts.map +1 -0
  199. package/packages/shared/dist/types.d.ts +144 -0
  200. package/packages/shared/dist/types.d.ts.map +1 -0
  201. package/packages/shared/dist/unified.d.ts +139 -0
  202. package/packages/shared/dist/unified.d.ts.map +1 -0
  203. package/packages/shared/dist/utils.d.ts +60 -0
  204. package/packages/shared/dist/utils.d.ts.map +1 -0
  205. package/packages/shared/package.json +4 -4
  206. package/packages/shared/src/index.ts +1 -0
  207. package/packages/shared/src/unified.ts +174 -0
  208. package/packages/web/app/api/claude/sessions/route.ts +1 -1
  209. package/packages/web/app/api/claude/status/route.ts +1 -1
  210. package/packages/web/app/api/migrate/route.ts +46 -0
  211. package/packages/web/app/api/projects/[id]/route.ts +1 -1
  212. package/packages/web/app/api/projects/[id]/stats/route.ts +30 -2
  213. package/packages/web/app/api/projects/[id]/status/route.ts +1 -1
  214. package/packages/web/app/api/projects/route.ts +1 -1
  215. package/packages/web/app/api/settings/route.ts +97 -0
  216. package/packages/web/app/api/v2/projects/[id]/unified/route.ts +57 -0
  217. package/packages/web/app/globals.css +38 -0
  218. package/packages/web/app/layout.tsx +10 -2
  219. package/packages/web/app/page.tsx +9 -224
  220. package/packages/web/app/project/[id]/page.tsx +191 -63
  221. package/packages/web/app/project/[id]/stats/loading.tsx +43 -0
  222. package/packages/web/app/project/[id]/stats/page.tsx +204 -163
  223. package/packages/web/app/settings/page.tsx +222 -2
  224. package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +2 -0
  225. package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +50 -0
  226. package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +8 -0
  227. package/packages/web/components/ActivityTimeline/hooks/index.ts +2 -0
  228. package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +9 -0
  229. package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +23 -0
  230. package/packages/web/components/ActivityTimeline/index.ts +2 -0
  231. package/packages/web/components/AgentsCard/AgentsCard.tsx +63 -0
  232. package/packages/web/components/AgentsCard/AgentsCard.types.ts +13 -0
  233. package/packages/web/components/AgentsCard/index.ts +2 -0
  234. package/packages/web/components/AppSidebar/AppSidebar.tsx +190 -0
  235. package/packages/web/components/AppSidebar/index.ts +1 -0
  236. package/packages/web/components/BackLink/BackLink.tsx +18 -0
  237. package/packages/web/components/BackLink/BackLink.types.ts +5 -0
  238. package/packages/web/components/BackLink/index.ts +2 -0
  239. package/packages/web/components/BentoCard/BentoCard.constants.ts +16 -0
  240. package/packages/web/components/BentoCard/BentoCard.tsx +47 -0
  241. package/packages/web/components/BentoCard/BentoCard.types.ts +15 -0
  242. package/packages/web/components/BentoCard/index.ts +2 -0
  243. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +9 -0
  244. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +18 -0
  245. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +5 -0
  246. package/packages/web/components/BentoCardSkeleton/index.ts +2 -0
  247. package/packages/web/components/{stats → BentoGrid}/BentoGrid.tsx +4 -8
  248. package/packages/web/components/BentoGrid/BentoGrid.types.ts +4 -0
  249. package/packages/web/components/BentoGrid/index.ts +2 -0
  250. package/packages/web/components/CommandButton/index.ts +1 -0
  251. package/packages/web/components/ConnectionStatus/index.ts +1 -0
  252. package/packages/web/components/DashboardContent/DashboardContent.tsx +254 -0
  253. package/packages/web/components/DashboardContent/index.ts +1 -0
  254. package/packages/web/components/DateGroup/DateGroup.tsx +18 -0
  255. package/packages/web/components/DateGroup/DateGroup.types.ts +6 -0
  256. package/packages/web/components/DateGroup/DateGroup.utils.ts +11 -0
  257. package/packages/web/components/DateGroup/index.ts +2 -0
  258. package/packages/web/components/{stats → EmptyState}/EmptyState.tsx +1 -10
  259. package/packages/web/components/EmptyState/EmptyState.types.ts +10 -0
  260. package/packages/web/components/EmptyState/index.ts +2 -0
  261. package/packages/web/components/EventRow/EventRow.constants.ts +10 -0
  262. package/packages/web/components/EventRow/EventRow.tsx +49 -0
  263. package/packages/web/components/EventRow/EventRow.types.ts +7 -0
  264. package/packages/web/components/EventRow/EventRow.utils.ts +49 -0
  265. package/packages/web/components/EventRow/index.ts +2 -0
  266. package/packages/web/components/ExpandButton/ExpandButton.tsx +18 -0
  267. package/packages/web/components/ExpandButton/ExpandButton.types.ts +6 -0
  268. package/packages/web/components/ExpandButton/index.ts +2 -0
  269. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +14 -0
  270. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +5 -0
  271. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +13 -0
  272. package/packages/web/components/HealthGradientBackground/index.ts +2 -0
  273. package/packages/web/components/HeroSection/HeroSection.tsx +55 -0
  274. package/packages/web/components/HeroSection/HeroSection.types.ts +14 -0
  275. package/packages/web/components/HeroSection/HeroSection.utils.ts +7 -0
  276. package/packages/web/components/HeroSection/hooks/index.ts +2 -0
  277. package/packages/web/components/HeroSection/hooks/useCountUp.ts +45 -0
  278. package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +18 -0
  279. package/packages/web/components/HeroSection/index.ts +2 -0
  280. package/packages/web/components/{stats → IdeasCard}/IdeasCard.tsx +3 -14
  281. package/packages/web/components/IdeasCard/IdeasCard.types.ts +9 -0
  282. package/packages/web/components/IdeasCard/index.ts +2 -0
  283. package/packages/web/components/InsightMessage/InsightMessage.tsx +9 -0
  284. package/packages/web/components/InsightMessage/InsightMessage.types.ts +3 -0
  285. package/packages/web/components/InsightMessage/index.ts +2 -0
  286. package/packages/web/components/Logo/index.ts +1 -0
  287. package/packages/web/components/MarkdownContent/index.ts +1 -0
  288. package/packages/web/components/NowCard/NowCard.tsx +93 -0
  289. package/packages/web/components/NowCard/NowCard.types.ts +15 -0
  290. package/packages/web/components/NowCard/index.ts +2 -0
  291. package/packages/web/components/ProgressRing/ProgressRing.constants.ts +20 -0
  292. package/packages/web/components/{stats → ProgressRing}/ProgressRing.tsx +4 -27
  293. package/packages/web/components/ProgressRing/ProgressRing.types.ts +11 -0
  294. package/packages/web/components/ProgressRing/index.ts +2 -0
  295. package/packages/web/components/ProjectAvatar/index.ts +1 -0
  296. package/packages/web/components/Providers/index.ts +1 -0
  297. package/packages/web/components/QueueCard/QueueCard.tsx +72 -0
  298. package/packages/web/components/QueueCard/QueueCard.types.ts +11 -0
  299. package/packages/web/components/QueueCard/QueueCard.utils.ts +12 -0
  300. package/packages/web/components/QueueCard/index.ts +2 -0
  301. package/packages/web/components/{stats → RoadmapCard}/RoadmapCard.tsx +3 -23
  302. package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +15 -0
  303. package/packages/web/components/RoadmapCard/index.ts +2 -0
  304. package/packages/web/components/{stats → ShipsCard}/ShipsCard.tsx +4 -22
  305. package/packages/web/components/ShipsCard/ShipsCard.types.ts +12 -0
  306. package/packages/web/components/ShipsCard/ShipsCard.utils.ts +4 -0
  307. package/packages/web/components/ShipsCard/index.ts +2 -0
  308. package/packages/web/components/{stats → SparklineChart}/SparklineChart.tsx +1 -7
  309. package/packages/web/components/SparklineChart/SparklineChart.types.ts +6 -0
  310. package/packages/web/components/SparklineChart/index.ts +2 -0
  311. package/packages/web/components/StreakCard/StreakCard.constants.ts +2 -0
  312. package/packages/web/components/{stats → StreakCard}/StreakCard.tsx +5 -11
  313. package/packages/web/components/StreakCard/StreakCard.types.ts +4 -0
  314. package/packages/web/components/StreakCard/index.ts +2 -0
  315. package/packages/web/components/TasksCounter/TasksCounter.tsx +14 -0
  316. package/packages/web/components/TasksCounter/TasksCounter.types.ts +3 -0
  317. package/packages/web/components/TasksCounter/index.ts +2 -0
  318. package/packages/web/components/TechStackBadges/index.ts +1 -0
  319. package/packages/web/components/{TerminalTab.tsx → TerminalTabs/TerminalTab.tsx} +11 -0
  320. package/packages/web/components/{TerminalTabs.tsx → TerminalTabs/TerminalTabs.tsx} +29 -28
  321. package/packages/web/components/TerminalTabs/index.ts +1 -0
  322. package/packages/web/components/VelocityBadge/VelocityBadge.tsx +27 -0
  323. package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +3 -0
  324. package/packages/web/components/VelocityBadge/index.ts +2 -0
  325. package/packages/web/components/VelocityCard/VelocityCard.tsx +71 -0
  326. package/packages/web/components/VelocityCard/VelocityCard.types.ts +7 -0
  327. package/packages/web/components/VelocityCard/index.ts +2 -0
  328. package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +13 -0
  329. package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +3 -0
  330. package/packages/web/components/WeeklySparkline/index.ts +2 -0
  331. package/packages/web/components/ui/input.tsx +21 -0
  332. package/packages/web/context/TerminalTabsContext.tsx +46 -1
  333. package/packages/web/hooks/useClaudeTerminal.ts +71 -21
  334. package/packages/web/hooks/useProjectStats.ts +55 -0
  335. package/packages/web/hooks/useProjects.ts +6 -6
  336. package/packages/web/lib/actions/projects.ts +15 -0
  337. package/packages/web/lib/json-loader.ts +630 -0
  338. package/packages/web/lib/services/index.ts +9 -0
  339. package/packages/web/lib/services/migration.server.ts +600 -0
  340. package/packages/web/lib/services/projects.server.ts +52 -0
  341. package/packages/web/lib/services/stats.server.ts +264 -0
  342. package/packages/web/lib/unified-loader.ts +396 -0
  343. package/packages/web/package.json +10 -7
  344. package/packages/web/server.ts +58 -8
  345. package/templates/commands/done.md +76 -32
  346. package/templates/commands/feature.md +121 -47
  347. package/templates/commands/idea.md +81 -8
  348. package/templates/commands/now.md +41 -17
  349. package/templates/commands/ship.md +64 -25
  350. package/templates/commands/sync.md +28 -3
  351. package/core/agentic/agent-router.js +0 -140
  352. package/core/agentic/chain-of-thought.js +0 -578
  353. package/core/agentic/command-executor.js +0 -417
  354. package/core/agentic/context-filter.js +0 -354
  355. package/core/agentic/ground-truth.js +0 -591
  356. package/core/agentic/loop-detector.js +0 -406
  357. package/core/agentic/memory-system.js +0 -845
  358. package/core/agentic/parallel-tools.js +0 -366
  359. package/core/agentic/plan-mode.js +0 -572
  360. package/core/agentic/prompt-builder.js +0 -352
  361. package/core/agentic/response-templates.js +0 -290
  362. package/core/agentic/semantic-compression.js +0 -517
  363. package/core/agentic/think-blocks.js +0 -657
  364. package/core/agentic/tool-registry.js +0 -184
  365. package/core/agentic/validation-rules.js +0 -380
  366. package/core/command-registry.js +0 -698
  367. package/core/commands.js +0 -2237
  368. package/core/domain/task-stack.js +0 -497
  369. package/core/infrastructure/legacy-installer-detector.js +0 -546
  370. package/core/infrastructure/migrator.js +0 -796
  371. package/core/infrastructure/session-manager.js +0 -390
  372. package/core/utils/file-helper.js +0 -329
  373. package/packages/web/app/api/projects/[id]/delete/route.ts +0 -21
  374. package/packages/web/app/api/stats/route.ts +0 -38
  375. package/packages/web/components/AppSidebar.tsx +0 -113
  376. package/packages/web/components/stats/ActivityTimeline.tsx +0 -201
  377. package/packages/web/components/stats/AgentsCard.tsx +0 -56
  378. package/packages/web/components/stats/BentoCard.tsx +0 -88
  379. package/packages/web/components/stats/HeroSection.tsx +0 -172
  380. package/packages/web/components/stats/NowCard.tsx +0 -71
  381. package/packages/web/components/stats/QueueCard.tsx +0 -58
  382. package/packages/web/components/stats/VelocityCard.tsx +0 -60
  383. package/packages/web/components/stats/index.ts +0 -17
  384. package/packages/web/hooks/useStats.ts +0 -28
  385. /package/packages/web/components/{CommandButton.tsx → CommandButton/CommandButton.tsx} +0 -0
  386. /package/packages/web/components/{ConnectionStatus.tsx → ConnectionStatus/ConnectionStatus.tsx} +0 -0
  387. /package/packages/web/components/{Logo.tsx → Logo/Logo.tsx} +0 -0
  388. /package/packages/web/components/{MarkdownContent.tsx → MarkdownContent/MarkdownContent.tsx} +0 -0
  389. /package/packages/web/components/{ProjectAvatar.tsx → ProjectAvatar/ProjectAvatar.tsx} +0 -0
  390. /package/packages/web/components/{providers.tsx → Providers/Providers.tsx} +0 -0
  391. /package/packages/web/components/{TechStackBadges.tsx → TechStackBadges/TechStackBadges.tsx} +0 -0
@@ -1,21 +1,31 @@
1
1
  /**
2
2
  * SmartCache - Intelligent Persistent Cache for Agents
3
- *
3
+ *
4
4
  * Cache with specific keys: {projectId}-{domain}-{techStack}
5
5
  * Persists to disk for cross-session caching
6
6
  * Invalidates only when stack changes
7
- *
7
+ *
8
8
  * @version 1.0.0
9
9
  */
10
10
 
11
- const fs = require('fs').promises
12
- const path = require('path')
13
- const os = require('os')
14
- const crypto = require('crypto')
15
- const log = require('../utils/logger')
11
+ import fs from 'fs/promises'
12
+ import path from 'path'
13
+ import os from 'os'
14
+ import crypto from 'crypto'
15
+ import log from '../utils/logger'
16
+
17
+ interface CacheStats {
18
+ size: number
19
+ keys: string[]
20
+ }
16
21
 
17
22
  class SmartCache {
18
- constructor(projectId = null) {
23
+ projectId: string | null
24
+ memoryCache: Map<string, unknown>
25
+ cacheDir: string
26
+ cacheFile: string
27
+
28
+ constructor(projectId: string | null = null) {
19
29
  this.projectId = projectId
20
30
  this.memoryCache = new Map()
21
31
  this.cacheDir = path.join(os.homedir(), '.prjct-cli', 'cache')
@@ -27,11 +37,11 @@ class SmartCache {
27
37
  /**
28
38
  * Initialize cache - load from disk
29
39
  */
30
- async initialize() {
40
+ async initialize(): Promise<void> {
31
41
  try {
32
42
  await fs.mkdir(this.cacheDir, { recursive: true })
33
43
  await this.loadFromDisk()
34
- } catch (error) {
44
+ } catch {
35
45
  // Cache file doesn't exist yet - that's ok
36
46
  this.memoryCache = new Map()
37
47
  }
@@ -41,7 +51,7 @@ class SmartCache {
41
51
  * Generate cache key
42
52
  * Format: {projectId}-{domain}-{techStackHash}
43
53
  */
44
- generateKey(projectId, domain, techStack = {}) {
54
+ generateKey(projectId: string | null, domain: string, techStack: Record<string, unknown> = {}): string {
45
55
  const techString = JSON.stringify(techStack)
46
56
  const techHash = crypto.createHash('md5').update(techString).digest('hex').substring(0, 8)
47
57
  return `${projectId || 'global'}-${domain}-${techHash}`
@@ -50,26 +60,26 @@ class SmartCache {
50
60
  /**
51
61
  * Get from cache
52
62
  */
53
- async get(key) {
63
+ async get<T = unknown>(key: string): Promise<T | null> {
54
64
  // Check memory first
55
65
  if (this.memoryCache.has(key)) {
56
- return this.memoryCache.get(key)
66
+ return this.memoryCache.get(key) as T
57
67
  }
58
68
 
59
69
  // Load from disk if not in memory
60
70
  await this.loadFromDisk()
61
- return this.memoryCache.get(key) || null
71
+ return (this.memoryCache.get(key) as T) || null
62
72
  }
63
73
 
64
74
  /**
65
75
  * Set in cache
66
76
  */
67
- async set(key, value) {
77
+ async set(key: string, value: unknown): Promise<void> {
68
78
  // Set in memory
69
79
  this.memoryCache.set(key, value)
70
80
 
71
81
  // Persist to disk (async, don't wait)
72
- this.persistToDisk().catch(err => {
82
+ this.persistToDisk().catch((err) => {
73
83
  log.error('Cache persist error:', err.message)
74
84
  })
75
85
  }
@@ -77,7 +87,7 @@ class SmartCache {
77
87
  /**
78
88
  * Check if key exists
79
89
  */
80
- async has(key) {
90
+ async has(key: string): Promise<boolean> {
81
91
  if (this.memoryCache.has(key)) {
82
92
  return true
83
93
  }
@@ -89,7 +99,7 @@ class SmartCache {
89
99
  /**
90
100
  * Clear cache
91
101
  */
92
- async clear() {
102
+ async clear(): Promise<void> {
93
103
  this.memoryCache.clear()
94
104
  try {
95
105
  await fs.unlink(this.cacheFile)
@@ -101,26 +111,26 @@ class SmartCache {
101
111
  /**
102
112
  * Invalidate cache for a project (when stack changes)
103
113
  */
104
- async invalidateProject(projectId) {
105
- const keysToDelete = []
114
+ async invalidateProject(projectId: string): Promise<void> {
115
+ const keysToDelete: string[] = []
106
116
  for (const key of this.memoryCache.keys()) {
107
117
  if (key.startsWith(`${projectId}-`)) {
108
118
  keysToDelete.push(key)
109
119
  }
110
120
  }
111
121
 
112
- keysToDelete.forEach(key => this.memoryCache.delete(key))
122
+ keysToDelete.forEach((key) => this.memoryCache.delete(key))
113
123
  await this.persistToDisk()
114
124
  }
115
125
 
116
126
  /**
117
127
  * Load cache from disk
118
128
  */
119
- async loadFromDisk() {
129
+ async loadFromDisk(): Promise<void> {
120
130
  try {
121
131
  const content = await fs.readFile(this.cacheFile, 'utf-8')
122
- const data = JSON.parse(content)
123
-
132
+ const data = JSON.parse(content) as Record<string, unknown>
133
+
124
134
  // Restore to memory cache
125
135
  for (const [key, value] of Object.entries(data)) {
126
136
  this.memoryCache.set(key, value)
@@ -134,11 +144,11 @@ class SmartCache {
134
144
  /**
135
145
  * Persist cache to disk
136
146
  */
137
- async persistToDisk() {
147
+ async persistToDisk(): Promise<void> {
138
148
  try {
139
149
  const data = Object.fromEntries(this.memoryCache)
140
150
  await fs.writeFile(this.cacheFile, JSON.stringify(data, null, 2), 'utf-8')
141
- } catch (error) {
151
+ } catch {
142
152
  // Fail silently - cache is best effort
143
153
  }
144
154
  }
@@ -146,13 +156,12 @@ class SmartCache {
146
156
  /**
147
157
  * Get cache statistics
148
158
  */
149
- getStats() {
159
+ getStats(): CacheStats {
150
160
  return {
151
161
  size: this.memoryCache.size,
152
- keys: Array.from(this.memoryCache.keys())
162
+ keys: Array.from(this.memoryCache.keys()),
153
163
  }
154
164
  }
155
165
  }
156
166
 
157
- module.exports = SmartCache
158
-
167
+ export default SmartCache
@@ -9,28 +9,57 @@
9
9
  * @version 1.0.0
10
10
  */
11
11
 
12
- const fs = require('fs').promises
13
- const path = require('path')
14
- const { exec } = require('child_process')
15
- const { promisify } = require('util')
16
- const pathManager = require('../infrastructure/path-manager')
17
- const configManager = require('../infrastructure/config-manager')
18
- const { emit } = require('../bus')
12
+ import fs from 'fs/promises'
13
+ import path from 'path'
14
+ import { exec } from 'child_process'
15
+ import { promisify } from 'util'
16
+ import pathManager from '../infrastructure/path-manager'
17
+ import configManager from '../infrastructure/config-manager'
18
+ import { emit } from '../bus'
19
19
 
20
20
  const execAsync = promisify(exec)
21
21
 
22
+ interface SnapshotInfo {
23
+ hash: string | null
24
+ message: string
25
+ timestamp: string
26
+ files: string[]
27
+ }
28
+
29
+ interface SnapshotListItem {
30
+ hash: string
31
+ short: string
32
+ message: string
33
+ date: string
34
+ }
35
+
36
+ interface RestoreResult {
37
+ hash: string
38
+ files: string[]
39
+ timestamp: string
40
+ }
41
+
42
+ interface RedoStackEntry {
43
+ hash: string
44
+ message: string
45
+ timestamp: string
46
+ files: string[]
47
+ }
48
+
22
49
  class SnapshotManager {
23
- constructor(projectPath) {
50
+ projectPath: string
51
+ projectId: string | null = null
52
+ snapshotDir: string | null = null
53
+ initialized: boolean = false
54
+
55
+ constructor(projectPath: string) {
24
56
  this.projectPath = projectPath
25
- this.projectId = null
26
- this.snapshotDir = null
27
- this.initialized = false
28
57
  }
29
58
 
30
59
  /**
31
60
  * Initialize snapshot system for project
32
61
  */
33
- async initialize() {
62
+ async initialize(): Promise<void> {
34
63
  this.projectId = await configManager.getProjectId(this.projectPath)
35
64
  if (!this.projectId) {
36
65
  throw new Error('No prjct project found. Run /p:init first.')
@@ -57,54 +86,48 @@ class SnapshotManager {
57
86
  /**
58
87
  * Initialize internal Git repository
59
88
  */
60
- async initGitRepo() {
61
- const gitDir = path.join(this.snapshotDir, '.git')
62
-
89
+ async initGitRepo(): Promise<void> {
63
90
  // Create bare-ish repo structure
64
91
  await execAsync(`git init "${this.snapshotDir}"`, { cwd: this.projectPath })
65
92
 
66
93
  // Configure for snapshot use
67
- await execAsync(`git config user.email "prjct@local"`, { cwd: this.snapshotDir })
68
- await execAsync(`git config user.name "prjct-snapshots"`, { cwd: this.snapshotDir })
94
+ await execAsync(`git config user.email "prjct@local"`, { cwd: this.snapshotDir! })
95
+ await execAsync(`git config user.name "prjct-snapshots"`, { cwd: this.snapshotDir! })
69
96
 
70
97
  // Create initial empty commit
71
- await execAsync(`git commit --allow-empty -m "init: snapshot system"`, { cwd: this.snapshotDir })
98
+ await execAsync(`git commit --allow-empty -m "init: snapshot system"`, { cwd: this.snapshotDir! })
72
99
  }
73
100
 
74
101
  /**
75
102
  * Create a snapshot of current project state
76
- *
77
- * @param {string} message - Snapshot description
78
- * @param {string[]} files - Specific files to track (optional, defaults to all changed)
79
- * @returns {Promise<Object>} Snapshot info {hash, message, timestamp, files}
80
103
  */
81
- async create(message, files = null) {
104
+ async create(message: string, files: string[] | null = null): Promise<SnapshotInfo> {
82
105
  if (!this.initialized) await this.initialize()
83
106
 
84
107
  const timestamp = new Date().toISOString()
85
108
 
86
109
  // Copy changed files to snapshot directory
87
- const changedFiles = files || await this.getChangedFiles()
110
+ const changedFiles = files || (await this.getChangedFiles())
88
111
 
89
112
  if (changedFiles.length === 0) {
90
113
  return {
91
114
  hash: null,
92
115
  message: 'No changes to snapshot',
93
116
  timestamp,
94
- files: []
117
+ files: [],
95
118
  }
96
119
  }
97
120
 
98
121
  // Copy files to snapshot dir maintaining structure
99
122
  for (const file of changedFiles) {
100
123
  const srcPath = path.join(this.projectPath, file)
101
- const destPath = path.join(this.snapshotDir, file)
124
+ const destPath = path.join(this.snapshotDir!, file)
102
125
 
103
126
  try {
104
127
  const content = await fs.readFile(srcPath, 'utf-8')
105
128
  await fs.mkdir(path.dirname(destPath), { recursive: true })
106
129
  await fs.writeFile(destPath, content)
107
- } catch (err) {
130
+ } catch {
108
131
  // File might be deleted, mark for removal
109
132
  try {
110
133
  await fs.unlink(destPath)
@@ -113,13 +136,13 @@ class SnapshotManager {
113
136
  }
114
137
 
115
138
  // Stage and commit in snapshot repo
116
- await execAsync(`git add -A`, { cwd: this.snapshotDir })
139
+ await execAsync(`git add -A`, { cwd: this.snapshotDir! })
117
140
 
118
141
  const commitMsg = `${message}\n\nFiles: ${changedFiles.length}\nTimestamp: ${timestamp}`
119
- await execAsync(`git commit -m "${commitMsg.replace(/"/g, '\\"')}"`, { cwd: this.snapshotDir })
142
+ await execAsync(`git commit -m "${commitMsg.replace(/"/g, '\\"')}"`, { cwd: this.snapshotDir! })
120
143
 
121
144
  // Get commit hash
122
- const { stdout } = await execAsync(`git rev-parse HEAD`, { cwd: this.snapshotDir })
145
+ const { stdout } = await execAsync(`git rev-parse HEAD`, { cwd: this.snapshotDir! })
123
146
  const hash = stdout.trim()
124
147
 
125
148
  // Log to manifest
@@ -127,7 +150,7 @@ class SnapshotManager {
127
150
  hash,
128
151
  message,
129
152
  timestamp,
130
- files: changedFiles
153
+ files: changedFiles,
131
154
  })
132
155
 
133
156
  // Emit event for plugins
@@ -136,7 +159,7 @@ class SnapshotManager {
136
159
  message,
137
160
  timestamp,
138
161
  filesCount: changedFiles.length,
139
- projectId: this.projectId
162
+ projectId: this.projectId,
140
163
  })
141
164
 
142
165
  return { hash, message, timestamp, files: changedFiles }
@@ -145,18 +168,15 @@ class SnapshotManager {
145
168
  /**
146
169
  * Get list of changed files in project
147
170
  */
148
- async getChangedFiles() {
171
+ async getChangedFiles(): Promise<string[]> {
149
172
  try {
150
- const { stdout } = await execAsync(
151
- `git status --porcelain`,
152
- { cwd: this.projectPath }
153
- )
173
+ const { stdout } = await execAsync(`git status --porcelain`, { cwd: this.projectPath })
154
174
 
155
175
  return stdout
156
176
  .split('\n')
157
177
  .filter(Boolean)
158
- .map(line => line.slice(3).trim())
159
- .filter(file => !file.startsWith('.prjct/'))
178
+ .map((line) => line.slice(3).trim())
179
+ .filter((file) => !file.startsWith('.prjct/'))
160
180
  } catch {
161
181
  return []
162
182
  }
@@ -164,30 +184,27 @@ class SnapshotManager {
164
184
 
165
185
  /**
166
186
  * List all snapshots
167
- *
168
- * @param {number} limit - Max snapshots to return
169
- * @returns {Promise<Array>} List of snapshots
170
187
  */
171
- async list(limit = 10) {
188
+ async list(limit: number = 10): Promise<SnapshotListItem[]> {
172
189
  if (!this.initialized) await this.initialize()
173
190
 
174
191
  try {
175
192
  const { stdout } = await execAsync(
176
193
  `git log --pretty=format:'{"hash":"%H","short":"%h","message":"%s","date":"%ai"}' -n ${limit}`,
177
- { cwd: this.snapshotDir }
194
+ { cwd: this.snapshotDir! }
178
195
  )
179
196
 
180
197
  return stdout
181
198
  .split('\n')
182
199
  .filter(Boolean)
183
- .map(line => {
200
+ .map((line) => {
184
201
  try {
185
- return JSON.parse(line)
202
+ return JSON.parse(line) as SnapshotListItem
186
203
  } catch {
187
204
  return null
188
205
  }
189
206
  })
190
- .filter(Boolean)
207
+ .filter((item): item is SnapshotListItem => item !== null)
191
208
  } catch {
192
209
  return []
193
210
  }
@@ -195,34 +212,30 @@ class SnapshotManager {
195
212
 
196
213
  /**
197
214
  * Restore project to a specific snapshot
198
- *
199
- * @param {string} hash - Commit hash to restore
200
- * @returns {Promise<Object>} Restore result
201
215
  */
202
- async restore(hash) {
216
+ async restore(hash: string): Promise<RestoreResult> {
203
217
  if (!this.initialized) await this.initialize()
204
218
 
205
219
  // Get files changed in that commit
206
- const { stdout: filesOutput } = await execAsync(
207
- `git diff-tree --no-commit-id --name-only -r ${hash}`,
208
- { cwd: this.snapshotDir }
209
- )
220
+ const { stdout: filesOutput } = await execAsync(`git diff-tree --no-commit-id --name-only -r ${hash}`, {
221
+ cwd: this.snapshotDir!,
222
+ })
210
223
 
211
224
  const files = filesOutput.split('\n').filter(Boolean)
212
225
 
213
226
  // Checkout files from that snapshot
214
- await execAsync(`git checkout ${hash} -- .`, { cwd: this.snapshotDir })
227
+ await execAsync(`git checkout ${hash} -- .`, { cwd: this.snapshotDir! })
215
228
 
216
229
  // Copy files back to project
217
230
  for (const file of files) {
218
- const srcPath = path.join(this.snapshotDir, file)
231
+ const srcPath = path.join(this.snapshotDir!, file)
219
232
  const destPath = path.join(this.projectPath, file)
220
233
 
221
234
  try {
222
235
  const content = await fs.readFile(srcPath, 'utf-8')
223
236
  await fs.mkdir(path.dirname(destPath), { recursive: true })
224
237
  await fs.writeFile(destPath, content)
225
- } catch (err) {
238
+ } catch {
226
239
  // File doesn't exist in snapshot, might need to delete from project
227
240
  try {
228
241
  await fs.unlink(destPath)
@@ -240,7 +253,7 @@ class SnapshotManager {
240
253
  hash,
241
254
  filesCount: files.length,
242
255
  timestamp,
243
- projectId: this.projectId
256
+ projectId: this.projectId,
244
257
  })
245
258
 
246
259
  return { hash, files, timestamp }
@@ -248,18 +261,12 @@ class SnapshotManager {
248
261
 
249
262
  /**
250
263
  * Get diff between current state and a snapshot
251
- *
252
- * @param {string} hash - Snapshot hash to compare
253
- * @returns {Promise<string>} Diff output
254
264
  */
255
- async diff(hash) {
265
+ async diff(hash: string): Promise<string> {
256
266
  if (!this.initialized) await this.initialize()
257
267
 
258
268
  try {
259
- const { stdout } = await execAsync(
260
- `git diff ${hash} --stat`,
261
- { cwd: this.snapshotDir }
262
- )
269
+ const { stdout } = await execAsync(`git diff ${hash} --stat`, { cwd: this.snapshotDir! })
263
270
  return stdout
264
271
  } catch {
265
272
  return ''
@@ -269,14 +276,11 @@ class SnapshotManager {
269
276
  /**
270
277
  * Get the most recent snapshot hash
271
278
  */
272
- async getLatestHash() {
279
+ async getLatestHash(): Promise<string | null> {
273
280
  if (!this.initialized) await this.initialize()
274
281
 
275
282
  try {
276
- const { stdout } = await execAsync(
277
- `git rev-parse HEAD`,
278
- { cwd: this.snapshotDir }
279
- )
283
+ const { stdout } = await execAsync(`git rev-parse HEAD`, { cwd: this.snapshotDir! })
280
284
  return stdout.trim()
281
285
  } catch {
282
286
  return null
@@ -286,14 +290,11 @@ class SnapshotManager {
286
290
  /**
287
291
  * Get the hash before the current one (for undo)
288
292
  */
289
- async getPreviousHash() {
293
+ async getPreviousHash(): Promise<string | null> {
290
294
  if (!this.initialized) await this.initialize()
291
295
 
292
296
  try {
293
- const { stdout } = await execAsync(
294
- `git rev-parse HEAD~1`,
295
- { cwd: this.snapshotDir }
296
- )
297
+ const { stdout } = await execAsync(`git rev-parse HEAD~1`, { cwd: this.snapshotDir! })
297
298
  return stdout.trim()
298
299
  } catch {
299
300
  return null
@@ -303,12 +304,13 @@ class SnapshotManager {
303
304
  /**
304
305
  * Log snapshot to manifest
305
306
  */
306
- async logSnapshot(snapshot) {
307
- const manifestPath = path.join(this.snapshotDir, 'manifest.jsonl')
308
- const entry = JSON.stringify({
309
- type: 'snapshot',
310
- ...snapshot
311
- }) + '\n'
307
+ async logSnapshot(snapshot: SnapshotInfo): Promise<void> {
308
+ const manifestPath = path.join(this.snapshotDir!, 'manifest.jsonl')
309
+ const entry =
310
+ JSON.stringify({
311
+ type: 'snapshot',
312
+ ...snapshot,
313
+ }) + '\n'
312
314
 
313
315
  await fs.appendFile(manifestPath, entry)
314
316
  }
@@ -316,14 +318,15 @@ class SnapshotManager {
316
318
  /**
317
319
  * Log restoration to manifest
318
320
  */
319
- async logRestore(hash, files) {
320
- const manifestPath = path.join(this.snapshotDir, 'manifest.jsonl')
321
- const entry = JSON.stringify({
322
- type: 'restore',
323
- hash,
324
- files,
325
- timestamp: new Date().toISOString()
326
- }) + '\n'
321
+ async logRestore(hash: string, files: string[]): Promise<void> {
322
+ const manifestPath = path.join(this.snapshotDir!, 'manifest.jsonl')
323
+ const entry =
324
+ JSON.stringify({
325
+ type: 'restore',
326
+ hash,
327
+ files,
328
+ timestamp: new Date().toISOString(),
329
+ }) + '\n'
327
330
 
328
331
  await fs.appendFile(manifestPath, entry)
329
332
  }
@@ -332,8 +335,8 @@ class SnapshotManager {
332
335
  * Get redo stack (snapshots after current position)
333
336
  * This tracks undone snapshots that can be redone
334
337
  */
335
- async getRedoStack() {
336
- const stackPath = path.join(this.snapshotDir, 'redo-stack.json')
338
+ async getRedoStack(): Promise<RedoStackEntry[]> {
339
+ const stackPath = path.join(this.snapshotDir!, 'redo-stack.json')
337
340
  try {
338
341
  const content = await fs.readFile(stackPath, 'utf-8')
339
342
  return JSON.parse(content)
@@ -345,20 +348,20 @@ class SnapshotManager {
345
348
  /**
346
349
  * Push to redo stack (when undoing)
347
350
  */
348
- async pushToRedoStack(snapshot) {
351
+ async pushToRedoStack(snapshot: RedoStackEntry): Promise<void> {
349
352
  const stack = await this.getRedoStack()
350
353
  stack.push(snapshot)
351
- const stackPath = path.join(this.snapshotDir, 'redo-stack.json')
354
+ const stackPath = path.join(this.snapshotDir!, 'redo-stack.json')
352
355
  await fs.writeFile(stackPath, JSON.stringify(stack, null, 2))
353
356
  }
354
357
 
355
358
  /**
356
359
  * Pop from redo stack (when redoing)
357
360
  */
358
- async popFromRedoStack() {
361
+ async popFromRedoStack(): Promise<RedoStackEntry | undefined> {
359
362
  const stack = await this.getRedoStack()
360
363
  const snapshot = stack.pop()
361
- const stackPath = path.join(this.snapshotDir, 'redo-stack.json')
364
+ const stackPath = path.join(this.snapshotDir!, 'redo-stack.json')
362
365
  await fs.writeFile(stackPath, JSON.stringify(stack, null, 2))
363
366
  return snapshot
364
367
  }
@@ -366,10 +369,10 @@ class SnapshotManager {
366
369
  /**
367
370
  * Clear redo stack (when creating new snapshot after undo)
368
371
  */
369
- async clearRedoStack() {
370
- const stackPath = path.join(this.snapshotDir, 'redo-stack.json')
372
+ async clearRedoStack(): Promise<void> {
373
+ const stackPath = path.join(this.snapshotDir!, 'redo-stack.json')
371
374
  await fs.writeFile(stackPath, '[]')
372
375
  }
373
376
  }
374
377
 
375
- module.exports = SnapshotManager
378
+ export default SnapshotManager