/** * certify_merge — the merge semantic certificate (change: add-merge-semantic-certificate). * * Catches the disjoint-footprint failure textual merge cannot see: branch A adds a call to * `parseConfig`; branch B — touching entirely different files — renames a parameter, narrows its * type, or removes the export. Each branch is green alone, the merge is green textually, the * combination is broken. Completes the coordination arc: plan_parallel_work (before dispatch) → * map_in_flight_conflicts (in flight) → certify_merge (at landing). * * How: build the call graph at the merge-base and at each side, compute each side's changed * (signature) / removed symbols (classified with the public-surface breaking-change rules), and * cross-join — one side's breaking/removed symbols × the OTHER side's ADDED call/import edges into * them, both directions. A rename handled within a branch never crosses the branch boundary, so a * migrated rename is not a false conflict; a call the other branch adds to the old name is. * * Honest: a change that cannot be proven compatible is `potentially-incompatible`, never silently * compatible; the verdict is a sound lower bound ("no detected incompatibility", never "safe"); * unresolvable refs are fatal; unindexed languages and diff-fetch failures are disclosed. Advisory * finding `merge-semantic-conflict`. Siblings: map_in_flight_conflicts (footprint overlap in * flight) and the merge-tree oracle (will git textually conflict) vs this (what breaks when it does * not). The `openlore certify-merge` CLI and retained-edge (non-added) conflicts are follow-ups. */ import type { CallEdge, FunctionNode } from '../../analyzer/call-graph-types.js'; import { type ChangeClass } from '../../analyzer/public-surface.js'; export interface CertifyMergeInput { directory: string; ours: string; theirs: string; /** Explicit base; defaults to the merge-base of ours/theirs. */ base?: string; maxFindings?: number; } /** A symbol one side changed or removed relative to the base, with its breaking classification. */ export interface ChangedSymbol { id: string; name: string; /** 'removed' | the signature-change class. */ kind: 'removed' | ChangeClass; ruleCodes: string[]; } interface MergeFinding { verdict: 'incompatible' | 'potentially-incompatible'; side: string; changedBy: string; caller: string; callee: string; line: number | undefined; rule: string; } /** Simple call graph shape the join needs. */ interface Graph { nodes: Map; edges: CallEdge[]; } /** Symbols the `side` graph changed (signature) or removed relative to `base`. Pure. */ export declare function changedSymbols(base: Graph, side: Graph): ChangedSymbol[]; /** Edges the `side` graph ADDED relative to `base` (direct calls only). Pure. */ export declare function addedEdges(base: Graph, side: Graph): CallEdge[]; /** * Cross-join: for each edge the `addingSide` added, if its callee is a symbol the `changingSide` * broke or removed, emit a conflict. `incompatible` for a removal or a breaking signature change; * `potentially-incompatible` for anything only potentially-breaking. Pure. */ export declare function crossJoin(addingSide: string, added: readonly CallEdge[], changingSide: string, changed: readonly ChangedSymbol[], nameOf: (id: string) => string | undefined): MergeFinding[]; export declare function handleCertifyMerge(input: CertifyMergeInput): Promise>; export {}; //# sourceMappingURL=merge-semantic-certificate.d.ts.map