@jokerized/getresearchdone 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +103 -0
- package/README.md +211 -0
- package/agents/grd-baseline-assessor.md +684 -0
- package/agents/grd-code-reviewer.md +300 -0
- package/agents/grd-codebase-mapper.md +355 -0
- package/agents/grd-critique-agent.md +119 -0
- package/agents/grd-debugger.md +519 -0
- package/agents/grd-deep-diver.md +737 -0
- package/agents/grd-eval-planner.md +913 -0
- package/agents/grd-eval-reporter.md +717 -0
- package/agents/grd-executor.md +683 -0
- package/agents/grd-feasibility-analyst.md +624 -0
- package/agents/grd-integration-checker.md +367 -0
- package/agents/grd-knowledge-miner.md +81 -0
- package/agents/grd-migrator.md +88 -0
- package/agents/grd-phase-researcher.md +697 -0
- package/agents/grd-plan-checker.md +443 -0
- package/agents/grd-planner.md +1532 -0
- package/agents/grd-product-owner.md +562 -0
- package/agents/grd-project-researcher.md +513 -0
- package/agents/grd-research-synthesizer.md +273 -0
- package/agents/grd-roadmapper.md +798 -0
- package/agents/grd-surveyor.md +566 -0
- package/agents/grd-verifier.md +893 -0
- package/bin/gd.js +4 -0
- package/bin/gd.ts +227 -0
- package/bin/grd-manifest.js +4 -0
- package/bin/grd-manifest.ts +286 -0
- package/bin/grd-mcp-server.js +4 -0
- package/bin/grd-mcp-server.ts +124 -0
- package/bin/grd-tools.js +4 -0
- package/bin/grd-tools.ts +2471 -0
- package/bin/postinstall.js +4 -0
- package/bin/postinstall.ts +80 -0
- package/commands/add-phase.md +123 -0
- package/commands/add-todo.md +87 -0
- package/commands/assess-baseline.md +289 -0
- package/commands/autopilot.md +100 -0
- package/commands/autoplan.md +55 -0
- package/commands/check-todos.md +87 -0
- package/commands/compare-methods.md +262 -0
- package/commands/complete-milestone.md +225 -0
- package/commands/debug.md +372 -0
- package/commands/deep-dive.md +288 -0
- package/commands/discover.md +281 -0
- package/commands/discuss-phase.md +188 -0
- package/commands/discuss.md +55 -0
- package/commands/eval-report.md +310 -0
- package/commands/evolve.md +79 -0
- package/commands/execute-phase.md +1017 -0
- package/commands/feasibility.md +292 -0
- package/commands/help.md +407 -0
- package/commands/init.md +1508 -0
- package/commands/insert-phase.md +113 -0
- package/commands/iterate.md +327 -0
- package/commands/list-phase-assumptions.md +217 -0
- package/commands/long-term-roadmap.md +202 -0
- package/commands/map-codebase.md +111 -0
- package/commands/migrate.md +159 -0
- package/commands/new-milestone.md +169 -0
- package/commands/pause-work.md +83 -0
- package/commands/plan-milestone-gaps.md +373 -0
- package/commands/plan-phase.md +655 -0
- package/commands/principles.md +328 -0
- package/commands/product-plan.md +319 -0
- package/commands/progress.md +481 -0
- package/commands/quick.md +167 -0
- package/commands/reapply-patches.md +154 -0
- package/commands/remove-phase.md +97 -0
- package/commands/requirement.md +96 -0
- package/commands/resume-project.md +113 -0
- package/commands/settings.md +1144 -0
- package/commands/survey.md +242 -0
- package/commands/sync.md +246 -0
- package/commands/tracker-setup.md +322 -0
- package/commands/update.md +202 -0
- package/commands/verify-phase.md +335 -0
- package/commands/verify-work.md +701 -0
- package/commands/wireup.md +29 -0
- package/dist/bin/gd.d.ts +3 -0
- package/dist/bin/gd.d.ts.map +1 -0
- package/dist/bin/gd.js +178 -0
- package/dist/bin/gd.js.map +1 -0
- package/dist/bin/grd-manifest.d.ts +3 -0
- package/dist/bin/grd-manifest.d.ts.map +1 -0
- package/dist/bin/grd-manifest.js +202 -0
- package/dist/bin/grd-manifest.js.map +1 -0
- package/dist/bin/grd-mcp-server.d.ts +3 -0
- package/dist/bin/grd-mcp-server.d.ts.map +1 -0
- package/dist/bin/grd-mcp-server.js +71 -0
- package/dist/bin/grd-mcp-server.js.map +1 -0
- package/dist/bin/grd-tools.d.ts +3 -0
- package/dist/bin/grd-tools.d.ts.map +1 -0
- package/dist/bin/grd-tools.js +1680 -0
- package/dist/bin/grd-tools.js.map +1 -0
- package/dist/bin/postinstall.d.ts +3 -0
- package/dist/bin/postinstall.d.ts.map +1 -0
- package/dist/bin/postinstall.js +61 -0
- package/dist/bin/postinstall.js.map +1 -0
- package/dist/lib/autopilot-milestone.d.ts +2 -0
- package/dist/lib/autopilot-milestone.d.ts.map +1 -0
- package/dist/lib/autopilot-milestone.js +94 -0
- package/dist/lib/autopilot-milestone.js.map +1 -0
- package/dist/lib/autopilot-pipeline.d.ts +2 -0
- package/dist/lib/autopilot-pipeline.d.ts.map +1 -0
- package/dist/lib/autopilot-pipeline.js +830 -0
- package/dist/lib/autopilot-pipeline.js.map +1 -0
- package/dist/lib/autopilot-waves.d.ts +2 -0
- package/dist/lib/autopilot-waves.d.ts.map +1 -0
- package/dist/lib/autopilot-waves.js +266 -0
- package/dist/lib/autopilot-waves.js.map +1 -0
- package/dist/lib/autopilot.d.ts +2 -0
- package/dist/lib/autopilot.d.ts.map +1 -0
- package/dist/lib/autopilot.js +1314 -0
- package/dist/lib/autopilot.js.map +1 -0
- package/dist/lib/autoplan.d.ts +2 -0
- package/dist/lib/autoplan.d.ts.map +1 -0
- package/dist/lib/autoplan.js +198 -0
- package/dist/lib/autoplan.js.map +1 -0
- package/dist/lib/autoresearch.d.ts +2 -0
- package/dist/lib/autoresearch.d.ts.map +1 -0
- package/dist/lib/autoresearch.js +626 -0
- package/dist/lib/autoresearch.js.map +1 -0
- package/dist/lib/backend.d.ts +2 -0
- package/dist/lib/backend.d.ts.map +1 -0
- package/dist/lib/backend.js +1036 -0
- package/dist/lib/backend.js.map +1 -0
- package/dist/lib/benchmark.d.ts +99 -0
- package/dist/lib/benchmark.d.ts.map +1 -0
- package/dist/lib/benchmark.js +278 -0
- package/dist/lib/benchmark.js.map +1 -0
- package/dist/lib/citations.d.ts +2 -0
- package/dist/lib/citations.d.ts.map +1 -0
- package/dist/lib/citations.js +642 -0
- package/dist/lib/citations.js.map +1 -0
- package/dist/lib/cleanup.d.ts +2 -0
- package/dist/lib/cleanup.d.ts.map +1 -0
- package/dist/lib/cleanup.js +1222 -0
- package/dist/lib/cleanup.js.map +1 -0
- package/dist/lib/cli/adapters.d.ts +10 -0
- package/dist/lib/cli/adapters.d.ts.map +1 -0
- package/dist/lib/cli/adapters.js +27 -0
- package/dist/lib/cli/adapters.js.map +1 -0
- package/dist/lib/cli/agent.d.ts +17 -0
- package/dist/lib/cli/agent.d.ts.map +1 -0
- package/dist/lib/cli/agent.js +53 -0
- package/dist/lib/cli/agent.js.map +1 -0
- package/dist/lib/cli/index.d.ts +21 -0
- package/dist/lib/cli/index.d.ts.map +1 -0
- package/dist/lib/cli/index.js +264 -0
- package/dist/lib/cli/index.js.map +1 -0
- package/dist/lib/cli/output.d.ts +20 -0
- package/dist/lib/cli/output.d.ts.map +1 -0
- package/dist/lib/cli/output.js +22 -0
- package/dist/lib/cli/output.js.map +1 -0
- package/dist/lib/cli/scan-dispatch.d.ts +9 -0
- package/dist/lib/cli/scan-dispatch.d.ts.map +1 -0
- package/dist/lib/cli/scan-dispatch.js +107 -0
- package/dist/lib/cli/scan-dispatch.js.map +1 -0
- package/dist/lib/cli/tools.d.ts +16 -0
- package/dist/lib/cli/tools.d.ts.map +1 -0
- package/dist/lib/cli/tools.js +168 -0
- package/dist/lib/cli/tools.js.map +1 -0
- package/dist/lib/commands/_dashboard-parsers.d.ts +2 -0
- package/dist/lib/commands/_dashboard-parsers.d.ts.map +1 -0
- package/dist/lib/commands/_dashboard-parsers.js +192 -0
- package/dist/lib/commands/_dashboard-parsers.js.map +1 -0
- package/dist/lib/commands/analysis.d.ts +2 -0
- package/dist/lib/commands/analysis.d.ts.map +1 -0
- package/dist/lib/commands/analysis.js +1418 -0
- package/dist/lib/commands/analysis.js.map +1 -0
- package/dist/lib/commands/assumptions.d.ts +2 -0
- package/dist/lib/commands/assumptions.d.ts.map +1 -0
- package/dist/lib/commands/assumptions.js +166 -0
- package/dist/lib/commands/assumptions.js.map +1 -0
- package/dist/lib/commands/blame.d.ts +2 -0
- package/dist/lib/commands/blame.d.ts.map +1 -0
- package/dist/lib/commands/blame.js +133 -0
- package/dist/lib/commands/blame.js.map +1 -0
- package/dist/lib/commands/budget.d.ts +2 -0
- package/dist/lib/commands/budget.d.ts.map +1 -0
- package/dist/lib/commands/budget.js +100 -0
- package/dist/lib/commands/budget.js.map +1 -0
- package/dist/lib/commands/check-plans.d.ts +2 -0
- package/dist/lib/commands/check-plans.d.ts.map +1 -0
- package/dist/lib/commands/check-plans.js +190 -0
- package/dist/lib/commands/check-plans.js.map +1 -0
- package/dist/lib/commands/config.d.ts +2 -0
- package/dist/lib/commands/config.d.ts.map +1 -0
- package/dist/lib/commands/config.js +188 -0
- package/dist/lib/commands/config.js.map +1 -0
- package/dist/lib/commands/dashboard.d.ts +2 -0
- package/dist/lib/commands/dashboard.d.ts.map +1 -0
- package/dist/lib/commands/dashboard.js +466 -0
- package/dist/lib/commands/dashboard.js.map +1 -0
- package/dist/lib/commands/estimate.d.ts +2 -0
- package/dist/lib/commands/estimate.d.ts.map +1 -0
- package/dist/lib/commands/estimate.js +148 -0
- package/dist/lib/commands/estimate.js.map +1 -0
- package/dist/lib/commands/eval-diff.d.ts +2 -0
- package/dist/lib/commands/eval-diff.d.ts.map +1 -0
- package/dist/lib/commands/eval-diff.js +213 -0
- package/dist/lib/commands/eval-diff.js.map +1 -0
- package/dist/lib/commands/freshness.d.ts +2 -0
- package/dist/lib/commands/freshness.d.ts.map +1 -0
- package/dist/lib/commands/freshness.js +163 -0
- package/dist/lib/commands/freshness.js.map +1 -0
- package/dist/lib/commands/health.d.ts +2 -0
- package/dist/lib/commands/health.d.ts.map +1 -0
- package/dist/lib/commands/health.js +435 -0
- package/dist/lib/commands/health.js.map +1 -0
- package/dist/lib/commands/index.d.ts +2 -0
- package/dist/lib/commands/index.d.ts.map +1 -0
- package/dist/lib/commands/index.js +128 -0
- package/dist/lib/commands/index.js.map +1 -0
- package/dist/lib/commands/install.d.ts +56 -0
- package/dist/lib/commands/install.d.ts.map +1 -0
- package/dist/lib/commands/install.js +214 -0
- package/dist/lib/commands/install.js.map +1 -0
- package/dist/lib/commands/knowhow-aggregator.d.ts +2 -0
- package/dist/lib/commands/knowhow-aggregator.d.ts.map +1 -0
- package/dist/lib/commands/knowhow-aggregator.js +279 -0
- package/dist/lib/commands/knowhow-aggregator.js.map +1 -0
- package/dist/lib/commands/knowledge-search.d.ts +2 -0
- package/dist/lib/commands/knowledge-search.d.ts.map +1 -0
- package/dist/lib/commands/knowledge-search.js +113 -0
- package/dist/lib/commands/knowledge-search.js.map +1 -0
- package/dist/lib/commands/long-term-roadmap.d.ts +2 -0
- package/dist/lib/commands/long-term-roadmap.d.ts.map +1 -0
- package/dist/lib/commands/long-term-roadmap.js +272 -0
- package/dist/lib/commands/long-term-roadmap.js.map +1 -0
- package/dist/lib/commands/patterns.d.ts +91 -0
- package/dist/lib/commands/patterns.d.ts.map +1 -0
- package/dist/lib/commands/patterns.js +391 -0
- package/dist/lib/commands/patterns.js.map +1 -0
- package/dist/lib/commands/phase-info.d.ts +2 -0
- package/dist/lib/commands/phase-info.d.ts.map +1 -0
- package/dist/lib/commands/phase-info.js +509 -0
- package/dist/lib/commands/phase-info.js.map +1 -0
- package/dist/lib/commands/plan-lint.d.ts +56 -0
- package/dist/lib/commands/plan-lint.d.ts.map +1 -0
- package/dist/lib/commands/plan-lint.js +481 -0
- package/dist/lib/commands/plan-lint.js.map +1 -0
- package/dist/lib/commands/plan-phase.d.ts +53 -0
- package/dist/lib/commands/plan-phase.d.ts.map +1 -0
- package/dist/lib/commands/plan-phase.js +288 -0
- package/dist/lib/commands/plan-phase.js.map +1 -0
- package/dist/lib/commands/progress.d.ts +2 -0
- package/dist/lib/commands/progress.d.ts.map +1 -0
- package/dist/lib/commands/progress.js +266 -0
- package/dist/lib/commands/progress.js.map +1 -0
- package/dist/lib/commands/quality.d.ts +2 -0
- package/dist/lib/commands/quality.d.ts.map +1 -0
- package/dist/lib/commands/quality.js +80 -0
- package/dist/lib/commands/quality.js.map +1 -0
- package/dist/lib/commands/rollback.d.ts +2 -0
- package/dist/lib/commands/rollback.d.ts.map +1 -0
- package/dist/lib/commands/rollback.js +145 -0
- package/dist/lib/commands/rollback.js.map +1 -0
- package/dist/lib/commands/scan.d.ts +25 -0
- package/dist/lib/commands/scan.d.ts.map +1 -0
- package/dist/lib/commands/scan.js +28 -0
- package/dist/lib/commands/scan.js.map +1 -0
- package/dist/lib/commands/search.d.ts +2 -0
- package/dist/lib/commands/search.d.ts.map +1 -0
- package/dist/lib/commands/search.js +212 -0
- package/dist/lib/commands/search.js.map +1 -0
- package/dist/lib/commands/select-candidate.d.ts +128 -0
- package/dist/lib/commands/select-candidate.d.ts.map +1 -0
- package/dist/lib/commands/select-candidate.js +518 -0
- package/dist/lib/commands/select-candidate.js.map +1 -0
- package/dist/lib/commands/singularity.d.ts +2 -0
- package/dist/lib/commands/singularity.d.ts.map +1 -0
- package/dist/lib/commands/singularity.js +185 -0
- package/dist/lib/commands/singularity.js.map +1 -0
- package/dist/lib/commands/slug-timestamp.d.ts +2 -0
- package/dist/lib/commands/slug-timestamp.d.ts.map +1 -0
- package/dist/lib/commands/slug-timestamp.js +54 -0
- package/dist/lib/commands/slug-timestamp.js.map +1 -0
- package/dist/lib/commands/tail.d.ts +2 -0
- package/dist/lib/commands/tail.d.ts.map +1 -0
- package/dist/lib/commands/tail.js +100 -0
- package/dist/lib/commands/tail.js.map +1 -0
- package/dist/lib/commands/todo.d.ts +2 -0
- package/dist/lib/commands/todo.d.ts.map +1 -0
- package/dist/lib/commands/todo.js +200 -0
- package/dist/lib/commands/todo.js.map +1 -0
- package/dist/lib/commands/watch.d.ts +2 -0
- package/dist/lib/commands/watch.d.ts.map +1 -0
- package/dist/lib/commands/watch.js +72 -0
- package/dist/lib/commands/watch.js.map +1 -0
- package/dist/lib/complexity.d.ts +55 -0
- package/dist/lib/complexity.d.ts.map +1 -0
- package/dist/lib/complexity.js +80 -0
- package/dist/lib/complexity.js.map +1 -0
- package/dist/lib/context/agents.d.ts +2 -0
- package/dist/lib/context/agents.d.ts.map +1 -0
- package/dist/lib/context/agents.js +344 -0
- package/dist/lib/context/agents.js.map +1 -0
- package/dist/lib/context/base.d.ts +2 -0
- package/dist/lib/context/base.d.ts.map +1 -0
- package/dist/lib/context/base.js +81 -0
- package/dist/lib/context/base.js.map +1 -0
- package/dist/lib/context/execute.d.ts +2 -0
- package/dist/lib/context/execute.d.ts.map +1 -0
- package/dist/lib/context/execute.js +753 -0
- package/dist/lib/context/execute.js.map +1 -0
- package/dist/lib/context/index.d.ts +2 -0
- package/dist/lib/context/index.d.ts.map +1 -0
- package/dist/lib/context/index.js +88 -0
- package/dist/lib/context/index.js.map +1 -0
- package/dist/lib/context/progress.d.ts +2 -0
- package/dist/lib/context/progress.d.ts.map +1 -0
- package/dist/lib/context/progress.js +178 -0
- package/dist/lib/context/progress.js.map +1 -0
- package/dist/lib/context/project.d.ts +2 -0
- package/dist/lib/context/project.d.ts.map +1 -0
- package/dist/lib/context/project.js +413 -0
- package/dist/lib/context/project.js.map +1 -0
- package/dist/lib/context/research.d.ts +2 -0
- package/dist/lib/context/research.d.ts.map +1 -0
- package/dist/lib/context/research.js +466 -0
- package/dist/lib/context/research.js.map +1 -0
- package/dist/lib/dead-ends.d.ts +28 -0
- package/dist/lib/dead-ends.d.ts.map +1 -0
- package/dist/lib/dead-ends.js +451 -0
- package/dist/lib/dead-ends.js.map +1 -0
- package/dist/lib/deps.d.ts +2 -0
- package/dist/lib/deps.d.ts.map +1 -0
- package/dist/lib/deps.js +630 -0
- package/dist/lib/deps.js.map +1 -0
- package/dist/lib/discussion.d.ts +2 -0
- package/dist/lib/discussion.d.ts.map +1 -0
- package/dist/lib/discussion.js +1041 -0
- package/dist/lib/discussion.js.map +1 -0
- package/dist/lib/drift.d.ts +36 -0
- package/dist/lib/drift.d.ts.map +1 -0
- package/dist/lib/drift.js +481 -0
- package/dist/lib/drift.js.map +1 -0
- package/dist/lib/evolve/_dimensions-features.d.ts +2 -0
- package/dist/lib/evolve/_dimensions-features.d.ts.map +1 -0
- package/dist/lib/evolve/_dimensions-features.js +369 -0
- package/dist/lib/evolve/_dimensions-features.js.map +1 -0
- package/dist/lib/evolve/_dimensions.d.ts +2 -0
- package/dist/lib/evolve/_dimensions.d.ts.map +1 -0
- package/dist/lib/evolve/_dimensions.js +358 -0
- package/dist/lib/evolve/_dimensions.js.map +1 -0
- package/dist/lib/evolve/_product-ideation.d.ts +2 -0
- package/dist/lib/evolve/_product-ideation.d.ts.map +1 -0
- package/dist/lib/evolve/_product-ideation.js +281 -0
- package/dist/lib/evolve/_product-ideation.js.map +1 -0
- package/dist/lib/evolve/_prompts.d.ts +2 -0
- package/dist/lib/evolve/_prompts.d.ts.map +1 -0
- package/dist/lib/evolve/_prompts.js +153 -0
- package/dist/lib/evolve/_prompts.js.map +1 -0
- package/dist/lib/evolve/cli.d.ts +2 -0
- package/dist/lib/evolve/cli.d.ts.map +1 -0
- package/dist/lib/evolve/cli.js +224 -0
- package/dist/lib/evolve/cli.js.map +1 -0
- package/dist/lib/evolve/discovery.d.ts +2 -0
- package/dist/lib/evolve/discovery.d.ts.map +1 -0
- package/dist/lib/evolve/discovery.js +391 -0
- package/dist/lib/evolve/discovery.js.map +1 -0
- package/dist/lib/evolve/index.d.ts +2 -0
- package/dist/lib/evolve/index.d.ts.map +1 -0
- package/dist/lib/evolve/index.js +88 -0
- package/dist/lib/evolve/index.js.map +1 -0
- package/dist/lib/evolve/orchestrator.d.ts +2 -0
- package/dist/lib/evolve/orchestrator.d.ts.map +1 -0
- package/dist/lib/evolve/orchestrator.js +851 -0
- package/dist/lib/evolve/orchestrator.js.map +1 -0
- package/dist/lib/evolve/scoring.d.ts +2 -0
- package/dist/lib/evolve/scoring.d.ts.map +1 -0
- package/dist/lib/evolve/scoring.js +118 -0
- package/dist/lib/evolve/scoring.js.map +1 -0
- package/dist/lib/evolve/state.d.ts +2 -0
- package/dist/lib/evolve/state.d.ts.map +1 -0
- package/dist/lib/evolve/state.js +264 -0
- package/dist/lib/evolve/state.js.map +1 -0
- package/dist/lib/evolve/types.d.ts +249 -0
- package/dist/lib/evolve/types.d.ts.map +1 -0
- package/dist/lib/evolve/types.js +3 -0
- package/dist/lib/evolve/types.js.map +1 -0
- package/dist/lib/frontmatter.d.ts +2 -0
- package/dist/lib/frontmatter.d.ts.map +1 -0
- package/dist/lib/frontmatter.js +513 -0
- package/dist/lib/frontmatter.js.map +1 -0
- package/dist/lib/gates.d.ts +2 -0
- package/dist/lib/gates.d.ts.map +1 -0
- package/dist/lib/gates.js +578 -0
- package/dist/lib/gates.js.map +1 -0
- package/dist/lib/genome.d.ts +10 -0
- package/dist/lib/genome.d.ts.map +1 -0
- package/dist/lib/genome.js +368 -0
- package/dist/lib/genome.js.map +1 -0
- package/dist/lib/got.d.ts +2 -0
- package/dist/lib/got.d.ts.map +1 -0
- package/dist/lib/got.js +280 -0
- package/dist/lib/got.js.map +1 -0
- package/dist/lib/invariants.d.ts +2 -0
- package/dist/lib/invariants.d.ts.map +1 -0
- package/dist/lib/invariants.js +298 -0
- package/dist/lib/invariants.js.map +1 -0
- package/dist/lib/knowledge.d.ts +2 -0
- package/dist/lib/knowledge.d.ts.map +1 -0
- package/dist/lib/knowledge.js +658 -0
- package/dist/lib/knowledge.js.map +1 -0
- package/dist/lib/long-term-roadmap.d.ts +2 -0
- package/dist/lib/long-term-roadmap.d.ts.map +1 -0
- package/dist/lib/long-term-roadmap.js +602 -0
- package/dist/lib/long-term-roadmap.js.map +1 -0
- package/dist/lib/markdown-split.d.ts +2 -0
- package/dist/lib/markdown-split.d.ts.map +1 -0
- package/dist/lib/markdown-split.js +199 -0
- package/dist/lib/markdown-split.js.map +1 -0
- package/dist/lib/mcp-server.d.ts +2 -0
- package/dist/lib/mcp-server.d.ts.map +1 -0
- package/dist/lib/mcp-server.js +2424 -0
- package/dist/lib/mcp-server.js.map +1 -0
- package/dist/lib/metrics.d.ts +16 -0
- package/dist/lib/metrics.d.ts.map +1 -0
- package/dist/lib/metrics.js +48 -0
- package/dist/lib/metrics.js.map +1 -0
- package/dist/lib/overstory.d.ts +2 -0
- package/dist/lib/overstory.d.ts.map +1 -0
- package/dist/lib/overstory.js +211 -0
- package/dist/lib/overstory.js.map +1 -0
- package/dist/lib/parallel.d.ts +2 -0
- package/dist/lib/parallel.d.ts.map +1 -0
- package/dist/lib/parallel.js +349 -0
- package/dist/lib/parallel.js.map +1 -0
- package/dist/lib/paths.d.ts +2 -0
- package/dist/lib/paths.d.ts.map +1 -0
- package/dist/lib/paths.js +254 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/lib/phase-complete-llm.d.ts +22 -0
- package/dist/lib/phase-complete-llm.d.ts.map +1 -0
- package/dist/lib/phase-complete-llm.js +331 -0
- package/dist/lib/phase-complete-llm.js.map +1 -0
- package/dist/lib/phase-complete.d.ts +46 -0
- package/dist/lib/phase-complete.d.ts.map +1 -0
- package/dist/lib/phase-complete.js +278 -0
- package/dist/lib/phase-complete.js.map +1 -0
- package/dist/lib/phase-io.d.ts +2 -0
- package/dist/lib/phase-io.d.ts.map +1 -0
- package/dist/lib/phase-io.js +126 -0
- package/dist/lib/phase-io.js.map +1 -0
- package/dist/lib/phase.d.ts +2 -0
- package/dist/lib/phase.d.ts.map +1 -0
- package/dist/lib/phase.js +1344 -0
- package/dist/lib/phase.js.map +1 -0
- package/dist/lib/plan-tournament.d.ts +63 -0
- package/dist/lib/plan-tournament.d.ts.map +1 -0
- package/dist/lib/plan-tournament.js +353 -0
- package/dist/lib/plan-tournament.js.map +1 -0
- package/dist/lib/refinement.d.ts +74 -0
- package/dist/lib/refinement.d.ts.map +1 -0
- package/dist/lib/refinement.js +283 -0
- package/dist/lib/refinement.js.map +1 -0
- package/dist/lib/requirements.d.ts +2 -0
- package/dist/lib/requirements.d.ts.map +1 -0
- package/dist/lib/requirements.js +355 -0
- package/dist/lib/requirements.js.map +1 -0
- package/dist/lib/research-bundle.d.ts +2 -0
- package/dist/lib/research-bundle.d.ts.map +1 -0
- package/dist/lib/research-bundle.js +246 -0
- package/dist/lib/research-bundle.js.map +1 -0
- package/dist/lib/roadmap.d.ts +2 -0
- package/dist/lib/roadmap.d.ts.map +1 -0
- package/dist/lib/roadmap.js +541 -0
- package/dist/lib/roadmap.js.map +1 -0
- package/dist/lib/sample.d.ts +16 -0
- package/dist/lib/sample.d.ts.map +1 -0
- package/dist/lib/sample.js +20 -0
- package/dist/lib/sample.js.map +1 -0
- package/dist/lib/scaffold.d.ts +2 -0
- package/dist/lib/scaffold.d.ts.map +1 -0
- package/dist/lib/scaffold.js +355 -0
- package/dist/lib/scaffold.js.map +1 -0
- package/dist/lib/scan/_utils.d.ts +11 -0
- package/dist/lib/scan/_utils.d.ts.map +1 -0
- package/dist/lib/scan/_utils.js +36 -0
- package/dist/lib/scan/_utils.js.map +1 -0
- package/dist/lib/scan/base64.d.ts +15 -0
- package/dist/lib/scan/base64.d.ts.map +1 -0
- package/dist/lib/scan/base64.js +66 -0
- package/dist/lib/scan/base64.js.map +1 -0
- package/dist/lib/scan/ignorefile.d.ts +30 -0
- package/dist/lib/scan/ignorefile.d.ts.map +1 -0
- package/dist/lib/scan/ignorefile.js +101 -0
- package/dist/lib/scan/ignorefile.js.map +1 -0
- package/dist/lib/scan/injection.d.ts +14 -0
- package/dist/lib/scan/injection.d.ts.map +1 -0
- package/dist/lib/scan/injection.js +39 -0
- package/dist/lib/scan/injection.js.map +1 -0
- package/dist/lib/scan/patterns.d.ts +17 -0
- package/dist/lib/scan/patterns.d.ts.map +1 -0
- package/dist/lib/scan/patterns.js +123 -0
- package/dist/lib/scan/patterns.js.map +1 -0
- package/dist/lib/scan/strip-markdown.d.ts +7 -0
- package/dist/lib/scan/strip-markdown.d.ts.map +1 -0
- package/dist/lib/scan/strip-markdown.js +38 -0
- package/dist/lib/scan/strip-markdown.js.map +1 -0
- package/dist/lib/scan/types.d.ts +23 -0
- package/dist/lib/scan/types.d.ts.map +1 -0
- package/dist/lib/scan/types.js +3 -0
- package/dist/lib/scan/types.js.map +1 -0
- package/dist/lib/scheduler-wait.d.ts +2 -0
- package/dist/lib/scheduler-wait.d.ts.map +1 -0
- package/dist/lib/scheduler-wait.js +59 -0
- package/dist/lib/scheduler-wait.js.map +1 -0
- package/dist/lib/scheduler.d.ts +254 -0
- package/dist/lib/scheduler.d.ts.map +1 -0
- package/dist/lib/scheduler.js +1147 -0
- package/dist/lib/scheduler.js.map +1 -0
- package/dist/lib/state.d.ts +2 -0
- package/dist/lib/state.d.ts.map +1 -0
- package/dist/lib/state.js +744 -0
- package/dist/lib/state.js.map +1 -0
- package/dist/lib/think.d.ts +18 -0
- package/dist/lib/think.d.ts.map +1 -0
- package/dist/lib/think.js +317 -0
- package/dist/lib/think.js.map +1 -0
- package/dist/lib/tracker.d.ts +2 -0
- package/dist/lib/tracker.d.ts.map +1 -0
- package/dist/lib/tracker.js +1121 -0
- package/dist/lib/tracker.js.map +1 -0
- package/dist/lib/types.d.ts +1514 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +4 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +1363 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/verify.d.ts +2 -0
- package/dist/lib/verify.d.ts.map +1 -0
- package/dist/lib/verify.js +1153 -0
- package/dist/lib/verify.js.map +1 -0
- package/dist/lib/wireup/autofix.d.ts +2 -0
- package/dist/lib/wireup/autofix.d.ts.map +1 -0
- package/dist/lib/wireup/autofix.js +188 -0
- package/dist/lib/wireup/autofix.js.map +1 -0
- package/dist/lib/wireup/cli.d.ts +2 -0
- package/dist/lib/wireup/cli.d.ts.map +1 -0
- package/dist/lib/wireup/cli.js +194 -0
- package/dist/lib/wireup/cli.js.map +1 -0
- package/dist/lib/wireup/detection.d.ts +47 -0
- package/dist/lib/wireup/detection.d.ts.map +1 -0
- package/dist/lib/wireup/detection.js +410 -0
- package/dist/lib/wireup/detection.js.map +1 -0
- package/dist/lib/wireup/discovery.d.ts +2 -0
- package/dist/lib/wireup/discovery.d.ts.map +1 -0
- package/dist/lib/wireup/discovery.js +934 -0
- package/dist/lib/wireup/discovery.js.map +1 -0
- package/dist/lib/wireup/execution.d.ts +2 -0
- package/dist/lib/wireup/execution.d.ts.map +1 -0
- package/dist/lib/wireup/execution.js +573 -0
- package/dist/lib/wireup/execution.js.map +1 -0
- package/dist/lib/wireup/index.d.ts +2 -0
- package/dist/lib/wireup/index.d.ts.map +1 -0
- package/dist/lib/wireup/index.js +85 -0
- package/dist/lib/wireup/index.js.map +1 -0
- package/dist/lib/wireup/orchestrator.d.ts +2 -0
- package/dist/lib/wireup/orchestrator.d.ts.map +1 -0
- package/dist/lib/wireup/orchestrator.js +366 -0
- package/dist/lib/wireup/orchestrator.js.map +1 -0
- package/dist/lib/wireup/report.d.ts +47 -0
- package/dist/lib/wireup/report.d.ts.map +1 -0
- package/dist/lib/wireup/report.js +201 -0
- package/dist/lib/wireup/report.js.map +1 -0
- package/dist/lib/wireup/scenarios.d.ts +2 -0
- package/dist/lib/wireup/scenarios.d.ts.map +1 -0
- package/dist/lib/wireup/scenarios.js +516 -0
- package/dist/lib/wireup/scenarios.js.map +1 -0
- package/dist/lib/wireup/state.d.ts +2 -0
- package/dist/lib/wireup/state.d.ts.map +1 -0
- package/dist/lib/wireup/state.js +102 -0
- package/dist/lib/wireup/state.js.map +1 -0
- package/dist/lib/wireup/types.d.ts +376 -0
- package/dist/lib/wireup/types.d.ts.map +1 -0
- package/dist/lib/wireup/types.js +3 -0
- package/dist/lib/wireup/types.js.map +1 -0
- package/dist/lib/worktree.d.ts +2 -0
- package/dist/lib/worktree.d.ts.map +1 -0
- package/dist/lib/worktree.js +999 -0
- package/dist/lib/worktree.js.map +1 -0
- package/lib/autopilot-milestone.ts +136 -0
- package/lib/autopilot-pipeline.ts +1179 -0
- package/lib/autopilot-waves.ts +361 -0
- package/lib/autopilot.ts +1874 -0
- package/lib/autoplan.ts +280 -0
- package/lib/autoresearch.js +4 -0
- package/lib/autoresearch.ts +886 -0
- package/lib/backend.ts +1252 -0
- package/lib/benchmark.ts +341 -0
- package/lib/citations.ts +760 -0
- package/lib/cleanup.ts +1588 -0
- package/lib/cli/adapters.ts +41 -0
- package/lib/cli/agent.ts +83 -0
- package/lib/cli/index.ts +273 -0
- package/lib/cli/output.ts +33 -0
- package/lib/cli/scan-dispatch.ts +130 -0
- package/lib/cli/tools.ts +198 -0
- package/lib/commands/_dashboard-parsers.ts +275 -0
- package/lib/commands/analysis.ts +1851 -0
- package/lib/commands/assumptions.ts +232 -0
- package/lib/commands/blame.ts +174 -0
- package/lib/commands/budget.ts +148 -0
- package/lib/commands/check-plans.ts +233 -0
- package/lib/commands/config.ts +287 -0
- package/lib/commands/dashboard.ts +680 -0
- package/lib/commands/estimate.ts +204 -0
- package/lib/commands/eval-diff.ts +252 -0
- package/lib/commands/freshness.ts +213 -0
- package/lib/commands/health.ts +607 -0
- package/lib/commands/index.ts +266 -0
- package/lib/commands/install.ts +307 -0
- package/lib/commands/knowhow-aggregator.ts +345 -0
- package/lib/commands/knowledge-search.ts +153 -0
- package/lib/commands/long-term-roadmap.ts +390 -0
- package/lib/commands/patterns.ts +465 -0
- package/lib/commands/phase-info.ts +698 -0
- package/lib/commands/plan-lint.ts +546 -0
- package/lib/commands/plan-phase.ts +375 -0
- package/lib/commands/progress.ts +319 -0
- package/lib/commands/quality.ts +138 -0
- package/lib/commands/rollback.ts +195 -0
- package/lib/commands/scan.ts +72 -0
- package/lib/commands/search.ts +300 -0
- package/lib/commands/select-candidate.ts +687 -0
- package/lib/commands/singularity.ts +222 -0
- package/lib/commands/slug-timestamp.ts +74 -0
- package/lib/commands/tail.ts +129 -0
- package/lib/commands/todo.ts +273 -0
- package/lib/commands/watch.ts +80 -0
- package/lib/complexity.ts +117 -0
- package/lib/context/agents.ts +505 -0
- package/lib/context/base.ts +123 -0
- package/lib/context/execute.ts +977 -0
- package/lib/context/index.ts +110 -0
- package/lib/context/progress.ts +278 -0
- package/lib/context/project.ts +531 -0
- package/lib/context/research.ts +646 -0
- package/lib/dead-ends.ts +506 -0
- package/lib/deps.ts +773 -0
- package/lib/discussion.ts +1275 -0
- package/lib/drift.ts +519 -0
- package/lib/evolve/_dimensions-features.ts +525 -0
- package/lib/evolve/_dimensions.ts +511 -0
- package/lib/evolve/_product-ideation.ts +405 -0
- package/lib/evolve/_prompts.ts +178 -0
- package/lib/evolve/cli.ts +330 -0
- package/lib/evolve/discovery.ts +571 -0
- package/lib/evolve/index.ts +105 -0
- package/lib/evolve/orchestrator.ts +1139 -0
- package/lib/evolve/scoring.ts +167 -0
- package/lib/evolve/state.ts +330 -0
- package/lib/evolve/types.ts +290 -0
- package/lib/frontmatter.ts +615 -0
- package/lib/gates.ts +695 -0
- package/lib/genome.ts +402 -0
- package/lib/got.js +4 -0
- package/lib/got.ts +361 -0
- package/lib/invariants.ts +378 -0
- package/lib/knowledge.ts +768 -0
- package/lib/long-term-roadmap.ts +806 -0
- package/lib/markdown-split.ts +273 -0
- package/lib/mcp-server.ts +3292 -0
- package/lib/metrics.ts +49 -0
- package/lib/overstory.ts +270 -0
- package/lib/parallel.ts +570 -0
- package/lib/paths.ts +293 -0
- package/lib/phase-complete-llm.ts +376 -0
- package/lib/phase-complete.ts +366 -0
- package/lib/phase-io.ts +101 -0
- package/lib/phase.ts +1981 -0
- package/lib/plan-tournament.ts +426 -0
- package/lib/refinement.ts +349 -0
- package/lib/requirements.ts +469 -0
- package/lib/research-bundle.ts +300 -0
- package/lib/roadmap.ts +775 -0
- package/lib/scaffold.ts +480 -0
- package/lib/scan/_utils.ts +37 -0
- package/lib/scan/base64.ts +90 -0
- package/lib/scan/ignorefile.ts +109 -0
- package/lib/scan/injection.ts +67 -0
- package/lib/scan/patterns.ts +139 -0
- package/lib/scan/strip-markdown.ts +39 -0
- package/lib/scan/types.ts +28 -0
- package/lib/scheduler-wait.ts +58 -0
- package/lib/scheduler.ts +1370 -0
- package/lib/state.ts +1000 -0
- package/lib/think.ts +365 -0
- package/lib/tracker.ts +1591 -0
- package/lib/types.ts +1663 -0
- package/lib/utils.ts +1479 -0
- package/lib/verify.ts +1434 -0
- package/lib/wireup/autofix.ts +241 -0
- package/lib/wireup/cli.ts +278 -0
- package/lib/wireup/detection.ts +542 -0
- package/lib/wireup/discovery.ts +1063 -0
- package/lib/wireup/execution.ts +686 -0
- package/lib/wireup/index.ts +117 -0
- package/lib/wireup/orchestrator.ts +519 -0
- package/lib/wireup/report.ts +286 -0
- package/lib/wireup/scenarios.ts +616 -0
- package/lib/wireup/state.ts +139 -0
- package/lib/wireup/types.ts +436 -0
- package/lib/worktree.ts +1309 -0
- package/package.json +67 -0
package/lib/gates.ts
ADDED
|
@@ -0,0 +1,695 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GRD Validation Gate System — Pre-flight checks for workflow commands
|
|
5
|
+
*
|
|
6
|
+
* Detects phase directory collisions, orphaned phases, stale artifacts,
|
|
7
|
+
* and milestone state inconsistencies before commands execute.
|
|
8
|
+
*
|
|
9
|
+
* Dependencies: utils.js (one-directional, no circular deps)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { RunCache, GrdConfig, GateViolation, PreflightResult } from './types';
|
|
13
|
+
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
loadConfig,
|
|
19
|
+
normalizePhaseName,
|
|
20
|
+
safeReadFile,
|
|
21
|
+
stripShippedSections,
|
|
22
|
+
createRunCache,
|
|
23
|
+
} = require('./utils');
|
|
24
|
+
const { phasesDir: getPhasesDirPath } = require('./paths');
|
|
25
|
+
const { validateStructural, validateCrossPhase, extractPlanArtifact } = require('./invariants') as {
|
|
26
|
+
validateStructural: (plan: import('./types').PlanArtifact) => import('./types').ValidationResult;
|
|
27
|
+
validateCrossPhase: (
|
|
28
|
+
plans: import('./types').PlanArtifact[]
|
|
29
|
+
) => import('./types').ValidationResult;
|
|
30
|
+
extractPlanArtifact: (content: string) => import('./types').PlanArtifact;
|
|
31
|
+
};
|
|
32
|
+
const { buildCitationGraph, findUnresolved } = require('./citations') as {
|
|
33
|
+
buildCitationGraph: (papersDir: string) => import('./types').CitationGraph;
|
|
34
|
+
findUnresolved: (
|
|
35
|
+
graph: import('./types').CitationGraph,
|
|
36
|
+
priority?: 'critical' | 'normal' | 'low'
|
|
37
|
+
) => import('./types').CitationNode[];
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
import type { TraversalOptions, TraversalResult, CitationGraph } from './types';
|
|
41
|
+
|
|
42
|
+
// ─── Domain Types ─────────────────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
/** Options passed to gate checks and runPreflightGates. */
|
|
45
|
+
interface GateOptions {
|
|
46
|
+
phase?: string;
|
|
47
|
+
skipGates?: boolean;
|
|
48
|
+
[key: string]: unknown;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** A gate check function signature. */
|
|
52
|
+
type GateCheckFn = (cwd: string, opts: GateOptions) => GateViolation[];
|
|
53
|
+
|
|
54
|
+
/** Registry mapping command names to gate check names. */
|
|
55
|
+
type GateRegistryMap = Record<string, string[]>;
|
|
56
|
+
|
|
57
|
+
/** Registry mapping gate names to check functions. */
|
|
58
|
+
type GateCheckMap = Record<string, GateCheckFn>;
|
|
59
|
+
|
|
60
|
+
// ─── File Content Cache ───────────────────────────────────────────────────────
|
|
61
|
+
const _gatesCache: RunCache = createRunCache();
|
|
62
|
+
|
|
63
|
+
function _gatesCachedRead(p: string): string | null {
|
|
64
|
+
return _gatesCache.get(p, safeReadFile) as string | null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ─── Gate Check Functions ─────────────────────────────────────────────────────
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Check for phase directories on disk that are not in ROADMAP.md.
|
|
71
|
+
*/
|
|
72
|
+
function checkOrphanedPhases(cwd: string): GateViolation[] {
|
|
73
|
+
const violations: GateViolation[] = [];
|
|
74
|
+
const roadmapPath: string = path.join(cwd, '.planning', 'ROADMAP.md');
|
|
75
|
+
const phasesDir: string = getPhasesDirPath(cwd);
|
|
76
|
+
|
|
77
|
+
const roadmapContent: string | null = _gatesCachedRead(roadmapPath);
|
|
78
|
+
if (!roadmapContent) return violations;
|
|
79
|
+
const activeContent: string = stripShippedSections(roadmapContent);
|
|
80
|
+
|
|
81
|
+
// Extract phases from ROADMAP
|
|
82
|
+
const roadmapPhases: Set<string> = new Set();
|
|
83
|
+
const phasePattern: RegExp = /#{2,3}\s*Phase\s+(\d+(?:\.\d+)?)\s*:/gi;
|
|
84
|
+
let m: RegExpExecArray | null;
|
|
85
|
+
while ((m = phasePattern.exec(activeContent)) !== null) {
|
|
86
|
+
roadmapPhases.add(m[1]);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Get phases on disk
|
|
90
|
+
try {
|
|
91
|
+
const entries: import('fs').Dirent[] = fs.readdirSync(phasesDir, {
|
|
92
|
+
withFileTypes: true,
|
|
93
|
+
});
|
|
94
|
+
const dirs: string[] = entries
|
|
95
|
+
.filter((e: import('fs').Dirent) => e.isDirectory())
|
|
96
|
+
.map((e: import('fs').Dirent) => e.name);
|
|
97
|
+
|
|
98
|
+
for (const dir of dirs) {
|
|
99
|
+
const dm: RegExpMatchArray | null = dir.match(/^(\d+(?:\.\d+)?)/);
|
|
100
|
+
if (!dm) continue;
|
|
101
|
+
const phaseNum: string = dm[1];
|
|
102
|
+
const unpadded: string = String(parseInt(phaseNum, 10));
|
|
103
|
+
|
|
104
|
+
if (!roadmapPhases.has(phaseNum) && !roadmapPhases.has(unpadded)) {
|
|
105
|
+
violations.push({
|
|
106
|
+
code: 'ORPHANED_PHASE',
|
|
107
|
+
severity: 'error',
|
|
108
|
+
message: `Phase directory "${dir}" exists on disk but not in ROADMAP.md`,
|
|
109
|
+
fix: 'Run `/grd:complete-milestone` to archive old phase directories, or manually remove the orphaned directory',
|
|
110
|
+
context: { directory: dir, phase_number: phaseNum },
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
} catch (err: unknown) {
|
|
115
|
+
// ENOENT: phases dir may not exist — silent
|
|
116
|
+
const fsErr = err as { code?: string; message?: string };
|
|
117
|
+
if (fsErr.code !== 'ENOENT') {
|
|
118
|
+
process.stderr.write(
|
|
119
|
+
`Warning: unexpected error reading phases directory: ${fsErr.message}\n`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return violations;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Check that a target phase exists in ROADMAP.md.
|
|
129
|
+
*/
|
|
130
|
+
function checkPhaseInRoadmap(cwd: string, phase: string): GateViolation[] {
|
|
131
|
+
const violations: GateViolation[] = [];
|
|
132
|
+
if (!phase) return violations;
|
|
133
|
+
|
|
134
|
+
const roadmapPath: string = path.join(cwd, '.planning', 'ROADMAP.md');
|
|
135
|
+
const phasesDir: string = getPhasesDirPath(cwd);
|
|
136
|
+
const roadmapContent: string | null = _gatesCachedRead(roadmapPath);
|
|
137
|
+
if (!roadmapContent) return violations;
|
|
138
|
+
const activeContent: string = stripShippedSections(roadmapContent);
|
|
139
|
+
|
|
140
|
+
// Only flag if the phase exists on disk but not in ROADMAP.
|
|
141
|
+
// If it doesn't exist on disk either, let normal command logic handle "not found".
|
|
142
|
+
const normalized: string = normalizePhaseName(phase);
|
|
143
|
+
let existsOnDisk: boolean = false;
|
|
144
|
+
try {
|
|
145
|
+
const entries: import('fs').Dirent[] = fs.readdirSync(phasesDir, {
|
|
146
|
+
withFileTypes: true,
|
|
147
|
+
});
|
|
148
|
+
const dirs: string[] = entries
|
|
149
|
+
.filter((e: import('fs').Dirent) => e.isDirectory())
|
|
150
|
+
.map((e: import('fs').Dirent) => e.name);
|
|
151
|
+
existsOnDisk = dirs.some((d: string) => d.startsWith(normalized));
|
|
152
|
+
} catch {
|
|
153
|
+
// phases dir may not exist
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (!existsOnDisk) return violations;
|
|
157
|
+
|
|
158
|
+
const unpadded: string = String(parseInt(normalized, 10));
|
|
159
|
+
const phaseRegex: RegExp = new RegExp(
|
|
160
|
+
`#{2,}\\s*Phase\\s+(?:${normalized}|${unpadded})\\s*:`,
|
|
161
|
+
'i'
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
if (!phaseRegex.test(activeContent)) {
|
|
165
|
+
violations.push({
|
|
166
|
+
code: 'PHASE_NOT_IN_ROADMAP',
|
|
167
|
+
severity: 'error',
|
|
168
|
+
message: `Phase ${phase} not found in ROADMAP.md — may be from a previous milestone`,
|
|
169
|
+
fix: 'Ensure the phase exists in the current ROADMAP.md, or archive old phases with `/grd:complete-milestone`',
|
|
170
|
+
context: { phase },
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return violations;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Check that a target phase has at least one plan.
|
|
179
|
+
*/
|
|
180
|
+
function checkPhaseHasPlans(cwd: string, phase: string): GateViolation[] {
|
|
181
|
+
const violations: GateViolation[] = [];
|
|
182
|
+
if (!phase) return violations;
|
|
183
|
+
|
|
184
|
+
const phasesDir: string = getPhasesDirPath(cwd);
|
|
185
|
+
const normalized: string = normalizePhaseName(phase);
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
const entries: import('fs').Dirent[] = fs.readdirSync(phasesDir, {
|
|
189
|
+
withFileTypes: true,
|
|
190
|
+
});
|
|
191
|
+
const dirs: string[] = entries
|
|
192
|
+
.filter((e: import('fs').Dirent) => e.isDirectory())
|
|
193
|
+
.map((e: import('fs').Dirent) => e.name);
|
|
194
|
+
const match: string | undefined = dirs.find((d: string) => d.startsWith(normalized));
|
|
195
|
+
if (!match) return violations;
|
|
196
|
+
|
|
197
|
+
const phaseFiles: string[] = fs.readdirSync(path.join(phasesDir, match));
|
|
198
|
+
const plans: string[] = phaseFiles.filter(
|
|
199
|
+
(f: string) => f.endsWith('-PLAN.md') || f === 'PLAN.md'
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
if (plans.length === 0) {
|
|
203
|
+
violations.push({
|
|
204
|
+
code: 'PHASE_NO_PLANS',
|
|
205
|
+
severity: 'error',
|
|
206
|
+
message: `Phase ${phase} has no plans — run /grd:plan-phase ${phase} first`,
|
|
207
|
+
fix: `Run \`/grd:plan-phase ${phase}\` to create execution plans`,
|
|
208
|
+
context: { phase, directory: match },
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
} catch {
|
|
212
|
+
// phase dir may not exist
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return violations;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Check for stale artifacts (summaries without matching plans).
|
|
220
|
+
*/
|
|
221
|
+
function checkNoStaleArtifacts(cwd: string, phase: string): GateViolation[] {
|
|
222
|
+
const violations: GateViolation[] = [];
|
|
223
|
+
if (!phase) return violations;
|
|
224
|
+
|
|
225
|
+
const phasesDir: string = getPhasesDirPath(cwd);
|
|
226
|
+
const normalized: string = normalizePhaseName(phase);
|
|
227
|
+
|
|
228
|
+
try {
|
|
229
|
+
const entries: import('fs').Dirent[] = fs.readdirSync(phasesDir, {
|
|
230
|
+
withFileTypes: true,
|
|
231
|
+
});
|
|
232
|
+
const dirs: string[] = entries
|
|
233
|
+
.filter((e: import('fs').Dirent) => e.isDirectory())
|
|
234
|
+
.map((e: import('fs').Dirent) => e.name);
|
|
235
|
+
const match: string | undefined = dirs.find((d: string) => d.startsWith(normalized));
|
|
236
|
+
if (!match) return violations;
|
|
237
|
+
|
|
238
|
+
const phaseFiles: string[] = fs.readdirSync(path.join(phasesDir, match));
|
|
239
|
+
const plans: Set<string> = new Set(
|
|
240
|
+
phaseFiles
|
|
241
|
+
.filter((f: string) => f.endsWith('-PLAN.md'))
|
|
242
|
+
.map((f: string) => f.replace('-PLAN.md', ''))
|
|
243
|
+
);
|
|
244
|
+
const summaries: string[] = phaseFiles
|
|
245
|
+
.filter((f: string) => f.endsWith('-SUMMARY.md'))
|
|
246
|
+
.map((f: string) => f.replace('-SUMMARY.md', ''));
|
|
247
|
+
|
|
248
|
+
for (const sid of summaries) {
|
|
249
|
+
if (!plans.has(sid)) {
|
|
250
|
+
violations.push({
|
|
251
|
+
code: 'STALE_ARTIFACTS',
|
|
252
|
+
severity: 'warning',
|
|
253
|
+
message: `Summary ${sid}-SUMMARY.md in phase ${phase} has no matching PLAN.md`,
|
|
254
|
+
fix: 'Remove the orphaned summary or recreate the missing plan',
|
|
255
|
+
context: { phase, summary: `${sid}-SUMMARY.md` },
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
} catch {
|
|
260
|
+
// phase dir may not exist
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return violations;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Check that completed milestone phases have been archived.
|
|
268
|
+
*/
|
|
269
|
+
function checkOldPhasesArchived(cwd: string): GateViolation[] {
|
|
270
|
+
const violations: GateViolation[] = [];
|
|
271
|
+
const statePath: string = path.join(cwd, '.planning', 'STATE.md');
|
|
272
|
+
const phasesDir: string = getPhasesDirPath(cwd);
|
|
273
|
+
|
|
274
|
+
const stateContent: string | null = safeReadFile(statePath);
|
|
275
|
+
if (!stateContent) return violations;
|
|
276
|
+
|
|
277
|
+
// Check if STATE.md indicates a milestone was completed
|
|
278
|
+
const milestoneCompletePattern: RegExp = /milestone\s+complete/i;
|
|
279
|
+
if (!milestoneCompletePattern.test(stateContent)) return violations;
|
|
280
|
+
|
|
281
|
+
// If milestone is marked complete, phases dir should be empty
|
|
282
|
+
try {
|
|
283
|
+
const entries: import('fs').Dirent[] = fs.readdirSync(phasesDir, {
|
|
284
|
+
withFileTypes: true,
|
|
285
|
+
});
|
|
286
|
+
const dirs: string[] = entries
|
|
287
|
+
.filter((e: import('fs').Dirent) => e.isDirectory())
|
|
288
|
+
.map((e: import('fs').Dirent) => e.name);
|
|
289
|
+
|
|
290
|
+
if (dirs.length > 0) {
|
|
291
|
+
violations.push({
|
|
292
|
+
code: 'UNARCHIVED_PHASES',
|
|
293
|
+
severity: 'error',
|
|
294
|
+
message: `STATE.md indicates milestone complete but ${dirs.length} phase directories remain on disk`,
|
|
295
|
+
fix: 'Run `/grd:complete-milestone` to properly archive phase directories before starting a new milestone',
|
|
296
|
+
context: { phase_count: dirs.length, directories: dirs },
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
} catch {
|
|
300
|
+
// phases dir may not exist
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return violations;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Check milestone state coherence between STATE.md and disk state.
|
|
308
|
+
*/
|
|
309
|
+
function checkMilestoneStateCoherence(cwd: string): GateViolation[] {
|
|
310
|
+
const violations: GateViolation[] = [];
|
|
311
|
+
const statePath: string = path.join(cwd, '.planning', 'STATE.md');
|
|
312
|
+
const roadmapPath: string = path.join(cwd, '.planning', 'ROADMAP.md');
|
|
313
|
+
|
|
314
|
+
const stateContent: string | null = safeReadFile(statePath);
|
|
315
|
+
if (!stateContent) return violations;
|
|
316
|
+
|
|
317
|
+
const roadmapContent: string | null = _gatesCachedRead(roadmapPath);
|
|
318
|
+
const activeContent: string | null = roadmapContent ? stripShippedSections(roadmapContent) : null;
|
|
319
|
+
|
|
320
|
+
// Check: STATE references a phase that doesn't exist in ROADMAP
|
|
321
|
+
const activePhaseMatch: RegExpMatchArray | null = stateContent.match(
|
|
322
|
+
/\*\*(?:Active phase|Current Phase):\*\*\s*(\d+(?:\.\d+)?)/i
|
|
323
|
+
);
|
|
324
|
+
if (activePhaseMatch && activeContent) {
|
|
325
|
+
const activePhase: string = activePhaseMatch[1];
|
|
326
|
+
const unpadded: string = String(parseInt(activePhase, 10));
|
|
327
|
+
const phaseInRoadmap: RegExp = new RegExp(
|
|
328
|
+
`#{2,}\\s*Phase\\s+(?:${activePhase}|${unpadded})\\s*:`,
|
|
329
|
+
'i'
|
|
330
|
+
);
|
|
331
|
+
if (!phaseInRoadmap.test(activeContent)) {
|
|
332
|
+
violations.push({
|
|
333
|
+
code: 'MILESTONE_STATE_CONFUSION',
|
|
334
|
+
severity: 'error',
|
|
335
|
+
message: `STATE.md references Phase ${activePhase} but it does not exist in ROADMAP.md`,
|
|
336
|
+
fix: 'Update STATE.md to reference a valid phase, or run `/grd:complete-milestone` to reset state',
|
|
337
|
+
context: { active_phase: activePhase },
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return violations;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Check plan invariants: structural validity for each plan and cross-phase consistency.
|
|
347
|
+
*
|
|
348
|
+
* Satisfies REQ-180 (Pre-Flight Validation Gate): invalid plans are hard-rejected
|
|
349
|
+
* before execution. Reads all *-PLAN.md files in the target phase directory,
|
|
350
|
+
* runs validateStructural per plan, then validateCrossPhase across all plans.
|
|
351
|
+
*/
|
|
352
|
+
function checkInvariantValidation(cwd: string, opts: GateOptions): GateViolation[] {
|
|
353
|
+
const violations: GateViolation[] = [];
|
|
354
|
+
if (!opts.phase) return violations;
|
|
355
|
+
|
|
356
|
+
const phasesDir: string = getPhasesDirPath(cwd);
|
|
357
|
+
const normalized: string = normalizePhaseName(opts.phase as string);
|
|
358
|
+
|
|
359
|
+
// Locate the phase directory on disk
|
|
360
|
+
let phaseDir: string;
|
|
361
|
+
try {
|
|
362
|
+
const entries: import('fs').Dirent[] = fs.readdirSync(phasesDir, { withFileTypes: true });
|
|
363
|
+
const match = entries
|
|
364
|
+
.filter((e: import('fs').Dirent) => e.isDirectory())
|
|
365
|
+
.map((e: import('fs').Dirent) => e.name)
|
|
366
|
+
.find((d: string) => d.startsWith(normalized));
|
|
367
|
+
if (!match) return violations;
|
|
368
|
+
phaseDir = path.join(phasesDir, match);
|
|
369
|
+
} catch {
|
|
370
|
+
return violations;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Read all *-PLAN.md files
|
|
374
|
+
let planFiles: string[];
|
|
375
|
+
try {
|
|
376
|
+
const phaseContents: string[] = fs.readdirSync(phaseDir);
|
|
377
|
+
planFiles = phaseContents.filter((f: string) => f.endsWith('-PLAN.md') || f === 'PLAN.md');
|
|
378
|
+
} catch {
|
|
379
|
+
return violations;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (planFiles.length === 0) return violations;
|
|
383
|
+
|
|
384
|
+
const planArtifacts: import('./types').PlanArtifact[] = [];
|
|
385
|
+
|
|
386
|
+
// Structural validation per plan
|
|
387
|
+
for (const planFile of planFiles) {
|
|
388
|
+
const planPath = path.join(phaseDir, planFile);
|
|
389
|
+
const content: string | null = safeReadFile(planPath);
|
|
390
|
+
if (!content) continue;
|
|
391
|
+
|
|
392
|
+
const artifact = extractPlanArtifact(content);
|
|
393
|
+
planArtifacts.push(artifact);
|
|
394
|
+
|
|
395
|
+
const result = validateStructural(artifact);
|
|
396
|
+
for (const err of result.errors) {
|
|
397
|
+
violations.push({
|
|
398
|
+
code: 'INVARIANT_STRUCTURAL',
|
|
399
|
+
severity: 'error',
|
|
400
|
+
message: `${planFile}: ${err}`,
|
|
401
|
+
fix: `Fix the structural issue in ${planFile} before execution`,
|
|
402
|
+
context: { plan: planFile, error: err },
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
for (const warn of result.warnings) {
|
|
406
|
+
violations.push({
|
|
407
|
+
code: 'INVARIANT_STRUCTURAL',
|
|
408
|
+
severity: 'warning',
|
|
409
|
+
message: `${planFile}: ${warn}`,
|
|
410
|
+
fix: `Consider fixing the structural warning in ${planFile}`,
|
|
411
|
+
context: { plan: planFile, warning: warn },
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Cross-phase validation across all plans in the set
|
|
417
|
+
if (planArtifacts.length > 0) {
|
|
418
|
+
const crossResult = validateCrossPhase(planArtifacts);
|
|
419
|
+
for (const err of crossResult.errors) {
|
|
420
|
+
violations.push({
|
|
421
|
+
code: 'INVARIANT_CROSS_PHASE',
|
|
422
|
+
severity: 'error',
|
|
423
|
+
message: err,
|
|
424
|
+
fix: 'Resolve cross-phase dependency conflicts between plans',
|
|
425
|
+
context: { error: err },
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
for (const warn of crossResult.warnings) {
|
|
429
|
+
violations.push({
|
|
430
|
+
code: 'INVARIANT_CROSS_PHASE',
|
|
431
|
+
severity: 'warning',
|
|
432
|
+
message: warn,
|
|
433
|
+
fix: 'Consider adding provides/requires to plans for dependency tracking',
|
|
434
|
+
context: { warning: warn },
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
return violations;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Check for unresolved critical citation dependencies.
|
|
444
|
+
*
|
|
445
|
+
* Only runs when citation_gate is enabled in config (default: false).
|
|
446
|
+
* Reads the citation graph from .planning/research/PAPERS.md if it exists.
|
|
447
|
+
* Returns GateViolation[] for each critical unresolved CitationNode.
|
|
448
|
+
*
|
|
449
|
+
* Satisfies REQ-184 (Citation Recovery — configurable gate).
|
|
450
|
+
*/
|
|
451
|
+
function checkCitationGate(cwd: string, _opts: GateOptions): GateViolation[] {
|
|
452
|
+
const violations: GateViolation[] = [];
|
|
453
|
+
const config: GrdConfig = loadConfig(cwd);
|
|
454
|
+
|
|
455
|
+
// Only run if citation_gate is enabled in config (default: false)
|
|
456
|
+
const citationGateEnabled = (config as unknown as Record<string, unknown>).citation_gate === true;
|
|
457
|
+
if (!citationGateEnabled) return violations;
|
|
458
|
+
|
|
459
|
+
// Find research directory for current milestone
|
|
460
|
+
const researchDir = path.join(cwd, '.planning', 'research');
|
|
461
|
+
const papersPath = path.join(researchDir, 'PAPERS.md');
|
|
462
|
+
|
|
463
|
+
// Only check if PAPERS.md exists
|
|
464
|
+
try {
|
|
465
|
+
fs.statSync(papersPath);
|
|
466
|
+
} catch {
|
|
467
|
+
return violations;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
try {
|
|
471
|
+
const graph = buildCitationGraph(researchDir);
|
|
472
|
+
const criticalUnresolved = findUnresolved(graph, 'critical');
|
|
473
|
+
|
|
474
|
+
for (const node of criticalUnresolved) {
|
|
475
|
+
violations.push({
|
|
476
|
+
code: 'CITATION_UNRESOLVED_CRITICAL',
|
|
477
|
+
severity: 'error',
|
|
478
|
+
message: `Critical citation dependency "${node.slug}" (${node.title}) is unresolved — run citation recovery before planning`,
|
|
479
|
+
fix: 'Run `/grd:research-phase` with citation recovery enabled, or manually resolve the dependency',
|
|
480
|
+
context: { slug: node.slug, title: node.title, priority: node.priority },
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
} catch {
|
|
484
|
+
// Citation graph build failed — non-blocking
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
return violations;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Check for unresolved transitive citation dependencies (warning severity).
|
|
492
|
+
*
|
|
493
|
+
* Only runs when transitive_citation_gate is enabled in config (default: false).
|
|
494
|
+
* Performs BFS traversal of the citation graph and reports unresolved leaf nodes
|
|
495
|
+
* as warnings — these do not block plan-phase execution.
|
|
496
|
+
*
|
|
497
|
+
* Warning (not error) severity follows the principle that transitive dependencies
|
|
498
|
+
* are informational — they inform what additional work may be needed without
|
|
499
|
+
* blocking a researcher from planning a phase.
|
|
500
|
+
*/
|
|
501
|
+
function checkTransitiveCitationGate(cwd: string, _opts: GateOptions): GateViolation[] {
|
|
502
|
+
const violations: GateViolation[] = [];
|
|
503
|
+
const config: GrdConfig = loadConfig(cwd);
|
|
504
|
+
const enabled = (config as unknown as Record<string, unknown>).transitive_citation_gate === true;
|
|
505
|
+
if (!enabled) return violations;
|
|
506
|
+
|
|
507
|
+
const researchDir = path.join(cwd, '.planning', 'research');
|
|
508
|
+
const papersPath = path.join(researchDir, 'PAPERS.md');
|
|
509
|
+
try {
|
|
510
|
+
fs.statSync(papersPath);
|
|
511
|
+
} catch {
|
|
512
|
+
return violations;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
try {
|
|
516
|
+
const graph: CitationGraph = buildCitationGraph(researchDir);
|
|
517
|
+
const { traverseCitationGraph } = require('./citations') as {
|
|
518
|
+
traverseCitationGraph: (
|
|
519
|
+
g: CitationGraph,
|
|
520
|
+
opts?: Partial<TraversalOptions>
|
|
521
|
+
) => TraversalResult;
|
|
522
|
+
};
|
|
523
|
+
const result: TraversalResult = traverseCitationGraph(graph);
|
|
524
|
+
for (const node of result.unresolved_leaves) {
|
|
525
|
+
violations.push({
|
|
526
|
+
code: 'CITATION_UNRESOLVED_TRANSITIVE',
|
|
527
|
+
severity: 'warning',
|
|
528
|
+
message: `Transitive citation dependency "${node.slug}" is unresolved — consider running auto-retrieval`,
|
|
529
|
+
fix: 'Enable transitive auto-retrieval or manually add a PAPERS.md entry for this dependency',
|
|
530
|
+
context: { slug: node.slug, priority: node.priority },
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
} catch {
|
|
534
|
+
// Non-blocking
|
|
535
|
+
}
|
|
536
|
+
return violations;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// ─── Gate Registry ────────────────────────────────────────────────────────────
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Declarative mapping of commands to their required gate checks.
|
|
543
|
+
*/
|
|
544
|
+
const GATE_REGISTRY: GateRegistryMap = {
|
|
545
|
+
'execute-phase': [
|
|
546
|
+
'orphaned-phases',
|
|
547
|
+
'phase-in-roadmap',
|
|
548
|
+
'phase-has-plans',
|
|
549
|
+
'invariant-validation',
|
|
550
|
+
],
|
|
551
|
+
'plan-phase': [
|
|
552
|
+
'orphaned-phases',
|
|
553
|
+
'phase-in-roadmap',
|
|
554
|
+
'no-stale-artifacts',
|
|
555
|
+
'invariant-validation',
|
|
556
|
+
'citation-gate',
|
|
557
|
+
'transitive-citation-gate',
|
|
558
|
+
],
|
|
559
|
+
'new-milestone': ['old-phases-archived', 'milestone-state-coherence'],
|
|
560
|
+
'phase-add': ['orphaned-phases'],
|
|
561
|
+
'phase-insert': ['orphaned-phases'],
|
|
562
|
+
'phase-complete': ['phase-in-roadmap'],
|
|
563
|
+
'milestone-complete': ['milestone-state-coherence'],
|
|
564
|
+
'verify-work': ['phase-in-roadmap'],
|
|
565
|
+
iterate: ['phase-in-roadmap', 'phase-has-plans'],
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Map gate names to check functions.
|
|
570
|
+
*/
|
|
571
|
+
const GATE_CHECKS: GateCheckMap = {
|
|
572
|
+
'orphaned-phases': (cwd: string) => checkOrphanedPhases(cwd),
|
|
573
|
+
'phase-in-roadmap': (cwd: string, opts: GateOptions) =>
|
|
574
|
+
checkPhaseInRoadmap(cwd, opts.phase || ''),
|
|
575
|
+
'phase-has-plans': (cwd: string, opts: GateOptions) => checkPhaseHasPlans(cwd, opts.phase || ''),
|
|
576
|
+
'no-stale-artifacts': (cwd: string, opts: GateOptions) =>
|
|
577
|
+
checkNoStaleArtifacts(cwd, opts.phase || ''),
|
|
578
|
+
'old-phases-archived': (cwd: string) => checkOldPhasesArchived(cwd),
|
|
579
|
+
'milestone-state-coherence': (cwd: string) => checkMilestoneStateCoherence(cwd),
|
|
580
|
+
'invariant-validation': (cwd: string, opts: GateOptions) => checkInvariantValidation(cwd, opts),
|
|
581
|
+
'citation-gate': (cwd: string, opts: GateOptions) => checkCitationGate(cwd, opts),
|
|
582
|
+
'transitive-citation-gate': (cwd: string, opts: GateOptions) =>
|
|
583
|
+
checkTransitiveCitationGate(cwd, opts),
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
// ─── Main Entry Point ─────────────────────────────────────────────────────────
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* Run pre-flight gate checks for a command.
|
|
590
|
+
*/
|
|
591
|
+
function runPreflightGates(
|
|
592
|
+
cwd: string,
|
|
593
|
+
command: string,
|
|
594
|
+
options: GateOptions = {}
|
|
595
|
+
): PreflightResult {
|
|
596
|
+
const result: PreflightResult = {
|
|
597
|
+
passed: true,
|
|
598
|
+
bypassed: false,
|
|
599
|
+
errors: [],
|
|
600
|
+
warnings: [],
|
|
601
|
+
command,
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
// skipGates: true bypasses all checks immediately
|
|
605
|
+
if (options.skipGates) {
|
|
606
|
+
result.bypassed = true;
|
|
607
|
+
return result;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// New project safety: if no ROADMAP.md exists, all checks pass
|
|
611
|
+
const roadmapPath: string = path.join(cwd, '.planning', 'ROADMAP.md');
|
|
612
|
+
try {
|
|
613
|
+
fs.statSync(roadmapPath);
|
|
614
|
+
} catch {
|
|
615
|
+
return result;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// Look up gates for this command
|
|
619
|
+
const gateNames: string[] | undefined = GATE_REGISTRY[command];
|
|
620
|
+
if (!gateNames) return result;
|
|
621
|
+
|
|
622
|
+
_gatesCache.init();
|
|
623
|
+
try {
|
|
624
|
+
// Run each gate check
|
|
625
|
+
for (const gateName of gateNames) {
|
|
626
|
+
const checkFn: GateCheckFn | undefined = GATE_CHECKS[gateName];
|
|
627
|
+
if (!checkFn) continue;
|
|
628
|
+
|
|
629
|
+
try {
|
|
630
|
+
const violations: GateViolation[] = checkFn(cwd, options);
|
|
631
|
+
for (const v of violations) {
|
|
632
|
+
if (v.severity === 'error') {
|
|
633
|
+
result.errors.push(v);
|
|
634
|
+
} else {
|
|
635
|
+
result.warnings.push(v);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
} catch (e) {
|
|
639
|
+
const msg = (e as Error).message || String(e);
|
|
640
|
+
process.stderr.write(`[gates] gate '${gateName}' threw: ${msg}\n`);
|
|
641
|
+
result.warnings.push({
|
|
642
|
+
code: 'GATE_ERROR',
|
|
643
|
+
severity: 'warning',
|
|
644
|
+
message: `Gate '${gateName}' internal error: ${msg}`,
|
|
645
|
+
fix: 'Check the gate implementation for bugs or update the failing check',
|
|
646
|
+
context: {},
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// YOLO bypass: if autonomous_mode is enabled, pass regardless of errors
|
|
652
|
+
const config: GrdConfig = loadConfig(cwd);
|
|
653
|
+
if (config.autonomous_mode) {
|
|
654
|
+
result.bypassed = true;
|
|
655
|
+
result.passed = true;
|
|
656
|
+
return result;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// Determine pass/fail based on errors
|
|
660
|
+
if (result.errors.length > 0) {
|
|
661
|
+
result.passed = false;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
return result;
|
|
665
|
+
} finally {
|
|
666
|
+
_gatesCache.reset();
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* Reset the internal gates run cache (useful for testing).
|
|
672
|
+
*/
|
|
673
|
+
function resetGatesCache(): void {
|
|
674
|
+
_gatesCache.reset();
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// ─── Exports ──────────────────────────────────────────────────────────────────
|
|
678
|
+
|
|
679
|
+
module.exports = {
|
|
680
|
+
// Gate check functions (for direct use and testing)
|
|
681
|
+
checkOrphanedPhases,
|
|
682
|
+
checkPhaseInRoadmap,
|
|
683
|
+
checkPhaseHasPlans,
|
|
684
|
+
checkNoStaleArtifacts,
|
|
685
|
+
checkOldPhasesArchived,
|
|
686
|
+
checkMilestoneStateCoherence,
|
|
687
|
+
checkInvariantValidation,
|
|
688
|
+
checkCitationGate,
|
|
689
|
+
checkTransitiveCitationGate,
|
|
690
|
+
// Registry and runner
|
|
691
|
+
GATE_REGISTRY,
|
|
692
|
+
_GATE_CHECKS: GATE_CHECKS,
|
|
693
|
+
runPreflightGates,
|
|
694
|
+
resetGatesCache,
|
|
695
|
+
};
|