/** * The risk axes of a computed plan, counted once. * * The human readout has always shown these ("2 destructive, 1 with data * loss", "may replace" per row) while the structured detail carried to agent * surfaces carried only a total. That asymmetry is the reason this lives in * its own module rather than inside the renderer: two surfaces answering * "how risky is this apply?" differently is the drift, and a renderer is not * a place another producer can import from without depending on formatting. * * Counts are per-axis and never derived by subtraction. A row can be an * `update` action AND carry `replacementMode: "may"`, so the action counts in * `ChangeCounts` cannot answer the replacement question — and a bucket * computed as `total - known` would silently absorb a replacement mode added * to the union later. */ import type { ReplacementMode } from "../../../types/deployEvent.js"; import type { DeployPlanResourceChange } from "./types.js"; /** Per-replacement-mode row counts, one key per {@link ReplacementMode}. */ export type ReplacementModeCounts = Record; export interface PlanRiskCounts { /** Row counts by replacement verdict. Keys track REPLACEMENT_MODES exactly. */ replacement: ReplacementModeCounts; /** Replace OR destroy — a true mutation loss (orphan/retain is NOT this). */ destructive: number; /** Destructive AND stateful: the data would not survive the apply. */ dataLoss: number; /** Removed from the stack but physically retained by a DeletionPolicy. */ retained: number; } /** Count the risk axes of a plan's rows. Pure; safe on an empty plan. */ export declare function summarisePlanRisk(changes: readonly DeployPlanResourceChange[]): PlanRiskCounts;