@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,325 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
/**
|
|
4
|
+
* Crew Orchestrator — executes workflow definitions by dispatching to agents.
|
|
5
|
+
*/
|
|
6
|
+
import { getChangedFiles, isTestFile } from '../agent/git.js';
|
|
7
|
+
import { preprocess } from '../pipeline/stage0_preprocess.js';
|
|
8
|
+
import { logger } from '../logger.js';
|
|
9
|
+
import { BudgetExceededError } from '../base_provider.js';
|
|
10
|
+
import { BudgetLedger } from '../budget_ledger.js';
|
|
11
|
+
import { createEmptyUsageStats, mergeUsageStats } from './context.js';
|
|
12
|
+
import { WORKFLOWS } from './workflows.js';
|
|
13
|
+
export class CrewOrchestrator {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.agents = new Map();
|
|
16
|
+
}
|
|
17
|
+
registerAgent(agent) {
|
|
18
|
+
this.agents.set(agent.role, agent);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Load and register plugins from file paths.
|
|
22
|
+
* Each module must default-export an object satisfying AgentPlugin.
|
|
23
|
+
*/
|
|
24
|
+
async loadPlugins(pluginPaths) {
|
|
25
|
+
const loaded = [];
|
|
26
|
+
for (const pluginPath of pluginPaths) {
|
|
27
|
+
try {
|
|
28
|
+
// Security: Only allow relative paths (starting with . or ..) to prevent loading arbitrary modules.
|
|
29
|
+
// Absolute paths, URLs, and node_modules references are rejected.
|
|
30
|
+
if (!pluginPath.startsWith('.')) {
|
|
31
|
+
logger.warn(`Plugin path must be relative (start with ./): ${pluginPath} — skipped`);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const resolved = new URL(pluginPath, `file://${process.cwd()}/`).href;
|
|
35
|
+
// Security: reject paths that resolve outside the workspace (e.g., ../../etc/evil.js)
|
|
36
|
+
const cwd = `file://${process.cwd()}/`;
|
|
37
|
+
if (!resolved.startsWith(cwd)) {
|
|
38
|
+
logger.warn(`Plugin path '${pluginPath}' resolves outside workspace — skipped`);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const mod = await import(resolved);
|
|
42
|
+
const plugin = mod.default || mod;
|
|
43
|
+
if (!plugin.role || typeof plugin.execute !== 'function') {
|
|
44
|
+
logger.warn(`Plugin at ${pluginPath} missing required role/execute — skipped`);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
// Warn if plugin overrides a built-in agent
|
|
48
|
+
if (this.agents.has(plugin.role)) {
|
|
49
|
+
logger.warn(`Plugin '${plugin.role}' overrides built-in agent — ensure this is intentional`);
|
|
50
|
+
}
|
|
51
|
+
this.agents.set(plugin.role, plugin);
|
|
52
|
+
loaded.push(plugin.role);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
56
|
+
logger.warn(`Failed to load plugin ${pluginPath}: ${msg}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return loaded;
|
|
60
|
+
}
|
|
61
|
+
async run(config) {
|
|
62
|
+
const workflow = WORKFLOWS[config.workflow || 'full-qa'];
|
|
63
|
+
const timings = {};
|
|
64
|
+
const warnings = [];
|
|
65
|
+
// Load plugins if configured, then inject them into workflow phases
|
|
66
|
+
const pluginRoles = [];
|
|
67
|
+
if (config.plugins && config.plugins.length > 0) {
|
|
68
|
+
const loaded = await this.loadPlugins(config.plugins);
|
|
69
|
+
pluginRoles.push(...loaded);
|
|
70
|
+
if (loaded.length > 0) {
|
|
71
|
+
logger.info(`Loaded ${loaded.length} plugins: ${loaded.join(', ')}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const effectivePhases = this.injectPluginsIntoPhases(workflow.phases, pluginRoles);
|
|
75
|
+
// Step 1: Get changed files
|
|
76
|
+
const gitResult = getChangedFiles(config.appPath, config.gitSince, {
|
|
77
|
+
includeUncommitted: config.gitIncludeUncommitted,
|
|
78
|
+
});
|
|
79
|
+
if (gitResult.error) {
|
|
80
|
+
warnings.push(`Git diff warning: ${gitResult.error}`);
|
|
81
|
+
}
|
|
82
|
+
const changedFiles = gitResult.files
|
|
83
|
+
.map((f) => f.replace(/\\/g, '/'))
|
|
84
|
+
.filter((f) => !isTestFile(f));
|
|
85
|
+
if (changedFiles.length === 0) {
|
|
86
|
+
warnings.push('No changed application files detected.');
|
|
87
|
+
}
|
|
88
|
+
// Create shared budget ledger for aggregate cost tracking across all agents
|
|
89
|
+
const budgetLedger = config.budgetUSD ? new BudgetLedger(config.budgetUSD) : undefined;
|
|
90
|
+
// Initialize context (will be populated during preprocess phase)
|
|
91
|
+
const ctx = {
|
|
92
|
+
changedFiles,
|
|
93
|
+
routeFamilies: [],
|
|
94
|
+
manifest: null,
|
|
95
|
+
apiSurface: { pageObjects: [], generatedAt: '' },
|
|
96
|
+
specIndex: { specs: [], indexedAt: '' },
|
|
97
|
+
context: { documents: [], warnings: [] },
|
|
98
|
+
familyGroups: [],
|
|
99
|
+
preprocessResult: null,
|
|
100
|
+
appPath: config.appPath,
|
|
101
|
+
testsRoot: config.testsRoot,
|
|
102
|
+
gitSince: config.gitSince,
|
|
103
|
+
providerOverride: config.providerOverride,
|
|
104
|
+
budgetUSD: config.budgetUSD,
|
|
105
|
+
budgetLedger,
|
|
106
|
+
impactedFlows: [],
|
|
107
|
+
strategyEntries: [],
|
|
108
|
+
testDesigns: [],
|
|
109
|
+
crossImpacts: [],
|
|
110
|
+
regressionRisks: [],
|
|
111
|
+
findings: [],
|
|
112
|
+
generatedSpecs: [],
|
|
113
|
+
usage: createEmptyUsageStats(),
|
|
114
|
+
agentUsage: [],
|
|
115
|
+
messages: [],
|
|
116
|
+
warnings,
|
|
117
|
+
};
|
|
118
|
+
// Execute each phase
|
|
119
|
+
for (const phase of effectivePhases) {
|
|
120
|
+
const timer = logger.timer(`crew:${phase.name}`);
|
|
121
|
+
if (phase.handler === 'built-in') {
|
|
122
|
+
await this.runBuiltInPhase(phase.name, ctx, config);
|
|
123
|
+
// Dry-run: after preprocess, return summary without running agents
|
|
124
|
+
if (config.dryRun && phase.name === 'preprocess') {
|
|
125
|
+
timings[phase.name] = timer.end();
|
|
126
|
+
ctx.warnings.push('Dry run — no LLM calls were made.');
|
|
127
|
+
return { context: ctx, warnings, timings, dryRun: true };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else if (phase.parallel && phase.parallel.length > 0) {
|
|
131
|
+
await this.runParallel(phase.parallel, phase.name, ctx);
|
|
132
|
+
}
|
|
133
|
+
else if (phase.sequential && phase.sequential.length > 0) {
|
|
134
|
+
await this.runSequential(phase.sequential, phase.name, ctx);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
warnings.push(`Phase '${phase.name}' has no handler, parallel, or sequential agents — skipped.`);
|
|
138
|
+
}
|
|
139
|
+
timings[phase.name] = timer.end();
|
|
140
|
+
// Budget check — prefer ledger (aggregate across all providers) over ctx.usage
|
|
141
|
+
const currentCost = budgetLedger ? budgetLedger.totalCost : ctx.usage.totalCost;
|
|
142
|
+
if (config.budgetUSD && currentCost >= config.budgetUSD) {
|
|
143
|
+
warnings.push(`Budget limit reached ($${currentCost.toFixed(4)} >= $${config.budgetUSD}). Stopping workflow.`);
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return { context: ctx, warnings, timings };
|
|
148
|
+
}
|
|
149
|
+
async dispatch(role, action, ctx) {
|
|
150
|
+
const agent = this.agents.get(role);
|
|
151
|
+
if (!agent) {
|
|
152
|
+
return {
|
|
153
|
+
role,
|
|
154
|
+
status: 'failed',
|
|
155
|
+
output: null,
|
|
156
|
+
warnings: [`Agent '${role}' is not registered.`],
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
const task = { role, action, input: null };
|
|
160
|
+
const startMs = Date.now();
|
|
161
|
+
try {
|
|
162
|
+
const result = await agent.execute(task, ctx);
|
|
163
|
+
const durationMs = Date.now() - startMs;
|
|
164
|
+
if (result.usage) {
|
|
165
|
+
mergeUsageStats(ctx.usage, result.usage);
|
|
166
|
+
ctx.agentUsage.push({
|
|
167
|
+
agent: role,
|
|
168
|
+
inputTokens: result.usage.totalInputTokens,
|
|
169
|
+
outputTokens: result.usage.totalOutputTokens,
|
|
170
|
+
cost: result.usage.totalCost,
|
|
171
|
+
durationMs,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
175
|
+
ctx.warnings.push(...result.warnings);
|
|
176
|
+
}
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
if (error instanceof BudgetExceededError) {
|
|
181
|
+
ctx.warnings.push(`Budget exceeded ($${error.currentCost.toFixed(4)} >= $${error.budgetUSD}). Agent '${role}' skipped.`);
|
|
182
|
+
return { role, status: 'failed', output: null, warnings: [error.message] };
|
|
183
|
+
}
|
|
184
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
185
|
+
ctx.warnings.push(`Agent '${role}' failed: ${message}`);
|
|
186
|
+
return { role, status: 'failed', output: null, warnings: [message] };
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async parallel(roles, action, ctx) {
|
|
190
|
+
const promises = roles.map((role) => this.dispatch(role, action, ctx));
|
|
191
|
+
return Promise.all(promises);
|
|
192
|
+
}
|
|
193
|
+
async broadcast(msg, ctx) {
|
|
194
|
+
ctx.messages.push(msg);
|
|
195
|
+
const promises = [];
|
|
196
|
+
for (const agent of this.agents.values()) {
|
|
197
|
+
if (agent.onMessage && agent.role !== msg.from) {
|
|
198
|
+
promises.push(agent.onMessage(msg).catch((err) => {
|
|
199
|
+
ctx.warnings.push(`Broadcast to ${agent.role} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
await Promise.all(promises);
|
|
204
|
+
}
|
|
205
|
+
async runBuiltInPhase(name, ctx, config) {
|
|
206
|
+
if (name === 'preprocess') {
|
|
207
|
+
if (ctx.changedFiles.length === 0) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const result = preprocess(ctx.changedFiles, {
|
|
211
|
+
appPath: config.appPath,
|
|
212
|
+
testsRoot: config.testsRoot,
|
|
213
|
+
routeFamilies: config.routeFamilies,
|
|
214
|
+
apiSurface: config.apiSurface,
|
|
215
|
+
});
|
|
216
|
+
ctx.preprocessResult = result;
|
|
217
|
+
ctx.manifest = result.manifest;
|
|
218
|
+
ctx.routeFamilies = result.manifest?.families || [];
|
|
219
|
+
ctx.apiSurface = result.apiSurface;
|
|
220
|
+
ctx.specIndex = result.specIndex;
|
|
221
|
+
ctx.context = result.context;
|
|
222
|
+
ctx.familyGroups = result.familyGroups;
|
|
223
|
+
ctx.warnings.push(...result.warnings);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
async runParallel(roles, phaseName, ctx) {
|
|
227
|
+
logger.info(`Crew phase '${phaseName}': running ${roles.join(', ')} in parallel`);
|
|
228
|
+
const results = await this.parallel(roles, phaseName, ctx);
|
|
229
|
+
this.checkPhaseResults(phaseName, results, ctx);
|
|
230
|
+
}
|
|
231
|
+
async runSequential(roles, phaseName, ctx) {
|
|
232
|
+
logger.info(`Crew phase '${phaseName}': running ${roles.join(' → ')} sequentially`);
|
|
233
|
+
const results = [];
|
|
234
|
+
for (const role of roles) {
|
|
235
|
+
results.push(await this.dispatch(role, phaseName, ctx));
|
|
236
|
+
}
|
|
237
|
+
this.checkPhaseResults(phaseName, results, ctx);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Inject loaded plugins into workflow phases based on their `phase` and `runAfter` fields.
|
|
241
|
+
* Plugins with `runAfter` dependencies are appended to the sequential list of the matching phase;
|
|
242
|
+
* plugins without `runAfter` are appended to the parallel list.
|
|
243
|
+
* Returns a new array of phases (does not mutate the original workflow definition).
|
|
244
|
+
*/
|
|
245
|
+
injectPluginsIntoPhases(phases, pluginRoles) {
|
|
246
|
+
if (pluginRoles.length === 0)
|
|
247
|
+
return phases;
|
|
248
|
+
// Build mutable copies keyed by phase name
|
|
249
|
+
const phaseMap = new Map();
|
|
250
|
+
const ordered = [];
|
|
251
|
+
for (const p of phases) {
|
|
252
|
+
ordered.push(p.name);
|
|
253
|
+
if (p.handler === 'built-in') {
|
|
254
|
+
phaseMap.set(p.name, { handler: 'built-in' });
|
|
255
|
+
}
|
|
256
|
+
else if (p.parallel) {
|
|
257
|
+
phaseMap.set(p.name, { parallel: [...p.parallel] });
|
|
258
|
+
}
|
|
259
|
+
else if (p.sequential) {
|
|
260
|
+
phaseMap.set(p.name, { sequential: [...p.sequential] });
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
for (const role of pluginRoles) {
|
|
264
|
+
const agent = this.agents.get(role);
|
|
265
|
+
if (!agent)
|
|
266
|
+
continue;
|
|
267
|
+
const plugin = agent;
|
|
268
|
+
if (!plugin.phase)
|
|
269
|
+
continue;
|
|
270
|
+
const target = phaseMap.get(plugin.phase);
|
|
271
|
+
if (!target) {
|
|
272
|
+
logger.warn(`Plugin '${role}' targets phase '${plugin.phase}' which does not exist in workflow — skipped`);
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
if (target.handler === 'built-in') {
|
|
276
|
+
logger.warn(`Plugin '${role}' targets built-in phase '${plugin.phase}' — not supported, skipped`);
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
const pluginRole = role;
|
|
280
|
+
if (plugin.runAfter && plugin.runAfter.length > 0) {
|
|
281
|
+
// Validate that runAfter dependencies are either in this phase or a prior phase
|
|
282
|
+
const phaseRoles = target.parallel || target.sequential || [];
|
|
283
|
+
const missingDeps = plugin.runAfter.filter((dep) => !phaseRoles.includes(dep) && !this.agents.has(dep));
|
|
284
|
+
if (missingDeps.length > 0) {
|
|
285
|
+
logger.warn(`Plugin '${role}' has unresolved runAfter deps [${missingDeps.join(', ')}] — injecting anyway`);
|
|
286
|
+
}
|
|
287
|
+
// Plugin has dependencies — must run sequentially
|
|
288
|
+
if (target.sequential) {
|
|
289
|
+
target.sequential.push(pluginRole);
|
|
290
|
+
}
|
|
291
|
+
else if (target.parallel) {
|
|
292
|
+
// Convert to sequential to respect dependency ordering
|
|
293
|
+
target.sequential = [...target.parallel, pluginRole];
|
|
294
|
+
delete target.parallel;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
if (target.parallel) {
|
|
299
|
+
target.parallel.push(pluginRole);
|
|
300
|
+
}
|
|
301
|
+
else if (target.sequential) {
|
|
302
|
+
target.sequential.push(pluginRole);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
logger.info(`Plugin '${role}' injected into phase '${plugin.phase}'`);
|
|
306
|
+
}
|
|
307
|
+
// Rebuild WorkflowPhase array
|
|
308
|
+
return ordered.map((name) => {
|
|
309
|
+
const entry = phaseMap.get(name);
|
|
310
|
+
if (entry.handler === 'built-in')
|
|
311
|
+
return { name, handler: 'built-in' };
|
|
312
|
+
if (entry.parallel)
|
|
313
|
+
return { name, parallel: entry.parallel };
|
|
314
|
+
if (entry.sequential)
|
|
315
|
+
return { name, sequential: entry.sequential };
|
|
316
|
+
throw new Error(`Phase '${name}' has no handler, parallel, or sequential agents after plugin injection`);
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
checkPhaseResults(phaseName, results, ctx) {
|
|
320
|
+
const allFailed = results.length > 0 && results.every((r) => r.status === 'failed');
|
|
321
|
+
if (allFailed) {
|
|
322
|
+
ctx.warnings.push(`Phase '${phaseName}': all ${results.length} agent(s) failed. Downstream phases may produce empty results.`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
/**
|
|
4
|
+
* Shared provider creation for crew agents — ensures consistent provider
|
|
5
|
+
* instantiation and prevents usage stats fragmentation.
|
|
6
|
+
*/
|
|
7
|
+
import { LLMProviderFactory } from '../provider_factory.js';
|
|
8
|
+
import { BaseProvider } from '../base_provider.js';
|
|
9
|
+
import { ModelRouter } from '../model_router.js';
|
|
10
|
+
export async function getCrewProvider(providerOverride, budgetUSD, opts) {
|
|
11
|
+
let effectiveOverride = providerOverride;
|
|
12
|
+
// Apply model routing if configured and agent role is provided
|
|
13
|
+
if (opts?.agentRole && opts?.modelRoutingProviderType) {
|
|
14
|
+
const router = new ModelRouter(opts.modelRoutingProviderType, opts.modelRoutingOverrides);
|
|
15
|
+
const model = router.getModel(opts.agentRole);
|
|
16
|
+
if (model) {
|
|
17
|
+
// Override uses provider:model format (e.g., "anthropic:claude-haiku-4-5-20251001")
|
|
18
|
+
effectiveOverride = `${opts.modelRoutingProviderType}:${model}`;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const provider = effectiveOverride
|
|
22
|
+
? await LLMProviderFactory.createFromString(effectiveOverride)
|
|
23
|
+
: await LLMProviderFactory.createFromEnv();
|
|
24
|
+
if (provider instanceof BaseProvider) {
|
|
25
|
+
if (opts?.budgetLedger) {
|
|
26
|
+
provider.setBudgetLedger(opts.budgetLedger);
|
|
27
|
+
}
|
|
28
|
+
else if (budgetUSD !== undefined) {
|
|
29
|
+
provider.setBudget(budgetUSD);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return provider;
|
|
33
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
/**
|
|
4
|
+
* Sanitize strings before interpolating into LLM prompts.
|
|
5
|
+
* Strips common prompt injection patterns while preserving useful content.
|
|
6
|
+
*/
|
|
7
|
+
const INJECTION_PATTERNS = [
|
|
8
|
+
/ignore\s+(all\s+)?previous\s+instructions/gi,
|
|
9
|
+
/disregard\s+(all\s+)?(above|prior|previous)/gi,
|
|
10
|
+
/system\s*:\s*/gi,
|
|
11
|
+
/\[INST\]/gi,
|
|
12
|
+
/<<SYS>>/gi,
|
|
13
|
+
/<\|im_start\|>/gi,
|
|
14
|
+
/\bHuman\s*:\s*/gi,
|
|
15
|
+
/\bAssistant\s*:\s*/gi,
|
|
16
|
+
];
|
|
17
|
+
const MAX_FIELD_LENGTH = 2000;
|
|
18
|
+
export function sanitizeForPrompt(value) {
|
|
19
|
+
let sanitized = value.slice(0, MAX_FIELD_LENGTH);
|
|
20
|
+
for (const pattern of INJECTION_PATTERNS) {
|
|
21
|
+
sanitized = sanitized.replace(pattern, '[filtered]');
|
|
22
|
+
}
|
|
23
|
+
return sanitized;
|
|
24
|
+
}
|
|
25
|
+
export function sanitizeArray(values) {
|
|
26
|
+
return values.map((v) => sanitizeForPrompt(v));
|
|
27
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
|
+
// See LICENSE.txt for license information.
|
|
3
|
+
export const WORKFLOWS = {
|
|
4
|
+
'full-qa': {
|
|
5
|
+
name: 'full-qa',
|
|
6
|
+
description: 'Full multi-agent QA analysis: understand → strategize → execute → validate',
|
|
7
|
+
phases: [
|
|
8
|
+
{ name: 'preprocess', handler: 'built-in' },
|
|
9
|
+
{ name: 'understand', parallel: ['impact-analyst', 'cross-impact', 'regression-advisor'] },
|
|
10
|
+
{ name: 'strategize', sequential: ['strategist', 'test-designer'] },
|
|
11
|
+
{ name: 'execute', parallel: ['generator'] },
|
|
12
|
+
{ name: 'validate', sequential: ['executor', 'healer'] },
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
'quick-check': {
|
|
16
|
+
name: 'quick-check',
|
|
17
|
+
description: 'Quick impact analysis with strategy recommendations',
|
|
18
|
+
phases: [
|
|
19
|
+
{ name: 'preprocess', handler: 'built-in' },
|
|
20
|
+
{ name: 'understand', parallel: ['impact-analyst'] },
|
|
21
|
+
{ name: 'strategize', sequential: ['strategist'] },
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
'design-only': {
|
|
25
|
+
name: 'design-only',
|
|
26
|
+
description: 'Impact analysis through test design — no generation or execution',
|
|
27
|
+
phases: [
|
|
28
|
+
{ name: 'preprocess', handler: 'built-in' },
|
|
29
|
+
{ name: 'understand', parallel: ['impact-analyst', 'cross-impact'] },
|
|
30
|
+
{ name: 'strategize', sequential: ['strategist', 'test-designer'] },
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
};
|