@sienklogic/plan-build-run 2.18.1 → 2.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1265 -296
- package/CLAUDE.md +56 -34
- package/LICENSE +2 -1
- package/README.md +412 -177
- package/bin/install.js +2752 -0
- package/dashboard/bin/cli.cjs +96 -0
- package/dashboard/bin/stop.cjs +129 -0
- package/dashboard/eslint.config.js +37 -0
- package/dashboard/index.html +20 -0
- package/dashboard/package.json +27 -25
- package/dashboard/server/index.js +142 -0
- package/dashboard/server/lib/frontmatter.js +92 -0
- package/dashboard/server/middleware/static.js +35 -0
- package/dashboard/server/package.json +16 -0
- package/dashboard/server/routes/agents.js +213 -0
- package/dashboard/server/routes/config.js +64 -0
- package/dashboard/server/routes/health.js +95 -0
- package/dashboard/server/routes/incidents.js +78 -0
- package/dashboard/server/routes/intel.js +69 -0
- package/dashboard/server/routes/memory.js +107 -0
- package/dashboard/server/routes/planning.js +234 -0
- package/dashboard/server/routes/progress.js +77 -0
- package/dashboard/server/routes/projects.js +36 -0
- package/dashboard/server/routes/requirements.js +40 -0
- package/dashboard/server/routes/roadmap.js +69 -0
- package/dashboard/server/routes/sessions.js +70 -0
- package/dashboard/server/routes/status.js +25 -0
- package/dashboard/server/routes/telemetry.js +214 -0
- package/dashboard/server/services/file-watcher.js +105 -0
- package/dashboard/server/services/planning-reader.js +741 -0
- package/dashboard/server/test/cli.test.js +34 -0
- package/dashboard/server/test/frontmatter.test.js +104 -0
- package/dashboard/server/test/isolation.test.js +32 -0
- package/dashboard/server/test/planning-reader.test.js +151 -0
- package/dashboard/server/test/routes.test.js +91 -0
- package/dashboard/server/test/ws.test.js +81 -0
- package/dashboard/server/ws.js +96 -0
- package/dashboard/src/App.jsx +165 -0
- package/dashboard/src/components/charts/BudgetBars.jsx +42 -0
- package/dashboard/src/components/charts/ContextRadar.jsx +34 -0
- package/dashboard/src/components/charts/PhaseDonut.jsx +66 -0
- package/dashboard/src/components/charts/SuccessTrend.jsx +45 -0
- package/dashboard/src/components/charts/TokenChart.jsx +55 -0
- package/dashboard/src/components/charts/index.js +5 -0
- package/dashboard/src/components/config/CfgSection.jsx +93 -0
- package/dashboard/src/components/layout/Header.jsx +89 -0
- package/dashboard/src/components/layout/ProjectSwitcher.jsx +160 -0
- package/dashboard/src/components/layout/Sidebar.jsx +161 -0
- package/dashboard/src/components/ui/AutoModeBanner.jsx +138 -0
- package/dashboard/src/components/ui/BackButton.jsx +27 -0
- package/dashboard/src/components/ui/Badge.jsx +27 -0
- package/dashboard/src/components/ui/Card.jsx +23 -0
- package/dashboard/src/components/ui/ChartTooltip.jsx +48 -0
- package/dashboard/src/components/ui/CheckpointBox.jsx +110 -0
- package/dashboard/src/components/ui/CodeBlock.jsx +27 -0
- package/dashboard/src/components/ui/ConfidenceBadge.jsx +20 -0
- package/dashboard/src/components/ui/ConfirmModal.jsx +161 -0
- package/dashboard/src/components/ui/ConnectionBanner.jsx +60 -0
- package/dashboard/src/components/ui/ErrorBoundary.jsx +106 -0
- package/dashboard/src/components/ui/ErrorBox.jsx +107 -0
- package/dashboard/src/components/ui/KeyValue.jsx +33 -0
- package/dashboard/src/components/ui/LoadingSkeleton.jsx +84 -0
- package/dashboard/src/components/ui/MetricCard.jsx +58 -0
- package/dashboard/src/components/ui/NextUpBlock.jsx +92 -0
- package/dashboard/src/components/ui/NumberInput.jsx +44 -0
- package/dashboard/src/components/ui/PBRBanner.jsx +47 -0
- package/dashboard/src/components/ui/PipelineView.jsx +130 -0
- package/dashboard/src/components/ui/ProgressBar.jsx +28 -0
- package/dashboard/src/components/ui/ProgressDisplay.jsx +47 -0
- package/dashboard/src/components/ui/QualityGateBadge.jsx +15 -0
- package/dashboard/src/components/ui/SectionTitle.jsx +35 -0
- package/dashboard/src/components/ui/SelectInput.jsx +45 -0
- package/dashboard/src/components/ui/StatusDot.jsx +51 -0
- package/dashboard/src/components/ui/StatusSymbol.jsx +49 -0
- package/dashboard/src/components/ui/TabBar.jsx +41 -0
- package/dashboard/src/components/ui/TextInput.jsx +42 -0
- package/dashboard/src/components/ui/Toast.jsx +117 -0
- package/dashboard/src/components/ui/Toggle.jsx +70 -0
- package/dashboard/src/components/ui/index.js +29 -0
- package/dashboard/src/hooks/useDocumentTitle.js +16 -0
- package/dashboard/src/hooks/useFetch.js +50 -0
- package/dashboard/src/hooks/useToast.jsx +43 -0
- package/dashboard/src/hooks/useWebSocket.js +103 -0
- package/dashboard/src/lib/api.js +112 -0
- package/dashboard/src/lib/configSchema.js +189 -0
- package/dashboard/src/lib/constants.js +22 -0
- package/dashboard/src/main.jsx +15 -0
- package/dashboard/src/pages/AgentsPage.jsx +191 -0
- package/dashboard/src/pages/ConfigPage.jsx +298 -0
- package/dashboard/src/pages/HooksPage.jsx +412 -0
- package/dashboard/src/pages/IncidentsPage.jsx +135 -0
- package/dashboard/src/pages/IntelPage.jsx +193 -0
- package/dashboard/src/pages/LiveFeed.jsx +274 -0
- package/dashboard/src/pages/MemoryPage.jsx +107 -0
- package/dashboard/src/pages/OnboardingPage.jsx +117 -0
- package/dashboard/src/pages/Overview.jsx +360 -0
- package/dashboard/src/pages/PhaseDetailView.jsx +216 -0
- package/dashboard/src/pages/PlanningPage.jsx +181 -0
- package/dashboard/src/pages/ProgressPage.jsx +249 -0
- package/dashboard/src/pages/ResearchPage.jsx +129 -0
- package/dashboard/src/pages/RoadmapPage.jsx +251 -0
- package/dashboard/src/pages/SessionsPage.jsx +117 -0
- package/dashboard/src/pages/Telemetry.jsx +166 -0
- package/dashboard/src/pages/planning/DecisionsTab.jsx +153 -0
- package/dashboard/src/pages/planning/FilesTab.jsx +420 -0
- package/dashboard/src/pages/planning/MilestoneDetail.jsx +319 -0
- package/dashboard/src/pages/planning/MilestonesTab.jsx +151 -0
- package/dashboard/src/pages/planning/NotesTab.jsx +251 -0
- package/dashboard/src/pages/planning/PhasesTab.jsx +218 -0
- package/dashboard/src/pages/planning/QuickTab.jsx +50 -0
- package/dashboard/src/pages/planning/ResearchTab.jsx +103 -0
- package/dashboard/src/pages/planning/TodosTab.jsx +297 -0
- package/dashboard/src/theme/ThemeProvider.jsx +38 -0
- package/dashboard/src/theme/tokens.js +17 -0
- package/dashboard/tests/components/ConfirmModal.test.jsx +179 -0
- package/dashboard/tests/components/ConnectionBanner.test.jsx +37 -0
- package/dashboard/tests/components/ErrorBoundary.test.jsx +59 -0
- package/dashboard/tests/components/LoadingSkeleton.test.jsx +46 -0
- package/dashboard/tests/components/ToastContainer.test.jsx +47 -0
- package/dashboard/tests/components/Toggle.test.jsx +61 -0
- package/dashboard/tests/hooks/useFetch.test.jsx +77 -0
- package/dashboard/tests/hooks/useToast.test.jsx +78 -0
- package/dashboard/tests/hooks/useWebSocket.test.jsx +128 -0
- package/dashboard/tests/pages/ConfigPage.test.jsx +199 -0
- package/dashboard/tests/pages/PlanningPage.test.jsx +119 -0
- package/dashboard/tests/pages/planning/FilesTab.test.jsx +198 -0
- package/dashboard/tests/pages/planning/NotesTab.test.jsx +178 -0
- package/dashboard/tests/pages/planning/TodosTab.test.jsx +188 -0
- package/dashboard/tests/performance.test.jsx +46 -0
- package/dashboard/tests/routes/config.test.js +98 -0
- package/dashboard/tests/routes/health.test.js +40 -0
- package/dashboard/tests/routes/planning.test.js +112 -0
- package/dashboard/tests/routes/roadmap.test.js +91 -0
- package/dashboard/tests/routes/status.test.js +131 -0
- package/dashboard/tests/server/planning-reader.test.js +153 -0
- package/dashboard/tests/setup.js +7 -0
- package/dashboard/vite.config.js +41 -0
- package/package.json +55 -40
- package/plan-build-run/bin/config-schema.json +1420 -0
- package/plugins/pbr/.claude-plugin/plugin.json +1 -1
- package/plugins/pbr/CLAUDE.md +19 -0
- package/plugins/pbr/UI-CONSISTENCY-GAPS.md +1 -1
- package/plugins/pbr/agents/advisor-researcher.md +100 -0
- package/plugins/pbr/agents/audit.md +205 -89
- package/plugins/pbr/agents/codebase-mapper.md +158 -23
- package/plugins/pbr/agents/debugger.md +222 -30
- package/plugins/pbr/agents/dev-sync.md +206 -0
- package/plugins/pbr/agents/executor.md +717 -39
- package/plugins/pbr/agents/general.md +71 -6
- package/plugins/pbr/agents/integration-checker.md +146 -30
- package/plugins/pbr/agents/intel-updater.md +332 -0
- package/plugins/pbr/agents/nyquist-auditor.md +253 -0
- package/plugins/pbr/agents/plan-checker.md +270 -61
- package/plugins/pbr/agents/planner.md +440 -42
- package/plugins/pbr/agents/researcher.md +223 -36
- package/plugins/pbr/agents/roadmapper.md +397 -0
- package/plugins/pbr/agents/synthesizer.md +170 -26
- package/plugins/pbr/agents/ui-checker.md +203 -0
- package/plugins/pbr/agents/ui-researcher.md +224 -0
- package/plugins/pbr/agents/verifier.md +495 -47
- package/plugins/pbr/commands/add-phase.md +75 -0
- package/plugins/pbr/commands/add-todo.md +8 -0
- package/plugins/pbr/commands/audit-fix.md +5 -0
- package/plugins/pbr/commands/audit-milestone.md +8 -0
- package/plugins/pbr/commands/autonomous.md +5 -0
- package/plugins/pbr/commands/backlog.md +6 -0
- package/plugins/pbr/commands/check-todos.md +8 -0
- package/plugins/pbr/commands/complete-milestone.md +8 -0
- package/plugins/pbr/commands/config.md +1 -1
- package/plugins/pbr/commands/discuss-phase.md +6 -0
- package/plugins/pbr/commands/do.md +5 -0
- package/plugins/pbr/commands/execute-phase.md +6 -0
- package/plugins/pbr/commands/fast.md +6 -0
- package/plugins/pbr/commands/forensics.md +6 -0
- package/plugins/pbr/commands/import.md +1 -1
- package/plugins/pbr/commands/insert-phase.md +65 -0
- package/plugins/pbr/commands/intel.md +5 -0
- package/plugins/pbr/commands/join-discord.md +11 -0
- package/plugins/pbr/commands/list-phase-assumptions.md +5 -0
- package/plugins/pbr/commands/map-codebase.md +6 -0
- package/plugins/pbr/commands/milestone-summary.md +6 -0
- package/plugins/pbr/commands/new-milestone.md +8 -0
- package/plugins/pbr/commands/new-project.md +6 -0
- package/plugins/pbr/commands/pause-work.md +5 -0
- package/plugins/pbr/commands/plan-milestone-gaps.md +7 -0
- package/plugins/pbr/commands/plan-phase.md +6 -0
- package/plugins/pbr/commands/plant-seed.md +6 -0
- package/plugins/pbr/commands/profile-user.md +5 -0
- package/plugins/pbr/commands/profile.md +5 -0
- package/plugins/pbr/commands/progress.md +6 -0
- package/plugins/pbr/commands/quick.md +1 -1
- package/plugins/pbr/commands/reapply-patches.md +47 -0
- package/plugins/pbr/commands/release.md +6 -0
- package/plugins/pbr/commands/remove-phase.md +66 -0
- package/plugins/pbr/commands/research-phase.md +59 -0
- package/plugins/pbr/commands/resume-work.md +5 -0
- package/plugins/pbr/commands/seed.md +6 -0
- package/plugins/pbr/commands/session-report.md +5 -0
- package/plugins/pbr/commands/set-profile.md +6 -0
- package/plugins/pbr/commands/settings.md +5 -0
- package/plugins/pbr/commands/setup.md +1 -1
- package/plugins/pbr/commands/ship.md +5 -0
- package/plugins/pbr/commands/stats.md +6 -0
- package/plugins/pbr/commands/test.md +5 -0
- package/plugins/pbr/commands/thread.md +6 -0
- package/plugins/pbr/commands/todo.md +1 -1
- package/plugins/pbr/commands/ui-phase.md +5 -0
- package/plugins/pbr/commands/ui-review.md +5 -0
- package/plugins/pbr/commands/undo.md +5 -0
- package/plugins/pbr/commands/update.md +37 -0
- package/plugins/pbr/commands/validate-phase.md +5 -0
- package/plugins/pbr/commands/verify-work.md +6 -0
- package/plugins/pbr/dashboard/package-lock.json +6 -0
- package/plugins/pbr/dist/architecture-guard.js +59 -0
- package/plugins/pbr/dist/audit-dimensions.js +556 -0
- package/plugins/pbr/dist/auto-continue.js +277 -0
- package/plugins/pbr/dist/block-skill-self-read.js +124 -0
- package/plugins/pbr/dist/check-agent-state-write.js +63 -0
- package/plugins/pbr/dist/check-config-change.js +162 -0
- package/plugins/pbr/dist/check-cross-plugin-sync.js +93 -0
- package/plugins/pbr/dist/check-dangerous-commands.js +193 -0
- package/plugins/pbr/dist/check-direct-state-write.js +37 -0
- package/plugins/pbr/dist/check-doc-sprawl.js +102 -0
- package/plugins/pbr/dist/check-phase-boundary.js +191 -0
- package/plugins/pbr/dist/check-plan-format.js +241 -0
- package/plugins/pbr/dist/check-read-first.js +345 -0
- package/plugins/pbr/dist/check-roadmap-sync.js +503 -0
- package/plugins/pbr/dist/check-skill-workflow.js +354 -0
- package/plugins/pbr/dist/check-state-sync.js +658 -0
- package/plugins/pbr/dist/check-subagent-output.js +452 -0
- package/plugins/pbr/dist/check-summary-gate.js +199 -0
- package/plugins/pbr/dist/context-bridge.js +425 -0
- package/plugins/pbr/dist/context-budget-check.js +442 -0
- package/plugins/pbr/dist/context-quality.js +271 -0
- package/plugins/pbr/dist/enforce-context-budget.js +138 -0
- package/plugins/pbr/dist/enforce-pbr-workflow.js +277 -0
- package/plugins/pbr/dist/event-handler.js +202 -0
- package/plugins/pbr/dist/event-logger.js +125 -0
- package/plugins/pbr/dist/feedback-loop.js +172 -0
- package/plugins/pbr/dist/graph-update.js +422 -0
- package/plugins/pbr/dist/hook-logger.js +114 -0
- package/plugins/pbr/dist/hook-server-client.js +361 -0
- package/plugins/pbr/dist/hook-server.js +606 -0
- package/plugins/pbr/dist/hooks-schema.json +87 -0
- package/plugins/pbr/dist/instructions-loaded.js +173 -0
- package/plugins/pbr/dist/intercept-plan-mode.js +81 -0
- package/plugins/pbr/dist/log-notification.js +131 -0
- package/plugins/pbr/dist/log-subagent.js +349 -0
- package/plugins/pbr/dist/log-tool-failure.js +140 -0
- package/plugins/pbr/dist/milestone-learnings.js +569 -0
- package/plugins/pbr/dist/pbr-tools.js +2044 -0
- package/plugins/pbr/dist/post-bash-triage.js +154 -0
- package/plugins/pbr/dist/post-compact.js +135 -0
- package/plugins/pbr/dist/post-hoc.js +286 -0
- package/plugins/pbr/dist/post-write-dispatch.js +279 -0
- package/plugins/pbr/dist/post-write-quality.js +208 -0
- package/plugins/pbr/dist/pre-bash-dispatch.js +218 -0
- package/plugins/pbr/dist/pre-skill-dispatch.js +114 -0
- package/plugins/pbr/dist/pre-task-dispatch.js +297 -0
- package/plugins/pbr/dist/pre-write-dispatch.js +234 -0
- package/plugins/pbr/dist/progress-tracker.js +198 -0
- package/plugins/pbr/dist/prompt-guard.js +114 -0
- package/plugins/pbr/dist/prompt-routing.js +209 -0
- package/plugins/pbr/dist/quick-status.js +179 -0
- package/plugins/pbr/dist/record-incident.js +37 -0
- package/plugins/pbr/dist/run-hook.js +144 -0
- package/plugins/pbr/dist/session-cleanup.js +683 -0
- package/plugins/pbr/dist/session-tracker.js +124 -0
- package/plugins/pbr/dist/status-line.js +847 -0
- package/plugins/pbr/dist/suggest-compact.js +315 -0
- package/plugins/pbr/dist/sync-context-to-claude.js +100 -0
- package/plugins/pbr/dist/task-completed.js +206 -0
- package/plugins/pbr/dist/track-context-budget.js +432 -0
- package/plugins/pbr/dist/track-user-gates.js +88 -0
- package/plugins/pbr/dist/trust-tracker.js +193 -0
- package/plugins/pbr/dist/validate-commit.js +271 -0
- package/plugins/pbr/dist/validate-skill-args.js +222 -0
- package/plugins/pbr/dist/validate-task.js +301 -0
- package/plugins/pbr/dist/worktree-create.js +144 -0
- package/plugins/pbr/dist/worktree-remove.js +147 -0
- package/plugins/pbr/hooks/hooks.json +143 -60
- package/plugins/pbr/references/agent-contracts.md +40 -9
- package/plugins/pbr/references/agent-teams.md +3 -3
- package/plugins/pbr/references/archive/checkpoints.md +189 -0
- package/plugins/pbr/references/archive/context-quality-tiers.md +45 -0
- package/plugins/pbr/references/archive/hook-ordering.md +89 -0
- package/plugins/pbr/references/archive/limitations.md +106 -0
- package/plugins/pbr/references/archive/pbr-rules.md +194 -0
- package/plugins/pbr/references/archive/pbr-tools-cli.md +415 -0
- package/plugins/pbr/references/archive/pretooluse-jsonl-behavior.md +58 -0
- package/plugins/pbr/references/archive/signal-files.md +41 -0
- package/plugins/pbr/references/archive/tmux-setup.md +288 -0
- package/plugins/pbr/references/archive/verification-matrix.md +34 -0
- package/plugins/pbr/references/archive/verification-patterns.md +277 -0
- package/plugins/pbr/references/archive/worktree-sparse-checkout.md +86 -0
- package/plugins/pbr/references/behavioral-contexts.md +53 -0
- package/plugins/pbr/references/checkpoints.md +723 -104
- package/plugins/pbr/references/config-reference.md +472 -10
- package/plugins/pbr/references/continuation-format.md +1 -0
- package/plugins/pbr/references/decimal-phase-calculation.md +65 -0
- package/plugins/pbr/references/deviation-rules.md +12 -0
- package/plugins/pbr/references/git-integration.md +110 -27
- package/plugins/pbr/references/git-planning-commit.md +35 -0
- package/plugins/pbr/references/model-profile-resolution.md +34 -0
- package/plugins/pbr/references/model-profiles.md +90 -7
- package/plugins/pbr/references/model-selection.md +1 -1
- package/plugins/pbr/references/node-repair.md +48 -0
- package/plugins/pbr/references/plan-authoring.md +65 -0
- package/plugins/pbr/references/plan-format.md +161 -10
- package/plugins/pbr/references/questioning.md +138 -49
- package/plugins/pbr/references/reading-verification.md +4 -4
- package/plugins/pbr/references/tdd.md +263 -0
- package/plugins/pbr/references/ui-brand.md +449 -0
- package/plugins/pbr/references/verification-overrides.md +39 -0
- package/plugins/pbr/references/verification-patterns.md +529 -113
- package/plugins/pbr/scripts/architecture-guard.js +59 -0
- package/plugins/pbr/scripts/audit-checks/behavioral-compliance.js +2098 -0
- package/plugins/pbr/scripts/audit-checks/error-analysis.js +989 -0
- package/plugins/pbr/scripts/audit-checks/feature-verification.js +723 -0
- package/plugins/pbr/scripts/audit-checks/index.js +433 -0
- package/plugins/pbr/scripts/audit-checks/infrastructure.js +816 -0
- package/plugins/pbr/scripts/audit-checks/quality-metrics.js +452 -0
- package/plugins/pbr/scripts/audit-checks/session-quality.js +980 -0
- package/plugins/pbr/scripts/audit-checks/si-agent-hook-config-checks.js +466 -0
- package/plugins/pbr/scripts/audit-checks/si-cross-cutting-checks.js +272 -0
- package/plugins/pbr/scripts/audit-checks/si-skill-checks.js +424 -0
- package/plugins/pbr/scripts/audit-checks/workflow-compliance.js +1211 -0
- package/plugins/pbr/scripts/audit-dimensions.js +556 -0
- package/plugins/pbr/scripts/auto-continue.js +198 -31
- package/plugins/pbr/scripts/block-skill-self-read.js +124 -0
- package/plugins/pbr/scripts/check-agent-state-write.js +63 -0
- package/plugins/pbr/scripts/check-config-change.js +162 -0
- package/plugins/pbr/scripts/check-cross-plugin-sync.js +93 -0
- package/plugins/pbr/scripts/check-dangerous-commands.js +18 -5
- package/plugins/pbr/scripts/check-direct-state-write.js +37 -0
- package/plugins/pbr/scripts/check-phase-boundary.js +3 -8
- package/plugins/pbr/scripts/check-plan-format.js +166 -277
- package/plugins/pbr/scripts/check-read-first.js +345 -0
- package/plugins/pbr/scripts/check-roadmap-sync.js +167 -10
- package/plugins/pbr/scripts/check-skill-workflow.js +24 -27
- package/plugins/pbr/scripts/check-state-sync.js +339 -215
- package/plugins/pbr/scripts/check-subagent-output.js +338 -276
- package/plugins/pbr/scripts/check-summary-gate.js +2 -1
- package/plugins/pbr/scripts/config-schema.json +1247 -95
- package/plugins/pbr/scripts/context-bridge.js +425 -0
- package/plugins/pbr/scripts/context-budget-check.js +169 -14
- package/plugins/pbr/scripts/context-quality.js +271 -0
- package/plugins/pbr/scripts/enforce-context-budget.js +138 -0
- package/plugins/pbr/scripts/enforce-pbr-workflow.js +277 -0
- package/plugins/pbr/scripts/event-handler.js +128 -77
- package/plugins/pbr/scripts/event-logger.js +58 -25
- package/plugins/pbr/scripts/feedback-loop.js +172 -0
- package/plugins/pbr/scripts/graph-update.js +422 -0
- package/plugins/pbr/scripts/hook-logger.js +69 -35
- package/plugins/pbr/scripts/hook-server-client.js +361 -0
- package/plugins/pbr/scripts/hook-server.js +606 -0
- package/plugins/pbr/scripts/hooks-schema.json +13 -5
- package/plugins/pbr/scripts/instructions-loaded.js +173 -0
- package/plugins/pbr/scripts/intent-router.cjs +147 -0
- package/plugins/pbr/scripts/intercept-plan-mode.js +52 -18
- package/plugins/pbr/scripts/lib/alternatives.js +203 -0
- package/plugins/pbr/scripts/lib/audit.js +65 -0
- package/plugins/pbr/scripts/lib/auto-cleanup.js +221 -0
- package/plugins/pbr/scripts/lib/auto-verify.js +103 -0
- package/plugins/pbr/scripts/lib/autonomy.js +91 -0
- package/plugins/pbr/scripts/lib/build.js +719 -0
- package/plugins/pbr/scripts/lib/ci-fix-loop.js +228 -0
- package/plugins/pbr/scripts/lib/circuit-state.js +133 -0
- package/plugins/pbr/scripts/lib/commands.js +483 -0
- package/plugins/pbr/scripts/lib/completion.js +377 -0
- package/plugins/pbr/scripts/lib/compound.js +216 -0
- package/plugins/pbr/scripts/lib/config.js +1315 -0
- package/plugins/pbr/scripts/lib/context.js +254 -0
- package/plugins/pbr/scripts/lib/contextual-help.js +207 -0
- package/plugins/pbr/scripts/lib/convention-detector.js +413 -0
- package/plugins/pbr/scripts/lib/core.js +1569 -0
- package/plugins/pbr/scripts/lib/dashboard-launch.js +364 -0
- package/plugins/pbr/scripts/lib/data-hygiene.js +179 -0
- package/plugins/pbr/scripts/lib/decision-extraction.js +183 -0
- package/plugins/pbr/scripts/lib/decisions.js +194 -0
- package/plugins/pbr/scripts/lib/dependency-break.js +147 -0
- package/plugins/pbr/scripts/lib/format-validators.js +1050 -0
- package/plugins/pbr/scripts/lib/frontmatter.js +302 -0
- package/plugins/pbr/scripts/lib/gates/advisories.js +129 -0
- package/plugins/pbr/scripts/lib/gates/build-dependency.js +115 -0
- package/plugins/pbr/scripts/lib/gates/build-executor.js +104 -0
- package/plugins/pbr/scripts/lib/gates/doc-existence.js +46 -0
- package/plugins/pbr/scripts/lib/gates/helpers.js +93 -0
- package/plugins/pbr/scripts/lib/gates/inline-execution.js +185 -0
- package/plugins/pbr/scripts/lib/gates/milestone-complete.js +136 -0
- package/plugins/pbr/scripts/lib/gates/milestone-summary.js +119 -0
- package/plugins/pbr/scripts/lib/gates/multi-phase-loader.js +147 -0
- package/plugins/pbr/scripts/lib/gates/plan-executor.js +36 -0
- package/plugins/pbr/scripts/lib/gates/plan-validation.js +114 -0
- package/plugins/pbr/scripts/lib/gates/quick-executor.js +76 -0
- package/plugins/pbr/scripts/lib/gates/review-planner.js +61 -0
- package/plugins/pbr/scripts/lib/gates/review-verifier.js +69 -0
- package/plugins/pbr/scripts/lib/gates/rich-agent-context.js +143 -0
- package/plugins/pbr/scripts/lib/gates/user-confirmation.js +93 -0
- package/plugins/pbr/scripts/lib/graph-cli.js +89 -0
- package/plugins/pbr/scripts/lib/graph.js +553 -0
- package/plugins/pbr/scripts/lib/health-checks.js +107 -0
- package/plugins/pbr/scripts/lib/health-phase06.js +120 -0
- package/plugins/pbr/scripts/lib/health.js +133 -0
- package/plugins/pbr/scripts/lib/help.js +151 -0
- package/plugins/pbr/scripts/lib/history.js +150 -0
- package/plugins/pbr/scripts/lib/hypothesis-runner.js +127 -0
- package/plugins/pbr/scripts/lib/impact-analysis.js +319 -0
- package/plugins/pbr/scripts/lib/incidents.js +190 -0
- package/plugins/pbr/scripts/lib/init.js +643 -0
- package/plugins/pbr/scripts/lib/insights-parser.js +320 -0
- package/plugins/pbr/scripts/lib/intel.js +653 -0
- package/plugins/pbr/scripts/lib/learnings.js +511 -0
- package/plugins/pbr/scripts/lib/local-llm/client.js +237 -0
- package/plugins/pbr/scripts/lib/local-llm/health.js +12 -0
- package/plugins/pbr/scripts/lib/local-llm/index.js +89 -0
- package/plugins/pbr/scripts/lib/local-llm/metrics.js +20 -0
- package/plugins/pbr/scripts/lib/local-llm/operations/classify-artifact.js +4 -0
- package/plugins/pbr/scripts/lib/local-llm/operations/classify-commit.js +4 -0
- package/plugins/pbr/scripts/lib/local-llm/operations/classify-error.js +4 -0
- package/plugins/pbr/scripts/lib/local-llm/operations/classify-file-intent.js +4 -0
- package/plugins/pbr/scripts/lib/local-llm/operations/score-source.js +72 -0
- package/plugins/pbr/scripts/lib/local-llm/operations/summarize-context.js +62 -0
- package/plugins/pbr/scripts/lib/local-llm/operations/triage-test-output.js +12 -0
- package/plugins/pbr/scripts/lib/local-llm/operations/validate-task.js +4 -0
- package/plugins/pbr/scripts/lib/local-llm/router.js +101 -0
- package/plugins/pbr/scripts/lib/local-llm/shadow.js +60 -0
- package/plugins/pbr/scripts/lib/local-llm/threshold-tuner.js +118 -0
- package/plugins/pbr/scripts/lib/migrate.js +298 -0
- package/plugins/pbr/scripts/lib/milestone.js +306 -0
- package/plugins/pbr/scripts/lib/negative-knowledge.js +194 -0
- package/plugins/pbr/scripts/lib/notification-throttle.js +141 -0
- package/plugins/pbr/scripts/lib/onboarding-generator.js +288 -0
- package/plugins/pbr/scripts/lib/parse-args.js +134 -0
- package/plugins/pbr/scripts/lib/pattern-routing.js +55 -0
- package/plugins/pbr/scripts/lib/patterns.js +272 -0
- package/plugins/pbr/scripts/lib/perf.js +190 -0
- package/plugins/pbr/scripts/lib/phase.js +1027 -0
- package/plugins/pbr/scripts/lib/pid-lock.js +154 -0
- package/plugins/pbr/scripts/lib/post-hoc.js +160 -0
- package/plugins/pbr/scripts/lib/pre-commit-checks.js +220 -0
- package/plugins/pbr/scripts/lib/pre-research.js +133 -0
- package/plugins/pbr/scripts/lib/preview.js +174 -0
- package/plugins/pbr/scripts/lib/progress-visualization.js +296 -0
- package/plugins/pbr/scripts/lib/quick-init.js +131 -0
- package/plugins/pbr/scripts/lib/reference.js +236 -0
- package/plugins/pbr/scripts/lib/requirements.js +153 -0
- package/plugins/pbr/scripts/lib/resolve-root.js +66 -0
- package/plugins/pbr/scripts/lib/reverse-spec.js +259 -0
- package/plugins/pbr/scripts/lib/roadmap.js +1113 -0
- package/plugins/pbr/scripts/lib/security-scan.js +200 -0
- package/plugins/pbr/scripts/lib/session-briefing.js +895 -0
- package/plugins/pbr/scripts/lib/skill-section.js +99 -0
- package/plugins/pbr/scripts/lib/smart-next-task.js +207 -0
- package/plugins/pbr/scripts/lib/snapshot-manager.js +232 -0
- package/plugins/pbr/scripts/lib/spec-diff.js +209 -0
- package/plugins/pbr/scripts/lib/spec-engine.js +189 -0
- package/plugins/pbr/scripts/lib/spot-check.js +642 -0
- package/plugins/pbr/scripts/lib/state-queue.js +171 -0
- package/plugins/pbr/scripts/lib/state.js +1187 -0
- package/plugins/pbr/scripts/lib/status-render.js +511 -0
- package/plugins/pbr/scripts/lib/step-verify.js +149 -0
- package/plugins/pbr/scripts/lib/subagent-validators.js +1059 -0
- package/plugins/pbr/scripts/lib/suggest-next.js +435 -0
- package/plugins/pbr/scripts/lib/team-composer.js +87 -0
- package/plugins/pbr/scripts/lib/team-coordinator.js +153 -0
- package/plugins/pbr/scripts/lib/tech-debt-scanner.js +116 -0
- package/plugins/pbr/scripts/lib/template.js +222 -0
- package/plugins/pbr/scripts/lib/templates.js +362 -0
- package/plugins/pbr/scripts/lib/test-cache.js +54 -0
- package/plugins/pbr/scripts/lib/test-selection.js +163 -0
- package/plugins/pbr/scripts/lib/todo.js +300 -0
- package/plugins/pbr/scripts/lib/trust-gate.js +84 -0
- package/plugins/pbr/scripts/lib/verify.js +1473 -0
- package/plugins/pbr/scripts/lib/wiring-check.js +196 -0
- package/plugins/pbr/scripts/log-notification.js +131 -0
- package/plugins/pbr/scripts/log-subagent.js +203 -18
- package/plugins/pbr/scripts/log-tool-failure.js +60 -8
- package/plugins/pbr/scripts/milestone-learnings.js +569 -0
- package/plugins/pbr/scripts/package.json +1 -0
- package/plugins/pbr/scripts/pbr-tools.js +1833 -1167
- package/plugins/pbr/scripts/post-bash-triage.js +154 -0
- package/plugins/pbr/scripts/post-compact.js +135 -0
- package/plugins/pbr/scripts/post-hoc.js +286 -0
- package/plugins/pbr/scripts/post-write-dispatch.js +237 -31
- package/plugins/pbr/scripts/post-write-quality.js +4 -3
- package/plugins/pbr/scripts/pre-bash-dispatch.js +155 -23
- package/plugins/pbr/scripts/pre-skill-dispatch.js +114 -0
- package/plugins/pbr/scripts/pre-task-dispatch.js +297 -0
- package/plugins/pbr/scripts/pre-write-dispatch.js +171 -47
- package/plugins/pbr/scripts/progress-tracker.js +144 -307
- package/plugins/pbr/scripts/prompt-guard.js +114 -0
- package/plugins/pbr/scripts/prompt-routing.js +209 -0
- package/plugins/pbr/scripts/quick-status.js +179 -0
- package/plugins/pbr/scripts/record-incident.js +37 -0
- package/plugins/pbr/scripts/risk-classifier.cjs +123 -0
- package/plugins/pbr/scripts/run-hook.js +62 -10
- package/plugins/pbr/scripts/session-cleanup.js +458 -29
- package/plugins/pbr/scripts/session-tracker.js +124 -0
- package/plugins/pbr/scripts/status-line.js +591 -32
- package/plugins/pbr/scripts/suggest-compact.js +203 -7
- package/plugins/pbr/scripts/sync-context-to-claude.js +100 -0
- package/plugins/pbr/scripts/task-completed.js +165 -4
- package/plugins/pbr/scripts/test/config.test.js +126 -0
- package/plugins/pbr/scripts/test/cross-platform.test.js +131 -0
- package/plugins/pbr/scripts/test/fixtures/config.json +20 -0
- package/plugins/pbr/scripts/test/fixtures/plan.md +54 -0
- package/plugins/pbr/scripts/test/fixtures/project.md +30 -0
- package/plugins/pbr/scripts/test/fixtures/roadmap.md +55 -0
- package/plugins/pbr/scripts/test/fixtures/state.md +60 -0
- package/plugins/pbr/scripts/test/fixtures/summary.md +35 -0
- package/plugins/pbr/scripts/test/fixtures.test.js +184 -0
- package/plugins/pbr/scripts/test/phase.test.js +142 -0
- package/plugins/pbr/scripts/test/roadmap.test.js +96 -0
- package/plugins/pbr/scripts/test/state.test.js +163 -0
- package/plugins/pbr/scripts/track-context-budget.js +368 -99
- package/plugins/pbr/scripts/track-user-gates.js +88 -0
- package/plugins/pbr/scripts/trust-tracker.js +193 -0
- package/plugins/pbr/scripts/validate-commit.js +97 -26
- package/plugins/pbr/scripts/validate-skill-args.js +87 -15
- package/plugins/pbr/scripts/validate-task.js +112 -626
- package/plugins/pbr/scripts/worktree-create.js +144 -0
- package/plugins/pbr/scripts/worktree-remove.js +147 -0
- package/plugins/pbr/skills/audit/SKILL.md +195 -24
- package/plugins/pbr/skills/audit-fix/SKILL.md +326 -0
- package/plugins/pbr/skills/autonomous/SKILL.md +545 -0
- package/plugins/pbr/skills/backlog/SKILL.md +56 -0
- package/plugins/pbr/skills/begin/SKILL.md +507 -153
- package/plugins/pbr/skills/begin/templates/STATE.md.tmpl +1 -2
- package/plugins/pbr/skills/begin/templates/config.json.tmpl +415 -36
- package/plugins/pbr/skills/begin/templates/researcher-prompt.md.tmpl +28 -0
- package/plugins/pbr/skills/begin/templates/roadmap-prompt.md.tmpl +28 -3
- package/plugins/pbr/skills/begin/templates/synthesis-prompt.md.tmpl +33 -5
- package/plugins/pbr/skills/build/SKILL.md +1040 -354
- package/plugins/pbr/skills/build/templates/continuation-prompt.md.tmpl +26 -0
- package/plugins/pbr/skills/build/templates/executor-prompt.md.tmpl +77 -0
- package/plugins/pbr/skills/build/templates/inline-verifier-prompt.md.tmpl +33 -0
- package/plugins/pbr/skills/config/SKILL.md +111 -9
- package/plugins/pbr/skills/continue/SKILL.md +113 -33
- package/plugins/pbr/skills/dashboard/SKILL.md +21 -9
- package/plugins/pbr/skills/debug/SKILL.md +70 -12
- package/plugins/pbr/skills/debug/templates/continuation-prompt.md.tmpl +12 -1
- package/plugins/pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +12 -5
- package/plugins/pbr/skills/discuss/SKILL.md +206 -25
- package/plugins/pbr/skills/discuss/templates/CONTEXT.md.tmpl +21 -1
- package/plugins/pbr/skills/do/SKILL.md +119 -24
- package/plugins/pbr/skills/explore/SKILL.md +95 -20
- package/plugins/pbr/skills/fast/SKILL.md +94 -0
- package/plugins/pbr/skills/forensics/SKILL.md +144 -0
- package/plugins/pbr/skills/health/SKILL.md +44 -117
- package/plugins/pbr/skills/help/SKILL.md +83 -101
- package/plugins/pbr/skills/import/SKILL.md +332 -13
- package/plugins/pbr/skills/intel/SKILL.md +131 -0
- package/plugins/pbr/skills/list-phase-assumptions/SKILL.md +231 -0
- package/plugins/pbr/skills/milestone/SKILL.md +421 -263
- package/plugins/pbr/skills/milestone/templates/audit-output.md.tmpl +76 -0
- package/plugins/pbr/skills/milestone/templates/complete-output.md.tmpl +32 -0
- package/plugins/pbr/skills/milestone/templates/edge-cases.md +54 -0
- package/plugins/pbr/skills/milestone/templates/gaps-output.md.tmpl +25 -0
- package/plugins/pbr/skills/milestone/templates/integration-checker-prompt.md.tmpl +25 -0
- package/plugins/pbr/skills/milestone/templates/new-output.md.tmpl +29 -0
- package/plugins/pbr/skills/milestone-summary/SKILL.md +86 -0
- package/plugins/pbr/skills/note/SKILL.md +20 -4
- package/plugins/pbr/skills/pause/SKILL.md +53 -14
- package/plugins/pbr/skills/pause/templates/continue-here.md.tmpl +33 -52
- package/plugins/pbr/skills/plan/SKILL.md +526 -280
- package/plugins/pbr/skills/plan/templates/checker-prompt.md.tmpl +5 -2
- package/plugins/pbr/skills/plan/templates/completion-output.md.tmpl +27 -0
- package/plugins/pbr/skills/plan/templates/planner-prompt.md.tmpl +27 -1
- package/plugins/pbr/skills/plan/templates/revision-prompt.md.tmpl +21 -5
- package/plugins/pbr/skills/profile/SKILL.md +185 -0
- package/plugins/pbr/skills/profile-user/SKILL.md +226 -0
- package/plugins/pbr/skills/quick/SKILL.md +434 -100
- package/plugins/pbr/skills/release/SKILL.md +206 -0
- package/plugins/pbr/skills/resume/SKILL.md +169 -46
- package/plugins/pbr/skills/review/SKILL.md +217 -164
- package/plugins/pbr/skills/review/templates/verifier-prompt.md.tmpl +7 -0
- package/plugins/pbr/skills/scan/SKILL.md +151 -106
- package/plugins/pbr/skills/scan/templates/mapper-prompt.md.tmpl +5 -56
- package/plugins/pbr/skills/seed/SKILL.md +87 -0
- package/plugins/pbr/skills/session-report/SKILL.md +130 -0
- package/plugins/pbr/skills/setup/SKILL.md +149 -202
- package/plugins/pbr/skills/shared/agent-context-enrichment.md +21 -0
- package/plugins/pbr/skills/shared/agent-type-resolution.md +32 -0
- package/plugins/pbr/skills/shared/commit-planning-docs.md +8 -0
- package/plugins/pbr/skills/shared/context-budget.md +66 -1
- package/plugins/pbr/skills/shared/context-loader-task.md +18 -11
- package/plugins/pbr/skills/shared/digest-select.md +2 -2
- package/plugins/pbr/skills/shared/domain-probes.md +1 -1
- package/plugins/pbr/skills/shared/error-reporting.md +38 -60
- package/plugins/pbr/skills/shared/gate-prompts.md +4 -2
- package/plugins/pbr/skills/shared/memory-capture.md +48 -0
- package/plugins/pbr/skills/shared/phase-argument-parsing.md +4 -4
- package/plugins/pbr/skills/shared/revision-loop.md +24 -6
- package/plugins/pbr/skills/shared/state-update.md +47 -54
- package/plugins/pbr/skills/shared/universal-anti-patterns.md +27 -4
- package/plugins/pbr/skills/ship/SKILL.md +155 -0
- package/plugins/pbr/skills/stats/SKILL.md +80 -0
- package/plugins/pbr/skills/status/SKILL.md +184 -119
- package/plugins/pbr/skills/test/SKILL.md +254 -0
- package/plugins/pbr/skills/thread/SKILL.md +73 -0
- package/plugins/pbr/skills/todo/SKILL.md +28 -72
- package/plugins/pbr/skills/ui-phase/SKILL.md +180 -0
- package/plugins/pbr/skills/ui-review/SKILL.md +206 -0
- package/plugins/pbr/skills/undo/SKILL.md +221 -0
- package/plugins/pbr/skills/validate-phase/SKILL.md +362 -0
- package/plugins/pbr/templates/CONTEXT.md.tmpl +45 -20
- package/plugins/pbr/templates/DISCOVERY.md.tmpl +29 -0
- package/plugins/pbr/templates/DISCUSSION-LOG.md.tmpl +49 -0
- package/plugins/pbr/templates/HANDOFF.json.tmpl +30 -0
- package/plugins/pbr/templates/INTEGRATION-REPORT.md.tmpl +18 -2
- package/plugins/pbr/templates/MILESTONE-AUDIT.md.tmpl +44 -0
- package/plugins/pbr/templates/PROJECT.md.tmpl +126 -0
- package/plugins/pbr/templates/REQUIREMENTS.md.tmpl +96 -0
- package/plugins/pbr/templates/RETROSPECTIVE.md.tmpl +43 -0
- package/plugins/pbr/templates/ROADMAP.md.tmpl +108 -14
- package/plugins/pbr/templates/SUMMARY-complex.md.tmpl +133 -0
- package/plugins/pbr/templates/SUMMARY-minimal.md.tmpl +55 -0
- package/plugins/pbr/templates/SUMMARY.md.tmpl +21 -0
- package/plugins/pbr/templates/UAT.md.tmpl +94 -0
- package/plugins/pbr/templates/UI-SPEC.md.tmpl +144 -0
- package/plugins/pbr/templates/VALIDATION.md.tmpl +94 -0
- package/plugins/pbr/templates/VERIFICATION-DETAIL.md.tmpl +49 -13
- package/plugins/pbr/templates/project-CONTEXT.md.tmpl +59 -0
- package/plugins/pbr/templates/research-outputs/ARCHITECTURE.md.tmpl +91 -0
- package/plugins/pbr/templates/research-outputs/FEATURES.md.tmpl +64 -0
- package/plugins/pbr/templates/research-outputs/PITFALLS.md.tmpl +50 -0
- package/plugins/pbr/templates/research-outputs/STACK.md.tmpl +63 -0
- package/plugins/pbr/templates/research-outputs/SUMMARY.md.tmpl +98 -0
- package/scripts/build-hooks.js +61 -0
- package/scripts/check-ci.js +100 -0
- package/scripts/clean-changelog.js +364 -0
- package/scripts/generate-derivatives.js +581 -0
- package/scripts/posttest.js +93 -0
- package/scripts/release.js +262 -0
- package/scripts/run-tests.cjs +29 -0
- package/scripts/test-wrapper.js +43 -0
- package/dashboard/bin/cli.js +0 -25
- package/dashboard/public/css/layout.css +0 -636
- package/dashboard/public/css/status-colors.css +0 -98
- package/dashboard/public/css/tokens.css +0 -59
- package/dashboard/public/js/htmx-title.js +0 -5
- package/dashboard/public/js/sidebar-toggle.js +0 -34
- package/dashboard/public/js/sse-client.js +0 -100
- package/dashboard/public/js/theme-toggle.js +0 -46
- package/dashboard/src/app.js +0 -91
- package/dashboard/src/middleware/current-phase.js +0 -24
- package/dashboard/src/middleware/errorHandler.js +0 -52
- package/dashboard/src/middleware/notFoundHandler.js +0 -9
- package/dashboard/src/repositories/planning.repository.js +0 -130
- package/dashboard/src/routes/events.routes.js +0 -45
- package/dashboard/src/routes/index.routes.js +0 -35
- package/dashboard/src/routes/pages.routes.js +0 -426
- package/dashboard/src/server.js +0 -42
- package/dashboard/src/services/analytics.service.js +0 -141
- package/dashboard/src/services/dashboard.service.js +0 -309
- package/dashboard/src/services/milestone.service.js +0 -222
- package/dashboard/src/services/notes.service.js +0 -50
- package/dashboard/src/services/phase.service.js +0 -232
- package/dashboard/src/services/project.service.js +0 -57
- package/dashboard/src/services/roadmap.service.js +0 -244
- package/dashboard/src/services/sse.service.js +0 -58
- package/dashboard/src/services/todo.service.js +0 -263
- package/dashboard/src/services/watcher.service.js +0 -48
- package/dashboard/src/utils/cache.js +0 -55
- package/dashboard/src/views/analytics.ejs +0 -5
- package/dashboard/src/views/coming-soon.ejs +0 -11
- package/dashboard/src/views/dependencies.ejs +0 -5
- package/dashboard/src/views/error.ejs +0 -20
- package/dashboard/src/views/index.ejs +0 -5
- package/dashboard/src/views/milestone-detail.ejs +0 -5
- package/dashboard/src/views/milestones.ejs +0 -5
- package/dashboard/src/views/notes.ejs +0 -5
- package/dashboard/src/views/partials/analytics-content.ejs +0 -90
- package/dashboard/src/views/partials/breadcrumbs.ejs +0 -14
- package/dashboard/src/views/partials/dashboard-content.ejs +0 -84
- package/dashboard/src/views/partials/dependencies-content.ejs +0 -48
- package/dashboard/src/views/partials/empty-state.ejs +0 -7
- package/dashboard/src/views/partials/footer.ejs +0 -3
- package/dashboard/src/views/partials/head.ejs +0 -30
- package/dashboard/src/views/partials/header.ejs +0 -21
- package/dashboard/src/views/partials/layout-bottom.ejs +0 -6
- package/dashboard/src/views/partials/layout-top.ejs +0 -15
- package/dashboard/src/views/partials/milestone-detail-content.ejs +0 -20
- package/dashboard/src/views/partials/milestones-content.ejs +0 -88
- package/dashboard/src/views/partials/notes-content.ejs +0 -23
- package/dashboard/src/views/partials/phase-content.ejs +0 -193
- package/dashboard/src/views/partials/phase-doc-content.ejs +0 -38
- package/dashboard/src/views/partials/phases-content.ejs +0 -124
- package/dashboard/src/views/partials/roadmap-content.ejs +0 -155
- package/dashboard/src/views/partials/sidebar.ejs +0 -99
- package/dashboard/src/views/partials/todo-create-content.ejs +0 -54
- package/dashboard/src/views/partials/todo-detail-content.ejs +0 -42
- package/dashboard/src/views/partials/todos-content.ejs +0 -94
- package/dashboard/src/views/phase-detail.ejs +0 -5
- package/dashboard/src/views/phase-doc.ejs +0 -5
- package/dashboard/src/views/phases.ejs +0 -5
- package/dashboard/src/views/roadmap.ejs +0 -5
- package/dashboard/src/views/todo-create.ejs +0 -5
- package/dashboard/src/views/todo-detail.ejs +0 -5
- package/dashboard/src/views/todos.ejs +0 -5
- package/plugins/copilot-pbr/CHANGELOG.md +0 -19
- package/plugins/copilot-pbr/README.md +0 -139
- package/plugins/copilot-pbr/agents/audit.agent.md +0 -113
- package/plugins/copilot-pbr/agents/codebase-mapper.agent.md +0 -151
- package/plugins/copilot-pbr/agents/debugger.agent.md +0 -172
- package/plugins/copilot-pbr/agents/executor.agent.md +0 -267
- package/plugins/copilot-pbr/agents/general.agent.md +0 -88
- package/plugins/copilot-pbr/agents/integration-checker.agent.md +0 -119
- package/plugins/copilot-pbr/agents/plan-checker.agent.md +0 -199
- package/plugins/copilot-pbr/agents/planner.agent.md +0 -238
- package/plugins/copilot-pbr/agents/researcher.agent.md +0 -186
- package/plugins/copilot-pbr/agents/synthesizer.agent.md +0 -126
- package/plugins/copilot-pbr/agents/verifier.agent.md +0 -228
- package/plugins/copilot-pbr/hooks/hooks.json +0 -156
- package/plugins/copilot-pbr/plugin.json +0 -30
- package/plugins/copilot-pbr/references/agent-anti-patterns.md +0 -25
- package/plugins/copilot-pbr/references/agent-contracts.md +0 -297
- package/plugins/copilot-pbr/references/agent-interactions.md +0 -135
- package/plugins/copilot-pbr/references/agent-teams.md +0 -55
- package/plugins/copilot-pbr/references/checkpoints.md +0 -158
- package/plugins/copilot-pbr/references/common-bug-patterns.md +0 -14
- package/plugins/copilot-pbr/references/config-reference.md +0 -442
- package/plugins/copilot-pbr/references/continuation-format.md +0 -213
- package/plugins/copilot-pbr/references/deviation-rules.md +0 -113
- package/plugins/copilot-pbr/references/git-integration.md +0 -227
- package/plugins/copilot-pbr/references/integration-patterns.md +0 -118
- package/plugins/copilot-pbr/references/model-profiles.md +0 -100
- package/plugins/copilot-pbr/references/model-selection.md +0 -32
- package/plugins/copilot-pbr/references/pbr-rules.md +0 -195
- package/plugins/copilot-pbr/references/pbr-tools-cli.md +0 -285
- package/plugins/copilot-pbr/references/plan-authoring.md +0 -182
- package/plugins/copilot-pbr/references/plan-format.md +0 -288
- package/plugins/copilot-pbr/references/planning-config.md +0 -214
- package/plugins/copilot-pbr/references/questioning.md +0 -215
- package/plugins/copilot-pbr/references/reading-verification.md +0 -128
- package/plugins/copilot-pbr/references/stub-patterns.md +0 -161
- package/plugins/copilot-pbr/references/subagent-coordination.md +0 -120
- package/plugins/copilot-pbr/references/ui-formatting.md +0 -444
- package/plugins/copilot-pbr/references/verification-patterns.md +0 -199
- package/plugins/copilot-pbr/references/wave-execution.md +0 -96
- package/plugins/copilot-pbr/rules/pbr-workflow.mdc +0 -48
- package/plugins/copilot-pbr/setup.ps1 +0 -93
- package/plugins/copilot-pbr/setup.sh +0 -93
- package/plugins/copilot-pbr/skills/audit/SKILL.md +0 -330
- package/plugins/copilot-pbr/skills/begin/SKILL.md +0 -589
- package/plugins/copilot-pbr/skills/begin/templates/PROJECT.md.tmpl +0 -34
- package/plugins/copilot-pbr/skills/begin/templates/REQUIREMENTS.md.tmpl +0 -19
- package/plugins/copilot-pbr/skills/begin/templates/STATE.md.tmpl +0 -50
- package/plugins/copilot-pbr/skills/begin/templates/config.json.tmpl +0 -64
- package/plugins/copilot-pbr/skills/begin/templates/researcher-prompt.md.tmpl +0 -20
- package/plugins/copilot-pbr/skills/begin/templates/roadmap-prompt.md.tmpl +0 -31
- package/plugins/copilot-pbr/skills/begin/templates/synthesis-prompt.md.tmpl +0 -17
- package/plugins/copilot-pbr/skills/build/SKILL.md +0 -960
- package/plugins/copilot-pbr/skills/config/SKILL.md +0 -250
- package/plugins/copilot-pbr/skills/continue/SKILL.md +0 -159
- package/plugins/copilot-pbr/skills/dashboard/SKILL.md +0 -43
- package/plugins/copilot-pbr/skills/debug/SKILL.md +0 -508
- package/plugins/copilot-pbr/skills/debug/templates/continuation-prompt.md.tmpl +0 -17
- package/plugins/copilot-pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +0 -28
- package/plugins/copilot-pbr/skills/discuss/SKILL.md +0 -353
- package/plugins/copilot-pbr/skills/discuss/templates/CONTEXT.md.tmpl +0 -62
- package/plugins/copilot-pbr/skills/discuss/templates/decision-categories.md +0 -10
- package/plugins/copilot-pbr/skills/do/SKILL.md +0 -66
- package/plugins/copilot-pbr/skills/explore/SKILL.md +0 -373
- package/plugins/copilot-pbr/skills/health/SKILL.md +0 -274
- package/plugins/copilot-pbr/skills/health/templates/check-pattern.md.tmpl +0 -31
- package/plugins/copilot-pbr/skills/health/templates/output-format.md.tmpl +0 -64
- package/plugins/copilot-pbr/skills/help/SKILL.md +0 -170
- package/plugins/copilot-pbr/skills/import/SKILL.md +0 -502
- package/plugins/copilot-pbr/skills/milestone/SKILL.md +0 -745
- package/plugins/copilot-pbr/skills/milestone/templates/audit-report.md.tmpl +0 -49
- package/plugins/copilot-pbr/skills/milestone/templates/stats-file.md.tmpl +0 -31
- package/plugins/copilot-pbr/skills/note/SKILL.md +0 -213
- package/plugins/copilot-pbr/skills/pause/SKILL.md +0 -247
- package/plugins/copilot-pbr/skills/pause/templates/continue-here.md.tmpl +0 -72
- package/plugins/copilot-pbr/skills/plan/SKILL.md +0 -662
- package/plugins/copilot-pbr/skills/plan/templates/checker-prompt.md.tmpl +0 -22
- package/plugins/copilot-pbr/skills/plan/templates/gap-closure-prompt.md.tmpl +0 -33
- package/plugins/copilot-pbr/skills/plan/templates/planner-prompt.md.tmpl +0 -39
- package/plugins/copilot-pbr/skills/plan/templates/researcher-prompt.md.tmpl +0 -20
- package/plugins/copilot-pbr/skills/plan/templates/revision-prompt.md.tmpl +0 -24
- package/plugins/copilot-pbr/skills/quick/SKILL.md +0 -376
- package/plugins/copilot-pbr/skills/resume/SKILL.md +0 -399
- package/plugins/copilot-pbr/skills/review/SKILL.md +0 -653
- package/plugins/copilot-pbr/skills/review/templates/debugger-prompt.md.tmpl +0 -61
- package/plugins/copilot-pbr/skills/review/templates/gap-planner-prompt.md.tmpl +0 -41
- package/plugins/copilot-pbr/skills/review/templates/verifier-prompt.md.tmpl +0 -116
- package/plugins/copilot-pbr/skills/scan/SKILL.md +0 -299
- package/plugins/copilot-pbr/skills/scan/templates/mapper-prompt.md.tmpl +0 -202
- package/plugins/copilot-pbr/skills/setup/SKILL.md +0 -296
- package/plugins/copilot-pbr/skills/shared/commit-planning-docs.md +0 -36
- package/plugins/copilot-pbr/skills/shared/config-loading.md +0 -103
- package/plugins/copilot-pbr/skills/shared/context-budget.md +0 -41
- package/plugins/copilot-pbr/skills/shared/context-loader-task.md +0 -87
- package/plugins/copilot-pbr/skills/shared/digest-select.md +0 -80
- package/plugins/copilot-pbr/skills/shared/domain-probes.md +0 -126
- package/plugins/copilot-pbr/skills/shared/error-reporting.md +0 -81
- package/plugins/copilot-pbr/skills/shared/gate-prompts.md +0 -389
- package/plugins/copilot-pbr/skills/shared/phase-argument-parsing.md +0 -46
- package/plugins/copilot-pbr/skills/shared/progress-display.md +0 -53
- package/plugins/copilot-pbr/skills/shared/revision-loop.md +0 -82
- package/plugins/copilot-pbr/skills/shared/state-loading.md +0 -63
- package/plugins/copilot-pbr/skills/shared/state-update.md +0 -162
- package/plugins/copilot-pbr/skills/shared/universal-anti-patterns.md +0 -38
- package/plugins/copilot-pbr/skills/status/SKILL.md +0 -362
- package/plugins/copilot-pbr/skills/statusline/SKILL.md +0 -149
- package/plugins/copilot-pbr/skills/todo/SKILL.md +0 -279
- package/plugins/copilot-pbr/templates/CONTEXT.md.tmpl +0 -53
- package/plugins/copilot-pbr/templates/INTEGRATION-REPORT.md.tmpl +0 -152
- package/plugins/copilot-pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -98
- package/plugins/copilot-pbr/templates/ROADMAP.md.tmpl +0 -41
- package/plugins/copilot-pbr/templates/SUMMARY.md.tmpl +0 -82
- package/plugins/copilot-pbr/templates/VERIFICATION-DETAIL.md.tmpl +0 -117
- package/plugins/copilot-pbr/templates/codebase/ARCHITECTURE.md.tmpl +0 -98
- package/plugins/copilot-pbr/templates/codebase/CONCERNS.md.tmpl +0 -93
- package/plugins/copilot-pbr/templates/codebase/CONVENTIONS.md.tmpl +0 -104
- package/plugins/copilot-pbr/templates/codebase/INTEGRATIONS.md.tmpl +0 -78
- package/plugins/copilot-pbr/templates/codebase/STACK.md.tmpl +0 -78
- package/plugins/copilot-pbr/templates/codebase/STRUCTURE.md.tmpl +0 -80
- package/plugins/copilot-pbr/templates/codebase/TESTING.md.tmpl +0 -107
- package/plugins/copilot-pbr/templates/continue-here.md.tmpl +0 -74
- package/plugins/copilot-pbr/templates/prompt-partials/phase-project-context.md.tmpl +0 -38
- package/plugins/copilot-pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
- package/plugins/copilot-pbr/templates/research/STACK.md.tmpl +0 -71
- package/plugins/copilot-pbr/templates/research/SUMMARY.md.tmpl +0 -112
- package/plugins/copilot-pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
- package/plugins/copilot-pbr/templates/research-outputs/project-research.md.tmpl +0 -99
- package/plugins/copilot-pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
- package/plugins/cursor-pbr/.cursor-plugin/plugin.json +0 -32
- package/plugins/cursor-pbr/CHANGELOG.md +0 -15
- package/plugins/cursor-pbr/README.md +0 -123
- package/plugins/cursor-pbr/agents/audit.md +0 -178
- package/plugins/cursor-pbr/agents/codebase-mapper.md +0 -150
- package/plugins/cursor-pbr/agents/debugger.md +0 -171
- package/plugins/cursor-pbr/agents/executor.md +0 -266
- package/plugins/cursor-pbr/agents/general.md +0 -87
- package/plugins/cursor-pbr/agents/integration-checker.md +0 -118
- package/plugins/cursor-pbr/agents/plan-checker.md +0 -198
- package/plugins/cursor-pbr/agents/planner.md +0 -237
- package/plugins/cursor-pbr/agents/researcher.md +0 -185
- package/plugins/cursor-pbr/agents/synthesizer.md +0 -125
- package/plugins/cursor-pbr/agents/verifier.md +0 -227
- package/plugins/cursor-pbr/assets/.gitkeep +0 -0
- package/plugins/cursor-pbr/assets/logo.svg +0 -21
- package/plugins/cursor-pbr/hooks/hooks.json +0 -213
- package/plugins/cursor-pbr/references/agent-anti-patterns.md +0 -25
- package/plugins/cursor-pbr/references/agent-contracts.md +0 -297
- package/plugins/cursor-pbr/references/agent-interactions.md +0 -135
- package/plugins/cursor-pbr/references/agent-teams.md +0 -55
- package/plugins/cursor-pbr/references/checkpoints.md +0 -158
- package/plugins/cursor-pbr/references/common-bug-patterns.md +0 -14
- package/plugins/cursor-pbr/references/config-reference.md +0 -442
- package/plugins/cursor-pbr/references/continuation-format.md +0 -213
- package/plugins/cursor-pbr/references/deviation-rules.md +0 -113
- package/plugins/cursor-pbr/references/git-integration.md +0 -227
- package/plugins/cursor-pbr/references/integration-patterns.md +0 -118
- package/plugins/cursor-pbr/references/model-profiles.md +0 -100
- package/plugins/cursor-pbr/references/model-selection.md +0 -32
- package/plugins/cursor-pbr/references/pbr-rules.md +0 -195
- package/plugins/cursor-pbr/references/pbr-tools-cli.md +0 -285
- package/plugins/cursor-pbr/references/plan-authoring.md +0 -182
- package/plugins/cursor-pbr/references/plan-format.md +0 -288
- package/plugins/cursor-pbr/references/planning-config.md +0 -214
- package/plugins/cursor-pbr/references/questioning.md +0 -215
- package/plugins/cursor-pbr/references/reading-verification.md +0 -128
- package/plugins/cursor-pbr/references/stub-patterns.md +0 -161
- package/plugins/cursor-pbr/references/subagent-coordination.md +0 -120
- package/plugins/cursor-pbr/references/ui-formatting.md +0 -444
- package/plugins/cursor-pbr/references/verification-patterns.md +0 -199
- package/plugins/cursor-pbr/references/wave-execution.md +0 -96
- package/plugins/cursor-pbr/rules/pbr-workflow.mdc +0 -48
- package/plugins/cursor-pbr/setup.ps1 +0 -78
- package/plugins/cursor-pbr/setup.sh +0 -83
- package/plugins/cursor-pbr/skills/audit/SKILL.md +0 -331
- package/plugins/cursor-pbr/skills/begin/SKILL.md +0 -589
- package/plugins/cursor-pbr/skills/begin/templates/PROJECT.md.tmpl +0 -34
- package/plugins/cursor-pbr/skills/begin/templates/REQUIREMENTS.md.tmpl +0 -19
- package/plugins/cursor-pbr/skills/begin/templates/STATE.md.tmpl +0 -50
- package/plugins/cursor-pbr/skills/begin/templates/config.json.tmpl +0 -64
- package/plugins/cursor-pbr/skills/begin/templates/researcher-prompt.md.tmpl +0 -20
- package/plugins/cursor-pbr/skills/begin/templates/roadmap-prompt.md.tmpl +0 -31
- package/plugins/cursor-pbr/skills/begin/templates/synthesis-prompt.md.tmpl +0 -17
- package/plugins/cursor-pbr/skills/build/SKILL.md +0 -961
- package/plugins/cursor-pbr/skills/config/SKILL.md +0 -252
- package/plugins/cursor-pbr/skills/continue/SKILL.md +0 -159
- package/plugins/cursor-pbr/skills/dashboard/SKILL.md +0 -44
- package/plugins/cursor-pbr/skills/debug/SKILL.md +0 -512
- package/plugins/cursor-pbr/skills/debug/templates/continuation-prompt.md.tmpl +0 -17
- package/plugins/cursor-pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +0 -28
- package/plugins/cursor-pbr/skills/discuss/SKILL.md +0 -354
- package/plugins/cursor-pbr/skills/discuss/templates/CONTEXT.md.tmpl +0 -62
- package/plugins/cursor-pbr/skills/discuss/templates/decision-categories.md +0 -10
- package/plugins/cursor-pbr/skills/do/SKILL.md +0 -67
- package/plugins/cursor-pbr/skills/explore/SKILL.md +0 -376
- package/plugins/cursor-pbr/skills/health/SKILL.md +0 -274
- package/plugins/cursor-pbr/skills/health/templates/check-pattern.md.tmpl +0 -31
- package/plugins/cursor-pbr/skills/health/templates/output-format.md.tmpl +0 -64
- package/plugins/cursor-pbr/skills/help/SKILL.md +0 -170
- package/plugins/cursor-pbr/skills/import/SKILL.md +0 -505
- package/plugins/cursor-pbr/skills/milestone/SKILL.md +0 -746
- package/plugins/cursor-pbr/skills/milestone/templates/audit-report.md.tmpl +0 -49
- package/plugins/cursor-pbr/skills/milestone/templates/stats-file.md.tmpl +0 -31
- package/plugins/cursor-pbr/skills/note/SKILL.md +0 -214
- package/plugins/cursor-pbr/skills/pause/SKILL.md +0 -248
- package/plugins/cursor-pbr/skills/pause/templates/continue-here.md.tmpl +0 -72
- package/plugins/cursor-pbr/skills/plan/SKILL.md +0 -663
- package/plugins/cursor-pbr/skills/plan/templates/checker-prompt.md.tmpl +0 -22
- package/plugins/cursor-pbr/skills/plan/templates/gap-closure-prompt.md.tmpl +0 -33
- package/plugins/cursor-pbr/skills/plan/templates/planner-prompt.md.tmpl +0 -39
- package/plugins/cursor-pbr/skills/plan/templates/researcher-prompt.md.tmpl +0 -20
- package/plugins/cursor-pbr/skills/plan/templates/revision-prompt.md.tmpl +0 -24
- package/plugins/cursor-pbr/skills/quick/SKILL.md +0 -376
- package/plugins/cursor-pbr/skills/resume/SKILL.md +0 -399
- package/plugins/cursor-pbr/skills/review/SKILL.md +0 -654
- package/plugins/cursor-pbr/skills/review/templates/debugger-prompt.md.tmpl +0 -61
- package/plugins/cursor-pbr/skills/review/templates/gap-planner-prompt.md.tmpl +0 -41
- package/plugins/cursor-pbr/skills/review/templates/verifier-prompt.md.tmpl +0 -116
- package/plugins/cursor-pbr/skills/scan/SKILL.md +0 -300
- package/plugins/cursor-pbr/skills/scan/templates/mapper-prompt.md.tmpl +0 -202
- package/plugins/cursor-pbr/skills/setup/SKILL.md +0 -296
- package/plugins/cursor-pbr/skills/shared/commit-planning-docs.md +0 -36
- package/plugins/cursor-pbr/skills/shared/config-loading.md +0 -103
- package/plugins/cursor-pbr/skills/shared/context-budget.md +0 -41
- package/plugins/cursor-pbr/skills/shared/context-loader-task.md +0 -87
- package/plugins/cursor-pbr/skills/shared/digest-select.md +0 -80
- package/plugins/cursor-pbr/skills/shared/domain-probes.md +0 -126
- package/plugins/cursor-pbr/skills/shared/error-reporting.md +0 -81
- package/plugins/cursor-pbr/skills/shared/gate-prompts.md +0 -389
- package/plugins/cursor-pbr/skills/shared/phase-argument-parsing.md +0 -46
- package/plugins/cursor-pbr/skills/shared/progress-display.md +0 -53
- package/plugins/cursor-pbr/skills/shared/revision-loop.md +0 -82
- package/plugins/cursor-pbr/skills/shared/state-loading.md +0 -63
- package/plugins/cursor-pbr/skills/shared/state-update.md +0 -162
- package/plugins/cursor-pbr/skills/shared/universal-anti-patterns.md +0 -38
- package/plugins/cursor-pbr/skills/status/SKILL.md +0 -362
- package/plugins/cursor-pbr/skills/statusline/SKILL.md +0 -150
- package/plugins/cursor-pbr/skills/todo/SKILL.md +0 -280
- package/plugins/cursor-pbr/templates/CONTEXT.md.tmpl +0 -53
- package/plugins/cursor-pbr/templates/INTEGRATION-REPORT.md.tmpl +0 -152
- package/plugins/cursor-pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -98
- package/plugins/cursor-pbr/templates/ROADMAP.md.tmpl +0 -41
- package/plugins/cursor-pbr/templates/SUMMARY.md.tmpl +0 -82
- package/plugins/cursor-pbr/templates/VERIFICATION-DETAIL.md.tmpl +0 -117
- package/plugins/cursor-pbr/templates/codebase/ARCHITECTURE.md.tmpl +0 -98
- package/plugins/cursor-pbr/templates/codebase/CONCERNS.md.tmpl +0 -93
- package/plugins/cursor-pbr/templates/codebase/CONVENTIONS.md.tmpl +0 -104
- package/plugins/cursor-pbr/templates/codebase/INTEGRATIONS.md.tmpl +0 -78
- package/plugins/cursor-pbr/templates/codebase/STACK.md.tmpl +0 -78
- package/plugins/cursor-pbr/templates/codebase/STRUCTURE.md.tmpl +0 -80
- package/plugins/cursor-pbr/templates/codebase/TESTING.md.tmpl +0 -107
- package/plugins/cursor-pbr/templates/continue-here.md.tmpl +0 -74
- package/plugins/cursor-pbr/templates/prompt-partials/phase-project-context.md.tmpl +0 -38
- package/plugins/cursor-pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
- package/plugins/cursor-pbr/templates/research/STACK.md.tmpl +0 -71
- package/plugins/cursor-pbr/templates/research/SUMMARY.md.tmpl +0 -112
- package/plugins/cursor-pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
- package/plugins/cursor-pbr/templates/research-outputs/project-research.md.tmpl +0 -99
- package/plugins/cursor-pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
- package/plugins/pbr/references/agent-interactions.md +0 -134
- package/plugins/pbr/references/pbr-rules.md +0 -194
- package/plugins/pbr/references/pbr-tools-cli.md +0 -285
- package/plugins/pbr/references/planning-config.md +0 -213
- package/plugins/pbr/references/subagent-coordination.md +0 -119
- package/plugins/pbr/references/ui-formatting.md +0 -444
- package/plugins/pbr/scripts/validate-plugin-structure.js +0 -183
- package/plugins/pbr/skills/milestone/templates/audit-report.md.tmpl +0 -48
- package/plugins/pbr/skills/shared/progress-display.md +0 -53
- package/plugins/pbr/skills/shared/state-loading.md +0 -62
- package/plugins/pbr/templates/RESEARCH-SUMMARY.md.tmpl +0 -97
- package/plugins/pbr/templates/research/ARCHITECTURE.md.tmpl +0 -124
- package/plugins/pbr/templates/research/STACK.md.tmpl +0 -71
- package/plugins/pbr/templates/research/SUMMARY.md.tmpl +0 -112
- package/plugins/pbr/templates/research-outputs/phase-research.md.tmpl +0 -81
- package/plugins/pbr/templates/research-outputs/project-research.md.tmpl +0 -99
- package/plugins/pbr/templates/research-outputs/synthesis.md.tmpl +0 -36
- /package/plugins/pbr/references/{agent-anti-patterns.md → archive/agent-anti-patterns.md} +0 -0
|
@@ -0,0 +1,1059 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* lib/subagent-validators.js — Extracted validator functions and constants
|
|
5
|
+
* from check-subagent-output.js.
|
|
6
|
+
*
|
|
7
|
+
* Contains: AGENT_TO_SKILL, AGENT_OUTPUTS, SKILL_CHECKS, and all helper
|
|
8
|
+
* functions used for subagent output validation.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const { logHook } = require('../hook-logger');
|
|
14
|
+
const { KNOWN_AGENTS, sessionLoad } = require('../pbr-tools');
|
|
15
|
+
const { detectConventions, writeConventions } = require('./convention-detector');
|
|
16
|
+
const { resolveSessionPath } = require('./core');
|
|
17
|
+
|
|
18
|
+
// Agent-type to skill mapping for .active-skill auto-creation
|
|
19
|
+
const AGENT_TO_SKILL = {
|
|
20
|
+
'pbr:executor': 'build', 'pbr:planner': 'plan', 'pbr:verifier': 'review',
|
|
21
|
+
'pbr:researcher': 'plan', 'pbr:synthesizer': 'plan', 'pbr:audit': 'audit',
|
|
22
|
+
'pbr:debugger': 'debug', 'pbr:codebase-mapper': 'begin', 'pbr:roadmapper': 'begin',
|
|
23
|
+
'pbr:nyquist-auditor': 'validate', 'pbr:intel-updater': 'intel',
|
|
24
|
+
'pbr:ui-checker': 'ui-review', 'pbr:ui-researcher': 'ui-phase'
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Load a feature flag value from config.json.
|
|
29
|
+
* @param {string} planningDir - Path to .planning directory
|
|
30
|
+
* @param {string} flagName - Feature flag name (e.g. 'trust_tracking')
|
|
31
|
+
* @returns {*} Flag value or undefined if not found
|
|
32
|
+
*/
|
|
33
|
+
function loadFeatureFlag(planningDir, flagName) {
|
|
34
|
+
try {
|
|
35
|
+
const configPath = path.join(planningDir, 'config.json');
|
|
36
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
37
|
+
return config.features?.[flagName];
|
|
38
|
+
} catch (_e) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Check whether trust tracking is enabled in config.
|
|
45
|
+
* @param {string} planningDir - Path to .planning directory
|
|
46
|
+
* @returns {boolean} True if trust_tracking is not explicitly disabled
|
|
47
|
+
*/
|
|
48
|
+
function shouldTrackTrust(planningDir) {
|
|
49
|
+
const flag = loadFeatureFlag(planningDir, 'trust_tracking');
|
|
50
|
+
return flag !== false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Extract verification outcome from the most recent VERIFICATION.md
|
|
55
|
+
* in the current phase directory.
|
|
56
|
+
* @param {string} planningDir - Path to .planning directory
|
|
57
|
+
* @returns {{ passed: boolean, category: string, mustHavesPassed: number|undefined, mustHavesTotal: number|undefined }|null}
|
|
58
|
+
*/
|
|
59
|
+
function extractVerificationOutcome(planningDir) {
|
|
60
|
+
try {
|
|
61
|
+
const verFiles = findInPhaseDir(planningDir, /^VERIFICATION\.md$/i);
|
|
62
|
+
if (verFiles.length === 0) return null;
|
|
63
|
+
|
|
64
|
+
const verPath = path.join(planningDir, verFiles[0]);
|
|
65
|
+
const content = fs.readFileSync(verPath, 'utf8');
|
|
66
|
+
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
67
|
+
if (!fmMatch) return null;
|
|
68
|
+
|
|
69
|
+
const fm = fmMatch[1];
|
|
70
|
+
const statusMatch = fm.match(/^status:\s*(\S+)/mi);
|
|
71
|
+
if (!statusMatch) return null;
|
|
72
|
+
|
|
73
|
+
const status = statusMatch[1];
|
|
74
|
+
const passed = status === 'passed';
|
|
75
|
+
|
|
76
|
+
// Extract must_haves counts
|
|
77
|
+
const passedMatch = fm.match(/^must_haves_passed:\s*(\d+)/mi);
|
|
78
|
+
const totalMatch = fm.match(/^must_haves_total:\s*(\d+)/mi);
|
|
79
|
+
const mustHavesPassed = passedMatch ? parseInt(passedMatch[1], 10) : undefined;
|
|
80
|
+
const mustHavesTotal = totalMatch ? parseInt(totalMatch[1], 10) : undefined;
|
|
81
|
+
|
|
82
|
+
// Extract category from STATE.md phase_slug
|
|
83
|
+
let category = 'unknown';
|
|
84
|
+
const stateFile = path.join(planningDir, 'STATE.md');
|
|
85
|
+
if (fs.existsSync(stateFile)) {
|
|
86
|
+
const stateContent = fs.readFileSync(stateFile, 'utf8');
|
|
87
|
+
const slugMatch = stateContent.match(/^phase_slug:\s*"?([^"\n]+)"?/mi);
|
|
88
|
+
if (slugMatch) {
|
|
89
|
+
category = slugMatch[1].trim();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return { passed, category, mustHavesPassed, mustHavesTotal };
|
|
94
|
+
} catch (_e) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Check if a file was modified recently (within thresholdMs).
|
|
101
|
+
* Returns false if file doesn't exist or on error.
|
|
102
|
+
*/
|
|
103
|
+
function isRecent(filePath, thresholdMs = 1800000) {
|
|
104
|
+
try {
|
|
105
|
+
const stat = fs.statSync(filePath);
|
|
106
|
+
return (Date.now() - stat.mtimeMs) < thresholdMs;
|
|
107
|
+
} catch (_e) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Extract current phase number from STATE.md, preferring frontmatter over body.
|
|
114
|
+
* @param {string} stateContent - Full STATE.md content
|
|
115
|
+
* @returns {string|null} Phase number string or null
|
|
116
|
+
*/
|
|
117
|
+
function getCurrentPhase(stateContent) {
|
|
118
|
+
// Prefer frontmatter (always up-to-date)
|
|
119
|
+
const fmMatch = stateContent.match(/^current_phase:\s*(\d+)/m);
|
|
120
|
+
if (fmMatch) return fmMatch[1];
|
|
121
|
+
// Fall back to body text
|
|
122
|
+
const bodyMatch = stateContent.match(/Phase:\s*(\d+)\s+of\s+\d+/);
|
|
123
|
+
return bodyMatch ? bodyMatch[1] : null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function findInPhaseDir(planningDir, pattern) {
|
|
127
|
+
const matches = [];
|
|
128
|
+
const phasesDir = path.join(planningDir, 'phases');
|
|
129
|
+
if (!fs.existsSync(phasesDir)) return matches;
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
// Find the active phase from STATE.md (prefer frontmatter over body)
|
|
133
|
+
const stateFile = path.join(planningDir, 'STATE.md');
|
|
134
|
+
if (!fs.existsSync(stateFile)) return matches;
|
|
135
|
+
|
|
136
|
+
const stateContent = fs.readFileSync(stateFile, 'utf8');
|
|
137
|
+
const phaseNum = getCurrentPhase(stateContent);
|
|
138
|
+
if (!phaseNum) return matches;
|
|
139
|
+
|
|
140
|
+
const currentPhase = phaseNum.padStart(2, '0');
|
|
141
|
+
const dirs = fs.readdirSync(phasesDir).filter(d => d.startsWith(currentPhase));
|
|
142
|
+
if (dirs.length === 0) return matches;
|
|
143
|
+
|
|
144
|
+
const phaseDir = path.join(phasesDir, dirs[0]);
|
|
145
|
+
const files = fs.readdirSync(phaseDir);
|
|
146
|
+
for (const file of files) {
|
|
147
|
+
if (pattern.test(file)) {
|
|
148
|
+
// Check it's non-empty
|
|
149
|
+
const filePath = path.join(phaseDir, file);
|
|
150
|
+
const stat = fs.statSync(filePath);
|
|
151
|
+
if (stat.size > 0) {
|
|
152
|
+
matches.push(path.join('phases', dirs[0], file));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
} catch (_e) {
|
|
157
|
+
// best-effort
|
|
158
|
+
}
|
|
159
|
+
return matches;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function findInQuickDir(planningDir, pattern) {
|
|
163
|
+
const matches = [];
|
|
164
|
+
const quickDir = path.join(planningDir, 'quick');
|
|
165
|
+
if (!fs.existsSync(quickDir)) return matches;
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
// Find the most recent quick task directory (highest NNN)
|
|
169
|
+
const dirs = fs.readdirSync(quickDir)
|
|
170
|
+
.filter(d => /^\d{3}-/.test(d))
|
|
171
|
+
.sort()
|
|
172
|
+
.reverse();
|
|
173
|
+
if (dirs.length === 0) return matches;
|
|
174
|
+
|
|
175
|
+
const latestDir = path.join(quickDir, dirs[0]);
|
|
176
|
+
const stat = fs.statSync(latestDir);
|
|
177
|
+
if (!stat.isDirectory()) return matches;
|
|
178
|
+
|
|
179
|
+
const files = fs.readdirSync(latestDir);
|
|
180
|
+
for (const file of files) {
|
|
181
|
+
if (pattern.test(file)) {
|
|
182
|
+
const filePath = path.join(latestDir, file);
|
|
183
|
+
const fileStat = fs.statSync(filePath);
|
|
184
|
+
if (fileStat.size > 0) {
|
|
185
|
+
matches.push(path.join('quick', dirs[0], file));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
} catch (_e) {
|
|
190
|
+
// best-effort
|
|
191
|
+
}
|
|
192
|
+
return matches;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function checkSummaryCommits(planningDir, foundFiles, warnings) {
|
|
196
|
+
// Look for SUMMARY files in found list
|
|
197
|
+
const summaryFiles = foundFiles.filter(f => /SUMMARY/i.test(f));
|
|
198
|
+
for (const relPath of summaryFiles) {
|
|
199
|
+
try {
|
|
200
|
+
const fullPath = path.join(planningDir, relPath);
|
|
201
|
+
const content = fs.readFileSync(fullPath, 'utf8');
|
|
202
|
+
// Parse frontmatter for commits field
|
|
203
|
+
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
204
|
+
if (!fmMatch) continue;
|
|
205
|
+
const fm = fmMatch[1];
|
|
206
|
+
const commitsMatch = fm.match(/commits:\s*(\[.*?\]|.*)/);
|
|
207
|
+
if (!commitsMatch) {
|
|
208
|
+
warnings.push(`${relPath}: No "commits" field in frontmatter. Executor should record commit hashes.`);
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
const commitsVal = commitsMatch[1].trim();
|
|
212
|
+
if (commitsVal === '[]' || commitsVal === '' || commitsVal === '~' || commitsVal === 'null') {
|
|
213
|
+
warnings.push(`${relPath}: "commits" field is empty. Executor may have failed to commit changes.`);
|
|
214
|
+
}
|
|
215
|
+
} catch (_e) { /* best-effort */ }
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Check SUMMARY.md deviations for Rule 3/4 (action: "ask") that require user review.
|
|
221
|
+
* These deviations were flagged by the executor as needing human decision.
|
|
222
|
+
*
|
|
223
|
+
* @param {string} planningDir - Path to .planning/
|
|
224
|
+
* @param {string[]} foundFiles - List of found output files (relative to planningDir)
|
|
225
|
+
* @param {string[]} warnings - Array to push warnings into
|
|
226
|
+
*/
|
|
227
|
+
function checkDeviationsRequiringReview(planningDir, foundFiles, warnings) {
|
|
228
|
+
const summaryFiles = foundFiles.filter(f => /SUMMARY/i.test(f));
|
|
229
|
+
for (const relPath of summaryFiles) {
|
|
230
|
+
try {
|
|
231
|
+
const fullPath = path.join(planningDir, relPath);
|
|
232
|
+
const content = fs.readFileSync(fullPath, 'utf8');
|
|
233
|
+
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
234
|
+
if (!fmMatch) continue;
|
|
235
|
+
const fm = fmMatch[1];
|
|
236
|
+
|
|
237
|
+
// Parse deviations block for items with action: "ask"
|
|
238
|
+
const deviationsIdx = fm.indexOf('deviations:');
|
|
239
|
+
if (deviationsIdx === -1) continue;
|
|
240
|
+
|
|
241
|
+
const afterDeviations = fm.substring(deviationsIdx + 'deviations:'.length);
|
|
242
|
+
const firstLine = afterDeviations.split(/\r?\n/)[0].trim();
|
|
243
|
+
if (firstLine === '[]' || firstLine === 'none' || firstLine === '~' || firstLine === 'null') continue;
|
|
244
|
+
|
|
245
|
+
const askDeviations = [];
|
|
246
|
+
const lines = afterDeviations.split(/\r?\n/);
|
|
247
|
+
let currentItem = null;
|
|
248
|
+
|
|
249
|
+
for (const line of lines) {
|
|
250
|
+
if (/^\s+-\s+rule:/.test(line)) {
|
|
251
|
+
if (currentItem && currentItem.action === 'ask') askDeviations.push(currentItem);
|
|
252
|
+
currentItem = {};
|
|
253
|
+
const ruleMatch = line.match(/rule:\s*(\d+)/);
|
|
254
|
+
if (ruleMatch) currentItem.rule = ruleMatch[1];
|
|
255
|
+
} else if (currentItem) {
|
|
256
|
+
if (/^[a-zA-Z_][a-zA-Z0-9_]*:/.test(line)) {
|
|
257
|
+
if (currentItem.action === 'ask') askDeviations.push(currentItem);
|
|
258
|
+
currentItem = null;
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
const actionMatch = line.match(/^\s+action:\s*["']?(\w+)/);
|
|
262
|
+
if (actionMatch) currentItem.action = actionMatch[1];
|
|
263
|
+
const descMatch = line.match(/^\s+description:\s*["']?(.+?)["']?\s*$/);
|
|
264
|
+
if (descMatch) currentItem.description = descMatch[1];
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (currentItem && currentItem.action === 'ask') askDeviations.push(currentItem);
|
|
268
|
+
|
|
269
|
+
if (askDeviations.length > 0) {
|
|
270
|
+
const descriptions = askDeviations
|
|
271
|
+
.map(d => d.description || `Rule ${d.rule || '?'}`)
|
|
272
|
+
.join('; ');
|
|
273
|
+
warnings.push(`Executor flagged ${askDeviations.length} deviation(s) requiring review: ${descriptions}`);
|
|
274
|
+
}
|
|
275
|
+
} catch (_e) { /* best-effort */ }
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Log a compliance violation to .planning/logs/compliance.jsonl.
|
|
281
|
+
* These are surfaced to the user at session end by session-cleanup.js.
|
|
282
|
+
* @param {string} planningDir - Path to .planning/
|
|
283
|
+
* @param {string} agentType - Agent that violated
|
|
284
|
+
* @param {string} violation - What was missing or wrong
|
|
285
|
+
* @param {string} severity - 'required' or 'advisory'
|
|
286
|
+
*/
|
|
287
|
+
function logCompliance(planningDir, agentType, violation, severity) {
|
|
288
|
+
try {
|
|
289
|
+
const logsDir = path.join(planningDir, 'logs');
|
|
290
|
+
if (!fs.existsSync(logsDir)) fs.mkdirSync(logsDir, { recursive: true });
|
|
291
|
+
const logFile = path.join(logsDir, 'compliance.jsonl');
|
|
292
|
+
const entry = JSON.stringify({
|
|
293
|
+
ts: new Date().toISOString(),
|
|
294
|
+
agent: agentType,
|
|
295
|
+
violation,
|
|
296
|
+
severity
|
|
297
|
+
});
|
|
298
|
+
fs.appendFileSync(logFile, entry + '\n', 'utf8');
|
|
299
|
+
} catch (_e) {
|
|
300
|
+
// Best-effort — never crash the hook
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Check for seeds whose trigger matches the completed phase slug.
|
|
306
|
+
* When an executor completes, check if any seed files in .planning/seeds/
|
|
307
|
+
* have a trigger field matching the current phase slug.
|
|
308
|
+
* @param {string} planningDir - Path to .planning/
|
|
309
|
+
* @param {string[]} warnings - Mutable warnings array to push into
|
|
310
|
+
*/
|
|
311
|
+
function checkTriggeredSeeds(planningDir, warnings) {
|
|
312
|
+
try {
|
|
313
|
+
const seedsDir = path.join(planningDir, 'seeds');
|
|
314
|
+
if (!fs.existsSync(seedsDir)) return;
|
|
315
|
+
|
|
316
|
+
// Get current phase slug from STATE.md
|
|
317
|
+
const stateFile = path.join(planningDir, 'STATE.md');
|
|
318
|
+
if (!fs.existsSync(stateFile)) return;
|
|
319
|
+
const stateContent = fs.readFileSync(stateFile, 'utf8');
|
|
320
|
+
const slugMatch = stateContent.match(/^phase_slug:\s*"?([^"\n]+)"?/mi);
|
|
321
|
+
if (!slugMatch) return;
|
|
322
|
+
const phaseSlug = slugMatch[1].trim();
|
|
323
|
+
|
|
324
|
+
const seeds = fs.readdirSync(seedsDir).filter(f => f.endsWith('.md'));
|
|
325
|
+
const triggered = [];
|
|
326
|
+
for (const seed of seeds) {
|
|
327
|
+
try {
|
|
328
|
+
const content = fs.readFileSync(path.join(seedsDir, seed), 'utf-8');
|
|
329
|
+
const triggerMatch = content.match(/trigger:\s*"([^"]+)"/);
|
|
330
|
+
if (triggerMatch && phaseSlug.includes(triggerMatch[1])) {
|
|
331
|
+
const idMatch = seed.match(/SEED-(\d+)/);
|
|
332
|
+
triggered.push({ id: idMatch ? idMatch[1] : seed, trigger: triggerMatch[1] });
|
|
333
|
+
}
|
|
334
|
+
} catch (_e) { /* skip unreadable seeds */ }
|
|
335
|
+
}
|
|
336
|
+
if (triggered.length > 0) {
|
|
337
|
+
const seedList = triggered.map(s => `SEED-${s.id} (trigger: ${s.trigger})`).join(', ');
|
|
338
|
+
warnings.push(`Seed(s) triggered by phase completion: ${seedList}. Review with /pbr:explore.`);
|
|
339
|
+
}
|
|
340
|
+
} catch (_e) { /* non-fatal */ }
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Check that LEARNINGS.md exists in the current phase directory.
|
|
345
|
+
* LEARNINGS.md is REQUIRED for all agents — every agent must document what it learned.
|
|
346
|
+
* @param {string} planningDir - Path to .planning/
|
|
347
|
+
* @param {string[]} warnings - Mutable warnings array to push into
|
|
348
|
+
* @param {string} agentLabel - Human-readable agent label for the warning message
|
|
349
|
+
*/
|
|
350
|
+
function checkLearningsRequired(planningDir, warnings, agentLabel) {
|
|
351
|
+
const learningsFiles = findInPhaseDir(planningDir, /^LEARNINGS\.md$/i);
|
|
352
|
+
if (learningsFiles.length === 0) {
|
|
353
|
+
warnings.push(`[REQUIRED] No LEARNINGS.md found in phase directory. The ${agentLabel} agent MUST write LEARNINGS.md documenting what it learned — patterns discovered, pitfalls avoided, decisions made. This is required for cross-phase knowledge transfer.`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Agent type -> expected output patterns
|
|
358
|
+
const AGENT_OUTPUTS = {
|
|
359
|
+
'pbr:executor': {
|
|
360
|
+
description: 'SUMMARY.md in the phase or quick directory',
|
|
361
|
+
check: (planningDir) => {
|
|
362
|
+
// Check phase directory first, then quick directory
|
|
363
|
+
const phaseMatches = findInPhaseDir(planningDir, /^SUMMARY.*\.md$/i);
|
|
364
|
+
if (phaseMatches.length > 0) return phaseMatches;
|
|
365
|
+
return findInQuickDir(planningDir, /^SUMMARY.*\.md$/i);
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
'pbr:planner': {
|
|
369
|
+
description: 'PLAN.md in the phase directory',
|
|
370
|
+
check: (planningDir) => findInPhaseDir(planningDir, /^PLAN.*\.md$/i)
|
|
371
|
+
},
|
|
372
|
+
'pbr:verifier': {
|
|
373
|
+
description: 'VERIFICATION.md in the phase directory',
|
|
374
|
+
check: (planningDir) => findInPhaseDir(planningDir, /^VERIFICATION\.md$/i)
|
|
375
|
+
},
|
|
376
|
+
'pbr:researcher': {
|
|
377
|
+
description: 'research file in .planning/research/',
|
|
378
|
+
check: (planningDir) => {
|
|
379
|
+
const researchDir = path.join(planningDir, 'research');
|
|
380
|
+
if (!fs.existsSync(researchDir)) return [];
|
|
381
|
+
try {
|
|
382
|
+
const allFiles = fs.readdirSync(researchDir)
|
|
383
|
+
.filter(f => f.endsWith('.md'))
|
|
384
|
+
.map(f => path.join('research', f));
|
|
385
|
+
if (allFiles.length === 0) return [];
|
|
386
|
+
const recentFiles = allFiles.filter(f => isRecent(path.join(planningDir, f)));
|
|
387
|
+
if (recentFiles.length === 0) {
|
|
388
|
+
// Files exist but none are recent — return them but flag staleness
|
|
389
|
+
allFiles._stale = true;
|
|
390
|
+
}
|
|
391
|
+
return allFiles;
|
|
392
|
+
} catch (_e) {
|
|
393
|
+
return [];
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
'pbr:synthesizer': {
|
|
398
|
+
description: 'synthesis file in .planning/research/ or CONTEXT.md update',
|
|
399
|
+
check: (planningDir) => {
|
|
400
|
+
const researchDir = path.join(planningDir, 'research');
|
|
401
|
+
if (fs.existsSync(researchDir)) {
|
|
402
|
+
try {
|
|
403
|
+
const files = fs.readdirSync(researchDir).filter(f => f.endsWith('.md'));
|
|
404
|
+
if (files.length > 0) {
|
|
405
|
+
const allFiles = files.map(f => path.join('research', f));
|
|
406
|
+
const recentFiles = allFiles.filter(f => isRecent(path.join(planningDir, f)));
|
|
407
|
+
if (recentFiles.length === 0) {
|
|
408
|
+
allFiles._stale = true;
|
|
409
|
+
}
|
|
410
|
+
return allFiles;
|
|
411
|
+
}
|
|
412
|
+
} catch (_e) { /* best-effort */ }
|
|
413
|
+
}
|
|
414
|
+
const contextFile = path.join(planningDir, 'CONTEXT.md');
|
|
415
|
+
if (fs.existsSync(contextFile)) {
|
|
416
|
+
try {
|
|
417
|
+
const stat = fs.statSync(contextFile);
|
|
418
|
+
if (stat.size > 0) {
|
|
419
|
+
const result = ['CONTEXT.md'];
|
|
420
|
+
if (!isRecent(contextFile)) {
|
|
421
|
+
result._stale = true;
|
|
422
|
+
}
|
|
423
|
+
return result;
|
|
424
|
+
}
|
|
425
|
+
} catch (_e) { /* best-effort */ }
|
|
426
|
+
}
|
|
427
|
+
return [];
|
|
428
|
+
}
|
|
429
|
+
},
|
|
430
|
+
'pbr:plan-checker': {
|
|
431
|
+
description: 'advisory output (no file expected)',
|
|
432
|
+
noFileExpected: true,
|
|
433
|
+
check: () => []
|
|
434
|
+
},
|
|
435
|
+
'pbr:integration-checker': {
|
|
436
|
+
description: 'INTEGRATION-REPORT.md in the phase directory',
|
|
437
|
+
check: (planningDir) => findInPhaseDir(planningDir, /^INTEGRATION-REPORT\.md$/i)
|
|
438
|
+
},
|
|
439
|
+
'pbr:debugger': {
|
|
440
|
+
description: 'debug file in .planning/debug/',
|
|
441
|
+
check: (planningDir) => {
|
|
442
|
+
const debugDir = path.join(planningDir, 'debug');
|
|
443
|
+
if (!fs.existsSync(debugDir)) return [];
|
|
444
|
+
try {
|
|
445
|
+
return fs.readdirSync(debugDir)
|
|
446
|
+
.filter(f => f.endsWith('.md'))
|
|
447
|
+
.map(f => path.join('debug', f));
|
|
448
|
+
} catch (_e) {
|
|
449
|
+
return [];
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
},
|
|
453
|
+
'pbr:codebase-mapper': {
|
|
454
|
+
description: 'codebase map in .planning/codebase/',
|
|
455
|
+
check: (planningDir) => {
|
|
456
|
+
const codebaseDir = path.join(planningDir, 'codebase');
|
|
457
|
+
if (!fs.existsSync(codebaseDir)) return [];
|
|
458
|
+
try {
|
|
459
|
+
return fs.readdirSync(codebaseDir)
|
|
460
|
+
.filter(f => f.endsWith('.md'))
|
|
461
|
+
.map(f => path.join('codebase', f));
|
|
462
|
+
} catch (_e) {
|
|
463
|
+
return [];
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
},
|
|
467
|
+
'pbr:general': {
|
|
468
|
+
description: 'advisory output (no file expected)',
|
|
469
|
+
noFileExpected: true,
|
|
470
|
+
check: () => []
|
|
471
|
+
},
|
|
472
|
+
'pbr:audit': {
|
|
473
|
+
description: 'audit report in .planning/audits/',
|
|
474
|
+
check: (planningDir) => {
|
|
475
|
+
const auditsDir = path.join(planningDir, 'audits');
|
|
476
|
+
if (!fs.existsSync(auditsDir)) return [];
|
|
477
|
+
try {
|
|
478
|
+
return fs.readdirSync(auditsDir)
|
|
479
|
+
.filter(f => f.endsWith('.md'))
|
|
480
|
+
.map(f => path.join('audits', f));
|
|
481
|
+
} catch (_e) {
|
|
482
|
+
return [];
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
},
|
|
486
|
+
'pbr:dev-sync': {
|
|
487
|
+
description: 'advisory output (no file expected)',
|
|
488
|
+
noFileExpected: true,
|
|
489
|
+
check: () => []
|
|
490
|
+
},
|
|
491
|
+
'pbr:intel-updater': {
|
|
492
|
+
description: 'intel files in .planning/intel/',
|
|
493
|
+
check: (planningDir) => {
|
|
494
|
+
const intelDir = path.join(planningDir, 'intel');
|
|
495
|
+
if (!fs.existsSync(intelDir)) return [];
|
|
496
|
+
try {
|
|
497
|
+
return fs.readdirSync(intelDir)
|
|
498
|
+
.filter(f => f.endsWith('.md') || f.endsWith('.json'))
|
|
499
|
+
.map(f => path.join('intel', f));
|
|
500
|
+
} catch (_e) {
|
|
501
|
+
return [];
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
},
|
|
505
|
+
'pbr:ui-checker': {
|
|
506
|
+
description: 'UI-REVIEW.md in the phase directory',
|
|
507
|
+
check: (planningDir) => findInPhaseDir(planningDir, /^UI-REVIEW\.md$/i)
|
|
508
|
+
},
|
|
509
|
+
'pbr:ui-researcher': {
|
|
510
|
+
description: 'UI-SPEC.md in the phase directory',
|
|
511
|
+
check: (planningDir) => findInPhaseDir(planningDir, /^UI-SPEC\.md$/i)
|
|
512
|
+
},
|
|
513
|
+
'pbr:roadmapper': {
|
|
514
|
+
description: 'ROADMAP.md in .planning/',
|
|
515
|
+
check: (planningDir) => {
|
|
516
|
+
const roadmapPath = path.join(planningDir, 'ROADMAP.md');
|
|
517
|
+
if (fs.existsSync(roadmapPath)) {
|
|
518
|
+
const result = ['ROADMAP.md'];
|
|
519
|
+
if (!isRecent(roadmapPath)) {
|
|
520
|
+
result._stale = true;
|
|
521
|
+
}
|
|
522
|
+
return result;
|
|
523
|
+
}
|
|
524
|
+
return [];
|
|
525
|
+
}
|
|
526
|
+
},
|
|
527
|
+
'pbr:nyquist-auditor': {
|
|
528
|
+
description: 'VALIDATION.md in the phase directory',
|
|
529
|
+
check: (planningDir) => {
|
|
530
|
+
const phaseMatches = findInPhaseDir(planningDir, /^VALIDATION\.md$/i);
|
|
531
|
+
return phaseMatches;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Check if ROADMAP.md is stale after executor/verifier completion.
|
|
538
|
+
* Detects: (1) no Progress table for current milestone, (2) table exists but
|
|
539
|
+
* phase row is out of date vs. phase artifacts on disk.
|
|
540
|
+
*
|
|
541
|
+
* @param {string} planningDir - Path to .planning/
|
|
542
|
+
* @returns {string|null} Warning message or null if in sync
|
|
543
|
+
*/
|
|
544
|
+
function checkRoadmapStaleness(planningDir) {
|
|
545
|
+
const roadmapPath = path.join(planningDir, 'ROADMAP.md');
|
|
546
|
+
if (!fs.existsSync(roadmapPath)) return null;
|
|
547
|
+
|
|
548
|
+
try {
|
|
549
|
+
const content = fs.readFileSync(roadmapPath, 'utf8');
|
|
550
|
+
|
|
551
|
+
// Check if there's a Progress table at all
|
|
552
|
+
const hasProgressTable = /Plans\s*Complete/i.test(content);
|
|
553
|
+
if (!hasProgressTable) {
|
|
554
|
+
return 'ROADMAP.md has no Progress table for the current milestone. The orchestrator should add a Progress table with columns: Phase | Plans Complete | Status | Completed. See skills/shared/state-update.md for format.';
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// If table exists, check if current phase row is present
|
|
558
|
+
const stateFile = path.join(planningDir, 'STATE.md');
|
|
559
|
+
if (fs.existsSync(stateFile)) {
|
|
560
|
+
const stateContent = fs.readFileSync(stateFile, 'utf8');
|
|
561
|
+
const currentPhase = getCurrentPhase(stateContent);
|
|
562
|
+
if (currentPhase) {
|
|
563
|
+
const paddedPhase = currentPhase.padStart(2, '0');
|
|
564
|
+
const phaseInTable = new RegExp(`\\|\\s*${paddedPhase}\\.`).test(content) ||
|
|
565
|
+
new RegExp(`\\|\\s*${parseInt(currentPhase, 10)}\\.`).test(content);
|
|
566
|
+
if (!phaseInTable) {
|
|
567
|
+
return `ROADMAP.md Progress table exists but has no row for Phase ${currentPhase}. Add a row for the current phase.`;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
} catch (_e) {
|
|
572
|
+
// best-effort
|
|
573
|
+
}
|
|
574
|
+
return null;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// Skill-specific check lookup table keyed by 'activeSkill:agentType'
|
|
578
|
+
const SKILL_CHECKS = {
|
|
579
|
+
'begin:pbr:planner': {
|
|
580
|
+
description: 'begin planner core files',
|
|
581
|
+
check: (planningDir, _found, warnings) => {
|
|
582
|
+
const coreFiles = ['REQUIREMENTS.md', 'ROADMAP.md', 'STATE.md'];
|
|
583
|
+
for (const f of coreFiles) {
|
|
584
|
+
if (!fs.existsSync(path.join(planningDir, f))) {
|
|
585
|
+
warnings.push(`Begin planner: ${f} was not created. The project may be in an incomplete state.`);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
'plan:pbr:researcher': {
|
|
591
|
+
description: 'plan researcher phase-level RESEARCH.md and LEARNINGS.md',
|
|
592
|
+
check: (planningDir, found, warnings) => {
|
|
593
|
+
const phaseResearch = findInPhaseDir(planningDir, /^RESEARCH\.md$/i);
|
|
594
|
+
if (found.length === 0 && phaseResearch.length === 0) {
|
|
595
|
+
warnings.push('Plan researcher: No research output found in .planning/research/ or in the phase directory.');
|
|
596
|
+
}
|
|
597
|
+
checkLearningsRequired(planningDir, warnings, 'researcher');
|
|
598
|
+
}
|
|
599
|
+
},
|
|
600
|
+
'plan:pbr:planner': {
|
|
601
|
+
description: 'plan planner LEARNINGS.md',
|
|
602
|
+
check: (planningDir, _found, warnings) => {
|
|
603
|
+
checkLearningsRequired(planningDir, warnings, 'planner');
|
|
604
|
+
}
|
|
605
|
+
},
|
|
606
|
+
'scan:pbr:codebase-mapper': {
|
|
607
|
+
description: 'scan codebase-mapper 4 focus areas',
|
|
608
|
+
check: (planningDir, _found, warnings) => {
|
|
609
|
+
const expectedAreas = ['tech', 'arch', 'quality', 'concerns'];
|
|
610
|
+
const codebaseDir = path.join(planningDir, 'codebase');
|
|
611
|
+
if (fs.existsSync(codebaseDir)) {
|
|
612
|
+
try {
|
|
613
|
+
const files = fs.readdirSync(codebaseDir).map(f => f.toLowerCase());
|
|
614
|
+
for (const area of expectedAreas) {
|
|
615
|
+
if (!files.some(f => f.includes(area))) {
|
|
616
|
+
warnings.push(`Scan mapper: No output file containing "${area}" found in .planning/codebase/. One of the 4 mappers may have failed.`);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
} catch (_e) { /* best-effort */ }
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
},
|
|
623
|
+
'review:pbr:verifier': {
|
|
624
|
+
description: 'review verifier VERIFICATION.md status, LEARNINGS.md, and trust update',
|
|
625
|
+
check: (planningDir, _found, warnings) => {
|
|
626
|
+
const verFiles = findInPhaseDir(planningDir, /^VERIFICATION\.md$/i);
|
|
627
|
+
for (const vf of verFiles) {
|
|
628
|
+
try {
|
|
629
|
+
const content = fs.readFileSync(path.join(planningDir, vf), 'utf8');
|
|
630
|
+
const statusMatch = content.match(/^status:\s*(\S+)/mi);
|
|
631
|
+
if (statusMatch && statusMatch[1] === 'gaps_found') {
|
|
632
|
+
warnings.push('Review verifier: VERIFICATION.md has status "gaps_found" — ensure gaps are surfaced to the user.');
|
|
633
|
+
}
|
|
634
|
+
} catch (_e) { /* best-effort */ }
|
|
635
|
+
}
|
|
636
|
+
checkLearningsRequired(planningDir, warnings, 'verifier');
|
|
637
|
+
|
|
638
|
+
// Trust score update: record verification outcome
|
|
639
|
+
try {
|
|
640
|
+
if (!shouldTrackTrust(planningDir)) return;
|
|
641
|
+
const outcome = extractVerificationOutcome(planningDir);
|
|
642
|
+
if (!outcome) return;
|
|
643
|
+
const { recordOutcome } = require('../trust-tracker');
|
|
644
|
+
recordOutcome(planningDir, 'pbr:executor', outcome.category, outcome.passed);
|
|
645
|
+
recordOutcome(planningDir, 'pbr:verifier', outcome.category, true);
|
|
646
|
+
logHook('check-subagent-output', 'PostToolUse', 'trust-updated', {
|
|
647
|
+
agent: 'pbr:executor',
|
|
648
|
+
category: outcome.category,
|
|
649
|
+
passed: outcome.passed
|
|
650
|
+
});
|
|
651
|
+
} catch (_e) {
|
|
652
|
+
// Never crash the hook for trust tracking failures
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
},
|
|
656
|
+
'build:pbr:executor': {
|
|
657
|
+
description: 'build executor SUMMARY commits, self-check, LEARNINGS.md, and convention update',
|
|
658
|
+
check: (planningDir, found, warnings) => {
|
|
659
|
+
// Warn if no SUMMARY.md was created by the executor
|
|
660
|
+
if (found.length === 0) {
|
|
661
|
+
warnings.push('Build executor completed but no SUMMARY.md was found in the phase or quick directory. The executor may have skipped artifact creation. Re-run the build skill to generate the missing artifact.');
|
|
662
|
+
}
|
|
663
|
+
checkSummaryCommits(planningDir, found, warnings);
|
|
664
|
+
// Check for deviations requiring user review (Rule 3/4 with action: "ask")
|
|
665
|
+
checkDeviationsRequiringReview(planningDir, found, warnings);
|
|
666
|
+
// Validate self-verification ran when feature is enabled
|
|
667
|
+
const summaryFiles = found.filter(f => /SUMMARY/i.test(f));
|
|
668
|
+
for (const relPath of summaryFiles) {
|
|
669
|
+
try {
|
|
670
|
+
const fullPath = path.join(planningDir, relPath);
|
|
671
|
+
const { resolveConfig } = require('./config');
|
|
672
|
+
const config = resolveConfig(planningDir);
|
|
673
|
+
const selfCheckWarnings = validateSelfCheck(fullPath, config);
|
|
674
|
+
warnings.push(...selfCheckWarnings);
|
|
675
|
+
} catch (_e) { /* best-effort */ }
|
|
676
|
+
}
|
|
677
|
+
// Extract feedback for agent prompt enrichment
|
|
678
|
+
try {
|
|
679
|
+
const { extractFeedback, isEnabled } = require('../feedback-loop');
|
|
680
|
+
if (isEnabled(planningDir)) {
|
|
681
|
+
const phaseDirMatches = found.filter(f => /^phases[/\\]/.test(f));
|
|
682
|
+
const phaseDir = phaseDirMatches.length > 0
|
|
683
|
+
? path.join(planningDir, phaseDirMatches[0].split(/[/\\]/).slice(0, 2).join(path.sep))
|
|
684
|
+
: null;
|
|
685
|
+
if (phaseDir) {
|
|
686
|
+
const feedback = extractFeedback(phaseDir);
|
|
687
|
+
if (feedback) {
|
|
688
|
+
warnings.push(`Feedback loop: ${feedback.summary || 'verification feedback recorded'}`);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
} catch (_e) { /* best-effort */ }
|
|
693
|
+
checkLearningsRequired(planningDir, warnings, 'executor');
|
|
694
|
+
// Check for seeds triggered by this phase completion
|
|
695
|
+
checkTriggeredSeeds(planningDir, warnings);
|
|
696
|
+
// Log post-hoc skip for non-quick executors (audit evidence)
|
|
697
|
+
const { logEvent } = require('../event-logger');
|
|
698
|
+
logEvent('post_hoc', 'post_hoc_skipped', { reason: 'not_quick_task', feature: 'post_hoc_artifacts' });
|
|
699
|
+
// Update conventions after successful build
|
|
700
|
+
updateConventionsAfterBuild(planningDir);
|
|
701
|
+
// Log inline execution decision for audit
|
|
702
|
+
try {
|
|
703
|
+
const inlineSignal = path.join(planningDir, '.inline-active');
|
|
704
|
+
const wasInline = fs.existsSync(inlineSignal);
|
|
705
|
+
logInlineDecision(planningDir, {
|
|
706
|
+
inline: wasInline,
|
|
707
|
+
decision: wasInline ? 'inline' : 'delegate',
|
|
708
|
+
reason: wasInline ? 'signal file present' : 'normal task spawn',
|
|
709
|
+
taskCount: found.filter(f => /SUMMARY/i.test(f)).length,
|
|
710
|
+
fileCount: 0
|
|
711
|
+
});
|
|
712
|
+
} catch (_e) { /* best-effort — never crash for audit logging */ }
|
|
713
|
+
}
|
|
714
|
+
},
|
|
715
|
+
'quick:pbr:executor': {
|
|
716
|
+
description: 'quick executor SUMMARY commits and post-hoc generation',
|
|
717
|
+
check: (planningDir, found, warnings) => {
|
|
718
|
+
checkSummaryCommits(planningDir, found, warnings);
|
|
719
|
+
// Post-hoc SUMMARY.md generation for quick tasks
|
|
720
|
+
const postHocEnabled = loadFeatureFlag(planningDir, 'post_hoc_artifacts');
|
|
721
|
+
if (postHocEnabled === false) {
|
|
722
|
+
const { logEvent } = require('../event-logger');
|
|
723
|
+
logEvent('post_hoc', 'post_hoc_skipped', { reason: 'feature_disabled', feature: 'post_hoc_artifacts' });
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
// Check if SUMMARY.md is missing in the quick dir
|
|
727
|
+
const quickSummaries = findInQuickDir(planningDir, /^SUMMARY.*\.md$/i);
|
|
728
|
+
if (quickSummaries.length > 0) return; // Already exists, no need for post-hoc
|
|
729
|
+
// Find the latest quick task directory
|
|
730
|
+
const quickDir = path.join(planningDir, 'quick');
|
|
731
|
+
if (!fs.existsSync(quickDir)) return;
|
|
732
|
+
try {
|
|
733
|
+
const dirs = fs.readdirSync(quickDir)
|
|
734
|
+
.filter(d => /^\d{3}-/.test(d))
|
|
735
|
+
.sort()
|
|
736
|
+
.reverse();
|
|
737
|
+
if (dirs.length === 0) return;
|
|
738
|
+
const taskDir = path.join(quickDir, dirs[0]);
|
|
739
|
+
const taskSlug = dirs[0];
|
|
740
|
+
// Attempt post-hoc generation
|
|
741
|
+
try {
|
|
742
|
+
const { generateSummary } = require(path.join(__dirname, 'post-hoc'));
|
|
743
|
+
const projectRoot = path.resolve(planningDir, '..');
|
|
744
|
+
const result = generateSummary(projectRoot, taskDir, {
|
|
745
|
+
commitPattern: taskSlug.replace(/^(\d{3})-.*/, 'quick-$1')
|
|
746
|
+
});
|
|
747
|
+
const { logEvent } = require('../event-logger');
|
|
748
|
+
logEvent('post_hoc', 'post_hoc_summary_generated', {
|
|
749
|
+
taskDir: taskSlug,
|
|
750
|
+
commitCount: result.commitCount,
|
|
751
|
+
feature: 'post_hoc_artifacts',
|
|
752
|
+
timestamp: new Date().toISOString()
|
|
753
|
+
});
|
|
754
|
+
warnings.push(`SUMMARY.md auto-generated post-hoc for quick task ${taskSlug} (${result.commitCount} commits found)`);
|
|
755
|
+
} catch (_genErr) {
|
|
756
|
+
const { logEvent } = require('../event-logger');
|
|
757
|
+
logEvent('post_hoc', 'post_hoc_generation_failed', {
|
|
758
|
+
taskDir: taskSlug,
|
|
759
|
+
error: _genErr.message,
|
|
760
|
+
feature: 'post_hoc_artifacts'
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
} catch (_e) { /* best-effort */ }
|
|
764
|
+
}
|
|
765
|
+
},
|
|
766
|
+
'begin:pbr:researcher': {
|
|
767
|
+
description: 'begin researcher YAML frontmatter validation',
|
|
768
|
+
check: (planningDir, found, warnings) => {
|
|
769
|
+
const EXPECTED_NAMES = ['STACK.md', 'FEATURES.md', 'ARCHITECTURE.md', 'PITFALLS.md'];
|
|
770
|
+
for (const relPath of found) {
|
|
771
|
+
const basename = path.basename(relPath);
|
|
772
|
+
// Skip SUMMARY.md -- that's synthesizer output
|
|
773
|
+
if (basename.toUpperCase() === 'SUMMARY.MD') continue;
|
|
774
|
+
try {
|
|
775
|
+
// Warn if unexpected filename
|
|
776
|
+
if (!EXPECTED_NAMES.includes(basename)) {
|
|
777
|
+
warnings.push(`${basename}: unexpected research file name. Expected one of: ${EXPECTED_NAMES.join(', ')}`);
|
|
778
|
+
}
|
|
779
|
+
// Read and validate YAML frontmatter
|
|
780
|
+
const fullPath = path.join(planningDir, relPath);
|
|
781
|
+
const content = fs.readFileSync(fullPath, 'utf8');
|
|
782
|
+
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
783
|
+
if (!fmMatch) {
|
|
784
|
+
warnings.push(`${basename}: YAML frontmatter is missing. Researcher output must include frontmatter with confidence and sources_checked fields.`);
|
|
785
|
+
continue;
|
|
786
|
+
}
|
|
787
|
+
const fm = fmMatch[1];
|
|
788
|
+
if (!/confidence\s*:/i.test(fm)) {
|
|
789
|
+
warnings.push(`${basename}: frontmatter missing "confidence" field.`);
|
|
790
|
+
}
|
|
791
|
+
if (!/sources_checked\s*:/i.test(fm)) {
|
|
792
|
+
warnings.push(`${basename}: frontmatter missing "sources_checked" field.`);
|
|
793
|
+
}
|
|
794
|
+
} catch (_e) { /* best-effort */ }
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
},
|
|
798
|
+
'begin:pbr:roadmapper': {
|
|
799
|
+
description: 'begin roadmapper LEARNINGS.md',
|
|
800
|
+
check: (planningDir, _found, warnings) => {
|
|
801
|
+
checkLearningsRequired(planningDir, warnings, 'roadmapper');
|
|
802
|
+
}
|
|
803
|
+
},
|
|
804
|
+
'debug:pbr:debugger': {
|
|
805
|
+
description: 'debug agent LEARNINGS.md',
|
|
806
|
+
check: (planningDir, _found, warnings) => {
|
|
807
|
+
// Debugger writes to .planning/debug/ — check LEARNINGS there
|
|
808
|
+
const debugDir = path.join(planningDir, 'debug');
|
|
809
|
+
if (!fs.existsSync(debugDir)) return;
|
|
810
|
+
try {
|
|
811
|
+
const files = fs.readdirSync(debugDir);
|
|
812
|
+
const hasLearnings = files.some(f => /^LEARNINGS/i.test(f));
|
|
813
|
+
if (!hasLearnings) {
|
|
814
|
+
warnings.push('[REQUIRED] No LEARNINGS.md found in .planning/debug/. The debugger agent MUST document what it learned — root causes found, debugging approaches that worked, environment quirks discovered.');
|
|
815
|
+
}
|
|
816
|
+
} catch (_e) { /* best-effort */ }
|
|
817
|
+
}
|
|
818
|
+
},
|
|
819
|
+
'begin:pbr:synthesizer': {
|
|
820
|
+
description: 'begin synthesizer SUMMARY.md structure validation',
|
|
821
|
+
check: (planningDir, _found, warnings) => {
|
|
822
|
+
// Check for SUMMARY.md in research directory
|
|
823
|
+
const researchDir = path.join(planningDir, 'research');
|
|
824
|
+
const summaryPath = path.join(researchDir, 'SUMMARY.md');
|
|
825
|
+
try {
|
|
826
|
+
if (!fs.existsSync(summaryPath)) {
|
|
827
|
+
warnings.push('SUMMARY.md not found in .planning/research/. Synthesizer must produce a SUMMARY.md.');
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
const content = fs.readFileSync(summaryPath, 'utf8');
|
|
831
|
+
// Check for Research Coverage table
|
|
832
|
+
if (!/research\s+coverage/i.test(content)) {
|
|
833
|
+
warnings.push('SUMMARY.md missing "Research Coverage" table.');
|
|
834
|
+
}
|
|
835
|
+
// Check for Confidence Assessment table
|
|
836
|
+
if (!/confidence\s+assessment/i.test(content)) {
|
|
837
|
+
warnings.push('SUMMARY.md missing "Confidence Assessment" table.');
|
|
838
|
+
}
|
|
839
|
+
// Check all 4 dimensions are referenced
|
|
840
|
+
const dimensions = ['Stack', 'Features', 'Architecture', 'Pitfalls'];
|
|
841
|
+
for (const dim of dimensions) {
|
|
842
|
+
if (!new RegExp(dim, 'i').test(content)) {
|
|
843
|
+
warnings.push(`SUMMARY.md missing dimension: ${dim}. All 4 research dimensions must be covered.`);
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
} catch (_e) { /* best-effort */ }
|
|
847
|
+
}
|
|
848
|
+
},
|
|
849
|
+
'milestone:pbr:general': {
|
|
850
|
+
description: 'milestone archive completeness validation',
|
|
851
|
+
check: (planningDir, _found, warnings) => {
|
|
852
|
+
// After milestone completion, verify the archive structure
|
|
853
|
+
const milestonesDir = path.join(planningDir, 'milestones');
|
|
854
|
+
if (!fs.existsSync(milestonesDir)) return;
|
|
855
|
+
|
|
856
|
+
try {
|
|
857
|
+
// Find the most recent milestone archive (highest version)
|
|
858
|
+
const archiveDirs = fs.readdirSync(milestonesDir)
|
|
859
|
+
.filter(d => d.startsWith('v') && fs.statSync(path.join(milestonesDir, d)).isDirectory())
|
|
860
|
+
.sort()
|
|
861
|
+
.reverse();
|
|
862
|
+
|
|
863
|
+
if (archiveDirs.length === 0) return;
|
|
864
|
+
|
|
865
|
+
const latestArchive = path.join(milestonesDir, archiveDirs[0]);
|
|
866
|
+
const archiveFiles = fs.readdirSync(latestArchive);
|
|
867
|
+
|
|
868
|
+
// Check for required archive files
|
|
869
|
+
if (!archiveFiles.includes('ROADMAP.md')) {
|
|
870
|
+
warnings.push(`[REQUIRED] Milestone archive ${archiveDirs[0]}: missing ROADMAP.md snapshot`);
|
|
871
|
+
}
|
|
872
|
+
if (!archiveFiles.includes('STATS.md')) {
|
|
873
|
+
warnings.push(`[REQUIRED] Milestone archive ${archiveDirs[0]}: missing STATS.md summary`);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
// Check for phases/ subdirectory with per-phase artifacts
|
|
877
|
+
const archivePhasesDir = path.join(latestArchive, 'phases');
|
|
878
|
+
if (fs.existsSync(archivePhasesDir)) {
|
|
879
|
+
const phaseDirs = fs.readdirSync(archivePhasesDir)
|
|
880
|
+
.filter(d => fs.statSync(path.join(archivePhasesDir, d)).isDirectory());
|
|
881
|
+
|
|
882
|
+
for (const pd of phaseDirs) {
|
|
883
|
+
const phaseFiles = fs.readdirSync(path.join(archivePhasesDir, pd));
|
|
884
|
+
const hasPlan = phaseFiles.some(f => /^PLAN/i.test(f));
|
|
885
|
+
const hasSummary = phaseFiles.some(f => /^SUMMARY/i.test(f));
|
|
886
|
+
const hasVerification = phaseFiles.some(f => f === 'VERIFICATION.md');
|
|
887
|
+
|
|
888
|
+
if (!hasPlan) warnings.push(`[REQUIRED] Archive phase ${pd}: missing PLAN.md`);
|
|
889
|
+
if (!hasSummary) warnings.push(`[REQUIRED] Archive phase ${pd}: missing SUMMARY.md`);
|
|
890
|
+
if (!hasVerification) warnings.push(`[REQUIRED] Archive phase ${pd}: missing VERIFICATION.md`);
|
|
891
|
+
}
|
|
892
|
+
} else {
|
|
893
|
+
warnings.push(`[REQUIRED] Milestone archive ${archiveDirs[0]}: missing phases/ subdirectory`);
|
|
894
|
+
}
|
|
895
|
+
} catch (_e) { /* best-effort */ }
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
};
|
|
899
|
+
|
|
900
|
+
/**
|
|
901
|
+
* Update convention patterns after a build executor completes.
|
|
902
|
+
* Gated by features.convention_memory config toggle.
|
|
903
|
+
* Non-fatal — convention detection failure never crashes the hook.
|
|
904
|
+
*
|
|
905
|
+
* @param {string} planningDir - Path to .planning directory
|
|
906
|
+
*/
|
|
907
|
+
function updateConventionsAfterBuild(planningDir) {
|
|
908
|
+
try {
|
|
909
|
+
const config = loadFeatureFlag(planningDir, 'convention_memory');
|
|
910
|
+
if (config === false) return;
|
|
911
|
+
|
|
912
|
+
const cwd = process.env.PBR_PROJECT_ROOT || process.cwd();
|
|
913
|
+
const conventions = detectConventions(cwd);
|
|
914
|
+
const totalPatterns = Object.values(conventions).reduce((sum, arr) => sum + arr.length, 0);
|
|
915
|
+
if (totalPatterns > 0) {
|
|
916
|
+
writeConventions(planningDir, conventions);
|
|
917
|
+
logHook('check-subagent-output', 'PostToolUse', 'conventions-updated', { patterns: totalPatterns });
|
|
918
|
+
}
|
|
919
|
+
} catch (_e) {
|
|
920
|
+
// Convention detection failure is non-fatal
|
|
921
|
+
logHook('check-subagent-output', 'PostToolUse', 'conventions-failed', { error: _e.message });
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
/**
|
|
926
|
+
* Log an inline execution decision to .planning/logs/hooks.jsonl for audit evidence.
|
|
927
|
+
* Called by the build skill orchestrator after running shouldInlineExecution.
|
|
928
|
+
*
|
|
929
|
+
* @param {string} planningDir - Path to .planning/ directory
|
|
930
|
+
* @param {object} decision - Result from shouldInlineExecution
|
|
931
|
+
* @param {boolean} decision.inline - Whether inline execution was chosen
|
|
932
|
+
* @param {string} [decision.reason] - Reason for the decision
|
|
933
|
+
* @param {number} [decision.taskCount] - Number of tasks in the plan
|
|
934
|
+
* @param {number} [decision.fileCount] - Number of files in the plan
|
|
935
|
+
* @param {number} [decision.estimatedLines] - Estimated lines of code
|
|
936
|
+
*/
|
|
937
|
+
function logInlineDecision(planningDir, decision) {
|
|
938
|
+
try {
|
|
939
|
+
const logsDir = path.join(planningDir, 'logs');
|
|
940
|
+
if (!fs.existsSync(logsDir)) fs.mkdirSync(logsDir, { recursive: true });
|
|
941
|
+
const logFile = path.join(logsDir, 'hooks.jsonl');
|
|
942
|
+
const entry = JSON.stringify({
|
|
943
|
+
timestamp: new Date().toISOString(),
|
|
944
|
+
hook: 'inline-execution-gate',
|
|
945
|
+
decision: decision.inline ? 'inline' : 'delegate',
|
|
946
|
+
reason: decision.reason || null,
|
|
947
|
+
taskCount: decision.taskCount || 0,
|
|
948
|
+
fileCount: decision.fileCount || 0,
|
|
949
|
+
estimatedLines: decision.estimatedLines || 0
|
|
950
|
+
});
|
|
951
|
+
fs.appendFileSync(logFile, entry + '\n', 'utf8');
|
|
952
|
+
} catch (_e) {
|
|
953
|
+
// Best-effort — never crash the caller
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
/**
|
|
958
|
+
* Validate self-verification data in an executor SUMMARY.md file.
|
|
959
|
+
*/
|
|
960
|
+
function validateSelfCheck(summaryPath, config) {
|
|
961
|
+
if (!config || !config.features || !config.features.self_verification) {
|
|
962
|
+
return [];
|
|
963
|
+
}
|
|
964
|
+
const warnings = [];
|
|
965
|
+
try {
|
|
966
|
+
const content = fs.readFileSync(summaryPath, 'utf8');
|
|
967
|
+
const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
968
|
+
if (!fmMatch) {
|
|
969
|
+
warnings.push('Executor SUMMARY.md missing self_check field — self-verification may not have run');
|
|
970
|
+
return warnings;
|
|
971
|
+
}
|
|
972
|
+
const fm = fmMatch[1];
|
|
973
|
+
if (!/self_check\s*:/i.test(fm)) {
|
|
974
|
+
warnings.push('Executor SUMMARY.md missing self_check field — self-verification may not have run');
|
|
975
|
+
return warnings;
|
|
976
|
+
}
|
|
977
|
+
const failedMatch = fm.match(/failed\s*:\s*(\d+)/);
|
|
978
|
+
const retriesMatch = fm.match(/retries\s*:\s*(\d+)/);
|
|
979
|
+
if (failedMatch && parseInt(failedMatch[1], 10) > 0) {
|
|
980
|
+
const failed = failedMatch[1];
|
|
981
|
+
const retries = retriesMatch ? retriesMatch[1] : '0';
|
|
982
|
+
warnings.push(`Executor self-check reported ${failed} failed must-haves after ${retries} retries`);
|
|
983
|
+
}
|
|
984
|
+
} catch (_e) { /* skip gracefully */ }
|
|
985
|
+
return warnings;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
/**
|
|
989
|
+
* Skills that require AskUserQuestion gate prompts.
|
|
990
|
+
* Value = minimum expected calls (0 = conditional, warn only if zero).
|
|
991
|
+
*/
|
|
992
|
+
const SKILLS_REQUIRING_GATES = {
|
|
993
|
+
health: 1,
|
|
994
|
+
milestone: 1,
|
|
995
|
+
import: 1,
|
|
996
|
+
review: 1,
|
|
997
|
+
discuss: 1,
|
|
998
|
+
build: 0
|
|
999
|
+
};
|
|
1000
|
+
|
|
1001
|
+
/**
|
|
1002
|
+
* Check whether a gate-requiring skill completed without any AskUserQuestion calls.
|
|
1003
|
+
* Called by check-subagent-output.js after subagent completion.
|
|
1004
|
+
*
|
|
1005
|
+
* @param {string} planningDir - Path to .planning/ directory
|
|
1006
|
+
* @param {string} skillName - Active skill name
|
|
1007
|
+
* @returns {string|null} Warning message or null if compliant
|
|
1008
|
+
*/
|
|
1009
|
+
function checkUserGateCompliance(planningDir, skillName) {
|
|
1010
|
+
if (!skillName || !Object.prototype.hasOwnProperty.call(SKILLS_REQUIRING_GATES, skillName)) {
|
|
1011
|
+
return null; // Not a gate-requiring skill
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
const signalPath = path.join(planningDir, '.user-gate-passed');
|
|
1015
|
+
|
|
1016
|
+
try {
|
|
1017
|
+
if (!fs.existsSync(signalPath)) {
|
|
1018
|
+
return `Skill '${skillName}' completed without any AskUserQuestion calls. This skill has gate-prompt references that should require user confirmation.`;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
const signalData = JSON.parse(fs.readFileSync(signalPath, 'utf8'));
|
|
1022
|
+
|
|
1023
|
+
// Check if signal matches current skill
|
|
1024
|
+
if (signalData.skill !== skillName) {
|
|
1025
|
+
return `Skill '${skillName}' completed without any AskUserQuestion calls. This skill has gate-prompt references that should require user confirmation.`;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// Signal exists and matches — clean up
|
|
1029
|
+
try { fs.unlinkSync(signalPath); } catch (_e) { /* best-effort cleanup */ }
|
|
1030
|
+
return null;
|
|
1031
|
+
} catch (_e) {
|
|
1032
|
+
// If signal file exists but can't be parsed, treat as missing
|
|
1033
|
+
return `Skill '${skillName}' completed without any AskUserQuestion calls. This skill has gate-prompt references that should require user confirmation.`;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
module.exports = {
|
|
1038
|
+
AGENT_TO_SKILL,
|
|
1039
|
+
AGENT_OUTPUTS,
|
|
1040
|
+
SKILL_CHECKS,
|
|
1041
|
+
findInPhaseDir,
|
|
1042
|
+
findInQuickDir,
|
|
1043
|
+
checkSummaryCommits,
|
|
1044
|
+
checkDeviationsRequiringReview,
|
|
1045
|
+
logCompliance,
|
|
1046
|
+
checkTriggeredSeeds,
|
|
1047
|
+
checkLearningsRequired,
|
|
1048
|
+
isRecent,
|
|
1049
|
+
getCurrentPhase,
|
|
1050
|
+
checkRoadmapStaleness,
|
|
1051
|
+
logInlineDecision,
|
|
1052
|
+
extractVerificationOutcome,
|
|
1053
|
+
shouldTrackTrust,
|
|
1054
|
+
loadFeatureFlag,
|
|
1055
|
+
updateConventionsAfterBuild,
|
|
1056
|
+
validateSelfCheck,
|
|
1057
|
+
checkUserGateCompliance,
|
|
1058
|
+
SKILLS_REQUIRING_GATES
|
|
1059
|
+
};
|