@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
|
@@ -0,0 +1,886 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GRD AutoResearch -- Karpathy-style autonomous experiment loop integrated with NERFIFY research.
|
|
5
|
+
*
|
|
6
|
+
* Inspired by karpathy/autoresearch: hypothesis → modify → run → evaluate → keep/revert → repeat.
|
|
7
|
+
* Combined with NERFIFY: survey → deep-dive → citation graph → knowledge mining → plan.
|
|
8
|
+
*
|
|
9
|
+
* Each iteration:
|
|
10
|
+
* 1. Research: survey papers or mine KNOWHOW for ideas (if enabled)
|
|
11
|
+
* 2. Hypothesize: form a specific improvement hypothesis
|
|
12
|
+
* 3. Implement: modify code via claude -p subprocess
|
|
13
|
+
* 4. Evaluate: run tests + metrics against baseline
|
|
14
|
+
* 5. Decide: keep if metric improved, revert if not
|
|
15
|
+
* 6. Log: append result to AUTORESEARCH.tsv
|
|
16
|
+
* 7. Mine: extract knowledge patterns from successful experiments
|
|
17
|
+
* 8. Repeat indefinitely until stopped
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type { GrdConfig, MilestoneInfo } from './types';
|
|
21
|
+
import type { Scheduler } from './scheduler';
|
|
22
|
+
|
|
23
|
+
const fs = require('fs') as typeof import('fs');
|
|
24
|
+
const path = require('path') as typeof import('path');
|
|
25
|
+
const childProcess = require('child_process') as typeof import('child_process');
|
|
26
|
+
|
|
27
|
+
const {
|
|
28
|
+
loadConfig,
|
|
29
|
+
getMilestoneInfo,
|
|
30
|
+
output,
|
|
31
|
+
error,
|
|
32
|
+
MODEL_PROFILES,
|
|
33
|
+
resolveModelForAgent,
|
|
34
|
+
}: {
|
|
35
|
+
loadConfig: (cwd: string) => GrdConfig;
|
|
36
|
+
getMilestoneInfo: (cwd: string) => MilestoneInfo;
|
|
37
|
+
output: (result: unknown, raw: boolean, rawValue?: unknown) => never;
|
|
38
|
+
error: (msg: string) => never;
|
|
39
|
+
MODEL_PROFILES: Record<string, Record<string, string>>;
|
|
40
|
+
resolveModelForAgent: (
|
|
41
|
+
config: GrdConfig,
|
|
42
|
+
agentType: string,
|
|
43
|
+
cwd?: string,
|
|
44
|
+
options?: { effectiveTierOverride?: import('./types').ModelTier }
|
|
45
|
+
) => string;
|
|
46
|
+
} = require('./utils');
|
|
47
|
+
|
|
48
|
+
const {
|
|
49
|
+
getEffectiveTierForDispatch,
|
|
50
|
+
}: {
|
|
51
|
+
getEffectiveTierForDispatch: (opts: {
|
|
52
|
+
agentType: string;
|
|
53
|
+
prompt: string;
|
|
54
|
+
config: GrdConfig;
|
|
55
|
+
scheduler: { getStates(): Map<string, import('./types').BackendUsageState> } | null;
|
|
56
|
+
schedulerConfig?: import('./types').SchedulerConfig;
|
|
57
|
+
superpowersConfig?: import('./types').SuperpowersConfig;
|
|
58
|
+
modelProfiles: Record<string, Record<string, string>>;
|
|
59
|
+
}) => import('./types').ModelTier;
|
|
60
|
+
} = require('./backend');
|
|
61
|
+
|
|
62
|
+
const {
|
|
63
|
+
researchDir: getResearchDir,
|
|
64
|
+
planningDir: getPlanningDir,
|
|
65
|
+
}: {
|
|
66
|
+
researchDir: (cwd: string) => string;
|
|
67
|
+
planningDir: (cwd: string) => string;
|
|
68
|
+
} = require('./paths');
|
|
69
|
+
|
|
70
|
+
const {
|
|
71
|
+
ADAPTERS: _ADAPTERS,
|
|
72
|
+
}: {
|
|
73
|
+
ADAPTERS: Record<string, { binary: string }>;
|
|
74
|
+
} = require('./scheduler');
|
|
75
|
+
|
|
76
|
+
const {
|
|
77
|
+
buildKnowledgeInjectionBlock,
|
|
78
|
+
}: {
|
|
79
|
+
buildKnowledgeInjectionBlock: (cwd: string, phaseNum: string, moduleHints?: string[]) => string;
|
|
80
|
+
} = require('./knowledge');
|
|
81
|
+
|
|
82
|
+
const {
|
|
83
|
+
buildCitationGraph,
|
|
84
|
+
findUnresolved,
|
|
85
|
+
}: {
|
|
86
|
+
buildCitationGraph: (content: string) => {
|
|
87
|
+
nodes: { slug: string; title: string; resolved: boolean; priority: string }[];
|
|
88
|
+
edges: { from: string; to: string; type: string }[];
|
|
89
|
+
};
|
|
90
|
+
findUnresolved: (graph: {
|
|
91
|
+
nodes: { slug: string; title: string; resolved: boolean; priority: string }[];
|
|
92
|
+
edges: { from: string; to: string; type: string }[];
|
|
93
|
+
}) => { slug: string; title: string; priority: string }[];
|
|
94
|
+
} = require('./citations');
|
|
95
|
+
|
|
96
|
+
// ─── Constants ──────────────────────────────────────────────────────────────
|
|
97
|
+
|
|
98
|
+
/** Maximum characters from LANDSCAPE.md injected into research context. Override via arConfig.autoresearch?.landscape_max_chars. */
|
|
99
|
+
const LANDSCAPE_MAX_CHARS = 3000;
|
|
100
|
+
|
|
101
|
+
// ─── Types ──────────────────────────────────────────────────────────────────
|
|
102
|
+
|
|
103
|
+
interface AutoResearchOptions {
|
|
104
|
+
/** Research topic / area of focus */
|
|
105
|
+
topic: string;
|
|
106
|
+
/** Maximum number of experiments (0 = unlimited) */
|
|
107
|
+
maxExperiments: number;
|
|
108
|
+
/** Time budget per experiment in minutes */
|
|
109
|
+
timeBudget: number;
|
|
110
|
+
/** Metric to optimize: 'test_count' | 'coverage' | 'lint_errors' | 'custom' */
|
|
111
|
+
metric: string;
|
|
112
|
+
/** Whether to auto-survey if no LANDSCAPE.md exists */
|
|
113
|
+
autoSurvey: boolean;
|
|
114
|
+
/** Maximum deep-dives per loop iteration */
|
|
115
|
+
maxDeepDives: number;
|
|
116
|
+
/** Model override for claude -p */
|
|
117
|
+
model?: string;
|
|
118
|
+
/** Max turns per subprocess */
|
|
119
|
+
maxTurns?: number;
|
|
120
|
+
/** Dry run — don't actually run experiments */
|
|
121
|
+
dryRun: boolean;
|
|
122
|
+
/** Optional scheduler for per-account token tracking and rate-limit handling */
|
|
123
|
+
scheduler?: Scheduler | null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
interface ExperimentResult {
|
|
127
|
+
id: number;
|
|
128
|
+
commit: string;
|
|
129
|
+
metric_value: number;
|
|
130
|
+
metric_name: string;
|
|
131
|
+
status: 'keep' | 'discard' | 'crash';
|
|
132
|
+
hypothesis: string;
|
|
133
|
+
research_source: string;
|
|
134
|
+
duration_seconds: number;
|
|
135
|
+
timestamp: string;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
interface AutoResearchState {
|
|
139
|
+
experiments: ExperimentResult[];
|
|
140
|
+
baseline: number;
|
|
141
|
+
best: number;
|
|
142
|
+
topic: string;
|
|
143
|
+
started_at: string;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
147
|
+
|
|
148
|
+
function _log(msg: string): void {
|
|
149
|
+
const ts = new Date().toISOString().slice(11, 19);
|
|
150
|
+
process.stderr.write(`[autoresearch ${ts}] ${msg}\n`);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function _execGit(cwd: string, args: string[]): { stdout: string; exitCode: number } {
|
|
154
|
+
try {
|
|
155
|
+
const result = childProcess.spawnSync('git', args, {
|
|
156
|
+
cwd,
|
|
157
|
+
stdio: 'pipe',
|
|
158
|
+
encoding: 'utf-8',
|
|
159
|
+
});
|
|
160
|
+
return { stdout: (result.stdout || '').trim(), exitCode: result.status ?? 1 };
|
|
161
|
+
} catch {
|
|
162
|
+
return { stdout: '', exitCode: 1 };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Async spawn wrapper. When a scheduler is provided, routes through
|
|
168
|
+
* scheduler.spawn for per-account token tracking and rate-limit handling.
|
|
169
|
+
* SchedulerSpawnResult.stdout carries captured subprocess stdout when
|
|
170
|
+
* captureOutput is true, so the scheduler path is used unconditionally.
|
|
171
|
+
* Falls back to the synchronous path (_spawnClaudeSync) only when no
|
|
172
|
+
* scheduler is provided.
|
|
173
|
+
*/
|
|
174
|
+
async function _spawnClaude(
|
|
175
|
+
cwd: string,
|
|
176
|
+
prompt: string,
|
|
177
|
+
opts: {
|
|
178
|
+
timeout?: number;
|
|
179
|
+
maxTurns?: number;
|
|
180
|
+
model?: string;
|
|
181
|
+
captureOutput?: boolean;
|
|
182
|
+
scheduler?: Scheduler | null;
|
|
183
|
+
/** Agent type hint for complexity-based tier routing (M2). */
|
|
184
|
+
agentType?: string;
|
|
185
|
+
/** Override binary name for the sync fallback path. Defaults to ADAPTERS.claude.binary. */
|
|
186
|
+
binary?: string;
|
|
187
|
+
} = {}
|
|
188
|
+
): Promise<{ exitCode: number; stdout: string; timedOut: boolean }> {
|
|
189
|
+
if (opts.scheduler) {
|
|
190
|
+
try {
|
|
191
|
+
const result = await opts.scheduler.spawn(prompt, {
|
|
192
|
+
cwd,
|
|
193
|
+
model: opts.model,
|
|
194
|
+
timeout: opts.timeout,
|
|
195
|
+
maxTurns: opts.maxTurns,
|
|
196
|
+
captureOutput: opts.captureOutput,
|
|
197
|
+
agentType: opts.agentType,
|
|
198
|
+
});
|
|
199
|
+
return {
|
|
200
|
+
exitCode: result.exitCode,
|
|
201
|
+
stdout: result.stdout || '',
|
|
202
|
+
timedOut: result.timedOut,
|
|
203
|
+
};
|
|
204
|
+
} catch (e) {
|
|
205
|
+
if (e instanceof Error && e.message.includes('SIGINT')) throw e;
|
|
206
|
+
return { exitCode: 1, stdout: '', timedOut: false };
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
const binary = opts.binary ?? _ADAPTERS['claude']?.binary ?? 'claude';
|
|
210
|
+
return _spawnClaudeSync(cwd, prompt, { ...opts, binary });
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function _spawnClaudeSync(
|
|
214
|
+
cwd: string,
|
|
215
|
+
prompt: string,
|
|
216
|
+
opts: { timeout?: number; maxTurns?: number; model?: string; captureOutput?: boolean; binary?: string } = {}
|
|
217
|
+
): { exitCode: number; stdout: string; timedOut: boolean } {
|
|
218
|
+
const binary = opts.binary ?? (_ADAPTERS['claude']?.binary ?? 'claude');
|
|
219
|
+
const args: string[] = ['-p', prompt, '--verbose', '--dangerously-skip-permissions'];
|
|
220
|
+
if (opts.maxTurns !== undefined && opts.maxTurns > 0) args.push('--max-turns', String(opts.maxTurns));
|
|
221
|
+
if (opts.model) args.push('--model', opts.model);
|
|
222
|
+
|
|
223
|
+
const env: Record<string, string | undefined> = { ...process.env };
|
|
224
|
+
for (const key of Object.keys(env)) {
|
|
225
|
+
if (key === 'CLAUDECODE' || key.startsWith('CLAUDE_CODE_') || key.startsWith('CLAUDECODE_')) {
|
|
226
|
+
delete env[key];
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const result = childProcess.spawnSync(binary, args, {
|
|
231
|
+
cwd,
|
|
232
|
+
stdio: opts.captureOutput ? 'pipe' : ['ignore', 'pipe', 'pipe'],
|
|
233
|
+
env,
|
|
234
|
+
encoding: 'utf-8',
|
|
235
|
+
timeout: opts.timeout,
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
if (!opts.captureOutput) {
|
|
239
|
+
if (result.stdout) process.stdout.write(result.stdout as string);
|
|
240
|
+
if (result.stderr) process.stderr.write(result.stderr as string);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const timedOut = !!(result.error && (result.error as NodeJS.ErrnoException).code === 'ETIMEDOUT');
|
|
244
|
+
return {
|
|
245
|
+
exitCode: timedOut ? 124 : (result.status ?? 1),
|
|
246
|
+
stdout: (result.stdout || '') as string,
|
|
247
|
+
timedOut,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// ─── Metric Collection ──────────────────────────────────────────────────────
|
|
252
|
+
|
|
253
|
+
function _collectMetric(cwd: string, metric: string, timeouts?: import('./types').GrdTimeouts): number {
|
|
254
|
+
const testTimeout = timeouts?.autoresearch_test_ms ?? 120000;
|
|
255
|
+
const coverageTimeout = timeouts?.autoresearch_coverage_ms ?? 180000;
|
|
256
|
+
const lintTimeout = timeouts?.autoresearch_lint_ms ?? 60000;
|
|
257
|
+
switch (metric) {
|
|
258
|
+
case 'test_count': {
|
|
259
|
+
const result = childProcess.spawnSync('npx', ['jest', '--json', '--silent'], {
|
|
260
|
+
cwd,
|
|
261
|
+
stdio: 'pipe',
|
|
262
|
+
encoding: 'utf-8',
|
|
263
|
+
timeout: testTimeout,
|
|
264
|
+
});
|
|
265
|
+
try {
|
|
266
|
+
const json = JSON.parse((result.stdout || '') as string);
|
|
267
|
+
return json.numPassedTests || 0;
|
|
268
|
+
} catch {
|
|
269
|
+
return 0;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
case 'coverage': {
|
|
273
|
+
// Omit --silent so the coverage table appears in stdout for the fallback parser.
|
|
274
|
+
// The primary path (coverage-summary.json) is unaffected; --silent would hide
|
|
275
|
+
// the table and cause the fallback to always return 0.
|
|
276
|
+
const result = childProcess.spawnSync(
|
|
277
|
+
'npx',
|
|
278
|
+
['jest', '--coverage', '--coverageReporters=json-summary'],
|
|
279
|
+
{ cwd, stdio: 'pipe', encoding: 'utf-8', timeout: coverageTimeout }
|
|
280
|
+
);
|
|
281
|
+
try {
|
|
282
|
+
const summaryPath = path.join(cwd, 'coverage', 'coverage-summary.json');
|
|
283
|
+
if (fs.existsSync(summaryPath)) {
|
|
284
|
+
const summary = JSON.parse(fs.readFileSync(summaryPath, 'utf-8'));
|
|
285
|
+
return summary.total?.lines?.pct || 0;
|
|
286
|
+
}
|
|
287
|
+
} catch {
|
|
288
|
+
// fall through
|
|
289
|
+
}
|
|
290
|
+
return _extractCoverageFromOutput((result.stdout || '') as string);
|
|
291
|
+
}
|
|
292
|
+
case 'lint_errors': {
|
|
293
|
+
const result = childProcess.spawnSync('npx', ['eslint', 'bin/', 'lib/', '--format', 'json'], {
|
|
294
|
+
cwd,
|
|
295
|
+
stdio: 'pipe',
|
|
296
|
+
encoding: 'utf-8',
|
|
297
|
+
timeout: lintTimeout,
|
|
298
|
+
});
|
|
299
|
+
try {
|
|
300
|
+
const json = JSON.parse((result.stdout || '') as string);
|
|
301
|
+
const total = json.reduce(
|
|
302
|
+
(sum: number, file: { errorCount: number }) => sum + file.errorCount,
|
|
303
|
+
0
|
|
304
|
+
);
|
|
305
|
+
// Negate: lower is better, so more errors = worse
|
|
306
|
+
return -total;
|
|
307
|
+
} catch {
|
|
308
|
+
return -999;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
default:
|
|
312
|
+
return 0;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function _extractCoverageFromOutput(output: string): number {
|
|
317
|
+
// Parse "All files | XX.XX |" from jest coverage table
|
|
318
|
+
const match = output.match(/All files\s*\|\s*([\d.]+)/);
|
|
319
|
+
return match ? parseFloat(match[1]) : 0;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// ─── TSV Logging ────────────────────────────────────────────────────────────
|
|
323
|
+
|
|
324
|
+
const TSV_HEADER =
|
|
325
|
+
'id\tcommit\tmetric_name\tmetric_value\tstatus\thypothesis\tresearch_source\tduration_s\ttimestamp\n';
|
|
326
|
+
|
|
327
|
+
function _initTsv(tsvPath: string): void {
|
|
328
|
+
if (!fs.existsSync(tsvPath)) {
|
|
329
|
+
fs.writeFileSync(tsvPath, TSV_HEADER, 'utf-8');
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function _appendTsv(tsvPath: string, result: ExperimentResult): void {
|
|
334
|
+
const line = [
|
|
335
|
+
result.id,
|
|
336
|
+
result.commit,
|
|
337
|
+
result.metric_name,
|
|
338
|
+
result.metric_value.toFixed(4),
|
|
339
|
+
result.status,
|
|
340
|
+
result.hypothesis.replace(/\t/g, ' ').replace(/\n/g, ' ').slice(0, 200),
|
|
341
|
+
result.research_source.replace(/\t/g, ' '),
|
|
342
|
+
result.duration_seconds,
|
|
343
|
+
result.timestamp,
|
|
344
|
+
].join('\t');
|
|
345
|
+
fs.appendFileSync(tsvPath, line + '\n', 'utf-8');
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// ─── Research Context ───────────────────────────────────────────────────────
|
|
349
|
+
|
|
350
|
+
function _buildResearchContext(cwd: string, topic: string, iteration: number): string {
|
|
351
|
+
const researchDir = getResearchDir(cwd);
|
|
352
|
+
const parts: string[] = [];
|
|
353
|
+
|
|
354
|
+
// LANDSCAPE.md
|
|
355
|
+
const landscapePath = path.join(researchDir, 'LANDSCAPE.md');
|
|
356
|
+
if (fs.existsSync(landscapePath)) {
|
|
357
|
+
const content = fs.readFileSync(landscapePath, 'utf-8') as string;
|
|
358
|
+
parts.push(`<landscape>\n${content.slice(0, LANDSCAPE_MAX_CHARS)}\n</landscape>`);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// PAPERS.md — citation graph summary
|
|
362
|
+
const papersPath = path.join(researchDir, 'PAPERS.md');
|
|
363
|
+
if (fs.existsSync(papersPath)) {
|
|
364
|
+
const content = fs.readFileSync(papersPath, 'utf-8') as string;
|
|
365
|
+
try {
|
|
366
|
+
const graph = buildCitationGraph(content);
|
|
367
|
+
const unresolved = findUnresolved(graph);
|
|
368
|
+
parts.push(
|
|
369
|
+
`<citation_graph papers="${graph.nodes.length}" edges="${graph.edges.length}" unresolved="${unresolved.length}" />`
|
|
370
|
+
);
|
|
371
|
+
} catch {
|
|
372
|
+
// citation parsing may fail on sparse PAPERS.md
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// KNOWHOW.md — accumulated patterns
|
|
377
|
+
const knowhow = buildKnowledgeInjectionBlock(cwd, String(iteration));
|
|
378
|
+
if (knowhow) {
|
|
379
|
+
parts.push(knowhow);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return parts.length > 0
|
|
383
|
+
? `<research_context topic="${topic}">\n${parts.join('\n\n')}\n</research_context>`
|
|
384
|
+
: '';
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// ─── Experiment Prompt ──────────────────────────────────────────────────────
|
|
388
|
+
|
|
389
|
+
function _buildExperimentPrompt(
|
|
390
|
+
cwd: string,
|
|
391
|
+
topic: string,
|
|
392
|
+
iteration: number,
|
|
393
|
+
baseline: number,
|
|
394
|
+
best: number,
|
|
395
|
+
metric: string,
|
|
396
|
+
history: ExperimentResult[]
|
|
397
|
+
): string {
|
|
398
|
+
const researchContext = _buildResearchContext(cwd, topic, iteration);
|
|
399
|
+
const recentHistory = history
|
|
400
|
+
.slice(-10)
|
|
401
|
+
.map(
|
|
402
|
+
(e) =>
|
|
403
|
+
` ${e.id}. [${e.status}] ${e.metric_name}=${e.metric_value.toFixed(4)} — ${e.hypothesis.slice(0, 80)}`
|
|
404
|
+
)
|
|
405
|
+
.join('\n');
|
|
406
|
+
|
|
407
|
+
return `You are an autonomous research agent running experiment #${iteration} in the autoresearch loop.
|
|
408
|
+
|
|
409
|
+
## Goal
|
|
410
|
+
Improve the codebase metric: **${metric}** (higher is better).
|
|
411
|
+
- Baseline: ${baseline.toFixed(4)}
|
|
412
|
+
- Current best: ${best.toFixed(4)}
|
|
413
|
+
- Topic: ${topic}
|
|
414
|
+
|
|
415
|
+
## Recent Experiment History
|
|
416
|
+
${recentHistory || '(no experiments yet — this is the first)'}
|
|
417
|
+
|
|
418
|
+
${researchContext}
|
|
419
|
+
|
|
420
|
+
## Instructions
|
|
421
|
+
|
|
422
|
+
1. **Hypothesize**: Based on the research context, codebase state, and experiment history, form a specific hypothesis for improvement. Consider:
|
|
423
|
+
- Papers and techniques from LANDSCAPE.md
|
|
424
|
+
- Patterns from KNOWHOW.md that worked in prior phases
|
|
425
|
+
- Gaps identified in the citation graph
|
|
426
|
+
- Ideas that haven't been tried yet (check history)
|
|
427
|
+
|
|
428
|
+
2. **Implement**: Make targeted code changes to test your hypothesis. Keep changes small and focused — one idea per experiment. Modify only what's necessary.
|
|
429
|
+
|
|
430
|
+
3. **Verify**: Run the test suite to make sure nothing is broken: \`npm test\`
|
|
431
|
+
|
|
432
|
+
4. **Report**: Print a single-line summary at the end:
|
|
433
|
+
HYPOTHESIS: <one-line description of what you tried>
|
|
434
|
+
|
|
435
|
+
IMPORTANT:
|
|
436
|
+
- Do NOT ask for confirmation. You are autonomous.
|
|
437
|
+
- Make exactly ONE focused change per experiment.
|
|
438
|
+
- If tests fail, try to fix them. If you can't after 2 attempts, revert all changes.
|
|
439
|
+
- Keep changes simple. A small improvement with clean code beats a large improvement with complex hacks.
|
|
440
|
+
- Do NOT modify test files to make tests pass — improve the actual code.
|
|
441
|
+
- Commit your changes with a descriptive message starting with "autoresearch:".`;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// ─── Core Loop ──────────────────────────────────────────────────────────────
|
|
445
|
+
|
|
446
|
+
async function _runAutoresearchLoop(
|
|
447
|
+
cwd: string,
|
|
448
|
+
options: AutoResearchOptions
|
|
449
|
+
): Promise<AutoResearchState> {
|
|
450
|
+
const { topic, maxExperiments, timeBudget, metric, model, maxTurns, dryRun, scheduler, maxDeepDives } = options;
|
|
451
|
+
|
|
452
|
+
// Load config once for the adaptive tier chain (Spec 4).
|
|
453
|
+
const arConfig: GrdConfig = loadConfig(cwd);
|
|
454
|
+
|
|
455
|
+
const planningDir = getPlanningDir(cwd);
|
|
456
|
+
const tsvPath = path.join(planningDir, 'AUTORESEARCH.tsv');
|
|
457
|
+
const branchName = `autoresearch/${new Date().toISOString().slice(0, 10).replace(/-/g, '')}`;
|
|
458
|
+
|
|
459
|
+
// Create branch
|
|
460
|
+
_log(`Starting autoresearch on topic: ${topic}`);
|
|
461
|
+
_log(
|
|
462
|
+
`Metric: ${metric}, time budget: ${timeBudget > 0 ? `${timeBudget}min` : 'unlimited'}/experiment, max: ${maxExperiments || 'unlimited'}`
|
|
463
|
+
);
|
|
464
|
+
|
|
465
|
+
const branchResult = _execGit(cwd, ['checkout', '-b', branchName]);
|
|
466
|
+
if (branchResult.exitCode !== 0) {
|
|
467
|
+
// Branch creation failed — most likely the branch already exists
|
|
468
|
+
// from a prior same-day run. Try to check out the existing branch
|
|
469
|
+
// instead of silently running on whatever branch is current.
|
|
470
|
+
const checkoutResult = _execGit(cwd, ['checkout', branchName]);
|
|
471
|
+
if (checkoutResult.exitCode !== 0) {
|
|
472
|
+
throw new Error(
|
|
473
|
+
`[autoresearch] failed to create or checkout branch '${branchName}': ` +
|
|
474
|
+
`create exit ${branchResult.exitCode}, checkout exit ${checkoutResult.exitCode}. ` +
|
|
475
|
+
`Please delete the existing branch or run from a clean worktree.`
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
process.stderr.write(`[autoresearch] branch '${branchName}' already exists, reusing\n`);
|
|
479
|
+
}
|
|
480
|
+
_log(`Created branch: ${branchName}`);
|
|
481
|
+
|
|
482
|
+
_initTsv(tsvPath);
|
|
483
|
+
|
|
484
|
+
// Step 1: Collect baseline metric
|
|
485
|
+
_log('Collecting baseline metric...');
|
|
486
|
+
const baseline = _collectMetric(cwd, metric, arConfig.timeouts);
|
|
487
|
+
_log(`Baseline ${metric}: ${baseline.toFixed(4)}`);
|
|
488
|
+
|
|
489
|
+
let best = baseline;
|
|
490
|
+
let deepDivesThisRun = 0;
|
|
491
|
+
const experiments: ExperimentResult[] = [];
|
|
492
|
+
|
|
493
|
+
// Log baseline
|
|
494
|
+
const baselineResult: ExperimentResult = {
|
|
495
|
+
id: 0,
|
|
496
|
+
commit: _execGit(cwd, ['rev-parse', '--short', 'HEAD']).stdout,
|
|
497
|
+
metric_value: baseline,
|
|
498
|
+
metric_name: metric,
|
|
499
|
+
status: 'keep',
|
|
500
|
+
hypothesis: 'baseline',
|
|
501
|
+
research_source: 'initial',
|
|
502
|
+
duration_seconds: 0,
|
|
503
|
+
timestamp: new Date().toISOString(),
|
|
504
|
+
};
|
|
505
|
+
_appendTsv(tsvPath, baselineResult);
|
|
506
|
+
experiments.push(baselineResult);
|
|
507
|
+
|
|
508
|
+
// Step 2: Auto-survey if enabled and no LANDSCAPE.md
|
|
509
|
+
if (options.autoSurvey) {
|
|
510
|
+
const researchDir = getResearchDir(cwd);
|
|
511
|
+
const landscapePath = path.join(researchDir, 'LANDSCAPE.md');
|
|
512
|
+
if (!fs.existsSync(landscapePath)) {
|
|
513
|
+
_log('No LANDSCAPE.md found — running auto-survey...');
|
|
514
|
+
if (!dryRun) {
|
|
515
|
+
const surveyPrompt = `Use the Skill tool to invoke skill "grd:survey" with args "${topic}". Autonomous mode — make all decisions yourself, no questions.`;
|
|
516
|
+
// Resolve the effective model for the survey dispatch (Spec 4 chain).
|
|
517
|
+
// Honour explicit --model flag; otherwise use the adaptive tier.
|
|
518
|
+
const surveyTier = getEffectiveTierForDispatch({
|
|
519
|
+
agentType: 'grd-surveyor',
|
|
520
|
+
prompt: surveyPrompt,
|
|
521
|
+
config: arConfig,
|
|
522
|
+
scheduler: scheduler ?? null,
|
|
523
|
+
schedulerConfig: arConfig.scheduler,
|
|
524
|
+
superpowersConfig: arConfig.superpowers,
|
|
525
|
+
modelProfiles: MODEL_PROFILES,
|
|
526
|
+
});
|
|
527
|
+
const surveyModel: string | undefined = model
|
|
528
|
+
? model
|
|
529
|
+
: resolveModelForAgent(arConfig, 'autoresearch', cwd, {
|
|
530
|
+
effectiveTierOverride: surveyTier,
|
|
531
|
+
});
|
|
532
|
+
await _spawnClaude(cwd, surveyPrompt, {
|
|
533
|
+
// Codex r9 P2: pass 0 explicitly for unlimited (same fix as
|
|
534
|
+
// the experiment spawn path).
|
|
535
|
+
timeout: timeBudget > 0 ? timeBudget * 60 * 1000 : 0,
|
|
536
|
+
model: surveyModel,
|
|
537
|
+
maxTurns,
|
|
538
|
+
scheduler,
|
|
539
|
+
agentType: 'grd-surveyor',
|
|
540
|
+
});
|
|
541
|
+
_log('Auto-survey complete');
|
|
542
|
+
} else {
|
|
543
|
+
_log('(dry-run) Would run survey');
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// Step 3: Experiment loop
|
|
549
|
+
let iteration = 1;
|
|
550
|
+
// Dry-run with --max 0 would spin forever (Infinity); cap at 3 to show a representative sample.
|
|
551
|
+
const maxIter = dryRun && maxExperiments === 0 ? 3 : maxExperiments || Infinity;
|
|
552
|
+
|
|
553
|
+
while (iteration <= maxIter) {
|
|
554
|
+
_log(`\n═══ Experiment #${iteration} ═══`);
|
|
555
|
+
const startTime = Date.now();
|
|
556
|
+
|
|
557
|
+
if (dryRun) {
|
|
558
|
+
_log(`(dry-run) Would run experiment #${iteration}`);
|
|
559
|
+
const dryResult: ExperimentResult = {
|
|
560
|
+
id: iteration,
|
|
561
|
+
commit: 'dry-run',
|
|
562
|
+
metric_value: 0,
|
|
563
|
+
metric_name: metric,
|
|
564
|
+
status: 'discard',
|
|
565
|
+
hypothesis: 'dry-run',
|
|
566
|
+
research_source: 'dry-run',
|
|
567
|
+
duration_seconds: 0,
|
|
568
|
+
timestamp: new Date().toISOString(),
|
|
569
|
+
};
|
|
570
|
+
experiments.push(dryResult);
|
|
571
|
+
iteration++;
|
|
572
|
+
continue;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// Save current HEAD for potential revert
|
|
576
|
+
const headBefore = _execGit(cwd, ['rev-parse', 'HEAD']).stdout;
|
|
577
|
+
|
|
578
|
+
// Build prompt with research context
|
|
579
|
+
const prompt = _buildExperimentPrompt(
|
|
580
|
+
cwd,
|
|
581
|
+
topic,
|
|
582
|
+
iteration,
|
|
583
|
+
baseline,
|
|
584
|
+
best,
|
|
585
|
+
metric,
|
|
586
|
+
experiments
|
|
587
|
+
);
|
|
588
|
+
|
|
589
|
+
// Resolve the effective model for the experiment dispatch (Spec 4 chain).
|
|
590
|
+
// Honour explicit --model flag; otherwise use the adaptive tier.
|
|
591
|
+
const experimentTier = getEffectiveTierForDispatch({
|
|
592
|
+
agentType: 'grd-executor',
|
|
593
|
+
prompt,
|
|
594
|
+
config: arConfig,
|
|
595
|
+
scheduler: scheduler ?? null,
|
|
596
|
+
schedulerConfig: arConfig.scheduler,
|
|
597
|
+
superpowersConfig: arConfig.superpowers,
|
|
598
|
+
modelProfiles: MODEL_PROFILES,
|
|
599
|
+
});
|
|
600
|
+
const experimentModel: string | undefined = model
|
|
601
|
+
? model
|
|
602
|
+
: resolveModelForAgent(arConfig, 'autoresearch', cwd, {
|
|
603
|
+
effectiveTierOverride: experimentTier,
|
|
604
|
+
});
|
|
605
|
+
// Spawn experiment subprocess
|
|
606
|
+
const spawnResult = await _spawnClaude(cwd, prompt, {
|
|
607
|
+
// Codex r7 P2: pass 0 explicitly so scheduler interprets as
|
|
608
|
+
// "unlimited" (vs undefined → scheduler 2hr default).
|
|
609
|
+
timeout: timeBudget > 0 ? timeBudget * 60 * 1000 : 0,
|
|
610
|
+
model: experimentModel,
|
|
611
|
+
maxTurns,
|
|
612
|
+
captureOutput: true,
|
|
613
|
+
scheduler,
|
|
614
|
+
agentType: 'grd-executor',
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
const durationSeconds = Math.round((Date.now() - startTime) / 1000);
|
|
618
|
+
|
|
619
|
+
// Extract hypothesis from output
|
|
620
|
+
const hypothesisMatch = (spawnResult.stdout || '').match(/HYPOTHESIS:\s*(.+)/);
|
|
621
|
+
const hypothesis = hypothesisMatch ? hypothesisMatch[1].trim() : 'unknown';
|
|
622
|
+
|
|
623
|
+
if (spawnResult.timedOut) {
|
|
624
|
+
_log(`Experiment #${iteration} timed out (${timeBudget}min) — reverting`);
|
|
625
|
+
_execGit(cwd, ['reset', '--hard', headBefore]);
|
|
626
|
+
_execGit(cwd, ['clean', '-fd']);
|
|
627
|
+
|
|
628
|
+
const crashResult: ExperimentResult = {
|
|
629
|
+
id: iteration,
|
|
630
|
+
commit: '0000000',
|
|
631
|
+
metric_value: 0,
|
|
632
|
+
metric_name: metric,
|
|
633
|
+
status: 'crash',
|
|
634
|
+
hypothesis: `TIMEOUT: ${hypothesis}`,
|
|
635
|
+
research_source: 'timeout',
|
|
636
|
+
duration_seconds: durationSeconds,
|
|
637
|
+
timestamp: new Date().toISOString(),
|
|
638
|
+
};
|
|
639
|
+
_appendTsv(tsvPath, crashResult);
|
|
640
|
+
experiments.push(crashResult);
|
|
641
|
+
iteration++;
|
|
642
|
+
continue;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
if (spawnResult.exitCode !== 0) {
|
|
646
|
+
_log(`Experiment #${iteration} failed (exit ${spawnResult.exitCode}) — reverting`);
|
|
647
|
+
_execGit(cwd, ['reset', '--hard', headBefore]);
|
|
648
|
+
_execGit(cwd, ['clean', '-fd']);
|
|
649
|
+
|
|
650
|
+
const crashResult: ExperimentResult = {
|
|
651
|
+
id: iteration,
|
|
652
|
+
commit: '0000000',
|
|
653
|
+
metric_value: 0,
|
|
654
|
+
metric_name: metric,
|
|
655
|
+
status: 'crash',
|
|
656
|
+
hypothesis,
|
|
657
|
+
research_source: 'crash',
|
|
658
|
+
duration_seconds: durationSeconds,
|
|
659
|
+
timestamp: new Date().toISOString(),
|
|
660
|
+
};
|
|
661
|
+
_appendTsv(tsvPath, crashResult);
|
|
662
|
+
experiments.push(crashResult);
|
|
663
|
+
iteration++;
|
|
664
|
+
continue;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// Evaluate metric
|
|
668
|
+
_log(`Evaluating ${metric}...`);
|
|
669
|
+
const newMetric = _collectMetric(cwd, metric, arConfig.timeouts);
|
|
670
|
+
const commit = _execGit(cwd, ['rev-parse', '--short', 'HEAD']).stdout;
|
|
671
|
+
const improved = newMetric > best;
|
|
672
|
+
|
|
673
|
+
if (improved) {
|
|
674
|
+
_log(
|
|
675
|
+
`✓ KEEP — ${metric}: ${best.toFixed(4)} → ${newMetric.toFixed(4)} (+${(newMetric - best).toFixed(4)})`
|
|
676
|
+
);
|
|
677
|
+
best = newMetric;
|
|
678
|
+
|
|
679
|
+
const keepResult: ExperimentResult = {
|
|
680
|
+
id: iteration,
|
|
681
|
+
commit,
|
|
682
|
+
metric_value: newMetric,
|
|
683
|
+
metric_name: metric,
|
|
684
|
+
status: 'keep',
|
|
685
|
+
hypothesis,
|
|
686
|
+
research_source: 'experiment',
|
|
687
|
+
duration_seconds: durationSeconds,
|
|
688
|
+
timestamp: new Date().toISOString(),
|
|
689
|
+
};
|
|
690
|
+
_appendTsv(tsvPath, keepResult);
|
|
691
|
+
experiments.push(keepResult);
|
|
692
|
+
|
|
693
|
+
// After a successful keep, run a deep-dive if budget allows
|
|
694
|
+
if (maxDeepDives > 0 && deepDivesThisRun < maxDeepDives) {
|
|
695
|
+
deepDivesThisRun++;
|
|
696
|
+
_log(`Running deep-dive ${deepDivesThisRun}/${maxDeepDives} after successful keep...`);
|
|
697
|
+
const deepDivePrompt = `Use the Skill tool to invoke skill "grd:deep-dive" with args "${topic}". Focus on the most recent successful experiment. Autonomous mode — make all decisions yourself, no questions.`;
|
|
698
|
+
const deepDiveTier = getEffectiveTierForDispatch({
|
|
699
|
+
agentType: 'grd-deep-diver',
|
|
700
|
+
prompt: deepDivePrompt,
|
|
701
|
+
config: arConfig,
|
|
702
|
+
scheduler: scheduler ?? null,
|
|
703
|
+
schedulerConfig: arConfig.scheduler,
|
|
704
|
+
superpowersConfig: arConfig.superpowers,
|
|
705
|
+
modelProfiles: MODEL_PROFILES,
|
|
706
|
+
});
|
|
707
|
+
const deepDiveModel: string | undefined = model
|
|
708
|
+
? model
|
|
709
|
+
: resolveModelForAgent(arConfig, 'autoresearch', cwd, {
|
|
710
|
+
effectiveTierOverride: deepDiveTier,
|
|
711
|
+
});
|
|
712
|
+
await _spawnClaude(cwd, deepDivePrompt, {
|
|
713
|
+
// Codex r9 P2: pass 0 explicitly for unlimited.
|
|
714
|
+
timeout: timeBudget > 0 ? timeBudget * 60 * 1000 : 0,
|
|
715
|
+
model: deepDiveModel,
|
|
716
|
+
maxTurns,
|
|
717
|
+
scheduler,
|
|
718
|
+
agentType: 'grd-deep-diver',
|
|
719
|
+
});
|
|
720
|
+
_log(`Deep-dive ${deepDivesThisRun} complete`);
|
|
721
|
+
}
|
|
722
|
+
} else {
|
|
723
|
+
_log(`✗ DISCARD — ${metric}: ${newMetric.toFixed(4)} (best: ${best.toFixed(4)}) — reverting`);
|
|
724
|
+
_execGit(cwd, ['reset', '--hard', headBefore]);
|
|
725
|
+
_execGit(cwd, ['clean', '-fd']);
|
|
726
|
+
|
|
727
|
+
const discardResult: ExperimentResult = {
|
|
728
|
+
id: iteration,
|
|
729
|
+
commit,
|
|
730
|
+
metric_value: newMetric,
|
|
731
|
+
metric_name: metric,
|
|
732
|
+
status: 'discard',
|
|
733
|
+
hypothesis,
|
|
734
|
+
research_source: 'experiment',
|
|
735
|
+
duration_seconds: durationSeconds,
|
|
736
|
+
timestamp: new Date().toISOString(),
|
|
737
|
+
};
|
|
738
|
+
_appendTsv(tsvPath, discardResult);
|
|
739
|
+
experiments.push(discardResult);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
iteration++;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
_log(`\nAutoresearch complete: ${experiments.length - 1} experiments`);
|
|
746
|
+
_log(
|
|
747
|
+
`Baseline: ${baseline.toFixed(4)} → Best: ${best.toFixed(4)} (Δ${(best - baseline).toFixed(4)})`
|
|
748
|
+
);
|
|
749
|
+
|
|
750
|
+
const kept = experiments.filter((e) => e.status === 'keep').length - 1; // exclude baseline
|
|
751
|
+
const discarded = experiments.filter((e) => e.status === 'discard').length;
|
|
752
|
+
const crashed = experiments.filter((e) => e.status === 'crash').length;
|
|
753
|
+
_log(`Kept: ${kept}, Discarded: ${discarded}, Crashed: ${crashed}`);
|
|
754
|
+
_log(`Results logged to: ${tsvPath}`);
|
|
755
|
+
|
|
756
|
+
return {
|
|
757
|
+
experiments,
|
|
758
|
+
baseline,
|
|
759
|
+
best,
|
|
760
|
+
topic,
|
|
761
|
+
started_at: experiments[0]?.timestamp || new Date().toISOString(),
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// ─── CLI Commands ───────────────────────────────────────────────────────────
|
|
766
|
+
|
|
767
|
+
async function cmdAutoResearch(
|
|
768
|
+
cwd: string,
|
|
769
|
+
args: string[],
|
|
770
|
+
raw: boolean,
|
|
771
|
+
scheduler?: Scheduler | null
|
|
772
|
+
): Promise<void> {
|
|
773
|
+
// Parse flags
|
|
774
|
+
const flagVal = (name: string, fallback?: string): string | undefined => {
|
|
775
|
+
const i = args.indexOf(name);
|
|
776
|
+
return i !== -1 && i + 1 < args.length ? args[i + 1] : fallback;
|
|
777
|
+
};
|
|
778
|
+
|
|
779
|
+
// Find positional topic: first arg not starting with -- and not a flag value
|
|
780
|
+
const flagsWithValues = new Set([
|
|
781
|
+
'--metric',
|
|
782
|
+
'--max',
|
|
783
|
+
'--time-budget',
|
|
784
|
+
'--max-deep-dives',
|
|
785
|
+
'--model',
|
|
786
|
+
'--max-turns',
|
|
787
|
+
]);
|
|
788
|
+
const flagValueIndices = new Set<number>();
|
|
789
|
+
for (let i = 0; i < args.length; i++) {
|
|
790
|
+
if (flagsWithValues.has(args[i]) && i + 1 < args.length) {
|
|
791
|
+
flagValueIndices.add(i + 1);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
const topic = args.find((a, i) => !a.startsWith('--') && !flagValueIndices.has(i));
|
|
795
|
+
if (!topic) {
|
|
796
|
+
error(
|
|
797
|
+
'Topic required. Usage: gd autoresearch <topic> [--metric test_count] [--max N] [--time-budget M]'
|
|
798
|
+
);
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// 0 = unlimited (default); any positive integer caps the experiment count
|
|
803
|
+
const maxExperimentsRaw = flagVal('--max') ? parseInt(flagVal('--max')!, 10) : 0;
|
|
804
|
+
if (isNaN(maxExperimentsRaw) || maxExperimentsRaw < 0) {
|
|
805
|
+
error('--max must be a non-negative integer (0 = unlimited)');
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
const timeBudgetRaw = parseInt(flagVal('--time-budget', '10')!, 10);
|
|
809
|
+
if (isNaN(timeBudgetRaw) || timeBudgetRaw < 0) {
|
|
810
|
+
error('--time-budget must be a non-negative integer');
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
const maxDeepDivesRaw = parseInt(flagVal('--max-deep-dives', '3')!, 10);
|
|
814
|
+
if (isNaN(maxDeepDivesRaw) || maxDeepDivesRaw < 0) {
|
|
815
|
+
error('--max-deep-dives must be a non-negative integer');
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
const maxTurnsRaw = flagVal('--max-turns') ? parseInt(flagVal('--max-turns')!, 10) : undefined;
|
|
819
|
+
if (maxTurnsRaw !== undefined && (isNaN(maxTurnsRaw) || maxTurnsRaw <= 0)) {
|
|
820
|
+
error('--max-turns must be a positive integer');
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
const options: AutoResearchOptions = {
|
|
824
|
+
topic,
|
|
825
|
+
maxExperiments: maxExperimentsRaw, // 0 = unlimited
|
|
826
|
+
timeBudget: timeBudgetRaw,
|
|
827
|
+
metric: flagVal('--metric', 'test_count')!,
|
|
828
|
+
autoSurvey: !args.includes('--no-survey'),
|
|
829
|
+
maxDeepDives: maxDeepDivesRaw,
|
|
830
|
+
model: flagVal('--model'),
|
|
831
|
+
maxTurns: maxTurnsRaw,
|
|
832
|
+
dryRun: args.includes('--dry-run'),
|
|
833
|
+
scheduler,
|
|
834
|
+
};
|
|
835
|
+
|
|
836
|
+
const state = await _runAutoresearchLoop(cwd, options);
|
|
837
|
+
|
|
838
|
+
output(
|
|
839
|
+
{
|
|
840
|
+
topic: state.topic,
|
|
841
|
+
total_experiments: state.experiments.length - 1,
|
|
842
|
+
baseline: state.baseline,
|
|
843
|
+
best: state.best,
|
|
844
|
+
improvement: state.best - state.baseline,
|
|
845
|
+
kept: state.experiments.filter((e) => e.status === 'keep').length - 1,
|
|
846
|
+
discarded: state.experiments.filter((e) => e.status === 'discard').length,
|
|
847
|
+
crashed: state.experiments.filter((e) => e.status === 'crash').length,
|
|
848
|
+
tsv_path: path.join(getPlanningDir(cwd), 'AUTORESEARCH.tsv'),
|
|
849
|
+
},
|
|
850
|
+
raw,
|
|
851
|
+
`AutoResearch: ${state.experiments.length - 1} experiments, baseline=${state.baseline.toFixed(4)} → best=${state.best.toFixed(4)}`
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
function cmdInitAutoResearch(cwd: string, raw: boolean): void {
|
|
856
|
+
const config = loadConfig(cwd);
|
|
857
|
+
const milestone = getMilestoneInfo(cwd);
|
|
858
|
+
const researchDir = getResearchDir(cwd);
|
|
859
|
+
|
|
860
|
+
const hasLandscape = fs.existsSync(path.join(researchDir, 'LANDSCAPE.md'));
|
|
861
|
+
const hasPapers = fs.existsSync(path.join(researchDir, 'PAPERS.md'));
|
|
862
|
+
const hasKnowhow = fs.existsSync(path.join(researchDir, 'KNOWHOW.md'));
|
|
863
|
+
|
|
864
|
+
output(
|
|
865
|
+
{
|
|
866
|
+
milestone_version: milestone.version,
|
|
867
|
+
milestone_name: milestone.name,
|
|
868
|
+
research_dir: path.relative(cwd, researchDir),
|
|
869
|
+
has_landscape: hasLandscape,
|
|
870
|
+
has_papers: hasPapers,
|
|
871
|
+
has_knowhow: hasKnowhow,
|
|
872
|
+
config: {
|
|
873
|
+
model_profile: (config as unknown as Record<string, unknown>).model_profile,
|
|
874
|
+
autonomous_mode: (config as unknown as Record<string, unknown>).autonomous_mode,
|
|
875
|
+
},
|
|
876
|
+
},
|
|
877
|
+
raw,
|
|
878
|
+
`AutoResearch ready: milestone=${milestone.version}, landscape=${hasLandscape}, papers=${hasPapers}, knowhow=${hasKnowhow}`
|
|
879
|
+
);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
module.exports = {
|
|
883
|
+
cmdAutoResearch,
|
|
884
|
+
cmdInitAutoResearch,
|
|
885
|
+
_spawnClaude,
|
|
886
|
+
};
|