CNA-VGAP-013: No gate checks include reachability or compiles each public C++ header alone; the two scripts that did are stale campaign tools wired to nothing
Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
check_include_reachability.py and check_header_self_containment.py hard-code the August 2026 module graph and are called by no CMake file, test or workflow, and no current gate compiles each framework public C++ header in isolation.
- Identifier
CNA-VGAP-013- Category
- Verification gap
- Subsystem
- Build & CI
- Status
- Open
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - Evidence basis
- Source-verified: read at TARGET, not executed
- Tests touching this area
- Yes: see Current tests
- Affected contract
- modularization/tools/check_include_reachability.py; modularization/tools/check_header_self_containment.py; the physical module include contract
Expected behaviour
CNA's own physical-modules.md lists check_include_reachability.py under Validators: every #include "CNA/..." in every module TU must resolve through the declared module graph. A header self-containment check (each public header compiles alone against its module's include closure) is the compile-side complement of the link probes.
Actual behaviour at TARGET
Both scripts under modularization/tools/ hard-code the module graph of the August 2026 split: fourteen framework modules, no platform, diagnostics, design, phone, inspector, content-pipeline, video-ffmpeg or c-api, and a renderer-family table from before the renderer set was curated. By reading, the reachability table cannot reach the platform module from runtime, graphics, input or audio sources that include CNA/Platform headers, so running it today would report false violations. No file under cmake/, .github/workflows/ or scripts/ invokes either script.
The only compile-side header gates that exist are narrower: ContractIsSdlFreeTests.cpp compiles all platform contract headers together in one TU, and CApiHeaderCompatibility compiles only the C headers.
Source locations
modularization/tools/check_include_reachability.py— PUBLIC, PRIVATE and FAMILY tablesmodularization/tools/check_header_self_containment.py— PUBLIC tabledocs/physical-modules.md— Validators list naming check_include_reachability.pymodules/platform/tests/CNA/Platform/ContractIsSdlFreeTests.cpp— one TU including every platform contract headercmake/Tests/ModuleProbes.cmake— CApiHeaderCompatibility registration (C headers only)
Evidence
Checked by reading the named sources at 009d40f5; nothing was built or executed for this entry. A grep of cmake/, .github/workflows/ and scripts/ at 009d40f5 found no caller. The scripts were not run, so the exact false-positive set is inferred from their tables.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
Link-side closure is covered by ModuleProbes.cmake (with the caveat in CNA-VGAP-019). Nothing checks include-side reachability or per-header self-containment for the C++ surface.
Regression test
Regenerate the module tables from the CMake target graph (or read them from a configure-time export), then register both scripts as CTest cases that fail on a violation; a planted header that includes an undeclared module's header must fail them.
Blast radius
Any change that adds an undeclared include edge between modules, or a public header that compiles only after another include. Consumers that include a single CNA header first are the ones who would see the failure.
Workaround
No workaround is known.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Internals
- Module graph
- Known issues
- Verification gap index