Verification tiers: evidence forms, oracle authority and CI reporting

CNA snapshot 009d40f5  ·  Deep Dives › Reference matrices  ·  source links pinned to 009d40f5

✓

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. Read from the workflow files, CMake registrations, tools and tests at 009d40f5. No workflow, test, benchmark or gate was run; whether any job is green was not checked. Benchmark and Inspector end-to-end figures are CNA's own records.

This reference is a decoding key for verification claims about CNA at snapshot 009d40f5. It does not rank tests on one line from weak to strong: a compile probe, a hostile-input test, a pixel comparison and a native-host run answer different questions. The useful record is an evidence vector naming the subject, the build and host, proof that the intended route engaged, the observation point, the oracle and the retained artifact. The tables below give the claim labels, what each evidence form does and does not establish (with a CNA instance of each), which authority decides which question, what CNA's automation actually runs, and how to report a CI result without overclaiming. The vocabulary itself is defined on Compatibility levels and the evidence vector; this page applies it.

Claim labels

The labels describe what was established; none is a synonym for "supported". The right-hand column gives the nearest term of the evidence scale these pages use (source exists, configures, builds, links, unit tested, integration tested, runtime observed, visual compared, real hardware observed, XNA oracle compared).

LabelMinimum evidenceNearest site term
Source-provenA pinned implementation, fallback, refusal or absence was inspected along a reachable source routesource exists (source-verified)
Compile-provenThe named declarations, includes, templates and link closure compiled in a recorded configurationconfigures, builds, links
Runtime-observedThe named path executed and yielded the recorded state, value, file, trace or lifecycle eventunit tested or integration tested when an assertion judged it; runtime observed otherwise
Renderer-engagedThe intended renderer family and its native or translation API were identified during executionruntime observed, with the engagement token named
Oracle-comparedAn observation was compared with an identified authority under a stated policyXNA oracle compared when the authority is real XNA
Pixel-verifiedSelected pixels or a frame were compared at a named readback boundary, renderer, host and tolerancevisual compared
Manually observedA person inspected the output without a retained, discriminating oraclereal hardware observed, when that is where it happened
Historically recordedA dated artifact reports the result; it was not rerun for the claimCNA-recorded, with date and configuration
BlockedA named external precondition stopped the attempted route before its subjectnot executed, with the reason
UnsupportedThe pinned implementation has an explicit refusal, an absent factory or a documented lack of the pathsource exists (for the refusal)
Not attemptedNo execution claim is made; source or compile evidence may still existnot executed

"Test exists", "test was registered", "test ran" and "oracle discriminated" are four separate statements. A skipped test is not a pass, a dry-run mutation is not a killed mutation, and an uploaded log is useful only when it identifies the binary, configuration, host and observation that produced it.

Evidence forms are not interchangeable

Evidence formA green result establishesIt does not establishCNA instance at 009d40f5
Header or compile probeNames, signatures, templates, includes and link closure are usable in the selected buildRuntime semantics, resource creation, rendering or host engagementThe fifteen ModuleProbe_* consumers; the C API header compatibility matrix
Strict-XNA positive probeCode restricted to the intended XNA surface compiles with CNA_STRICT_XNA_APIThat the negative guard catches a leaked extensionStrictXnaApiSurfaceCheck_Compile_Run
Strict-XNA negative probeA deliberate CNAEXT call fails compilation, so the guard is sensitiveCoverage of every unmarked or misclassified declarationStrictXnaApiSurfaceLeakCheck_MustFailToCompile (Devices and sensors only)
Pure deterministic testA value, transition, parser result or exception matches its asserted oracle on that hostRenderer, window-system, driver or external-runtime engagementMost of the CnaMathTests and CnaContentTests corpus
Hostile-input testA named malformed boundary rejects, contains or reports the input as assertedCorrect behaviour for valid data, or completeness of the malformed corpusThe deterministic fuzz-named suites, for example LzxDecoderFuzzTests.cpp
Trace or HEADLESS testRouting, validation, counters or state order reached the trace implementationRasterisation, GPU work, visible pixels or real occlusion samplesThe HEADLESS renderer's Validation and Trace modes
Source-path auditAt the pinned revision a reachable implementation, refusal, fallback or parameter loss is visible in sourceSuccessful compilation or execution on a required hostEvery "checked by reading" statement on these pages
Readback or small-pixel testThe exercised renderer produced the asserted value at the selected readback boundaryWhole-scene fidelity, another renderer, or a path the readback bypassesExpectPixel programs built on PixelTestGame
Golden-image comparisonA captured frame matches a retained reference under the recorded tolerance and environmentThat the reference is authoritative or portableThe 17 EasyGL goldens, reused by Vulkan
Differential runCNA agrees with a named independent implementation or real XNA for the exercised inputsGeneral parity beyond that corpus; two implementations can share a defectThe FNA value harness; D3D9_XNA_Diff
Native-host artifactThe requested executable, runtime, device or browser and the observation point all engaged on the named hostOther hosts, other identities or long-duration behaviourCNA's recorded native-MSVC and Linux-plus-Chrome Inspector runs
CI workflow successThe trigger reached every recorded step and its gates passed for that matrix legJobs excluded by path filters, dispatch-only workflows, dead configure legs, or tests never registered in that configurationAny run of the 20 workflow files

The strict probes, the pixel harness and the oracles named here are explained on When failing to compile is the pass and Oracles, tolerances and engagement gates.

Oracle authority depends on the question

For API shape, CNA's census takes Microsoft's XNA runtime XML documentation and DLL metadata as the target surface (audit_xna_runtime_surface.py); a converted, searchable copy of that documentation is a reading aid, not a gate and not a substitute for the original assemblies. For behaviour, CNA's contributor rules name FNA as the ordinary reference and measured XNA as the tie-break, while a format specification or a native API can outrank both for a narrower question. A project-authored expected value is an oracle only when its derivation is reviewable and independent of the code under test.

QuestionPreferred authority and controlWhere CNA does this
Public API shapeThe XNA reference assemblies and documentation; normalise C# to C++ idioms explicitly, then compile positive and negative probesThe runtime census (331/331 types, 3,627/3,627 members, representation only); the strict-XNA probes
Managed behaviourReal XNA where executable; otherwise pinned FNA plus independently chosen edge cases and documented deliberate deviationsThe six real-XNA probes and the framework packing oracle; the FNA value harness; deviations recorded in comments citing the XNA IL
File-format semanticsThe owning specification and independently generated fixtures; compare production output with a separate decoder or digest where practicalThe XNB specification conformance entries; the LZX differential against FNA's decoder; CNB golden byte vectors
GPU or API behaviourThe native API contract plus renderer-owned execution evidence; another renderer only as a localisation controlThe Vulkan and OpenGL4 output gates; the Direct2D debug-log gate; the 64×64 cross-renderer dumps
Project extensionA written CNA contract, negative cases and a discriminating test; XNA and FNA cannot define a CNA-only featureCNAEXT surfaces and their tests
Historical reconstructionOriginal executables, source and data, and versioned captures; decompiled code is evidence to audit, not a behavioural specificationThe captured-XNA references; expected values whose comments cite decompiled XNA sources

A renderer or platform claim needs a complete record

   subject + revisions               build + host identity
   (CNA sha, sibling shas,           (selector, family, options,
    local diff, test name)            OS, driver, display, prefix)
              \                            /
               v                          v
 engagement --> [        bounded claim        ] <-- observation point
 proof (token,                                      (return value, trace,
 browser verdict,                                    readback, frame, file)
 native handle)   ^                          ^
                 /                            \
   oracle + policy                     outcome + artifact
   (authority, tolerance,              (pass / fail / expected fail /
    normalisation)                      skip / unsupported / blocked /
                                        not attempted; log, image, digest)
Figure. The evidence vector behind a durable claim. Six coordinates point into one bounded claim: the exact subject and revisions, the build and host identity, proof that the intended renderer or service engaged, the observation point, the oracle with its tolerance policy, and the outcome with a retained artifact. The labels in the first table are projections of this record (a source-proven claim fills only the first coordinate; a pixel-verified one fills all six), not rungs on a single ladder.
FieldRecordExample of a field that changes the meaning
Source identityCNA commit, sibling commits (sharp-runtime, easy-gl, meta-gl), local-diff status, generated shader or table revisionsharp-runtime on next rather than main
Build identityPublic renderer selector, implementation family or profile, build type, toolchain, feature options, the exact configure and build commandsMinGW g++ cross-build versus native MSVC for the same Direct3D identity
Host identityOS and architecture, native API or translation runtime, device and driver, display mode, browser or emulator or physical hardware, relevant environment variablesMesa llvmpipe under Xvfb versus a real GPU under private Weston
SubjectThe exact test, demo, asset, API operation, malformed case or renderer routeA discovered CnaTests case versus a standalone *_test.cpp program
Engagement proofA log marker, API or device identity, browser verdict, screenshot, readback or lifecycle trace proving the intended route ranA DXVK: line versus a gate-skipped wrapper
OracleThe expected value, image or exception and its authority; tolerance and normalisation rulesReal-XNA PNG at 0 versus a CNA golden at 60
OutcomePass, fail, expected fail, skip, unsupported, blocked or not attempted; never one overloaded "supported" bitExit 77 reported by CTest as skipped
ArtifactA retained log, image, trace, manifest, digest or CI record with a reproducible locatorThe Direct2D Proton identity file naming the runtime that produced a pass

The vector separates, for example, a MinGW binary running through Wine and DXVK from a native MSVC Direct3D run; a browser page served over loopback HTTP from one opened as a local file; an iOS simulator launch (what apple-ci.yml runs, beside a device final link) from a signed build on a physical device; and an Android source path (no workflow builds Android at this snapshot) from an APK that installs and presents a frame from its selected renderer. All are useful milestones, and none is a synonym for another.

Automation at the snapshot

The trigger facts below were read from the 20 files in .github/workflows. They are source-verified configuration, not a record that any job passed.

FactValue
Workflow files and jobs20 files, 28 jobs (platform-ci.yml 6, apple-ci.yml 3, gltf-renderer-stride-ci.yml 2, one each elsewhere)
Manual startAll 20 declare workflow_dispatch
Push or pull-request trigger18 files: 17 on next, develop and main (several path-filtered), plus content-pipeline-windows-ci.yml on pushes to its own branch
Manual onlyd3d-windows-ci.yml and gdi-windows-ci.yml
Not covered by any workflowAndroid, native Wayland, a build of the C API library, the XNA oracle corpus, the FNA harness, CNA_DIAGNOSTICS above OFF, CNA_BUILD_INSPECTOR, any coverage tool

The native C ABI shows why a workflow file cannot promote a state. Its five workflows are build-free checks, the checked-in release gate reads "Not ready" with one unmet criterion (468 public symbols unmapped), and the generator behind the coverage criterion refuses to run while three public modules are unclassified in its scope table (see Known Issues). Neither a green subset of those checks nor the presence of the files makes the ABI release-ready; browser harnesses, sanitizers, mutation routes and native-platform jobs likewise establish only the configurations and artifacts they execute. The per-workflow scope table is on What CI covers, and what it does not.

What the specialised lanes add, and where they stop

  • Portable Linux. The general job runs an unfiltered ctest of one EasyGL identity under Xvfb and classifies failures against a one-entry expected-failure list; the input and devices jobs run focused matrices with sanitizer selections; the 32-bit job builds three arithmetic checks, not a 32-bit CNA; the glTF jobs' oracles are narrower than a model-rendering campaign.
  • Browsers and runtime selection. htmldom-ci.yml is the strongest automated browser route (served page, real Chromium, verdict object, compositor pixels). The Emscripten multi-renderer job is designed to prove a compatible bundle links (but it, htmldom-ci.yml, devices-tests.yml and the Apple and Metal workflows pin a sharp-runtime revision that lacks a component CNA's default build now requests, so by a static reading they stop at configure at this snapshot: CNA-BUG-199), and the native multi-renderer job proves descriptor generation and early runtime selection for a CPU and diagnostic set; neither proves every renderer's pixels.
  • Platforms. platform-ci.yml treats platform, renderer and audio as independent axes: a contract matrix (SDL3, SDL2, Vulkan, Software, Headless, Terminal), a MinGW Win32 harness executed under Wine, a manual native-MSVC Win32 job, two SDL-free X11 lanes and an SDL-enable matrix. It has no Wayland job: the live Weston, Mutter, XKB, input-method, clipboard and portal suites are registered for the environments they need and run only where a developer provides them, and a missing compositor is a skip, not a passing behaviour test.
  • Apple and Windows. The macOS workflows build and run portable suites and the native Metal contract tests with MTL_DEBUG_LAYER and MTL_SHADER_VALIDATION set; they do not imply iOS or tvOS devices or every GPU. The Direct3D and GDI workflows are manual. Native MSVC, MinGW under Wine with DXVK, WARP, and a physical interactive Windows machine remain different evidence tiers (see Direct3D: what each tier proves).
  • Content Pipeline. content-pipeline-windows-ci.yml builds the CLI and the CPU pipeline tests with MSVC and exercises the CLI (explain, workers, clean, deterministic rebuild) from a fixture directory deliberately named with non-ASCII characters (CNA-MSVC-Zażółć-曲線) under the runner's temporary directory, which catches path, encoding and packaging assumptions a Linux build cannot. A green build-time tool is still not runtime content proof: XNB, CNB and runtime loading keep their own container and object-graph tests.

Diagnostics and Inspector in automation

Neither subsystem has a workflow, and no workflow or configure preset sets CNA_DIAGNOSTICS above OFF or turns on CNA_BUILD_INSPECTOR. A CI build therefore compiles only the two level-independent diagnostics tests and none of the STATS or FULL cases, and the 27 Inspector tests are never compiled there (the per-level table is on What the diagnostics corpus proves). The overhead figures for both are CNA's own benchmark records from one machine (an AMD Ryzen 7 PRO 7840U with GCC 14.2): evidence for regression on that machine, not a universal budget. CNA's notes record a Linux-plus-Chrome and a native-MSVC end-to-end Inspector run and list macOS runtime validation as pending; those are CNA-recorded, not reproduced here. The generated audits that do run (the XNA census, the renderer registry, platform containment, module closure, the content inventories) are structural proof, not behavioural parity.

Sanitizers, GPU validation, fuzzing, mutation and coverage

  • Sanitizers. ASan and UBSan run in one row of input-ci.yml (with detect_leaks=0, so no leak check) and in gltf-sanitizers-ci.yml (leak detection on, but deliberately scoped to the glTF selection: its header, written on 2026-08-12, records that a full run of the same binary then reported 58 UBSan findings and 7 leaks elsewhere, among them signed-integer overflow in the math GetHashCode implementations (CNA-BUG-252), and it refuses an allowlist; a dated CNA note, not re-measured here); devices-tests.yml uses the devices-ubsan preset. Leak suppressions must name a leak reproduced without CNA code (the model is on ASan and UBSan). A sanitizer-clean CPU route says nothing about a native driver's state or pixels.
  • GPU validation is family-specific and must itself prove engagement: the [Vulkan Validation] and [OpenGL4 GL Error] output gates, the Direct3D debug layers and the Direct2D debug-log gate in the native workflow, Metal's validation variables, and WebGPU's error scopes inside the renderer.
  • Fuzzing. Fuzz-named GoogleTest suites are deterministic adversarial loops that run with the ordinary corpus. libFuzzer entry points exist (the compiled-effect harness with CNA_FX_FUZZER_ENTRY_POINT=ON, the model and intermediate-format harnesses, and two C API fuzz sources compiled as an object library), but no workflow runs a continuous fuzzing campaign.
  • Mutation. The Direct2D mutation checker runs only as a dry run (anchors still apply) in a manual workflow; applying, rebuilding and observing each expected failure is a manual step.
  • Coverage. No workflow configures gcov, lcov, gcovr or llvm-cov, so reports named "coverage" describe API or feature inventories unless they say otherwise.

How to report CI honestly

A useful CI statement names the workflow and the run, the trigger, the commit, the matrix tuple, the targets built, the tests selected, the skips, the implementation-engagement token and the retained artifacts. "Covered by CI" is too coarse: automatic browser pixels from htmldom-ci.yml, a manual native-Windows Direct3D run, a generated ABI baseline and a source-only registry comparison are all valid evidence, and they prove four different things.

# the facts a CI claim should carry, filled from the run itself
workflow=platform-ci.yml run=<run id> trigger=push commit=009d40f5
tuple="CNA_PLATFORM=HEADLESS renderer=OPENGLES3 audio=NULL"
selected="ctest -L platform" ran=R skipped=S failed=F
engagement="none needed (headless contract)" artifacts="<log locator>"

The block is an illustrative template, not output of a real run.

A minimum claim recipe

Before writing "works", write a narrower sentence that answers six questions:

  1. What exact subject and revision were examined?
  2. Which build, renderer, platform and host actually engaged?
  3. Where was behaviour observed: a return value, a trace, a readback, a frame, a file or a network peer?
  4. What independent authority supplied the expected result?
  5. Which negative or perturbed case shows the check can fail?
  6. What artifact lets the next reader reproduce or falsify the claim?

A claim that cannot yet answer all six can still be useful: label it with the strongest label it earns from the first table (source-proven, compile-proven, runtime-observed, renderer-engaged, oracle-compared, pixel-verified, manually observed, historically recorded, blocked, unsupported or not attempted) and do not silently promote it to behavioural parity. Worked sentences that follow these rules are on How to word a claim.

Where current defects are listed

Defects that exist at this snapshot, each with its evidence and the discriminating regression that would prove a fix, are published on Known Issues, not on this page. The rule that applies to them is the one above: "source-proven" there means the defective condition is visible in the pinned source, not that a reproducer was run, and a fix earns its status only with a test that fails before it and passes after.

The earlier conserved backlog of 31 findings was re-verified at this snapshot. Twenty-four keep their CNA-BUG-### number and have an entry (001, 002, 003, 004, 006, 008, 016, 017, 021, 022, 025, 026, 027, 028, 029, 036, 045, 047, 050, 052, 055, 058, 061, 062; 029, 036, 045, 050, 055 and 058 are narrowed to what survives). The other seven have no page under their old number, for the reasons below.

Earlier IDOutcome at 009d40f5Where it is recorded
CNA-BUG-007Fixed: the loose tier wraps any std::exception from a reader, including a malformed .gltf loaded through Load<Model>, in ContentLoadException. Other Load<T> routes (a wrong-type .xnb, the loose SoundEffect tier, a disposed manager) still leak other exception types; that is a different entryContent robustness, what a failed load throws, CNA-BUG-122
CNA-BUG-019Not a defect: Game::Dispose() raises Disposed on every call, as XNA 4.0 (no disposed guard in Game.Dispose(bool)) and FNA doDisposed: repeated, re-entrant and throwing disposal
CNA-BUG-020Not a divergence: a throwing component leaves the game not marked disposed and a later Dispose() starts again, which is how XNA (which has no disposed flag) behaves; the shape is documentedsame section; the related index-shift defect is CNA-BUG-087
CNA-BUG-023Not a defect: XNA reads CanDeserializeIntoExistingObject only in reflection-driven member discovery, which CNA does not have, so the unconsulted property changes no observable behaviourXNB container and object graph
CNA-BUG-024Partly fixed: the graphics exceptions now derive from System::Exception; the surviving item is that ContentLoadException derives from std::runtime_error by designCNA-GAP-001
CNA-BUG-032Still true, filed as a verification gap: the module link-closure gates skip in every Ninja treeCNA-VGAP-019
CNA-BUG-042Not a defect: CheckForNaNs() and the getDebugDisplayStringProperty() of nine of the ten types that carry one are private, uncalled ported debugger aids (only Color's is public, marked CNAEXT, and the C API calls it)Math module internals

Evidence and limits

The trigger table, the lane descriptions and the "not covered" list were read from the workflow files at 009d40f5; the instances in the evidence-form and authority tables were read from the CMake registrations, tools and tests named. No workflow, test, benchmark or gate was run for this page, and whether any job is green at the snapshot was not checked. Benchmark, Inspector end-to-end and recorded pass figures are CNA's own records, attributed as such.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.