@sienklogic/plan-build-run 2.21.1 → 2.21.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1331 -323
- package/CLAUDE.md +75 -40
- 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 +151 -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 +234 -0
- package/dashboard/server/routes/config.js +64 -0
- package/dashboard/server/routes/health.js +98 -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 +233 -0
- package/dashboard/server/services/file-watcher.js +105 -0
- package/dashboard/server/services/planning-reader.js +727 -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 +56 -41
- package/plan-build-run/bin/config-schema.json +1298 -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 +101 -0
- package/plugins/pbr/agents/audit.md +207 -89
- package/plugins/pbr/agents/codebase-mapper.md +158 -23
- package/plugins/pbr/agents/debugger.md +210 -34
- package/plugins/pbr/agents/dev-sync.md +206 -0
- package/plugins/pbr/agents/executor.md +734 -38
- package/plugins/pbr/agents/general.md +69 -5
- package/plugins/pbr/agents/integration-checker.md +147 -31
- package/plugins/pbr/agents/intel-updater.md +332 -0
- package/plugins/pbr/agents/nyquist-auditor.md +254 -0
- package/plugins/pbr/agents/plan-checker.md +268 -65
- package/plugins/pbr/agents/planner.md +449 -41
- package/plugins/pbr/agents/researcher.md +218 -37
- package/plugins/pbr/agents/roadmapper.md +398 -0
- package/plugins/pbr/agents/synthesizer.md +166 -25
- package/plugins/pbr/agents/ui-checker.md +204 -0
- package/plugins/pbr/agents/ui-researcher.md +224 -0
- package/plugins/pbr/agents/verifier.md +570 -46
- 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/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 +76 -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 +213 -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 +227 -0
- package/plugins/pbr/dist/check-read-first.js +345 -0
- package/plugins/pbr/dist/check-roadmap-sync.js +507 -0
- package/plugins/pbr/dist/check-skill-workflow.js +354 -0
- package/plugins/pbr/dist/check-state-sync.js +676 -0
- package/plugins/pbr/dist/check-subagent-output.js +425 -0
- package/plugins/pbr/dist/check-summary-gate.js +188 -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 +212 -0
- package/plugins/pbr/dist/event-logger.js +125 -0
- package/plugins/pbr/dist/feedback-loop.js +155 -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 +664 -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 +367 -0
- package/plugins/pbr/dist/log-tool-failure.js +140 -0
- package/plugins/pbr/dist/milestone-learnings.js +519 -0
- package/plugins/pbr/dist/pbr-tools.js +493 -0
- package/plugins/pbr/dist/post-bash-triage.js +96 -0
- package/plugins/pbr/dist/post-compact.js +135 -0
- package/plugins/pbr/dist/post-hoc.js +237 -0
- package/plugins/pbr/dist/post-write-dispatch.js +243 -0
- package/plugins/pbr/dist/post-write-quality.js +208 -0
- package/plugins/pbr/dist/pre-bash-dispatch.js +212 -0
- package/plugins/pbr/dist/pre-skill-dispatch.js +114 -0
- package/plugins/pbr/dist/pre-task-dispatch.js +269 -0
- package/plugins/pbr/dist/pre-write-dispatch.js +234 -0
- package/plugins/pbr/dist/progress-tracker.js +173 -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 +132 -0
- package/plugins/pbr/dist/session-cleanup.js +653 -0
- package/plugins/pbr/dist/session-tracker.js +124 -0
- package/plugins/pbr/dist/status-line.js +849 -0
- package/plugins/pbr/dist/suggest-compact.js +307 -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 +233 -0
- package/plugins/pbr/dist/validate-skill-args.js +222 -0
- package/plugins/pbr/dist/validate-task.js +271 -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 +137 -65
- package/plugins/pbr/references/agent-contracts.md +39 -8
- 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/assumptions.md +42 -0
- package/plugins/pbr/references/checkpoints.md +723 -104
- package/plugins/pbr/references/config-reference.md +387 -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/few-shot-examples/audit.md +77 -0
- package/plugins/pbr/references/few-shot-examples/check-plan-format.md +172 -0
- package/plugins/pbr/references/few-shot-examples/check-subagent-output.md +118 -0
- package/plugins/pbr/references/few-shot-examples/integration-checker.md +70 -0
- package/plugins/pbr/references/few-shot-examples/nyquist-auditor.md +83 -0
- package/plugins/pbr/references/few-shot-examples/plan-checker.md +73 -0
- package/plugins/pbr/references/few-shot-examples/ui-checker.md +71 -0
- package/plugins/pbr/references/few-shot-examples/verifier.md +109 -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 +184 -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/thinking-models-planning.md +47 -0
- package/plugins/pbr/references/thinking-models-verification.md +44 -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 +76 -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 +455 -0
- package/plugins/pbr/scripts/audit-checks/session-quality.js +980 -0
- package/plugins/pbr/scripts/audit-checks/si-agent-hook-config-checks.js +396 -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 +1175 -0
- package/plugins/pbr/scripts/audit-dimensions.js +556 -0
- package/plugins/pbr/scripts/auto-continue.js +192 -37
- 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 +84 -1
- 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 -2
- package/plugins/pbr/scripts/check-plan-format.js +153 -354
- package/plugins/pbr/scripts/check-read-first.js +345 -0
- package/plugins/pbr/scripts/check-roadmap-sync.js +174 -19
- package/plugins/pbr/scripts/check-skill-workflow.js +21 -16
- package/plugins/pbr/scripts/check-state-sync.js +352 -220
- package/plugins/pbr/scripts/check-subagent-output.js +296 -333
- package/plugins/pbr/scripts/check-summary-gate.js +5 -15
- package/plugins/pbr/scripts/commands/benchmarks.js +195 -0
- package/plugins/pbr/scripts/commands/calibrate.js +530 -0
- package/plugins/pbr/scripts/commands/config.js +72 -0
- package/plugins/pbr/scripts/commands/misc.js +779 -0
- package/plugins/pbr/scripts/commands/phase.js +293 -0
- package/plugins/pbr/scripts/commands/roadmap.js +75 -0
- package/plugins/pbr/scripts/commands/state.js +84 -0
- package/plugins/pbr/scripts/commands/stress-test.js +349 -0
- package/plugins/pbr/scripts/commands/todo.js +191 -0
- package/plugins/pbr/scripts/commands/verify.js +169 -0
- package/plugins/pbr/scripts/config-schema.json +1183 -95
- package/plugins/pbr/scripts/context-bridge.js +425 -0
- package/plugins/pbr/scripts/context-budget-check.js +171 -16
- 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 +137 -87
- package/plugins/pbr/scripts/event-logger.js +58 -25
- package/plugins/pbr/scripts/feedback-loop.js +155 -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 +664 -0
- package/plugins/pbr/scripts/hooks-schema.json +12 -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 +123 -0
- package/plugins/pbr/scripts/lib/benchmark.js +190 -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/commands.js +483 -0
- package/plugins/pbr/scripts/lib/compound.js +222 -0
- package/plugins/pbr/scripts/lib/config-cache.js +83 -0
- package/plugins/pbr/scripts/lib/config.js +1469 -0
- package/plugins/pbr/scripts/lib/context.js +254 -0
- package/plugins/pbr/scripts/lib/contextual-help.js +183 -0
- package/plugins/pbr/scripts/lib/convention-detector.js +413 -0
- package/plugins/pbr/scripts/lib/core.js +1585 -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 +1049 -0
- package/plugins/pbr/scripts/lib/frontmatter.js +302 -0
- package/plugins/pbr/scripts/lib/gates/advisories.js +133 -0
- package/plugins/pbr/scripts/lib/gates/build-dependency.js +118 -0
- package/plugins/pbr/scripts/lib/gates/build-executor.js +106 -0
- package/plugins/pbr/scripts/lib/gates/doc-existence.js +46 -0
- package/plugins/pbr/scripts/lib/gates/helpers.js +98 -0
- package/plugins/pbr/scripts/lib/gates/inline-execution.js +187 -0
- package/plugins/pbr/scripts/lib/gates/milestone-complete.js +139 -0
- package/plugins/pbr/scripts/lib/gates/milestone-summary.js +121 -0
- package/plugins/pbr/scripts/lib/gates/multi-phase-loader.js +149 -0
- package/plugins/pbr/scripts/lib/gates/plan-executor.js +36 -0
- package/plugins/pbr/scripts/lib/gates/plan-validation.js +115 -0
- package/plugins/pbr/scripts/lib/gates/quick-executor.js +78 -0
- package/plugins/pbr/scripts/lib/gates/review-planner.js +63 -0
- package/plugins/pbr/scripts/lib/gates/review-verifier.js +71 -0
- package/plugins/pbr/scripts/lib/gates/rich-agent-context.js +148 -0
- package/plugins/pbr/scripts/lib/gates/sprint-preflight.js +30 -0
- package/plugins/pbr/scripts/lib/gates/user-confirmation.js +95 -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/handoff-validators.js +224 -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 +132 -0
- package/plugins/pbr/scripts/lib/help.js +100 -0
- package/plugins/pbr/scripts/lib/history.js +150 -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/migrate.js +309 -0
- package/plugins/pbr/scripts/lib/milestone.js +306 -0
- package/plugins/pbr/scripts/lib/msys-path.js +20 -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 +1043 -0
- package/plugins/pbr/scripts/lib/pid-lock.js +156 -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 +126 -0
- package/plugins/pbr/scripts/lib/premature-completion.js +312 -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 +1089 -0
- package/plugins/pbr/scripts/lib/security-scan.js +200 -0
- package/plugins/pbr/scripts/lib/session-briefing.js +918 -0
- package/plugins/pbr/scripts/lib/skill-section.js +99 -0
- package/plugins/pbr/scripts/lib/smart-next-task.js +198 -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 +539 -0
- package/plugins/pbr/scripts/lib/state-queue.js +171 -0
- package/plugins/pbr/scripts/lib/state.js +1082 -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 +1119 -0
- package/plugins/pbr/scripts/lib/suggest-next.js +435 -0
- package/plugins/pbr/scripts/lib/tech-debt-scanner.js +116 -0
- package/plugins/pbr/scripts/lib/templates.js +362 -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/verify.js +1561 -0
- package/plugins/pbr/scripts/log-notification.js +131 -0
- package/plugins/pbr/scripts/log-subagent.js +221 -18
- package/plugins/pbr/scripts/log-tool-failure.js +60 -5
- package/plugins/pbr/scripts/milestone-learnings.js +519 -0
- package/plugins/pbr/scripts/package.json +1 -1
- package/plugins/pbr/scripts/pbr-tools.js +362 -1247
- package/plugins/pbr/scripts/post-bash-triage.js +96 -0
- package/plugins/pbr/scripts/post-compact.js +135 -0
- package/plugins/pbr/scripts/post-hoc.js +237 -0
- package/plugins/pbr/scripts/post-write-dispatch.js +201 -31
- package/plugins/pbr/scripts/post-write-quality.js +4 -3
- package/plugins/pbr/scripts/pre-bash-dispatch.js +147 -51
- package/plugins/pbr/scripts/pre-skill-dispatch.js +114 -0
- package/plugins/pbr/scripts/pre-task-dispatch.js +269 -0
- package/plugins/pbr/scripts/pre-write-dispatch.js +170 -72
- package/plugins/pbr/scripts/progress-tracker.js +121 -324
- 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 +63 -23
- package/plugins/pbr/scripts/session-cleanup.js +428 -29
- package/plugins/pbr/scripts/session-tracker.js +124 -0
- package/plugins/pbr/scripts/status-line.js +571 -43
- package/plugins/pbr/scripts/suggest-compact.js +201 -13
- 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 +120 -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 +155 -0
- package/plugins/pbr/scripts/track-context-budget.js +368 -104
- 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 +51 -19
- package/plugins/pbr/scripts/validate-skill-args.js +85 -14
- package/plugins/pbr/scripts/validate-task.js +83 -622
- 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 +551 -0
- package/plugins/pbr/skills/backlog/SKILL.md +56 -0
- package/plugins/pbr/skills/begin/SKILL.md +508 -153
- package/plugins/pbr/skills/begin/templates/STATE.md.tmpl +1 -2
- package/plugins/pbr/skills/begin/templates/config.json.tmpl +419 -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 +1180 -357
- 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/build/templates/qa-round-context.md.tmpl +16 -0
- package/plugins/pbr/skills/config/SKILL.md +112 -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 +205 -24
- 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 +35 -115
- package/plugins/pbr/skills/help/SKILL.md +83 -123
- 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 +383 -274
- 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 +54 -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 +20 -2
- package/plugins/pbr/skills/plan/templates/completion-output.md.tmpl +27 -0
- package/plugins/pbr/skills/plan/templates/planner-prompt.md.tmpl +43 -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 +227 -0
- package/plugins/pbr/skills/quick/SKILL.md +435 -100
- package/plugins/pbr/skills/release/SKILL.md +206 -0
- package/plugins/pbr/skills/resume/SKILL.md +170 -46
- package/plugins/pbr/skills/review/SKILL.md +233 -165
- package/plugins/pbr/skills/review/templates/verifier-prompt.md.tmpl +7 -0
- package/plugins/pbr/skills/scan/SKILL.md +152 -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 +150 -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/criterion-writing.md +58 -0
- 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 +46 -61
- 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 +110 -0
- package/plugins/pbr/skills/status/SKILL.md +185 -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 +106 -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 +54 -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 -704
- 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 -258
- package/dashboard/src/services/sse.service.js +0 -58
- package/dashboard/src/services/todo.service.js +0 -272
- 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 -43
- package/dashboard/src/views/partials/layout-top.ejs +0 -16
- 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 -180
- 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 -97
- 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 -184
- package/plugins/copilot-pbr/agents/executor.agent.md +0 -269
- package/plugins/copilot-pbr/agents/general.agent.md +0 -89
- package/plugins/copilot-pbr/agents/integration-checker.agent.md +0 -121
- package/plugins/copilot-pbr/agents/plan-checker.agent.md +0 -208
- package/plugins/copilot-pbr/agents/planner.agent.md +0 -240
- package/plugins/copilot-pbr/agents/researcher.agent.md +0 -188
- 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 -258
- 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 -959
- 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 -283
- 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 -193
- package/plugins/copilot-pbr/skills/import/SKILL.md +0 -502
- package/plugins/copilot-pbr/skills/milestone/SKILL.md +0 -806
- 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-recovery-strategies.md +0 -51
- 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 -170
- 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 -48
- 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 -183
- package/plugins/cursor-pbr/agents/executor.md +0 -268
- package/plugins/cursor-pbr/agents/general.md +0 -88
- package/plugins/cursor-pbr/agents/integration-checker.md +0 -120
- package/plugins/cursor-pbr/agents/plan-checker.md +0 -207
- package/plugins/cursor-pbr/agents/planner.md +0 -239
- package/plugins/cursor-pbr/agents/researcher.md +0 -187
- 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 -224
- 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 -960
- 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 -283
- 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 -193
- package/plugins/cursor-pbr/skills/import/SKILL.md +0 -505
- package/plugins/cursor-pbr/skills/milestone/SKILL.md +0 -807
- 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-recovery-strategies.md +0 -51
- 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 -170
- 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 -48
- 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/error-recovery-strategies.md +0 -51
- 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
|
@@ -3,1376 +3,491 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* pbr-tools.js — Structured JSON state operations for Plan-Build-Run skills.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Thin router that delegates CLI commands to handler modules in commands/.
|
|
7
|
+
* Core logic lives in lib/ modules. Wrapper functions here provide backward
|
|
8
|
+
* compatibility for hook scripts and tests that require('./pbr-tools').
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
* state
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* phase-info <phase> — Comprehensive single-phase status → JSON
|
|
19
|
-
* roadmap update-status <phase> <status> — Update phase status in ROADMAP.md
|
|
20
|
-
* roadmap update-plans <phase> <complete> <total> — Update phase plans in ROADMAP.md
|
|
21
|
-
* history append <type> <title> [body] — Append record to HISTORY.md
|
|
22
|
-
* history load — Load all HISTORY.md records as JSON
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
const fs = require('fs');
|
|
26
|
-
const path = require('path');
|
|
27
|
-
|
|
28
|
-
const cwd = process.cwd();
|
|
29
|
-
const planningDir = path.join(cwd, '.planning');
|
|
30
|
-
|
|
31
|
-
// --- Phase status transition state machine ---
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Valid phase status transitions. Each key is a current status, and its value
|
|
35
|
-
* is an array of statuses that are legal to transition to. This is advisory —
|
|
36
|
-
* invalid transitions produce a stderr warning but are not blocked, to avoid
|
|
37
|
-
* breaking existing workflows.
|
|
10
|
+
* Command modules:
|
|
11
|
+
* commands/state.js — state, state-bundle
|
|
12
|
+
* commands/config.js — config, validate
|
|
13
|
+
* commands/roadmap.js — roadmap
|
|
14
|
+
* commands/phase.js — phase, compound, init, plan-index, frontmatter, must-haves, phase-info, milestone-stats
|
|
15
|
+
* commands/verify.js — verify, spot-check, staleness-check, summary-gate, checkpoint, seeds
|
|
16
|
+
* commands/todo.js — todo, history, auto-cleanup
|
|
17
|
+
* commands/misc.js — all remaining (intel, learnings, session, claim, spec, help, etc.)
|
|
38
18
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* planned -> building
|
|
42
|
-
* building -> built, partial, needs_fixes
|
|
43
|
-
* built -> verified, needs_fixes
|
|
44
|
-
* partial -> building, needs_fixes
|
|
45
|
-
* verified -> building (re-execution)
|
|
46
|
-
* needs_fixes -> planned, building
|
|
47
|
-
* skipped -> pending (unskip)
|
|
48
|
-
*/
|
|
49
|
-
const VALID_STATUS_TRANSITIONS = {
|
|
50
|
-
pending: ['planned', 'skipped'],
|
|
51
|
-
planned: ['building'],
|
|
52
|
-
building: ['built', 'partial', 'needs_fixes'],
|
|
53
|
-
built: ['verified', 'needs_fixes'],
|
|
54
|
-
partial: ['building', 'needs_fixes'],
|
|
55
|
-
verified: ['building'],
|
|
56
|
-
needs_fixes: ['planned', 'building'],
|
|
57
|
-
skipped: ['pending']
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Check whether a phase status transition is valid according to the state machine.
|
|
62
|
-
* Returns { valid, warning? } — never blocks, only advises.
|
|
19
|
+
* Usage: node ${CLAUDE_PLUGIN_ROOT}/scripts/pbr-tools.js <command> [args]
|
|
20
|
+
* Run `pbr-tools.js help` for full command listing.
|
|
63
21
|
*
|
|
64
|
-
*
|
|
65
|
-
* @param {string} newStatus - Desired phase status
|
|
66
|
-
* @returns {{ valid: boolean, warning?: string }}
|
|
22
|
+
* Environment: PBR_PROJECT_ROOT — Override project root directory
|
|
67
23
|
*/
|
|
68
|
-
function validateStatusTransition(oldStatus, newStatus) {
|
|
69
|
-
const from = (oldStatus || '').trim().toLowerCase();
|
|
70
|
-
const to = (newStatus || '').trim().toLowerCase();
|
|
71
24
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return { valid: true };
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// If the old status is unknown to our map, we can't validate — allow it
|
|
78
|
-
if (!VALID_STATUS_TRANSITIONS[from]) {
|
|
79
|
-
return { valid: true };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const allowed = VALID_STATUS_TRANSITIONS[from];
|
|
83
|
-
if (allowed.includes(to)) {
|
|
84
|
-
return { valid: true };
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
valid: false,
|
|
89
|
-
warning: `Suspicious status transition: "${from}" -> "${to}". Expected one of: [${allowed.join(', ')}]. Proceeding anyway (advisory).`
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// --- Cached config loader ---
|
|
25
|
+
const fs = require('fs');
|
|
26
|
+
const path = require('path');
|
|
94
27
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
28
|
+
// --- Import lib modules (used by wrapper functions for backward-compat exports) ---
|
|
29
|
+
const { KNOWN_AGENTS, VALID_STATUS_TRANSITIONS, validateStatusTransition, output, error,
|
|
30
|
+
parseYamlFrontmatter, parseMustHaves, findFiles, tailLines, countMustHaves,
|
|
31
|
+
determinePhaseStatus, atomicWrite, lockedFileUpdate, writeActiveSkill,
|
|
32
|
+
sessionLoad, sessionSave, SESSION_ALLOWED_KEYS, acquireClaim, releaseClaim,
|
|
33
|
+
listClaims: _listClaims } = require('./lib/core');
|
|
34
|
+
const { configLoad: _configLoad, configClearCache: _configClearCache,
|
|
35
|
+
configValidate: _configValidate, resolveDepthProfile, DEPTH_PROFILE_DEFAULTS,
|
|
36
|
+
loadUserDefaults, saveUserDefaults, mergeUserDefaults, USER_DEFAULTS_PATH } = require('./lib/config');
|
|
37
|
+
const { parseStateMd, updateFrontmatterField, stateLoad: _stateLoad,
|
|
38
|
+
stateCheckProgress: _stateCheckProgress, stateUpdate: _stateUpdate,
|
|
39
|
+
statePatch: _statePatch, stateAdvancePlan: _stateAdvancePlan,
|
|
40
|
+
stateRecordMetric: _stateRecordMetric, stateRecordActivity: _stateRecordActivity,
|
|
41
|
+
stateUpdateProgress: _stateUpdateProgress, stateReconcile: _stateReconcile,
|
|
42
|
+
stateBackup: _stateBackup } = require('./lib/state');
|
|
43
|
+
const { parseRoadmapMd, findRoadmapRow, updateTableRow,
|
|
44
|
+
roadmapUpdateStatus: _roadmapUpdateStatus, roadmapUpdatePlans: _roadmapUpdatePlans,
|
|
45
|
+
roadmapAnalyze: _roadmapAnalyze } = require('./lib/roadmap');
|
|
46
|
+
const { frontmatter: _frontmatter, planIndex: _planIndex,
|
|
47
|
+
mustHavesCollect: _mustHavesCollect, phaseInfo: _phaseInfo, phaseAdd: _phaseAdd,
|
|
48
|
+
phaseRemove: _phaseRemove, phaseList: _phaseList, milestoneStats: _milestoneStats,
|
|
49
|
+
phaseComplete: _phaseComplete, phaseInsert: _phaseInsert,
|
|
50
|
+
phaseNextNumber: _phaseNextNumber } = require('./lib/phase');
|
|
51
|
+
const { compoundInitPhase: _compoundInitPhase, compoundCompletePhase: _compoundCompletePhase,
|
|
52
|
+
compoundInitMilestone: _compoundInitMilestone } = require('./lib/compound');
|
|
53
|
+
const { initExecutePhase: _initExecutePhase, initPlanPhase: _initPlanPhase,
|
|
54
|
+
initQuick: _initQuick, initVerifyWork: _initVerifyWork, initResume: _initResume,
|
|
55
|
+
initProgress: _initProgress, initStateBundle: _initStateBundle,
|
|
56
|
+
initContinue: _initContinue, initMilestone: _initMilestone, initBegin: _initBegin,
|
|
57
|
+
initStatus: _initStatus, initMapCodebase: _initMapCodebase } = require('./lib/init');
|
|
58
|
+
const { historyAppend: _historyAppend, historyLoad: _historyLoad } = require('./lib/history');
|
|
59
|
+
const { todoList: _todoList, todoGet: _todoGet, todoAdd: _todoAdd, todoDone: _todoDone } = require('./lib/todo');
|
|
60
|
+
const { autoCloseTodos: _autoCloseTodos, autoArchiveNotes: _autoArchiveNotes } = require('./lib/auto-cleanup');
|
|
61
|
+
const { applyMigrations: _applyMigrations } = require('./lib/migrate');
|
|
62
|
+
const { verifySpotCheck: _verifySpotCheck } = require('./lib/spot-check');
|
|
63
|
+
const { referenceGet: _referenceGet } = require('./lib/reference');
|
|
64
|
+
const { skillSection: _skillSection, listAvailableSkills: _listAvailableSkills } = require('./lib/skill-section');
|
|
65
|
+
const { helpList: _helpList, skillMetadata: _skillMetadata } = require('./lib/help');
|
|
66
|
+
const { stepVerify: _stepVerify } = require('./lib/step-verify');
|
|
67
|
+
const { contextTriage: _contextTriage } = require('./lib/context');
|
|
68
|
+
const { phaseAlternatives: _phaseAlternatives, prerequisiteAlternatives: _prereqAlternatives,
|
|
69
|
+
configAlternatives: _configAlternatives } = require('./lib/alternatives');
|
|
70
|
+
const { stalenessCheck: _stalenessCheck, summaryGate: _summaryGate,
|
|
71
|
+
checkpointInit: _checkpointInit, checkpointUpdate: _checkpointUpdate,
|
|
72
|
+
seedsMatch: _seedsMatch, ciPoll: _ciPoll, rollback: _rollback } = require('./lib/build');
|
|
73
|
+
const { parseJestOutput: _parseJestOutput, parseLintOutput: _parseLintOutput,
|
|
74
|
+
autoFixLint: _autoFixLint, runCiFixLoop: _runCiFixLoop } = require('./lib/ci-fix-loop');
|
|
75
|
+
const { quickStatus: _quickStatus } = require('./quick-status');
|
|
76
|
+
|
|
77
|
+
// --- Command modules (CLI dispatch handlers) ---
|
|
78
|
+
const { handleState, handleStateBundle } = require('./commands/state');
|
|
79
|
+
const { handleConfig } = require('./commands/config');
|
|
80
|
+
const { handleRoadmap } = require('./commands/roadmap');
|
|
81
|
+
const { handlePhase, handleCompound, handleInit, handlePhaseDirect } = require('./commands/phase');
|
|
82
|
+
const { handleVerify, handleSpotCheckDirect, handleStalenessCheck, handleSummaryGate, handleCheckpoint, handleSeeds } = require('./commands/verify');
|
|
83
|
+
const { handleTodo, handleHistory, handleAutoCleanup } = require('./commands/todo');
|
|
84
|
+
const { handleMisc } = require('./commands/misc');
|
|
85
|
+
const { handleBenchmarks } = require('./commands/benchmarks');
|
|
86
|
+
const { handleCalibrate } = require('./commands/calibrate');
|
|
87
|
+
const { handleStressTest } = require('./commands/stress-test');
|
|
88
|
+
const { normalizeMsysPath } = require('./lib/msys-path');
|
|
89
|
+
|
|
90
|
+
// --- Module-level state (for backwards compatibility) ---
|
|
91
|
+
|
|
92
|
+
let cwd = process.env.PBR_PROJECT_ROOT || process.cwd();
|
|
93
|
+
cwd = normalizeMsysPath(cwd);
|
|
94
|
+
let planningDir = path.join(cwd, '.planning');
|
|
95
|
+
|
|
96
|
+
// --- Wrapper functions that pass planningDir to lib modules ---
|
|
97
|
+
// These preserve the original function signatures (no planningDir param)
|
|
98
|
+
// so existing callers (hook scripts, tests) continue to work.
|
|
98
99
|
|
|
99
|
-
/**
|
|
100
|
-
* Load config.json with in-process mtime-based caching.
|
|
101
|
-
* Returns the parsed config object, or null if not found / parse error.
|
|
102
|
-
* Cache invalidates when file mtime changes or path differs.
|
|
103
|
-
*
|
|
104
|
-
* @param {string} [dir] - Path to .planning directory (defaults to cwd/.planning)
|
|
105
|
-
* @returns {object|null} Parsed config or null
|
|
106
|
-
*/
|
|
107
100
|
function configLoad(dir) {
|
|
108
|
-
|
|
109
|
-
try {
|
|
110
|
-
if (!fs.existsSync(configPath)) return null;
|
|
111
|
-
const stat = fs.statSync(configPath);
|
|
112
|
-
const mtime = stat.mtimeMs;
|
|
113
|
-
if (_configCache && mtime === _configMtime && configPath === _configPath) {
|
|
114
|
-
return _configCache;
|
|
115
|
-
}
|
|
116
|
-
_configCache = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
117
|
-
_configMtime = mtime;
|
|
118
|
-
_configPath = configPath;
|
|
119
|
-
return _configCache;
|
|
120
|
-
} catch (_e) {
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
101
|
+
return _configLoad(dir || planningDir);
|
|
123
102
|
}
|
|
124
103
|
|
|
125
|
-
/**
|
|
126
|
-
* Clear the configLoad() in-process cache.
|
|
127
|
-
* Useful in tests where multiple temp directories are used in rapid succession.
|
|
128
|
-
*/
|
|
129
104
|
function configClearCache() {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
105
|
+
_configClearCache();
|
|
106
|
+
cwd = process.env.PBR_PROJECT_ROOT || process.cwd();
|
|
107
|
+
cwd = normalizeMsysPath(cwd);
|
|
108
|
+
planningDir = path.join(cwd, '.planning');
|
|
133
109
|
}
|
|
134
110
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
* Reads the entire file but only parses (JSON.parse) the trailing entries.
|
|
138
|
-
* For JSONL files where full parsing is expensive, this avoids parsing
|
|
139
|
-
* all lines when you only need recent entries.
|
|
140
|
-
*
|
|
141
|
-
* @param {string} filePath - Absolute path to the file
|
|
142
|
-
* @param {number} n - Number of trailing lines to return
|
|
143
|
-
* @returns {string[]} Array of raw line strings (last n lines)
|
|
144
|
-
*/
|
|
145
|
-
function tailLines(filePath, n) {
|
|
146
|
-
try {
|
|
147
|
-
if (!fs.existsSync(filePath)) return [];
|
|
148
|
-
const content = fs.readFileSync(filePath, 'utf8').trim();
|
|
149
|
-
if (!content) return [];
|
|
150
|
-
const lines = content.split('\n');
|
|
151
|
-
if (lines.length <= n) return lines;
|
|
152
|
-
return lines.slice(lines.length - n);
|
|
153
|
-
} catch (_e) {
|
|
154
|
-
return [];
|
|
155
|
-
}
|
|
111
|
+
function configValidate(preloadedConfig) {
|
|
112
|
+
return _configValidate(preloadedConfig, planningDir);
|
|
156
113
|
}
|
|
157
114
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
*/
|
|
162
|
-
const DEPTH_PROFILE_DEFAULTS = {
|
|
163
|
-
quick: {
|
|
164
|
-
'features.research_phase': false,
|
|
165
|
-
'features.plan_checking': false,
|
|
166
|
-
'features.goal_verification': false,
|
|
167
|
-
'features.inline_verify': false,
|
|
168
|
-
'scan.mapper_count': 2,
|
|
169
|
-
'scan.mapper_areas': ['tech', 'arch'],
|
|
170
|
-
'debug.max_hypothesis_rounds': 3
|
|
171
|
-
},
|
|
172
|
-
standard: {
|
|
173
|
-
'features.research_phase': true,
|
|
174
|
-
'features.plan_checking': true,
|
|
175
|
-
'features.goal_verification': true,
|
|
176
|
-
'features.inline_verify': false,
|
|
177
|
-
'scan.mapper_count': 4,
|
|
178
|
-
'scan.mapper_areas': ['tech', 'arch', 'quality', 'concerns'],
|
|
179
|
-
'debug.max_hypothesis_rounds': 5
|
|
180
|
-
},
|
|
181
|
-
comprehensive: {
|
|
182
|
-
'features.research_phase': true,
|
|
183
|
-
'features.plan_checking': true,
|
|
184
|
-
'features.goal_verification': true,
|
|
185
|
-
'features.inline_verify': true,
|
|
186
|
-
'scan.mapper_count': 4,
|
|
187
|
-
'scan.mapper_areas': ['tech', 'arch', 'quality', 'concerns'],
|
|
188
|
-
'debug.max_hypothesis_rounds': 10
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Resolve the effective depth profile for the current config.
|
|
194
|
-
* Merges built-in defaults with any user overrides from config.depth_profiles.
|
|
195
|
-
*
|
|
196
|
-
* @param {object|null} config - Parsed config.json (from configLoad). If null, returns 'standard' defaults.
|
|
197
|
-
* @returns {{ depth: string, profile: object }} The resolved depth name and flattened profile settings.
|
|
198
|
-
*/
|
|
199
|
-
function resolveDepthProfile(config) {
|
|
200
|
-
const depth = (config && config.depth) || 'standard';
|
|
201
|
-
const defaults = DEPTH_PROFILE_DEFAULTS[depth] || DEPTH_PROFILE_DEFAULTS.standard;
|
|
202
|
-
|
|
203
|
-
// Merge user overrides if present
|
|
204
|
-
const userOverrides = (config && config.depth_profiles && config.depth_profiles[depth]) || {};
|
|
205
|
-
const profile = { ...defaults, ...userOverrides };
|
|
115
|
+
function stateLoad() {
|
|
116
|
+
return _stateLoad(planningDir);
|
|
117
|
+
}
|
|
206
118
|
|
|
207
|
-
|
|
119
|
+
function stateCheckProgress() {
|
|
120
|
+
return _stateCheckProgress(planningDir);
|
|
208
121
|
}
|
|
209
122
|
|
|
210
|
-
function
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const subcommand = args[1];
|
|
123
|
+
function stateUpdate(field, value) {
|
|
124
|
+
return _stateUpdate(field, value, planningDir);
|
|
125
|
+
}
|
|
214
126
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
output(stateLoad());
|
|
218
|
-
} else if (command === 'state' && subcommand === 'check-progress') {
|
|
219
|
-
output(stateCheckProgress());
|
|
220
|
-
} else if (command === 'state' && subcommand === 'update') {
|
|
221
|
-
const field = args[2];
|
|
222
|
-
const value = args[3];
|
|
223
|
-
if (!field || value === undefined) {
|
|
224
|
-
error('Usage: pbr-tools.js state update <field> <value>\nFields: current_phase, status, plans_complete, last_activity');
|
|
225
|
-
}
|
|
226
|
-
output(stateUpdate(field, value));
|
|
227
|
-
} else if (command === 'config' && subcommand === 'validate') {
|
|
228
|
-
output(configValidate());
|
|
229
|
-
} else if (command === 'config' && subcommand === 'resolve-depth') {
|
|
230
|
-
const dir = args[2] || undefined;
|
|
231
|
-
const config = configLoad(dir);
|
|
232
|
-
output(resolveDepthProfile(config));
|
|
233
|
-
} else if (command === 'plan-index') {
|
|
234
|
-
const phase = args[1];
|
|
235
|
-
if (!phase) {
|
|
236
|
-
error('Usage: pbr-tools.js plan-index <phase-number>');
|
|
237
|
-
}
|
|
238
|
-
output(planIndex(phase));
|
|
239
|
-
} else if (command === 'frontmatter') {
|
|
240
|
-
const filePath = args[1];
|
|
241
|
-
if (!filePath) {
|
|
242
|
-
error('Usage: pbr-tools.js frontmatter <filepath>');
|
|
243
|
-
}
|
|
244
|
-
output(frontmatter(filePath));
|
|
245
|
-
} else if (command === 'must-haves') {
|
|
246
|
-
const phase = args[1];
|
|
247
|
-
if (!phase) {
|
|
248
|
-
error('Usage: pbr-tools.js must-haves <phase-number>');
|
|
249
|
-
}
|
|
250
|
-
output(mustHavesCollect(phase));
|
|
251
|
-
} else if (command === 'phase-info') {
|
|
252
|
-
const phase = args[1];
|
|
253
|
-
if (!phase) {
|
|
254
|
-
error('Usage: pbr-tools.js phase-info <phase-number>');
|
|
255
|
-
}
|
|
256
|
-
output(phaseInfo(phase));
|
|
257
|
-
} else if (command === 'roadmap' && subcommand === 'update-status') {
|
|
258
|
-
const phase = args[2];
|
|
259
|
-
const status = args[3];
|
|
260
|
-
if (!phase || !status) {
|
|
261
|
-
error('Usage: pbr-tools.js roadmap update-status <phase-number> <status>');
|
|
262
|
-
}
|
|
263
|
-
output(roadmapUpdateStatus(phase, status));
|
|
264
|
-
} else if (command === 'roadmap' && subcommand === 'update-plans') {
|
|
265
|
-
const phase = args[2];
|
|
266
|
-
const complete = args[3];
|
|
267
|
-
const total = args[4];
|
|
268
|
-
if (!phase || complete === undefined || total === undefined) {
|
|
269
|
-
error('Usage: pbr-tools.js roadmap update-plans <phase-number> <complete> <total>');
|
|
270
|
-
}
|
|
271
|
-
output(roadmapUpdatePlans(phase, complete, total));
|
|
272
|
-
} else if (command === 'history' && subcommand === 'append') {
|
|
273
|
-
const type = args[2]; // 'milestone' or 'phase'
|
|
274
|
-
const title = args[3];
|
|
275
|
-
const body = args[4] || '';
|
|
276
|
-
if (!type || !title) {
|
|
277
|
-
error('Usage: pbr-tools.js history append <milestone|phase> <title> [body]');
|
|
278
|
-
}
|
|
279
|
-
output(historyAppend({ type, title, body }));
|
|
280
|
-
} else if (command === 'history' && subcommand === 'load') {
|
|
281
|
-
output(historyLoad());
|
|
282
|
-
} else if (command === 'event') {
|
|
283
|
-
const category = args[1];
|
|
284
|
-
const event = args[2];
|
|
285
|
-
let details = {};
|
|
286
|
-
if (args[3]) {
|
|
287
|
-
try { details = JSON.parse(args[3]); } catch (_e) { details = { raw: args[3] }; }
|
|
288
|
-
}
|
|
289
|
-
if (!category || !event) {
|
|
290
|
-
error('Usage: pbr-tools.js event <category> <event> [JSON-details]');
|
|
291
|
-
}
|
|
292
|
-
const { logEvent } = require('./event-logger');
|
|
293
|
-
logEvent(category, event, details);
|
|
294
|
-
output({ logged: true, category, event });
|
|
295
|
-
} else {
|
|
296
|
-
error(`Unknown command: ${args.join(' ')}\nCommands: state load|check-progress|update, config validate, plan-index, frontmatter, must-haves, phase-info, roadmap update-status|update-plans, history append|load, event`);
|
|
297
|
-
}
|
|
298
|
-
} catch (e) {
|
|
299
|
-
error(e.message);
|
|
300
|
-
}
|
|
127
|
+
function statePatch(jsonStr) {
|
|
128
|
+
return _statePatch(jsonStr, planningDir);
|
|
301
129
|
}
|
|
302
130
|
|
|
303
|
-
|
|
131
|
+
function stateAdvancePlan() {
|
|
132
|
+
return _stateAdvancePlan(planningDir);
|
|
133
|
+
}
|
|
304
134
|
|
|
305
|
-
function
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
config: null,
|
|
309
|
-
state: null,
|
|
310
|
-
roadmap: null,
|
|
311
|
-
phase_count: 0,
|
|
312
|
-
current_phase: null,
|
|
313
|
-
progress: null
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
if (!fs.existsSync(planningDir)) {
|
|
317
|
-
return result;
|
|
318
|
-
}
|
|
319
|
-
result.exists = true;
|
|
135
|
+
function stateRecordMetric(metricArgs) {
|
|
136
|
+
return _stateRecordMetric(metricArgs, planningDir);
|
|
137
|
+
}
|
|
320
138
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
try {
|
|
325
|
-
result.config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
326
|
-
} catch (_) {
|
|
327
|
-
result.config = { _error: 'Failed to parse config.json' };
|
|
328
|
-
}
|
|
329
|
-
}
|
|
139
|
+
function stateRecordActivity(description) {
|
|
140
|
+
return _stateRecordActivity(description, planningDir);
|
|
141
|
+
}
|
|
330
142
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const content = fs.readFileSync(statePath, 'utf8');
|
|
335
|
-
result.state = parseStateMd(content);
|
|
336
|
-
}
|
|
143
|
+
function stateUpdateProgress() {
|
|
144
|
+
return _stateUpdateProgress(planningDir);
|
|
145
|
+
}
|
|
337
146
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
const content = fs.readFileSync(roadmapPath, 'utf8');
|
|
342
|
-
result.roadmap = parseRoadmapMd(content);
|
|
343
|
-
result.phase_count = result.roadmap.phases.length;
|
|
344
|
-
}
|
|
147
|
+
function stateReconcile() {
|
|
148
|
+
return _stateReconcile(planningDir);
|
|
149
|
+
}
|
|
345
150
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
}
|
|
151
|
+
function stateBackup() {
|
|
152
|
+
return _stateBackup(planningDir);
|
|
153
|
+
}
|
|
350
154
|
|
|
351
|
-
|
|
352
|
-
|
|
155
|
+
function roadmapAnalyze() {
|
|
156
|
+
return _roadmapAnalyze(planningDir);
|
|
157
|
+
}
|
|
353
158
|
|
|
354
|
-
|
|
159
|
+
function roadmapUpdateStatus(phaseNum, newStatus) {
|
|
160
|
+
return _roadmapUpdateStatus(phaseNum, newStatus, planningDir);
|
|
355
161
|
}
|
|
356
162
|
|
|
357
|
-
function
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
return { phases: [], total_plans: 0, completed_plans: 0, percentage: 0 };
|
|
361
|
-
}
|
|
163
|
+
function roadmapUpdatePlans(phaseNum, complete, total) {
|
|
164
|
+
return _roadmapUpdatePlans(phaseNum, complete, total, planningDir);
|
|
165
|
+
}
|
|
362
166
|
|
|
363
|
-
const phases = [];
|
|
364
|
-
let totalPlans = 0;
|
|
365
|
-
let completedPlans = 0;
|
|
366
|
-
|
|
367
|
-
const entries = fs.readdirSync(phasesDir, { withFileTypes: true })
|
|
368
|
-
.filter(e => e.isDirectory())
|
|
369
|
-
.sort((a, b) => a.name.localeCompare(b.name));
|
|
370
|
-
|
|
371
|
-
for (const entry of entries) {
|
|
372
|
-
const phaseDir = path.join(phasesDir, entry.name);
|
|
373
|
-
const plans = findFiles(phaseDir, /-PLAN\.md$/);
|
|
374
|
-
const summaries = findFiles(phaseDir, /^SUMMARY-.*\.md$/);
|
|
375
|
-
const verification = fs.existsSync(path.join(phaseDir, 'VERIFICATION.md'));
|
|
376
|
-
|
|
377
|
-
const completedSummaries = summaries.filter(s => {
|
|
378
|
-
const content = fs.readFileSync(path.join(phaseDir, s), 'utf8');
|
|
379
|
-
return /status:\s*["']?complete/i.test(content);
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
const phaseInfo = {
|
|
383
|
-
directory: entry.name,
|
|
384
|
-
plans: plans.length,
|
|
385
|
-
summaries: summaries.length,
|
|
386
|
-
completed: completedSummaries.length,
|
|
387
|
-
has_verification: verification,
|
|
388
|
-
status: determinePhaseStatus(plans.length, completedSummaries.length, summaries.length, verification, phaseDir)
|
|
389
|
-
};
|
|
390
|
-
|
|
391
|
-
phases.push(phaseInfo);
|
|
392
|
-
totalPlans += plans.length;
|
|
393
|
-
completedPlans += completedSummaries.length;
|
|
394
|
-
}
|
|
395
167
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
total_plans: totalPlans,
|
|
399
|
-
completed_plans: completedPlans,
|
|
400
|
-
percentage: totalPlans > 0 ? Math.round((completedPlans / totalPlans) * 100) : 0
|
|
401
|
-
};
|
|
168
|
+
function frontmatter(filePath) {
|
|
169
|
+
return _frontmatter(filePath);
|
|
402
170
|
}
|
|
403
171
|
|
|
404
172
|
function planIndex(phaseNum) {
|
|
405
|
-
|
|
406
|
-
if (!fs.existsSync(phasesDir)) {
|
|
407
|
-
return { error: 'No phases directory found' };
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
// Find phase directory matching the number
|
|
411
|
-
const entries = fs.readdirSync(phasesDir, { withFileTypes: true })
|
|
412
|
-
.filter(e => e.isDirectory());
|
|
413
|
-
|
|
414
|
-
const phaseDir = entries.find(e => e.name.startsWith(phaseNum.padStart(2, '0') + '-'));
|
|
415
|
-
if (!phaseDir) {
|
|
416
|
-
return { error: `No phase directory found matching phase ${phaseNum}` };
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
const fullDir = path.join(phasesDir, phaseDir.name);
|
|
420
|
-
const planFiles = findFiles(fullDir, /-PLAN\.md$/);
|
|
421
|
-
|
|
422
|
-
const plans = [];
|
|
423
|
-
const waves = {};
|
|
424
|
-
|
|
425
|
-
for (const file of planFiles) {
|
|
426
|
-
const content = fs.readFileSync(path.join(fullDir, file), 'utf8');
|
|
427
|
-
const frontmatter = parseYamlFrontmatter(content);
|
|
428
|
-
|
|
429
|
-
const plan = {
|
|
430
|
-
file,
|
|
431
|
-
plan_id: frontmatter.plan || file.replace(/-PLAN\.md$/, ''),
|
|
432
|
-
wave: parseInt(frontmatter.wave, 10) || 1,
|
|
433
|
-
type: frontmatter.type || 'unknown',
|
|
434
|
-
autonomous: frontmatter.autonomous !== false,
|
|
435
|
-
depends_on: frontmatter.depends_on || [],
|
|
436
|
-
gap_closure: frontmatter.gap_closure || false,
|
|
437
|
-
has_summary: fs.existsSync(path.join(fullDir, `SUMMARY-${frontmatter.plan || ''}.md`)),
|
|
438
|
-
must_haves_count: countMustHaves(frontmatter.must_haves)
|
|
439
|
-
};
|
|
440
|
-
|
|
441
|
-
plans.push(plan);
|
|
442
|
-
|
|
443
|
-
const waveKey = `wave_${plan.wave}`;
|
|
444
|
-
if (!waves[waveKey]) waves[waveKey] = [];
|
|
445
|
-
waves[waveKey].push(plan.plan_id);
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
return {
|
|
449
|
-
phase: phaseDir.name,
|
|
450
|
-
total_plans: plans.length,
|
|
451
|
-
plans,
|
|
452
|
-
waves
|
|
453
|
-
};
|
|
173
|
+
return _planIndex(phaseNum, planningDir);
|
|
454
174
|
}
|
|
455
175
|
|
|
456
|
-
function
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
config = preloadedConfig;
|
|
460
|
-
} else {
|
|
461
|
-
const configPath = path.join(planningDir, 'config.json');
|
|
462
|
-
if (!fs.existsSync(configPath)) {
|
|
463
|
-
return { valid: false, errors: ['config.json not found'], warnings: [] };
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
try {
|
|
467
|
-
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
468
|
-
} catch (e) {
|
|
469
|
-
return { valid: false, errors: [`config.json is not valid JSON: ${e.message}`], warnings: [] };
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
const schema = JSON.parse(fs.readFileSync(path.join(__dirname, 'config-schema.json'), 'utf8'));
|
|
474
|
-
const warnings = [];
|
|
475
|
-
const errors = [];
|
|
476
|
-
|
|
477
|
-
validateObject(config, schema, '', errors, warnings);
|
|
478
|
-
|
|
479
|
-
// Semantic conflict detection — logical contradictions that pass schema validation
|
|
480
|
-
// Clear contradictions → errors; ambiguous/preference issues → warnings
|
|
481
|
-
if (config.mode === 'autonomous' && config.gates) {
|
|
482
|
-
const activeGates = Object.entries(config.gates || {}).filter(([, v]) => v === true).map(([k]) => k);
|
|
483
|
-
if (activeGates.length > 0) {
|
|
484
|
-
errors.push(`mode=autonomous with active gates (${activeGates.join(', ')}): gates are unreachable in autonomous mode`);
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
if (config.features && config.features.auto_continue && config.mode === 'interactive') {
|
|
488
|
-
warnings.push('features.auto_continue=true with mode=interactive: auto_continue only fires in autonomous mode');
|
|
489
|
-
}
|
|
490
|
-
if (config.parallelization) {
|
|
491
|
-
if (config.parallelization.enabled === false && config.parallelization.plan_level === true) {
|
|
492
|
-
warnings.push('parallelization.enabled=false with plan_level=true: plan_level is ignored when parallelization is disabled');
|
|
493
|
-
}
|
|
494
|
-
if (config.parallelization.max_concurrent_agents === 1 && config.teams && config.teams.coordination) {
|
|
495
|
-
errors.push('parallelization.max_concurrent_agents=1 with teams.coordination set: teams require concurrent agents to be useful');
|
|
496
|
-
}
|
|
497
|
-
}
|
|
176
|
+
function mustHavesCollect(phaseNum) {
|
|
177
|
+
return _mustHavesCollect(phaseNum, planningDir);
|
|
178
|
+
}
|
|
498
179
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
errors,
|
|
502
|
-
warnings
|
|
503
|
-
};
|
|
180
|
+
function phaseInfo(phaseNum) {
|
|
181
|
+
return _phaseInfo(phaseNum, planningDir);
|
|
504
182
|
}
|
|
505
183
|
|
|
506
|
-
|
|
184
|
+
function phaseAdd(slug, afterPhase, options) {
|
|
185
|
+
return _phaseAdd(slug, afterPhase, planningDir, options);
|
|
186
|
+
}
|
|
507
187
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
* Wraps parseYamlFrontmatter() + parseMustHaves().
|
|
511
|
-
*/
|
|
512
|
-
function frontmatter(filePath) {
|
|
513
|
-
const resolved = path.resolve(filePath);
|
|
514
|
-
if (!fs.existsSync(resolved)) {
|
|
515
|
-
return { error: `File not found: ${resolved}` };
|
|
516
|
-
}
|
|
517
|
-
const content = fs.readFileSync(resolved, 'utf8');
|
|
518
|
-
return parseYamlFrontmatter(content);
|
|
188
|
+
function phaseRemove(phaseNum) {
|
|
189
|
+
return _phaseRemove(phaseNum, planningDir);
|
|
519
190
|
}
|
|
520
191
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
*/
|
|
525
|
-
function mustHavesCollect(phaseNum) {
|
|
526
|
-
const phasesDir = path.join(planningDir, 'phases');
|
|
527
|
-
if (!fs.existsSync(phasesDir)) {
|
|
528
|
-
return { error: 'No phases directory found' };
|
|
529
|
-
}
|
|
192
|
+
function phaseList(opts) {
|
|
193
|
+
return _phaseList(planningDir, opts);
|
|
194
|
+
}
|
|
530
195
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
if (!phaseDir) {
|
|
535
|
-
return { error: `No phase directory found matching phase ${phaseNum}` };
|
|
536
|
-
}
|
|
196
|
+
function phaseNextNumber() {
|
|
197
|
+
return _phaseNextNumber(planningDir);
|
|
198
|
+
}
|
|
537
199
|
|
|
538
|
-
|
|
539
|
-
|
|
200
|
+
function phaseComplete(phaseNum) {
|
|
201
|
+
return _phaseComplete(phaseNum, planningDir);
|
|
202
|
+
}
|
|
540
203
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
const allKeyLinks = new Set();
|
|
204
|
+
function phaseInsert(position, slug, options) {
|
|
205
|
+
return _phaseInsert(position, slug, planningDir, options);
|
|
206
|
+
}
|
|
545
207
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
const planId = fm.plan || file.replace(/-PLAN\.md$/, '');
|
|
550
|
-
const mh = fm.must_haves || { truths: [], artifacts: [], key_links: [] };
|
|
208
|
+
function milestoneStats(version) {
|
|
209
|
+
return _milestoneStats(version, planningDir);
|
|
210
|
+
}
|
|
551
211
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
(mh.key_links || []).forEach(k => allKeyLinks.add(k));
|
|
556
|
-
}
|
|
212
|
+
function compoundInitPhase(phaseNum, slug, opts) {
|
|
213
|
+
return _compoundInitPhase(phaseNum, slug, planningDir, opts);
|
|
214
|
+
}
|
|
557
215
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
key_links: [...allKeyLinks]
|
|
562
|
-
};
|
|
216
|
+
function compoundCompletePhase(phaseNum) {
|
|
217
|
+
return _compoundCompletePhase(phaseNum, planningDir);
|
|
218
|
+
}
|
|
563
219
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
plans: perPlan,
|
|
567
|
-
all,
|
|
568
|
-
total: all.truths.length + all.artifacts.length + all.key_links.length
|
|
569
|
-
};
|
|
220
|
+
function compoundInitMilestone(version, opts) {
|
|
221
|
+
return _compoundInitMilestone(version, planningDir, opts);
|
|
570
222
|
}
|
|
571
223
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
function phaseInfo(phaseNum) {
|
|
576
|
-
const phasesDir = path.join(planningDir, 'phases');
|
|
577
|
-
if (!fs.existsSync(phasesDir)) {
|
|
578
|
-
return { error: 'No phases directory found' };
|
|
579
|
-
}
|
|
224
|
+
function initExecutePhase(phaseNum, overridePlanningDir, overrideModel) {
|
|
225
|
+
return _initExecutePhase(phaseNum, overridePlanningDir || planningDir, overrideModel);
|
|
226
|
+
}
|
|
580
227
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
if (!phaseDir) {
|
|
585
|
-
return { error: `No phase directory found matching phase ${phaseNum}` };
|
|
586
|
-
}
|
|
228
|
+
function initPlanPhase(phaseNum, overridePlanningDir, overrideModel) {
|
|
229
|
+
return _initPlanPhase(phaseNum, overridePlanningDir || planningDir, overrideModel);
|
|
230
|
+
}
|
|
587
231
|
|
|
588
|
-
|
|
232
|
+
function initQuick(description) {
|
|
233
|
+
return _initQuick(description, planningDir);
|
|
234
|
+
}
|
|
589
235
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
if (fs.existsSync(roadmapPath)) {
|
|
594
|
-
const roadmapContent = fs.readFileSync(roadmapPath, 'utf8');
|
|
595
|
-
const roadmap = parseRoadmapMd(roadmapContent);
|
|
596
|
-
roadmapInfo = roadmap.phases.find(p => p.number === phaseNum.padStart(2, '0')) || null;
|
|
597
|
-
}
|
|
236
|
+
function initVerifyWork(phaseNum, overridePlanningDir, overrideModel) {
|
|
237
|
+
return _initVerifyWork(phaseNum, overridePlanningDir || planningDir, overrideModel);
|
|
238
|
+
}
|
|
598
239
|
|
|
599
|
-
|
|
600
|
-
|
|
240
|
+
function initResume() {
|
|
241
|
+
return _initResume(planningDir);
|
|
242
|
+
}
|
|
601
243
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
if (fs.existsSync(verificationPath)) {
|
|
606
|
-
const vContent = fs.readFileSync(verificationPath, 'utf8');
|
|
607
|
-
verification = parseYamlFrontmatter(vContent);
|
|
608
|
-
}
|
|
244
|
+
function initProgress() {
|
|
245
|
+
return _initProgress(planningDir);
|
|
246
|
+
}
|
|
609
247
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
const content = fs.readFileSync(path.join(fullDir, f), 'utf8');
|
|
614
|
-
const fm = parseYamlFrontmatter(content);
|
|
615
|
-
return { file: f, plan: fm.plan || f.replace(/^SUMMARY-|\.md$/g, ''), status: fm.status || 'unknown' };
|
|
616
|
-
});
|
|
617
|
-
|
|
618
|
-
// Determine filesystem status
|
|
619
|
-
const planCount = plans.total_plans || 0;
|
|
620
|
-
const completedCount = summaries.filter(s => s.status === 'complete').length;
|
|
621
|
-
const hasVerification = fs.existsSync(verificationPath);
|
|
622
|
-
const fsStatus = determinePhaseStatus(planCount, completedCount, summaryFiles.length, hasVerification, fullDir);
|
|
623
|
-
|
|
624
|
-
return {
|
|
625
|
-
phase: phaseDir.name,
|
|
626
|
-
name: roadmapInfo ? roadmapInfo.name : phaseDir.name.replace(/^\d+-/, ''),
|
|
627
|
-
goal: roadmapInfo ? roadmapInfo.goal : null,
|
|
628
|
-
roadmap_status: roadmapInfo ? roadmapInfo.status : null,
|
|
629
|
-
filesystem_status: fsStatus,
|
|
630
|
-
plans: plans.plans || [],
|
|
631
|
-
plan_count: planCount,
|
|
632
|
-
summaries,
|
|
633
|
-
completed: completedCount,
|
|
634
|
-
verification,
|
|
635
|
-
has_context: fs.existsSync(path.join(fullDir, 'CONTEXT.md'))
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
// --- Mutation commands ---
|
|
248
|
+
function initContinue() {
|
|
249
|
+
return _initContinue(planningDir);
|
|
250
|
+
}
|
|
640
251
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
*
|
|
645
|
-
* @param {string} field - One of: current_phase, status, plans_complete, last_activity
|
|
646
|
-
* @param {string} value - New value (use 'now' for last_activity to auto-timestamp)
|
|
647
|
-
*/
|
|
648
|
-
function stateUpdate(field, value) {
|
|
649
|
-
const statePath = path.join(planningDir, 'STATE.md');
|
|
650
|
-
if (!fs.existsSync(statePath)) {
|
|
651
|
-
return { success: false, error: 'STATE.md not found' };
|
|
652
|
-
}
|
|
252
|
+
function initMilestone() {
|
|
253
|
+
return _initMilestone(planningDir);
|
|
254
|
+
}
|
|
653
255
|
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
}
|
|
256
|
+
function initBegin() {
|
|
257
|
+
return _initBegin(planningDir);
|
|
258
|
+
}
|
|
658
259
|
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
}
|
|
260
|
+
function initStatus() {
|
|
261
|
+
return _initStatus(planningDir);
|
|
262
|
+
}
|
|
663
263
|
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
return updateFrontmatterField(content, field, value);
|
|
668
|
-
}
|
|
669
|
-
return updateLegacyStateField(content, field, value);
|
|
670
|
-
});
|
|
264
|
+
function initMapCodebase() {
|
|
265
|
+
return _initMapCodebase(planningDir);
|
|
266
|
+
}
|
|
671
267
|
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
}
|
|
675
|
-
return { success: false, error: result.error };
|
|
268
|
+
function stateBundle(phaseNum) {
|
|
269
|
+
return _initStateBundle(phaseNum, planningDir);
|
|
676
270
|
}
|
|
677
271
|
|
|
678
|
-
/**
|
|
679
|
-
* Append a record to HISTORY.md. Creates the file if it doesn't exist.
|
|
680
|
-
* Each entry is a markdown section appended at the end.
|
|
681
|
-
*
|
|
682
|
-
* @param {object} entry - { type: 'milestone'|'phase', title: string, body: string }
|
|
683
|
-
* @param {string} [dir] - Path to .planning directory (defaults to cwd/.planning)
|
|
684
|
-
* @returns {{success: boolean, error?: string}}
|
|
685
|
-
*/
|
|
686
272
|
function historyAppend(entry, dir) {
|
|
687
|
-
|
|
688
|
-
const timestamp = new Date().toISOString().slice(0, 10);
|
|
689
|
-
|
|
690
|
-
let header = '';
|
|
691
|
-
if (!fs.existsSync(historyPath)) {
|
|
692
|
-
header = '# Project History\n\nCompleted milestones and phase records. This file is append-only.\n\n';
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
const section = `${header}## ${entry.type === 'milestone' ? 'Milestone' : 'Phase'}: ${entry.title}\n_Completed: ${timestamp}_\n\n${entry.body.trim()}\n\n---\n\n`;
|
|
696
|
-
|
|
697
|
-
try {
|
|
698
|
-
fs.appendFileSync(historyPath, section, 'utf8');
|
|
699
|
-
return { success: true };
|
|
700
|
-
} catch (e) {
|
|
701
|
-
return { success: false, error: e.message };
|
|
702
|
-
}
|
|
273
|
+
return _historyAppend(entry, dir || planningDir);
|
|
703
274
|
}
|
|
704
275
|
|
|
705
|
-
/**
|
|
706
|
-
* Load HISTORY.md and parse it into structured records.
|
|
707
|
-
* Returns null if HISTORY.md doesn't exist.
|
|
708
|
-
*
|
|
709
|
-
* @param {string} [dir] - Path to .planning directory
|
|
710
|
-
* @returns {object|null} { records: [{type, title, date, body}], line_count }
|
|
711
|
-
*/
|
|
712
276
|
function historyLoad(dir) {
|
|
713
|
-
|
|
714
|
-
if (!fs.existsSync(historyPath)) return null;
|
|
715
|
-
|
|
716
|
-
const content = fs.readFileSync(historyPath, 'utf8');
|
|
717
|
-
const records = [];
|
|
718
|
-
const sectionRegex = /^## (Milestone|Phase): (.+)\n_Completed: (\d{4}-\d{2}-\d{2})_\n\n([\s\S]*?)(?=\n---|\s*$)/gm;
|
|
719
|
-
|
|
720
|
-
let match;
|
|
721
|
-
while ((match = sectionRegex.exec(content)) !== null) {
|
|
722
|
-
records.push({
|
|
723
|
-
type: match[1].toLowerCase(),
|
|
724
|
-
title: match[2].trim(),
|
|
725
|
-
date: match[3],
|
|
726
|
-
body: match[4].trim()
|
|
727
|
-
});
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
return {
|
|
731
|
-
records,
|
|
732
|
-
line_count: content.split('\n').length
|
|
733
|
-
};
|
|
277
|
+
return _historyLoad(dir || planningDir);
|
|
734
278
|
}
|
|
735
279
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
*/
|
|
739
|
-
function roadmapUpdateStatus(phaseNum, newStatus) {
|
|
740
|
-
const roadmapPath = path.join(planningDir, 'ROADMAP.md');
|
|
741
|
-
if (!fs.existsSync(roadmapPath)) {
|
|
742
|
-
return { success: false, error: 'ROADMAP.md not found' };
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
let oldStatus = null;
|
|
746
|
-
|
|
747
|
-
const result = lockedFileUpdate(roadmapPath, (content) => {
|
|
748
|
-
const lines = content.split('\n');
|
|
749
|
-
const rowIdx = findRoadmapRow(lines, phaseNum);
|
|
750
|
-
if (rowIdx === -1) {
|
|
751
|
-
return content; // No matching row found
|
|
752
|
-
}
|
|
753
|
-
const parts = lines[rowIdx].split('|');
|
|
754
|
-
oldStatus = parts[6] ? parts[6].trim() : 'unknown';
|
|
755
|
-
lines[rowIdx] = updateTableRow(lines[rowIdx], 5, newStatus);
|
|
756
|
-
return lines.join('\n');
|
|
757
|
-
});
|
|
758
|
-
|
|
759
|
-
if (!oldStatus) {
|
|
760
|
-
return { success: false, error: `Phase ${phaseNum} not found in ROADMAP.md table` };
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
// Advisory transition validation — warn on suspicious transitions but don't block
|
|
764
|
-
const transition = validateStatusTransition(oldStatus, newStatus);
|
|
765
|
-
if (!transition.valid && transition.warning) {
|
|
766
|
-
process.stderr.write(`[pbr-tools] WARNING: ${transition.warning}\n`);
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
if (result.success) {
|
|
770
|
-
const response = { success: true, old_status: oldStatus, new_status: newStatus };
|
|
771
|
-
if (!transition.valid) {
|
|
772
|
-
response.transition_warning = transition.warning;
|
|
773
|
-
}
|
|
774
|
-
return response;
|
|
775
|
-
}
|
|
776
|
-
return { success: false, error: result.error };
|
|
280
|
+
function todoList(opts) {
|
|
281
|
+
return _todoList(planningDir, opts);
|
|
777
282
|
}
|
|
778
283
|
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
*/
|
|
782
|
-
function roadmapUpdatePlans(phaseNum, complete, total) {
|
|
783
|
-
const roadmapPath = path.join(planningDir, 'ROADMAP.md');
|
|
784
|
-
if (!fs.existsSync(roadmapPath)) {
|
|
785
|
-
return { success: false, error: 'ROADMAP.md not found' };
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
let oldPlans = null;
|
|
789
|
-
const newPlans = `${complete}/${total}`;
|
|
790
|
-
|
|
791
|
-
const result = lockedFileUpdate(roadmapPath, (content) => {
|
|
792
|
-
const lines = content.split('\n');
|
|
793
|
-
const rowIdx = findRoadmapRow(lines, phaseNum);
|
|
794
|
-
if (rowIdx === -1) {
|
|
795
|
-
return content;
|
|
796
|
-
}
|
|
797
|
-
const parts = lines[rowIdx].split('|');
|
|
798
|
-
oldPlans = parts[4] ? parts[4].trim() : 'unknown';
|
|
799
|
-
lines[rowIdx] = updateTableRow(lines[rowIdx], 3, newPlans);
|
|
800
|
-
return lines.join('\n');
|
|
801
|
-
});
|
|
802
|
-
|
|
803
|
-
if (!oldPlans) {
|
|
804
|
-
return { success: false, error: `Phase ${phaseNum} not found in ROADMAP.md table` };
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
if (result.success) {
|
|
808
|
-
return { success: true, old_plans: oldPlans, new_plans: newPlans };
|
|
809
|
-
}
|
|
810
|
-
return { success: false, error: result.error };
|
|
284
|
+
function todoGet(num) {
|
|
285
|
+
return _todoGet(planningDir, num);
|
|
811
286
|
}
|
|
812
287
|
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
/**
|
|
816
|
-
* Update a field in legacy (non-frontmatter) STATE.md content.
|
|
817
|
-
* Pure function: content in, content out.
|
|
818
|
-
*/
|
|
819
|
-
function updateLegacyStateField(content, field, value) {
|
|
820
|
-
const lines = content.split('\n');
|
|
821
|
-
|
|
822
|
-
switch (field) {
|
|
823
|
-
case 'current_phase': {
|
|
824
|
-
const idx = lines.findIndex(l => /Phase:\s*\d+\s+of\s+\d+/.test(l));
|
|
825
|
-
if (idx !== -1) {
|
|
826
|
-
lines[idx] = lines[idx].replace(/(Phase:\s*)\d+/, (_, prefix) => `${prefix}${value}`);
|
|
827
|
-
}
|
|
828
|
-
break;
|
|
829
|
-
}
|
|
830
|
-
case 'status': {
|
|
831
|
-
const idx = lines.findIndex(l => /^Status:/i.test(l));
|
|
832
|
-
if (idx !== -1) {
|
|
833
|
-
lines[idx] = `Status: ${value}`;
|
|
834
|
-
} else {
|
|
835
|
-
const phaseIdx = lines.findIndex(l => /Phase:/.test(l));
|
|
836
|
-
if (phaseIdx !== -1) {
|
|
837
|
-
lines.splice(phaseIdx + 1, 0, `Status: ${value}`);
|
|
838
|
-
} else {
|
|
839
|
-
lines.push(`Status: ${value}`);
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
break;
|
|
843
|
-
}
|
|
844
|
-
case 'plans_complete': {
|
|
845
|
-
const idx = lines.findIndex(l => /Plan:\s*\d+\s+of\s+\d+/.test(l));
|
|
846
|
-
if (idx !== -1) {
|
|
847
|
-
lines[idx] = lines[idx].replace(/(Plan:\s*)\d+/, (_, prefix) => `${prefix}${value}`);
|
|
848
|
-
}
|
|
849
|
-
break;
|
|
850
|
-
}
|
|
851
|
-
case 'last_activity': {
|
|
852
|
-
const idx = lines.findIndex(l => /^Last Activity:/i.test(l));
|
|
853
|
-
if (idx !== -1) {
|
|
854
|
-
lines[idx] = `Last Activity: ${value}`;
|
|
855
|
-
} else {
|
|
856
|
-
const statusIdx = lines.findIndex(l => /^Status:/i.test(l));
|
|
857
|
-
if (statusIdx !== -1) {
|
|
858
|
-
lines.splice(statusIdx + 1, 0, `Last Activity: ${value}`);
|
|
859
|
-
} else {
|
|
860
|
-
lines.push(`Last Activity: ${value}`);
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
break;
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
return lines.join('\n');
|
|
288
|
+
function todoAdd(title, opts) {
|
|
289
|
+
return _todoAdd(planningDir, title, opts);
|
|
868
290
|
}
|
|
869
291
|
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
* Pure function: content in, content out.
|
|
873
|
-
*/
|
|
874
|
-
function updateFrontmatterField(content, field, value) {
|
|
875
|
-
const match = content.match(/^(---\s*\n)([\s\S]*?)(\n---)/);
|
|
876
|
-
if (!match) return content;
|
|
877
|
-
|
|
878
|
-
const before = match[1];
|
|
879
|
-
let yaml = match[2];
|
|
880
|
-
const after = match[3];
|
|
881
|
-
const rest = content.slice(match[0].length);
|
|
882
|
-
|
|
883
|
-
// Format value: integers stay bare, strings get quotes
|
|
884
|
-
const isNum = /^\d+$/.test(String(value));
|
|
885
|
-
const formatted = isNum ? value : `"${value}"`;
|
|
886
|
-
|
|
887
|
-
const fieldRegex = new RegExp(`^(${field})\\s*:.*$`, 'm');
|
|
888
|
-
if (fieldRegex.test(yaml)) {
|
|
889
|
-
yaml = yaml.replace(fieldRegex, () => `${field}: ${formatted}`);
|
|
890
|
-
} else {
|
|
891
|
-
yaml = yaml + `\n${field}: ${formatted}`;
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
return before + yaml + after + rest;
|
|
292
|
+
function todoDone(num) {
|
|
293
|
+
return _todoDone(planningDir, num);
|
|
895
294
|
}
|
|
896
295
|
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
* @returns {number} Line index or -1 if not found
|
|
900
|
-
*/
|
|
901
|
-
function findRoadmapRow(lines, phaseNum) {
|
|
902
|
-
const paddedPhase = phaseNum.padStart(2, '0');
|
|
903
|
-
for (let i = 0; i < lines.length; i++) {
|
|
904
|
-
if (!lines[i].includes('|')) continue;
|
|
905
|
-
const parts = lines[i].split('|');
|
|
906
|
-
if (parts.length < 3) continue;
|
|
907
|
-
const phaseCol = parts[1] ? parts[1].trim() : '';
|
|
908
|
-
if (phaseCol === paddedPhase) {
|
|
909
|
-
return i;
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
return -1;
|
|
296
|
+
function autoCloseTodos(context) {
|
|
297
|
+
return _autoCloseTodos(planningDir, context);
|
|
913
298
|
}
|
|
914
299
|
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
* @param {string} row - The full table row string (e.g., "| 01 | Setup | ... |")
|
|
918
|
-
* @param {number} columnIndex - 0-based column index (Phase=0, Name=1, ..., Status=5)
|
|
919
|
-
* @param {string} newValue - New cell value
|
|
920
|
-
* @returns {string} Updated row
|
|
921
|
-
*/
|
|
922
|
-
function updateTableRow(row, columnIndex, newValue) {
|
|
923
|
-
const parts = row.split('|');
|
|
924
|
-
// parts[0] is empty (before first |), data starts at parts[1]
|
|
925
|
-
const partIndex = columnIndex + 1;
|
|
926
|
-
if (partIndex < parts.length) {
|
|
927
|
-
parts[partIndex] = ` ${newValue} `;
|
|
928
|
-
}
|
|
929
|
-
return parts.join('|');
|
|
300
|
+
function autoArchiveNotes(context) {
|
|
301
|
+
return _autoArchiveNotes(planningDir, context);
|
|
930
302
|
}
|
|
931
303
|
|
|
932
|
-
/**
|
|
933
|
-
* Lightweight JSON Schema validator — supports type, enum, properties,
|
|
934
|
-
* additionalProperties, minimum, maximum for the config schema.
|
|
935
|
-
*/
|
|
936
|
-
function validateObject(value, schema, prefix, errors, warnings) {
|
|
937
|
-
if (schema.type && typeof value !== schema.type) {
|
|
938
|
-
if (!(schema.type === 'integer' && typeof value === 'number' && Number.isInteger(value))) {
|
|
939
|
-
errors.push(`${prefix || 'root'}: expected ${schema.type}, got ${typeof value}`);
|
|
940
|
-
return;
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
if (schema.enum && !schema.enum.includes(value)) {
|
|
945
|
-
errors.push(`${prefix || 'root'}: value "${value}" not in allowed values [${schema.enum.join(', ')}]`);
|
|
946
|
-
return;
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
if (schema.minimum !== undefined && value < schema.minimum) {
|
|
950
|
-
errors.push(`${prefix || 'root'}: value ${value} is below minimum ${schema.minimum}`);
|
|
951
|
-
}
|
|
952
|
-
if (schema.maximum !== undefined && value > schema.maximum) {
|
|
953
|
-
errors.push(`${prefix || 'root'}: value ${value} is above maximum ${schema.maximum}`);
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
if (schema.type === 'object' && schema.properties) {
|
|
957
|
-
const knownKeys = new Set(Object.keys(schema.properties));
|
|
958
304
|
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
if (!knownKeys.has(key)) {
|
|
962
|
-
if (schema.additionalProperties === false) {
|
|
963
|
-
warnings.push(`${fullKey}: unrecognized key (possible typo?)`);
|
|
964
|
-
}
|
|
965
|
-
continue;
|
|
966
|
-
}
|
|
967
|
-
validateObject(value[key], schema.properties[key], fullKey, errors, warnings);
|
|
968
|
-
}
|
|
969
|
-
}
|
|
305
|
+
function migrate(options) {
|
|
306
|
+
return _applyMigrations(planningDir, options);
|
|
970
307
|
}
|
|
971
308
|
|
|
972
|
-
/**
|
|
973
|
-
* Locked file update: read-modify-write with exclusive lockfile.
|
|
974
|
-
* Prevents concurrent writes to STATE.md and ROADMAP.md.
|
|
975
|
-
*
|
|
976
|
-
* @param {string} filePath - Absolute path to the file to update
|
|
977
|
-
* @param {function} updateFn - Receives current content, returns new content
|
|
978
|
-
* @param {object} opts - Options: { retries: 3, retryDelayMs: 100, timeoutMs: 5000 }
|
|
979
|
-
* @returns {object} { success, content?, error? }
|
|
980
|
-
*/
|
|
981
|
-
function lockedFileUpdate(filePath, updateFn, opts = {}) {
|
|
982
|
-
const retries = opts.retries || 3;
|
|
983
|
-
const retryDelayMs = opts.retryDelayMs || 100;
|
|
984
|
-
const timeoutMs = opts.timeoutMs || 5000;
|
|
985
|
-
const lockPath = filePath + '.lock';
|
|
986
|
-
|
|
987
|
-
let lockFd = null;
|
|
988
|
-
let lockAcquired = false;
|
|
989
|
-
|
|
990
|
-
try {
|
|
991
|
-
// Acquire lock with retries
|
|
992
|
-
for (let attempt = 0; attempt < retries; attempt++) {
|
|
993
|
-
try {
|
|
994
|
-
lockFd = fs.openSync(lockPath, 'wx');
|
|
995
|
-
lockAcquired = true;
|
|
996
|
-
break;
|
|
997
|
-
} catch (e) {
|
|
998
|
-
if (e.code === 'EEXIST') {
|
|
999
|
-
// Lock exists — check if stale (older than timeoutMs)
|
|
1000
|
-
try {
|
|
1001
|
-
const stats = fs.statSync(lockPath);
|
|
1002
|
-
if (Date.now() - stats.mtimeMs > timeoutMs) {
|
|
1003
|
-
// Stale lock — remove and retry
|
|
1004
|
-
fs.unlinkSync(lockPath);
|
|
1005
|
-
continue;
|
|
1006
|
-
}
|
|
1007
|
-
} catch (_statErr) {
|
|
1008
|
-
// Lock disappeared between check — retry
|
|
1009
|
-
continue;
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
if (attempt < retries - 1) {
|
|
1013
|
-
// Wait and retry
|
|
1014
|
-
const waitMs = retryDelayMs * (attempt + 1);
|
|
1015
|
-
const start = Date.now();
|
|
1016
|
-
while (Date.now() - start < waitMs) {
|
|
1017
|
-
// Busy wait (synchronous context)
|
|
1018
|
-
}
|
|
1019
|
-
continue;
|
|
1020
|
-
}
|
|
1021
|
-
return { success: false, error: `Could not acquire lock for ${path.basename(filePath)} after ${retries} attempts` };
|
|
1022
|
-
}
|
|
1023
|
-
throw e;
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
if (!lockAcquired) {
|
|
1028
|
-
return { success: false, error: `Could not acquire lock for ${path.basename(filePath)}` };
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
// Write PID to lock file for debugging
|
|
1032
|
-
fs.writeSync(lockFd, `${process.pid}`);
|
|
1033
|
-
fs.closeSync(lockFd);
|
|
1034
|
-
lockFd = null;
|
|
1035
|
-
|
|
1036
|
-
// Read current content
|
|
1037
|
-
let content = '';
|
|
1038
|
-
if (fs.existsSync(filePath)) {
|
|
1039
|
-
content = fs.readFileSync(filePath, 'utf8');
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
// Apply update
|
|
1043
|
-
const newContent = updateFn(content);
|
|
1044
|
-
|
|
1045
|
-
// Write back atomically
|
|
1046
|
-
const writeResult = atomicWrite(filePath, newContent);
|
|
1047
|
-
if (!writeResult.success) {
|
|
1048
|
-
return { success: false, error: writeResult.error };
|
|
1049
|
-
}
|
|
1050
309
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
return { success: false, error: e.message };
|
|
1054
|
-
} finally {
|
|
1055
|
-
// Close fd if still open
|
|
1056
|
-
try {
|
|
1057
|
-
if (lockFd !== null) fs.closeSync(lockFd);
|
|
1058
|
-
} catch (_e) { /* ignore */ }
|
|
1059
|
-
// Only release lock if we acquired it
|
|
1060
|
-
if (lockAcquired) {
|
|
1061
|
-
try {
|
|
1062
|
-
fs.unlinkSync(lockPath);
|
|
1063
|
-
} catch (_e) { /* ignore — may already be cleaned up */ }
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
310
|
+
function verifySpotCheck(type, dirPath) {
|
|
311
|
+
return _verifySpotCheck(type, dirPath);
|
|
1066
312
|
}
|
|
1067
313
|
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
progress: null,
|
|
1075
|
-
status: null,
|
|
1076
|
-
line_count: content.split('\n').length,
|
|
1077
|
-
format: 'legacy' // 'legacy' or 'frontmatter'
|
|
1078
|
-
};
|
|
1079
|
-
|
|
1080
|
-
// Check for YAML frontmatter (version 2 format)
|
|
1081
|
-
const frontmatter = parseYamlFrontmatter(content);
|
|
1082
|
-
if (frontmatter.version === 2 || frontmatter.current_phase !== undefined) {
|
|
1083
|
-
result.format = 'frontmatter';
|
|
1084
|
-
result.current_phase = frontmatter.current_phase || null;
|
|
1085
|
-
result.total_phases = frontmatter.total_phases || null;
|
|
1086
|
-
result.phase_name = frontmatter.phase_slug || frontmatter.phase_name || null;
|
|
1087
|
-
result.status = frontmatter.status || null;
|
|
1088
|
-
result.progress = frontmatter.progress_percent !== undefined ? frontmatter.progress_percent : null;
|
|
1089
|
-
result.plans_total = frontmatter.plans_total || null;
|
|
1090
|
-
result.plans_complete = frontmatter.plans_complete || null;
|
|
1091
|
-
result.last_activity = frontmatter.last_activity || null;
|
|
1092
|
-
result.last_command = frontmatter.last_command || null;
|
|
1093
|
-
result.blockers = frontmatter.blockers || [];
|
|
1094
|
-
return result;
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
// Legacy regex-based parsing (version 1 format, no frontmatter)
|
|
1098
|
-
// DEPRECATED (2026-02): v1 STATE.md format (no YAML frontmatter) is deprecated.
|
|
1099
|
-
// New projects should use v2 (frontmatter) format, generated by /pbr:setup.
|
|
1100
|
-
// v1 support will be removed in a future major version.
|
|
1101
|
-
process.stderr.write('[pbr] WARNING: STATE.md uses legacy v1 format. Run /pbr:setup to migrate to v2 format.\n');
|
|
1102
|
-
// Extract "Phase: N of M"
|
|
1103
|
-
const phaseMatch = content.match(/Phase:\s*(\d+)\s+of\s+(\d+)/);
|
|
1104
|
-
if (phaseMatch) {
|
|
1105
|
-
result.current_phase = parseInt(phaseMatch[1], 10);
|
|
1106
|
-
result.total_phases = parseInt(phaseMatch[2], 10);
|
|
1107
|
-
}
|
|
314
|
+
function referenceGet(name, options) {
|
|
315
|
+
// Resolve plugin root — try CLAUDE_PLUGIN_ROOT env, then walk up from __dirname
|
|
316
|
+
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || path.resolve(__dirname, '..');
|
|
317
|
+
let root = normalizeMsysPath(pluginRoot);
|
|
318
|
+
return _referenceGet(name, options, root);
|
|
319
|
+
}
|
|
1108
320
|
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
321
|
+
function resolvePluginRoot() {
|
|
322
|
+
// Resolve plugin root — try CLAUDE_PLUGIN_ROOT env, then walk up from __dirname
|
|
323
|
+
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || path.resolve(__dirname, '..');
|
|
324
|
+
return normalizeMsysPath(pluginRoot);
|
|
325
|
+
}
|
|
1114
326
|
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
result.progress = parseInt(progressMatch[1], 10);
|
|
1119
|
-
}
|
|
327
|
+
function skillSectionGet(skillName, sectionQuery) {
|
|
328
|
+
return _skillSection(skillName, sectionQuery, resolvePluginRoot());
|
|
329
|
+
}
|
|
1120
330
|
|
|
1121
|
-
|
|
1122
|
-
const
|
|
1123
|
-
|
|
1124
|
-
|
|
331
|
+
function listSkillHeadings(skillName) {
|
|
332
|
+
const { listHeadings } = require('./lib/reference');
|
|
333
|
+
const root = resolvePluginRoot();
|
|
334
|
+
const skillPath = require('path').join(root, 'skills', skillName, 'SKILL.md');
|
|
335
|
+
if (!require('fs').existsSync(skillPath)) {
|
|
336
|
+
return { error: `Skill not found: ${skillName}`, available: _listAvailableSkills(root) };
|
|
1125
337
|
}
|
|
338
|
+
const content = require('fs').readFileSync(skillPath, 'utf8');
|
|
339
|
+
return { skill: skillName, headings: listHeadings(content) };
|
|
340
|
+
}
|
|
1126
341
|
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
function parseRoadmapMd(content) {
|
|
1131
|
-
const result = { phases: [], has_progress_table: false };
|
|
1132
|
-
|
|
1133
|
-
// Find Phase Overview table
|
|
1134
|
-
const overviewMatch = content.match(/## Phase Overview[\s\S]*?\|[\s\S]*?(?=\n##|\s*$)/);
|
|
1135
|
-
if (overviewMatch) {
|
|
1136
|
-
const rows = overviewMatch[0].split('\n').filter(r => r.includes('|'));
|
|
1137
|
-
// Skip header and separator rows
|
|
1138
|
-
for (let i = 2; i < rows.length; i++) {
|
|
1139
|
-
const cols = rows[i].split('|').map(c => c.trim()).filter(Boolean);
|
|
1140
|
-
if (cols.length >= 3) {
|
|
1141
|
-
result.phases.push({
|
|
1142
|
-
number: cols[0],
|
|
1143
|
-
name: cols[1],
|
|
1144
|
-
goal: cols[2],
|
|
1145
|
-
plans: cols[3] || '',
|
|
1146
|
-
wave: cols[4] || '',
|
|
1147
|
-
status: cols[5] || 'pending'
|
|
1148
|
-
});
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
}
|
|
342
|
+
function contextTriage(options) {
|
|
343
|
+
return _contextTriage(options, planningDir);
|
|
344
|
+
}
|
|
1152
345
|
|
|
1153
|
-
|
|
1154
|
-
|
|
346
|
+
function stalenessCheck(phaseSlug) { return _stalenessCheck(phaseSlug, planningDir); }
|
|
347
|
+
function summaryGate(phaseSlug, planId) { return _summaryGate(phaseSlug, planId, planningDir); }
|
|
348
|
+
function checkpointInit(phaseSlug, plans) { return _checkpointInit(phaseSlug, plans, planningDir); }
|
|
349
|
+
function checkpointUpdate(phaseSlug, opts) { return _checkpointUpdate(phaseSlug, opts, planningDir); }
|
|
350
|
+
function seedsMatch(phaseSlug, phaseNum) { return _seedsMatch(phaseSlug, phaseNum, planningDir); }
|
|
351
|
+
function ciPoll(runId, timeoutSecs) { return _ciPoll(runId, timeoutSecs, planningDir); }
|
|
352
|
+
function ciFix(options) { return _runCiFixLoop({ ...options, cwd: path.resolve('.') }); }
|
|
353
|
+
function rollbackPlan(manifestPath) { return _rollback(manifestPath, planningDir); }
|
|
1155
354
|
|
|
1156
|
-
|
|
355
|
+
function helpListCmd() {
|
|
356
|
+
const root = resolvePluginRoot();
|
|
357
|
+
return _helpList(root);
|
|
358
|
+
}
|
|
359
|
+
function skillMetadataCmd(skillName) {
|
|
360
|
+
const root = resolvePluginRoot();
|
|
361
|
+
return _skillMetadata(skillName, root);
|
|
1157
362
|
}
|
|
1158
363
|
|
|
1159
|
-
function
|
|
1160
|
-
const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
1161
|
-
if (!match) return {};
|
|
1162
|
-
|
|
1163
|
-
const yaml = match[1];
|
|
1164
|
-
const result = {};
|
|
364
|
+
function quickStatus() { return _quickStatus(planningDir); }
|
|
1165
365
|
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
366
|
+
/**
|
|
367
|
+
* Build cleanup context from phase SUMMARY files and git log.
|
|
368
|
+
* @param {string} phaseNum - Phase number (e.g. "38")
|
|
369
|
+
* @returns {{ phaseName: string, phaseNum: string, keyFiles: string[], commitMessages: string[], summaryDescriptions: string[] }}
|
|
370
|
+
*/
|
|
371
|
+
function buildCleanupContext(phaseNum) {
|
|
372
|
+
const padded = String(phaseNum).padStart(2, '0');
|
|
373
|
+
const phasesDir = path.join(planningDir, 'phases');
|
|
374
|
+
if (!fs.existsSync(phasesDir)) throw new Error('No phases directory found');
|
|
1169
375
|
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
if (/^\s+-\s+/.test(line) && currentKey) {
|
|
1173
|
-
const val = line.replace(/^\s+-\s+/, '').trim().replace(/^["']|["']$/g, '');
|
|
1174
|
-
if (!result[currentKey]) result[currentKey] = [];
|
|
1175
|
-
if (Array.isArray(result[currentKey])) {
|
|
1176
|
-
result[currentKey].push(val);
|
|
1177
|
-
}
|
|
1178
|
-
continue;
|
|
1179
|
-
}
|
|
376
|
+
const phaseDir = fs.readdirSync(phasesDir).find(d => d.startsWith(padded + '-'));
|
|
377
|
+
if (!phaseDir) throw new Error(`Phase ${phaseNum} directory not found`);
|
|
1180
378
|
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
if (kvMatch) {
|
|
1184
|
-
currentKey = kvMatch[1];
|
|
1185
|
-
let val = kvMatch[2].trim();
|
|
379
|
+
const phaseName = phaseDir.replace(/^\d+-/, '').replace(/-/g, ' ');
|
|
380
|
+
const phaseDirPath = path.join(phasesDir, phaseDir);
|
|
1186
381
|
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
382
|
+
// Collect key_files and descriptions from all SUMMARY files
|
|
383
|
+
const keyFiles = [];
|
|
384
|
+
const summaryDescriptions = [];
|
|
385
|
+
const summaryFiles = fs.readdirSync(phaseDirPath).filter(f => /^SUMMARY/i.test(f) && f.endsWith('.md'));
|
|
386
|
+
for (const sf of summaryFiles) {
|
|
387
|
+
try {
|
|
388
|
+
const content = fs.readFileSync(path.join(phaseDirPath, sf), 'utf8');
|
|
389
|
+
const fm = parseYamlFrontmatter(content);
|
|
390
|
+
if (fm.key_files && Array.isArray(fm.key_files)) {
|
|
391
|
+
keyFiles.push(...fm.key_files.map(kf => typeof kf === 'string' ? kf.split(':')[0].trim() : ''));
|
|
1190
392
|
}
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
if (val.startsWith('[') && val.endsWith(']')) {
|
|
1194
|
-
result[currentKey] = val.slice(1, -1).split(',')
|
|
1195
|
-
.map(v => v.trim().replace(/^["']|["']$/g, ''))
|
|
1196
|
-
.filter(Boolean);
|
|
1197
|
-
continue;
|
|
393
|
+
if (fm.provides && Array.isArray(fm.provides)) {
|
|
394
|
+
summaryDescriptions.push(...fm.provides);
|
|
1198
395
|
}
|
|
1199
|
-
|
|
1200
|
-
// Clean quotes
|
|
1201
|
-
val = val.replace(/^["']|["']$/g, '');
|
|
1202
|
-
|
|
1203
|
-
// Type coercion
|
|
1204
|
-
if (val === 'true') val = true;
|
|
1205
|
-
else if (val === 'false') val = false;
|
|
1206
|
-
else if (/^\d+$/.test(val)) val = parseInt(val, 10);
|
|
1207
|
-
|
|
1208
|
-
result[currentKey] = val;
|
|
1209
|
-
}
|
|
396
|
+
} catch (_e) { /* skip unreadable summaries */ }
|
|
1210
397
|
}
|
|
1211
398
|
|
|
1212
|
-
//
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
let section = null;
|
|
1223
|
-
|
|
1224
|
-
const inMustHaves = yaml.split('\n');
|
|
1225
|
-
let collecting = false;
|
|
1226
|
-
|
|
1227
|
-
for (const line of inMustHaves) {
|
|
1228
|
-
if (/^\s*must_haves:/.test(line)) {
|
|
1229
|
-
collecting = true;
|
|
1230
|
-
continue;
|
|
1231
|
-
}
|
|
1232
|
-
if (collecting) {
|
|
1233
|
-
if (/^\s{2}truths:/.test(line)) { section = 'truths'; continue; }
|
|
1234
|
-
if (/^\s{2}artifacts:/.test(line)) { section = 'artifacts'; continue; }
|
|
1235
|
-
if (/^\s{2}key_links:/.test(line)) { section = 'key_links'; continue; }
|
|
1236
|
-
if (/^\w/.test(line)) break; // New top-level key, stop
|
|
1237
|
-
|
|
1238
|
-
if (section && /^\s+-\s+/.test(line)) {
|
|
1239
|
-
result[section].push(line.replace(/^\s+-\s+/, '').trim().replace(/^["']|["']$/g, ''));
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
}
|
|
399
|
+
// Get recent commit messages
|
|
400
|
+
let commitMessages = [];
|
|
401
|
+
try {
|
|
402
|
+
const { execSync } = require('child_process');
|
|
403
|
+
const log = execSync('git log --oneline -20', { encoding: 'utf8', cwd: path.join(planningDir, '..') });
|
|
404
|
+
commitMessages = log.split('\n').filter(l => l.trim()).map(l => {
|
|
405
|
+
const parts = l.match(/^[0-9a-f]+\s+(.*)/);
|
|
406
|
+
return parts ? parts[1] : '';
|
|
407
|
+
}).filter(Boolean);
|
|
408
|
+
} catch (_e) { /* git not available */ }
|
|
1243
409
|
|
|
1244
|
-
return
|
|
410
|
+
return { phaseName, phaseNum: String(phaseNum), keyFiles, commitMessages, summaryDescriptions };
|
|
1245
411
|
}
|
|
1246
412
|
|
|
1247
|
-
// ---
|
|
413
|
+
// --- Claim wrapper functions ---
|
|
1248
414
|
|
|
1249
|
-
function
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
return [];
|
|
1254
|
-
}
|
|
415
|
+
function claimAcquire(phaseSlug, sessionId, skill) {
|
|
416
|
+
const phaseDir = path.join(planningDir, 'phases', phaseSlug);
|
|
417
|
+
if (!fs.existsSync(phaseDir)) return { error: `Phase directory not found: ${phaseSlug}` };
|
|
418
|
+
return acquireClaim(planningDir, phaseDir, sessionId, skill);
|
|
1255
419
|
}
|
|
1256
420
|
|
|
1257
|
-
function
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
return 'not_started';
|
|
1262
|
-
}
|
|
1263
|
-
if (completedCount === 0 && summaryCount === 0) return 'planned';
|
|
1264
|
-
if (completedCount < planCount) return 'building';
|
|
1265
|
-
if (!hasVerification) return 'built';
|
|
1266
|
-
// Check verification status
|
|
1267
|
-
try {
|
|
1268
|
-
const vContent = fs.readFileSync(path.join(phaseDir, 'VERIFICATION.md'), 'utf8');
|
|
1269
|
-
if (/status:\s*["']?passed/i.test(vContent)) return 'verified';
|
|
1270
|
-
if (/status:\s*["']?gaps_found/i.test(vContent)) return 'needs_fixes';
|
|
1271
|
-
return 'reviewed';
|
|
1272
|
-
} catch (_) {
|
|
1273
|
-
return 'built';
|
|
1274
|
-
}
|
|
421
|
+
function claimRelease(phaseSlug, sessionId) {
|
|
422
|
+
const phaseDir = path.join(planningDir, 'phases', phaseSlug);
|
|
423
|
+
if (!fs.existsSync(phaseDir)) return { error: `Phase directory not found: ${phaseSlug}` };
|
|
424
|
+
return releaseClaim(planningDir, phaseDir, sessionId);
|
|
1275
425
|
}
|
|
1276
426
|
|
|
1277
|
-
function
|
|
1278
|
-
|
|
1279
|
-
return (mustHaves.truths || []).length +
|
|
1280
|
-
(mustHaves.artifacts || []).length +
|
|
1281
|
-
(mustHaves.key_links || []).length;
|
|
427
|
+
function claimList() {
|
|
428
|
+
return _listClaims(planningDir);
|
|
1282
429
|
}
|
|
1283
430
|
|
|
1284
|
-
function calculateProgress() {
|
|
1285
|
-
const phasesDir = path.join(planningDir, 'phases');
|
|
1286
|
-
if (!fs.existsSync(phasesDir)) {
|
|
1287
|
-
return { total: 0, completed: 0, percentage: 0 };
|
|
1288
|
-
}
|
|
1289
|
-
|
|
1290
|
-
let total = 0;
|
|
1291
|
-
let completed = 0;
|
|
1292
|
-
|
|
1293
|
-
const entries = fs.readdirSync(phasesDir, { withFileTypes: true })
|
|
1294
|
-
.filter(e => e.isDirectory());
|
|
1295
|
-
|
|
1296
|
-
for (const entry of entries) {
|
|
1297
|
-
const dir = path.join(phasesDir, entry.name);
|
|
1298
|
-
const plans = findFiles(dir, /-PLAN\.md$/);
|
|
1299
|
-
total += plans.length;
|
|
1300
431
|
|
|
1301
|
-
|
|
1302
|
-
for (const s of summaries) {
|
|
1303
|
-
const content = fs.readFileSync(path.join(dir, s), 'utf8');
|
|
1304
|
-
if (/status:\s*["']?complete/i.test(content)) completed++;
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
432
|
+
// --- CLI entry point (thin router — delegates to command modules) ---
|
|
1307
433
|
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
};
|
|
1313
|
-
}
|
|
1314
|
-
|
|
1315
|
-
function output(data) {
|
|
1316
|
-
process.stdout.write(JSON.stringify(data, null, 2));
|
|
1317
|
-
process.exit(0);
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1320
|
-
function error(msg) {
|
|
1321
|
-
process.stdout.write(JSON.stringify({ error: msg }));
|
|
1322
|
-
process.exit(1);
|
|
1323
|
-
}
|
|
1324
|
-
|
|
1325
|
-
/**
|
|
1326
|
-
* Write content to a file atomically: write to .tmp, backup original to .bak,
|
|
1327
|
-
* rename .tmp over original. On failure, restore from .bak if available.
|
|
1328
|
-
*
|
|
1329
|
-
* @param {string} filePath - Target file path
|
|
1330
|
-
* @param {string} content - Content to write
|
|
1331
|
-
* @returns {{success: boolean, error?: string}} Result
|
|
1332
|
-
*/
|
|
1333
|
-
function atomicWrite(filePath, content) {
|
|
1334
|
-
const tmpPath = filePath + '.tmp';
|
|
1335
|
-
const bakPath = filePath + '.bak';
|
|
434
|
+
async function main() {
|
|
435
|
+
const args = process.argv.slice(2);
|
|
436
|
+
const command = args[0];
|
|
437
|
+
const ctx = { planningDir, cwd, output, error };
|
|
1336
438
|
|
|
1337
439
|
try {
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
if (
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
440
|
+
if (command === 'state') {
|
|
441
|
+
await handleState(args, ctx);
|
|
442
|
+
} else if (command === 'state-bundle') {
|
|
443
|
+
handleStateBundle(args, ctx);
|
|
444
|
+
} else if (command === 'config' || command === 'validate') {
|
|
445
|
+
await handleConfig(args, ctx);
|
|
446
|
+
} else if (command === 'roadmap') {
|
|
447
|
+
await handleRoadmap(args, ctx);
|
|
448
|
+
} else if (command === 'phase') {
|
|
449
|
+
await handlePhase(args, ctx);
|
|
450
|
+
} else if (command === 'compound') {
|
|
451
|
+
await handleCompound(args, ctx);
|
|
452
|
+
} else if (command === 'init') {
|
|
453
|
+
await handleInit(args, ctx);
|
|
454
|
+
} else if (['plan-index', 'frontmatter', 'must-haves', 'phase-info', 'milestone-stats'].includes(command)) {
|
|
455
|
+
handlePhaseDirect(args, ctx);
|
|
456
|
+
} else if (command === 'verify') {
|
|
457
|
+
handleVerify(args, ctx);
|
|
458
|
+
} else if (command === 'spot-check') {
|
|
459
|
+
handleSpotCheckDirect(args, ctx);
|
|
460
|
+
} else if (command === 'staleness-check') {
|
|
461
|
+
handleStalenessCheck(args, ctx);
|
|
462
|
+
} else if (command === 'summary-gate') {
|
|
463
|
+
handleSummaryGate(args, ctx);
|
|
464
|
+
} else if (command === 'checkpoint') {
|
|
465
|
+
handleCheckpoint(args, ctx);
|
|
466
|
+
} else if (command === 'seeds') {
|
|
467
|
+
handleSeeds(args, ctx);
|
|
468
|
+
} else if (command === 'todo') {
|
|
469
|
+
handleTodo(args, ctx);
|
|
470
|
+
} else if (command === 'history') {
|
|
471
|
+
handleHistory(args, ctx);
|
|
472
|
+
} else if (command === 'auto-cleanup') {
|
|
473
|
+
handleAutoCleanup(args, ctx);
|
|
474
|
+
} else if (command === 'benchmarks') {
|
|
475
|
+
await handleBenchmarks(args, ctx);
|
|
476
|
+
} else if (command === 'calibrate') {
|
|
477
|
+
handleCalibrate(args, ctx);
|
|
478
|
+
} else if (command === 'stress-test') {
|
|
479
|
+
await handleStressTest(args, ctx);
|
|
480
|
+
} else {
|
|
481
|
+
// Delegate to misc handler for all remaining commands
|
|
482
|
+
const result = await handleMisc(args, ctx);
|
|
483
|
+
if (result === 'NOT_HANDLED') {
|
|
484
|
+
error(`Unknown command: ${args.join(' ')}\nRun: pbr-tools.js help`);
|
|
1347
485
|
}
|
|
1348
486
|
}
|
|
1349
|
-
|
|
1350
|
-
// 3. Rename temp over original (atomic on most filesystems)
|
|
1351
|
-
fs.renameSync(tmpPath, filePath);
|
|
1352
|
-
|
|
1353
|
-
return { success: true };
|
|
1354
487
|
} catch (e) {
|
|
1355
|
-
|
|
1356
|
-
try {
|
|
1357
|
-
if (fs.existsSync(bakPath)) {
|
|
1358
|
-
fs.copyFileSync(bakPath, filePath);
|
|
1359
|
-
}
|
|
1360
|
-
} catch (_restoreErr) {
|
|
1361
|
-
// Restore also failed — nothing more we can do
|
|
1362
|
-
}
|
|
1363
|
-
|
|
1364
|
-
// Clean up temp file if it still exists
|
|
1365
|
-
try {
|
|
1366
|
-
if (fs.existsSync(tmpPath)) {
|
|
1367
|
-
fs.unlinkSync(tmpPath);
|
|
1368
|
-
}
|
|
1369
|
-
} catch (_cleanupErr) {
|
|
1370
|
-
// Best-effort cleanup
|
|
1371
|
-
}
|
|
1372
|
-
|
|
1373
|
-
return { success: false, error: e.message };
|
|
488
|
+
error(e.message);
|
|
1374
489
|
}
|
|
1375
490
|
}
|
|
1376
491
|
|
|
1377
|
-
if (require.main === module || process.argv[1] === __filename) { main(); }
|
|
1378
|
-
module.exports = { parseStateMd, parseRoadmapMd, parseYamlFrontmatter, parseMustHaves, countMustHaves, stateLoad, stateCheckProgress, configLoad, configClearCache, configValidate, lockedFileUpdate, planIndex, determinePhaseStatus, findFiles, atomicWrite, tailLines, frontmatter, mustHavesCollect, phaseInfo, stateUpdate, roadmapUpdateStatus, roadmapUpdatePlans,
|
|
492
|
+
if (require.main === module || process.argv[1] === __filename) { main().catch(err => { process.stderr.write(err.message + '\n'); process.exit(1); }); }
|
|
493
|
+
module.exports = { KNOWN_AGENTS, initExecutePhase, initPlanPhase, initQuick, initVerifyWork, initResume, initProgress, initStateBundle: stateBundle, stateBundle, statePatch, stateAdvancePlan, stateRecordMetric, stateRecordActivity, stateUpdateProgress, parseStateMd, parseRoadmapMd, parseYamlFrontmatter, parseMustHaves, countMustHaves, stateLoad, stateCheckProgress, configLoad, configClearCache, configValidate, lockedFileUpdate, planIndex, determinePhaseStatus, findFiles, atomicWrite, tailLines, frontmatter, mustHavesCollect, phaseInfo, stateUpdate, roadmapUpdateStatus, roadmapUpdatePlans, roadmapAnalyze, updateFrontmatterField, updateTableRow, findRoadmapRow, resolveDepthProfile, DEPTH_PROFILE_DEFAULTS, historyAppend, historyLoad, VALID_STATUS_TRANSITIONS, validateStatusTransition, writeActiveSkill, phaseAdd, phaseRemove, phaseList, loadUserDefaults, saveUserDefaults, mergeUserDefaults, USER_DEFAULTS_PATH, todoList, todoGet, todoAdd, todoDone, migrate, verifySpotCheck, referenceGet, milestoneStats, contextTriage, stalenessCheck, summaryGate, checkpointInit, checkpointUpdate, seedsMatch, ciPoll, ciFix, parseJestOutput: _parseJestOutput, parseLintOutput: _parseLintOutput, autoFixLint: _autoFixLint, runCiFixLoop: _runCiFixLoop, rollbackPlan, sessionLoad, sessionSave, SESSION_ALLOWED_KEYS, claimAcquire, claimRelease, claimList, skillSectionGet, listSkillHeadings, stepVerify: _stepVerify, phaseAlternatives: _phaseAlternatives, prerequisiteAlternatives: _prereqAlternatives, configAlternatives: _configAlternatives, phaseComplete, phaseInsert, quickStatus, autoCloseTodos, autoArchiveNotes, buildCleanupContext, helpListCmd, skillMetadataCmd, initMapCodebase };
|