/** * Artifact diff — pack-shaped structured comparison, not generic text diff. * * Laws: * - Same-pack only. Cross-pack diffs throw loudly. * - Lists diff as {added, removed, unchanged} matched on a primary key * field per item kind. No "changed" bucket in this slice — keep it * boring and legible. * - Narrative fields diff as {before, after}. release_note_draft also * carries a compact LCS line diff because that's where it materially * helps review. * - Evidence is summarized (counts + referenced paths + path delta), * never exploded chunk-by-chunk. * - Weak flip gets top billing — surfaced at the envelope level, not * buried inside the per-field diff. * - Deterministic ordering: every list is sorted by its primary key * before returning. */ import type { PackArtifact } from "./scan.js"; export interface ListDiff { added: T[]; removed: T[]; unchanged: T[]; } export interface StringDiff { before: string; after: string; } export type LineOp = "same" | "add" | "remove"; export interface LineDiffEntry { op: LineOp; line: string; } export interface ReleaseNoteDiff extends StringDiff { line_diff: LineDiffEntry[]; } export interface WeakFlip { a: boolean; b: boolean; flipped: boolean; /** Present only when flipped: "weakened" (strong → weak) or "strengthened" (weak → strong). */ direction?: "weakened" | "strengthened"; } export interface EvidenceSummary { a: { count: number; referenced_paths: string[]; }; b: { count: number; referenced_paths: string[]; }; path_delta: { added: string[]; removed: string[]; }; } export interface IncidentDiff { root_cause_hypotheses: ListDiff<{ hypothesis: string; confidence: string; }>; affected_surfaces: ListDiff<{ surface: string; }>; timeline_clues: ListDiff<{ clue: string; }>; next_checks: ListDiff<{ check: string; why: string; }>; coverage_notes: ListDiff; evidence_summary: EvidenceSummary; } export interface ExtractedFactsDiff { a_present: boolean; b_present: boolean; package_names?: ListDiff; entrypoints?: ListDiff<{ file: string; purpose: string; }>; scripts?: ListDiff<{ name: string; command: string; }>; config_files?: ListDiff; exposed_surfaces?: ListDiff; runtime_hints?: ListDiff; scripts_touched?: ListDiff; config_surfaces?: ListDiff; } export interface RepoDiff { repo_thesis: StringDiff; architecture_shape: StringDiff; key_surfaces: ListDiff<{ surface: string; why: string; }>; risk_areas: ListDiff<{ risk: string; }>; read_next: ListDiff<{ file: string; why: string; }>; coverage_notes: ListDiff; extracted_facts: ExtractedFactsDiff; evidence_summary: EvidenceSummary; } export interface ChangeDiff { change_summary: StringDiff; why_it_matters: StringDiff; affected_surfaces: ListDiff<{ surface: string; }>; likely_breakpoints: ListDiff<{ breakpoint: string; }>; validation_checks: ListDiff<{ check: string; why: string; }>; release_note_draft: ReleaseNoteDiff; coverage_notes: ListDiff; extracted_facts: ExtractedFactsDiff; evidence_summary: EvidenceSummary; } export interface ArtifactDiffIdentity { slug: string; created_at: string; title: string; } export type ArtifactDiffResult = ({ pack: "incident_pack"; a: ArtifactDiffIdentity; b: ArtifactDiffIdentity; weak: WeakFlip; diff: IncidentDiff; }) | ({ pack: "repo_pack"; a: ArtifactDiffIdentity; b: ArtifactDiffIdentity; weak: WeakFlip; diff: RepoDiff; }) | ({ pack: "change_pack"; a: ArtifactDiffIdentity; b: ArtifactDiffIdentity; weak: WeakFlip; diff: ChangeDiff; }); /** * Compact LCS-based line diff. Used only for release_note_draft where * it materially helps review. O(m*n); release notes are tiny so this * is trivial in practice. */ export declare function lineDiff(before: string, after: string): LineDiffEntry[]; export declare function diffArtifacts(a: PackArtifact, b: PackArtifact): ArtifactDiffResult; //# sourceMappingURL=diff.d.ts.map