Review large AI-generated areas without trusting them

CNA snapshot c1c316b9  ·  Development › Human Takeover  ·  source links pinned to c1c316b9

✓

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. Counts come from the TARGET tree and Git objects; guards were read from CMake, scripts and workflows, not run. Test outcomes quoted from merge messages and plans are CNA's own records, not reproduced. Retired renderer identities are deliberately not named.

CNA was built at scale with AI assistance, and the tree carries the paper trail: commit subjects with task IDs, 106 plan files, frozen audit and remediation archives, root-level handoff notes, and comments that cite tasks. This page says how far each of those can be trusted, which of CNA's own mechanical guards are stronger evidence than any prose (and what each one really enforces), and how to review a very large diff without trusting its author, using one of the campaign merges in the snapshot's history as the worked example. Read it before you accept a change because a plan row, a status banner or a comment says it is done.

The rule

Current source and active CMake are authoritative. Plans, audits, handoff notes and comments explain intent and history, and can be stale. CNA's own files say the same about themselves. The archives audit/AUDIT_FINAL_REPORT.md, remediation/README.md and modularization/RECONCILIATION.md each open with a banner that they predate the 2026-09-17 renderer curation and must be read “as a fact about that date, never as current CNA support”. plans/README.md says the status recorded inside each plan is authoritative and refuses to copy task counts into the index. 29 of the 117 plan files open with a retired-renderer, superseded or rejected-candidate banner (26 use the words “retired renderer — historical record”). AGENTS.md and CLAUDE.md tell an assistant not to treat “old CNA code or AI-generated stubs” as authoritative when they conflict with the FNA reference API.

In practice: behaviour is answered by the implementation, the active CMake that compiles it and the tests registered for a given configuration; why, by git log and the plan; whether something is supported, by the registry (cmake/RendererIdentities.cmake), the CI workflows and Known uncertainty and history.

How the assistance shows in the tree

The instruction files address assistants directly (porting conventions, CNAEXT tagging, “always commit after finishing a task”). Some archives are written as resume prompts: audit/AUDIT_PROGRESS.md says that if context is lost the session should resume from that file and continue “fully autonomously” with “no further questions”, and the last section of NEXT.md is a resume prompt for a session on the DIRECTX9 branch. Those are instructions to a past agent, not project policy and not authorization for you. Git cannot separate assistant-written from human-written work: all 9,709 reachable commits carry one author name, none of the 3,687 commits since the v0.1.0-alpha.1 tag has a Co-authored-by trailer, and 3,205 of those 3,687 carry a signature header (212 of them SSH rather than PGP signatures), which attests the committing key and not that anyone read the diff.

The artifacts and how far each can be trusted

Figures were counted from the TARGET tree and history at c1c316b9; patterns are simple, so treat the percentages as approximate.

ArtifactWhat it is at the snapshotUse it forDo not use it for
Commit subjects and task IDs3,687 commits since the tag; 3,648 subjects follow type(scope): (for example perf(Task WEBGPUPERF-0006): one command encoder per frame; a render-target cycle no longer submits); 841 carry (Task …) or (Tasks …); by a simple pattern, about 3,270 (89 %) contain a PREFIX-number token. AGENTS.md asks for one task per commit, yet 30 (Task …) subjects use a range, the widest, MOD-713..MOD-731, naming 19 IDs, and one merge subject, merge(WIN11-0003..0103), names 101.Finding the plan that holds the evidence: WEBGPUPERF-0nnn is plans/plan_webgpu_perf.md, SMG is plans/plan_sdlgpu_modern_graphics.md, STREETS is plans/plan_street_sdlgpu.md, WGF is plans/plan_webgpu_failing_eight.md.Scope. An ID can have no commit (WIN11-0001 and WIN11-0002 are plan-only rows in plans/plan_windows11_directx.md), and one commit can carry 19.
First-parent merges1,299 first-parent commits since the tag: 1,251 direct commits and 48 merges (65 merges in all, 29 named merge(<Campaign>)). The other 2,388 commits sit inside merged branches.The integration story: what landed when, and the summary numbers in merge messages.The content of a “fold” merge, which can carry edits no branch commit shows (worked example below).
Plans116 Markdown plans in plans/, each a table of task rows with status and evidence; one more, plan/plan_compilation.md, sits in the singular plan/ directory and is not in the index.Intent, the decision trail, what was measured on which host, and where CNA recorded its own corrections.Current behaviour or “done”. See the examples below the table.
Audit and remediationaudit/ holds 2,574 files, 2,370 of them per-file *.audit.md reports (the final report counts 2,297 eligible ones); remediation/ turns them into 105 root-cause tasks and is marked a closed historical archive.Leads: a finding may still be true.Current defects. remediation/README.md says tasks marked “Verification required: YES” rest on static analysis that was never executed, that CTest results for about 220 tests were meaningless until REMED-BUILD-001, and that some tests “assert the bug”.
Spikes and modularization recordsspikes/: 23 probe directories. CLAUDE.md keeps a probe while its renderer is a candidate or supported and removes it on retirement. modularization/: 142 files of inventories from the 2026-08 restructuring.A recorded measurement (the six xna-*-spike probes) or the layout at a date.Current layout.
Root notesNEXT.md: 7,143 lines, 72 second-level sections, newest dated 2026-09-28; 10 topical NEXT*.md files and two handoff_*.md files, three of the 13 marked as retired-renderer records. known_bugs.md (75 lines) dropped retired-renderer entries; misc/known_bugs.md has 381; AUDIT.md is an XNA API audit of 2,206 lines with dated notes; CHECKLIST.md is the per-file porting checklist.Dated context and the reasoning behind a change.Live status. NEXT.md was last changed by 76c9bda29 (2026-10-04) and AUDIT.md by db68149e3 (2026-10-03), followed by 370 and 371 commits up to TARGET, although AGENTS.md says to update them at task end; NEXT.md contains none of the SMG, STREETS, WGF, VMG, GTI, WEBGPUPERF, STREETPERF or WIN11 IDs.
Documents in docs/151 Markdown files at the top of docs/ (192 with its subdirectories). Some are dated measurement reports (docs/d3d9-divergence-report.md: “Status: 2026-07-15”, 31 scenes); some are living design pages (docs/opengl33-renderer.md, docs/physical-modules.md); docs/removed-renderers.md records the reserved ABI values.Rationale and dated evidence, after reading the status line.A count or table you have not compared with the registry or CMake.
Instruction filesAGENTS.md has 493 lines and CLAUDE.md 666; they have diverged (see the drift table).The conventions the code was written under.A description of the code, or of the current FNA/XNA tie-break.
Comments citing tasks2,025 of about 4,660 source, build, script and data files under modules/, cmake/, scripts/, tools/, tests/ and examples/ cite a plans/plan_*.md path: about 6,100 citations of some 75 plans.Which campaign to read and why a line exists.The comment's claim about behaviour. Ten citations name four plan files that do not exist at TARGET (plan_devices_phase4/6/7/8.md; commit 4cb7578b6, “Old plans were deleted”, removed them from the repository root on 2026-07-07, and the comments cite them under a plans/ path they never had), including doc comments in the public headers Accelerometer.hpp, Gyroscope.hpp and SensorBase.hpp.

Plan rows are claims, and CNA's plans record their own corrections. SOFTWARE-375, 376 and 390 were closed as done, and SOFTWARE-457 (2026-09-12) records that Microsoft's assembler invalidated the evidence behind them: the fixtures used operand forms the compiler forbids, and both CNA compile paths had accepted seven forged violations (plans/plan_software.md). plans/plan_webgpu.md counts 200 done rows and one open one (counted from its own row tables by tools/count_webgpu_plan_status.sh) and says “read the row count as a count of rows, not as a parity claim”; the plan plans/plan_webgpu_failing_eight.md then records that ctest -L WebGPU had eight failures on rows marked done, three of them tests asserting behaviour the framework had deliberately changed: “a plan row being green says the work was done, not that the test still describes the framework it was written against.”

Drift found while verifying these pages

Each row was checked by reading the named source at c1c316b9. It is a sample, not a census; the point is the shape of the mismatch.

Where the claim livesWhat TARGET does
The IsLatched() comment in GraphicsRendererSelection.hpp: the selection latches when the first GraphicsDevice begins construction.GraphicsDevice::resolveRenderer in GraphicsDevice.cpp calls GraphicsRendererSelectionAccessEXT::Latch only after a candidate renderer was created, and its own comment says latching up front “was the first cut, and it was wrong”. Two comments disagree; behaviour follows the implementation (latch internals).
Device-loss comments: GraphicsDevice.hpp (deviceStatus_) says only the Direct3D 9 renderer ever calls the device-event callback; GraphicsDevice.cpp (createRenderer) says nine of ten renderers never do.Calls to RendererDeviceEvent::Lost exist in four families: Vulkan, WebGPU, DirectX9 and DirectX11. The comments describe a ten-renderer world.
A comment in Sdl3Platform.cpp cites Game::UpdateInput().No such function exists under modules/; the pump is the tail of Game::PollEvents.
Stale counts in prose: cmake/Tests/ModuleProbes.cmake still describes an earlier registry (it “pins the 42 public renderer identities”); scripts/check_renderer_descriptors.py says a build “compiles all 45”; docs/c-api/LIMITATIONS.md says “Four of the 49 renderers are built and run here”; the header of general-tests-ci.yml says “all 14 renderers”.The registry holds 14 identities over 12 families. The enforced number lives in the table inside scripts/check_renderer_identities.py. CNA's own row RTR-P13-8 (plans/plan_runtimerenderer.md) says a count in prose is “a fact with no owner”.
cmake/PlatformHotPathLint.cmake contrasts itself with a ratchet that “warns because the whole tree is over budget by design”.cmake/PlatformRatchet.cmake defaults CNA_PLATFORM_RATCHET_STRICT to ON, and tools/platform/sdl_budget.json records a budget of 0 files and 0 references with an irreversible floor of 0.
TODO.md, a sensors roadmap last changed by a commit dated 2026-04-11, lists Gyroscope, Compass and Motion as unchecked.modules/devices/src/Sensors/ holds implementations of all three and Android sensor backends.
docs/cross-renderer-parity-fixtures.md: EasyGL, WebGPU and SDL GPU register the fixtures; the “Current fixtures” table lists 13.ParityFixtures.cmake lists 32 fixtures, and four families call cna_register_parity_fixtures(): EasyGL, WebGPU, SDL_GPU and DirectX11.
scripts/run-oracle-corpus-diff-easygl.sh defaults DISPLAY to :0, calling that “this project's own CNA_TEST_DISPLAY default”.Since GTI-0001 that variable defaults to empty (cmake/TestDisplayPolicy.cmake), and CLAUDE.md forbids running oracles on the owner's live desktop; the script still falls back to :0 when DISPLAY is unset (by reading; not executed).
AGENTS.md calls FNA “the authoritative behavioral and API reference”.CLAUDE.md calls it the “working” reference and adds a tie-break decided on 2026-09-04 (0e62e7368): where measured Microsoft XNA and FNA disagree, CNA follows XNA. AGENTS.md has no such section, defers to CLAUDE.md for layout and lacks the Platform Boundary chapter; CHECKLIST.md says FNA is authoritative for behaviour and the XNA reference assemblies for API surface.

CNA's mechanical guards: what each really enforces

A guard is stronger evidence than prose only for what it matches, in the configuration that runs it, and with the exit code it actually produces. The table gives, for each, when it runs, what it enforces and what it cannot see. Registrations were read from CMake and workflows; nothing was executed.

GuardRunsEnforcesBlind spot
scripts/check_renderer_identities.pyCTest RendererIdentityRegistry; a step in multi-renderer-ci.ymlThe 14 identities agree across the enum, the CMake list and the runtime registry chain; C ABI values are pinned and retired ones reserved; retired names are not selectable; counts stated in docs/runtime-renderer-selection.md, docs/renderer-expansion-candidates.md, docs/physical-modules.md and plans/plan_platform.md match.Counts only in those listed files and only in the phrasings “N public identities” and “N implementation families”; LIMITATIONS.md and comments are outside it.
cmake/RendererIdentities.cmake and the CnaRendererRetired_* script-mode testsConfigure time; CTestAn unknown renderer name given to CNA_GRAPHICS_RENDERER or as a member of CNA_GRAPHICS_RENDERERS is refused by name, and a retired name on every route (also CNA_RENDERER_<X>); an unknown CNA_RENDERER_<X> switch is not checked. One test per retired identity is generated from the list, plus a list of route and control cases (a refused name on each route, and live names that must be accepted).Says nothing about a public renderer's quality.
cmake/RendererDescriptorGate.cmake, with scripts/check_renderer_descriptors.py and scripts/check_runtime_renderer_discipline.pyConfigure time (CNA_BUILD_RENDERER_DESCRIPTOR_GATE defaults ON); check_renderer_descriptors.py as a step in multi-renderer-ci.yml (no CTest registers it at this snapshot); CTest RuntimeRendererDisciplineEvery family's descriptor translation unit is compiled in every configuration (an object library nothing links); a registered identity without a matching descriptor namespace fails configure; no CNA_RENDERER_* macro may appear in modules/graphics/src/.Compiles descriptors, does not check what they answer. DIRECTX9 and DIRECTX11 (and Vulkan without SDK headers) are compiled only by their own family builds.
cmake/PlatformRatchet.cmakeConfigure time; on by default and strict by defaultSDL references in production files outside the allowlist must stay at zero (tools/platform/sdl_ratchet.py, budget file at 0/0); a separate audit classifies test and example uses.A textual match, comments included. Skipped with a status line when Python 3 is absent; passing results are cached by input fingerprint.
cmake/PlatformHotPathLint.cmakeConfigure time, hard errorNo platform call through a platform receiver inside a loop whose header mentions per-pixel, per-vertex, per-fragment, per-sample or per-event tokens; an annotation needs a reason.Its own docstring: both judgements under-report, so a pass is not proof.
cmake/TestDisplayPolicy.cmakeConfigure time; CTests CnaTestDisplayPolicy, CnaTestDisplayPolicyAsSubproject, CnaTestDisplayIsolationRegistered tests do not target the live desktop: CNA_TEST_DISPLAY is empty by default, :0 needs CNA_TEST_ALLOW_LIVE_DISPLAY=ON, every test carries a Wayland guard (non-Windows); the last test inspects ctest --show-only=json-v1 of the configured tree.Registrations, not what a script does inside a test (see the :0 fallback above). The last two need CMake 3.28 or newer.
cmake/Tests/ModuleProbes.cmake with scripts/check_module_link_closure.pyCTest, native builds with tests onUp to 15 minimal probes, one per module alias; the probe's link line must not contain forbidden archives (and must contain required ones). Native-SDK-free and Vulkan-only closure gates exist for single-renderer HEADLESS and VULKAN builds.Reads CMakeFiles/<target>.dir/link.txt and exits 77 (skip) without it; the unit, tests, multi-renderer and cnaext presets and the general-tests and multi-renderer workflows all use Ninja, and no workflow names these tests.
scripts/check_no_posix_setenv.pyNowhere: no CMake file or workflow registers it at this snapshot, so it runs only by handWhen run: no setenv or unsetenv outside comment lines in modules/, tools/, tests/ (they do not exist on MinGW-w64).Everything, while nothing runs it: by reading, Gamer Services tests and examples, a Content Pipeline serializer test and a networking tool under tools/ contain such calls at TARGET, and no gate reports them.
tools/xnb/check_plan_status.py, tools/count_webgpu_plan_status.sh, the CApiLimitations and CApiDocExportCounts testsThe XNB plan check: CTest CnaXnbPlanStatusConsistency; the WebGPU counter: by hand; the C API tests: CTestA plan's stated totals agree with its own task table, and no line contradicts a closed decision (the XNB pipeline plan only); status counts derive from rows; C API document counts derive from the inventory.Rows, not behaviour: a green row can stay green after its test breaks.
tools/audit_xna_runtime_surface.pyManual; not registered by CMake or a workflow (searched)A census of documented XNA types and members against CNA's public headers.Representation only; its default input is a directory beside the repository.

Sibling audits in the same style are scripts/check_renderer_target_discipline.py (RendererTargetDiscipline), scripts/check_renderer_combinations.py (RendererCombinationRegistry) and scripts/check_removed_renderer_api.py (RendererCurationApiDecisions). The CNAEXT guard, matrix, naming, nodiscard and Doxygen checks (scripts/check_cnaext_guards.sh and its neighbours) are still in the tree, but no CMake file or workflow runs them at this snapshot.

Three reading rules follow. Know when a guard runs: configure time, CTest, CI or by hand. Know what it matches: a regular expression, a compile, or a registration list. Know how it fails: skip or fail, and which condition sets the exit status. The last matters most for oracle scripts, where a printed difference does not always produce a non-zero exit; the oracle page gives the case.

A review method for a big diff

  1. Read the campaign structure first. git log --first-parent --merges <base>..<head> lists the integration story. For one merge M: git rev-list --count M^1..M^2, git diff --shortstat M^1 M, and git diff-tree --cc -r --name-only M, which lists the files the merge itself edited relative to both parents. Then open the plan that the branch name or IDs point to and compare its stated scope with the commits.
  2. Map changed paths to owners. Group git diff --numstat by module directory and look each owner up in Source ownership. Shared modules (modules/graphics tests and headers) mean every renderer is in scope even when the title names one.
  3. Read the tests before the implementation. Which existing tests changed expectations, and does the message name a measurement (a real-XNA probe, a task ID) or merely a new result? Check where each test is registered: renderer gate lists such as CNA_RENDERER_IS(…), the source filters in cmake/UnitTests.cmake, and the skip convention.
  4. Extract the invariants the change relies on (architectural invariants) and find a test for each: per-device GL contexts, compute bindings restored after a dispatch, the selection latch, ownership order (ownership map).
  5. Check comment and behaviour drift in the touched files. Header doc against .cpp comment against code; prose counts against registrations and lists; task citations that resolve to nothing.
  6. Look for hedged evidence. “Measured” against “reasoned”, “expected”, “should”, “not measured”; a claim with no command or test; one GPU, one driver, one date. tools/xnb/check_plan_status.py is a model of the rule: a plan's stated totals and its closed decisions must agree with its own rows.
  7. Distrust “all tests pass” without a configuration. Ask for renderer, platform, audio option, generator, display, skips and known failures (reporting evidence honestly).
  8. Record what you could not verify (investigation record), including hardware you lack and numbers you could only cross-check.

Worked example: reading a campaign merge, 0f690d7d5

The WebGPU per-draw binding campaign reached next as merge(WebGPUPerf), 2026-09-27, an ancestor of this snapshot. The commands are those of the method; the numbers were counted from Git objects.

Structure

The first parent is b1e4a2414, the tip of next at the time; the second is 196b14bd0 (WEBGPUPERF-0006). The merge base is 85c3baa09, the commit that had already put WEBGPUPERF-0001..0004 on next directly, and next had moved three commits past it, so the branch is a linear stack of five commits on that base. git diff-tree --cc lists no file: the merge commit edits nothing of its own. The message claims WEBGPUPERF-0005..0008; the five commits carry exactly those four IDs, one of them in a documentation commit that records what the ShaderEffect and compiled-effect routes still cost per draw, and plans/plan_webgpu_perf.md has rows 0001 to 0008, every one with a commit. Compare the fold merges of other campaigns, whose merge commits can carry edits that no branch commit shows.

Owners

git diff --shortstat b1e4a2414 0f690d7d5 reports 15 files, +1,505 and −548 lines. By directory: modules/renderers/webgpu/src 4 files (+719, −486), its include 2 (+166, −12), its examples 7 (+432, −41) and its tests 1 (+114), and the plan (+74, −7). A merge titled for one renderer that stays inside that renderer's directory is the narrow case: no shared test, header or module outside the family moved, so the blast radius is the WebGPU paths of the stock effects, SpriteBatch, ShaderEffect and compiled effects, which the message names. The first half of the campaign, 85c3baa09, had the same shape (7 files, all under modules/renderers/webgpu and the plan).

Checks that cost nothing

  • Tests before implementation. The merge extends webgpu_binding_cost_test.cpp by 365 lines; it is registered as the CTest WebGPU_BindingCost (label WebGPU) in webgpu/examples/CMakeLists.txt. Its header lists checks A to O, and each pair pins both halves of the change: a draw still puts its own colour in its own cell, and a steady frame creates no bind group and makes a number of queue writes that does not grow with its draw count; a texture re-created every frame never meets a stale cached group; four render-target cycles before the back buffer are one submission, and a SetData between two of them lands in order. The cost checks read the renderer's own counters, so they prove the counters, not wall-clock time, and the program needs a display and a WebGPU adapter: a host without them says nothing. The merge also adds one GoogleTest case, WebGPUCompiledEffectDrawTest.SteadyDrawsBuildNoGroupsAndCopyNoGeometry, which skips unless the build selected the WebGPU renderer.
  • Numbers in the message against the tree. “CnaGraphicsExtTests 73 + 3 HLSL skips” sums to 76, exactly the static test-definition count under modules/graphics-ext/tests/ at the merge, which a WebGPU-only diff should leave untouched. “CnaRendererTests 273” cannot be checked against a static count: the renderer test directories hold 1,029 definitions in 69 files at the merge, and the source filters in cmake/UnitTests.cmake decide which of them a WebGPU build compiles. “ctest -L WebGPU 147/147” was not recounted, and “the same 20 pre-existing failures” of CnaGraphicsTests are not named, so the message alone cannot show that no new failure replaced an old one.
  • A claim about the parts not changed. The message says “next already carried 0001-0004 (85c3baa09)”; git merge-base returns exactly that commit, which confirms the split of the campaign across a direct commit and a merge.

What stays unverified

Every pass, fail and skip count, the street frame times (91–95 ms before, 26–29 ms after, Vulkan 36–39 ms) and the render-target switch cost (about 57 µs before, about 16 µs after) are CNA's records from one Linux development host with wgpu-native and from one application, cna-street; none was reproduced, and none says anything about the browser build, where WebGPU goes through Emscripten's port. The WebGPU family has no internals page here; its place among the families is on the renderer family map.

Short checklist

  • Which file decides the behaviour: source, active CMake, a registered test? Not a plan, note or comment.
  • Which merge or campaign brought it in, did a fold merge edit files on its own, and which owners and renderers does it touch beyond the one in the title?
  • Did any test expectation change, and is the reason a measurement or merely a new result?
  • Which invariant does the change rely on and which test pins it; do header docs, comments and behaviour agree; do stated counts match a registry?
  • Is each evidence claim measured, dated, and tied to a host and a configuration?
  • Would the guard that covers this area run in your configuration, and would it fail on this change?
  • What did you not verify, and who can?

Limits of this page

Nothing was built or run; every statement was checked by reading files and Git objects at c1c316b9. The drift table is a sample, percentages come from simple patterns, and the guard descriptions state registrations and script logic, not outcomes at this snapshot. Which files an assistant wrote is not recoverable from Git and is not claimed. The oracle-specific evidence rules are on Using the XNA oracle as evidence.

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