@sienklogic/plan-build-run 2.21.0 → 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 (983) hide show
  1. package/CHANGELOG.md +1331 -299
  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 +212 -34
  147. package/plugins/pbr/agents/dev-sync.md +206 -0
  148. package/plugins/pbr/agents/executor.md +737 -39
  149. package/plugins/pbr/agents/general.md +71 -6
  150. package/plugins/pbr/agents/integration-checker.md +148 -30
  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 -66
  154. package/plugins/pbr/agents/planner.md +451 -42
  155. package/plugins/pbr/agents/researcher.md +219 -36
  156. package/plugins/pbr/agents/roadmapper.md +398 -0
  157. package/plugins/pbr/agents/synthesizer.md +166 -26
  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 +571 -47
  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/do.md +5 -0
  172. package/plugins/pbr/commands/execute-phase.md +6 -0
  173. package/plugins/pbr/commands/fast.md +6 -0
  174. package/plugins/pbr/commands/forensics.md +6 -0
  175. package/plugins/pbr/commands/import.md +1 -1
  176. package/plugins/pbr/commands/insert-phase.md +65 -0
  177. package/plugins/pbr/commands/intel.md +5 -0
  178. package/plugins/pbr/commands/join-discord.md +11 -0
  179. package/plugins/pbr/commands/list-phase-assumptions.md +5 -0
  180. package/plugins/pbr/commands/map-codebase.md +6 -0
  181. package/plugins/pbr/commands/milestone-summary.md +6 -0
  182. package/plugins/pbr/commands/new-milestone.md +8 -0
  183. package/plugins/pbr/commands/new-project.md +6 -0
  184. package/plugins/pbr/commands/pause-work.md +5 -0
  185. package/plugins/pbr/commands/plan-milestone-gaps.md +7 -0
  186. package/plugins/pbr/commands/plan-phase.md +6 -0
  187. package/plugins/pbr/commands/plant-seed.md +6 -0
  188. package/plugins/pbr/commands/profile-user.md +5 -0
  189. package/plugins/pbr/commands/profile.md +5 -0
  190. package/plugins/pbr/commands/progress.md +6 -0
  191. package/plugins/pbr/commands/quick.md +1 -1
  192. package/plugins/pbr/commands/reapply-patches.md +47 -0
  193. package/plugins/pbr/commands/release.md +6 -0
  194. package/plugins/pbr/commands/remove-phase.md +66 -0
  195. package/plugins/pbr/commands/research-phase.md +59 -0
  196. package/plugins/pbr/commands/resume-work.md +5 -0
  197. package/plugins/pbr/commands/seed.md +6 -0
  198. package/plugins/pbr/commands/session-report.md +5 -0
  199. package/plugins/pbr/commands/set-profile.md +6 -0
  200. package/plugins/pbr/commands/settings.md +5 -0
  201. package/plugins/pbr/commands/setup.md +1 -1
  202. package/plugins/pbr/commands/ship.md +5 -0
  203. package/plugins/pbr/commands/stats.md +6 -0
  204. package/plugins/pbr/commands/test.md +5 -0
  205. package/plugins/pbr/commands/thread.md +6 -0
  206. package/plugins/pbr/commands/todo.md +1 -1
  207. package/plugins/pbr/commands/ui-phase.md +5 -0
  208. package/plugins/pbr/commands/ui-review.md +5 -0
  209. package/plugins/pbr/commands/undo.md +5 -0
  210. package/plugins/pbr/commands/update.md +37 -0
  211. package/plugins/pbr/commands/validate-phase.md +5 -0
  212. package/plugins/pbr/commands/verify-work.md +6 -0
  213. package/plugins/pbr/dashboard/package-lock.json +6 -0
  214. package/plugins/pbr/dist/architecture-guard.js +76 -0
  215. package/plugins/pbr/dist/audit-dimensions.js +556 -0
  216. package/plugins/pbr/dist/auto-continue.js +277 -0
  217. package/plugins/pbr/dist/block-skill-self-read.js +124 -0
  218. package/plugins/pbr/dist/check-agent-state-write.js +63 -0
  219. package/plugins/pbr/dist/check-config-change.js +213 -0
  220. package/plugins/pbr/dist/check-cross-plugin-sync.js +93 -0
  221. package/plugins/pbr/dist/check-dangerous-commands.js +193 -0
  222. package/plugins/pbr/dist/check-direct-state-write.js +37 -0
  223. package/plugins/pbr/dist/check-doc-sprawl.js +102 -0
  224. package/plugins/pbr/dist/check-phase-boundary.js +191 -0
  225. package/plugins/pbr/dist/check-plan-format.js +227 -0
  226. package/plugins/pbr/dist/check-read-first.js +345 -0
  227. package/plugins/pbr/dist/check-roadmap-sync.js +507 -0
  228. package/plugins/pbr/dist/check-skill-workflow.js +354 -0
  229. package/plugins/pbr/dist/check-state-sync.js +676 -0
  230. package/plugins/pbr/dist/check-subagent-output.js +425 -0
  231. package/plugins/pbr/dist/check-summary-gate.js +188 -0
  232. package/plugins/pbr/dist/context-bridge.js +425 -0
  233. package/plugins/pbr/dist/context-budget-check.js +442 -0
  234. package/plugins/pbr/dist/context-quality.js +271 -0
  235. package/plugins/pbr/dist/enforce-context-budget.js +138 -0
  236. package/plugins/pbr/dist/enforce-pbr-workflow.js +277 -0
  237. package/plugins/pbr/dist/event-handler.js +212 -0
  238. package/plugins/pbr/dist/event-logger.js +125 -0
  239. package/plugins/pbr/dist/feedback-loop.js +155 -0
  240. package/plugins/pbr/dist/graph-update.js +422 -0
  241. package/plugins/pbr/dist/hook-logger.js +114 -0
  242. package/plugins/pbr/dist/hook-server-client.js +361 -0
  243. package/plugins/pbr/dist/hook-server.js +664 -0
  244. package/plugins/pbr/dist/hooks-schema.json +87 -0
  245. package/plugins/pbr/dist/instructions-loaded.js +173 -0
  246. package/plugins/pbr/dist/intercept-plan-mode.js +81 -0
  247. package/plugins/pbr/dist/log-notification.js +131 -0
  248. package/plugins/pbr/dist/log-subagent.js +367 -0
  249. package/plugins/pbr/dist/log-tool-failure.js +140 -0
  250. package/plugins/pbr/dist/milestone-learnings.js +519 -0
  251. package/plugins/pbr/dist/pbr-tools.js +493 -0
  252. package/plugins/pbr/dist/post-bash-triage.js +96 -0
  253. package/plugins/pbr/dist/post-compact.js +135 -0
  254. package/plugins/pbr/dist/post-hoc.js +237 -0
  255. package/plugins/pbr/dist/post-write-dispatch.js +243 -0
  256. package/plugins/pbr/dist/post-write-quality.js +208 -0
  257. package/plugins/pbr/dist/pre-bash-dispatch.js +212 -0
  258. package/plugins/pbr/dist/pre-skill-dispatch.js +114 -0
  259. package/plugins/pbr/dist/pre-task-dispatch.js +269 -0
  260. package/plugins/pbr/dist/pre-write-dispatch.js +234 -0
  261. package/plugins/pbr/dist/progress-tracker.js +173 -0
  262. package/plugins/pbr/dist/prompt-guard.js +114 -0
  263. package/plugins/pbr/dist/prompt-routing.js +209 -0
  264. package/plugins/pbr/dist/quick-status.js +179 -0
  265. package/plugins/pbr/dist/record-incident.js +37 -0
  266. package/plugins/pbr/dist/run-hook.js +132 -0
  267. package/plugins/pbr/dist/session-cleanup.js +653 -0
  268. package/plugins/pbr/dist/session-tracker.js +124 -0
  269. package/plugins/pbr/dist/status-line.js +849 -0
  270. package/plugins/pbr/dist/suggest-compact.js +307 -0
  271. package/plugins/pbr/dist/sync-context-to-claude.js +100 -0
  272. package/plugins/pbr/dist/task-completed.js +206 -0
  273. package/plugins/pbr/dist/track-context-budget.js +432 -0
  274. package/plugins/pbr/dist/track-user-gates.js +88 -0
  275. package/plugins/pbr/dist/trust-tracker.js +193 -0
  276. package/plugins/pbr/dist/validate-commit.js +233 -0
  277. package/plugins/pbr/dist/validate-skill-args.js +222 -0
  278. package/plugins/pbr/dist/validate-task.js +271 -0
  279. package/plugins/pbr/dist/worktree-create.js +144 -0
  280. package/plugins/pbr/dist/worktree-remove.js +147 -0
  281. package/plugins/pbr/hooks/hooks.json +137 -65
  282. package/plugins/pbr/references/agent-contracts.md +39 -8
  283. package/plugins/pbr/references/agent-teams.md +3 -3
  284. package/plugins/pbr/references/archive/checkpoints.md +189 -0
  285. package/plugins/pbr/references/archive/context-quality-tiers.md +45 -0
  286. package/plugins/pbr/references/archive/hook-ordering.md +89 -0
  287. package/plugins/pbr/references/archive/limitations.md +106 -0
  288. package/plugins/pbr/references/archive/pbr-rules.md +194 -0
  289. package/plugins/pbr/references/archive/pbr-tools-cli.md +415 -0
  290. package/plugins/pbr/references/archive/pretooluse-jsonl-behavior.md +58 -0
  291. package/plugins/pbr/references/archive/signal-files.md +41 -0
  292. package/plugins/pbr/references/archive/tmux-setup.md +288 -0
  293. package/plugins/pbr/references/archive/verification-matrix.md +34 -0
  294. package/plugins/pbr/references/archive/verification-patterns.md +277 -0
  295. package/plugins/pbr/references/archive/worktree-sparse-checkout.md +86 -0
  296. package/plugins/pbr/references/assumptions.md +42 -0
  297. package/plugins/pbr/references/checkpoints.md +723 -104
  298. package/plugins/pbr/references/config-reference.md +387 -10
  299. package/plugins/pbr/references/continuation-format.md +1 -0
  300. package/plugins/pbr/references/decimal-phase-calculation.md +65 -0
  301. package/plugins/pbr/references/deviation-rules.md +12 -0
  302. package/plugins/pbr/references/few-shot-examples/audit.md +77 -0
  303. package/plugins/pbr/references/few-shot-examples/check-plan-format.md +172 -0
  304. package/plugins/pbr/references/few-shot-examples/check-subagent-output.md +118 -0
  305. package/plugins/pbr/references/few-shot-examples/integration-checker.md +70 -0
  306. package/plugins/pbr/references/few-shot-examples/nyquist-auditor.md +83 -0
  307. package/plugins/pbr/references/few-shot-examples/plan-checker.md +73 -0
  308. package/plugins/pbr/references/few-shot-examples/ui-checker.md +71 -0
  309. package/plugins/pbr/references/few-shot-examples/verifier.md +109 -0
  310. package/plugins/pbr/references/git-integration.md +110 -27
  311. package/plugins/pbr/references/git-planning-commit.md +35 -0
  312. package/plugins/pbr/references/model-profile-resolution.md +34 -0
  313. package/plugins/pbr/references/model-profiles.md +90 -7
  314. package/plugins/pbr/references/model-selection.md +1 -1
  315. package/plugins/pbr/references/node-repair.md +48 -0
  316. package/plugins/pbr/references/plan-authoring.md +65 -0
  317. package/plugins/pbr/references/plan-format.md +184 -10
  318. package/plugins/pbr/references/questioning.md +138 -49
  319. package/plugins/pbr/references/reading-verification.md +4 -4
  320. package/plugins/pbr/references/tdd.md +263 -0
  321. package/plugins/pbr/references/thinking-models-planning.md +47 -0
  322. package/plugins/pbr/references/thinking-models-verification.md +44 -0
  323. package/plugins/pbr/references/ui-brand.md +449 -0
  324. package/plugins/pbr/references/verification-overrides.md +39 -0
  325. package/plugins/pbr/references/verification-patterns.md +529 -113
  326. package/plugins/pbr/scripts/architecture-guard.js +76 -0
  327. package/plugins/pbr/scripts/audit-checks/behavioral-compliance.js +2098 -0
  328. package/plugins/pbr/scripts/audit-checks/error-analysis.js +989 -0
  329. package/plugins/pbr/scripts/audit-checks/feature-verification.js +723 -0
  330. package/plugins/pbr/scripts/audit-checks/index.js +433 -0
  331. package/plugins/pbr/scripts/audit-checks/infrastructure.js +816 -0
  332. package/plugins/pbr/scripts/audit-checks/quality-metrics.js +455 -0
  333. package/plugins/pbr/scripts/audit-checks/session-quality.js +980 -0
  334. package/plugins/pbr/scripts/audit-checks/si-agent-hook-config-checks.js +396 -0
  335. package/plugins/pbr/scripts/audit-checks/si-cross-cutting-checks.js +272 -0
  336. package/plugins/pbr/scripts/audit-checks/si-skill-checks.js +424 -0
  337. package/plugins/pbr/scripts/audit-checks/workflow-compliance.js +1175 -0
  338. package/plugins/pbr/scripts/audit-dimensions.js +556 -0
  339. package/plugins/pbr/scripts/auto-continue.js +192 -37
  340. package/plugins/pbr/scripts/block-skill-self-read.js +124 -0
  341. package/plugins/pbr/scripts/check-agent-state-write.js +63 -0
  342. package/plugins/pbr/scripts/check-config-change.js +84 -1
  343. package/plugins/pbr/scripts/check-cross-plugin-sync.js +93 -0
  344. package/plugins/pbr/scripts/check-dangerous-commands.js +18 -5
  345. package/plugins/pbr/scripts/check-direct-state-write.js +37 -0
  346. package/plugins/pbr/scripts/check-phase-boundary.js +3 -8
  347. package/plugins/pbr/scripts/check-plan-format.js +153 -278
  348. package/plugins/pbr/scripts/check-read-first.js +345 -0
  349. package/plugins/pbr/scripts/check-roadmap-sync.js +174 -19
  350. package/plugins/pbr/scripts/check-skill-workflow.js +24 -27
  351. package/plugins/pbr/scripts/check-state-sync.js +360 -218
  352. package/plugins/pbr/scripts/check-subagent-output.js +308 -273
  353. package/plugins/pbr/scripts/check-summary-gate.js +5 -15
  354. package/plugins/pbr/scripts/commands/benchmarks.js +195 -0
  355. package/plugins/pbr/scripts/commands/calibrate.js +530 -0
  356. package/plugins/pbr/scripts/commands/config.js +72 -0
  357. package/plugins/pbr/scripts/commands/misc.js +779 -0
  358. package/plugins/pbr/scripts/commands/phase.js +293 -0
  359. package/plugins/pbr/scripts/commands/roadmap.js +75 -0
  360. package/plugins/pbr/scripts/commands/state.js +84 -0
  361. package/plugins/pbr/scripts/commands/stress-test.js +349 -0
  362. package/plugins/pbr/scripts/commands/todo.js +191 -0
  363. package/plugins/pbr/scripts/commands/verify.js +169 -0
  364. package/plugins/pbr/scripts/config-schema.json +1183 -95
  365. package/plugins/pbr/scripts/context-bridge.js +425 -0
  366. package/plugins/pbr/scripts/context-budget-check.js +171 -16
  367. package/plugins/pbr/scripts/context-quality.js +271 -0
  368. package/plugins/pbr/scripts/enforce-context-budget.js +138 -0
  369. package/plugins/pbr/scripts/enforce-pbr-workflow.js +277 -0
  370. package/plugins/pbr/scripts/event-handler.js +137 -87
  371. package/plugins/pbr/scripts/event-logger.js +58 -25
  372. package/plugins/pbr/scripts/feedback-loop.js +155 -0
  373. package/plugins/pbr/scripts/graph-update.js +422 -0
  374. package/plugins/pbr/scripts/hook-logger.js +69 -35
  375. package/plugins/pbr/scripts/hook-server-client.js +361 -0
  376. package/plugins/pbr/scripts/hook-server.js +664 -0
  377. package/plugins/pbr/scripts/hooks-schema.json +12 -5
  378. package/plugins/pbr/scripts/instructions-loaded.js +173 -0
  379. package/plugins/pbr/scripts/intent-router.cjs +147 -0
  380. package/plugins/pbr/scripts/intercept-plan-mode.js +52 -18
  381. package/plugins/pbr/scripts/lib/alternatives.js +203 -0
  382. package/plugins/pbr/scripts/lib/audit.js +65 -0
  383. package/plugins/pbr/scripts/lib/auto-cleanup.js +221 -0
  384. package/plugins/pbr/scripts/lib/auto-verify.js +123 -0
  385. package/plugins/pbr/scripts/lib/benchmark.js +190 -0
  386. package/plugins/pbr/scripts/lib/build.js +719 -0
  387. package/plugins/pbr/scripts/lib/ci-fix-loop.js +228 -0
  388. package/plugins/pbr/scripts/lib/commands.js +483 -0
  389. package/plugins/pbr/scripts/lib/compound.js +222 -0
  390. package/plugins/pbr/scripts/lib/config-cache.js +83 -0
  391. package/plugins/pbr/scripts/lib/config.js +1469 -0
  392. package/plugins/pbr/scripts/lib/context.js +254 -0
  393. package/plugins/pbr/scripts/lib/contextual-help.js +183 -0
  394. package/plugins/pbr/scripts/lib/convention-detector.js +413 -0
  395. package/plugins/pbr/scripts/lib/core.js +1585 -0
  396. package/plugins/pbr/scripts/lib/dashboard-launch.js +364 -0
  397. package/plugins/pbr/scripts/lib/data-hygiene.js +179 -0
  398. package/plugins/pbr/scripts/lib/decision-extraction.js +183 -0
  399. package/plugins/pbr/scripts/lib/decisions.js +194 -0
  400. package/plugins/pbr/scripts/lib/dependency-break.js +147 -0
  401. package/plugins/pbr/scripts/lib/format-validators.js +1049 -0
  402. package/plugins/pbr/scripts/lib/frontmatter.js +302 -0
  403. package/plugins/pbr/scripts/lib/gates/advisories.js +133 -0
  404. package/plugins/pbr/scripts/lib/gates/build-dependency.js +118 -0
  405. package/plugins/pbr/scripts/lib/gates/build-executor.js +106 -0
  406. package/plugins/pbr/scripts/lib/gates/doc-existence.js +46 -0
  407. package/plugins/pbr/scripts/lib/gates/helpers.js +98 -0
  408. package/plugins/pbr/scripts/lib/gates/inline-execution.js +187 -0
  409. package/plugins/pbr/scripts/lib/gates/milestone-complete.js +139 -0
  410. package/plugins/pbr/scripts/lib/gates/milestone-summary.js +121 -0
  411. package/plugins/pbr/scripts/lib/gates/multi-phase-loader.js +149 -0
  412. package/plugins/pbr/scripts/lib/gates/plan-executor.js +36 -0
  413. package/plugins/pbr/scripts/lib/gates/plan-validation.js +115 -0
  414. package/plugins/pbr/scripts/lib/gates/quick-executor.js +78 -0
  415. package/plugins/pbr/scripts/lib/gates/review-planner.js +63 -0
  416. package/plugins/pbr/scripts/lib/gates/review-verifier.js +71 -0
  417. package/plugins/pbr/scripts/lib/gates/rich-agent-context.js +148 -0
  418. package/plugins/pbr/scripts/lib/gates/sprint-preflight.js +30 -0
  419. package/plugins/pbr/scripts/lib/gates/user-confirmation.js +95 -0
  420. package/plugins/pbr/scripts/lib/graph-cli.js +89 -0
  421. package/plugins/pbr/scripts/lib/graph.js +553 -0
  422. package/plugins/pbr/scripts/lib/handoff-validators.js +224 -0
  423. package/plugins/pbr/scripts/lib/health-checks.js +107 -0
  424. package/plugins/pbr/scripts/lib/health-phase06.js +120 -0
  425. package/plugins/pbr/scripts/lib/health.js +132 -0
  426. package/plugins/pbr/scripts/lib/help.js +100 -0
  427. package/plugins/pbr/scripts/lib/history.js +150 -0
  428. package/plugins/pbr/scripts/lib/impact-analysis.js +319 -0
  429. package/plugins/pbr/scripts/lib/incidents.js +190 -0
  430. package/plugins/pbr/scripts/lib/init.js +643 -0
  431. package/plugins/pbr/scripts/lib/insights-parser.js +320 -0
  432. package/plugins/pbr/scripts/lib/intel.js +653 -0
  433. package/plugins/pbr/scripts/lib/learnings.js +511 -0
  434. package/plugins/pbr/scripts/lib/migrate.js +309 -0
  435. package/plugins/pbr/scripts/lib/milestone.js +306 -0
  436. package/plugins/pbr/scripts/lib/msys-path.js +20 -0
  437. package/plugins/pbr/scripts/lib/negative-knowledge.js +194 -0
  438. package/plugins/pbr/scripts/lib/notification-throttle.js +141 -0
  439. package/plugins/pbr/scripts/lib/onboarding-generator.js +288 -0
  440. package/plugins/pbr/scripts/lib/parse-args.js +134 -0
  441. package/plugins/pbr/scripts/lib/pattern-routing.js +55 -0
  442. package/plugins/pbr/scripts/lib/patterns.js +272 -0
  443. package/plugins/pbr/scripts/lib/perf.js +190 -0
  444. package/plugins/pbr/scripts/lib/phase.js +1043 -0
  445. package/plugins/pbr/scripts/lib/pid-lock.js +156 -0
  446. package/plugins/pbr/scripts/lib/post-hoc.js +160 -0
  447. package/plugins/pbr/scripts/lib/pre-commit-checks.js +220 -0
  448. package/plugins/pbr/scripts/lib/pre-research.js +126 -0
  449. package/plugins/pbr/scripts/lib/premature-completion.js +312 -0
  450. package/plugins/pbr/scripts/lib/preview.js +174 -0
  451. package/plugins/pbr/scripts/lib/progress-visualization.js +296 -0
  452. package/plugins/pbr/scripts/lib/quick-init.js +131 -0
  453. package/plugins/pbr/scripts/lib/reference.js +236 -0
  454. package/plugins/pbr/scripts/lib/requirements.js +153 -0
  455. package/plugins/pbr/scripts/lib/resolve-root.js +66 -0
  456. package/plugins/pbr/scripts/lib/reverse-spec.js +259 -0
  457. package/plugins/pbr/scripts/lib/roadmap.js +1089 -0
  458. package/plugins/pbr/scripts/lib/security-scan.js +200 -0
  459. package/plugins/pbr/scripts/lib/session-briefing.js +918 -0
  460. package/plugins/pbr/scripts/lib/skill-section.js +99 -0
  461. package/plugins/pbr/scripts/lib/smart-next-task.js +198 -0
  462. package/plugins/pbr/scripts/lib/snapshot-manager.js +232 -0
  463. package/plugins/pbr/scripts/lib/spec-diff.js +209 -0
  464. package/plugins/pbr/scripts/lib/spec-engine.js +189 -0
  465. package/plugins/pbr/scripts/lib/spot-check.js +539 -0
  466. package/plugins/pbr/scripts/lib/state-queue.js +171 -0
  467. package/plugins/pbr/scripts/lib/state.js +1082 -0
  468. package/plugins/pbr/scripts/lib/status-render.js +511 -0
  469. package/plugins/pbr/scripts/lib/step-verify.js +149 -0
  470. package/plugins/pbr/scripts/lib/subagent-validators.js +1119 -0
  471. package/plugins/pbr/scripts/lib/suggest-next.js +435 -0
  472. package/plugins/pbr/scripts/lib/tech-debt-scanner.js +116 -0
  473. package/plugins/pbr/scripts/lib/templates.js +362 -0
  474. package/plugins/pbr/scripts/lib/test-selection.js +163 -0
  475. package/plugins/pbr/scripts/lib/todo.js +300 -0
  476. package/plugins/pbr/scripts/lib/verify.js +1561 -0
  477. package/plugins/pbr/scripts/log-notification.js +131 -0
  478. package/plugins/pbr/scripts/log-subagent.js +221 -18
  479. package/plugins/pbr/scripts/log-tool-failure.js +60 -8
  480. package/plugins/pbr/scripts/milestone-learnings.js +519 -0
  481. package/plugins/pbr/scripts/package.json +1 -1
  482. package/plugins/pbr/scripts/pbr-tools.js +362 -1247
  483. package/plugins/pbr/scripts/post-bash-triage.js +96 -0
  484. package/plugins/pbr/scripts/post-compact.js +135 -0
  485. package/plugins/pbr/scripts/post-hoc.js +237 -0
  486. package/plugins/pbr/scripts/post-write-dispatch.js +201 -31
  487. package/plugins/pbr/scripts/post-write-quality.js +4 -3
  488. package/plugins/pbr/scripts/pre-bash-dispatch.js +147 -51
  489. package/plugins/pbr/scripts/pre-skill-dispatch.js +114 -0
  490. package/plugins/pbr/scripts/pre-task-dispatch.js +269 -0
  491. package/plugins/pbr/scripts/pre-write-dispatch.js +170 -73
  492. package/plugins/pbr/scripts/progress-tracker.js +121 -324
  493. package/plugins/pbr/scripts/prompt-guard.js +114 -0
  494. package/plugins/pbr/scripts/prompt-routing.js +209 -0
  495. package/plugins/pbr/scripts/quick-status.js +179 -0
  496. package/plugins/pbr/scripts/record-incident.js +37 -0
  497. package/plugins/pbr/scripts/risk-classifier.cjs +123 -0
  498. package/plugins/pbr/scripts/run-hook.js +63 -23
  499. package/plugins/pbr/scripts/session-cleanup.js +428 -29
  500. package/plugins/pbr/scripts/session-tracker.js +124 -0
  501. package/plugins/pbr/scripts/status-line.js +593 -32
  502. package/plugins/pbr/scripts/suggest-compact.js +201 -13
  503. package/plugins/pbr/scripts/sync-context-to-claude.js +100 -0
  504. package/plugins/pbr/scripts/task-completed.js +165 -4
  505. package/plugins/pbr/scripts/test/config.test.js +126 -0
  506. package/plugins/pbr/scripts/test/cross-platform.test.js +120 -0
  507. package/plugins/pbr/scripts/test/fixtures/config.json +20 -0
  508. package/plugins/pbr/scripts/test/fixtures/plan.md +54 -0
  509. package/plugins/pbr/scripts/test/fixtures/project.md +30 -0
  510. package/plugins/pbr/scripts/test/fixtures/roadmap.md +55 -0
  511. package/plugins/pbr/scripts/test/fixtures/state.md +60 -0
  512. package/plugins/pbr/scripts/test/fixtures/summary.md +35 -0
  513. package/plugins/pbr/scripts/test/fixtures.test.js +184 -0
  514. package/plugins/pbr/scripts/test/phase.test.js +142 -0
  515. package/plugins/pbr/scripts/test/roadmap.test.js +96 -0
  516. package/plugins/pbr/scripts/test/state.test.js +155 -0
  517. package/plugins/pbr/scripts/track-context-budget.js +368 -104
  518. package/plugins/pbr/scripts/track-user-gates.js +88 -0
  519. package/plugins/pbr/scripts/trust-tracker.js +193 -0
  520. package/plugins/pbr/scripts/validate-commit.js +59 -26
  521. package/plugins/pbr/scripts/validate-skill-args.js +87 -15
  522. package/plugins/pbr/scripts/validate-task.js +83 -627
  523. package/plugins/pbr/scripts/worktree-create.js +144 -0
  524. package/plugins/pbr/scripts/worktree-remove.js +147 -0
  525. package/plugins/pbr/skills/audit/SKILL.md +195 -24
  526. package/plugins/pbr/skills/audit-fix/SKILL.md +326 -0
  527. package/plugins/pbr/skills/autonomous/SKILL.md +551 -0
  528. package/plugins/pbr/skills/backlog/SKILL.md +56 -0
  529. package/plugins/pbr/skills/begin/SKILL.md +508 -153
  530. package/plugins/pbr/skills/begin/templates/STATE.md.tmpl +1 -2
  531. package/plugins/pbr/skills/begin/templates/config.json.tmpl +419 -36
  532. package/plugins/pbr/skills/begin/templates/researcher-prompt.md.tmpl +28 -0
  533. package/plugins/pbr/skills/begin/templates/roadmap-prompt.md.tmpl +28 -3
  534. package/plugins/pbr/skills/begin/templates/synthesis-prompt.md.tmpl +33 -5
  535. package/plugins/pbr/skills/build/SKILL.md +1180 -358
  536. package/plugins/pbr/skills/build/templates/continuation-prompt.md.tmpl +26 -0
  537. package/plugins/pbr/skills/build/templates/executor-prompt.md.tmpl +77 -0
  538. package/plugins/pbr/skills/build/templates/inline-verifier-prompt.md.tmpl +33 -0
  539. package/plugins/pbr/skills/build/templates/qa-round-context.md.tmpl +16 -0
  540. package/plugins/pbr/skills/config/SKILL.md +112 -9
  541. package/plugins/pbr/skills/continue/SKILL.md +113 -33
  542. package/plugins/pbr/skills/dashboard/SKILL.md +21 -9
  543. package/plugins/pbr/skills/debug/SKILL.md +70 -12
  544. package/plugins/pbr/skills/debug/templates/continuation-prompt.md.tmpl +12 -1
  545. package/plugins/pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +12 -5
  546. package/plugins/pbr/skills/discuss/SKILL.md +205 -24
  547. package/plugins/pbr/skills/discuss/templates/CONTEXT.md.tmpl +21 -1
  548. package/plugins/pbr/skills/do/SKILL.md +119 -24
  549. package/plugins/pbr/skills/explore/SKILL.md +95 -20
  550. package/plugins/pbr/skills/fast/SKILL.md +94 -0
  551. package/plugins/pbr/skills/forensics/SKILL.md +144 -0
  552. package/plugins/pbr/skills/health/SKILL.md +35 -117
  553. package/plugins/pbr/skills/help/SKILL.md +83 -123
  554. package/plugins/pbr/skills/import/SKILL.md +332 -13
  555. package/plugins/pbr/skills/intel/SKILL.md +131 -0
  556. package/plugins/pbr/skills/list-phase-assumptions/SKILL.md +231 -0
  557. package/plugins/pbr/skills/milestone/SKILL.md +383 -274
  558. package/plugins/pbr/skills/milestone/templates/audit-output.md.tmpl +76 -0
  559. package/plugins/pbr/skills/milestone/templates/complete-output.md.tmpl +32 -0
  560. package/plugins/pbr/skills/milestone/templates/edge-cases.md +54 -0
  561. package/plugins/pbr/skills/milestone/templates/gaps-output.md.tmpl +25 -0
  562. package/plugins/pbr/skills/milestone/templates/integration-checker-prompt.md.tmpl +25 -0
  563. package/plugins/pbr/skills/milestone/templates/new-output.md.tmpl +29 -0
  564. package/plugins/pbr/skills/milestone-summary/SKILL.md +86 -0
  565. package/plugins/pbr/skills/note/SKILL.md +20 -4
  566. package/plugins/pbr/skills/pause/SKILL.md +54 -14
  567. package/plugins/pbr/skills/pause/templates/continue-here.md.tmpl +33 -52
  568. package/plugins/pbr/skills/plan/SKILL.md +526 -280
  569. package/plugins/pbr/skills/plan/templates/checker-prompt.md.tmpl +20 -2
  570. package/plugins/pbr/skills/plan/templates/completion-output.md.tmpl +27 -0
  571. package/plugins/pbr/skills/plan/templates/planner-prompt.md.tmpl +43 -1
  572. package/plugins/pbr/skills/plan/templates/revision-prompt.md.tmpl +21 -5
  573. package/plugins/pbr/skills/profile/SKILL.md +185 -0
  574. package/plugins/pbr/skills/profile-user/SKILL.md +227 -0
  575. package/plugins/pbr/skills/quick/SKILL.md +435 -100
  576. package/plugins/pbr/skills/release/SKILL.md +206 -0
  577. package/plugins/pbr/skills/resume/SKILL.md +170 -46
  578. package/plugins/pbr/skills/review/SKILL.md +233 -165
  579. package/plugins/pbr/skills/review/templates/verifier-prompt.md.tmpl +7 -0
  580. package/plugins/pbr/skills/scan/SKILL.md +152 -106
  581. package/plugins/pbr/skills/scan/templates/mapper-prompt.md.tmpl +5 -56
  582. package/plugins/pbr/skills/seed/SKILL.md +87 -0
  583. package/plugins/pbr/skills/session-report/SKILL.md +130 -0
  584. package/plugins/pbr/skills/setup/SKILL.md +150 -202
  585. package/plugins/pbr/skills/shared/agent-context-enrichment.md +21 -0
  586. package/plugins/pbr/skills/shared/agent-type-resolution.md +32 -0
  587. package/plugins/pbr/skills/shared/commit-planning-docs.md +8 -0
  588. package/plugins/pbr/skills/shared/context-budget.md +66 -1
  589. package/plugins/pbr/skills/shared/context-loader-task.md +18 -11
  590. package/plugins/pbr/skills/shared/criterion-writing.md +58 -0
  591. package/plugins/pbr/skills/shared/digest-select.md +2 -2
  592. package/plugins/pbr/skills/shared/domain-probes.md +1 -1
  593. package/plugins/pbr/skills/shared/error-reporting.md +38 -60
  594. package/plugins/pbr/skills/shared/gate-prompts.md +4 -2
  595. package/plugins/pbr/skills/shared/memory-capture.md +48 -0
  596. package/plugins/pbr/skills/shared/phase-argument-parsing.md +4 -4
  597. package/plugins/pbr/skills/shared/revision-loop.md +24 -6
  598. package/plugins/pbr/skills/shared/state-update.md +49 -56
  599. package/plugins/pbr/skills/shared/universal-anti-patterns.md +27 -4
  600. package/plugins/pbr/skills/ship/SKILL.md +155 -0
  601. package/plugins/pbr/skills/stats/SKILL.md +110 -0
  602. package/plugins/pbr/skills/status/SKILL.md +185 -119
  603. package/plugins/pbr/skills/test/SKILL.md +254 -0
  604. package/plugins/pbr/skills/thread/SKILL.md +73 -0
  605. package/plugins/pbr/skills/todo/SKILL.md +28 -72
  606. package/plugins/pbr/skills/ui-phase/SKILL.md +180 -0
  607. package/plugins/pbr/skills/ui-review/SKILL.md +206 -0
  608. package/plugins/pbr/skills/undo/SKILL.md +221 -0
  609. package/plugins/pbr/skills/validate-phase/SKILL.md +362 -0
  610. package/plugins/pbr/templates/CONTEXT.md.tmpl +45 -20
  611. package/plugins/pbr/templates/DISCOVERY.md.tmpl +29 -0
  612. package/plugins/pbr/templates/DISCUSSION-LOG.md.tmpl +49 -0
  613. package/plugins/pbr/templates/HANDOFF.json.tmpl +30 -0
  614. package/plugins/pbr/templates/INTEGRATION-REPORT.md.tmpl +18 -2
  615. package/plugins/pbr/templates/MILESTONE-AUDIT.md.tmpl +44 -0
  616. package/plugins/pbr/templates/PROJECT.md.tmpl +126 -0
  617. package/plugins/pbr/templates/REQUIREMENTS.md.tmpl +96 -0
  618. package/plugins/pbr/templates/RETROSPECTIVE.md.tmpl +43 -0
  619. package/plugins/pbr/templates/ROADMAP.md.tmpl +108 -14
  620. package/plugins/pbr/templates/SUMMARY-complex.md.tmpl +133 -0
  621. package/plugins/pbr/templates/SUMMARY-minimal.md.tmpl +55 -0
  622. package/plugins/pbr/templates/SUMMARY.md.tmpl +21 -0
  623. package/plugins/pbr/templates/UAT.md.tmpl +94 -0
  624. package/plugins/pbr/templates/UI-SPEC.md.tmpl +144 -0
  625. package/plugins/pbr/templates/VALIDATION.md.tmpl +94 -0
  626. package/plugins/pbr/templates/VERIFICATION-DETAIL.md.tmpl +54 -13
  627. package/plugins/pbr/templates/project-CONTEXT.md.tmpl +59 -0
  628. package/plugins/pbr/templates/research-outputs/ARCHITECTURE.md.tmpl +91 -0
  629. package/plugins/pbr/templates/research-outputs/FEATURES.md.tmpl +64 -0
  630. package/plugins/pbr/templates/research-outputs/PITFALLS.md.tmpl +50 -0
  631. package/plugins/pbr/templates/research-outputs/STACK.md.tmpl +63 -0
  632. package/plugins/pbr/templates/research-outputs/SUMMARY.md.tmpl +98 -0
  633. package/scripts/build-hooks.js +61 -0
  634. package/scripts/check-ci.js +100 -0
  635. package/scripts/clean-changelog.js +364 -0
  636. package/scripts/generate-derivatives.js +581 -0
  637. package/scripts/posttest.js +93 -0
  638. package/scripts/release.js +262 -0
  639. package/scripts/run-tests.cjs +29 -0
  640. package/scripts/test-wrapper.js +43 -0
  641. package/dashboard/bin/cli.js +0 -25
  642. package/dashboard/public/css/layout.css +0 -704
  643. package/dashboard/public/css/status-colors.css +0 -98
  644. package/dashboard/public/css/tokens.css +0 -59
  645. package/dashboard/public/js/htmx-title.js +0 -5
  646. package/dashboard/public/js/sidebar-toggle.js +0 -34
  647. package/dashboard/public/js/sse-client.js +0 -100
  648. package/dashboard/public/js/theme-toggle.js +0 -46
  649. package/dashboard/src/app.js +0 -91
  650. package/dashboard/src/middleware/current-phase.js +0 -24
  651. package/dashboard/src/middleware/errorHandler.js +0 -52
  652. package/dashboard/src/middleware/notFoundHandler.js +0 -9
  653. package/dashboard/src/repositories/planning.repository.js +0 -130
  654. package/dashboard/src/routes/events.routes.js +0 -45
  655. package/dashboard/src/routes/index.routes.js +0 -35
  656. package/dashboard/src/routes/pages.routes.js +0 -426
  657. package/dashboard/src/server.js +0 -42
  658. package/dashboard/src/services/analytics.service.js +0 -141
  659. package/dashboard/src/services/dashboard.service.js +0 -309
  660. package/dashboard/src/services/milestone.service.js +0 -222
  661. package/dashboard/src/services/notes.service.js +0 -50
  662. package/dashboard/src/services/phase.service.js +0 -232
  663. package/dashboard/src/services/project.service.js +0 -57
  664. package/dashboard/src/services/roadmap.service.js +0 -258
  665. package/dashboard/src/services/sse.service.js +0 -58
  666. package/dashboard/src/services/todo.service.js +0 -272
  667. package/dashboard/src/services/watcher.service.js +0 -48
  668. package/dashboard/src/utils/cache.js +0 -55
  669. package/dashboard/src/views/analytics.ejs +0 -5
  670. package/dashboard/src/views/coming-soon.ejs +0 -11
  671. package/dashboard/src/views/dependencies.ejs +0 -5
  672. package/dashboard/src/views/error.ejs +0 -20
  673. package/dashboard/src/views/index.ejs +0 -5
  674. package/dashboard/src/views/milestone-detail.ejs +0 -5
  675. package/dashboard/src/views/milestones.ejs +0 -5
  676. package/dashboard/src/views/notes.ejs +0 -5
  677. package/dashboard/src/views/partials/analytics-content.ejs +0 -90
  678. package/dashboard/src/views/partials/breadcrumbs.ejs +0 -14
  679. package/dashboard/src/views/partials/dashboard-content.ejs +0 -84
  680. package/dashboard/src/views/partials/dependencies-content.ejs +0 -48
  681. package/dashboard/src/views/partials/empty-state.ejs +0 -7
  682. package/dashboard/src/views/partials/footer.ejs +0 -3
  683. package/dashboard/src/views/partials/head.ejs +0 -30
  684. package/dashboard/src/views/partials/header.ejs +0 -21
  685. package/dashboard/src/views/partials/layout-bottom.ejs +0 -43
  686. package/dashboard/src/views/partials/layout-top.ejs +0 -16
  687. package/dashboard/src/views/partials/milestone-detail-content.ejs +0 -20
  688. package/dashboard/src/views/partials/milestones-content.ejs +0 -88
  689. package/dashboard/src/views/partials/notes-content.ejs +0 -23
  690. package/dashboard/src/views/partials/phase-content.ejs +0 -193
  691. package/dashboard/src/views/partials/phase-doc-content.ejs +0 -38
  692. package/dashboard/src/views/partials/phases-content.ejs +0 -124
  693. package/dashboard/src/views/partials/roadmap-content.ejs +0 -180
  694. package/dashboard/src/views/partials/sidebar.ejs +0 -99
  695. package/dashboard/src/views/partials/todo-create-content.ejs +0 -54
  696. package/dashboard/src/views/partials/todo-detail-content.ejs +0 -42
  697. package/dashboard/src/views/partials/todos-content.ejs +0 -97
  698. package/dashboard/src/views/phase-detail.ejs +0 -5
  699. package/dashboard/src/views/phase-doc.ejs +0 -5
  700. package/dashboard/src/views/phases.ejs +0 -5
  701. package/dashboard/src/views/roadmap.ejs +0 -5
  702. package/dashboard/src/views/todo-create.ejs +0 -5
  703. package/dashboard/src/views/todo-detail.ejs +0 -5
  704. package/dashboard/src/views/todos.ejs +0 -5
  705. package/plugins/copilot-pbr/CHANGELOG.md +0 -19
  706. package/plugins/copilot-pbr/README.md +0 -139
  707. package/plugins/copilot-pbr/agents/audit.agent.md +0 -113
  708. package/plugins/copilot-pbr/agents/codebase-mapper.agent.md +0 -151
  709. package/plugins/copilot-pbr/agents/debugger.agent.md +0 -182
  710. package/plugins/copilot-pbr/agents/executor.agent.md +0 -267
  711. package/plugins/copilot-pbr/agents/general.agent.md +0 -88
  712. package/plugins/copilot-pbr/agents/integration-checker.agent.md +0 -119
  713. package/plugins/copilot-pbr/agents/plan-checker.agent.md +0 -208
  714. package/plugins/copilot-pbr/agents/planner.agent.md +0 -238
  715. package/plugins/copilot-pbr/agents/researcher.agent.md +0 -186
  716. package/plugins/copilot-pbr/agents/synthesizer.agent.md +0 -126
  717. package/plugins/copilot-pbr/agents/verifier.agent.md +0 -228
  718. package/plugins/copilot-pbr/hooks/hooks.json +0 -258
  719. package/plugins/copilot-pbr/plugin.json +0 -30
  720. package/plugins/copilot-pbr/references/agent-anti-patterns.md +0 -25
  721. package/plugins/copilot-pbr/references/agent-contracts.md +0 -297
  722. package/plugins/copilot-pbr/references/agent-interactions.md +0 -135
  723. package/plugins/copilot-pbr/references/agent-teams.md +0 -55
  724. package/plugins/copilot-pbr/references/checkpoints.md +0 -158
  725. package/plugins/copilot-pbr/references/common-bug-patterns.md +0 -14
  726. package/plugins/copilot-pbr/references/config-reference.md +0 -442
  727. package/plugins/copilot-pbr/references/continuation-format.md +0 -213
  728. package/plugins/copilot-pbr/references/deviation-rules.md +0 -113
  729. package/plugins/copilot-pbr/references/git-integration.md +0 -227
  730. package/plugins/copilot-pbr/references/integration-patterns.md +0 -118
  731. package/plugins/copilot-pbr/references/model-profiles.md +0 -100
  732. package/plugins/copilot-pbr/references/model-selection.md +0 -32
  733. package/plugins/copilot-pbr/references/pbr-rules.md +0 -195
  734. package/plugins/copilot-pbr/references/pbr-tools-cli.md +0 -285
  735. package/plugins/copilot-pbr/references/plan-authoring.md +0 -182
  736. package/plugins/copilot-pbr/references/plan-format.md +0 -288
  737. package/plugins/copilot-pbr/references/planning-config.md +0 -214
  738. package/plugins/copilot-pbr/references/questioning.md +0 -215
  739. package/plugins/copilot-pbr/references/reading-verification.md +0 -128
  740. package/plugins/copilot-pbr/references/stub-patterns.md +0 -161
  741. package/plugins/copilot-pbr/references/subagent-coordination.md +0 -120
  742. package/plugins/copilot-pbr/references/ui-formatting.md +0 -444
  743. package/plugins/copilot-pbr/references/verification-patterns.md +0 -199
  744. package/plugins/copilot-pbr/references/wave-execution.md +0 -96
  745. package/plugins/copilot-pbr/rules/pbr-workflow.mdc +0 -48
  746. package/plugins/copilot-pbr/setup.ps1 +0 -93
  747. package/plugins/copilot-pbr/setup.sh +0 -93
  748. package/plugins/copilot-pbr/skills/audit/SKILL.md +0 -330
  749. package/plugins/copilot-pbr/skills/begin/SKILL.md +0 -589
  750. package/plugins/copilot-pbr/skills/begin/templates/PROJECT.md.tmpl +0 -34
  751. package/plugins/copilot-pbr/skills/begin/templates/REQUIREMENTS.md.tmpl +0 -19
  752. package/plugins/copilot-pbr/skills/begin/templates/STATE.md.tmpl +0 -50
  753. package/plugins/copilot-pbr/skills/begin/templates/config.json.tmpl +0 -64
  754. package/plugins/copilot-pbr/skills/begin/templates/researcher-prompt.md.tmpl +0 -20
  755. package/plugins/copilot-pbr/skills/begin/templates/roadmap-prompt.md.tmpl +0 -31
  756. package/plugins/copilot-pbr/skills/begin/templates/synthesis-prompt.md.tmpl +0 -17
  757. package/plugins/copilot-pbr/skills/build/SKILL.md +0 -960
  758. package/plugins/copilot-pbr/skills/config/SKILL.md +0 -250
  759. package/plugins/copilot-pbr/skills/continue/SKILL.md +0 -159
  760. package/plugins/copilot-pbr/skills/dashboard/SKILL.md +0 -43
  761. package/plugins/copilot-pbr/skills/debug/SKILL.md +0 -508
  762. package/plugins/copilot-pbr/skills/debug/templates/continuation-prompt.md.tmpl +0 -17
  763. package/plugins/copilot-pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +0 -28
  764. package/plugins/copilot-pbr/skills/discuss/SKILL.md +0 -353
  765. package/plugins/copilot-pbr/skills/discuss/templates/CONTEXT.md.tmpl +0 -62
  766. package/plugins/copilot-pbr/skills/discuss/templates/decision-categories.md +0 -10
  767. package/plugins/copilot-pbr/skills/do/SKILL.md +0 -66
  768. package/plugins/copilot-pbr/skills/explore/SKILL.md +0 -373
  769. package/plugins/copilot-pbr/skills/health/SKILL.md +0 -283
  770. package/plugins/copilot-pbr/skills/health/templates/check-pattern.md.tmpl +0 -31
  771. package/plugins/copilot-pbr/skills/health/templates/output-format.md.tmpl +0 -64
  772. package/plugins/copilot-pbr/skills/help/SKILL.md +0 -193
  773. package/plugins/copilot-pbr/skills/import/SKILL.md +0 -502
  774. package/plugins/copilot-pbr/skills/milestone/SKILL.md +0 -806
  775. package/plugins/copilot-pbr/skills/milestone/templates/audit-report.md.tmpl +0 -49
  776. package/plugins/copilot-pbr/skills/milestone/templates/stats-file.md.tmpl +0 -31
  777. package/plugins/copilot-pbr/skills/note/SKILL.md +0 -213
  778. package/plugins/copilot-pbr/skills/pause/SKILL.md +0 -247
  779. package/plugins/copilot-pbr/skills/pause/templates/continue-here.md.tmpl +0 -72
  780. package/plugins/copilot-pbr/skills/plan/SKILL.md +0 -662
  781. package/plugins/copilot-pbr/skills/plan/templates/checker-prompt.md.tmpl +0 -22
  782. package/plugins/copilot-pbr/skills/plan/templates/gap-closure-prompt.md.tmpl +0 -33
  783. package/plugins/copilot-pbr/skills/plan/templates/planner-prompt.md.tmpl +0 -39
  784. package/plugins/copilot-pbr/skills/plan/templates/researcher-prompt.md.tmpl +0 -20
  785. package/plugins/copilot-pbr/skills/plan/templates/revision-prompt.md.tmpl +0 -24
  786. package/plugins/copilot-pbr/skills/quick/SKILL.md +0 -376
  787. package/plugins/copilot-pbr/skills/resume/SKILL.md +0 -399
  788. package/plugins/copilot-pbr/skills/review/SKILL.md +0 -653
  789. package/plugins/copilot-pbr/skills/review/templates/debugger-prompt.md.tmpl +0 -61
  790. package/plugins/copilot-pbr/skills/review/templates/gap-planner-prompt.md.tmpl +0 -41
  791. package/plugins/copilot-pbr/skills/review/templates/verifier-prompt.md.tmpl +0 -116
  792. package/plugins/copilot-pbr/skills/scan/SKILL.md +0 -299
  793. package/plugins/copilot-pbr/skills/scan/templates/mapper-prompt.md.tmpl +0 -202
  794. package/plugins/copilot-pbr/skills/setup/SKILL.md +0 -296
  795. package/plugins/copilot-pbr/skills/shared/commit-planning-docs.md +0 -36
  796. package/plugins/copilot-pbr/skills/shared/config-loading.md +0 -103
  797. package/plugins/copilot-pbr/skills/shared/context-budget.md +0 -41
  798. package/plugins/copilot-pbr/skills/shared/context-loader-task.md +0 -87
  799. package/plugins/copilot-pbr/skills/shared/digest-select.md +0 -80
  800. package/plugins/copilot-pbr/skills/shared/domain-probes.md +0 -126
  801. package/plugins/copilot-pbr/skills/shared/error-recovery-strategies.md +0 -51
  802. package/plugins/copilot-pbr/skills/shared/error-reporting.md +0 -81
  803. package/plugins/copilot-pbr/skills/shared/gate-prompts.md +0 -389
  804. package/plugins/copilot-pbr/skills/shared/phase-argument-parsing.md +0 -46
  805. package/plugins/copilot-pbr/skills/shared/progress-display.md +0 -53
  806. package/plugins/copilot-pbr/skills/shared/revision-loop.md +0 -82
  807. package/plugins/copilot-pbr/skills/shared/state-loading.md +0 -63
  808. package/plugins/copilot-pbr/skills/shared/state-update.md +0 -162
  809. package/plugins/copilot-pbr/skills/shared/universal-anti-patterns.md +0 -38
  810. package/plugins/copilot-pbr/skills/status/SKILL.md +0 -362
  811. package/plugins/copilot-pbr/skills/statusline/SKILL.md +0 -149
  812. package/plugins/copilot-pbr/skills/todo/SKILL.md +0 -279
  813. package/plugins/copilot-pbr/templates/CONTEXT.md.tmpl +0 -53
  814. package/plugins/copilot-pbr/templates/INTEGRATION-REPORT.md.tmpl +0 -152
  815. package/plugins/copilot-pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -98
  816. package/plugins/copilot-pbr/templates/ROADMAP.md.tmpl +0 -41
  817. package/plugins/copilot-pbr/templates/SUMMARY.md.tmpl +0 -82
  818. package/plugins/copilot-pbr/templates/VERIFICATION-DETAIL.md.tmpl +0 -117
  819. package/plugins/copilot-pbr/templates/codebase/ARCHITECTURE.md.tmpl +0 -98
  820. package/plugins/copilot-pbr/templates/codebase/CONCERNS.md.tmpl +0 -93
  821. package/plugins/copilot-pbr/templates/codebase/CONVENTIONS.md.tmpl +0 -104
  822. package/plugins/copilot-pbr/templates/codebase/INTEGRATIONS.md.tmpl +0 -78
  823. package/plugins/copilot-pbr/templates/codebase/STACK.md.tmpl +0 -78
  824. package/plugins/copilot-pbr/templates/codebase/STRUCTURE.md.tmpl +0 -80
  825. package/plugins/copilot-pbr/templates/codebase/TESTING.md.tmpl +0 -107
  826. package/plugins/copilot-pbr/templates/continue-here.md.tmpl +0 -74
  827. package/plugins/copilot-pbr/templates/prompt-partials/phase-project-context.md.tmpl +0 -38
  828. package/plugins/copilot-pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
  829. package/plugins/copilot-pbr/templates/research/STACK.md.tmpl +0 -71
  830. package/plugins/copilot-pbr/templates/research/SUMMARY.md.tmpl +0 -112
  831. package/plugins/copilot-pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
  832. package/plugins/copilot-pbr/templates/research-outputs/project-research.md.tmpl +0 -99
  833. package/plugins/copilot-pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
  834. package/plugins/cursor-pbr/.cursor-plugin/plugin.json +0 -32
  835. package/plugins/cursor-pbr/CHANGELOG.md +0 -15
  836. package/plugins/cursor-pbr/README.md +0 -123
  837. package/plugins/cursor-pbr/agents/audit.md +0 -178
  838. package/plugins/cursor-pbr/agents/codebase-mapper.md +0 -150
  839. package/plugins/cursor-pbr/agents/debugger.md +0 -181
  840. package/plugins/cursor-pbr/agents/executor.md +0 -266
  841. package/plugins/cursor-pbr/agents/general.md +0 -87
  842. package/plugins/cursor-pbr/agents/integration-checker.md +0 -118
  843. package/plugins/cursor-pbr/agents/plan-checker.md +0 -207
  844. package/plugins/cursor-pbr/agents/planner.md +0 -237
  845. package/plugins/cursor-pbr/agents/researcher.md +0 -185
  846. package/plugins/cursor-pbr/agents/synthesizer.md +0 -125
  847. package/plugins/cursor-pbr/agents/verifier.md +0 -227
  848. package/plugins/cursor-pbr/assets/.gitkeep +0 -0
  849. package/plugins/cursor-pbr/assets/logo.svg +0 -21
  850. package/plugins/cursor-pbr/hooks/hooks.json +0 -224
  851. package/plugins/cursor-pbr/references/agent-anti-patterns.md +0 -25
  852. package/plugins/cursor-pbr/references/agent-contracts.md +0 -297
  853. package/plugins/cursor-pbr/references/agent-interactions.md +0 -135
  854. package/plugins/cursor-pbr/references/agent-teams.md +0 -55
  855. package/plugins/cursor-pbr/references/checkpoints.md +0 -158
  856. package/plugins/cursor-pbr/references/common-bug-patterns.md +0 -14
  857. package/plugins/cursor-pbr/references/config-reference.md +0 -442
  858. package/plugins/cursor-pbr/references/continuation-format.md +0 -213
  859. package/plugins/cursor-pbr/references/deviation-rules.md +0 -113
  860. package/plugins/cursor-pbr/references/git-integration.md +0 -227
  861. package/plugins/cursor-pbr/references/integration-patterns.md +0 -118
  862. package/plugins/cursor-pbr/references/model-profiles.md +0 -100
  863. package/plugins/cursor-pbr/references/model-selection.md +0 -32
  864. package/plugins/cursor-pbr/references/pbr-rules.md +0 -195
  865. package/plugins/cursor-pbr/references/pbr-tools-cli.md +0 -285
  866. package/plugins/cursor-pbr/references/plan-authoring.md +0 -182
  867. package/plugins/cursor-pbr/references/plan-format.md +0 -288
  868. package/plugins/cursor-pbr/references/planning-config.md +0 -214
  869. package/plugins/cursor-pbr/references/questioning.md +0 -215
  870. package/plugins/cursor-pbr/references/reading-verification.md +0 -128
  871. package/plugins/cursor-pbr/references/stub-patterns.md +0 -161
  872. package/plugins/cursor-pbr/references/subagent-coordination.md +0 -120
  873. package/plugins/cursor-pbr/references/ui-formatting.md +0 -444
  874. package/plugins/cursor-pbr/references/verification-patterns.md +0 -199
  875. package/plugins/cursor-pbr/references/wave-execution.md +0 -96
  876. package/plugins/cursor-pbr/rules/pbr-workflow.mdc +0 -48
  877. package/plugins/cursor-pbr/setup.ps1 +0 -78
  878. package/plugins/cursor-pbr/setup.sh +0 -83
  879. package/plugins/cursor-pbr/skills/audit/SKILL.md +0 -331
  880. package/plugins/cursor-pbr/skills/begin/SKILL.md +0 -589
  881. package/plugins/cursor-pbr/skills/begin/templates/PROJECT.md.tmpl +0 -34
  882. package/plugins/cursor-pbr/skills/begin/templates/REQUIREMENTS.md.tmpl +0 -19
  883. package/plugins/cursor-pbr/skills/begin/templates/STATE.md.tmpl +0 -50
  884. package/plugins/cursor-pbr/skills/begin/templates/config.json.tmpl +0 -64
  885. package/plugins/cursor-pbr/skills/begin/templates/researcher-prompt.md.tmpl +0 -20
  886. package/plugins/cursor-pbr/skills/begin/templates/roadmap-prompt.md.tmpl +0 -31
  887. package/plugins/cursor-pbr/skills/begin/templates/synthesis-prompt.md.tmpl +0 -17
  888. package/plugins/cursor-pbr/skills/build/SKILL.md +0 -961
  889. package/plugins/cursor-pbr/skills/config/SKILL.md +0 -252
  890. package/plugins/cursor-pbr/skills/continue/SKILL.md +0 -159
  891. package/plugins/cursor-pbr/skills/dashboard/SKILL.md +0 -44
  892. package/plugins/cursor-pbr/skills/debug/SKILL.md +0 -512
  893. package/plugins/cursor-pbr/skills/debug/templates/continuation-prompt.md.tmpl +0 -17
  894. package/plugins/cursor-pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +0 -28
  895. package/plugins/cursor-pbr/skills/discuss/SKILL.md +0 -354
  896. package/plugins/cursor-pbr/skills/discuss/templates/CONTEXT.md.tmpl +0 -62
  897. package/plugins/cursor-pbr/skills/discuss/templates/decision-categories.md +0 -10
  898. package/plugins/cursor-pbr/skills/do/SKILL.md +0 -67
  899. package/plugins/cursor-pbr/skills/explore/SKILL.md +0 -376
  900. package/plugins/cursor-pbr/skills/health/SKILL.md +0 -283
  901. package/plugins/cursor-pbr/skills/health/templates/check-pattern.md.tmpl +0 -31
  902. package/plugins/cursor-pbr/skills/health/templates/output-format.md.tmpl +0 -64
  903. package/plugins/cursor-pbr/skills/help/SKILL.md +0 -193
  904. package/plugins/cursor-pbr/skills/import/SKILL.md +0 -505
  905. package/plugins/cursor-pbr/skills/milestone/SKILL.md +0 -807
  906. package/plugins/cursor-pbr/skills/milestone/templates/audit-report.md.tmpl +0 -49
  907. package/plugins/cursor-pbr/skills/milestone/templates/stats-file.md.tmpl +0 -31
  908. package/plugins/cursor-pbr/skills/note/SKILL.md +0 -214
  909. package/plugins/cursor-pbr/skills/pause/SKILL.md +0 -248
  910. package/plugins/cursor-pbr/skills/pause/templates/continue-here.md.tmpl +0 -72
  911. package/plugins/cursor-pbr/skills/plan/SKILL.md +0 -663
  912. package/plugins/cursor-pbr/skills/plan/templates/checker-prompt.md.tmpl +0 -22
  913. package/plugins/cursor-pbr/skills/plan/templates/gap-closure-prompt.md.tmpl +0 -33
  914. package/plugins/cursor-pbr/skills/plan/templates/planner-prompt.md.tmpl +0 -39
  915. package/plugins/cursor-pbr/skills/plan/templates/researcher-prompt.md.tmpl +0 -20
  916. package/plugins/cursor-pbr/skills/plan/templates/revision-prompt.md.tmpl +0 -24
  917. package/plugins/cursor-pbr/skills/quick/SKILL.md +0 -376
  918. package/plugins/cursor-pbr/skills/resume/SKILL.md +0 -399
  919. package/plugins/cursor-pbr/skills/review/SKILL.md +0 -654
  920. package/plugins/cursor-pbr/skills/review/templates/debugger-prompt.md.tmpl +0 -61
  921. package/plugins/cursor-pbr/skills/review/templates/gap-planner-prompt.md.tmpl +0 -41
  922. package/plugins/cursor-pbr/skills/review/templates/verifier-prompt.md.tmpl +0 -116
  923. package/plugins/cursor-pbr/skills/scan/SKILL.md +0 -300
  924. package/plugins/cursor-pbr/skills/scan/templates/mapper-prompt.md.tmpl +0 -202
  925. package/plugins/cursor-pbr/skills/setup/SKILL.md +0 -296
  926. package/plugins/cursor-pbr/skills/shared/commit-planning-docs.md +0 -36
  927. package/plugins/cursor-pbr/skills/shared/config-loading.md +0 -103
  928. package/plugins/cursor-pbr/skills/shared/context-budget.md +0 -41
  929. package/plugins/cursor-pbr/skills/shared/context-loader-task.md +0 -87
  930. package/plugins/cursor-pbr/skills/shared/digest-select.md +0 -80
  931. package/plugins/cursor-pbr/skills/shared/domain-probes.md +0 -126
  932. package/plugins/cursor-pbr/skills/shared/error-recovery-strategies.md +0 -51
  933. package/plugins/cursor-pbr/skills/shared/error-reporting.md +0 -81
  934. package/plugins/cursor-pbr/skills/shared/gate-prompts.md +0 -389
  935. package/plugins/cursor-pbr/skills/shared/phase-argument-parsing.md +0 -46
  936. package/plugins/cursor-pbr/skills/shared/progress-display.md +0 -53
  937. package/plugins/cursor-pbr/skills/shared/revision-loop.md +0 -82
  938. package/plugins/cursor-pbr/skills/shared/state-loading.md +0 -63
  939. package/plugins/cursor-pbr/skills/shared/state-update.md +0 -162
  940. package/plugins/cursor-pbr/skills/shared/universal-anti-patterns.md +0 -38
  941. package/plugins/cursor-pbr/skills/status/SKILL.md +0 -362
  942. package/plugins/cursor-pbr/skills/statusline/SKILL.md +0 -150
  943. package/plugins/cursor-pbr/skills/todo/SKILL.md +0 -280
  944. package/plugins/cursor-pbr/templates/CONTEXT.md.tmpl +0 -53
  945. package/plugins/cursor-pbr/templates/INTEGRATION-REPORT.md.tmpl +0 -152
  946. package/plugins/cursor-pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -98
  947. package/plugins/cursor-pbr/templates/ROADMAP.md.tmpl +0 -41
  948. package/plugins/cursor-pbr/templates/SUMMARY.md.tmpl +0 -82
  949. package/plugins/cursor-pbr/templates/VERIFICATION-DETAIL.md.tmpl +0 -117
  950. package/plugins/cursor-pbr/templates/codebase/ARCHITECTURE.md.tmpl +0 -98
  951. package/plugins/cursor-pbr/templates/codebase/CONCERNS.md.tmpl +0 -93
  952. package/plugins/cursor-pbr/templates/codebase/CONVENTIONS.md.tmpl +0 -104
  953. package/plugins/cursor-pbr/templates/codebase/INTEGRATIONS.md.tmpl +0 -78
  954. package/plugins/cursor-pbr/templates/codebase/STACK.md.tmpl +0 -78
  955. package/plugins/cursor-pbr/templates/codebase/STRUCTURE.md.tmpl +0 -80
  956. package/plugins/cursor-pbr/templates/codebase/TESTING.md.tmpl +0 -107
  957. package/plugins/cursor-pbr/templates/continue-here.md.tmpl +0 -74
  958. package/plugins/cursor-pbr/templates/prompt-partials/phase-project-context.md.tmpl +0 -38
  959. package/plugins/cursor-pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
  960. package/plugins/cursor-pbr/templates/research/STACK.md.tmpl +0 -71
  961. package/plugins/cursor-pbr/templates/research/SUMMARY.md.tmpl +0 -112
  962. package/plugins/cursor-pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
  963. package/plugins/cursor-pbr/templates/research-outputs/project-research.md.tmpl +0 -99
  964. package/plugins/cursor-pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
  965. package/plugins/pbr/references/agent-interactions.md +0 -134
  966. package/plugins/pbr/references/pbr-rules.md +0 -194
  967. package/plugins/pbr/references/pbr-tools-cli.md +0 -285
  968. package/plugins/pbr/references/planning-config.md +0 -213
  969. package/plugins/pbr/references/subagent-coordination.md +0 -119
  970. package/plugins/pbr/references/ui-formatting.md +0 -444
  971. package/plugins/pbr/scripts/validate-plugin-structure.js +0 -183
  972. package/plugins/pbr/skills/milestone/templates/audit-report.md.tmpl +0 -48
  973. package/plugins/pbr/skills/shared/error-recovery-strategies.md +0 -51
  974. package/plugins/pbr/skills/shared/progress-display.md +0 -53
  975. package/plugins/pbr/skills/shared/state-loading.md +0 -62
  976. package/plugins/pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -97
  977. package/plugins/pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
  978. package/plugins/pbr/templates/research/STACK.md.tmpl +0 -71
  979. package/plugins/pbr/templates/research/SUMMARY.md.tmpl +0 -112
  980. package/plugins/pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
  981. package/plugins/pbr/templates/research-outputs/project-research.md.tmpl +0 -99
  982. package/plugins/pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
  983. /package/plugins/pbr/references/{agent-anti-patterns.md → archive/agent-anti-patterns.md} +0 -0
@@ -0,0 +1,1082 @@
1
+ /**
2
+ * lib/state.cjs — STATE.md operations for Plan-Build-Run tools.
3
+ *
4
+ * Handles loading, parsing, updating, patching, and advancing STATE.md.
5
+ * Pure-function API: all operations take planningDir as a parameter.
6
+ *
7
+ * Hybrid module merging PBR reference features with GSD-unique utilities.
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+ const {
13
+ parseYamlFrontmatter,
14
+ findFiles,
15
+ lockedFileUpdate,
16
+ calculateProgress,
17
+ determinePhaseStatus
18
+ } = require('./core');
19
+
20
+ // --- Status enum ---
21
+
22
+ const STATUS_VALUES = ['idle', 'planned', 'building', 'built', 'verifying', 'verified', 'complete'];
23
+
24
+ const STATUS_ALIASES = {
25
+ 'planning': 'planned',
26
+ 'executing': 'building',
27
+ 'done': 'complete',
28
+ 'completed': 'complete'
29
+ };
30
+
31
+ /**
32
+ * Normalize a status value to the canonical 7-value enum.
33
+ * Returns null if the value is not a valid status or alias.
34
+ *
35
+ * @param {string} value
36
+ * @returns {string|null}
37
+ */
38
+ function normalizeStatus(value) {
39
+ if (!value || typeof value !== 'string') return null;
40
+ const lower = value.toLowerCase().trim();
41
+ if (STATUS_VALUES.includes(lower)) return lower;
42
+ return STATUS_ALIASES[lower] || null;
43
+ }
44
+
45
+ /**
46
+ * Auto-regenerate STATE.md frontmatter fields from disk scan.
47
+ * Overwrites plans_total, plans_complete, progress_percent from filesystem truth.
48
+ * Normalizes status to the 7-value enum.
49
+ *
50
+ * @param {string} content - Current STATE.md content
51
+ * @param {string} planningDir - Path to .planning directory
52
+ * @returns {string} Updated content
53
+ */
54
+ function syncStateFrontmatter(content, planningDir) {
55
+ const fm = parseYamlFrontmatter(content);
56
+ if (fm.version !== 2 && fm.current_phase === undefined) return content;
57
+
58
+ const progress = stateCheckProgress(planningDir);
59
+ let updated = content;
60
+
61
+ updated = updateFrontmatterField(updated, 'plans_total', String(progress.total_plans));
62
+ updated = updateFrontmatterField(updated, 'plans_complete', String(progress.completed_plans));
63
+ updated = updateFrontmatterField(updated, 'progress_percent', String(progress.percentage));
64
+
65
+ // Normalize status if present
66
+ if (fm.status) {
67
+ const normalized = normalizeStatus(fm.status);
68
+ if (normalized && normalized !== fm.status) {
69
+ updated = updateFrontmatterField(updated, 'status', normalized);
70
+ }
71
+ }
72
+
73
+ return updated;
74
+ }
75
+
76
+ // --- Parsers ---
77
+
78
+ function parseStateMd(content) {
79
+ // Normalize CRLF to LF at parse boundary for cross-platform support
80
+ const normalized = content.replace(/\r\n/g, '\n');
81
+ const result = {
82
+ current_phase: null,
83
+ phase_name: null,
84
+ progress: null,
85
+ status: null,
86
+ line_count: normalized.split('\n').length,
87
+ format: 'frontmatter'
88
+ };
89
+
90
+ // Check for YAML frontmatter (version 2 format)
91
+ const frontmatter = parseYamlFrontmatter(normalized);
92
+ result.format = 'frontmatter';
93
+ result.current_phase = frontmatter.current_phase || null;
94
+ result.phase_name = frontmatter.phase_slug || frontmatter.phase_name || null;
95
+ result.status = frontmatter.status || null;
96
+ result.progress = frontmatter.progress_percent !== undefined ? frontmatter.progress_percent : null;
97
+ result.plans_total = frontmatter.plans_total || null;
98
+ result.plans_complete = frontmatter.plans_complete || null;
99
+ result.last_activity = frontmatter.last_activity || null;
100
+ result.last_command = frontmatter.last_command || null;
101
+ result.blockers = frontmatter.blockers || [];
102
+ result.velocity = frontmatter.velocity || null;
103
+ result.session_last = frontmatter.session_last || null;
104
+ result.session_stopped_at = frontmatter.session_stopped_at || null;
105
+ result.session_resume = frontmatter.session_resume || null;
106
+ return result;
107
+ }
108
+
109
+ // --- Mutation helpers ---
110
+
111
+
112
+ /**
113
+ * Update a field in YAML frontmatter content.
114
+ * Pure function: content in, content out.
115
+ */
116
+ function updateFrontmatterField(content, field, value) {
117
+ const match = content.match(/^(---\s*\n)([\s\S]*?)(\n---)/);
118
+ if (!match) return content;
119
+
120
+ const before = match[1];
121
+ let yaml = match[2];
122
+ const after = match[3];
123
+ const rest = content.slice(match[0].length);
124
+
125
+ // Format value: null stays bare, integers stay bare, strings get quotes
126
+ const isNull = value === null || value === 'null';
127
+ const isNum = !isNull && /^\d+$/.test(String(value));
128
+ const formatted = isNull ? 'null' : isNum ? value : `"${value}"`;
129
+
130
+ const fieldRegex = new RegExp(`^(${field})\\s*:.*$`, 'm');
131
+ if (fieldRegex.test(yaml)) {
132
+ yaml = yaml.replace(fieldRegex, () => `${field}: ${formatted}`);
133
+ } else {
134
+ yaml = yaml + `\n${field}: ${formatted}`;
135
+ }
136
+
137
+ return before + yaml + after + rest;
138
+ }
139
+
140
+ // --- Body sync ---
141
+
142
+ /**
143
+ * Build a text progress bar: [####::::::::::::::::] 20%
144
+ * @param {number} pct - Percentage 0-100
145
+ * @returns {string}
146
+ */
147
+ function buildProgressBar(pct) {
148
+ const width = 20;
149
+ const filled = Math.round((pct / 100) * width);
150
+ const empty = width - filled;
151
+ return `[${'█'.repeat(filled)}${'░'.repeat(empty)}] ${pct}%`;
152
+ }
153
+
154
+ /**
155
+ * After updating a frontmatter field, also update the corresponding body line
156
+ * so both representations stay in sync. Pure function: content in, content out.
157
+ *
158
+ * Field-to-body mapping:
159
+ * status -> "Status: {value}"
160
+ * plans_complete -> "Plan: {N} of ..." (replaces the number before "of")
161
+ * progress_percent-> "Progress: [{bar}] {N}%"
162
+ * last_activity -> "Last activity: {value}"
163
+ * current_phase -> "Phase: {N} of ..." (replaces the number before "of")
164
+ * phase_slug -> "Phase: N of M ({Name})" (replaces the parenthesized name)
165
+ *
166
+ * Fields without body equivalents (last_command, blockers) are no-ops.
167
+ *
168
+ * @param {string} content - Full STATE.md content (frontmatter already updated)
169
+ * @param {string} field - The field that was updated
170
+ * @param {string} value - The new value
171
+ * @returns {string} Content with body line also updated
172
+ */
173
+ function syncBodyLine(content, field, value) {
174
+ switch (field) {
175
+ case 'status': {
176
+ const display = String(value).replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
177
+ return content.replace(/^Status:\s*.+/m, `Status: ${display}`);
178
+ }
179
+ case 'plans_complete': {
180
+ return content.replace(/^(Plan:\s*)\d+/m, `$1${value}`);
181
+ }
182
+ case 'plans_total': {
183
+ return content.replace(/^(Plan:\s*\d+\s+of\s+)\d+/m, `$1${value}`);
184
+ }
185
+ case 'progress_percent': {
186
+ const pct = parseInt(value, 10);
187
+ if (isNaN(pct)) return content;
188
+ return content.replace(/^Progress:\s*.+/m, `Progress: ${buildProgressBar(pct)}`);
189
+ }
190
+ case 'last_activity': {
191
+ return content.replace(/^(Last activity:\s*).+/im, `$1${value}`);
192
+ }
193
+ case 'current_phase': {
194
+ return content.replace(/^(Phase:\s*)\d+/m, `$1${value}`);
195
+ }
196
+ case 'phase_slug': {
197
+ const name = String(value).replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
198
+ // Replace "(OldName)" or "-- OldName" in the Phase line
199
+ const withParens = content.replace(/^(Phase:\s*\d+\s+of\s+\d+\s*)\(.*?\)/m, `$1(${name})`);
200
+ if (withParens !== content) return withParens;
201
+ return content.replace(/^(Phase:\s*\d+\s+of\s+\d+\s*)--\s*.+/m, `$1-- ${name}`);
202
+ }
203
+ case 'session_last': {
204
+ const pattern = /^Last session:\s*.+/im;
205
+ if (pattern.test(content)) return content.replace(pattern, `Last session: ${value}`);
206
+ return content;
207
+ }
208
+ case 'session_stopped_at': {
209
+ const pattern = /^Stopped at:\s*.+/im;
210
+ if (pattern.test(content)) return content.replace(pattern, `Stopped at: ${value}`);
211
+ return content;
212
+ }
213
+ case 'session_resume': {
214
+ const pattern = /^Resume:\s*.+/im;
215
+ if (pattern.test(content)) return content.replace(pattern, `Resume: ${value}`);
216
+ return content;
217
+ }
218
+ default:
219
+ return content;
220
+ }
221
+ }
222
+
223
+ // --- Commands ---
224
+
225
+ /**
226
+ * Load full project state from .planning/ directory.
227
+ *
228
+ * @param {string} [planningDir] - Path to .planning directory
229
+ * @returns {object} Full state object
230
+ */
231
+ function stateLoad(planningDir) {
232
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
233
+ const { parseRoadmapMd } = require('./roadmap');
234
+
235
+ const result = {
236
+ exists: false,
237
+ config: null,
238
+ state: null,
239
+ roadmap: null,
240
+ phase_count: 0,
241
+ current_phase: null,
242
+ progress: null
243
+ };
244
+
245
+ if (!fs.existsSync(dir)) {
246
+ return result;
247
+ }
248
+ result.exists = true;
249
+
250
+ // Load config.json
251
+ const configPath = path.join(dir, 'config.json');
252
+ if (fs.existsSync(configPath)) {
253
+ try {
254
+ result.config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
255
+ } catch (_) {
256
+ result.config = { _error: 'Failed to parse config.json' };
257
+ }
258
+ }
259
+
260
+ // Load STATE.md
261
+ const statePath = path.join(dir, 'STATE.md');
262
+ if (fs.existsSync(statePath)) {
263
+ const content = fs.readFileSync(statePath, 'utf8');
264
+ result.state = parseStateMd(content);
265
+ }
266
+
267
+ // Load ROADMAP.md
268
+ const roadmapPath = path.join(dir, 'ROADMAP.md');
269
+ if (fs.existsSync(roadmapPath)) {
270
+ const content = fs.readFileSync(roadmapPath, 'utf8');
271
+ result.roadmap = parseRoadmapMd(content);
272
+ result.phase_count = result.roadmap.phases.length;
273
+ }
274
+
275
+ // Extract current phase
276
+ if (result.state && result.state.current_phase) {
277
+ result.current_phase = result.state.current_phase;
278
+ }
279
+
280
+ // Calculate progress
281
+ result.progress = calculateProgress(dir);
282
+
283
+ return result;
284
+ }
285
+
286
+ /**
287
+ * Recalculate progress from filesystem.
288
+ *
289
+ * @param {string} [planningDir] - Path to .planning directory
290
+ * @returns {object} Progress object
291
+ */
292
+ function stateCheckProgress(planningDir) {
293
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
294
+ const phasesDir = path.join(dir, 'phases');
295
+ if (!fs.existsSync(phasesDir)) {
296
+ return { phases: [], total_plans: 0, completed_plans: 0, percentage: 0 };
297
+ }
298
+
299
+ const phases = [];
300
+ let totalPlans = 0;
301
+ let completedPlans = 0;
302
+
303
+ const entries = fs.readdirSync(phasesDir, { withFileTypes: true })
304
+ .filter(e => e.isDirectory())
305
+ .sort((a, b) => a.name.localeCompare(b.name));
306
+
307
+ for (const entry of entries) {
308
+ const phaseDir = path.join(phasesDir, entry.name);
309
+ const plans = findFiles(phaseDir, /PLAN.*\.md$/i);
310
+ const summaries = findFiles(phaseDir, /^SUMMARY-.*\.md$/);
311
+ const verification = fs.existsSync(path.join(phaseDir, 'VERIFICATION.md'));
312
+
313
+ const completedSummaries = summaries.filter(s => {
314
+ const content = fs.readFileSync(path.join(phaseDir, s), 'utf8');
315
+ return /status:\s*["']?complete/i.test(content);
316
+ });
317
+
318
+ const phaseInfoObj = {
319
+ directory: entry.name,
320
+ plans: plans.length,
321
+ summaries: summaries.length,
322
+ completed: completedSummaries.length,
323
+ has_verification: verification,
324
+ status: determinePhaseStatus(plans.length, completedSummaries.length, summaries.length, verification, phaseDir)
325
+ };
326
+
327
+ phases.push(phaseInfoObj);
328
+ totalPlans += plans.length;
329
+ completedPlans += completedSummaries.length;
330
+ }
331
+
332
+ return {
333
+ phases,
334
+ total_plans: totalPlans,
335
+ completed_plans: completedPlans,
336
+ percentage: totalPlans > 0 ? Math.round((completedPlans / totalPlans) * 100) : 0
337
+ };
338
+ }
339
+
340
+ /**
341
+ * Atomically update a field in STATE.md using lockedFileUpdate.
342
+ * Updates frontmatter (v2) format STATE.md.
343
+ *
344
+ * @param {string} field - One of: current_phase, status, plans_complete, last_activity,
345
+ * progress_percent, phase_slug, total_phases, last_command, blockers
346
+ * @param {string} value - New value (use 'now' for last_activity to auto-timestamp)
347
+ * @param {string} [planningDir] - Path to .planning directory
348
+ */
349
+ async function stateUpdate(field, value, planningDir) {
350
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
351
+ const statePath = path.join(dir, 'STATE.md');
352
+ if (!fs.existsSync(statePath)) {
353
+ return { success: false, error: 'STATE.md not found' };
354
+ }
355
+
356
+ // All 13 STATE.md frontmatter fields supported by stateUpdate
357
+ const validFields = [
358
+ 'current_phase',
359
+ 'status',
360
+ 'plans_complete',
361
+ 'plans_total',
362
+ 'last_activity',
363
+ 'progress_percent',
364
+ 'phase_slug',
365
+ 'last_command',
366
+ 'blockers',
367
+ 'velocity',
368
+ 'session_last',
369
+ 'session_stopped_at',
370
+ 'session_resume'
371
+ ];
372
+ if (!validFields.includes(field)) {
373
+ return { success: false, error: `Invalid field: ${field}. Valid fields: ${validFields.join(', ')}` };
374
+ }
375
+
376
+ // Auto-timestamp
377
+ if (field === 'last_activity' && value === 'now') {
378
+ value = new Date().toISOString().slice(0, 19).replace('T', ' ');
379
+ }
380
+
381
+ const result = await lockedFileUpdate(statePath, (content) => {
382
+ let updated = updateFrontmatterField(content, field, value);
383
+ updated = syncBodyLine(updated, field, value);
384
+ return updated;
385
+ });
386
+
387
+ if (result.success) {
388
+ return { success: true, field, value };
389
+ }
390
+ return { success: false, error: result.error };
391
+ }
392
+
393
+ /**
394
+ * Batch-update multiple STATE.md fields at once.
395
+ *
396
+ * @param {string} jsonStr - JSON string of field:value pairs
397
+ * @param {string} [planningDir] - Path to .planning directory
398
+ */
399
+ async function statePatch(jsonStr, planningDir) {
400
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
401
+ const statePath = path.join(dir, 'STATE.md');
402
+ if (!fs.existsSync(statePath)) return { success: false, error: "STATE.md not found" };
403
+ let fields;
404
+ try { fields = JSON.parse(jsonStr); } catch (_e) { return { success: false, error: "Invalid JSON" }; }
405
+ const validFields = ["current_phase", "status", "plans_complete", "plans_total", "last_activity", "progress_percent", "phase_slug", "last_command", "blockers", "velocity", "session_last", "session_stopped_at", "session_resume"];
406
+ const invalidFields = Object.keys(fields).filter(f => !validFields.includes(f));
407
+ if (invalidFields.length > 0) return { success: false, error: "Unknown fields: " + invalidFields.join(", ") };
408
+
409
+ const result = await lockedFileUpdate(statePath, (content) => {
410
+ let updated = content;
411
+ for (const [field, value] of Object.entries(fields)) {
412
+ let val = String(value);
413
+ if (field === 'last_activity' && val === 'now') {
414
+ val = new Date().toISOString().slice(0, 19).replace('T', ' ');
415
+ }
416
+ updated = updateFrontmatterField(updated, field, val);
417
+ updated = syncBodyLine(updated, field, val);
418
+ }
419
+ return updated;
420
+ });
421
+
422
+ if (!result.success) return { success: false, error: result.error };
423
+ return { success: true, updated: Object.keys(fields) };
424
+ }
425
+
426
+ /**
427
+ * Advance the plan counter in STATE.md by 1.
428
+ *
429
+ * @param {string} [planningDir] - Path to .planning directory
430
+ */
431
+ async function stateAdvancePlan(planningDir) {
432
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
433
+ const statePath = path.join(dir, 'STATE.md');
434
+ if (!fs.existsSync(statePath)) return { success: false, error: "STATE.md not found" };
435
+
436
+ let resultData = {};
437
+ const result = await lockedFileUpdate(statePath, (content) => {
438
+ const planMatch = content.match(/Plan:\s*(\d+)\s+of\s+(\d+)/);
439
+ if (!planMatch) {
440
+ resultData = { error: "Could not find Plan: N of M in STATE.md" };
441
+ return content;
442
+ }
443
+ const current = parseInt(planMatch[1], 10);
444
+ const total = parseInt(planMatch[2], 10);
445
+ const next = Math.min(current + 1, total);
446
+ const progressPct = total > 0 ? Math.round((next / total) * 100) : 0;
447
+ resultData = { previous_plan: current, current_plan: next, total_plans: total, progress_percent: progressPct };
448
+
449
+ let updated = content;
450
+ updated = updateFrontmatterField(updated, 'plans_complete', String(next));
451
+ updated = syncBodyLine(updated, 'plans_complete', String(next));
452
+ updated = updateFrontmatterField(updated, 'progress_percent', String(progressPct));
453
+ updated = syncBodyLine(updated, 'progress_percent', String(progressPct));
454
+ return updated;
455
+ });
456
+
457
+ if (resultData.error) return { success: false, error: resultData.error };
458
+ if (!result.success) return { success: false, error: result.error };
459
+ return { success: true, ...resultData };
460
+ }
461
+
462
+ /**
463
+ * Record a session metric in STATE.md (history section).
464
+ *
465
+ * @param {string[]} metricArgs - CLI args like ['--duration', '30m', '--plans-completed', '3']
466
+ * @param {string} [planningDir] - Path to .planning directory
467
+ */
468
+ async function stateRecordMetric(metricArgs, planningDir) {
469
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
470
+ let duration = null, plansCompleted = null;
471
+ for (let i = 0; i < metricArgs.length; i++) {
472
+ if (metricArgs[i] === "--duration" && metricArgs[i + 1]) {
473
+ const match = metricArgs[i + 1].match(/(\d+)(m|s|h)/);
474
+ if (match) { const val = parseInt(match[1], 10); const unit = match[2]; duration = unit === "h" ? val * 60 : unit === "s" ? Math.round(val / 60) : val; }
475
+ i++;
476
+ } else if (metricArgs[i] === "--plans-completed" && metricArgs[i + 1]) {
477
+ plansCompleted = parseInt(metricArgs[i + 1], 10); i++;
478
+ }
479
+ }
480
+ const parts = [];
481
+ if (duration !== null) parts.push("duration: " + duration + "m");
482
+ if (plansCompleted !== null) parts.push("plans_completed: " + plansCompleted);
483
+
484
+ // Append metric to STATE.md metrics table if present
485
+ if (parts.length > 0) {
486
+ const statePath = path.join(dir, 'STATE.md');
487
+ if (fs.existsSync(statePath)) {
488
+ await lockedFileUpdate(statePath, (content) => {
489
+ const metricsPattern = /(##\s*Performance Metrics[\s\S]*?\n\|[^\n]+\n\|[-|\s]+\n)([\s\S]*?)(?=\n##|\n$|$)/i;
490
+ const metricsMatch = content.match(metricsPattern);
491
+ if (metricsMatch) {
492
+ let tableBody = metricsMatch[2].trimEnd();
493
+ const newRow = `| Metric | ${parts.join(', ')} |`;
494
+ if (tableBody.trim() === '' || tableBody.includes('None yet')) {
495
+ tableBody = newRow;
496
+ } else {
497
+ tableBody = tableBody + '\n' + newRow;
498
+ }
499
+ return content.replace(metricsPattern, (_match, header) => `${header}${tableBody}\n`);
500
+ }
501
+ return content;
502
+ });
503
+ }
504
+ }
505
+
506
+ await stateUpdate("last_activity", "now", dir);
507
+ return { success: true, duration_minutes: duration, plans_completed: plansCompleted };
508
+ }
509
+
510
+ /**
511
+ * Record a velocity metric in STATE.md frontmatter.
512
+ * Stores metrics as a JSON string in the `velocity` field.
513
+ * Tracks last 5 entries per metric type and calculates trend.
514
+ *
515
+ * @param {string} metricType - Metric type (e.g., 'plan_duration', 'phase_duration')
516
+ * @param {number|string} value - Metric value
517
+ * @param {string} [planningDir] - Path to .planning directory
518
+ * @returns {object} { success, metricType, value, trend }
519
+ */
520
+ async function stateRecordVelocity(metricType, value, planningDir) {
521
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
522
+ const statePath = path.join(dir, 'STATE.md');
523
+ if (!fs.existsSync(statePath)) {
524
+ return { success: false, error: 'STATE.md not found' };
525
+ }
526
+
527
+ // Read current velocity from frontmatter
528
+ const content = fs.readFileSync(statePath, 'utf8');
529
+ const parsed = parseStateMd(content);
530
+ let velocity = {};
531
+ if (parsed.velocity) {
532
+ try {
533
+ velocity = typeof parsed.velocity === 'string' ? JSON.parse(parsed.velocity) : parsed.velocity;
534
+ } catch (_) {
535
+ velocity = {};
536
+ }
537
+ }
538
+
539
+ // Initialize metric history if needed
540
+ if (!velocity[metricType]) {
541
+ velocity[metricType] = { history: [], trend: 'stable' };
542
+ }
543
+
544
+ const numValue = Number(value);
545
+ const entry = { value: numValue, timestamp: new Date().toISOString() };
546
+ velocity[metricType].history.push(entry);
547
+
548
+ // Keep last 5 entries
549
+ if (velocity[metricType].history.length > 5) {
550
+ velocity[metricType].history = velocity[metricType].history.slice(-5);
551
+ }
552
+
553
+ // Calculate trend from history
554
+ const hist = velocity[metricType].history;
555
+ if (hist.length >= 2) {
556
+ const recent = hist.slice(-3).map(h => h.value);
557
+ const avg = recent.reduce((a, b) => a + b, 0) / recent.length;
558
+ const first = hist[0].value;
559
+ if (avg < first * 0.85) {
560
+ velocity[metricType].trend = 'improving';
561
+ } else if (avg > first * 1.15) {
562
+ velocity[metricType].trend = 'degrading';
563
+ } else {
564
+ velocity[metricType].trend = 'stable';
565
+ }
566
+ }
567
+
568
+ // Write back via stateUpdate
569
+ const result = await stateUpdate('velocity', JSON.stringify(velocity), dir);
570
+ if (!result.success) return result;
571
+ return { success: true, metricType, value: numValue, trend: velocity[metricType].trend };
572
+ }
573
+
574
+ /**
575
+ * Record session continuity info in STATE.md.
576
+ * Updates session_last, session_stopped_at, and session_resume fields.
577
+ *
578
+ * @param {string} stoppedAt - Description of where the session stopped
579
+ * @param {string} resumeFile - Path to resume file (e.g., .PROGRESS-02-01)
580
+ * @param {string} [planningDir] - Path to .planning directory
581
+ * @returns {object} { success, session_last, session_stopped_at, session_resume }
582
+ */
583
+ async function stateRecordSession(stoppedAt, resumeFile, planningDir) {
584
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
585
+ const now = new Date().toISOString().slice(0, 19).replace('T', ' ');
586
+
587
+ const r1 = await stateUpdate('session_last', now, dir);
588
+ if (!r1.success) return r1;
589
+
590
+ const r2 = await stateUpdate('session_stopped_at', stoppedAt, dir);
591
+ if (!r2.success) return r2;
592
+
593
+ const r3 = await stateUpdate('session_resume', resumeFile, dir);
594
+ if (!r3.success) return r3;
595
+
596
+ return { success: true, session_last: now, session_stopped_at: stoppedAt, session_resume: resumeFile };
597
+ }
598
+
599
+ /**
600
+ * Record an activity description with today's date in STATE.md last_activity.
601
+ *
602
+ * @param {string} description - Activity description (e.g., "Built phase 3")
603
+ * @param {string} [planningDir] - Path to .planning directory
604
+ * @returns {object} { success: true, last_activity: "YYYY-MM-DD description" }
605
+ */
606
+ async function stateRecordActivity(description, planningDir) {
607
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
608
+ const today = new Date().toISOString().slice(0, 10);
609
+ const value = `${today} ${description}`;
610
+ const result = await stateUpdate('last_activity', value, dir);
611
+ if (!result.success) return result;
612
+ return { success: true, last_activity: value };
613
+ }
614
+
615
+ /**
616
+ * Recalculate progress from filesystem and atomically update STATE.md
617
+ * with progress_percent, plans_complete, and plans_total.
618
+ *
619
+ * @param {string} [planningDir] - Path to .planning directory
620
+ * @returns {object} { success, percent, completed_plans, total_plans }
621
+ */
622
+ async function stateUpdateProgress(planningDir) {
623
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
624
+ const statePath = path.join(dir, 'STATE.md');
625
+ if (!fs.existsSync(statePath)) {
626
+ return { success: false, error: 'STATE.md not found' };
627
+ }
628
+
629
+ const progress = stateCheckProgress(dir);
630
+ const { percentage, completed_plans, total_plans } = progress;
631
+
632
+ const result = await lockedFileUpdate(statePath, (content) => {
633
+ let updated = content;
634
+ // Update frontmatter fields
635
+ updated = updateFrontmatterField(updated, 'progress_percent', percentage);
636
+ updated = updateFrontmatterField(updated, 'plans_complete', completed_plans);
637
+ updated = updateFrontmatterField(updated, 'plans_total', total_plans);
638
+ // Update body lines
639
+ updated = syncBodyLine(updated, 'progress_percent', percentage);
640
+ updated = syncBodyLine(updated, 'plans_complete', completed_plans);
641
+ updated = syncBodyLine(updated, 'plans_total', total_plans);
642
+ return updated;
643
+ });
644
+
645
+ if (!result.success) return { success: false, error: result.error };
646
+ return { success: true, percent: percentage, completed_plans, total_plans };
647
+ }
648
+
649
+ /**
650
+ * Get current state status summary (minimal, for quick checks).
651
+ *
652
+ * @param {string} [planningDir] - Path to .planning directory
653
+ * @returns {object} { status, current_phase, phase_name }
654
+ */
655
+ function stateGetStatus(planningDir) {
656
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
657
+ const statePath = path.join(dir, 'STATE.md');
658
+ if (!fs.existsSync(statePath)) {
659
+ return { error: 'STATE.md not found' };
660
+ }
661
+ const content = fs.readFileSync(statePath, 'utf8');
662
+ const parsed = parseStateMd(content);
663
+ return {
664
+ status: parsed.status,
665
+ current_phase: parsed.current_phase,
666
+ phase_name: parsed.phase_name,
667
+ progress: parsed.progress,
668
+ format: parsed.format
669
+ };
670
+ }
671
+
672
+ /**
673
+ * Take a comprehensive snapshot of project state for display/reporting.
674
+ * Extracts all fields, decisions, blockers, and session info from STATE.md.
675
+ *
676
+ * @param {string} [planningDir] - Path to .planning directory
677
+ * @returns {object} Full state snapshot
678
+ */
679
+ function stateSnapshot(planningDir) {
680
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
681
+ const statePath = path.join(dir, 'STATE.md');
682
+ if (!fs.existsSync(statePath)) {
683
+ return { error: 'STATE.md not found' };
684
+ }
685
+
686
+ const content = fs.readFileSync(statePath, 'utf8');
687
+ const parsed = parseStateMd(content);
688
+
689
+ // Extract decisions
690
+ const decisions = [];
691
+ const decisionsMatch = content.match(/###?\s*(?:Decisions|Decisions Made)[\s\S]*?\n([\s\S]*?)(?=\n###?|\n##[^#]|$)/i);
692
+ if (decisionsMatch) {
693
+ const items = decisionsMatch[1].match(/^-\s+(.+)$/gm) || [];
694
+ for (const item of items) {
695
+ decisions.push(item.replace(/^-\s+/, '').trim());
696
+ }
697
+ }
698
+
699
+ // Extract blockers
700
+ const blockers = [];
701
+ const blockersMatch = content.match(/###?\s*(?:Blockers|Blockers\/Concerns|Concerns)[\s\S]*?\n([\s\S]*?)(?=\n###?|\n##[^#]|$)/i);
702
+ if (blockersMatch) {
703
+ const items = blockersMatch[1].match(/^-\s+(.+)$/gm) || [];
704
+ for (const item of items) {
705
+ const text = item.replace(/^-\s+/, '').trim();
706
+ if (text && !text.match(/^None\.?$/i)) {
707
+ blockers.push(text);
708
+ }
709
+ }
710
+ }
711
+
712
+ // Extract session info
713
+ const session = { last_date: null, stopped_at: null, resume_file: null };
714
+ const lastSessionMatch = content.match(/Last session:\s*(.+)/i);
715
+ if (lastSessionMatch) session.last_date = lastSessionMatch[1].trim();
716
+ const stoppedMatch = content.match(/Stopped at:\s*(.+)/i);
717
+ if (stoppedMatch) session.stopped_at = stoppedMatch[1].trim();
718
+ const resumeMatch = content.match(/Resume file:\s*(.+)/i);
719
+ if (resumeMatch) session.resume_file = resumeMatch[1].trim();
720
+
721
+ return {
722
+ ...parsed,
723
+ decisions,
724
+ blockers: blockers.length > 0 ? blockers : (parsed.blockers || []),
725
+ session
726
+ };
727
+ }
728
+
729
+ /**
730
+ * Atomically mark a phase as complete in STATE.md.
731
+ * Updates status to "complete" and records phase completion in last_activity,
732
+ * all within a single lockedFileUpdate call for atomicity.
733
+ *
734
+ * @param {number|string} phaseNum - Phase number to mark complete
735
+ * @param {string} [planningDir] - Path to .planning directory
736
+ * @returns {object} { success: true, phase, status } or { success: false, error }
737
+ */
738
+ async function statePhaseComplete(phaseNum, planningDir) {
739
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
740
+ const statePath = path.join(dir, 'STATE.md');
741
+ if (!fs.existsSync(statePath)) {
742
+ return { success: false, error: 'STATE.md not found' };
743
+ }
744
+
745
+ const today = new Date().toISOString().slice(0, 10);
746
+ const activityValue = `${today} Phase ${phaseNum} complete`;
747
+
748
+ const result = await lockedFileUpdate(statePath, (content) => {
749
+ let updated = content;
750
+ // Update frontmatter fields
751
+ updated = updateFrontmatterField(updated, 'status', 'complete');
752
+ updated = updateFrontmatterField(updated, 'last_activity', activityValue);
753
+ // Sync body lines
754
+ updated = syncBodyLine(updated, 'status', 'complete');
755
+ updated = syncBodyLine(updated, 'last_activity', activityValue);
756
+ updated = syncStateFrontmatter(updated, dir);
757
+ return updated;
758
+ });
759
+
760
+ if (!result.success) {
761
+ return { success: false, error: result.error };
762
+ }
763
+ return { success: true, phase: Number(phaseNum), status: 'complete' };
764
+ }
765
+
766
+ /**
767
+ * Re-derive state from filesystem and correct any drift in STATE.md.
768
+ * Compares plans_complete, plans_total, and progress_percent between
769
+ * the current STATE.md and the filesystem-derived values from stateCheckProgress.
770
+ * Corrects any differences atomically via lockedFileUpdate.
771
+ *
772
+ * @param {string} [planningDir] - Path to .planning directory
773
+ * @returns {object} { success, corrected: [...fieldNames], derived: { plans_complete, plans_total, progress_percent } }
774
+ */
775
+ async function stateRederive(planningDir) {
776
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
777
+ const statePath = path.join(dir, 'STATE.md');
778
+ if (!fs.existsSync(statePath)) {
779
+ return { success: false, error: 'STATE.md not found' };
780
+ }
781
+
782
+ // Derive current state from filesystem
783
+ const progress = stateCheckProgress(dir);
784
+ const derived = {
785
+ plans_complete: progress.completed_plans,
786
+ plans_total: progress.total_plans,
787
+ progress_percent: progress.percentage
788
+ };
789
+
790
+ // Read current STATE.md values
791
+ const content = fs.readFileSync(statePath, 'utf8');
792
+ const current = parseStateMd(content);
793
+
794
+ // Compare and find drifted fields
795
+ const corrected = [];
796
+ if (Number(current.plans_complete || 0) !== derived.plans_complete) {
797
+ corrected.push('plans_complete');
798
+ }
799
+ if (Number(current.plans_total || 0) !== derived.plans_total) {
800
+ corrected.push('plans_total');
801
+ }
802
+ if (Number(current.progress || 0) !== derived.progress_percent) {
803
+ corrected.push('progress_percent');
804
+ }
805
+
806
+ // If drift detected, correct atomically
807
+ if (corrected.length > 0) {
808
+ const result = await lockedFileUpdate(statePath, (fileContent) => {
809
+ let updated = fileContent;
810
+ for (const field of corrected) {
811
+ const value = derived[field];
812
+ updated = updateFrontmatterField(updated, field, value);
813
+ updated = syncBodyLine(updated, field, value);
814
+ }
815
+ return updated;
816
+ });
817
+
818
+ if (!result.success) {
819
+ return { success: false, error: result.error };
820
+ }
821
+ }
822
+
823
+ return { success: true, corrected, derived };
824
+ }
825
+
826
+ /**
827
+ * Signal that the project is waiting on an external action.
828
+ * Creates a WAITING.json file in the .planning directory.
829
+ *
830
+ * @param {string} reason - Why the project is waiting
831
+ * @param {string} [expectedDuration] - Expected wait duration (e.g., 'minutes', 'hours', 'unknown')
832
+ * @param {string} [planningDir] - Path to .planning directory
833
+ * @returns {object} { success, path }
834
+ */
835
+ function stateSignalWaiting(reason, expectedDuration, planningDir) {
836
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
837
+ const waitingPath = path.join(dir, 'WAITING.json');
838
+ const data = {
839
+ status: 'waiting',
840
+ reason,
841
+ expected_duration: expectedDuration || 'unknown',
842
+ created_at: new Date().toISOString(),
843
+ signal: 'waiting'
844
+ };
845
+ fs.writeFileSync(waitingPath, JSON.stringify(data, null, 2), 'utf-8');
846
+ return { success: true, path: waitingPath };
847
+ }
848
+
849
+ /**
850
+ * Clear the waiting signal by removing WAITING.json.
851
+ *
852
+ * @param {string} [planningDir] - Path to .planning directory
853
+ * @returns {object} { success, was_waiting }
854
+ */
855
+ function stateSignalResume(planningDir) {
856
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
857
+ const waitingPath = path.join(dir, 'WAITING.json');
858
+ if (fs.existsSync(waitingPath)) {
859
+ fs.unlinkSync(waitingPath);
860
+ return { success: true, was_waiting: true };
861
+ }
862
+ return { success: true, was_waiting: false };
863
+ }
864
+
865
+ /**
866
+ * Check if the project is currently in a waiting state.
867
+ *
868
+ * @param {string} [planningDir] - Path to .planning directory
869
+ * @returns {object|null} Parsed WAITING.json contents, or null if not waiting
870
+ */
871
+ function stateCheckWaiting(planningDir) {
872
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
873
+ const waitingPath = path.join(dir, 'WAITING.json');
874
+ if (!fs.existsSync(waitingPath)) return null;
875
+ try {
876
+ return JSON.parse(fs.readFileSync(waitingPath, 'utf-8'));
877
+ } catch (_) { return null; }
878
+ }
879
+
880
+ /**
881
+ * Reconcile STATE.md with ROADMAP.md by re-deriving phases_total and
882
+ * current_phase from the active milestone, and detecting phantom phase
883
+ * rows (ROADMAP.md progress rows with no directory on disk).
884
+ *
885
+ * @param {string} [planningDir] - Path to .planning directory
886
+ * @returns {object} { corrected: boolean, changes: string[], phantoms: string[] }
887
+ */
888
+ async function stateReconcile(planningDir) {
889
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
890
+ const statePath = path.join(dir, 'STATE.md');
891
+ const roadmapPath = path.join(dir, 'ROADMAP.md');
892
+ const phasesDir = path.join(dir, 'phases');
893
+
894
+ const changes = [];
895
+ const phantoms = [];
896
+
897
+ if (!fs.existsSync(statePath)) {
898
+ return { corrected: false, changes: [], phantoms: [], error: 'STATE.md not found' };
899
+ }
900
+ if (!fs.existsSync(roadmapPath)) {
901
+ return { corrected: false, changes: [], phantoms: [], error: 'ROADMAP.md not found' };
902
+ }
903
+
904
+ // Parse ROADMAP.md to get phase list
905
+ const { parseRoadmapMd } = require('./roadmap');
906
+ const roadmapContent = fs.readFileSync(roadmapPath, 'utf8');
907
+ const roadmap = parseRoadmapMd(roadmapContent);
908
+
909
+ // Get actual phase directories on disk
910
+ const dirsOnDisk = new Set();
911
+ if (fs.existsSync(phasesDir)) {
912
+ for (const entry of fs.readdirSync(phasesDir, { withFileTypes: true })) {
913
+ if (entry.isDirectory() && /^\d{2}-/.test(entry.name)) {
914
+ const numMatch = entry.name.match(/^(\d+)/);
915
+ if (numMatch) dirsOnDisk.add(parseInt(numMatch[1], 10));
916
+ }
917
+ }
918
+ }
919
+
920
+ // Filter roadmap phases to active milestone (non-complete/shipped phases,
921
+ // or all phases if no milestone distinction is available)
922
+ const completeStatuses = new Set(['complete', 'completed', 'verified', 'shipped']);
923
+ const activePhases = [];
924
+
925
+ for (const phase of roadmap.phases) {
926
+ const numMatch = String(phase.number).match(/^(\d+)/);
927
+ if (!numMatch) continue;
928
+ const phaseNum = parseInt(numMatch[1], 10);
929
+ const status = (phase.status || '').toLowerCase().trim();
930
+
931
+ activePhases.push({ num: phaseNum, status });
932
+ }
933
+
934
+ // Derive correct phases_total: count of phases with directories on disk
935
+ // (active milestone phases that actually exist)
936
+ // Fallback: if roadmap parser found no phases (e.g., heading-only format
937
+ // not yet in table), use raw disk directory count to avoid writing 0
938
+ let phasesTotal = activePhases.filter(p => dirsOnDisk.has(p.num)).length;
939
+ if (phasesTotal === 0 && dirsOnDisk.size > 0) {
940
+ phasesTotal = dirsOnDisk.size;
941
+ }
942
+
943
+ // Derive correct current_phase: lowest phase that is NOT complete/verified/shipped
944
+ const nonCompletePhasesOnDisk = activePhases
945
+ .filter(p => dirsOnDisk.has(p.num) && !completeStatuses.has(p.status))
946
+ .sort((a, b) => a.num - b.num);
947
+ const currentPhase = nonCompletePhasesOnDisk.length > 0 ? nonCompletePhasesOnDisk[0].num : null;
948
+
949
+ // Detect phantom phases: roadmap rows with no corresponding directory
950
+ for (const phase of activePhases) {
951
+ if (!dirsOnDisk.has(phase.num)) {
952
+ const label = `Phase ${String(phase.num).padStart(2, '0')} (status: ${phase.status || 'unknown'})`;
953
+ phantoms.push(label);
954
+ }
955
+ }
956
+
957
+ // Read current STATE.md and compute corrections
958
+ const stateContent = fs.readFileSync(statePath, 'utf8');
959
+ const parsed = parseStateMd(stateContent);
960
+
961
+ const fieldsToUpdate = {};
962
+ if (phasesTotal !== Number(parsed.plans_total || 0)) {
963
+ fieldsToUpdate.plans_total = phasesTotal;
964
+ changes.push(`plans_total: ${parsed.plans_total || 0} -> ${phasesTotal}`);
965
+ }
966
+
967
+ // When no active phases remain (e.g., after milestone complete archives all phases),
968
+ // reset STATE.md to idle state so downstream consumers don't read stale data.
969
+ // Read raw frontmatter for accurate field checks since parseStateMd remaps some fields.
970
+ const rawFm = parseYamlFrontmatter(stateContent);
971
+
972
+ if (currentPhase === null && phasesTotal === 0) {
973
+ const currentPhaseVal = parsed.current_phase;
974
+ if (currentPhaseVal !== null && currentPhaseVal !== undefined && String(currentPhaseVal) !== 'null') {
975
+ fieldsToUpdate.current_phase = 'null';
976
+ changes.push(`current_phase: ${currentPhaseVal} -> null`);
977
+ }
978
+ if (rawFm.phase_slug && String(rawFm.phase_slug) !== 'null') {
979
+ fieldsToUpdate.phase_slug = 'null';
980
+ changes.push(`phase_slug: ${rawFm.phase_slug} -> null`);
981
+ }
982
+ if (rawFm.phase_name && String(rawFm.phase_name) !== 'null') {
983
+ fieldsToUpdate.phase_name = 'null';
984
+ changes.push(`phase_name: ${rawFm.phase_name} -> null`);
985
+ }
986
+ const currentStatus = (parsed.status || '').toLowerCase();
987
+ if (currentStatus && currentStatus !== 'idle') {
988
+ fieldsToUpdate.status = 'idle';
989
+ changes.push(`status: ${parsed.status} -> idle`);
990
+ }
991
+ if (Number(rawFm.progress_percent || 0) !== 0) {
992
+ fieldsToUpdate.progress_percent = 0;
993
+ changes.push(`progress_percent: ${rawFm.progress_percent || 0} -> 0`);
994
+ }
995
+ if (Number(parsed.plans_complete || 0) !== 0) {
996
+ fieldsToUpdate.plans_complete = 0;
997
+ changes.push(`plans_complete: ${parsed.plans_complete || 0} -> 0`);
998
+ }
999
+ if (Number(rawFm.phases_total || 0) !== 0) {
1000
+ fieldsToUpdate.phases_total = 0;
1001
+ changes.push(`phases_total: ${rawFm.phases_total || 0} -> 0`);
1002
+ }
1003
+ } else if (currentPhase !== null && currentPhase !== Number(parsed.current_phase || 0)) {
1004
+ fieldsToUpdate.current_phase = currentPhase;
1005
+ changes.push(`current_phase: ${parsed.current_phase || 0} -> ${currentPhase}`);
1006
+ }
1007
+
1008
+ // Apply corrections atomically
1009
+ if (Object.keys(fieldsToUpdate).length > 0) {
1010
+ await lockedFileUpdate(statePath, (content) => {
1011
+ let updated = content;
1012
+ for (const [field, value] of Object.entries(fieldsToUpdate)) {
1013
+ updated = updateFrontmatterField(updated, field, value);
1014
+ updated = syncBodyLine(updated, field, value);
1015
+ }
1016
+ return updated;
1017
+ });
1018
+ }
1019
+
1020
+ return { corrected: changes.length > 0, changes, phantoms };
1021
+ }
1022
+
1023
+ /**
1024
+ * Create a timestamped backup of STATE.md and ROADMAP.md.
1025
+ * Writes a JSON file to .planning/.state-backup-{timestamp}.json
1026
+ * containing the raw content of both files plus metadata.
1027
+ * @param {string} [planningDir] - Path to .planning directory
1028
+ * @returns {{ backed_up: boolean, path: string|null, files: string[] }}
1029
+ */
1030
+ function stateBackup(planningDir) {
1031
+ const dir = planningDir || path.join(process.env.PBR_PROJECT_ROOT || process.cwd(), '.planning');
1032
+ const statePath = path.join(dir, 'STATE.md');
1033
+ const roadmapPath = path.join(dir, 'ROADMAP.md');
1034
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
1035
+ const backupPath = path.join(dir, `.state-backup-${timestamp}.json`);
1036
+
1037
+ const backup = { timestamp: new Date().toISOString(), files: {} };
1038
+ let fileCount = 0;
1039
+
1040
+ for (const [name, filePath] of [['STATE.md', statePath], ['ROADMAP.md', roadmapPath]]) {
1041
+ if (fs.existsSync(filePath)) {
1042
+ backup.files[name] = fs.readFileSync(filePath, 'utf8');
1043
+ fileCount++;
1044
+ }
1045
+ }
1046
+
1047
+ if (fileCount === 0) {
1048
+ return { backed_up: false, path: null, files: [] };
1049
+ }
1050
+
1051
+ fs.writeFileSync(backupPath, JSON.stringify(backup, null, 2));
1052
+ return { backed_up: true, path: backupPath, files: Object.keys(backup.files) };
1053
+ }
1054
+
1055
+ module.exports = {
1056
+ parseStateMd,
1057
+ updateFrontmatterField,
1058
+ syncBodyLine,
1059
+ buildProgressBar,
1060
+ stateLoad,
1061
+ stateCheckProgress,
1062
+ stateUpdate,
1063
+ statePatch,
1064
+ stateAdvancePlan,
1065
+ stateRecordMetric,
1066
+ stateRecordActivity,
1067
+ stateUpdateProgress,
1068
+ stateGetStatus,
1069
+ stateSnapshot,
1070
+ statePhaseComplete,
1071
+ stateRederive,
1072
+ stateRecordVelocity,
1073
+ stateRecordSession,
1074
+ stateSignalWaiting,
1075
+ stateSignalResume,
1076
+ stateCheckWaiting,
1077
+ stateReconcile,
1078
+ stateBackup,
1079
+ syncStateFrontmatter,
1080
+ normalizeStatus,
1081
+ STATUS_VALUES
1082
+ };