/** * Blast-radius risk scoring. * * Composes three signals — dependency breadth, test coverage of dependents, * and complexity of dependents — into a single RiskLevel. Intended as a * shared primitive for both the MCP `get_dependents` response and the * review-side blast-radius injection. */ import { type RiskLevel } from '../insights/types.js'; export interface BlastRadiusRiskInput { /** Distinct dependents across all hops. */ dependentCount: number; /** Dependents with no associated test file. */ uncoveredDependents: number; /** Max complexity (cyclomatic or cognitive) among dependents. Optional. */ maxDependentComplexity?: number; /** * True when at least one untested dependent has high complexity. * Supplied by the caller to keep this helper independent of any * specific complexity-report shape. */ hasHighComplexityUncovered?: boolean; /** * Already-classified complexity tier across dependents (e.g. * `ComplexityMetrics.complexityRiskBoost`), independent of test coverage. * Optional -- callers that don't compute one (no floor applied) behave * exactly as before this field existed. * * A high/critical complexity signal describes dependents that are hard to * change safely; full test coverage lowers the odds of a *silent* break, * it doesn't shrink that blast radius. Without this, a fully-tested file * with a critical-complexity caller could come back `riskLevel: "low"` * despite its own `complexityRiskBoost` reading `"critical"` (#933) -- * `classifyLevel` below only ever looked at complexity through * `hasHighComplexityUncovered`, which requires an untested dependent to * fire at all, so "high complexity, zero untested" had no path to * escalate anything. */ complexityRiskBoost?: RiskLevel; } export interface BlastRadiusRisk { level: RiskLevel; /** * Short phrases describing why the level was assigned, in the order they * contributed. Used verbatim by renderers (e.g. "14 callers, 3 untested, * max complexity 18, untested high-complexity dependent"). */ reasoning: string[]; } /** * Compute a consolidated risk level for a blast radius. * * Thresholds are deliberately conservative — the goal is to surface risk, not * to be statistically rigorous. Callers that want finer control should consume * the raw input fields directly. * * The result is monotonic in `complexityRiskBoost`: it is never raised below * `complexityFloor(complexityRiskBoost)` (see that function's doc comment), * so a `high`/`critical` boost can never be paired with a `low` verdict. */ export declare function computeBlastRadiusRisk(input: BlastRadiusRiskInput): BlastRadiusRisk; //# sourceMappingURL=blast-radius-risk.d.ts.map