@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,686 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GRD Wireup -- HTTP and CLI scenario execution engine
|
|
5
|
+
*
|
|
6
|
+
* Runs generated wireup scenarios against localhost services and CLI commands.
|
|
7
|
+
* Captures results with per-step pass/fail comparison.
|
|
8
|
+
*
|
|
9
|
+
* Uses only Node.js built-ins: fetch (Node 18+) for HTTP, child_process for CLI.
|
|
10
|
+
* No external HTTP library dependencies.
|
|
11
|
+
*
|
|
12
|
+
* @dependencies ./types, child_process (built-in), node:fetch (built-in, Node 18+)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type {
|
|
16
|
+
WireupScenario,
|
|
17
|
+
ScenarioResult,
|
|
18
|
+
StepResult,
|
|
19
|
+
HttpStepResult,
|
|
20
|
+
CliStepResult,
|
|
21
|
+
ExecutionOptions,
|
|
22
|
+
BrowserStep,
|
|
23
|
+
BrowserStepResult,
|
|
24
|
+
BrowserScenarioResult,
|
|
25
|
+
} from './types';
|
|
26
|
+
|
|
27
|
+
const fs = require('fs') as typeof import('fs');
|
|
28
|
+
const path = require('path') as typeof import('path');
|
|
29
|
+
|
|
30
|
+
const _commandCache = new Map<string, { command: string; prependArgs: string[] }>();
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Resolve a CLI command to its local bin equivalent when not on PATH.
|
|
34
|
+
* Falls back to `npx` for package.json bin entries.
|
|
35
|
+
*/
|
|
36
|
+
function _resolveCommand(command: string, cwd: string): { command: string; prependArgs: string[] } {
|
|
37
|
+
const cached = _commandCache.get(command);
|
|
38
|
+
if (cached !== undefined) return cached;
|
|
39
|
+
|
|
40
|
+
const check = spawnSync('which', [command], { encoding: 'utf-8', timeout: 5_000 });
|
|
41
|
+
if (check.status === 0 && check.stdout.trim()) {
|
|
42
|
+
const result = { command, prependArgs: [] as string[] };
|
|
43
|
+
_commandCache.set(command, result);
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const localBin = path.join(cwd, 'bin', `${command}.js`);
|
|
48
|
+
if (fs.existsSync(localBin)) {
|
|
49
|
+
const result = { command: 'node', prependArgs: [localBin] };
|
|
50
|
+
_commandCache.set(command, result);
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const result = { command: 'npx', prependArgs: [command] };
|
|
55
|
+
_commandCache.set(command, result);
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const { spawnSync } = require('child_process') as {
|
|
60
|
+
spawnSync: (
|
|
61
|
+
command: string,
|
|
62
|
+
args: string[],
|
|
63
|
+
options: {
|
|
64
|
+
encoding: 'utf-8';
|
|
65
|
+
timeout: number;
|
|
66
|
+
cwd?: string;
|
|
67
|
+
env?: NodeJS.ProcessEnv;
|
|
68
|
+
}
|
|
69
|
+
) => {
|
|
70
|
+
status: number | null;
|
|
71
|
+
stdout: string;
|
|
72
|
+
stderr: string;
|
|
73
|
+
error?: Error;
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// ─── Default Options ──────────────────────────────────────────────────────────
|
|
78
|
+
|
|
79
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
80
|
+
|
|
81
|
+
function _escapeRegExp(s: string): string {
|
|
82
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ─── Static Analysis Helpers ──────────────────────────────────────────────────
|
|
86
|
+
|
|
87
|
+
const STATIC_SKIP_DIRS: Set<string> = new Set([
|
|
88
|
+
'node_modules', 'dist', 'build', '.next', '.nuxt', '.output',
|
|
89
|
+
'.git', '.worktrees', 'coverage', '.planning',
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
function _collectSourceFiles(dir: string): string[] {
|
|
93
|
+
const results: string[] = [];
|
|
94
|
+
let entries: import('fs').Dirent[];
|
|
95
|
+
try {
|
|
96
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
97
|
+
} catch {
|
|
98
|
+
return results; // Permission error or missing dir
|
|
99
|
+
}
|
|
100
|
+
for (const entry of entries) {
|
|
101
|
+
const full: string = path.join(dir, entry.name);
|
|
102
|
+
if (entry.isDirectory()) {
|
|
103
|
+
if (!STATIC_SKIP_DIRS.has(entry.name)) {
|
|
104
|
+
results.push(..._collectSourceFiles(full));
|
|
105
|
+
}
|
|
106
|
+
} else if (/\.(ts|js|tsx|jsx|vue|svelte)$/.test(entry.name)) {
|
|
107
|
+
results.push(full);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return results;
|
|
111
|
+
}
|
|
112
|
+
const DEFAULT_BASE_URL = 'http://localhost:3000';
|
|
113
|
+
|
|
114
|
+
// ─── Shared Helpers ──────────────────────────────────────────────────────────
|
|
115
|
+
|
|
116
|
+
function parseExpectedOutcome(step: WireupScenario['steps'][number]): Record<string, unknown> {
|
|
117
|
+
if (typeof step.expected_outcome === 'string') {
|
|
118
|
+
try {
|
|
119
|
+
const parsed: unknown = JSON.parse(step.expected_outcome);
|
|
120
|
+
if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
121
|
+
return parsed as Record<string, unknown>;
|
|
122
|
+
}
|
|
123
|
+
} catch {
|
|
124
|
+
// Not a JSON string — treat as a plain description with no structured expectations
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return {};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ─── HTTP Step Execution ──────────────────────────────────────────────────────
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Execute an HTTP scenario step using Node.js built-in fetch.
|
|
134
|
+
*
|
|
135
|
+
* Captures status code, response headers, and body text.
|
|
136
|
+
* Compares against expected_outcome fields:
|
|
137
|
+
* - status: number match
|
|
138
|
+
* - body_contains: substring match
|
|
139
|
+
* - headers: key-value match (case-insensitive header names)
|
|
140
|
+
*
|
|
141
|
+
* Network errors (ECONNREFUSED, timeout) produce a failed result with
|
|
142
|
+
* an error message — they do NOT throw.
|
|
143
|
+
*/
|
|
144
|
+
async function executeHttpStep(
|
|
145
|
+
stepIndex: number,
|
|
146
|
+
step: WireupScenario['steps'][number],
|
|
147
|
+
options: ExecutionOptions
|
|
148
|
+
): Promise<HttpStepResult> {
|
|
149
|
+
const startTime = Date.now();
|
|
150
|
+
const baseUrl = options.base_url ?? DEFAULT_BASE_URL;
|
|
151
|
+
const timeoutMs = options.timeout_ms ?? DEFAULT_TIMEOUT_MS;
|
|
152
|
+
|
|
153
|
+
const params = step.parameters as Record<string, unknown>;
|
|
154
|
+
const method = typeof params['method'] === 'string' ? params['method'] : 'GET';
|
|
155
|
+
const endpoint = typeof params['endpoint'] === 'string' ? params['endpoint'] : '/';
|
|
156
|
+
const normalizedEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
|
|
157
|
+
const url = endpoint.startsWith('http') ? endpoint : `${baseUrl}${normalizedEndpoint}`;
|
|
158
|
+
|
|
159
|
+
const expectedOutcome = parseExpectedOutcome(step);
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
const controller = new AbortController();
|
|
163
|
+
const timerId = setTimeout(() => controller.abort(), timeoutMs);
|
|
164
|
+
|
|
165
|
+
let response: Response;
|
|
166
|
+
try {
|
|
167
|
+
response = await fetch(url, {
|
|
168
|
+
method,
|
|
169
|
+
signal: controller.signal,
|
|
170
|
+
headers:
|
|
171
|
+
params['headers'] !== undefined && typeof params['headers'] === 'object'
|
|
172
|
+
? (params['headers'] as Record<string, string>)
|
|
173
|
+
: undefined,
|
|
174
|
+
body:
|
|
175
|
+
params['body'] !== undefined
|
|
176
|
+
? JSON.stringify(params['body'])
|
|
177
|
+
: undefined,
|
|
178
|
+
});
|
|
179
|
+
} finally {
|
|
180
|
+
clearTimeout(timerId);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const body = await response.text();
|
|
184
|
+
const statusCode = response.status;
|
|
185
|
+
|
|
186
|
+
// Convert Headers to plain object
|
|
187
|
+
const headers: Record<string, string> = {};
|
|
188
|
+
response.headers.forEach((value, key) => {
|
|
189
|
+
headers[key.toLowerCase()] = value;
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Evaluate pass/fail
|
|
193
|
+
const checks: boolean[] = [];
|
|
194
|
+
|
|
195
|
+
if (typeof expectedOutcome['status'] === 'number') {
|
|
196
|
+
checks.push(statusCode === expectedOutcome['status']);
|
|
197
|
+
}
|
|
198
|
+
if (typeof expectedOutcome['body_contains'] === 'string') {
|
|
199
|
+
checks.push(body.includes(expectedOutcome['body_contains']));
|
|
200
|
+
}
|
|
201
|
+
if (
|
|
202
|
+
expectedOutcome['headers'] !== null &&
|
|
203
|
+
typeof expectedOutcome['headers'] === 'object' &&
|
|
204
|
+
!Array.isArray(expectedOutcome['headers'])
|
|
205
|
+
) {
|
|
206
|
+
const expectedHeaders = expectedOutcome['headers'] as Record<string, string>;
|
|
207
|
+
for (const [key, val] of Object.entries(expectedHeaders)) {
|
|
208
|
+
checks.push(headers[key.toLowerCase()] === val);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const passed = checks.length === 0 ? statusCode >= 200 && statusCode < 300 : checks.every(Boolean);
|
|
213
|
+
const durationMs = Date.now() - startTime;
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
step_index: stepIndex,
|
|
217
|
+
step_type: 'http',
|
|
218
|
+
passed,
|
|
219
|
+
expected: expectedOutcome,
|
|
220
|
+
actual: { status_code: statusCode, body: body.slice(0, 500) },
|
|
221
|
+
duration_ms: durationMs,
|
|
222
|
+
status_code: statusCode,
|
|
223
|
+
headers,
|
|
224
|
+
body,
|
|
225
|
+
};
|
|
226
|
+
} catch (err: unknown) {
|
|
227
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
228
|
+
const durationMs = Date.now() - startTime;
|
|
229
|
+
return {
|
|
230
|
+
step_index: stepIndex,
|
|
231
|
+
step_type: 'http',
|
|
232
|
+
passed: false,
|
|
233
|
+
expected: expectedOutcome,
|
|
234
|
+
actual: null,
|
|
235
|
+
error: errorMessage,
|
|
236
|
+
duration_ms: durationMs,
|
|
237
|
+
status_code: 0,
|
|
238
|
+
headers: {},
|
|
239
|
+
body: '',
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// ─── CLI Step Execution ───────────────────────────────────────────────────────
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Execute a CLI scenario step using child_process.spawnSync.
|
|
248
|
+
*
|
|
249
|
+
* Captures stdout, stderr, and exit code.
|
|
250
|
+
* Compares against expected_outcome fields:
|
|
251
|
+
* - exit_code: exact match
|
|
252
|
+
* - stdout_contains: substring match
|
|
253
|
+
* - stderr_contains: substring match
|
|
254
|
+
*
|
|
255
|
+
* Spawn errors produce a failed result with an error message — they do NOT throw.
|
|
256
|
+
*
|
|
257
|
+
* NOTE: Uses spawnSync (not exec) to avoid shell injection. The command and args
|
|
258
|
+
* are passed directly to the OS without shell interpretation.
|
|
259
|
+
*/
|
|
260
|
+
async function executeCliStep(
|
|
261
|
+
stepIndex: number,
|
|
262
|
+
step: WireupScenario['steps'][number],
|
|
263
|
+
options: ExecutionOptions,
|
|
264
|
+
cwd: string
|
|
265
|
+
): Promise<CliStepResult> {
|
|
266
|
+
const startTime = Date.now();
|
|
267
|
+
const timeoutMs = options.timeout_ms ?? DEFAULT_TIMEOUT_MS;
|
|
268
|
+
|
|
269
|
+
const params = step.parameters as Record<string, unknown>;
|
|
270
|
+
const rawCommand = typeof params['command'] === 'string' ? params['command'] : 'echo';
|
|
271
|
+
const rawArgs: string[] = Array.isArray(params['args'])
|
|
272
|
+
? (params['args'] as unknown[]).map(String)
|
|
273
|
+
: [];
|
|
274
|
+
|
|
275
|
+
// Resolve command to local bin if not on PATH
|
|
276
|
+
const resolved = _resolveCommand(rawCommand, cwd);
|
|
277
|
+
const command = resolved.command;
|
|
278
|
+
const args = [...resolved.prependArgs, ...rawArgs];
|
|
279
|
+
|
|
280
|
+
const expectedOutcome = parseExpectedOutcome(step);
|
|
281
|
+
|
|
282
|
+
try {
|
|
283
|
+
const result = spawnSync(command, args, {
|
|
284
|
+
encoding: 'utf-8',
|
|
285
|
+
timeout: timeoutMs,
|
|
286
|
+
cwd,
|
|
287
|
+
env: process.env,
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
if (result.error) {
|
|
291
|
+
const durationMs = Date.now() - startTime;
|
|
292
|
+
return {
|
|
293
|
+
step_index: stepIndex,
|
|
294
|
+
step_type: 'cli',
|
|
295
|
+
passed: false,
|
|
296
|
+
expected: expectedOutcome,
|
|
297
|
+
actual: null,
|
|
298
|
+
error: result.error.message,
|
|
299
|
+
duration_ms: durationMs,
|
|
300
|
+
exit_code: -1,
|
|
301
|
+
stdout: '',
|
|
302
|
+
stderr: '',
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const exitCode = result.status ?? -1;
|
|
307
|
+
const stdout = result.stdout ?? '';
|
|
308
|
+
const stderr = result.stderr ?? '';
|
|
309
|
+
|
|
310
|
+
// Evaluate pass/fail
|
|
311
|
+
const checks: boolean[] = [];
|
|
312
|
+
|
|
313
|
+
if (typeof expectedOutcome['exit_code'] === 'number') {
|
|
314
|
+
checks.push(exitCode === expectedOutcome['exit_code']);
|
|
315
|
+
}
|
|
316
|
+
if (typeof expectedOutcome['stdout_contains'] === 'string') {
|
|
317
|
+
checks.push(stdout.includes(expectedOutcome['stdout_contains']));
|
|
318
|
+
}
|
|
319
|
+
if (typeof expectedOutcome['stderr_contains'] === 'string') {
|
|
320
|
+
checks.push(stderr.includes(expectedOutcome['stderr_contains']));
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Default: exit code 0 means pass if no explicit expectations
|
|
324
|
+
const passed = checks.length === 0 ? exitCode === 0 : checks.every(Boolean);
|
|
325
|
+
const durationMs = Date.now() - startTime;
|
|
326
|
+
|
|
327
|
+
return {
|
|
328
|
+
step_index: stepIndex,
|
|
329
|
+
step_type: 'cli',
|
|
330
|
+
passed,
|
|
331
|
+
expected: expectedOutcome,
|
|
332
|
+
actual: { exit_code: exitCode, stdout: stdout.slice(0, 500), stderr: stderr.slice(0, 200) },
|
|
333
|
+
duration_ms: durationMs,
|
|
334
|
+
exit_code: exitCode,
|
|
335
|
+
stdout,
|
|
336
|
+
stderr,
|
|
337
|
+
};
|
|
338
|
+
} catch (err: unknown) {
|
|
339
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
340
|
+
const durationMs = Date.now() - startTime;
|
|
341
|
+
return {
|
|
342
|
+
step_index: stepIndex,
|
|
343
|
+
step_type: 'cli',
|
|
344
|
+
passed: false,
|
|
345
|
+
expected: expectedOutcome,
|
|
346
|
+
actual: null,
|
|
347
|
+
error: errorMessage,
|
|
348
|
+
duration_ms: durationMs,
|
|
349
|
+
exit_code: -1,
|
|
350
|
+
stdout: '',
|
|
351
|
+
stderr: '',
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// ─── Static Analysis Step Execution ──────────────────────────────────────────
|
|
357
|
+
|
|
358
|
+
function executeStaticStep(
|
|
359
|
+
stepIndex: number,
|
|
360
|
+
step: WireupScenario['steps'][number],
|
|
361
|
+
cwd: string
|
|
362
|
+
): StepResult {
|
|
363
|
+
const startTime = Date.now();
|
|
364
|
+
try {
|
|
365
|
+
const params = step.parameters as Record<string, unknown>;
|
|
366
|
+
const check = typeof params['check'] === 'string' ? params['check'] : '';
|
|
367
|
+
const filePath = typeof params['filePath'] === 'string' ? params['filePath'] : '';
|
|
368
|
+
const exportName = typeof params['exportName'] === 'string' ? params['exportName'] : '';
|
|
369
|
+
const absPath: string = path.join(cwd, filePath);
|
|
370
|
+
const escaped: string = _escapeRegExp(exportName);
|
|
371
|
+
|
|
372
|
+
if (check === 'export_exists') {
|
|
373
|
+
let content: string;
|
|
374
|
+
try {
|
|
375
|
+
content = fs.readFileSync(absPath, 'utf-8');
|
|
376
|
+
} catch (readErr: unknown) {
|
|
377
|
+
const code = (readErr as NodeJS.ErrnoException).code;
|
|
378
|
+
const detail: string = code === 'ENOENT'
|
|
379
|
+
? `File not found: ${filePath}`
|
|
380
|
+
: `Cannot read ${filePath}: ${code || (readErr instanceof Error ? readErr.message : String(readErr))}`;
|
|
381
|
+
return {
|
|
382
|
+
step_index: stepIndex, step_type: 'static', passed: false,
|
|
383
|
+
expected: step.expected_outcome, actual: detail,
|
|
384
|
+
duration_ms: Date.now() - startTime,
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
const exportPatterns: RegExp[] = [
|
|
388
|
+
new RegExp(`export\\s+(?:async\\s+)?(?:function|const|class|let|var)\\s+${escaped}\\b`),
|
|
389
|
+
new RegExp(`export\\s+default\\s+(?:function|class)\\s+${escaped}\\b`),
|
|
390
|
+
new RegExp(`export\\s*\\{[^}]*\\b${escaped}\\b`),
|
|
391
|
+
new RegExp(`exports\\.${escaped}\\s*=`),
|
|
392
|
+
new RegExp(`module\\.exports\\s*=\\s*\\{[^}]*\\b${escaped}\\b`),
|
|
393
|
+
];
|
|
394
|
+
const found: boolean = exportPatterns.some((p) => p.test(content));
|
|
395
|
+
return {
|
|
396
|
+
step_index: stepIndex, step_type: 'static', passed: found,
|
|
397
|
+
expected: step.expected_outcome,
|
|
398
|
+
actual: found ? `Export '${exportName}' found in ${filePath}` : `Export '${exportName}' not found in ${filePath}`,
|
|
399
|
+
duration_ms: Date.now() - startTime,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (check === 'import_graph_connected') {
|
|
404
|
+
const allFiles: string[] = _collectSourceFiles(cwd);
|
|
405
|
+
let referenced: boolean = false;
|
|
406
|
+
const namePattern: RegExp = new RegExp(`\\b${escaped}\\b`);
|
|
407
|
+
for (const file of allFiles) {
|
|
408
|
+
if (path.resolve(file) === path.resolve(absPath)) continue;
|
|
409
|
+
try {
|
|
410
|
+
const content: string = fs.readFileSync(file, 'utf-8');
|
|
411
|
+
if (namePattern.test(content)) { referenced = true; break; }
|
|
412
|
+
} catch (readErr: unknown) {
|
|
413
|
+
const code = (readErr as NodeJS.ErrnoException).code;
|
|
414
|
+
if (code !== 'ENOENT' && code !== 'EACCES') throw readErr;
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
return {
|
|
419
|
+
step_index: stepIndex, step_type: 'static', passed: referenced,
|
|
420
|
+
expected: step.expected_outcome,
|
|
421
|
+
actual: referenced
|
|
422
|
+
? `Export '${exportName}' is referenced in the project`
|
|
423
|
+
: `Export '${exportName}' has no references outside ${filePath}`,
|
|
424
|
+
duration_ms: Date.now() - startTime,
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
return {
|
|
429
|
+
step_index: stepIndex, step_type: 'static', passed: false,
|
|
430
|
+
expected: step.expected_outcome, actual: `Unknown static check: ${check}`,
|
|
431
|
+
duration_ms: Date.now() - startTime,
|
|
432
|
+
};
|
|
433
|
+
} catch (err: unknown) {
|
|
434
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
435
|
+
return {
|
|
436
|
+
step_index: stepIndex, step_type: 'static', passed: false,
|
|
437
|
+
expected: step.expected_outcome, actual: `Unexpected error: ${errorMessage}`,
|
|
438
|
+
duration_ms: Date.now() - startTime,
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// ─── Scenario Execution ───────────────────────────────────────────────────────
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Probe the base URL to check if a local server is running.
|
|
447
|
+
* Returns true if a TCP connection succeeds, false otherwise.
|
|
448
|
+
*/
|
|
449
|
+
async function _isServerReachable(baseUrl: string): Promise<boolean> {
|
|
450
|
+
try {
|
|
451
|
+
const url = new URL(baseUrl);
|
|
452
|
+
const net = require('net') as typeof import('net');
|
|
453
|
+
return new Promise<boolean>((resolve) => {
|
|
454
|
+
const socket = net.createConnection(
|
|
455
|
+
{ host: url.hostname, port: Number(url.port) || 80, timeout: 1000 },
|
|
456
|
+
() => { socket.destroy(); resolve(true); }
|
|
457
|
+
);
|
|
458
|
+
socket.on('error', () => { resolve(false); });
|
|
459
|
+
socket.on('timeout', () => { socket.destroy(); resolve(false); });
|
|
460
|
+
});
|
|
461
|
+
} catch {
|
|
462
|
+
return false;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Execute a list of wireup scenarios sequentially against localhost services.
|
|
468
|
+
*
|
|
469
|
+
* Scenarios are executed one-at-a-time (not parallel) to avoid overwhelming
|
|
470
|
+
* localhost services under test.
|
|
471
|
+
*
|
|
472
|
+
* Step dispatch:
|
|
473
|
+
* - 'http' -> executeHttpStep (skipped if no server is reachable)
|
|
474
|
+
* - 'cli' -> executeCliStep
|
|
475
|
+
* - 'static' -> executeStaticStep
|
|
476
|
+
* - 'browser', 'assert' -> skipped (Phase 80); marked as passed=true with a note
|
|
477
|
+
*
|
|
478
|
+
* @param cwd - Absolute path to the project root (used as working directory for CLI steps)
|
|
479
|
+
* @param scenarios - Array of WireupScenario objects from generateScenarios()
|
|
480
|
+
* @param options - Optional execution configuration (timeout, base_url)
|
|
481
|
+
* @returns Array of ScenarioResult objects with per-step pass/fail
|
|
482
|
+
*/
|
|
483
|
+
async function executeScenarios(
|
|
484
|
+
cwd: string,
|
|
485
|
+
scenarios: WireupScenario[],
|
|
486
|
+
options: ExecutionOptions = {}
|
|
487
|
+
): Promise<ScenarioResult[]> {
|
|
488
|
+
const results: ScenarioResult[] = [];
|
|
489
|
+
|
|
490
|
+
// Check if any scenario needs HTTP steps — if so, probe the server once
|
|
491
|
+
const hasHttpSteps: boolean = scenarios.some((s) =>
|
|
492
|
+
s.steps.some((step) => step.step_type === 'http')
|
|
493
|
+
);
|
|
494
|
+
const baseUrl: string = options.base_url || DEFAULT_BASE_URL;
|
|
495
|
+
const serverReachable: boolean = hasHttpSteps ? await _isServerReachable(baseUrl) : false;
|
|
496
|
+
|
|
497
|
+
for (const scenario of scenarios) {
|
|
498
|
+
const scenarioStart = Date.now();
|
|
499
|
+
const stepResults: StepResult[] = [];
|
|
500
|
+
|
|
501
|
+
for (let i = 0; i < scenario.steps.length; i++) {
|
|
502
|
+
const step = scenario.steps[i];
|
|
503
|
+
|
|
504
|
+
if (step.step_type === 'http') {
|
|
505
|
+
if (!serverReachable) {
|
|
506
|
+
// Skip HTTP steps on non-webapp projects — no server running
|
|
507
|
+
stepResults.push({
|
|
508
|
+
step_index: i,
|
|
509
|
+
step_type: 'http' as const,
|
|
510
|
+
passed: true,
|
|
511
|
+
expected: step.expected_outcome,
|
|
512
|
+
actual: `skipped (no server at ${baseUrl})`,
|
|
513
|
+
duration_ms: 0,
|
|
514
|
+
status_code: 0,
|
|
515
|
+
headers: {},
|
|
516
|
+
body: '',
|
|
517
|
+
} as HttpStepResult);
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
const result = await executeHttpStep(i, step, options);
|
|
521
|
+
stepResults.push(result);
|
|
522
|
+
} else if (step.step_type === 'cli') {
|
|
523
|
+
const result = await executeCliStep(i, step, options, cwd);
|
|
524
|
+
stepResults.push(result);
|
|
525
|
+
} else if (step.step_type === 'static') {
|
|
526
|
+
const result = executeStaticStep(i, step, cwd);
|
|
527
|
+
stepResults.push(result);
|
|
528
|
+
} else {
|
|
529
|
+
// 'browser' and 'assert' are Phase 80 — skip and mark as passed
|
|
530
|
+
const skippedResult: StepResult = {
|
|
531
|
+
step_index: i,
|
|
532
|
+
step_type: 'cli', // Use cli as the base type for skipped steps
|
|
533
|
+
passed: true,
|
|
534
|
+
expected: step.expected_outcome,
|
|
535
|
+
actual: `skipped (${step.step_type} steps handled in Phase 80)`,
|
|
536
|
+
duration_ms: 0,
|
|
537
|
+
};
|
|
538
|
+
stepResults.push(skippedResult);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
const overallPassed = stepResults.every((r) => r.passed);
|
|
543
|
+
const scenarioDuration = Date.now() - scenarioStart;
|
|
544
|
+
|
|
545
|
+
results.push({
|
|
546
|
+
scenario_id: scenario.feature.functionName,
|
|
547
|
+
feature_id: scenario.feature.functionName,
|
|
548
|
+
step_results: stepResults,
|
|
549
|
+
overall_passed: overallPassed,
|
|
550
|
+
duration_ms: scenarioDuration,
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
return results;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// ─── Browser Scenario Execution ───────────────────────────────────────────────
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Convert browser steps to human-readable manual testing instructions.
|
|
561
|
+
*
|
|
562
|
+
* Each step is rendered as a numbered instruction for a manual tester.
|
|
563
|
+
* Used when Playwright MCP is unavailable to provide fallback guidance.
|
|
564
|
+
*
|
|
565
|
+
* @param steps - Array of BrowserStep objects from the scenario
|
|
566
|
+
* @returns Array of numbered human-readable manual testing instructions
|
|
567
|
+
*/
|
|
568
|
+
function generateManualSteps(steps: BrowserStep[]): string[] {
|
|
569
|
+
return steps.map((step, i) => {
|
|
570
|
+
const n = i + 1;
|
|
571
|
+
switch (step.action) {
|
|
572
|
+
case 'navigate':
|
|
573
|
+
return `${n}. Open browser and navigate to ${step.url ?? '<url>'}`;
|
|
574
|
+
case 'fill':
|
|
575
|
+
return `${n}. Enter "${step.value ?? '<value>'}" in the field matching selector "${step.selector ?? '<selector>'}"`;
|
|
576
|
+
case 'click':
|
|
577
|
+
return `${n}. Click on the element matching selector "${step.selector ?? '<selector>'}"`;
|
|
578
|
+
case 'snapshot':
|
|
579
|
+
return `${n}. Take a visual snapshot of the current page and verify its appearance`;
|
|
580
|
+
case 'evaluate':
|
|
581
|
+
return `${n}. Execute in browser console: ${step.script ?? '<script>'} and verify the result`;
|
|
582
|
+
default:
|
|
583
|
+
return `${n}. Perform ${step.action} action`;
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* Execute a browser scenario using Playwright MCP tools (when available),
|
|
590
|
+
* or return a structured skip result with manual testing guidance (when unavailable).
|
|
591
|
+
*
|
|
592
|
+
* When playwright_available is false:
|
|
593
|
+
* - Returns status: 'skipped' with skip_reason and manual_steps
|
|
594
|
+
* - No browser interaction is attempted
|
|
595
|
+
*
|
|
596
|
+
* When playwright_available is true:
|
|
597
|
+
* - Iterates through steps and builds structured MCP tool call payloads
|
|
598
|
+
* - NOTE: Actual MCP tool invocation is delegated to the calling wireup agent context.
|
|
599
|
+
* This function produces the step execution plan; the wireup orchestrator invokes the tools.
|
|
600
|
+
* - Returns BrowserScenarioResult with per-step results
|
|
601
|
+
*
|
|
602
|
+
* @param _cwd - Absolute path to project root (reserved for future use / auto-detection)
|
|
603
|
+
* @param scenario - Browser scenario definition with steps array
|
|
604
|
+
* @param playwrightAvailable - Whether Playwright MCP tools are available in the current agent context
|
|
605
|
+
* @returns BrowserScenarioResult with status, steps, and any console errors captured
|
|
606
|
+
*/
|
|
607
|
+
function executeBrowserScenario(
|
|
608
|
+
_cwd: string,
|
|
609
|
+
scenario: { scenario_id: string; feature: string; steps: BrowserStep[] },
|
|
610
|
+
playwrightAvailable: boolean
|
|
611
|
+
): BrowserScenarioResult {
|
|
612
|
+
// Guard: skip gracefully when Playwright MCP is not available
|
|
613
|
+
if (!playwrightAvailable) {
|
|
614
|
+
return {
|
|
615
|
+
scenario_id: scenario.scenario_id,
|
|
616
|
+
feature: scenario.feature,
|
|
617
|
+
status: 'skipped',
|
|
618
|
+
skip_reason:
|
|
619
|
+
'Playwright MCP tools not available. Install @anthropic/mcp-playwright or configure playwright.enabled in .planning/config.json',
|
|
620
|
+
manual_steps: generateManualSteps(scenario.steps),
|
|
621
|
+
steps: scenario.steps.map((step) => ({
|
|
622
|
+
action: step.action,
|
|
623
|
+
status: 'skipped' as const,
|
|
624
|
+
})),
|
|
625
|
+
console_errors: [],
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// Build step execution plan (actual MCP calls delegated to orchestrator/agent context)
|
|
630
|
+
const stepResults: BrowserStepResult[] = [];
|
|
631
|
+
const consoleErrors: string[] = [];
|
|
632
|
+
|
|
633
|
+
for (const step of scenario.steps) {
|
|
634
|
+
// Construct the Playwright MCP tool call payload for this step
|
|
635
|
+
let toolPayload: { tool: string; params: Record<string, unknown> };
|
|
636
|
+
switch (step.action) {
|
|
637
|
+
case 'navigate':
|
|
638
|
+
toolPayload = { tool: 'browser_navigate', params: { url: step.url ?? '' } };
|
|
639
|
+
break;
|
|
640
|
+
case 'fill':
|
|
641
|
+
toolPayload = {
|
|
642
|
+
tool: 'browser_fill_form',
|
|
643
|
+
params: { selector: step.selector ?? '', value: step.value ?? '' },
|
|
644
|
+
};
|
|
645
|
+
break;
|
|
646
|
+
case 'click':
|
|
647
|
+
toolPayload = { tool: 'browser_click', params: { selector: step.selector ?? '' } };
|
|
648
|
+
break;
|
|
649
|
+
case 'snapshot':
|
|
650
|
+
toolPayload = { tool: 'browser_snapshot', params: {} };
|
|
651
|
+
break;
|
|
652
|
+
case 'evaluate':
|
|
653
|
+
toolPayload = { tool: 'browser_evaluate', params: { script: step.script ?? '' } };
|
|
654
|
+
break;
|
|
655
|
+
default:
|
|
656
|
+
toolPayload = { tool: 'browser_snapshot', params: {} };
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// Record the planned step with tool payload — actual invocation is delegated to the orchestrator
|
|
660
|
+
stepResults.push({
|
|
661
|
+
action: step.action,
|
|
662
|
+
status: 'skipped',
|
|
663
|
+
tool_payload: toolPayload,
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
return {
|
|
668
|
+
scenario_id: scenario.scenario_id,
|
|
669
|
+
feature: scenario.feature,
|
|
670
|
+
status: 'skipped',
|
|
671
|
+
skip_reason: 'Execution delegated to wireup orchestrator agent context — tool payloads prepared but not yet invoked',
|
|
672
|
+
steps: stepResults,
|
|
673
|
+
console_errors: consoleErrors,
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// ─── Exports ──────────────────────────────────────────────────────────────────
|
|
678
|
+
|
|
679
|
+
module.exports = {
|
|
680
|
+
executeScenarios,
|
|
681
|
+
executeHttpStep,
|
|
682
|
+
executeCliStep,
|
|
683
|
+
executeStaticStep,
|
|
684
|
+
executeBrowserScenario,
|
|
685
|
+
generateManualSteps,
|
|
686
|
+
};
|