# Lineage graph inputs `pipewhy.lineage.LineageGraph` validates C1 copy/transform/derived edge arrays against explicit artifact, evidence and transform ID contexts. `LineageContext` records the source namespace/declaration version, scope and inventory coverage. The graph borrows read-only exports and requires stable source aliases; it preserves original edge positions and supplies a separate immutable sorted artifact index. Cycles and parallel edges are allowed. Containment remains separate. `LineageIndex(graph)` builds flat forward/reverse adjacency indexes. `reachable(index, artifact_id)` returns unique downstream IDs; `direction="reverse"` finds ancestors. Relation filters and an explicit `include_self` option control selection. Results retain scope coverage/failures and owned immutable ID arrays. `check_copy(graph, observations, edge_id, evidence=...)` keeps captured content status separate from a check qualified by selected `Evidence` metadata. Missing provenance or reads stay unknown, while observed differences remain visible. These local checks describe captured content and declared dependence. `RetainedRecords` and `check_retained_records` bind explicitly supplied historical C2 rows to their snapshot metadata and observed fingerprint. Missing value retention stays unavailable; the checker never fills it from a live source. `check_cents_to_dollars` compares selected C2 integer/Decimal amounts exactly, with explicit unavailable/unsupported outcomes and bounded payload work. `check_transform` evaluates the versioned `TransformRule` for keyed cents-to-dollars datasets using retained rows verified against their captured fingerprints. Reordered rows align by typed integer keys; duplicates, missing keys and unavailable evidence have explicit outcomes. It preserves raw content differences separately from the qualified transform result. `divergence_candidates(index, before, after, checks=...)` selects direct historical content changes and links selected checks by changed source/target role. It retains uncertain comparison rows and missing graph/check evidence; candidates carry no claim of proven cause. `rank_earliest(divergence, windows)` ranks explicitly bound `ObservationWindows` within declared clock domains. Tied/overlapping windows and unknown clocks remain unresolved; no operation time is inferred from declarations. `impact(index, start_ids, divergence=...)` returns unique declared downstream exposure and a separate observed content-change label. Cycles, shared descendants and repeated starts do not inflate counts. Missing observations and incomplete graph coverage remain explicit. `incident_observations(ranking, IncidentPolicy(...))` prepares full canonical grouping/observation identities and explicit temporal eligibility. `IncidentRegistry(...).register(...)` returns a new registry and stable assignments: exact repeats reuse IDs, while known intervals can recur inside an anchored window. Unknown timing and late observations remain separate. `export_arrays()` and `IncidentRegistry.from_arrays(...)` preserve those IDs through C5 storage with strict state replay validation. Original analysis evidence remains necessary for explanations. `ANALYSIS_SCHEMA_VERSION` and `tests/fixtures/lineage_schema_v1.json` publish the analysis boundary for downstream query/CLI consumers, including separate status families and required uncertainty.