@sienklogic/plan-build-run 2.21.1 → 2.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (982) hide show
  1. package/CHANGELOG.md +1331 -323
  2. package/CLAUDE.md +75 -40
  3. package/LICENSE +2 -1
  4. package/README.md +412 -177
  5. package/bin/install.js +2752 -0
  6. package/dashboard/bin/cli.cjs +96 -0
  7. package/dashboard/bin/stop.cjs +129 -0
  8. package/dashboard/eslint.config.js +37 -0
  9. package/dashboard/index.html +20 -0
  10. package/dashboard/package.json +27 -25
  11. package/dashboard/server/index.js +151 -0
  12. package/dashboard/server/lib/frontmatter.js +92 -0
  13. package/dashboard/server/middleware/static.js +35 -0
  14. package/dashboard/server/package.json +16 -0
  15. package/dashboard/server/routes/agents.js +234 -0
  16. package/dashboard/server/routes/config.js +64 -0
  17. package/dashboard/server/routes/health.js +98 -0
  18. package/dashboard/server/routes/incidents.js +78 -0
  19. package/dashboard/server/routes/intel.js +69 -0
  20. package/dashboard/server/routes/memory.js +107 -0
  21. package/dashboard/server/routes/planning.js +234 -0
  22. package/dashboard/server/routes/progress.js +77 -0
  23. package/dashboard/server/routes/projects.js +36 -0
  24. package/dashboard/server/routes/requirements.js +40 -0
  25. package/dashboard/server/routes/roadmap.js +69 -0
  26. package/dashboard/server/routes/sessions.js +70 -0
  27. package/dashboard/server/routes/status.js +25 -0
  28. package/dashboard/server/routes/telemetry.js +233 -0
  29. package/dashboard/server/services/file-watcher.js +105 -0
  30. package/dashboard/server/services/planning-reader.js +727 -0
  31. package/dashboard/server/test/cli.test.js +34 -0
  32. package/dashboard/server/test/frontmatter.test.js +104 -0
  33. package/dashboard/server/test/isolation.test.js +32 -0
  34. package/dashboard/server/test/planning-reader.test.js +151 -0
  35. package/dashboard/server/test/routes.test.js +91 -0
  36. package/dashboard/server/test/ws.test.js +81 -0
  37. package/dashboard/server/ws.js +96 -0
  38. package/dashboard/src/App.jsx +165 -0
  39. package/dashboard/src/components/charts/BudgetBars.jsx +42 -0
  40. package/dashboard/src/components/charts/ContextRadar.jsx +34 -0
  41. package/dashboard/src/components/charts/PhaseDonut.jsx +66 -0
  42. package/dashboard/src/components/charts/SuccessTrend.jsx +45 -0
  43. package/dashboard/src/components/charts/TokenChart.jsx +55 -0
  44. package/dashboard/src/components/charts/index.js +5 -0
  45. package/dashboard/src/components/config/CfgSection.jsx +93 -0
  46. package/dashboard/src/components/layout/Header.jsx +89 -0
  47. package/dashboard/src/components/layout/ProjectSwitcher.jsx +160 -0
  48. package/dashboard/src/components/layout/Sidebar.jsx +161 -0
  49. package/dashboard/src/components/ui/AutoModeBanner.jsx +138 -0
  50. package/dashboard/src/components/ui/BackButton.jsx +27 -0
  51. package/dashboard/src/components/ui/Badge.jsx +27 -0
  52. package/dashboard/src/components/ui/Card.jsx +23 -0
  53. package/dashboard/src/components/ui/ChartTooltip.jsx +48 -0
  54. package/dashboard/src/components/ui/CheckpointBox.jsx +110 -0
  55. package/dashboard/src/components/ui/CodeBlock.jsx +27 -0
  56. package/dashboard/src/components/ui/ConfidenceBadge.jsx +20 -0
  57. package/dashboard/src/components/ui/ConfirmModal.jsx +161 -0
  58. package/dashboard/src/components/ui/ConnectionBanner.jsx +60 -0
  59. package/dashboard/src/components/ui/ErrorBoundary.jsx +106 -0
  60. package/dashboard/src/components/ui/ErrorBox.jsx +107 -0
  61. package/dashboard/src/components/ui/KeyValue.jsx +33 -0
  62. package/dashboard/src/components/ui/LoadingSkeleton.jsx +84 -0
  63. package/dashboard/src/components/ui/MetricCard.jsx +58 -0
  64. package/dashboard/src/components/ui/NextUpBlock.jsx +92 -0
  65. package/dashboard/src/components/ui/NumberInput.jsx +44 -0
  66. package/dashboard/src/components/ui/PBRBanner.jsx +47 -0
  67. package/dashboard/src/components/ui/PipelineView.jsx +130 -0
  68. package/dashboard/src/components/ui/ProgressBar.jsx +28 -0
  69. package/dashboard/src/components/ui/ProgressDisplay.jsx +47 -0
  70. package/dashboard/src/components/ui/QualityGateBadge.jsx +15 -0
  71. package/dashboard/src/components/ui/SectionTitle.jsx +35 -0
  72. package/dashboard/src/components/ui/SelectInput.jsx +45 -0
  73. package/dashboard/src/components/ui/StatusDot.jsx +51 -0
  74. package/dashboard/src/components/ui/StatusSymbol.jsx +49 -0
  75. package/dashboard/src/components/ui/TabBar.jsx +41 -0
  76. package/dashboard/src/components/ui/TextInput.jsx +42 -0
  77. package/dashboard/src/components/ui/Toast.jsx +117 -0
  78. package/dashboard/src/components/ui/Toggle.jsx +70 -0
  79. package/dashboard/src/components/ui/index.js +29 -0
  80. package/dashboard/src/hooks/useDocumentTitle.js +16 -0
  81. package/dashboard/src/hooks/useFetch.js +50 -0
  82. package/dashboard/src/hooks/useToast.jsx +43 -0
  83. package/dashboard/src/hooks/useWebSocket.js +103 -0
  84. package/dashboard/src/lib/api.js +112 -0
  85. package/dashboard/src/lib/configSchema.js +189 -0
  86. package/dashboard/src/lib/constants.js +22 -0
  87. package/dashboard/src/main.jsx +15 -0
  88. package/dashboard/src/pages/AgentsPage.jsx +191 -0
  89. package/dashboard/src/pages/ConfigPage.jsx +298 -0
  90. package/dashboard/src/pages/HooksPage.jsx +412 -0
  91. package/dashboard/src/pages/IncidentsPage.jsx +135 -0
  92. package/dashboard/src/pages/IntelPage.jsx +193 -0
  93. package/dashboard/src/pages/LiveFeed.jsx +274 -0
  94. package/dashboard/src/pages/MemoryPage.jsx +107 -0
  95. package/dashboard/src/pages/OnboardingPage.jsx +117 -0
  96. package/dashboard/src/pages/Overview.jsx +360 -0
  97. package/dashboard/src/pages/PhaseDetailView.jsx +216 -0
  98. package/dashboard/src/pages/PlanningPage.jsx +181 -0
  99. package/dashboard/src/pages/ProgressPage.jsx +249 -0
  100. package/dashboard/src/pages/ResearchPage.jsx +129 -0
  101. package/dashboard/src/pages/RoadmapPage.jsx +251 -0
  102. package/dashboard/src/pages/SessionsPage.jsx +117 -0
  103. package/dashboard/src/pages/Telemetry.jsx +166 -0
  104. package/dashboard/src/pages/planning/DecisionsTab.jsx +153 -0
  105. package/dashboard/src/pages/planning/FilesTab.jsx +420 -0
  106. package/dashboard/src/pages/planning/MilestoneDetail.jsx +319 -0
  107. package/dashboard/src/pages/planning/MilestonesTab.jsx +151 -0
  108. package/dashboard/src/pages/planning/NotesTab.jsx +251 -0
  109. package/dashboard/src/pages/planning/PhasesTab.jsx +218 -0
  110. package/dashboard/src/pages/planning/QuickTab.jsx +50 -0
  111. package/dashboard/src/pages/planning/ResearchTab.jsx +103 -0
  112. package/dashboard/src/pages/planning/TodosTab.jsx +297 -0
  113. package/dashboard/src/theme/ThemeProvider.jsx +38 -0
  114. package/dashboard/src/theme/tokens.js +17 -0
  115. package/dashboard/tests/components/ConfirmModal.test.jsx +179 -0
  116. package/dashboard/tests/components/ConnectionBanner.test.jsx +37 -0
  117. package/dashboard/tests/components/ErrorBoundary.test.jsx +59 -0
  118. package/dashboard/tests/components/LoadingSkeleton.test.jsx +46 -0
  119. package/dashboard/tests/components/ToastContainer.test.jsx +47 -0
  120. package/dashboard/tests/components/Toggle.test.jsx +61 -0
  121. package/dashboard/tests/hooks/useFetch.test.jsx +77 -0
  122. package/dashboard/tests/hooks/useToast.test.jsx +78 -0
  123. package/dashboard/tests/hooks/useWebSocket.test.jsx +128 -0
  124. package/dashboard/tests/pages/ConfigPage.test.jsx +199 -0
  125. package/dashboard/tests/pages/PlanningPage.test.jsx +119 -0
  126. package/dashboard/tests/pages/planning/FilesTab.test.jsx +198 -0
  127. package/dashboard/tests/pages/planning/NotesTab.test.jsx +178 -0
  128. package/dashboard/tests/pages/planning/TodosTab.test.jsx +188 -0
  129. package/dashboard/tests/performance.test.jsx +46 -0
  130. package/dashboard/tests/routes/config.test.js +98 -0
  131. package/dashboard/tests/routes/health.test.js +40 -0
  132. package/dashboard/tests/routes/planning.test.js +112 -0
  133. package/dashboard/tests/routes/roadmap.test.js +91 -0
  134. package/dashboard/tests/routes/status.test.js +131 -0
  135. package/dashboard/tests/server/planning-reader.test.js +153 -0
  136. package/dashboard/tests/setup.js +7 -0
  137. package/dashboard/vite.config.js +41 -0
  138. package/package.json +56 -41
  139. package/plan-build-run/bin/config-schema.json +1298 -0
  140. package/plugins/pbr/.claude-plugin/plugin.json +1 -1
  141. package/plugins/pbr/CLAUDE.md +19 -0
  142. package/plugins/pbr/UI-CONSISTENCY-GAPS.md +1 -1
  143. package/plugins/pbr/agents/advisor-researcher.md +101 -0
  144. package/plugins/pbr/agents/audit.md +207 -89
  145. package/plugins/pbr/agents/codebase-mapper.md +158 -23
  146. package/plugins/pbr/agents/debugger.md +210 -34
  147. package/plugins/pbr/agents/dev-sync.md +206 -0
  148. package/plugins/pbr/agents/executor.md +734 -38
  149. package/plugins/pbr/agents/general.md +69 -5
  150. package/plugins/pbr/agents/integration-checker.md +147 -31
  151. package/plugins/pbr/agents/intel-updater.md +332 -0
  152. package/plugins/pbr/agents/nyquist-auditor.md +254 -0
  153. package/plugins/pbr/agents/plan-checker.md +268 -65
  154. package/plugins/pbr/agents/planner.md +449 -41
  155. package/plugins/pbr/agents/researcher.md +218 -37
  156. package/plugins/pbr/agents/roadmapper.md +398 -0
  157. package/plugins/pbr/agents/synthesizer.md +166 -25
  158. package/plugins/pbr/agents/ui-checker.md +204 -0
  159. package/plugins/pbr/agents/ui-researcher.md +224 -0
  160. package/plugins/pbr/agents/verifier.md +570 -46
  161. package/plugins/pbr/commands/add-phase.md +75 -0
  162. package/plugins/pbr/commands/add-todo.md +8 -0
  163. package/plugins/pbr/commands/audit-fix.md +5 -0
  164. package/plugins/pbr/commands/audit-milestone.md +8 -0
  165. package/plugins/pbr/commands/autonomous.md +5 -0
  166. package/plugins/pbr/commands/backlog.md +6 -0
  167. package/plugins/pbr/commands/check-todos.md +8 -0
  168. package/plugins/pbr/commands/complete-milestone.md +8 -0
  169. package/plugins/pbr/commands/config.md +1 -1
  170. package/plugins/pbr/commands/discuss-phase.md +6 -0
  171. package/plugins/pbr/commands/execute-phase.md +6 -0
  172. package/plugins/pbr/commands/fast.md +6 -0
  173. package/plugins/pbr/commands/forensics.md +6 -0
  174. package/plugins/pbr/commands/import.md +1 -1
  175. package/plugins/pbr/commands/insert-phase.md +65 -0
  176. package/plugins/pbr/commands/intel.md +5 -0
  177. package/plugins/pbr/commands/join-discord.md +11 -0
  178. package/plugins/pbr/commands/list-phase-assumptions.md +5 -0
  179. package/plugins/pbr/commands/map-codebase.md +6 -0
  180. package/plugins/pbr/commands/milestone-summary.md +6 -0
  181. package/plugins/pbr/commands/new-milestone.md +8 -0
  182. package/plugins/pbr/commands/new-project.md +6 -0
  183. package/plugins/pbr/commands/pause-work.md +5 -0
  184. package/plugins/pbr/commands/plan-milestone-gaps.md +7 -0
  185. package/plugins/pbr/commands/plan-phase.md +6 -0
  186. package/plugins/pbr/commands/plant-seed.md +6 -0
  187. package/plugins/pbr/commands/profile-user.md +5 -0
  188. package/plugins/pbr/commands/profile.md +5 -0
  189. package/plugins/pbr/commands/progress.md +6 -0
  190. package/plugins/pbr/commands/quick.md +1 -1
  191. package/plugins/pbr/commands/reapply-patches.md +47 -0
  192. package/plugins/pbr/commands/release.md +6 -0
  193. package/plugins/pbr/commands/remove-phase.md +66 -0
  194. package/plugins/pbr/commands/research-phase.md +59 -0
  195. package/plugins/pbr/commands/resume-work.md +5 -0
  196. package/plugins/pbr/commands/seed.md +6 -0
  197. package/plugins/pbr/commands/session-report.md +5 -0
  198. package/plugins/pbr/commands/set-profile.md +6 -0
  199. package/plugins/pbr/commands/settings.md +5 -0
  200. package/plugins/pbr/commands/setup.md +1 -1
  201. package/plugins/pbr/commands/ship.md +5 -0
  202. package/plugins/pbr/commands/stats.md +6 -0
  203. package/plugins/pbr/commands/test.md +5 -0
  204. package/plugins/pbr/commands/thread.md +6 -0
  205. package/plugins/pbr/commands/todo.md +1 -1
  206. package/plugins/pbr/commands/ui-phase.md +5 -0
  207. package/plugins/pbr/commands/ui-review.md +5 -0
  208. package/plugins/pbr/commands/undo.md +5 -0
  209. package/plugins/pbr/commands/update.md +37 -0
  210. package/plugins/pbr/commands/validate-phase.md +5 -0
  211. package/plugins/pbr/commands/verify-work.md +6 -0
  212. package/plugins/pbr/dashboard/package-lock.json +6 -0
  213. package/plugins/pbr/dist/architecture-guard.js +76 -0
  214. package/plugins/pbr/dist/audit-dimensions.js +556 -0
  215. package/plugins/pbr/dist/auto-continue.js +277 -0
  216. package/plugins/pbr/dist/block-skill-self-read.js +124 -0
  217. package/plugins/pbr/dist/check-agent-state-write.js +63 -0
  218. package/plugins/pbr/dist/check-config-change.js +213 -0
  219. package/plugins/pbr/dist/check-cross-plugin-sync.js +93 -0
  220. package/plugins/pbr/dist/check-dangerous-commands.js +193 -0
  221. package/plugins/pbr/dist/check-direct-state-write.js +37 -0
  222. package/plugins/pbr/dist/check-doc-sprawl.js +102 -0
  223. package/plugins/pbr/dist/check-phase-boundary.js +191 -0
  224. package/plugins/pbr/dist/check-plan-format.js +227 -0
  225. package/plugins/pbr/dist/check-read-first.js +345 -0
  226. package/plugins/pbr/dist/check-roadmap-sync.js +507 -0
  227. package/plugins/pbr/dist/check-skill-workflow.js +354 -0
  228. package/plugins/pbr/dist/check-state-sync.js +676 -0
  229. package/plugins/pbr/dist/check-subagent-output.js +425 -0
  230. package/plugins/pbr/dist/check-summary-gate.js +188 -0
  231. package/plugins/pbr/dist/context-bridge.js +425 -0
  232. package/plugins/pbr/dist/context-budget-check.js +442 -0
  233. package/plugins/pbr/dist/context-quality.js +271 -0
  234. package/plugins/pbr/dist/enforce-context-budget.js +138 -0
  235. package/plugins/pbr/dist/enforce-pbr-workflow.js +277 -0
  236. package/plugins/pbr/dist/event-handler.js +212 -0
  237. package/plugins/pbr/dist/event-logger.js +125 -0
  238. package/plugins/pbr/dist/feedback-loop.js +155 -0
  239. package/plugins/pbr/dist/graph-update.js +422 -0
  240. package/plugins/pbr/dist/hook-logger.js +114 -0
  241. package/plugins/pbr/dist/hook-server-client.js +361 -0
  242. package/plugins/pbr/dist/hook-server.js +664 -0
  243. package/plugins/pbr/dist/hooks-schema.json +87 -0
  244. package/plugins/pbr/dist/instructions-loaded.js +173 -0
  245. package/plugins/pbr/dist/intercept-plan-mode.js +81 -0
  246. package/plugins/pbr/dist/log-notification.js +131 -0
  247. package/plugins/pbr/dist/log-subagent.js +367 -0
  248. package/plugins/pbr/dist/log-tool-failure.js +140 -0
  249. package/plugins/pbr/dist/milestone-learnings.js +519 -0
  250. package/plugins/pbr/dist/pbr-tools.js +493 -0
  251. package/plugins/pbr/dist/post-bash-triage.js +96 -0
  252. package/plugins/pbr/dist/post-compact.js +135 -0
  253. package/plugins/pbr/dist/post-hoc.js +237 -0
  254. package/plugins/pbr/dist/post-write-dispatch.js +243 -0
  255. package/plugins/pbr/dist/post-write-quality.js +208 -0
  256. package/plugins/pbr/dist/pre-bash-dispatch.js +212 -0
  257. package/plugins/pbr/dist/pre-skill-dispatch.js +114 -0
  258. package/plugins/pbr/dist/pre-task-dispatch.js +269 -0
  259. package/plugins/pbr/dist/pre-write-dispatch.js +234 -0
  260. package/plugins/pbr/dist/progress-tracker.js +173 -0
  261. package/plugins/pbr/dist/prompt-guard.js +114 -0
  262. package/plugins/pbr/dist/prompt-routing.js +209 -0
  263. package/plugins/pbr/dist/quick-status.js +179 -0
  264. package/plugins/pbr/dist/record-incident.js +37 -0
  265. package/plugins/pbr/dist/run-hook.js +132 -0
  266. package/plugins/pbr/dist/session-cleanup.js +653 -0
  267. package/plugins/pbr/dist/session-tracker.js +124 -0
  268. package/plugins/pbr/dist/status-line.js +849 -0
  269. package/plugins/pbr/dist/suggest-compact.js +307 -0
  270. package/plugins/pbr/dist/sync-context-to-claude.js +100 -0
  271. package/plugins/pbr/dist/task-completed.js +206 -0
  272. package/plugins/pbr/dist/track-context-budget.js +432 -0
  273. package/plugins/pbr/dist/track-user-gates.js +88 -0
  274. package/plugins/pbr/dist/trust-tracker.js +193 -0
  275. package/plugins/pbr/dist/validate-commit.js +233 -0
  276. package/plugins/pbr/dist/validate-skill-args.js +222 -0
  277. package/plugins/pbr/dist/validate-task.js +271 -0
  278. package/plugins/pbr/dist/worktree-create.js +144 -0
  279. package/plugins/pbr/dist/worktree-remove.js +147 -0
  280. package/plugins/pbr/hooks/hooks.json +137 -65
  281. package/plugins/pbr/references/agent-contracts.md +39 -8
  282. package/plugins/pbr/references/agent-teams.md +3 -3
  283. package/plugins/pbr/references/archive/checkpoints.md +189 -0
  284. package/plugins/pbr/references/archive/context-quality-tiers.md +45 -0
  285. package/plugins/pbr/references/archive/hook-ordering.md +89 -0
  286. package/plugins/pbr/references/archive/limitations.md +106 -0
  287. package/plugins/pbr/references/archive/pbr-rules.md +194 -0
  288. package/plugins/pbr/references/archive/pbr-tools-cli.md +415 -0
  289. package/plugins/pbr/references/archive/pretooluse-jsonl-behavior.md +58 -0
  290. package/plugins/pbr/references/archive/signal-files.md +41 -0
  291. package/plugins/pbr/references/archive/tmux-setup.md +288 -0
  292. package/plugins/pbr/references/archive/verification-matrix.md +34 -0
  293. package/plugins/pbr/references/archive/verification-patterns.md +277 -0
  294. package/plugins/pbr/references/archive/worktree-sparse-checkout.md +86 -0
  295. package/plugins/pbr/references/assumptions.md +42 -0
  296. package/plugins/pbr/references/checkpoints.md +723 -104
  297. package/plugins/pbr/references/config-reference.md +387 -10
  298. package/plugins/pbr/references/continuation-format.md +1 -0
  299. package/plugins/pbr/references/decimal-phase-calculation.md +65 -0
  300. package/plugins/pbr/references/deviation-rules.md +12 -0
  301. package/plugins/pbr/references/few-shot-examples/audit.md +77 -0
  302. package/plugins/pbr/references/few-shot-examples/check-plan-format.md +172 -0
  303. package/plugins/pbr/references/few-shot-examples/check-subagent-output.md +118 -0
  304. package/plugins/pbr/references/few-shot-examples/integration-checker.md +70 -0
  305. package/plugins/pbr/references/few-shot-examples/nyquist-auditor.md +83 -0
  306. package/plugins/pbr/references/few-shot-examples/plan-checker.md +73 -0
  307. package/plugins/pbr/references/few-shot-examples/ui-checker.md +71 -0
  308. package/plugins/pbr/references/few-shot-examples/verifier.md +109 -0
  309. package/plugins/pbr/references/git-integration.md +110 -27
  310. package/plugins/pbr/references/git-planning-commit.md +35 -0
  311. package/plugins/pbr/references/model-profile-resolution.md +34 -0
  312. package/plugins/pbr/references/model-profiles.md +90 -7
  313. package/plugins/pbr/references/model-selection.md +1 -1
  314. package/plugins/pbr/references/node-repair.md +48 -0
  315. package/plugins/pbr/references/plan-authoring.md +65 -0
  316. package/plugins/pbr/references/plan-format.md +184 -10
  317. package/plugins/pbr/references/questioning.md +138 -49
  318. package/plugins/pbr/references/reading-verification.md +4 -4
  319. package/plugins/pbr/references/tdd.md +263 -0
  320. package/plugins/pbr/references/thinking-models-planning.md +47 -0
  321. package/plugins/pbr/references/thinking-models-verification.md +44 -0
  322. package/plugins/pbr/references/ui-brand.md +449 -0
  323. package/plugins/pbr/references/verification-overrides.md +39 -0
  324. package/plugins/pbr/references/verification-patterns.md +529 -113
  325. package/plugins/pbr/scripts/architecture-guard.js +76 -0
  326. package/plugins/pbr/scripts/audit-checks/behavioral-compliance.js +2098 -0
  327. package/plugins/pbr/scripts/audit-checks/error-analysis.js +989 -0
  328. package/plugins/pbr/scripts/audit-checks/feature-verification.js +723 -0
  329. package/plugins/pbr/scripts/audit-checks/index.js +433 -0
  330. package/plugins/pbr/scripts/audit-checks/infrastructure.js +816 -0
  331. package/plugins/pbr/scripts/audit-checks/quality-metrics.js +455 -0
  332. package/plugins/pbr/scripts/audit-checks/session-quality.js +980 -0
  333. package/plugins/pbr/scripts/audit-checks/si-agent-hook-config-checks.js +396 -0
  334. package/plugins/pbr/scripts/audit-checks/si-cross-cutting-checks.js +272 -0
  335. package/plugins/pbr/scripts/audit-checks/si-skill-checks.js +424 -0
  336. package/plugins/pbr/scripts/audit-checks/workflow-compliance.js +1175 -0
  337. package/plugins/pbr/scripts/audit-dimensions.js +556 -0
  338. package/plugins/pbr/scripts/auto-continue.js +192 -37
  339. package/plugins/pbr/scripts/block-skill-self-read.js +124 -0
  340. package/plugins/pbr/scripts/check-agent-state-write.js +63 -0
  341. package/plugins/pbr/scripts/check-config-change.js +84 -1
  342. package/plugins/pbr/scripts/check-cross-plugin-sync.js +93 -0
  343. package/plugins/pbr/scripts/check-dangerous-commands.js +18 -5
  344. package/plugins/pbr/scripts/check-direct-state-write.js +37 -0
  345. package/plugins/pbr/scripts/check-phase-boundary.js +3 -2
  346. package/plugins/pbr/scripts/check-plan-format.js +153 -354
  347. package/plugins/pbr/scripts/check-read-first.js +345 -0
  348. package/plugins/pbr/scripts/check-roadmap-sync.js +174 -19
  349. package/plugins/pbr/scripts/check-skill-workflow.js +21 -16
  350. package/plugins/pbr/scripts/check-state-sync.js +352 -220
  351. package/plugins/pbr/scripts/check-subagent-output.js +296 -333
  352. package/plugins/pbr/scripts/check-summary-gate.js +5 -15
  353. package/plugins/pbr/scripts/commands/benchmarks.js +195 -0
  354. package/plugins/pbr/scripts/commands/calibrate.js +530 -0
  355. package/plugins/pbr/scripts/commands/config.js +72 -0
  356. package/plugins/pbr/scripts/commands/misc.js +779 -0
  357. package/plugins/pbr/scripts/commands/phase.js +293 -0
  358. package/plugins/pbr/scripts/commands/roadmap.js +75 -0
  359. package/plugins/pbr/scripts/commands/state.js +84 -0
  360. package/plugins/pbr/scripts/commands/stress-test.js +349 -0
  361. package/plugins/pbr/scripts/commands/todo.js +191 -0
  362. package/plugins/pbr/scripts/commands/verify.js +169 -0
  363. package/plugins/pbr/scripts/config-schema.json +1183 -95
  364. package/plugins/pbr/scripts/context-bridge.js +425 -0
  365. package/plugins/pbr/scripts/context-budget-check.js +171 -16
  366. package/plugins/pbr/scripts/context-quality.js +271 -0
  367. package/plugins/pbr/scripts/enforce-context-budget.js +138 -0
  368. package/plugins/pbr/scripts/enforce-pbr-workflow.js +277 -0
  369. package/plugins/pbr/scripts/event-handler.js +137 -87
  370. package/plugins/pbr/scripts/event-logger.js +58 -25
  371. package/plugins/pbr/scripts/feedback-loop.js +155 -0
  372. package/plugins/pbr/scripts/graph-update.js +422 -0
  373. package/plugins/pbr/scripts/hook-logger.js +69 -35
  374. package/plugins/pbr/scripts/hook-server-client.js +361 -0
  375. package/plugins/pbr/scripts/hook-server.js +664 -0
  376. package/plugins/pbr/scripts/hooks-schema.json +12 -5
  377. package/plugins/pbr/scripts/instructions-loaded.js +173 -0
  378. package/plugins/pbr/scripts/intent-router.cjs +147 -0
  379. package/plugins/pbr/scripts/intercept-plan-mode.js +52 -18
  380. package/plugins/pbr/scripts/lib/alternatives.js +203 -0
  381. package/plugins/pbr/scripts/lib/audit.js +65 -0
  382. package/plugins/pbr/scripts/lib/auto-cleanup.js +221 -0
  383. package/plugins/pbr/scripts/lib/auto-verify.js +123 -0
  384. package/plugins/pbr/scripts/lib/benchmark.js +190 -0
  385. package/plugins/pbr/scripts/lib/build.js +719 -0
  386. package/plugins/pbr/scripts/lib/ci-fix-loop.js +228 -0
  387. package/plugins/pbr/scripts/lib/commands.js +483 -0
  388. package/plugins/pbr/scripts/lib/compound.js +222 -0
  389. package/plugins/pbr/scripts/lib/config-cache.js +83 -0
  390. package/plugins/pbr/scripts/lib/config.js +1469 -0
  391. package/plugins/pbr/scripts/lib/context.js +254 -0
  392. package/plugins/pbr/scripts/lib/contextual-help.js +183 -0
  393. package/plugins/pbr/scripts/lib/convention-detector.js +413 -0
  394. package/plugins/pbr/scripts/lib/core.js +1585 -0
  395. package/plugins/pbr/scripts/lib/dashboard-launch.js +364 -0
  396. package/plugins/pbr/scripts/lib/data-hygiene.js +179 -0
  397. package/plugins/pbr/scripts/lib/decision-extraction.js +183 -0
  398. package/plugins/pbr/scripts/lib/decisions.js +194 -0
  399. package/plugins/pbr/scripts/lib/dependency-break.js +147 -0
  400. package/plugins/pbr/scripts/lib/format-validators.js +1049 -0
  401. package/plugins/pbr/scripts/lib/frontmatter.js +302 -0
  402. package/plugins/pbr/scripts/lib/gates/advisories.js +133 -0
  403. package/plugins/pbr/scripts/lib/gates/build-dependency.js +118 -0
  404. package/plugins/pbr/scripts/lib/gates/build-executor.js +106 -0
  405. package/plugins/pbr/scripts/lib/gates/doc-existence.js +46 -0
  406. package/plugins/pbr/scripts/lib/gates/helpers.js +98 -0
  407. package/plugins/pbr/scripts/lib/gates/inline-execution.js +187 -0
  408. package/plugins/pbr/scripts/lib/gates/milestone-complete.js +139 -0
  409. package/plugins/pbr/scripts/lib/gates/milestone-summary.js +121 -0
  410. package/plugins/pbr/scripts/lib/gates/multi-phase-loader.js +149 -0
  411. package/plugins/pbr/scripts/lib/gates/plan-executor.js +36 -0
  412. package/plugins/pbr/scripts/lib/gates/plan-validation.js +115 -0
  413. package/plugins/pbr/scripts/lib/gates/quick-executor.js +78 -0
  414. package/plugins/pbr/scripts/lib/gates/review-planner.js +63 -0
  415. package/plugins/pbr/scripts/lib/gates/review-verifier.js +71 -0
  416. package/plugins/pbr/scripts/lib/gates/rich-agent-context.js +148 -0
  417. package/plugins/pbr/scripts/lib/gates/sprint-preflight.js +30 -0
  418. package/plugins/pbr/scripts/lib/gates/user-confirmation.js +95 -0
  419. package/plugins/pbr/scripts/lib/graph-cli.js +89 -0
  420. package/plugins/pbr/scripts/lib/graph.js +553 -0
  421. package/plugins/pbr/scripts/lib/handoff-validators.js +224 -0
  422. package/plugins/pbr/scripts/lib/health-checks.js +107 -0
  423. package/plugins/pbr/scripts/lib/health-phase06.js +120 -0
  424. package/plugins/pbr/scripts/lib/health.js +132 -0
  425. package/plugins/pbr/scripts/lib/help.js +100 -0
  426. package/plugins/pbr/scripts/lib/history.js +150 -0
  427. package/plugins/pbr/scripts/lib/impact-analysis.js +319 -0
  428. package/plugins/pbr/scripts/lib/incidents.js +190 -0
  429. package/plugins/pbr/scripts/lib/init.js +643 -0
  430. package/plugins/pbr/scripts/lib/insights-parser.js +320 -0
  431. package/plugins/pbr/scripts/lib/intel.js +653 -0
  432. package/plugins/pbr/scripts/lib/learnings.js +511 -0
  433. package/plugins/pbr/scripts/lib/migrate.js +309 -0
  434. package/plugins/pbr/scripts/lib/milestone.js +306 -0
  435. package/plugins/pbr/scripts/lib/msys-path.js +20 -0
  436. package/plugins/pbr/scripts/lib/negative-knowledge.js +194 -0
  437. package/plugins/pbr/scripts/lib/notification-throttle.js +141 -0
  438. package/plugins/pbr/scripts/lib/onboarding-generator.js +288 -0
  439. package/plugins/pbr/scripts/lib/parse-args.js +134 -0
  440. package/plugins/pbr/scripts/lib/pattern-routing.js +55 -0
  441. package/plugins/pbr/scripts/lib/patterns.js +272 -0
  442. package/plugins/pbr/scripts/lib/perf.js +190 -0
  443. package/plugins/pbr/scripts/lib/phase.js +1043 -0
  444. package/plugins/pbr/scripts/lib/pid-lock.js +156 -0
  445. package/plugins/pbr/scripts/lib/post-hoc.js +160 -0
  446. package/plugins/pbr/scripts/lib/pre-commit-checks.js +220 -0
  447. package/plugins/pbr/scripts/lib/pre-research.js +126 -0
  448. package/plugins/pbr/scripts/lib/premature-completion.js +312 -0
  449. package/plugins/pbr/scripts/lib/preview.js +174 -0
  450. package/plugins/pbr/scripts/lib/progress-visualization.js +296 -0
  451. package/plugins/pbr/scripts/lib/quick-init.js +131 -0
  452. package/plugins/pbr/scripts/lib/reference.js +236 -0
  453. package/plugins/pbr/scripts/lib/requirements.js +153 -0
  454. package/plugins/pbr/scripts/lib/resolve-root.js +66 -0
  455. package/plugins/pbr/scripts/lib/reverse-spec.js +259 -0
  456. package/plugins/pbr/scripts/lib/roadmap.js +1089 -0
  457. package/plugins/pbr/scripts/lib/security-scan.js +200 -0
  458. package/plugins/pbr/scripts/lib/session-briefing.js +918 -0
  459. package/plugins/pbr/scripts/lib/skill-section.js +99 -0
  460. package/plugins/pbr/scripts/lib/smart-next-task.js +198 -0
  461. package/plugins/pbr/scripts/lib/snapshot-manager.js +232 -0
  462. package/plugins/pbr/scripts/lib/spec-diff.js +209 -0
  463. package/plugins/pbr/scripts/lib/spec-engine.js +189 -0
  464. package/plugins/pbr/scripts/lib/spot-check.js +539 -0
  465. package/plugins/pbr/scripts/lib/state-queue.js +171 -0
  466. package/plugins/pbr/scripts/lib/state.js +1082 -0
  467. package/plugins/pbr/scripts/lib/status-render.js +511 -0
  468. package/plugins/pbr/scripts/lib/step-verify.js +149 -0
  469. package/plugins/pbr/scripts/lib/subagent-validators.js +1119 -0
  470. package/plugins/pbr/scripts/lib/suggest-next.js +435 -0
  471. package/plugins/pbr/scripts/lib/tech-debt-scanner.js +116 -0
  472. package/plugins/pbr/scripts/lib/templates.js +362 -0
  473. package/plugins/pbr/scripts/lib/test-selection.js +163 -0
  474. package/plugins/pbr/scripts/lib/todo.js +300 -0
  475. package/plugins/pbr/scripts/lib/verify.js +1561 -0
  476. package/plugins/pbr/scripts/log-notification.js +131 -0
  477. package/plugins/pbr/scripts/log-subagent.js +221 -18
  478. package/plugins/pbr/scripts/log-tool-failure.js +60 -5
  479. package/plugins/pbr/scripts/milestone-learnings.js +519 -0
  480. package/plugins/pbr/scripts/package.json +1 -1
  481. package/plugins/pbr/scripts/pbr-tools.js +362 -1247
  482. package/plugins/pbr/scripts/post-bash-triage.js +96 -0
  483. package/plugins/pbr/scripts/post-compact.js +135 -0
  484. package/plugins/pbr/scripts/post-hoc.js +237 -0
  485. package/plugins/pbr/scripts/post-write-dispatch.js +201 -31
  486. package/plugins/pbr/scripts/post-write-quality.js +4 -3
  487. package/plugins/pbr/scripts/pre-bash-dispatch.js +147 -51
  488. package/plugins/pbr/scripts/pre-skill-dispatch.js +114 -0
  489. package/plugins/pbr/scripts/pre-task-dispatch.js +269 -0
  490. package/plugins/pbr/scripts/pre-write-dispatch.js +170 -72
  491. package/plugins/pbr/scripts/progress-tracker.js +121 -324
  492. package/plugins/pbr/scripts/prompt-guard.js +114 -0
  493. package/plugins/pbr/scripts/prompt-routing.js +209 -0
  494. package/plugins/pbr/scripts/quick-status.js +179 -0
  495. package/plugins/pbr/scripts/record-incident.js +37 -0
  496. package/plugins/pbr/scripts/risk-classifier.cjs +123 -0
  497. package/plugins/pbr/scripts/run-hook.js +63 -23
  498. package/plugins/pbr/scripts/session-cleanup.js +428 -29
  499. package/plugins/pbr/scripts/session-tracker.js +124 -0
  500. package/plugins/pbr/scripts/status-line.js +571 -43
  501. package/plugins/pbr/scripts/suggest-compact.js +201 -13
  502. package/plugins/pbr/scripts/sync-context-to-claude.js +100 -0
  503. package/plugins/pbr/scripts/task-completed.js +165 -4
  504. package/plugins/pbr/scripts/test/config.test.js +126 -0
  505. package/plugins/pbr/scripts/test/cross-platform.test.js +120 -0
  506. package/plugins/pbr/scripts/test/fixtures/config.json +20 -0
  507. package/plugins/pbr/scripts/test/fixtures/plan.md +54 -0
  508. package/plugins/pbr/scripts/test/fixtures/project.md +30 -0
  509. package/plugins/pbr/scripts/test/fixtures/roadmap.md +55 -0
  510. package/plugins/pbr/scripts/test/fixtures/state.md +60 -0
  511. package/plugins/pbr/scripts/test/fixtures/summary.md +35 -0
  512. package/plugins/pbr/scripts/test/fixtures.test.js +184 -0
  513. package/plugins/pbr/scripts/test/phase.test.js +142 -0
  514. package/plugins/pbr/scripts/test/roadmap.test.js +96 -0
  515. package/plugins/pbr/scripts/test/state.test.js +155 -0
  516. package/plugins/pbr/scripts/track-context-budget.js +368 -104
  517. package/plugins/pbr/scripts/track-user-gates.js +88 -0
  518. package/plugins/pbr/scripts/trust-tracker.js +193 -0
  519. package/plugins/pbr/scripts/validate-commit.js +51 -19
  520. package/plugins/pbr/scripts/validate-skill-args.js +85 -14
  521. package/plugins/pbr/scripts/validate-task.js +83 -622
  522. package/plugins/pbr/scripts/worktree-create.js +144 -0
  523. package/plugins/pbr/scripts/worktree-remove.js +147 -0
  524. package/plugins/pbr/skills/audit/SKILL.md +195 -24
  525. package/plugins/pbr/skills/audit-fix/SKILL.md +326 -0
  526. package/plugins/pbr/skills/autonomous/SKILL.md +551 -0
  527. package/plugins/pbr/skills/backlog/SKILL.md +56 -0
  528. package/plugins/pbr/skills/begin/SKILL.md +508 -153
  529. package/plugins/pbr/skills/begin/templates/STATE.md.tmpl +1 -2
  530. package/plugins/pbr/skills/begin/templates/config.json.tmpl +419 -36
  531. package/plugins/pbr/skills/begin/templates/researcher-prompt.md.tmpl +28 -0
  532. package/plugins/pbr/skills/begin/templates/roadmap-prompt.md.tmpl +28 -3
  533. package/plugins/pbr/skills/begin/templates/synthesis-prompt.md.tmpl +33 -5
  534. package/plugins/pbr/skills/build/SKILL.md +1180 -357
  535. package/plugins/pbr/skills/build/templates/continuation-prompt.md.tmpl +26 -0
  536. package/plugins/pbr/skills/build/templates/executor-prompt.md.tmpl +77 -0
  537. package/plugins/pbr/skills/build/templates/inline-verifier-prompt.md.tmpl +33 -0
  538. package/plugins/pbr/skills/build/templates/qa-round-context.md.tmpl +16 -0
  539. package/plugins/pbr/skills/config/SKILL.md +112 -9
  540. package/plugins/pbr/skills/continue/SKILL.md +113 -33
  541. package/plugins/pbr/skills/dashboard/SKILL.md +21 -9
  542. package/plugins/pbr/skills/debug/SKILL.md +70 -12
  543. package/plugins/pbr/skills/debug/templates/continuation-prompt.md.tmpl +12 -1
  544. package/plugins/pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +12 -5
  545. package/plugins/pbr/skills/discuss/SKILL.md +205 -24
  546. package/plugins/pbr/skills/discuss/templates/CONTEXT.md.tmpl +21 -1
  547. package/plugins/pbr/skills/do/SKILL.md +119 -24
  548. package/plugins/pbr/skills/explore/SKILL.md +95 -20
  549. package/plugins/pbr/skills/fast/SKILL.md +94 -0
  550. package/plugins/pbr/skills/forensics/SKILL.md +144 -0
  551. package/plugins/pbr/skills/health/SKILL.md +35 -115
  552. package/plugins/pbr/skills/help/SKILL.md +83 -123
  553. package/plugins/pbr/skills/import/SKILL.md +332 -13
  554. package/plugins/pbr/skills/intel/SKILL.md +131 -0
  555. package/plugins/pbr/skills/list-phase-assumptions/SKILL.md +231 -0
  556. package/plugins/pbr/skills/milestone/SKILL.md +383 -274
  557. package/plugins/pbr/skills/milestone/templates/audit-output.md.tmpl +76 -0
  558. package/plugins/pbr/skills/milestone/templates/complete-output.md.tmpl +32 -0
  559. package/plugins/pbr/skills/milestone/templates/edge-cases.md +54 -0
  560. package/plugins/pbr/skills/milestone/templates/gaps-output.md.tmpl +25 -0
  561. package/plugins/pbr/skills/milestone/templates/integration-checker-prompt.md.tmpl +25 -0
  562. package/plugins/pbr/skills/milestone/templates/new-output.md.tmpl +29 -0
  563. package/plugins/pbr/skills/milestone-summary/SKILL.md +86 -0
  564. package/plugins/pbr/skills/note/SKILL.md +20 -4
  565. package/plugins/pbr/skills/pause/SKILL.md +54 -14
  566. package/plugins/pbr/skills/pause/templates/continue-here.md.tmpl +33 -52
  567. package/plugins/pbr/skills/plan/SKILL.md +526 -280
  568. package/plugins/pbr/skills/plan/templates/checker-prompt.md.tmpl +20 -2
  569. package/plugins/pbr/skills/plan/templates/completion-output.md.tmpl +27 -0
  570. package/plugins/pbr/skills/plan/templates/planner-prompt.md.tmpl +43 -1
  571. package/plugins/pbr/skills/plan/templates/revision-prompt.md.tmpl +21 -5
  572. package/plugins/pbr/skills/profile/SKILL.md +185 -0
  573. package/plugins/pbr/skills/profile-user/SKILL.md +227 -0
  574. package/plugins/pbr/skills/quick/SKILL.md +435 -100
  575. package/plugins/pbr/skills/release/SKILL.md +206 -0
  576. package/plugins/pbr/skills/resume/SKILL.md +170 -46
  577. package/plugins/pbr/skills/review/SKILL.md +233 -165
  578. package/plugins/pbr/skills/review/templates/verifier-prompt.md.tmpl +7 -0
  579. package/plugins/pbr/skills/scan/SKILL.md +152 -106
  580. package/plugins/pbr/skills/scan/templates/mapper-prompt.md.tmpl +5 -56
  581. package/plugins/pbr/skills/seed/SKILL.md +87 -0
  582. package/plugins/pbr/skills/session-report/SKILL.md +130 -0
  583. package/plugins/pbr/skills/setup/SKILL.md +150 -202
  584. package/plugins/pbr/skills/shared/agent-context-enrichment.md +21 -0
  585. package/plugins/pbr/skills/shared/agent-type-resolution.md +32 -0
  586. package/plugins/pbr/skills/shared/commit-planning-docs.md +8 -0
  587. package/plugins/pbr/skills/shared/context-budget.md +66 -1
  588. package/plugins/pbr/skills/shared/context-loader-task.md +18 -11
  589. package/plugins/pbr/skills/shared/criterion-writing.md +58 -0
  590. package/plugins/pbr/skills/shared/digest-select.md +2 -2
  591. package/plugins/pbr/skills/shared/domain-probes.md +1 -1
  592. package/plugins/pbr/skills/shared/error-reporting.md +38 -60
  593. package/plugins/pbr/skills/shared/gate-prompts.md +4 -2
  594. package/plugins/pbr/skills/shared/memory-capture.md +48 -0
  595. package/plugins/pbr/skills/shared/phase-argument-parsing.md +4 -4
  596. package/plugins/pbr/skills/shared/revision-loop.md +24 -6
  597. package/plugins/pbr/skills/shared/state-update.md +46 -61
  598. package/plugins/pbr/skills/shared/universal-anti-patterns.md +27 -4
  599. package/plugins/pbr/skills/ship/SKILL.md +155 -0
  600. package/plugins/pbr/skills/stats/SKILL.md +110 -0
  601. package/plugins/pbr/skills/status/SKILL.md +185 -119
  602. package/plugins/pbr/skills/test/SKILL.md +254 -0
  603. package/plugins/pbr/skills/thread/SKILL.md +73 -0
  604. package/plugins/pbr/skills/todo/SKILL.md +28 -72
  605. package/plugins/pbr/skills/ui-phase/SKILL.md +180 -0
  606. package/plugins/pbr/skills/ui-review/SKILL.md +206 -0
  607. package/plugins/pbr/skills/undo/SKILL.md +221 -0
  608. package/plugins/pbr/skills/validate-phase/SKILL.md +362 -0
  609. package/plugins/pbr/templates/CONTEXT.md.tmpl +45 -20
  610. package/plugins/pbr/templates/DISCOVERY.md.tmpl +29 -0
  611. package/plugins/pbr/templates/DISCUSSION-LOG.md.tmpl +49 -0
  612. package/plugins/pbr/templates/HANDOFF.json.tmpl +30 -0
  613. package/plugins/pbr/templates/INTEGRATION-REPORT.md.tmpl +18 -2
  614. package/plugins/pbr/templates/MILESTONE-AUDIT.md.tmpl +44 -0
  615. package/plugins/pbr/templates/PROJECT.md.tmpl +126 -0
  616. package/plugins/pbr/templates/REQUIREMENTS.md.tmpl +96 -0
  617. package/plugins/pbr/templates/RETROSPECTIVE.md.tmpl +43 -0
  618. package/plugins/pbr/templates/ROADMAP.md.tmpl +106 -14
  619. package/plugins/pbr/templates/SUMMARY-complex.md.tmpl +133 -0
  620. package/plugins/pbr/templates/SUMMARY-minimal.md.tmpl +55 -0
  621. package/plugins/pbr/templates/SUMMARY.md.tmpl +21 -0
  622. package/plugins/pbr/templates/UAT.md.tmpl +94 -0
  623. package/plugins/pbr/templates/UI-SPEC.md.tmpl +144 -0
  624. package/plugins/pbr/templates/VALIDATION.md.tmpl +94 -0
  625. package/plugins/pbr/templates/VERIFICATION-DETAIL.md.tmpl +54 -13
  626. package/plugins/pbr/templates/project-CONTEXT.md.tmpl +59 -0
  627. package/plugins/pbr/templates/research-outputs/ARCHITECTURE.md.tmpl +91 -0
  628. package/plugins/pbr/templates/research-outputs/FEATURES.md.tmpl +64 -0
  629. package/plugins/pbr/templates/research-outputs/PITFALLS.md.tmpl +50 -0
  630. package/plugins/pbr/templates/research-outputs/STACK.md.tmpl +63 -0
  631. package/plugins/pbr/templates/research-outputs/SUMMARY.md.tmpl +98 -0
  632. package/scripts/build-hooks.js +61 -0
  633. package/scripts/check-ci.js +100 -0
  634. package/scripts/clean-changelog.js +364 -0
  635. package/scripts/generate-derivatives.js +581 -0
  636. package/scripts/posttest.js +93 -0
  637. package/scripts/release.js +262 -0
  638. package/scripts/run-tests.cjs +29 -0
  639. package/scripts/test-wrapper.js +43 -0
  640. package/dashboard/bin/cli.js +0 -25
  641. package/dashboard/public/css/layout.css +0 -704
  642. package/dashboard/public/css/status-colors.css +0 -98
  643. package/dashboard/public/css/tokens.css +0 -59
  644. package/dashboard/public/js/htmx-title.js +0 -5
  645. package/dashboard/public/js/sidebar-toggle.js +0 -34
  646. package/dashboard/public/js/sse-client.js +0 -100
  647. package/dashboard/public/js/theme-toggle.js +0 -46
  648. package/dashboard/src/app.js +0 -91
  649. package/dashboard/src/middleware/current-phase.js +0 -24
  650. package/dashboard/src/middleware/errorHandler.js +0 -52
  651. package/dashboard/src/middleware/notFoundHandler.js +0 -9
  652. package/dashboard/src/repositories/planning.repository.js +0 -130
  653. package/dashboard/src/routes/events.routes.js +0 -45
  654. package/dashboard/src/routes/index.routes.js +0 -35
  655. package/dashboard/src/routes/pages.routes.js +0 -426
  656. package/dashboard/src/server.js +0 -42
  657. package/dashboard/src/services/analytics.service.js +0 -141
  658. package/dashboard/src/services/dashboard.service.js +0 -309
  659. package/dashboard/src/services/milestone.service.js +0 -222
  660. package/dashboard/src/services/notes.service.js +0 -50
  661. package/dashboard/src/services/phase.service.js +0 -232
  662. package/dashboard/src/services/project.service.js +0 -57
  663. package/dashboard/src/services/roadmap.service.js +0 -258
  664. package/dashboard/src/services/sse.service.js +0 -58
  665. package/dashboard/src/services/todo.service.js +0 -272
  666. package/dashboard/src/services/watcher.service.js +0 -48
  667. package/dashboard/src/utils/cache.js +0 -55
  668. package/dashboard/src/views/analytics.ejs +0 -5
  669. package/dashboard/src/views/coming-soon.ejs +0 -11
  670. package/dashboard/src/views/dependencies.ejs +0 -5
  671. package/dashboard/src/views/error.ejs +0 -20
  672. package/dashboard/src/views/index.ejs +0 -5
  673. package/dashboard/src/views/milestone-detail.ejs +0 -5
  674. package/dashboard/src/views/milestones.ejs +0 -5
  675. package/dashboard/src/views/notes.ejs +0 -5
  676. package/dashboard/src/views/partials/analytics-content.ejs +0 -90
  677. package/dashboard/src/views/partials/breadcrumbs.ejs +0 -14
  678. package/dashboard/src/views/partials/dashboard-content.ejs +0 -84
  679. package/dashboard/src/views/partials/dependencies-content.ejs +0 -48
  680. package/dashboard/src/views/partials/empty-state.ejs +0 -7
  681. package/dashboard/src/views/partials/footer.ejs +0 -3
  682. package/dashboard/src/views/partials/head.ejs +0 -30
  683. package/dashboard/src/views/partials/header.ejs +0 -21
  684. package/dashboard/src/views/partials/layout-bottom.ejs +0 -43
  685. package/dashboard/src/views/partials/layout-top.ejs +0 -16
  686. package/dashboard/src/views/partials/milestone-detail-content.ejs +0 -20
  687. package/dashboard/src/views/partials/milestones-content.ejs +0 -88
  688. package/dashboard/src/views/partials/notes-content.ejs +0 -23
  689. package/dashboard/src/views/partials/phase-content.ejs +0 -193
  690. package/dashboard/src/views/partials/phase-doc-content.ejs +0 -38
  691. package/dashboard/src/views/partials/phases-content.ejs +0 -124
  692. package/dashboard/src/views/partials/roadmap-content.ejs +0 -180
  693. package/dashboard/src/views/partials/sidebar.ejs +0 -99
  694. package/dashboard/src/views/partials/todo-create-content.ejs +0 -54
  695. package/dashboard/src/views/partials/todo-detail-content.ejs +0 -42
  696. package/dashboard/src/views/partials/todos-content.ejs +0 -97
  697. package/dashboard/src/views/phase-detail.ejs +0 -5
  698. package/dashboard/src/views/phase-doc.ejs +0 -5
  699. package/dashboard/src/views/phases.ejs +0 -5
  700. package/dashboard/src/views/roadmap.ejs +0 -5
  701. package/dashboard/src/views/todo-create.ejs +0 -5
  702. package/dashboard/src/views/todo-detail.ejs +0 -5
  703. package/dashboard/src/views/todos.ejs +0 -5
  704. package/plugins/copilot-pbr/CHANGELOG.md +0 -19
  705. package/plugins/copilot-pbr/README.md +0 -139
  706. package/plugins/copilot-pbr/agents/audit.agent.md +0 -113
  707. package/plugins/copilot-pbr/agents/codebase-mapper.agent.md +0 -151
  708. package/plugins/copilot-pbr/agents/debugger.agent.md +0 -184
  709. package/plugins/copilot-pbr/agents/executor.agent.md +0 -269
  710. package/plugins/copilot-pbr/agents/general.agent.md +0 -89
  711. package/plugins/copilot-pbr/agents/integration-checker.agent.md +0 -121
  712. package/plugins/copilot-pbr/agents/plan-checker.agent.md +0 -208
  713. package/plugins/copilot-pbr/agents/planner.agent.md +0 -240
  714. package/plugins/copilot-pbr/agents/researcher.agent.md +0 -188
  715. package/plugins/copilot-pbr/agents/synthesizer.agent.md +0 -126
  716. package/plugins/copilot-pbr/agents/verifier.agent.md +0 -228
  717. package/plugins/copilot-pbr/hooks/hooks.json +0 -258
  718. package/plugins/copilot-pbr/plugin.json +0 -30
  719. package/plugins/copilot-pbr/references/agent-anti-patterns.md +0 -25
  720. package/plugins/copilot-pbr/references/agent-contracts.md +0 -297
  721. package/plugins/copilot-pbr/references/agent-interactions.md +0 -135
  722. package/plugins/copilot-pbr/references/agent-teams.md +0 -55
  723. package/plugins/copilot-pbr/references/checkpoints.md +0 -158
  724. package/plugins/copilot-pbr/references/common-bug-patterns.md +0 -14
  725. package/plugins/copilot-pbr/references/config-reference.md +0 -442
  726. package/plugins/copilot-pbr/references/continuation-format.md +0 -213
  727. package/plugins/copilot-pbr/references/deviation-rules.md +0 -113
  728. package/plugins/copilot-pbr/references/git-integration.md +0 -227
  729. package/plugins/copilot-pbr/references/integration-patterns.md +0 -118
  730. package/plugins/copilot-pbr/references/model-profiles.md +0 -100
  731. package/plugins/copilot-pbr/references/model-selection.md +0 -32
  732. package/plugins/copilot-pbr/references/pbr-rules.md +0 -195
  733. package/plugins/copilot-pbr/references/pbr-tools-cli.md +0 -285
  734. package/plugins/copilot-pbr/references/plan-authoring.md +0 -182
  735. package/plugins/copilot-pbr/references/plan-format.md +0 -288
  736. package/plugins/copilot-pbr/references/planning-config.md +0 -214
  737. package/plugins/copilot-pbr/references/questioning.md +0 -215
  738. package/plugins/copilot-pbr/references/reading-verification.md +0 -128
  739. package/plugins/copilot-pbr/references/stub-patterns.md +0 -161
  740. package/plugins/copilot-pbr/references/subagent-coordination.md +0 -120
  741. package/plugins/copilot-pbr/references/ui-formatting.md +0 -444
  742. package/plugins/copilot-pbr/references/verification-patterns.md +0 -199
  743. package/plugins/copilot-pbr/references/wave-execution.md +0 -96
  744. package/plugins/copilot-pbr/rules/pbr-workflow.mdc +0 -48
  745. package/plugins/copilot-pbr/setup.ps1 +0 -93
  746. package/plugins/copilot-pbr/setup.sh +0 -93
  747. package/plugins/copilot-pbr/skills/audit/SKILL.md +0 -330
  748. package/plugins/copilot-pbr/skills/begin/SKILL.md +0 -589
  749. package/plugins/copilot-pbr/skills/begin/templates/PROJECT.md.tmpl +0 -34
  750. package/plugins/copilot-pbr/skills/begin/templates/REQUIREMENTS.md.tmpl +0 -19
  751. package/plugins/copilot-pbr/skills/begin/templates/STATE.md.tmpl +0 -50
  752. package/plugins/copilot-pbr/skills/begin/templates/config.json.tmpl +0 -64
  753. package/plugins/copilot-pbr/skills/begin/templates/researcher-prompt.md.tmpl +0 -20
  754. package/plugins/copilot-pbr/skills/begin/templates/roadmap-prompt.md.tmpl +0 -31
  755. package/plugins/copilot-pbr/skills/begin/templates/synthesis-prompt.md.tmpl +0 -17
  756. package/plugins/copilot-pbr/skills/build/SKILL.md +0 -959
  757. package/plugins/copilot-pbr/skills/config/SKILL.md +0 -250
  758. package/plugins/copilot-pbr/skills/continue/SKILL.md +0 -159
  759. package/plugins/copilot-pbr/skills/dashboard/SKILL.md +0 -43
  760. package/plugins/copilot-pbr/skills/debug/SKILL.md +0 -508
  761. package/plugins/copilot-pbr/skills/debug/templates/continuation-prompt.md.tmpl +0 -17
  762. package/plugins/copilot-pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +0 -28
  763. package/plugins/copilot-pbr/skills/discuss/SKILL.md +0 -353
  764. package/plugins/copilot-pbr/skills/discuss/templates/CONTEXT.md.tmpl +0 -62
  765. package/plugins/copilot-pbr/skills/discuss/templates/decision-categories.md +0 -10
  766. package/plugins/copilot-pbr/skills/do/SKILL.md +0 -66
  767. package/plugins/copilot-pbr/skills/explore/SKILL.md +0 -373
  768. package/plugins/copilot-pbr/skills/health/SKILL.md +0 -283
  769. package/plugins/copilot-pbr/skills/health/templates/check-pattern.md.tmpl +0 -31
  770. package/plugins/copilot-pbr/skills/health/templates/output-format.md.tmpl +0 -64
  771. package/plugins/copilot-pbr/skills/help/SKILL.md +0 -193
  772. package/plugins/copilot-pbr/skills/import/SKILL.md +0 -502
  773. package/plugins/copilot-pbr/skills/milestone/SKILL.md +0 -806
  774. package/plugins/copilot-pbr/skills/milestone/templates/audit-report.md.tmpl +0 -49
  775. package/plugins/copilot-pbr/skills/milestone/templates/stats-file.md.tmpl +0 -31
  776. package/plugins/copilot-pbr/skills/note/SKILL.md +0 -213
  777. package/plugins/copilot-pbr/skills/pause/SKILL.md +0 -247
  778. package/plugins/copilot-pbr/skills/pause/templates/continue-here.md.tmpl +0 -72
  779. package/plugins/copilot-pbr/skills/plan/SKILL.md +0 -662
  780. package/plugins/copilot-pbr/skills/plan/templates/checker-prompt.md.tmpl +0 -22
  781. package/plugins/copilot-pbr/skills/plan/templates/gap-closure-prompt.md.tmpl +0 -33
  782. package/plugins/copilot-pbr/skills/plan/templates/planner-prompt.md.tmpl +0 -39
  783. package/plugins/copilot-pbr/skills/plan/templates/researcher-prompt.md.tmpl +0 -20
  784. package/plugins/copilot-pbr/skills/plan/templates/revision-prompt.md.tmpl +0 -24
  785. package/plugins/copilot-pbr/skills/quick/SKILL.md +0 -376
  786. package/plugins/copilot-pbr/skills/resume/SKILL.md +0 -399
  787. package/plugins/copilot-pbr/skills/review/SKILL.md +0 -653
  788. package/plugins/copilot-pbr/skills/review/templates/debugger-prompt.md.tmpl +0 -61
  789. package/plugins/copilot-pbr/skills/review/templates/gap-planner-prompt.md.tmpl +0 -41
  790. package/plugins/copilot-pbr/skills/review/templates/verifier-prompt.md.tmpl +0 -116
  791. package/plugins/copilot-pbr/skills/scan/SKILL.md +0 -299
  792. package/plugins/copilot-pbr/skills/scan/templates/mapper-prompt.md.tmpl +0 -202
  793. package/plugins/copilot-pbr/skills/setup/SKILL.md +0 -296
  794. package/plugins/copilot-pbr/skills/shared/commit-planning-docs.md +0 -36
  795. package/plugins/copilot-pbr/skills/shared/config-loading.md +0 -103
  796. package/plugins/copilot-pbr/skills/shared/context-budget.md +0 -41
  797. package/plugins/copilot-pbr/skills/shared/context-loader-task.md +0 -87
  798. package/plugins/copilot-pbr/skills/shared/digest-select.md +0 -80
  799. package/plugins/copilot-pbr/skills/shared/domain-probes.md +0 -126
  800. package/plugins/copilot-pbr/skills/shared/error-recovery-strategies.md +0 -51
  801. package/plugins/copilot-pbr/skills/shared/error-reporting.md +0 -81
  802. package/plugins/copilot-pbr/skills/shared/gate-prompts.md +0 -389
  803. package/plugins/copilot-pbr/skills/shared/phase-argument-parsing.md +0 -46
  804. package/plugins/copilot-pbr/skills/shared/progress-display.md +0 -53
  805. package/plugins/copilot-pbr/skills/shared/revision-loop.md +0 -82
  806. package/plugins/copilot-pbr/skills/shared/state-loading.md +0 -63
  807. package/plugins/copilot-pbr/skills/shared/state-update.md +0 -170
  808. package/plugins/copilot-pbr/skills/shared/universal-anti-patterns.md +0 -38
  809. package/plugins/copilot-pbr/skills/status/SKILL.md +0 -362
  810. package/plugins/copilot-pbr/skills/statusline/SKILL.md +0 -149
  811. package/plugins/copilot-pbr/skills/todo/SKILL.md +0 -279
  812. package/plugins/copilot-pbr/templates/CONTEXT.md.tmpl +0 -53
  813. package/plugins/copilot-pbr/templates/INTEGRATION-REPORT.md.tmpl +0 -152
  814. package/plugins/copilot-pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -98
  815. package/plugins/copilot-pbr/templates/ROADMAP.md.tmpl +0 -48
  816. package/plugins/copilot-pbr/templates/SUMMARY.md.tmpl +0 -82
  817. package/plugins/copilot-pbr/templates/VERIFICATION-DETAIL.md.tmpl +0 -117
  818. package/plugins/copilot-pbr/templates/codebase/ARCHITECTURE.md.tmpl +0 -98
  819. package/plugins/copilot-pbr/templates/codebase/CONCERNS.md.tmpl +0 -93
  820. package/plugins/copilot-pbr/templates/codebase/CONVENTIONS.md.tmpl +0 -104
  821. package/plugins/copilot-pbr/templates/codebase/INTEGRATIONS.md.tmpl +0 -78
  822. package/plugins/copilot-pbr/templates/codebase/STACK.md.tmpl +0 -78
  823. package/plugins/copilot-pbr/templates/codebase/STRUCTURE.md.tmpl +0 -80
  824. package/plugins/copilot-pbr/templates/codebase/TESTING.md.tmpl +0 -107
  825. package/plugins/copilot-pbr/templates/continue-here.md.tmpl +0 -74
  826. package/plugins/copilot-pbr/templates/prompt-partials/phase-project-context.md.tmpl +0 -38
  827. package/plugins/copilot-pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
  828. package/plugins/copilot-pbr/templates/research/STACK.md.tmpl +0 -71
  829. package/plugins/copilot-pbr/templates/research/SUMMARY.md.tmpl +0 -112
  830. package/plugins/copilot-pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
  831. package/plugins/copilot-pbr/templates/research-outputs/project-research.md.tmpl +0 -99
  832. package/plugins/copilot-pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
  833. package/plugins/cursor-pbr/.cursor-plugin/plugin.json +0 -32
  834. package/plugins/cursor-pbr/CHANGELOG.md +0 -15
  835. package/plugins/cursor-pbr/README.md +0 -123
  836. package/plugins/cursor-pbr/agents/audit.md +0 -178
  837. package/plugins/cursor-pbr/agents/codebase-mapper.md +0 -150
  838. package/plugins/cursor-pbr/agents/debugger.md +0 -183
  839. package/plugins/cursor-pbr/agents/executor.md +0 -268
  840. package/plugins/cursor-pbr/agents/general.md +0 -88
  841. package/plugins/cursor-pbr/agents/integration-checker.md +0 -120
  842. package/plugins/cursor-pbr/agents/plan-checker.md +0 -207
  843. package/plugins/cursor-pbr/agents/planner.md +0 -239
  844. package/plugins/cursor-pbr/agents/researcher.md +0 -187
  845. package/plugins/cursor-pbr/agents/synthesizer.md +0 -125
  846. package/plugins/cursor-pbr/agents/verifier.md +0 -227
  847. package/plugins/cursor-pbr/assets/.gitkeep +0 -0
  848. package/plugins/cursor-pbr/assets/logo.svg +0 -21
  849. package/plugins/cursor-pbr/hooks/hooks.json +0 -224
  850. package/plugins/cursor-pbr/references/agent-anti-patterns.md +0 -25
  851. package/plugins/cursor-pbr/references/agent-contracts.md +0 -297
  852. package/plugins/cursor-pbr/references/agent-interactions.md +0 -135
  853. package/plugins/cursor-pbr/references/agent-teams.md +0 -55
  854. package/plugins/cursor-pbr/references/checkpoints.md +0 -158
  855. package/plugins/cursor-pbr/references/common-bug-patterns.md +0 -14
  856. package/plugins/cursor-pbr/references/config-reference.md +0 -442
  857. package/plugins/cursor-pbr/references/continuation-format.md +0 -213
  858. package/plugins/cursor-pbr/references/deviation-rules.md +0 -113
  859. package/plugins/cursor-pbr/references/git-integration.md +0 -227
  860. package/plugins/cursor-pbr/references/integration-patterns.md +0 -118
  861. package/plugins/cursor-pbr/references/model-profiles.md +0 -100
  862. package/plugins/cursor-pbr/references/model-selection.md +0 -32
  863. package/plugins/cursor-pbr/references/pbr-rules.md +0 -195
  864. package/plugins/cursor-pbr/references/pbr-tools-cli.md +0 -285
  865. package/plugins/cursor-pbr/references/plan-authoring.md +0 -182
  866. package/plugins/cursor-pbr/references/plan-format.md +0 -288
  867. package/plugins/cursor-pbr/references/planning-config.md +0 -214
  868. package/plugins/cursor-pbr/references/questioning.md +0 -215
  869. package/plugins/cursor-pbr/references/reading-verification.md +0 -128
  870. package/plugins/cursor-pbr/references/stub-patterns.md +0 -161
  871. package/plugins/cursor-pbr/references/subagent-coordination.md +0 -120
  872. package/plugins/cursor-pbr/references/ui-formatting.md +0 -444
  873. package/plugins/cursor-pbr/references/verification-patterns.md +0 -199
  874. package/plugins/cursor-pbr/references/wave-execution.md +0 -96
  875. package/plugins/cursor-pbr/rules/pbr-workflow.mdc +0 -48
  876. package/plugins/cursor-pbr/setup.ps1 +0 -78
  877. package/plugins/cursor-pbr/setup.sh +0 -83
  878. package/plugins/cursor-pbr/skills/audit/SKILL.md +0 -331
  879. package/plugins/cursor-pbr/skills/begin/SKILL.md +0 -589
  880. package/plugins/cursor-pbr/skills/begin/templates/PROJECT.md.tmpl +0 -34
  881. package/plugins/cursor-pbr/skills/begin/templates/REQUIREMENTS.md.tmpl +0 -19
  882. package/plugins/cursor-pbr/skills/begin/templates/STATE.md.tmpl +0 -50
  883. package/plugins/cursor-pbr/skills/begin/templates/config.json.tmpl +0 -64
  884. package/plugins/cursor-pbr/skills/begin/templates/researcher-prompt.md.tmpl +0 -20
  885. package/plugins/cursor-pbr/skills/begin/templates/roadmap-prompt.md.tmpl +0 -31
  886. package/plugins/cursor-pbr/skills/begin/templates/synthesis-prompt.md.tmpl +0 -17
  887. package/plugins/cursor-pbr/skills/build/SKILL.md +0 -960
  888. package/plugins/cursor-pbr/skills/config/SKILL.md +0 -252
  889. package/plugins/cursor-pbr/skills/continue/SKILL.md +0 -159
  890. package/plugins/cursor-pbr/skills/dashboard/SKILL.md +0 -44
  891. package/plugins/cursor-pbr/skills/debug/SKILL.md +0 -512
  892. package/plugins/cursor-pbr/skills/debug/templates/continuation-prompt.md.tmpl +0 -17
  893. package/plugins/cursor-pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +0 -28
  894. package/plugins/cursor-pbr/skills/discuss/SKILL.md +0 -354
  895. package/plugins/cursor-pbr/skills/discuss/templates/CONTEXT.md.tmpl +0 -62
  896. package/plugins/cursor-pbr/skills/discuss/templates/decision-categories.md +0 -10
  897. package/plugins/cursor-pbr/skills/do/SKILL.md +0 -67
  898. package/plugins/cursor-pbr/skills/explore/SKILL.md +0 -376
  899. package/plugins/cursor-pbr/skills/health/SKILL.md +0 -283
  900. package/plugins/cursor-pbr/skills/health/templates/check-pattern.md.tmpl +0 -31
  901. package/plugins/cursor-pbr/skills/health/templates/output-format.md.tmpl +0 -64
  902. package/plugins/cursor-pbr/skills/help/SKILL.md +0 -193
  903. package/plugins/cursor-pbr/skills/import/SKILL.md +0 -505
  904. package/plugins/cursor-pbr/skills/milestone/SKILL.md +0 -807
  905. package/plugins/cursor-pbr/skills/milestone/templates/audit-report.md.tmpl +0 -49
  906. package/plugins/cursor-pbr/skills/milestone/templates/stats-file.md.tmpl +0 -31
  907. package/plugins/cursor-pbr/skills/note/SKILL.md +0 -214
  908. package/plugins/cursor-pbr/skills/pause/SKILL.md +0 -248
  909. package/plugins/cursor-pbr/skills/pause/templates/continue-here.md.tmpl +0 -72
  910. package/plugins/cursor-pbr/skills/plan/SKILL.md +0 -663
  911. package/plugins/cursor-pbr/skills/plan/templates/checker-prompt.md.tmpl +0 -22
  912. package/plugins/cursor-pbr/skills/plan/templates/gap-closure-prompt.md.tmpl +0 -33
  913. package/plugins/cursor-pbr/skills/plan/templates/planner-prompt.md.tmpl +0 -39
  914. package/plugins/cursor-pbr/skills/plan/templates/researcher-prompt.md.tmpl +0 -20
  915. package/plugins/cursor-pbr/skills/plan/templates/revision-prompt.md.tmpl +0 -24
  916. package/plugins/cursor-pbr/skills/quick/SKILL.md +0 -376
  917. package/plugins/cursor-pbr/skills/resume/SKILL.md +0 -399
  918. package/plugins/cursor-pbr/skills/review/SKILL.md +0 -654
  919. package/plugins/cursor-pbr/skills/review/templates/debugger-prompt.md.tmpl +0 -61
  920. package/plugins/cursor-pbr/skills/review/templates/gap-planner-prompt.md.tmpl +0 -41
  921. package/plugins/cursor-pbr/skills/review/templates/verifier-prompt.md.tmpl +0 -116
  922. package/plugins/cursor-pbr/skills/scan/SKILL.md +0 -300
  923. package/plugins/cursor-pbr/skills/scan/templates/mapper-prompt.md.tmpl +0 -202
  924. package/plugins/cursor-pbr/skills/setup/SKILL.md +0 -296
  925. package/plugins/cursor-pbr/skills/shared/commit-planning-docs.md +0 -36
  926. package/plugins/cursor-pbr/skills/shared/config-loading.md +0 -103
  927. package/plugins/cursor-pbr/skills/shared/context-budget.md +0 -41
  928. package/plugins/cursor-pbr/skills/shared/context-loader-task.md +0 -87
  929. package/plugins/cursor-pbr/skills/shared/digest-select.md +0 -80
  930. package/plugins/cursor-pbr/skills/shared/domain-probes.md +0 -126
  931. package/plugins/cursor-pbr/skills/shared/error-recovery-strategies.md +0 -51
  932. package/plugins/cursor-pbr/skills/shared/error-reporting.md +0 -81
  933. package/plugins/cursor-pbr/skills/shared/gate-prompts.md +0 -389
  934. package/plugins/cursor-pbr/skills/shared/phase-argument-parsing.md +0 -46
  935. package/plugins/cursor-pbr/skills/shared/progress-display.md +0 -53
  936. package/plugins/cursor-pbr/skills/shared/revision-loop.md +0 -82
  937. package/plugins/cursor-pbr/skills/shared/state-loading.md +0 -63
  938. package/plugins/cursor-pbr/skills/shared/state-update.md +0 -170
  939. package/plugins/cursor-pbr/skills/shared/universal-anti-patterns.md +0 -38
  940. package/plugins/cursor-pbr/skills/status/SKILL.md +0 -362
  941. package/plugins/cursor-pbr/skills/statusline/SKILL.md +0 -150
  942. package/plugins/cursor-pbr/skills/todo/SKILL.md +0 -280
  943. package/plugins/cursor-pbr/templates/CONTEXT.md.tmpl +0 -53
  944. package/plugins/cursor-pbr/templates/INTEGRATION-REPORT.md.tmpl +0 -152
  945. package/plugins/cursor-pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -98
  946. package/plugins/cursor-pbr/templates/ROADMAP.md.tmpl +0 -48
  947. package/plugins/cursor-pbr/templates/SUMMARY.md.tmpl +0 -82
  948. package/plugins/cursor-pbr/templates/VERIFICATION-DETAIL.md.tmpl +0 -117
  949. package/plugins/cursor-pbr/templates/codebase/ARCHITECTURE.md.tmpl +0 -98
  950. package/plugins/cursor-pbr/templates/codebase/CONCERNS.md.tmpl +0 -93
  951. package/plugins/cursor-pbr/templates/codebase/CONVENTIONS.md.tmpl +0 -104
  952. package/plugins/cursor-pbr/templates/codebase/INTEGRATIONS.md.tmpl +0 -78
  953. package/plugins/cursor-pbr/templates/codebase/STACK.md.tmpl +0 -78
  954. package/plugins/cursor-pbr/templates/codebase/STRUCTURE.md.tmpl +0 -80
  955. package/plugins/cursor-pbr/templates/codebase/TESTING.md.tmpl +0 -107
  956. package/plugins/cursor-pbr/templates/continue-here.md.tmpl +0 -74
  957. package/plugins/cursor-pbr/templates/prompt-partials/phase-project-context.md.tmpl +0 -38
  958. package/plugins/cursor-pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
  959. package/plugins/cursor-pbr/templates/research/STACK.md.tmpl +0 -71
  960. package/plugins/cursor-pbr/templates/research/SUMMARY.md.tmpl +0 -112
  961. package/plugins/cursor-pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
  962. package/plugins/cursor-pbr/templates/research-outputs/project-research.md.tmpl +0 -99
  963. package/plugins/cursor-pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
  964. package/plugins/pbr/references/agent-interactions.md +0 -134
  965. package/plugins/pbr/references/pbr-rules.md +0 -194
  966. package/plugins/pbr/references/pbr-tools-cli.md +0 -285
  967. package/plugins/pbr/references/planning-config.md +0 -213
  968. package/plugins/pbr/references/subagent-coordination.md +0 -119
  969. package/plugins/pbr/references/ui-formatting.md +0 -444
  970. package/plugins/pbr/scripts/validate-plugin-structure.js +0 -183
  971. package/plugins/pbr/skills/milestone/templates/audit-report.md.tmpl +0 -48
  972. package/plugins/pbr/skills/shared/error-recovery-strategies.md +0 -51
  973. package/plugins/pbr/skills/shared/progress-display.md +0 -53
  974. package/plugins/pbr/skills/shared/state-loading.md +0 -62
  975. package/plugins/pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -97
  976. package/plugins/pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
  977. package/plugins/pbr/templates/research/STACK.md.tmpl +0 -71
  978. package/plugins/pbr/templates/research/SUMMARY.md.tmpl +0 -112
  979. package/plugins/pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
  980. package/plugins/pbr/templates/research-outputs/project-research.md.tmpl +0 -99
  981. package/plugins/pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
  982. /package/plugins/pbr/references/{agent-anti-patterns.md → archive/agent-anti-patterns.md} +0 -0
@@ -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
+ };