Header-pass body coverage is one blanket header_inline_bodies unit, not per body¶
Index: Known gaps
Status (updated 2026-10-14 at 54ab356ea): PARTIAL, narrowed. Recorded 2026-10-11 at 2a1ccb0c8 as OPEN: model/source_graph_coverage.py gave a header-only pass exactly one covered unit, HEADER_INLINE_BODIES, for the body-dependent kinds (DECL_CALLS_DECL, DECL_REFERENCES_DECL), and no fact recorded which function bodies were fully seen on each side.
What is fixed¶
- Per-declaration body fact.
call_graph.collect_function_bodieslists every function declaration whose body (aCompoundStmt) the header AST carries, using the call walker's own scope tracking and identity. Both projection paths (project_header_graph_ast, the streamedproject_header_graph_ast_file), the bisected-parse merge and the projection cache carry it asHeaderGraphAstProjection.function_bodies.seed_ast_graphmarks each already-seededdecl://node with theheader_bodyattribute (model.source_graph_coverage.HEADER_BODY_ATTR); it lives in the existing free-form nodeattrs, so no stored-schema field changed. - Per-body judgement.
source_graph_coverage.bodies_seenreads that fact: every body for a confirmed build-integrated pass, the marked nodes for a clean header-only pass, and nothing for a narrowed, degraded or absent one.body_scoped_closuresadmits a body-dependent kind that neither side trusts project-wide only for edges whose source body was seen on both sides, and drops that kind's other edges from both closures._internal_dependency_findings(PUBLIC_API_INTERNAL_DEPENDENCY_ADDED) uses it, so a call or reference added inside an inline function visible on both sides is now reported, and one whose body is out of line on either side is still declined. - Regression tests:
tests/test_header_body_coverage.py(every seen/unseen body shape for one entry, an exhaustive two-entry domain, non-call references, producer and cache round-trips).
What remains¶
false-clean — Two readers still use the blanket unit:
pass_coverage_records(and socompare.edge_query'sEdgeEvidence.query/source_graph_covers) still gives a header pass the singleHEADER_INLINE_BODIESunit for the body kinds, so an edge query about one body answersunknowneven when that body is marked seen. Fixing it needs per-declaration units inCoverageRecord's scope vocabulary (today compile-unit paths), which is a coverage-model design change, not a reader change._call_reachability_findings(CALL_GRAPH_PUBLIC_ENTRY_REACHABILITY_CHANGED) still requires whole-projectDECL_CALLS_DECLcoverage on both sides. Its transitive reachability count would need every body along each path seen on both sides.
The fact records presence only, not the body's digest; ADR-077 D5's digest would let a reader tell "body unchanged" from "body changed" without the edges, and is not needed by the readers above. Owner: ADR-077 D5.