@sienklogic/plan-build-run 2.11.0 → 2.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1222) hide show
  1. package/CHANGELOG.md +1102 -220
  2. package/CLAUDE.md +54 -34
  3. package/LICENSE +2 -1
  4. package/README.md +261 -182
  5. package/agents/pbr-audit.md +266 -0
  6. package/agents/pbr-codebase-mapper.md +236 -0
  7. package/agents/pbr-debugger.md +312 -0
  8. package/agents/pbr-dev-sync.md +220 -0
  9. package/agents/pbr-executor.md +591 -0
  10. package/agents/pbr-general.md +191 -0
  11. package/agents/pbr-integration-checker.md +237 -0
  12. package/agents/pbr-intel-updater.md +296 -0
  13. package/agents/pbr-nyquist-auditor.md +252 -0
  14. package/agents/pbr-plan-checker.md +312 -0
  15. package/agents/pbr-planner.md +539 -0
  16. package/agents/pbr-researcher.md +314 -0
  17. package/agents/pbr-roadmapper.md +346 -0
  18. package/agents/pbr-synthesizer.md +271 -0
  19. package/agents/pbr-ui-checker.md +202 -0
  20. package/agents/pbr-ui-researcher.md +223 -0
  21. package/agents/pbr-verifier.md +495 -0
  22. package/bin/install.js +2752 -0
  23. package/commands/pbr/add-phase.md +75 -0
  24. package/commands/pbr/add-todo.md +8 -0
  25. package/commands/pbr/audit-milestone.md +8 -0
  26. package/commands/pbr/audit.md +5 -0
  27. package/commands/pbr/autonomous.md +5 -0
  28. package/commands/pbr/begin.md +5 -0
  29. package/commands/pbr/build.md +5 -0
  30. package/commands/pbr/check-todos.md +8 -0
  31. package/commands/pbr/complete-milestone.md +8 -0
  32. package/commands/pbr/config.md +5 -0
  33. package/commands/pbr/continue.md +5 -0
  34. package/commands/pbr/dashboard.md +5 -0
  35. package/commands/pbr/debug.md +5 -0
  36. package/commands/pbr/discuss-phase.md +6 -0
  37. package/commands/pbr/discuss.md +5 -0
  38. package/commands/pbr/do.md +5 -0
  39. package/commands/pbr/execute-phase.md +6 -0
  40. package/commands/pbr/explore.md +5 -0
  41. package/commands/pbr/health.md +5 -0
  42. package/commands/pbr/help.md +5 -0
  43. package/commands/pbr/import.md +5 -0
  44. package/commands/pbr/insert-phase.md +65 -0
  45. package/commands/pbr/intel.md +5 -0
  46. package/commands/pbr/join-discord.md +11 -0
  47. package/commands/pbr/list-phase-assumptions.md +69 -0
  48. package/commands/pbr/map-codebase.md +6 -0
  49. package/commands/pbr/milestone.md +5 -0
  50. package/commands/pbr/new-milestone.md +8 -0
  51. package/commands/pbr/new-project.md +6 -0
  52. package/commands/pbr/note.md +5 -0
  53. package/commands/pbr/pause-work.md +5 -0
  54. package/commands/pbr/pause.md +5 -0
  55. package/commands/pbr/plan-milestone-gaps.md +7 -0
  56. package/commands/pbr/plan-phase.md +6 -0
  57. package/commands/pbr/plan.md +5 -0
  58. package/commands/pbr/profile-user.md +5 -0
  59. package/commands/pbr/profile.md +5 -0
  60. package/commands/pbr/progress.md +6 -0
  61. package/commands/pbr/quick.md +5 -0
  62. package/commands/pbr/reapply-patches.md +47 -0
  63. package/commands/pbr/release.md +6 -0
  64. package/commands/pbr/remove-phase.md +66 -0
  65. package/commands/pbr/research-phase.md +59 -0
  66. package/commands/pbr/resume-work.md +5 -0
  67. package/commands/pbr/resume.md +5 -0
  68. package/commands/pbr/review.md +5 -0
  69. package/commands/pbr/scan.md +5 -0
  70. package/commands/pbr/session-report.md +5 -0
  71. package/commands/pbr/set-profile.md +6 -0
  72. package/commands/pbr/settings.md +5 -0
  73. package/commands/pbr/setup.md +5 -0
  74. package/commands/pbr/ship.md +5 -0
  75. package/commands/pbr/status.md +5 -0
  76. package/commands/pbr/statusline.md +5 -0
  77. package/commands/pbr/test.md +5 -0
  78. package/commands/pbr/todo.md +5 -0
  79. package/commands/pbr/ui-phase.md +5 -0
  80. package/commands/pbr/ui-review.md +5 -0
  81. package/commands/pbr/undo.md +5 -0
  82. package/commands/pbr/update.md +37 -0
  83. package/commands/pbr/validate-phase.md +5 -0
  84. package/commands/pbr/verify-work.md +6 -0
  85. package/dashboard/bin/cli.cjs +96 -0
  86. package/dashboard/bin/stop.cjs +129 -0
  87. package/dashboard/eslint.config.js +37 -0
  88. package/dashboard/index.html +20 -0
  89. package/dashboard/package.json +28 -23
  90. package/dashboard/server/index.js +136 -0
  91. package/dashboard/server/lib/frontmatter.js +92 -0
  92. package/dashboard/server/middleware/static.js +35 -0
  93. package/dashboard/server/package.json +16 -0
  94. package/dashboard/server/routes/agents.js +213 -0
  95. package/dashboard/server/routes/config.js +64 -0
  96. package/dashboard/server/routes/health.js +95 -0
  97. package/dashboard/server/routes/memory.js +107 -0
  98. package/dashboard/server/routes/planning.js +234 -0
  99. package/dashboard/server/routes/progress.js +77 -0
  100. package/dashboard/server/routes/projects.js +36 -0
  101. package/dashboard/server/routes/requirements.js +40 -0
  102. package/dashboard/server/routes/roadmap.js +69 -0
  103. package/dashboard/server/routes/status.js +25 -0
  104. package/dashboard/server/routes/telemetry.js +171 -0
  105. package/dashboard/server/services/file-watcher.js +105 -0
  106. package/dashboard/server/services/planning-reader.js +741 -0
  107. package/dashboard/server/test/cli.test.js +34 -0
  108. package/dashboard/server/test/frontmatter.test.js +104 -0
  109. package/dashboard/server/test/isolation.test.js +32 -0
  110. package/dashboard/server/test/planning-reader.test.js +151 -0
  111. package/dashboard/server/test/routes.test.js +91 -0
  112. package/dashboard/server/test/ws.test.js +81 -0
  113. package/dashboard/server/ws.js +96 -0
  114. package/dashboard/src/App.jsx +154 -0
  115. package/dashboard/src/components/charts/BudgetBars.jsx +42 -0
  116. package/dashboard/src/components/charts/ContextRadar.jsx +34 -0
  117. package/dashboard/src/components/charts/PhaseDonut.jsx +66 -0
  118. package/dashboard/src/components/charts/SuccessTrend.jsx +45 -0
  119. package/dashboard/src/components/charts/TokenChart.jsx +55 -0
  120. package/dashboard/src/components/charts/index.js +5 -0
  121. package/dashboard/src/components/config/CfgSection.jsx +93 -0
  122. package/dashboard/src/components/layout/Header.jsx +89 -0
  123. package/dashboard/src/components/layout/ProjectSwitcher.jsx +160 -0
  124. package/dashboard/src/components/layout/Sidebar.jsx +161 -0
  125. package/dashboard/src/components/ui/AutoModeBanner.jsx +138 -0
  126. package/dashboard/src/components/ui/BackButton.jsx +27 -0
  127. package/dashboard/src/components/ui/Badge.jsx +27 -0
  128. package/dashboard/src/components/ui/Card.jsx +23 -0
  129. package/dashboard/src/components/ui/ChartTooltip.jsx +48 -0
  130. package/dashboard/src/components/ui/CheckpointBox.jsx +110 -0
  131. package/dashboard/src/components/ui/CodeBlock.jsx +27 -0
  132. package/dashboard/src/components/ui/ConfidenceBadge.jsx +20 -0
  133. package/dashboard/src/components/ui/ConfirmModal.jsx +161 -0
  134. package/dashboard/src/components/ui/ConnectionBanner.jsx +60 -0
  135. package/dashboard/src/components/ui/ErrorBoundary.jsx +106 -0
  136. package/dashboard/src/components/ui/ErrorBox.jsx +107 -0
  137. package/dashboard/src/components/ui/KeyValue.jsx +33 -0
  138. package/dashboard/src/components/ui/LoadingSkeleton.jsx +84 -0
  139. package/dashboard/src/components/ui/MetricCard.jsx +58 -0
  140. package/dashboard/src/components/ui/NextUpBlock.jsx +92 -0
  141. package/dashboard/src/components/ui/NumberInput.jsx +44 -0
  142. package/dashboard/src/components/ui/PBRBanner.jsx +47 -0
  143. package/dashboard/src/components/ui/PipelineView.jsx +130 -0
  144. package/dashboard/src/components/ui/ProgressBar.jsx +28 -0
  145. package/dashboard/src/components/ui/ProgressDisplay.jsx +47 -0
  146. package/dashboard/src/components/ui/QualityGateBadge.jsx +15 -0
  147. package/dashboard/src/components/ui/SectionTitle.jsx +35 -0
  148. package/dashboard/src/components/ui/SelectInput.jsx +45 -0
  149. package/dashboard/src/components/ui/StatusDot.jsx +51 -0
  150. package/dashboard/src/components/ui/StatusSymbol.jsx +49 -0
  151. package/dashboard/src/components/ui/TabBar.jsx +41 -0
  152. package/dashboard/src/components/ui/TextInput.jsx +42 -0
  153. package/dashboard/src/components/ui/Toast.jsx +117 -0
  154. package/dashboard/src/components/ui/Toggle.jsx +70 -0
  155. package/dashboard/src/components/ui/index.js +29 -0
  156. package/dashboard/src/hooks/useDocumentTitle.js +16 -0
  157. package/dashboard/src/hooks/useFetch.js +50 -0
  158. package/dashboard/src/hooks/useToast.jsx +43 -0
  159. package/dashboard/src/hooks/useWebSocket.js +103 -0
  160. package/dashboard/src/lib/api.js +112 -0
  161. package/dashboard/src/lib/configSchema.js +189 -0
  162. package/dashboard/src/lib/constants.js +18 -0
  163. package/dashboard/src/main.jsx +15 -0
  164. package/dashboard/src/pages/AgentsPage.jsx +191 -0
  165. package/dashboard/src/pages/ConfigPage.jsx +298 -0
  166. package/dashboard/src/pages/HooksPage.jsx +412 -0
  167. package/dashboard/src/pages/LiveFeed.jsx +274 -0
  168. package/dashboard/src/pages/MemoryPage.jsx +107 -0
  169. package/dashboard/src/pages/OnboardingPage.jsx +117 -0
  170. package/dashboard/src/pages/Overview.jsx +360 -0
  171. package/dashboard/src/pages/PhaseDetailView.jsx +216 -0
  172. package/dashboard/src/pages/PlanningPage.jsx +181 -0
  173. package/dashboard/src/pages/ProgressPage.jsx +249 -0
  174. package/dashboard/src/pages/RoadmapPage.jsx +251 -0
  175. package/dashboard/src/pages/Telemetry.jsx +113 -0
  176. package/dashboard/src/pages/planning/DecisionsTab.jsx +153 -0
  177. package/dashboard/src/pages/planning/FilesTab.jsx +420 -0
  178. package/dashboard/src/pages/planning/MilestoneDetail.jsx +319 -0
  179. package/dashboard/src/pages/planning/MilestonesTab.jsx +151 -0
  180. package/dashboard/src/pages/planning/NotesTab.jsx +251 -0
  181. package/dashboard/src/pages/planning/PhasesTab.jsx +218 -0
  182. package/dashboard/src/pages/planning/QuickTab.jsx +50 -0
  183. package/dashboard/src/pages/planning/ResearchTab.jsx +103 -0
  184. package/dashboard/src/pages/planning/TodosTab.jsx +297 -0
  185. package/dashboard/src/theme/ThemeProvider.jsx +38 -0
  186. package/dashboard/src/theme/tokens.js +17 -0
  187. package/dashboard/tests/components/ConfirmModal.test.jsx +179 -0
  188. package/dashboard/tests/components/ConnectionBanner.test.jsx +37 -0
  189. package/dashboard/tests/components/ErrorBoundary.test.jsx +59 -0
  190. package/dashboard/tests/components/LoadingSkeleton.test.jsx +46 -0
  191. package/dashboard/tests/components/ToastContainer.test.jsx +47 -0
  192. package/dashboard/tests/components/Toggle.test.jsx +61 -0
  193. package/dashboard/tests/hooks/useFetch.test.jsx +77 -0
  194. package/dashboard/tests/hooks/useToast.test.jsx +78 -0
  195. package/dashboard/tests/hooks/useWebSocket.test.jsx +128 -0
  196. package/dashboard/tests/pages/ConfigPage.test.jsx +199 -0
  197. package/dashboard/tests/pages/PlanningPage.test.jsx +119 -0
  198. package/dashboard/tests/pages/planning/FilesTab.test.jsx +198 -0
  199. package/dashboard/tests/pages/planning/NotesTab.test.jsx +178 -0
  200. package/dashboard/tests/pages/planning/TodosTab.test.jsx +188 -0
  201. package/dashboard/tests/performance.test.jsx +46 -0
  202. package/dashboard/tests/routes/config.test.js +98 -0
  203. package/dashboard/tests/routes/health.test.js +40 -0
  204. package/dashboard/tests/routes/planning.test.js +112 -0
  205. package/dashboard/tests/routes/roadmap.test.js +91 -0
  206. package/dashboard/tests/routes/status.test.js +131 -0
  207. package/dashboard/tests/server/planning-reader.test.js +153 -0
  208. package/dashboard/tests/setup.js +7 -0
  209. package/dashboard/vite.config.js +41 -0
  210. package/hooks/dist/auto-continue.js +277 -0
  211. package/hooks/dist/block-skill-self-read.js +80 -0
  212. package/hooks/dist/check-agent-state-write.js +63 -0
  213. package/hooks/dist/check-config-change.js +188 -0
  214. package/hooks/dist/check-dangerous-commands.js +185 -0
  215. package/hooks/dist/check-doc-sprawl.js +102 -0
  216. package/hooks/dist/check-phase-boundary.js +191 -0
  217. package/hooks/dist/check-plan-format.js +227 -0
  218. package/hooks/dist/check-roadmap-sync.js +503 -0
  219. package/hooks/dist/check-skill-workflow.js +354 -0
  220. package/hooks/dist/check-state-sync.js +637 -0
  221. package/hooks/dist/check-subagent-output.js +401 -0
  222. package/hooks/dist/check-summary-gate.js +199 -0
  223. package/hooks/dist/context-bridge.js +406 -0
  224. package/hooks/dist/context-budget-check.js +442 -0
  225. package/hooks/dist/context-quality.js +271 -0
  226. package/hooks/dist/enforce-pbr-workflow.js +277 -0
  227. package/hooks/dist/event-handler.js +203 -0
  228. package/hooks/dist/event-logger.js +125 -0
  229. package/hooks/dist/hook-logger.js +112 -0
  230. package/hooks/dist/hook-server-client.js +342 -0
  231. package/hooks/dist/hook-server.js +352 -0
  232. package/hooks/dist/hooks-schema.json +85 -0
  233. package/hooks/dist/hooks.json +309 -0
  234. package/hooks/dist/instructions-loaded.js +107 -0
  235. package/hooks/dist/intel-queue.js +152 -0
  236. package/hooks/dist/intercept-plan-mode.js +50 -0
  237. package/hooks/dist/log-notification.js +125 -0
  238. package/hooks/dist/log-subagent.js +306 -0
  239. package/hooks/dist/log-tool-failure.js +140 -0
  240. package/hooks/dist/milestone-learnings.js +569 -0
  241. package/hooks/dist/pbr-tools.js +5 -0
  242. package/hooks/dist/post-bash-triage.js +152 -0
  243. package/hooks/dist/post-compact.js +135 -0
  244. package/hooks/dist/post-write-dispatch.js +277 -0
  245. package/hooks/dist/post-write-quality.js +208 -0
  246. package/hooks/dist/pre-bash-dispatch.js +158 -0
  247. package/hooks/dist/pre-write-dispatch.js +165 -0
  248. package/hooks/dist/progress-tracker.js +198 -0
  249. package/hooks/dist/prompt-routing.js +209 -0
  250. package/hooks/dist/run-hook.js +144 -0
  251. package/hooks/dist/session-cleanup.js +617 -0
  252. package/hooks/dist/session-tracker.js +124 -0
  253. package/hooks/dist/status-line.js +793 -0
  254. package/hooks/dist/suggest-compact.js +296 -0
  255. package/hooks/dist/sync-context-to-claude.js +100 -0
  256. package/hooks/dist/task-completed.js +206 -0
  257. package/hooks/dist/track-context-budget.js +405 -0
  258. package/hooks/dist/trust-tracker.js +193 -0
  259. package/hooks/dist/validate-commit.js +270 -0
  260. package/hooks/dist/validate-skill-args.js +222 -0
  261. package/hooks/dist/validate-task.js +272 -0
  262. package/hooks/dist/worktree-create.js +144 -0
  263. package/hooks/dist/worktree-remove.js +147 -0
  264. package/package.json +59 -40
  265. package/plan-build-run/bin/config-schema.json +1416 -0
  266. package/plan-build-run/bin/dashboard-launch.cjs +114 -0
  267. package/plan-build-run/bin/event-logger.cjs +92 -0
  268. package/plan-build-run/bin/lib/alternatives.cjs +198 -0
  269. package/plan-build-run/bin/lib/auto-cleanup.cjs +7 -0
  270. package/plan-build-run/bin/lib/build.cjs +717 -0
  271. package/plan-build-run/bin/lib/circuit-state.cjs +133 -0
  272. package/plan-build-run/bin/lib/commands.cjs +482 -0
  273. package/plan-build-run/bin/lib/config.cjs +770 -0
  274. package/plan-build-run/bin/lib/context.cjs +216 -0
  275. package/plan-build-run/bin/lib/contextual-help.cjs +207 -0
  276. package/plan-build-run/bin/lib/core.cjs +1563 -0
  277. package/plan-build-run/bin/lib/decisions.cjs +194 -0
  278. package/plan-build-run/bin/lib/frontmatter.cjs +299 -0
  279. package/plan-build-run/bin/lib/gates/advisories.cjs +129 -0
  280. package/plan-build-run/bin/lib/gates/build-dependency.cjs +115 -0
  281. package/plan-build-run/bin/lib/gates/build-executor.cjs +104 -0
  282. package/plan-build-run/bin/lib/gates/doc-existence.cjs +46 -0
  283. package/plan-build-run/bin/lib/gates/helpers.cjs +93 -0
  284. package/plan-build-run/bin/lib/gates/inline-execution.cjs +185 -0
  285. package/plan-build-run/bin/lib/gates/milestone-complete.cjs +136 -0
  286. package/plan-build-run/bin/lib/gates/milestone-summary.cjs +119 -0
  287. package/plan-build-run/bin/lib/gates/plan-executor.cjs +36 -0
  288. package/plan-build-run/bin/lib/gates/quick-executor.cjs +76 -0
  289. package/plan-build-run/bin/lib/gates/review-planner.cjs +61 -0
  290. package/plan-build-run/bin/lib/gates/review-verifier.cjs +69 -0
  291. package/plan-build-run/bin/lib/graph-cli.cjs +89 -0
  292. package/plan-build-run/bin/lib/graph.cjs +554 -0
  293. package/plan-build-run/bin/lib/health-phase06.cjs +120 -0
  294. package/plan-build-run/bin/lib/health.cjs +133 -0
  295. package/plan-build-run/bin/lib/history.cjs +147 -0
  296. package/plan-build-run/bin/lib/hypothesis-runner.cjs +127 -0
  297. package/plan-build-run/bin/lib/impact-analysis.cjs +319 -0
  298. package/plan-build-run/bin/lib/incidents.cjs +190 -0
  299. package/plan-build-run/bin/lib/init.cjs +367 -0
  300. package/plan-build-run/bin/lib/intel.cjs +653 -0
  301. package/plan-build-run/bin/lib/learnings.cjs +511 -0
  302. package/plan-build-run/bin/lib/local-llm/health.cjs +12 -0
  303. package/plan-build-run/bin/lib/local-llm/index.cjs +89 -0
  304. package/plan-build-run/bin/lib/local-llm/metrics.cjs +20 -0
  305. package/plan-build-run/bin/lib/local-llm/operations/classify-artifact.cjs +4 -0
  306. package/plan-build-run/bin/lib/local-llm/operations/classify-commit.cjs +4 -0
  307. package/plan-build-run/bin/lib/local-llm/operations/classify-error.cjs +4 -0
  308. package/plan-build-run/bin/lib/local-llm/operations/classify-file-intent.cjs +4 -0
  309. package/plan-build-run/bin/lib/local-llm/operations/triage-test-output.cjs +12 -0
  310. package/plan-build-run/bin/lib/local-llm/operations/validate-task.cjs +4 -0
  311. package/plan-build-run/bin/lib/migrate.cjs +298 -0
  312. package/plan-build-run/bin/lib/milestone.cjs +306 -0
  313. package/plan-build-run/bin/lib/negative-knowledge.cjs +194 -0
  314. package/plan-build-run/bin/lib/onboarding-generator.cjs +288 -0
  315. package/plan-build-run/bin/lib/parse-args.cjs +134 -0
  316. package/plan-build-run/bin/lib/patterns.cjs +272 -0
  317. package/plan-build-run/bin/lib/phase.cjs +1021 -0
  318. package/plan-build-run/bin/lib/post-hoc.cjs +160 -0
  319. package/plan-build-run/bin/lib/preview.cjs +174 -0
  320. package/plan-build-run/bin/lib/progress-visualization.cjs +296 -0
  321. package/plan-build-run/bin/lib/quick-init.cjs +131 -0
  322. package/plan-build-run/bin/lib/reference.cjs +234 -0
  323. package/plan-build-run/bin/lib/requirements.cjs +153 -0
  324. package/plan-build-run/bin/lib/reverse-spec.cjs +259 -0
  325. package/plan-build-run/bin/lib/roadmap.cjs +1097 -0
  326. package/plan-build-run/bin/lib/security-scan.cjs +200 -0
  327. package/plan-build-run/bin/lib/skill-section.cjs +98 -0
  328. package/plan-build-run/bin/lib/spec-diff.cjs +209 -0
  329. package/plan-build-run/bin/lib/spec-engine.cjs +189 -0
  330. package/plan-build-run/bin/lib/spot-check.cjs +510 -0
  331. package/plan-build-run/bin/lib/state.cjs +1050 -0
  332. package/plan-build-run/bin/lib/status-render.cjs +527 -0
  333. package/plan-build-run/bin/lib/step-verify.cjs +149 -0
  334. package/plan-build-run/bin/lib/suggest-next.cjs +316 -0
  335. package/plan-build-run/bin/lib/team-composer.cjs +85 -0
  336. package/plan-build-run/bin/lib/team-coordinator.cjs +151 -0
  337. package/plan-build-run/bin/lib/template.cjs +222 -0
  338. package/plan-build-run/bin/lib/templates.cjs +362 -0
  339. package/plan-build-run/bin/lib/test-selection.cjs +163 -0
  340. package/plan-build-run/bin/lib/todo.cjs +300 -0
  341. package/plan-build-run/bin/lib/validation.cjs +187 -0
  342. package/plan-build-run/bin/lib/verify.cjs +1451 -0
  343. package/plan-build-run/bin/pbr-tools.cjs +1877 -0
  344. package/plan-build-run/references/CLAUDE.md +7 -0
  345. package/plan-build-run/references/agent-contracts.md +326 -0
  346. package/plan-build-run/references/agent-teams.md +54 -0
  347. package/plan-build-run/references/behavioral-contexts.md +53 -0
  348. package/plan-build-run/references/checkpoints.md +776 -0
  349. package/plan-build-run/references/config-reference.md +613 -0
  350. package/plan-build-run/references/continuation-format.md +249 -0
  351. package/plan-build-run/references/debugging/CLAUDE.md +7 -0
  352. package/plan-build-run/references/decimal-phase-calculation.md +65 -0
  353. package/plan-build-run/references/git-integration.md +309 -0
  354. package/plan-build-run/references/git-planning-commit.md +38 -0
  355. package/plan-build-run/references/model-profile-resolution.md +34 -0
  356. package/plan-build-run/references/model-profiles.md +182 -0
  357. package/plan-build-run/references/model-selection.md +53 -0
  358. package/plan-build-run/references/phase-argument-parsing.md +61 -0
  359. package/plan-build-run/references/plan-authoring.md +246 -0
  360. package/plan-build-run/references/plan-format.md +351 -0
  361. package/plan-build-run/references/planning-config.md +200 -0
  362. package/plan-build-run/references/questioning.md +162 -0
  363. package/plan-build-run/references/reading-verification.md +127 -0
  364. package/plan-build-run/references/stub-patterns.md +160 -0
  365. package/plan-build-run/references/tdd.md +263 -0
  366. package/plan-build-run/references/ui-brand.md +187 -0
  367. package/plan-build-run/references/verification-overrides.md +38 -0
  368. package/plan-build-run/references/verification-patterns.md +612 -0
  369. package/plan-build-run/references/wave-execution.md +52 -0
  370. package/plan-build-run/skills/audit/SKILL.md +347 -0
  371. package/plan-build-run/skills/autonomous/SKILL.md +460 -0
  372. package/plan-build-run/skills/begin/SKILL.md +926 -0
  373. package/plan-build-run/skills/begin/templates/PROJECT.md.tmpl +33 -0
  374. package/plan-build-run/skills/begin/templates/REQUIREMENTS.md.tmpl +18 -0
  375. package/plan-build-run/skills/begin/templates/STATE.md.tmpl +48 -0
  376. package/plan-build-run/skills/begin/templates/config.json.tmpl +451 -0
  377. package/plan-build-run/skills/begin/templates/project-CONTEXT.md.tmpl +19 -0
  378. package/plan-build-run/skills/begin/templates/researcher-prompt.md.tmpl +47 -0
  379. package/plan-build-run/skills/begin/templates/roadmap-prompt.md.tmpl +49 -0
  380. package/plan-build-run/skills/begin/templates/synthesis-prompt.md.tmpl +44 -0
  381. package/plan-build-run/skills/build/SKILL.md +1655 -0
  382. package/plan-build-run/skills/build/templates/continuation-prompt.md.tmpl +26 -0
  383. package/plan-build-run/skills/build/templates/executor-prompt.md.tmpl +70 -0
  384. package/plan-build-run/skills/build/templates/inline-verifier-prompt.md.tmpl +33 -0
  385. package/plan-build-run/skills/config/SKILL.md +357 -0
  386. package/plan-build-run/skills/continue/SKILL.md +266 -0
  387. package/plan-build-run/skills/dashboard/SKILL.md +12 -0
  388. package/plan-build-run/skills/debug/SKILL.md +573 -0
  389. package/plan-build-run/skills/debug/templates/continuation-prompt.md.tmpl +27 -0
  390. package/plan-build-run/skills/debug/templates/initial-investigation-prompt.md.tmpl +34 -0
  391. package/plan-build-run/skills/discuss/SKILL.md +489 -0
  392. package/plan-build-run/skills/discuss/templates/CONTEXT.md.tmpl +61 -0
  393. package/plan-build-run/skills/discuss/templates/decision-categories.md +9 -0
  394. package/plan-build-run/skills/discuss/templates/project-CONTEXT.md.tmpl +19 -0
  395. package/plan-build-run/skills/do/SKILL.md +165 -0
  396. package/plan-build-run/skills/explore/SKILL.md +449 -0
  397. package/plan-build-run/skills/health/SKILL.md +332 -0
  398. package/plan-build-run/skills/health/templates/check-pattern.md.tmpl +30 -0
  399. package/plan-build-run/skills/health/templates/output-format.md.tmpl +63 -0
  400. package/plan-build-run/skills/help/SKILL.md +236 -0
  401. package/plan-build-run/skills/import/SKILL.md +827 -0
  402. package/plan-build-run/skills/intel/SKILL.md +131 -0
  403. package/plan-build-run/skills/milestone/SKILL.md +825 -0
  404. package/plan-build-run/skills/milestone/templates/audit-output.md.tmpl +76 -0
  405. package/plan-build-run/skills/milestone/templates/complete-output.md.tmpl +32 -0
  406. package/plan-build-run/skills/milestone/templates/edge-cases.md +54 -0
  407. package/plan-build-run/skills/milestone/templates/gaps-output.md.tmpl +25 -0
  408. package/plan-build-run/skills/milestone/templates/integration-checker-prompt.md.tmpl +25 -0
  409. package/plan-build-run/skills/milestone/templates/new-output.md.tmpl +29 -0
  410. package/plan-build-run/skills/milestone/templates/stats-file.md.tmpl +30 -0
  411. package/plan-build-run/skills/note/SKILL.md +221 -0
  412. package/plan-build-run/skills/pause/SKILL.md +259 -0
  413. package/plan-build-run/skills/pause/templates/continue-here.md.tmpl +71 -0
  414. package/plan-build-run/skills/plan/SKILL.md +852 -0
  415. package/plan-build-run/skills/plan/decimal-phase-calc.md +98 -0
  416. package/plan-build-run/skills/plan/templates/checker-prompt.md.tmpl +21 -0
  417. package/plan-build-run/skills/plan/templates/completion-output.md.tmpl +27 -0
  418. package/plan-build-run/skills/plan/templates/gap-closure-prompt.md.tmpl +32 -0
  419. package/plan-build-run/skills/plan/templates/planner-prompt.md.tmpl +38 -0
  420. package/plan-build-run/skills/plan/templates/prompt-partials/phase-project-context.md.tmpl +21 -0
  421. package/plan-build-run/skills/plan/templates/researcher-prompt.md.tmpl +19 -0
  422. package/plan-build-run/skills/plan/templates/revision-prompt.md.tmpl +23 -0
  423. package/plan-build-run/skills/profile/SKILL.md +173 -0
  424. package/plan-build-run/skills/profile-user/SKILL.md +220 -0
  425. package/plan-build-run/skills/quick/SKILL.md +727 -0
  426. package/plan-build-run/skills/release/SKILL.md +206 -0
  427. package/plan-build-run/skills/resume/SKILL.md +499 -0
  428. package/plan-build-run/skills/review/SKILL.md +763 -0
  429. package/plan-build-run/skills/review/templates/debugger-prompt.md.tmpl +60 -0
  430. package/plan-build-run/skills/review/templates/gap-planner-prompt.md.tmpl +40 -0
  431. package/plan-build-run/skills/review/templates/verifier-prompt.md.tmpl +115 -0
  432. package/plan-build-run/skills/scan/SKILL.md +330 -0
  433. package/plan-build-run/skills/scan/templates/mapper-prompt.md.tmpl +201 -0
  434. package/plan-build-run/skills/session-report/SKILL.md +128 -0
  435. package/plan-build-run/skills/setup/SKILL.md +246 -0
  436. package/plan-build-run/skills/shared/agent-type-resolution.md +20 -0
  437. package/plan-build-run/skills/shared/commit-planning-docs.md +43 -0
  438. package/plan-build-run/skills/shared/config-loading.md +102 -0
  439. package/plan-build-run/skills/shared/context-budget.md +105 -0
  440. package/plan-build-run/skills/shared/context-loader-task.md +91 -0
  441. package/plan-build-run/skills/shared/digest-select.md +79 -0
  442. package/plan-build-run/skills/shared/domain-probes.md +125 -0
  443. package/plan-build-run/skills/shared/error-reporting.md +59 -0
  444. package/plan-build-run/skills/shared/gate-prompts.md +390 -0
  445. package/plan-build-run/skills/shared/phase-argument-parsing.md +45 -0
  446. package/plan-build-run/skills/shared/revision-loop.md +81 -0
  447. package/plan-build-run/skills/shared/state-update.md +154 -0
  448. package/plan-build-run/skills/shared/universal-anti-patterns.md +59 -0
  449. package/plan-build-run/skills/ship/SKILL.md +154 -0
  450. package/plan-build-run/skills/status/SKILL.md +520 -0
  451. package/plan-build-run/skills/statusline/SKILL.md +151 -0
  452. package/plan-build-run/skills/test/SKILL.md +254 -0
  453. package/plan-build-run/skills/todo/SKILL.md +285 -0
  454. package/plan-build-run/skills/ui-phase/SKILL.md +177 -0
  455. package/plan-build-run/skills/ui-review/SKILL.md +204 -0
  456. package/plan-build-run/skills/undo/SKILL.md +216 -0
  457. package/plan-build-run/skills/validate-phase/SKILL.md +358 -0
  458. package/plan-build-run/templates/CLAUDE.md +7 -0
  459. package/plan-build-run/templates/DEBUG.md +164 -0
  460. package/plan-build-run/templates/UAT.md +247 -0
  461. package/plan-build-run/templates/VALIDATION.md +76 -0
  462. package/plan-build-run/templates/codebase/architecture.md +255 -0
  463. package/plan-build-run/templates/codebase/concerns.md +310 -0
  464. package/plan-build-run/templates/codebase/conventions.md +307 -0
  465. package/plan-build-run/templates/codebase/integrations.md +280 -0
  466. package/plan-build-run/templates/codebase/stack.md +186 -0
  467. package/plan-build-run/templates/codebase/structure.md +285 -0
  468. package/plan-build-run/templates/codebase/testing.md +480 -0
  469. package/plan-build-run/templates/config.json +37 -0
  470. package/plan-build-run/templates/context.md +297 -0
  471. package/plan-build-run/templates/continue-here.md +78 -0
  472. package/plan-build-run/templates/crud-flow-verification.md +277 -0
  473. package/plan-build-run/templates/debug-subagent-prompt.md +91 -0
  474. package/plan-build-run/templates/deferred-items.md +19 -0
  475. package/plan-build-run/templates/discovery.md +146 -0
  476. package/plan-build-run/templates/milestone-archive.md +123 -0
  477. package/plan-build-run/templates/milestone.md +115 -0
  478. package/plan-build-run/templates/phase-prompt.md +569 -0
  479. package/plan-build-run/templates/planner-subagent-prompt.md +117 -0
  480. package/plan-build-run/templates/project.md +184 -0
  481. package/plan-build-run/templates/requirements.md +231 -0
  482. package/plan-build-run/templates/research-outputs/ARCHITECTURE.md.tmpl +86 -0
  483. package/plan-build-run/templates/research-outputs/FEATURES.md.tmpl +77 -0
  484. package/plan-build-run/templates/research-outputs/PITFALLS.md.tmpl +65 -0
  485. package/plan-build-run/templates/research-outputs/STACK.md.tmpl +80 -0
  486. package/plan-build-run/templates/research-project/ARCHITECTURE.md +204 -0
  487. package/plan-build-run/templates/research-project/FEATURES.md +147 -0
  488. package/plan-build-run/templates/research-project/PITFALLS.md +200 -0
  489. package/plan-build-run/templates/research-project/STACK.md +120 -0
  490. package/plan-build-run/templates/research-project/SUMMARY.md +170 -0
  491. package/plan-build-run/templates/research.md +552 -0
  492. package/plan-build-run/templates/retrospective.md +54 -0
  493. package/plan-build-run/templates/roadmap.md +202 -0
  494. package/plan-build-run/templates/seed.md +16 -0
  495. package/plan-build-run/templates/state.md +176 -0
  496. package/plan-build-run/templates/summary-complex.md +59 -0
  497. package/plan-build-run/templates/summary-minimal.md +41 -0
  498. package/plan-build-run/templates/summary-standard.md +48 -0
  499. package/plan-build-run/templates/summary.md +248 -0
  500. package/plan-build-run/templates/user-setup.md +311 -0
  501. package/plan-build-run/templates/verification-report.md +322 -0
  502. package/plan-build-run/workflows/add-phase.md +111 -0
  503. package/plan-build-run/workflows/add-todo.md +157 -0
  504. package/plan-build-run/workflows/audit-milestone.md +241 -0
  505. package/plan-build-run/workflows/check-todos.md +176 -0
  506. package/plan-build-run/workflows/complete-milestone.md +644 -0
  507. package/plan-build-run/workflows/diagnose-issues.md +219 -0
  508. package/plan-build-run/workflows/discovery-phase.md +289 -0
  509. package/plan-build-run/workflows/discuss-phase.md +429 -0
  510. package/plan-build-run/workflows/execute-phase.md +439 -0
  511. package/plan-build-run/workflows/execute-plan.md +437 -0
  512. package/plan-build-run/workflows/explore.md +150 -0
  513. package/plan-build-run/workflows/help.md +470 -0
  514. package/plan-build-run/workflows/insert-phase.md +129 -0
  515. package/plan-build-run/workflows/list-phase-assumptions.md +178 -0
  516. package/plan-build-run/workflows/map-codebase.md +327 -0
  517. package/plan-build-run/workflows/new-milestone.md +373 -0
  518. package/plan-build-run/workflows/new-project.md +1009 -0
  519. package/plan-build-run/workflows/note.md +90 -0
  520. package/plan-build-run/workflows/pause-work.md +122 -0
  521. package/plan-build-run/workflows/plan-milestone-gaps.md +256 -0
  522. package/plan-build-run/workflows/plan-phase.md +376 -0
  523. package/plan-build-run/workflows/progress.md +431 -0
  524. package/plan-build-run/workflows/quick.md +230 -0
  525. package/plan-build-run/workflows/remove-phase.md +154 -0
  526. package/plan-build-run/workflows/research-phase.md +74 -0
  527. package/plan-build-run/workflows/resume-project.md +306 -0
  528. package/plan-build-run/workflows/set-profile.md +80 -0
  529. package/plan-build-run/workflows/settings.md +145 -0
  530. package/plan-build-run/workflows/transition.md +539 -0
  531. package/plan-build-run/workflows/update.md +212 -0
  532. package/plan-build-run/workflows/verify-phase.md +226 -0
  533. package/plan-build-run/workflows/verify-work.md +465 -0
  534. package/plugins/pbr/.claude-plugin/plugin.json +1 -1
  535. package/plugins/pbr/CLAUDE.md +19 -0
  536. package/plugins/pbr/UI-CONSISTENCY-GAPS.md +1 -1
  537. package/plugins/pbr/agents/audit.md +285 -0
  538. package/plugins/pbr/agents/codebase-mapper.md +110 -18
  539. package/plugins/pbr/agents/debugger.md +231 -29
  540. package/plugins/pbr/agents/dev-sync.md +206 -0
  541. package/plugins/pbr/agents/executor.md +601 -39
  542. package/plugins/pbr/agents/general.md +71 -6
  543. package/plugins/pbr/agents/integration-checker.md +146 -30
  544. package/plugins/pbr/agents/intel-updater.md +333 -0
  545. package/plugins/pbr/agents/nyquist-auditor.md +253 -0
  546. package/plugins/pbr/agents/plan-checker.md +177 -60
  547. package/plugins/pbr/agents/planner.md +404 -42
  548. package/plugins/pbr/agents/researcher.md +239 -36
  549. package/plugins/pbr/agents/roadmapper.md +384 -0
  550. package/plugins/pbr/agents/synthesizer.md +169 -26
  551. package/plugins/pbr/agents/ui-checker.md +203 -0
  552. package/plugins/pbr/agents/ui-researcher.md +224 -0
  553. package/plugins/pbr/agents/verifier.md +452 -48
  554. package/plugins/pbr/commands/add-phase.md +75 -0
  555. package/plugins/pbr/commands/add-todo.md +8 -0
  556. package/plugins/pbr/commands/audit-milestone.md +8 -0
  557. package/plugins/pbr/commands/audit.md +5 -0
  558. package/plugins/pbr/commands/autonomous.md +5 -0
  559. package/plugins/pbr/commands/begin.md +1 -1
  560. package/plugins/pbr/commands/build.md +1 -1
  561. package/plugins/pbr/commands/check-todos.md +8 -0
  562. package/plugins/pbr/commands/complete-milestone.md +8 -0
  563. package/plugins/pbr/commands/config.md +2 -2
  564. package/plugins/pbr/commands/continue.md +1 -1
  565. package/plugins/pbr/commands/dashboard.md +1 -1
  566. package/plugins/pbr/commands/debug.md +1 -1
  567. package/plugins/pbr/commands/discuss-phase.md +6 -0
  568. package/plugins/pbr/commands/discuss.md +1 -1
  569. package/plugins/pbr/commands/do.md +5 -0
  570. package/plugins/pbr/commands/execute-phase.md +6 -0
  571. package/plugins/pbr/commands/explore.md +1 -1
  572. package/plugins/pbr/commands/health.md +1 -1
  573. package/plugins/pbr/commands/help.md +1 -1
  574. package/plugins/pbr/commands/import.md +2 -2
  575. package/plugins/pbr/commands/insert-phase.md +65 -0
  576. package/plugins/pbr/commands/intel.md +5 -0
  577. package/plugins/pbr/commands/join-discord.md +11 -0
  578. package/plugins/pbr/commands/list-phase-assumptions.md +69 -0
  579. package/plugins/pbr/commands/map-codebase.md +6 -0
  580. package/plugins/pbr/commands/milestone.md +1 -1
  581. package/plugins/pbr/commands/new-milestone.md +8 -0
  582. package/plugins/pbr/commands/new-project.md +6 -0
  583. package/plugins/pbr/commands/note.md +1 -1
  584. package/plugins/pbr/commands/pause-work.md +5 -0
  585. package/plugins/pbr/commands/pause.md +1 -1
  586. package/plugins/pbr/commands/plan-milestone-gaps.md +7 -0
  587. package/plugins/pbr/commands/plan-phase.md +6 -0
  588. package/plugins/pbr/commands/plan.md +1 -1
  589. package/plugins/pbr/commands/profile-user.md +5 -0
  590. package/plugins/pbr/commands/profile.md +5 -0
  591. package/plugins/pbr/commands/progress.md +6 -0
  592. package/plugins/pbr/commands/quick.md +2 -2
  593. package/plugins/pbr/commands/reapply-patches.md +47 -0
  594. package/plugins/pbr/commands/release.md +6 -0
  595. package/plugins/pbr/commands/remove-phase.md +66 -0
  596. package/plugins/pbr/commands/research-phase.md +59 -0
  597. package/plugins/pbr/commands/resume-work.md +5 -0
  598. package/plugins/pbr/commands/resume.md +1 -1
  599. package/plugins/pbr/commands/review.md +1 -1
  600. package/plugins/pbr/commands/scan.md +1 -1
  601. package/plugins/pbr/commands/session-report.md +5 -0
  602. package/plugins/pbr/commands/set-profile.md +6 -0
  603. package/plugins/pbr/commands/settings.md +5 -0
  604. package/plugins/pbr/commands/setup.md +2 -2
  605. package/plugins/pbr/commands/ship.md +5 -0
  606. package/plugins/pbr/commands/status.md +1 -1
  607. package/plugins/pbr/commands/statusline.md +1 -1
  608. package/plugins/pbr/commands/test.md +5 -0
  609. package/plugins/pbr/commands/todo.md +2 -2
  610. package/plugins/pbr/commands/ui-phase.md +5 -0
  611. package/plugins/pbr/commands/ui-review.md +5 -0
  612. package/plugins/pbr/commands/undo.md +5 -0
  613. package/plugins/pbr/commands/update.md +37 -0
  614. package/plugins/pbr/commands/validate-phase.md +5 -0
  615. package/plugins/pbr/commands/verify-work.md +6 -0
  616. package/plugins/pbr/dashboard/package-lock.json +6 -0
  617. package/plugins/pbr/hooks/hooks.json +102 -13
  618. package/plugins/pbr/references/agent-contracts.md +37 -8
  619. package/plugins/pbr/references/agent-teams.md +3 -3
  620. package/plugins/pbr/references/archive/checkpoints.md +189 -0
  621. package/plugins/pbr/references/archive/context-quality-tiers.md +45 -0
  622. package/plugins/pbr/references/archive/pbr-rules.md +194 -0
  623. package/plugins/pbr/references/archive/verification-patterns.md +277 -0
  624. package/plugins/pbr/references/config-reference.md +182 -10
  625. package/plugins/pbr/references/continuation-format.md +1 -0
  626. package/plugins/pbr/references/deviation-rules.md +12 -0
  627. package/plugins/pbr/references/git-integration.md +110 -27
  628. package/plugins/pbr/references/hook-ordering.md +89 -0
  629. package/plugins/pbr/references/limitations.md +106 -0
  630. package/plugins/pbr/references/model-profiles.md +90 -7
  631. package/plugins/pbr/references/model-selection.md +1 -1
  632. package/plugins/pbr/references/node-repair.md +48 -0
  633. package/plugins/pbr/references/pbr-tools-cli.md +132 -2
  634. package/plugins/pbr/references/plan-authoring.md +65 -0
  635. package/plugins/pbr/references/plan-format.md +161 -10
  636. package/plugins/pbr/references/pretooluse-jsonl-behavior.md +58 -0
  637. package/plugins/pbr/references/questioning.md +138 -49
  638. package/plugins/pbr/references/reading-verification.md +4 -4
  639. package/plugins/pbr/references/signal-files.md +41 -0
  640. package/plugins/pbr/references/tmux-setup.md +288 -0
  641. package/plugins/pbr/references/ui-brand.md +449 -0
  642. package/plugins/pbr/references/worktree-sparse-checkout.md +86 -0
  643. package/plugins/pbr/scripts/architecture-guard.js +257 -0
  644. package/plugins/pbr/scripts/audit-checks/behavioral-compliance.js +2098 -0
  645. package/plugins/pbr/scripts/audit-checks/error-analysis.js +895 -0
  646. package/plugins/pbr/scripts/audit-checks/feature-verification.js +723 -0
  647. package/plugins/pbr/scripts/audit-checks/index.js +433 -0
  648. package/plugins/pbr/scripts/audit-checks/infrastructure.js +816 -0
  649. package/plugins/pbr/scripts/audit-checks/quality-metrics.js +452 -0
  650. package/plugins/pbr/scripts/audit-checks/session-quality.js +980 -0
  651. package/plugins/pbr/scripts/audit-checks/si-agent-hook-config-checks.js +467 -0
  652. package/plugins/pbr/scripts/audit-checks/si-cross-cutting-checks.js +272 -0
  653. package/plugins/pbr/scripts/audit-checks/si-skill-checks.js +424 -0
  654. package/plugins/pbr/scripts/audit-checks/workflow-compliance.js +1210 -0
  655. package/plugins/pbr/scripts/audit-dimensions.js +552 -0
  656. package/plugins/pbr/scripts/auto-continue.js +211 -32
  657. package/plugins/pbr/scripts/block-skill-self-read.js +85 -0
  658. package/plugins/pbr/scripts/check-agent-state-write.js +74 -0
  659. package/plugins/pbr/scripts/check-config-change.js +188 -0
  660. package/plugins/pbr/scripts/check-cross-plugin-sync.js +93 -0
  661. package/plugins/pbr/scripts/check-dangerous-commands.js +9 -5
  662. package/plugins/pbr/scripts/check-direct-state-write.js +37 -0
  663. package/plugins/pbr/scripts/check-phase-boundary.js +2 -8
  664. package/plugins/pbr/scripts/check-plan-format.js +149 -274
  665. package/plugins/pbr/scripts/check-roadmap-sync.js +175 -10
  666. package/plugins/pbr/scripts/check-skill-workflow.js +38 -34
  667. package/plugins/pbr/scripts/check-state-sync.js +344 -216
  668. package/plugins/pbr/scripts/check-subagent-output.js +297 -256
  669. package/plugins/pbr/scripts/check-summary-gate.js +1 -1
  670. package/plugins/pbr/scripts/config-schema.json +1252 -95
  671. package/plugins/pbr/scripts/context-bridge.js +439 -0
  672. package/plugins/pbr/scripts/context-budget-check.js +89 -9
  673. package/plugins/pbr/scripts/context-quality.js +272 -0
  674. package/plugins/pbr/scripts/enforce-pbr-workflow.js +277 -0
  675. package/plugins/pbr/scripts/event-handler.js +129 -77
  676. package/plugins/pbr/scripts/event-logger.js +61 -26
  677. package/plugins/pbr/scripts/feedback-loop.js +172 -0
  678. package/plugins/pbr/scripts/graph-update.js +199 -0
  679. package/plugins/pbr/scripts/hook-logger.js +76 -35
  680. package/plugins/pbr/scripts/hook-server-client.js +258 -0
  681. package/plugins/pbr/scripts/hook-server.js +334 -0
  682. package/plugins/pbr/scripts/hooks-schema.json +5 -1
  683. package/plugins/pbr/scripts/instructions-loaded.js +107 -0
  684. package/plugins/pbr/scripts/intel-queue.js +152 -0
  685. package/plugins/pbr/scripts/intent-router.cjs +147 -0
  686. package/plugins/pbr/scripts/intercept-plan-mode.js +52 -0
  687. package/plugins/pbr/scripts/lib/alternatives.js +203 -0
  688. package/plugins/pbr/scripts/lib/auto-cleanup.js +221 -0
  689. package/plugins/pbr/scripts/lib/auto-verify.js +103 -0
  690. package/plugins/pbr/scripts/lib/autonomy.js +91 -0
  691. package/plugins/pbr/scripts/lib/build.js +719 -0
  692. package/plugins/pbr/scripts/lib/ci-fix-loop.js +228 -0
  693. package/plugins/pbr/scripts/lib/circuit-state.js +133 -0
  694. package/plugins/pbr/scripts/lib/config.js +901 -0
  695. package/plugins/pbr/scripts/lib/context.js +254 -0
  696. package/plugins/pbr/scripts/lib/convention-detector.js +413 -0
  697. package/plugins/pbr/scripts/lib/core.js +939 -0
  698. package/plugins/pbr/scripts/lib/dashboard-launch.js +170 -0
  699. package/plugins/pbr/scripts/lib/decision-extraction.js +267 -0
  700. package/plugins/pbr/scripts/lib/dependency-break.js +147 -0
  701. package/plugins/pbr/scripts/lib/format-validators.js +947 -0
  702. package/plugins/pbr/scripts/lib/gates/advisories.js +129 -0
  703. package/plugins/pbr/scripts/lib/gates/build-dependency.js +115 -0
  704. package/plugins/pbr/scripts/lib/gates/build-executor.js +104 -0
  705. package/plugins/pbr/scripts/lib/gates/doc-existence.js +46 -0
  706. package/plugins/pbr/scripts/lib/gates/helpers.js +141 -0
  707. package/plugins/pbr/scripts/lib/gates/inline-execution.js +185 -0
  708. package/plugins/pbr/scripts/lib/gates/milestone-complete.js +136 -0
  709. package/plugins/pbr/scripts/lib/gates/milestone-summary.js +119 -0
  710. package/plugins/pbr/scripts/lib/gates/multi-phase-loader.js +147 -0
  711. package/plugins/pbr/scripts/lib/gates/plan-executor.js +36 -0
  712. package/plugins/pbr/scripts/lib/gates/quick-executor.js +76 -0
  713. package/plugins/pbr/scripts/lib/gates/review-planner.js +61 -0
  714. package/plugins/pbr/scripts/lib/gates/review-verifier.js +69 -0
  715. package/plugins/pbr/scripts/lib/gates/rich-agent-context.js +143 -0
  716. package/plugins/pbr/scripts/lib/health-checks.js +215 -0
  717. package/plugins/pbr/scripts/lib/history.js +150 -0
  718. package/plugins/pbr/scripts/lib/init.js +302 -0
  719. package/plugins/pbr/scripts/lib/learnings.js +432 -0
  720. package/plugins/pbr/scripts/lib/migrate.js +169 -0
  721. package/plugins/pbr/scripts/lib/parse-args.js +134 -0
  722. package/plugins/pbr/scripts/lib/pattern-routing.js +55 -0
  723. package/plugins/pbr/scripts/lib/phase.js +935 -0
  724. package/plugins/pbr/scripts/lib/pre-research.js +133 -0
  725. package/plugins/pbr/scripts/lib/preview.js +174 -0
  726. package/plugins/pbr/scripts/lib/quick-init.js +131 -0
  727. package/plugins/pbr/scripts/lib/reference.js +236 -0
  728. package/plugins/pbr/scripts/lib/resolve-root.js +66 -0
  729. package/plugins/pbr/scripts/lib/roadmap.js +784 -0
  730. package/plugins/pbr/scripts/lib/session-briefing.js +879 -0
  731. package/plugins/pbr/scripts/lib/skill-section.js +99 -0
  732. package/plugins/pbr/scripts/lib/smart-next-task.js +225 -0
  733. package/plugins/pbr/scripts/lib/snapshot-manager.js +225 -0
  734. package/plugins/pbr/scripts/lib/spot-check.js +509 -0
  735. package/plugins/pbr/scripts/lib/state.js +565 -0
  736. package/plugins/pbr/scripts/lib/status-render.js +511 -0
  737. package/plugins/pbr/scripts/lib/step-verify.js +149 -0
  738. package/plugins/pbr/scripts/lib/subagent-validators.js +1010 -0
  739. package/plugins/pbr/scripts/lib/suggest-next.js +316 -0
  740. package/plugins/pbr/scripts/lib/tech-debt-scanner.js +116 -0
  741. package/plugins/pbr/scripts/lib/test-cache.js +54 -0
  742. package/plugins/pbr/scripts/lib/todo.js +300 -0
  743. package/plugins/pbr/scripts/lib/trust-gate.js +84 -0
  744. package/plugins/pbr/scripts/local-llm/client.js +237 -0
  745. package/plugins/pbr/scripts/local-llm/health.js +220 -0
  746. package/plugins/pbr/scripts/local-llm/metrics.js +340 -0
  747. package/plugins/pbr/scripts/local-llm/operations/classify-artifact.js +76 -0
  748. package/plugins/pbr/scripts/local-llm/operations/classify-commit.js +137 -0
  749. package/plugins/pbr/scripts/local-llm/operations/classify-error.js +75 -0
  750. package/plugins/pbr/scripts/local-llm/operations/classify-file-intent.js +171 -0
  751. package/plugins/pbr/scripts/local-llm/operations/score-source.js +72 -0
  752. package/plugins/pbr/scripts/local-llm/operations/summarize-context.js +62 -0
  753. package/plugins/pbr/scripts/local-llm/operations/triage-test-output.js +72 -0
  754. package/plugins/pbr/scripts/local-llm/operations/validate-task.js +59 -0
  755. package/plugins/pbr/scripts/local-llm/router.js +101 -0
  756. package/plugins/pbr/scripts/local-llm/shadow.js +60 -0
  757. package/plugins/pbr/scripts/local-llm/threshold-tuner.js +118 -0
  758. package/plugins/pbr/scripts/log-subagent.js +129 -26
  759. package/plugins/pbr/scripts/log-tool-failure.js +58 -5
  760. package/plugins/pbr/scripts/milestone-learnings.js +569 -0
  761. package/plugins/pbr/scripts/package.json +1 -0
  762. package/plugins/pbr/scripts/pbr-tools.js +1361 -1214
  763. package/plugins/pbr/scripts/post-bash-triage.js +163 -0
  764. package/plugins/pbr/scripts/post-compact.js +135 -0
  765. package/plugins/pbr/scripts/post-hoc.js +286 -0
  766. package/plugins/pbr/scripts/post-write-dispatch.js +315 -30
  767. package/plugins/pbr/scripts/post-write-quality.js +3 -3
  768. package/plugins/pbr/scripts/pre-bash-dispatch.js +81 -4
  769. package/plugins/pbr/scripts/pre-write-dispatch.js +76 -20
  770. package/plugins/pbr/scripts/progress-tracker.js +145 -277
  771. package/plugins/pbr/scripts/quick-status.js +179 -0
  772. package/plugins/pbr/scripts/record-incident.js +37 -0
  773. package/plugins/pbr/scripts/risk-classifier.cjs +123 -0
  774. package/plugins/pbr/scripts/run-hook.js +49 -8
  775. package/plugins/pbr/scripts/session-cleanup.js +379 -7
  776. package/plugins/pbr/scripts/session-tracker.js +124 -0
  777. package/plugins/pbr/scripts/status-line.js +540 -27
  778. package/plugins/pbr/scripts/suggest-compact.js +183 -7
  779. package/plugins/pbr/scripts/sync-context-to-claude.js +100 -0
  780. package/plugins/pbr/scripts/task-completed.js +125 -3
  781. package/plugins/pbr/scripts/test/config.test.js +126 -0
  782. package/plugins/pbr/scripts/test/cross-platform.test.js +131 -0
  783. package/plugins/pbr/scripts/test/fixtures/config.json +20 -0
  784. package/plugins/pbr/scripts/test/fixtures/plan.md +54 -0
  785. package/plugins/pbr/scripts/test/fixtures/project.md +30 -0
  786. package/plugins/pbr/scripts/test/fixtures/roadmap.md +55 -0
  787. package/plugins/pbr/scripts/test/fixtures/state.md +60 -0
  788. package/plugins/pbr/scripts/test/fixtures/summary.md +35 -0
  789. package/plugins/pbr/scripts/test/fixtures.test.js +184 -0
  790. package/plugins/pbr/scripts/test/phase.test.js +142 -0
  791. package/plugins/pbr/scripts/test/roadmap.test.js +96 -0
  792. package/plugins/pbr/scripts/test/state.test.js +163 -0
  793. package/plugins/pbr/scripts/track-context-budget.js +323 -88
  794. package/plugins/pbr/scripts/trust-tracker.js +193 -0
  795. package/plugins/pbr/scripts/validate-commit.js +76 -11
  796. package/plugins/pbr/scripts/validate-skill-args.js +18 -14
  797. package/plugins/pbr/scripts/validate-task.js +93 -614
  798. package/plugins/pbr/scripts/worktree-create.js +144 -0
  799. package/plugins/pbr/scripts/worktree-remove.js +147 -0
  800. package/plugins/pbr/skills/audit/SKILL.md +478 -0
  801. package/plugins/pbr/skills/autonomous/SKILL.md +460 -0
  802. package/plugins/pbr/skills/begin/SKILL.md +447 -142
  803. package/plugins/pbr/skills/begin/templates/STATE.md.tmpl +1 -2
  804. package/plugins/pbr/skills/begin/templates/config.json.tmpl +423 -36
  805. package/plugins/pbr/skills/begin/templates/researcher-prompt.md.tmpl +28 -0
  806. package/plugins/pbr/skills/begin/templates/roadmap-prompt.md.tmpl +26 -3
  807. package/plugins/pbr/skills/begin/templates/synthesis-prompt.md.tmpl +33 -5
  808. package/plugins/pbr/skills/build/SKILL.md +1010 -327
  809. package/plugins/pbr/skills/build/templates/continuation-prompt.md.tmpl +26 -0
  810. package/plugins/pbr/skills/build/templates/executor-prompt.md.tmpl +77 -0
  811. package/plugins/pbr/skills/build/templates/inline-verifier-prompt.md.tmpl +33 -0
  812. package/plugins/pbr/skills/config/SKILL.md +108 -9
  813. package/plugins/pbr/skills/continue/SKILL.md +118 -19
  814. package/plugins/pbr/skills/dashboard/SKILL.md +21 -9
  815. package/plugins/pbr/skills/debug/SKILL.md +62 -10
  816. package/plugins/pbr/skills/debug/templates/continuation-prompt.md.tmpl +12 -1
  817. package/plugins/pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +12 -5
  818. package/plugins/pbr/skills/discuss/SKILL.md +155 -23
  819. package/plugins/pbr/skills/discuss/templates/CONTEXT.md.tmpl +21 -1
  820. package/plugins/pbr/skills/do/SKILL.md +119 -24
  821. package/plugins/pbr/skills/explore/SKILL.md +83 -16
  822. package/plugins/pbr/skills/health/SKILL.md +74 -17
  823. package/plugins/pbr/skills/help/SKILL.md +123 -39
  824. package/plugins/pbr/skills/import/SKILL.md +327 -13
  825. package/plugins/pbr/skills/intel/SKILL.md +131 -0
  826. package/plugins/pbr/skills/milestone/SKILL.md +342 -260
  827. package/plugins/pbr/skills/milestone/templates/audit-output.md.tmpl +76 -0
  828. package/plugins/pbr/skills/milestone/templates/complete-output.md.tmpl +32 -0
  829. package/plugins/pbr/skills/milestone/templates/edge-cases.md +54 -0
  830. package/plugins/pbr/skills/milestone/templates/gaps-output.md.tmpl +25 -0
  831. package/plugins/pbr/skills/milestone/templates/integration-checker-prompt.md.tmpl +25 -0
  832. package/plugins/pbr/skills/milestone/templates/new-output.md.tmpl +29 -0
  833. package/plugins/pbr/skills/note/SKILL.md +10 -2
  834. package/plugins/pbr/skills/pause/SKILL.md +51 -7
  835. package/plugins/pbr/skills/pause/templates/continue-here.md.tmpl +33 -52
  836. package/plugins/pbr/skills/plan/SKILL.md +418 -268
  837. package/plugins/pbr/skills/plan/templates/checker-prompt.md.tmpl +5 -2
  838. package/plugins/pbr/skills/plan/templates/completion-output.md.tmpl +27 -0
  839. package/plugins/pbr/skills/plan/templates/revision-prompt.md.tmpl +21 -5
  840. package/plugins/pbr/skills/profile/SKILL.md +183 -0
  841. package/plugins/pbr/skills/profile-user/SKILL.md +224 -0
  842. package/plugins/pbr/skills/quick/SKILL.md +440 -95
  843. package/plugins/pbr/skills/release/SKILL.md +206 -0
  844. package/plugins/pbr/skills/resume/SKILL.md +122 -27
  845. package/plugins/pbr/skills/review/SKILL.md +219 -154
  846. package/plugins/pbr/skills/review/templates/verifier-prompt.md.tmpl +7 -0
  847. package/plugins/pbr/skills/scan/SKILL.md +36 -12
  848. package/plugins/pbr/skills/scan/templates/mapper-prompt.md.tmpl +1 -1
  849. package/plugins/pbr/skills/session-report/SKILL.md +128 -0
  850. package/plugins/pbr/skills/setup/SKILL.md +149 -202
  851. package/plugins/pbr/skills/shared/agent-context-enrichment.md +21 -0
  852. package/plugins/pbr/skills/shared/agent-type-resolution.md +20 -0
  853. package/plugins/pbr/skills/shared/commit-planning-docs.md +8 -0
  854. package/plugins/pbr/skills/shared/context-budget.md +66 -1
  855. package/plugins/pbr/skills/shared/context-loader-task.md +15 -8
  856. package/plugins/pbr/skills/shared/digest-select.md +2 -2
  857. package/plugins/pbr/skills/shared/domain-probes.md +1 -1
  858. package/plugins/pbr/skills/shared/error-reporting.md +38 -60
  859. package/plugins/pbr/skills/shared/gate-prompts.md +4 -2
  860. package/plugins/pbr/skills/shared/memory-capture.md +48 -0
  861. package/plugins/pbr/skills/shared/phase-argument-parsing.md +4 -4
  862. package/plugins/pbr/skills/shared/revision-loop.md +24 -6
  863. package/plugins/pbr/skills/shared/state-update.md +47 -54
  864. package/plugins/pbr/skills/shared/universal-anti-patterns.md +27 -4
  865. package/plugins/pbr/skills/ship/SKILL.md +154 -0
  866. package/plugins/pbr/skills/status/SKILL.md +201 -53
  867. package/plugins/pbr/skills/test/SKILL.md +254 -0
  868. package/plugins/pbr/skills/todo/SKILL.md +13 -11
  869. package/plugins/pbr/skills/ui-phase/SKILL.md +179 -0
  870. package/plugins/pbr/skills/ui-review/SKILL.md +206 -0
  871. package/plugins/pbr/skills/undo/SKILL.md +218 -0
  872. package/plugins/pbr/skills/validate-phase/SKILL.md +358 -0
  873. package/plugins/pbr/templates/CONTEXT.md.tmpl +45 -20
  874. package/plugins/pbr/templates/DISCOVERY.md.tmpl +29 -0
  875. package/plugins/pbr/templates/HANDOFF.json.tmpl +30 -0
  876. package/plugins/pbr/templates/INTEGRATION-REPORT.md.tmpl +18 -2
  877. package/plugins/pbr/templates/KNOWLEDGE.md.tmpl +39 -0
  878. package/plugins/pbr/templates/MILESTONE-AUDIT.md.tmpl +44 -0
  879. package/plugins/pbr/templates/PROJECT.md.tmpl +126 -0
  880. package/plugins/pbr/templates/REQUIREMENTS.md.tmpl +96 -0
  881. package/plugins/pbr/templates/RETROSPECTIVE.md.tmpl +43 -0
  882. package/plugins/pbr/templates/ROADMAP.md.tmpl +108 -14
  883. package/plugins/pbr/templates/SUMMARY-complex.md.tmpl +133 -0
  884. package/plugins/pbr/templates/SUMMARY-minimal.md.tmpl +55 -0
  885. package/plugins/pbr/templates/SUMMARY.md.tmpl +21 -0
  886. package/plugins/pbr/templates/VERIFICATION-DETAIL.md.tmpl +49 -13
  887. package/plugins/pbr/templates/project-CONTEXT.md.tmpl +59 -0
  888. package/plugins/pbr/templates/research-outputs/ARCHITECTURE.md.tmpl +91 -0
  889. package/plugins/pbr/templates/research-outputs/FEATURES.md.tmpl +64 -0
  890. package/plugins/pbr/templates/research-outputs/PITFALLS.md.tmpl +50 -0
  891. package/plugins/pbr/templates/research-outputs/STACK.md.tmpl +63 -0
  892. package/plugins/pbr/templates/research-outputs/SUMMARY.md.tmpl +98 -0
  893. package/scripts/build-hooks.js +61 -0
  894. package/scripts/check-ci.js +100 -0
  895. package/scripts/clean-changelog.js +362 -0
  896. package/scripts/generate-derivatives.js +581 -0
  897. package/scripts/posttest.js +93 -0
  898. package/scripts/release.js +196 -0
  899. package/scripts/run-tests.cjs +29 -0
  900. package/dashboard/bin/cli.js +0 -25
  901. package/dashboard/public/css/layout.css +0 -472
  902. package/dashboard/public/css/status-colors.css +0 -98
  903. package/dashboard/public/js/htmx-title.js +0 -5
  904. package/dashboard/public/js/sidebar-toggle.js +0 -20
  905. package/dashboard/src/app.js +0 -78
  906. package/dashboard/src/middleware/errorHandler.js +0 -52
  907. package/dashboard/src/middleware/notFoundHandler.js +0 -9
  908. package/dashboard/src/repositories/planning.repository.js +0 -130
  909. package/dashboard/src/routes/events.routes.js +0 -40
  910. package/dashboard/src/routes/index.routes.js +0 -31
  911. package/dashboard/src/routes/pages.routes.js +0 -308
  912. package/dashboard/src/server.js +0 -42
  913. package/dashboard/src/services/dashboard.service.js +0 -309
  914. package/dashboard/src/services/milestone.service.js +0 -154
  915. package/dashboard/src/services/phase.service.js +0 -226
  916. package/dashboard/src/services/project.service.js +0 -57
  917. package/dashboard/src/services/roadmap.service.js +0 -171
  918. package/dashboard/src/services/sse.service.js +0 -58
  919. package/dashboard/src/services/todo.service.js +0 -254
  920. package/dashboard/src/services/watcher.service.js +0 -48
  921. package/dashboard/src/views/coming-soon.ejs +0 -11
  922. package/dashboard/src/views/error.ejs +0 -13
  923. package/dashboard/src/views/index.ejs +0 -5
  924. package/dashboard/src/views/layout.ejs +0 -1
  925. package/dashboard/src/views/milestone-detail.ejs +0 -5
  926. package/dashboard/src/views/milestones.ejs +0 -5
  927. package/dashboard/src/views/partials/dashboard-content.ejs +0 -77
  928. package/dashboard/src/views/partials/footer.ejs +0 -3
  929. package/dashboard/src/views/partials/head.ejs +0 -27
  930. package/dashboard/src/views/partials/header.ejs +0 -12
  931. package/dashboard/src/views/partials/layout-bottom.ejs +0 -15
  932. package/dashboard/src/views/partials/layout-top.ejs +0 -8
  933. package/dashboard/src/views/partials/milestone-detail-content.ejs +0 -19
  934. package/dashboard/src/views/partials/milestones-content.ejs +0 -44
  935. package/dashboard/src/views/partials/phase-content.ejs +0 -189
  936. package/dashboard/src/views/partials/phase-doc-content.ejs +0 -38
  937. package/dashboard/src/views/partials/phases-content.ejs +0 -117
  938. package/dashboard/src/views/partials/roadmap-content.ejs +0 -142
  939. package/dashboard/src/views/partials/sidebar.ejs +0 -46
  940. package/dashboard/src/views/partials/todo-create-content.ejs +0 -53
  941. package/dashboard/src/views/partials/todo-detail-content.ejs +0 -38
  942. package/dashboard/src/views/partials/todos-content.ejs +0 -53
  943. package/dashboard/src/views/phase-detail.ejs +0 -5
  944. package/dashboard/src/views/phase-doc.ejs +0 -5
  945. package/dashboard/src/views/phases.ejs +0 -5
  946. package/dashboard/src/views/roadmap.ejs +0 -5
  947. package/dashboard/src/views/todo-create.ejs +0 -5
  948. package/dashboard/src/views/todo-detail.ejs +0 -5
  949. package/dashboard/src/views/todos.ejs +0 -5
  950. package/plugins/copilot-pbr/CHANGELOG.md +0 -19
  951. package/plugins/copilot-pbr/README.md +0 -129
  952. package/plugins/copilot-pbr/agents/codebase-mapper.agent.md +0 -151
  953. package/plugins/copilot-pbr/agents/debugger.agent.md +0 -172
  954. package/plugins/copilot-pbr/agents/executor.agent.md +0 -267
  955. package/plugins/copilot-pbr/agents/general.agent.md +0 -88
  956. package/plugins/copilot-pbr/agents/integration-checker.agent.md +0 -119
  957. package/plugins/copilot-pbr/agents/plan-checker.agent.md +0 -199
  958. package/plugins/copilot-pbr/agents/planner.agent.md +0 -238
  959. package/plugins/copilot-pbr/agents/researcher.agent.md +0 -186
  960. package/plugins/copilot-pbr/agents/synthesizer.agent.md +0 -126
  961. package/plugins/copilot-pbr/agents/verifier.agent.md +0 -228
  962. package/plugins/copilot-pbr/hooks/hooks.json +0 -144
  963. package/plugins/copilot-pbr/plugin.json +0 -30
  964. package/plugins/copilot-pbr/references/agent-anti-patterns.md +0 -25
  965. package/plugins/copilot-pbr/references/agent-contracts.md +0 -297
  966. package/plugins/copilot-pbr/references/agent-interactions.md +0 -135
  967. package/plugins/copilot-pbr/references/agent-teams.md +0 -55
  968. package/plugins/copilot-pbr/references/checkpoints.md +0 -158
  969. package/plugins/copilot-pbr/references/common-bug-patterns.md +0 -14
  970. package/plugins/copilot-pbr/references/config-reference.md +0 -442
  971. package/plugins/copilot-pbr/references/continuation-format.md +0 -213
  972. package/plugins/copilot-pbr/references/deviation-rules.md +0 -113
  973. package/plugins/copilot-pbr/references/git-integration.md +0 -227
  974. package/plugins/copilot-pbr/references/integration-patterns.md +0 -118
  975. package/plugins/copilot-pbr/references/model-profiles.md +0 -100
  976. package/plugins/copilot-pbr/references/model-selection.md +0 -32
  977. package/plugins/copilot-pbr/references/pbr-rules.md +0 -195
  978. package/plugins/copilot-pbr/references/pbr-tools-cli.md +0 -285
  979. package/plugins/copilot-pbr/references/plan-authoring.md +0 -182
  980. package/plugins/copilot-pbr/references/plan-format.md +0 -288
  981. package/plugins/copilot-pbr/references/planning-config.md +0 -214
  982. package/plugins/copilot-pbr/references/questioning.md +0 -215
  983. package/plugins/copilot-pbr/references/reading-verification.md +0 -128
  984. package/plugins/copilot-pbr/references/stub-patterns.md +0 -161
  985. package/plugins/copilot-pbr/references/subagent-coordination.md +0 -120
  986. package/plugins/copilot-pbr/references/ui-formatting.md +0 -444
  987. package/plugins/copilot-pbr/references/verification-patterns.md +0 -199
  988. package/plugins/copilot-pbr/references/wave-execution.md +0 -96
  989. package/plugins/copilot-pbr/rules/pbr-workflow.mdc +0 -48
  990. package/plugins/copilot-pbr/setup.ps1 +0 -93
  991. package/plugins/copilot-pbr/setup.sh +0 -93
  992. package/plugins/copilot-pbr/skills/begin/SKILL.md +0 -589
  993. package/plugins/copilot-pbr/skills/begin/templates/PROJECT.md.tmpl +0 -34
  994. package/plugins/copilot-pbr/skills/begin/templates/REQUIREMENTS.md.tmpl +0 -19
  995. package/plugins/copilot-pbr/skills/begin/templates/STATE.md.tmpl +0 -50
  996. package/plugins/copilot-pbr/skills/begin/templates/config.json.tmpl +0 -64
  997. package/plugins/copilot-pbr/skills/begin/templates/researcher-prompt.md.tmpl +0 -20
  998. package/plugins/copilot-pbr/skills/begin/templates/roadmap-prompt.md.tmpl +0 -31
  999. package/plugins/copilot-pbr/skills/begin/templates/synthesis-prompt.md.tmpl +0 -17
  1000. package/plugins/copilot-pbr/skills/build/SKILL.md +0 -955
  1001. package/plugins/copilot-pbr/skills/config/SKILL.md +0 -250
  1002. package/plugins/copilot-pbr/skills/continue/SKILL.md +0 -159
  1003. package/plugins/copilot-pbr/skills/dashboard/SKILL.md +0 -43
  1004. package/plugins/copilot-pbr/skills/debug/SKILL.md +0 -508
  1005. package/plugins/copilot-pbr/skills/debug/templates/continuation-prompt.md.tmpl +0 -17
  1006. package/plugins/copilot-pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +0 -28
  1007. package/plugins/copilot-pbr/skills/discuss/SKILL.md +0 -353
  1008. package/plugins/copilot-pbr/skills/discuss/templates/CONTEXT.md.tmpl +0 -62
  1009. package/plugins/copilot-pbr/skills/discuss/templates/decision-categories.md +0 -10
  1010. package/plugins/copilot-pbr/skills/do/SKILL.md +0 -66
  1011. package/plugins/copilot-pbr/skills/explore/SKILL.md +0 -373
  1012. package/plugins/copilot-pbr/skills/health/SKILL.md +0 -274
  1013. package/plugins/copilot-pbr/skills/health/templates/check-pattern.md.tmpl +0 -31
  1014. package/plugins/copilot-pbr/skills/health/templates/output-format.md.tmpl +0 -64
  1015. package/plugins/copilot-pbr/skills/help/SKILL.md +0 -152
  1016. package/plugins/copilot-pbr/skills/import/SKILL.md +0 -502
  1017. package/plugins/copilot-pbr/skills/milestone/SKILL.md +0 -745
  1018. package/plugins/copilot-pbr/skills/milestone/templates/audit-report.md.tmpl +0 -49
  1019. package/plugins/copilot-pbr/skills/milestone/templates/stats-file.md.tmpl +0 -31
  1020. package/plugins/copilot-pbr/skills/note/SKILL.md +0 -213
  1021. package/plugins/copilot-pbr/skills/pause/SKILL.md +0 -247
  1022. package/plugins/copilot-pbr/skills/pause/templates/continue-here.md.tmpl +0 -72
  1023. package/plugins/copilot-pbr/skills/plan/SKILL.md +0 -662
  1024. package/plugins/copilot-pbr/skills/plan/templates/checker-prompt.md.tmpl +0 -22
  1025. package/plugins/copilot-pbr/skills/plan/templates/gap-closure-prompt.md.tmpl +0 -33
  1026. package/plugins/copilot-pbr/skills/plan/templates/planner-prompt.md.tmpl +0 -39
  1027. package/plugins/copilot-pbr/skills/plan/templates/researcher-prompt.md.tmpl +0 -20
  1028. package/plugins/copilot-pbr/skills/plan/templates/revision-prompt.md.tmpl +0 -24
  1029. package/plugins/copilot-pbr/skills/quick/SKILL.md +0 -376
  1030. package/plugins/copilot-pbr/skills/resume/SKILL.md +0 -399
  1031. package/plugins/copilot-pbr/skills/review/SKILL.md +0 -653
  1032. package/plugins/copilot-pbr/skills/review/templates/debugger-prompt.md.tmpl +0 -61
  1033. package/plugins/copilot-pbr/skills/review/templates/gap-planner-prompt.md.tmpl +0 -41
  1034. package/plugins/copilot-pbr/skills/review/templates/verifier-prompt.md.tmpl +0 -116
  1035. package/plugins/copilot-pbr/skills/scan/SKILL.md +0 -299
  1036. package/plugins/copilot-pbr/skills/scan/templates/mapper-prompt.md.tmpl +0 -202
  1037. package/plugins/copilot-pbr/skills/setup/SKILL.md +0 -296
  1038. package/plugins/copilot-pbr/skills/shared/commit-planning-docs.md +0 -36
  1039. package/plugins/copilot-pbr/skills/shared/config-loading.md +0 -103
  1040. package/plugins/copilot-pbr/skills/shared/context-budget.md +0 -41
  1041. package/plugins/copilot-pbr/skills/shared/context-loader-task.md +0 -87
  1042. package/plugins/copilot-pbr/skills/shared/digest-select.md +0 -80
  1043. package/plugins/copilot-pbr/skills/shared/domain-probes.md +0 -126
  1044. package/plugins/copilot-pbr/skills/shared/error-reporting.md +0 -81
  1045. package/plugins/copilot-pbr/skills/shared/gate-prompts.md +0 -389
  1046. package/plugins/copilot-pbr/skills/shared/phase-argument-parsing.md +0 -46
  1047. package/plugins/copilot-pbr/skills/shared/progress-display.md +0 -53
  1048. package/plugins/copilot-pbr/skills/shared/revision-loop.md +0 -82
  1049. package/plugins/copilot-pbr/skills/shared/state-loading.md +0 -63
  1050. package/plugins/copilot-pbr/skills/shared/state-update.md +0 -162
  1051. package/plugins/copilot-pbr/skills/shared/universal-anti-patterns.md +0 -38
  1052. package/plugins/copilot-pbr/skills/status/SKILL.md +0 -362
  1053. package/plugins/copilot-pbr/skills/statusline/SKILL.md +0 -149
  1054. package/plugins/copilot-pbr/skills/todo/SKILL.md +0 -279
  1055. package/plugins/copilot-pbr/templates/CONTEXT.md.tmpl +0 -53
  1056. package/plugins/copilot-pbr/templates/INTEGRATION-REPORT.md.tmpl +0 -152
  1057. package/plugins/copilot-pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -98
  1058. package/plugins/copilot-pbr/templates/ROADMAP.md.tmpl +0 -41
  1059. package/plugins/copilot-pbr/templates/SUMMARY.md.tmpl +0 -82
  1060. package/plugins/copilot-pbr/templates/VERIFICATION-DETAIL.md.tmpl +0 -117
  1061. package/plugins/copilot-pbr/templates/codebase/ARCHITECTURE.md.tmpl +0 -98
  1062. package/plugins/copilot-pbr/templates/codebase/CONCERNS.md.tmpl +0 -93
  1063. package/plugins/copilot-pbr/templates/codebase/CONVENTIONS.md.tmpl +0 -104
  1064. package/plugins/copilot-pbr/templates/codebase/INTEGRATIONS.md.tmpl +0 -78
  1065. package/plugins/copilot-pbr/templates/codebase/STACK.md.tmpl +0 -78
  1066. package/plugins/copilot-pbr/templates/codebase/STRUCTURE.md.tmpl +0 -80
  1067. package/plugins/copilot-pbr/templates/codebase/TESTING.md.tmpl +0 -107
  1068. package/plugins/copilot-pbr/templates/continue-here.md.tmpl +0 -74
  1069. package/plugins/copilot-pbr/templates/prompt-partials/phase-project-context.md.tmpl +0 -38
  1070. package/plugins/copilot-pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
  1071. package/plugins/copilot-pbr/templates/research/STACK.md.tmpl +0 -71
  1072. package/plugins/copilot-pbr/templates/research/SUMMARY.md.tmpl +0 -112
  1073. package/plugins/copilot-pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
  1074. package/plugins/copilot-pbr/templates/research-outputs/project-research.md.tmpl +0 -99
  1075. package/plugins/copilot-pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
  1076. package/plugins/cursor-pbr/.cursor-plugin/plugin.json +0 -32
  1077. package/plugins/cursor-pbr/CHANGELOG.md +0 -15
  1078. package/plugins/cursor-pbr/README.md +0 -118
  1079. package/plugins/cursor-pbr/agents/codebase-mapper.md +0 -150
  1080. package/plugins/cursor-pbr/agents/debugger.md +0 -171
  1081. package/plugins/cursor-pbr/agents/executor.md +0 -266
  1082. package/plugins/cursor-pbr/agents/general.md +0 -87
  1083. package/plugins/cursor-pbr/agents/integration-checker.md +0 -118
  1084. package/plugins/cursor-pbr/agents/plan-checker.md +0 -198
  1085. package/plugins/cursor-pbr/agents/planner.md +0 -237
  1086. package/plugins/cursor-pbr/agents/researcher.md +0 -185
  1087. package/plugins/cursor-pbr/agents/synthesizer.md +0 -125
  1088. package/plugins/cursor-pbr/agents/verifier.md +0 -227
  1089. package/plugins/cursor-pbr/assets/.gitkeep +0 -0
  1090. package/plugins/cursor-pbr/assets/logo.svg +0 -21
  1091. package/plugins/cursor-pbr/hooks/hooks.json +0 -203
  1092. package/plugins/cursor-pbr/references/agent-anti-patterns.md +0 -25
  1093. package/plugins/cursor-pbr/references/agent-contracts.md +0 -297
  1094. package/plugins/cursor-pbr/references/agent-interactions.md +0 -135
  1095. package/plugins/cursor-pbr/references/agent-teams.md +0 -55
  1096. package/plugins/cursor-pbr/references/checkpoints.md +0 -158
  1097. package/plugins/cursor-pbr/references/common-bug-patterns.md +0 -14
  1098. package/plugins/cursor-pbr/references/config-reference.md +0 -442
  1099. package/plugins/cursor-pbr/references/continuation-format.md +0 -213
  1100. package/plugins/cursor-pbr/references/deviation-rules.md +0 -113
  1101. package/plugins/cursor-pbr/references/git-integration.md +0 -227
  1102. package/plugins/cursor-pbr/references/integration-patterns.md +0 -118
  1103. package/plugins/cursor-pbr/references/model-profiles.md +0 -100
  1104. package/plugins/cursor-pbr/references/model-selection.md +0 -32
  1105. package/plugins/cursor-pbr/references/pbr-rules.md +0 -195
  1106. package/plugins/cursor-pbr/references/pbr-tools-cli.md +0 -285
  1107. package/plugins/cursor-pbr/references/plan-authoring.md +0 -182
  1108. package/plugins/cursor-pbr/references/plan-format.md +0 -288
  1109. package/plugins/cursor-pbr/references/planning-config.md +0 -214
  1110. package/plugins/cursor-pbr/references/questioning.md +0 -215
  1111. package/plugins/cursor-pbr/references/reading-verification.md +0 -128
  1112. package/plugins/cursor-pbr/references/stub-patterns.md +0 -161
  1113. package/plugins/cursor-pbr/references/subagent-coordination.md +0 -120
  1114. package/plugins/cursor-pbr/references/ui-formatting.md +0 -444
  1115. package/plugins/cursor-pbr/references/verification-patterns.md +0 -199
  1116. package/plugins/cursor-pbr/references/wave-execution.md +0 -96
  1117. package/plugins/cursor-pbr/rules/pbr-workflow.mdc +0 -48
  1118. package/plugins/cursor-pbr/setup.ps1 +0 -78
  1119. package/plugins/cursor-pbr/setup.sh +0 -83
  1120. package/plugins/cursor-pbr/skills/begin/SKILL.md +0 -589
  1121. package/plugins/cursor-pbr/skills/begin/templates/PROJECT.md.tmpl +0 -34
  1122. package/plugins/cursor-pbr/skills/begin/templates/REQUIREMENTS.md.tmpl +0 -19
  1123. package/plugins/cursor-pbr/skills/begin/templates/STATE.md.tmpl +0 -50
  1124. package/plugins/cursor-pbr/skills/begin/templates/config.json.tmpl +0 -64
  1125. package/plugins/cursor-pbr/skills/begin/templates/researcher-prompt.md.tmpl +0 -20
  1126. package/plugins/cursor-pbr/skills/begin/templates/roadmap-prompt.md.tmpl +0 -31
  1127. package/plugins/cursor-pbr/skills/begin/templates/synthesis-prompt.md.tmpl +0 -17
  1128. package/plugins/cursor-pbr/skills/build/SKILL.md +0 -956
  1129. package/plugins/cursor-pbr/skills/config/SKILL.md +0 -252
  1130. package/plugins/cursor-pbr/skills/continue/SKILL.md +0 -159
  1131. package/plugins/cursor-pbr/skills/dashboard/SKILL.md +0 -44
  1132. package/plugins/cursor-pbr/skills/debug/SKILL.md +0 -512
  1133. package/plugins/cursor-pbr/skills/debug/templates/continuation-prompt.md.tmpl +0 -17
  1134. package/plugins/cursor-pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +0 -28
  1135. package/plugins/cursor-pbr/skills/discuss/SKILL.md +0 -354
  1136. package/plugins/cursor-pbr/skills/discuss/templates/CONTEXT.md.tmpl +0 -62
  1137. package/plugins/cursor-pbr/skills/discuss/templates/decision-categories.md +0 -10
  1138. package/plugins/cursor-pbr/skills/do/SKILL.md +0 -67
  1139. package/plugins/cursor-pbr/skills/explore/SKILL.md +0 -376
  1140. package/plugins/cursor-pbr/skills/health/SKILL.md +0 -274
  1141. package/plugins/cursor-pbr/skills/health/templates/check-pattern.md.tmpl +0 -31
  1142. package/plugins/cursor-pbr/skills/health/templates/output-format.md.tmpl +0 -64
  1143. package/plugins/cursor-pbr/skills/help/SKILL.md +0 -152
  1144. package/plugins/cursor-pbr/skills/import/SKILL.md +0 -505
  1145. package/plugins/cursor-pbr/skills/milestone/SKILL.md +0 -746
  1146. package/plugins/cursor-pbr/skills/milestone/templates/audit-report.md.tmpl +0 -49
  1147. package/plugins/cursor-pbr/skills/milestone/templates/stats-file.md.tmpl +0 -31
  1148. package/plugins/cursor-pbr/skills/note/SKILL.md +0 -214
  1149. package/plugins/cursor-pbr/skills/pause/SKILL.md +0 -248
  1150. package/plugins/cursor-pbr/skills/pause/templates/continue-here.md.tmpl +0 -72
  1151. package/plugins/cursor-pbr/skills/plan/SKILL.md +0 -663
  1152. package/plugins/cursor-pbr/skills/plan/templates/checker-prompt.md.tmpl +0 -22
  1153. package/plugins/cursor-pbr/skills/plan/templates/gap-closure-prompt.md.tmpl +0 -33
  1154. package/plugins/cursor-pbr/skills/plan/templates/planner-prompt.md.tmpl +0 -39
  1155. package/plugins/cursor-pbr/skills/plan/templates/researcher-prompt.md.tmpl +0 -20
  1156. package/plugins/cursor-pbr/skills/plan/templates/revision-prompt.md.tmpl +0 -24
  1157. package/plugins/cursor-pbr/skills/quick/SKILL.md +0 -376
  1158. package/plugins/cursor-pbr/skills/resume/SKILL.md +0 -399
  1159. package/plugins/cursor-pbr/skills/review/SKILL.md +0 -654
  1160. package/plugins/cursor-pbr/skills/review/templates/debugger-prompt.md.tmpl +0 -61
  1161. package/plugins/cursor-pbr/skills/review/templates/gap-planner-prompt.md.tmpl +0 -41
  1162. package/plugins/cursor-pbr/skills/review/templates/verifier-prompt.md.tmpl +0 -116
  1163. package/plugins/cursor-pbr/skills/scan/SKILL.md +0 -300
  1164. package/plugins/cursor-pbr/skills/scan/templates/mapper-prompt.md.tmpl +0 -202
  1165. package/plugins/cursor-pbr/skills/setup/SKILL.md +0 -296
  1166. package/plugins/cursor-pbr/skills/shared/commit-planning-docs.md +0 -36
  1167. package/plugins/cursor-pbr/skills/shared/config-loading.md +0 -103
  1168. package/plugins/cursor-pbr/skills/shared/context-budget.md +0 -41
  1169. package/plugins/cursor-pbr/skills/shared/context-loader-task.md +0 -87
  1170. package/plugins/cursor-pbr/skills/shared/digest-select.md +0 -80
  1171. package/plugins/cursor-pbr/skills/shared/domain-probes.md +0 -126
  1172. package/plugins/cursor-pbr/skills/shared/error-reporting.md +0 -81
  1173. package/plugins/cursor-pbr/skills/shared/gate-prompts.md +0 -389
  1174. package/plugins/cursor-pbr/skills/shared/phase-argument-parsing.md +0 -46
  1175. package/plugins/cursor-pbr/skills/shared/progress-display.md +0 -53
  1176. package/plugins/cursor-pbr/skills/shared/revision-loop.md +0 -82
  1177. package/plugins/cursor-pbr/skills/shared/state-loading.md +0 -63
  1178. package/plugins/cursor-pbr/skills/shared/state-update.md +0 -162
  1179. package/plugins/cursor-pbr/skills/shared/universal-anti-patterns.md +0 -38
  1180. package/plugins/cursor-pbr/skills/status/SKILL.md +0 -362
  1181. package/plugins/cursor-pbr/skills/statusline/SKILL.md +0 -150
  1182. package/plugins/cursor-pbr/skills/todo/SKILL.md +0 -280
  1183. package/plugins/cursor-pbr/templates/CONTEXT.md.tmpl +0 -53
  1184. package/plugins/cursor-pbr/templates/INTEGRATION-REPORT.md.tmpl +0 -152
  1185. package/plugins/cursor-pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -98
  1186. package/plugins/cursor-pbr/templates/ROADMAP.md.tmpl +0 -41
  1187. package/plugins/cursor-pbr/templates/SUMMARY.md.tmpl +0 -82
  1188. package/plugins/cursor-pbr/templates/VERIFICATION-DETAIL.md.tmpl +0 -117
  1189. package/plugins/cursor-pbr/templates/codebase/ARCHITECTURE.md.tmpl +0 -98
  1190. package/plugins/cursor-pbr/templates/codebase/CONCERNS.md.tmpl +0 -93
  1191. package/plugins/cursor-pbr/templates/codebase/CONVENTIONS.md.tmpl +0 -104
  1192. package/plugins/cursor-pbr/templates/codebase/INTEGRATIONS.md.tmpl +0 -78
  1193. package/plugins/cursor-pbr/templates/codebase/STACK.md.tmpl +0 -78
  1194. package/plugins/cursor-pbr/templates/codebase/STRUCTURE.md.tmpl +0 -80
  1195. package/plugins/cursor-pbr/templates/codebase/TESTING.md.tmpl +0 -107
  1196. package/plugins/cursor-pbr/templates/continue-here.md.tmpl +0 -74
  1197. package/plugins/cursor-pbr/templates/prompt-partials/phase-project-context.md.tmpl +0 -38
  1198. package/plugins/cursor-pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
  1199. package/plugins/cursor-pbr/templates/research/STACK.md.tmpl +0 -71
  1200. package/plugins/cursor-pbr/templates/research/SUMMARY.md.tmpl +0 -112
  1201. package/plugins/cursor-pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
  1202. package/plugins/cursor-pbr/templates/research-outputs/project-research.md.tmpl +0 -99
  1203. package/plugins/cursor-pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
  1204. package/plugins/pbr/references/agent-interactions.md +0 -134
  1205. package/plugins/pbr/references/checkpoints.md +0 -157
  1206. package/plugins/pbr/references/pbr-rules.md +0 -194
  1207. package/plugins/pbr/references/planning-config.md +0 -213
  1208. package/plugins/pbr/references/subagent-coordination.md +0 -119
  1209. package/plugins/pbr/references/ui-formatting.md +0 -444
  1210. package/plugins/pbr/references/verification-patterns.md +0 -198
  1211. package/plugins/pbr/scripts/validate-plugin-structure.js +0 -183
  1212. package/plugins/pbr/skills/milestone/templates/audit-report.md.tmpl +0 -48
  1213. package/plugins/pbr/skills/shared/progress-display.md +0 -53
  1214. package/plugins/pbr/skills/shared/state-loading.md +0 -62
  1215. package/plugins/pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -97
  1216. package/plugins/pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
  1217. package/plugins/pbr/templates/research/STACK.md.tmpl +0 -71
  1218. package/plugins/pbr/templates/research/SUMMARY.md.tmpl +0 -112
  1219. package/plugins/pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
  1220. package/plugins/pbr/templates/research-outputs/project-research.md.tmpl +0 -99
  1221. package/plugins/pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
  1222. /package/plugins/pbr/references/{agent-anti-patterns.md → archive/agent-anti-patterns.md} +0 -0
@@ -0,0 +1,1563 @@
1
+ /**
2
+ * lib/core.cjs — Foundation utilities for Plan-Build-Run tools.
3
+ *
4
+ * Pure utility functions with no dependencies on other lib modules.
5
+ * Provides: output/error formatting, YAML frontmatter parsing, status transitions,
6
+ * file operations (atomicWrite, lockedFileUpdate, findFiles, tailLines),
7
+ * session management, phase claiming, path utilities, and shared constants.
8
+ *
9
+ * Hybrid module merging PBR reference features with GSD-unique utilities.
10
+ */
11
+
12
+ const fs = require('fs');
13
+ const os = require('os');
14
+ const path = require('path');
15
+ const { execSync } = require('child_process');
16
+
17
+ // ─── Module-level planningDir with MSYS path bridging ─────────────────────────
18
+
19
+ let cwd = process.env.PBR_PROJECT_ROOT || process.cwd();
20
+
21
+ // MSYS path bridging: convert /c/Users/... to C:\Users\... on Windows
22
+ const msysMatch = cwd.match(/^\/([a-zA-Z])\/(.*)/);
23
+ if (msysMatch) cwd = msysMatch[1] + ':' + path.sep + msysMatch[2];
24
+
25
+ let planningDir = path.join(cwd, '.planning');
26
+
27
+ /**
28
+ * Override the working directory for subagent use.
29
+ * Updates both cwd and planningDir.
30
+ *
31
+ * @param {string} newCwd - New working directory path
32
+ */
33
+ function setCwd(newCwd) {
34
+ cwd = newCwd;
35
+ // Apply MSYS bridging to the new cwd as well
36
+ const m = cwd.match(/^\/([a-zA-Z])\/(.*)/);
37
+ if (m) cwd = m[1] + ':' + path.sep + m[2];
38
+ planningDir = path.join(cwd, '.planning');
39
+ }
40
+
41
+ // ─── Canonical agent list ─────────────────────────────────────────────────────
42
+
43
+ /**
44
+ * Canonical list of known PBR agent types.
45
+ * Used by validate-task and check-subagent-output to avoid drift.
46
+ */
47
+ const KNOWN_AGENTS = [
48
+ 'executor',
49
+ 'planner',
50
+ 'verifier',
51
+ 'researcher',
52
+ 'synthesizer',
53
+ 'plan-checker',
54
+ 'integration-checker',
55
+ 'debugger',
56
+ 'codebase-mapper',
57
+ 'audit',
58
+ 'general',
59
+ 'dev-sync',
60
+ 'roadmapper',
61
+ 'nyquist-auditor',
62
+ 'intel-updater',
63
+ 'ui-checker',
64
+ 'ui-researcher'
65
+ ];
66
+
67
+ // ─── Phase status transition state machine ────────────────────────────────────
68
+
69
+ /**
70
+ * Valid phase status transitions. Each key is a current status, and its value
71
+ * is an array of statuses that are legal to transition to. This is advisory —
72
+ * invalid transitions produce a stderr warning but are not blocked.
73
+ *
74
+ * State machine:
75
+ * pending -> planned, skipped
76
+ * planned -> building
77
+ * building -> built, partial, needs_fixes
78
+ * built -> verified, needs_fixes
79
+ * partial -> building, needs_fixes
80
+ * verified -> building (re-execution)
81
+ * needs_fixes -> planned, building
82
+ * skipped -> pending (unskip)
83
+ */
84
+ const VALID_STATUS_TRANSITIONS = {
85
+ not_started: ['discussed', 'ready_to_plan', 'planned', 'skipped'],
86
+ discussed: ['ready_to_plan', 'planning'],
87
+ ready_to_plan: ['planning', 'planned'],
88
+ planning: ['planned'],
89
+ planned: ['ready_to_execute', 'building'],
90
+ ready_to_execute: ['building'],
91
+ building: ['built', 'partial', 'needs_fixes'],
92
+ built: ['verified', 'needs_fixes'],
93
+ partial: ['building', 'needs_fixes'],
94
+ verified: ['complete', 'building'],
95
+ needs_fixes: ['planned', 'building', 'ready_to_plan'],
96
+ complete: [],
97
+ skipped: ['not_started', 'pending'],
98
+ // Legacy aliases (backward compat)
99
+ pending: ['planned', 'discussed', 'skipped', 'not_started']
100
+ };
101
+
102
+ /**
103
+ * Human-readable labels for plan/phase statuses.
104
+ */
105
+ const STATUS_LABELS = {
106
+ not_started: 'Not Started',
107
+ discussed: 'Discussed',
108
+ ready_to_plan: 'Ready to Plan',
109
+ planning: 'Planning',
110
+ planned: 'Planned',
111
+ ready_to_execute: 'Ready to Execute',
112
+ building: 'Building',
113
+ built: 'Built',
114
+ partial: 'Partial',
115
+ verified: 'Verified',
116
+ needs_fixes: 'Needs Fixes',
117
+ complete: 'Complete',
118
+ skipped: 'Skipped',
119
+ // Legacy aliases
120
+ pending: 'Not Started',
121
+ reviewed: 'Verified'
122
+ };
123
+
124
+ /**
125
+ * Check whether a phase status transition is valid according to the state machine.
126
+ * Returns { valid, warning? } — never blocks, only advises.
127
+ *
128
+ * @param {string} oldStatus - Current phase status
129
+ * @param {string} newStatus - Desired phase status
130
+ * @returns {{ valid: boolean, warning?: string }}
131
+ */
132
+ function validateStatusTransition(oldStatus, newStatus) {
133
+ const from = (oldStatus || '').trim().toLowerCase();
134
+ const to = (newStatus || '').trim().toLowerCase();
135
+
136
+ if (from === to) return { valid: true };
137
+
138
+ if (!VALID_STATUS_TRANSITIONS[from]) return { valid: true };
139
+
140
+ const allowed = VALID_STATUS_TRANSITIONS[from];
141
+ if (allowed.includes(to)) return { valid: true };
142
+
143
+ return {
144
+ valid: false,
145
+ warning: `Suspicious status transition: "${from}" -> "${to}". Expected one of: [${allowed.join(', ')}]. Proceeding anyway (advisory).`
146
+ };
147
+ }
148
+
149
+ // ─── Model Profile Table ─────────────────────────────────────────────────────
150
+
151
+ const MODEL_PROFILES = {
152
+ 'pbr-planner': { quality: 'opus', balanced: 'opus', budget: 'sonnet' },
153
+ 'pbr-roadmapper': { quality: 'opus', balanced: 'sonnet', budget: 'sonnet' },
154
+ 'pbr-executor': { quality: 'opus', balanced: 'sonnet', budget: 'sonnet' },
155
+ 'pbr-researcher': { quality: 'opus', balanced: 'sonnet', budget: 'haiku' },
156
+ 'pbr-synthesizer': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
157
+ 'pbr-debugger': { quality: 'opus', balanced: 'sonnet', budget: 'sonnet' },
158
+ 'pbr-codebase-mapper': { quality: 'sonnet', balanced: 'haiku', budget: 'haiku' },
159
+ 'pbr-verifier': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
160
+ 'pbr-plan-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
161
+ 'pbr-integration-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
162
+ 'pbr-nyquist-auditor': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
163
+ };
164
+
165
+ // ─── Path helpers ─────────────────────────────────────────────────────────────
166
+
167
+ /** Normalize a path to always use forward slashes (cross-platform). */
168
+ function toPosixPath(p) {
169
+ return p.split(path.sep).join('/');
170
+ }
171
+
172
+ // ─── Output helpers ───────────────────────────────────────────────────────────
173
+
174
+ function output(data, raw, rawValue) {
175
+ if (raw && rawValue !== undefined) {
176
+ process.stdout.write(String(rawValue));
177
+ } else {
178
+ const json = JSON.stringify(data, null, 2);
179
+ if (json.length > 50000) {
180
+ const tmpPath = path.join(os.tmpdir(), `pbr-${Date.now()}.json`);
181
+ fs.writeFileSync(tmpPath, json, 'utf8');
182
+ process.stdout.write('@file:' + tmpPath + '\n');
183
+ } else {
184
+ process.stdout.write(json + '\n');
185
+ }
186
+ }
187
+ process.exit(0);
188
+ }
189
+
190
+ function error(msg) {
191
+ process.stderr.write('Error: ' + msg + '\n');
192
+ process.exit(1);
193
+ }
194
+
195
+ // ─── File & path utilities ────────────────────────────────────────────────────
196
+
197
+ /**
198
+ * Read a file safely, returning null on any error.
199
+ *
200
+ * @param {string} filePath - Absolute path to the file
201
+ * @returns {string|null} File contents or null
202
+ */
203
+ function safeReadFile(filePath) {
204
+ try {
205
+ return fs.readFileSync(filePath, 'utf8');
206
+ } catch {
207
+ return null;
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Ensure a directory exists, creating it recursively if needed.
213
+ *
214
+ * @param {string} dirPath - Directory path to ensure
215
+ */
216
+ function ensureDir(dirPath) {
217
+ fs.mkdirSync(dirPath, { recursive: true });
218
+ }
219
+
220
+ /**
221
+ * Find files in a directory matching a regex pattern.
222
+ *
223
+ * @param {string} dir - Directory to search
224
+ * @param {RegExp} pattern - Pattern to match filenames against
225
+ * @returns {string[]} Sorted array of matching filenames
226
+ */
227
+ function findFiles(dir, pattern) {
228
+ try {
229
+ return fs.readdirSync(dir).filter(f => pattern.test(f)).sort();
230
+ } catch (_) {
231
+ return [];
232
+ }
233
+ }
234
+
235
+ /**
236
+ * Read the last N lines from a file.
237
+ *
238
+ * @param {string} filePath - Absolute path to the file
239
+ * @param {number} n - Number of trailing lines to return
240
+ * @returns {string[]} Array of line strings
241
+ */
242
+ function tailLines(filePath, n) {
243
+ try {
244
+ if (!fs.existsSync(filePath)) return [];
245
+ const content = fs.readFileSync(filePath, 'utf8').trim();
246
+ if (!content) return [];
247
+ const lines = content.replace(/\r\n/g, '\n').split('\n');
248
+ if (lines.length <= n) return lines;
249
+ return lines.slice(lines.length - n);
250
+ } catch (_e) {
251
+ return [];
252
+ }
253
+ }
254
+
255
+ // ─── Git utilities ────────────────────────────────────────────────────────────
256
+
257
+ /**
258
+ * Execute a git command and return the result.
259
+ *
260
+ * @param {string} gitCwd - Working directory for git
261
+ * @param {string[]} args - Git command arguments
262
+ * @returns {{ exitCode: number, stdout: string, stderr: string }}
263
+ */
264
+ function execGit(gitCwd, args) {
265
+ try {
266
+ const escaped = args.map(a => {
267
+ if (/^[a-zA-Z0-9._\-/=:@]+$/.test(a)) return a;
268
+ return "'" + a.replace(/'/g, "'\\''") + "'";
269
+ });
270
+ const stdout = execSync('git ' + escaped.join(' '), {
271
+ cwd: gitCwd,
272
+ stdio: 'pipe',
273
+ encoding: 'utf-8',
274
+ });
275
+ return { exitCode: 0, stdout: stdout.trim(), stderr: '' };
276
+ } catch (err) {
277
+ return {
278
+ exitCode: err.status ?? 1,
279
+ stdout: (err.stdout ?? '').toString().trim(),
280
+ stderr: (err.stderr ?? '').toString().trim(),
281
+ };
282
+ }
283
+ }
284
+
285
+ /**
286
+ * Check if a path is git-ignored.
287
+ *
288
+ * @param {string} gitCwd - Working directory
289
+ * @param {string} targetPath - Path to check
290
+ * @returns {boolean}
291
+ */
292
+ function isGitIgnored(gitCwd, targetPath) {
293
+ try {
294
+ execSync('git check-ignore -q --no-index -- ' + targetPath.replace(/[^a-zA-Z0-9._\-/]/g, ''), {
295
+ cwd: gitCwd,
296
+ stdio: 'pipe',
297
+ });
298
+ return true;
299
+ } catch {
300
+ return false;
301
+ }
302
+ }
303
+
304
+ // ─── YAML frontmatter parsing ─────────────────────────────────────────────────
305
+
306
+ /**
307
+ * Parse YAML frontmatter from markdown content.
308
+ * Handles flat key-value pairs, inline arrays, and multi-line arrays.
309
+ *
310
+ * @param {string} content - Markdown content with optional frontmatter
311
+ * @returns {object} Parsed frontmatter as a plain object
312
+ */
313
+ function parseYamlFrontmatter(content) {
314
+ const normalized = content.replace(/\r\n/g, '\n');
315
+ const match = normalized.match(/^---\s*\n([\s\S]*?)\n---/);
316
+ if (!match) return {};
317
+
318
+ const yaml = match[1];
319
+ const result = {};
320
+
321
+ const lines = yaml.split('\n');
322
+ let currentKey = null;
323
+
324
+ for (const line of lines) {
325
+ // Array item
326
+ if (/^\s+-\s+/.test(line) && currentKey) {
327
+ const val = line.replace(/^\s+-\s+/, '').trim().replace(/^["']|["']$/g, '');
328
+ if (!result[currentKey]) result[currentKey] = [];
329
+ if (Array.isArray(result[currentKey])) {
330
+ result[currentKey].push(val);
331
+ }
332
+ continue;
333
+ }
334
+
335
+ // Key-value pair
336
+ const kvMatch = line.match(/^(\w[\w_]*)\s*:\s*(.*)/);
337
+ if (kvMatch) {
338
+ currentKey = kvMatch[1];
339
+ let val = kvMatch[2].trim();
340
+
341
+ if (val === '' || val === '|') continue;
342
+
343
+ // Handle arrays on same line: [a, b, c]
344
+ if (val.startsWith('[') && val.endsWith(']')) {
345
+ result[currentKey] = val.slice(1, -1).split(',')
346
+ .map(v => v.trim().replace(/^["']|["']$/g, ''))
347
+ .filter(Boolean);
348
+ continue;
349
+ }
350
+
351
+ // Clean quotes
352
+ val = val.replace(/^["']|["']$/g, '');
353
+
354
+ // Type coercion
355
+ if (val === 'true') val = true;
356
+ else if (val === 'false') val = false;
357
+ else if (/^\d+$/.test(val)) val = parseInt(val, 10);
358
+
359
+ result[currentKey] = val;
360
+ }
361
+ }
362
+
363
+ // Handle must_haves as a nested object
364
+ if (yaml.includes('must_haves:')) {
365
+ result.must_haves = parseMustHaves(yaml);
366
+ }
367
+
368
+ return result;
369
+ }
370
+
371
+ /**
372
+ * Parse the must_haves section from YAML frontmatter.
373
+ *
374
+ * @param {string} yaml - Raw YAML content (without --- delimiters)
375
+ * @returns {{ truths: string[], artifacts: string[], key_links: string[] }}
376
+ */
377
+ function parseMustHaves(yaml) {
378
+ const result = { truths: [], artifacts: [], key_links: [] };
379
+ let section = null;
380
+
381
+ const inMustHaves = yaml.replace(/\r\n/g, '\n').split('\n');
382
+ let collecting = false;
383
+
384
+ for (const line of inMustHaves) {
385
+ if (/^\s*must_haves:/.test(line)) {
386
+ collecting = true;
387
+ continue;
388
+ }
389
+ if (collecting) {
390
+ if (/^\s{2}truths:/.test(line)) { section = 'truths'; continue; }
391
+ if (/^\s{2}artifacts:/.test(line)) { section = 'artifacts'; continue; }
392
+ if (/^\s{2}key_links:/.test(line)) { section = 'key_links'; continue; }
393
+ if (/^\w/.test(line)) break;
394
+
395
+ if (section && /^\s+-\s+/.test(line)) {
396
+ result[section].push(line.replace(/^\s+-\s+/, '').trim().replace(/^["']|["']$/g, ''));
397
+ }
398
+ }
399
+ }
400
+
401
+ return result;
402
+ }
403
+
404
+ /**
405
+ * Set/update YAML frontmatter fields in markdown content.
406
+ * Creates frontmatter block if none exists.
407
+ *
408
+ * @param {string} content - Markdown content
409
+ * @param {object} updates - Key-value pairs to set in frontmatter
410
+ * @returns {string} Updated content
411
+ */
412
+ function setYamlFrontmatter(content, updates) {
413
+ const normalized = content.replace(/\r\n/g, '\n');
414
+ const match = normalized.match(/^---\s*\n([\s\S]*?)\n---/);
415
+
416
+ if (!match) {
417
+ // No existing frontmatter — create one
418
+ const lines = Object.entries(updates).map(([k, v]) => {
419
+ if (Array.isArray(v)) {
420
+ return `${k}:\n${v.map(item => ` - ${item}`).join('\n')}`;
421
+ }
422
+ if (typeof v === 'string' && (v.includes(':') || v.includes('#'))) {
423
+ return `${k}: "${v}"`;
424
+ }
425
+ return `${k}: ${v}`;
426
+ });
427
+ return `---\n${lines.join('\n')}\n---\n${normalized}`;
428
+ }
429
+
430
+ let yaml = match[1];
431
+
432
+ for (const [key, value] of Object.entries(updates)) {
433
+ const keyRegex = new RegExp(`^(${key})\\s*:.*$`, 'm');
434
+ const formatted = typeof value === 'string' && (value.includes(':') || value.includes('#'))
435
+ ? `"${value}"`
436
+ : String(value);
437
+
438
+ if (keyRegex.test(yaml)) {
439
+ yaml = yaml.replace(keyRegex, `${key}: ${formatted}`);
440
+ } else {
441
+ yaml += `\n${key}: ${formatted}`;
442
+ }
443
+ }
444
+
445
+ return normalized.replace(/^---\s*\n[\s\S]*?\n---/, `---\n${yaml}\n---`);
446
+ }
447
+
448
+ // ─── Misc utilities ───────────────────────────────────────────────────────────
449
+
450
+ function countMustHaves(mustHaves) {
451
+ if (!mustHaves) return 0;
452
+ return (mustHaves.truths || []).length +
453
+ (mustHaves.artifacts || []).length +
454
+ (mustHaves.key_links || []).length;
455
+ }
456
+
457
+ function determinePhaseStatus(planCount, completedCount, summaryCount, hasVerification, phaseDir) {
458
+ if (planCount === 0) {
459
+ if (fs.existsSync(path.join(phaseDir, 'CONTEXT.md'))) return 'discussed';
460
+ return 'not_started';
461
+ }
462
+ if (completedCount === 0 && summaryCount === 0) return 'planned';
463
+ if (completedCount < planCount) return 'building';
464
+ if (!hasVerification) return 'built';
465
+ try {
466
+ const vContent = fs.readFileSync(path.join(phaseDir, 'VERIFICATION.md'), 'utf8');
467
+ if (/status:\s*["']?passed/i.test(vContent)) return 'verified';
468
+ if (/status:\s*["']?gaps_found/i.test(vContent)) return 'needs_fixes';
469
+ return 'reviewed';
470
+ } catch (_) {
471
+ return 'built';
472
+ }
473
+ }
474
+
475
+ function calculateProgress(pDir) {
476
+ const phasesDir = path.join(pDir, 'phases');
477
+ if (!fs.existsSync(phasesDir)) {
478
+ return { total: 0, completed: 0, percentage: 0 };
479
+ }
480
+
481
+ let total = 0;
482
+ let completed = 0;
483
+
484
+ const entries = fs.readdirSync(phasesDir, { withFileTypes: true })
485
+ .filter(e => e.isDirectory());
486
+
487
+ for (const entry of entries) {
488
+ const dir = path.join(phasesDir, entry.name);
489
+ const plans = findFiles(dir, /PLAN.*\.md$/i);
490
+ total += plans.length;
491
+
492
+ const summaries = findFiles(dir, /^SUMMARY-.*\.md$/);
493
+ for (const s of summaries) {
494
+ const content = fs.readFileSync(path.join(dir, s), 'utf8');
495
+ if (/status:\s*["']?complete/i.test(content)) completed++;
496
+ }
497
+ }
498
+
499
+ return {
500
+ total,
501
+ completed,
502
+ percentage: total > 0 ? Math.round((completed / total) * 100) : 0
503
+ };
504
+ }
505
+
506
+ /**
507
+ * Return an ISO 8601 UTC timestamp string.
508
+ *
509
+ * @returns {string} ISO timestamp
510
+ */
511
+ function currentTimestamp() {
512
+ return new Date().toISOString();
513
+ }
514
+
515
+ /**
516
+ * Generate a URL-safe slug from a string.
517
+ *
518
+ * @param {string} text - Input text
519
+ * @returns {string|null} Slugified string or null
520
+ */
521
+ function generateSlug(text) {
522
+ if (!text) return null;
523
+ return text.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
524
+ }
525
+
526
+ /**
527
+ * Resolve the model name for an agent type based on config.
528
+ *
529
+ * @param {string} agentType - Agent type key (e.g., 'pbr-executor')
530
+ * @param {object} config - Config object with model_profile and optional model_overrides
531
+ * @returns {string} Resolved model name
532
+ */
533
+ function resolveModel(agentType, config) {
534
+ // Check per-agent override first
535
+ const override = config && config.model_overrides && config.model_overrides[agentType];
536
+ if (override) {
537
+ return override === 'opus' ? 'inherit' : override;
538
+ }
539
+
540
+ // Fall back to profile lookup
541
+ const profile = (config && config.model_profile) || 'balanced';
542
+ const agentModels = MODEL_PROFILES[agentType];
543
+ if (!agentModels) return 'sonnet';
544
+ const resolved = agentModels[profile] || agentModels['balanced'] || 'sonnet';
545
+ return resolved === 'opus' ? 'inherit' : resolved;
546
+ }
547
+
548
+ // ─── Regex and phase utilities ────────────────────────────────────────────────
549
+
550
+ function escapeRegex(value) {
551
+ return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
552
+ }
553
+
554
+ function normalizePhaseName(phase) {
555
+ const match = String(phase).match(/^(\d+)([A-Z])?((?:\.\d+)*)/i);
556
+ if (!match) return phase;
557
+ const padded = match[1].padStart(2, '0');
558
+ const letter = match[2] ? match[2].toUpperCase() : '';
559
+ const decimal = match[3] || '';
560
+ return padded + letter + decimal;
561
+ }
562
+
563
+ function comparePhaseNum(a, b) {
564
+ const pa = String(a).match(/^(\d+)([A-Z])?((?:\.\d+)*)/i);
565
+ const pb = String(b).match(/^(\d+)([A-Z])?((?:\.\d+)*)/i);
566
+ if (!pa || !pb) return String(a).localeCompare(String(b));
567
+ const intDiff = parseInt(pa[1], 10) - parseInt(pb[1], 10);
568
+ if (intDiff !== 0) return intDiff;
569
+ const la = (pa[2] || '').toUpperCase();
570
+ const lb = (pb[2] || '').toUpperCase();
571
+ if (la !== lb) {
572
+ if (!la) return -1;
573
+ if (!lb) return 1;
574
+ return la < lb ? -1 : 1;
575
+ }
576
+ const aDecParts = pa[3] ? pa[3].slice(1).split('.').map(p => parseInt(p, 10)) : [];
577
+ const bDecParts = pb[3] ? pb[3].slice(1).split('.').map(p => parseInt(p, 10)) : [];
578
+ const maxLen = Math.max(aDecParts.length, bDecParts.length);
579
+ if (aDecParts.length === 0 && bDecParts.length > 0) return -1;
580
+ if (bDecParts.length === 0 && aDecParts.length > 0) return 1;
581
+ for (let i = 0; i < maxLen; i++) {
582
+ const av = Number.isFinite(aDecParts[i]) ? aDecParts[i] : 0;
583
+ const bv = Number.isFinite(bDecParts[i]) ? bDecParts[i] : 0;
584
+ if (av !== bv) return av - bv;
585
+ }
586
+ return 0;
587
+ }
588
+
589
+ function searchPhaseInDir(baseDir, relBase, normalized) {
590
+ try {
591
+ const entries = fs.readdirSync(baseDir, { withFileTypes: true });
592
+ const dirs = entries.filter(e => e.isDirectory()).map(e => e.name).sort((a, b) => comparePhaseNum(a, b));
593
+ const match = dirs.find(d => d.startsWith(normalized));
594
+ if (!match) return null;
595
+
596
+ const dirMatch = match.match(/^(\d+[A-Z]?(?:\.\d+)*)-?(.*)/i);
597
+ const phaseNumber = dirMatch ? dirMatch[1] : normalized;
598
+ const phaseName = dirMatch && dirMatch[2] ? dirMatch[2] : null;
599
+ const phaseDir = path.join(baseDir, match);
600
+ const phaseFiles = fs.readdirSync(phaseDir);
601
+
602
+ const plans = phaseFiles.filter(f => f.endsWith('-PLAN.md') || f === 'PLAN.md').sort();
603
+ const summaries = phaseFiles.filter(f => f.endsWith('-SUMMARY.md') || f === 'SUMMARY.md').sort();
604
+ const hasResearch = phaseFiles.some(f => f.endsWith('-RESEARCH.md') || f === 'RESEARCH.md');
605
+ const hasContext = phaseFiles.some(f => f.endsWith('-CONTEXT.md') || f === 'CONTEXT.md');
606
+ const hasVerification = phaseFiles.some(f => f.endsWith('-VERIFICATION.md') || f === 'VERIFICATION.md');
607
+
608
+ const completedPlanIds = new Set(
609
+ summaries.map(s => s.replace('-SUMMARY.md', '').replace('SUMMARY.md', ''))
610
+ );
611
+ const incompletePlans = plans.filter(p => {
612
+ const planId = p.replace('-PLAN.md', '').replace('PLAN.md', '');
613
+ return !completedPlanIds.has(planId);
614
+ });
615
+
616
+ return {
617
+ found: true,
618
+ directory: toPosixPath(path.join(relBase, match)),
619
+ phase_number: phaseNumber,
620
+ phase_name: phaseName,
621
+ phase_slug: phaseName ? phaseName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') : null,
622
+ plans,
623
+ summaries,
624
+ incomplete_plans: incompletePlans,
625
+ has_research: hasResearch,
626
+ has_context: hasContext,
627
+ has_verification: hasVerification,
628
+ };
629
+ } catch {
630
+ return null;
631
+ }
632
+ }
633
+
634
+ function findPhaseInternal(phaseCwd, phase) {
635
+ if (!phase) return null;
636
+
637
+ const phasesDir = path.join(phaseCwd, '.planning', 'phases');
638
+ const normalized = normalizePhaseName(phase);
639
+
640
+ const current = searchPhaseInDir(phasesDir, '.planning/phases', normalized);
641
+ if (current) return current;
642
+
643
+ const milestonesDir = path.join(phaseCwd, '.planning', 'milestones');
644
+ if (!fs.existsSync(milestonesDir)) return null;
645
+
646
+ try {
647
+ const milestoneEntries = fs.readdirSync(milestonesDir, { withFileTypes: true });
648
+ const archiveDirs = milestoneEntries
649
+ .filter(e => e.isDirectory() && /^v[\d.]+-phases$/.test(e.name))
650
+ .map(e => e.name)
651
+ .sort()
652
+ .reverse();
653
+
654
+ for (const archiveName of archiveDirs) {
655
+ const version = archiveName.match(/^(v[\d.]+)-phases$/)[1];
656
+ const archivePath = path.join(milestonesDir, archiveName);
657
+ const relBase = '.planning/milestones/' + archiveName;
658
+ const result = searchPhaseInDir(archivePath, relBase, normalized);
659
+ if (result) {
660
+ result.archived = version;
661
+ return result;
662
+ }
663
+ }
664
+ } catch { /* best effort */ }
665
+
666
+ return null;
667
+ }
668
+
669
+ function getArchivedPhaseDirs(archCwd) {
670
+ const milestonesDir = path.join(archCwd, '.planning', 'milestones');
671
+ const results = [];
672
+
673
+ if (!fs.existsSync(milestonesDir)) return results;
674
+
675
+ try {
676
+ const milestoneEntries = fs.readdirSync(milestonesDir, { withFileTypes: true });
677
+ const phaseDirs = milestoneEntries
678
+ .filter(e => e.isDirectory() && /^v[\d.]+-phases$/.test(e.name))
679
+ .map(e => e.name)
680
+ .sort()
681
+ .reverse();
682
+
683
+ for (const archiveName of phaseDirs) {
684
+ const version = archiveName.match(/^(v[\d.]+)-phases$/)[1];
685
+ const archivePath = path.join(milestonesDir, archiveName);
686
+ const entries = fs.readdirSync(archivePath, { withFileTypes: true });
687
+ const dirs = entries.filter(e => e.isDirectory()).map(e => e.name).sort((a, b) => comparePhaseNum(a, b));
688
+
689
+ for (const dir of dirs) {
690
+ results.push({
691
+ name: dir,
692
+ milestone: version,
693
+ basePath: path.join('.planning', 'milestones', archiveName),
694
+ fullPath: path.join(archivePath, dir),
695
+ });
696
+ }
697
+ }
698
+ } catch { /* best effort */ }
699
+
700
+ return results;
701
+ }
702
+
703
+ // ─── Roadmap & milestone utilities ────────────────────────────────────────────
704
+
705
+ function getRoadmapPhaseInternal(rmCwd, phaseNum) {
706
+ if (!phaseNum) return null;
707
+ const roadmapPath = path.join(rmCwd, '.planning', 'ROADMAP.md');
708
+ if (!fs.existsSync(roadmapPath)) return null;
709
+
710
+ try {
711
+ const content = fs.readFileSync(roadmapPath, 'utf8');
712
+ const escapedPhase = escapeRegex(phaseNum.toString());
713
+ const phasePattern = new RegExp(`#{2,4}\\s*Phase\\s+${escapedPhase}:\\s*([^\\n]+)`, 'i');
714
+ const headerMatch = content.match(phasePattern);
715
+ if (!headerMatch) return null;
716
+
717
+ const phaseName = headerMatch[1].trim();
718
+ const headerIndex = headerMatch.index;
719
+ const restOfContent = content.slice(headerIndex);
720
+ const nextHeaderMatch = restOfContent.match(/\n#{2,4}\s+Phase\s+\d/i);
721
+ const sectionEnd = nextHeaderMatch ? headerIndex + nextHeaderMatch.index : content.length;
722
+ const section = content.slice(headerIndex, sectionEnd).trim();
723
+
724
+ const goalMatch = section.match(/\*\*Goal:\*\*\s*([^\n]+)/i);
725
+ const goal = goalMatch ? goalMatch[1].trim() : null;
726
+
727
+ return {
728
+ found: true,
729
+ phase_number: phaseNum.toString(),
730
+ phase_name: phaseName,
731
+ goal,
732
+ section,
733
+ };
734
+ } catch {
735
+ return null;
736
+ }
737
+ }
738
+
739
+ function getMilestoneInfo(miCwd) {
740
+ try {
741
+ const roadmap = fs.readFileSync(path.join(miCwd, '.planning', 'ROADMAP.md'), 'utf8');
742
+
743
+ const inProgressMatch = roadmap.match(/\u{1F6A7}\s*\*\*v(\d+\.\d+)\s+([^*]+)\*\*/u);
744
+ if (inProgressMatch) {
745
+ return {
746
+ version: 'v' + inProgressMatch[1],
747
+ name: inProgressMatch[2].trim(),
748
+ };
749
+ }
750
+
751
+ const cleaned = roadmap.replace(/<details>[\s\S]*?<\/details>/gi, '');
752
+ const headingMatch = cleaned.match(/## .*v(\d+\.\d+)[:\s]+([^\n(]+)/);
753
+ if (headingMatch) {
754
+ return {
755
+ version: 'v' + headingMatch[1],
756
+ name: headingMatch[2].trim(),
757
+ };
758
+ }
759
+ const versionMatch = cleaned.match(/v(\d+\.\d+)/);
760
+ return {
761
+ version: versionMatch ? versionMatch[0] : 'v1.0',
762
+ name: 'milestone',
763
+ };
764
+ } catch {
765
+ return { version: 'v1.0', name: 'milestone' };
766
+ }
767
+ }
768
+
769
+ /**
770
+ * Returns a filter function that checks whether a phase directory belongs
771
+ * to the current milestone based on ROADMAP.md phase headings.
772
+ */
773
+ function getMilestonePhaseFilter(filterCwd) {
774
+ const milestonePhaseNums = new Set();
775
+ try {
776
+ const roadmap = fs.readFileSync(path.join(filterCwd, '.planning', 'ROADMAP.md'), 'utf8');
777
+ const phasePattern = /#{2,4}\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:/gi;
778
+ let m;
779
+ while ((m = phasePattern.exec(roadmap)) !== null) {
780
+ milestonePhaseNums.add(m[1]);
781
+ }
782
+ } catch { /* best effort */ }
783
+
784
+ if (milestonePhaseNums.size === 0) {
785
+ const passAll = () => true;
786
+ passAll.phaseCount = 0;
787
+ return passAll;
788
+ }
789
+
790
+ const normalized = new Set(
791
+ [...milestonePhaseNums].map(n => (n.replace(/^0+/, '') || '0').toLowerCase())
792
+ );
793
+
794
+ function isDirInMilestone(dirName) {
795
+ const dm = dirName.match(/^0*(\d+[A-Za-z]?(?:\.\d+)*)/);
796
+ if (!dm) return false;
797
+ return normalized.has(dm[1].toLowerCase());
798
+ }
799
+ isDirInMilestone.phaseCount = milestonePhaseNums.size;
800
+ return isDirInMilestone;
801
+ }
802
+
803
+ // ─── Atomic file operations ───────────────────────────────────────────────────
804
+
805
+ /**
806
+ * Write content to a file atomically: write to .tmp, backup original to .bak,
807
+ * rename .tmp over original. On failure, restore from .bak if available.
808
+ *
809
+ * @param {string} filePath - Target file path
810
+ * @param {string} content - Content to write
811
+ * @returns {{success: boolean, error?: string}} Result
812
+ */
813
+ function atomicWrite(filePath, content) {
814
+ const tmpPath = filePath + '.tmp';
815
+ const bakPath = filePath + '.bak';
816
+
817
+ try {
818
+ fs.writeFileSync(tmpPath, content, 'utf8');
819
+
820
+ if (fs.existsSync(filePath)) {
821
+ try { fs.copyFileSync(filePath, bakPath); } catch (_e) { /* non-fatal */ }
822
+ }
823
+
824
+ fs.renameSync(tmpPath, filePath);
825
+
826
+ try {
827
+ if (fs.existsSync(bakPath)) fs.unlinkSync(bakPath);
828
+ } catch (_e) { /* non-fatal */ }
829
+
830
+ return { success: true };
831
+ } catch (e) {
832
+ try {
833
+ if (fs.existsSync(bakPath)) fs.copyFileSync(bakPath, filePath);
834
+ } catch (_restoreErr) { /* nothing more we can do */ }
835
+ try {
836
+ if (fs.existsSync(tmpPath)) fs.unlinkSync(tmpPath);
837
+ } catch (_cleanupErr) { /* best effort */ }
838
+
839
+ return { success: false, error: e.message };
840
+ }
841
+ }
842
+
843
+ /**
844
+ * Locked file update: read-modify-write with exclusive lockfile.
845
+ * Prevents concurrent writes to STATE.md and ROADMAP.md.
846
+ *
847
+ * @param {string} filePath - Absolute path to the file to update
848
+ * @param {function} updateFn - Receives current content, returns new content
849
+ * @param {object} opts - Options: { retries: 3, retryDelayMs: 100, timeoutMs: 5000 }
850
+ * @returns {object} { success, content?, error? }
851
+ */
852
+ function lockedFileUpdate(filePath, updateFn, opts = {}) {
853
+ const retries = opts.retries || 3;
854
+ const retryDelayMs = opts.retryDelayMs || 100;
855
+ const timeoutMs = opts.timeoutMs || 5000;
856
+ const lockPath = filePath + '.lock';
857
+
858
+ let lockFd = null;
859
+ let lockAcquired = false;
860
+
861
+ try {
862
+ for (let attempt = 0; attempt < retries; attempt++) {
863
+ try {
864
+ lockFd = fs.openSync(lockPath, 'wx');
865
+ lockAcquired = true;
866
+ break;
867
+ } catch (e) {
868
+ if (e.code === 'EEXIST') {
869
+ try {
870
+ const stats = fs.statSync(lockPath);
871
+ if (Date.now() - stats.mtimeMs > timeoutMs) {
872
+ fs.unlinkSync(lockPath);
873
+ continue;
874
+ }
875
+ } catch (_statErr) {
876
+ continue;
877
+ }
878
+
879
+ if (attempt < retries - 1) {
880
+ const waitMs = retryDelayMs * (attempt + 1);
881
+ try {
882
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, waitMs);
883
+ } catch (_atomicsErr) {
884
+ const end = Date.now() + waitMs;
885
+ while (Date.now() < end) { /* last-resort fallback */ }
886
+ }
887
+ continue;
888
+ }
889
+ return { success: false, error: `Could not acquire lock for ${path.basename(filePath)} after ${retries} attempts` };
890
+ }
891
+ throw e;
892
+ }
893
+ }
894
+
895
+ if (!lockAcquired) {
896
+ return { success: false, error: `Could not acquire lock for ${path.basename(filePath)}` };
897
+ }
898
+
899
+ fs.writeSync(lockFd, `${process.pid}`);
900
+ fs.closeSync(lockFd);
901
+ lockFd = null;
902
+
903
+ let content = '';
904
+ if (fs.existsSync(filePath)) {
905
+ content = fs.readFileSync(filePath, 'utf8');
906
+ }
907
+
908
+ const newContent = updateFn(content);
909
+
910
+ const writeResult = atomicWrite(filePath, newContent);
911
+ if (!writeResult.success) {
912
+ return { success: false, error: writeResult.error };
913
+ }
914
+
915
+ return { success: true, content: newContent };
916
+ } catch (e) {
917
+ return { success: false, error: e.message };
918
+ } finally {
919
+ try {
920
+ if (lockFd !== null) fs.closeSync(lockFd);
921
+ } catch (_e) { /* ignore */ }
922
+ if (lockAcquired) {
923
+ try { fs.unlinkSync(lockPath); } catch (_e) { /* ignore */ }
924
+ }
925
+ }
926
+ }
927
+
928
+ // ─── Lightweight JSON Schema validator ────────────────────────────────────────
929
+
930
+ /**
931
+ * Validate an object against a simple JSON Schema subset.
932
+ * Supports type, enum, properties, additionalProperties, minimum, maximum.
933
+ *
934
+ * @param {*} value - Value to validate
935
+ * @param {object} schema - JSON Schema subset
936
+ * @param {string} prefix - Path prefix for error messages
937
+ * @param {string[]} errors - Array to push errors to
938
+ * @param {string[]} warnings - Array to push warnings to
939
+ */
940
+ function validateObject(value, schema, prefix, errors, warnings) {
941
+ if (schema.type) {
942
+ const types = Array.isArray(schema.type) ? schema.type : [schema.type];
943
+ const actualType = typeof value;
944
+ const typeMatch = types.some(t => {
945
+ if (t === 'integer') return actualType === 'number' && Number.isInteger(value);
946
+ return actualType === t;
947
+ });
948
+ if (!typeMatch) {
949
+ errors.push(`${prefix || 'root'}: expected ${types.join('|')}, got ${actualType}`);
950
+ return;
951
+ }
952
+ }
953
+
954
+ if (schema.enum && !schema.enum.includes(value)) {
955
+ errors.push(`${prefix || 'root'}: value "${value}" not in allowed values [${schema.enum.join(', ')}]`);
956
+ return;
957
+ }
958
+
959
+ if (schema.minimum !== undefined && value < schema.minimum) {
960
+ errors.push(`${prefix || 'root'}: value ${value} is below minimum ${schema.minimum}`);
961
+ }
962
+ if (schema.maximum !== undefined && value > schema.maximum) {
963
+ errors.push(`${prefix || 'root'}: value ${value} is above maximum ${schema.maximum}`);
964
+ }
965
+
966
+ if (schema.type === 'object' && schema.properties) {
967
+ const knownKeys = new Set(Object.keys(schema.properties));
968
+ for (const key of Object.keys(value)) {
969
+ const fullKey = prefix ? `${prefix}.${key}` : key;
970
+ if (!knownKeys.has(key)) {
971
+ if (schema.additionalProperties === false) {
972
+ warnings.push(`${fullKey}: unrecognized key (possible typo?)`);
973
+ }
974
+ continue;
975
+ }
976
+ validateObject(value[key], schema.properties[key], fullKey, errors, warnings);
977
+ }
978
+ }
979
+ }
980
+
981
+ // ─── Session-scoped path resolution ───────────────────────────────────────────
982
+
983
+ const STALE_SESSION_MS = 4 * 60 * 60 * 1000; // 4 hours
984
+
985
+ /**
986
+ * Resolve a session-scoped file path.
987
+ *
988
+ * @param {string} pDir - Path to .planning/ directory
989
+ * @param {string} filename - Filename to resolve
990
+ * @param {string} sessionId - Session identifier
991
+ * @returns {string} Resolved path
992
+ */
993
+ function resolveSessionPath(pDir, filename, sessionId) {
994
+ return path.join(pDir, '.sessions', sessionId, filename);
995
+ }
996
+
997
+ /**
998
+ * Ensure session directory exists and write meta.json.
999
+ *
1000
+ * @param {string} pDir - Path to .planning/ directory
1001
+ * @param {string} sessionId - Session identifier
1002
+ */
1003
+ function ensureSessionDir(pDir, sessionId) {
1004
+ const dirPath = path.join(pDir, '.sessions', sessionId);
1005
+ fs.mkdirSync(dirPath, { recursive: true });
1006
+ const metaPath = path.join(dirPath, 'meta.json');
1007
+ if (!fs.existsSync(metaPath)) {
1008
+ fs.writeFileSync(metaPath, JSON.stringify({
1009
+ session_id: sessionId,
1010
+ created: new Date().toISOString(),
1011
+ pid: process.pid
1012
+ }, null, 2), 'utf8');
1013
+ }
1014
+ }
1015
+
1016
+ /**
1017
+ * Remove a session directory and all its contents.
1018
+ *
1019
+ * @param {string} pDir - Path to .planning/ directory
1020
+ * @param {string} sessionId - Session identifier
1021
+ */
1022
+ function removeSessionDir(pDir, sessionId) {
1023
+ const dirPath = path.join(pDir, '.sessions', sessionId);
1024
+ if (fs.existsSync(dirPath)) {
1025
+ fs.rmSync(dirPath, { recursive: true, force: true });
1026
+ }
1027
+ }
1028
+
1029
+ /**
1030
+ * Remove stale session directories older than STALE_SESSION_MS.
1031
+ *
1032
+ * @param {string} pDir - Path to .planning/ directory
1033
+ * @returns {Array<{sessionId: string, age: number}>} Removed sessions
1034
+ */
1035
+ function cleanStaleSessions(pDir) {
1036
+ const sessionsDir = path.join(pDir, '.sessions');
1037
+ if (!fs.existsSync(sessionsDir)) return [];
1038
+
1039
+ const removed = [];
1040
+ try {
1041
+ const entries = fs.readdirSync(sessionsDir, { withFileTypes: true });
1042
+ for (const entry of entries) {
1043
+ if (!entry.isDirectory()) continue;
1044
+ const dirPath = path.join(sessionsDir, entry.name);
1045
+ let ageMs = 0;
1046
+
1047
+ const metaPath = path.join(dirPath, 'meta.json');
1048
+ try {
1049
+ const meta = JSON.parse(fs.readFileSync(metaPath, 'utf8'));
1050
+ ageMs = Date.now() - new Date(meta.created).getTime();
1051
+ } catch (_e) {
1052
+ try {
1053
+ const stats = fs.statSync(dirPath);
1054
+ ageMs = Date.now() - stats.mtimeMs;
1055
+ } catch (_statErr) {
1056
+ continue;
1057
+ }
1058
+ }
1059
+
1060
+ if (ageMs > STALE_SESSION_MS) {
1061
+ fs.rmSync(dirPath, { recursive: true, force: true });
1062
+ removed.push({ sessionId: entry.name, age: ageMs });
1063
+ }
1064
+ }
1065
+ } catch (_e) { /* best effort */ }
1066
+
1067
+ return removed;
1068
+ }
1069
+
1070
+ // ─── Session state management ─────────────────────────────────────────────────
1071
+
1072
+ const SESSION_ALLOWED_KEYS = ['activeSkill', 'compactCounter', 'sessionStart', 'activeOperation', 'activePlan'];
1073
+
1074
+ /**
1075
+ * Load .session.json from .planning/ directory.
1076
+ *
1077
+ * @param {string} dir - Path to .planning/ directory
1078
+ * @param {string} [sessionId] - Session identifier for session-scoped path
1079
+ * @returns {object} Parsed session data or empty object
1080
+ */
1081
+ function sessionLoad(dir, sessionId) {
1082
+ const sessionPath = sessionId
1083
+ ? resolveSessionPath(dir, '.session.json', sessionId)
1084
+ : path.join(dir, '.session.json');
1085
+ try {
1086
+ if (!fs.existsSync(sessionPath)) return {};
1087
+ const content = fs.readFileSync(sessionPath, 'utf8');
1088
+ return JSON.parse(content);
1089
+ } catch (_e) {
1090
+ return {};
1091
+ }
1092
+ }
1093
+
1094
+ /**
1095
+ * Save data to .session.json using atomic write.
1096
+ * Merges provided data with existing session data.
1097
+ *
1098
+ * @param {string} dir - Path to .planning/ directory
1099
+ * @param {object} data - Key-value pairs to merge into session
1100
+ * @param {string} [sessionId] - Session identifier for session-scoped path
1101
+ * @returns {{ success: boolean, error?: string }}
1102
+ */
1103
+ function sessionSave(dir, data, sessionId) {
1104
+ const sessionPath = sessionId
1105
+ ? resolveSessionPath(dir, '.session.json', sessionId)
1106
+ : path.join(dir, '.session.json');
1107
+ const tmpPath = sessionPath + '.tmp';
1108
+ try {
1109
+ if (sessionId) ensureSessionDir(dir, sessionId);
1110
+ const existing = sessionLoad(dir, sessionId);
1111
+ const merged = Object.assign(existing, data);
1112
+ fs.writeFileSync(tmpPath, JSON.stringify(merged, null, 2), 'utf8');
1113
+ fs.renameSync(tmpPath, sessionPath);
1114
+ return { success: true };
1115
+ } catch (e) {
1116
+ try { if (fs.existsSync(tmpPath)) fs.unlinkSync(tmpPath); } catch (_) { /* cleanup */ }
1117
+ return { success: false, error: e.message };
1118
+ }
1119
+ }
1120
+
1121
+ /**
1122
+ * Clear session data by removing the .session.json file.
1123
+ *
1124
+ * @param {string} dir - Path to .planning/ directory
1125
+ * @param {string} [sessionId] - Session identifier for session-scoped path
1126
+ * @returns {{ success: boolean, error?: string }}
1127
+ */
1128
+ function sessionClear(dir, sessionId) {
1129
+ const sessionPath = sessionId
1130
+ ? resolveSessionPath(dir, '.session.json', sessionId)
1131
+ : path.join(dir, '.session.json');
1132
+ try {
1133
+ if (fs.existsSync(sessionPath)) fs.unlinkSync(sessionPath);
1134
+ return { success: true };
1135
+ } catch (e) {
1136
+ return { success: false, error: e.message };
1137
+ }
1138
+ }
1139
+
1140
+ /**
1141
+ * Dump all session data as a JSON object for debugging.
1142
+ *
1143
+ * @param {string} dir - Path to .planning/ directory
1144
+ * @param {string} [sessionId] - Session identifier for session-scoped path
1145
+ * @returns {object} Session data including metadata
1146
+ */
1147
+ function sessionDump(dir, sessionId) {
1148
+ const data = sessionLoad(dir, sessionId);
1149
+ const sessionPath = sessionId
1150
+ ? resolveSessionPath(dir, '.session.json', sessionId)
1151
+ : path.join(dir, '.session.json');
1152
+ return {
1153
+ path: sessionPath,
1154
+ exists: fs.existsSync(sessionPath),
1155
+ data,
1156
+ keys: Object.keys(data)
1157
+ };
1158
+ }
1159
+
1160
+ /**
1161
+ * Write .active-skill with OS-level mutual exclusion.
1162
+ *
1163
+ * @param {string} pDir - Path to .planning/ directory
1164
+ * @param {string} skillName - Skill name to write
1165
+ * @param {string} [sessionId] - Session identifier for session-scoped path
1166
+ * @returns {{success: boolean, warning?: string}} Result
1167
+ */
1168
+ function writeActiveSkill(pDir, skillName, sessionId) {
1169
+ const skillFile = sessionId
1170
+ ? resolveSessionPath(pDir, '.active-skill', sessionId)
1171
+ : path.join(pDir, '.active-skill');
1172
+ const lockFile = skillFile + '.lock';
1173
+ const staleThresholdMs = 60 * 60 * 1000;
1174
+
1175
+ if (sessionId) ensureSessionDir(pDir, sessionId);
1176
+
1177
+ let lockFd = null;
1178
+ try {
1179
+ lockFd = fs.openSync(lockFile, 'wx');
1180
+ fs.writeSync(lockFd, `${process.pid}`);
1181
+ fs.closeSync(lockFd);
1182
+ lockFd = null;
1183
+
1184
+ let warning = null;
1185
+ if (fs.existsSync(skillFile)) {
1186
+ try {
1187
+ const stats = fs.statSync(skillFile);
1188
+ const ageMs = Date.now() - stats.mtimeMs;
1189
+ if (ageMs < staleThresholdMs) {
1190
+ const existing = fs.readFileSync(skillFile, 'utf8').trim();
1191
+ warning = `.active-skill already set to "${existing}" (${Math.round(ageMs / 60000)}min ago). Overwriting.`;
1192
+ }
1193
+ } catch (_e) { /* file disappeared */ }
1194
+ }
1195
+
1196
+ fs.writeFileSync(skillFile, skillName, 'utf8');
1197
+ try { sessionSave(pDir, { activeSkill: skillName }, sessionId); } catch (_e) { /* non-fatal */ }
1198
+ try { fs.unlinkSync(lockFile); } catch (_e) { /* best effort */ }
1199
+
1200
+ return { success: true, warning };
1201
+ } catch (e) {
1202
+ try { if (lockFd !== null) fs.closeSync(lockFd); } catch (_e) { /* ignore */ }
1203
+
1204
+ if (e.code === 'EEXIST') {
1205
+ try {
1206
+ const lockStats = fs.statSync(lockFile);
1207
+ const lockAgeMs = Date.now() - lockStats.mtimeMs;
1208
+ if (lockAgeMs > staleThresholdMs) {
1209
+ fs.unlinkSync(lockFile);
1210
+ return writeActiveSkill(pDir, skillName, sessionId);
1211
+ }
1212
+ } catch (_statErr) {
1213
+ return writeActiveSkill(pDir, skillName, sessionId);
1214
+ }
1215
+ return { success: false, warning: `.active-skill.lock held by another process.` };
1216
+ }
1217
+
1218
+ try {
1219
+ fs.writeFileSync(skillFile, skillName, 'utf8');
1220
+ return { success: true, warning: `Lock failed (${e.code}), wrote without lock` };
1221
+ } catch (writeErr) {
1222
+ return { success: false, warning: `Failed to write .active-skill: ${writeErr.message}` };
1223
+ }
1224
+ }
1225
+ }
1226
+
1227
+ // ─── Phase claiming ───────────────────────────────────────────────────────────
1228
+
1229
+ /**
1230
+ * Check whether a claim is stale (its session directory no longer exists).
1231
+ *
1232
+ * @param {object} claimData - Parsed .claim JSON (must have session_id)
1233
+ * @param {string} pDir - Path to .planning/ directory
1234
+ * @returns {{ stale: boolean, reason?: string }}
1235
+ */
1236
+ function isClaimStale(claimData, pDir) {
1237
+ const sessionDir = path.join(pDir, '.sessions', claimData.session_id);
1238
+ if (!fs.existsSync(sessionDir)) {
1239
+ return { stale: true, reason: 'session_dir_missing' };
1240
+ }
1241
+ return { stale: false };
1242
+ }
1243
+
1244
+ /**
1245
+ * Acquire a phase claim for a session. Auto-releases stale claims.
1246
+ *
1247
+ * @param {string} pDir - Path to .planning/ directory
1248
+ * @param {string} phaseDir - Absolute path to the phase directory
1249
+ * @param {string} sessionId - Session identifier
1250
+ * @param {string} skill - Skill name acquiring the claim
1251
+ * @returns {{ acquired: boolean, conflict?: object, auto_released?: object }}
1252
+ */
1253
+ function acquireClaim(pDir, phaseDir, sessionId, skill) {
1254
+ const claimPath = path.join(phaseDir, '.claim');
1255
+ let autoReleased = null;
1256
+
1257
+ if (fs.existsSync(claimPath)) {
1258
+ try {
1259
+ const existing = JSON.parse(fs.readFileSync(claimPath, 'utf8'));
1260
+ if (existing.session_id !== sessionId) {
1261
+ const staleCheck = isClaimStale(existing, pDir);
1262
+ if (staleCheck.stale) {
1263
+ fs.unlinkSync(claimPath);
1264
+ autoReleased = existing;
1265
+ } else {
1266
+ return {
1267
+ acquired: false,
1268
+ conflict: {
1269
+ session_id: existing.session_id,
1270
+ skill: existing.skill,
1271
+ started: existing.started,
1272
+ pid: existing.pid
1273
+ },
1274
+ auto_released: null
1275
+ };
1276
+ }
1277
+ }
1278
+ } catch (_e) {
1279
+ try { fs.unlinkSync(claimPath); } catch (_unlinkErr) { /* best effort */ }
1280
+ }
1281
+ }
1282
+
1283
+ const claimData = {
1284
+ session_id: sessionId,
1285
+ skill: skill,
1286
+ started: new Date().toISOString(),
1287
+ pid: process.pid
1288
+ };
1289
+ fs.writeFileSync(claimPath, JSON.stringify(claimData, null, 2), 'utf8');
1290
+
1291
+ return { acquired: true, conflict: null, auto_released: autoReleased };
1292
+ }
1293
+
1294
+ /**
1295
+ * Release a phase claim owned by a specific session.
1296
+ *
1297
+ * @param {string} _pDir - Path to .planning/ directory (unused, for API consistency)
1298
+ * @param {string} phaseDir - Absolute path to the phase directory
1299
+ * @param {string} sessionId - Session identifier
1300
+ * @returns {{ released: boolean, reason?: string, owner?: string }}
1301
+ */
1302
+ function releaseClaim(_pDir, phaseDir, sessionId) {
1303
+ const claimPath = path.join(phaseDir, '.claim');
1304
+
1305
+ if (!fs.existsSync(claimPath)) {
1306
+ return { released: false, reason: 'no_claim' };
1307
+ }
1308
+
1309
+ try {
1310
+ const claim = JSON.parse(fs.readFileSync(claimPath, 'utf8'));
1311
+ if (claim.session_id !== sessionId) {
1312
+ return { released: false, reason: 'not_owner', owner: claim.session_id };
1313
+ }
1314
+ fs.unlinkSync(claimPath);
1315
+ return { released: true };
1316
+ } catch (_e) {
1317
+ try { fs.unlinkSync(claimPath); } catch (_unlinkErr) { /* best effort */ }
1318
+ return { released: true };
1319
+ }
1320
+ }
1321
+
1322
+ /**
1323
+ * List all active phase claims.
1324
+ *
1325
+ * @param {string} pDir - Path to .planning/ directory
1326
+ * @returns {{ claims: Array<object> }}
1327
+ */
1328
+ function listClaims(pDir) {
1329
+ const phasesDir = path.join(pDir, 'phases');
1330
+ if (!fs.existsSync(phasesDir)) {
1331
+ return { claims: [] };
1332
+ }
1333
+
1334
+ const results = [];
1335
+ try {
1336
+ const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
1337
+ for (const entry of entries) {
1338
+ if (!entry.isDirectory()) continue;
1339
+ const claimPath = path.join(phasesDir, entry.name, '.claim');
1340
+ if (!fs.existsSync(claimPath)) continue;
1341
+ try {
1342
+ const claimData = JSON.parse(fs.readFileSync(claimPath, 'utf8'));
1343
+ results.push({
1344
+ phase: entry.name,
1345
+ ...claimData,
1346
+ stale: isClaimStale(claimData, pDir).stale
1347
+ });
1348
+ } catch (_e) { /* skip malformed */ }
1349
+ }
1350
+ } catch (_e) { /* best effort */ }
1351
+
1352
+ return { claims: results };
1353
+ }
1354
+
1355
+ /**
1356
+ * Release all claims held by a specific session across all phase directories.
1357
+ *
1358
+ * @param {string} pDir - Path to .planning/ directory
1359
+ * @param {string} sessionId - Session identifier
1360
+ * @returns {{ released: string[] }}
1361
+ */
1362
+ function releaseSessionClaims(pDir, sessionId) {
1363
+ const phasesDir = path.join(pDir, 'phases');
1364
+ if (!fs.existsSync(phasesDir)) {
1365
+ return { released: [] };
1366
+ }
1367
+
1368
+ const released = [];
1369
+ try {
1370
+ const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
1371
+ for (const entry of entries) {
1372
+ if (!entry.isDirectory()) continue;
1373
+ const claimPath = path.join(phasesDir, entry.name, '.claim');
1374
+ if (!fs.existsSync(claimPath)) continue;
1375
+ try {
1376
+ const claimData = JSON.parse(fs.readFileSync(claimPath, 'utf8'));
1377
+ if (claimData.session_id === sessionId) {
1378
+ fs.unlinkSync(claimPath);
1379
+ released.push(entry.name);
1380
+ }
1381
+ } catch (_e) { /* skip malformed */ }
1382
+ }
1383
+ } catch (_e) { /* best effort */ }
1384
+
1385
+ return { released };
1386
+ }
1387
+
1388
+ // ─── Config loader (lightweight, used by core only) ───────────────────────────
1389
+
1390
+ function loadConfig(configCwd) {
1391
+ const configPath = path.join(configCwd, '.planning', 'config.json');
1392
+ const defaults = {
1393
+ model_profile: 'balanced',
1394
+ commit_docs: true,
1395
+ search_gitignored: false,
1396
+ branching_strategy: 'none',
1397
+ phase_branch_template: 'pbr/phase-{phase}-{slug}',
1398
+ milestone_branch_template: 'pbr/{milestone}-{slug}',
1399
+ research: true,
1400
+ plan_checker: true,
1401
+ verifier: true,
1402
+ nyquist_validation: true,
1403
+ parallelization: true,
1404
+ brave_search: false,
1405
+ };
1406
+
1407
+ try {
1408
+ const raw = fs.readFileSync(configPath, 'utf8');
1409
+ const parsed = JSON.parse(raw);
1410
+
1411
+ if ('depth' in parsed && !('granularity' in parsed)) {
1412
+ const depthToGranularity = { quick: 'coarse', standard: 'standard', comprehensive: 'fine' };
1413
+ parsed.granularity = depthToGranularity[parsed.depth] || parsed.depth;
1414
+ delete parsed.depth;
1415
+ try { fs.writeFileSync(configPath, JSON.stringify(parsed, null, 2), 'utf8'); } catch { /* best effort */ }
1416
+ }
1417
+
1418
+ const get = (key, nested) => {
1419
+ if (parsed[key] !== undefined) return parsed[key];
1420
+ if (nested && parsed[nested.section] && parsed[nested.section][nested.field] !== undefined) {
1421
+ return parsed[nested.section][nested.field];
1422
+ }
1423
+ return undefined;
1424
+ };
1425
+
1426
+ const parallelization = (() => {
1427
+ const val = get('parallelization');
1428
+ if (typeof val === 'boolean') return val;
1429
+ if (typeof val === 'object' && val !== null && 'enabled' in val) return val.enabled;
1430
+ return defaults.parallelization;
1431
+ })();
1432
+
1433
+ return {
1434
+ model_profile: get('model_profile') ?? defaults.model_profile,
1435
+ commit_docs: get('commit_docs', { section: 'planning', field: 'commit_docs' }) ?? defaults.commit_docs,
1436
+ search_gitignored: get('search_gitignored', { section: 'planning', field: 'search_gitignored' }) ?? defaults.search_gitignored,
1437
+ branching_strategy: get('branching_strategy', { section: 'git', field: 'branching_strategy' }) ?? defaults.branching_strategy,
1438
+ phase_branch_template: get('phase_branch_template', { section: 'git', field: 'phase_branch_template' }) ?? defaults.phase_branch_template,
1439
+ milestone_branch_template: get('milestone_branch_template', { section: 'git', field: 'milestone_branch_template' }) ?? defaults.milestone_branch_template,
1440
+ research: get('research', { section: 'workflow', field: 'research' }) ?? defaults.research,
1441
+ plan_checker: get('plan_checker', { section: 'workflow', field: 'plan_check' }) ?? defaults.plan_checker,
1442
+ verifier: get('verifier', { section: 'workflow', field: 'verifier' }) ?? defaults.verifier,
1443
+ nyquist_validation: get('nyquist_validation', { section: 'workflow', field: 'nyquist_validation' }) ?? defaults.nyquist_validation,
1444
+ parallelization,
1445
+ brave_search: get('brave_search') ?? defaults.brave_search,
1446
+ model_overrides: parsed.model_overrides || null,
1447
+ };
1448
+ } catch {
1449
+ return defaults;
1450
+ }
1451
+ }
1452
+
1453
+ /**
1454
+ * Check if a path is git-ignored, scoped to a cwd.
1455
+ *
1456
+ * @param {string} igCwd - Working directory
1457
+ * @param {string} targetPath - Path to check
1458
+ * @returns {boolean}
1459
+ */
1460
+ function pathExistsInternal(peCwd, targetPath) {
1461
+ const fullPath = path.isAbsolute(targetPath) ? targetPath : path.join(peCwd, targetPath);
1462
+ try {
1463
+ fs.statSync(fullPath);
1464
+ return true;
1465
+ } catch {
1466
+ return false;
1467
+ }
1468
+ }
1469
+
1470
+ function resolveModelInternal(rmCwd, agentType) {
1471
+ const config = loadConfig(rmCwd);
1472
+ return resolveModel(agentType, config);
1473
+ }
1474
+
1475
+ // ─── Exports ──────────────────────────────────────────────────────────────────
1476
+
1477
+ module.exports = {
1478
+ // Module-level state
1479
+ setCwd,
1480
+
1481
+ // Constants
1482
+ KNOWN_AGENTS,
1483
+ VALID_STATUS_TRANSITIONS,
1484
+ STATUS_LABELS,
1485
+ MODEL_PROFILES,
1486
+ SESSION_ALLOWED_KEYS,
1487
+ STALE_SESSION_MS,
1488
+
1489
+ // Status transitions
1490
+ validateStatusTransition,
1491
+
1492
+ // Output
1493
+ output,
1494
+ error,
1495
+
1496
+ // Path & file utilities
1497
+ toPosixPath,
1498
+ safeReadFile,
1499
+ ensureDir,
1500
+ findFiles,
1501
+ tailLines,
1502
+ escapeRegex,
1503
+
1504
+ // Git utilities
1505
+ execGit,
1506
+ isGitIgnored,
1507
+
1508
+ // YAML frontmatter
1509
+ parseYamlFrontmatter,
1510
+ parseMustHaves,
1511
+ setYamlFrontmatter,
1512
+
1513
+ // Misc utilities
1514
+ countMustHaves,
1515
+ determinePhaseStatus,
1516
+ calculateProgress,
1517
+ currentTimestamp,
1518
+ generateSlug,
1519
+ resolveModel,
1520
+
1521
+ // Phase utilities
1522
+ normalizePhaseName,
1523
+ comparePhaseNum,
1524
+ searchPhaseInDir,
1525
+ findPhaseInternal,
1526
+ getArchivedPhaseDirs,
1527
+
1528
+ // Roadmap & milestone
1529
+ getRoadmapPhaseInternal,
1530
+ getMilestoneInfo,
1531
+ getMilestonePhaseFilter,
1532
+
1533
+ // Config loader (lightweight)
1534
+ loadConfig,
1535
+ pathExistsInternal,
1536
+ resolveModelInternal,
1537
+ generateSlugInternal: generateSlug,
1538
+
1539
+ // Atomic operations
1540
+ atomicWrite,
1541
+ lockedFileUpdate,
1542
+
1543
+ // Schema validation
1544
+ validateObject,
1545
+
1546
+ // Session management
1547
+ resolveSessionPath,
1548
+ ensureSessionDir,
1549
+ removeSessionDir,
1550
+ cleanStaleSessions,
1551
+ sessionLoad,
1552
+ sessionSave,
1553
+ sessionClear,
1554
+ sessionDump,
1555
+ writeActiveSkill,
1556
+
1557
+ // Phase claiming
1558
+ isClaimStale,
1559
+ acquireClaim,
1560
+ releaseClaim,
1561
+ listClaims,
1562
+ releaseSessionClaims,
1563
+ };