prjct-cli 0.11.4 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (385) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +81 -25
  3. package/bin/dev.js +1 -1
  4. package/bin/generate-views.js +209 -0
  5. package/bin/migrate-to-json.js +742 -0
  6. package/bin/prjct +5 -5
  7. package/bin/serve.js +246 -54
  8. package/core/__tests__/agentic/{memory-system.test.js → memory-system.test.ts} +12 -23
  9. package/core/__tests__/agentic/{plan-mode.test.js → plan-mode.test.ts} +26 -24
  10. package/core/__tests__/agentic/{prompt-builder.test.js → prompt-builder.test.ts} +3 -8
  11. package/core/__tests__/utils/date-helper.test.ts +405 -0
  12. package/core/__tests__/utils/{output.test.js → output.test.ts} +12 -24
  13. package/core/agentic/agent-router.ts +137 -0
  14. package/core/agentic/chain-of-thought.ts +228 -0
  15. package/core/agentic/command-executor/command-executor.ts +384 -0
  16. package/core/agentic/command-executor/index.ts +16 -0
  17. package/core/agentic/command-executor/status-signal.ts +38 -0
  18. package/core/agentic/command-executor/types.ts +79 -0
  19. package/core/agentic/command-executor.ts +8 -0
  20. package/core/agentic/{context-builder.js → context-builder.ts} +99 -89
  21. package/core/agentic/context-filter.ts +365 -0
  22. package/core/agentic/ground-truth/index.ts +76 -0
  23. package/core/agentic/ground-truth/types.ts +33 -0
  24. package/core/agentic/ground-truth/utils.ts +48 -0
  25. package/core/agentic/ground-truth/verifiers/analyze.ts +54 -0
  26. package/core/agentic/ground-truth/verifiers/done.ts +75 -0
  27. package/core/agentic/ground-truth/verifiers/feature.ts +70 -0
  28. package/core/agentic/ground-truth/verifiers/index.ts +37 -0
  29. package/core/agentic/ground-truth/verifiers/init.ts +52 -0
  30. package/core/agentic/ground-truth/verifiers/now.ts +57 -0
  31. package/core/agentic/ground-truth/verifiers/ship.ts +85 -0
  32. package/core/agentic/ground-truth/verifiers/spec.ts +45 -0
  33. package/core/agentic/ground-truth/verifiers/sync.ts +47 -0
  34. package/core/agentic/ground-truth/verifiers.ts +6 -0
  35. package/core/agentic/ground-truth.ts +8 -0
  36. package/core/agentic/loop-detector/error-analysis.ts +97 -0
  37. package/core/agentic/loop-detector/hallucination.ts +71 -0
  38. package/core/agentic/loop-detector/index.ts +41 -0
  39. package/core/agentic/loop-detector/loop-detector.ts +222 -0
  40. package/core/agentic/loop-detector/types.ts +66 -0
  41. package/core/agentic/loop-detector.ts +8 -0
  42. package/core/agentic/memory-system/history.ts +53 -0
  43. package/core/agentic/memory-system/index.ts +192 -0
  44. package/core/agentic/memory-system/patterns.ts +156 -0
  45. package/core/agentic/memory-system/semantic-memories.ts +277 -0
  46. package/core/agentic/memory-system/session.ts +21 -0
  47. package/core/agentic/memory-system/types.ts +159 -0
  48. package/core/agentic/memory-system.ts +8 -0
  49. package/core/agentic/parallel-tools.ts +165 -0
  50. package/core/agentic/plan-mode/approval.ts +57 -0
  51. package/core/agentic/plan-mode/constants.ts +44 -0
  52. package/core/agentic/plan-mode/index.ts +28 -0
  53. package/core/agentic/plan-mode/plan-mode.ts +406 -0
  54. package/core/agentic/plan-mode/types.ts +193 -0
  55. package/core/agentic/plan-mode.ts +8 -0
  56. package/core/agentic/prompt-builder.ts +566 -0
  57. package/core/agentic/response-templates.ts +164 -0
  58. package/core/agentic/semantic-compression.ts +273 -0
  59. package/core/agentic/services.ts +206 -0
  60. package/core/agentic/smart-context.ts +476 -0
  61. package/core/agentic/{template-loader.js → template-loader.ts} +35 -18
  62. package/core/agentic/think-blocks.ts +202 -0
  63. package/core/agentic/tool-registry.ts +119 -0
  64. package/core/agentic/validation-rules.ts +313 -0
  65. package/core/agents/index.ts +28 -0
  66. package/core/agents/performance.ts +444 -0
  67. package/core/agents/types.ts +126 -0
  68. package/core/bus/{index.js → index.ts} +57 -61
  69. package/core/command-registry/categories.ts +23 -0
  70. package/core/command-registry/commands.ts +15 -0
  71. package/core/command-registry/core-commands.ts +319 -0
  72. package/core/command-registry/index.ts +158 -0
  73. package/core/command-registry/optional-commands.ts +119 -0
  74. package/core/command-registry/setup-commands.ts +53 -0
  75. package/core/command-registry/types.ts +59 -0
  76. package/core/command-registry.ts +9 -0
  77. package/core/commands/analysis.ts +298 -0
  78. package/core/commands/analytics.ts +288 -0
  79. package/core/commands/base.ts +273 -0
  80. package/core/commands/index.ts +211 -0
  81. package/core/commands/maintenance.ts +226 -0
  82. package/core/commands/planning.ts +311 -0
  83. package/core/commands/setup.ts +309 -0
  84. package/core/commands/shipping.ts +188 -0
  85. package/core/commands/types.ts +183 -0
  86. package/core/commands/workflow.ts +226 -0
  87. package/core/commands.ts +11 -0
  88. package/core/constants/formats.ts +187 -0
  89. package/core/constants/index.ts +7 -0
  90. package/core/{context-sync.js → context-sync.ts} +59 -26
  91. package/core/data/agents-manager.ts +76 -0
  92. package/core/data/analysis-manager.ts +83 -0
  93. package/core/data/base-manager.ts +156 -0
  94. package/core/data/ideas-manager.ts +81 -0
  95. package/core/data/index.ts +32 -0
  96. package/core/data/outcomes-manager.ts +96 -0
  97. package/core/data/project-manager.ts +75 -0
  98. package/core/data/roadmap-manager.ts +118 -0
  99. package/core/data/shipped-manager.ts +65 -0
  100. package/core/data/state-manager.ts +214 -0
  101. package/core/domain/{agent-generator.js → agent-generator.ts} +77 -57
  102. package/core/domain/{agent-loader.js → agent-loader.ts} +65 -56
  103. package/core/domain/{agent-matcher.js → agent-matcher.ts} +51 -24
  104. package/core/domain/{agent-validator.js → agent-validator.ts} +70 -37
  105. package/core/domain/{analyzer.js → analyzer.ts} +91 -85
  106. package/core/domain/{architect-session.js → architect-session.ts} +49 -34
  107. package/core/domain/{architecture-generator.js → architecture-generator.ts} +25 -13
  108. package/core/domain/{context-estimator.js → context-estimator.ts} +57 -36
  109. package/core/domain/{product-standards.js → product-standards.ts} +40 -26
  110. package/core/domain/{smart-cache.js → smart-cache.ts} +39 -30
  111. package/core/domain/{snapshot-manager.js → snapshot-manager.ts} +103 -100
  112. package/core/domain/{task-analyzer.js → task-analyzer.ts} +82 -43
  113. package/core/domain/task-stack/index.ts +19 -0
  114. package/core/domain/task-stack/parser.ts +86 -0
  115. package/core/domain/task-stack/storage.ts +123 -0
  116. package/core/domain/task-stack/task-stack.ts +340 -0
  117. package/core/domain/task-stack/types.ts +51 -0
  118. package/core/domain/task-stack.ts +8 -0
  119. package/core/{index.js → index.ts} +61 -18
  120. package/core/infrastructure/{agent-detector.js → agent-detector.ts} +62 -23
  121. package/core/infrastructure/agents/{claude-agent.js → claude-agent.ts} +61 -21
  122. package/core/infrastructure/{author-detector.js → author-detector.ts} +42 -49
  123. package/core/infrastructure/{capability-installer.js → capability-installer.ts} +51 -27
  124. package/core/infrastructure/{command-installer.js → command-installer/command-installer.ts} +43 -144
  125. package/core/infrastructure/command-installer/global-config.ts +106 -0
  126. package/core/infrastructure/command-installer/index.ts +25 -0
  127. package/core/infrastructure/command-installer/types.ts +41 -0
  128. package/core/infrastructure/command-installer.ts +8 -0
  129. package/core/infrastructure/{config-manager.js → config-manager.ts} +60 -80
  130. package/core/infrastructure/{editors-config.js → editors-config.ts} +33 -31
  131. package/core/infrastructure/legacy-installer-detector/cleanup.ts +216 -0
  132. package/core/infrastructure/legacy-installer-detector/detection.ts +95 -0
  133. package/core/infrastructure/legacy-installer-detector/index.ts +171 -0
  134. package/core/infrastructure/legacy-installer-detector/migration.ts +87 -0
  135. package/core/infrastructure/legacy-installer-detector/types.ts +42 -0
  136. package/core/infrastructure/legacy-installer-detector.ts +7 -0
  137. package/core/infrastructure/migrator/file-operations.ts +125 -0
  138. package/core/infrastructure/migrator/index.ts +288 -0
  139. package/core/infrastructure/migrator/project-scanner.ts +89 -0
  140. package/core/infrastructure/migrator/reports.ts +117 -0
  141. package/core/infrastructure/migrator/types.ts +124 -0
  142. package/core/infrastructure/migrator/validation.ts +94 -0
  143. package/core/infrastructure/migrator/version-migration.ts +117 -0
  144. package/core/infrastructure/migrator.ts +10 -0
  145. package/core/infrastructure/{path-manager.js → path-manager.ts} +51 -91
  146. package/core/infrastructure/session-manager/index.ts +23 -0
  147. package/core/infrastructure/session-manager/migration.ts +88 -0
  148. package/core/infrastructure/session-manager/session-manager.ts +307 -0
  149. package/core/infrastructure/session-manager/types.ts +45 -0
  150. package/core/infrastructure/session-manager.ts +8 -0
  151. package/core/infrastructure/{setup.js → setup.ts} +29 -21
  152. package/core/infrastructure/{update-checker.js → update-checker.ts} +40 -18
  153. package/core/outcomes/analyzer.ts +333 -0
  154. package/core/outcomes/index.ts +34 -0
  155. package/core/outcomes/recorder.ts +194 -0
  156. package/core/outcomes/types.ts +145 -0
  157. package/core/plugin/{hooks.js → hooks.ts} +56 -58
  158. package/core/plugin/{index.js → index.ts} +19 -8
  159. package/core/plugin/{loader.js → loader.ts} +87 -69
  160. package/core/plugin/{registry.js → registry.ts} +49 -45
  161. package/core/plugins/{webhook.js → webhook.ts} +43 -27
  162. package/core/schemas/agents.ts +27 -0
  163. package/core/schemas/analysis.ts +41 -0
  164. package/core/schemas/ideas.ts +83 -0
  165. package/core/schemas/index.ts +73 -0
  166. package/core/schemas/outcomes.ts +22 -0
  167. package/core/schemas/project.ts +26 -0
  168. package/core/schemas/roadmap.ts +90 -0
  169. package/core/schemas/shipped.ts +82 -0
  170. package/core/schemas/state.ts +107 -0
  171. package/core/session/index.ts +17 -0
  172. package/core/session/{metrics.js → metrics.ts} +64 -46
  173. package/core/session/{index.js → session-manager.ts} +51 -117
  174. package/core/session/types.ts +29 -0
  175. package/core/session/utils.ts +57 -0
  176. package/core/state/index.ts +25 -0
  177. package/core/state/manager.ts +376 -0
  178. package/core/state/types.ts +185 -0
  179. package/core/tsconfig.json +22 -0
  180. package/core/types/index.ts +506 -0
  181. package/core/utils/{animations.js → animations.ts} +74 -28
  182. package/core/utils/{branding.js → branding.ts} +29 -4
  183. package/core/utils/{date-helper.js → date-helper.ts} +31 -74
  184. package/core/utils/file-helper.ts +262 -0
  185. package/core/utils/{jsonl-helper.js → jsonl-helper.ts} +71 -107
  186. package/core/utils/{logger.js → logger.ts} +24 -12
  187. package/core/utils/{output.js → output.ts} +25 -13
  188. package/core/utils/{project-capabilities.js → project-capabilities.ts} +31 -18
  189. package/core/utils/{session-helper.js → session-helper.ts} +79 -66
  190. package/core/utils/{version.js → version.ts} +23 -31
  191. package/core/view-generator.ts +536 -0
  192. package/package.json +23 -17
  193. package/packages/shared/.turbo/turbo-build.log +14 -0
  194. package/packages/shared/dist/index.d.ts +8 -613
  195. package/packages/shared/dist/index.d.ts.map +1 -0
  196. package/packages/shared/dist/index.js +4110 -118
  197. package/packages/shared/dist/schemas.d.ts +408 -0
  198. package/packages/shared/dist/schemas.d.ts.map +1 -0
  199. package/packages/shared/dist/types.d.ts +144 -0
  200. package/packages/shared/dist/types.d.ts.map +1 -0
  201. package/packages/shared/dist/unified.d.ts +139 -0
  202. package/packages/shared/dist/unified.d.ts.map +1 -0
  203. package/packages/shared/dist/utils.d.ts +60 -0
  204. package/packages/shared/dist/utils.d.ts.map +1 -0
  205. package/packages/shared/package.json +4 -4
  206. package/packages/shared/src/index.ts +1 -0
  207. package/packages/shared/src/unified.ts +174 -0
  208. package/packages/web/app/api/claude/sessions/route.ts +1 -1
  209. package/packages/web/app/api/claude/status/route.ts +1 -1
  210. package/packages/web/app/api/migrate/route.ts +46 -0
  211. package/packages/web/app/api/projects/[id]/route.ts +1 -1
  212. package/packages/web/app/api/projects/[id]/stats/route.ts +30 -2
  213. package/packages/web/app/api/projects/[id]/status/route.ts +1 -1
  214. package/packages/web/app/api/projects/route.ts +1 -1
  215. package/packages/web/app/api/settings/route.ts +97 -0
  216. package/packages/web/app/api/v2/projects/[id]/unified/route.ts +57 -0
  217. package/packages/web/app/globals.css +38 -0
  218. package/packages/web/app/layout.tsx +10 -2
  219. package/packages/web/app/page.tsx +9 -224
  220. package/packages/web/app/project/[id]/page.tsx +191 -63
  221. package/packages/web/app/project/[id]/stats/loading.tsx +43 -0
  222. package/packages/web/app/project/[id]/stats/page.tsx +203 -403
  223. package/packages/web/app/settings/page.tsx +222 -2
  224. package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +2 -0
  225. package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +50 -0
  226. package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +8 -0
  227. package/packages/web/components/ActivityTimeline/hooks/index.ts +2 -0
  228. package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +9 -0
  229. package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +23 -0
  230. package/packages/web/components/ActivityTimeline/index.ts +2 -0
  231. package/packages/web/components/AgentsCard/AgentsCard.tsx +63 -0
  232. package/packages/web/components/AgentsCard/AgentsCard.types.ts +13 -0
  233. package/packages/web/components/AgentsCard/index.ts +2 -0
  234. package/packages/web/components/AppSidebar/AppSidebar.tsx +134 -0
  235. package/packages/web/components/AppSidebar/index.ts +1 -0
  236. package/packages/web/components/BackLink/BackLink.tsx +18 -0
  237. package/packages/web/components/BackLink/BackLink.types.ts +5 -0
  238. package/packages/web/components/BackLink/index.ts +2 -0
  239. package/packages/web/components/BentoCard/BentoCard.constants.ts +16 -0
  240. package/packages/web/components/BentoCard/BentoCard.tsx +47 -0
  241. package/packages/web/components/BentoCard/BentoCard.types.ts +15 -0
  242. package/packages/web/components/BentoCard/index.ts +2 -0
  243. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +9 -0
  244. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +18 -0
  245. package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +5 -0
  246. package/packages/web/components/BentoCardSkeleton/index.ts +2 -0
  247. package/packages/web/components/BentoGrid/BentoGrid.tsx +18 -0
  248. package/packages/web/components/BentoGrid/BentoGrid.types.ts +4 -0
  249. package/packages/web/components/BentoGrid/index.ts +2 -0
  250. package/packages/web/components/CommandButton/index.ts +1 -0
  251. package/packages/web/components/ConnectionStatus/index.ts +1 -0
  252. package/packages/web/components/DashboardContent/DashboardContent.tsx +254 -0
  253. package/packages/web/components/DashboardContent/index.ts +1 -0
  254. package/packages/web/components/DateGroup/DateGroup.tsx +18 -0
  255. package/packages/web/components/DateGroup/DateGroup.types.ts +6 -0
  256. package/packages/web/components/DateGroup/DateGroup.utils.ts +11 -0
  257. package/packages/web/components/DateGroup/index.ts +2 -0
  258. package/packages/web/components/EmptyState/EmptyState.tsx +58 -0
  259. package/packages/web/components/EmptyState/EmptyState.types.ts +10 -0
  260. package/packages/web/components/EmptyState/index.ts +2 -0
  261. package/packages/web/components/EventRow/EventRow.constants.ts +10 -0
  262. package/packages/web/components/EventRow/EventRow.tsx +49 -0
  263. package/packages/web/components/EventRow/EventRow.types.ts +7 -0
  264. package/packages/web/components/EventRow/EventRow.utils.ts +49 -0
  265. package/packages/web/components/EventRow/index.ts +2 -0
  266. package/packages/web/components/ExpandButton/ExpandButton.tsx +18 -0
  267. package/packages/web/components/ExpandButton/ExpandButton.types.ts +6 -0
  268. package/packages/web/components/ExpandButton/index.ts +2 -0
  269. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +14 -0
  270. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +5 -0
  271. package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +13 -0
  272. package/packages/web/components/HealthGradientBackground/index.ts +2 -0
  273. package/packages/web/components/HeroSection/HeroSection.tsx +55 -0
  274. package/packages/web/components/HeroSection/HeroSection.types.ts +14 -0
  275. package/packages/web/components/HeroSection/HeroSection.utils.ts +7 -0
  276. package/packages/web/components/HeroSection/hooks/index.ts +2 -0
  277. package/packages/web/components/HeroSection/hooks/useCountUp.ts +45 -0
  278. package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +18 -0
  279. package/packages/web/components/HeroSection/index.ts +2 -0
  280. package/packages/web/components/IdeasCard/IdeasCard.tsx +48 -0
  281. package/packages/web/components/IdeasCard/IdeasCard.types.ts +9 -0
  282. package/packages/web/components/IdeasCard/index.ts +2 -0
  283. package/packages/web/components/InsightMessage/InsightMessage.tsx +9 -0
  284. package/packages/web/components/InsightMessage/InsightMessage.types.ts +3 -0
  285. package/packages/web/components/InsightMessage/index.ts +2 -0
  286. package/packages/web/components/Logo/index.ts +1 -0
  287. package/packages/web/components/MarkdownContent/index.ts +1 -0
  288. package/packages/web/components/NowCard/NowCard.tsx +93 -0
  289. package/packages/web/components/NowCard/NowCard.types.ts +15 -0
  290. package/packages/web/components/NowCard/index.ts +2 -0
  291. package/packages/web/components/ProgressRing/ProgressRing.constants.ts +20 -0
  292. package/packages/web/components/ProgressRing/ProgressRing.tsx +51 -0
  293. package/packages/web/components/ProgressRing/ProgressRing.types.ts +11 -0
  294. package/packages/web/components/ProgressRing/index.ts +2 -0
  295. package/packages/web/components/ProjectAvatar/index.ts +1 -0
  296. package/packages/web/components/Providers/index.ts +1 -0
  297. package/packages/web/components/QueueCard/QueueCard.tsx +72 -0
  298. package/packages/web/components/QueueCard/QueueCard.types.ts +11 -0
  299. package/packages/web/components/QueueCard/QueueCard.utils.ts +12 -0
  300. package/packages/web/components/QueueCard/index.ts +2 -0
  301. package/packages/web/components/RoadmapCard/RoadmapCard.tsx +77 -0
  302. package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +15 -0
  303. package/packages/web/components/RoadmapCard/index.ts +2 -0
  304. package/packages/web/components/ShipsCard/ShipsCard.tsx +52 -0
  305. package/packages/web/components/ShipsCard/ShipsCard.types.ts +12 -0
  306. package/packages/web/components/ShipsCard/ShipsCard.utils.ts +4 -0
  307. package/packages/web/components/ShipsCard/index.ts +2 -0
  308. package/packages/web/components/SparklineChart/SparklineChart.tsx +38 -0
  309. package/packages/web/components/SparklineChart/SparklineChart.types.ts +6 -0
  310. package/packages/web/components/SparklineChart/index.ts +2 -0
  311. package/packages/web/components/StreakCard/StreakCard.constants.ts +2 -0
  312. package/packages/web/components/StreakCard/StreakCard.tsx +53 -0
  313. package/packages/web/components/StreakCard/StreakCard.types.ts +4 -0
  314. package/packages/web/components/StreakCard/index.ts +2 -0
  315. package/packages/web/components/TasksCounter/TasksCounter.tsx +14 -0
  316. package/packages/web/components/TasksCounter/TasksCounter.types.ts +3 -0
  317. package/packages/web/components/TasksCounter/index.ts +2 -0
  318. package/packages/web/components/TechStackBadges/index.ts +1 -0
  319. package/packages/web/components/{TerminalTab.tsx → TerminalTabs/TerminalTab.tsx} +11 -0
  320. package/packages/web/components/{TerminalTabs.tsx → TerminalTabs/TerminalTabs.tsx} +29 -28
  321. package/packages/web/components/TerminalTabs/index.ts +1 -0
  322. package/packages/web/components/VelocityBadge/VelocityBadge.tsx +27 -0
  323. package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +3 -0
  324. package/packages/web/components/VelocityBadge/index.ts +2 -0
  325. package/packages/web/components/VelocityCard/VelocityCard.tsx +71 -0
  326. package/packages/web/components/VelocityCard/VelocityCard.types.ts +7 -0
  327. package/packages/web/components/VelocityCard/index.ts +2 -0
  328. package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +13 -0
  329. package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +3 -0
  330. package/packages/web/components/WeeklySparkline/index.ts +2 -0
  331. package/packages/web/components/ui/input.tsx +21 -0
  332. package/packages/web/components/ui/tooltip.tsx +2 -2
  333. package/packages/web/context/TerminalTabsContext.tsx +46 -1
  334. package/packages/web/hooks/useClaudeTerminal.ts +71 -21
  335. package/packages/web/hooks/useProjectStats.ts +55 -0
  336. package/packages/web/hooks/useProjects.ts +6 -6
  337. package/packages/web/lib/actions/projects.ts +15 -0
  338. package/packages/web/lib/json-loader.ts +630 -0
  339. package/packages/web/lib/services/index.ts +9 -0
  340. package/packages/web/lib/services/migration.server.ts +598 -0
  341. package/packages/web/lib/services/projects.server.ts +52 -0
  342. package/packages/web/lib/services/stats.server.ts +264 -0
  343. package/packages/web/lib/unified-loader.ts +396 -0
  344. package/packages/web/next-env.d.ts +1 -1
  345. package/packages/web/package.json +10 -6
  346. package/packages/web/server.ts +36 -6
  347. package/templates/commands/done.md +76 -32
  348. package/templates/commands/feature.md +121 -47
  349. package/templates/commands/idea.md +81 -8
  350. package/templates/commands/now.md +41 -17
  351. package/templates/commands/ship.md +64 -25
  352. package/templates/commands/sync.md +28 -3
  353. package/core/agentic/agent-router.js +0 -128
  354. package/core/agentic/chain-of-thought.js +0 -578
  355. package/core/agentic/command-executor.js +0 -421
  356. package/core/agentic/context-filter.js +0 -354
  357. package/core/agentic/ground-truth.js +0 -591
  358. package/core/agentic/loop-detector.js +0 -406
  359. package/core/agentic/memory-system.js +0 -850
  360. package/core/agentic/parallel-tools.js +0 -366
  361. package/core/agentic/plan-mode.js +0 -572
  362. package/core/agentic/prompt-builder.js +0 -338
  363. package/core/agentic/response-templates.js +0 -290
  364. package/core/agentic/semantic-compression.js +0 -517
  365. package/core/agentic/think-blocks.js +0 -657
  366. package/core/agentic/tool-registry.js +0 -184
  367. package/core/agentic/validation-rules.js +0 -380
  368. package/core/command-registry.js +0 -698
  369. package/core/commands.js +0 -2237
  370. package/core/domain/task-stack.js +0 -497
  371. package/core/infrastructure/legacy-installer-detector.js +0 -546
  372. package/core/infrastructure/migrator.js +0 -799
  373. package/core/infrastructure/session-manager.js +0 -390
  374. package/core/utils/file-helper.js +0 -329
  375. package/packages/web/app/api/projects/[id]/delete/route.ts +0 -21
  376. package/packages/web/app/api/stats/route.ts +0 -38
  377. package/packages/web/components/AppSidebar.tsx +0 -113
  378. package/packages/web/hooks/useStats.ts +0 -28
  379. /package/packages/web/components/{CommandButton.tsx → CommandButton/CommandButton.tsx} +0 -0
  380. /package/packages/web/components/{ConnectionStatus.tsx → ConnectionStatus/ConnectionStatus.tsx} +0 -0
  381. /package/packages/web/components/{Logo.tsx → Logo/Logo.tsx} +0 -0
  382. /package/packages/web/components/{MarkdownContent.tsx → MarkdownContent/MarkdownContent.tsx} +0 -0
  383. /package/packages/web/components/{ProjectAvatar.tsx → ProjectAvatar/ProjectAvatar.tsx} +0 -0
  384. /package/packages/web/components/{providers.tsx → Providers/Providers.tsx} +0 -0
  385. /package/packages/web/components/{TechStackBadges.tsx → TechStackBadges/TechStackBadges.tsx} +0 -0
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Chain of Thought Reasoning
3
+ * Implements step-by-step reasoning for complex commands
4
+ *
5
+ * @module agentic/chain-of-thought
6
+ * @version 1.0.0
7
+ */
8
+
9
+ interface Context {
10
+ projectId?: string | null
11
+ projectPath: string
12
+ params: Record<string, unknown>
13
+ }
14
+
15
+ interface State {
16
+ now?: string | null
17
+ next?: string | null
18
+ shipped?: string | null
19
+ analysis?: string | null
20
+ [key: string]: unknown
21
+ }
22
+
23
+ interface ReasoningStep {
24
+ step: string
25
+ passed: boolean
26
+ details?: string
27
+ }
28
+
29
+ interface ReasoningResult {
30
+ commandName: string
31
+ reasoning: {
32
+ steps: ReasoningStep[]
33
+ allPassed: boolean
34
+ criticalIssues: string[]
35
+ } | null
36
+ plan: string[]
37
+ confidence: number
38
+ }
39
+
40
+ /**
41
+ * Commands that require chain of thought reasoning
42
+ */
43
+ const REASONING_REQUIRED_COMMANDS = ['ship', 'feature', 'spec', 'cleanup', 'migrate']
44
+
45
+ /**
46
+ * Check if command requires reasoning
47
+ */
48
+ function requiresReasoning(commandName: string): boolean {
49
+ return REASONING_REQUIRED_COMMANDS.includes(commandName)
50
+ }
51
+
52
+ /**
53
+ * Reason through a command before execution
54
+ */
55
+ async function reason(commandName: string, context: Context, state: State): Promise<ReasoningResult> {
56
+ const steps: ReasoningStep[] = []
57
+ const plan: string[] = []
58
+ const criticalIssues: string[] = []
59
+
60
+ switch (commandName) {
61
+ case 'ship':
62
+ // Check prerequisites
63
+ if (state.now && !state.now.includes('No current task')) {
64
+ steps.push({ step: 'Has active task', passed: true })
65
+ } else {
66
+ steps.push({ step: 'Has active task', passed: false, details: 'No active task to ship' })
67
+ criticalIssues.push('No active task')
68
+ }
69
+
70
+ // Check if there's content to ship
71
+ if (state.shipped) {
72
+ steps.push({ step: 'Shipped log accessible', passed: true })
73
+ } else {
74
+ steps.push({ step: 'Shipped log accessible', passed: false, details: 'shipped.md not found' })
75
+ }
76
+
77
+ // Plan
78
+ plan.push('Read current task from now.md')
79
+ plan.push('Calculate duration')
80
+ plan.push('Append to shipped.md')
81
+ plan.push('Clear now.md')
82
+ plan.push('Update metrics')
83
+ break
84
+
85
+ case 'feature':
86
+ // Check if description provided
87
+ if (context.params.description || context.params.feature) {
88
+ steps.push({ step: 'Has feature description', passed: true })
89
+ } else {
90
+ steps.push({ step: 'Has feature description', passed: false, details: 'No description provided' })
91
+ criticalIssues.push('Missing feature description')
92
+ }
93
+
94
+ // Check roadmap accessibility
95
+ if (state.analysis) {
96
+ steps.push({ step: 'Project analyzed', passed: true })
97
+ } else {
98
+ steps.push({ step: 'Project analyzed', passed: false, details: 'Run /p:sync first' })
99
+ }
100
+
101
+ // Plan
102
+ plan.push('Parse feature description')
103
+ plan.push('Generate tasks breakdown')
104
+ plan.push('Add to roadmap.md')
105
+ plan.push('Add tasks to next.md')
106
+ plan.push('Suggest starting first task')
107
+ break
108
+
109
+ case 'spec':
110
+ // Check if feature name provided
111
+ if (context.params.feature || context.params.name) {
112
+ steps.push({ step: 'Has spec name', passed: true })
113
+ } else {
114
+ steps.push({ step: 'Has spec name', passed: false, details: 'No spec name provided' })
115
+ criticalIssues.push('Missing spec name')
116
+ }
117
+
118
+ // Plan
119
+ plan.push('Generate spec template')
120
+ plan.push('Analyze requirements')
121
+ plan.push('Create spec file')
122
+ plan.push('Link to roadmap')
123
+ break
124
+
125
+ case 'cleanup':
126
+ // Check for analysis
127
+ if (state.analysis) {
128
+ steps.push({ step: 'Has code analysis', passed: true })
129
+ } else {
130
+ steps.push({ step: 'Has code analysis', passed: false, details: 'Run /p:analyze first' })
131
+ }
132
+
133
+ // Plan
134
+ plan.push('Scan for unused code')
135
+ plan.push('Identify dead imports')
136
+ plan.push('List files to clean')
137
+ plan.push('Show preview')
138
+ plan.push('Wait for approval')
139
+ plan.push('Execute cleanup')
140
+ break
141
+
142
+ case 'migrate':
143
+ // Always warn for migrate
144
+ steps.push({
145
+ step: 'Migration safety check',
146
+ passed: true,
147
+ details: 'Will require manual approval',
148
+ })
149
+
150
+ // Plan
151
+ plan.push('Analyze current state')
152
+ plan.push('Generate migration plan')
153
+ plan.push('Show affected files')
154
+ plan.push('Request approval')
155
+ plan.push('Execute migration')
156
+ plan.push('Verify results')
157
+ break
158
+
159
+ default:
160
+ // Generic plan
161
+ plan.push('Execute command')
162
+ break
163
+ }
164
+
165
+ // Calculate confidence
166
+ const passedSteps = steps.filter((s) => s.passed).length
167
+ const totalSteps = steps.length
168
+ const confidence = totalSteps > 0 ? passedSteps / totalSteps : 1
169
+
170
+ return {
171
+ commandName,
172
+ reasoning:
173
+ steps.length > 0
174
+ ? {
175
+ steps,
176
+ allPassed: criticalIssues.length === 0,
177
+ criticalIssues,
178
+ }
179
+ : null,
180
+ plan,
181
+ confidence,
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Format reasoning plan for display
187
+ */
188
+ function formatPlan(result: ReasoningResult): string {
189
+ const lines: string[] = []
190
+
191
+ lines.push(`📋 Chain of Thought: ${result.commandName}`)
192
+ lines.push('')
193
+
194
+ if (result.reasoning) {
195
+ lines.push('Steps:')
196
+ result.reasoning.steps.forEach((step) => {
197
+ const icon = step.passed ? '✅' : '❌'
198
+ lines.push(` ${icon} ${step.step}`)
199
+ if (step.details) {
200
+ lines.push(` ${step.details}`)
201
+ }
202
+ })
203
+ lines.push('')
204
+
205
+ if (result.reasoning.criticalIssues.length > 0) {
206
+ lines.push('Critical Issues:')
207
+ result.reasoning.criticalIssues.forEach((issue) => {
208
+ lines.push(` ⚠️ ${issue}`)
209
+ })
210
+ lines.push('')
211
+ }
212
+ }
213
+
214
+ if (result.plan.length > 0) {
215
+ lines.push('Plan:')
216
+ result.plan.forEach((step, i) => {
217
+ lines.push(` ${i + 1}. ${step}`)
218
+ })
219
+ lines.push('')
220
+ }
221
+
222
+ lines.push(`Confidence: ${Math.round(result.confidence * 100)}%`)
223
+
224
+ return lines.join('\n')
225
+ }
226
+
227
+ export { requiresReasoning, reason, formatPlan, REASONING_REQUIRED_COMMANDS }
228
+ export default { requiresReasoning, reason, formatPlan }
@@ -0,0 +1,384 @@
1
+ /**
2
+ * Command Executor Class
3
+ * Orchestrates command execution with agentic delegation.
4
+ */
5
+
6
+ import path from 'path'
7
+ import os from 'os'
8
+ import templateLoader from '../template-loader'
9
+ import contextBuilder from '../context-builder'
10
+ import promptBuilder from '../prompt-builder'
11
+ import toolRegistry from '../tool-registry'
12
+ import { validate, formatError } from '../validation-rules'
13
+ import loopDetector from '../loop-detector'
14
+ import chainOfThought from '../chain-of-thought'
15
+ import semanticCompression from '../semantic-compression'
16
+ import responseTemplates from '../response-templates'
17
+ import memorySystem from '../memory-system'
18
+ import groundTruth from '../ground-truth'
19
+ import thinkBlocks from '../think-blocks'
20
+ import parallelTools from '../parallel-tools'
21
+ import planMode from '../plan-mode'
22
+ import { signalStart, signalEnd } from './status-signal'
23
+ import type { ExecutionResult, SimpleExecutionResult, ExecutionToolsFn } from './types'
24
+
25
+ export class CommandExecutor {
26
+ /**
27
+ * Signal that a command is running (for status line)
28
+ */
29
+ signalStart(commandName: string): void {
30
+ signalStart(commandName)
31
+ }
32
+
33
+ /**
34
+ * Signal that command has finished (for status line)
35
+ */
36
+ signalEnd(): void {
37
+ signalEnd()
38
+ }
39
+
40
+ /**
41
+ * Execute a prjct command with full agentic delegation
42
+ */
43
+ async execute(
44
+ commandName: string,
45
+ params: Record<string, unknown>,
46
+ projectPath: string
47
+ ): Promise<ExecutionResult> {
48
+ // Signal start for status line
49
+ this.signalStart(commandName)
50
+
51
+ // Context for loop detection
52
+ const loopContext = (params.task as string) || (params.description as string) || ''
53
+
54
+ // Check if we're in a loop BEFORE attempting
55
+ if (loopDetector.shouldEscalate(commandName, loopContext)) {
56
+ const escalation = loopDetector.getEscalationInfo(commandName, loopContext)
57
+ this.signalEnd()
58
+ return {
59
+ success: false,
60
+ error: escalation?.message,
61
+ escalation,
62
+ isLoopDetected: true,
63
+ suggestion: escalation?.suggestion,
64
+ }
65
+ }
66
+
67
+ try {
68
+ // 1. Load template
69
+ const template = await templateLoader.load(commandName)
70
+
71
+ // 2. Build METADATA context only (lazy loading - no file reads yet)
72
+ const metadataContext = await contextBuilder.build(projectPath, params)
73
+
74
+ // 2.5. VALIDATE: Pre-flight checks with specific errors
75
+ const validation = await validate(commandName, metadataContext as unknown as Parameters<typeof validate>[1])
76
+ if (!validation.valid) {
77
+ this.signalEnd()
78
+ return {
79
+ success: false,
80
+ error: formatError(validation),
81
+ validation,
82
+ isValidationError: true,
83
+ }
84
+ }
85
+
86
+ // 2.55. P3.4 PLAN MODE: Check if command requires planning
87
+ const requiresPlanning = planMode.requiresPlanning(commandName)
88
+ const isDestructive = planMode.isDestructive(commandName)
89
+ const isInPlanningMode = planMode.isInPlanningMode(metadataContext.projectId!)
90
+
91
+ // Start planning mode if required and not already in it
92
+ let activePlan = null
93
+ if (requiresPlanning && !isInPlanningMode && !params.skipPlanning) {
94
+ activePlan = planMode.startPlanning(metadataContext.projectId!, commandName, params)
95
+ } else if (isInPlanningMode) {
96
+ activePlan = planMode.getActivePlan(metadataContext.projectId!)
97
+ }
98
+
99
+ // 2.6. GROUND TRUTH: Verify actual state before critical operations
100
+ let groundTruthResult = null
101
+ if (groundTruth.requiresVerification(commandName)) {
102
+ const preState = await contextBuilder.loadStateForCommand(metadataContext, commandName)
103
+ groundTruthResult = await groundTruth.verify(
104
+ commandName,
105
+ metadataContext as unknown as Parameters<typeof groundTruth.verify>[1],
106
+ preState
107
+ )
108
+
109
+ // Log warnings but don't block (user can override)
110
+ if (!groundTruthResult.verified && groundTruthResult.warnings.length > 0) {
111
+ console.log(groundTruth.formatWarnings(groundTruthResult))
112
+ }
113
+ }
114
+
115
+ // 2.7. THINK BLOCKS (P3.1): Dynamic reasoning based on triggers
116
+ let thinkBlock = null
117
+ const preThinkState =
118
+ groundTruthResult?.actual || (await contextBuilder.loadStateForCommand(metadataContext, commandName))
119
+ const thinkTrigger = thinkBlocks.detectTrigger(
120
+ commandName,
121
+ metadataContext as unknown as Parameters<typeof thinkBlocks.detectTrigger>[1],
122
+ preThinkState as Parameters<typeof thinkBlocks.detectTrigger>[2]
123
+ )
124
+ if (thinkTrigger) {
125
+ thinkBlock = await thinkBlocks.generate(
126
+ thinkTrigger,
127
+ commandName,
128
+ metadataContext as unknown as Parameters<typeof thinkBlocks.generate>[2],
129
+ preThinkState as Parameters<typeof thinkBlocks.generate>[3]
130
+ )
131
+
132
+ // Log think block if in debug mode
133
+ if (process.env.PRJCT_DEBUG === 'true') {
134
+ console.log(thinkBlocks.format(thinkBlock, true))
135
+ }
136
+ }
137
+
138
+ // 2.8. CHAIN OF THOUGHT: Reasoning for critical commands
139
+ let reasoning = null
140
+ if (chainOfThought.requiresReasoning(commandName)) {
141
+ const reasoningState = await contextBuilder.loadStateForCommand(metadataContext, commandName)
142
+ reasoning = await chainOfThought.reason(
143
+ commandName,
144
+ metadataContext as unknown as Parameters<typeof chainOfThought.reason>[1],
145
+ reasoningState as Parameters<typeof chainOfThought.reason>[2]
146
+ )
147
+
148
+ // If reasoning shows critical issues, warn but continue
149
+ if (reasoning.reasoning && !reasoning.reasoning.allPassed) {
150
+ console.log('⚠️ Chain of Thought detected issues:')
151
+ console.log(chainOfThought.formatPlan(reasoning))
152
+ }
153
+ }
154
+
155
+ // 3. AGENTIC: Claude decides agent assignment via templates
156
+ let context: Record<string, unknown> = metadataContext as unknown as Record<string, unknown>
157
+
158
+ // Provide agent info to context so Claude can delegate
159
+ context = {
160
+ ...context,
161
+ agentsPath: path.join(os.homedir(), '.prjct-cli', 'projects', metadataContext.projectId || '', 'agents'),
162
+ agentRoutingPath: path.join(__dirname, '..', '..', '..', 'templates', 'agentic', 'agent-routing.md'),
163
+ agenticDelegation: true,
164
+ }
165
+
166
+ // 6. Load state with filtered context
167
+ const rawState = await contextBuilder.loadState(metadataContext)
168
+
169
+ // 6.5. SEMANTIC COMPRESSION: Compress state for reduced token usage
170
+ const compressedState: Record<string, unknown> = {}
171
+ for (const [key, content] of Object.entries(rawState)) {
172
+ if (content) {
173
+ const compressed = semanticCompression.compress(content, key)
174
+ compressedState[key] = {
175
+ raw: content,
176
+ summary: compressed.summary,
177
+ compressed,
178
+ }
179
+ } else {
180
+ compressedState[key] = { raw: null, summary: 'Empty', compressed: null }
181
+ }
182
+ }
183
+
184
+ // Use compressed summaries for prompt, keep raw for tool execution
185
+ const state = {
186
+ ...rawState,
187
+ _compressed: compressedState,
188
+ _compressionMetrics: semanticCompression.getMetrics(),
189
+ }
190
+
191
+ // 7. MEMORY: Load learned patterns AND relevant memories for this command
192
+ let learnedPatterns = null
193
+ let relevantMemories = null
194
+ if (metadataContext.projectId) {
195
+ learnedPatterns = {
196
+ commit_footer: await memorySystem.getSmartDecision(metadataContext.projectId, 'commit_footer'),
197
+ branch_naming: await memorySystem.getSmartDecision(metadataContext.projectId, 'branch_naming'),
198
+ test_before_ship: await memorySystem.getSmartDecision(metadataContext.projectId, 'test_before_ship'),
199
+ preferred_agent: await memorySystem.getSmartDecision(
200
+ metadataContext.projectId,
201
+ `preferred_agent_${commandName}`
202
+ ),
203
+ }
204
+
205
+ // P3.3: Get relevant memories for context
206
+ relevantMemories = await memorySystem.getRelevantMemories(
207
+ metadataContext.projectId,
208
+ { commandName, params },
209
+ 5
210
+ )
211
+ }
212
+
213
+ // 9. Build prompt - NO agent assignment here, Claude decides via templates
214
+ const planInfo = {
215
+ isPlanning: requiresPlanning || isInPlanningMode,
216
+ requiresApproval: isDestructive && !params.approved,
217
+ active: activePlan,
218
+ allowedTools: planMode.getAllowedTools(isInPlanningMode, template.frontmatter['allowed-tools'] || []),
219
+ }
220
+ // Agent is null - Claude assigns via Task tool using agent-routing.md
221
+ const prompt = promptBuilder.build(
222
+ template,
223
+ context as Parameters<typeof promptBuilder.build>[1],
224
+ state,
225
+ null,
226
+ learnedPatterns,
227
+ thinkBlock,
228
+ relevantMemories,
229
+ planInfo
230
+ )
231
+
232
+ // Log agentic mode
233
+ console.log(`🤖 Agentic delegation enabled - Claude will assign agent via Task tool`)
234
+
235
+ // Record successful attempt
236
+ loopDetector.recordSuccess(commandName, loopContext)
237
+
238
+ // Signal end for status line
239
+ this.signalEnd()
240
+
241
+ return {
242
+ success: true,
243
+ template,
244
+ context,
245
+ state,
246
+ prompt,
247
+ agenticDelegation: true,
248
+ agentsPath: context.agentsPath as string,
249
+ agentRoutingPath: context.agentRoutingPath as string,
250
+ reasoning,
251
+ thinkBlock,
252
+ groundTruth: groundTruthResult,
253
+ compressionMetrics: state._compressionMetrics,
254
+ learnedPatterns,
255
+ relevantMemories,
256
+ formatResponse: (data: unknown) => responseTemplates.format(commandName, data as Parameters<typeof responseTemplates.format>[1]),
257
+ formatThinkBlock: (verbose: boolean) => thinkBlocks.format(thinkBlock, verbose),
258
+ parallel: {
259
+ execute: (toolCalls: unknown[]) => parallelTools.execute(toolCalls as Parameters<typeof parallelTools.execute>[0]),
260
+ readAll: (paths: string[]) => parallelTools.readAll(paths),
261
+ canParallelize: (tools: string[]) => parallelTools.canParallelize(tools),
262
+ getMetrics: () => parallelTools.getMetrics(),
263
+ },
264
+ memory: {
265
+ create: (memory: unknown) =>
266
+ memorySystem.createMemory(metadataContext.projectId!, memory as Parameters<typeof memorySystem.createMemory>[1]),
267
+ autoRemember: (type: string, value: string, ctx?: string) =>
268
+ memorySystem.autoRemember(metadataContext.projectId!, type, value, ctx),
269
+ search: (query: string) => memorySystem.searchMemories(metadataContext.projectId!, query),
270
+ findByTags: (tags: string[]) => memorySystem.findByTags(metadataContext.projectId!, tags),
271
+ getStats: () => memorySystem.getMemoryStats(metadataContext.projectId!),
272
+ },
273
+ plan: {
274
+ active: activePlan,
275
+ isPlanning: requiresPlanning || isInPlanningMode,
276
+ isDestructive,
277
+ requiresApproval: isDestructive && !params.approved,
278
+ recordInfo: (info: unknown) =>
279
+ planMode.recordGatheredInfo(metadataContext.projectId!, info as Parameters<typeof planMode.recordGatheredInfo>[1]),
280
+ setAnalysis: (analysis: unknown) => planMode.setAnalysis(metadataContext.projectId!, analysis),
281
+ propose: (plan: unknown) =>
282
+ planMode.proposePlan(metadataContext.projectId!, plan as Parameters<typeof planMode.proposePlan>[1]),
283
+ approve: (feedback?: string | null) => planMode.approvePlan(metadataContext.projectId!, feedback),
284
+ reject: (reason?: string | null) => planMode.rejectPlan(metadataContext.projectId!, reason),
285
+ getApprovalPrompt: () =>
286
+ planMode.generateApprovalPrompt(commandName, context as Parameters<typeof planMode.generateApprovalPrompt>[1]),
287
+ startExecution: () => planMode.startExecution(metadataContext.projectId!),
288
+ getNextStep: () => planMode.getNextStep(metadataContext.projectId!),
289
+ completeStep: (result?: unknown) => planMode.completeStep(metadataContext.projectId!, result),
290
+ failStep: (error: string) => planMode.failStep(metadataContext.projectId!, error),
291
+ abort: (reason?: string) => planMode.abortPlan(metadataContext.projectId!, reason),
292
+ getStatus: () => planMode.formatStatus(metadataContext.projectId!),
293
+ getAllowedTools: () =>
294
+ planMode.getAllowedTools(isInPlanningMode, template.frontmatter['allowed-tools'] || []),
295
+ },
296
+ }
297
+ } catch (error) {
298
+ // Signal end for status line
299
+ this.signalEnd()
300
+
301
+ // Record failed attempt for loop detection
302
+ const attemptInfo = loopDetector.recordAttempt(commandName, loopContext, {
303
+ success: false,
304
+ error: (error as Error).message,
305
+ })
306
+
307
+ // Check if we should escalate after this failure
308
+ if (attemptInfo.shouldEscalate) {
309
+ const escalation = loopDetector.getEscalationInfo(commandName, loopContext)
310
+ return {
311
+ success: false,
312
+ error: escalation?.message,
313
+ escalation,
314
+ isLoopDetected: true,
315
+ suggestion: escalation?.suggestion,
316
+ }
317
+ }
318
+
319
+ return {
320
+ success: false,
321
+ error: (error as Error).message,
322
+ attemptNumber: attemptInfo.attemptNumber,
323
+ isLooping: attemptInfo.isLooping,
324
+ }
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Execute tool with permission check
330
+ */
331
+ async executeTool(toolName: string, args: unknown[], allowedTools: string[]): Promise<unknown> {
332
+ // Check if tool is allowed
333
+ if (!toolRegistry.isAllowed(toolName, allowedTools)) {
334
+ throw new Error(`Tool ${toolName} not allowed for this command`)
335
+ }
336
+
337
+ // Get tool function
338
+ const tool = toolRegistry.get(toolName)
339
+ if (!tool) {
340
+ throw new Error(`Tool ${toolName} not found`)
341
+ }
342
+
343
+ // Execute tool
344
+ return await tool(...args)
345
+ }
346
+
347
+ /**
348
+ * Simple execution for direct tool access (legacy migration helper)
349
+ */
350
+ async executeSimple(
351
+ commandName: string,
352
+ executionFn: ExecutionToolsFn,
353
+ projectPath: string
354
+ ): Promise<SimpleExecutionResult> {
355
+ try {
356
+ // Load template to get allowed tools
357
+ const template = await templateLoader.load(commandName)
358
+ const allowedTools = template.frontmatter['allowed-tools'] || []
359
+
360
+ // Build context
361
+ const context = await contextBuilder.build(projectPath)
362
+
363
+ // Create tools proxy that checks permissions
364
+ const tools = {
365
+ read: async (filePath: string) => this.executeTool('Read', [filePath], allowedTools),
366
+ write: async (filePath: string, content: string) => this.executeTool('Write', [filePath, content], allowedTools),
367
+ bash: async (command: string) => this.executeTool('Bash', [command], allowedTools),
368
+ }
369
+
370
+ // Execute user function with tools
371
+ const result = await executionFn(tools, context)
372
+
373
+ return {
374
+ success: true,
375
+ result,
376
+ }
377
+ } catch (error) {
378
+ return {
379
+ success: false,
380
+ error: (error as Error).message,
381
+ }
382
+ }
383
+ }
384
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Command Executor
3
+ * Orchestrates command execution with agentic delegation.
4
+ *
5
+ * @module agentic/command-executor
6
+ * @version 3.4
7
+ */
8
+
9
+ export type { ExecutionResult, SimpleExecutionResult, ExecutionToolsFn } from './types'
10
+ export { signalStart, signalEnd } from './status-signal'
11
+ export { CommandExecutor } from './command-executor'
12
+
13
+ import { CommandExecutor } from './command-executor'
14
+
15
+ const commandExecutor = new CommandExecutor()
16
+ export default commandExecutor
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Status Signal
3
+ * Running file for status line integration
4
+ */
5
+
6
+ import fs from 'fs'
7
+ import path from 'path'
8
+ import os from 'os'
9
+
10
+ const RUNNING_FILE = path.join(os.homedir(), '.prjct-cli', '.running')
11
+
12
+ /**
13
+ * Signal that a command is running (for status line)
14
+ */
15
+ export function signalStart(commandName: string): void {
16
+ try {
17
+ const dir = path.dirname(RUNNING_FILE)
18
+ if (!fs.existsSync(dir)) {
19
+ fs.mkdirSync(dir, { recursive: true })
20
+ }
21
+ fs.writeFileSync(RUNNING_FILE, `/p:${commandName}`)
22
+ } catch {
23
+ // Silently ignore - status line is optional
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Signal that command has finished (for status line)
29
+ */
30
+ export function signalEnd(): void {
31
+ try {
32
+ if (fs.existsSync(RUNNING_FILE)) {
33
+ fs.unlinkSync(RUNNING_FILE)
34
+ }
35
+ } catch {
36
+ // Silently ignore - status line is optional
37
+ }
38
+ }