@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,288 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
4
|
+
import { join, resolve } from 'path';
|
|
5
|
+
import { runTargetedSpecHeal } from '../agent/pipeline.js';
|
|
6
|
+
import { extractPlaywrightUnstableSpecs } from '../agent/playwright_report.js';
|
|
7
|
+
import { resolvePlaywrightBinary, runCommand } from '../agent/process_runner.js';
|
|
8
|
+
import { logger } from '../logger.js';
|
|
9
|
+
/**
|
|
10
|
+
* Resolve heal targets from one or more sources, in priority order:
|
|
11
|
+
* 1. Playwright JSON report (CI failures/flakes)
|
|
12
|
+
* 2. Stage 3 generated specs (newly written files that need runtime validation)
|
|
13
|
+
* 3. Explicit target list
|
|
14
|
+
*/
|
|
15
|
+
export function resolveHealTargets(testsRoot, options, decisions) {
|
|
16
|
+
const targets = [];
|
|
17
|
+
const seen = new Set();
|
|
18
|
+
const addTarget = (specPath, status, reason) => {
|
|
19
|
+
// Normalize to absolute path so relative (from Playwright report) and absolute
|
|
20
|
+
// (from generated specs) deduplicate correctly
|
|
21
|
+
let normalized = specPath.replace(/\\/g, '/');
|
|
22
|
+
if (!specPath.startsWith('/') && !(/^[A-Za-z]:[\\/]/).test(specPath)) {
|
|
23
|
+
normalized = join(testsRoot, specPath).replace(/\\/g, '/');
|
|
24
|
+
}
|
|
25
|
+
if (seen.has(normalized)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
seen.add(normalized);
|
|
29
|
+
// Try to match to a FlowDecision for context
|
|
30
|
+
const decision = findDecisionForSpec(normalized, decisions, testsRoot);
|
|
31
|
+
targets.push({ specPath: normalized, status, decision, reason });
|
|
32
|
+
};
|
|
33
|
+
// Source 1: Playwright JSON report
|
|
34
|
+
if (options.playwrightReportPath) {
|
|
35
|
+
const reportPath = resolve(options.playwrightReportPath);
|
|
36
|
+
if (existsSync(reportPath)) {
|
|
37
|
+
const unstable = extractPlaywrightUnstableSpecs(reportPath, [testsRoot]);
|
|
38
|
+
for (const spec of unstable) {
|
|
39
|
+
addTarget(spec.specPath, spec.status, `Playwright report: failingTests=${spec.failingTests}, flakyTests=${spec.flakyTests}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Source 2: Stage 3 generated specs (heal immediately after generation)
|
|
44
|
+
if (options.generatedSpecs) {
|
|
45
|
+
for (const gen of options.generatedSpecs) {
|
|
46
|
+
if (gen.written) {
|
|
47
|
+
addTarget(gen.specPath, 'failed', `Newly generated spec — needs runtime validation`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Source 3: Explicit targets
|
|
52
|
+
if (options.explicitTargets) {
|
|
53
|
+
for (const t of options.explicitTargets) {
|
|
54
|
+
addTarget(t.specPath, t.status, t.reason);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return targets;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Find the FlowDecision most relevant to a given spec path by matching
|
|
61
|
+
* targetSpec / newSpecPath / specPath suffix against decisions.
|
|
62
|
+
*/
|
|
63
|
+
function findDecisionForSpec(specPath, decisions, testsRoot) {
|
|
64
|
+
const normalizedRoot = testsRoot.replace(/\\/g, '/');
|
|
65
|
+
const relative = specPath.startsWith(normalizedRoot)
|
|
66
|
+
? specPath.slice(normalizedRoot.length).replace(/^\//, '')
|
|
67
|
+
: specPath;
|
|
68
|
+
return decisions.find((d) => {
|
|
69
|
+
const target = (d.targetSpec || d.newSpecPath || '').replace(/\\/g, '/');
|
|
70
|
+
if (!target)
|
|
71
|
+
return false;
|
|
72
|
+
// Exact match
|
|
73
|
+
if (target === relative || target === specPath)
|
|
74
|
+
return true;
|
|
75
|
+
// Suffix match with path-segment boundary (must be preceded by /)
|
|
76
|
+
if (relative.endsWith(`/${target}`) || target.endsWith(`/${relative}`))
|
|
77
|
+
return true;
|
|
78
|
+
return false;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
const MAX_HEAL_CYCLES = 2;
|
|
82
|
+
/**
|
|
83
|
+
* Verify a healed spec by running it with Playwright.
|
|
84
|
+
* Returns null on success, or the error message on failure.
|
|
85
|
+
*/
|
|
86
|
+
function verifyHealedSpec(testsRoot, specPath, playwrightBinary) {
|
|
87
|
+
if (!playwrightBinary) {
|
|
88
|
+
return null; // Can't verify without playwright — assume success
|
|
89
|
+
}
|
|
90
|
+
// Resolve to absolute path to prevent argument injection via paths starting with '-'
|
|
91
|
+
const safePath = resolve(specPath);
|
|
92
|
+
const result = runCommand(playwrightBinary, ['test', safePath, '--retries', '1', '--reporter', 'list'], testsRoot, 60000);
|
|
93
|
+
if (result.status === 0) {
|
|
94
|
+
return null; // Passed
|
|
95
|
+
}
|
|
96
|
+
// Extract meaningful error from output
|
|
97
|
+
const output = [result.stdout, result.stderr].filter(Boolean).join('\n');
|
|
98
|
+
const errorLines = output.split('\n').filter((l) => l.includes('Error') || l.includes('error') || l.includes('FAILED') || l.includes('Timeout')).slice(0, 5);
|
|
99
|
+
return errorLines.join('\n') || result.error || 'Verification failed';
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Mark a spec as test.fixme() when healing cannot fix it.
|
|
103
|
+
* Adds a comment explaining the failure.
|
|
104
|
+
*/
|
|
105
|
+
function markSpecAsFixme(specPath, reason) {
|
|
106
|
+
if (!existsSync(specPath))
|
|
107
|
+
return;
|
|
108
|
+
try {
|
|
109
|
+
const content = readFileSync(specPath, 'utf-8');
|
|
110
|
+
const fixmeComment = `// HEAL-INCOMPLETE: ${reason.split('\n')[0].slice(0, 120)}`;
|
|
111
|
+
let commentAdded = false;
|
|
112
|
+
let inBlockComment = false;
|
|
113
|
+
const lines = content.split('\n');
|
|
114
|
+
const result = [];
|
|
115
|
+
for (const line of lines) {
|
|
116
|
+
// Minimal block-comment tracking to avoid replacing test( inside /* ... */
|
|
117
|
+
if (!inBlockComment && line.includes('/*'))
|
|
118
|
+
inBlockComment = true;
|
|
119
|
+
if (inBlockComment) {
|
|
120
|
+
if (line.includes('*/'))
|
|
121
|
+
inBlockComment = false;
|
|
122
|
+
result.push(line);
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const match = line.match(/^([ \t]*)(test\()/);
|
|
126
|
+
if (match) {
|
|
127
|
+
const indent = match[1];
|
|
128
|
+
if (!commentAdded) {
|
|
129
|
+
commentAdded = true;
|
|
130
|
+
result.push(`${indent}${fixmeComment}`);
|
|
131
|
+
}
|
|
132
|
+
result.push(line.replace(/^([ \t]*)test\(/, '$1test.fixme('));
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
result.push(line);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
writeFileSync(specPath, result.join('\n'), 'utf-8');
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Best effort — don't fail the pipeline
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
export async function runHealStage(testsRoot, targets, config) {
|
|
145
|
+
const warnings = [];
|
|
146
|
+
let healAttempts = 0;
|
|
147
|
+
let healSuccess = 0;
|
|
148
|
+
if (targets.length === 0) {
|
|
149
|
+
return {
|
|
150
|
+
targets,
|
|
151
|
+
summary: {
|
|
152
|
+
runner: 'package-native',
|
|
153
|
+
results: [],
|
|
154
|
+
warnings: ['No heal targets provided.'],
|
|
155
|
+
},
|
|
156
|
+
warnings,
|
|
157
|
+
healAttempts: 0,
|
|
158
|
+
healSuccess: 0,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
const healTargets = targets.map((t) => ({
|
|
162
|
+
specPath: t.specPath,
|
|
163
|
+
status: t.status,
|
|
164
|
+
reason: t.reason,
|
|
165
|
+
}));
|
|
166
|
+
const pipelineConfig = {
|
|
167
|
+
enabled: true,
|
|
168
|
+
scenarios: 1,
|
|
169
|
+
outputDir: config.outputDir || 'specs/functional/ai-assisted',
|
|
170
|
+
heal: true,
|
|
171
|
+
dryRun: config.dryRun,
|
|
172
|
+
mcp: config.mcp ?? true,
|
|
173
|
+
mcpAllowFallback: config.mcpAllowFallback ?? false,
|
|
174
|
+
mcpOnly: config.mcpOnly ?? false,
|
|
175
|
+
mcpCommandTimeoutMs: config.mcpCommandTimeoutMs,
|
|
176
|
+
mcpRetries: config.mcpRetries ?? 1,
|
|
177
|
+
};
|
|
178
|
+
const summary = runTargetedSpecHeal(testsRoot, healTargets, pipelineConfig);
|
|
179
|
+
healAttempts += summary.results.filter((r) => r.healStatus === 'success' || r.healStatus === 'failed').length;
|
|
180
|
+
warnings.push(...summary.warnings);
|
|
181
|
+
// Verify-after-heal: re-run healed specs to confirm fixes work
|
|
182
|
+
if (!config.dryRun) {
|
|
183
|
+
const playwrightBinary = resolvePlaywrightBinary(testsRoot);
|
|
184
|
+
const healedResults = summary.results.filter((r) => r.healStatus === 'success');
|
|
185
|
+
for (const result of healedResults) {
|
|
186
|
+
const normalizedFlowId = result.flowId.replace(/\\/g, '/');
|
|
187
|
+
// Try exact match first, then path-suffix match with segment boundary
|
|
188
|
+
let target = targets.find((t) => {
|
|
189
|
+
const normalizedSpec = t.specPath.replace(/\\/g, '/');
|
|
190
|
+
return normalizedSpec === normalizedFlowId;
|
|
191
|
+
});
|
|
192
|
+
if (!target) {
|
|
193
|
+
// Basename fallback: only accept if exactly one candidate matches
|
|
194
|
+
const candidates = targets.filter((t) => {
|
|
195
|
+
const specBasename = t.specPath.split('/').pop() || '';
|
|
196
|
+
const flowBasename = normalizedFlowId.split('/').pop() || '';
|
|
197
|
+
return specBasename === flowBasename;
|
|
198
|
+
});
|
|
199
|
+
if (candidates.length === 1) {
|
|
200
|
+
target = candidates[0];
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const specPath = target?.specPath || result.flowId;
|
|
204
|
+
if (!existsSync(specPath)) {
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
let verifyError = verifyHealedSpec(testsRoot, specPath, playwrightBinary);
|
|
208
|
+
if (verifyError) {
|
|
209
|
+
logger.info(`Heal verification failed for ${specPath}, attempting re-heal (cycle 2/${MAX_HEAL_CYCLES})`);
|
|
210
|
+
healAttempts++;
|
|
211
|
+
// Re-heal with enriched failure detail
|
|
212
|
+
const reHealTargets = [{
|
|
213
|
+
specPath,
|
|
214
|
+
status: 'failed',
|
|
215
|
+
reason: `Re-heal: verification failed after first heal. Error: ${verifyError.slice(0, 500)}`,
|
|
216
|
+
}];
|
|
217
|
+
const reHealSummary = runTargetedSpecHeal(testsRoot, reHealTargets, pipelineConfig);
|
|
218
|
+
warnings.push(...reHealSummary.warnings);
|
|
219
|
+
const reHealed = reHealSummary.results.find((r) => r.healStatus === 'success');
|
|
220
|
+
if (reHealed) {
|
|
221
|
+
verifyError = verifyHealedSpec(testsRoot, specPath, playwrightBinary);
|
|
222
|
+
}
|
|
223
|
+
if (verifyError) {
|
|
224
|
+
// After 2 cycles, mark as fixme
|
|
225
|
+
logger.warn(`Heal-and-verify failed after ${MAX_HEAL_CYCLES} cycles for ${specPath}, marking as test.fixme()`);
|
|
226
|
+
markSpecAsFixme(specPath, verifyError);
|
|
227
|
+
result.healStatus = 'failed';
|
|
228
|
+
result.error = `heal-incomplete: ${verifyError.slice(0, 200)}`;
|
|
229
|
+
warnings.push(`Heal-incomplete: ${specPath} — marked as test.fixme() after ${MAX_HEAL_CYCLES} failed cycles`);
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
healSuccess++;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
healSuccess++;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return { targets, summary, warnings, healAttempts, healSuccess };
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Convenience: extract heal targets from a complete pipeline report + optional
|
|
244
|
+
* Playwright run results, then run the heal stage.
|
|
245
|
+
*/
|
|
246
|
+
export async function healFromReport(testsRoot, report, options) {
|
|
247
|
+
const targets = resolveHealTargets(testsRoot, {
|
|
248
|
+
playwrightReportPath: options.playwrightReportPath,
|
|
249
|
+
generatedSpecs: options.generatedSpecs,
|
|
250
|
+
}, report.decisions);
|
|
251
|
+
return runHealStage(testsRoot, targets, options.healConfig || { mcp: true });
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Write a heal summary section to the pipeline report markdown.
|
|
255
|
+
*/
|
|
256
|
+
export function renderHealMarkdown(result) {
|
|
257
|
+
const lines = ['## Heal Results', ''];
|
|
258
|
+
const healedCount = result.summary.results.filter((r) => r.healStatus === 'success').length;
|
|
259
|
+
const failedCount = result.summary.results.filter((r) => r.healStatus === 'failed').length;
|
|
260
|
+
const skippedCount = result.summary.results.filter((r) => r.healStatus === 'skipped').length;
|
|
261
|
+
const successRate = result.healAttempts > 0
|
|
262
|
+
? `${Math.round((result.healSuccess / result.healAttempts) * 100)}%`
|
|
263
|
+
: 'n/a';
|
|
264
|
+
lines.push(`| Metric | Value |`);
|
|
265
|
+
lines.push(`|--------|-------|`);
|
|
266
|
+
lines.push(`| Targets | ${result.targets.length} |`);
|
|
267
|
+
lines.push(`| Healed | ${healedCount} |`);
|
|
268
|
+
lines.push(`| Failed | ${failedCount} |`);
|
|
269
|
+
lines.push(`| Skipped | ${skippedCount} |`);
|
|
270
|
+
lines.push(`| Heal Attempts | ${result.healAttempts} |`);
|
|
271
|
+
lines.push(`| Verified Passing | ${result.healSuccess} |`);
|
|
272
|
+
lines.push(`| Success Rate | ${successRate} |`);
|
|
273
|
+
lines.push('');
|
|
274
|
+
for (const r of result.summary.results) {
|
|
275
|
+
const icon = r.healStatus === 'success' ? '✅' : r.healStatus === 'failed' ? '❌' : '⏭';
|
|
276
|
+
lines.push(`- ${icon} \`${r.flowId}\` — heal: ${r.healStatus || 'n/a'}`);
|
|
277
|
+
if (r.error) {
|
|
278
|
+
lines.push(` - Error: ${r.error}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (result.warnings.length > 0) {
|
|
282
|
+
lines.push('', '### Heal Warnings', '');
|
|
283
|
+
for (const w of result.warnings) {
|
|
284
|
+
lines.push(`- ${w}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return lines.join('\n');
|
|
288
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
import { EventEmitter } from 'events';
|
|
4
|
+
export class ProgressReporter extends EventEmitter {
|
|
5
|
+
constructor(options) {
|
|
6
|
+
super();
|
|
7
|
+
this.isTTY = options?.isTTY ?? (process.stdout.isTTY === true);
|
|
8
|
+
this.silent = (options?.quiet ?? false) || (options?.jsonMode ?? false);
|
|
9
|
+
this.completedAgents = 0;
|
|
10
|
+
this.totalAgents = 0;
|
|
11
|
+
this.currentPhase = '';
|
|
12
|
+
}
|
|
13
|
+
phaseStart(phase, agentCount) {
|
|
14
|
+
const payload = { phase, agentCount };
|
|
15
|
+
this.emit('phase-start', payload);
|
|
16
|
+
if (this.silent) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
this.currentPhase = phase;
|
|
20
|
+
this.completedAgents = 0;
|
|
21
|
+
this.totalAgents = agentCount;
|
|
22
|
+
const message = `--- Phase: ${phase} (${agentCount} agent${agentCount !== 1 ? 's' : ''}) ---`;
|
|
23
|
+
this.writeLine(message);
|
|
24
|
+
}
|
|
25
|
+
agentStart(agent, family) {
|
|
26
|
+
const payload = { agent, family };
|
|
27
|
+
this.emit('agent-start', payload);
|
|
28
|
+
if (this.silent) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const familyLabel = family ? ` processing ${family}` : '';
|
|
32
|
+
if (this.isTTY) {
|
|
33
|
+
const progress = `[${this.completedAgents}/${this.totalAgents} agents]`;
|
|
34
|
+
const message = `${progress} ${this.currentPhase}: ${agent}${familyLabel}...`;
|
|
35
|
+
process.stdout.write(`\r${clearLine()}${message}`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
const message = `[${this.currentPhase}] ${agent} started${familyLabel ? ':' + familyLabel : ''}`;
|
|
39
|
+
this.writeLine(message);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
agentComplete(agent, family, tokens, cost, durationMs) {
|
|
43
|
+
const payload = { agent, family, tokens, cost, durationMs };
|
|
44
|
+
this.emit('agent-complete', payload);
|
|
45
|
+
if (this.silent) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
this.completedAgents++;
|
|
49
|
+
const costStr = formatCost(cost);
|
|
50
|
+
const durationStr = formatDuration(durationMs);
|
|
51
|
+
const tokensStr = formatTokens(tokens);
|
|
52
|
+
const familyLabel = family ? ` ${family}` : '';
|
|
53
|
+
if (this.isTTY) {
|
|
54
|
+
const progress = `[${this.completedAgents}/${this.totalAgents} agents]`;
|
|
55
|
+
const message = `${progress} ${this.currentPhase}: ${agent} complete${familyLabel} (${tokensStr}, ${costStr}, ${durationStr})`;
|
|
56
|
+
process.stdout.write(`\r${clearLine()}${message}\n`);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
const message = `[${this.currentPhase}] ${agent} complete:${familyLabel} (${tokensStr}, ${costStr}, ${durationStr})`;
|
|
60
|
+
this.writeLine(message);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
phaseComplete(phase, elapsedMs) {
|
|
64
|
+
const payload = { phase, elapsedMs };
|
|
65
|
+
this.emit('phase-complete', payload);
|
|
66
|
+
if (this.silent) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const durationStr = formatDuration(elapsedMs);
|
|
70
|
+
const message = `--- Phase ${phase} complete (${durationStr}) ---`;
|
|
71
|
+
this.writeLine(message);
|
|
72
|
+
}
|
|
73
|
+
workflowComplete(totalCost, totalTokens, elapsedMs) {
|
|
74
|
+
const payload = { totalCost, totalTokens, elapsedMs };
|
|
75
|
+
this.emit('workflow-complete', payload);
|
|
76
|
+
if (this.silent) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const costStr = formatCost(totalCost);
|
|
80
|
+
const tokensStr = formatTokens(totalTokens);
|
|
81
|
+
const durationStr = formatDuration(elapsedMs);
|
|
82
|
+
const message = `=== Workflow complete: ${tokensStr}, ${costStr}, ${durationStr} ===`;
|
|
83
|
+
this.writeLine(message);
|
|
84
|
+
}
|
|
85
|
+
writeLine(message) {
|
|
86
|
+
process.stdout.write(message + '\n');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function clearLine() {
|
|
90
|
+
return '\x1B[2K';
|
|
91
|
+
}
|
|
92
|
+
function formatCost(cost) {
|
|
93
|
+
return `$${cost.toFixed(2)}`;
|
|
94
|
+
}
|
|
95
|
+
function formatTokens(tokens) {
|
|
96
|
+
if (tokens >= 1000000) {
|
|
97
|
+
return `${(tokens / 1000000).toFixed(1)}M tokens`;
|
|
98
|
+
}
|
|
99
|
+
if (tokens >= 1000) {
|
|
100
|
+
return `${(tokens / 1000).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ',')} tokens`;
|
|
101
|
+
}
|
|
102
|
+
return `${tokens} tokens`;
|
|
103
|
+
}
|
|
104
|
+
function formatDuration(ms) {
|
|
105
|
+
const seconds = Math.round(ms / 1000);
|
|
106
|
+
if (seconds >= 60) {
|
|
107
|
+
const minutes = Math.floor(seconds / 60);
|
|
108
|
+
const remainingSeconds = seconds % 60;
|
|
109
|
+
return remainingSeconds > 0 ? `${minutes}m${remainingSeconds}s` : `${minutes}m`;
|
|
110
|
+
}
|
|
111
|
+
return `${seconds}s`;
|
|
112
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
import { extractJsonFromResponse } from './json_extract.js';
|
|
4
|
+
import { sanitizeForPrompt } from '../crew/sanitize.js';
|
|
5
|
+
export function buildCoveragePrompt(ctx) {
|
|
6
|
+
const flowsBlock = ctx.flows
|
|
7
|
+
.map((f) => {
|
|
8
|
+
const actions = f.userActions.length > 0 ? f.userActions.map((a) => sanitizeForPrompt(a)).join('; ') : 'unknown';
|
|
9
|
+
return `- ${f.flowId} (${f.priority}): ${f.flowName}\n Route: ${f.route}\n User actions: ${actions}\n Evidence: ${sanitizeForPrompt(f.evidence)}`;
|
|
10
|
+
})
|
|
11
|
+
.join('\n\n');
|
|
12
|
+
const specsBlock = ctx.specs
|
|
13
|
+
.map((s) => {
|
|
14
|
+
return `### ${s.relativePath}\nTest titles: ${s.testTitles.join(', ')}\n\`\`\`typescript\n${s.content}\n\`\`\``;
|
|
15
|
+
})
|
|
16
|
+
.join('\n\n');
|
|
17
|
+
return [
|
|
18
|
+
`You are evaluating whether existing ${ctx.profile?.projectName || 'the project'} ${ctx.profile?.testFramework || 'Playwright'} E2E tests cover the impacted flows.`,
|
|
19
|
+
'',
|
|
20
|
+
`IMPACTED FLOWS (${ctx.flows.length}):`,
|
|
21
|
+
flowsBlock,
|
|
22
|
+
'',
|
|
23
|
+
`EXISTING SPEC FILES (${ctx.specs.length}):`,
|
|
24
|
+
specsBlock,
|
|
25
|
+
'',
|
|
26
|
+
ctx.contextBlock,
|
|
27
|
+
'',
|
|
28
|
+
'For each flow, determine coverage.',
|
|
29
|
+
'',
|
|
30
|
+
'Return strict JSON only with this shape:',
|
|
31
|
+
'{"coverage":[{"flowId":"<flow_id>","action":"run_existing|add_scenarios|create_spec|cannot_determine","existingSpecs":[{"path":"<relative path>","testTitles":["<exact test title>"],"coverageLevel":"full|partial|none","missingScenarios":["<specific scenario>"]}],"scenariosToAdd":["<scenario description>"],"targetSpec":"<path to extend>","newSpecPath":"<path for new spec>","blockingReason":"<why cannot_determine>","confidence":0-100}]}',
|
|
32
|
+
'',
|
|
33
|
+
'Rules:',
|
|
34
|
+
'- When claiming coverage exists, you MUST quote the exact test title from the spec file.',
|
|
35
|
+
'- If a spec tests a related but different flow, mark as "partial" not "full".',
|
|
36
|
+
'- Do NOT claim coverage exists if you cannot cite the exact test.',
|
|
37
|
+
'- Scenario gaps must be stated as user actions, not code changes.',
|
|
38
|
+
' Wrong: "test the new isEditing state"',
|
|
39
|
+
' Right: "test editing a scheduled message while it is in pending state"',
|
|
40
|
+
'- For add_scenarios, specify which existing spec file to extend in targetSpec.',
|
|
41
|
+
`- For create_spec, suggest a path following ${ctx.profile?.projectName || 'the project'} conventions.`,
|
|
42
|
+
'- Prefer adding scenarios to existing specs over creating new spec files.',
|
|
43
|
+
'',
|
|
44
|
+
'SEMANTIC MATCHING RULES (critical for accuracy):',
|
|
45
|
+
'- A happy-path test does NOT cover the negative/error path of the same feature.',
|
|
46
|
+
' "user can edit post" does NOT cover "user without permission cannot edit post".',
|
|
47
|
+
'- A test for one user role does NOT cover a different role.',
|
|
48
|
+
' "admin can delete channel" does NOT cover "member cannot delete channel".',
|
|
49
|
+
'- A test for creation does NOT cover editing or deletion of the same entity.',
|
|
50
|
+
'- "partial" means: same feature area but different specific scenario.',
|
|
51
|
+
'- "full" means: the exact user action sequence and outcome is tested.',
|
|
52
|
+
'- When in doubt between "full" and "partial", choose "partial".',
|
|
53
|
+
].join('\n');
|
|
54
|
+
}
|
|
55
|
+
export function parseCoverageResponse(text) {
|
|
56
|
+
return extractJsonFromResponse(text, (obj) => obj != null && typeof obj === 'object' && Array.isArray(obj.coverage));
|
|
57
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
import { sanitizeForPrompt } from '../crew/sanitize.js';
|
|
4
|
+
import { extractJsonFromResponse } from './json_extract.js';
|
|
5
|
+
export function buildCrossImpactPrompt(ctx) {
|
|
6
|
+
const familiesBlock = ctx.families
|
|
7
|
+
.map((f) => {
|
|
8
|
+
const paths = [
|
|
9
|
+
...(f.webappPaths || []),
|
|
10
|
+
...(f.serverPaths || []),
|
|
11
|
+
...(f.components || []),
|
|
12
|
+
];
|
|
13
|
+
return `- ${f.id}: routes=[${f.routes.join(', ')}] paths=[${paths.join(', ')}] pageObjects=[${(f.pageObjects || []).join(', ')}]`;
|
|
14
|
+
})
|
|
15
|
+
.join('\n');
|
|
16
|
+
const changedBlock = ctx.changedFiles.map((f) => sanitizeForPrompt(f)).join('\n');
|
|
17
|
+
return [
|
|
18
|
+
`You are analyzing code changes in ${ctx.projectName || 'the project'} to identify cross-family ripple effects.`,
|
|
19
|
+
'When a change in one route family could affect another family through shared dependencies,',
|
|
20
|
+
'that is a cross-impact.',
|
|
21
|
+
'',
|
|
22
|
+
`CHANGED FILES (${ctx.changedFiles.length}):`,
|
|
23
|
+
changedBlock,
|
|
24
|
+
'',
|
|
25
|
+
`DIRECTLY IMPACTED FAMILIES: ${ctx.directlyImpactedFamilyIds.join(', ')}`,
|
|
26
|
+
'',
|
|
27
|
+
`ALL ROUTE FAMILIES (${ctx.families.length}):`,
|
|
28
|
+
familiesBlock,
|
|
29
|
+
'',
|
|
30
|
+
'TASK: Identify cross-family impacts. For each pair, explain the shared dependency.',
|
|
31
|
+
'',
|
|
32
|
+
'Look for:',
|
|
33
|
+
'1. Shared webapp paths (same component used by multiple families)',
|
|
34
|
+
'2. Shared page objects (same PO class referenced by multiple families)',
|
|
35
|
+
'3. Shared API endpoints (changes affecting data used by multiple families)',
|
|
36
|
+
'4. Shared components (React components imported across family boundaries)',
|
|
37
|
+
'5. Shared state management (Redux stores, contexts used across families)',
|
|
38
|
+
'',
|
|
39
|
+
'Return strict JSON only with this shape:',
|
|
40
|
+
'{"crossImpacts":[{"sourceFamily":"<directly impacted family>","affectedFamily":"<indirectly affected family>","sharedDependency":"<what connects them>","riskLevel":"high|medium|low","evidence":"<specific file/component/API that creates the dependency>"}]}',
|
|
41
|
+
'',
|
|
42
|
+
'Rules:',
|
|
43
|
+
'- Only report cross-impacts where both families are in the manifest.',
|
|
44
|
+
'- sourceFamily must be one of the directly impacted families.',
|
|
45
|
+
'- affectedFamily must be DIFFERENT from sourceFamily.',
|
|
46
|
+
'- Risk levels: high = shared data model/state, medium = shared UI component, low = shared utility.',
|
|
47
|
+
'- Evidence must cite specific files, components, or API paths.',
|
|
48
|
+
'- Return empty array if no cross-impacts are found.',
|
|
49
|
+
].join('\n');
|
|
50
|
+
}
|
|
51
|
+
export function parseCrossImpactResponse(text) {
|
|
52
|
+
return extractJsonFromResponse(text, (obj) => obj != null && typeof obj === 'object' && Array.isArray(obj.crossImpacts));
|
|
53
|
+
}
|