@sienklogic/plan-build-run 2.21.0 → 2.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (983) hide show
  1. package/CHANGELOG.md +1331 -299
  2. package/CLAUDE.md +75 -40
  3. package/LICENSE +2 -1
  4. package/README.md +412 -177
  5. package/bin/install.js +2752 -0
  6. package/dashboard/bin/cli.cjs +96 -0
  7. package/dashboard/bin/stop.cjs +129 -0
  8. package/dashboard/eslint.config.js +37 -0
  9. package/dashboard/index.html +20 -0
  10. package/dashboard/package.json +27 -25
  11. package/dashboard/server/index.js +151 -0
  12. package/dashboard/server/lib/frontmatter.js +92 -0
  13. package/dashboard/server/middleware/static.js +35 -0
  14. package/dashboard/server/package.json +16 -0
  15. package/dashboard/server/routes/agents.js +234 -0
  16. package/dashboard/server/routes/config.js +64 -0
  17. package/dashboard/server/routes/health.js +98 -0
  18. package/dashboard/server/routes/incidents.js +78 -0
  19. package/dashboard/server/routes/intel.js +69 -0
  20. package/dashboard/server/routes/memory.js +107 -0
  21. package/dashboard/server/routes/planning.js +234 -0
  22. package/dashboard/server/routes/progress.js +77 -0
  23. package/dashboard/server/routes/projects.js +36 -0
  24. package/dashboard/server/routes/requirements.js +40 -0
  25. package/dashboard/server/routes/roadmap.js +69 -0
  26. package/dashboard/server/routes/sessions.js +70 -0
  27. package/dashboard/server/routes/status.js +25 -0
  28. package/dashboard/server/routes/telemetry.js +233 -0
  29. package/dashboard/server/services/file-watcher.js +105 -0
  30. package/dashboard/server/services/planning-reader.js +727 -0
  31. package/dashboard/server/test/cli.test.js +34 -0
  32. package/dashboard/server/test/frontmatter.test.js +104 -0
  33. package/dashboard/server/test/isolation.test.js +32 -0
  34. package/dashboard/server/test/planning-reader.test.js +151 -0
  35. package/dashboard/server/test/routes.test.js +91 -0
  36. package/dashboard/server/test/ws.test.js +81 -0
  37. package/dashboard/server/ws.js +96 -0
  38. package/dashboard/src/App.jsx +165 -0
  39. package/dashboard/src/components/charts/BudgetBars.jsx +42 -0
  40. package/dashboard/src/components/charts/ContextRadar.jsx +34 -0
  41. package/dashboard/src/components/charts/PhaseDonut.jsx +66 -0
  42. package/dashboard/src/components/charts/SuccessTrend.jsx +45 -0
  43. package/dashboard/src/components/charts/TokenChart.jsx +55 -0
  44. package/dashboard/src/components/charts/index.js +5 -0
  45. package/dashboard/src/components/config/CfgSection.jsx +93 -0
  46. package/dashboard/src/components/layout/Header.jsx +89 -0
  47. package/dashboard/src/components/layout/ProjectSwitcher.jsx +160 -0
  48. package/dashboard/src/components/layout/Sidebar.jsx +161 -0
  49. package/dashboard/src/components/ui/AutoModeBanner.jsx +138 -0
  50. package/dashboard/src/components/ui/BackButton.jsx +27 -0
  51. package/dashboard/src/components/ui/Badge.jsx +27 -0
  52. package/dashboard/src/components/ui/Card.jsx +23 -0
  53. package/dashboard/src/components/ui/ChartTooltip.jsx +48 -0
  54. package/dashboard/src/components/ui/CheckpointBox.jsx +110 -0
  55. package/dashboard/src/components/ui/CodeBlock.jsx +27 -0
  56. package/dashboard/src/components/ui/ConfidenceBadge.jsx +20 -0
  57. package/dashboard/src/components/ui/ConfirmModal.jsx +161 -0
  58. package/dashboard/src/components/ui/ConnectionBanner.jsx +60 -0
  59. package/dashboard/src/components/ui/ErrorBoundary.jsx +106 -0
  60. package/dashboard/src/components/ui/ErrorBox.jsx +107 -0
  61. package/dashboard/src/components/ui/KeyValue.jsx +33 -0
  62. package/dashboard/src/components/ui/LoadingSkeleton.jsx +84 -0
  63. package/dashboard/src/components/ui/MetricCard.jsx +58 -0
  64. package/dashboard/src/components/ui/NextUpBlock.jsx +92 -0
  65. package/dashboard/src/components/ui/NumberInput.jsx +44 -0
  66. package/dashboard/src/components/ui/PBRBanner.jsx +47 -0
  67. package/dashboard/src/components/ui/PipelineView.jsx +130 -0
  68. package/dashboard/src/components/ui/ProgressBar.jsx +28 -0
  69. package/dashboard/src/components/ui/ProgressDisplay.jsx +47 -0
  70. package/dashboard/src/components/ui/QualityGateBadge.jsx +15 -0
  71. package/dashboard/src/components/ui/SectionTitle.jsx +35 -0
  72. package/dashboard/src/components/ui/SelectInput.jsx +45 -0
  73. package/dashboard/src/components/ui/StatusDot.jsx +51 -0
  74. package/dashboard/src/components/ui/StatusSymbol.jsx +49 -0
  75. package/dashboard/src/components/ui/TabBar.jsx +41 -0
  76. package/dashboard/src/components/ui/TextInput.jsx +42 -0
  77. package/dashboard/src/components/ui/Toast.jsx +117 -0
  78. package/dashboard/src/components/ui/Toggle.jsx +70 -0
  79. package/dashboard/src/components/ui/index.js +29 -0
  80. package/dashboard/src/hooks/useDocumentTitle.js +16 -0
  81. package/dashboard/src/hooks/useFetch.js +50 -0
  82. package/dashboard/src/hooks/useToast.jsx +43 -0
  83. package/dashboard/src/hooks/useWebSocket.js +103 -0
  84. package/dashboard/src/lib/api.js +112 -0
  85. package/dashboard/src/lib/configSchema.js +189 -0
  86. package/dashboard/src/lib/constants.js +22 -0
  87. package/dashboard/src/main.jsx +15 -0
  88. package/dashboard/src/pages/AgentsPage.jsx +191 -0
  89. package/dashboard/src/pages/ConfigPage.jsx +298 -0
  90. package/dashboard/src/pages/HooksPage.jsx +412 -0
  91. package/dashboard/src/pages/IncidentsPage.jsx +135 -0
  92. package/dashboard/src/pages/IntelPage.jsx +193 -0
  93. package/dashboard/src/pages/LiveFeed.jsx +274 -0
  94. package/dashboard/src/pages/MemoryPage.jsx +107 -0
  95. package/dashboard/src/pages/OnboardingPage.jsx +117 -0
  96. package/dashboard/src/pages/Overview.jsx +360 -0
  97. package/dashboard/src/pages/PhaseDetailView.jsx +216 -0
  98. package/dashboard/src/pages/PlanningPage.jsx +181 -0
  99. package/dashboard/src/pages/ProgressPage.jsx +249 -0
  100. package/dashboard/src/pages/ResearchPage.jsx +129 -0
  101. package/dashboard/src/pages/RoadmapPage.jsx +251 -0
  102. package/dashboard/src/pages/SessionsPage.jsx +117 -0
  103. package/dashboard/src/pages/Telemetry.jsx +166 -0
  104. package/dashboard/src/pages/planning/DecisionsTab.jsx +153 -0
  105. package/dashboard/src/pages/planning/FilesTab.jsx +420 -0
  106. package/dashboard/src/pages/planning/MilestoneDetail.jsx +319 -0
  107. package/dashboard/src/pages/planning/MilestonesTab.jsx +151 -0
  108. package/dashboard/src/pages/planning/NotesTab.jsx +251 -0
  109. package/dashboard/src/pages/planning/PhasesTab.jsx +218 -0
  110. package/dashboard/src/pages/planning/QuickTab.jsx +50 -0
  111. package/dashboard/src/pages/planning/ResearchTab.jsx +103 -0
  112. package/dashboard/src/pages/planning/TodosTab.jsx +297 -0
  113. package/dashboard/src/theme/ThemeProvider.jsx +38 -0
  114. package/dashboard/src/theme/tokens.js +17 -0
  115. package/dashboard/tests/components/ConfirmModal.test.jsx +179 -0
  116. package/dashboard/tests/components/ConnectionBanner.test.jsx +37 -0
  117. package/dashboard/tests/components/ErrorBoundary.test.jsx +59 -0
  118. package/dashboard/tests/components/LoadingSkeleton.test.jsx +46 -0
  119. package/dashboard/tests/components/ToastContainer.test.jsx +47 -0
  120. package/dashboard/tests/components/Toggle.test.jsx +61 -0
  121. package/dashboard/tests/hooks/useFetch.test.jsx +77 -0
  122. package/dashboard/tests/hooks/useToast.test.jsx +78 -0
  123. package/dashboard/tests/hooks/useWebSocket.test.jsx +128 -0
  124. package/dashboard/tests/pages/ConfigPage.test.jsx +199 -0
  125. package/dashboard/tests/pages/PlanningPage.test.jsx +119 -0
  126. package/dashboard/tests/pages/planning/FilesTab.test.jsx +198 -0
  127. package/dashboard/tests/pages/planning/NotesTab.test.jsx +178 -0
  128. package/dashboard/tests/pages/planning/TodosTab.test.jsx +188 -0
  129. package/dashboard/tests/performance.test.jsx +46 -0
  130. package/dashboard/tests/routes/config.test.js +98 -0
  131. package/dashboard/tests/routes/health.test.js +40 -0
  132. package/dashboard/tests/routes/planning.test.js +112 -0
  133. package/dashboard/tests/routes/roadmap.test.js +91 -0
  134. package/dashboard/tests/routes/status.test.js +131 -0
  135. package/dashboard/tests/server/planning-reader.test.js +153 -0
  136. package/dashboard/tests/setup.js +7 -0
  137. package/dashboard/vite.config.js +41 -0
  138. package/package.json +56 -41
  139. package/plan-build-run/bin/config-schema.json +1298 -0
  140. package/plugins/pbr/.claude-plugin/plugin.json +1 -1
  141. package/plugins/pbr/CLAUDE.md +19 -0
  142. package/plugins/pbr/UI-CONSISTENCY-GAPS.md +1 -1
  143. package/plugins/pbr/agents/advisor-researcher.md +101 -0
  144. package/plugins/pbr/agents/audit.md +207 -89
  145. package/plugins/pbr/agents/codebase-mapper.md +158 -23
  146. package/plugins/pbr/agents/debugger.md +212 -34
  147. package/plugins/pbr/agents/dev-sync.md +206 -0
  148. package/plugins/pbr/agents/executor.md +737 -39
  149. package/plugins/pbr/agents/general.md +71 -6
  150. package/plugins/pbr/agents/integration-checker.md +148 -30
  151. package/plugins/pbr/agents/intel-updater.md +332 -0
  152. package/plugins/pbr/agents/nyquist-auditor.md +254 -0
  153. package/plugins/pbr/agents/plan-checker.md +268 -66
  154. package/plugins/pbr/agents/planner.md +451 -42
  155. package/plugins/pbr/agents/researcher.md +219 -36
  156. package/plugins/pbr/agents/roadmapper.md +398 -0
  157. package/plugins/pbr/agents/synthesizer.md +166 -26
  158. package/plugins/pbr/agents/ui-checker.md +204 -0
  159. package/plugins/pbr/agents/ui-researcher.md +224 -0
  160. package/plugins/pbr/agents/verifier.md +571 -47
  161. package/plugins/pbr/commands/add-phase.md +75 -0
  162. package/plugins/pbr/commands/add-todo.md +8 -0
  163. package/plugins/pbr/commands/audit-fix.md +5 -0
  164. package/plugins/pbr/commands/audit-milestone.md +8 -0
  165. package/plugins/pbr/commands/autonomous.md +5 -0
  166. package/plugins/pbr/commands/backlog.md +6 -0
  167. package/plugins/pbr/commands/check-todos.md +8 -0
  168. package/plugins/pbr/commands/complete-milestone.md +8 -0
  169. package/plugins/pbr/commands/config.md +1 -1
  170. package/plugins/pbr/commands/discuss-phase.md +6 -0
  171. package/plugins/pbr/commands/do.md +5 -0
  172. package/plugins/pbr/commands/execute-phase.md +6 -0
  173. package/plugins/pbr/commands/fast.md +6 -0
  174. package/plugins/pbr/commands/forensics.md +6 -0
  175. package/plugins/pbr/commands/import.md +1 -1
  176. package/plugins/pbr/commands/insert-phase.md +65 -0
  177. package/plugins/pbr/commands/intel.md +5 -0
  178. package/plugins/pbr/commands/join-discord.md +11 -0
  179. package/plugins/pbr/commands/list-phase-assumptions.md +5 -0
  180. package/plugins/pbr/commands/map-codebase.md +6 -0
  181. package/plugins/pbr/commands/milestone-summary.md +6 -0
  182. package/plugins/pbr/commands/new-milestone.md +8 -0
  183. package/plugins/pbr/commands/new-project.md +6 -0
  184. package/plugins/pbr/commands/pause-work.md +5 -0
  185. package/plugins/pbr/commands/plan-milestone-gaps.md +7 -0
  186. package/plugins/pbr/commands/plan-phase.md +6 -0
  187. package/plugins/pbr/commands/plant-seed.md +6 -0
  188. package/plugins/pbr/commands/profile-user.md +5 -0
  189. package/plugins/pbr/commands/profile.md +5 -0
  190. package/plugins/pbr/commands/progress.md +6 -0
  191. package/plugins/pbr/commands/quick.md +1 -1
  192. package/plugins/pbr/commands/reapply-patches.md +47 -0
  193. package/plugins/pbr/commands/release.md +6 -0
  194. package/plugins/pbr/commands/remove-phase.md +66 -0
  195. package/plugins/pbr/commands/research-phase.md +59 -0
  196. package/plugins/pbr/commands/resume-work.md +5 -0
  197. package/plugins/pbr/commands/seed.md +6 -0
  198. package/plugins/pbr/commands/session-report.md +5 -0
  199. package/plugins/pbr/commands/set-profile.md +6 -0
  200. package/plugins/pbr/commands/settings.md +5 -0
  201. package/plugins/pbr/commands/setup.md +1 -1
  202. package/plugins/pbr/commands/ship.md +5 -0
  203. package/plugins/pbr/commands/stats.md +6 -0
  204. package/plugins/pbr/commands/test.md +5 -0
  205. package/plugins/pbr/commands/thread.md +6 -0
  206. package/plugins/pbr/commands/todo.md +1 -1
  207. package/plugins/pbr/commands/ui-phase.md +5 -0
  208. package/plugins/pbr/commands/ui-review.md +5 -0
  209. package/plugins/pbr/commands/undo.md +5 -0
  210. package/plugins/pbr/commands/update.md +37 -0
  211. package/plugins/pbr/commands/validate-phase.md +5 -0
  212. package/plugins/pbr/commands/verify-work.md +6 -0
  213. package/plugins/pbr/dashboard/package-lock.json +6 -0
  214. package/plugins/pbr/dist/architecture-guard.js +76 -0
  215. package/plugins/pbr/dist/audit-dimensions.js +556 -0
  216. package/plugins/pbr/dist/auto-continue.js +277 -0
  217. package/plugins/pbr/dist/block-skill-self-read.js +124 -0
  218. package/plugins/pbr/dist/check-agent-state-write.js +63 -0
  219. package/plugins/pbr/dist/check-config-change.js +213 -0
  220. package/plugins/pbr/dist/check-cross-plugin-sync.js +93 -0
  221. package/plugins/pbr/dist/check-dangerous-commands.js +193 -0
  222. package/plugins/pbr/dist/check-direct-state-write.js +37 -0
  223. package/plugins/pbr/dist/check-doc-sprawl.js +102 -0
  224. package/plugins/pbr/dist/check-phase-boundary.js +191 -0
  225. package/plugins/pbr/dist/check-plan-format.js +227 -0
  226. package/plugins/pbr/dist/check-read-first.js +345 -0
  227. package/plugins/pbr/dist/check-roadmap-sync.js +507 -0
  228. package/plugins/pbr/dist/check-skill-workflow.js +354 -0
  229. package/plugins/pbr/dist/check-state-sync.js +676 -0
  230. package/plugins/pbr/dist/check-subagent-output.js +425 -0
  231. package/plugins/pbr/dist/check-summary-gate.js +188 -0
  232. package/plugins/pbr/dist/context-bridge.js +425 -0
  233. package/plugins/pbr/dist/context-budget-check.js +442 -0
  234. package/plugins/pbr/dist/context-quality.js +271 -0
  235. package/plugins/pbr/dist/enforce-context-budget.js +138 -0
  236. package/plugins/pbr/dist/enforce-pbr-workflow.js +277 -0
  237. package/plugins/pbr/dist/event-handler.js +212 -0
  238. package/plugins/pbr/dist/event-logger.js +125 -0
  239. package/plugins/pbr/dist/feedback-loop.js +155 -0
  240. package/plugins/pbr/dist/graph-update.js +422 -0
  241. package/plugins/pbr/dist/hook-logger.js +114 -0
  242. package/plugins/pbr/dist/hook-server-client.js +361 -0
  243. package/plugins/pbr/dist/hook-server.js +664 -0
  244. package/plugins/pbr/dist/hooks-schema.json +87 -0
  245. package/plugins/pbr/dist/instructions-loaded.js +173 -0
  246. package/plugins/pbr/dist/intercept-plan-mode.js +81 -0
  247. package/plugins/pbr/dist/log-notification.js +131 -0
  248. package/plugins/pbr/dist/log-subagent.js +367 -0
  249. package/plugins/pbr/dist/log-tool-failure.js +140 -0
  250. package/plugins/pbr/dist/milestone-learnings.js +519 -0
  251. package/plugins/pbr/dist/pbr-tools.js +493 -0
  252. package/plugins/pbr/dist/post-bash-triage.js +96 -0
  253. package/plugins/pbr/dist/post-compact.js +135 -0
  254. package/plugins/pbr/dist/post-hoc.js +237 -0
  255. package/plugins/pbr/dist/post-write-dispatch.js +243 -0
  256. package/plugins/pbr/dist/post-write-quality.js +208 -0
  257. package/plugins/pbr/dist/pre-bash-dispatch.js +212 -0
  258. package/plugins/pbr/dist/pre-skill-dispatch.js +114 -0
  259. package/plugins/pbr/dist/pre-task-dispatch.js +269 -0
  260. package/plugins/pbr/dist/pre-write-dispatch.js +234 -0
  261. package/plugins/pbr/dist/progress-tracker.js +173 -0
  262. package/plugins/pbr/dist/prompt-guard.js +114 -0
  263. package/plugins/pbr/dist/prompt-routing.js +209 -0
  264. package/plugins/pbr/dist/quick-status.js +179 -0
  265. package/plugins/pbr/dist/record-incident.js +37 -0
  266. package/plugins/pbr/dist/run-hook.js +132 -0
  267. package/plugins/pbr/dist/session-cleanup.js +653 -0
  268. package/plugins/pbr/dist/session-tracker.js +124 -0
  269. package/plugins/pbr/dist/status-line.js +849 -0
  270. package/plugins/pbr/dist/suggest-compact.js +307 -0
  271. package/plugins/pbr/dist/sync-context-to-claude.js +100 -0
  272. package/plugins/pbr/dist/task-completed.js +206 -0
  273. package/plugins/pbr/dist/track-context-budget.js +432 -0
  274. package/plugins/pbr/dist/track-user-gates.js +88 -0
  275. package/plugins/pbr/dist/trust-tracker.js +193 -0
  276. package/plugins/pbr/dist/validate-commit.js +233 -0
  277. package/plugins/pbr/dist/validate-skill-args.js +222 -0
  278. package/plugins/pbr/dist/validate-task.js +271 -0
  279. package/plugins/pbr/dist/worktree-create.js +144 -0
  280. package/plugins/pbr/dist/worktree-remove.js +147 -0
  281. package/plugins/pbr/hooks/hooks.json +137 -65
  282. package/plugins/pbr/references/agent-contracts.md +39 -8
  283. package/plugins/pbr/references/agent-teams.md +3 -3
  284. package/plugins/pbr/references/archive/checkpoints.md +189 -0
  285. package/plugins/pbr/references/archive/context-quality-tiers.md +45 -0
  286. package/plugins/pbr/references/archive/hook-ordering.md +89 -0
  287. package/plugins/pbr/references/archive/limitations.md +106 -0
  288. package/plugins/pbr/references/archive/pbr-rules.md +194 -0
  289. package/plugins/pbr/references/archive/pbr-tools-cli.md +415 -0
  290. package/plugins/pbr/references/archive/pretooluse-jsonl-behavior.md +58 -0
  291. package/plugins/pbr/references/archive/signal-files.md +41 -0
  292. package/plugins/pbr/references/archive/tmux-setup.md +288 -0
  293. package/plugins/pbr/references/archive/verification-matrix.md +34 -0
  294. package/plugins/pbr/references/archive/verification-patterns.md +277 -0
  295. package/plugins/pbr/references/archive/worktree-sparse-checkout.md +86 -0
  296. package/plugins/pbr/references/assumptions.md +42 -0
  297. package/plugins/pbr/references/checkpoints.md +723 -104
  298. package/plugins/pbr/references/config-reference.md +387 -10
  299. package/plugins/pbr/references/continuation-format.md +1 -0
  300. package/plugins/pbr/references/decimal-phase-calculation.md +65 -0
  301. package/plugins/pbr/references/deviation-rules.md +12 -0
  302. package/plugins/pbr/references/few-shot-examples/audit.md +77 -0
  303. package/plugins/pbr/references/few-shot-examples/check-plan-format.md +172 -0
  304. package/plugins/pbr/references/few-shot-examples/check-subagent-output.md +118 -0
  305. package/plugins/pbr/references/few-shot-examples/integration-checker.md +70 -0
  306. package/plugins/pbr/references/few-shot-examples/nyquist-auditor.md +83 -0
  307. package/plugins/pbr/references/few-shot-examples/plan-checker.md +73 -0
  308. package/plugins/pbr/references/few-shot-examples/ui-checker.md +71 -0
  309. package/plugins/pbr/references/few-shot-examples/verifier.md +109 -0
  310. package/plugins/pbr/references/git-integration.md +110 -27
  311. package/plugins/pbr/references/git-planning-commit.md +35 -0
  312. package/plugins/pbr/references/model-profile-resolution.md +34 -0
  313. package/plugins/pbr/references/model-profiles.md +90 -7
  314. package/plugins/pbr/references/model-selection.md +1 -1
  315. package/plugins/pbr/references/node-repair.md +48 -0
  316. package/plugins/pbr/references/plan-authoring.md +65 -0
  317. package/plugins/pbr/references/plan-format.md +184 -10
  318. package/plugins/pbr/references/questioning.md +138 -49
  319. package/plugins/pbr/references/reading-verification.md +4 -4
  320. package/plugins/pbr/references/tdd.md +263 -0
  321. package/plugins/pbr/references/thinking-models-planning.md +47 -0
  322. package/plugins/pbr/references/thinking-models-verification.md +44 -0
  323. package/plugins/pbr/references/ui-brand.md +449 -0
  324. package/plugins/pbr/references/verification-overrides.md +39 -0
  325. package/plugins/pbr/references/verification-patterns.md +529 -113
  326. package/plugins/pbr/scripts/architecture-guard.js +76 -0
  327. package/plugins/pbr/scripts/audit-checks/behavioral-compliance.js +2098 -0
  328. package/plugins/pbr/scripts/audit-checks/error-analysis.js +989 -0
  329. package/plugins/pbr/scripts/audit-checks/feature-verification.js +723 -0
  330. package/plugins/pbr/scripts/audit-checks/index.js +433 -0
  331. package/plugins/pbr/scripts/audit-checks/infrastructure.js +816 -0
  332. package/plugins/pbr/scripts/audit-checks/quality-metrics.js +455 -0
  333. package/plugins/pbr/scripts/audit-checks/session-quality.js +980 -0
  334. package/plugins/pbr/scripts/audit-checks/si-agent-hook-config-checks.js +396 -0
  335. package/plugins/pbr/scripts/audit-checks/si-cross-cutting-checks.js +272 -0
  336. package/plugins/pbr/scripts/audit-checks/si-skill-checks.js +424 -0
  337. package/plugins/pbr/scripts/audit-checks/workflow-compliance.js +1175 -0
  338. package/plugins/pbr/scripts/audit-dimensions.js +556 -0
  339. package/plugins/pbr/scripts/auto-continue.js +192 -37
  340. package/plugins/pbr/scripts/block-skill-self-read.js +124 -0
  341. package/plugins/pbr/scripts/check-agent-state-write.js +63 -0
  342. package/plugins/pbr/scripts/check-config-change.js +84 -1
  343. package/plugins/pbr/scripts/check-cross-plugin-sync.js +93 -0
  344. package/plugins/pbr/scripts/check-dangerous-commands.js +18 -5
  345. package/plugins/pbr/scripts/check-direct-state-write.js +37 -0
  346. package/plugins/pbr/scripts/check-phase-boundary.js +3 -8
  347. package/plugins/pbr/scripts/check-plan-format.js +153 -278
  348. package/plugins/pbr/scripts/check-read-first.js +345 -0
  349. package/plugins/pbr/scripts/check-roadmap-sync.js +174 -19
  350. package/plugins/pbr/scripts/check-skill-workflow.js +24 -27
  351. package/plugins/pbr/scripts/check-state-sync.js +360 -218
  352. package/plugins/pbr/scripts/check-subagent-output.js +308 -273
  353. package/plugins/pbr/scripts/check-summary-gate.js +5 -15
  354. package/plugins/pbr/scripts/commands/benchmarks.js +195 -0
  355. package/plugins/pbr/scripts/commands/calibrate.js +530 -0
  356. package/plugins/pbr/scripts/commands/config.js +72 -0
  357. package/plugins/pbr/scripts/commands/misc.js +779 -0
  358. package/plugins/pbr/scripts/commands/phase.js +293 -0
  359. package/plugins/pbr/scripts/commands/roadmap.js +75 -0
  360. package/plugins/pbr/scripts/commands/state.js +84 -0
  361. package/plugins/pbr/scripts/commands/stress-test.js +349 -0
  362. package/plugins/pbr/scripts/commands/todo.js +191 -0
  363. package/plugins/pbr/scripts/commands/verify.js +169 -0
  364. package/plugins/pbr/scripts/config-schema.json +1183 -95
  365. package/plugins/pbr/scripts/context-bridge.js +425 -0
  366. package/plugins/pbr/scripts/context-budget-check.js +171 -16
  367. package/plugins/pbr/scripts/context-quality.js +271 -0
  368. package/plugins/pbr/scripts/enforce-context-budget.js +138 -0
  369. package/plugins/pbr/scripts/enforce-pbr-workflow.js +277 -0
  370. package/plugins/pbr/scripts/event-handler.js +137 -87
  371. package/plugins/pbr/scripts/event-logger.js +58 -25
  372. package/plugins/pbr/scripts/feedback-loop.js +155 -0
  373. package/plugins/pbr/scripts/graph-update.js +422 -0
  374. package/plugins/pbr/scripts/hook-logger.js +69 -35
  375. package/plugins/pbr/scripts/hook-server-client.js +361 -0
  376. package/plugins/pbr/scripts/hook-server.js +664 -0
  377. package/plugins/pbr/scripts/hooks-schema.json +12 -5
  378. package/plugins/pbr/scripts/instructions-loaded.js +173 -0
  379. package/plugins/pbr/scripts/intent-router.cjs +147 -0
  380. package/plugins/pbr/scripts/intercept-plan-mode.js +52 -18
  381. package/plugins/pbr/scripts/lib/alternatives.js +203 -0
  382. package/plugins/pbr/scripts/lib/audit.js +65 -0
  383. package/plugins/pbr/scripts/lib/auto-cleanup.js +221 -0
  384. package/plugins/pbr/scripts/lib/auto-verify.js +123 -0
  385. package/plugins/pbr/scripts/lib/benchmark.js +190 -0
  386. package/plugins/pbr/scripts/lib/build.js +719 -0
  387. package/plugins/pbr/scripts/lib/ci-fix-loop.js +228 -0
  388. package/plugins/pbr/scripts/lib/commands.js +483 -0
  389. package/plugins/pbr/scripts/lib/compound.js +222 -0
  390. package/plugins/pbr/scripts/lib/config-cache.js +83 -0
  391. package/plugins/pbr/scripts/lib/config.js +1469 -0
  392. package/plugins/pbr/scripts/lib/context.js +254 -0
  393. package/plugins/pbr/scripts/lib/contextual-help.js +183 -0
  394. package/plugins/pbr/scripts/lib/convention-detector.js +413 -0
  395. package/plugins/pbr/scripts/lib/core.js +1585 -0
  396. package/plugins/pbr/scripts/lib/dashboard-launch.js +364 -0
  397. package/plugins/pbr/scripts/lib/data-hygiene.js +179 -0
  398. package/plugins/pbr/scripts/lib/decision-extraction.js +183 -0
  399. package/plugins/pbr/scripts/lib/decisions.js +194 -0
  400. package/plugins/pbr/scripts/lib/dependency-break.js +147 -0
  401. package/plugins/pbr/scripts/lib/format-validators.js +1049 -0
  402. package/plugins/pbr/scripts/lib/frontmatter.js +302 -0
  403. package/plugins/pbr/scripts/lib/gates/advisories.js +133 -0
  404. package/plugins/pbr/scripts/lib/gates/build-dependency.js +118 -0
  405. package/plugins/pbr/scripts/lib/gates/build-executor.js +106 -0
  406. package/plugins/pbr/scripts/lib/gates/doc-existence.js +46 -0
  407. package/plugins/pbr/scripts/lib/gates/helpers.js +98 -0
  408. package/plugins/pbr/scripts/lib/gates/inline-execution.js +187 -0
  409. package/plugins/pbr/scripts/lib/gates/milestone-complete.js +139 -0
  410. package/plugins/pbr/scripts/lib/gates/milestone-summary.js +121 -0
  411. package/plugins/pbr/scripts/lib/gates/multi-phase-loader.js +149 -0
  412. package/plugins/pbr/scripts/lib/gates/plan-executor.js +36 -0
  413. package/plugins/pbr/scripts/lib/gates/plan-validation.js +115 -0
  414. package/plugins/pbr/scripts/lib/gates/quick-executor.js +78 -0
  415. package/plugins/pbr/scripts/lib/gates/review-planner.js +63 -0
  416. package/plugins/pbr/scripts/lib/gates/review-verifier.js +71 -0
  417. package/plugins/pbr/scripts/lib/gates/rich-agent-context.js +148 -0
  418. package/plugins/pbr/scripts/lib/gates/sprint-preflight.js +30 -0
  419. package/plugins/pbr/scripts/lib/gates/user-confirmation.js +95 -0
  420. package/plugins/pbr/scripts/lib/graph-cli.js +89 -0
  421. package/plugins/pbr/scripts/lib/graph.js +553 -0
  422. package/plugins/pbr/scripts/lib/handoff-validators.js +224 -0
  423. package/plugins/pbr/scripts/lib/health-checks.js +107 -0
  424. package/plugins/pbr/scripts/lib/health-phase06.js +120 -0
  425. package/plugins/pbr/scripts/lib/health.js +132 -0
  426. package/plugins/pbr/scripts/lib/help.js +100 -0
  427. package/plugins/pbr/scripts/lib/history.js +150 -0
  428. package/plugins/pbr/scripts/lib/impact-analysis.js +319 -0
  429. package/plugins/pbr/scripts/lib/incidents.js +190 -0
  430. package/plugins/pbr/scripts/lib/init.js +643 -0
  431. package/plugins/pbr/scripts/lib/insights-parser.js +320 -0
  432. package/plugins/pbr/scripts/lib/intel.js +653 -0
  433. package/plugins/pbr/scripts/lib/learnings.js +511 -0
  434. package/plugins/pbr/scripts/lib/migrate.js +309 -0
  435. package/plugins/pbr/scripts/lib/milestone.js +306 -0
  436. package/plugins/pbr/scripts/lib/msys-path.js +20 -0
  437. package/plugins/pbr/scripts/lib/negative-knowledge.js +194 -0
  438. package/plugins/pbr/scripts/lib/notification-throttle.js +141 -0
  439. package/plugins/pbr/scripts/lib/onboarding-generator.js +288 -0
  440. package/plugins/pbr/scripts/lib/parse-args.js +134 -0
  441. package/plugins/pbr/scripts/lib/pattern-routing.js +55 -0
  442. package/plugins/pbr/scripts/lib/patterns.js +272 -0
  443. package/plugins/pbr/scripts/lib/perf.js +190 -0
  444. package/plugins/pbr/scripts/lib/phase.js +1043 -0
  445. package/plugins/pbr/scripts/lib/pid-lock.js +156 -0
  446. package/plugins/pbr/scripts/lib/post-hoc.js +160 -0
  447. package/plugins/pbr/scripts/lib/pre-commit-checks.js +220 -0
  448. package/plugins/pbr/scripts/lib/pre-research.js +126 -0
  449. package/plugins/pbr/scripts/lib/premature-completion.js +312 -0
  450. package/plugins/pbr/scripts/lib/preview.js +174 -0
  451. package/plugins/pbr/scripts/lib/progress-visualization.js +296 -0
  452. package/plugins/pbr/scripts/lib/quick-init.js +131 -0
  453. package/plugins/pbr/scripts/lib/reference.js +236 -0
  454. package/plugins/pbr/scripts/lib/requirements.js +153 -0
  455. package/plugins/pbr/scripts/lib/resolve-root.js +66 -0
  456. package/plugins/pbr/scripts/lib/reverse-spec.js +259 -0
  457. package/plugins/pbr/scripts/lib/roadmap.js +1089 -0
  458. package/plugins/pbr/scripts/lib/security-scan.js +200 -0
  459. package/plugins/pbr/scripts/lib/session-briefing.js +918 -0
  460. package/plugins/pbr/scripts/lib/skill-section.js +99 -0
  461. package/plugins/pbr/scripts/lib/smart-next-task.js +198 -0
  462. package/plugins/pbr/scripts/lib/snapshot-manager.js +232 -0
  463. package/plugins/pbr/scripts/lib/spec-diff.js +209 -0
  464. package/plugins/pbr/scripts/lib/spec-engine.js +189 -0
  465. package/plugins/pbr/scripts/lib/spot-check.js +539 -0
  466. package/plugins/pbr/scripts/lib/state-queue.js +171 -0
  467. package/plugins/pbr/scripts/lib/state.js +1082 -0
  468. package/plugins/pbr/scripts/lib/status-render.js +511 -0
  469. package/plugins/pbr/scripts/lib/step-verify.js +149 -0
  470. package/plugins/pbr/scripts/lib/subagent-validators.js +1119 -0
  471. package/plugins/pbr/scripts/lib/suggest-next.js +435 -0
  472. package/plugins/pbr/scripts/lib/tech-debt-scanner.js +116 -0
  473. package/plugins/pbr/scripts/lib/templates.js +362 -0
  474. package/plugins/pbr/scripts/lib/test-selection.js +163 -0
  475. package/plugins/pbr/scripts/lib/todo.js +300 -0
  476. package/plugins/pbr/scripts/lib/verify.js +1561 -0
  477. package/plugins/pbr/scripts/log-notification.js +131 -0
  478. package/plugins/pbr/scripts/log-subagent.js +221 -18
  479. package/plugins/pbr/scripts/log-tool-failure.js +60 -8
  480. package/plugins/pbr/scripts/milestone-learnings.js +519 -0
  481. package/plugins/pbr/scripts/package.json +1 -1
  482. package/plugins/pbr/scripts/pbr-tools.js +362 -1247
  483. package/plugins/pbr/scripts/post-bash-triage.js +96 -0
  484. package/plugins/pbr/scripts/post-compact.js +135 -0
  485. package/plugins/pbr/scripts/post-hoc.js +237 -0
  486. package/plugins/pbr/scripts/post-write-dispatch.js +201 -31
  487. package/plugins/pbr/scripts/post-write-quality.js +4 -3
  488. package/plugins/pbr/scripts/pre-bash-dispatch.js +147 -51
  489. package/plugins/pbr/scripts/pre-skill-dispatch.js +114 -0
  490. package/plugins/pbr/scripts/pre-task-dispatch.js +269 -0
  491. package/plugins/pbr/scripts/pre-write-dispatch.js +170 -73
  492. package/plugins/pbr/scripts/progress-tracker.js +121 -324
  493. package/plugins/pbr/scripts/prompt-guard.js +114 -0
  494. package/plugins/pbr/scripts/prompt-routing.js +209 -0
  495. package/plugins/pbr/scripts/quick-status.js +179 -0
  496. package/plugins/pbr/scripts/record-incident.js +37 -0
  497. package/plugins/pbr/scripts/risk-classifier.cjs +123 -0
  498. package/plugins/pbr/scripts/run-hook.js +63 -23
  499. package/plugins/pbr/scripts/session-cleanup.js +428 -29
  500. package/plugins/pbr/scripts/session-tracker.js +124 -0
  501. package/plugins/pbr/scripts/status-line.js +593 -32
  502. package/plugins/pbr/scripts/suggest-compact.js +201 -13
  503. package/plugins/pbr/scripts/sync-context-to-claude.js +100 -0
  504. package/plugins/pbr/scripts/task-completed.js +165 -4
  505. package/plugins/pbr/scripts/test/config.test.js +126 -0
  506. package/plugins/pbr/scripts/test/cross-platform.test.js +120 -0
  507. package/plugins/pbr/scripts/test/fixtures/config.json +20 -0
  508. package/plugins/pbr/scripts/test/fixtures/plan.md +54 -0
  509. package/plugins/pbr/scripts/test/fixtures/project.md +30 -0
  510. package/plugins/pbr/scripts/test/fixtures/roadmap.md +55 -0
  511. package/plugins/pbr/scripts/test/fixtures/state.md +60 -0
  512. package/plugins/pbr/scripts/test/fixtures/summary.md +35 -0
  513. package/plugins/pbr/scripts/test/fixtures.test.js +184 -0
  514. package/plugins/pbr/scripts/test/phase.test.js +142 -0
  515. package/plugins/pbr/scripts/test/roadmap.test.js +96 -0
  516. package/plugins/pbr/scripts/test/state.test.js +155 -0
  517. package/plugins/pbr/scripts/track-context-budget.js +368 -104
  518. package/plugins/pbr/scripts/track-user-gates.js +88 -0
  519. package/plugins/pbr/scripts/trust-tracker.js +193 -0
  520. package/plugins/pbr/scripts/validate-commit.js +59 -26
  521. package/plugins/pbr/scripts/validate-skill-args.js +87 -15
  522. package/plugins/pbr/scripts/validate-task.js +83 -627
  523. package/plugins/pbr/scripts/worktree-create.js +144 -0
  524. package/plugins/pbr/scripts/worktree-remove.js +147 -0
  525. package/plugins/pbr/skills/audit/SKILL.md +195 -24
  526. package/plugins/pbr/skills/audit-fix/SKILL.md +326 -0
  527. package/plugins/pbr/skills/autonomous/SKILL.md +551 -0
  528. package/plugins/pbr/skills/backlog/SKILL.md +56 -0
  529. package/plugins/pbr/skills/begin/SKILL.md +508 -153
  530. package/plugins/pbr/skills/begin/templates/STATE.md.tmpl +1 -2
  531. package/plugins/pbr/skills/begin/templates/config.json.tmpl +419 -36
  532. package/plugins/pbr/skills/begin/templates/researcher-prompt.md.tmpl +28 -0
  533. package/plugins/pbr/skills/begin/templates/roadmap-prompt.md.tmpl +28 -3
  534. package/plugins/pbr/skills/begin/templates/synthesis-prompt.md.tmpl +33 -5
  535. package/plugins/pbr/skills/build/SKILL.md +1180 -358
  536. package/plugins/pbr/skills/build/templates/continuation-prompt.md.tmpl +26 -0
  537. package/plugins/pbr/skills/build/templates/executor-prompt.md.tmpl +77 -0
  538. package/plugins/pbr/skills/build/templates/inline-verifier-prompt.md.tmpl +33 -0
  539. package/plugins/pbr/skills/build/templates/qa-round-context.md.tmpl +16 -0
  540. package/plugins/pbr/skills/config/SKILL.md +112 -9
  541. package/plugins/pbr/skills/continue/SKILL.md +113 -33
  542. package/plugins/pbr/skills/dashboard/SKILL.md +21 -9
  543. package/plugins/pbr/skills/debug/SKILL.md +70 -12
  544. package/plugins/pbr/skills/debug/templates/continuation-prompt.md.tmpl +12 -1
  545. package/plugins/pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +12 -5
  546. package/plugins/pbr/skills/discuss/SKILL.md +205 -24
  547. package/plugins/pbr/skills/discuss/templates/CONTEXT.md.tmpl +21 -1
  548. package/plugins/pbr/skills/do/SKILL.md +119 -24
  549. package/plugins/pbr/skills/explore/SKILL.md +95 -20
  550. package/plugins/pbr/skills/fast/SKILL.md +94 -0
  551. package/plugins/pbr/skills/forensics/SKILL.md +144 -0
  552. package/plugins/pbr/skills/health/SKILL.md +35 -117
  553. package/plugins/pbr/skills/help/SKILL.md +83 -123
  554. package/plugins/pbr/skills/import/SKILL.md +332 -13
  555. package/plugins/pbr/skills/intel/SKILL.md +131 -0
  556. package/plugins/pbr/skills/list-phase-assumptions/SKILL.md +231 -0
  557. package/plugins/pbr/skills/milestone/SKILL.md +383 -274
  558. package/plugins/pbr/skills/milestone/templates/audit-output.md.tmpl +76 -0
  559. package/plugins/pbr/skills/milestone/templates/complete-output.md.tmpl +32 -0
  560. package/plugins/pbr/skills/milestone/templates/edge-cases.md +54 -0
  561. package/plugins/pbr/skills/milestone/templates/gaps-output.md.tmpl +25 -0
  562. package/plugins/pbr/skills/milestone/templates/integration-checker-prompt.md.tmpl +25 -0
  563. package/plugins/pbr/skills/milestone/templates/new-output.md.tmpl +29 -0
  564. package/plugins/pbr/skills/milestone-summary/SKILL.md +86 -0
  565. package/plugins/pbr/skills/note/SKILL.md +20 -4
  566. package/plugins/pbr/skills/pause/SKILL.md +54 -14
  567. package/plugins/pbr/skills/pause/templates/continue-here.md.tmpl +33 -52
  568. package/plugins/pbr/skills/plan/SKILL.md +526 -280
  569. package/plugins/pbr/skills/plan/templates/checker-prompt.md.tmpl +20 -2
  570. package/plugins/pbr/skills/plan/templates/completion-output.md.tmpl +27 -0
  571. package/plugins/pbr/skills/plan/templates/planner-prompt.md.tmpl +43 -1
  572. package/plugins/pbr/skills/plan/templates/revision-prompt.md.tmpl +21 -5
  573. package/plugins/pbr/skills/profile/SKILL.md +185 -0
  574. package/plugins/pbr/skills/profile-user/SKILL.md +227 -0
  575. package/plugins/pbr/skills/quick/SKILL.md +435 -100
  576. package/plugins/pbr/skills/release/SKILL.md +206 -0
  577. package/plugins/pbr/skills/resume/SKILL.md +170 -46
  578. package/plugins/pbr/skills/review/SKILL.md +233 -165
  579. package/plugins/pbr/skills/review/templates/verifier-prompt.md.tmpl +7 -0
  580. package/plugins/pbr/skills/scan/SKILL.md +152 -106
  581. package/plugins/pbr/skills/scan/templates/mapper-prompt.md.tmpl +5 -56
  582. package/plugins/pbr/skills/seed/SKILL.md +87 -0
  583. package/plugins/pbr/skills/session-report/SKILL.md +130 -0
  584. package/plugins/pbr/skills/setup/SKILL.md +150 -202
  585. package/plugins/pbr/skills/shared/agent-context-enrichment.md +21 -0
  586. package/plugins/pbr/skills/shared/agent-type-resolution.md +32 -0
  587. package/plugins/pbr/skills/shared/commit-planning-docs.md +8 -0
  588. package/plugins/pbr/skills/shared/context-budget.md +66 -1
  589. package/plugins/pbr/skills/shared/context-loader-task.md +18 -11
  590. package/plugins/pbr/skills/shared/criterion-writing.md +58 -0
  591. package/plugins/pbr/skills/shared/digest-select.md +2 -2
  592. package/plugins/pbr/skills/shared/domain-probes.md +1 -1
  593. package/plugins/pbr/skills/shared/error-reporting.md +38 -60
  594. package/plugins/pbr/skills/shared/gate-prompts.md +4 -2
  595. package/plugins/pbr/skills/shared/memory-capture.md +48 -0
  596. package/plugins/pbr/skills/shared/phase-argument-parsing.md +4 -4
  597. package/plugins/pbr/skills/shared/revision-loop.md +24 -6
  598. package/plugins/pbr/skills/shared/state-update.md +49 -56
  599. package/plugins/pbr/skills/shared/universal-anti-patterns.md +27 -4
  600. package/plugins/pbr/skills/ship/SKILL.md +155 -0
  601. package/plugins/pbr/skills/stats/SKILL.md +110 -0
  602. package/plugins/pbr/skills/status/SKILL.md +185 -119
  603. package/plugins/pbr/skills/test/SKILL.md +254 -0
  604. package/plugins/pbr/skills/thread/SKILL.md +73 -0
  605. package/plugins/pbr/skills/todo/SKILL.md +28 -72
  606. package/plugins/pbr/skills/ui-phase/SKILL.md +180 -0
  607. package/plugins/pbr/skills/ui-review/SKILL.md +206 -0
  608. package/plugins/pbr/skills/undo/SKILL.md +221 -0
  609. package/plugins/pbr/skills/validate-phase/SKILL.md +362 -0
  610. package/plugins/pbr/templates/CONTEXT.md.tmpl +45 -20
  611. package/plugins/pbr/templates/DISCOVERY.md.tmpl +29 -0
  612. package/plugins/pbr/templates/DISCUSSION-LOG.md.tmpl +49 -0
  613. package/plugins/pbr/templates/HANDOFF.json.tmpl +30 -0
  614. package/plugins/pbr/templates/INTEGRATION-REPORT.md.tmpl +18 -2
  615. package/plugins/pbr/templates/MILESTONE-AUDIT.md.tmpl +44 -0
  616. package/plugins/pbr/templates/PROJECT.md.tmpl +126 -0
  617. package/plugins/pbr/templates/REQUIREMENTS.md.tmpl +96 -0
  618. package/plugins/pbr/templates/RETROSPECTIVE.md.tmpl +43 -0
  619. package/plugins/pbr/templates/ROADMAP.md.tmpl +108 -14
  620. package/plugins/pbr/templates/SUMMARY-complex.md.tmpl +133 -0
  621. package/plugins/pbr/templates/SUMMARY-minimal.md.tmpl +55 -0
  622. package/plugins/pbr/templates/SUMMARY.md.tmpl +21 -0
  623. package/plugins/pbr/templates/UAT.md.tmpl +94 -0
  624. package/plugins/pbr/templates/UI-SPEC.md.tmpl +144 -0
  625. package/plugins/pbr/templates/VALIDATION.md.tmpl +94 -0
  626. package/plugins/pbr/templates/VERIFICATION-DETAIL.md.tmpl +54 -13
  627. package/plugins/pbr/templates/project-CONTEXT.md.tmpl +59 -0
  628. package/plugins/pbr/templates/research-outputs/ARCHITECTURE.md.tmpl +91 -0
  629. package/plugins/pbr/templates/research-outputs/FEATURES.md.tmpl +64 -0
  630. package/plugins/pbr/templates/research-outputs/PITFALLS.md.tmpl +50 -0
  631. package/plugins/pbr/templates/research-outputs/STACK.md.tmpl +63 -0
  632. package/plugins/pbr/templates/research-outputs/SUMMARY.md.tmpl +98 -0
  633. package/scripts/build-hooks.js +61 -0
  634. package/scripts/check-ci.js +100 -0
  635. package/scripts/clean-changelog.js +364 -0
  636. package/scripts/generate-derivatives.js +581 -0
  637. package/scripts/posttest.js +93 -0
  638. package/scripts/release.js +262 -0
  639. package/scripts/run-tests.cjs +29 -0
  640. package/scripts/test-wrapper.js +43 -0
  641. package/dashboard/bin/cli.js +0 -25
  642. package/dashboard/public/css/layout.css +0 -704
  643. package/dashboard/public/css/status-colors.css +0 -98
  644. package/dashboard/public/css/tokens.css +0 -59
  645. package/dashboard/public/js/htmx-title.js +0 -5
  646. package/dashboard/public/js/sidebar-toggle.js +0 -34
  647. package/dashboard/public/js/sse-client.js +0 -100
  648. package/dashboard/public/js/theme-toggle.js +0 -46
  649. package/dashboard/src/app.js +0 -91
  650. package/dashboard/src/middleware/current-phase.js +0 -24
  651. package/dashboard/src/middleware/errorHandler.js +0 -52
  652. package/dashboard/src/middleware/notFoundHandler.js +0 -9
  653. package/dashboard/src/repositories/planning.repository.js +0 -130
  654. package/dashboard/src/routes/events.routes.js +0 -45
  655. package/dashboard/src/routes/index.routes.js +0 -35
  656. package/dashboard/src/routes/pages.routes.js +0 -426
  657. package/dashboard/src/server.js +0 -42
  658. package/dashboard/src/services/analytics.service.js +0 -141
  659. package/dashboard/src/services/dashboard.service.js +0 -309
  660. package/dashboard/src/services/milestone.service.js +0 -222
  661. package/dashboard/src/services/notes.service.js +0 -50
  662. package/dashboard/src/services/phase.service.js +0 -232
  663. package/dashboard/src/services/project.service.js +0 -57
  664. package/dashboard/src/services/roadmap.service.js +0 -258
  665. package/dashboard/src/services/sse.service.js +0 -58
  666. package/dashboard/src/services/todo.service.js +0 -272
  667. package/dashboard/src/services/watcher.service.js +0 -48
  668. package/dashboard/src/utils/cache.js +0 -55
  669. package/dashboard/src/views/analytics.ejs +0 -5
  670. package/dashboard/src/views/coming-soon.ejs +0 -11
  671. package/dashboard/src/views/dependencies.ejs +0 -5
  672. package/dashboard/src/views/error.ejs +0 -20
  673. package/dashboard/src/views/index.ejs +0 -5
  674. package/dashboard/src/views/milestone-detail.ejs +0 -5
  675. package/dashboard/src/views/milestones.ejs +0 -5
  676. package/dashboard/src/views/notes.ejs +0 -5
  677. package/dashboard/src/views/partials/analytics-content.ejs +0 -90
  678. package/dashboard/src/views/partials/breadcrumbs.ejs +0 -14
  679. package/dashboard/src/views/partials/dashboard-content.ejs +0 -84
  680. package/dashboard/src/views/partials/dependencies-content.ejs +0 -48
  681. package/dashboard/src/views/partials/empty-state.ejs +0 -7
  682. package/dashboard/src/views/partials/footer.ejs +0 -3
  683. package/dashboard/src/views/partials/head.ejs +0 -30
  684. package/dashboard/src/views/partials/header.ejs +0 -21
  685. package/dashboard/src/views/partials/layout-bottom.ejs +0 -43
  686. package/dashboard/src/views/partials/layout-top.ejs +0 -16
  687. package/dashboard/src/views/partials/milestone-detail-content.ejs +0 -20
  688. package/dashboard/src/views/partials/milestones-content.ejs +0 -88
  689. package/dashboard/src/views/partials/notes-content.ejs +0 -23
  690. package/dashboard/src/views/partials/phase-content.ejs +0 -193
  691. package/dashboard/src/views/partials/phase-doc-content.ejs +0 -38
  692. package/dashboard/src/views/partials/phases-content.ejs +0 -124
  693. package/dashboard/src/views/partials/roadmap-content.ejs +0 -180
  694. package/dashboard/src/views/partials/sidebar.ejs +0 -99
  695. package/dashboard/src/views/partials/todo-create-content.ejs +0 -54
  696. package/dashboard/src/views/partials/todo-detail-content.ejs +0 -42
  697. package/dashboard/src/views/partials/todos-content.ejs +0 -97
  698. package/dashboard/src/views/phase-detail.ejs +0 -5
  699. package/dashboard/src/views/phase-doc.ejs +0 -5
  700. package/dashboard/src/views/phases.ejs +0 -5
  701. package/dashboard/src/views/roadmap.ejs +0 -5
  702. package/dashboard/src/views/todo-create.ejs +0 -5
  703. package/dashboard/src/views/todo-detail.ejs +0 -5
  704. package/dashboard/src/views/todos.ejs +0 -5
  705. package/plugins/copilot-pbr/CHANGELOG.md +0 -19
  706. package/plugins/copilot-pbr/README.md +0 -139
  707. package/plugins/copilot-pbr/agents/audit.agent.md +0 -113
  708. package/plugins/copilot-pbr/agents/codebase-mapper.agent.md +0 -151
  709. package/plugins/copilot-pbr/agents/debugger.agent.md +0 -182
  710. package/plugins/copilot-pbr/agents/executor.agent.md +0 -267
  711. package/plugins/copilot-pbr/agents/general.agent.md +0 -88
  712. package/plugins/copilot-pbr/agents/integration-checker.agent.md +0 -119
  713. package/plugins/copilot-pbr/agents/plan-checker.agent.md +0 -208
  714. package/plugins/copilot-pbr/agents/planner.agent.md +0 -238
  715. package/plugins/copilot-pbr/agents/researcher.agent.md +0 -186
  716. package/plugins/copilot-pbr/agents/synthesizer.agent.md +0 -126
  717. package/plugins/copilot-pbr/agents/verifier.agent.md +0 -228
  718. package/plugins/copilot-pbr/hooks/hooks.json +0 -258
  719. package/plugins/copilot-pbr/plugin.json +0 -30
  720. package/plugins/copilot-pbr/references/agent-anti-patterns.md +0 -25
  721. package/plugins/copilot-pbr/references/agent-contracts.md +0 -297
  722. package/plugins/copilot-pbr/references/agent-interactions.md +0 -135
  723. package/plugins/copilot-pbr/references/agent-teams.md +0 -55
  724. package/plugins/copilot-pbr/references/checkpoints.md +0 -158
  725. package/plugins/copilot-pbr/references/common-bug-patterns.md +0 -14
  726. package/plugins/copilot-pbr/references/config-reference.md +0 -442
  727. package/plugins/copilot-pbr/references/continuation-format.md +0 -213
  728. package/plugins/copilot-pbr/references/deviation-rules.md +0 -113
  729. package/plugins/copilot-pbr/references/git-integration.md +0 -227
  730. package/plugins/copilot-pbr/references/integration-patterns.md +0 -118
  731. package/plugins/copilot-pbr/references/model-profiles.md +0 -100
  732. package/plugins/copilot-pbr/references/model-selection.md +0 -32
  733. package/plugins/copilot-pbr/references/pbr-rules.md +0 -195
  734. package/plugins/copilot-pbr/references/pbr-tools-cli.md +0 -285
  735. package/plugins/copilot-pbr/references/plan-authoring.md +0 -182
  736. package/plugins/copilot-pbr/references/plan-format.md +0 -288
  737. package/plugins/copilot-pbr/references/planning-config.md +0 -214
  738. package/plugins/copilot-pbr/references/questioning.md +0 -215
  739. package/plugins/copilot-pbr/references/reading-verification.md +0 -128
  740. package/plugins/copilot-pbr/references/stub-patterns.md +0 -161
  741. package/plugins/copilot-pbr/references/subagent-coordination.md +0 -120
  742. package/plugins/copilot-pbr/references/ui-formatting.md +0 -444
  743. package/plugins/copilot-pbr/references/verification-patterns.md +0 -199
  744. package/plugins/copilot-pbr/references/wave-execution.md +0 -96
  745. package/plugins/copilot-pbr/rules/pbr-workflow.mdc +0 -48
  746. package/plugins/copilot-pbr/setup.ps1 +0 -93
  747. package/plugins/copilot-pbr/setup.sh +0 -93
  748. package/plugins/copilot-pbr/skills/audit/SKILL.md +0 -330
  749. package/plugins/copilot-pbr/skills/begin/SKILL.md +0 -589
  750. package/plugins/copilot-pbr/skills/begin/templates/PROJECT.md.tmpl +0 -34
  751. package/plugins/copilot-pbr/skills/begin/templates/REQUIREMENTS.md.tmpl +0 -19
  752. package/plugins/copilot-pbr/skills/begin/templates/STATE.md.tmpl +0 -50
  753. package/plugins/copilot-pbr/skills/begin/templates/config.json.tmpl +0 -64
  754. package/plugins/copilot-pbr/skills/begin/templates/researcher-prompt.md.tmpl +0 -20
  755. package/plugins/copilot-pbr/skills/begin/templates/roadmap-prompt.md.tmpl +0 -31
  756. package/plugins/copilot-pbr/skills/begin/templates/synthesis-prompt.md.tmpl +0 -17
  757. package/plugins/copilot-pbr/skills/build/SKILL.md +0 -960
  758. package/plugins/copilot-pbr/skills/config/SKILL.md +0 -250
  759. package/plugins/copilot-pbr/skills/continue/SKILL.md +0 -159
  760. package/plugins/copilot-pbr/skills/dashboard/SKILL.md +0 -43
  761. package/plugins/copilot-pbr/skills/debug/SKILL.md +0 -508
  762. package/plugins/copilot-pbr/skills/debug/templates/continuation-prompt.md.tmpl +0 -17
  763. package/plugins/copilot-pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +0 -28
  764. package/plugins/copilot-pbr/skills/discuss/SKILL.md +0 -353
  765. package/plugins/copilot-pbr/skills/discuss/templates/CONTEXT.md.tmpl +0 -62
  766. package/plugins/copilot-pbr/skills/discuss/templates/decision-categories.md +0 -10
  767. package/plugins/copilot-pbr/skills/do/SKILL.md +0 -66
  768. package/plugins/copilot-pbr/skills/explore/SKILL.md +0 -373
  769. package/plugins/copilot-pbr/skills/health/SKILL.md +0 -283
  770. package/plugins/copilot-pbr/skills/health/templates/check-pattern.md.tmpl +0 -31
  771. package/plugins/copilot-pbr/skills/health/templates/output-format.md.tmpl +0 -64
  772. package/plugins/copilot-pbr/skills/help/SKILL.md +0 -193
  773. package/plugins/copilot-pbr/skills/import/SKILL.md +0 -502
  774. package/plugins/copilot-pbr/skills/milestone/SKILL.md +0 -806
  775. package/plugins/copilot-pbr/skills/milestone/templates/audit-report.md.tmpl +0 -49
  776. package/plugins/copilot-pbr/skills/milestone/templates/stats-file.md.tmpl +0 -31
  777. package/plugins/copilot-pbr/skills/note/SKILL.md +0 -213
  778. package/plugins/copilot-pbr/skills/pause/SKILL.md +0 -247
  779. package/plugins/copilot-pbr/skills/pause/templates/continue-here.md.tmpl +0 -72
  780. package/plugins/copilot-pbr/skills/plan/SKILL.md +0 -662
  781. package/plugins/copilot-pbr/skills/plan/templates/checker-prompt.md.tmpl +0 -22
  782. package/plugins/copilot-pbr/skills/plan/templates/gap-closure-prompt.md.tmpl +0 -33
  783. package/plugins/copilot-pbr/skills/plan/templates/planner-prompt.md.tmpl +0 -39
  784. package/plugins/copilot-pbr/skills/plan/templates/researcher-prompt.md.tmpl +0 -20
  785. package/plugins/copilot-pbr/skills/plan/templates/revision-prompt.md.tmpl +0 -24
  786. package/plugins/copilot-pbr/skills/quick/SKILL.md +0 -376
  787. package/plugins/copilot-pbr/skills/resume/SKILL.md +0 -399
  788. package/plugins/copilot-pbr/skills/review/SKILL.md +0 -653
  789. package/plugins/copilot-pbr/skills/review/templates/debugger-prompt.md.tmpl +0 -61
  790. package/plugins/copilot-pbr/skills/review/templates/gap-planner-prompt.md.tmpl +0 -41
  791. package/plugins/copilot-pbr/skills/review/templates/verifier-prompt.md.tmpl +0 -116
  792. package/plugins/copilot-pbr/skills/scan/SKILL.md +0 -299
  793. package/plugins/copilot-pbr/skills/scan/templates/mapper-prompt.md.tmpl +0 -202
  794. package/plugins/copilot-pbr/skills/setup/SKILL.md +0 -296
  795. package/plugins/copilot-pbr/skills/shared/commit-planning-docs.md +0 -36
  796. package/plugins/copilot-pbr/skills/shared/config-loading.md +0 -103
  797. package/plugins/copilot-pbr/skills/shared/context-budget.md +0 -41
  798. package/plugins/copilot-pbr/skills/shared/context-loader-task.md +0 -87
  799. package/plugins/copilot-pbr/skills/shared/digest-select.md +0 -80
  800. package/plugins/copilot-pbr/skills/shared/domain-probes.md +0 -126
  801. package/plugins/copilot-pbr/skills/shared/error-recovery-strategies.md +0 -51
  802. package/plugins/copilot-pbr/skills/shared/error-reporting.md +0 -81
  803. package/plugins/copilot-pbr/skills/shared/gate-prompts.md +0 -389
  804. package/plugins/copilot-pbr/skills/shared/phase-argument-parsing.md +0 -46
  805. package/plugins/copilot-pbr/skills/shared/progress-display.md +0 -53
  806. package/plugins/copilot-pbr/skills/shared/revision-loop.md +0 -82
  807. package/plugins/copilot-pbr/skills/shared/state-loading.md +0 -63
  808. package/plugins/copilot-pbr/skills/shared/state-update.md +0 -162
  809. package/plugins/copilot-pbr/skills/shared/universal-anti-patterns.md +0 -38
  810. package/plugins/copilot-pbr/skills/status/SKILL.md +0 -362
  811. package/plugins/copilot-pbr/skills/statusline/SKILL.md +0 -149
  812. package/plugins/copilot-pbr/skills/todo/SKILL.md +0 -279
  813. package/plugins/copilot-pbr/templates/CONTEXT.md.tmpl +0 -53
  814. package/plugins/copilot-pbr/templates/INTEGRATION-REPORT.md.tmpl +0 -152
  815. package/plugins/copilot-pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -98
  816. package/plugins/copilot-pbr/templates/ROADMAP.md.tmpl +0 -41
  817. package/plugins/copilot-pbr/templates/SUMMARY.md.tmpl +0 -82
  818. package/plugins/copilot-pbr/templates/VERIFICATION-DETAIL.md.tmpl +0 -117
  819. package/plugins/copilot-pbr/templates/codebase/ARCHITECTURE.md.tmpl +0 -98
  820. package/plugins/copilot-pbr/templates/codebase/CONCERNS.md.tmpl +0 -93
  821. package/plugins/copilot-pbr/templates/codebase/CONVENTIONS.md.tmpl +0 -104
  822. package/plugins/copilot-pbr/templates/codebase/INTEGRATIONS.md.tmpl +0 -78
  823. package/plugins/copilot-pbr/templates/codebase/STACK.md.tmpl +0 -78
  824. package/plugins/copilot-pbr/templates/codebase/STRUCTURE.md.tmpl +0 -80
  825. package/plugins/copilot-pbr/templates/codebase/TESTING.md.tmpl +0 -107
  826. package/plugins/copilot-pbr/templates/continue-here.md.tmpl +0 -74
  827. package/plugins/copilot-pbr/templates/prompt-partials/phase-project-context.md.tmpl +0 -38
  828. package/plugins/copilot-pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
  829. package/plugins/copilot-pbr/templates/research/STACK.md.tmpl +0 -71
  830. package/plugins/copilot-pbr/templates/research/SUMMARY.md.tmpl +0 -112
  831. package/plugins/copilot-pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
  832. package/plugins/copilot-pbr/templates/research-outputs/project-research.md.tmpl +0 -99
  833. package/plugins/copilot-pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
  834. package/plugins/cursor-pbr/.cursor-plugin/plugin.json +0 -32
  835. package/plugins/cursor-pbr/CHANGELOG.md +0 -15
  836. package/plugins/cursor-pbr/README.md +0 -123
  837. package/plugins/cursor-pbr/agents/audit.md +0 -178
  838. package/plugins/cursor-pbr/agents/codebase-mapper.md +0 -150
  839. package/plugins/cursor-pbr/agents/debugger.md +0 -181
  840. package/plugins/cursor-pbr/agents/executor.md +0 -266
  841. package/plugins/cursor-pbr/agents/general.md +0 -87
  842. package/plugins/cursor-pbr/agents/integration-checker.md +0 -118
  843. package/plugins/cursor-pbr/agents/plan-checker.md +0 -207
  844. package/plugins/cursor-pbr/agents/planner.md +0 -237
  845. package/plugins/cursor-pbr/agents/researcher.md +0 -185
  846. package/plugins/cursor-pbr/agents/synthesizer.md +0 -125
  847. package/plugins/cursor-pbr/agents/verifier.md +0 -227
  848. package/plugins/cursor-pbr/assets/.gitkeep +0 -0
  849. package/plugins/cursor-pbr/assets/logo.svg +0 -21
  850. package/plugins/cursor-pbr/hooks/hooks.json +0 -224
  851. package/plugins/cursor-pbr/references/agent-anti-patterns.md +0 -25
  852. package/plugins/cursor-pbr/references/agent-contracts.md +0 -297
  853. package/plugins/cursor-pbr/references/agent-interactions.md +0 -135
  854. package/plugins/cursor-pbr/references/agent-teams.md +0 -55
  855. package/plugins/cursor-pbr/references/checkpoints.md +0 -158
  856. package/plugins/cursor-pbr/references/common-bug-patterns.md +0 -14
  857. package/plugins/cursor-pbr/references/config-reference.md +0 -442
  858. package/plugins/cursor-pbr/references/continuation-format.md +0 -213
  859. package/plugins/cursor-pbr/references/deviation-rules.md +0 -113
  860. package/plugins/cursor-pbr/references/git-integration.md +0 -227
  861. package/plugins/cursor-pbr/references/integration-patterns.md +0 -118
  862. package/plugins/cursor-pbr/references/model-profiles.md +0 -100
  863. package/plugins/cursor-pbr/references/model-selection.md +0 -32
  864. package/plugins/cursor-pbr/references/pbr-rules.md +0 -195
  865. package/plugins/cursor-pbr/references/pbr-tools-cli.md +0 -285
  866. package/plugins/cursor-pbr/references/plan-authoring.md +0 -182
  867. package/plugins/cursor-pbr/references/plan-format.md +0 -288
  868. package/plugins/cursor-pbr/references/planning-config.md +0 -214
  869. package/plugins/cursor-pbr/references/questioning.md +0 -215
  870. package/plugins/cursor-pbr/references/reading-verification.md +0 -128
  871. package/plugins/cursor-pbr/references/stub-patterns.md +0 -161
  872. package/plugins/cursor-pbr/references/subagent-coordination.md +0 -120
  873. package/plugins/cursor-pbr/references/ui-formatting.md +0 -444
  874. package/plugins/cursor-pbr/references/verification-patterns.md +0 -199
  875. package/plugins/cursor-pbr/references/wave-execution.md +0 -96
  876. package/plugins/cursor-pbr/rules/pbr-workflow.mdc +0 -48
  877. package/plugins/cursor-pbr/setup.ps1 +0 -78
  878. package/plugins/cursor-pbr/setup.sh +0 -83
  879. package/plugins/cursor-pbr/skills/audit/SKILL.md +0 -331
  880. package/plugins/cursor-pbr/skills/begin/SKILL.md +0 -589
  881. package/plugins/cursor-pbr/skills/begin/templates/PROJECT.md.tmpl +0 -34
  882. package/plugins/cursor-pbr/skills/begin/templates/REQUIREMENTS.md.tmpl +0 -19
  883. package/plugins/cursor-pbr/skills/begin/templates/STATE.md.tmpl +0 -50
  884. package/plugins/cursor-pbr/skills/begin/templates/config.json.tmpl +0 -64
  885. package/plugins/cursor-pbr/skills/begin/templates/researcher-prompt.md.tmpl +0 -20
  886. package/plugins/cursor-pbr/skills/begin/templates/roadmap-prompt.md.tmpl +0 -31
  887. package/plugins/cursor-pbr/skills/begin/templates/synthesis-prompt.md.tmpl +0 -17
  888. package/plugins/cursor-pbr/skills/build/SKILL.md +0 -961
  889. package/plugins/cursor-pbr/skills/config/SKILL.md +0 -252
  890. package/plugins/cursor-pbr/skills/continue/SKILL.md +0 -159
  891. package/plugins/cursor-pbr/skills/dashboard/SKILL.md +0 -44
  892. package/plugins/cursor-pbr/skills/debug/SKILL.md +0 -512
  893. package/plugins/cursor-pbr/skills/debug/templates/continuation-prompt.md.tmpl +0 -17
  894. package/plugins/cursor-pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +0 -28
  895. package/plugins/cursor-pbr/skills/discuss/SKILL.md +0 -354
  896. package/plugins/cursor-pbr/skills/discuss/templates/CONTEXT.md.tmpl +0 -62
  897. package/plugins/cursor-pbr/skills/discuss/templates/decision-categories.md +0 -10
  898. package/plugins/cursor-pbr/skills/do/SKILL.md +0 -67
  899. package/plugins/cursor-pbr/skills/explore/SKILL.md +0 -376
  900. package/plugins/cursor-pbr/skills/health/SKILL.md +0 -283
  901. package/plugins/cursor-pbr/skills/health/templates/check-pattern.md.tmpl +0 -31
  902. package/plugins/cursor-pbr/skills/health/templates/output-format.md.tmpl +0 -64
  903. package/plugins/cursor-pbr/skills/help/SKILL.md +0 -193
  904. package/plugins/cursor-pbr/skills/import/SKILL.md +0 -505
  905. package/plugins/cursor-pbr/skills/milestone/SKILL.md +0 -807
  906. package/plugins/cursor-pbr/skills/milestone/templates/audit-report.md.tmpl +0 -49
  907. package/plugins/cursor-pbr/skills/milestone/templates/stats-file.md.tmpl +0 -31
  908. package/plugins/cursor-pbr/skills/note/SKILL.md +0 -214
  909. package/plugins/cursor-pbr/skills/pause/SKILL.md +0 -248
  910. package/plugins/cursor-pbr/skills/pause/templates/continue-here.md.tmpl +0 -72
  911. package/plugins/cursor-pbr/skills/plan/SKILL.md +0 -663
  912. package/plugins/cursor-pbr/skills/plan/templates/checker-prompt.md.tmpl +0 -22
  913. package/plugins/cursor-pbr/skills/plan/templates/gap-closure-prompt.md.tmpl +0 -33
  914. package/plugins/cursor-pbr/skills/plan/templates/planner-prompt.md.tmpl +0 -39
  915. package/plugins/cursor-pbr/skills/plan/templates/researcher-prompt.md.tmpl +0 -20
  916. package/plugins/cursor-pbr/skills/plan/templates/revision-prompt.md.tmpl +0 -24
  917. package/plugins/cursor-pbr/skills/quick/SKILL.md +0 -376
  918. package/plugins/cursor-pbr/skills/resume/SKILL.md +0 -399
  919. package/plugins/cursor-pbr/skills/review/SKILL.md +0 -654
  920. package/plugins/cursor-pbr/skills/review/templates/debugger-prompt.md.tmpl +0 -61
  921. package/plugins/cursor-pbr/skills/review/templates/gap-planner-prompt.md.tmpl +0 -41
  922. package/plugins/cursor-pbr/skills/review/templates/verifier-prompt.md.tmpl +0 -116
  923. package/plugins/cursor-pbr/skills/scan/SKILL.md +0 -300
  924. package/plugins/cursor-pbr/skills/scan/templates/mapper-prompt.md.tmpl +0 -202
  925. package/plugins/cursor-pbr/skills/setup/SKILL.md +0 -296
  926. package/plugins/cursor-pbr/skills/shared/commit-planning-docs.md +0 -36
  927. package/plugins/cursor-pbr/skills/shared/config-loading.md +0 -103
  928. package/plugins/cursor-pbr/skills/shared/context-budget.md +0 -41
  929. package/plugins/cursor-pbr/skills/shared/context-loader-task.md +0 -87
  930. package/plugins/cursor-pbr/skills/shared/digest-select.md +0 -80
  931. package/plugins/cursor-pbr/skills/shared/domain-probes.md +0 -126
  932. package/plugins/cursor-pbr/skills/shared/error-recovery-strategies.md +0 -51
  933. package/plugins/cursor-pbr/skills/shared/error-reporting.md +0 -81
  934. package/plugins/cursor-pbr/skills/shared/gate-prompts.md +0 -389
  935. package/plugins/cursor-pbr/skills/shared/phase-argument-parsing.md +0 -46
  936. package/plugins/cursor-pbr/skills/shared/progress-display.md +0 -53
  937. package/plugins/cursor-pbr/skills/shared/revision-loop.md +0 -82
  938. package/plugins/cursor-pbr/skills/shared/state-loading.md +0 -63
  939. package/plugins/cursor-pbr/skills/shared/state-update.md +0 -162
  940. package/plugins/cursor-pbr/skills/shared/universal-anti-patterns.md +0 -38
  941. package/plugins/cursor-pbr/skills/status/SKILL.md +0 -362
  942. package/plugins/cursor-pbr/skills/statusline/SKILL.md +0 -150
  943. package/plugins/cursor-pbr/skills/todo/SKILL.md +0 -280
  944. package/plugins/cursor-pbr/templates/CONTEXT.md.tmpl +0 -53
  945. package/plugins/cursor-pbr/templates/INTEGRATION-REPORT.md.tmpl +0 -152
  946. package/plugins/cursor-pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -98
  947. package/plugins/cursor-pbr/templates/ROADMAP.md.tmpl +0 -41
  948. package/plugins/cursor-pbr/templates/SUMMARY.md.tmpl +0 -82
  949. package/plugins/cursor-pbr/templates/VERIFICATION-DETAIL.md.tmpl +0 -117
  950. package/plugins/cursor-pbr/templates/codebase/ARCHITECTURE.md.tmpl +0 -98
  951. package/plugins/cursor-pbr/templates/codebase/CONCERNS.md.tmpl +0 -93
  952. package/plugins/cursor-pbr/templates/codebase/CONVENTIONS.md.tmpl +0 -104
  953. package/plugins/cursor-pbr/templates/codebase/INTEGRATIONS.md.tmpl +0 -78
  954. package/plugins/cursor-pbr/templates/codebase/STACK.md.tmpl +0 -78
  955. package/plugins/cursor-pbr/templates/codebase/STRUCTURE.md.tmpl +0 -80
  956. package/plugins/cursor-pbr/templates/codebase/TESTING.md.tmpl +0 -107
  957. package/plugins/cursor-pbr/templates/continue-here.md.tmpl +0 -74
  958. package/plugins/cursor-pbr/templates/prompt-partials/phase-project-context.md.tmpl +0 -38
  959. package/plugins/cursor-pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
  960. package/plugins/cursor-pbr/templates/research/STACK.md.tmpl +0 -71
  961. package/plugins/cursor-pbr/templates/research/SUMMARY.md.tmpl +0 -112
  962. package/plugins/cursor-pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
  963. package/plugins/cursor-pbr/templates/research-outputs/project-research.md.tmpl +0 -99
  964. package/plugins/cursor-pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
  965. package/plugins/pbr/references/agent-interactions.md +0 -134
  966. package/plugins/pbr/references/pbr-rules.md +0 -194
  967. package/plugins/pbr/references/pbr-tools-cli.md +0 -285
  968. package/plugins/pbr/references/planning-config.md +0 -213
  969. package/plugins/pbr/references/subagent-coordination.md +0 -119
  970. package/plugins/pbr/references/ui-formatting.md +0 -444
  971. package/plugins/pbr/scripts/validate-plugin-structure.js +0 -183
  972. package/plugins/pbr/skills/milestone/templates/audit-report.md.tmpl +0 -48
  973. package/plugins/pbr/skills/shared/error-recovery-strategies.md +0 -51
  974. package/plugins/pbr/skills/shared/progress-display.md +0 -53
  975. package/plugins/pbr/skills/shared/state-loading.md +0 -62
  976. package/plugins/pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -97
  977. package/plugins/pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
  978. package/plugins/pbr/templates/research/STACK.md.tmpl +0 -71
  979. package/plugins/pbr/templates/research/SUMMARY.md.tmpl +0 -112
  980. package/plugins/pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
  981. package/plugins/pbr/templates/research-outputs/project-research.md.tmpl +0 -99
  982. package/plugins/pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
  983. /package/plugins/pbr/references/{agent-anti-patterns.md → archive/agent-anti-patterns.md} +0 -0
@@ -0,0 +1,1561 @@
1
+ /**
2
+ * Verify — Verification suite, consistency, and health validation
3
+ */
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const { safeReadFile, normalizePhaseName, execGit, findPhaseInternal, getMilestoneInfo, output, error } = require('./core');
8
+ const { extractFrontmatter, parseMustHavesBlock } = require('./frontmatter');
9
+ const { logHook } = require('../hook-logger');
10
+ // writeStateMd was never exported from state.cjs — use fs.writeFileSync directly
11
+
12
+ function cmdVerifySummary(cwd, summaryPath, checkFileCount, raw) {
13
+ if (!summaryPath) {
14
+ error('summary-path required');
15
+ }
16
+
17
+ const fullPath = path.join(cwd, summaryPath);
18
+ const checkCount = checkFileCount || 2;
19
+
20
+ // Check 1: Summary exists
21
+ if (!fs.existsSync(fullPath)) {
22
+ const result = {
23
+ passed: false,
24
+ checks: {
25
+ summary_exists: false,
26
+ files_created: { checked: 0, found: 0, missing: [] },
27
+ commits_exist: false,
28
+ self_check: 'not_found',
29
+ },
30
+ errors: ['SUMMARY.md not found'],
31
+ };
32
+ output(result, raw, 'failed');
33
+ return;
34
+ }
35
+
36
+ const content = fs.readFileSync(fullPath, 'utf-8');
37
+ const errors = [];
38
+
39
+ // Check 2: Spot-check files mentioned in summary
40
+ const mentionedFiles = new Set();
41
+ const patterns = [
42
+ /`([^`]+\.[a-zA-Z]+)`/g,
43
+ /(?:Created|Modified|Added|Updated|Edited):\s*`?([^\s`]+\.[a-zA-Z]+)`?/gi,
44
+ ];
45
+
46
+ for (const pattern of patterns) {
47
+ let m;
48
+ while ((m = pattern.exec(content)) !== null) {
49
+ const filePath = m[1];
50
+ if (filePath && !filePath.startsWith('http') && filePath.includes('/')) {
51
+ mentionedFiles.add(filePath);
52
+ }
53
+ }
54
+ }
55
+
56
+ const filesToCheck = Array.from(mentionedFiles).slice(0, checkCount);
57
+ const missing = [];
58
+ for (const file of filesToCheck) {
59
+ if (!fs.existsSync(path.join(cwd, file))) {
60
+ missing.push(file);
61
+ }
62
+ }
63
+
64
+ // Check 3: Commits exist
65
+ const commitHashPattern = /\b[0-9a-f]{7,40}\b/g;
66
+ const hashes = content.match(commitHashPattern) || [];
67
+ let commitsExist = false;
68
+ if (hashes.length > 0) {
69
+ for (const hash of hashes.slice(0, 3)) {
70
+ const result = execGit(cwd, ['cat-file', '-t', hash]);
71
+ if (result.exitCode === 0 && result.stdout === 'commit') {
72
+ commitsExist = true;
73
+ break;
74
+ }
75
+ }
76
+ }
77
+
78
+ // Check 4: Self-check section
79
+ let selfCheck = 'not_found';
80
+ const selfCheckPattern = /##\s*(?:Self[- ]?Check|Verification|Quality Check)/i;
81
+ if (selfCheckPattern.test(content)) {
82
+ const passPattern = /(?:all\s+)?(?:pass|✓|✅|complete|succeeded)/i;
83
+ const failPattern = /(?:fail|✗|❌|incomplete|blocked)/i;
84
+ const checkSection = content.slice(content.search(selfCheckPattern));
85
+ if (failPattern.test(checkSection)) {
86
+ selfCheck = 'failed';
87
+ } else if (passPattern.test(checkSection)) {
88
+ selfCheck = 'passed';
89
+ }
90
+ }
91
+
92
+ if (missing.length > 0) errors.push('Missing files: ' + missing.join(', '));
93
+ if (!commitsExist && hashes.length > 0) errors.push('Referenced commit hashes not found in git history');
94
+ if (selfCheck === 'failed') errors.push('Self-check section indicates failure');
95
+
96
+ const checks = {
97
+ summary_exists: true,
98
+ files_created: { checked: filesToCheck.length, found: filesToCheck.length - missing.length, missing },
99
+ commits_exist: commitsExist,
100
+ self_check: selfCheck,
101
+ };
102
+
103
+ const passed = missing.length === 0 && selfCheck !== 'failed';
104
+ const result = { passed, checks, errors };
105
+ output(result, raw, passed ? 'passed' : 'failed');
106
+ }
107
+
108
+ function cmdVerifyPlanStructure(cwd, filePath, raw) {
109
+ if (!filePath) { error('file path required'); }
110
+ const fullPath = path.isAbsolute(filePath) ? filePath : path.join(cwd, filePath);
111
+ const content = safeReadFile(fullPath);
112
+ if (!content) { output({ error: 'File not found', path: filePath }, raw); return; }
113
+
114
+ const fm = extractFrontmatter(content);
115
+ const errors = [];
116
+ const warnings = [];
117
+
118
+ // Check required frontmatter fields
119
+ const required = ['phase', 'plan', 'type', 'wave', 'depends_on', 'files_modified', 'autonomous', 'must_haves'];
120
+ for (const field of required) {
121
+ if (fm[field] === undefined) errors.push(`Missing required frontmatter field: ${field}`);
122
+ }
123
+
124
+ // Parse and check task elements
125
+ const taskPattern = /<task[^>]*>([\s\S]*?)<\/task>/g;
126
+ const tasks = [];
127
+ let taskMatch;
128
+ while ((taskMatch = taskPattern.exec(content)) !== null) {
129
+ const taskContent = taskMatch[1];
130
+ const nameMatch = taskContent.match(/<name>([\s\S]*?)<\/name>/);
131
+ const taskName = nameMatch ? nameMatch[1].trim() : 'unnamed';
132
+ const hasReadFirst = /<read_first>/.test(taskContent);
133
+ const hasFiles = /<files>/.test(taskContent);
134
+ const hasAction = /<action>/.test(taskContent);
135
+ const hasAcceptanceCriteria = /<acceptance_criteria>/.test(taskContent);
136
+ const hasVerify = /<verify>/.test(taskContent);
137
+ const hasDone = /<done>/.test(taskContent);
138
+
139
+ if (!nameMatch) errors.push('Task missing <name> element');
140
+ if (!hasAction) errors.push(`Task '${taskName}' missing <action>`);
141
+ if (!hasVerify) errors.push(`Task '${taskName}' missing <verify>`);
142
+ if (!hasDone) errors.push(`Task '${taskName}' missing <done>`);
143
+ if (!hasFiles) warnings.push(`Task '${taskName}' missing <files>`);
144
+ if (!hasReadFirst) warnings.push(`Task '${taskName}' missing <read_first>`);
145
+ if (!hasAcceptanceCriteria) warnings.push(`Task '${taskName}' missing <acceptance_criteria>`);
146
+
147
+ tasks.push({ name: taskName, hasReadFirst, hasFiles, hasAction, hasAcceptanceCriteria, hasVerify, hasDone });
148
+ }
149
+
150
+ if (tasks.length === 0) warnings.push('No <task> elements found');
151
+
152
+ // Wave/depends_on consistency
153
+ if (fm.wave && parseInt(fm.wave) > 1 && (!fm.depends_on || (Array.isArray(fm.depends_on) && fm.depends_on.length === 0))) {
154
+ warnings.push('Wave > 1 but depends_on is empty');
155
+ }
156
+
157
+ // Autonomous/checkpoint consistency
158
+ const hasCheckpoints = /<task\s+type=["']?checkpoint/.test(content);
159
+ if (hasCheckpoints && fm.autonomous !== 'false' && fm.autonomous !== false) {
160
+ errors.push('Has checkpoint tasks but autonomous is not false');
161
+ }
162
+
163
+ output({
164
+ valid: errors.length === 0,
165
+ errors,
166
+ warnings,
167
+ task_count: tasks.length,
168
+ tasks,
169
+ frontmatter_fields: Object.keys(fm),
170
+ }, raw, errors.length === 0 ? 'valid' : 'invalid');
171
+ }
172
+
173
+ function cmdVerifyPhaseCompleteness(cwd, phase, raw) {
174
+ if (!phase) { error('phase required'); }
175
+ const phaseInfo = findPhaseInternal(cwd, phase);
176
+ if (!phaseInfo || !phaseInfo.found) {
177
+ output({ error: 'Phase not found', phase }, raw);
178
+ return;
179
+ }
180
+
181
+ const errors = [];
182
+ const warnings = [];
183
+ const phaseDir = path.join(cwd, phaseInfo.directory);
184
+
185
+ // List plans and summaries
186
+ let files;
187
+ try { files = fs.readdirSync(phaseDir); } catch (err) { logHook('verify', 'debug', 'Cannot read phase directory', { dir: phaseDir, error: err.message }); output({ error: 'Cannot read phase directory' }, raw); return; }
188
+
189
+ const plans = files.filter(f => f.match(/-PLAN\.md$/i));
190
+ const summaries = files.filter(f => f.match(/-SUMMARY\.md$/i));
191
+
192
+ // Extract plan IDs (everything before -PLAN.md)
193
+ const planIds = new Set(plans.map(p => p.replace(/-PLAN\.md$/i, '')));
194
+ const summaryIds = new Set(summaries.map(s => s.replace(/-SUMMARY\.md$/i, '')));
195
+
196
+ // Plans without summaries
197
+ const incompletePlans = [...planIds].filter(id => !summaryIds.has(id));
198
+ if (incompletePlans.length > 0) {
199
+ errors.push(`Plans without summaries: ${incompletePlans.join(', ')}`);
200
+ }
201
+
202
+ // Summaries without plans (orphans)
203
+ const orphanSummaries = [...summaryIds].filter(id => !planIds.has(id));
204
+ if (orphanSummaries.length > 0) {
205
+ warnings.push(`Summaries without plans: ${orphanSummaries.join(', ')}`);
206
+ }
207
+
208
+ output({
209
+ complete: errors.length === 0,
210
+ phase: phaseInfo.phase_number,
211
+ plan_count: plans.length,
212
+ summary_count: summaries.length,
213
+ incomplete_plans: incompletePlans,
214
+ orphan_summaries: orphanSummaries,
215
+ errors,
216
+ warnings,
217
+ }, raw, errors.length === 0 ? 'complete' : 'incomplete');
218
+ }
219
+
220
+ function cmdVerifyReferences(cwd, filePath, raw) {
221
+ if (!filePath) { error('file path required'); }
222
+ const fullPath = path.isAbsolute(filePath) ? filePath : path.join(cwd, filePath);
223
+ const content = safeReadFile(fullPath);
224
+ if (!content) { output({ error: 'File not found', path: filePath }, raw); return; }
225
+
226
+ const found = [];
227
+ const missing = [];
228
+
229
+ // Find @-references: @path/to/file (must contain / to be a file path)
230
+ const atRefs = content.match(/@([^\s\n,)]+\/[^\s\n,)]+)/g) || [];
231
+ for (const ref of atRefs) {
232
+ const cleanRef = ref.slice(1); // remove @
233
+ const resolved = cleanRef.startsWith('~/')
234
+ ? path.join(process.env.HOME || '', cleanRef.slice(2))
235
+ : path.join(cwd, cleanRef);
236
+ if (fs.existsSync(resolved)) {
237
+ found.push(cleanRef);
238
+ } else {
239
+ missing.push(cleanRef);
240
+ }
241
+ }
242
+
243
+ // Find backtick file paths that look like real paths (contain / and have extension)
244
+ const backtickRefs = content.match(/`([^`]+\/[^`]+\.[a-zA-Z]{1,10})`/g) || [];
245
+ for (const ref of backtickRefs) {
246
+ const cleanRef = ref.slice(1, -1); // remove backticks
247
+ if (cleanRef.startsWith('http') || cleanRef.includes('${') || cleanRef.includes('{{')) continue;
248
+ if (found.includes(cleanRef) || missing.includes(cleanRef)) continue; // dedup
249
+ const resolved = path.join(cwd, cleanRef);
250
+ if (fs.existsSync(resolved)) {
251
+ found.push(cleanRef);
252
+ } else {
253
+ missing.push(cleanRef);
254
+ }
255
+ }
256
+
257
+ output({
258
+ valid: missing.length === 0,
259
+ found: found.length,
260
+ missing,
261
+ total: found.length + missing.length,
262
+ }, raw, missing.length === 0 ? 'valid' : 'invalid');
263
+ }
264
+
265
+ function cmdVerifyCommits(cwd, hashes, raw) {
266
+ if (!hashes || hashes.length === 0) { error('At least one commit hash required'); }
267
+
268
+ const valid = [];
269
+ const invalid = [];
270
+ for (const hash of hashes) {
271
+ const result = execGit(cwd, ['cat-file', '-t', hash]);
272
+ if (result.exitCode === 0 && result.stdout.trim() === 'commit') {
273
+ valid.push(hash);
274
+ } else {
275
+ invalid.push(hash);
276
+ }
277
+ }
278
+
279
+ output({
280
+ all_valid: invalid.length === 0,
281
+ valid,
282
+ invalid,
283
+ total: hashes.length,
284
+ }, raw, invalid.length === 0 ? 'valid' : 'invalid');
285
+ }
286
+
287
+ /**
288
+ * Parse a string-format artifact into { path, min_lines } or null if descriptive text.
289
+ * Handles: "path/to/file.ext: >N lines", "path/to/file.ext", "descriptive text"
290
+ */
291
+ function parseStringArtifact(str) {
292
+ const pathLineMatch = str.match(/^([^\s:]+\.\w+)(?::\s*>(\d+)\s*lines?)?/);
293
+ if (pathLineMatch) {
294
+ return { path: pathLineMatch[1], min_lines: pathLineMatch[2] ? parseInt(pathLineMatch[2]) : null };
295
+ }
296
+ return null; // Descriptive text, skip
297
+ }
298
+
299
+ function cmdVerifyArtifacts(cwd, planFilePath, raw) {
300
+ if (!planFilePath) { error('plan file path required'); }
301
+ const fullPath = path.isAbsolute(planFilePath) ? planFilePath : path.join(cwd, planFilePath);
302
+ const content = safeReadFile(fullPath);
303
+ if (!content) { output({ error: 'File not found', path: planFilePath }, raw); return; }
304
+
305
+ const artifacts = parseMustHavesBlock(content, 'artifacts');
306
+ if (artifacts.length === 0) {
307
+ output({ error: 'No must_haves.artifacts found in frontmatter', path: planFilePath }, raw);
308
+ return;
309
+ }
310
+
311
+ const results = [];
312
+ for (const artifact of artifacts) {
313
+ let artObj = artifact;
314
+ if (typeof artifact === 'string') {
315
+ artObj = parseStringArtifact(artifact);
316
+ if (!artObj) continue; // genuinely descriptive, skip
317
+ }
318
+ const artPath = artObj.path;
319
+ if (!artPath) continue;
320
+
321
+ const artFullPath = path.join(cwd, artPath);
322
+ const exists = fs.existsSync(artFullPath);
323
+ const check = { path: artPath, exists, issues: [], passed: false };
324
+
325
+ if (exists) {
326
+ const fileContent = safeReadFile(artFullPath) || '';
327
+ const lineCount = fileContent.split('\n').length;
328
+
329
+ if (artObj.min_lines && lineCount < artObj.min_lines) {
330
+ check.issues.push(`Only ${lineCount} lines, need ${artObj.min_lines}`);
331
+ }
332
+ if (artObj.contains && !fileContent.includes(artObj.contains)) {
333
+ check.issues.push(`Missing pattern: ${artObj.contains}`);
334
+ }
335
+ if (artObj.exports) {
336
+ const exports = Array.isArray(artObj.exports) ? artObj.exports : [artObj.exports];
337
+ for (const exp of exports) {
338
+ if (!fileContent.includes(exp)) check.issues.push(`Missing export: ${exp}`);
339
+ }
340
+ }
341
+ check.passed = check.issues.length === 0;
342
+ } else {
343
+ check.issues.push('File not found');
344
+ }
345
+
346
+ results.push(check);
347
+ }
348
+
349
+ const passed = results.filter(r => r.passed).length;
350
+ output({
351
+ all_passed: passed === results.length,
352
+ passed,
353
+ total: results.length,
354
+ artifacts: results,
355
+ }, raw, passed === results.length ? 'valid' : 'invalid');
356
+ }
357
+
358
+ function cmdVerifyKeyLinks(cwd, planFilePath, raw) {
359
+ if (!planFilePath) { error('plan file path required'); }
360
+ const fullPath = path.isAbsolute(planFilePath) ? planFilePath : path.join(cwd, planFilePath);
361
+ const content = safeReadFile(fullPath);
362
+ if (!content) { output({ error: 'File not found', path: planFilePath }, raw); return; }
363
+
364
+ const keyLinks = parseMustHavesBlock(content, 'key_links');
365
+ if (keyLinks.length === 0) {
366
+ output({ error: 'No must_haves.key_links found in frontmatter', path: planFilePath }, raw);
367
+ return;
368
+ }
369
+
370
+ const results = [];
371
+ for (const link of keyLinks) {
372
+ if (typeof link === 'string') {
373
+ // String-format key_link: attempt to extract file paths, otherwise treat as descriptive
374
+ const pathMatch = link.match(/([^\s]+\.\w+)/g);
375
+ if (pathMatch && pathMatch.length >= 1) {
376
+ // Try to verify the first file path mentioned exists
377
+ const firstPath = pathMatch[0];
378
+ const exists = fs.existsSync(path.join(cwd, firstPath));
379
+ results.push({
380
+ description: link,
381
+ verified: exists ? 'partial' : false,
382
+ detail: exists ? 'Referenced file exists — manual wiring check recommended' : `Referenced file not found: ${firstPath}`,
383
+ });
384
+ } else {
385
+ results.push({
386
+ description: link,
387
+ verified: 'manual',
388
+ detail: 'Descriptive key_link — requires manual verification',
389
+ });
390
+ }
391
+ continue;
392
+ }
393
+ const check = { from: link.from, to: link.to, via: link.via || '', verified: false, detail: '' };
394
+
395
+ const sourceContent = safeReadFile(path.join(cwd, link.from || ''));
396
+ if (!sourceContent) {
397
+ check.detail = 'Source file not found';
398
+ } else if (link.pattern) {
399
+ try {
400
+ const regex = new RegExp(link.pattern);
401
+ if (regex.test(sourceContent)) {
402
+ check.verified = true;
403
+ check.detail = 'Pattern found in source';
404
+ } else {
405
+ const targetContent = safeReadFile(path.join(cwd, link.to || ''));
406
+ if (targetContent && regex.test(targetContent)) {
407
+ check.verified = true;
408
+ check.detail = 'Pattern found in target';
409
+ } else {
410
+ check.detail = `Pattern "${link.pattern}" not found in source or target`;
411
+ }
412
+ }
413
+ } catch (err) {
414
+ logHook('verify', 'debug', 'Invalid regex pattern', { pattern: link.pattern, error: err.message });
415
+ check.detail = `Invalid regex pattern: ${link.pattern}`;
416
+ }
417
+ } else {
418
+ // No pattern: just check source references target
419
+ if (sourceContent.includes(link.to || '')) {
420
+ check.verified = true;
421
+ check.detail = 'Target referenced in source';
422
+ } else {
423
+ check.detail = 'Target not referenced in source';
424
+ }
425
+ }
426
+
427
+ results.push(check);
428
+ }
429
+
430
+ const verified = results.filter(r => r.verified).length;
431
+ output({
432
+ all_verified: verified === results.length,
433
+ verified,
434
+ total: results.length,
435
+ links: results,
436
+ }, raw, verified === results.length ? 'valid' : 'invalid');
437
+ }
438
+
439
+ function cmdValidateConsistency(cwd, raw) {
440
+ const roadmapPath = path.join(cwd, '.planning', 'ROADMAP.md');
441
+ const phasesDir = path.join(cwd, '.planning', 'phases');
442
+ const errors = [];
443
+ const warnings = [];
444
+
445
+ // Check for ROADMAP
446
+ if (!fs.existsSync(roadmapPath)) {
447
+ errors.push('ROADMAP.md not found');
448
+ output({ passed: false, errors, warnings }, raw, 'failed');
449
+ return;
450
+ }
451
+
452
+ const roadmapContent = fs.readFileSync(roadmapPath, 'utf-8');
453
+
454
+ // Extract phases from ROADMAP
455
+ const roadmapPhases = new Set();
456
+ const phasePattern = /#{2,4}\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:/gi;
457
+ let m;
458
+ while ((m = phasePattern.exec(roadmapContent)) !== null) {
459
+ roadmapPhases.add(m[1]);
460
+ }
461
+
462
+ // Get phases on disk
463
+ const diskPhases = new Set();
464
+ try {
465
+ const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
466
+ const dirs = entries.filter(e => e.isDirectory()).map(e => e.name);
467
+ for (const dir of dirs) {
468
+ const dm = dir.match(/^(\d+[A-Z]?(?:\.\d+)*)/i);
469
+ if (dm) diskPhases.add(dm[1]);
470
+ }
471
+ } catch (err) { logHook('verify', 'debug', 'Failed to read phases directory', { error: err.message }); }
472
+
473
+ // Check: phases in ROADMAP but not on disk
474
+ for (const p of roadmapPhases) {
475
+ if (!diskPhases.has(p) && !diskPhases.has(normalizePhaseName(p))) {
476
+ warnings.push(`Phase ${p} in ROADMAP.md but no directory on disk`);
477
+ }
478
+ }
479
+
480
+ // Check: phases on disk but not in ROADMAP
481
+ for (const p of diskPhases) {
482
+ const unpadded = String(parseInt(p, 10));
483
+ if (!roadmapPhases.has(p) && !roadmapPhases.has(unpadded)) {
484
+ warnings.push(`Phase ${p} exists on disk but not in ROADMAP.md`);
485
+ }
486
+ }
487
+
488
+ // Check: sequential phase numbers (integers only)
489
+ const integerPhases = [...diskPhases]
490
+ .filter(p => !p.includes('.'))
491
+ .map(p => parseInt(p, 10))
492
+ .sort((a, b) => a - b);
493
+
494
+ for (let i = 1; i < integerPhases.length; i++) {
495
+ if (integerPhases[i] !== integerPhases[i - 1] + 1) {
496
+ warnings.push(`Gap in phase numbering: ${integerPhases[i - 1]} → ${integerPhases[i]}`);
497
+ }
498
+ }
499
+
500
+ // Check: plan numbering within phases
501
+ try {
502
+ const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
503
+ const dirs = entries.filter(e => e.isDirectory()).map(e => e.name).sort();
504
+
505
+ for (const dir of dirs) {
506
+ const phaseFiles = fs.readdirSync(path.join(phasesDir, dir));
507
+ const plans = phaseFiles.filter(f => f.endsWith('-PLAN.md')).sort();
508
+
509
+ // Extract plan numbers
510
+ const planNums = plans.map(p => {
511
+ const pm = p.match(/-(\d{2})-PLAN\.md$/);
512
+ return pm ? parseInt(pm[1], 10) : null;
513
+ }).filter(n => n !== null);
514
+
515
+ for (let i = 1; i < planNums.length; i++) {
516
+ if (planNums[i] !== planNums[i - 1] + 1) {
517
+ warnings.push(`Gap in plan numbering in ${dir}: plan ${planNums[i - 1]} → ${planNums[i]}`);
518
+ }
519
+ }
520
+
521
+ // Check: plans without summaries (completed plans)
522
+ const summaries = phaseFiles.filter(f => f.endsWith('-SUMMARY.md'));
523
+ const planIds = new Set(plans.map(p => p.replace('-PLAN.md', '')));
524
+ const summaryIds = new Set(summaries.map(s => s.replace('-SUMMARY.md', '')));
525
+
526
+ // Summary without matching plan is suspicious
527
+ for (const sid of summaryIds) {
528
+ if (!planIds.has(sid)) {
529
+ warnings.push(`Summary ${sid}-SUMMARY.md in ${dir} has no matching PLAN.md`);
530
+ }
531
+ }
532
+ }
533
+ } catch (err) { logHook('verify', 'debug', 'Failed to check plan numbering', { error: err.message }); }
534
+
535
+ // Check: frontmatter in plans has required fields
536
+ try {
537
+ const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
538
+ const dirs = entries.filter(e => e.isDirectory()).map(e => e.name);
539
+
540
+ for (const dir of dirs) {
541
+ const phaseFiles = fs.readdirSync(path.join(phasesDir, dir));
542
+ const plans = phaseFiles.filter(f => f.endsWith('-PLAN.md'));
543
+
544
+ for (const plan of plans) {
545
+ const content = fs.readFileSync(path.join(phasesDir, dir, plan), 'utf-8');
546
+ const fm = extractFrontmatter(content);
547
+
548
+ if (!fm.wave) {
549
+ warnings.push(`${dir}/${plan}: missing 'wave' in frontmatter`);
550
+ }
551
+ }
552
+ }
553
+ } catch (err) { logHook('verify', 'debug', 'Failed to check plan frontmatter', { error: err.message }); }
554
+
555
+ const passed = errors.length === 0;
556
+ output({ passed, errors, warnings, warning_count: warnings.length }, raw, passed ? 'passed' : 'failed');
557
+ }
558
+
559
+ /**
560
+ * Check Phase 05 features: decision_journal, negative_knowledge, living_requirements.
561
+ * @param {string} planningDir - Path to .planning directory
562
+ * @param {object} config - Parsed config.json
563
+ * @returns {object} Per-feature status object
564
+ */
565
+ function checkPhase05Features(planningDir, config) {
566
+ const features = config.features || {};
567
+ const result = {};
568
+
569
+ // decision_journal
570
+ if (features.decision_journal === false) {
571
+ result.decision_journal = { enabled: false, status: 'disabled' };
572
+ } else if (features.decision_journal) {
573
+ const decisionsDir = path.join(planningDir, 'decisions');
574
+ if (fs.existsSync(decisionsDir)) {
575
+ result.decision_journal = { enabled: true, status: 'healthy' };
576
+ } else {
577
+ result.decision_journal = { enabled: true, status: 'degraded', reason: 'decisions directory not found' };
578
+ }
579
+ }
580
+
581
+ // negative_knowledge
582
+ if (features.negative_knowledge === false) {
583
+ result.negative_knowledge = { enabled: false, status: 'disabled' };
584
+ } else if (features.negative_knowledge) {
585
+ const nkDir = path.join(planningDir, 'negative-knowledge');
586
+ if (fs.existsSync(nkDir)) {
587
+ result.negative_knowledge = { enabled: true, status: 'healthy' };
588
+ } else {
589
+ result.negative_knowledge = { enabled: true, status: 'degraded', reason: 'negative-knowledge directory not found' };
590
+ }
591
+ }
592
+
593
+ // living_requirements
594
+ if (features.living_requirements === false) {
595
+ result.living_requirements = { enabled: false, status: 'disabled' };
596
+ } else if (features.living_requirements) {
597
+ const reqPath = path.join(planningDir, 'REQUIREMENTS.md');
598
+ if (fs.existsSync(reqPath)) {
599
+ const content = fs.readFileSync(reqPath, 'utf-8');
600
+ if (/REQ-/.test(content)) {
601
+ result.living_requirements = { enabled: true, status: 'healthy' };
602
+ } else {
603
+ result.living_requirements = { enabled: true, status: 'degraded', reason: 'REQUIREMENTS.md not found or has no REQ-IDs' };
604
+ }
605
+ } else {
606
+ result.living_requirements = { enabled: true, status: 'degraded', reason: 'REQUIREMENTS.md not found or has no REQ-IDs' };
607
+ }
608
+ }
609
+
610
+ return Object.keys(result).length > 0 ? result : null;
611
+ }
612
+
613
+ function cmdValidateHealth(cwd, options, raw) {
614
+ const planningDir = path.join(cwd, '.planning');
615
+ const projectPath = path.join(planningDir, 'PROJECT.md');
616
+ const roadmapPath = path.join(planningDir, 'ROADMAP.md');
617
+ const statePath = path.join(planningDir, 'STATE.md');
618
+ const configPath = path.join(planningDir, 'config.json');
619
+ const phasesDir = path.join(planningDir, 'phases');
620
+
621
+ const errors = [];
622
+ const warnings = [];
623
+ const info = [];
624
+ const repairs = [];
625
+
626
+ // Helper to add issue
627
+ const addIssue = (severity, code, message, fix, repairable = false) => {
628
+ const issue = { code, message, fix, repairable };
629
+ if (severity === 'error') errors.push(issue);
630
+ else if (severity === 'warning') warnings.push(issue);
631
+ else info.push(issue);
632
+ };
633
+
634
+ // ─── Check 1: .planning/ exists ───────────────────────────────────────────
635
+ if (!fs.existsSync(planningDir)) {
636
+ addIssue('error', 'E001', '.planning/ directory not found', 'Run /pbr:new-project to initialize');
637
+ output({
638
+ status: 'broken',
639
+ errors,
640
+ warnings,
641
+ info,
642
+ repairable_count: 0,
643
+ }, raw);
644
+ return;
645
+ }
646
+
647
+ // ─── Check 2: PROJECT.md exists and has required sections ─────────────────
648
+ if (!fs.existsSync(projectPath)) {
649
+ addIssue('error', 'E002', 'PROJECT.md not found', 'Run /pbr:new-project to create');
650
+ } else {
651
+ const content = fs.readFileSync(projectPath, 'utf-8');
652
+ const requiredSections = ['## What This Is', '## Core Value', '## Requirements'];
653
+ for (const section of requiredSections) {
654
+ if (!content.includes(section)) {
655
+ addIssue('warning', 'W001', `PROJECT.md missing section: ${section}`, 'Add section manually');
656
+ }
657
+ }
658
+ }
659
+
660
+ // ─── Check 3: ROADMAP.md exists ───────────────────────────────────────────
661
+ if (!fs.existsSync(roadmapPath)) {
662
+ addIssue('error', 'E003', 'ROADMAP.md not found', 'Run /pbr:new-milestone to create roadmap');
663
+ }
664
+
665
+ // ─── Check 4: STATE.md exists and references valid phases ─────────────────
666
+ if (!fs.existsSync(statePath)) {
667
+ addIssue('error', 'E004', 'STATE.md not found', 'Run /pbr:health --repair to regenerate', true);
668
+ repairs.push('regenerateState');
669
+ } else {
670
+ const stateContent = fs.readFileSync(statePath, 'utf-8');
671
+ // Extract phase references from STATE.md
672
+ const phaseRefs = [...stateContent.matchAll(/[Pp]hase\s+(\d+(?:\.\d+)*)/g)].map(m => m[1]);
673
+ // Get disk phases
674
+ const diskPhases = new Set();
675
+ try {
676
+ const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
677
+ for (const e of entries) {
678
+ if (e.isDirectory()) {
679
+ const m = e.name.match(/^(\d+(?:\.\d+)*)/);
680
+ if (m) diskPhases.add(m[1]);
681
+ }
682
+ }
683
+ } catch (err) { logHook('verify', 'debug', 'Failed to read phases for state validation', { error: err.message }); }
684
+ // Check for invalid references
685
+ for (const ref of phaseRefs) {
686
+ const normalizedRef = String(parseInt(ref, 10)).padStart(2, '0');
687
+ if (!diskPhases.has(ref) && !diskPhases.has(normalizedRef) && !diskPhases.has(String(parseInt(ref, 10)))) {
688
+ // Only warn if phases dir has any content (not just an empty project)
689
+ if (diskPhases.size > 0) {
690
+ addIssue('warning', 'W002', `STATE.md references phase ${ref}, but only phases ${[...diskPhases].sort().join(', ')} exist`, 'Run /pbr:health --repair to regenerate STATE.md', true);
691
+ if (!repairs.includes('regenerateState')) repairs.push('regenerateState');
692
+ }
693
+ }
694
+ }
695
+ }
696
+
697
+ // ─── Check 5: config.json valid JSON + valid schema ───────────────────────
698
+ if (!fs.existsSync(configPath)) {
699
+ addIssue('warning', 'W003', 'config.json not found', 'Run /pbr:health --repair to create with defaults', true);
700
+ repairs.push('createConfig');
701
+ } else {
702
+ try {
703
+ const raw = fs.readFileSync(configPath, 'utf-8');
704
+ const parsed = JSON.parse(raw);
705
+ // Validate known fields
706
+ const validProfiles = ['quality', 'balanced', 'budget'];
707
+ if (parsed.model_profile && !validProfiles.includes(parsed.model_profile)) {
708
+ addIssue('warning', 'W004', `config.json: invalid model_profile "${parsed.model_profile}"`, `Valid values: ${validProfiles.join(', ')}`);
709
+ }
710
+ } catch (err) {
711
+ addIssue('error', 'E005', `config.json: JSON parse error - ${err.message}`, 'Run /pbr:health --repair to reset to defaults', true);
712
+ repairs.push('resetConfig');
713
+ }
714
+ }
715
+
716
+ // ─── Check 5b: Nyquist validation key presence ──────────────────────────
717
+ if (fs.existsSync(configPath)) {
718
+ try {
719
+ const configRaw = fs.readFileSync(configPath, 'utf-8');
720
+ const configParsed = JSON.parse(configRaw);
721
+ if (configParsed.workflow && configParsed.workflow.nyquist_validation === undefined) {
722
+ addIssue('warning', 'W008', 'config.json: workflow.nyquist_validation absent (defaults to enabled but agents may skip)', 'Run /pbr:health --repair to add key', true);
723
+ if (!repairs.includes('addNyquistKey')) repairs.push('addNyquistKey');
724
+ }
725
+ } catch (err) { logHook('verify', 'debug', 'Failed to check nyquist key', { error: err.message }); }
726
+ }
727
+
728
+ // ─── Check 6: Phase directory naming (NN-name format) ─────────────────────
729
+ try {
730
+ const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
731
+ for (const e of entries) {
732
+ if (e.isDirectory() && !e.name.match(/^\d{2}(?:\.\d+)*-[\w-]+$/)) {
733
+ addIssue('warning', 'W005', `Phase directory "${e.name}" doesn't follow NN-name format`, 'Rename to match pattern (e.g., 01-setup)');
734
+ }
735
+ }
736
+ } catch (err) { logHook('verify', 'debug', 'Failed to check phase directory naming', { error: err.message }); }
737
+
738
+ // ─── Check 7: Orphaned plans (PLAN without SUMMARY) ───────────────────────
739
+ try {
740
+ const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
741
+ for (const e of entries) {
742
+ if (!e.isDirectory()) continue;
743
+ const phaseFiles = fs.readdirSync(path.join(phasesDir, e.name));
744
+ const plans = phaseFiles.filter(f => f.endsWith('-PLAN.md') || f === 'PLAN.md');
745
+ const summaries = phaseFiles.filter(f => f.endsWith('-SUMMARY.md') || f === 'SUMMARY.md');
746
+ const summaryBases = new Set(summaries.map(s => s.replace('-SUMMARY.md', '').replace('SUMMARY.md', '')));
747
+
748
+ for (const plan of plans) {
749
+ const planBase = plan.replace('-PLAN.md', '').replace('PLAN.md', '');
750
+ if (!summaryBases.has(planBase)) {
751
+ addIssue('info', 'I001', `${e.name}/${plan} has no SUMMARY.md`, 'May be in progress');
752
+ }
753
+ }
754
+ }
755
+ } catch (err) { logHook('verify', 'debug', 'Failed to check orphaned plans', { error: err.message }); }
756
+
757
+ // ─── Check 7b: Nyquist VALIDATION.md consistency ────────────────────────
758
+ try {
759
+ const phaseEntries = fs.readdirSync(phasesDir, { withFileTypes: true });
760
+ for (const e of phaseEntries) {
761
+ if (!e.isDirectory()) continue;
762
+ const phaseFiles = fs.readdirSync(path.join(phasesDir, e.name));
763
+ const hasResearch = phaseFiles.some(f => f.endsWith('-RESEARCH.md'));
764
+ const hasValidation = phaseFiles.some(f => f.endsWith('-VALIDATION.md'));
765
+ if (hasResearch && !hasValidation) {
766
+ const researchFile = phaseFiles.find(f => f.endsWith('-RESEARCH.md'));
767
+ const researchContent = fs.readFileSync(path.join(phasesDir, e.name, researchFile), 'utf-8');
768
+ if (researchContent.includes('## Validation Architecture')) {
769
+ addIssue('warning', 'W009', `Phase ${e.name}: has Validation Architecture in RESEARCH.md but no VALIDATION.md`, 'Re-run /pbr:plan-phase with --research to regenerate');
770
+ }
771
+ }
772
+ }
773
+ } catch (err) { logHook('verify', 'debug', 'Failed to check nyquist validation', { error: err.message }); }
774
+
775
+ // ─── Check 8: Run existing consistency checks ─────────────────────────────
776
+ // Inline subset of cmdValidateConsistency
777
+ if (fs.existsSync(roadmapPath)) {
778
+ const roadmapContent = fs.readFileSync(roadmapPath, 'utf-8');
779
+ const roadmapPhases = new Set();
780
+ const phasePattern = /#{2,4}\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:/gi;
781
+ let m;
782
+ while ((m = phasePattern.exec(roadmapContent)) !== null) {
783
+ roadmapPhases.add(m[1]);
784
+ }
785
+
786
+ const diskPhases = new Set();
787
+ try {
788
+ const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
789
+ for (const e of entries) {
790
+ if (e.isDirectory()) {
791
+ const dm = e.name.match(/^(\d+[A-Z]?(?:\.\d+)*)/i);
792
+ if (dm) diskPhases.add(dm[1]);
793
+ }
794
+ }
795
+ } catch (err) { logHook('verify', 'debug', 'Failed to read phases for roadmap check', { error: err.message }); }
796
+
797
+ // Phases in ROADMAP but not on disk
798
+ for (const p of roadmapPhases) {
799
+ const padded = String(parseInt(p, 10)).padStart(2, '0');
800
+ if (!diskPhases.has(p) && !diskPhases.has(padded)) {
801
+ addIssue('warning', 'W006', `Phase ${p} in ROADMAP.md but no directory on disk`, 'Create phase directory or remove from roadmap');
802
+ }
803
+ }
804
+
805
+ // Phases on disk but not in ROADMAP
806
+ for (const p of diskPhases) {
807
+ const unpadded = String(parseInt(p, 10));
808
+ if (!roadmapPhases.has(p) && !roadmapPhases.has(unpadded)) {
809
+ addIssue('warning', 'W007', `Phase ${p} exists on disk but not in ROADMAP.md`, 'Add to roadmap or remove directory');
810
+ }
811
+ }
812
+ }
813
+
814
+ // ─── Check 9: Phase 1 feature status ────────────────────────────────────────
815
+ const feature_status = {};
816
+ if (fs.existsSync(configPath)) {
817
+ try {
818
+ const configRaw = fs.readFileSync(configPath, 'utf-8');
819
+ const configParsed = JSON.parse(configRaw);
820
+ const features = configParsed.features || {};
821
+ const workflow = configParsed.workflow || {};
822
+
823
+ // enhanced_session_start: default true (enabled unless explicitly false)
824
+ const essEnabled = features.enhanced_session_start !== false;
825
+ feature_status.enhanced_session_start = { enabled: essEnabled, status: essEnabled ? 'healthy' : 'disabled' };
826
+
827
+ // context_quality_scoring: default true (enabled unless explicitly false)
828
+ const cqsEnabled = features.context_quality_scoring !== false;
829
+ feature_status.context_quality_scoring = { enabled: cqsEnabled, status: cqsEnabled ? 'healthy' : 'disabled' };
830
+
831
+ // skip_rag: default false (enabled only if explicitly true)
832
+ const srEnabled = features.skip_rag === true;
833
+ feature_status.skip_rag = { enabled: srEnabled, status: srEnabled ? 'healthy' : 'disabled' };
834
+
835
+ // ─── Phase 8 feature checks ──────────────────────────────────────────
836
+
837
+ // graduated_verification: default true; degraded if enabled but no trust data
838
+ const gvEnabled = features.graduated_verification !== false;
839
+ if (!gvEnabled) {
840
+ feature_status.graduated_verification = { enabled: false, status: 'disabled' };
841
+ } else {
842
+ const trustScoresPath = path.join(planningDir, 'trust', 'scores.json');
843
+ const hasTrustData = fs.existsSync(trustScoresPath);
844
+ feature_status.graduated_verification = {
845
+ enabled: true,
846
+ status: hasTrustData ? 'healthy' : 'degraded'
847
+ };
848
+ }
849
+
850
+ // self_verification: default true; healthy if enabled, disabled otherwise
851
+ const svEnabled = features.self_verification !== false;
852
+ feature_status.self_verification = {
853
+ enabled: svEnabled,
854
+ status: svEnabled ? 'healthy' : 'disabled'
855
+ };
856
+
857
+ // autonomy: check autonomy.level config property
858
+ const autonomyConfig = configParsed.autonomy || {};
859
+ const autonomyLevel = autonomyConfig.level || 'supervised';
860
+ const autonomyExplicit = !!(configParsed.autonomy && configParsed.autonomy.level);
861
+ feature_status.autonomy = {
862
+ enabled: true,
863
+ status: autonomyExplicit ? 'healthy' : 'degraded',
864
+ level: autonomyLevel
865
+ };
866
+
867
+ // Validate orchestrator_budget_pct range (15-50)
868
+ const budgetPct = configParsed.orchestrator_budget_pct;
869
+ if (budgetPct !== undefined) {
870
+ if (budgetPct < 15 || budgetPct > 50) {
871
+ addIssue('warning', 'W010', `orchestrator_budget_pct is ${budgetPct}, outside valid range 15-50`, 'Set to a value between 15 and 50 in config.json');
872
+ }
873
+ }
874
+
875
+ // ─── Check 10: Phase 2 feature status ──────────────────────────────────────
876
+ // inline_simple_tasks: default true, degraded if enabled but inline_max_files/inline_max_lines missing
877
+ const istEnabled = features.inline_simple_tasks !== false;
878
+ if (istEnabled) {
879
+ const hasMaxFiles = workflow.inline_max_files !== undefined &&
880
+ typeof workflow.inline_max_files === 'number' &&
881
+ workflow.inline_max_files >= 1 && workflow.inline_max_files <= 20;
882
+ const hasMaxLines = workflow.inline_max_lines !== undefined &&
883
+ typeof workflow.inline_max_lines === 'number' &&
884
+ workflow.inline_max_lines >= 10 && workflow.inline_max_lines <= 500;
885
+ if (!hasMaxFiles || !hasMaxLines) {
886
+ feature_status.inline_simple_tasks = { enabled: true, status: 'degraded' };
887
+ addIssue('warning', 'W012', 'inline_simple_tasks enabled but inline_max_files/inline_max_lines not configured or invalid', 'Add workflow.inline_max_files (1-20) and workflow.inline_max_lines (10-500) to config.json');
888
+ } else {
889
+ feature_status.inline_simple_tasks = { enabled: true, status: 'enabled' };
890
+ }
891
+ } else {
892
+ feature_status.inline_simple_tasks = { enabled: false, status: 'disabled' };
893
+ }
894
+
895
+ // rich_agent_prompts: default true, no extra validation needed
896
+ const rapEnabled = features.rich_agent_prompts !== false;
897
+ feature_status.rich_agent_prompts = { enabled: rapEnabled, status: rapEnabled ? 'enabled' : 'disabled' };
898
+
899
+ // multi_phase_awareness: default true, degraded if enabled but max_phases_in_context missing
900
+ const mpaEnabled = features.multi_phase_awareness !== false;
901
+ if (mpaEnabled) {
902
+ const hasMaxPhases = workflow.max_phases_in_context !== undefined &&
903
+ typeof workflow.max_phases_in_context === 'number' &&
904
+ workflow.max_phases_in_context >= 1 && workflow.max_phases_in_context <= 10;
905
+ if (!hasMaxPhases) {
906
+ feature_status.multi_phase_awareness = { enabled: true, status: 'degraded' };
907
+ addIssue('warning', 'W013', 'multi_phase_awareness enabled but max_phases_in_context not configured or invalid', 'Add workflow.max_phases_in_context (1-10) to config.json');
908
+ } else {
909
+ feature_status.multi_phase_awareness = { enabled: true, status: 'enabled' };
910
+ }
911
+ } else {
912
+ feature_status.multi_phase_awareness = { enabled: false, status: 'disabled' };
913
+ }
914
+ } catch (err) { logHook('verify', 'debug', 'Config parse error (handled in Check 5)', { error: err.message }); }
915
+ }
916
+
917
+ // ─── Check 11: Phase 05 feature status ────────────────────────────────────
918
+ {
919
+ let p05Config = {};
920
+ try { p05Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { logHook('verify', 'debug', 'Failed to parse config for phase05', { error: err.message }); }
921
+ var phase05_features = checkPhase05Features(planningDir, p05Config);
922
+ }
923
+
924
+ // ─── Check 12: Trust tracking health ──────────────────────────────────────
925
+ {
926
+ let config = {};
927
+ try { config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { logHook('verify', 'debug', 'Failed to parse config for trust', { error: err.message }); }
928
+
929
+ if (config.features && config.features.trust_tracking === false) {
930
+ addIssue('info', 'I-TRUST-DISABLED', 'trust_tracking is disabled in config', 'Enable features.trust_tracking in config.json if desired');
931
+ } else {
932
+ const trustFile = path.join(planningDir, 'trust', 'agent-scores.json');
933
+ if (!fs.existsSync(trustFile)) {
934
+ addIssue('info', 'I-TRUST-DEGRADED', 'trust_tracking: degraded — agent-scores.json missing. Will populate after first verification.', 'Run a build cycle to generate trust data');
935
+ } else {
936
+ try {
937
+ const scores = JSON.parse(fs.readFileSync(trustFile, 'utf-8'));
938
+ const agents = Object.keys(scores);
939
+ let totalOutcomes = 0;
940
+ for (const agent of agents) {
941
+ for (const cat of Object.values(scores[agent])) {
942
+ totalOutcomes += (cat.pass || 0) + (cat.fail || 0);
943
+ }
944
+ }
945
+ addIssue('info', 'I-TRUST-HEALTHY', `trust_tracking: healthy — ${agents.length} agents, ${totalOutcomes} outcomes tracked`, '');
946
+ } catch (err) {
947
+ logHook('verify', 'warn', 'Failed to parse agent-scores.json', { error: err.message });
948
+ addIssue('info', 'I-TRUST-DEGRADED', 'trust_tracking: degraded — agent-scores.json exists but is malformed', 'Delete .planning/trust/agent-scores.json to reset');
949
+ }
950
+ }
951
+ }
952
+
953
+ if (config.features && config.features.confidence_calibration === false) {
954
+ addIssue('info', 'I-CONFIDENCE-DISABLED', 'confidence_calibration is disabled in config', 'Enable features.confidence_calibration in config.json if desired');
955
+ } else {
956
+ const trustFile = path.join(planningDir, 'trust', 'agent-scores.json');
957
+ if (!fs.existsSync(trustFile)) {
958
+ addIssue('info', 'I-CONFIDENCE-DEGRADED', 'confidence_calibration: degraded — no trust data available', 'Run a build cycle to generate trust data');
959
+ } else {
960
+ try {
961
+ JSON.parse(fs.readFileSync(trustFile, 'utf-8'));
962
+ addIssue('info', 'I-CONFIDENCE-HEALTHY', 'confidence_calibration: healthy — trust data available for calibration', '');
963
+ } catch (err) {
964
+ logHook('verify', 'warn', 'Failed to parse trust data for confidence', { error: err.message });
965
+ addIssue('info', 'I-CONFIDENCE-DEGRADED', 'confidence_calibration: degraded — trust data malformed', 'Delete .planning/trust/agent-scores.json to reset');
966
+ }
967
+ }
968
+ }
969
+ }
970
+
971
+ // ─── Check 13: Architecture graph feature health ──────────────────────────
972
+ try {
973
+ const graph = require('./graph');
974
+ const graphHealth = graph.graphHealthCheck(planningDir);
975
+ const guardHealth = graph.guardHealthCheck(planningDir);
976
+ feature_status.architecture_graph = graphHealth;
977
+ feature_status.architecture_guard = guardHealth;
978
+ } catch (err) { logHook('verify', 'debug', 'Graph module not available', { error: err.message }); }
979
+
980
+ // ─── Check 14: Phase 15 DX feature health ────────────────────────────────
981
+ {
982
+ let p15Config = {};
983
+ try { p15Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { logHook('verify', 'debug', 'Failed to parse config for phase15', { error: err.message }); }
984
+ const p15Features = (p15Config && p15Config.features) || {};
985
+
986
+ const checkDxFeature = (featureName, modulePath, exportName) => {
987
+ const enabled = p15Features[featureName] !== false; // default true
988
+ if (!enabled) {
989
+ return { enabled: false, status: 'disabled', detail: 'Feature disabled in config' };
990
+ }
991
+ try {
992
+ const mod = require(modulePath);
993
+ if (typeof mod[exportName] === 'function') {
994
+ // Attempt a lightweight invocation to confirm operational
995
+ const result = mod[exportName](planningDir, p15Config);
996
+ const operational = result && result.enabled !== false;
997
+ return {
998
+ enabled: true,
999
+ status: operational ? 'healthy' : 'degraded',
1000
+ detail: operational ? `${exportName} returned data` : 'Module returned disabled stub',
1001
+ };
1002
+ }
1003
+ return { enabled: true, status: 'degraded', detail: `${exportName} not a function` };
1004
+ } catch (err) {
1005
+ return { enabled: true, status: 'degraded', detail: `Error: ${err.message}` };
1006
+ }
1007
+ };
1008
+
1009
+ feature_status.progress_visualization = checkDxFeature(
1010
+ 'progress_visualization',
1011
+ path.join(__dirname, 'progress-visualization.js'),
1012
+ 'getProgressData'
1013
+ );
1014
+ feature_status.contextual_help = checkDxFeature(
1015
+ 'contextual_help',
1016
+ path.join(__dirname, 'contextual-help.js'),
1017
+ 'getContextualHelp'
1018
+ );
1019
+ feature_status.team_onboarding = checkDxFeature(
1020
+ 'team_onboarding',
1021
+ path.join(__dirname, 'onboarding-generator.js'),
1022
+ 'generateOnboardingGuide'
1023
+ );
1024
+ }
1025
+
1026
+ // ─── Check 15: Phase 14 Quality & Safety feature health ───────────────────
1027
+ {
1028
+ let p14Config = {};
1029
+ try { p14Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { logHook('verify', 'debug', 'Failed to parse config for phase14', { error: err.message }); }
1030
+
1031
+ const p14Features = p14Config.features || {};
1032
+
1033
+ // Helper: check a feature module loads correctly
1034
+ const checkFeatureHealth = (featureName, configEnabled, modulePath, validationFn) => {
1035
+ if (!configEnabled) {
1036
+ addIssue('info', `I-${featureName.toUpperCase()}-DISABLED`, `${featureName}: disabled`, `Enable features.${featureName} in config.json if desired`);
1037
+ return { enabled: false, status: 'disabled' };
1038
+ }
1039
+ try {
1040
+ const mod = require(modulePath);
1041
+ const isValid = validationFn(mod);
1042
+ if (isValid) {
1043
+ return { enabled: true, status: 'healthy' };
1044
+ }
1045
+ addIssue('warning', `W-${featureName.toUpperCase()}-DEGRADED`, `${featureName}: degraded (module validation failed)`, `Check ${modulePath} exports`);
1046
+ return { enabled: true, status: 'degraded' };
1047
+ } catch (err) {
1048
+ logHook('verify', 'debug', 'Feature module load failed', { feature: featureName, error: err.message });
1049
+ addIssue('warning', `W-${featureName.toUpperCase()}-DEGRADED`, `${featureName}: degraded (module load failed)`, `Ensure ${modulePath} exists and is valid`);
1050
+ return { enabled: true, status: 'degraded' };
1051
+ }
1052
+ };
1053
+
1054
+ // regression_prevention: default true
1055
+ const rpEnabled = p14Features.regression_prevention !== false;
1056
+ const rpModPath = path.join(__dirname, 'test-selection.js');
1057
+ const rpHealth = checkFeatureHealth(
1058
+ 'regression_prevention',
1059
+ rpEnabled,
1060
+ rpModPath,
1061
+ (mod) => typeof mod.selectTests === 'function'
1062
+ );
1063
+ if (rpHealth.status === 'healthy') {
1064
+ addIssue('info', 'I-RP-HEALTHY', 'regression_prevention: healthy', '');
1065
+ }
1066
+ feature_status.regression_prevention = rpHealth;
1067
+
1068
+ // security_scanning: default true
1069
+ const ssEnabled = p14Features.security_scanning !== false;
1070
+ const ssModPath = path.join(__dirname, 'security-scan.js');
1071
+ const ssHealth = checkFeatureHealth(
1072
+ 'security_scanning',
1073
+ ssEnabled,
1074
+ ssModPath,
1075
+ (mod) => Array.isArray(mod.SECURITY_RULES) && mod.SECURITY_RULES.length > 0
1076
+ );
1077
+ if (ssHealth.status === 'healthy') {
1078
+ try {
1079
+ const ssMod = require(ssModPath);
1080
+ const ruleCount = ssMod.SECURITY_RULES.length;
1081
+ addIssue('info', 'I-SS-HEALTHY', `security_scanning: healthy (${ruleCount} rules loaded)`, '');
1082
+ } catch (err) { logHook('verify', 'debug', 'Failed to load security rules', { error: err.message }); }
1083
+ }
1084
+ feature_status.security_scanning = ssHealth;
1085
+ }
1086
+
1087
+ // ─── Check 16: Phase 11 Spec-Driven Development feature health ───────────
1088
+ {
1089
+ let p11Config = {};
1090
+ try { p11Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { logHook('verify', 'debug', 'Failed to parse config for phase11', { error: err.message }); }
1091
+ const p11Features = p11Config.features || {};
1092
+
1093
+ const checkSpecFeatureHealth = (featureName, defaultEnabled, modulePath, exportName) => {
1094
+ const isEnabled = p11Features[featureName] === undefined ? defaultEnabled : p11Features[featureName];
1095
+ if (!isEnabled) {
1096
+ return { status: 'disabled', enabled: false, details: 'Feature toggle off' };
1097
+ }
1098
+ try {
1099
+ const mod = require(modulePath);
1100
+ if (typeof mod[exportName] === 'function') {
1101
+ return { status: 'healthy', enabled: true, details: `${exportName} loaded` };
1102
+ }
1103
+ return { status: 'degraded', enabled: true, details: `${exportName} not a function` };
1104
+ } catch (err) {
1105
+ logHook('verify', 'debug', 'Cannot load spec module', { error: err.message });
1106
+ return { status: 'degraded', enabled: true, details: `Cannot load module: ${err.message}` };
1107
+ }
1108
+ };
1109
+
1110
+ feature_status.machine_executable_plans = checkSpecFeatureHealth(
1111
+ 'machine_executable_plans', false, path.join(__dirname, 'spec-engine.js'), 'parsePlanToSpec'
1112
+ );
1113
+ feature_status.spec_diffing = checkSpecFeatureHealth(
1114
+ 'spec_diffing', true, path.join(__dirname, 'spec-diff.js'), 'diffSpecs'
1115
+ );
1116
+ feature_status.reverse_spec = checkSpecFeatureHealth(
1117
+ 'reverse_spec', true, path.join(__dirname, 'reverse-spec.js'), 'generateReverseSpec'
1118
+ );
1119
+ feature_status.predictive_impact = checkSpecFeatureHealth(
1120
+ 'predictive_impact', true, path.join(__dirname, 'impact-analysis.js'), 'analyzeImpact'
1121
+ );
1122
+ }
1123
+
1124
+ // ─── Check 17: Phase 16 cross-project intelligence feature health ────────
1125
+ {
1126
+ let p16Config = {};
1127
+ try { p16Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { logHook('verify', 'debug', 'Failed to parse config for phase16', { error: err.message }); }
1128
+ const p16Features = p16Config.features || {};
1129
+
1130
+ // Helper: check if a feature is enabled (default true unless explicitly false)
1131
+ const checkFeatureToggle = (key, healthCheck) => {
1132
+ const enabled = p16Features[key] !== false;
1133
+ if (!enabled) {
1134
+ return { enabled: false, status: 'disabled' };
1135
+ }
1136
+ return { enabled: true, status: healthCheck() ? 'healthy' : 'degraded' };
1137
+ };
1138
+
1139
+ // cross_project_patterns: healthy if ~/.claude/patterns/ exists and has .json files
1140
+ feature_status.cross_project_patterns = checkFeatureToggle(
1141
+ 'cross_project_patterns',
1142
+ () => {
1143
+ try {
1144
+ const patternsDir = require('path').join(require('os').homedir(), '.claude', 'patterns');
1145
+ return fs.existsSync(patternsDir) &&
1146
+ fs.readdirSync(patternsDir).some(f => f.endsWith('.json'));
1147
+ } catch (err) { logHook('verify', 'debug', 'Failed to check patterns dir', { error: err.message }); return false; }
1148
+ }
1149
+ );
1150
+
1151
+ // spec_templates: always healthy when enabled (built-in templates always available)
1152
+ feature_status.spec_templates = checkFeatureToggle(
1153
+ 'spec_templates',
1154
+ () => true
1155
+ );
1156
+
1157
+ // global_learnings: healthy if ~/.claude/learnings.jsonl exists
1158
+ feature_status.global_learnings = checkFeatureToggle(
1159
+ 'global_learnings',
1160
+ () => {
1161
+ try {
1162
+ const learningsPath = require('path').join(require('os').homedir(), '.claude', 'learnings.jsonl');
1163
+ return fs.existsSync(learningsPath);
1164
+ } catch (err) { logHook('verify', 'debug', 'Failed to check learnings path', { error: err.message }); return false; }
1165
+ }
1166
+ );
1167
+ }
1168
+
1169
+ // ─── Check 18: Phase 3 (zero-friction) feature status ────────────────────
1170
+ {
1171
+ let p3Config = {};
1172
+ try { p3Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { logHook('verify', 'debug', 'Failed to parse config for phase3', { error: err.message }); }
1173
+ const p3Features = p3Config.features || {};
1174
+
1175
+ const zfqEnabled = p3Features.zero_friction_quick !== false;
1176
+ feature_status.zero_friction_quick = {
1177
+ enabled: zfqEnabled,
1178
+ status: zfqEnabled ? 'healthy' : 'disabled',
1179
+ };
1180
+ }
1181
+
1182
+ // ─── Check 19: Phase 4 (NL routing) feature status ───────────────────────
1183
+ {
1184
+ let p4Config = {};
1185
+ try { p4Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { logHook('verify', 'debug', 'Failed to parse config for phase4', { error: err.message }); }
1186
+ const p4Features = p4Config.features || {};
1187
+ const pluginRoot = path.resolve(__dirname, '..', '..', '..', 'plugins', 'pbr');
1188
+
1189
+ // natural_language_routing: default true; try to load module
1190
+ const nlrEnabled = p4Features.natural_language_routing !== false;
1191
+ if (!nlrEnabled) {
1192
+ feature_status.natural_language_routing = { enabled: false, status: 'disabled' };
1193
+ } else {
1194
+ try {
1195
+ require(path.join(pluginRoot, 'scripts', 'lib', 'alternatives.js'));
1196
+ feature_status.natural_language_routing = { enabled: true, status: 'healthy' };
1197
+ } catch (err) {
1198
+ logHook('verify', 'debug', 'Failed to load alternatives.js', { error: err.message });
1199
+ feature_status.natural_language_routing = { enabled: true, status: 'degraded' };
1200
+ }
1201
+ }
1202
+
1203
+ // adaptive_ceremony: default true; workflow-only feature, no module
1204
+ const acEnabled = p4Features.adaptive_ceremony !== false;
1205
+ feature_status.adaptive_ceremony = {
1206
+ enabled: acEnabled,
1207
+ status: acEnabled ? 'healthy' : 'disabled',
1208
+ };
1209
+ }
1210
+
1211
+ // ─── Check 20: Phase 6 (convention memory) feature status ────────────────
1212
+ {
1213
+ let p6Config = {};
1214
+ try { p6Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { logHook('verify', 'debug', 'Failed to parse config for phase6', { error: err.message }); }
1215
+ const p6Features = p6Config.features || {};
1216
+ const pluginRoot = path.resolve(__dirname, '..', '..', '..', 'plugins', 'pbr');
1217
+
1218
+ // convention_memory: default true; try to load module
1219
+ const cmEnabled = p6Features.convention_memory !== false;
1220
+ if (!cmEnabled) {
1221
+ feature_status.convention_memory = { enabled: false, status: 'disabled' };
1222
+ } else {
1223
+ try {
1224
+ require(path.join(pluginRoot, 'scripts', 'lib', 'convention-detector.js'));
1225
+ feature_status.convention_memory = { enabled: true, status: 'healthy' };
1226
+ } catch (err) {
1227
+ logHook('verify', 'debug', 'Failed to load convention-detector.js', { error: err.message });
1228
+ feature_status.convention_memory = { enabled: true, status: 'degraded' };
1229
+ }
1230
+ }
1231
+
1232
+ // mental_model_snapshots: default true; try to load module
1233
+ const mmsEnabled = p6Features.mental_model_snapshots !== false;
1234
+ if (!mmsEnabled) {
1235
+ feature_status.mental_model_snapshots = { enabled: false, status: 'disabled' };
1236
+ } else {
1237
+ try {
1238
+ require(path.join(pluginRoot, 'scripts', 'lib', 'snapshot-manager.js'));
1239
+ feature_status.mental_model_snapshots = { enabled: true, status: 'healthy' };
1240
+ } catch (err) {
1241
+ logHook('verify', 'debug', 'Failed to load snapshot-manager.js', { error: err.message });
1242
+ feature_status.mental_model_snapshots = { enabled: true, status: 'degraded' };
1243
+ }
1244
+ }
1245
+ }
1246
+
1247
+ // ─── Check 21: Phase 9 (proactive intelligence) feature status ───────────
1248
+ {
1249
+ let p9Config = {};
1250
+ try { p9Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { logHook('verify', 'debug', 'Failed to parse config for phase9', { error: err.message }); }
1251
+ const scriptsDir = path.resolve(__dirname, '..', '..', '..', 'plugins', 'pbr', 'scripts');
1252
+ const { checkFeatureHealth: checkPhase9FeatureHealth } = require('./health');
1253
+ const phase9Features = [
1254
+ 'smart_next_task',
1255
+ 'dependency_break_detection',
1256
+ 'pre_research',
1257
+ 'pattern_routing',
1258
+ 'tech_debt_surfacing',
1259
+ ];
1260
+ for (const name of phase9Features) {
1261
+ const result = checkPhase9FeatureHealth(name, p9Config, scriptsDir);
1262
+ feature_status[name] = { enabled: result.status !== 'disabled', status: result.status };
1263
+ }
1264
+ }
1265
+
1266
+ // ─── Check 22: Phase 10 (post-hoc) feature status ────────────────────────
1267
+ {
1268
+ const p10ModPath = path.resolve(__dirname, '..', '..', '..', 'plugins', 'pbr', 'scripts', 'lib', 'health-checks.js');
1269
+ try {
1270
+ const p10Checks = require(p10ModPath);
1271
+ const postHocResult = p10Checks.checkPostHocArtifacts(planningDir);
1272
+ feature_status.post_hoc_artifacts = {
1273
+ enabled: postHocResult.enabled,
1274
+ status: postHocResult.status,
1275
+ };
1276
+ const feedbackResult = p10Checks.checkAgentFeedbackLoop(planningDir);
1277
+ feature_status.agent_feedback_loop = {
1278
+ enabled: feedbackResult.enabled,
1279
+ status: feedbackResult.status,
1280
+ };
1281
+ const metricsResult = p10Checks.checkSessionMetrics(planningDir);
1282
+ feature_status.session_metrics = {
1283
+ enabled: metricsResult.enabled,
1284
+ status: metricsResult.status,
1285
+ };
1286
+ } catch (err) {
1287
+ logHook('verify', 'debug', 'Failed to load health-checks.js', { error: err.message });
1288
+ // health-checks.js not available — mark all as degraded
1289
+ feature_status.post_hoc_artifacts = { enabled: true, status: 'degraded' };
1290
+ feature_status.agent_feedback_loop = { enabled: true, status: 'degraded' };
1291
+ feature_status.session_metrics = { enabled: true, status: 'degraded' };
1292
+ }
1293
+ }
1294
+
1295
+ // ─── Check 23: Phase 13 (multi-agent) feature status ─────────────────────
1296
+ {
1297
+ let p13Config = {};
1298
+ try { p13Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { logHook('verify', 'debug', 'Failed to parse config for phase13', { error: err.message }); }
1299
+ const { checkMultiAgentHealth } = require('./health');
1300
+ const multiAgentResults = checkMultiAgentHealth(p13Config);
1301
+ for (const result of multiAgentResults) {
1302
+ feature_status[result.feature] = {
1303
+ enabled: result.status !== 'disabled',
1304
+ status: result.status,
1305
+ };
1306
+ }
1307
+ }
1308
+
1309
+ // ─── Perform repairs if requested ─────────────────────────────────────────
1310
+ const repairActions = [];
1311
+ if (options.repair && repairs.length > 0) {
1312
+ for (const repair of repairs) {
1313
+ try {
1314
+ switch (repair) {
1315
+ case 'createConfig':
1316
+ case 'resetConfig': {
1317
+ const defaults = {
1318
+ model_profile: 'balanced',
1319
+ commit_docs: true,
1320
+ search_gitignored: false,
1321
+ branching_strategy: 'none',
1322
+ research: true,
1323
+ plan_checker: true,
1324
+ verifier: true,
1325
+ parallelization: true,
1326
+ };
1327
+ fs.writeFileSync(configPath, JSON.stringify(defaults, null, 2), 'utf-8');
1328
+ repairActions.push({ action: repair, success: true, path: 'config.json' });
1329
+ break;
1330
+ }
1331
+ case 'regenerateState': {
1332
+ // Create timestamped backup before overwriting
1333
+ if (fs.existsSync(statePath)) {
1334
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
1335
+ const backupPath = `${statePath}.bak-${timestamp}`;
1336
+ fs.copyFileSync(statePath, backupPath);
1337
+ repairActions.push({ action: 'backupState', success: true, path: backupPath });
1338
+ }
1339
+ // Generate minimal STATE.md from ROADMAP.md structure
1340
+ const milestone = getMilestoneInfo(cwd);
1341
+ let stateContent = `# Session State\n\n`;
1342
+ stateContent += `## Project Reference\n\n`;
1343
+ stateContent += `See: .planning/PROJECT.md\n\n`;
1344
+ stateContent += `## Position\n\n`;
1345
+ stateContent += `**Milestone:** ${milestone.version} ${milestone.name}\n`;
1346
+ stateContent += `**Current phase:** (determining...)\n`;
1347
+ stateContent += `**Status:** Resuming\n\n`;
1348
+ stateContent += `## Session Log\n\n`;
1349
+ stateContent += `- ${new Date().toISOString().split('T')[0]}: STATE.md regenerated by /pbr:health --repair\n`;
1350
+ fs.writeFileSync(statePath, stateContent, 'utf-8');
1351
+ repairActions.push({ action: repair, success: true, path: 'STATE.md' });
1352
+ break;
1353
+ }
1354
+ case 'addNyquistKey': {
1355
+ if (fs.existsSync(configPath)) {
1356
+ try {
1357
+ const configRaw = fs.readFileSync(configPath, 'utf-8');
1358
+ const configParsed = JSON.parse(configRaw);
1359
+ if (!configParsed.workflow) configParsed.workflow = {};
1360
+ if (configParsed.workflow.nyquist_validation === undefined) {
1361
+ configParsed.workflow.nyquist_validation = true;
1362
+ fs.writeFileSync(configPath, JSON.stringify(configParsed, null, 2), 'utf-8');
1363
+ }
1364
+ repairActions.push({ action: repair, success: true, path: 'config.json' });
1365
+ } catch (err) {
1366
+ repairActions.push({ action: repair, success: false, error: err.message });
1367
+ }
1368
+ }
1369
+ break;
1370
+ }
1371
+ }
1372
+ } catch (err) {
1373
+ repairActions.push({ action: repair, success: false, error: err.message });
1374
+ }
1375
+ }
1376
+ }
1377
+
1378
+ // ─── Determine overall status ─────────────────────────────────────────────
1379
+ let status;
1380
+ if (errors.length > 0) {
1381
+ status = 'broken';
1382
+ } else if (warnings.length > 0) {
1383
+ status = 'degraded';
1384
+ } else {
1385
+ status = 'healthy';
1386
+ }
1387
+
1388
+ const repairableCount = errors.filter(e => e.repairable).length +
1389
+ warnings.filter(w => w.repairable).length;
1390
+
1391
+ output({
1392
+ status,
1393
+ errors,
1394
+ warnings,
1395
+ info,
1396
+ repairable_count: repairableCount,
1397
+ repairs_performed: repairActions.length > 0 ? repairActions : undefined,
1398
+ feature_status: Object.keys(feature_status).length > 0 ? feature_status : undefined,
1399
+ phase05_features: phase05_features || undefined,
1400
+ }, raw);
1401
+ }
1402
+
1403
+ /**
1404
+ * Generic health check for a feature backed by a loadable module.
1405
+ * @param {string} featureName - Feature name (e.g. 'natural_language_routing')
1406
+ * @param {string} planningDir - Path to .planning directory
1407
+ * @param {string} pluginRoot - Path to plugin root (plugins/pbr)
1408
+ * @param {string} togglePath - Dot path in config.features (same as featureName)
1409
+ * @param {string} modulePath - Relative path under pluginRoot to the module
1410
+ * @param {string} exportName - Name of the expected export function
1411
+ * @returns {{ feature: string, status: string, details: string }}
1412
+ */
1413
+ function checkFeatureModuleHealth(featureName, planningDir, pluginRoot, modulePath, exportName) {
1414
+ const configPath = path.join(planningDir, 'config.json');
1415
+ let config = {};
1416
+ try {
1417
+ if (fs.existsSync(configPath)) {
1418
+ config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
1419
+ }
1420
+ } catch (err) {
1421
+ logHook('verify', 'debug', 'Config unreadable for feature health', { error: err.message });
1422
+ // Config unreadable — treat as defaults
1423
+ }
1424
+
1425
+ const features = config.features || {};
1426
+
1427
+ // Check toggle (default true)
1428
+ if (features[featureName] === false) {
1429
+ return { feature: featureName, status: 'disabled', details: 'Feature toggle off' };
1430
+ }
1431
+
1432
+ // Try to load the module
1433
+ const fullModulePath = path.join(pluginRoot, modulePath);
1434
+ try {
1435
+ const mod = require(fullModulePath);
1436
+ if (typeof mod[exportName] === 'function') {
1437
+ return { feature: featureName, status: 'healthy', details: `${exportName} loaded from ${modulePath}` };
1438
+ }
1439
+ return { feature: featureName, status: 'degraded', details: `${exportName} not a function in ${modulePath}` };
1440
+ } catch (err) {
1441
+ return { feature: featureName, status: 'degraded', details: `Cannot load ${modulePath}: ${err.message}` };
1442
+ }
1443
+ }
1444
+
1445
+ /**
1446
+ * Health check for natural_language_routing feature.
1447
+ * @param {string} planningDir - Path to .planning directory
1448
+ * @param {string} pluginRoot - Path to plugin root (plugins/pbr)
1449
+ * @returns {{ feature: string, status: string, details: string }}
1450
+ */
1451
+ function checkNLRoutingHealth(planningDir, pluginRoot) {
1452
+ return checkFeatureModuleHealth(
1453
+ 'natural_language_routing', planningDir, pluginRoot,
1454
+ path.join('scripts', 'intent-router.cjs'), 'classifyIntent'
1455
+ );
1456
+ }
1457
+
1458
+ /**
1459
+ * Health check for adaptive_ceremony feature.
1460
+ * @param {string} planningDir - Path to .planning directory
1461
+ * @param {string} pluginRoot - Path to plugin root (plugins/pbr)
1462
+ * @returns {{ feature: string, status: string, details: string }}
1463
+ */
1464
+ function checkAdaptiveCeremonyHealth(planningDir, pluginRoot) {
1465
+ return checkFeatureModuleHealth(
1466
+ 'adaptive_ceremony', planningDir, pluginRoot,
1467
+ path.join('scripts', 'risk-classifier.cjs'), 'classifyRisk'
1468
+ );
1469
+ }
1470
+
1471
+ /**
1472
+ * Check assumption registry for stale or never-validated entries.
1473
+ *
1474
+ * Reads references/assumptions.md, parses the markdown table, and returns
1475
+ * entries that are stale (older than thresholdDays) or never validated.
1476
+ *
1477
+ * @param {string} cwd - Working directory (project root or plugin root)
1478
+ * @param {number} [thresholdDays=90] - Days after which validation is stale
1479
+ * @returns {{ stale: string[], neverValidated: string[], total: number, fresh: number }}
1480
+ */
1481
+ function checkAssumptionStaleness(cwd, thresholdDays) {
1482
+ const threshold = typeof thresholdDays === 'number' ? thresholdDays : 90;
1483
+ const empty = { stale: [], neverValidated: [], total: 0, fresh: 0 };
1484
+
1485
+ // Try multiple possible locations for the assumptions file
1486
+ const candidates = [
1487
+ path.join(cwd, 'plugins', 'pbr', 'references', 'assumptions.md'),
1488
+ path.join(cwd, 'references', 'assumptions.md'),
1489
+ ];
1490
+
1491
+ let content = null;
1492
+ for (const candidate of candidates) {
1493
+ const result = safeReadFile(candidate);
1494
+ if (result) {
1495
+ content = result;
1496
+ break;
1497
+ }
1498
+ }
1499
+
1500
+ if (!content) return empty;
1501
+
1502
+ const lines = content.split('\n');
1503
+ const dataRows = lines.filter(line => {
1504
+ if (!line.startsWith('|')) return false;
1505
+ if (line.includes('---')) return false;
1506
+ if (line.includes('Component') && line.includes('Type')) return false;
1507
+ return true;
1508
+ });
1509
+
1510
+ const stale = [];
1511
+ const neverValidated = [];
1512
+ let freshCount = 0;
1513
+ const now = new Date();
1514
+
1515
+ for (const row of dataRows) {
1516
+ const cells = row.split('|').map(c => c.trim()).filter(Boolean);
1517
+ if (cells.length < 6) continue;
1518
+
1519
+ const component = cells[0];
1520
+ const lastValidated = cells[5];
1521
+
1522
+ if (!lastValidated || lastValidated === '-') {
1523
+ neverValidated.push(component);
1524
+ } else {
1525
+ const validDate = new Date(lastValidated);
1526
+ if (isNaN(validDate.getTime())) {
1527
+ neverValidated.push(component);
1528
+ } else {
1529
+ const daysDiff = Math.floor((now - validDate) / (1000 * 60 * 60 * 24));
1530
+ if (daysDiff > threshold) {
1531
+ stale.push(component);
1532
+ } else {
1533
+ freshCount++;
1534
+ }
1535
+ }
1536
+ }
1537
+ }
1538
+
1539
+ return {
1540
+ stale,
1541
+ neverValidated,
1542
+ total: dataRows.length,
1543
+ fresh: freshCount,
1544
+ };
1545
+ }
1546
+
1547
+ module.exports = {
1548
+ cmdVerifySummary,
1549
+ cmdVerifyPlanStructure,
1550
+ cmdVerifyPhaseCompleteness,
1551
+ cmdVerifyReferences,
1552
+ cmdVerifyCommits,
1553
+ cmdVerifyArtifacts,
1554
+ cmdVerifyKeyLinks,
1555
+ cmdValidateConsistency,
1556
+ cmdValidateHealth,
1557
+ checkNLRoutingHealth,
1558
+ checkAdaptiveCeremonyHealth,
1559
+ checkFeatureModuleHealth,
1560
+ checkAssumptionStaleness,
1561
+ };