@yasserkhanorg/impact-gate 2.0.0
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/LICENSE +168 -0
- package/README.md +520 -0
- package/dist/adapters/cypress.d.ts +10 -0
- package/dist/adapters/cypress.d.ts.map +1 -0
- package/dist/adapters/cypress.js +86 -0
- package/dist/adapters/framework_adapter.d.ts +41 -0
- package/dist/adapters/framework_adapter.d.ts.map +1 -0
- package/dist/adapters/framework_adapter.js +152 -0
- package/dist/adapters/playwright.d.ts +10 -0
- package/dist/adapters/playwright.d.ts.map +1 -0
- package/dist/adapters/playwright.js +86 -0
- package/dist/adapters/pytest.d.ts +10 -0
- package/dist/adapters/pytest.d.ts.map +1 -0
- package/dist/adapters/pytest.js +96 -0
- package/dist/adapters/supertest.d.ts +12 -0
- package/dist/adapters/supertest.d.ts.map +1 -0
- package/dist/adapters/supertest.js +85 -0
- package/dist/agent/api_catalog.d.ts +11 -0
- package/dist/agent/api_catalog.d.ts.map +1 -0
- package/dist/agent/api_catalog.js +210 -0
- package/dist/agent/config.d.ts +193 -0
- package/dist/agent/config.d.ts.map +1 -0
- package/dist/agent/config.js +875 -0
- package/dist/agent/feedback.d.ts +91 -0
- package/dist/agent/feedback.d.ts.map +1 -0
- package/dist/agent/feedback.js +323 -0
- package/dist/agent/git.d.ts +19 -0
- package/dist/agent/git.d.ts.map +1 -0
- package/dist/agent/git.js +257 -0
- package/dist/agent/handoff.d.ts +22 -0
- package/dist/agent/handoff.d.ts.map +1 -0
- package/dist/agent/handoff.js +180 -0
- package/dist/agent/llm_agents_flow.d.ts +15 -0
- package/dist/agent/llm_agents_flow.d.ts.map +1 -0
- package/dist/agent/llm_agents_flow.js +434 -0
- package/dist/agent/native_flow.d.ts +6 -0
- package/dist/agent/native_flow.d.ts.map +1 -0
- package/dist/agent/native_flow.js +179 -0
- package/dist/agent/pipeline.d.ts +7 -0
- package/dist/agent/pipeline.d.ts.map +1 -0
- package/dist/agent/pipeline.js +260 -0
- package/dist/agent/pipeline_types.d.ts +54 -0
- package/dist/agent/pipeline_types.d.ts.map +1 -0
- package/dist/agent/pipeline_types.js +4 -0
- package/dist/agent/pipeline_utils.d.ts +12 -0
- package/dist/agent/pipeline_utils.d.ts.map +1 -0
- package/dist/agent/pipeline_utils.js +156 -0
- package/dist/agent/plan.d.ts +170 -0
- package/dist/agent/plan.d.ts.map +1 -0
- package/dist/agent/plan.js +86 -0
- package/dist/agent/playwright_report.d.ts +8 -0
- package/dist/agent/playwright_report.d.ts.map +1 -0
- package/dist/agent/playwright_report.js +126 -0
- package/dist/agent/process_runner.d.ts +10 -0
- package/dist/agent/process_runner.d.ts.map +1 -0
- package/dist/agent/process_runner.js +92 -0
- package/dist/agent/spec_generator.d.ts +5 -0
- package/dist/agent/spec_generator.d.ts.map +1 -0
- package/dist/agent/spec_generator.js +253 -0
- package/dist/agent/test_path.d.ts +2 -0
- package/dist/agent/test_path.d.ts.map +1 -0
- package/dist/agent/test_path.js +23 -0
- package/dist/agent/traceability_capture.d.ts +18 -0
- package/dist/agent/traceability_capture.d.ts.map +1 -0
- package/dist/agent/traceability_capture.js +313 -0
- package/dist/agent/traceability_ingest.d.ts +21 -0
- package/dist/agent/traceability_ingest.d.ts.map +1 -0
- package/dist/agent/traceability_ingest.js +237 -0
- package/dist/agent/types.d.ts +42 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +4 -0
- package/dist/agent/utils.d.ts +13 -0
- package/dist/agent/utils.d.ts.map +1 -0
- package/dist/agent/utils.js +152 -0
- package/dist/agent/validation_runner.d.ts +5 -0
- package/dist/agent/validation_runner.d.ts.map +1 -0
- package/dist/agent/validation_runner.js +77 -0
- package/dist/agentic/fix_loop.d.ts +26 -0
- package/dist/agentic/fix_loop.d.ts.map +1 -0
- package/dist/agentic/fix_loop.js +96 -0
- package/dist/agentic/playwright_runner.d.ts +43 -0
- package/dist/agentic/playwright_runner.d.ts.map +1 -0
- package/dist/agentic/playwright_runner.js +165 -0
- package/dist/agentic/runner.d.ts +27 -0
- package/dist/agentic/runner.d.ts.map +1 -0
- package/dist/agentic/runner.js +210 -0
- package/dist/agentic/types.d.ts +62 -0
- package/dist/agentic/types.d.ts.map +1 -0
- package/dist/agentic/types.js +4 -0
- package/dist/agents/coverage-evaluator.d.ts +8 -0
- package/dist/agents/coverage-evaluator.d.ts.map +1 -0
- package/dist/agents/coverage-evaluator.js +41 -0
- package/dist/agents/cross-impact.d.ts +13 -0
- package/dist/agents/cross-impact.d.ts.map +1 -0
- package/dist/agents/cross-impact.js +140 -0
- package/dist/agents/executor.d.ts +8 -0
- package/dist/agents/executor.d.ts.map +1 -0
- package/dist/agents/executor.js +75 -0
- package/dist/agents/explorer.d.ts +12 -0
- package/dist/agents/explorer.d.ts.map +1 -0
- package/dist/agents/explorer.js +43 -0
- package/dist/agents/generator.d.ts +8 -0
- package/dist/agents/generator.d.ts.map +1 -0
- package/dist/agents/generator.js +77 -0
- package/dist/agents/healer.d.ts +8 -0
- package/dist/agents/healer.d.ts.map +1 -0
- package/dist/agents/healer.js +31 -0
- package/dist/agents/impact-analyst.d.ts +8 -0
- package/dist/agents/impact-analyst.d.ts.map +1 -0
- package/dist/agents/impact-analyst.js +38 -0
- package/dist/agents/regression-advisor.d.ts +8 -0
- package/dist/agents/regression-advisor.d.ts.map +1 -0
- package/dist/agents/regression-advisor.js +116 -0
- package/dist/agents/strategist.d.ts +9 -0
- package/dist/agents/strategist.d.ts.map +1 -0
- package/dist/agents/strategist.js +92 -0
- package/dist/agents/test-designer.d.ts +8 -0
- package/dist/agents/test-designer.d.ts.map +1 -0
- package/dist/agents/test-designer.js +111 -0
- package/dist/anthropic_provider.d.ts +65 -0
- package/dist/anthropic_provider.d.ts.map +1 -0
- package/dist/anthropic_provider.js +334 -0
- package/dist/api.d.ts +48 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +151 -0
- package/dist/base_provider.d.ts +109 -0
- package/dist/base_provider.d.ts.map +1 -0
- package/dist/base_provider.js +203 -0
- package/dist/budget_ledger.d.ts +28 -0
- package/dist/budget_ledger.d.ts.map +1 -0
- package/dist/budget_ledger.js +62 -0
- package/dist/cache/cached_provider.d.ts +49 -0
- package/dist/cache/cached_provider.d.ts.map +1 -0
- package/dist/cache/cached_provider.js +91 -0
- package/dist/cache/response_cache.d.ts +79 -0
- package/dist/cache/response_cache.d.ts.map +1 -0
- package/dist/cache/response_cache.js +177 -0
- package/dist/cli/commands/analyze.d.ts +3 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/analyze.js +77 -0
- package/dist/cli/commands/bootstrap.d.ts +3 -0
- package/dist/cli/commands/bootstrap.d.ts.map +1 -0
- package/dist/cli/commands/bootstrap.js +109 -0
- package/dist/cli/commands/cost_report.d.ts +3 -0
- package/dist/cli/commands/cost_report.d.ts.map +1 -0
- package/dist/cli/commands/cost_report.js +115 -0
- package/dist/cli/commands/crew.d.ts +3 -0
- package/dist/cli/commands/crew.d.ts.map +1 -0
- package/dist/cli/commands/crew.js +255 -0
- package/dist/cli/commands/feedback.d.ts +3 -0
- package/dist/cli/commands/feedback.d.ts.map +1 -0
- package/dist/cli/commands/feedback.js +39 -0
- package/dist/cli/commands/finalize.d.ts +3 -0
- package/dist/cli/commands/finalize.d.ts.map +1 -0
- package/dist/cli/commands/finalize.js +41 -0
- package/dist/cli/commands/gate.d.ts +3 -0
- package/dist/cli/commands/gate.d.ts.map +1 -0
- package/dist/cli/commands/gate.js +89 -0
- package/dist/cli/commands/generate.d.ts +4 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +108 -0
- package/dist/cli/commands/heal.d.ts +3 -0
- package/dist/cli/commands/heal.d.ts.map +1 -0
- package/dist/cli/commands/heal.js +60 -0
- package/dist/cli/commands/impact.d.ts +4 -0
- package/dist/cli/commands/impact.d.ts.map +1 -0
- package/dist/cli/commands/impact.js +33 -0
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +169 -0
- package/dist/cli/commands/llm_health.d.ts +2 -0
- package/dist/cli/commands/llm_health.d.ts.map +1 -0
- package/dist/cli/commands/llm_health.js +22 -0
- package/dist/cli/commands/plan.d.ts +4 -0
- package/dist/cli/commands/plan.d.ts.map +1 -0
- package/dist/cli/commands/plan.js +120 -0
- package/dist/cli/commands/plan_crew.d.ts +17 -0
- package/dist/cli/commands/plan_crew.d.ts.map +1 -0
- package/dist/cli/commands/plan_crew.js +316 -0
- package/dist/cli/commands/traceability.d.ts +4 -0
- package/dist/cli/commands/traceability.d.ts.map +1 -0
- package/dist/cli/commands/traceability.js +77 -0
- package/dist/cli/commands/train.d.ts +3 -0
- package/dist/cli/commands/train.d.ts.map +1 -0
- package/dist/cli/commands/train.js +391 -0
- package/dist/cli/defaults.d.ts +35 -0
- package/dist/cli/defaults.d.ts.map +1 -0
- package/dist/cli/defaults.js +172 -0
- package/dist/cli/errors.d.ts +27 -0
- package/dist/cli/errors.d.ts.map +1 -0
- package/dist/cli/errors.js +57 -0
- package/dist/cli/parse_args.d.ts +6 -0
- package/dist/cli/parse_args.d.ts.map +1 -0
- package/dist/cli/parse_args.js +257 -0
- package/dist/cli/types.d.ts +87 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +4 -0
- package/dist/cli/usage.d.ts +2 -0
- package/dist/cli/usage.d.ts.map +1 -0
- package/dist/cli/usage.js +109 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +194 -0
- package/dist/crew/context.d.ts +55 -0
- package/dist/crew/context.d.ts.map +1 -0
- package/dist/crew/context.js +36 -0
- package/dist/crew/orchestrator.d.ts +50 -0
- package/dist/crew/orchestrator.d.ts.map +1 -0
- package/dist/crew/orchestrator.js +329 -0
- package/dist/crew/protocol.d.ts +46 -0
- package/dist/crew/protocol.d.ts.map +1 -0
- package/dist/crew/protocol.js +4 -0
- package/dist/crew/provider.d.ts +17 -0
- package/dist/crew/provider.d.ts.map +1 -0
- package/dist/crew/provider.js +36 -0
- package/dist/crew/sanitize.d.ts +3 -0
- package/dist/crew/sanitize.d.ts.map +1 -0
- package/dist/crew/sanitize.js +31 -0
- package/dist/crew/types.d.ts +52 -0
- package/dist/crew/types.d.ts.map +1 -0
- package/dist/crew/types.js +4 -0
- package/dist/crew/workflows.d.ts +52 -0
- package/dist/crew/workflows.d.ts.map +1 -0
- package/dist/crew/workflows.js +36 -0
- package/dist/custom_provider.d.ts +20 -0
- package/dist/custom_provider.d.ts.map +1 -0
- package/dist/custom_provider.js +277 -0
- package/dist/engine/ai_enrichment.d.ts +44 -0
- package/dist/engine/ai_enrichment.d.ts.map +1 -0
- package/dist/engine/ai_enrichment.js +267 -0
- package/dist/engine/diff_loader.d.ts +11 -0
- package/dist/engine/diff_loader.d.ts.map +1 -0
- package/dist/engine/diff_loader.js +63 -0
- package/dist/engine/impact_engine.d.ts +72 -0
- package/dist/engine/impact_engine.d.ts.map +1 -0
- package/dist/engine/impact_engine.js +298 -0
- package/dist/engine/plan_builder.d.ts +11 -0
- package/dist/engine/plan_builder.d.ts.map +1 -0
- package/dist/engine/plan_builder.js +599 -0
- package/dist/esm/adapters/cypress.js +49 -0
- package/dist/esm/adapters/framework_adapter.js +114 -0
- package/dist/esm/adapters/playwright.js +49 -0
- package/dist/esm/adapters/pytest.js +59 -0
- package/dist/esm/adapters/supertest.js +48 -0
- package/dist/esm/agent/api_catalog.js +199 -0
- package/dist/esm/agent/config.js +872 -0
- package/dist/esm/agent/feedback.js +317 -0
- package/dist/esm/agent/git.js +252 -0
- package/dist/esm/agent/handoff.js +177 -0
- package/dist/esm/agent/llm_agents_flow.js +421 -0
- package/dist/esm/agent/native_flow.js +175 -0
- package/dist/esm/agent/pipeline.js +256 -0
- package/dist/esm/agent/pipeline_types.js +3 -0
- package/dist/esm/agent/pipeline_utils.js +146 -0
- package/dist/esm/agent/plan.js +83 -0
- package/dist/esm/agent/playwright_report.js +123 -0
- package/dist/esm/agent/process_runner.js +83 -0
- package/dist/esm/agent/spec_generator.js +249 -0
- package/dist/esm/agent/test_path.js +20 -0
- package/dist/esm/agent/traceability_capture.js +310 -0
- package/dist/esm/agent/traceability_ingest.js +234 -0
- package/dist/esm/agent/types.js +3 -0
- package/dist/esm/agent/utils.js +138 -0
- package/dist/esm/agent/validation_runner.js +73 -0
- package/dist/esm/agentic/fix_loop.js +91 -0
- package/dist/esm/agentic/playwright_runner.js +161 -0
- package/dist/esm/agentic/runner.js +207 -0
- package/dist/esm/agentic/types.js +3 -0
- package/dist/esm/agents/coverage-evaluator.js +37 -0
- package/dist/esm/agents/cross-impact.js +136 -0
- package/dist/esm/agents/executor.js +71 -0
- package/dist/esm/agents/explorer.js +39 -0
- package/dist/esm/agents/generator.js +73 -0
- package/dist/esm/agents/healer.js +27 -0
- package/dist/esm/agents/impact-analyst.js +34 -0
- package/dist/esm/agents/regression-advisor.js +112 -0
- package/dist/esm/agents/strategist.js +88 -0
- package/dist/esm/agents/test-designer.js +107 -0
- package/dist/esm/anthropic_provider.js +326 -0
- package/dist/esm/api.js +143 -0
- package/dist/esm/base_provider.js +198 -0
- package/dist/esm/budget_ledger.js +58 -0
- package/dist/esm/cache/cached_provider.js +85 -0
- package/dist/esm/cache/response_cache.js +140 -0
- package/dist/esm/cli/commands/analyze.js +74 -0
- package/dist/esm/cli/commands/bootstrap.js +106 -0
- package/dist/esm/cli/commands/cost_report.js +112 -0
- package/dist/esm/cli/commands/crew.js +252 -0
- package/dist/esm/cli/commands/feedback.js +36 -0
- package/dist/esm/cli/commands/finalize.js +38 -0
- package/dist/esm/cli/commands/gate.js +86 -0
- package/dist/esm/cli/commands/generate.js +105 -0
- package/dist/esm/cli/commands/heal.js +57 -0
- package/dist/esm/cli/commands/impact.js +30 -0
- package/dist/esm/cli/commands/init.js +133 -0
- package/dist/esm/cli/commands/llm_health.js +19 -0
- package/dist/esm/cli/commands/plan.js +117 -0
- package/dist/esm/cli/commands/plan_crew.js +309 -0
- package/dist/esm/cli/commands/traceability.js +73 -0
- package/dist/esm/cli/commands/train.js +355 -0
- package/dist/esm/cli/defaults.js +165 -0
- package/dist/esm/cli/errors.js +52 -0
- package/dist/esm/cli/parse_args.js +251 -0
- package/dist/esm/cli/types.js +3 -0
- package/dist/esm/cli/usage.js +106 -0
- package/dist/esm/cli.js +192 -0
- package/dist/esm/crew/context.js +32 -0
- package/dist/esm/crew/orchestrator.js +325 -0
- package/dist/esm/crew/protocol.js +3 -0
- package/dist/esm/crew/provider.js +33 -0
- package/dist/esm/crew/sanitize.js +27 -0
- package/dist/esm/crew/types.js +3 -0
- package/dist/esm/crew/workflows.js +33 -0
- package/dist/esm/custom_provider.js +273 -0
- package/dist/esm/engine/ai_enrichment.js +264 -0
- package/dist/esm/engine/diff_loader.js +59 -0
- package/dist/esm/engine/impact_engine.js +291 -0
- package/dist/esm/engine/plan_builder.js +593 -0
- package/dist/esm/index.js +72 -0
- package/dist/esm/knowledge/api_surface.js +408 -0
- package/dist/esm/knowledge/cluster_utils.js +60 -0
- package/dist/esm/knowledge/context_loader.js +85 -0
- package/dist/esm/knowledge/failure_history.js +121 -0
- package/dist/esm/knowledge/kg_bridge.js +381 -0
- package/dist/esm/knowledge/kg_types.js +3 -0
- package/dist/esm/knowledge/route_families.js +393 -0
- package/dist/esm/knowledge/spec_index.js +122 -0
- package/dist/esm/logger.js +115 -0
- package/dist/esm/mcp-server.js +621 -0
- package/dist/esm/metrics/prometheus.js +149 -0
- package/dist/esm/model_router.js +59 -0
- package/dist/esm/ollama_provider.js +301 -0
- package/dist/esm/openai_provider.js +243 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/pipeline/orchestrator.js +228 -0
- package/dist/esm/pipeline/spec_verifier.js +75 -0
- package/dist/esm/pipeline/stage0_preprocess.js +102 -0
- package/dist/esm/pipeline/stage1_impact.js +140 -0
- package/dist/esm/pipeline/stage2_coverage.js +153 -0
- package/dist/esm/pipeline/stage3_generation.js +284 -0
- package/dist/esm/pipeline/stage4_heal.js +288 -0
- package/dist/esm/progress.js +112 -0
- package/dist/esm/prompts/coverage.js +57 -0
- package/dist/esm/prompts/cross-impact.js +53 -0
- package/dist/esm/prompts/generation.js +297 -0
- package/dist/esm/prompts/generation_profile.js +147 -0
- package/dist/esm/prompts/heal.js +91 -0
- package/dist/esm/prompts/impact.js +63 -0
- package/dist/esm/prompts/json_extract.js +36 -0
- package/dist/esm/prompts/strategist.js +61 -0
- package/dist/esm/prompts/test-designer.js +92 -0
- package/dist/esm/provider_factory.js +366 -0
- package/dist/esm/provider_interface.js +23 -0
- package/dist/esm/provider_utils.js +96 -0
- package/dist/esm/qa-agent/cli.js +205 -0
- package/dist/esm/qa-agent/orchestrator.js +120 -0
- package/dist/esm/qa-agent/phase1/runner.js +139 -0
- package/dist/esm/qa-agent/phase1/scope.js +126 -0
- package/dist/esm/qa-agent/phase2/agent_browser.js +95 -0
- package/dist/esm/qa-agent/phase2/agent_loop.js +351 -0
- package/dist/esm/qa-agent/phase2/exploration_state.js +97 -0
- package/dist/esm/qa-agent/phase2/tools.js +386 -0
- package/dist/esm/qa-agent/phase2/vision.js +75 -0
- package/dist/esm/qa-agent/phase3/feedback.js +34 -0
- package/dist/esm/qa-agent/phase3/reporter.js +145 -0
- package/dist/esm/qa-agent/phase3/spec_generator.js +62 -0
- package/dist/esm/qa-agent/phase3/verdict.js +66 -0
- package/dist/esm/qa-agent/safe_env.js +23 -0
- package/dist/esm/qa-agent/types.js +3 -0
- package/dist/esm/reporters/junit.js +86 -0
- package/dist/esm/reporters/reporter.js +3 -0
- package/dist/esm/reporters/sarif.js +132 -0
- package/dist/esm/resilience/circuit_breaker.js +78 -0
- package/dist/esm/resilience/retry.js +56 -0
- package/dist/esm/sanitize.js +66 -0
- package/dist/esm/training/enricher.js +345 -0
- package/dist/esm/training/kg_scanner.js +115 -0
- package/dist/esm/training/merger.js +204 -0
- package/dist/esm/training/scanner.js +923 -0
- package/dist/esm/training/types.js +6 -0
- package/dist/esm/training/validator.js +254 -0
- package/dist/esm/validation/guardrails.js +101 -0
- package/dist/esm/validation/output_schema.js +80 -0
- package/dist/esm/version.js +33 -0
- package/dist/index.d.ts +99 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +169 -0
- package/dist/knowledge/api_surface.d.ts +37 -0
- package/dist/knowledge/api_surface.d.ts.map +1 -0
- package/dist/knowledge/api_surface.js +418 -0
- package/dist/knowledge/cluster_utils.d.ts +28 -0
- package/dist/knowledge/cluster_utils.d.ts.map +1 -0
- package/dist/knowledge/cluster_utils.js +67 -0
- package/dist/knowledge/context_loader.d.ts +13 -0
- package/dist/knowledge/context_loader.d.ts.map +1 -0
- package/dist/knowledge/context_loader.js +90 -0
- package/dist/knowledge/failure_history.d.ts +39 -0
- package/dist/knowledge/failure_history.d.ts.map +1 -0
- package/dist/knowledge/failure_history.js +128 -0
- package/dist/knowledge/kg_bridge.d.ts +31 -0
- package/dist/knowledge/kg_bridge.d.ts.map +1 -0
- package/dist/knowledge/kg_bridge.js +388 -0
- package/dist/knowledge/kg_types.d.ts +75 -0
- package/dist/knowledge/kg_types.d.ts.map +1 -0
- package/dist/knowledge/kg_types.js +4 -0
- package/dist/knowledge/route_families.d.ts +98 -0
- package/dist/knowledge/route_families.d.ts.map +1 -0
- package/dist/knowledge/route_families.js +410 -0
- package/dist/knowledge/spec_index.d.ts +18 -0
- package/dist/knowledge/spec_index.d.ts.map +1 -0
- package/dist/knowledge/spec_index.js +128 -0
- package/dist/logger.d.ts +31 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +119 -0
- package/dist/mcp-server.d.ts +68 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +629 -0
- package/dist/metrics/prometheus.d.ts +37 -0
- package/dist/metrics/prometheus.d.ts.map +1 -0
- package/dist/metrics/prometheus.js +153 -0
- package/dist/model_router.d.ts +28 -0
- package/dist/model_router.d.ts.map +1 -0
- package/dist/model_router.js +63 -0
- package/dist/ollama_provider.d.ts +65 -0
- package/dist/ollama_provider.d.ts.map +1 -0
- package/dist/ollama_provider.js +309 -0
- package/dist/openai_provider.d.ts +23 -0
- package/dist/openai_provider.d.ts.map +1 -0
- package/dist/openai_provider.js +251 -0
- package/dist/pipeline/orchestrator.d.ts +33 -0
- package/dist/pipeline/orchestrator.d.ts.map +1 -0
- package/dist/pipeline/orchestrator.js +231 -0
- package/dist/pipeline/spec_verifier.d.ts +20 -0
- package/dist/pipeline/spec_verifier.d.ts.map +1 -0
- package/dist/pipeline/spec_verifier.js +79 -0
- package/dist/pipeline/stage0_preprocess.d.ts +31 -0
- package/dist/pipeline/stage0_preprocess.d.ts.map +1 -0
- package/dist/pipeline/stage0_preprocess.js +105 -0
- package/dist/pipeline/stage1_impact.d.ts +19 -0
- package/dist/pipeline/stage1_impact.d.ts.map +1 -0
- package/dist/pipeline/stage1_impact.js +143 -0
- package/dist/pipeline/stage2_coverage.d.ts +19 -0
- package/dist/pipeline/stage2_coverage.d.ts.map +1 -0
- package/dist/pipeline/stage2_coverage.js +156 -0
- package/dist/pipeline/stage3_generation.d.ts +43 -0
- package/dist/pipeline/stage3_generation.d.ts.map +1 -0
- package/dist/pipeline/stage3_generation.js +287 -0
- package/dist/pipeline/stage4_heal.d.ts +62 -0
- package/dist/pipeline/stage4_heal.d.ts.map +1 -0
- package/dist/pipeline/stage4_heal.js +294 -0
- package/dist/progress.d.ts +22 -0
- package/dist/progress.d.ts.map +1 -0
- package/dist/progress.js +116 -0
- package/dist/prompts/coverage.d.ts +39 -0
- package/dist/prompts/coverage.d.ts.map +1 -0
- package/dist/prompts/coverage.js +61 -0
- package/dist/prompts/cross-impact.d.ts +23 -0
- package/dist/prompts/cross-impact.d.ts.map +1 -0
- package/dist/prompts/cross-impact.js +57 -0
- package/dist/prompts/generation.d.ts +25 -0
- package/dist/prompts/generation.d.ts.map +1 -0
- package/dist/prompts/generation.js +302 -0
- package/dist/prompts/generation_profile.d.ts +29 -0
- package/dist/prompts/generation_profile.d.ts.map +1 -0
- package/dist/prompts/generation_profile.js +151 -0
- package/dist/prompts/heal.d.ts +23 -0
- package/dist/prompts/heal.d.ts.map +1 -0
- package/dist/prompts/heal.js +95 -0
- package/dist/prompts/impact.d.ts +31 -0
- package/dist/prompts/impact.d.ts.map +1 -0
- package/dist/prompts/impact.js +67 -0
- package/dist/prompts/json_extract.d.ts +14 -0
- package/dist/prompts/json_extract.d.ts.map +1 -0
- package/dist/prompts/json_extract.js +39 -0
- package/dist/prompts/strategist.d.ts +25 -0
- package/dist/prompts/strategist.d.ts.map +1 -0
- package/dist/prompts/strategist.js +65 -0
- package/dist/prompts/test-designer.d.ts +35 -0
- package/dist/prompts/test-designer.d.ts.map +1 -0
- package/dist/prompts/test-designer.js +96 -0
- package/dist/provider_factory.d.ts +104 -0
- package/dist/provider_factory.d.ts.map +1 -0
- package/dist/provider_factory.js +371 -0
- package/dist/provider_interface.d.ts +365 -0
- package/dist/provider_interface.d.ts.map +1 -0
- package/dist/provider_interface.js +28 -0
- package/dist/provider_utils.d.ts +39 -0
- package/dist/provider_utils.d.ts.map +1 -0
- package/dist/provider_utils.js +103 -0
- package/dist/qa-agent/cli.d.ts +3 -0
- package/dist/qa-agent/cli.d.ts.map +1 -0
- package/dist/qa-agent/cli.js +207 -0
- package/dist/qa-agent/orchestrator.d.ts +3 -0
- package/dist/qa-agent/orchestrator.d.ts.map +1 -0
- package/dist/qa-agent/orchestrator.js +123 -0
- package/dist/qa-agent/phase1/runner.d.ts +3 -0
- package/dist/qa-agent/phase1/runner.d.ts.map +1 -0
- package/dist/qa-agent/phase1/runner.js +142 -0
- package/dist/qa-agent/phase1/scope.d.ts +6 -0
- package/dist/qa-agent/phase1/scope.d.ts.map +1 -0
- package/dist/qa-agent/phase1/scope.js +129 -0
- package/dist/qa-agent/phase2/agent_browser.d.ts +35 -0
- package/dist/qa-agent/phase2/agent_browser.d.ts.map +1 -0
- package/dist/qa-agent/phase2/agent_browser.js +99 -0
- package/dist/qa-agent/phase2/agent_loop.d.ts +3 -0
- package/dist/qa-agent/phase2/agent_loop.d.ts.map +1 -0
- package/dist/qa-agent/phase2/agent_loop.js +357 -0
- package/dist/qa-agent/phase2/exploration_state.d.ts +12 -0
- package/dist/qa-agent/phase2/exploration_state.d.ts.map +1 -0
- package/dist/qa-agent/phase2/exploration_state.js +109 -0
- package/dist/qa-agent/phase2/tools.d.ts +28 -0
- package/dist/qa-agent/phase2/tools.d.ts.map +1 -0
- package/dist/qa-agent/phase2/tools.js +390 -0
- package/dist/qa-agent/phase2/vision.d.ts +3 -0
- package/dist/qa-agent/phase2/vision.d.ts.map +1 -0
- package/dist/qa-agent/phase2/vision.js +78 -0
- package/dist/qa-agent/phase3/feedback.d.ts +3 -0
- package/dist/qa-agent/phase3/feedback.d.ts.map +1 -0
- package/dist/qa-agent/phase3/feedback.js +37 -0
- package/dist/qa-agent/phase3/reporter.d.ts +3 -0
- package/dist/qa-agent/phase3/reporter.d.ts.map +1 -0
- package/dist/qa-agent/phase3/reporter.js +148 -0
- package/dist/qa-agent/phase3/spec_generator.d.ts +3 -0
- package/dist/qa-agent/phase3/spec_generator.d.ts.map +1 -0
- package/dist/qa-agent/phase3/spec_generator.js +65 -0
- package/dist/qa-agent/phase3/verdict.d.ts +3 -0
- package/dist/qa-agent/phase3/verdict.d.ts.map +1 -0
- package/dist/qa-agent/phase3/verdict.js +69 -0
- package/dist/qa-agent/safe_env.d.ts +3 -0
- package/dist/qa-agent/safe_env.d.ts.map +1 -0
- package/dist/qa-agent/safe_env.js +26 -0
- package/dist/qa-agent/types.d.ts +130 -0
- package/dist/qa-agent/types.d.ts.map +1 -0
- package/dist/qa-agent/types.js +4 -0
- package/dist/reporters/junit.d.ts +6 -0
- package/dist/reporters/junit.d.ts.map +1 -0
- package/dist/reporters/junit.js +89 -0
- package/dist/reporters/reporter.d.ts +42 -0
- package/dist/reporters/reporter.d.ts.map +1 -0
- package/dist/reporters/reporter.js +4 -0
- package/dist/reporters/sarif.d.ts +7 -0
- package/dist/reporters/sarif.d.ts.map +1 -0
- package/dist/reporters/sarif.js +135 -0
- package/dist/resilience/circuit_breaker.d.ts +36 -0
- package/dist/resilience/circuit_breaker.d.ts.map +1 -0
- package/dist/resilience/circuit_breaker.js +82 -0
- package/dist/resilience/retry.d.ts +11 -0
- package/dist/resilience/retry.d.ts.map +1 -0
- package/dist/resilience/retry.js +59 -0
- package/dist/sanitize.d.ts +15 -0
- package/dist/sanitize.d.ts.map +1 -0
- package/dist/sanitize.js +71 -0
- package/dist/training/enricher.d.ts +17 -0
- package/dist/training/enricher.d.ts.map +1 -0
- package/dist/training/enricher.js +350 -0
- package/dist/training/kg_scanner.d.ts +13 -0
- package/dist/training/kg_scanner.d.ts.map +1 -0
- package/dist/training/kg_scanner.js +118 -0
- package/dist/training/merger.d.ts +15 -0
- package/dist/training/merger.d.ts.map +1 -0
- package/dist/training/merger.js +208 -0
- package/dist/training/scanner.d.ts +36 -0
- package/dist/training/scanner.d.ts.map +1 -0
- package/dist/training/scanner.js +932 -0
- package/dist/training/types.d.ts +117 -0
- package/dist/training/types.d.ts.map +1 -0
- package/dist/training/types.js +9 -0
- package/dist/training/validator.d.ts +21 -0
- package/dist/training/validator.d.ts.map +1 -0
- package/dist/training/validator.js +262 -0
- package/dist/validation/guardrails.d.ts +31 -0
- package/dist/validation/guardrails.d.ts.map +1 -0
- package/dist/validation/guardrails.js +112 -0
- package/dist/validation/output_schema.d.ts +67 -0
- package/dist/validation/output_schema.d.ts.map +1 -0
- package/dist/validation/output_schema.js +84 -0
- package/dist/version.d.ts +6 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +36 -0
- package/package.json +126 -0
- package/schemas/flow-decision.schema.json +83 -0
- package/schemas/gap.schema.json +18 -0
- package/schemas/impact.schema.json +455 -0
- package/schemas/plan.schema.json +491 -0
- package/schemas/route-families.schema.json +137 -0
- package/schemas/subsystem-risk-map.schema.json +62 -0
- package/schemas/traceability-input.schema.json +122 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
/**
|
|
4
|
+
* Cross-Impact Analyst Agent — finds ripple effects across route families
|
|
5
|
+
* by analyzing shared dependencies between changed families and all other families.
|
|
6
|
+
*/
|
|
7
|
+
import { getCrewProvider } from '../crew/provider.js';
|
|
8
|
+
import { buildCrossImpactPrompt, parseCrossImpactResponse } from '../prompts/cross-impact.js';
|
|
9
|
+
const VALID_RISK = new Set(['high', 'medium', 'low']);
|
|
10
|
+
const MAX_CROSS_IMPACTS = 50;
|
|
11
|
+
export class CrossImpactAgent {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.role = 'cross-impact';
|
|
14
|
+
}
|
|
15
|
+
async execute(_task, ctx) {
|
|
16
|
+
const warnings = [];
|
|
17
|
+
if (ctx.routeFamilies.length === 0) {
|
|
18
|
+
warnings.push('Cross-impact: no route families available.');
|
|
19
|
+
return { role: this.role, status: 'partial', output: [], warnings };
|
|
20
|
+
}
|
|
21
|
+
// Determine directly impacted families from family groups
|
|
22
|
+
const directlyImpacted = new Set(ctx.familyGroups.map((g) => g.familyId));
|
|
23
|
+
if (directlyImpacted.size === 0) {
|
|
24
|
+
warnings.push('Cross-impact: no directly impacted families.');
|
|
25
|
+
return { role: this.role, status: 'partial', output: [], warnings };
|
|
26
|
+
}
|
|
27
|
+
// First: deterministic cross-impact detection via shared paths
|
|
28
|
+
const deterministicCrossImpacts = this.detectDeterministic(ctx, directlyImpacted)
|
|
29
|
+
.slice(0, MAX_CROSS_IMPACTS);
|
|
30
|
+
ctx.crossImpacts.push(...deterministicCrossImpacts);
|
|
31
|
+
// Then: LLM-enriched analysis for semantic cross-impacts
|
|
32
|
+
try {
|
|
33
|
+
const provider = await getCrewProvider(ctx.providerOverride, ctx.budgetUSD, {
|
|
34
|
+
agentRole: 'cross-impact',
|
|
35
|
+
modelRoutingProviderType: ctx.modelRoutingProviderType,
|
|
36
|
+
modelRoutingOverrides: ctx.modelRoutingOverrides,
|
|
37
|
+
budgetLedger: ctx.budgetLedger,
|
|
38
|
+
});
|
|
39
|
+
const prompt = buildCrossImpactPrompt({
|
|
40
|
+
changedFiles: ctx.changedFiles,
|
|
41
|
+
families: ctx.routeFamilies,
|
|
42
|
+
directlyImpactedFamilyIds: Array.from(directlyImpacted),
|
|
43
|
+
});
|
|
44
|
+
const response = await provider.generateText(prompt, {
|
|
45
|
+
maxTokens: 3000,
|
|
46
|
+
temperature: 0,
|
|
47
|
+
timeout: 45000,
|
|
48
|
+
systemPrompt: 'Return only valid JSON. Do not include markdown fences unless necessary.',
|
|
49
|
+
});
|
|
50
|
+
const parsed = parseCrossImpactResponse(response.text);
|
|
51
|
+
if (parsed && parsed.crossImpacts.length > 0) {
|
|
52
|
+
const familyIds = new Set(ctx.routeFamilies.map((f) => f.id));
|
|
53
|
+
const llmCrossImpacts = parsed.crossImpacts
|
|
54
|
+
.filter((ci) => familyIds.has(ci.sourceFamily) &&
|
|
55
|
+
familyIds.has(ci.affectedFamily) &&
|
|
56
|
+
ci.sourceFamily !== ci.affectedFamily)
|
|
57
|
+
.map((ci) => ({
|
|
58
|
+
sourceFamily: ci.sourceFamily,
|
|
59
|
+
affectedFamily: ci.affectedFamily,
|
|
60
|
+
sharedDependency: ci.sharedDependency || 'unknown',
|
|
61
|
+
riskLevel: VALID_RISK.has(ci.riskLevel) ? ci.riskLevel : 'low',
|
|
62
|
+
evidence: ci.evidence || '',
|
|
63
|
+
}));
|
|
64
|
+
// Deduplicate against deterministic results
|
|
65
|
+
const existing = new Set(ctx.crossImpacts.map((ci) => `${ci.sourceFamily}->${ci.affectedFamily}`));
|
|
66
|
+
for (const ci of llmCrossImpacts) {
|
|
67
|
+
if (ctx.crossImpacts.length >= MAX_CROSS_IMPACTS)
|
|
68
|
+
break;
|
|
69
|
+
const key = `${ci.sourceFamily}->${ci.affectedFamily}`;
|
|
70
|
+
if (!existing.has(key)) {
|
|
71
|
+
ctx.crossImpacts.push(ci);
|
|
72
|
+
existing.add(key);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
role: this.role,
|
|
78
|
+
status: ctx.crossImpacts.length > 0 ? 'success' : 'partial',
|
|
79
|
+
output: ctx.crossImpacts,
|
|
80
|
+
usage: provider.getUsageStats(),
|
|
81
|
+
warnings,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
86
|
+
warnings.push(`Cross-impact LLM analysis failed: ${message}. Using deterministic results only.`);
|
|
87
|
+
return {
|
|
88
|
+
role: this.role,
|
|
89
|
+
status: deterministicCrossImpacts.length > 0 ? 'partial' : 'failed',
|
|
90
|
+
output: ctx.crossImpacts,
|
|
91
|
+
warnings,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Deterministic cross-impact detection: find families that share webapp/server paths
|
|
97
|
+
* or components with the directly impacted families.
|
|
98
|
+
*/
|
|
99
|
+
detectDeterministic(ctx, directlyImpacted) {
|
|
100
|
+
const results = [];
|
|
101
|
+
for (const sourceId of directlyImpacted) {
|
|
102
|
+
const source = ctx.routeFamilies.find((f) => f.id === sourceId);
|
|
103
|
+
if (!source)
|
|
104
|
+
continue;
|
|
105
|
+
const sourcePaths = new Set([
|
|
106
|
+
...(source.webappPaths || []),
|
|
107
|
+
...(source.serverPaths || []),
|
|
108
|
+
...(source.components || []),
|
|
109
|
+
]);
|
|
110
|
+
if (sourcePaths.size === 0)
|
|
111
|
+
continue;
|
|
112
|
+
for (const target of ctx.routeFamilies) {
|
|
113
|
+
if (target.id === sourceId)
|
|
114
|
+
continue;
|
|
115
|
+
const targetPaths = [
|
|
116
|
+
...(target.webappPaths || []),
|
|
117
|
+
...(target.serverPaths || []),
|
|
118
|
+
...(target.components || []),
|
|
119
|
+
];
|
|
120
|
+
for (const path of targetPaths) {
|
|
121
|
+
if (sourcePaths.has(path)) {
|
|
122
|
+
results.push({
|
|
123
|
+
sourceFamily: sourceId,
|
|
124
|
+
affectedFamily: target.id,
|
|
125
|
+
sharedDependency: path,
|
|
126
|
+
riskLevel: 'medium',
|
|
127
|
+
evidence: `Shared path: ${path} is referenced by both ${sourceId} and ${target.id}`,
|
|
128
|
+
});
|
|
129
|
+
break; // One match per family pair is enough
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return results;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
/**
|
|
4
|
+
* Executor Agent — wraps agentic test execution in the Agent interface.
|
|
5
|
+
* Runs generated specs through Playwright and collects results.
|
|
6
|
+
*/
|
|
7
|
+
import { getCrewProvider } from '../crew/provider.js';
|
|
8
|
+
import { runAgenticGeneration } from '../agentic/runner.js';
|
|
9
|
+
const MAX_FIX_ATTEMPTS = 2;
|
|
10
|
+
const TEST_TIMEOUT_MS = 120000;
|
|
11
|
+
export class ExecutorAgent {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.role = 'executor';
|
|
14
|
+
}
|
|
15
|
+
async execute(_task, ctx) {
|
|
16
|
+
const warnings = [];
|
|
17
|
+
const writtenSpecs = ctx.generatedSpecs.filter((s) => s.written);
|
|
18
|
+
if (writtenSpecs.length === 0) {
|
|
19
|
+
warnings.push('Executor: no written specs to execute.');
|
|
20
|
+
return { role: this.role, status: 'partial', output: null, warnings };
|
|
21
|
+
}
|
|
22
|
+
// Build ScenarioInput[] from generated specs + impacted flows
|
|
23
|
+
const flowMap = new Map(ctx.impactedFlows.map((f) => [f.flowId, f]));
|
|
24
|
+
const scenarios = writtenSpecs.map((spec) => {
|
|
25
|
+
const flow = flowMap.get(spec.flowId);
|
|
26
|
+
return {
|
|
27
|
+
id: spec.flowId,
|
|
28
|
+
name: flow?.flowName || spec.flowId,
|
|
29
|
+
scenarios: flow?.scenariosToAdd || [],
|
|
30
|
+
routeFamily: flow?.routeFamily || 'unknown',
|
|
31
|
+
priority: flow?.priority || 'P2',
|
|
32
|
+
targetSpec: spec.mode === 'add_scenarios' ? spec.specPath : undefined,
|
|
33
|
+
changedFiles: flow?.changedFiles,
|
|
34
|
+
evidence: flow?.evidence,
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
try {
|
|
38
|
+
const provider = await getCrewProvider(ctx.providerOverride, ctx.budgetUSD, {
|
|
39
|
+
agentRole: 'executor',
|
|
40
|
+
modelRoutingProviderType: ctx.modelRoutingProviderType,
|
|
41
|
+
modelRoutingOverrides: ctx.modelRoutingOverrides,
|
|
42
|
+
budgetLedger: ctx.budgetLedger,
|
|
43
|
+
});
|
|
44
|
+
const summary = await runAgenticGeneration({
|
|
45
|
+
scenarios,
|
|
46
|
+
config: {
|
|
47
|
+
maxAttempts: MAX_FIX_ATTEMPTS,
|
|
48
|
+
project: 'chrome',
|
|
49
|
+
testTimeoutMs: TEST_TIMEOUT_MS,
|
|
50
|
+
provider: ctx.providerOverride,
|
|
51
|
+
testsRoot: ctx.testsRoot,
|
|
52
|
+
},
|
|
53
|
+
provider,
|
|
54
|
+
apiSurface: ctx.apiSurface,
|
|
55
|
+
});
|
|
56
|
+
warnings.push(...summary.warnings);
|
|
57
|
+
return {
|
|
58
|
+
role: this.role,
|
|
59
|
+
status: summary.totalPassed > 0 ? 'success' : 'partial',
|
|
60
|
+
output: summary,
|
|
61
|
+
usage: provider.getUsageStats(),
|
|
62
|
+
warnings,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
67
|
+
warnings.push(`Executor failed: ${message}`);
|
|
68
|
+
return { role: this.role, status: 'failed', output: null, warnings };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
export class ExplorerAgent {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.role = 'explorer';
|
|
6
|
+
}
|
|
7
|
+
async execute(_task, ctx) {
|
|
8
|
+
const warnings = [];
|
|
9
|
+
// Explorer requires browser environment — skip gracefully if not available
|
|
10
|
+
try {
|
|
11
|
+
// Build target flows from impacted flows
|
|
12
|
+
const targetFlows = ctx.impactedFlows
|
|
13
|
+
.filter((d) => d.action !== 'cannot_determine')
|
|
14
|
+
.map((d) => ({
|
|
15
|
+
id: d.flowId,
|
|
16
|
+
name: d.flowName,
|
|
17
|
+
url: d.specificRoute,
|
|
18
|
+
priority: d.priority,
|
|
19
|
+
}));
|
|
20
|
+
if (targetFlows.length === 0) {
|
|
21
|
+
warnings.push('Explorer: no target flows for exploration.');
|
|
22
|
+
return { role: this.role, status: 'partial', output: null, warnings };
|
|
23
|
+
}
|
|
24
|
+
// Convert QA findings to crew findings
|
|
25
|
+
warnings.push(`Explorer: ${targetFlows.length} flows available for exploration (requires browser environment).`);
|
|
26
|
+
return {
|
|
27
|
+
role: this.role,
|
|
28
|
+
status: 'partial',
|
|
29
|
+
output: { targetFlows },
|
|
30
|
+
warnings,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
35
|
+
warnings.push(`Explorer failed: ${message}`);
|
|
36
|
+
return { role: this.role, status: 'failed', output: null, warnings };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
/**
|
|
4
|
+
* Generator Agent — wraps pipeline stage3 (test generation) in the Agent interface.
|
|
5
|
+
* Enhanced to accept TestCase[] from the Test Designer in addition to flat scenariosToAdd.
|
|
6
|
+
*/
|
|
7
|
+
import { runGenerationStage } from '../pipeline/stage3_generation.js';
|
|
8
|
+
/**
|
|
9
|
+
* Enrich FlowDecisions with TestDesign data from the crew context.
|
|
10
|
+
* Converts structured TestCase[] into scenariosToAdd strings that the
|
|
11
|
+
* existing generation prompt can consume.
|
|
12
|
+
*/
|
|
13
|
+
function enrichDecisionsWithTestDesigns(ctx) {
|
|
14
|
+
if (ctx.testDesigns.length === 0) {
|
|
15
|
+
return ctx.impactedFlows;
|
|
16
|
+
}
|
|
17
|
+
const designsByFlow = new Map(ctx.testDesigns.map((td) => [td.flowId, td]));
|
|
18
|
+
return ctx.impactedFlows.map((decision) => {
|
|
19
|
+
const design = designsByFlow.get(decision.flowId);
|
|
20
|
+
if (!design || design.testCases.length === 0) {
|
|
21
|
+
return decision;
|
|
22
|
+
}
|
|
23
|
+
// Convert structured test cases to scenario descriptions for the generator prompt
|
|
24
|
+
const designedScenarios = design.testCases.map((tc) => {
|
|
25
|
+
const steps = tc.steps.join(' → ');
|
|
26
|
+
return `[${tc.type}] ${tc.name}: ${steps} → Expected: ${tc.expectedOutcome}`;
|
|
27
|
+
});
|
|
28
|
+
// Merge with any existing scenarios, preferring designed ones
|
|
29
|
+
const existingScenarios = decision.scenariosToAdd || [];
|
|
30
|
+
const mergedScenarios = [...designedScenarios, ...existingScenarios];
|
|
31
|
+
return {
|
|
32
|
+
...decision,
|
|
33
|
+
scenariosToAdd: mergedScenarios,
|
|
34
|
+
// Intentionally promote run_existing → add_scenarios when the test-designer
|
|
35
|
+
// produced new test cases. This ensures designed tests are generated even if
|
|
36
|
+
// impact-analyst thought existing coverage was sufficient. The test-designer
|
|
37
|
+
// only runs for flows the strategist deemed worth testing.
|
|
38
|
+
action: decision.action === 'run_existing' && designedScenarios.length > 0
|
|
39
|
+
? 'add_scenarios'
|
|
40
|
+
: decision.action,
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
export class GeneratorAgent {
|
|
45
|
+
constructor() {
|
|
46
|
+
this.role = 'generator';
|
|
47
|
+
}
|
|
48
|
+
async execute(_task, ctx) {
|
|
49
|
+
const warnings = [];
|
|
50
|
+
const enrichedDecisions = enrichDecisionsWithTestDesigns(ctx);
|
|
51
|
+
const actionable = enrichedDecisions.filter((d) => d.action === 'create_spec' || d.action === 'add_scenarios');
|
|
52
|
+
if (actionable.length === 0) {
|
|
53
|
+
warnings.push('Generator: no actionable decisions for generation.');
|
|
54
|
+
return { role: this.role, status: 'partial', output: [], warnings };
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const result = await runGenerationStage(enrichedDecisions, ctx.apiSurface, ctx.testsRoot, { provider: ctx.providerOverride });
|
|
58
|
+
ctx.generatedSpecs.push(...result.generated);
|
|
59
|
+
warnings.push(...result.warnings);
|
|
60
|
+
return {
|
|
61
|
+
role: this.role,
|
|
62
|
+
status: result.generatedCount > 0 ? 'success' : 'partial',
|
|
63
|
+
output: result,
|
|
64
|
+
warnings,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
69
|
+
warnings.push(`Generator failed: ${message}`);
|
|
70
|
+
return { role: this.role, status: 'failed', output: null, warnings };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
/**
|
|
4
|
+
* Healer Agent — wraps pipeline stage4 (test healing) in the Agent interface.
|
|
5
|
+
*/
|
|
6
|
+
import { runHealStage, resolveHealTargets } from '../pipeline/stage4_heal.js';
|
|
7
|
+
export class HealerAgent {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.role = 'healer';
|
|
10
|
+
}
|
|
11
|
+
async execute(_task, ctx) {
|
|
12
|
+
const warnings = [];
|
|
13
|
+
const healTargets = resolveHealTargets(ctx.testsRoot, { generatedSpecs: ctx.generatedSpecs }, ctx.impactedFlows);
|
|
14
|
+
if (healTargets.length === 0) {
|
|
15
|
+
warnings.push('Healer: no heal targets found.');
|
|
16
|
+
return { role: this.role, status: 'partial', output: null, warnings };
|
|
17
|
+
}
|
|
18
|
+
const result = await runHealStage(ctx.testsRoot, healTargets, { mcp: true });
|
|
19
|
+
warnings.push(...result.warnings);
|
|
20
|
+
return {
|
|
21
|
+
role: this.role,
|
|
22
|
+
status: result.healSuccess > 0 ? 'success' : 'partial',
|
|
23
|
+
output: result,
|
|
24
|
+
warnings,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
/**
|
|
4
|
+
* Impact Analyst Agent — wraps pipeline stage1 (impact analysis) in the Agent interface.
|
|
5
|
+
*/
|
|
6
|
+
import { runImpactStage } from '../pipeline/stage1_impact.js';
|
|
7
|
+
export class ImpactAnalystAgent {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.role = 'impact-analyst';
|
|
10
|
+
}
|
|
11
|
+
async execute(_task, ctx) {
|
|
12
|
+
const warnings = [];
|
|
13
|
+
if (ctx.familyGroups.length === 0) {
|
|
14
|
+
warnings.push('Impact analyst: no family groups to analyze.');
|
|
15
|
+
return { role: this.role, status: 'partial', output: [], warnings };
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const result = await runImpactStage(ctx.familyGroups, ctx.manifest, ctx.specIndex, ctx.apiSurface, ctx.context, { provider: ctx.providerOverride });
|
|
19
|
+
ctx.impactedFlows.push(...result.decisions);
|
|
20
|
+
warnings.push(...result.warnings);
|
|
21
|
+
return {
|
|
22
|
+
role: this.role,
|
|
23
|
+
status: result.decisions.length > 0 ? 'success' : 'partial',
|
|
24
|
+
output: result.decisions,
|
|
25
|
+
warnings,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
30
|
+
warnings.push(`Impact analyst failed: ${message}`);
|
|
31
|
+
return { role: this.role, status: 'failed', output: null, warnings };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
/**
|
|
4
|
+
* Regression Advisor Agent — identifies historically regression-prone areas
|
|
5
|
+
* using traceability data and advises the Strategist on risk scores.
|
|
6
|
+
* Mostly deterministic (traceability data analysis), with optional LLM enrichment.
|
|
7
|
+
*/
|
|
8
|
+
import { readCalibration, readFlakyTests } from '../agent/feedback.js';
|
|
9
|
+
const FLAKY_RISK_MULTIPLIER = 15;
|
|
10
|
+
const LOW_PRECISION_RISK_MULTIPLIER = 30;
|
|
11
|
+
const PATTERN_RISK_SCORE = 30;
|
|
12
|
+
const PATTERN_RISK_ADDITIVE = 20;
|
|
13
|
+
const MAX_RISK_SCORE = 100;
|
|
14
|
+
const MIN_PRECISION_THRESHOLD = 0.5;
|
|
15
|
+
const MIN_CALIBRATION_SAMPLES = 3;
|
|
16
|
+
export class RegressionAdvisorAgent {
|
|
17
|
+
constructor() {
|
|
18
|
+
this.role = 'regression-advisor';
|
|
19
|
+
}
|
|
20
|
+
async execute(_task, ctx) {
|
|
21
|
+
const warnings = [];
|
|
22
|
+
const risks = [];
|
|
23
|
+
// Analyze calibration data for historical failure patterns
|
|
24
|
+
const calibration = readCalibration(ctx.testsRoot);
|
|
25
|
+
const flakyData = readFlakyTests(ctx.testsRoot);
|
|
26
|
+
// Build risk from flaky test data
|
|
27
|
+
if (flakyData && flakyData.tests.length > 0) {
|
|
28
|
+
const flakyByFamily = new Map();
|
|
29
|
+
for (const test of flakyData.tests) {
|
|
30
|
+
// Use subsystem field as family identifier
|
|
31
|
+
if (test.subsystem) {
|
|
32
|
+
flakyByFamily.set(test.subsystem, (flakyByFamily.get(test.subsystem) || 0) + 1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
for (const [familyId, count] of flakyByFamily) {
|
|
36
|
+
const isImpacted = ctx.familyGroups.some((g) => g.familyId === familyId);
|
|
37
|
+
if (isImpacted) {
|
|
38
|
+
risks.push({
|
|
39
|
+
familyId,
|
|
40
|
+
filePattern: '*',
|
|
41
|
+
riskScore: Math.min(MAX_RISK_SCORE, count * FLAKY_RISK_MULTIPLIER),
|
|
42
|
+
reason: `${count} flaky test(s) historically in this family`,
|
|
43
|
+
historicalFailures: count,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Build risk from calibration data (subsystem-level precision/recall)
|
|
49
|
+
if (calibration && calibration.bySubsystem) {
|
|
50
|
+
for (const [subsystem, metrics] of Object.entries(calibration.bySubsystem)) {
|
|
51
|
+
const isImpacted = ctx.familyGroups.some((g) => g.familyId === subsystem);
|
|
52
|
+
if (!isImpacted)
|
|
53
|
+
continue;
|
|
54
|
+
// Low precision means many false positives — the subsystem is noisy
|
|
55
|
+
if (metrics.precision < MIN_PRECISION_THRESHOLD && metrics.samples >= MIN_CALIBRATION_SAMPLES) {
|
|
56
|
+
const existing = risks.find((r) => r.familyId === subsystem);
|
|
57
|
+
const lowPrecisionScore = Math.round((1 - metrics.precision) * LOW_PRECISION_RISK_MULTIPLIER);
|
|
58
|
+
if (existing) {
|
|
59
|
+
existing.riskScore = Math.min(MAX_RISK_SCORE, existing.riskScore + lowPrecisionScore);
|
|
60
|
+
existing.reason += `; low calibration precision (${(metrics.precision * 100).toFixed(0)}%)`;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
risks.push({
|
|
64
|
+
familyId: subsystem,
|
|
65
|
+
filePattern: '*',
|
|
66
|
+
riskScore: lowPrecisionScore,
|
|
67
|
+
reason: `Low calibration precision (${(metrics.precision * 100).toFixed(0)}%) — historically noisy subsystem`,
|
|
68
|
+
historicalFailures: metrics.samples,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Analyze changed files for known regression-prone patterns
|
|
75
|
+
for (const group of ctx.familyGroups) {
|
|
76
|
+
const hasApiChange = group.files.some((f) => f.path.includes('/api/') || f.path.includes('/actions/') || f.path.includes('/reducers/'));
|
|
77
|
+
const hasAuthChange = group.files.some((f) => f.path.includes('auth') || f.path.includes('login') || f.path.includes('session'));
|
|
78
|
+
const hasDBChange = group.files.some((f) => f.path.includes('/store/') || f.path.includes('/model/') || f.path.includes('migration'));
|
|
79
|
+
if (hasApiChange || hasAuthChange || hasDBChange) {
|
|
80
|
+
const existing = risks.find((r) => r.familyId === group.familyId);
|
|
81
|
+
const patterns = [
|
|
82
|
+
hasApiChange && 'API changes',
|
|
83
|
+
hasAuthChange && 'auth changes',
|
|
84
|
+
hasDBChange && 'data model changes',
|
|
85
|
+
].filter(Boolean).join(', ');
|
|
86
|
+
if (existing) {
|
|
87
|
+
existing.riskScore = Math.min(MAX_RISK_SCORE, existing.riskScore + PATTERN_RISK_ADDITIVE);
|
|
88
|
+
existing.reason += `; regression-prone patterns: ${patterns}`;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
risks.push({
|
|
92
|
+
familyId: group.familyId,
|
|
93
|
+
filePattern: group.files.map((f) => f.path).join(', '),
|
|
94
|
+
riskScore: PATTERN_RISK_SCORE,
|
|
95
|
+
reason: `Regression-prone file patterns detected: ${patterns}`,
|
|
96
|
+
historicalFailures: 0,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
ctx.regressionRisks.push(...risks);
|
|
102
|
+
if (risks.length === 0) {
|
|
103
|
+
warnings.push('Regression advisor: no historical risk data found.');
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
role: this.role,
|
|
107
|
+
status: risks.length > 0 ? 'success' : 'partial',
|
|
108
|
+
output: risks,
|
|
109
|
+
warnings,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
/**
|
|
4
|
+
* Strategist Agent — designs overall test strategy from impact analysis,
|
|
5
|
+
* cross-impact data, and regression risk.
|
|
6
|
+
*/
|
|
7
|
+
import { getCrewProvider } from '../crew/provider.js';
|
|
8
|
+
import { buildStrategistPrompt, parseStrategistResponse } from '../prompts/strategist.js';
|
|
9
|
+
const VALID_APPROACHES = new Set(['full-test', 'smoke-test', 'skip', 'manual-review']);
|
|
10
|
+
const VALID_CATEGORIES = new Set([
|
|
11
|
+
'happy-path', 'edge-case', 'boundary', 'negative',
|
|
12
|
+
'state-transition', 'race-condition', 'permission', 'accessibility', 'performance',
|
|
13
|
+
]);
|
|
14
|
+
const VALID_RISK = new Set(['high', 'medium', 'low', 'none']);
|
|
15
|
+
export class StrategistAgent {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.role = 'strategist';
|
|
18
|
+
}
|
|
19
|
+
async execute(_task, ctx) {
|
|
20
|
+
const warnings = [];
|
|
21
|
+
if (ctx.impactedFlows.length === 0) {
|
|
22
|
+
warnings.push('Strategist: no impacted flows to strategize.');
|
|
23
|
+
return { role: this.role, status: 'partial', output: [], warnings };
|
|
24
|
+
}
|
|
25
|
+
const prompt = buildStrategistPrompt({
|
|
26
|
+
impactedFlows: ctx.impactedFlows,
|
|
27
|
+
crossImpacts: ctx.crossImpacts,
|
|
28
|
+
regressionRisks: ctx.regressionRisks,
|
|
29
|
+
});
|
|
30
|
+
try {
|
|
31
|
+
const provider = await getCrewProvider(ctx.providerOverride, ctx.budgetUSD, {
|
|
32
|
+
agentRole: 'strategist',
|
|
33
|
+
modelRoutingProviderType: ctx.modelRoutingProviderType,
|
|
34
|
+
modelRoutingOverrides: ctx.modelRoutingOverrides,
|
|
35
|
+
budgetLedger: ctx.budgetLedger,
|
|
36
|
+
});
|
|
37
|
+
const response = await provider.generateText(prompt, {
|
|
38
|
+
maxTokens: 4000,
|
|
39
|
+
temperature: 0,
|
|
40
|
+
timeout: 45000,
|
|
41
|
+
systemPrompt: 'Return only valid JSON. Do not include markdown fences unless necessary.',
|
|
42
|
+
});
|
|
43
|
+
const parsed = parseStrategistResponse(response.text);
|
|
44
|
+
if (!parsed || parsed.strategy.length === 0) {
|
|
45
|
+
warnings.push('Strategist: LLM returned no strategy.');
|
|
46
|
+
// Fall back to default strategy
|
|
47
|
+
ctx.strategyEntries.push(...this.buildDefaultStrategy(ctx));
|
|
48
|
+
return { role: this.role, status: 'partial', output: ctx.strategyEntries, warnings };
|
|
49
|
+
}
|
|
50
|
+
const entries = parsed.strategy.map((s) => ({
|
|
51
|
+
flowId: s.flowId,
|
|
52
|
+
flowName: s.flowName,
|
|
53
|
+
priority: (['P0', 'P1', 'P2'].includes(s.priority) ? s.priority : 'P2'),
|
|
54
|
+
approach: VALID_APPROACHES.has(s.approach) ? s.approach : 'full-test',
|
|
55
|
+
rationale: s.rationale || '',
|
|
56
|
+
testCategories: (s.testCategories || []).filter((c) => VALID_CATEGORIES.has(c)),
|
|
57
|
+
crossImpactRisk: VALID_RISK.has(s.crossImpactRisk) ? s.crossImpactRisk : 'none',
|
|
58
|
+
}));
|
|
59
|
+
ctx.strategyEntries.push(...entries);
|
|
60
|
+
return {
|
|
61
|
+
role: this.role,
|
|
62
|
+
status: 'success',
|
|
63
|
+
output: entries,
|
|
64
|
+
usage: provider.getUsageStats(),
|
|
65
|
+
warnings,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
70
|
+
warnings.push(`Strategist LLM failed: ${message}. Using default strategy.`);
|
|
71
|
+
ctx.strategyEntries.push(...this.buildDefaultStrategy(ctx));
|
|
72
|
+
return { role: this.role, status: 'partial', output: ctx.strategyEntries, warnings };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
buildDefaultStrategy(ctx) {
|
|
76
|
+
return ctx.impactedFlows
|
|
77
|
+
.filter((f) => f.action !== 'cannot_determine')
|
|
78
|
+
.map((f) => ({
|
|
79
|
+
flowId: f.flowId,
|
|
80
|
+
flowName: f.flowName,
|
|
81
|
+
priority: f.priority,
|
|
82
|
+
approach: (f.action === 'create_spec' || f.action === 'add_scenarios' ? 'full-test' : 'smoke-test'),
|
|
83
|
+
rationale: 'Default strategy based on impact action.',
|
|
84
|
+
testCategories: ['happy-path', 'edge-case'],
|
|
85
|
+
crossImpactRisk: 'none',
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
}
|