@dotsetlabs/bellwether 0.10.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/CHANGELOG.md +291 -0
- package/LICENSE +21 -0
- package/README.md +739 -0
- package/dist/auth/credentials.d.ts +64 -0
- package/dist/auth/credentials.js +218 -0
- package/dist/auth/index.d.ts +6 -0
- package/dist/auth/index.js +6 -0
- package/dist/auth/keychain.d.ts +64 -0
- package/dist/auth/keychain.js +268 -0
- package/dist/baseline/ab-testing.d.ts +80 -0
- package/dist/baseline/ab-testing.js +236 -0
- package/dist/baseline/ai-compatibility-scorer.d.ts +95 -0
- package/dist/baseline/ai-compatibility-scorer.js +606 -0
- package/dist/baseline/calibration.d.ts +77 -0
- package/dist/baseline/calibration.js +136 -0
- package/dist/baseline/category-matching.d.ts +85 -0
- package/dist/baseline/category-matching.js +289 -0
- package/dist/baseline/change-impact-analyzer.d.ts +98 -0
- package/dist/baseline/change-impact-analyzer.js +592 -0
- package/dist/baseline/comparator.d.ts +64 -0
- package/dist/baseline/comparator.js +916 -0
- package/dist/baseline/confidence.d.ts +55 -0
- package/dist/baseline/confidence.js +122 -0
- package/dist/baseline/converter.d.ts +61 -0
- package/dist/baseline/converter.js +585 -0
- package/dist/baseline/dependency-analyzer.d.ts +89 -0
- package/dist/baseline/dependency-analyzer.js +567 -0
- package/dist/baseline/deprecation-tracker.d.ts +133 -0
- package/dist/baseline/deprecation-tracker.js +322 -0
- package/dist/baseline/diff.d.ts +55 -0
- package/dist/baseline/diff.js +1584 -0
- package/dist/baseline/documentation-scorer.d.ts +205 -0
- package/dist/baseline/documentation-scorer.js +466 -0
- package/dist/baseline/embeddings.d.ts +118 -0
- package/dist/baseline/embeddings.js +251 -0
- package/dist/baseline/error-analyzer.d.ts +198 -0
- package/dist/baseline/error-analyzer.js +721 -0
- package/dist/baseline/evaluation/evaluator.d.ts +42 -0
- package/dist/baseline/evaluation/evaluator.js +323 -0
- package/dist/baseline/evaluation/expanded-dataset.d.ts +45 -0
- package/dist/baseline/evaluation/expanded-dataset.js +1164 -0
- package/dist/baseline/evaluation/golden-dataset.d.ts +58 -0
- package/dist/baseline/evaluation/golden-dataset.js +717 -0
- package/dist/baseline/evaluation/index.d.ts +15 -0
- package/dist/baseline/evaluation/index.js +15 -0
- package/dist/baseline/evaluation/types.d.ts +186 -0
- package/dist/baseline/evaluation/types.js +8 -0
- package/dist/baseline/external-dependency-detector.d.ts +181 -0
- package/dist/baseline/external-dependency-detector.js +524 -0
- package/dist/baseline/golden-output.d.ts +162 -0
- package/dist/baseline/golden-output.js +636 -0
- package/dist/baseline/health-scorer.d.ts +174 -0
- package/dist/baseline/health-scorer.js +451 -0
- package/dist/baseline/incremental-checker.d.ts +97 -0
- package/dist/baseline/incremental-checker.js +174 -0
- package/dist/baseline/index.d.ts +31 -0
- package/dist/baseline/index.js +42 -0
- package/dist/baseline/migration-generator.d.ts +137 -0
- package/dist/baseline/migration-generator.js +554 -0
- package/dist/baseline/migrations.d.ts +60 -0
- package/dist/baseline/migrations.js +197 -0
- package/dist/baseline/performance-tracker.d.ts +214 -0
- package/dist/baseline/performance-tracker.js +577 -0
- package/dist/baseline/pr-comment-generator.d.ts +117 -0
- package/dist/baseline/pr-comment-generator.js +546 -0
- package/dist/baseline/response-fingerprint.d.ts +127 -0
- package/dist/baseline/response-fingerprint.js +728 -0
- package/dist/baseline/response-schema-tracker.d.ts +129 -0
- package/dist/baseline/response-schema-tracker.js +420 -0
- package/dist/baseline/risk-scorer.d.ts +54 -0
- package/dist/baseline/risk-scorer.js +434 -0
- package/dist/baseline/saver.d.ts +89 -0
- package/dist/baseline/saver.js +554 -0
- package/dist/baseline/scenario-generator.d.ts +151 -0
- package/dist/baseline/scenario-generator.js +905 -0
- package/dist/baseline/schema-compare.d.ts +86 -0
- package/dist/baseline/schema-compare.js +557 -0
- package/dist/baseline/schema-evolution.d.ts +189 -0
- package/dist/baseline/schema-evolution.js +467 -0
- package/dist/baseline/semantic.d.ts +203 -0
- package/dist/baseline/semantic.js +908 -0
- package/dist/baseline/synonyms.d.ts +60 -0
- package/dist/baseline/synonyms.js +386 -0
- package/dist/baseline/telemetry.d.ts +165 -0
- package/dist/baseline/telemetry.js +294 -0
- package/dist/baseline/test-pruner.d.ts +120 -0
- package/dist/baseline/test-pruner.js +387 -0
- package/dist/baseline/types.d.ts +449 -0
- package/dist/baseline/types.js +5 -0
- package/dist/baseline/version.d.ts +138 -0
- package/dist/baseline/version.js +206 -0
- package/dist/cache/index.d.ts +5 -0
- package/dist/cache/index.js +5 -0
- package/dist/cache/response-cache.d.ts +151 -0
- package/dist/cache/response-cache.js +287 -0
- package/dist/ci/index.d.ts +60 -0
- package/dist/ci/index.js +342 -0
- package/dist/cli/commands/auth.d.ts +12 -0
- package/dist/cli/commands/auth.js +352 -0
- package/dist/cli/commands/badge.d.ts +3 -0
- package/dist/cli/commands/badge.js +74 -0
- package/dist/cli/commands/baseline-accept.d.ts +15 -0
- package/dist/cli/commands/baseline-accept.js +178 -0
- package/dist/cli/commands/baseline-migrate.d.ts +12 -0
- package/dist/cli/commands/baseline-migrate.js +164 -0
- package/dist/cli/commands/baseline.d.ts +14 -0
- package/dist/cli/commands/baseline.js +449 -0
- package/dist/cli/commands/beta.d.ts +10 -0
- package/dist/cli/commands/beta.js +231 -0
- package/dist/cli/commands/check.d.ts +11 -0
- package/dist/cli/commands/check.js +820 -0
- package/dist/cli/commands/cloud/badge.d.ts +3 -0
- package/dist/cli/commands/cloud/badge.js +74 -0
- package/dist/cli/commands/cloud/diff.d.ts +6 -0
- package/dist/cli/commands/cloud/diff.js +79 -0
- package/dist/cli/commands/cloud/history.d.ts +6 -0
- package/dist/cli/commands/cloud/history.js +102 -0
- package/dist/cli/commands/cloud/link.d.ts +9 -0
- package/dist/cli/commands/cloud/link.js +119 -0
- package/dist/cli/commands/cloud/login.d.ts +7 -0
- package/dist/cli/commands/cloud/login.js +499 -0
- package/dist/cli/commands/cloud/projects.d.ts +6 -0
- package/dist/cli/commands/cloud/projects.js +44 -0
- package/dist/cli/commands/cloud/shared.d.ts +7 -0
- package/dist/cli/commands/cloud/shared.js +42 -0
- package/dist/cli/commands/cloud/teams.d.ts +8 -0
- package/dist/cli/commands/cloud/teams.js +169 -0
- package/dist/cli/commands/cloud/upload.d.ts +8 -0
- package/dist/cli/commands/cloud/upload.js +181 -0
- package/dist/cli/commands/contract.d.ts +11 -0
- package/dist/cli/commands/contract.js +280 -0
- package/dist/cli/commands/discover.d.ts +3 -0
- package/dist/cli/commands/discover.js +82 -0
- package/dist/cli/commands/eval.d.ts +9 -0
- package/dist/cli/commands/eval.js +187 -0
- package/dist/cli/commands/explore.d.ts +11 -0
- package/dist/cli/commands/explore.js +437 -0
- package/dist/cli/commands/feedback.d.ts +9 -0
- package/dist/cli/commands/feedback.js +174 -0
- package/dist/cli/commands/golden.d.ts +12 -0
- package/dist/cli/commands/golden.js +407 -0
- package/dist/cli/commands/history.d.ts +10 -0
- package/dist/cli/commands/history.js +202 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.js +219 -0
- package/dist/cli/commands/interview.d.ts +3 -0
- package/dist/cli/commands/interview.js +903 -0
- package/dist/cli/commands/link.d.ts +10 -0
- package/dist/cli/commands/link.js +169 -0
- package/dist/cli/commands/login.d.ts +7 -0
- package/dist/cli/commands/login.js +499 -0
- package/dist/cli/commands/preset.d.ts +33 -0
- package/dist/cli/commands/preset.js +297 -0
- package/dist/cli/commands/profile.d.ts +33 -0
- package/dist/cli/commands/profile.js +286 -0
- package/dist/cli/commands/registry.d.ts +11 -0
- package/dist/cli/commands/registry.js +146 -0
- package/dist/cli/commands/shared.d.ts +79 -0
- package/dist/cli/commands/shared.js +196 -0
- package/dist/cli/commands/teams.d.ts +8 -0
- package/dist/cli/commands/teams.js +169 -0
- package/dist/cli/commands/test.d.ts +9 -0
- package/dist/cli/commands/test.js +500 -0
- package/dist/cli/commands/upload.d.ts +8 -0
- package/dist/cli/commands/upload.js +223 -0
- package/dist/cli/commands/validate-config.d.ts +6 -0
- package/dist/cli/commands/validate-config.js +35 -0
- package/dist/cli/commands/verify.d.ts +11 -0
- package/dist/cli/commands/verify.js +283 -0
- package/dist/cli/commands/watch.d.ts +12 -0
- package/dist/cli/commands/watch.js +253 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +178 -0
- package/dist/cli/interactive.d.ts +47 -0
- package/dist/cli/interactive.js +216 -0
- package/dist/cli/output/terminal-reporter.d.ts +19 -0
- package/dist/cli/output/terminal-reporter.js +104 -0
- package/dist/cli/output.d.ts +226 -0
- package/dist/cli/output.js +438 -0
- package/dist/cli/utils/env.d.ts +5 -0
- package/dist/cli/utils/env.js +14 -0
- package/dist/cli/utils/progress.d.ts +59 -0
- package/dist/cli/utils/progress.js +206 -0
- package/dist/cli/utils/server-context.d.ts +10 -0
- package/dist/cli/utils/server-context.js +36 -0
- package/dist/cloud/auth.d.ts +144 -0
- package/dist/cloud/auth.js +374 -0
- package/dist/cloud/client.d.ts +24 -0
- package/dist/cloud/client.js +65 -0
- package/dist/cloud/http-client.d.ts +38 -0
- package/dist/cloud/http-client.js +215 -0
- package/dist/cloud/index.d.ts +23 -0
- package/dist/cloud/index.js +25 -0
- package/dist/cloud/mock-client.d.ts +107 -0
- package/dist/cloud/mock-client.js +545 -0
- package/dist/cloud/types.d.ts +515 -0
- package/dist/cloud/types.js +15 -0
- package/dist/config/defaults.d.ts +160 -0
- package/dist/config/defaults.js +169 -0
- package/dist/config/loader.d.ts +24 -0
- package/dist/config/loader.js +122 -0
- package/dist/config/template.d.ts +42 -0
- package/dist/config/template.js +647 -0
- package/dist/config/validator.d.ts +2112 -0
- package/dist/config/validator.js +658 -0
- package/dist/constants/cloud.d.ts +107 -0
- package/dist/constants/cloud.js +110 -0
- package/dist/constants/core.d.ts +521 -0
- package/dist/constants/core.js +556 -0
- package/dist/constants/testing.d.ts +1283 -0
- package/dist/constants/testing.js +1568 -0
- package/dist/constants.d.ts +10 -0
- package/dist/constants.js +10 -0
- package/dist/contract/index.d.ts +6 -0
- package/dist/contract/index.js +5 -0
- package/dist/contract/validator.d.ts +177 -0
- package/dist/contract/validator.js +574 -0
- package/dist/cost/index.d.ts +6 -0
- package/dist/cost/index.js +5 -0
- package/dist/cost/tracker.d.ts +134 -0
- package/dist/cost/tracker.js +313 -0
- package/dist/discovery/discovery.d.ts +16 -0
- package/dist/discovery/discovery.js +173 -0
- package/dist/discovery/types.d.ts +51 -0
- package/dist/discovery/types.js +2 -0
- package/dist/docs/agents.d.ts +3 -0
- package/dist/docs/agents.js +995 -0
- package/dist/docs/contract.d.ts +51 -0
- package/dist/docs/contract.js +1681 -0
- package/dist/docs/generator.d.ts +4 -0
- package/dist/docs/generator.js +4 -0
- package/dist/docs/html-reporter.d.ts +9 -0
- package/dist/docs/html-reporter.js +757 -0
- package/dist/docs/index.d.ts +10 -0
- package/dist/docs/index.js +11 -0
- package/dist/docs/junit-reporter.d.ts +18 -0
- package/dist/docs/junit-reporter.js +210 -0
- package/dist/docs/report.d.ts +14 -0
- package/dist/docs/report.js +44 -0
- package/dist/docs/sarif-reporter.d.ts +19 -0
- package/dist/docs/sarif-reporter.js +335 -0
- package/dist/docs/shared.d.ts +35 -0
- package/dist/docs/shared.js +162 -0
- package/dist/docs/templates.d.ts +12 -0
- package/dist/docs/templates.js +76 -0
- package/dist/errors/index.d.ts +6 -0
- package/dist/errors/index.js +6 -0
- package/dist/errors/retry.d.ts +92 -0
- package/dist/errors/retry.js +323 -0
- package/dist/errors/types.d.ts +321 -0
- package/dist/errors/types.js +584 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +32 -0
- package/dist/interview/dependency-resolver.d.ts +11 -0
- package/dist/interview/dependency-resolver.js +32 -0
- package/dist/interview/interviewer.d.ts +232 -0
- package/dist/interview/interviewer.js +1939 -0
- package/dist/interview/mock-response-generator.d.ts +7 -0
- package/dist/interview/mock-response-generator.js +102 -0
- package/dist/interview/orchestrator.d.ts +237 -0
- package/dist/interview/orchestrator.js +1296 -0
- package/dist/interview/rate-limiter.d.ts +15 -0
- package/dist/interview/rate-limiter.js +55 -0
- package/dist/interview/response-validator.d.ts +10 -0
- package/dist/interview/response-validator.js +132 -0
- package/dist/interview/schema-inferrer.d.ts +8 -0
- package/dist/interview/schema-inferrer.js +71 -0
- package/dist/interview/schema-test-generator.d.ts +71 -0
- package/dist/interview/schema-test-generator.js +834 -0
- package/dist/interview/smart-value-generator.d.ts +155 -0
- package/dist/interview/smart-value-generator.js +554 -0
- package/dist/interview/stateful-test-runner.d.ts +19 -0
- package/dist/interview/stateful-test-runner.js +106 -0
- package/dist/interview/types.d.ts +561 -0
- package/dist/interview/types.js +2 -0
- package/dist/llm/anthropic.d.ts +41 -0
- package/dist/llm/anthropic.js +355 -0
- package/dist/llm/client.d.ts +123 -0
- package/dist/llm/client.js +42 -0
- package/dist/llm/factory.d.ts +38 -0
- package/dist/llm/factory.js +145 -0
- package/dist/llm/fallback.d.ts +140 -0
- package/dist/llm/fallback.js +379 -0
- package/dist/llm/index.d.ts +18 -0
- package/dist/llm/index.js +15 -0
- package/dist/llm/ollama.d.ts +37 -0
- package/dist/llm/ollama.js +330 -0
- package/dist/llm/openai.d.ts +25 -0
- package/dist/llm/openai.js +320 -0
- package/dist/llm/token-budget.d.ts +161 -0
- package/dist/llm/token-budget.js +395 -0
- package/dist/logging/logger.d.ts +70 -0
- package/dist/logging/logger.js +130 -0
- package/dist/metrics/collector.d.ts +106 -0
- package/dist/metrics/collector.js +547 -0
- package/dist/metrics/index.d.ts +7 -0
- package/dist/metrics/index.js +7 -0
- package/dist/metrics/prometheus.d.ts +20 -0
- package/dist/metrics/prometheus.js +241 -0
- package/dist/metrics/types.d.ts +209 -0
- package/dist/metrics/types.js +5 -0
- package/dist/persona/builtins.d.ts +54 -0
- package/dist/persona/builtins.js +219 -0
- package/dist/persona/index.d.ts +8 -0
- package/dist/persona/index.js +8 -0
- package/dist/persona/loader.d.ts +30 -0
- package/dist/persona/loader.js +190 -0
- package/dist/persona/types.d.ts +144 -0
- package/dist/persona/types.js +5 -0
- package/dist/persona/validation.d.ts +94 -0
- package/dist/persona/validation.js +332 -0
- package/dist/prompts/index.d.ts +5 -0
- package/dist/prompts/index.js +5 -0
- package/dist/prompts/templates.d.ts +180 -0
- package/dist/prompts/templates.js +431 -0
- package/dist/registry/client.d.ts +49 -0
- package/dist/registry/client.js +191 -0
- package/dist/registry/index.d.ts +7 -0
- package/dist/registry/index.js +6 -0
- package/dist/registry/types.d.ts +140 -0
- package/dist/registry/types.js +6 -0
- package/dist/scenarios/evaluator.d.ts +43 -0
- package/dist/scenarios/evaluator.js +206 -0
- package/dist/scenarios/index.d.ts +10 -0
- package/dist/scenarios/index.js +9 -0
- package/dist/scenarios/loader.d.ts +20 -0
- package/dist/scenarios/loader.js +285 -0
- package/dist/scenarios/types.d.ts +153 -0
- package/dist/scenarios/types.js +8 -0
- package/dist/security/index.d.ts +17 -0
- package/dist/security/index.js +18 -0
- package/dist/security/payloads.d.ts +61 -0
- package/dist/security/payloads.js +268 -0
- package/dist/security/security-tester.d.ts +42 -0
- package/dist/security/security-tester.js +582 -0
- package/dist/security/types.d.ts +166 -0
- package/dist/security/types.js +8 -0
- package/dist/transport/base-transport.d.ts +59 -0
- package/dist/transport/base-transport.js +38 -0
- package/dist/transport/http-transport.d.ts +67 -0
- package/dist/transport/http-transport.js +238 -0
- package/dist/transport/mcp-client.d.ts +141 -0
- package/dist/transport/mcp-client.js +496 -0
- package/dist/transport/sse-transport.d.ts +88 -0
- package/dist/transport/sse-transport.js +316 -0
- package/dist/transport/stdio-transport.d.ts +43 -0
- package/dist/transport/stdio-transport.js +238 -0
- package/dist/transport/types.d.ts +125 -0
- package/dist/transport/types.js +16 -0
- package/dist/utils/concurrency.d.ts +123 -0
- package/dist/utils/concurrency.js +213 -0
- package/dist/utils/formatters.d.ts +16 -0
- package/dist/utils/formatters.js +37 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/jsonpath.d.ts +87 -0
- package/dist/utils/jsonpath.js +326 -0
- package/dist/utils/markdown.d.ts +113 -0
- package/dist/utils/markdown.js +265 -0
- package/dist/utils/network.d.ts +14 -0
- package/dist/utils/network.js +17 -0
- package/dist/utils/sanitize.d.ts +92 -0
- package/dist/utils/sanitize.js +191 -0
- package/dist/utils/semantic.d.ts +194 -0
- package/dist/utils/semantic.js +1051 -0
- package/dist/utils/smart-truncate.d.ts +94 -0
- package/dist/utils/smart-truncate.js +361 -0
- package/dist/utils/timeout.d.ts +153 -0
- package/dist/utils/timeout.js +205 -0
- package/dist/utils/yaml-parser.d.ts +58 -0
- package/dist/utils/yaml-parser.js +86 -0
- package/dist/validation/index.d.ts +32 -0
- package/dist/validation/index.js +32 -0
- package/dist/validation/semantic-test-generator.d.ts +50 -0
- package/dist/validation/semantic-test-generator.js +176 -0
- package/dist/validation/semantic-types.d.ts +66 -0
- package/dist/validation/semantic-types.js +94 -0
- package/dist/validation/semantic-validator.d.ts +38 -0
- package/dist/validation/semantic-validator.js +340 -0
- package/dist/verification/index.d.ts +6 -0
- package/dist/verification/index.js +5 -0
- package/dist/verification/types.d.ts +133 -0
- package/dist/verification/types.js +5 -0
- package/dist/verification/verifier.d.ts +30 -0
- package/dist/verification/verifier.js +309 -0
- package/dist/version.d.ts +19 -0
- package/dist/version.js +48 -0
- package/dist/workflow/auto-generator.d.ts +27 -0
- package/dist/workflow/auto-generator.js +513 -0
- package/dist/workflow/discovery.d.ts +40 -0
- package/dist/workflow/discovery.js +195 -0
- package/dist/workflow/executor.d.ts +82 -0
- package/dist/workflow/executor.js +611 -0
- package/dist/workflow/index.d.ts +10 -0
- package/dist/workflow/index.js +10 -0
- package/dist/workflow/loader.d.ts +24 -0
- package/dist/workflow/loader.js +194 -0
- package/dist/workflow/state-tracker.d.ts +98 -0
- package/dist/workflow/state-tracker.js +424 -0
- package/dist/workflow/types.d.ts +337 -0
- package/dist/workflow/types.js +5 -0
- package/package.json +94 -0
- package/schemas/bellwether-check.schema.json +651 -0
|
@@ -0,0 +1,592 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Change Impact Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Provides semantic understanding of schema changes and their impact.
|
|
5
|
+
* Goes beyond simple hash comparison to understand what actually breaks.
|
|
6
|
+
*/
|
|
7
|
+
import { CHANGE_IMPACT } from '../constants.js';
|
|
8
|
+
// Re-export the centralized CHANGE_IMPACT constant for backwards compatibility
|
|
9
|
+
export { CHANGE_IMPACT } from '../constants.js';
|
|
10
|
+
/**
|
|
11
|
+
* Analyze the impact of changes between two tool fingerprints.
|
|
12
|
+
*/
|
|
13
|
+
export function analyzeToolChangeImpact(oldTool, newTool, workflows = []) {
|
|
14
|
+
const schemaChanges = analyzeSchemaChanges(oldTool.inputSchema, newTool.inputSchema);
|
|
15
|
+
const breakingChanges = schemaChanges.filter(c => c.breaking);
|
|
16
|
+
const affectedParameters = [...new Set(schemaChanges.map(c => c.parameterPath))];
|
|
17
|
+
// Find affected workflows
|
|
18
|
+
const affectedWorkflows = workflows
|
|
19
|
+
.filter(w => w.toolSequence.includes(oldTool.name))
|
|
20
|
+
.map(w => w.id);
|
|
21
|
+
// Calculate risk score
|
|
22
|
+
const riskScore = calculateRiskScore(schemaChanges);
|
|
23
|
+
// Determine severity
|
|
24
|
+
const severity = determineSeverity(riskScore, breakingChanges.length);
|
|
25
|
+
// Calculate migration complexity
|
|
26
|
+
const migrationComplexity = calculateMigrationComplexity(schemaChanges);
|
|
27
|
+
// Generate migration suggestion
|
|
28
|
+
const suggestedMigration = generateMigrationSuggestion(schemaChanges, oldTool.name);
|
|
29
|
+
return {
|
|
30
|
+
severity,
|
|
31
|
+
affectedWorkflows,
|
|
32
|
+
affectedParameters,
|
|
33
|
+
migrationComplexity,
|
|
34
|
+
suggestedMigration,
|
|
35
|
+
schemaChanges,
|
|
36
|
+
backwardsCompatible: breakingChanges.length === 0,
|
|
37
|
+
riskScore,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Analyze a complete diff and provide comprehensive impact analysis.
|
|
42
|
+
*/
|
|
43
|
+
export function analyzeDiffImpact(diff, oldBaseline, newBaseline) {
|
|
44
|
+
const toolImpacts = new Map();
|
|
45
|
+
const actionItems = [];
|
|
46
|
+
let totalBreakingChanges = 0;
|
|
47
|
+
// Analyze removed tools (always breaking)
|
|
48
|
+
for (const toolName of diff.toolsRemoved) {
|
|
49
|
+
const oldTool = oldBaseline.tools.find(t => t.name === toolName);
|
|
50
|
+
if (oldTool) {
|
|
51
|
+
const impact = {
|
|
52
|
+
severity: 'breaking',
|
|
53
|
+
affectedWorkflows: (oldBaseline.workflowSignatures || [])
|
|
54
|
+
.filter(w => w.toolSequence.includes(toolName))
|
|
55
|
+
.map(w => w.id),
|
|
56
|
+
affectedParameters: [],
|
|
57
|
+
migrationComplexity: 'complex',
|
|
58
|
+
suggestedMigration: `Tool "${toolName}" has been removed. You must find an alternative tool or remove all usages.`,
|
|
59
|
+
schemaChanges: [{
|
|
60
|
+
type: 'parameter_removed',
|
|
61
|
+
parameterPath: toolName,
|
|
62
|
+
breaking: true,
|
|
63
|
+
before: oldTool,
|
|
64
|
+
after: null,
|
|
65
|
+
description: `Tool "${toolName}" has been completely removed`,
|
|
66
|
+
}],
|
|
67
|
+
backwardsCompatible: false,
|
|
68
|
+
riskScore: 100,
|
|
69
|
+
};
|
|
70
|
+
toolImpacts.set(toolName, impact);
|
|
71
|
+
totalBreakingChanges++;
|
|
72
|
+
actionItems.push({
|
|
73
|
+
priority: 'critical',
|
|
74
|
+
tool: toolName,
|
|
75
|
+
description: `Tool "${toolName}" has been removed`,
|
|
76
|
+
suggestedAction: 'Find alternative tool or update all consumers to not use this tool',
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Analyze modified tools
|
|
81
|
+
for (const toolDiff of diff.toolsModified) {
|
|
82
|
+
const oldTool = oldBaseline.tools.find(t => t.name === toolDiff.tool);
|
|
83
|
+
const newTool = newBaseline.tools.find(t => t.name === toolDiff.tool);
|
|
84
|
+
if (oldTool && newTool) {
|
|
85
|
+
const impact = analyzeToolChangeImpact(oldTool, newTool, oldBaseline.workflowSignatures || []);
|
|
86
|
+
toolImpacts.set(toolDiff.tool, impact);
|
|
87
|
+
if (impact.severity === 'breaking') {
|
|
88
|
+
totalBreakingChanges++;
|
|
89
|
+
actionItems.push({
|
|
90
|
+
priority: 'critical',
|
|
91
|
+
tool: toolDiff.tool,
|
|
92
|
+
description: `Breaking changes detected in "${toolDiff.tool}"`,
|
|
93
|
+
suggestedAction: impact.suggestedMigration,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
else if (impact.severity === 'warning') {
|
|
97
|
+
actionItems.push({
|
|
98
|
+
priority: 'high',
|
|
99
|
+
tool: toolDiff.tool,
|
|
100
|
+
description: `Significant changes detected in "${toolDiff.tool}"`,
|
|
101
|
+
suggestedAction: impact.suggestedMigration,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Analyze added tools (non-breaking but noteworthy)
|
|
107
|
+
for (const toolName of diff.toolsAdded) {
|
|
108
|
+
const impact = {
|
|
109
|
+
severity: 'info',
|
|
110
|
+
affectedWorkflows: [],
|
|
111
|
+
affectedParameters: [],
|
|
112
|
+
migrationComplexity: 'trivial',
|
|
113
|
+
suggestedMigration: `New tool "${toolName}" is available. No action required for existing consumers.`,
|
|
114
|
+
schemaChanges: [{
|
|
115
|
+
type: 'parameter_added',
|
|
116
|
+
parameterPath: toolName,
|
|
117
|
+
breaking: false,
|
|
118
|
+
before: null,
|
|
119
|
+
after: newBaseline.tools.find(t => t.name === toolName),
|
|
120
|
+
description: `New tool "${toolName}" has been added`,
|
|
121
|
+
}],
|
|
122
|
+
backwardsCompatible: true,
|
|
123
|
+
riskScore: 0,
|
|
124
|
+
};
|
|
125
|
+
toolImpacts.set(toolName, impact);
|
|
126
|
+
actionItems.push({
|
|
127
|
+
priority: 'low',
|
|
128
|
+
tool: toolName,
|
|
129
|
+
description: `New tool "${toolName}" is available`,
|
|
130
|
+
suggestedAction: 'Consider using this new tool if applicable to your use case',
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
// Find all broken workflows
|
|
134
|
+
const brokenWorkflows = [];
|
|
135
|
+
for (const [, impact] of toolImpacts) {
|
|
136
|
+
if (!impact.backwardsCompatible) {
|
|
137
|
+
brokenWorkflows.push(...impact.affectedWorkflows);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const uniqueBrokenWorkflows = [...new Set(brokenWorkflows)];
|
|
141
|
+
// Determine overall severity and complexity
|
|
142
|
+
const overallSeverity = determineOverallSeverity(toolImpacts, diff);
|
|
143
|
+
const overallMigrationComplexity = determineOverallComplexity(toolImpacts);
|
|
144
|
+
// Generate summary
|
|
145
|
+
const summary = generateImpactSummary(diff, toolImpacts, uniqueBrokenWorkflows);
|
|
146
|
+
// Sort action items by priority
|
|
147
|
+
const priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
148
|
+
actionItems.sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);
|
|
149
|
+
return {
|
|
150
|
+
overallSeverity,
|
|
151
|
+
breakingChangesCount: totalBreakingChanges,
|
|
152
|
+
toolImpacts,
|
|
153
|
+
brokenWorkflows: uniqueBrokenWorkflows,
|
|
154
|
+
overallMigrationComplexity,
|
|
155
|
+
summary,
|
|
156
|
+
actionItems,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Analyze changes between two schemas and return detailed change information.
|
|
161
|
+
*/
|
|
162
|
+
export function analyzeSchemaChanges(oldSchema, newSchema) {
|
|
163
|
+
const changes = [];
|
|
164
|
+
if (!oldSchema && !newSchema) {
|
|
165
|
+
return changes;
|
|
166
|
+
}
|
|
167
|
+
if (!oldSchema && newSchema) {
|
|
168
|
+
// Schema added (new tool or schema now defined)
|
|
169
|
+
return changes;
|
|
170
|
+
}
|
|
171
|
+
if (oldSchema && !newSchema) {
|
|
172
|
+
// Schema removed
|
|
173
|
+
changes.push({
|
|
174
|
+
type: 'parameter_removed',
|
|
175
|
+
parameterPath: 'inputSchema',
|
|
176
|
+
breaking: true,
|
|
177
|
+
before: oldSchema,
|
|
178
|
+
after: null,
|
|
179
|
+
description: 'Input schema has been removed',
|
|
180
|
+
});
|
|
181
|
+
return changes;
|
|
182
|
+
}
|
|
183
|
+
// Compare properties
|
|
184
|
+
const oldProps = oldSchema?.properties || {};
|
|
185
|
+
const newProps = newSchema?.properties || {};
|
|
186
|
+
const oldRequired = oldSchema?.required || [];
|
|
187
|
+
const newRequired = newSchema?.required || [];
|
|
188
|
+
// Check for removed parameters
|
|
189
|
+
for (const [name, oldProp] of Object.entries(oldProps)) {
|
|
190
|
+
if (!(name in newProps)) {
|
|
191
|
+
changes.push({
|
|
192
|
+
type: 'parameter_removed',
|
|
193
|
+
parameterPath: name,
|
|
194
|
+
breaking: true,
|
|
195
|
+
before: oldProp,
|
|
196
|
+
after: null,
|
|
197
|
+
description: `Parameter "${name}" has been removed`,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Check for added parameters
|
|
202
|
+
for (const [name, newProp] of Object.entries(newProps)) {
|
|
203
|
+
if (!(name in oldProps)) {
|
|
204
|
+
const isRequired = newRequired.includes(name);
|
|
205
|
+
changes.push({
|
|
206
|
+
type: isRequired ? 'parameter_required_added' : 'parameter_added',
|
|
207
|
+
parameterPath: name,
|
|
208
|
+
breaking: isRequired,
|
|
209
|
+
before: null,
|
|
210
|
+
after: newProp,
|
|
211
|
+
description: isRequired
|
|
212
|
+
? `New required parameter "${name}" has been added`
|
|
213
|
+
: `New optional parameter "${name}" has been added`,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// Check for modified parameters
|
|
218
|
+
for (const [name, oldProp] of Object.entries(oldProps)) {
|
|
219
|
+
const newProp = newProps[name];
|
|
220
|
+
if (newProp) {
|
|
221
|
+
const propChanges = analyzePropertyChanges(name, oldProp, newProp, oldRequired, newRequired);
|
|
222
|
+
changes.push(...propChanges);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return changes;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Analyze changes to a single property.
|
|
229
|
+
*/
|
|
230
|
+
function analyzePropertyChanges(paramName, oldProp, newProp, oldRequired, newRequired) {
|
|
231
|
+
const changes = [];
|
|
232
|
+
// Check type changes
|
|
233
|
+
if (oldProp.type !== newProp.type) {
|
|
234
|
+
changes.push({
|
|
235
|
+
type: 'parameter_type_changed',
|
|
236
|
+
parameterPath: paramName,
|
|
237
|
+
breaking: true,
|
|
238
|
+
before: oldProp.type,
|
|
239
|
+
after: newProp.type,
|
|
240
|
+
description: `Parameter "${paramName}" type changed from "${oldProp.type}" to "${newProp.type}"`,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
// Check required status changes
|
|
244
|
+
const wasRequired = oldRequired.includes(paramName);
|
|
245
|
+
const isRequired = newRequired.includes(paramName);
|
|
246
|
+
if (!wasRequired && isRequired) {
|
|
247
|
+
changes.push({
|
|
248
|
+
type: 'parameter_required_added',
|
|
249
|
+
parameterPath: paramName,
|
|
250
|
+
breaking: true,
|
|
251
|
+
before: 'optional',
|
|
252
|
+
after: 'required',
|
|
253
|
+
description: `Parameter "${paramName}" is now required (was optional)`,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
else if (wasRequired && !isRequired) {
|
|
257
|
+
changes.push({
|
|
258
|
+
type: 'parameter_required_removed',
|
|
259
|
+
parameterPath: paramName,
|
|
260
|
+
breaking: false,
|
|
261
|
+
before: 'required',
|
|
262
|
+
after: 'optional',
|
|
263
|
+
description: `Parameter "${paramName}" is now optional (was required)`,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
// Check enum changes
|
|
267
|
+
const oldEnum = oldProp.enum;
|
|
268
|
+
const newEnum = newProp.enum;
|
|
269
|
+
if (oldEnum && newEnum) {
|
|
270
|
+
// Check for removed enum values
|
|
271
|
+
for (const value of oldEnum) {
|
|
272
|
+
if (!newEnum.includes(value)) {
|
|
273
|
+
changes.push({
|
|
274
|
+
type: 'enum_value_removed',
|
|
275
|
+
parameterPath: `${paramName}.enum`,
|
|
276
|
+
breaking: true,
|
|
277
|
+
before: value,
|
|
278
|
+
after: null,
|
|
279
|
+
description: `Enum value "${value}" removed from parameter "${paramName}"`,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// Check for added enum values
|
|
284
|
+
for (const value of newEnum) {
|
|
285
|
+
if (!oldEnum.includes(value)) {
|
|
286
|
+
changes.push({
|
|
287
|
+
type: 'enum_value_added',
|
|
288
|
+
parameterPath: `${paramName}.enum`,
|
|
289
|
+
breaking: false,
|
|
290
|
+
before: null,
|
|
291
|
+
after: value,
|
|
292
|
+
description: `Enum value "${value}" added to parameter "${paramName}"`,
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// Check constraint changes (min, max, minLength, maxLength, pattern)
|
|
298
|
+
const constraintProps = ['minimum', 'maximum', 'minLength', 'maxLength', 'pattern', 'minItems', 'maxItems'];
|
|
299
|
+
for (const constraint of constraintProps) {
|
|
300
|
+
const oldValue = oldProp[constraint];
|
|
301
|
+
const newValue = newProp[constraint];
|
|
302
|
+
if (oldValue === undefined && newValue !== undefined) {
|
|
303
|
+
// Constraint added
|
|
304
|
+
const isTightening = isConstraintTightening(constraint, undefined, newValue);
|
|
305
|
+
changes.push({
|
|
306
|
+
type: isTightening ? 'constraint_tightened' : 'constraint_added',
|
|
307
|
+
parameterPath: `${paramName}.${constraint}`,
|
|
308
|
+
breaking: isTightening,
|
|
309
|
+
before: oldValue,
|
|
310
|
+
after: newValue,
|
|
311
|
+
description: `Constraint "${constraint}" added to parameter "${paramName}" (value: ${newValue})`,
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
else if (oldValue !== undefined && newValue === undefined) {
|
|
315
|
+
// Constraint removed
|
|
316
|
+
changes.push({
|
|
317
|
+
type: 'constraint_removed',
|
|
318
|
+
parameterPath: `${paramName}.${constraint}`,
|
|
319
|
+
breaking: false,
|
|
320
|
+
before: oldValue,
|
|
321
|
+
after: newValue,
|
|
322
|
+
description: `Constraint "${constraint}" removed from parameter "${paramName}"`,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
else if (oldValue !== newValue) {
|
|
326
|
+
// Constraint changed
|
|
327
|
+
const isTightening = isConstraintTightening(constraint, oldValue, newValue);
|
|
328
|
+
changes.push({
|
|
329
|
+
type: isTightening ? 'constraint_tightened' : 'constraint_relaxed',
|
|
330
|
+
parameterPath: `${paramName}.${constraint}`,
|
|
331
|
+
breaking: isTightening,
|
|
332
|
+
before: oldValue,
|
|
333
|
+
after: newValue,
|
|
334
|
+
description: `Constraint "${constraint}" changed from ${oldValue} to ${newValue} for parameter "${paramName}"`,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
// Check format changes
|
|
339
|
+
if (oldProp.format !== newProp.format) {
|
|
340
|
+
changes.push({
|
|
341
|
+
type: 'format_changed',
|
|
342
|
+
parameterPath: `${paramName}.format`,
|
|
343
|
+
breaking: true,
|
|
344
|
+
before: oldProp.format,
|
|
345
|
+
after: newProp.format,
|
|
346
|
+
description: `Format changed from "${oldProp.format}" to "${newProp.format}" for parameter "${paramName}"`,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
// Check default value changes
|
|
350
|
+
if (JSON.stringify(oldProp.default) !== JSON.stringify(newProp.default)) {
|
|
351
|
+
changes.push({
|
|
352
|
+
type: 'default_changed',
|
|
353
|
+
parameterPath: `${paramName}.default`,
|
|
354
|
+
breaking: false,
|
|
355
|
+
before: oldProp.default,
|
|
356
|
+
after: newProp.default,
|
|
357
|
+
description: `Default value changed for parameter "${paramName}"`,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
return changes;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Determine if a constraint change is tightening (more restrictive).
|
|
364
|
+
*/
|
|
365
|
+
function isConstraintTightening(constraint, oldValue, newValue) {
|
|
366
|
+
if (oldValue === undefined) {
|
|
367
|
+
// Adding a constraint is always tightening
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
370
|
+
const oldNum = typeof oldValue === 'number' ? oldValue : null;
|
|
371
|
+
const newNum = typeof newValue === 'number' ? newValue : null;
|
|
372
|
+
if (oldNum === null || newNum === null) {
|
|
373
|
+
// For pattern changes, any change is potentially breaking
|
|
374
|
+
return constraint === 'pattern';
|
|
375
|
+
}
|
|
376
|
+
switch (constraint) {
|
|
377
|
+
case 'minimum':
|
|
378
|
+
case 'minLength':
|
|
379
|
+
case 'minItems':
|
|
380
|
+
// Increasing minimum is tightening
|
|
381
|
+
return newNum > oldNum;
|
|
382
|
+
case 'maximum':
|
|
383
|
+
case 'maxLength':
|
|
384
|
+
case 'maxItems':
|
|
385
|
+
// Decreasing maximum is tightening
|
|
386
|
+
return newNum < oldNum;
|
|
387
|
+
default:
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Calculate risk score based on schema changes.
|
|
393
|
+
*/
|
|
394
|
+
function calculateRiskScore(changes) {
|
|
395
|
+
if (changes.length === 0) {
|
|
396
|
+
return 0;
|
|
397
|
+
}
|
|
398
|
+
let totalScore = 0;
|
|
399
|
+
for (const change of changes) {
|
|
400
|
+
totalScore += CHANGE_IMPACT.RISK_WEIGHTS[change.type] || 0;
|
|
401
|
+
}
|
|
402
|
+
// Normalize to 0-100
|
|
403
|
+
return Math.min(100, totalScore);
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Determine severity from risk score and breaking changes count.
|
|
407
|
+
*/
|
|
408
|
+
function determineSeverity(riskScore, breakingCount) {
|
|
409
|
+
if (breakingCount > 0 || riskScore >= CHANGE_IMPACT.SEVERITY_THRESHOLDS.breaking) {
|
|
410
|
+
return 'breaking';
|
|
411
|
+
}
|
|
412
|
+
if (riskScore >= CHANGE_IMPACT.SEVERITY_THRESHOLDS.warning) {
|
|
413
|
+
return 'warning';
|
|
414
|
+
}
|
|
415
|
+
if (riskScore >= CHANGE_IMPACT.SEVERITY_THRESHOLDS.info) {
|
|
416
|
+
return 'info';
|
|
417
|
+
}
|
|
418
|
+
return 'none';
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Calculate migration complexity based on changes.
|
|
422
|
+
*/
|
|
423
|
+
function calculateMigrationComplexity(changes) {
|
|
424
|
+
const breakingChanges = changes.filter(c => c.breaking);
|
|
425
|
+
const count = breakingChanges.length;
|
|
426
|
+
if (count <= CHANGE_IMPACT.COMPLEXITY_THRESHOLDS.trivial) {
|
|
427
|
+
return 'trivial';
|
|
428
|
+
}
|
|
429
|
+
if (count <= CHANGE_IMPACT.COMPLEXITY_THRESHOLDS.simple) {
|
|
430
|
+
return 'simple';
|
|
431
|
+
}
|
|
432
|
+
if (count <= CHANGE_IMPACT.COMPLEXITY_THRESHOLDS.moderate) {
|
|
433
|
+
return 'moderate';
|
|
434
|
+
}
|
|
435
|
+
return 'complex';
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Generate migration suggestion based on changes.
|
|
439
|
+
*/
|
|
440
|
+
function generateMigrationSuggestion(changes, toolName) {
|
|
441
|
+
const breakingChanges = changes.filter(c => c.breaking);
|
|
442
|
+
if (breakingChanges.length === 0) {
|
|
443
|
+
return `No migration required for "${toolName}". Changes are backwards compatible.`;
|
|
444
|
+
}
|
|
445
|
+
const suggestions = [`Migration guide for "${toolName}":`];
|
|
446
|
+
for (const change of breakingChanges) {
|
|
447
|
+
switch (change.type) {
|
|
448
|
+
case 'parameter_removed':
|
|
449
|
+
suggestions.push(`- Remove usage of parameter "${change.parameterPath}"`);
|
|
450
|
+
break;
|
|
451
|
+
case 'parameter_required_added':
|
|
452
|
+
suggestions.push(`- Add required parameter "${change.parameterPath}" to all calls`);
|
|
453
|
+
break;
|
|
454
|
+
case 'parameter_type_changed':
|
|
455
|
+
suggestions.push(`- Update "${change.parameterPath}" from ${change.before} to ${change.after}`);
|
|
456
|
+
break;
|
|
457
|
+
case 'enum_value_removed':
|
|
458
|
+
suggestions.push(`- Replace enum value "${change.before}" with a valid alternative`);
|
|
459
|
+
break;
|
|
460
|
+
case 'constraint_tightened':
|
|
461
|
+
suggestions.push(`- Ensure "${change.parameterPath}" meets new constraint: ${change.after}`);
|
|
462
|
+
break;
|
|
463
|
+
case 'format_changed':
|
|
464
|
+
suggestions.push(`- Update format of "${change.parameterPath}" from ${change.before} to ${change.after}`);
|
|
465
|
+
break;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
return suggestions.join('\n');
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Determine overall severity from all tool impacts.
|
|
472
|
+
*/
|
|
473
|
+
function determineOverallSeverity(toolImpacts, diff) {
|
|
474
|
+
// Removed tools are always breaking
|
|
475
|
+
if (diff.toolsRemoved.length > 0) {
|
|
476
|
+
return 'breaking';
|
|
477
|
+
}
|
|
478
|
+
// Check all tool impacts
|
|
479
|
+
let hasBreaking = false;
|
|
480
|
+
let hasWarning = false;
|
|
481
|
+
let hasInfo = false;
|
|
482
|
+
for (const [, impact] of toolImpacts) {
|
|
483
|
+
if (impact.severity === 'breaking') {
|
|
484
|
+
hasBreaking = true;
|
|
485
|
+
}
|
|
486
|
+
else if (impact.severity === 'warning') {
|
|
487
|
+
hasWarning = true;
|
|
488
|
+
}
|
|
489
|
+
else if (impact.severity === 'info') {
|
|
490
|
+
hasInfo = true;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
if (hasBreaking)
|
|
494
|
+
return 'breaking';
|
|
495
|
+
if (hasWarning)
|
|
496
|
+
return 'warning';
|
|
497
|
+
if (hasInfo)
|
|
498
|
+
return 'info';
|
|
499
|
+
return 'none';
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Determine overall migration complexity.
|
|
503
|
+
*/
|
|
504
|
+
function determineOverallComplexity(toolImpacts) {
|
|
505
|
+
const complexities = Array.from(toolImpacts.values()).map(i => i.migrationComplexity);
|
|
506
|
+
// Return the highest complexity
|
|
507
|
+
if (complexities.includes('complex'))
|
|
508
|
+
return 'complex';
|
|
509
|
+
if (complexities.includes('moderate'))
|
|
510
|
+
return 'moderate';
|
|
511
|
+
if (complexities.includes('simple'))
|
|
512
|
+
return 'simple';
|
|
513
|
+
return 'trivial';
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Generate a human-readable impact summary.
|
|
517
|
+
*/
|
|
518
|
+
function generateImpactSummary(diff, toolImpacts, brokenWorkflows) {
|
|
519
|
+
const parts = [];
|
|
520
|
+
// Tools summary
|
|
521
|
+
if (diff.toolsRemoved.length > 0) {
|
|
522
|
+
parts.push(`${diff.toolsRemoved.length} tool(s) removed: ${diff.toolsRemoved.join(', ')}`);
|
|
523
|
+
}
|
|
524
|
+
if (diff.toolsAdded.length > 0) {
|
|
525
|
+
parts.push(`${diff.toolsAdded.length} tool(s) added: ${diff.toolsAdded.join(', ')}`);
|
|
526
|
+
}
|
|
527
|
+
if (diff.toolsModified.length > 0) {
|
|
528
|
+
parts.push(`${diff.toolsModified.length} tool(s) modified`);
|
|
529
|
+
}
|
|
530
|
+
// Breaking changes summary
|
|
531
|
+
let breakingCount = 0;
|
|
532
|
+
for (const [, impact] of toolImpacts) {
|
|
533
|
+
breakingCount += impact.schemaChanges.filter(c => c.breaking).length;
|
|
534
|
+
}
|
|
535
|
+
if (breakingCount > 0) {
|
|
536
|
+
parts.push(`${breakingCount} breaking change(s) detected`);
|
|
537
|
+
}
|
|
538
|
+
// Workflows summary
|
|
539
|
+
if (brokenWorkflows.length > 0) {
|
|
540
|
+
parts.push(`${brokenWorkflows.length} workflow(s) may be affected`);
|
|
541
|
+
}
|
|
542
|
+
return parts.length > 0 ? parts.join('. ') + '.' : 'No changes detected.';
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Check if a behavior change is actually breaking based on semantic analysis.
|
|
546
|
+
* This enhances the simple hash-based comparison with semantic understanding.
|
|
547
|
+
*/
|
|
548
|
+
export function isBreakingChange(change) {
|
|
549
|
+
// Schema changes are always potentially breaking
|
|
550
|
+
if (change.aspect === 'schema') {
|
|
551
|
+
// Check if it's just a description change within schema
|
|
552
|
+
if (change.description.toLowerCase().includes('description')) {
|
|
553
|
+
return false;
|
|
554
|
+
}
|
|
555
|
+
return true;
|
|
556
|
+
}
|
|
557
|
+
// Error handling changes that go from success to failure are breaking
|
|
558
|
+
if (change.aspect === 'error_handling') {
|
|
559
|
+
if (change.before === 'succeeded' && change.after === 'failed') {
|
|
560
|
+
return true;
|
|
561
|
+
}
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
// Response structure changes could be breaking
|
|
565
|
+
if (change.aspect === 'response_structure') {
|
|
566
|
+
// Check for field removal
|
|
567
|
+
if (change.description.toLowerCase().includes('removed') ||
|
|
568
|
+
change.description.toLowerCase().includes('missing')) {
|
|
569
|
+
return true;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
return change.severity === 'breaking';
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Get a quick summary of breaking changes for CI output.
|
|
576
|
+
*/
|
|
577
|
+
export function getBreakingChangeSummary(analysis) {
|
|
578
|
+
if (analysis.breakingChangesCount === 0) {
|
|
579
|
+
return 'No breaking changes detected.';
|
|
580
|
+
}
|
|
581
|
+
const lines = [
|
|
582
|
+
`Breaking Changes (${analysis.breakingChangesCount}):`,
|
|
583
|
+
];
|
|
584
|
+
for (const item of analysis.actionItems.filter(a => a.priority === 'critical')) {
|
|
585
|
+
lines.push(` - ${item.tool}: ${item.description}`);
|
|
586
|
+
}
|
|
587
|
+
if (analysis.brokenWorkflows.length > 0) {
|
|
588
|
+
lines.push(`\nAffected Workflows: ${analysis.brokenWorkflows.join(', ')}`);
|
|
589
|
+
}
|
|
590
|
+
return lines.join('\n');
|
|
591
|
+
}
|
|
592
|
+
//# sourceMappingURL=change-impact-analyzer.js.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural comparison for drift detection.
|
|
3
|
+
*
|
|
4
|
+
* Compares baselines using deterministic structural comparison:
|
|
5
|
+
* - Tool presence/absence
|
|
6
|
+
* - Schema changes (hash comparison)
|
|
7
|
+
* - Description changes (exact string comparison)
|
|
8
|
+
* - Workflow success/failure changes
|
|
9
|
+
*
|
|
10
|
+
* All comparisons are 100% deterministic - no LLM involvement.
|
|
11
|
+
*/
|
|
12
|
+
import type { InterviewResult } from '../interview/types.js';
|
|
13
|
+
import type { BehavioralBaseline, BehavioralDiff, BehaviorChange, BehaviorAspect, CompareOptions, ChangeSeverity, VersionCompatibilityInfo, SeverityConfig } from './types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Compare current interview results against a baseline.
|
|
16
|
+
*/
|
|
17
|
+
export declare function compareWithBaseline(baseline: BehavioralBaseline, current: InterviewResult, serverCommand: string, options?: CompareOptions): BehavioralDiff;
|
|
18
|
+
/**
|
|
19
|
+
* Compare two baselines directly.
|
|
20
|
+
* All changes are structural and deterministic.
|
|
21
|
+
*
|
|
22
|
+
* @param previous - The baseline to compare against (source/old)
|
|
23
|
+
* @param current - The current baseline (target/new)
|
|
24
|
+
* @param options - Comparison options
|
|
25
|
+
* @returns Diff result including version compatibility information
|
|
26
|
+
* @throws BaselineVersionError if versions are incompatible and ignoreVersionMismatch is false
|
|
27
|
+
*/
|
|
28
|
+
export declare function compareBaselines(previous: BehavioralBaseline, current: BehavioralBaseline, options?: CompareOptions): BehavioralDiff;
|
|
29
|
+
export declare function hasBreakingChanges(diff: BehavioralDiff): boolean;
|
|
30
|
+
export declare function hasSecurityChanges(diff: BehavioralDiff): boolean;
|
|
31
|
+
export declare function filterByMinimumSeverity(diff: BehavioralDiff, minSeverity: ChangeSeverity): BehaviorChange[];
|
|
32
|
+
/**
|
|
33
|
+
* Compare two severity levels.
|
|
34
|
+
* Returns negative if a < b, positive if a > b, 0 if equal.
|
|
35
|
+
*/
|
|
36
|
+
export declare function compareSeverity(a: ChangeSeverity, b: ChangeSeverity): number;
|
|
37
|
+
/**
|
|
38
|
+
* Check if a severity meets or exceeds a threshold.
|
|
39
|
+
*/
|
|
40
|
+
export declare function severityMeetsThreshold(severity: ChangeSeverity, threshold: ChangeSeverity): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Apply aspect overrides to a behavior change.
|
|
43
|
+
* Returns the modified severity based on aspect overrides.
|
|
44
|
+
*/
|
|
45
|
+
export declare function applyAspectOverride(change: BehaviorChange, aspectOverrides?: Partial<Record<BehaviorAspect, ChangeSeverity>>): ChangeSeverity;
|
|
46
|
+
/**
|
|
47
|
+
* Apply severity configuration to a diff result.
|
|
48
|
+
* Returns a new diff with filtered/modified changes based on config.
|
|
49
|
+
*/
|
|
50
|
+
export declare function applySeverityConfig(diff: BehavioralDiff, config: SeverityConfig): BehavioralDiff;
|
|
51
|
+
/**
|
|
52
|
+
* Determine the appropriate exit code based on diff severity and config.
|
|
53
|
+
* Returns true if the check should fail (non-zero exit).
|
|
54
|
+
*/
|
|
55
|
+
export declare function shouldFailOnDiff(diff: BehavioralDiff, failOnSeverity?: ChangeSeverity): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Check if two baselines have compatible versions for comparison.
|
|
58
|
+
*
|
|
59
|
+
* @param baseline1 - First baseline
|
|
60
|
+
* @param baseline2 - Second baseline
|
|
61
|
+
* @returns Version compatibility information
|
|
62
|
+
*/
|
|
63
|
+
export declare function checkBaselineVersionCompatibility(baseline1: BehavioralBaseline, baseline2: BehavioralBaseline): VersionCompatibilityInfo;
|
|
64
|
+
//# sourceMappingURL=comparator.d.ts.map
|