CNA-VGAP-019: The HEADLESS native-SDK-free and VULKAN link-closure gates run in no CI job
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 c1c316b9; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
Since AM4-167 the link-closure check also reads a Ninja tree's link line, so general-tests-ci.yml evaluates the gates of its OPENGLES3 tree; the NativeSdkFree_*, GraphicsNativeSdkFree and VulkanRendererClosure gates exist only in trees whose CI jobs never select them.
- Identifier
CNA-VGAP-019- Category
- Verification gap
- Subsystem
- Testing & evidence
- Status
- Narrowed (partially fixed; describes only what survives)
- Verified against
- CNA
c1c316b9(c1c316b9c7a846ce8002809c151fcd1af14942c9) - Evidence basis
- Source-verified: read at TARGET, not executed
- Tests touching this area
- Yes: see Current tests
- Affected contract
- The ModuleLinkClosure_NativeSdkFree_*, ModuleLinkClosure_GraphicsNativeSdkFree and ModuleLinkClosure_VulkanRendererClosure CTests registered by cmake/Tests/ModuleProbes.cmake
Expected behaviour
ModuleProbes.cmake describes each probe and its ModuleLinkClosure_* partner as "turning every module's real dependency closure into a permanent contract", and check_module_link_closure.py as "a permanent, mechanically checked contract": for example probe_math may link nothing but the math archive and Sharp Runtime, and the HEADLESS tree must show that renderer-neutral graphics needs no native graphics SDK. A contract of that kind is evidence only if some routine run evaluates it.
Actual behaviour at TARGET
check_module_link_closure.py now reads link.txt or, in a single-config Ninja tree, the target's final command from ninja -t commands -s, and returns 77 only when neither exists, so the unfiltered ctest of general-tests-ci.yml (Ninja, OPENGLES3) evaluates every closure gate that tree registers. ModuleProbes.cmake registers the native-SDK-free gates (ModuleLinkClosure_NativeSdkFree_*, ModuleLinkClosure_GraphicsNativeSdkFree) only when CNA_GRAPHICS_RENDERER is HEADLESS without multi-renderer, and ModuleLinkClosure_VulkanRendererClosure only in a single-renderer VULKAN tree. The CI jobs that configure such trees run labelled or named selections that leave these gates out (input-ci.yml runs -L input, gltf-renderer-stride-ci.yml -L gltf-conformance, platform-ci.yml only the CnaPlatform* suites), content-pipeline-windows-ci.yml runs no ctest, and multi-renderer-ci.yml's HEADLESS tree is multi-renderer, where the gates are not registered.
Source locations
scripts/check_module_link_closure.py— main and ninja_link_line: link.txt, else the Ninja final command, else exit 77cmake/Tests/ModuleProbes.cmake— the HEADLESS-only NativeSdkFree_*/GraphicsNativeSdkFree and VULKAN-only VulkanRendererClosure registrations.github/workflows/general-tests-ci.yml— -G Ninja OPENGLES3 configure and the unfiltered ctest run.github/workflows/input-ci.yml— VULKAN and other single-renderer cells run ctest -L input only.github/workflows/gltf-renderer-stride-ci.yml— HEADLESS and VULKAN cells run ctest -L gltf-conformance only
Evidence
Checked by reading check_module_link_closure.py, ModuleProbes.cmake and every workflow under .github/workflows for its renderer, generator and ctest selection at c1c316b9; not executed.
Narrowed at c1c316b9: 12ab7471b (AM4-167) added ninja_link_line, so the gates no longer report SKIP in a single-config Ninja tree; CNA records 28 of 28 gates measured and passing on its Mac (plans/plan_apple_m4.md, AM4-167). What survives is that the HEADLESS and VULKAN closure gates, which exist only in single-renderer trees of those identities, are selected by no CI job; a multi-config generator still gets exit 77.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
The gates are the tests. The OPENGLES3 tree's gates (ModuleLinkClosure_probe_math, _probe_storage and the rest) run in general-tests-ci.yml; the HEADLESS and VULKAN gates run only where someone runs ctest by hand in such a tree.
Regression test
Add -R '^ModuleLinkClosure_' to a single-renderer HEADLESS cell and to a single-renderer VULKAN cell (for example in gltf-renderer-stride-ci.yml), or give the gates a label one of those jobs already selects.
Blast radius
Evidence only: a native graphics SDK leaking into the renderer-neutral HEADLESS closure, or a forbidden input reaching the VULKAN renderer's closure, would not be caught by any automated run. No shipped behaviour is affected.
Workaround
Evaluate the gates in a single-renderer HEADLESS or VULKAN tree configured with CNA_BUILD_TESTS=ON: ctest -R '^ModuleLinkClosure_'.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Maintainer workflow
- Conventions that are enforced
- Reference
- Test targets
- Known issues
- Verification gap index