@sienklogic/plan-build-run 2.21.1 → 2.21.2

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 (982) hide show
  1. package/CHANGELOG.md +1331 -323
  2. package/CLAUDE.md +75 -40
  3. package/LICENSE +2 -1
  4. package/README.md +412 -177
  5. package/bin/install.js +2752 -0
  6. package/dashboard/bin/cli.cjs +96 -0
  7. package/dashboard/bin/stop.cjs +129 -0
  8. package/dashboard/eslint.config.js +37 -0
  9. package/dashboard/index.html +20 -0
  10. package/dashboard/package.json +27 -25
  11. package/dashboard/server/index.js +151 -0
  12. package/dashboard/server/lib/frontmatter.js +92 -0
  13. package/dashboard/server/middleware/static.js +35 -0
  14. package/dashboard/server/package.json +16 -0
  15. package/dashboard/server/routes/agents.js +234 -0
  16. package/dashboard/server/routes/config.js +64 -0
  17. package/dashboard/server/routes/health.js +98 -0
  18. package/dashboard/server/routes/incidents.js +78 -0
  19. package/dashboard/server/routes/intel.js +69 -0
  20. package/dashboard/server/routes/memory.js +107 -0
  21. package/dashboard/server/routes/planning.js +234 -0
  22. package/dashboard/server/routes/progress.js +77 -0
  23. package/dashboard/server/routes/projects.js +36 -0
  24. package/dashboard/server/routes/requirements.js +40 -0
  25. package/dashboard/server/routes/roadmap.js +69 -0
  26. package/dashboard/server/routes/sessions.js +70 -0
  27. package/dashboard/server/routes/status.js +25 -0
  28. package/dashboard/server/routes/telemetry.js +233 -0
  29. package/dashboard/server/services/file-watcher.js +105 -0
  30. package/dashboard/server/services/planning-reader.js +727 -0
  31. package/dashboard/server/test/cli.test.js +34 -0
  32. package/dashboard/server/test/frontmatter.test.js +104 -0
  33. package/dashboard/server/test/isolation.test.js +32 -0
  34. package/dashboard/server/test/planning-reader.test.js +151 -0
  35. package/dashboard/server/test/routes.test.js +91 -0
  36. package/dashboard/server/test/ws.test.js +81 -0
  37. package/dashboard/server/ws.js +96 -0
  38. package/dashboard/src/App.jsx +165 -0
  39. package/dashboard/src/components/charts/BudgetBars.jsx +42 -0
  40. package/dashboard/src/components/charts/ContextRadar.jsx +34 -0
  41. package/dashboard/src/components/charts/PhaseDonut.jsx +66 -0
  42. package/dashboard/src/components/charts/SuccessTrend.jsx +45 -0
  43. package/dashboard/src/components/charts/TokenChart.jsx +55 -0
  44. package/dashboard/src/components/charts/index.js +5 -0
  45. package/dashboard/src/components/config/CfgSection.jsx +93 -0
  46. package/dashboard/src/components/layout/Header.jsx +89 -0
  47. package/dashboard/src/components/layout/ProjectSwitcher.jsx +160 -0
  48. package/dashboard/src/components/layout/Sidebar.jsx +161 -0
  49. package/dashboard/src/components/ui/AutoModeBanner.jsx +138 -0
  50. package/dashboard/src/components/ui/BackButton.jsx +27 -0
  51. package/dashboard/src/components/ui/Badge.jsx +27 -0
  52. package/dashboard/src/components/ui/Card.jsx +23 -0
  53. package/dashboard/src/components/ui/ChartTooltip.jsx +48 -0
  54. package/dashboard/src/components/ui/CheckpointBox.jsx +110 -0
  55. package/dashboard/src/components/ui/CodeBlock.jsx +27 -0
  56. package/dashboard/src/components/ui/ConfidenceBadge.jsx +20 -0
  57. package/dashboard/src/components/ui/ConfirmModal.jsx +161 -0
  58. package/dashboard/src/components/ui/ConnectionBanner.jsx +60 -0
  59. package/dashboard/src/components/ui/ErrorBoundary.jsx +106 -0
  60. package/dashboard/src/components/ui/ErrorBox.jsx +107 -0
  61. package/dashboard/src/components/ui/KeyValue.jsx +33 -0
  62. package/dashboard/src/components/ui/LoadingSkeleton.jsx +84 -0
  63. package/dashboard/src/components/ui/MetricCard.jsx +58 -0
  64. package/dashboard/src/components/ui/NextUpBlock.jsx +92 -0
  65. package/dashboard/src/components/ui/NumberInput.jsx +44 -0
  66. package/dashboard/src/components/ui/PBRBanner.jsx +47 -0
  67. package/dashboard/src/components/ui/PipelineView.jsx +130 -0
  68. package/dashboard/src/components/ui/ProgressBar.jsx +28 -0
  69. package/dashboard/src/components/ui/ProgressDisplay.jsx +47 -0
  70. package/dashboard/src/components/ui/QualityGateBadge.jsx +15 -0
  71. package/dashboard/src/components/ui/SectionTitle.jsx +35 -0
  72. package/dashboard/src/components/ui/SelectInput.jsx +45 -0
  73. package/dashboard/src/components/ui/StatusDot.jsx +51 -0
  74. package/dashboard/src/components/ui/StatusSymbol.jsx +49 -0
  75. package/dashboard/src/components/ui/TabBar.jsx +41 -0
  76. package/dashboard/src/components/ui/TextInput.jsx +42 -0
  77. package/dashboard/src/components/ui/Toast.jsx +117 -0
  78. package/dashboard/src/components/ui/Toggle.jsx +70 -0
  79. package/dashboard/src/components/ui/index.js +29 -0
  80. package/dashboard/src/hooks/useDocumentTitle.js +16 -0
  81. package/dashboard/src/hooks/useFetch.js +50 -0
  82. package/dashboard/src/hooks/useToast.jsx +43 -0
  83. package/dashboard/src/hooks/useWebSocket.js +103 -0
  84. package/dashboard/src/lib/api.js +112 -0
  85. package/dashboard/src/lib/configSchema.js +189 -0
  86. package/dashboard/src/lib/constants.js +22 -0
  87. package/dashboard/src/main.jsx +15 -0
  88. package/dashboard/src/pages/AgentsPage.jsx +191 -0
  89. package/dashboard/src/pages/ConfigPage.jsx +298 -0
  90. package/dashboard/src/pages/HooksPage.jsx +412 -0
  91. package/dashboard/src/pages/IncidentsPage.jsx +135 -0
  92. package/dashboard/src/pages/IntelPage.jsx +193 -0
  93. package/dashboard/src/pages/LiveFeed.jsx +274 -0
  94. package/dashboard/src/pages/MemoryPage.jsx +107 -0
  95. package/dashboard/src/pages/OnboardingPage.jsx +117 -0
  96. package/dashboard/src/pages/Overview.jsx +360 -0
  97. package/dashboard/src/pages/PhaseDetailView.jsx +216 -0
  98. package/dashboard/src/pages/PlanningPage.jsx +181 -0
  99. package/dashboard/src/pages/ProgressPage.jsx +249 -0
  100. package/dashboard/src/pages/ResearchPage.jsx +129 -0
  101. package/dashboard/src/pages/RoadmapPage.jsx +251 -0
  102. package/dashboard/src/pages/SessionsPage.jsx +117 -0
  103. package/dashboard/src/pages/Telemetry.jsx +166 -0
  104. package/dashboard/src/pages/planning/DecisionsTab.jsx +153 -0
  105. package/dashboard/src/pages/planning/FilesTab.jsx +420 -0
  106. package/dashboard/src/pages/planning/MilestoneDetail.jsx +319 -0
  107. package/dashboard/src/pages/planning/MilestonesTab.jsx +151 -0
  108. package/dashboard/src/pages/planning/NotesTab.jsx +251 -0
  109. package/dashboard/src/pages/planning/PhasesTab.jsx +218 -0
  110. package/dashboard/src/pages/planning/QuickTab.jsx +50 -0
  111. package/dashboard/src/pages/planning/ResearchTab.jsx +103 -0
  112. package/dashboard/src/pages/planning/TodosTab.jsx +297 -0
  113. package/dashboard/src/theme/ThemeProvider.jsx +38 -0
  114. package/dashboard/src/theme/tokens.js +17 -0
  115. package/dashboard/tests/components/ConfirmModal.test.jsx +179 -0
  116. package/dashboard/tests/components/ConnectionBanner.test.jsx +37 -0
  117. package/dashboard/tests/components/ErrorBoundary.test.jsx +59 -0
  118. package/dashboard/tests/components/LoadingSkeleton.test.jsx +46 -0
  119. package/dashboard/tests/components/ToastContainer.test.jsx +47 -0
  120. package/dashboard/tests/components/Toggle.test.jsx +61 -0
  121. package/dashboard/tests/hooks/useFetch.test.jsx +77 -0
  122. package/dashboard/tests/hooks/useToast.test.jsx +78 -0
  123. package/dashboard/tests/hooks/useWebSocket.test.jsx +128 -0
  124. package/dashboard/tests/pages/ConfigPage.test.jsx +199 -0
  125. package/dashboard/tests/pages/PlanningPage.test.jsx +119 -0
  126. package/dashboard/tests/pages/planning/FilesTab.test.jsx +198 -0
  127. package/dashboard/tests/pages/planning/NotesTab.test.jsx +178 -0
  128. package/dashboard/tests/pages/planning/TodosTab.test.jsx +188 -0
  129. package/dashboard/tests/performance.test.jsx +46 -0
  130. package/dashboard/tests/routes/config.test.js +98 -0
  131. package/dashboard/tests/routes/health.test.js +40 -0
  132. package/dashboard/tests/routes/planning.test.js +112 -0
  133. package/dashboard/tests/routes/roadmap.test.js +91 -0
  134. package/dashboard/tests/routes/status.test.js +131 -0
  135. package/dashboard/tests/server/planning-reader.test.js +153 -0
  136. package/dashboard/tests/setup.js +7 -0
  137. package/dashboard/vite.config.js +41 -0
  138. package/package.json +56 -41
  139. package/plan-build-run/bin/config-schema.json +1298 -0
  140. package/plugins/pbr/.claude-plugin/plugin.json +1 -1
  141. package/plugins/pbr/CLAUDE.md +19 -0
  142. package/plugins/pbr/UI-CONSISTENCY-GAPS.md +1 -1
  143. package/plugins/pbr/agents/advisor-researcher.md +101 -0
  144. package/plugins/pbr/agents/audit.md +207 -89
  145. package/plugins/pbr/agents/codebase-mapper.md +158 -23
  146. package/plugins/pbr/agents/debugger.md +210 -34
  147. package/plugins/pbr/agents/dev-sync.md +206 -0
  148. package/plugins/pbr/agents/executor.md +734 -38
  149. package/plugins/pbr/agents/general.md +69 -5
  150. package/plugins/pbr/agents/integration-checker.md +147 -31
  151. package/plugins/pbr/agents/intel-updater.md +332 -0
  152. package/plugins/pbr/agents/nyquist-auditor.md +254 -0
  153. package/plugins/pbr/agents/plan-checker.md +268 -65
  154. package/plugins/pbr/agents/planner.md +449 -41
  155. package/plugins/pbr/agents/researcher.md +218 -37
  156. package/plugins/pbr/agents/roadmapper.md +398 -0
  157. package/plugins/pbr/agents/synthesizer.md +166 -25
  158. package/plugins/pbr/agents/ui-checker.md +204 -0
  159. package/plugins/pbr/agents/ui-researcher.md +224 -0
  160. package/plugins/pbr/agents/verifier.md +570 -46
  161. package/plugins/pbr/commands/add-phase.md +75 -0
  162. package/plugins/pbr/commands/add-todo.md +8 -0
  163. package/plugins/pbr/commands/audit-fix.md +5 -0
  164. package/plugins/pbr/commands/audit-milestone.md +8 -0
  165. package/plugins/pbr/commands/autonomous.md +5 -0
  166. package/plugins/pbr/commands/backlog.md +6 -0
  167. package/plugins/pbr/commands/check-todos.md +8 -0
  168. package/plugins/pbr/commands/complete-milestone.md +8 -0
  169. package/plugins/pbr/commands/config.md +1 -1
  170. package/plugins/pbr/commands/discuss-phase.md +6 -0
  171. package/plugins/pbr/commands/execute-phase.md +6 -0
  172. package/plugins/pbr/commands/fast.md +6 -0
  173. package/plugins/pbr/commands/forensics.md +6 -0
  174. package/plugins/pbr/commands/import.md +1 -1
  175. package/plugins/pbr/commands/insert-phase.md +65 -0
  176. package/plugins/pbr/commands/intel.md +5 -0
  177. package/plugins/pbr/commands/join-discord.md +11 -0
  178. package/plugins/pbr/commands/list-phase-assumptions.md +5 -0
  179. package/plugins/pbr/commands/map-codebase.md +6 -0
  180. package/plugins/pbr/commands/milestone-summary.md +6 -0
  181. package/plugins/pbr/commands/new-milestone.md +8 -0
  182. package/plugins/pbr/commands/new-project.md +6 -0
  183. package/plugins/pbr/commands/pause-work.md +5 -0
  184. package/plugins/pbr/commands/plan-milestone-gaps.md +7 -0
  185. package/plugins/pbr/commands/plan-phase.md +6 -0
  186. package/plugins/pbr/commands/plant-seed.md +6 -0
  187. package/plugins/pbr/commands/profile-user.md +5 -0
  188. package/plugins/pbr/commands/profile.md +5 -0
  189. package/plugins/pbr/commands/progress.md +6 -0
  190. package/plugins/pbr/commands/quick.md +1 -1
  191. package/plugins/pbr/commands/reapply-patches.md +47 -0
  192. package/plugins/pbr/commands/release.md +6 -0
  193. package/plugins/pbr/commands/remove-phase.md +66 -0
  194. package/plugins/pbr/commands/research-phase.md +59 -0
  195. package/plugins/pbr/commands/resume-work.md +5 -0
  196. package/plugins/pbr/commands/seed.md +6 -0
  197. package/plugins/pbr/commands/session-report.md +5 -0
  198. package/plugins/pbr/commands/set-profile.md +6 -0
  199. package/plugins/pbr/commands/settings.md +5 -0
  200. package/plugins/pbr/commands/setup.md +1 -1
  201. package/plugins/pbr/commands/ship.md +5 -0
  202. package/plugins/pbr/commands/stats.md +6 -0
  203. package/plugins/pbr/commands/test.md +5 -0
  204. package/plugins/pbr/commands/thread.md +6 -0
  205. package/plugins/pbr/commands/todo.md +1 -1
  206. package/plugins/pbr/commands/ui-phase.md +5 -0
  207. package/plugins/pbr/commands/ui-review.md +5 -0
  208. package/plugins/pbr/commands/undo.md +5 -0
  209. package/plugins/pbr/commands/update.md +37 -0
  210. package/plugins/pbr/commands/validate-phase.md +5 -0
  211. package/plugins/pbr/commands/verify-work.md +6 -0
  212. package/plugins/pbr/dashboard/package-lock.json +6 -0
  213. package/plugins/pbr/dist/architecture-guard.js +76 -0
  214. package/plugins/pbr/dist/audit-dimensions.js +556 -0
  215. package/plugins/pbr/dist/auto-continue.js +277 -0
  216. package/plugins/pbr/dist/block-skill-self-read.js +124 -0
  217. package/plugins/pbr/dist/check-agent-state-write.js +63 -0
  218. package/plugins/pbr/dist/check-config-change.js +213 -0
  219. package/plugins/pbr/dist/check-cross-plugin-sync.js +93 -0
  220. package/plugins/pbr/dist/check-dangerous-commands.js +193 -0
  221. package/plugins/pbr/dist/check-direct-state-write.js +37 -0
  222. package/plugins/pbr/dist/check-doc-sprawl.js +102 -0
  223. package/plugins/pbr/dist/check-phase-boundary.js +191 -0
  224. package/plugins/pbr/dist/check-plan-format.js +227 -0
  225. package/plugins/pbr/dist/check-read-first.js +345 -0
  226. package/plugins/pbr/dist/check-roadmap-sync.js +507 -0
  227. package/plugins/pbr/dist/check-skill-workflow.js +354 -0
  228. package/plugins/pbr/dist/check-state-sync.js +676 -0
  229. package/plugins/pbr/dist/check-subagent-output.js +425 -0
  230. package/plugins/pbr/dist/check-summary-gate.js +188 -0
  231. package/plugins/pbr/dist/context-bridge.js +425 -0
  232. package/plugins/pbr/dist/context-budget-check.js +442 -0
  233. package/plugins/pbr/dist/context-quality.js +271 -0
  234. package/plugins/pbr/dist/enforce-context-budget.js +138 -0
  235. package/plugins/pbr/dist/enforce-pbr-workflow.js +277 -0
  236. package/plugins/pbr/dist/event-handler.js +212 -0
  237. package/plugins/pbr/dist/event-logger.js +125 -0
  238. package/plugins/pbr/dist/feedback-loop.js +155 -0
  239. package/plugins/pbr/dist/graph-update.js +422 -0
  240. package/plugins/pbr/dist/hook-logger.js +114 -0
  241. package/plugins/pbr/dist/hook-server-client.js +361 -0
  242. package/plugins/pbr/dist/hook-server.js +664 -0
  243. package/plugins/pbr/dist/hooks-schema.json +87 -0
  244. package/plugins/pbr/dist/instructions-loaded.js +173 -0
  245. package/plugins/pbr/dist/intercept-plan-mode.js +81 -0
  246. package/plugins/pbr/dist/log-notification.js +131 -0
  247. package/plugins/pbr/dist/log-subagent.js +367 -0
  248. package/plugins/pbr/dist/log-tool-failure.js +140 -0
  249. package/plugins/pbr/dist/milestone-learnings.js +519 -0
  250. package/plugins/pbr/dist/pbr-tools.js +493 -0
  251. package/plugins/pbr/dist/post-bash-triage.js +96 -0
  252. package/plugins/pbr/dist/post-compact.js +135 -0
  253. package/plugins/pbr/dist/post-hoc.js +237 -0
  254. package/plugins/pbr/dist/post-write-dispatch.js +243 -0
  255. package/plugins/pbr/dist/post-write-quality.js +208 -0
  256. package/plugins/pbr/dist/pre-bash-dispatch.js +212 -0
  257. package/plugins/pbr/dist/pre-skill-dispatch.js +114 -0
  258. package/plugins/pbr/dist/pre-task-dispatch.js +269 -0
  259. package/plugins/pbr/dist/pre-write-dispatch.js +234 -0
  260. package/plugins/pbr/dist/progress-tracker.js +173 -0
  261. package/plugins/pbr/dist/prompt-guard.js +114 -0
  262. package/plugins/pbr/dist/prompt-routing.js +209 -0
  263. package/plugins/pbr/dist/quick-status.js +179 -0
  264. package/plugins/pbr/dist/record-incident.js +37 -0
  265. package/plugins/pbr/dist/run-hook.js +132 -0
  266. package/plugins/pbr/dist/session-cleanup.js +653 -0
  267. package/plugins/pbr/dist/session-tracker.js +124 -0
  268. package/plugins/pbr/dist/status-line.js +849 -0
  269. package/plugins/pbr/dist/suggest-compact.js +307 -0
  270. package/plugins/pbr/dist/sync-context-to-claude.js +100 -0
  271. package/plugins/pbr/dist/task-completed.js +206 -0
  272. package/plugins/pbr/dist/track-context-budget.js +432 -0
  273. package/plugins/pbr/dist/track-user-gates.js +88 -0
  274. package/plugins/pbr/dist/trust-tracker.js +193 -0
  275. package/plugins/pbr/dist/validate-commit.js +233 -0
  276. package/plugins/pbr/dist/validate-skill-args.js +222 -0
  277. package/plugins/pbr/dist/validate-task.js +271 -0
  278. package/plugins/pbr/dist/worktree-create.js +144 -0
  279. package/plugins/pbr/dist/worktree-remove.js +147 -0
  280. package/plugins/pbr/hooks/hooks.json +137 -65
  281. package/plugins/pbr/references/agent-contracts.md +39 -8
  282. package/plugins/pbr/references/agent-teams.md +3 -3
  283. package/plugins/pbr/references/archive/checkpoints.md +189 -0
  284. package/plugins/pbr/references/archive/context-quality-tiers.md +45 -0
  285. package/plugins/pbr/references/archive/hook-ordering.md +89 -0
  286. package/plugins/pbr/references/archive/limitations.md +106 -0
  287. package/plugins/pbr/references/archive/pbr-rules.md +194 -0
  288. package/plugins/pbr/references/archive/pbr-tools-cli.md +415 -0
  289. package/plugins/pbr/references/archive/pretooluse-jsonl-behavior.md +58 -0
  290. package/plugins/pbr/references/archive/signal-files.md +41 -0
  291. package/plugins/pbr/references/archive/tmux-setup.md +288 -0
  292. package/plugins/pbr/references/archive/verification-matrix.md +34 -0
  293. package/plugins/pbr/references/archive/verification-patterns.md +277 -0
  294. package/plugins/pbr/references/archive/worktree-sparse-checkout.md +86 -0
  295. package/plugins/pbr/references/assumptions.md +42 -0
  296. package/plugins/pbr/references/checkpoints.md +723 -104
  297. package/plugins/pbr/references/config-reference.md +387 -10
  298. package/plugins/pbr/references/continuation-format.md +1 -0
  299. package/plugins/pbr/references/decimal-phase-calculation.md +65 -0
  300. package/plugins/pbr/references/deviation-rules.md +12 -0
  301. package/plugins/pbr/references/few-shot-examples/audit.md +77 -0
  302. package/plugins/pbr/references/few-shot-examples/check-plan-format.md +172 -0
  303. package/plugins/pbr/references/few-shot-examples/check-subagent-output.md +118 -0
  304. package/plugins/pbr/references/few-shot-examples/integration-checker.md +70 -0
  305. package/plugins/pbr/references/few-shot-examples/nyquist-auditor.md +83 -0
  306. package/plugins/pbr/references/few-shot-examples/plan-checker.md +73 -0
  307. package/plugins/pbr/references/few-shot-examples/ui-checker.md +71 -0
  308. package/plugins/pbr/references/few-shot-examples/verifier.md +109 -0
  309. package/plugins/pbr/references/git-integration.md +110 -27
  310. package/plugins/pbr/references/git-planning-commit.md +35 -0
  311. package/plugins/pbr/references/model-profile-resolution.md +34 -0
  312. package/plugins/pbr/references/model-profiles.md +90 -7
  313. package/plugins/pbr/references/model-selection.md +1 -1
  314. package/plugins/pbr/references/node-repair.md +48 -0
  315. package/plugins/pbr/references/plan-authoring.md +65 -0
  316. package/plugins/pbr/references/plan-format.md +184 -10
  317. package/plugins/pbr/references/questioning.md +138 -49
  318. package/plugins/pbr/references/reading-verification.md +4 -4
  319. package/plugins/pbr/references/tdd.md +263 -0
  320. package/plugins/pbr/references/thinking-models-planning.md +47 -0
  321. package/plugins/pbr/references/thinking-models-verification.md +44 -0
  322. package/plugins/pbr/references/ui-brand.md +449 -0
  323. package/plugins/pbr/references/verification-overrides.md +39 -0
  324. package/plugins/pbr/references/verification-patterns.md +529 -113
  325. package/plugins/pbr/scripts/architecture-guard.js +76 -0
  326. package/plugins/pbr/scripts/audit-checks/behavioral-compliance.js +2098 -0
  327. package/plugins/pbr/scripts/audit-checks/error-analysis.js +989 -0
  328. package/plugins/pbr/scripts/audit-checks/feature-verification.js +723 -0
  329. package/plugins/pbr/scripts/audit-checks/index.js +433 -0
  330. package/plugins/pbr/scripts/audit-checks/infrastructure.js +816 -0
  331. package/plugins/pbr/scripts/audit-checks/quality-metrics.js +455 -0
  332. package/plugins/pbr/scripts/audit-checks/session-quality.js +980 -0
  333. package/plugins/pbr/scripts/audit-checks/si-agent-hook-config-checks.js +396 -0
  334. package/plugins/pbr/scripts/audit-checks/si-cross-cutting-checks.js +272 -0
  335. package/plugins/pbr/scripts/audit-checks/si-skill-checks.js +424 -0
  336. package/plugins/pbr/scripts/audit-checks/workflow-compliance.js +1175 -0
  337. package/plugins/pbr/scripts/audit-dimensions.js +556 -0
  338. package/plugins/pbr/scripts/auto-continue.js +192 -37
  339. package/plugins/pbr/scripts/block-skill-self-read.js +124 -0
  340. package/plugins/pbr/scripts/check-agent-state-write.js +63 -0
  341. package/plugins/pbr/scripts/check-config-change.js +84 -1
  342. package/plugins/pbr/scripts/check-cross-plugin-sync.js +93 -0
  343. package/plugins/pbr/scripts/check-dangerous-commands.js +18 -5
  344. package/plugins/pbr/scripts/check-direct-state-write.js +37 -0
  345. package/plugins/pbr/scripts/check-phase-boundary.js +3 -2
  346. package/plugins/pbr/scripts/check-plan-format.js +153 -354
  347. package/plugins/pbr/scripts/check-read-first.js +345 -0
  348. package/plugins/pbr/scripts/check-roadmap-sync.js +174 -19
  349. package/plugins/pbr/scripts/check-skill-workflow.js +21 -16
  350. package/plugins/pbr/scripts/check-state-sync.js +352 -220
  351. package/plugins/pbr/scripts/check-subagent-output.js +296 -333
  352. package/plugins/pbr/scripts/check-summary-gate.js +5 -15
  353. package/plugins/pbr/scripts/commands/benchmarks.js +195 -0
  354. package/plugins/pbr/scripts/commands/calibrate.js +530 -0
  355. package/plugins/pbr/scripts/commands/config.js +72 -0
  356. package/plugins/pbr/scripts/commands/misc.js +779 -0
  357. package/plugins/pbr/scripts/commands/phase.js +293 -0
  358. package/plugins/pbr/scripts/commands/roadmap.js +75 -0
  359. package/plugins/pbr/scripts/commands/state.js +84 -0
  360. package/plugins/pbr/scripts/commands/stress-test.js +349 -0
  361. package/plugins/pbr/scripts/commands/todo.js +191 -0
  362. package/plugins/pbr/scripts/commands/verify.js +169 -0
  363. package/plugins/pbr/scripts/config-schema.json +1183 -95
  364. package/plugins/pbr/scripts/context-bridge.js +425 -0
  365. package/plugins/pbr/scripts/context-budget-check.js +171 -16
  366. package/plugins/pbr/scripts/context-quality.js +271 -0
  367. package/plugins/pbr/scripts/enforce-context-budget.js +138 -0
  368. package/plugins/pbr/scripts/enforce-pbr-workflow.js +277 -0
  369. package/plugins/pbr/scripts/event-handler.js +137 -87
  370. package/plugins/pbr/scripts/event-logger.js +58 -25
  371. package/plugins/pbr/scripts/feedback-loop.js +155 -0
  372. package/plugins/pbr/scripts/graph-update.js +422 -0
  373. package/plugins/pbr/scripts/hook-logger.js +69 -35
  374. package/plugins/pbr/scripts/hook-server-client.js +361 -0
  375. package/plugins/pbr/scripts/hook-server.js +664 -0
  376. package/plugins/pbr/scripts/hooks-schema.json +12 -5
  377. package/plugins/pbr/scripts/instructions-loaded.js +173 -0
  378. package/plugins/pbr/scripts/intent-router.cjs +147 -0
  379. package/plugins/pbr/scripts/intercept-plan-mode.js +52 -18
  380. package/plugins/pbr/scripts/lib/alternatives.js +203 -0
  381. package/plugins/pbr/scripts/lib/audit.js +65 -0
  382. package/plugins/pbr/scripts/lib/auto-cleanup.js +221 -0
  383. package/plugins/pbr/scripts/lib/auto-verify.js +123 -0
  384. package/plugins/pbr/scripts/lib/benchmark.js +190 -0
  385. package/plugins/pbr/scripts/lib/build.js +719 -0
  386. package/plugins/pbr/scripts/lib/ci-fix-loop.js +228 -0
  387. package/plugins/pbr/scripts/lib/commands.js +483 -0
  388. package/plugins/pbr/scripts/lib/compound.js +222 -0
  389. package/plugins/pbr/scripts/lib/config-cache.js +83 -0
  390. package/plugins/pbr/scripts/lib/config.js +1469 -0
  391. package/plugins/pbr/scripts/lib/context.js +254 -0
  392. package/plugins/pbr/scripts/lib/contextual-help.js +183 -0
  393. package/plugins/pbr/scripts/lib/convention-detector.js +413 -0
  394. package/plugins/pbr/scripts/lib/core.js +1585 -0
  395. package/plugins/pbr/scripts/lib/dashboard-launch.js +364 -0
  396. package/plugins/pbr/scripts/lib/data-hygiene.js +179 -0
  397. package/plugins/pbr/scripts/lib/decision-extraction.js +183 -0
  398. package/plugins/pbr/scripts/lib/decisions.js +194 -0
  399. package/plugins/pbr/scripts/lib/dependency-break.js +147 -0
  400. package/plugins/pbr/scripts/lib/format-validators.js +1049 -0
  401. package/plugins/pbr/scripts/lib/frontmatter.js +302 -0
  402. package/plugins/pbr/scripts/lib/gates/advisories.js +133 -0
  403. package/plugins/pbr/scripts/lib/gates/build-dependency.js +118 -0
  404. package/plugins/pbr/scripts/lib/gates/build-executor.js +106 -0
  405. package/plugins/pbr/scripts/lib/gates/doc-existence.js +46 -0
  406. package/plugins/pbr/scripts/lib/gates/helpers.js +98 -0
  407. package/plugins/pbr/scripts/lib/gates/inline-execution.js +187 -0
  408. package/plugins/pbr/scripts/lib/gates/milestone-complete.js +139 -0
  409. package/plugins/pbr/scripts/lib/gates/milestone-summary.js +121 -0
  410. package/plugins/pbr/scripts/lib/gates/multi-phase-loader.js +149 -0
  411. package/plugins/pbr/scripts/lib/gates/plan-executor.js +36 -0
  412. package/plugins/pbr/scripts/lib/gates/plan-validation.js +115 -0
  413. package/plugins/pbr/scripts/lib/gates/quick-executor.js +78 -0
  414. package/plugins/pbr/scripts/lib/gates/review-planner.js +63 -0
  415. package/plugins/pbr/scripts/lib/gates/review-verifier.js +71 -0
  416. package/plugins/pbr/scripts/lib/gates/rich-agent-context.js +148 -0
  417. package/plugins/pbr/scripts/lib/gates/sprint-preflight.js +30 -0
  418. package/plugins/pbr/scripts/lib/gates/user-confirmation.js +95 -0
  419. package/plugins/pbr/scripts/lib/graph-cli.js +89 -0
  420. package/plugins/pbr/scripts/lib/graph.js +553 -0
  421. package/plugins/pbr/scripts/lib/handoff-validators.js +224 -0
  422. package/plugins/pbr/scripts/lib/health-checks.js +107 -0
  423. package/plugins/pbr/scripts/lib/health-phase06.js +120 -0
  424. package/plugins/pbr/scripts/lib/health.js +132 -0
  425. package/plugins/pbr/scripts/lib/help.js +100 -0
  426. package/plugins/pbr/scripts/lib/history.js +150 -0
  427. package/plugins/pbr/scripts/lib/impact-analysis.js +319 -0
  428. package/plugins/pbr/scripts/lib/incidents.js +190 -0
  429. package/plugins/pbr/scripts/lib/init.js +643 -0
  430. package/plugins/pbr/scripts/lib/insights-parser.js +320 -0
  431. package/plugins/pbr/scripts/lib/intel.js +653 -0
  432. package/plugins/pbr/scripts/lib/learnings.js +511 -0
  433. package/plugins/pbr/scripts/lib/migrate.js +309 -0
  434. package/plugins/pbr/scripts/lib/milestone.js +306 -0
  435. package/plugins/pbr/scripts/lib/msys-path.js +20 -0
  436. package/plugins/pbr/scripts/lib/negative-knowledge.js +194 -0
  437. package/plugins/pbr/scripts/lib/notification-throttle.js +141 -0
  438. package/plugins/pbr/scripts/lib/onboarding-generator.js +288 -0
  439. package/plugins/pbr/scripts/lib/parse-args.js +134 -0
  440. package/plugins/pbr/scripts/lib/pattern-routing.js +55 -0
  441. package/plugins/pbr/scripts/lib/patterns.js +272 -0
  442. package/plugins/pbr/scripts/lib/perf.js +190 -0
  443. package/plugins/pbr/scripts/lib/phase.js +1043 -0
  444. package/plugins/pbr/scripts/lib/pid-lock.js +156 -0
  445. package/plugins/pbr/scripts/lib/post-hoc.js +160 -0
  446. package/plugins/pbr/scripts/lib/pre-commit-checks.js +220 -0
  447. package/plugins/pbr/scripts/lib/pre-research.js +126 -0
  448. package/plugins/pbr/scripts/lib/premature-completion.js +312 -0
  449. package/plugins/pbr/scripts/lib/preview.js +174 -0
  450. package/plugins/pbr/scripts/lib/progress-visualization.js +296 -0
  451. package/plugins/pbr/scripts/lib/quick-init.js +131 -0
  452. package/plugins/pbr/scripts/lib/reference.js +236 -0
  453. package/plugins/pbr/scripts/lib/requirements.js +153 -0
  454. package/plugins/pbr/scripts/lib/resolve-root.js +66 -0
  455. package/plugins/pbr/scripts/lib/reverse-spec.js +259 -0
  456. package/plugins/pbr/scripts/lib/roadmap.js +1089 -0
  457. package/plugins/pbr/scripts/lib/security-scan.js +200 -0
  458. package/plugins/pbr/scripts/lib/session-briefing.js +918 -0
  459. package/plugins/pbr/scripts/lib/skill-section.js +99 -0
  460. package/plugins/pbr/scripts/lib/smart-next-task.js +198 -0
  461. package/plugins/pbr/scripts/lib/snapshot-manager.js +232 -0
  462. package/plugins/pbr/scripts/lib/spec-diff.js +209 -0
  463. package/plugins/pbr/scripts/lib/spec-engine.js +189 -0
  464. package/plugins/pbr/scripts/lib/spot-check.js +539 -0
  465. package/plugins/pbr/scripts/lib/state-queue.js +171 -0
  466. package/plugins/pbr/scripts/lib/state.js +1082 -0
  467. package/plugins/pbr/scripts/lib/status-render.js +511 -0
  468. package/plugins/pbr/scripts/lib/step-verify.js +149 -0
  469. package/plugins/pbr/scripts/lib/subagent-validators.js +1119 -0
  470. package/plugins/pbr/scripts/lib/suggest-next.js +435 -0
  471. package/plugins/pbr/scripts/lib/tech-debt-scanner.js +116 -0
  472. package/plugins/pbr/scripts/lib/templates.js +362 -0
  473. package/plugins/pbr/scripts/lib/test-selection.js +163 -0
  474. package/plugins/pbr/scripts/lib/todo.js +300 -0
  475. package/plugins/pbr/scripts/lib/verify.js +1561 -0
  476. package/plugins/pbr/scripts/log-notification.js +131 -0
  477. package/plugins/pbr/scripts/log-subagent.js +221 -18
  478. package/plugins/pbr/scripts/log-tool-failure.js +60 -5
  479. package/plugins/pbr/scripts/milestone-learnings.js +519 -0
  480. package/plugins/pbr/scripts/package.json +1 -1
  481. package/plugins/pbr/scripts/pbr-tools.js +362 -1247
  482. package/plugins/pbr/scripts/post-bash-triage.js +96 -0
  483. package/plugins/pbr/scripts/post-compact.js +135 -0
  484. package/plugins/pbr/scripts/post-hoc.js +237 -0
  485. package/plugins/pbr/scripts/post-write-dispatch.js +201 -31
  486. package/plugins/pbr/scripts/post-write-quality.js +4 -3
  487. package/plugins/pbr/scripts/pre-bash-dispatch.js +147 -51
  488. package/plugins/pbr/scripts/pre-skill-dispatch.js +114 -0
  489. package/plugins/pbr/scripts/pre-task-dispatch.js +269 -0
  490. package/plugins/pbr/scripts/pre-write-dispatch.js +170 -72
  491. package/plugins/pbr/scripts/progress-tracker.js +121 -324
  492. package/plugins/pbr/scripts/prompt-guard.js +114 -0
  493. package/plugins/pbr/scripts/prompt-routing.js +209 -0
  494. package/plugins/pbr/scripts/quick-status.js +179 -0
  495. package/plugins/pbr/scripts/record-incident.js +37 -0
  496. package/plugins/pbr/scripts/risk-classifier.cjs +123 -0
  497. package/plugins/pbr/scripts/run-hook.js +63 -23
  498. package/plugins/pbr/scripts/session-cleanup.js +428 -29
  499. package/plugins/pbr/scripts/session-tracker.js +124 -0
  500. package/plugins/pbr/scripts/status-line.js +571 -43
  501. package/plugins/pbr/scripts/suggest-compact.js +201 -13
  502. package/plugins/pbr/scripts/sync-context-to-claude.js +100 -0
  503. package/plugins/pbr/scripts/task-completed.js +165 -4
  504. package/plugins/pbr/scripts/test/config.test.js +126 -0
  505. package/plugins/pbr/scripts/test/cross-platform.test.js +120 -0
  506. package/plugins/pbr/scripts/test/fixtures/config.json +20 -0
  507. package/plugins/pbr/scripts/test/fixtures/plan.md +54 -0
  508. package/plugins/pbr/scripts/test/fixtures/project.md +30 -0
  509. package/plugins/pbr/scripts/test/fixtures/roadmap.md +55 -0
  510. package/plugins/pbr/scripts/test/fixtures/state.md +60 -0
  511. package/plugins/pbr/scripts/test/fixtures/summary.md +35 -0
  512. package/plugins/pbr/scripts/test/fixtures.test.js +184 -0
  513. package/plugins/pbr/scripts/test/phase.test.js +142 -0
  514. package/plugins/pbr/scripts/test/roadmap.test.js +96 -0
  515. package/plugins/pbr/scripts/test/state.test.js +155 -0
  516. package/plugins/pbr/scripts/track-context-budget.js +368 -104
  517. package/plugins/pbr/scripts/track-user-gates.js +88 -0
  518. package/plugins/pbr/scripts/trust-tracker.js +193 -0
  519. package/plugins/pbr/scripts/validate-commit.js +51 -19
  520. package/plugins/pbr/scripts/validate-skill-args.js +85 -14
  521. package/plugins/pbr/scripts/validate-task.js +83 -622
  522. package/plugins/pbr/scripts/worktree-create.js +144 -0
  523. package/plugins/pbr/scripts/worktree-remove.js +147 -0
  524. package/plugins/pbr/skills/audit/SKILL.md +195 -24
  525. package/plugins/pbr/skills/audit-fix/SKILL.md +326 -0
  526. package/plugins/pbr/skills/autonomous/SKILL.md +551 -0
  527. package/plugins/pbr/skills/backlog/SKILL.md +56 -0
  528. package/plugins/pbr/skills/begin/SKILL.md +508 -153
  529. package/plugins/pbr/skills/begin/templates/STATE.md.tmpl +1 -2
  530. package/plugins/pbr/skills/begin/templates/config.json.tmpl +419 -36
  531. package/plugins/pbr/skills/begin/templates/researcher-prompt.md.tmpl +28 -0
  532. package/plugins/pbr/skills/begin/templates/roadmap-prompt.md.tmpl +28 -3
  533. package/plugins/pbr/skills/begin/templates/synthesis-prompt.md.tmpl +33 -5
  534. package/plugins/pbr/skills/build/SKILL.md +1180 -357
  535. package/plugins/pbr/skills/build/templates/continuation-prompt.md.tmpl +26 -0
  536. package/plugins/pbr/skills/build/templates/executor-prompt.md.tmpl +77 -0
  537. package/plugins/pbr/skills/build/templates/inline-verifier-prompt.md.tmpl +33 -0
  538. package/plugins/pbr/skills/build/templates/qa-round-context.md.tmpl +16 -0
  539. package/plugins/pbr/skills/config/SKILL.md +112 -9
  540. package/plugins/pbr/skills/continue/SKILL.md +113 -33
  541. package/plugins/pbr/skills/dashboard/SKILL.md +21 -9
  542. package/plugins/pbr/skills/debug/SKILL.md +70 -12
  543. package/plugins/pbr/skills/debug/templates/continuation-prompt.md.tmpl +12 -1
  544. package/plugins/pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +12 -5
  545. package/plugins/pbr/skills/discuss/SKILL.md +205 -24
  546. package/plugins/pbr/skills/discuss/templates/CONTEXT.md.tmpl +21 -1
  547. package/plugins/pbr/skills/do/SKILL.md +119 -24
  548. package/plugins/pbr/skills/explore/SKILL.md +95 -20
  549. package/plugins/pbr/skills/fast/SKILL.md +94 -0
  550. package/plugins/pbr/skills/forensics/SKILL.md +144 -0
  551. package/plugins/pbr/skills/health/SKILL.md +35 -115
  552. package/plugins/pbr/skills/help/SKILL.md +83 -123
  553. package/plugins/pbr/skills/import/SKILL.md +332 -13
  554. package/plugins/pbr/skills/intel/SKILL.md +131 -0
  555. package/plugins/pbr/skills/list-phase-assumptions/SKILL.md +231 -0
  556. package/plugins/pbr/skills/milestone/SKILL.md +383 -274
  557. package/plugins/pbr/skills/milestone/templates/audit-output.md.tmpl +76 -0
  558. package/plugins/pbr/skills/milestone/templates/complete-output.md.tmpl +32 -0
  559. package/plugins/pbr/skills/milestone/templates/edge-cases.md +54 -0
  560. package/plugins/pbr/skills/milestone/templates/gaps-output.md.tmpl +25 -0
  561. package/plugins/pbr/skills/milestone/templates/integration-checker-prompt.md.tmpl +25 -0
  562. package/plugins/pbr/skills/milestone/templates/new-output.md.tmpl +29 -0
  563. package/plugins/pbr/skills/milestone-summary/SKILL.md +86 -0
  564. package/plugins/pbr/skills/note/SKILL.md +20 -4
  565. package/plugins/pbr/skills/pause/SKILL.md +54 -14
  566. package/plugins/pbr/skills/pause/templates/continue-here.md.tmpl +33 -52
  567. package/plugins/pbr/skills/plan/SKILL.md +526 -280
  568. package/plugins/pbr/skills/plan/templates/checker-prompt.md.tmpl +20 -2
  569. package/plugins/pbr/skills/plan/templates/completion-output.md.tmpl +27 -0
  570. package/plugins/pbr/skills/plan/templates/planner-prompt.md.tmpl +43 -1
  571. package/plugins/pbr/skills/plan/templates/revision-prompt.md.tmpl +21 -5
  572. package/plugins/pbr/skills/profile/SKILL.md +185 -0
  573. package/plugins/pbr/skills/profile-user/SKILL.md +227 -0
  574. package/plugins/pbr/skills/quick/SKILL.md +435 -100
  575. package/plugins/pbr/skills/release/SKILL.md +206 -0
  576. package/plugins/pbr/skills/resume/SKILL.md +170 -46
  577. package/plugins/pbr/skills/review/SKILL.md +233 -165
  578. package/plugins/pbr/skills/review/templates/verifier-prompt.md.tmpl +7 -0
  579. package/plugins/pbr/skills/scan/SKILL.md +152 -106
  580. package/plugins/pbr/skills/scan/templates/mapper-prompt.md.tmpl +5 -56
  581. package/plugins/pbr/skills/seed/SKILL.md +87 -0
  582. package/plugins/pbr/skills/session-report/SKILL.md +130 -0
  583. package/plugins/pbr/skills/setup/SKILL.md +150 -202
  584. package/plugins/pbr/skills/shared/agent-context-enrichment.md +21 -0
  585. package/plugins/pbr/skills/shared/agent-type-resolution.md +32 -0
  586. package/plugins/pbr/skills/shared/commit-planning-docs.md +8 -0
  587. package/plugins/pbr/skills/shared/context-budget.md +66 -1
  588. package/plugins/pbr/skills/shared/context-loader-task.md +18 -11
  589. package/plugins/pbr/skills/shared/criterion-writing.md +58 -0
  590. package/plugins/pbr/skills/shared/digest-select.md +2 -2
  591. package/plugins/pbr/skills/shared/domain-probes.md +1 -1
  592. package/plugins/pbr/skills/shared/error-reporting.md +38 -60
  593. package/plugins/pbr/skills/shared/gate-prompts.md +4 -2
  594. package/plugins/pbr/skills/shared/memory-capture.md +48 -0
  595. package/plugins/pbr/skills/shared/phase-argument-parsing.md +4 -4
  596. package/plugins/pbr/skills/shared/revision-loop.md +24 -6
  597. package/plugins/pbr/skills/shared/state-update.md +46 -61
  598. package/plugins/pbr/skills/shared/universal-anti-patterns.md +27 -4
  599. package/plugins/pbr/skills/ship/SKILL.md +155 -0
  600. package/plugins/pbr/skills/stats/SKILL.md +110 -0
  601. package/plugins/pbr/skills/status/SKILL.md +185 -119
  602. package/plugins/pbr/skills/test/SKILL.md +254 -0
  603. package/plugins/pbr/skills/thread/SKILL.md +73 -0
  604. package/plugins/pbr/skills/todo/SKILL.md +28 -72
  605. package/plugins/pbr/skills/ui-phase/SKILL.md +180 -0
  606. package/plugins/pbr/skills/ui-review/SKILL.md +206 -0
  607. package/plugins/pbr/skills/undo/SKILL.md +221 -0
  608. package/plugins/pbr/skills/validate-phase/SKILL.md +362 -0
  609. package/plugins/pbr/templates/CONTEXT.md.tmpl +45 -20
  610. package/plugins/pbr/templates/DISCOVERY.md.tmpl +29 -0
  611. package/plugins/pbr/templates/DISCUSSION-LOG.md.tmpl +49 -0
  612. package/plugins/pbr/templates/HANDOFF.json.tmpl +30 -0
  613. package/plugins/pbr/templates/INTEGRATION-REPORT.md.tmpl +18 -2
  614. package/plugins/pbr/templates/MILESTONE-AUDIT.md.tmpl +44 -0
  615. package/plugins/pbr/templates/PROJECT.md.tmpl +126 -0
  616. package/plugins/pbr/templates/REQUIREMENTS.md.tmpl +96 -0
  617. package/plugins/pbr/templates/RETROSPECTIVE.md.tmpl +43 -0
  618. package/plugins/pbr/templates/ROADMAP.md.tmpl +106 -14
  619. package/plugins/pbr/templates/SUMMARY-complex.md.tmpl +133 -0
  620. package/plugins/pbr/templates/SUMMARY-minimal.md.tmpl +55 -0
  621. package/plugins/pbr/templates/SUMMARY.md.tmpl +21 -0
  622. package/plugins/pbr/templates/UAT.md.tmpl +94 -0
  623. package/plugins/pbr/templates/UI-SPEC.md.tmpl +144 -0
  624. package/plugins/pbr/templates/VALIDATION.md.tmpl +94 -0
  625. package/plugins/pbr/templates/VERIFICATION-DETAIL.md.tmpl +54 -13
  626. package/plugins/pbr/templates/project-CONTEXT.md.tmpl +59 -0
  627. package/plugins/pbr/templates/research-outputs/ARCHITECTURE.md.tmpl +91 -0
  628. package/plugins/pbr/templates/research-outputs/FEATURES.md.tmpl +64 -0
  629. package/plugins/pbr/templates/research-outputs/PITFALLS.md.tmpl +50 -0
  630. package/plugins/pbr/templates/research-outputs/STACK.md.tmpl +63 -0
  631. package/plugins/pbr/templates/research-outputs/SUMMARY.md.tmpl +98 -0
  632. package/scripts/build-hooks.js +61 -0
  633. package/scripts/check-ci.js +100 -0
  634. package/scripts/clean-changelog.js +364 -0
  635. package/scripts/generate-derivatives.js +581 -0
  636. package/scripts/posttest.js +93 -0
  637. package/scripts/release.js +262 -0
  638. package/scripts/run-tests.cjs +29 -0
  639. package/scripts/test-wrapper.js +43 -0
  640. package/dashboard/bin/cli.js +0 -25
  641. package/dashboard/public/css/layout.css +0 -704
  642. package/dashboard/public/css/status-colors.css +0 -98
  643. package/dashboard/public/css/tokens.css +0 -59
  644. package/dashboard/public/js/htmx-title.js +0 -5
  645. package/dashboard/public/js/sidebar-toggle.js +0 -34
  646. package/dashboard/public/js/sse-client.js +0 -100
  647. package/dashboard/public/js/theme-toggle.js +0 -46
  648. package/dashboard/src/app.js +0 -91
  649. package/dashboard/src/middleware/current-phase.js +0 -24
  650. package/dashboard/src/middleware/errorHandler.js +0 -52
  651. package/dashboard/src/middleware/notFoundHandler.js +0 -9
  652. package/dashboard/src/repositories/planning.repository.js +0 -130
  653. package/dashboard/src/routes/events.routes.js +0 -45
  654. package/dashboard/src/routes/index.routes.js +0 -35
  655. package/dashboard/src/routes/pages.routes.js +0 -426
  656. package/dashboard/src/server.js +0 -42
  657. package/dashboard/src/services/analytics.service.js +0 -141
  658. package/dashboard/src/services/dashboard.service.js +0 -309
  659. package/dashboard/src/services/milestone.service.js +0 -222
  660. package/dashboard/src/services/notes.service.js +0 -50
  661. package/dashboard/src/services/phase.service.js +0 -232
  662. package/dashboard/src/services/project.service.js +0 -57
  663. package/dashboard/src/services/roadmap.service.js +0 -258
  664. package/dashboard/src/services/sse.service.js +0 -58
  665. package/dashboard/src/services/todo.service.js +0 -272
  666. package/dashboard/src/services/watcher.service.js +0 -48
  667. package/dashboard/src/utils/cache.js +0 -55
  668. package/dashboard/src/views/analytics.ejs +0 -5
  669. package/dashboard/src/views/coming-soon.ejs +0 -11
  670. package/dashboard/src/views/dependencies.ejs +0 -5
  671. package/dashboard/src/views/error.ejs +0 -20
  672. package/dashboard/src/views/index.ejs +0 -5
  673. package/dashboard/src/views/milestone-detail.ejs +0 -5
  674. package/dashboard/src/views/milestones.ejs +0 -5
  675. package/dashboard/src/views/notes.ejs +0 -5
  676. package/dashboard/src/views/partials/analytics-content.ejs +0 -90
  677. package/dashboard/src/views/partials/breadcrumbs.ejs +0 -14
  678. package/dashboard/src/views/partials/dashboard-content.ejs +0 -84
  679. package/dashboard/src/views/partials/dependencies-content.ejs +0 -48
  680. package/dashboard/src/views/partials/empty-state.ejs +0 -7
  681. package/dashboard/src/views/partials/footer.ejs +0 -3
  682. package/dashboard/src/views/partials/head.ejs +0 -30
  683. package/dashboard/src/views/partials/header.ejs +0 -21
  684. package/dashboard/src/views/partials/layout-bottom.ejs +0 -43
  685. package/dashboard/src/views/partials/layout-top.ejs +0 -16
  686. package/dashboard/src/views/partials/milestone-detail-content.ejs +0 -20
  687. package/dashboard/src/views/partials/milestones-content.ejs +0 -88
  688. package/dashboard/src/views/partials/notes-content.ejs +0 -23
  689. package/dashboard/src/views/partials/phase-content.ejs +0 -193
  690. package/dashboard/src/views/partials/phase-doc-content.ejs +0 -38
  691. package/dashboard/src/views/partials/phases-content.ejs +0 -124
  692. package/dashboard/src/views/partials/roadmap-content.ejs +0 -180
  693. package/dashboard/src/views/partials/sidebar.ejs +0 -99
  694. package/dashboard/src/views/partials/todo-create-content.ejs +0 -54
  695. package/dashboard/src/views/partials/todo-detail-content.ejs +0 -42
  696. package/dashboard/src/views/partials/todos-content.ejs +0 -97
  697. package/dashboard/src/views/phase-detail.ejs +0 -5
  698. package/dashboard/src/views/phase-doc.ejs +0 -5
  699. package/dashboard/src/views/phases.ejs +0 -5
  700. package/dashboard/src/views/roadmap.ejs +0 -5
  701. package/dashboard/src/views/todo-create.ejs +0 -5
  702. package/dashboard/src/views/todo-detail.ejs +0 -5
  703. package/dashboard/src/views/todos.ejs +0 -5
  704. package/plugins/copilot-pbr/CHANGELOG.md +0 -19
  705. package/plugins/copilot-pbr/README.md +0 -139
  706. package/plugins/copilot-pbr/agents/audit.agent.md +0 -113
  707. package/plugins/copilot-pbr/agents/codebase-mapper.agent.md +0 -151
  708. package/plugins/copilot-pbr/agents/debugger.agent.md +0 -184
  709. package/plugins/copilot-pbr/agents/executor.agent.md +0 -269
  710. package/plugins/copilot-pbr/agents/general.agent.md +0 -89
  711. package/plugins/copilot-pbr/agents/integration-checker.agent.md +0 -121
  712. package/plugins/copilot-pbr/agents/plan-checker.agent.md +0 -208
  713. package/plugins/copilot-pbr/agents/planner.agent.md +0 -240
  714. package/plugins/copilot-pbr/agents/researcher.agent.md +0 -188
  715. package/plugins/copilot-pbr/agents/synthesizer.agent.md +0 -126
  716. package/plugins/copilot-pbr/agents/verifier.agent.md +0 -228
  717. package/plugins/copilot-pbr/hooks/hooks.json +0 -258
  718. package/plugins/copilot-pbr/plugin.json +0 -30
  719. package/plugins/copilot-pbr/references/agent-anti-patterns.md +0 -25
  720. package/plugins/copilot-pbr/references/agent-contracts.md +0 -297
  721. package/plugins/copilot-pbr/references/agent-interactions.md +0 -135
  722. package/plugins/copilot-pbr/references/agent-teams.md +0 -55
  723. package/plugins/copilot-pbr/references/checkpoints.md +0 -158
  724. package/plugins/copilot-pbr/references/common-bug-patterns.md +0 -14
  725. package/plugins/copilot-pbr/references/config-reference.md +0 -442
  726. package/plugins/copilot-pbr/references/continuation-format.md +0 -213
  727. package/plugins/copilot-pbr/references/deviation-rules.md +0 -113
  728. package/plugins/copilot-pbr/references/git-integration.md +0 -227
  729. package/plugins/copilot-pbr/references/integration-patterns.md +0 -118
  730. package/plugins/copilot-pbr/references/model-profiles.md +0 -100
  731. package/plugins/copilot-pbr/references/model-selection.md +0 -32
  732. package/plugins/copilot-pbr/references/pbr-rules.md +0 -195
  733. package/plugins/copilot-pbr/references/pbr-tools-cli.md +0 -285
  734. package/plugins/copilot-pbr/references/plan-authoring.md +0 -182
  735. package/plugins/copilot-pbr/references/plan-format.md +0 -288
  736. package/plugins/copilot-pbr/references/planning-config.md +0 -214
  737. package/plugins/copilot-pbr/references/questioning.md +0 -215
  738. package/plugins/copilot-pbr/references/reading-verification.md +0 -128
  739. package/plugins/copilot-pbr/references/stub-patterns.md +0 -161
  740. package/plugins/copilot-pbr/references/subagent-coordination.md +0 -120
  741. package/plugins/copilot-pbr/references/ui-formatting.md +0 -444
  742. package/plugins/copilot-pbr/references/verification-patterns.md +0 -199
  743. package/plugins/copilot-pbr/references/wave-execution.md +0 -96
  744. package/plugins/copilot-pbr/rules/pbr-workflow.mdc +0 -48
  745. package/plugins/copilot-pbr/setup.ps1 +0 -93
  746. package/plugins/copilot-pbr/setup.sh +0 -93
  747. package/plugins/copilot-pbr/skills/audit/SKILL.md +0 -330
  748. package/plugins/copilot-pbr/skills/begin/SKILL.md +0 -589
  749. package/plugins/copilot-pbr/skills/begin/templates/PROJECT.md.tmpl +0 -34
  750. package/plugins/copilot-pbr/skills/begin/templates/REQUIREMENTS.md.tmpl +0 -19
  751. package/plugins/copilot-pbr/skills/begin/templates/STATE.md.tmpl +0 -50
  752. package/plugins/copilot-pbr/skills/begin/templates/config.json.tmpl +0 -64
  753. package/plugins/copilot-pbr/skills/begin/templates/researcher-prompt.md.tmpl +0 -20
  754. package/plugins/copilot-pbr/skills/begin/templates/roadmap-prompt.md.tmpl +0 -31
  755. package/plugins/copilot-pbr/skills/begin/templates/synthesis-prompt.md.tmpl +0 -17
  756. package/plugins/copilot-pbr/skills/build/SKILL.md +0 -959
  757. package/plugins/copilot-pbr/skills/config/SKILL.md +0 -250
  758. package/plugins/copilot-pbr/skills/continue/SKILL.md +0 -159
  759. package/plugins/copilot-pbr/skills/dashboard/SKILL.md +0 -43
  760. package/plugins/copilot-pbr/skills/debug/SKILL.md +0 -508
  761. package/plugins/copilot-pbr/skills/debug/templates/continuation-prompt.md.tmpl +0 -17
  762. package/plugins/copilot-pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +0 -28
  763. package/plugins/copilot-pbr/skills/discuss/SKILL.md +0 -353
  764. package/plugins/copilot-pbr/skills/discuss/templates/CONTEXT.md.tmpl +0 -62
  765. package/plugins/copilot-pbr/skills/discuss/templates/decision-categories.md +0 -10
  766. package/plugins/copilot-pbr/skills/do/SKILL.md +0 -66
  767. package/plugins/copilot-pbr/skills/explore/SKILL.md +0 -373
  768. package/plugins/copilot-pbr/skills/health/SKILL.md +0 -283
  769. package/plugins/copilot-pbr/skills/health/templates/check-pattern.md.tmpl +0 -31
  770. package/plugins/copilot-pbr/skills/health/templates/output-format.md.tmpl +0 -64
  771. package/plugins/copilot-pbr/skills/help/SKILL.md +0 -193
  772. package/plugins/copilot-pbr/skills/import/SKILL.md +0 -502
  773. package/plugins/copilot-pbr/skills/milestone/SKILL.md +0 -806
  774. package/plugins/copilot-pbr/skills/milestone/templates/audit-report.md.tmpl +0 -49
  775. package/plugins/copilot-pbr/skills/milestone/templates/stats-file.md.tmpl +0 -31
  776. package/plugins/copilot-pbr/skills/note/SKILL.md +0 -213
  777. package/plugins/copilot-pbr/skills/pause/SKILL.md +0 -247
  778. package/plugins/copilot-pbr/skills/pause/templates/continue-here.md.tmpl +0 -72
  779. package/plugins/copilot-pbr/skills/plan/SKILL.md +0 -662
  780. package/plugins/copilot-pbr/skills/plan/templates/checker-prompt.md.tmpl +0 -22
  781. package/plugins/copilot-pbr/skills/plan/templates/gap-closure-prompt.md.tmpl +0 -33
  782. package/plugins/copilot-pbr/skills/plan/templates/planner-prompt.md.tmpl +0 -39
  783. package/plugins/copilot-pbr/skills/plan/templates/researcher-prompt.md.tmpl +0 -20
  784. package/plugins/copilot-pbr/skills/plan/templates/revision-prompt.md.tmpl +0 -24
  785. package/plugins/copilot-pbr/skills/quick/SKILL.md +0 -376
  786. package/plugins/copilot-pbr/skills/resume/SKILL.md +0 -399
  787. package/plugins/copilot-pbr/skills/review/SKILL.md +0 -653
  788. package/plugins/copilot-pbr/skills/review/templates/debugger-prompt.md.tmpl +0 -61
  789. package/plugins/copilot-pbr/skills/review/templates/gap-planner-prompt.md.tmpl +0 -41
  790. package/plugins/copilot-pbr/skills/review/templates/verifier-prompt.md.tmpl +0 -116
  791. package/plugins/copilot-pbr/skills/scan/SKILL.md +0 -299
  792. package/plugins/copilot-pbr/skills/scan/templates/mapper-prompt.md.tmpl +0 -202
  793. package/plugins/copilot-pbr/skills/setup/SKILL.md +0 -296
  794. package/plugins/copilot-pbr/skills/shared/commit-planning-docs.md +0 -36
  795. package/plugins/copilot-pbr/skills/shared/config-loading.md +0 -103
  796. package/plugins/copilot-pbr/skills/shared/context-budget.md +0 -41
  797. package/plugins/copilot-pbr/skills/shared/context-loader-task.md +0 -87
  798. package/plugins/copilot-pbr/skills/shared/digest-select.md +0 -80
  799. package/plugins/copilot-pbr/skills/shared/domain-probes.md +0 -126
  800. package/plugins/copilot-pbr/skills/shared/error-recovery-strategies.md +0 -51
  801. package/plugins/copilot-pbr/skills/shared/error-reporting.md +0 -81
  802. package/plugins/copilot-pbr/skills/shared/gate-prompts.md +0 -389
  803. package/plugins/copilot-pbr/skills/shared/phase-argument-parsing.md +0 -46
  804. package/plugins/copilot-pbr/skills/shared/progress-display.md +0 -53
  805. package/plugins/copilot-pbr/skills/shared/revision-loop.md +0 -82
  806. package/plugins/copilot-pbr/skills/shared/state-loading.md +0 -63
  807. package/plugins/copilot-pbr/skills/shared/state-update.md +0 -170
  808. package/plugins/copilot-pbr/skills/shared/universal-anti-patterns.md +0 -38
  809. package/plugins/copilot-pbr/skills/status/SKILL.md +0 -362
  810. package/plugins/copilot-pbr/skills/statusline/SKILL.md +0 -149
  811. package/plugins/copilot-pbr/skills/todo/SKILL.md +0 -279
  812. package/plugins/copilot-pbr/templates/CONTEXT.md.tmpl +0 -53
  813. package/plugins/copilot-pbr/templates/INTEGRATION-REPORT.md.tmpl +0 -152
  814. package/plugins/copilot-pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -98
  815. package/plugins/copilot-pbr/templates/ROADMAP.md.tmpl +0 -48
  816. package/plugins/copilot-pbr/templates/SUMMARY.md.tmpl +0 -82
  817. package/plugins/copilot-pbr/templates/VERIFICATION-DETAIL.md.tmpl +0 -117
  818. package/plugins/copilot-pbr/templates/codebase/ARCHITECTURE.md.tmpl +0 -98
  819. package/plugins/copilot-pbr/templates/codebase/CONCERNS.md.tmpl +0 -93
  820. package/plugins/copilot-pbr/templates/codebase/CONVENTIONS.md.tmpl +0 -104
  821. package/plugins/copilot-pbr/templates/codebase/INTEGRATIONS.md.tmpl +0 -78
  822. package/plugins/copilot-pbr/templates/codebase/STACK.md.tmpl +0 -78
  823. package/plugins/copilot-pbr/templates/codebase/STRUCTURE.md.tmpl +0 -80
  824. package/plugins/copilot-pbr/templates/codebase/TESTING.md.tmpl +0 -107
  825. package/plugins/copilot-pbr/templates/continue-here.md.tmpl +0 -74
  826. package/plugins/copilot-pbr/templates/prompt-partials/phase-project-context.md.tmpl +0 -38
  827. package/plugins/copilot-pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
  828. package/plugins/copilot-pbr/templates/research/STACK.md.tmpl +0 -71
  829. package/plugins/copilot-pbr/templates/research/SUMMARY.md.tmpl +0 -112
  830. package/plugins/copilot-pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
  831. package/plugins/copilot-pbr/templates/research-outputs/project-research.md.tmpl +0 -99
  832. package/plugins/copilot-pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
  833. package/plugins/cursor-pbr/.cursor-plugin/plugin.json +0 -32
  834. package/plugins/cursor-pbr/CHANGELOG.md +0 -15
  835. package/plugins/cursor-pbr/README.md +0 -123
  836. package/plugins/cursor-pbr/agents/audit.md +0 -178
  837. package/plugins/cursor-pbr/agents/codebase-mapper.md +0 -150
  838. package/plugins/cursor-pbr/agents/debugger.md +0 -183
  839. package/plugins/cursor-pbr/agents/executor.md +0 -268
  840. package/plugins/cursor-pbr/agents/general.md +0 -88
  841. package/plugins/cursor-pbr/agents/integration-checker.md +0 -120
  842. package/plugins/cursor-pbr/agents/plan-checker.md +0 -207
  843. package/plugins/cursor-pbr/agents/planner.md +0 -239
  844. package/plugins/cursor-pbr/agents/researcher.md +0 -187
  845. package/plugins/cursor-pbr/agents/synthesizer.md +0 -125
  846. package/plugins/cursor-pbr/agents/verifier.md +0 -227
  847. package/plugins/cursor-pbr/assets/.gitkeep +0 -0
  848. package/plugins/cursor-pbr/assets/logo.svg +0 -21
  849. package/plugins/cursor-pbr/hooks/hooks.json +0 -224
  850. package/plugins/cursor-pbr/references/agent-anti-patterns.md +0 -25
  851. package/plugins/cursor-pbr/references/agent-contracts.md +0 -297
  852. package/plugins/cursor-pbr/references/agent-interactions.md +0 -135
  853. package/plugins/cursor-pbr/references/agent-teams.md +0 -55
  854. package/plugins/cursor-pbr/references/checkpoints.md +0 -158
  855. package/plugins/cursor-pbr/references/common-bug-patterns.md +0 -14
  856. package/plugins/cursor-pbr/references/config-reference.md +0 -442
  857. package/plugins/cursor-pbr/references/continuation-format.md +0 -213
  858. package/plugins/cursor-pbr/references/deviation-rules.md +0 -113
  859. package/plugins/cursor-pbr/references/git-integration.md +0 -227
  860. package/plugins/cursor-pbr/references/integration-patterns.md +0 -118
  861. package/plugins/cursor-pbr/references/model-profiles.md +0 -100
  862. package/plugins/cursor-pbr/references/model-selection.md +0 -32
  863. package/plugins/cursor-pbr/references/pbr-rules.md +0 -195
  864. package/plugins/cursor-pbr/references/pbr-tools-cli.md +0 -285
  865. package/plugins/cursor-pbr/references/plan-authoring.md +0 -182
  866. package/plugins/cursor-pbr/references/plan-format.md +0 -288
  867. package/plugins/cursor-pbr/references/planning-config.md +0 -214
  868. package/plugins/cursor-pbr/references/questioning.md +0 -215
  869. package/plugins/cursor-pbr/references/reading-verification.md +0 -128
  870. package/plugins/cursor-pbr/references/stub-patterns.md +0 -161
  871. package/plugins/cursor-pbr/references/subagent-coordination.md +0 -120
  872. package/plugins/cursor-pbr/references/ui-formatting.md +0 -444
  873. package/plugins/cursor-pbr/references/verification-patterns.md +0 -199
  874. package/plugins/cursor-pbr/references/wave-execution.md +0 -96
  875. package/plugins/cursor-pbr/rules/pbr-workflow.mdc +0 -48
  876. package/plugins/cursor-pbr/setup.ps1 +0 -78
  877. package/plugins/cursor-pbr/setup.sh +0 -83
  878. package/plugins/cursor-pbr/skills/audit/SKILL.md +0 -331
  879. package/plugins/cursor-pbr/skills/begin/SKILL.md +0 -589
  880. package/plugins/cursor-pbr/skills/begin/templates/PROJECT.md.tmpl +0 -34
  881. package/plugins/cursor-pbr/skills/begin/templates/REQUIREMENTS.md.tmpl +0 -19
  882. package/plugins/cursor-pbr/skills/begin/templates/STATE.md.tmpl +0 -50
  883. package/plugins/cursor-pbr/skills/begin/templates/config.json.tmpl +0 -64
  884. package/plugins/cursor-pbr/skills/begin/templates/researcher-prompt.md.tmpl +0 -20
  885. package/plugins/cursor-pbr/skills/begin/templates/roadmap-prompt.md.tmpl +0 -31
  886. package/plugins/cursor-pbr/skills/begin/templates/synthesis-prompt.md.tmpl +0 -17
  887. package/plugins/cursor-pbr/skills/build/SKILL.md +0 -960
  888. package/plugins/cursor-pbr/skills/config/SKILL.md +0 -252
  889. package/plugins/cursor-pbr/skills/continue/SKILL.md +0 -159
  890. package/plugins/cursor-pbr/skills/dashboard/SKILL.md +0 -44
  891. package/plugins/cursor-pbr/skills/debug/SKILL.md +0 -512
  892. package/plugins/cursor-pbr/skills/debug/templates/continuation-prompt.md.tmpl +0 -17
  893. package/plugins/cursor-pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +0 -28
  894. package/plugins/cursor-pbr/skills/discuss/SKILL.md +0 -354
  895. package/plugins/cursor-pbr/skills/discuss/templates/CONTEXT.md.tmpl +0 -62
  896. package/plugins/cursor-pbr/skills/discuss/templates/decision-categories.md +0 -10
  897. package/plugins/cursor-pbr/skills/do/SKILL.md +0 -67
  898. package/plugins/cursor-pbr/skills/explore/SKILL.md +0 -376
  899. package/plugins/cursor-pbr/skills/health/SKILL.md +0 -283
  900. package/plugins/cursor-pbr/skills/health/templates/check-pattern.md.tmpl +0 -31
  901. package/plugins/cursor-pbr/skills/health/templates/output-format.md.tmpl +0 -64
  902. package/plugins/cursor-pbr/skills/help/SKILL.md +0 -193
  903. package/plugins/cursor-pbr/skills/import/SKILL.md +0 -505
  904. package/plugins/cursor-pbr/skills/milestone/SKILL.md +0 -807
  905. package/plugins/cursor-pbr/skills/milestone/templates/audit-report.md.tmpl +0 -49
  906. package/plugins/cursor-pbr/skills/milestone/templates/stats-file.md.tmpl +0 -31
  907. package/plugins/cursor-pbr/skills/note/SKILL.md +0 -214
  908. package/plugins/cursor-pbr/skills/pause/SKILL.md +0 -248
  909. package/plugins/cursor-pbr/skills/pause/templates/continue-here.md.tmpl +0 -72
  910. package/plugins/cursor-pbr/skills/plan/SKILL.md +0 -663
  911. package/plugins/cursor-pbr/skills/plan/templates/checker-prompt.md.tmpl +0 -22
  912. package/plugins/cursor-pbr/skills/plan/templates/gap-closure-prompt.md.tmpl +0 -33
  913. package/plugins/cursor-pbr/skills/plan/templates/planner-prompt.md.tmpl +0 -39
  914. package/plugins/cursor-pbr/skills/plan/templates/researcher-prompt.md.tmpl +0 -20
  915. package/plugins/cursor-pbr/skills/plan/templates/revision-prompt.md.tmpl +0 -24
  916. package/plugins/cursor-pbr/skills/quick/SKILL.md +0 -376
  917. package/plugins/cursor-pbr/skills/resume/SKILL.md +0 -399
  918. package/plugins/cursor-pbr/skills/review/SKILL.md +0 -654
  919. package/plugins/cursor-pbr/skills/review/templates/debugger-prompt.md.tmpl +0 -61
  920. package/plugins/cursor-pbr/skills/review/templates/gap-planner-prompt.md.tmpl +0 -41
  921. package/plugins/cursor-pbr/skills/review/templates/verifier-prompt.md.tmpl +0 -116
  922. package/plugins/cursor-pbr/skills/scan/SKILL.md +0 -300
  923. package/plugins/cursor-pbr/skills/scan/templates/mapper-prompt.md.tmpl +0 -202
  924. package/plugins/cursor-pbr/skills/setup/SKILL.md +0 -296
  925. package/plugins/cursor-pbr/skills/shared/commit-planning-docs.md +0 -36
  926. package/plugins/cursor-pbr/skills/shared/config-loading.md +0 -103
  927. package/plugins/cursor-pbr/skills/shared/context-budget.md +0 -41
  928. package/plugins/cursor-pbr/skills/shared/context-loader-task.md +0 -87
  929. package/plugins/cursor-pbr/skills/shared/digest-select.md +0 -80
  930. package/plugins/cursor-pbr/skills/shared/domain-probes.md +0 -126
  931. package/plugins/cursor-pbr/skills/shared/error-recovery-strategies.md +0 -51
  932. package/plugins/cursor-pbr/skills/shared/error-reporting.md +0 -81
  933. package/plugins/cursor-pbr/skills/shared/gate-prompts.md +0 -389
  934. package/plugins/cursor-pbr/skills/shared/phase-argument-parsing.md +0 -46
  935. package/plugins/cursor-pbr/skills/shared/progress-display.md +0 -53
  936. package/plugins/cursor-pbr/skills/shared/revision-loop.md +0 -82
  937. package/plugins/cursor-pbr/skills/shared/state-loading.md +0 -63
  938. package/plugins/cursor-pbr/skills/shared/state-update.md +0 -170
  939. package/plugins/cursor-pbr/skills/shared/universal-anti-patterns.md +0 -38
  940. package/plugins/cursor-pbr/skills/status/SKILL.md +0 -362
  941. package/plugins/cursor-pbr/skills/statusline/SKILL.md +0 -150
  942. package/plugins/cursor-pbr/skills/todo/SKILL.md +0 -280
  943. package/plugins/cursor-pbr/templates/CONTEXT.md.tmpl +0 -53
  944. package/plugins/cursor-pbr/templates/INTEGRATION-REPORT.md.tmpl +0 -152
  945. package/plugins/cursor-pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -98
  946. package/plugins/cursor-pbr/templates/ROADMAP.md.tmpl +0 -48
  947. package/plugins/cursor-pbr/templates/SUMMARY.md.tmpl +0 -82
  948. package/plugins/cursor-pbr/templates/VERIFICATION-DETAIL.md.tmpl +0 -117
  949. package/plugins/cursor-pbr/templates/codebase/ARCHITECTURE.md.tmpl +0 -98
  950. package/plugins/cursor-pbr/templates/codebase/CONCERNS.md.tmpl +0 -93
  951. package/plugins/cursor-pbr/templates/codebase/CONVENTIONS.md.tmpl +0 -104
  952. package/plugins/cursor-pbr/templates/codebase/INTEGRATIONS.md.tmpl +0 -78
  953. package/plugins/cursor-pbr/templates/codebase/STACK.md.tmpl +0 -78
  954. package/plugins/cursor-pbr/templates/codebase/STRUCTURE.md.tmpl +0 -80
  955. package/plugins/cursor-pbr/templates/codebase/TESTING.md.tmpl +0 -107
  956. package/plugins/cursor-pbr/templates/continue-here.md.tmpl +0 -74
  957. package/plugins/cursor-pbr/templates/prompt-partials/phase-project-context.md.tmpl +0 -38
  958. package/plugins/cursor-pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
  959. package/plugins/cursor-pbr/templates/research/STACK.md.tmpl +0 -71
  960. package/plugins/cursor-pbr/templates/research/SUMMARY.md.tmpl +0 -112
  961. package/plugins/cursor-pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
  962. package/plugins/cursor-pbr/templates/research-outputs/project-research.md.tmpl +0 -99
  963. package/plugins/cursor-pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
  964. package/plugins/pbr/references/agent-interactions.md +0 -134
  965. package/plugins/pbr/references/pbr-rules.md +0 -194
  966. package/plugins/pbr/references/pbr-tools-cli.md +0 -285
  967. package/plugins/pbr/references/planning-config.md +0 -213
  968. package/plugins/pbr/references/subagent-coordination.md +0 -119
  969. package/plugins/pbr/references/ui-formatting.md +0 -444
  970. package/plugins/pbr/scripts/validate-plugin-structure.js +0 -183
  971. package/plugins/pbr/skills/milestone/templates/audit-report.md.tmpl +0 -48
  972. package/plugins/pbr/skills/shared/error-recovery-strategies.md +0 -51
  973. package/plugins/pbr/skills/shared/progress-display.md +0 -53
  974. package/plugins/pbr/skills/shared/state-loading.md +0 -62
  975. package/plugins/pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -97
  976. package/plugins/pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
  977. package/plugins/pbr/templates/research/STACK.md.tmpl +0 -71
  978. package/plugins/pbr/templates/research/SUMMARY.md.tmpl +0 -112
  979. package/plugins/pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
  980. package/plugins/pbr/templates/research-outputs/project-research.md.tmpl +0 -99
  981. package/plugins/pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
  982. /package/plugins/pbr/references/{agent-anti-patterns.md → archive/agent-anti-patterns.md} +0 -0
@@ -3,1376 +3,491 @@
3
3
  /**
4
4
  * pbr-tools.js — Structured JSON state operations for Plan-Build-Run skills.
5
5
  *
6
- * Provides read-only commands that return JSON, replacing LLM-based text parsing
7
- * of STATE.md, ROADMAP.md, and config.json. Skills call this via:
8
- * node ${CLAUDE_PLUGIN_ROOT}/scripts/pbr-tools.js <command> [args]
6
+ * Thin router that delegates CLI commands to handler modules in commands/.
7
+ * Core logic lives in lib/ modules. Wrapper functions here provide backward
8
+ * compatibility for hook scripts and tests that require('./pbr-tools').
9
9
  *
10
- * Commands:
11
- * state load Full project state as JSON
12
- * state check-progress Recalculate progress from filesystem
13
- * state update <f> <v> Atomically update a STATE.md field
14
- * config validate Validate config.json against schema
15
- * plan-index <phase> Plan inventory for a phase, grouped by wave
16
- * frontmatter <filepath> Parse .md file's YAML frontmatter → JSON
17
- * must-haves <phase> Collect all must-haves from phase plans JSON
18
- * phase-info <phase> — Comprehensive single-phase status → JSON
19
- * roadmap update-status <phase> <status> — Update phase status in ROADMAP.md
20
- * roadmap update-plans <phase> <complete> <total> — Update phase plans in ROADMAP.md
21
- * history append <type> <title> [body] — Append record to HISTORY.md
22
- * history load — Load all HISTORY.md records as JSON
23
- */
24
-
25
- const fs = require('fs');
26
- const path = require('path');
27
-
28
- const cwd = process.cwd();
29
- const planningDir = path.join(cwd, '.planning');
30
-
31
- // --- Phase status transition state machine ---
32
-
33
- /**
34
- * Valid phase status transitions. Each key is a current status, and its value
35
- * is an array of statuses that are legal to transition to. This is advisory —
36
- * invalid transitions produce a stderr warning but are not blocked, to avoid
37
- * breaking existing workflows.
10
+ * Command modules:
11
+ * commands/state.js state, state-bundle
12
+ * commands/config.js config, validate
13
+ * commands/roadmap.jsroadmap
14
+ * commands/phase.js phase, compound, init, plan-index, frontmatter, must-haves, phase-info, milestone-stats
15
+ * commands/verify.js verify, spot-check, staleness-check, summary-gate, checkpoint, seeds
16
+ * commands/todo.js todo, history, auto-cleanup
17
+ * commands/misc.js — all remaining (intel, learnings, session, claim, spec, help, etc.)
38
18
  *
39
- * State machine:
40
- * pending -> planned, skipped
41
- * planned -> building
42
- * building -> built, partial, needs_fixes
43
- * built -> verified, needs_fixes
44
- * partial -> building, needs_fixes
45
- * verified -> building (re-execution)
46
- * needs_fixes -> planned, building
47
- * skipped -> pending (unskip)
48
- */
49
- const VALID_STATUS_TRANSITIONS = {
50
- pending: ['planned', 'skipped'],
51
- planned: ['building'],
52
- building: ['built', 'partial', 'needs_fixes'],
53
- built: ['verified', 'needs_fixes'],
54
- partial: ['building', 'needs_fixes'],
55
- verified: ['building'],
56
- needs_fixes: ['planned', 'building'],
57
- skipped: ['pending']
58
- };
59
-
60
- /**
61
- * Check whether a phase status transition is valid according to the state machine.
62
- * Returns { valid, warning? } — never blocks, only advises.
19
+ * Usage: node ${CLAUDE_PLUGIN_ROOT}/scripts/pbr-tools.js <command> [args]
20
+ * Run `pbr-tools.js help` for full command listing.
63
21
  *
64
- * @param {string} oldStatus - Current phase status
65
- * @param {string} newStatus - Desired phase status
66
- * @returns {{ valid: boolean, warning?: string }}
22
+ * Environment: PBR_PROJECT_ROOT Override project root directory
67
23
  */
68
- function validateStatusTransition(oldStatus, newStatus) {
69
- const from = (oldStatus || '').trim().toLowerCase();
70
- const to = (newStatus || '').trim().toLowerCase();
71
24
 
72
- // If the status isn't changing, that's always fine
73
- if (from === to) {
74
- return { valid: true };
75
- }
76
-
77
- // If the old status is unknown to our map, we can't validate — allow it
78
- if (!VALID_STATUS_TRANSITIONS[from]) {
79
- return { valid: true };
80
- }
81
-
82
- const allowed = VALID_STATUS_TRANSITIONS[from];
83
- if (allowed.includes(to)) {
84
- return { valid: true };
85
- }
86
-
87
- return {
88
- valid: false,
89
- warning: `Suspicious status transition: "${from}" -> "${to}". Expected one of: [${allowed.join(', ')}]. Proceeding anyway (advisory).`
90
- };
91
- }
92
-
93
- // --- Cached config loader ---
25
+ const fs = require('fs');
26
+ const path = require('path');
94
27
 
95
- let _configCache = null;
96
- let _configMtime = 0;
97
- let _configPath = null;
28
+ // --- Import lib modules (used by wrapper functions for backward-compat exports) ---
29
+ const { KNOWN_AGENTS, VALID_STATUS_TRANSITIONS, validateStatusTransition, output, error,
30
+ parseYamlFrontmatter, parseMustHaves, findFiles, tailLines, countMustHaves,
31
+ determinePhaseStatus, atomicWrite, lockedFileUpdate, writeActiveSkill,
32
+ sessionLoad, sessionSave, SESSION_ALLOWED_KEYS, acquireClaim, releaseClaim,
33
+ listClaims: _listClaims } = require('./lib/core');
34
+ const { configLoad: _configLoad, configClearCache: _configClearCache,
35
+ configValidate: _configValidate, resolveDepthProfile, DEPTH_PROFILE_DEFAULTS,
36
+ loadUserDefaults, saveUserDefaults, mergeUserDefaults, USER_DEFAULTS_PATH } = require('./lib/config');
37
+ const { parseStateMd, updateFrontmatterField, stateLoad: _stateLoad,
38
+ stateCheckProgress: _stateCheckProgress, stateUpdate: _stateUpdate,
39
+ statePatch: _statePatch, stateAdvancePlan: _stateAdvancePlan,
40
+ stateRecordMetric: _stateRecordMetric, stateRecordActivity: _stateRecordActivity,
41
+ stateUpdateProgress: _stateUpdateProgress, stateReconcile: _stateReconcile,
42
+ stateBackup: _stateBackup } = require('./lib/state');
43
+ const { parseRoadmapMd, findRoadmapRow, updateTableRow,
44
+ roadmapUpdateStatus: _roadmapUpdateStatus, roadmapUpdatePlans: _roadmapUpdatePlans,
45
+ roadmapAnalyze: _roadmapAnalyze } = require('./lib/roadmap');
46
+ const { frontmatter: _frontmatter, planIndex: _planIndex,
47
+ mustHavesCollect: _mustHavesCollect, phaseInfo: _phaseInfo, phaseAdd: _phaseAdd,
48
+ phaseRemove: _phaseRemove, phaseList: _phaseList, milestoneStats: _milestoneStats,
49
+ phaseComplete: _phaseComplete, phaseInsert: _phaseInsert,
50
+ phaseNextNumber: _phaseNextNumber } = require('./lib/phase');
51
+ const { compoundInitPhase: _compoundInitPhase, compoundCompletePhase: _compoundCompletePhase,
52
+ compoundInitMilestone: _compoundInitMilestone } = require('./lib/compound');
53
+ const { initExecutePhase: _initExecutePhase, initPlanPhase: _initPlanPhase,
54
+ initQuick: _initQuick, initVerifyWork: _initVerifyWork, initResume: _initResume,
55
+ initProgress: _initProgress, initStateBundle: _initStateBundle,
56
+ initContinue: _initContinue, initMilestone: _initMilestone, initBegin: _initBegin,
57
+ initStatus: _initStatus, initMapCodebase: _initMapCodebase } = require('./lib/init');
58
+ const { historyAppend: _historyAppend, historyLoad: _historyLoad } = require('./lib/history');
59
+ const { todoList: _todoList, todoGet: _todoGet, todoAdd: _todoAdd, todoDone: _todoDone } = require('./lib/todo');
60
+ const { autoCloseTodos: _autoCloseTodos, autoArchiveNotes: _autoArchiveNotes } = require('./lib/auto-cleanup');
61
+ const { applyMigrations: _applyMigrations } = require('./lib/migrate');
62
+ const { verifySpotCheck: _verifySpotCheck } = require('./lib/spot-check');
63
+ const { referenceGet: _referenceGet } = require('./lib/reference');
64
+ const { skillSection: _skillSection, listAvailableSkills: _listAvailableSkills } = require('./lib/skill-section');
65
+ const { helpList: _helpList, skillMetadata: _skillMetadata } = require('./lib/help');
66
+ const { stepVerify: _stepVerify } = require('./lib/step-verify');
67
+ const { contextTriage: _contextTriage } = require('./lib/context');
68
+ const { phaseAlternatives: _phaseAlternatives, prerequisiteAlternatives: _prereqAlternatives,
69
+ configAlternatives: _configAlternatives } = require('./lib/alternatives');
70
+ const { stalenessCheck: _stalenessCheck, summaryGate: _summaryGate,
71
+ checkpointInit: _checkpointInit, checkpointUpdate: _checkpointUpdate,
72
+ seedsMatch: _seedsMatch, ciPoll: _ciPoll, rollback: _rollback } = require('./lib/build');
73
+ const { parseJestOutput: _parseJestOutput, parseLintOutput: _parseLintOutput,
74
+ autoFixLint: _autoFixLint, runCiFixLoop: _runCiFixLoop } = require('./lib/ci-fix-loop');
75
+ const { quickStatus: _quickStatus } = require('./quick-status');
76
+
77
+ // --- Command modules (CLI dispatch handlers) ---
78
+ const { handleState, handleStateBundle } = require('./commands/state');
79
+ const { handleConfig } = require('./commands/config');
80
+ const { handleRoadmap } = require('./commands/roadmap');
81
+ const { handlePhase, handleCompound, handleInit, handlePhaseDirect } = require('./commands/phase');
82
+ const { handleVerify, handleSpotCheckDirect, handleStalenessCheck, handleSummaryGate, handleCheckpoint, handleSeeds } = require('./commands/verify');
83
+ const { handleTodo, handleHistory, handleAutoCleanup } = require('./commands/todo');
84
+ const { handleMisc } = require('./commands/misc');
85
+ const { handleBenchmarks } = require('./commands/benchmarks');
86
+ const { handleCalibrate } = require('./commands/calibrate');
87
+ const { handleStressTest } = require('./commands/stress-test');
88
+ const { normalizeMsysPath } = require('./lib/msys-path');
89
+
90
+ // --- Module-level state (for backwards compatibility) ---
91
+
92
+ let cwd = process.env.PBR_PROJECT_ROOT || process.cwd();
93
+ cwd = normalizeMsysPath(cwd);
94
+ let planningDir = path.join(cwd, '.planning');
95
+
96
+ // --- Wrapper functions that pass planningDir to lib modules ---
97
+ // These preserve the original function signatures (no planningDir param)
98
+ // so existing callers (hook scripts, tests) continue to work.
98
99
 
99
- /**
100
- * Load config.json with in-process mtime-based caching.
101
- * Returns the parsed config object, or null if not found / parse error.
102
- * Cache invalidates when file mtime changes or path differs.
103
- *
104
- * @param {string} [dir] - Path to .planning directory (defaults to cwd/.planning)
105
- * @returns {object|null} Parsed config or null
106
- */
107
100
  function configLoad(dir) {
108
- const configPath = path.join(dir || planningDir, 'config.json');
109
- try {
110
- if (!fs.existsSync(configPath)) return null;
111
- const stat = fs.statSync(configPath);
112
- const mtime = stat.mtimeMs;
113
- if (_configCache && mtime === _configMtime && configPath === _configPath) {
114
- return _configCache;
115
- }
116
- _configCache = JSON.parse(fs.readFileSync(configPath, 'utf8'));
117
- _configMtime = mtime;
118
- _configPath = configPath;
119
- return _configCache;
120
- } catch (_e) {
121
- return null;
122
- }
101
+ return _configLoad(dir || planningDir);
123
102
  }
124
103
 
125
- /**
126
- * Clear the configLoad() in-process cache.
127
- * Useful in tests where multiple temp directories are used in rapid succession.
128
- */
129
104
  function configClearCache() {
130
- _configCache = null;
131
- _configMtime = 0;
132
- _configPath = null;
105
+ _configClearCache();
106
+ cwd = process.env.PBR_PROJECT_ROOT || process.cwd();
107
+ cwd = normalizeMsysPath(cwd);
108
+ planningDir = path.join(cwd, '.planning');
133
109
  }
134
110
 
135
- /**
136
- * Read the last N lines from a file efficiently.
137
- * Reads the entire file but only parses (JSON.parse) the trailing entries.
138
- * For JSONL files where full parsing is expensive, this avoids parsing
139
- * all lines when you only need recent entries.
140
- *
141
- * @param {string} filePath - Absolute path to the file
142
- * @param {number} n - Number of trailing lines to return
143
- * @returns {string[]} Array of raw line strings (last n lines)
144
- */
145
- function tailLines(filePath, n) {
146
- try {
147
- if (!fs.existsSync(filePath)) return [];
148
- const content = fs.readFileSync(filePath, 'utf8').trim();
149
- if (!content) return [];
150
- const lines = content.split('\n');
151
- if (lines.length <= n) return lines;
152
- return lines.slice(lines.length - n);
153
- } catch (_e) {
154
- return [];
155
- }
111
+ function configValidate(preloadedConfig) {
112
+ return _configValidate(preloadedConfig, planningDir);
156
113
  }
157
114
 
158
- /**
159
- * Built-in depth profile defaults. These define the effective settings
160
- * for each depth level. User config.depth_profiles overrides these.
161
- */
162
- const DEPTH_PROFILE_DEFAULTS = {
163
- quick: {
164
- 'features.research_phase': false,
165
- 'features.plan_checking': false,
166
- 'features.goal_verification': false,
167
- 'features.inline_verify': false,
168
- 'scan.mapper_count': 2,
169
- 'scan.mapper_areas': ['tech', 'arch'],
170
- 'debug.max_hypothesis_rounds': 3
171
- },
172
- standard: {
173
- 'features.research_phase': true,
174
- 'features.plan_checking': true,
175
- 'features.goal_verification': true,
176
- 'features.inline_verify': false,
177
- 'scan.mapper_count': 4,
178
- 'scan.mapper_areas': ['tech', 'arch', 'quality', 'concerns'],
179
- 'debug.max_hypothesis_rounds': 5
180
- },
181
- comprehensive: {
182
- 'features.research_phase': true,
183
- 'features.plan_checking': true,
184
- 'features.goal_verification': true,
185
- 'features.inline_verify': true,
186
- 'scan.mapper_count': 4,
187
- 'scan.mapper_areas': ['tech', 'arch', 'quality', 'concerns'],
188
- 'debug.max_hypothesis_rounds': 10
189
- }
190
- };
191
-
192
- /**
193
- * Resolve the effective depth profile for the current config.
194
- * Merges built-in defaults with any user overrides from config.depth_profiles.
195
- *
196
- * @param {object|null} config - Parsed config.json (from configLoad). If null, returns 'standard' defaults.
197
- * @returns {{ depth: string, profile: object }} The resolved depth name and flattened profile settings.
198
- */
199
- function resolveDepthProfile(config) {
200
- const depth = (config && config.depth) || 'standard';
201
- const defaults = DEPTH_PROFILE_DEFAULTS[depth] || DEPTH_PROFILE_DEFAULTS.standard;
202
-
203
- // Merge user overrides if present
204
- const userOverrides = (config && config.depth_profiles && config.depth_profiles[depth]) || {};
205
- const profile = { ...defaults, ...userOverrides };
115
+ function stateLoad() {
116
+ return _stateLoad(planningDir);
117
+ }
206
118
 
207
- return { depth, profile };
119
+ function stateCheckProgress() {
120
+ return _stateCheckProgress(planningDir);
208
121
  }
209
122
 
210
- function main() {
211
- const args = process.argv.slice(2);
212
- const command = args[0];
213
- const subcommand = args[1];
123
+ function stateUpdate(field, value) {
124
+ return _stateUpdate(field, value, planningDir);
125
+ }
214
126
 
215
- try {
216
- if (command === 'state' && subcommand === 'load') {
217
- output(stateLoad());
218
- } else if (command === 'state' && subcommand === 'check-progress') {
219
- output(stateCheckProgress());
220
- } else if (command === 'state' && subcommand === 'update') {
221
- const field = args[2];
222
- const value = args[3];
223
- if (!field || value === undefined) {
224
- error('Usage: pbr-tools.js state update <field> <value>\nFields: current_phase, status, plans_complete, last_activity');
225
- }
226
- output(stateUpdate(field, value));
227
- } else if (command === 'config' && subcommand === 'validate') {
228
- output(configValidate());
229
- } else if (command === 'config' && subcommand === 'resolve-depth') {
230
- const dir = args[2] || undefined;
231
- const config = configLoad(dir);
232
- output(resolveDepthProfile(config));
233
- } else if (command === 'plan-index') {
234
- const phase = args[1];
235
- if (!phase) {
236
- error('Usage: pbr-tools.js plan-index <phase-number>');
237
- }
238
- output(planIndex(phase));
239
- } else if (command === 'frontmatter') {
240
- const filePath = args[1];
241
- if (!filePath) {
242
- error('Usage: pbr-tools.js frontmatter <filepath>');
243
- }
244
- output(frontmatter(filePath));
245
- } else if (command === 'must-haves') {
246
- const phase = args[1];
247
- if (!phase) {
248
- error('Usage: pbr-tools.js must-haves <phase-number>');
249
- }
250
- output(mustHavesCollect(phase));
251
- } else if (command === 'phase-info') {
252
- const phase = args[1];
253
- if (!phase) {
254
- error('Usage: pbr-tools.js phase-info <phase-number>');
255
- }
256
- output(phaseInfo(phase));
257
- } else if (command === 'roadmap' && subcommand === 'update-status') {
258
- const phase = args[2];
259
- const status = args[3];
260
- if (!phase || !status) {
261
- error('Usage: pbr-tools.js roadmap update-status <phase-number> <status>');
262
- }
263
- output(roadmapUpdateStatus(phase, status));
264
- } else if (command === 'roadmap' && subcommand === 'update-plans') {
265
- const phase = args[2];
266
- const complete = args[3];
267
- const total = args[4];
268
- if (!phase || complete === undefined || total === undefined) {
269
- error('Usage: pbr-tools.js roadmap update-plans <phase-number> <complete> <total>');
270
- }
271
- output(roadmapUpdatePlans(phase, complete, total));
272
- } else if (command === 'history' && subcommand === 'append') {
273
- const type = args[2]; // 'milestone' or 'phase'
274
- const title = args[3];
275
- const body = args[4] || '';
276
- if (!type || !title) {
277
- error('Usage: pbr-tools.js history append <milestone|phase> <title> [body]');
278
- }
279
- output(historyAppend({ type, title, body }));
280
- } else if (command === 'history' && subcommand === 'load') {
281
- output(historyLoad());
282
- } else if (command === 'event') {
283
- const category = args[1];
284
- const event = args[2];
285
- let details = {};
286
- if (args[3]) {
287
- try { details = JSON.parse(args[3]); } catch (_e) { details = { raw: args[3] }; }
288
- }
289
- if (!category || !event) {
290
- error('Usage: pbr-tools.js event <category> <event> [JSON-details]');
291
- }
292
- const { logEvent } = require('./event-logger');
293
- logEvent(category, event, details);
294
- output({ logged: true, category, event });
295
- } else {
296
- error(`Unknown command: ${args.join(' ')}\nCommands: state load|check-progress|update, config validate, plan-index, frontmatter, must-haves, phase-info, roadmap update-status|update-plans, history append|load, event`);
297
- }
298
- } catch (e) {
299
- error(e.message);
300
- }
127
+ function statePatch(jsonStr) {
128
+ return _statePatch(jsonStr, planningDir);
301
129
  }
302
130
 
303
- // --- Commands ---
131
+ function stateAdvancePlan() {
132
+ return _stateAdvancePlan(planningDir);
133
+ }
304
134
 
305
- function stateLoad() {
306
- const result = {
307
- exists: false,
308
- config: null,
309
- state: null,
310
- roadmap: null,
311
- phase_count: 0,
312
- current_phase: null,
313
- progress: null
314
- };
315
-
316
- if (!fs.existsSync(planningDir)) {
317
- return result;
318
- }
319
- result.exists = true;
135
+ function stateRecordMetric(metricArgs) {
136
+ return _stateRecordMetric(metricArgs, planningDir);
137
+ }
320
138
 
321
- // Load config.json
322
- const configPath = path.join(planningDir, 'config.json');
323
- if (fs.existsSync(configPath)) {
324
- try {
325
- result.config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
326
- } catch (_) {
327
- result.config = { _error: 'Failed to parse config.json' };
328
- }
329
- }
139
+ function stateRecordActivity(description) {
140
+ return _stateRecordActivity(description, planningDir);
141
+ }
330
142
 
331
- // Load STATE.md
332
- const statePath = path.join(planningDir, 'STATE.md');
333
- if (fs.existsSync(statePath)) {
334
- const content = fs.readFileSync(statePath, 'utf8');
335
- result.state = parseStateMd(content);
336
- }
143
+ function stateUpdateProgress() {
144
+ return _stateUpdateProgress(planningDir);
145
+ }
337
146
 
338
- // Load ROADMAP.md
339
- const roadmapPath = path.join(planningDir, 'ROADMAP.md');
340
- if (fs.existsSync(roadmapPath)) {
341
- const content = fs.readFileSync(roadmapPath, 'utf8');
342
- result.roadmap = parseRoadmapMd(content);
343
- result.phase_count = result.roadmap.phases.length;
344
- }
147
+ function stateReconcile() {
148
+ return _stateReconcile(planningDir);
149
+ }
345
150
 
346
- // Extract current phase
347
- if (result.state && result.state.current_phase) {
348
- result.current_phase = result.state.current_phase;
349
- }
151
+ function stateBackup() {
152
+ return _stateBackup(planningDir);
153
+ }
350
154
 
351
- // Calculate progress
352
- result.progress = calculateProgress();
155
+ function roadmapAnalyze() {
156
+ return _roadmapAnalyze(planningDir);
157
+ }
353
158
 
354
- return result;
159
+ function roadmapUpdateStatus(phaseNum, newStatus) {
160
+ return _roadmapUpdateStatus(phaseNum, newStatus, planningDir);
355
161
  }
356
162
 
357
- function stateCheckProgress() {
358
- const phasesDir = path.join(planningDir, 'phases');
359
- if (!fs.existsSync(phasesDir)) {
360
- return { phases: [], total_plans: 0, completed_plans: 0, percentage: 0 };
361
- }
163
+ function roadmapUpdatePlans(phaseNum, complete, total) {
164
+ return _roadmapUpdatePlans(phaseNum, complete, total, planningDir);
165
+ }
362
166
 
363
- const phases = [];
364
- let totalPlans = 0;
365
- let completedPlans = 0;
366
-
367
- const entries = fs.readdirSync(phasesDir, { withFileTypes: true })
368
- .filter(e => e.isDirectory())
369
- .sort((a, b) => a.name.localeCompare(b.name));
370
-
371
- for (const entry of entries) {
372
- const phaseDir = path.join(phasesDir, entry.name);
373
- const plans = findFiles(phaseDir, /-PLAN\.md$/);
374
- const summaries = findFiles(phaseDir, /^SUMMARY-.*\.md$/);
375
- const verification = fs.existsSync(path.join(phaseDir, 'VERIFICATION.md'));
376
-
377
- const completedSummaries = summaries.filter(s => {
378
- const content = fs.readFileSync(path.join(phaseDir, s), 'utf8');
379
- return /status:\s*["']?complete/i.test(content);
380
- });
381
-
382
- const phaseInfo = {
383
- directory: entry.name,
384
- plans: plans.length,
385
- summaries: summaries.length,
386
- completed: completedSummaries.length,
387
- has_verification: verification,
388
- status: determinePhaseStatus(plans.length, completedSummaries.length, summaries.length, verification, phaseDir)
389
- };
390
-
391
- phases.push(phaseInfo);
392
- totalPlans += plans.length;
393
- completedPlans += completedSummaries.length;
394
- }
395
167
 
396
- return {
397
- phases,
398
- total_plans: totalPlans,
399
- completed_plans: completedPlans,
400
- percentage: totalPlans > 0 ? Math.round((completedPlans / totalPlans) * 100) : 0
401
- };
168
+ function frontmatter(filePath) {
169
+ return _frontmatter(filePath);
402
170
  }
403
171
 
404
172
  function planIndex(phaseNum) {
405
- const phasesDir = path.join(planningDir, 'phases');
406
- if (!fs.existsSync(phasesDir)) {
407
- return { error: 'No phases directory found' };
408
- }
409
-
410
- // Find phase directory matching the number
411
- const entries = fs.readdirSync(phasesDir, { withFileTypes: true })
412
- .filter(e => e.isDirectory());
413
-
414
- const phaseDir = entries.find(e => e.name.startsWith(phaseNum.padStart(2, '0') + '-'));
415
- if (!phaseDir) {
416
- return { error: `No phase directory found matching phase ${phaseNum}` };
417
- }
418
-
419
- const fullDir = path.join(phasesDir, phaseDir.name);
420
- const planFiles = findFiles(fullDir, /-PLAN\.md$/);
421
-
422
- const plans = [];
423
- const waves = {};
424
-
425
- for (const file of planFiles) {
426
- const content = fs.readFileSync(path.join(fullDir, file), 'utf8');
427
- const frontmatter = parseYamlFrontmatter(content);
428
-
429
- const plan = {
430
- file,
431
- plan_id: frontmatter.plan || file.replace(/-PLAN\.md$/, ''),
432
- wave: parseInt(frontmatter.wave, 10) || 1,
433
- type: frontmatter.type || 'unknown',
434
- autonomous: frontmatter.autonomous !== false,
435
- depends_on: frontmatter.depends_on || [],
436
- gap_closure: frontmatter.gap_closure || false,
437
- has_summary: fs.existsSync(path.join(fullDir, `SUMMARY-${frontmatter.plan || ''}.md`)),
438
- must_haves_count: countMustHaves(frontmatter.must_haves)
439
- };
440
-
441
- plans.push(plan);
442
-
443
- const waveKey = `wave_${plan.wave}`;
444
- if (!waves[waveKey]) waves[waveKey] = [];
445
- waves[waveKey].push(plan.plan_id);
446
- }
447
-
448
- return {
449
- phase: phaseDir.name,
450
- total_plans: plans.length,
451
- plans,
452
- waves
453
- };
173
+ return _planIndex(phaseNum, planningDir);
454
174
  }
455
175
 
456
- function configValidate(preloadedConfig) {
457
- let config;
458
- if (preloadedConfig) {
459
- config = preloadedConfig;
460
- } else {
461
- const configPath = path.join(planningDir, 'config.json');
462
- if (!fs.existsSync(configPath)) {
463
- return { valid: false, errors: ['config.json not found'], warnings: [] };
464
- }
465
-
466
- try {
467
- config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
468
- } catch (e) {
469
- return { valid: false, errors: [`config.json is not valid JSON: ${e.message}`], warnings: [] };
470
- }
471
- }
472
-
473
- const schema = JSON.parse(fs.readFileSync(path.join(__dirname, 'config-schema.json'), 'utf8'));
474
- const warnings = [];
475
- const errors = [];
476
-
477
- validateObject(config, schema, '', errors, warnings);
478
-
479
- // Semantic conflict detection — logical contradictions that pass schema validation
480
- // Clear contradictions → errors; ambiguous/preference issues → warnings
481
- if (config.mode === 'autonomous' && config.gates) {
482
- const activeGates = Object.entries(config.gates || {}).filter(([, v]) => v === true).map(([k]) => k);
483
- if (activeGates.length > 0) {
484
- errors.push(`mode=autonomous with active gates (${activeGates.join(', ')}): gates are unreachable in autonomous mode`);
485
- }
486
- }
487
- if (config.features && config.features.auto_continue && config.mode === 'interactive') {
488
- warnings.push('features.auto_continue=true with mode=interactive: auto_continue only fires in autonomous mode');
489
- }
490
- if (config.parallelization) {
491
- if (config.parallelization.enabled === false && config.parallelization.plan_level === true) {
492
- warnings.push('parallelization.enabled=false with plan_level=true: plan_level is ignored when parallelization is disabled');
493
- }
494
- if (config.parallelization.max_concurrent_agents === 1 && config.teams && config.teams.coordination) {
495
- errors.push('parallelization.max_concurrent_agents=1 with teams.coordination set: teams require concurrent agents to be useful');
496
- }
497
- }
176
+ function mustHavesCollect(phaseNum) {
177
+ return _mustHavesCollect(phaseNum, planningDir);
178
+ }
498
179
 
499
- return {
500
- valid: errors.length === 0,
501
- errors,
502
- warnings
503
- };
180
+ function phaseInfo(phaseNum) {
181
+ return _phaseInfo(phaseNum, planningDir);
504
182
  }
505
183
 
506
- // --- New read-only commands ---
184
+ function phaseAdd(slug, afterPhase, options) {
185
+ return _phaseAdd(slug, afterPhase, planningDir, options);
186
+ }
507
187
 
508
- /**
509
- * Parse a markdown file's YAML frontmatter and return as JSON.
510
- * Wraps parseYamlFrontmatter() + parseMustHaves().
511
- */
512
- function frontmatter(filePath) {
513
- const resolved = path.resolve(filePath);
514
- if (!fs.existsSync(resolved)) {
515
- return { error: `File not found: ${resolved}` };
516
- }
517
- const content = fs.readFileSync(resolved, 'utf8');
518
- return parseYamlFrontmatter(content);
188
+ function phaseRemove(phaseNum) {
189
+ return _phaseRemove(phaseNum, planningDir);
519
190
  }
520
191
 
521
- /**
522
- * Collect all must-haves from all PLAN.md files in a phase.
523
- * Returns per-plan grouping + flat deduplicated list + total count.
524
- */
525
- function mustHavesCollect(phaseNum) {
526
- const phasesDir = path.join(planningDir, 'phases');
527
- if (!fs.existsSync(phasesDir)) {
528
- return { error: 'No phases directory found' };
529
- }
192
+ function phaseList(opts) {
193
+ return _phaseList(planningDir, opts);
194
+ }
530
195
 
531
- const entries = fs.readdirSync(phasesDir, { withFileTypes: true })
532
- .filter(e => e.isDirectory());
533
- const phaseDir = entries.find(e => e.name.startsWith(phaseNum.padStart(2, '0') + '-'));
534
- if (!phaseDir) {
535
- return { error: `No phase directory found matching phase ${phaseNum}` };
536
- }
196
+ function phaseNextNumber() {
197
+ return _phaseNextNumber(planningDir);
198
+ }
537
199
 
538
- const fullDir = path.join(phasesDir, phaseDir.name);
539
- const planFiles = findFiles(fullDir, /-PLAN\.md$/);
200
+ function phaseComplete(phaseNum) {
201
+ return _phaseComplete(phaseNum, planningDir);
202
+ }
540
203
 
541
- const perPlan = {};
542
- const allTruths = new Set();
543
- const allArtifacts = new Set();
544
- const allKeyLinks = new Set();
204
+ function phaseInsert(position, slug, options) {
205
+ return _phaseInsert(position, slug, planningDir, options);
206
+ }
545
207
 
546
- for (const file of planFiles) {
547
- const content = fs.readFileSync(path.join(fullDir, file), 'utf8');
548
- const fm = parseYamlFrontmatter(content);
549
- const planId = fm.plan || file.replace(/-PLAN\.md$/, '');
550
- const mh = fm.must_haves || { truths: [], artifacts: [], key_links: [] };
208
+ function milestoneStats(version) {
209
+ return _milestoneStats(version, planningDir);
210
+ }
551
211
 
552
- perPlan[planId] = mh;
553
- (mh.truths || []).forEach(t => allTruths.add(t));
554
- (mh.artifacts || []).forEach(a => allArtifacts.add(a));
555
- (mh.key_links || []).forEach(k => allKeyLinks.add(k));
556
- }
212
+ function compoundInitPhase(phaseNum, slug, opts) {
213
+ return _compoundInitPhase(phaseNum, slug, planningDir, opts);
214
+ }
557
215
 
558
- const all = {
559
- truths: [...allTruths],
560
- artifacts: [...allArtifacts],
561
- key_links: [...allKeyLinks]
562
- };
216
+ function compoundCompletePhase(phaseNum) {
217
+ return _compoundCompletePhase(phaseNum, planningDir);
218
+ }
563
219
 
564
- return {
565
- phase: phaseDir.name,
566
- plans: perPlan,
567
- all,
568
- total: all.truths.length + all.artifacts.length + all.key_links.length
569
- };
220
+ function compoundInitMilestone(version, opts) {
221
+ return _compoundInitMilestone(version, planningDir, opts);
570
222
  }
571
223
 
572
- /**
573
- * Comprehensive single-phase status combining roadmap, filesystem, and plan data.
574
- */
575
- function phaseInfo(phaseNum) {
576
- const phasesDir = path.join(planningDir, 'phases');
577
- if (!fs.existsSync(phasesDir)) {
578
- return { error: 'No phases directory found' };
579
- }
224
+ function initExecutePhase(phaseNum, overridePlanningDir, overrideModel) {
225
+ return _initExecutePhase(phaseNum, overridePlanningDir || planningDir, overrideModel);
226
+ }
580
227
 
581
- const entries = fs.readdirSync(phasesDir, { withFileTypes: true })
582
- .filter(e => e.isDirectory());
583
- const phaseDir = entries.find(e => e.name.startsWith(phaseNum.padStart(2, '0') + '-'));
584
- if (!phaseDir) {
585
- return { error: `No phase directory found matching phase ${phaseNum}` };
586
- }
228
+ function initPlanPhase(phaseNum, overridePlanningDir, overrideModel) {
229
+ return _initPlanPhase(phaseNum, overridePlanningDir || planningDir, overrideModel);
230
+ }
587
231
 
588
- const fullDir = path.join(phasesDir, phaseDir.name);
232
+ function initQuick(description) {
233
+ return _initQuick(description, planningDir);
234
+ }
589
235
 
590
- // Get roadmap info
591
- let roadmapInfo = null;
592
- const roadmapPath = path.join(planningDir, 'ROADMAP.md');
593
- if (fs.existsSync(roadmapPath)) {
594
- const roadmapContent = fs.readFileSync(roadmapPath, 'utf8');
595
- const roadmap = parseRoadmapMd(roadmapContent);
596
- roadmapInfo = roadmap.phases.find(p => p.number === phaseNum.padStart(2, '0')) || null;
597
- }
236
+ function initVerifyWork(phaseNum, overridePlanningDir, overrideModel) {
237
+ return _initVerifyWork(phaseNum, overridePlanningDir || planningDir, overrideModel);
238
+ }
598
239
 
599
- // Get plan index
600
- const plans = planIndex(phaseNum);
240
+ function initResume() {
241
+ return _initResume(planningDir);
242
+ }
601
243
 
602
- // Check for verification
603
- const verificationPath = path.join(fullDir, 'VERIFICATION.md');
604
- let verification = null;
605
- if (fs.existsSync(verificationPath)) {
606
- const vContent = fs.readFileSync(verificationPath, 'utf8');
607
- verification = parseYamlFrontmatter(vContent);
608
- }
244
+ function initProgress() {
245
+ return _initProgress(planningDir);
246
+ }
609
247
 
610
- // Check summaries
611
- const summaryFiles = findFiles(fullDir, /^SUMMARY-.*\.md$/);
612
- const summaries = summaryFiles.map(f => {
613
- const content = fs.readFileSync(path.join(fullDir, f), 'utf8');
614
- const fm = parseYamlFrontmatter(content);
615
- return { file: f, plan: fm.plan || f.replace(/^SUMMARY-|\.md$/g, ''), status: fm.status || 'unknown' };
616
- });
617
-
618
- // Determine filesystem status
619
- const planCount = plans.total_plans || 0;
620
- const completedCount = summaries.filter(s => s.status === 'complete').length;
621
- const hasVerification = fs.existsSync(verificationPath);
622
- const fsStatus = determinePhaseStatus(planCount, completedCount, summaryFiles.length, hasVerification, fullDir);
623
-
624
- return {
625
- phase: phaseDir.name,
626
- name: roadmapInfo ? roadmapInfo.name : phaseDir.name.replace(/^\d+-/, ''),
627
- goal: roadmapInfo ? roadmapInfo.goal : null,
628
- roadmap_status: roadmapInfo ? roadmapInfo.status : null,
629
- filesystem_status: fsStatus,
630
- plans: plans.plans || [],
631
- plan_count: planCount,
632
- summaries,
633
- completed: completedCount,
634
- verification,
635
- has_context: fs.existsSync(path.join(fullDir, 'CONTEXT.md'))
636
- };
637
- }
638
-
639
- // --- Mutation commands ---
248
+ function initContinue() {
249
+ return _initContinue(planningDir);
250
+ }
640
251
 
641
- /**
642
- * Atomically update a field in STATE.md using lockedFileUpdate.
643
- * Supports both legacy and frontmatter (v2) formats.
644
- *
645
- * @param {string} field - One of: current_phase, status, plans_complete, last_activity
646
- * @param {string} value - New value (use 'now' for last_activity to auto-timestamp)
647
- */
648
- function stateUpdate(field, value) {
649
- const statePath = path.join(planningDir, 'STATE.md');
650
- if (!fs.existsSync(statePath)) {
651
- return { success: false, error: 'STATE.md not found' };
652
- }
252
+ function initMilestone() {
253
+ return _initMilestone(planningDir);
254
+ }
653
255
 
654
- const validFields = ['current_phase', 'status', 'plans_complete', 'last_activity'];
655
- if (!validFields.includes(field)) {
656
- return { success: false, error: `Invalid field: ${field}. Valid fields: ${validFields.join(', ')}` };
657
- }
256
+ function initBegin() {
257
+ return _initBegin(planningDir);
258
+ }
658
259
 
659
- // Auto-timestamp
660
- if (field === 'last_activity' && value === 'now') {
661
- value = new Date().toISOString().slice(0, 19).replace('T', ' ');
662
- }
260
+ function initStatus() {
261
+ return _initStatus(planningDir);
262
+ }
663
263
 
664
- const result = lockedFileUpdate(statePath, (content) => {
665
- const fm = parseYamlFrontmatter(content);
666
- if (fm.version === 2 || fm.current_phase !== undefined) {
667
- return updateFrontmatterField(content, field, value);
668
- }
669
- return updateLegacyStateField(content, field, value);
670
- });
264
+ function initMapCodebase() {
265
+ return _initMapCodebase(planningDir);
266
+ }
671
267
 
672
- if (result.success) {
673
- return { success: true, field, value };
674
- }
675
- return { success: false, error: result.error };
268
+ function stateBundle(phaseNum) {
269
+ return _initStateBundle(phaseNum, planningDir);
676
270
  }
677
271
 
678
- /**
679
- * Append a record to HISTORY.md. Creates the file if it doesn't exist.
680
- * Each entry is a markdown section appended at the end.
681
- *
682
- * @param {object} entry - { type: 'milestone'|'phase', title: string, body: string }
683
- * @param {string} [dir] - Path to .planning directory (defaults to cwd/.planning)
684
- * @returns {{success: boolean, error?: string}}
685
- */
686
272
  function historyAppend(entry, dir) {
687
- const historyPath = path.join(dir || planningDir, 'HISTORY.md');
688
- const timestamp = new Date().toISOString().slice(0, 10);
689
-
690
- let header = '';
691
- if (!fs.existsSync(historyPath)) {
692
- header = '# Project History\n\nCompleted milestones and phase records. This file is append-only.\n\n';
693
- }
694
-
695
- const section = `${header}## ${entry.type === 'milestone' ? 'Milestone' : 'Phase'}: ${entry.title}\n_Completed: ${timestamp}_\n\n${entry.body.trim()}\n\n---\n\n`;
696
-
697
- try {
698
- fs.appendFileSync(historyPath, section, 'utf8');
699
- return { success: true };
700
- } catch (e) {
701
- return { success: false, error: e.message };
702
- }
273
+ return _historyAppend(entry, dir || planningDir);
703
274
  }
704
275
 
705
- /**
706
- * Load HISTORY.md and parse it into structured records.
707
- * Returns null if HISTORY.md doesn't exist.
708
- *
709
- * @param {string} [dir] - Path to .planning directory
710
- * @returns {object|null} { records: [{type, title, date, body}], line_count }
711
- */
712
276
  function historyLoad(dir) {
713
- const historyPath = path.join(dir || planningDir, 'HISTORY.md');
714
- if (!fs.existsSync(historyPath)) return null;
715
-
716
- const content = fs.readFileSync(historyPath, 'utf8');
717
- const records = [];
718
- const sectionRegex = /^## (Milestone|Phase): (.+)\n_Completed: (\d{4}-\d{2}-\d{2})_\n\n([\s\S]*?)(?=\n---|\s*$)/gm;
719
-
720
- let match;
721
- while ((match = sectionRegex.exec(content)) !== null) {
722
- records.push({
723
- type: match[1].toLowerCase(),
724
- title: match[2].trim(),
725
- date: match[3],
726
- body: match[4].trim()
727
- });
728
- }
729
-
730
- return {
731
- records,
732
- line_count: content.split('\n').length
733
- };
277
+ return _historyLoad(dir || planningDir);
734
278
  }
735
279
 
736
- /**
737
- * Update the Status column for a phase in ROADMAP.md's Phase Overview table.
738
- */
739
- function roadmapUpdateStatus(phaseNum, newStatus) {
740
- const roadmapPath = path.join(planningDir, 'ROADMAP.md');
741
- if (!fs.existsSync(roadmapPath)) {
742
- return { success: false, error: 'ROADMAP.md not found' };
743
- }
744
-
745
- let oldStatus = null;
746
-
747
- const result = lockedFileUpdate(roadmapPath, (content) => {
748
- const lines = content.split('\n');
749
- const rowIdx = findRoadmapRow(lines, phaseNum);
750
- if (rowIdx === -1) {
751
- return content; // No matching row found
752
- }
753
- const parts = lines[rowIdx].split('|');
754
- oldStatus = parts[6] ? parts[6].trim() : 'unknown';
755
- lines[rowIdx] = updateTableRow(lines[rowIdx], 5, newStatus);
756
- return lines.join('\n');
757
- });
758
-
759
- if (!oldStatus) {
760
- return { success: false, error: `Phase ${phaseNum} not found in ROADMAP.md table` };
761
- }
762
-
763
- // Advisory transition validation — warn on suspicious transitions but don't block
764
- const transition = validateStatusTransition(oldStatus, newStatus);
765
- if (!transition.valid && transition.warning) {
766
- process.stderr.write(`[pbr-tools] WARNING: ${transition.warning}\n`);
767
- }
768
-
769
- if (result.success) {
770
- const response = { success: true, old_status: oldStatus, new_status: newStatus };
771
- if (!transition.valid) {
772
- response.transition_warning = transition.warning;
773
- }
774
- return response;
775
- }
776
- return { success: false, error: result.error };
280
+ function todoList(opts) {
281
+ return _todoList(planningDir, opts);
777
282
  }
778
283
 
779
- /**
780
- * Update the Plans column for a phase in ROADMAP.md's Phase Overview table.
781
- */
782
- function roadmapUpdatePlans(phaseNum, complete, total) {
783
- const roadmapPath = path.join(planningDir, 'ROADMAP.md');
784
- if (!fs.existsSync(roadmapPath)) {
785
- return { success: false, error: 'ROADMAP.md not found' };
786
- }
787
-
788
- let oldPlans = null;
789
- const newPlans = `${complete}/${total}`;
790
-
791
- const result = lockedFileUpdate(roadmapPath, (content) => {
792
- const lines = content.split('\n');
793
- const rowIdx = findRoadmapRow(lines, phaseNum);
794
- if (rowIdx === -1) {
795
- return content;
796
- }
797
- const parts = lines[rowIdx].split('|');
798
- oldPlans = parts[4] ? parts[4].trim() : 'unknown';
799
- lines[rowIdx] = updateTableRow(lines[rowIdx], 3, newPlans);
800
- return lines.join('\n');
801
- });
802
-
803
- if (!oldPlans) {
804
- return { success: false, error: `Phase ${phaseNum} not found in ROADMAP.md table` };
805
- }
806
-
807
- if (result.success) {
808
- return { success: true, old_plans: oldPlans, new_plans: newPlans };
809
- }
810
- return { success: false, error: result.error };
284
+ function todoGet(num) {
285
+ return _todoGet(planningDir, num);
811
286
  }
812
287
 
813
- // --- Mutation helpers ---
814
-
815
- /**
816
- * Update a field in legacy (non-frontmatter) STATE.md content.
817
- * Pure function: content in, content out.
818
- */
819
- function updateLegacyStateField(content, field, value) {
820
- const lines = content.split('\n');
821
-
822
- switch (field) {
823
- case 'current_phase': {
824
- const idx = lines.findIndex(l => /Phase:\s*\d+\s+of\s+\d+/.test(l));
825
- if (idx !== -1) {
826
- lines[idx] = lines[idx].replace(/(Phase:\s*)\d+/, (_, prefix) => `${prefix}${value}`);
827
- }
828
- break;
829
- }
830
- case 'status': {
831
- const idx = lines.findIndex(l => /^Status:/i.test(l));
832
- if (idx !== -1) {
833
- lines[idx] = `Status: ${value}`;
834
- } else {
835
- const phaseIdx = lines.findIndex(l => /Phase:/.test(l));
836
- if (phaseIdx !== -1) {
837
- lines.splice(phaseIdx + 1, 0, `Status: ${value}`);
838
- } else {
839
- lines.push(`Status: ${value}`);
840
- }
841
- }
842
- break;
843
- }
844
- case 'plans_complete': {
845
- const idx = lines.findIndex(l => /Plan:\s*\d+\s+of\s+\d+/.test(l));
846
- if (idx !== -1) {
847
- lines[idx] = lines[idx].replace(/(Plan:\s*)\d+/, (_, prefix) => `${prefix}${value}`);
848
- }
849
- break;
850
- }
851
- case 'last_activity': {
852
- const idx = lines.findIndex(l => /^Last Activity:/i.test(l));
853
- if (idx !== -1) {
854
- lines[idx] = `Last Activity: ${value}`;
855
- } else {
856
- const statusIdx = lines.findIndex(l => /^Status:/i.test(l));
857
- if (statusIdx !== -1) {
858
- lines.splice(statusIdx + 1, 0, `Last Activity: ${value}`);
859
- } else {
860
- lines.push(`Last Activity: ${value}`);
861
- }
862
- }
863
- break;
864
- }
865
- }
866
-
867
- return lines.join('\n');
288
+ function todoAdd(title, opts) {
289
+ return _todoAdd(planningDir, title, opts);
868
290
  }
869
291
 
870
- /**
871
- * Update a field in YAML frontmatter content.
872
- * Pure function: content in, content out.
873
- */
874
- function updateFrontmatterField(content, field, value) {
875
- const match = content.match(/^(---\s*\n)([\s\S]*?)(\n---)/);
876
- if (!match) return content;
877
-
878
- const before = match[1];
879
- let yaml = match[2];
880
- const after = match[3];
881
- const rest = content.slice(match[0].length);
882
-
883
- // Format value: integers stay bare, strings get quotes
884
- const isNum = /^\d+$/.test(String(value));
885
- const formatted = isNum ? value : `"${value}"`;
886
-
887
- const fieldRegex = new RegExp(`^(${field})\\s*:.*$`, 'm');
888
- if (fieldRegex.test(yaml)) {
889
- yaml = yaml.replace(fieldRegex, () => `${field}: ${formatted}`);
890
- } else {
891
- yaml = yaml + `\n${field}: ${formatted}`;
892
- }
893
-
894
- return before + yaml + after + rest;
292
+ function todoDone(num) {
293
+ return _todoDone(planningDir, num);
895
294
  }
896
295
 
897
- /**
898
- * Find the row index of a phase in a ROADMAP.md table.
899
- * @returns {number} Line index or -1 if not found
900
- */
901
- function findRoadmapRow(lines, phaseNum) {
902
- const paddedPhase = phaseNum.padStart(2, '0');
903
- for (let i = 0; i < lines.length; i++) {
904
- if (!lines[i].includes('|')) continue;
905
- const parts = lines[i].split('|');
906
- if (parts.length < 3) continue;
907
- const phaseCol = parts[1] ? parts[1].trim() : '';
908
- if (phaseCol === paddedPhase) {
909
- return i;
910
- }
911
- }
912
- return -1;
296
+ function autoCloseTodos(context) {
297
+ return _autoCloseTodos(planningDir, context);
913
298
  }
914
299
 
915
- /**
916
- * Update a specific column in a markdown table row.
917
- * @param {string} row - The full table row string (e.g., "| 01 | Setup | ... |")
918
- * @param {number} columnIndex - 0-based column index (Phase=0, Name=1, ..., Status=5)
919
- * @param {string} newValue - New cell value
920
- * @returns {string} Updated row
921
- */
922
- function updateTableRow(row, columnIndex, newValue) {
923
- const parts = row.split('|');
924
- // parts[0] is empty (before first |), data starts at parts[1]
925
- const partIndex = columnIndex + 1;
926
- if (partIndex < parts.length) {
927
- parts[partIndex] = ` ${newValue} `;
928
- }
929
- return parts.join('|');
300
+ function autoArchiveNotes(context) {
301
+ return _autoArchiveNotes(planningDir, context);
930
302
  }
931
303
 
932
- /**
933
- * Lightweight JSON Schema validator — supports type, enum, properties,
934
- * additionalProperties, minimum, maximum for the config schema.
935
- */
936
- function validateObject(value, schema, prefix, errors, warnings) {
937
- if (schema.type && typeof value !== schema.type) {
938
- if (!(schema.type === 'integer' && typeof value === 'number' && Number.isInteger(value))) {
939
- errors.push(`${prefix || 'root'}: expected ${schema.type}, got ${typeof value}`);
940
- return;
941
- }
942
- }
943
-
944
- if (schema.enum && !schema.enum.includes(value)) {
945
- errors.push(`${prefix || 'root'}: value "${value}" not in allowed values [${schema.enum.join(', ')}]`);
946
- return;
947
- }
948
-
949
- if (schema.minimum !== undefined && value < schema.minimum) {
950
- errors.push(`${prefix || 'root'}: value ${value} is below minimum ${schema.minimum}`);
951
- }
952
- if (schema.maximum !== undefined && value > schema.maximum) {
953
- errors.push(`${prefix || 'root'}: value ${value} is above maximum ${schema.maximum}`);
954
- }
955
-
956
- if (schema.type === 'object' && schema.properties) {
957
- const knownKeys = new Set(Object.keys(schema.properties));
958
304
 
959
- for (const key of Object.keys(value)) {
960
- const fullKey = prefix ? `${prefix}.${key}` : key;
961
- if (!knownKeys.has(key)) {
962
- if (schema.additionalProperties === false) {
963
- warnings.push(`${fullKey}: unrecognized key (possible typo?)`);
964
- }
965
- continue;
966
- }
967
- validateObject(value[key], schema.properties[key], fullKey, errors, warnings);
968
- }
969
- }
305
+ function migrate(options) {
306
+ return _applyMigrations(planningDir, options);
970
307
  }
971
308
 
972
- /**
973
- * Locked file update: read-modify-write with exclusive lockfile.
974
- * Prevents concurrent writes to STATE.md and ROADMAP.md.
975
- *
976
- * @param {string} filePath - Absolute path to the file to update
977
- * @param {function} updateFn - Receives current content, returns new content
978
- * @param {object} opts - Options: { retries: 3, retryDelayMs: 100, timeoutMs: 5000 }
979
- * @returns {object} { success, content?, error? }
980
- */
981
- function lockedFileUpdate(filePath, updateFn, opts = {}) {
982
- const retries = opts.retries || 3;
983
- const retryDelayMs = opts.retryDelayMs || 100;
984
- const timeoutMs = opts.timeoutMs || 5000;
985
- const lockPath = filePath + '.lock';
986
-
987
- let lockFd = null;
988
- let lockAcquired = false;
989
-
990
- try {
991
- // Acquire lock with retries
992
- for (let attempt = 0; attempt < retries; attempt++) {
993
- try {
994
- lockFd = fs.openSync(lockPath, 'wx');
995
- lockAcquired = true;
996
- break;
997
- } catch (e) {
998
- if (e.code === 'EEXIST') {
999
- // Lock exists — check if stale (older than timeoutMs)
1000
- try {
1001
- const stats = fs.statSync(lockPath);
1002
- if (Date.now() - stats.mtimeMs > timeoutMs) {
1003
- // Stale lock — remove and retry
1004
- fs.unlinkSync(lockPath);
1005
- continue;
1006
- }
1007
- } catch (_statErr) {
1008
- // Lock disappeared between check — retry
1009
- continue;
1010
- }
1011
-
1012
- if (attempt < retries - 1) {
1013
- // Wait and retry
1014
- const waitMs = retryDelayMs * (attempt + 1);
1015
- const start = Date.now();
1016
- while (Date.now() - start < waitMs) {
1017
- // Busy wait (synchronous context)
1018
- }
1019
- continue;
1020
- }
1021
- return { success: false, error: `Could not acquire lock for ${path.basename(filePath)} after ${retries} attempts` };
1022
- }
1023
- throw e;
1024
- }
1025
- }
1026
-
1027
- if (!lockAcquired) {
1028
- return { success: false, error: `Could not acquire lock for ${path.basename(filePath)}` };
1029
- }
1030
-
1031
- // Write PID to lock file for debugging
1032
- fs.writeSync(lockFd, `${process.pid}`);
1033
- fs.closeSync(lockFd);
1034
- lockFd = null;
1035
-
1036
- // Read current content
1037
- let content = '';
1038
- if (fs.existsSync(filePath)) {
1039
- content = fs.readFileSync(filePath, 'utf8');
1040
- }
1041
-
1042
- // Apply update
1043
- const newContent = updateFn(content);
1044
-
1045
- // Write back atomically
1046
- const writeResult = atomicWrite(filePath, newContent);
1047
- if (!writeResult.success) {
1048
- return { success: false, error: writeResult.error };
1049
- }
1050
309
 
1051
- return { success: true, content: newContent };
1052
- } catch (e) {
1053
- return { success: false, error: e.message };
1054
- } finally {
1055
- // Close fd if still open
1056
- try {
1057
- if (lockFd !== null) fs.closeSync(lockFd);
1058
- } catch (_e) { /* ignore */ }
1059
- // Only release lock if we acquired it
1060
- if (lockAcquired) {
1061
- try {
1062
- fs.unlinkSync(lockPath);
1063
- } catch (_e) { /* ignore — may already be cleaned up */ }
1064
- }
1065
- }
310
+ function verifySpotCheck(type, dirPath) {
311
+ return _verifySpotCheck(type, dirPath);
1066
312
  }
1067
313
 
1068
- // --- Parsers ---
1069
-
1070
- function parseStateMd(content) {
1071
- const result = {
1072
- current_phase: null,
1073
- phase_name: null,
1074
- progress: null,
1075
- status: null,
1076
- line_count: content.split('\n').length,
1077
- format: 'legacy' // 'legacy' or 'frontmatter'
1078
- };
1079
-
1080
- // Check for YAML frontmatter (version 2 format)
1081
- const frontmatter = parseYamlFrontmatter(content);
1082
- if (frontmatter.version === 2 || frontmatter.current_phase !== undefined) {
1083
- result.format = 'frontmatter';
1084
- result.current_phase = frontmatter.current_phase || null;
1085
- result.total_phases = frontmatter.total_phases || null;
1086
- result.phase_name = frontmatter.phase_slug || frontmatter.phase_name || null;
1087
- result.status = frontmatter.status || null;
1088
- result.progress = frontmatter.progress_percent !== undefined ? frontmatter.progress_percent : null;
1089
- result.plans_total = frontmatter.plans_total || null;
1090
- result.plans_complete = frontmatter.plans_complete || null;
1091
- result.last_activity = frontmatter.last_activity || null;
1092
- result.last_command = frontmatter.last_command || null;
1093
- result.blockers = frontmatter.blockers || [];
1094
- return result;
1095
- }
1096
-
1097
- // Legacy regex-based parsing (version 1 format, no frontmatter)
1098
- // DEPRECATED (2026-02): v1 STATE.md format (no YAML frontmatter) is deprecated.
1099
- // New projects should use v2 (frontmatter) format, generated by /pbr:setup.
1100
- // v1 support will be removed in a future major version.
1101
- process.stderr.write('[pbr] WARNING: STATE.md uses legacy v1 format. Run /pbr:setup to migrate to v2 format.\n');
1102
- // Extract "Phase: N of M"
1103
- const phaseMatch = content.match(/Phase:\s*(\d+)\s+of\s+(\d+)/);
1104
- if (phaseMatch) {
1105
- result.current_phase = parseInt(phaseMatch[1], 10);
1106
- result.total_phases = parseInt(phaseMatch[2], 10);
1107
- }
314
+ function referenceGet(name, options) {
315
+ // Resolve plugin root — try CLAUDE_PLUGIN_ROOT env, then walk up from __dirname
316
+ const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || path.resolve(__dirname, '..');
317
+ let root = normalizeMsysPath(pluginRoot);
318
+ return _referenceGet(name, options, root);
319
+ }
1108
320
 
1109
- // Extract phase name (line after "Phase:")
1110
- const nameMatch = content.match(/--\s+(.+?)(?:\n|$)/);
1111
- if (nameMatch) {
1112
- result.phase_name = nameMatch[1].trim();
1113
- }
321
+ function resolvePluginRoot() {
322
+ // Resolve plugin root — try CLAUDE_PLUGIN_ROOT env, then walk up from __dirname
323
+ const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || path.resolve(__dirname, '..');
324
+ return normalizeMsysPath(pluginRoot);
325
+ }
1114
326
 
1115
- // Extract progress percentage
1116
- const progressMatch = content.match(/(\d+)%/);
1117
- if (progressMatch) {
1118
- result.progress = parseInt(progressMatch[1], 10);
1119
- }
327
+ function skillSectionGet(skillName, sectionQuery) {
328
+ return _skillSection(skillName, sectionQuery, resolvePluginRoot());
329
+ }
1120
330
 
1121
- // Extract plan status
1122
- const statusMatch = content.match(/Status:\s*(.+?)(?:\n|$)/i);
1123
- if (statusMatch) {
1124
- result.status = statusMatch[1].trim();
331
+ function listSkillHeadings(skillName) {
332
+ const { listHeadings } = require('./lib/reference');
333
+ const root = resolvePluginRoot();
334
+ const skillPath = require('path').join(root, 'skills', skillName, 'SKILL.md');
335
+ if (!require('fs').existsSync(skillPath)) {
336
+ return { error: `Skill not found: ${skillName}`, available: _listAvailableSkills(root) };
1125
337
  }
338
+ const content = require('fs').readFileSync(skillPath, 'utf8');
339
+ return { skill: skillName, headings: listHeadings(content) };
340
+ }
1126
341
 
1127
- return result;
1128
- }
1129
-
1130
- function parseRoadmapMd(content) {
1131
- const result = { phases: [], has_progress_table: false };
1132
-
1133
- // Find Phase Overview table
1134
- const overviewMatch = content.match(/## Phase Overview[\s\S]*?\|[\s\S]*?(?=\n##|\s*$)/);
1135
- if (overviewMatch) {
1136
- const rows = overviewMatch[0].split('\n').filter(r => r.includes('|'));
1137
- // Skip header and separator rows
1138
- for (let i = 2; i < rows.length; i++) {
1139
- const cols = rows[i].split('|').map(c => c.trim()).filter(Boolean);
1140
- if (cols.length >= 3) {
1141
- result.phases.push({
1142
- number: cols[0],
1143
- name: cols[1],
1144
- goal: cols[2],
1145
- plans: cols[3] || '',
1146
- wave: cols[4] || '',
1147
- status: cols[5] || 'pending'
1148
- });
1149
- }
1150
- }
1151
- }
342
+ function contextTriage(options) {
343
+ return _contextTriage(options, planningDir);
344
+ }
1152
345
 
1153
- // Check for Progress table
1154
- result.has_progress_table = /## Progress/.test(content);
346
+ function stalenessCheck(phaseSlug) { return _stalenessCheck(phaseSlug, planningDir); }
347
+ function summaryGate(phaseSlug, planId) { return _summaryGate(phaseSlug, planId, planningDir); }
348
+ function checkpointInit(phaseSlug, plans) { return _checkpointInit(phaseSlug, plans, planningDir); }
349
+ function checkpointUpdate(phaseSlug, opts) { return _checkpointUpdate(phaseSlug, opts, planningDir); }
350
+ function seedsMatch(phaseSlug, phaseNum) { return _seedsMatch(phaseSlug, phaseNum, planningDir); }
351
+ function ciPoll(runId, timeoutSecs) { return _ciPoll(runId, timeoutSecs, planningDir); }
352
+ function ciFix(options) { return _runCiFixLoop({ ...options, cwd: path.resolve('.') }); }
353
+ function rollbackPlan(manifestPath) { return _rollback(manifestPath, planningDir); }
1155
354
 
1156
- return result;
355
+ function helpListCmd() {
356
+ const root = resolvePluginRoot();
357
+ return _helpList(root);
358
+ }
359
+ function skillMetadataCmd(skillName) {
360
+ const root = resolvePluginRoot();
361
+ return _skillMetadata(skillName, root);
1157
362
  }
1158
363
 
1159
- function parseYamlFrontmatter(content) {
1160
- const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
1161
- if (!match) return {};
1162
-
1163
- const yaml = match[1];
1164
- const result = {};
364
+ function quickStatus() { return _quickStatus(planningDir); }
1165
365
 
1166
- // Simple YAML parser for flat and basic nested values
1167
- const lines = yaml.split('\n');
1168
- let currentKey = null;
366
+ /**
367
+ * Build cleanup context from phase SUMMARY files and git log.
368
+ * @param {string} phaseNum - Phase number (e.g. "38")
369
+ * @returns {{ phaseName: string, phaseNum: string, keyFiles: string[], commitMessages: string[], summaryDescriptions: string[] }}
370
+ */
371
+ function buildCleanupContext(phaseNum) {
372
+ const padded = String(phaseNum).padStart(2, '0');
373
+ const phasesDir = path.join(planningDir, 'phases');
374
+ if (!fs.existsSync(phasesDir)) throw new Error('No phases directory found');
1169
375
 
1170
- for (const line of lines) {
1171
- // Array item
1172
- if (/^\s+-\s+/.test(line) && currentKey) {
1173
- const val = line.replace(/^\s+-\s+/, '').trim().replace(/^["']|["']$/g, '');
1174
- if (!result[currentKey]) result[currentKey] = [];
1175
- if (Array.isArray(result[currentKey])) {
1176
- result[currentKey].push(val);
1177
- }
1178
- continue;
1179
- }
376
+ const phaseDir = fs.readdirSync(phasesDir).find(d => d.startsWith(padded + '-'));
377
+ if (!phaseDir) throw new Error(`Phase ${phaseNum} directory not found`);
1180
378
 
1181
- // Key-value pair
1182
- const kvMatch = line.match(/^(\w[\w_]*)\s*:\s*(.*)/);
1183
- if (kvMatch) {
1184
- currentKey = kvMatch[1];
1185
- let val = kvMatch[2].trim();
379
+ const phaseName = phaseDir.replace(/^\d+-/, '').replace(/-/g, ' ');
380
+ const phaseDirPath = path.join(phasesDir, phaseDir);
1186
381
 
1187
- if (val === '' || val === '|') {
1188
- // Possible array or block follows
1189
- continue;
382
+ // Collect key_files and descriptions from all SUMMARY files
383
+ const keyFiles = [];
384
+ const summaryDescriptions = [];
385
+ const summaryFiles = fs.readdirSync(phaseDirPath).filter(f => /^SUMMARY/i.test(f) && f.endsWith('.md'));
386
+ for (const sf of summaryFiles) {
387
+ try {
388
+ const content = fs.readFileSync(path.join(phaseDirPath, sf), 'utf8');
389
+ const fm = parseYamlFrontmatter(content);
390
+ if (fm.key_files && Array.isArray(fm.key_files)) {
391
+ keyFiles.push(...fm.key_files.map(kf => typeof kf === 'string' ? kf.split(':')[0].trim() : ''));
1190
392
  }
1191
-
1192
- // Handle arrays on same line: [a, b, c]
1193
- if (val.startsWith('[') && val.endsWith(']')) {
1194
- result[currentKey] = val.slice(1, -1).split(',')
1195
- .map(v => v.trim().replace(/^["']|["']$/g, ''))
1196
- .filter(Boolean);
1197
- continue;
393
+ if (fm.provides && Array.isArray(fm.provides)) {
394
+ summaryDescriptions.push(...fm.provides);
1198
395
  }
1199
-
1200
- // Clean quotes
1201
- val = val.replace(/^["']|["']$/g, '');
1202
-
1203
- // Type coercion
1204
- if (val === 'true') val = true;
1205
- else if (val === 'false') val = false;
1206
- else if (/^\d+$/.test(val)) val = parseInt(val, 10);
1207
-
1208
- result[currentKey] = val;
1209
- }
396
+ } catch (_e) { /* skip unreadable summaries */ }
1210
397
  }
1211
398
 
1212
- // Handle must_haves as a nested object
1213
- if (yaml.includes('must_haves:')) {
1214
- result.must_haves = parseMustHaves(yaml);
1215
- }
1216
-
1217
- return result;
1218
- }
1219
-
1220
- function parseMustHaves(yaml) {
1221
- const result = { truths: [], artifacts: [], key_links: [] };
1222
- let section = null;
1223
-
1224
- const inMustHaves = yaml.split('\n');
1225
- let collecting = false;
1226
-
1227
- for (const line of inMustHaves) {
1228
- if (/^\s*must_haves:/.test(line)) {
1229
- collecting = true;
1230
- continue;
1231
- }
1232
- if (collecting) {
1233
- if (/^\s{2}truths:/.test(line)) { section = 'truths'; continue; }
1234
- if (/^\s{2}artifacts:/.test(line)) { section = 'artifacts'; continue; }
1235
- if (/^\s{2}key_links:/.test(line)) { section = 'key_links'; continue; }
1236
- if (/^\w/.test(line)) break; // New top-level key, stop
1237
-
1238
- if (section && /^\s+-\s+/.test(line)) {
1239
- result[section].push(line.replace(/^\s+-\s+/, '').trim().replace(/^["']|["']$/g, ''));
1240
- }
1241
- }
1242
- }
399
+ // Get recent commit messages
400
+ let commitMessages = [];
401
+ try {
402
+ const { execSync } = require('child_process');
403
+ const log = execSync('git log --oneline -20', { encoding: 'utf8', cwd: path.join(planningDir, '..') });
404
+ commitMessages = log.split('\n').filter(l => l.trim()).map(l => {
405
+ const parts = l.match(/^[0-9a-f]+\s+(.*)/);
406
+ return parts ? parts[1] : '';
407
+ }).filter(Boolean);
408
+ } catch (_e) { /* git not available */ }
1243
409
 
1244
- return result;
410
+ return { phaseName, phaseNum: String(phaseNum), keyFiles, commitMessages, summaryDescriptions };
1245
411
  }
1246
412
 
1247
- // --- Helpers ---
413
+ // --- Claim wrapper functions ---
1248
414
 
1249
- function findFiles(dir, pattern) {
1250
- try {
1251
- return fs.readdirSync(dir).filter(f => pattern.test(f)).sort();
1252
- } catch (_) {
1253
- return [];
1254
- }
415
+ function claimAcquire(phaseSlug, sessionId, skill) {
416
+ const phaseDir = path.join(planningDir, 'phases', phaseSlug);
417
+ if (!fs.existsSync(phaseDir)) return { error: `Phase directory not found: ${phaseSlug}` };
418
+ return acquireClaim(planningDir, phaseDir, sessionId, skill);
1255
419
  }
1256
420
 
1257
- function determinePhaseStatus(planCount, completedCount, summaryCount, hasVerification, phaseDir) {
1258
- if (planCount === 0) {
1259
- // Check for CONTEXT.md (discussed only)
1260
- if (fs.existsSync(path.join(phaseDir, 'CONTEXT.md'))) return 'discussed';
1261
- return 'not_started';
1262
- }
1263
- if (completedCount === 0 && summaryCount === 0) return 'planned';
1264
- if (completedCount < planCount) return 'building';
1265
- if (!hasVerification) return 'built';
1266
- // Check verification status
1267
- try {
1268
- const vContent = fs.readFileSync(path.join(phaseDir, 'VERIFICATION.md'), 'utf8');
1269
- if (/status:\s*["']?passed/i.test(vContent)) return 'verified';
1270
- if (/status:\s*["']?gaps_found/i.test(vContent)) return 'needs_fixes';
1271
- return 'reviewed';
1272
- } catch (_) {
1273
- return 'built';
1274
- }
421
+ function claimRelease(phaseSlug, sessionId) {
422
+ const phaseDir = path.join(planningDir, 'phases', phaseSlug);
423
+ if (!fs.existsSync(phaseDir)) return { error: `Phase directory not found: ${phaseSlug}` };
424
+ return releaseClaim(planningDir, phaseDir, sessionId);
1275
425
  }
1276
426
 
1277
- function countMustHaves(mustHaves) {
1278
- if (!mustHaves) return 0;
1279
- return (mustHaves.truths || []).length +
1280
- (mustHaves.artifacts || []).length +
1281
- (mustHaves.key_links || []).length;
427
+ function claimList() {
428
+ return _listClaims(planningDir);
1282
429
  }
1283
430
 
1284
- function calculateProgress() {
1285
- const phasesDir = path.join(planningDir, 'phases');
1286
- if (!fs.existsSync(phasesDir)) {
1287
- return { total: 0, completed: 0, percentage: 0 };
1288
- }
1289
-
1290
- let total = 0;
1291
- let completed = 0;
1292
-
1293
- const entries = fs.readdirSync(phasesDir, { withFileTypes: true })
1294
- .filter(e => e.isDirectory());
1295
-
1296
- for (const entry of entries) {
1297
- const dir = path.join(phasesDir, entry.name);
1298
- const plans = findFiles(dir, /-PLAN\.md$/);
1299
- total += plans.length;
1300
431
 
1301
- const summaries = findFiles(dir, /^SUMMARY-.*\.md$/);
1302
- for (const s of summaries) {
1303
- const content = fs.readFileSync(path.join(dir, s), 'utf8');
1304
- if (/status:\s*["']?complete/i.test(content)) completed++;
1305
- }
1306
- }
432
+ // --- CLI entry point (thin router — delegates to command modules) ---
1307
433
 
1308
- return {
1309
- total,
1310
- completed,
1311
- percentage: total > 0 ? Math.round((completed / total) * 100) : 0
1312
- };
1313
- }
1314
-
1315
- function output(data) {
1316
- process.stdout.write(JSON.stringify(data, null, 2));
1317
- process.exit(0);
1318
- }
1319
-
1320
- function error(msg) {
1321
- process.stdout.write(JSON.stringify({ error: msg }));
1322
- process.exit(1);
1323
- }
1324
-
1325
- /**
1326
- * Write content to a file atomically: write to .tmp, backup original to .bak,
1327
- * rename .tmp over original. On failure, restore from .bak if available.
1328
- *
1329
- * @param {string} filePath - Target file path
1330
- * @param {string} content - Content to write
1331
- * @returns {{success: boolean, error?: string}} Result
1332
- */
1333
- function atomicWrite(filePath, content) {
1334
- const tmpPath = filePath + '.tmp';
1335
- const bakPath = filePath + '.bak';
434
+ async function main() {
435
+ const args = process.argv.slice(2);
436
+ const command = args[0];
437
+ const ctx = { planningDir, cwd, output, error };
1336
438
 
1337
439
  try {
1338
- // 1. Write to temp file
1339
- fs.writeFileSync(tmpPath, content, 'utf8');
1340
-
1341
- // 2. Backup original if it exists
1342
- if (fs.existsSync(filePath)) {
1343
- try {
1344
- fs.copyFileSync(filePath, bakPath);
1345
- } catch (_e) {
1346
- // Backup failure is non-fatal proceed with rename
440
+ if (command === 'state') {
441
+ await handleState(args, ctx);
442
+ } else if (command === 'state-bundle') {
443
+ handleStateBundle(args, ctx);
444
+ } else if (command === 'config' || command === 'validate') {
445
+ await handleConfig(args, ctx);
446
+ } else if (command === 'roadmap') {
447
+ await handleRoadmap(args, ctx);
448
+ } else if (command === 'phase') {
449
+ await handlePhase(args, ctx);
450
+ } else if (command === 'compound') {
451
+ await handleCompound(args, ctx);
452
+ } else if (command === 'init') {
453
+ await handleInit(args, ctx);
454
+ } else if (['plan-index', 'frontmatter', 'must-haves', 'phase-info', 'milestone-stats'].includes(command)) {
455
+ handlePhaseDirect(args, ctx);
456
+ } else if (command === 'verify') {
457
+ handleVerify(args, ctx);
458
+ } else if (command === 'spot-check') {
459
+ handleSpotCheckDirect(args, ctx);
460
+ } else if (command === 'staleness-check') {
461
+ handleStalenessCheck(args, ctx);
462
+ } else if (command === 'summary-gate') {
463
+ handleSummaryGate(args, ctx);
464
+ } else if (command === 'checkpoint') {
465
+ handleCheckpoint(args, ctx);
466
+ } else if (command === 'seeds') {
467
+ handleSeeds(args, ctx);
468
+ } else if (command === 'todo') {
469
+ handleTodo(args, ctx);
470
+ } else if (command === 'history') {
471
+ handleHistory(args, ctx);
472
+ } else if (command === 'auto-cleanup') {
473
+ handleAutoCleanup(args, ctx);
474
+ } else if (command === 'benchmarks') {
475
+ await handleBenchmarks(args, ctx);
476
+ } else if (command === 'calibrate') {
477
+ handleCalibrate(args, ctx);
478
+ } else if (command === 'stress-test') {
479
+ await handleStressTest(args, ctx);
480
+ } else {
481
+ // Delegate to misc handler for all remaining commands
482
+ const result = await handleMisc(args, ctx);
483
+ if (result === 'NOT_HANDLED') {
484
+ error(`Unknown command: ${args.join(' ')}\nRun: pbr-tools.js help`);
1347
485
  }
1348
486
  }
1349
-
1350
- // 3. Rename temp over original (atomic on most filesystems)
1351
- fs.renameSync(tmpPath, filePath);
1352
-
1353
- return { success: true };
1354
487
  } catch (e) {
1355
- // Rename failed — try to restore from backup
1356
- try {
1357
- if (fs.existsSync(bakPath)) {
1358
- fs.copyFileSync(bakPath, filePath);
1359
- }
1360
- } catch (_restoreErr) {
1361
- // Restore also failed — nothing more we can do
1362
- }
1363
-
1364
- // Clean up temp file if it still exists
1365
- try {
1366
- if (fs.existsSync(tmpPath)) {
1367
- fs.unlinkSync(tmpPath);
1368
- }
1369
- } catch (_cleanupErr) {
1370
- // Best-effort cleanup
1371
- }
1372
-
1373
- return { success: false, error: e.message };
488
+ error(e.message);
1374
489
  }
1375
490
  }
1376
491
 
1377
- if (require.main === module || process.argv[1] === __filename) { main(); }
1378
- module.exports = { parseStateMd, parseRoadmapMd, parseYamlFrontmatter, parseMustHaves, countMustHaves, stateLoad, stateCheckProgress, configLoad, configClearCache, configValidate, lockedFileUpdate, planIndex, determinePhaseStatus, findFiles, atomicWrite, tailLines, frontmatter, mustHavesCollect, phaseInfo, stateUpdate, roadmapUpdateStatus, roadmapUpdatePlans, updateLegacyStateField, updateFrontmatterField, updateTableRow, findRoadmapRow, resolveDepthProfile, DEPTH_PROFILE_DEFAULTS, historyAppend, historyLoad, VALID_STATUS_TRANSITIONS, validateStatusTransition };
492
+ if (require.main === module || process.argv[1] === __filename) { main().catch(err => { process.stderr.write(err.message + '\n'); process.exit(1); }); }
493
+ module.exports = { KNOWN_AGENTS, initExecutePhase, initPlanPhase, initQuick, initVerifyWork, initResume, initProgress, initStateBundle: stateBundle, stateBundle, statePatch, stateAdvancePlan, stateRecordMetric, stateRecordActivity, stateUpdateProgress, parseStateMd, parseRoadmapMd, parseYamlFrontmatter, parseMustHaves, countMustHaves, stateLoad, stateCheckProgress, configLoad, configClearCache, configValidate, lockedFileUpdate, planIndex, determinePhaseStatus, findFiles, atomicWrite, tailLines, frontmatter, mustHavesCollect, phaseInfo, stateUpdate, roadmapUpdateStatus, roadmapUpdatePlans, roadmapAnalyze, updateFrontmatterField, updateTableRow, findRoadmapRow, resolveDepthProfile, DEPTH_PROFILE_DEFAULTS, historyAppend, historyLoad, VALID_STATUS_TRANSITIONS, validateStatusTransition, writeActiveSkill, phaseAdd, phaseRemove, phaseList, loadUserDefaults, saveUserDefaults, mergeUserDefaults, USER_DEFAULTS_PATH, todoList, todoGet, todoAdd, todoDone, migrate, verifySpotCheck, referenceGet, milestoneStats, contextTriage, stalenessCheck, summaryGate, checkpointInit, checkpointUpdate, seedsMatch, ciPoll, ciFix, parseJestOutput: _parseJestOutput, parseLintOutput: _parseLintOutput, autoFixLint: _autoFixLint, runCiFixLoop: _runCiFixLoop, rollbackPlan, sessionLoad, sessionSave, SESSION_ALLOWED_KEYS, claimAcquire, claimRelease, claimList, skillSectionGet, listSkillHeadings, stepVerify: _stepVerify, phaseAlternatives: _phaseAlternatives, prerequisiteAlternatives: _prereqAlternatives, configAlternatives: _configAlternatives, phaseComplete, phaseInsert, quickStatus, autoCloseTodos, autoArchiveNotes, buildCleanupContext, helpListCmd, skillMetadataCmd, initMapCodebase };