@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/paths.ts
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GRD Path Resolution -- Centralized .planning/ subdirectory path construction
|
|
5
|
+
*
|
|
6
|
+
* Single source of truth for all milestone-scoped directory paths.
|
|
7
|
+
* All other modules should import from this module instead of
|
|
8
|
+
* hardcoding path.join(cwd, '.planning', 'phases', ...) constructions.
|
|
9
|
+
*
|
|
10
|
+
* Always returns milestone-scoped paths (.planning/milestones/{milestone}/...).
|
|
11
|
+
* Callers use fs.mkdirSync({ recursive: true }) to create directories as needed.
|
|
12
|
+
*
|
|
13
|
+
* Dependencies: fs, path (Node built-in only -- no circular lib/ deps)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { Dirent } from 'fs';
|
|
17
|
+
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
|
|
21
|
+
// ─── Milestone Detection ────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Read the current milestone version from STATE.md.
|
|
25
|
+
*
|
|
26
|
+
* Reads the **Milestone:** field from .planning/STATE.md and extracts
|
|
27
|
+
* the version string (e.g., 'v0.2.1'). Returns 'anonymous' when
|
|
28
|
+
* STATE.md is missing, unreadable, has no Milestone field, or the
|
|
29
|
+
* field value contains no version string.
|
|
30
|
+
* @param cwd - Absolute path to the working directory (project root)
|
|
31
|
+
* @returns Current milestone version string (e.g., 'v0.2.1'), or 'anonymous' if not found
|
|
32
|
+
*/
|
|
33
|
+
function currentMilestone(cwd: string): string {
|
|
34
|
+
const statePath: string = path.join(cwd, '.planning', 'STATE.md');
|
|
35
|
+
|
|
36
|
+
let content: string;
|
|
37
|
+
try {
|
|
38
|
+
content = fs.readFileSync(statePath, 'utf-8');
|
|
39
|
+
} catch {
|
|
40
|
+
return inferMilestoneFromDisk(cwd);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Extract the **Milestone:** field value
|
|
44
|
+
const fieldMatch: RegExpMatchArray | null = content.match(/\*\*Milestone:\*\*\s*(.+)/i);
|
|
45
|
+
if (!fieldMatch) return inferMilestoneFromDisk(cwd);
|
|
46
|
+
|
|
47
|
+
const fieldValue: string = fieldMatch[1].trim();
|
|
48
|
+
if (!fieldValue) return inferMilestoneFromDisk(cwd);
|
|
49
|
+
|
|
50
|
+
// Extract just the version string (vX.Y or vX.Y.Z etc.)
|
|
51
|
+
const versionMatch: RegExpMatchArray | null = fieldValue.match(/(v[\d.]+)/);
|
|
52
|
+
if (!versionMatch) return inferMilestoneFromDisk(cwd);
|
|
53
|
+
|
|
54
|
+
return versionMatch[1];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Fallback: infer milestone from ROADMAP.md and .planning/milestones/ directory.
|
|
59
|
+
*
|
|
60
|
+
* Mirrors the 4-strategy approach from getMilestoneInfo() in utils.js
|
|
61
|
+
* (duplicated here to avoid circular dependency: utils.js imports paths.js).
|
|
62
|
+
* Falls back to scanning milestones/ directory if ROADMAP.md parsing fails.
|
|
63
|
+
*/
|
|
64
|
+
function inferMilestoneFromDisk(cwd: string): string {
|
|
65
|
+
// Collect active milestone directories on disk
|
|
66
|
+
const msDir: string = path.join(cwd, '.planning', 'milestones');
|
|
67
|
+
let activeDirs: string[] = [];
|
|
68
|
+
try {
|
|
69
|
+
const entries: Dirent[] = fs.readdirSync(msDir, { withFileTypes: true });
|
|
70
|
+
activeDirs = entries
|
|
71
|
+
.filter(
|
|
72
|
+
(e: Dirent) => e.isDirectory() && !e.name.endsWith('-phases') && e.name !== 'anonymous'
|
|
73
|
+
)
|
|
74
|
+
.map((e: Dirent) => e.name);
|
|
75
|
+
} catch {
|
|
76
|
+
// milestones dir doesn't exist
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// If exactly one active milestone dir, use it directly
|
|
80
|
+
if (activeDirs.length === 1) return activeDirs[0];
|
|
81
|
+
|
|
82
|
+
// If multiple dirs exist, disambiguate via ROADMAP.md
|
|
83
|
+
if (activeDirs.length > 1) {
|
|
84
|
+
const fromRoadmap: string | null = parseRoadmapMilestone(cwd);
|
|
85
|
+
if (fromRoadmap && activeDirs.includes(fromRoadmap)) return fromRoadmap;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return 'anonymous';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Parse ROADMAP.md for the active milestone version string.
|
|
93
|
+
* Mirrors strategies 1-3 from getMilestoneInfo() in utils.js.
|
|
94
|
+
* (Duplicated here to avoid circular dependency: utils.js imports paths.js.)
|
|
95
|
+
*/
|
|
96
|
+
function parseRoadmapMilestone(cwd: string): string | null {
|
|
97
|
+
try {
|
|
98
|
+
const raw: string = fs.readFileSync(path.join(cwd, '.planning', 'ROADMAP.md'), 'utf-8');
|
|
99
|
+
const roadmap: string = raw.replace(/<details>[\s\S]*?<\/details>/gi, '');
|
|
100
|
+
|
|
101
|
+
// Strategy 1: "(in progress)" milestone bullet
|
|
102
|
+
const inProgress: RegExpMatchArray | null = roadmap.match(
|
|
103
|
+
/-\s+(v[\d.]+)\s+[^\n(]+?\s*\(in progress\)/im
|
|
104
|
+
);
|
|
105
|
+
if (inProgress) return inProgress[1];
|
|
106
|
+
|
|
107
|
+
// Strategy 2: Last non-shipped milestone bullet
|
|
108
|
+
const bulletRegex = /-\s+(v[\d.]+)\s+[^\n(]+?(?:\s*\(([^)]*)\))?\s*$/gim;
|
|
109
|
+
let lastNonShipped: string | null = null;
|
|
110
|
+
let m: RegExpExecArray | null;
|
|
111
|
+
while ((m = bulletRegex.exec(roadmap)) !== null) {
|
|
112
|
+
if (!/shipped/i.test(m[2] || '')) lastNonShipped = m[1];
|
|
113
|
+
}
|
|
114
|
+
if (lastNonShipped) return lastNonShipped;
|
|
115
|
+
|
|
116
|
+
// Strategy 3: Heading format "## vX.Y.Z: Name"
|
|
117
|
+
const headingMatch: RegExpMatchArray | null = roadmap.match(
|
|
118
|
+
/^##\s+(?!#).*?(v\d+\.\d+(?:\.\d+)?)\s*[:\s]+([^\n(]+)/m
|
|
119
|
+
);
|
|
120
|
+
if (headingMatch) return headingMatch[1];
|
|
121
|
+
} catch {
|
|
122
|
+
// ROADMAP.md doesn't exist
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ─── Internal Helper ────────────────────────────────────────────────────────
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Return the milestone root directory path.
|
|
131
|
+
*/
|
|
132
|
+
function milestoneRoot(cwd: string, milestone: string): string {
|
|
133
|
+
return path.join(cwd, '.planning', 'milestones', milestone);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ─── Directory Path Functions ───────────────────────────────────────────────
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Root milestones container directory.
|
|
140
|
+
*/
|
|
141
|
+
function milestonesDir(cwd: string): string {
|
|
142
|
+
return path.join(cwd, '.planning', 'milestones');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Milestone-scoped phases directory.
|
|
147
|
+
*
|
|
148
|
+
* Always returns the milestone-scoped path (.planning/milestones/{milestone}/phases/).
|
|
149
|
+
* Callers should use fs.mkdirSync({ recursive: true }) to ensure the directory exists.
|
|
150
|
+
* @param cwd - Absolute path to the working directory (project root)
|
|
151
|
+
* @param milestone - Milestone version string (e.g., 'v0.2.1'); defaults to current milestone if omitted
|
|
152
|
+
* @returns Absolute path to the milestone-scoped phases directory
|
|
153
|
+
*/
|
|
154
|
+
function phasesDir(cwd: string, milestone?: string | null): string {
|
|
155
|
+
if (milestone == null) {
|
|
156
|
+
milestone = currentMilestone(cwd);
|
|
157
|
+
}
|
|
158
|
+
const milestonesBase: string = path.join(cwd, '.planning', 'milestones');
|
|
159
|
+
const resolved: string = path.join(milestoneRoot(cwd, milestone), 'phases');
|
|
160
|
+
if (!resolved.startsWith(milestonesBase + path.sep) && resolved !== milestonesBase) {
|
|
161
|
+
throw new Error(`Invalid milestone: path would escape .planning directory`);
|
|
162
|
+
}
|
|
163
|
+
return resolved;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Specific phase subdirectory within a milestone.
|
|
168
|
+
*
|
|
169
|
+
* Uses phasesDir() for the base path, inheriting its backward-compatible fallback.
|
|
170
|
+
*/
|
|
171
|
+
function phaseDir(cwd: string, milestone: string | undefined, phaseDirName: string): string {
|
|
172
|
+
const base: string = phasesDir(cwd, milestone);
|
|
173
|
+
const resolved: string = path.join(base, phaseDirName);
|
|
174
|
+
if (!resolved.startsWith(base + path.sep) && resolved !== base) {
|
|
175
|
+
throw new Error(`Invalid phase directory: path would escape phases directory`);
|
|
176
|
+
}
|
|
177
|
+
return resolved;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Milestone-scoped research directory.
|
|
182
|
+
*/
|
|
183
|
+
function researchDir(cwd: string, milestone?: string | null): string {
|
|
184
|
+
if (milestone == null) {
|
|
185
|
+
milestone = currentMilestone(cwd);
|
|
186
|
+
}
|
|
187
|
+
return path.join(milestoneRoot(cwd, milestone), 'research');
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Project-level codebase analysis directory.
|
|
192
|
+
*
|
|
193
|
+
* Always returns .planning/codebase/ -- codebase maps are project-wide,
|
|
194
|
+
* not scoped to a specific milestone.
|
|
195
|
+
* @param cwd - Absolute path to the working directory (project root)
|
|
196
|
+
* @returns Absolute path to the .planning/codebase/ directory
|
|
197
|
+
*/
|
|
198
|
+
function codebaseDir(cwd: string): string {
|
|
199
|
+
return path.join(cwd, '.planning', 'codebase');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Milestone-scoped todos directory.
|
|
204
|
+
*/
|
|
205
|
+
function todosDir(cwd: string, milestone?: string | null): string {
|
|
206
|
+
if (milestone == null) {
|
|
207
|
+
milestone = currentMilestone(cwd);
|
|
208
|
+
}
|
|
209
|
+
return path.join(milestoneRoot(cwd, milestone), 'todos');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Milestone-scoped discussions directory.
|
|
214
|
+
* Created at runtime by runDiscussion() via mkdirSync({ recursive: true }).
|
|
215
|
+
*/
|
|
216
|
+
function discussionsDir(cwd: string, milestone?: string | null): string {
|
|
217
|
+
if (milestone == null) {
|
|
218
|
+
milestone = currentMilestone(cwd);
|
|
219
|
+
}
|
|
220
|
+
const milestonesBase: string = path.join(cwd, '.planning', 'milestones');
|
|
221
|
+
const resolved: string = path.join(milestoneRoot(cwd, milestone), 'discussions');
|
|
222
|
+
if (!resolved.startsWith(milestonesBase + path.sep) && resolved !== milestonesBase) {
|
|
223
|
+
throw new Error('Invalid milestone: path would escape .planning directory');
|
|
224
|
+
}
|
|
225
|
+
return resolved;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Milestone-scoped quick tasks directory.
|
|
230
|
+
*/
|
|
231
|
+
function quickDir(cwd: string, milestone?: string | null): string {
|
|
232
|
+
if (milestone == null) {
|
|
233
|
+
milestone = currentMilestone(cwd);
|
|
234
|
+
}
|
|
235
|
+
return path.join(milestoneRoot(cwd, milestone), 'quick');
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Archived phases directory for a completed milestone.
|
|
240
|
+
*
|
|
241
|
+
* Matches the existing archive layout where completed milestone phases
|
|
242
|
+
* are stored as {version}-phases/ directories.
|
|
243
|
+
* @param cwd - Absolute path to the working directory (project root)
|
|
244
|
+
* @param version - Milestone version string used to form the archive directory name (e.g., 'v0.2.1')
|
|
245
|
+
* @returns Absolute path to the archived phases directory (e.g., .planning/milestones/v0.2.1-phases/)
|
|
246
|
+
*/
|
|
247
|
+
function archivedPhasesDir(cwd: string, version: string): string {
|
|
248
|
+
const milestonesBase: string = path.join(cwd, '.planning', 'milestones');
|
|
249
|
+
const resolved: string = path.join(milestonesBase, version + '-phases');
|
|
250
|
+
if (!resolved.startsWith(milestonesBase + path.sep) && resolved !== milestonesBase) {
|
|
251
|
+
throw new Error(`Invalid version: path would escape .planning directory`);
|
|
252
|
+
}
|
|
253
|
+
return resolved;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Milestone-scoped standards directory.
|
|
258
|
+
*/
|
|
259
|
+
function standardsDir(cwd: string, milestone?: string | null): string {
|
|
260
|
+
if (milestone == null) {
|
|
261
|
+
milestone = currentMilestone(cwd);
|
|
262
|
+
}
|
|
263
|
+
return path.join(milestoneRoot(cwd, milestone), 'standards');
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// ─── Exports ────────────────────────────────────────────────────────────────
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Root .planning directory path.
|
|
270
|
+
*
|
|
271
|
+
* Single source of truth for the .planning/ directory location.
|
|
272
|
+
* Use this instead of hardcoding path.join(cwd, '.planning', ...) constructions.
|
|
273
|
+
* @param cwd - Absolute path to the working directory (project root)
|
|
274
|
+
* @returns Absolute path to the .planning/ directory
|
|
275
|
+
*/
|
|
276
|
+
function planningDir(cwd: string): string {
|
|
277
|
+
return path.join(cwd, '.planning');
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
module.exports = {
|
|
281
|
+
currentMilestone,
|
|
282
|
+
planningDir,
|
|
283
|
+
milestonesDir,
|
|
284
|
+
phasesDir,
|
|
285
|
+
phaseDir,
|
|
286
|
+
researchDir,
|
|
287
|
+
codebaseDir,
|
|
288
|
+
todosDir,
|
|
289
|
+
discussionsDir,
|
|
290
|
+
quickDir,
|
|
291
|
+
standardsDir,
|
|
292
|
+
archivedPhasesDir,
|
|
293
|
+
};
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GRD Phase/Complete/LLM -- Opt-in LLM fallback for mechanical phase
|
|
5
|
+
* completion failures.
|
|
6
|
+
*
|
|
7
|
+
* When _phaseCompleteCore throws or returns gate_failed, and the user
|
|
8
|
+
* has opted in via config.phase_complete_llm_fallback = true, this
|
|
9
|
+
* module asks Claude (via the scheduler) to perform the phase finalize
|
|
10
|
+
* by editing ROADMAP.md and STATE.md directly.
|
|
11
|
+
*
|
|
12
|
+
* Verification is shallow: after the subprocess exits, we re-read
|
|
13
|
+
* ROADMAP.md and check for `- [x] Phase N`. If ticked, the fallback
|
|
14
|
+
* is considered successful. Otherwise returns null.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import * as fs from 'fs';
|
|
18
|
+
import * as path from 'path';
|
|
19
|
+
import { setTimeout as sleep } from 'timers/promises';
|
|
20
|
+
import type { GateViolation, PhaseCompleteResult } from './types';
|
|
21
|
+
import type { Scheduler } from './scheduler';
|
|
22
|
+
|
|
23
|
+
const { incrementCounter } = require('./metrics') as {
|
|
24
|
+
incrementCounter: (name: string, delta?: number) => void;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const FALLBACK_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes max
|
|
28
|
+
const PROMPT_MAX_CONTEXT_BYTES = 100_000; // 100KB ceiling
|
|
29
|
+
|
|
30
|
+
function _readFileTruncated(filePath: string, maxBytes: number): string | null {
|
|
31
|
+
try {
|
|
32
|
+
const buf = fs.readFileSync(filePath);
|
|
33
|
+
if (buf.length > maxBytes) {
|
|
34
|
+
return (
|
|
35
|
+
buf.subarray(0, maxBytes).toString('utf-8') +
|
|
36
|
+
`\n\n[... truncated, original ${buf.length} bytes]\n`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return buf.toString('utf-8');
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function _listPhaseDirContents(phaseDir: string): string[] {
|
|
46
|
+
try {
|
|
47
|
+
return fs.readdirSync(phaseDir).sort();
|
|
48
|
+
} catch {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function _describeFailure(failure: Error | { gate_errors?: GateViolation[] }): string {
|
|
54
|
+
if (failure instanceof Error) return `Exception: ${failure.message}`;
|
|
55
|
+
if ('gate_errors' in failure && failure.gate_errors) {
|
|
56
|
+
return `Gate failures: ${failure.gate_errors.map((g) => g.message).join('; ')}`;
|
|
57
|
+
}
|
|
58
|
+
return 'Unknown mechanical failure';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function _buildPrompt(
|
|
62
|
+
phaseNum: string,
|
|
63
|
+
roadmapContent: string | null,
|
|
64
|
+
stateContent: string | null,
|
|
65
|
+
phaseDirFiles: string[],
|
|
66
|
+
failureDescription: string
|
|
67
|
+
): string {
|
|
68
|
+
return [
|
|
69
|
+
`You are finalizing GRD Phase ${phaseNum} after the mechanical regex-based`,
|
|
70
|
+
`completion failed. Your job is to update .planning/ROADMAP.md and`,
|
|
71
|
+
`.planning/STATE.md directly using your file-editing tools.`,
|
|
72
|
+
'',
|
|
73
|
+
`Failure reason: ${failureDescription}`,
|
|
74
|
+
'',
|
|
75
|
+
`Phase directory contents:`,
|
|
76
|
+
phaseDirFiles.length > 0
|
|
77
|
+
? phaseDirFiles.map((f) => ` - ${f}`).join('\n')
|
|
78
|
+
: ' (empty or missing)',
|
|
79
|
+
'',
|
|
80
|
+
`## Current .planning/ROADMAP.md`,
|
|
81
|
+
'',
|
|
82
|
+
'```markdown',
|
|
83
|
+
roadmapContent || '[MISSING]',
|
|
84
|
+
'```',
|
|
85
|
+
'',
|
|
86
|
+
`## Current .planning/STATE.md`,
|
|
87
|
+
'',
|
|
88
|
+
'```markdown',
|
|
89
|
+
stateContent || '[MISSING]',
|
|
90
|
+
'```',
|
|
91
|
+
'',
|
|
92
|
+
`## Your task`,
|
|
93
|
+
'',
|
|
94
|
+
`1. Update ROADMAP.md so that the Phase ${phaseNum} entry is marked as`,
|
|
95
|
+
` completed. The exact format varies by project, but the canonical`,
|
|
96
|
+
` pattern is to change \`- [ ] Phase ${phaseNum}: ...\` into`,
|
|
97
|
+
` \`- [x] Phase ${phaseNum}: ... (completed ${new Date().toISOString().split('T')[0]})\`.`,
|
|
98
|
+
` If the roadmap has a progress table or status column, update that`,
|
|
99
|
+
` row to indicate Complete with today's date.`,
|
|
100
|
+
'',
|
|
101
|
+
`2. Update STATE.md so that Current Phase advances past ${phaseNum}`,
|
|
102
|
+
` if there is a next phase, or to "Milestone complete" if ${phaseNum}`,
|
|
103
|
+
` was the last phase. Update Last Activity to today's date and`,
|
|
104
|
+
` Last Activity Description to reflect the completion.`,
|
|
105
|
+
'',
|
|
106
|
+
`3. Do NOT modify any other files.`,
|
|
107
|
+
'',
|
|
108
|
+
`4. Do NOT run any subcommands beyond file editing (no git, no npm,`,
|
|
109
|
+
` no grd commands). Just edit the two files.`,
|
|
110
|
+
'',
|
|
111
|
+
`Start now. Use your file-editing tools.`,
|
|
112
|
+
].join('\n');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function _verifyRoadmapTicked(cwd: string, phaseNum: string): boolean {
|
|
116
|
+
const roadmapPath = path.join(cwd, '.planning', 'ROADMAP.md');
|
|
117
|
+
try {
|
|
118
|
+
const content = fs.readFileSync(roadmapPath, 'utf-8');
|
|
119
|
+
const pattern = new RegExp(
|
|
120
|
+
`-\\s*\\[x\\]\\s*Phase\\s+${phaseNum.replace('.', '\\.')}[\\s:]`,
|
|
121
|
+
'i'
|
|
122
|
+
);
|
|
123
|
+
return pattern.test(content);
|
|
124
|
+
} catch {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function _verifyStateAdvanced(cwd: string, phaseNum: string): boolean {
|
|
130
|
+
const statePath = path.join(cwd, '.planning', 'STATE.md');
|
|
131
|
+
let content: string;
|
|
132
|
+
try {
|
|
133
|
+
content = fs.readFileSync(statePath, 'utf-8');
|
|
134
|
+
} catch {
|
|
135
|
+
// Missing STATE.md is a verification failure — the LLM fallback
|
|
136
|
+
// should NEVER delete it. If it did, downstream state-dependent
|
|
137
|
+
// commands will break.
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Find the Current Phase line
|
|
142
|
+
const match = content.match(/\*\*Current Phase:\*\*\s*([^\n]*)/);
|
|
143
|
+
if (!match) return true; // no Current Phase field — skip check
|
|
144
|
+
|
|
145
|
+
const currentPhase = match[1].trim().toLowerCase();
|
|
146
|
+
|
|
147
|
+
// Acceptable post-completion values:
|
|
148
|
+
// - A different phase number (not phaseNum)
|
|
149
|
+
// - Contains "complete" (e.g., "Milestone complete")
|
|
150
|
+
if (currentPhase.includes('complete')) return true;
|
|
151
|
+
|
|
152
|
+
// Normalize: check if currentPhase starts with or equals phaseNum
|
|
153
|
+
// (handles "3", "03", "3:", "Phase 3", etc.)
|
|
154
|
+
const phasePattern = new RegExp(`^(phase\\s+)?0*${phaseNum.replace('.', '\\.')}(\\b|:|$)`, 'i');
|
|
155
|
+
return !phasePattern.test(currentPhase);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function _verifyProgressTableRow(cwd: string, phaseNum: string): boolean {
|
|
159
|
+
const roadmapPath = path.join(cwd, '.planning', 'ROADMAP.md');
|
|
160
|
+
let content: string;
|
|
161
|
+
try {
|
|
162
|
+
content = fs.readFileSync(roadmapPath, 'utf-8');
|
|
163
|
+
} catch {
|
|
164
|
+
return true; // missing — can't verify, assume ok
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Find a progress table row like `| 3 | ... | In Progress | ... |`.
|
|
168
|
+
// If no table is detected for this phase, skip the check (return true).
|
|
169
|
+
// If found, verify the Status column shows "Complete".
|
|
170
|
+
const rowPattern = new RegExp(
|
|
171
|
+
`\\|\\s*0*${phaseNum.replace('.', '\\.')}\\s*\\|([^|]*\\|){1,4}\\s*Complete\\s*\\|`,
|
|
172
|
+
'i'
|
|
173
|
+
);
|
|
174
|
+
const rowPatternIncomplete = new RegExp(
|
|
175
|
+
`\\|\\s*0*${phaseNum.replace('.', '\\.')}\\s*\\|[^\\n]*`,
|
|
176
|
+
'i'
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
const incompleteMatch = content.match(rowPatternIncomplete);
|
|
180
|
+
if (!incompleteMatch) return true; // no row for this phase, skip
|
|
181
|
+
|
|
182
|
+
// We have a row — does it say Complete?
|
|
183
|
+
return rowPattern.test(content);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function _verifyFallbackOutput(
|
|
187
|
+
cwd: string,
|
|
188
|
+
phaseNum: string
|
|
189
|
+
): {
|
|
190
|
+
ok: boolean;
|
|
191
|
+
checks: { name: string; passed: boolean }[];
|
|
192
|
+
} {
|
|
193
|
+
const roadmapTicked = _verifyRoadmapTicked(cwd, phaseNum);
|
|
194
|
+
const stateAdvanced = _verifyStateAdvanced(cwd, phaseNum);
|
|
195
|
+
const progressRow = _verifyProgressTableRow(cwd, phaseNum);
|
|
196
|
+
|
|
197
|
+
const checks = [
|
|
198
|
+
{ name: 'roadmap-ticked', passed: roadmapTicked },
|
|
199
|
+
{ name: 'state-advanced', passed: stateAdvanced },
|
|
200
|
+
{ name: 'progress-row', passed: progressRow },
|
|
201
|
+
];
|
|
202
|
+
|
|
203
|
+
// Require roadmap-ticked AND state-advanced. progress-row is advisory
|
|
204
|
+
// (returns true for skipped). So `passed: true` for the advisory check
|
|
205
|
+
// doesn't distinguish between "passed" and "skipped", but that's OK —
|
|
206
|
+
// we're using it as a heuristic, not a hard gate.
|
|
207
|
+
const ok = roadmapTicked && stateAdvanced;
|
|
208
|
+
return { ok, checks };
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function _buildSyntheticResult(cwd: string, phaseNum: string): PhaseCompleteResult {
|
|
212
|
+
const today = new Date().toISOString().split('T')[0];
|
|
213
|
+
const { _resolvePhaseSuccession } = require('./phase-complete') as {
|
|
214
|
+
_resolvePhaseSuccession: (
|
|
215
|
+
cwd: string,
|
|
216
|
+
phaseNum: string
|
|
217
|
+
) => {
|
|
218
|
+
phaseName: string;
|
|
219
|
+
plansExecuted: string;
|
|
220
|
+
nextPhaseNum: string | null;
|
|
221
|
+
nextPhaseName: string | null;
|
|
222
|
+
isLastPhase: boolean;
|
|
223
|
+
};
|
|
224
|
+
};
|
|
225
|
+
const succession = _resolvePhaseSuccession(cwd, phaseNum);
|
|
226
|
+
return {
|
|
227
|
+
completed_phase: phaseNum,
|
|
228
|
+
phase_name: succession.phaseName,
|
|
229
|
+
plans_executed: succession.plansExecuted,
|
|
230
|
+
next_phase: succession.nextPhaseNum,
|
|
231
|
+
next_phase_name: succession.nextPhaseName,
|
|
232
|
+
is_last_phase: succession.isLastPhase,
|
|
233
|
+
date: today,
|
|
234
|
+
roadmap_updated: true,
|
|
235
|
+
state_updated: true,
|
|
236
|
+
llm_fallback: true,
|
|
237
|
+
} as PhaseCompleteResult;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Single attempt at LLM fallback phase completion. Builds the prompt,
|
|
242
|
+
* spawns the subprocess, and verifies the roadmap checkbox.
|
|
243
|
+
*
|
|
244
|
+
* @param cwd - project working directory
|
|
245
|
+
* @param phaseNum - phase number string (e.g., '3')
|
|
246
|
+
* @param scheduler - scheduler instance to use for spawning
|
|
247
|
+
* @param failure - the original mechanical failure description
|
|
248
|
+
* @param attemptIndex - zero-based attempt index (used for log prefix)
|
|
249
|
+
* @returns synthetic PhaseCompleteResult on success, null on any failure
|
|
250
|
+
*/
|
|
251
|
+
async function _attemptOnce(
|
|
252
|
+
cwd: string,
|
|
253
|
+
phaseNum: string,
|
|
254
|
+
scheduler: Scheduler,
|
|
255
|
+
failure: Error | { gate_errors?: GateViolation[] },
|
|
256
|
+
attemptIndex: number
|
|
257
|
+
): Promise<PhaseCompleteResult | null> {
|
|
258
|
+
const roadmapPath = path.join(cwd, '.planning', 'ROADMAP.md');
|
|
259
|
+
const statePath = path.join(cwd, '.planning', 'STATE.md');
|
|
260
|
+
const roadmap = _readFileTruncated(roadmapPath, PROMPT_MAX_CONTEXT_BYTES);
|
|
261
|
+
const state = _readFileTruncated(statePath, PROMPT_MAX_CONTEXT_BYTES);
|
|
262
|
+
|
|
263
|
+
let phaseDirFiles: string[] = [];
|
|
264
|
+
try {
|
|
265
|
+
const { phasesDir } = require('./paths') as {
|
|
266
|
+
phasesDir: (cwd: string) => string;
|
|
267
|
+
};
|
|
268
|
+
const basePhasesDir = phasesDir(cwd);
|
|
269
|
+
const entries = fs.readdirSync(basePhasesDir);
|
|
270
|
+
const match = entries.find((e) => e.startsWith(`${phaseNum}-`));
|
|
271
|
+
if (match) {
|
|
272
|
+
phaseDirFiles = _listPhaseDirContents(path.join(basePhasesDir, match));
|
|
273
|
+
}
|
|
274
|
+
} catch {
|
|
275
|
+
// ignore
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const failureDescription = _describeFailure(failure);
|
|
279
|
+
const prompt = _buildPrompt(phaseNum, roadmap, state, phaseDirFiles, failureDescription);
|
|
280
|
+
const logPrefix =
|
|
281
|
+
attemptIndex > 0
|
|
282
|
+
? `[phase-complete-llm] (attempt ${attemptIndex + 1}) `
|
|
283
|
+
: `[phase-complete-llm] `;
|
|
284
|
+
|
|
285
|
+
process.stderr.write(
|
|
286
|
+
`${logPrefix}attempting LLM fallback for phase ${phaseNum} ` +
|
|
287
|
+
`(reason: ${failureDescription.slice(0, 200)})\n`
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
try {
|
|
291
|
+
const result = await scheduler.spawn(prompt, {
|
|
292
|
+
cwd,
|
|
293
|
+
timeout: FALLBACK_TIMEOUT_MS,
|
|
294
|
+
captureOutput: false,
|
|
295
|
+
});
|
|
296
|
+
if (result.exitCode !== 0) {
|
|
297
|
+
process.stderr.write(`${logPrefix}fallback subprocess exited with code ${result.exitCode}\n`);
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
} catch (e) {
|
|
301
|
+
process.stderr.write(`${logPrefix}fallback subprocess threw: ${(e as Error).message}\n`);
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Invalidate cached reads so verification sees fresh post-LLM content
|
|
306
|
+
const { clearRoadmapCache, clearStateCache } = require('./phase-io') as {
|
|
307
|
+
clearRoadmapCache: (filePath?: string) => void;
|
|
308
|
+
clearStateCache: (filePath?: string) => void;
|
|
309
|
+
};
|
|
310
|
+
clearRoadmapCache(path.join(cwd, '.planning', 'ROADMAP.md'));
|
|
311
|
+
clearStateCache(path.join(cwd, '.planning', 'STATE.md'));
|
|
312
|
+
|
|
313
|
+
const verification = _verifyFallbackOutput(cwd, phaseNum);
|
|
314
|
+
if (!verification.ok) {
|
|
315
|
+
const failed = verification.checks
|
|
316
|
+
.filter((c) => !c.passed)
|
|
317
|
+
.map((c) => c.name)
|
|
318
|
+
.join(', ');
|
|
319
|
+
process.stderr.write(`${logPrefix}verification failed — checks: ${failed}\n`);
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
process.stderr.write(`${logPrefix}fallback succeeded for phase ${phaseNum}\n`);
|
|
324
|
+
incrementCounter('phase_complete_llm_fallback.successes_total');
|
|
325
|
+
return _buildSyntheticResult(cwd, phaseNum);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Attempts to recover from a mechanical phase-completion failure by
|
|
330
|
+
* asking Claude to perform the ROADMAP.md and STATE.md edits directly.
|
|
331
|
+
* Returns a synthetic PhaseCompleteResult on success, null on any
|
|
332
|
+
* failure or when the scheduler is null.
|
|
333
|
+
*
|
|
334
|
+
* Retries up to `phase_complete_llm_fallback_retries` times (default 0)
|
|
335
|
+
* with exponential backoff: 2^attempt seconds between retries (2s, 4s, …).
|
|
336
|
+
*/
|
|
337
|
+
export async function attemptLlmFallbackCompletion(
|
|
338
|
+
cwd: string,
|
|
339
|
+
phaseNum: string,
|
|
340
|
+
scheduler: Scheduler | null,
|
|
341
|
+
failure: Error | { gate_errors?: GateViolation[] }
|
|
342
|
+
): Promise<PhaseCompleteResult | null> {
|
|
343
|
+
if (!scheduler) return null;
|
|
344
|
+
|
|
345
|
+
incrementCounter('phase_complete_llm_fallback.attempts_total');
|
|
346
|
+
|
|
347
|
+
// Read retry count from config
|
|
348
|
+
let maxRetries = 0;
|
|
349
|
+
try {
|
|
350
|
+
const { loadConfig } = require('./utils') as {
|
|
351
|
+
loadConfig: (cwd: string) => { phase_complete_llm_fallback_retries?: number };
|
|
352
|
+
};
|
|
353
|
+
const config = loadConfig(cwd);
|
|
354
|
+
maxRetries = Math.max(0, config.phase_complete_llm_fallback_retries ?? 0);
|
|
355
|
+
} catch {
|
|
356
|
+
// Use default of 0
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
360
|
+
const result = await _attemptOnce(cwd, phaseNum, scheduler, failure, attempt);
|
|
361
|
+
if (result !== null) return result;
|
|
362
|
+
if (attempt < maxRetries) {
|
|
363
|
+
const backoffMs = Math.pow(2, attempt) * 1000;
|
|
364
|
+
process.stderr.write(
|
|
365
|
+
`[phase-complete-llm] retrying after ${backoffMs / 1000}s (attempt ${attempt + 2}/${maxRetries + 1})\n`
|
|
366
|
+
);
|
|
367
|
+
await sleep(backoffMs);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
module.exports = {
|
|
374
|
+
attemptLlmFallbackCompletion,
|
|
375
|
+
_verifyFallbackOutput,
|
|
376
|
+
};
|