Known uncertainty and history

CNA snapshot 009d40f5  ·  Development › Human Takeover  ·  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. Every cited commit exists and is an ancestor of the snapshot; history is labelled fact, inference or unknown. Oracle and multi-renderer results are CNA's own records, not re-run for this page. Retired renderer identities are deliberately not named.

An inherited repository contains code, comments, tests and plans that disagree with each other. This page keeps the known gaps visible instead of converting "compiled", "registered" or "mentioned in a plan" into a support promise, and it separates what Git history proves from what it only suggests. Every claim is scoped to CNA snapshot 009d40f5 and, for bindings, to the binding revisions named. Read it before relying on any other Development page for a risky change.

Evidence-backed confidence limits

AreaWhat is establishedWhat is not established / next human check
Renderer breadthRendererIdentities.cmake defines the 25 public identities (CNA_RENDERER_PUBLIC_IDENTITIES, in C ABI value order) over 21 family directories; RendererSelection.cmake wires the selected targets and RendererRegistry.cmake generates the descriptor table. Pixel evidence exists per family in different forms (oracle scenes, goldens, 32 cross-renderer parity fixtures on four renderers).Registration does not mean full draw/resource parity or a runnable CI host. Only seven of the 21 families have a dedicated internals page in the Development area (EasyGL, Vulkan, OpenGL4, SDL_gpu, Software, Headless, Stub). Before claiming support, read the chosen family's source and its oracle or host job; the pixel-evidence-by-family table says what exists, not what is green.
XNA behavioural parity331 of 331 XNA 4.0 runtime types and 3,627 of 3,627 documented members are represented (a name census by tools/audit_xna_runtime_surface.py). A 39-scene oracle corpus holds real XNA 4.0 reference images captured under Wine and DXVK; CNA's records report the DIRECTX9 renderer at zero difference on all 39 at tolerance 0, through Wine and DXVK, outside CI.Representation is not behaviour, and one renderer's oracle result says nothing about the other 24 identities. See the oracle corpus and Using the XNA oracle as evidence.
Native-host validationPlatform conformance (PlatformConformanceTests.cpp) and focused mapper tests exist. CI has 20 workflow files (28 jobs): Linux cells, Apple cells, a Win32 cross-build executed under Wine on every push, and manual (workflow_dispatch) native-Windows lanes.A headless or Wine pass cannot establish physical display, DPI, input-device, compositor or GPU behaviour, and there is no Android or Wayland workflow. Read the workflow triggers and skips (what CI covers) and run a live relevant host where behaviour depends on it.
C API library buildThe C ABI is 0.29.0 (abi.h), 61 public headers, 4,055 exported routes; pure-C and C++ tests register when CNA_BUILD_C_API=ON; the c-api-* workflows run header, baseline, coverage and release-gate scripts.No workflow configures CNA_BUILD_C_API=ON, and CNA's own release gate reports "Not ready". Whether the library builds at this snapshot was not verified for these pages (C API gates).
External bindingsThe C#, Java, TypeScript, Python, Rust, Swift, Go and Ruby bindings are separate public repositories; each targets ABI 0.21.x (Ruby also admits 0.7.0), and five refuse 0.29.0 by an exact-version rule. The Development area has internals pages for the C#, Java and Python bindings at their recorded revisions.None of those revisions proves compatibility with this snapshot. A binding change needs its own ABI migration, revision pin and integration run. The TypeScript, Rust, Swift, Go and Ruby bindings have no Development internals page; their gates are summarised on the bindings boundary.
Thread safetySpecific locks and barriers exist: the recursive componentListsMutex_ for Game's component lists, the mixer's callback barriers, the HandleRegistry mutex, and the C API's creating-thread check (CNA_RESULT_THREAD).There is no source-backed blanket thread-safety guarantee for Game, GraphicsDevice or any renderer. Verify the concrete backend and callback path before off-thread use (thread and callback map).
Conditional testsUnitTests.cmake filters test sources and CTest routes by configured modules and hosts; renderer examples add separately named tests; skip code 77 is applied directory-wide and many cases GTEST_SKIP without a window or device.A green aggregate excludes absent configurations, and a skip is not a rendered result. No CTest total is derivable from the sources. Capture the configured inventory (ctest -N) and the actual runs, skips included.
Historical rationaleGit commits prove the structural transitions below.They do not prove all design intent, or that old plans remain authoritative. Prefer current source for behaviour and history for context.

The Development area itself is also an uncertainty register: a subsystem without a deep page needs manual source study before a maintainer relies on these pages for a risky change, and an existing page that was written from source reading may still leave platform-specific or live-hardware behaviour untested. Each page's evidence box states which kind of evidence it rests on.

Devices: explicit versus fallback shutdown

Established fact: DevicesShutdownCoordinator::Shutdown (DevicesShutdownCoordinator.cpp) explicitly destroys VibrateController's platform backend while the selected platform and its native services are still valid. A separate process harness, shutdown_ordering_harness.cpp, exercises both calling it and omitting it (DevicesShutdownOrderingTest.HarnessExitsCleanlyAfterShutdownCoordinatorThenRealSdlQuit and HarnessExitsCleanlyViaFallbackWhenExplicitShutdownIsOmitted). A search of production code under modules/ at this snapshot finds no Game or runtime call to the explicit shutdown function; its only caller outside the devices module is that harness.

Consequence, not a proven defect: an application that does not call it relies on the fallback. RegisterProcessExitFallback registers an atexit handler that only sets the shutdown flag and deliberately does not touch the platform, and the backend's release path, PlatformVibrateBackend::ReleaseService, calls into the platform only while that same platform is still the installed current one. The harness is built only where SDL3 is configured, and its test is excluded on Windows, Emscripten, Android, iOS and SDL2-only selections, so the native X11, Wayland and Win32 teardown orders are not exercised by it. Before changing singleton or platform teardown, exercise both process orders and inspect the actual application entry point. The devices and sensor lifetime page supplies the ownership trace; the user-level API is on Sensors.

Transitions whose history is actually recoverable

Renderer curation

Established fact: commit fc1b6a537 (2026-09-17, an ancestor of this snapshot and later than the v0.1.0-alpha.1 tag) retired 25 renderer identities and removed their implementations, keeping the 25 public identities over 21 physical families that exist now; the tagged release had shipped a much broader surface of 50 identities over 46 families (releases). Its message records that CMake identities became one list, cmake/RendererIdentities.cmake, holding the public names and every retired name with its reserved C ABI value (26 reserved values in total, one of them from an earlier removal); that this file is included from the root CMakeLists.txt before the SDL gates read the selection, so a retired name fails at configure time by name, with its reserved value, instead of silently configuring the host default — through every route that can name a renderer (CNA_GRAPHICS_RENDERER, each member of CNA_GRAPHICS_RENDERERS, each CNA_RENDERER_<X>); that per-family CMake and test wiring was removed; and that shared helpers were kept or removed by checking their remaining includers, not their names. These pages do not list the retired identities, by site policy.

Established fact (C ABI): the ABI's own release notes in docs/c-api/ABI_VERSIONING.md record the renderer range changing several times: 0.20.0 removed eleven identities, 0.22.0 restored ten of them with their old integers, 0.27.0 appended one, 0.28.0 retired twenty-five and moved CNA_GRAPHICS_RENDERER_MAXIMUM from 51 to 46, and 0.29.0 removed the SpriteBatch 2D mesh route (cna_sprite_batch_draw_mesh_ext and CNA_SpriteMeshEXT) that no remaining renderer implemented. Every surviving identity kept its integer; retired values stay reserved, and the next new identity takes value 52, not MAXIMUM + 1, as CNA/C/graphics.h states. scripts/check_renderer_identities.py fails if a retired name or value is reused, and RendererRetiredIdentityCase.cmake exercises the refusal in script mode.

Evidence-backed inference: the renderer set has been reversed before (removed in 0.20.0, largely restored in 0.22.0), so the retired list is a recorded decision, not proof that a retired backend was technically impossible. Maintenance consequence: a renderer name that is missing today is not automatically an unfinished current backend; check the retired-name gate and the reserved ordinals before adding an alias or reusing a number. CNA's commit message also records a multi-renderer configuration run after the change with no new failures relative to its baseline; that is CNA's own record, not re-run here. The current RendererIdentities.cmake and C graphics header are authoritative at this snapshot.

Platform rollout

Established fact: the Terminal platform was implemented as one dated sequence on 2026-08-12, before the v0.1.0-alpha.1 tag:

CommitStep
fbb98f922TerminalPlatform skeleton and CNA_PLATFORM=TERMINAL
95234ac46terminal lifecycle with restoration on every exit path
eca7a22e5presenting frames as characters, with the colour ladder
4b5497a27damage tracking and run-length SGR output
bc29fc7e0terminal resize as the window event every platform emits
ff3e2b677a frame budget that drops frames instead of blocking
826d5eff8exact Kitty keyboard input
ceb627cf1synthetic key releases for legacy terminals
32222e59fSGR mouse input
9850c63e8enforcing the terminal capability profile

After that tag came the native desktop backends, each integrated from its own branch by a three-way squash merge: Win32 (e73c63e38, 2026-09-14), X11 together with the unified CNA_ENABLE_SDL gate (60623a9b7, 2026-09-14), and Wayland (678c6a51b, 2026-09-15). All of these commits are ancestors of this snapshot. Current modules/platform/CMakeLists.txt compiles Headless into every build and Terminal into every POSIX build, whatever CNA_PLATFORM says, while the SDL, Win32, X11 and Wayland backends are compiled only for their own selection (Win32 because every source includes <windows.h>, X11 and Wayland because they carry real third-party link inputs); the selected platform remains a separate axis.

Established from current source, not only history: the same CMake file states the purpose of always compiling Terminal — a third implementation with a genuine display and genuine input that come from no windowing system, held to the same conformance suite as Headless. Evidence-backed inference: the order of the history and the current conformance wiring suggest the platform contract was deliberately pressured by implementations unlike SDL3 before the native desktop backends arrived. Unknown: whether every original design trade-off, or every migration goal described in historical plans, still has an active maintainer commitment. Use the current implementations and their tests to decide behaviour.

Generated renderer registry

Established fact: renderer registration is generated as an explicit build-tree C++ table from CMake, because inside a static archive the linker discards any object file nothing references, so a self-registering renderer would silently vanish unless the whole archive were force-linked. The current RendererRegistry.cmake states that reasoning, and the CMake architecture page shows the mechanism. Unknown: whether each family descriptor's declared capabilities match real hardware behaviour on every host; registry generation itself cannot test that.

Turn uncertainty into a human verification task

For a suspected weak area:

  1. record a precise claim ("a Vulkan render target survives a resize while a resource is pending");
  2. identify the code path and the current tests;
  3. configure a host that can actually execute it (for GPU work, the private runner tools/platform/run_gpu_tests_private.sh);
  4. add a characterization or negative test;
  5. capture the outcome, including skips.

If history explains only a past state, label it as history and verify the present implementation separately. Before assuming an area is clean, also read CNA's own bug registers, known_bugs.md and misc/known_bugs.md — records kept by CNA's authors, not verified by these pages. When a result is reusable, update the corresponding deep page and this register at a new CNA snapshot, following the maintenance & pin policy; do not silently erase a gap because a page grew longer.

The same subsystem is explained at four altitudes. These are the neighbouring pages at each one.