/** * Impact analysis + re-certification gating for DQL's answer layer. * * DQL composition is unbounded freeform `ref()`. The safety net: when a block * changes, you must know what downstream *certified* work it invalidates. * * Given changed block name(s) — from `dql diff` or explicit input — this module: * 1. walks the dependency DAG **downstream** to the full transitive set, * 2. flags the cross-domain edges that get invalidated, * 3. computes the resulting `domainTrust` delta, * 4. produces a **required re-cert** list (certified downstream depending on * a changed block's semantics). * * It also classifies whether a given block change is *semantic* (affects what * the block computes) or purely cosmetic (description/owner/tag/viz only). * The classification is **conservative**: when unsure, treat the change as * semantic so re-cert is required rather than silently skipped. * * This is the LOCAL engine. It does not manage org-wide workflow, approvals, * audit, or auto-re-certification — that is the cloud product. */ import type { LineageGraph } from './lineage-graph.js'; import type { DiffChange } from '../format/diff.js'; /** Reason a changed block was (or was not) classified as a semantic change. */ export type SemanticVerdict = 'semantic' | 'non-semantic'; export interface ChangedBlock { /** Block name (matches `block:` in the lineage graph). */ name: string; /** * Optional exact lineage node id. When omitted, impact analysis keeps the * historic block-only behavior and resolves `block:${name}`. */ nodeId?: string; /** Whether the change affects what the block computes. */ verdict: SemanticVerdict; /** Field paths that changed (for block-changed diffs). */ changedFields: string[]; /** True when the block was added or removed (always semantic). */ structural: boolean; } /** * Classify a single block-level `DiffChange` as semantic or non-semantic. * * - Added/removed blocks are always semantic (structural). * - A changed block is non-semantic only when **every** changed field is in * {@link NON_SEMANTIC_BLOCK_FIELDS}. A single unrecognized or semantic field * makes the whole change semantic (conservative default). */ export declare function classifyBlockChange(change: DiffChange): ChangedBlock | null; /** * Extract the set of changed blocks from a diff report's changes, classifying * each as semantic or non-semantic. Non-block changes (dashboards, workbooks, * cells, notebooks) are ignored here — impact is keyed off block identity. */ export declare function changedBlocksFromDiff(changes: DiffChange[]): ChangedBlock[]; export interface ImpactedNode { id: string; type: string; name: string; domain?: string; status?: string; owner?: string; } export interface CrossDomainImpact { from: string; to: string; /** Invalidated boundary edges: source feeds a target in another domain. */ edges: Array<{ source: string; target: string; }>; } export interface DomainTrustDelta { domain: string; /** Certified count before vs. after re-cert demotions. */ certifiedBefore: number; certifiedAfter: number; total: number; trustBefore: number; trustAfter: number; /** trustAfter - trustBefore (≤ 0). */ delta: number; } export interface RecertItem { id: string; type: string; name: string; domain?: string; owner?: string; status?: string; filePath?: string; recommendedStatus?: 'pending_recertification'; /** The changed block(s) whose semantics this artifact transitively depends on. */ invalidatedBy: string[]; } export interface ImpactReport { /** Changed blocks that were analyzed (semantic + non-semantic). */ changedBlocks: ChangedBlock[]; /** Changed blocks with a semantic verdict — only these propagate impact. */ semanticChanges: string[]; /** Full transitive downstream set across all semantic changes (excludes domain nodes). */ downstream: ImpactedNode[]; /** Cross-domain edges inside the invalidated zone, grouped by from→to. */ crossDomainImpacts: CrossDomainImpact[]; /** Certified artifacts that must be re-certified. */ requiresRecert: RecertItem[]; /** Per-domain trust delta caused by demoting the re-cert set. */ domainTrustDelta: DomainTrustDelta[]; /** True when certified downstream is invalidated and not already pending re-cert. */ hasCertifiedInvalidation: boolean; } export interface ComputeImpactOptions { /** * When true (default), a re-cert is only required for downstream nodes still * marked `certified`. Nodes already `pending_recertification` are reported in * the downstream set but do not, on their own, trip the gate — they are * already flagged. Set false to also count `pending_recertification`. */ ignoreAlreadyPending?: boolean; } /** * Compute the impact of a set of changed blocks against a lineage graph. * * Only blocks with a **semantic** verdict propagate downstream impact; a purely * cosmetic change (description/owner/tag only) produces an empty downstream set * and never trips the re-cert gate. */ export declare function computeImpact(graph: LineageGraph, changedBlocks: ChangedBlock[], options?: ComputeImpactOptions): ImpactReport; /** * One-shot helper: classify a diff's block changes and compute the impact * report in a single call. */ export declare function computeImpactFromDiff(graph: LineageGraph, changes: DiffChange[], options?: ComputeImpactOptions): ImpactReport; /** Render an impact report as human-readable text for the CLI. */ export declare function renderImpactText(report: ImpactReport): string; //# sourceMappingURL=impact.d.ts.map