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