# 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.
