{
 "schema": 1,
 "target": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
 "target_short": "009d40f5",
 "generated": "2026-09-25",
 "note": "Current defects only: this index lists what exists at `target`. Fixed defects are never listed. Generated by scripts/known_issues.py from the verified findings; do not edit by hand.",
 "classes": {
  "bug": {
   "label": "Bug",
   "id_prefix": "CNA-BUG",
   "definition": "Existing behaviour violates an intended or documented contract."
  },
  "functional-gap": {
   "label": "Functional gap",
   "id_prefix": "CNA-GAP",
   "definition": "Functionality is intentionally or currently incomplete or unsupported; nothing violates a contract, the contract is narrower than one might expect."
  },
  "platform-limitation": {
   "label": "Platform limitation",
   "id_prefix": "CNA-PLAT",
   "definition": "A host, platform or toolchain constraint makes behaviour differ or be unavailable."
  },
  "verification-gap": {
   "label": "Verification gap",
   "id_prefix": "CNA-VGAP",
   "definition": "An implementation exists, but the evidence that it behaves correctly is insufficient."
  }
 },
 "counts": {
  "bug": 232,
  "functional-gap": 70,
  "platform-limitation": 12,
  "verification-gap": 56
 },
 "issues": [
  {
   "id": "CNA-BUG-001",
   "class": "bug",
   "title": "Plane::Transform(plane, matrix) transposes the inverse in place through a non-aliasing-safe Matrix::Transpose",
   "summary": "Plane::Transform with a Matrix passes one object as both source and destination of Matrix::Transpose, which is not aliasing-safe, so any transform whose inverse is not symmetric (a translation, most rotations) yields a wrong plane.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "high",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "Plane::Transform(Plane, Matrix) and Plane::Transform(const Plane&, const Matrix&, Plane&); C ABI cna_plane_transform_matrix",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-001.html",
   "sources": [
    "modules/math/src/Plane.cpp",
    "modules/math/src/Matrix.cpp",
    "modules/math/src/Vector4.cpp",
    "modules/c-api/src/CnaCApiGeometry.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/PlaneTests.cpp",
    "modules/c-api/tests/pure_c/GeometrySmoke.c"
   ],
   "related": [
    "development/handbook/add-a-regression-test.html",
    "development/handbook/change-public-xna-behavior.html",
    "development/internals/modules/math.html",
    "docs/math-types.html"
   ]
  },
  {
   "id": "CNA-BUG-002",
   "class": "bug",
   "title": "BoundingSphere::Contains(const BoundingFrustum&) never returns Disjoint",
   "summary": "When any frustum corner lies outside the sphere, BoundingSphere::Contains(frustum) always answers Intersects, because its distance test compares a constant zero, so a frustum nowhere near the sphere is reported as overlapping.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContainmentType BoundingSphere::Contains(const BoundingFrustum&) const; C ABI cna_bounding_sphere_contains_frustum",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-002.html",
   "sources": [
    "modules/math/src/BoundingSphere.cpp",
    "modules/math/include/Microsoft/Xna/Framework/BoundingSphere.hpp",
    "modules/math/src/BoundingFrustum.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/BoundingSphereTests.cpp",
    "modules/c-api/src/CnaCApiGeometry.cpp"
   ],
   "related": [
    "development/handbook/add-a-regression-test.html",
    "development/internals/modules/math.html",
    "docs/math-types.html"
   ]
  },
  {
   "id": "CNA-BUG-003",
   "class": "bug",
   "title": "BoundingBox::Contains(const BoundingFrustum&) never returns Disjoint and answers Contains when only the first frustum corner is outside",
   "summary": "BoundingBox::Contains(frustum) classifies the frustum from its corners only, so a frustum wholly separate from the box is reported as Intersects, and one whose first corner alone lies outside is reported as Contains.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContainmentType BoundingBox::Contains(const BoundingFrustum&) const; C ABI cna_bounding_box_contains_frustum",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-003.html",
   "sources": [
    "modules/math/src/BoundingBox.cpp",
    "modules/math/src/BoundingFrustum.cpp",
    "modules/math/include/Microsoft/Xna/Framework/BoundingBox.hpp",
    "modules/math/tests/Microsoft/Xna/Framework/BoundingBoxTests.cpp",
    "modules/c-api/src/CnaCApiGeometry.cpp"
   ],
   "related": [
    "development/handbook/add-a-regression-test.html",
    "development/internals/modules/math.html",
    "docs/math-types.html"
   ]
  },
  {
   "id": "CNA-BUG-004",
   "class": "bug",
   "title": "BoundingFrustum::Intersects(Ray) never computes an entry distance: rays starting outside always miss, and an origin on a plane throws",
   "summary": "BoundingFrustum::Intersects(Ray) and Ray::Intersects(BoundingFrustum) report no hit for every ray whose origin is outside the frustum, whatever its direction, return 0 for an origin inside, and throw NotImplementedException for an origin on a plane.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "std::optional<float> BoundingFrustum::Intersects(Ray) const, its output-parameter form, Ray::Intersects(const BoundingFrustum&); C ABI cna_bounding_frustum_intersects_ray and cna_ray_intersects_frustum",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-004.html",
   "sources": [
    "modules/math/src/BoundingFrustum.cpp",
    "modules/math/include/Microsoft/Xna/Framework/BoundingFrustum.hpp",
    "modules/math/src/Ray.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/BoundingFrustumTests.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/RayTests.cpp",
    "modules/c-api/src/CnaCApiGeometry.cpp",
    "modules/c-api/include/CNA/C/geometry.h"
   ],
   "related": [
    "development/handbook/add-a-regression-test.html",
    "development/internals/modules/math.html",
    "docs/c-api.html",
    "docs/math-types.html"
   ]
  },
  {
   "id": "CNA-BUG-006",
   "class": "bug",
   "title": "SpriteEffect caches a MatrixTransform parameter that never exists, so OnApply() never sets the sprite projection",
   "summary": "SpriteEffect looks up a MatrixTransform parameter its base Effect never creates, so Parameters[\"MatrixTransform\"] is null and OnApply() returns before computing the orthographic projection and half-pixel offset.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Graphics::SpriteEffect: its MatrixTransform parameter and OnApply()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-006.html",
   "sources": [
    "modules/graphics/src/Xna/SpriteEffect.cpp",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/SpriteEffect.hpp",
    "modules/graphics/src/Xna/Effect.cpp",
    "modules/graphics/src/Xna/EffectParameterCollection.cpp",
    "modules/graphics/tests/Microsoft/Xna/Framework/Graphics/SpriteEffectTests.cpp",
    "modules/c-api/src/CnaCApiEffects.cpp"
   ],
   "related": [
    "development/handbook/change-public-xna-behavior.html",
    "development/internals/graphics/draw-call.html",
    "docs/effects.html"
   ]
  },
  {
   "id": "CNA-BUG-008",
   "class": "bug",
   "title": "Load<Song> and Load<Video> resolve a same-named .cnj file and return a media object that points at JSON",
   "summary": "ResolveAssetPath tries name.cnj before the Song and Video readers' media extensions, and neither reader handles .cnj, so a same-named .cnj silently becomes the Song or Video file.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "open",
   "severity": "medium",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "ContentManager::Load for Media::Song and Media::Video (the loose-file tier)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-008.html",
   "sources": [
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentManager.hpp",
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/media/src/Xna/Song.cpp",
    "modules/media/src/Xna/Video/Video.cpp"
   ],
   "related": [
    "development/handbook/modify-contentmanager.html",
    "development/internals/content/runtime.html",
    "docs/audio.html",
    "docs/content-manager.html",
    "docs/tutorials/15-background-music.html"
   ]
  },
  {
   "id": "CNA-BUG-012",
   "class": "bug",
   "title": "Two tests still encode the wrong occlusion-query expectation for SDL_GPU after the renderer was made truthful",
   "summary": "SDL_GPU now reports OcclusionQuery false and refuses queries, but the shared capability test still expects true and SdlGpu_OcclusionQuery_Limitation expects a refusal message the public constructor never produces.",
   "subsystem": "Testing & evidence",
   "status": "narrowed",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDeviceCapabilityTest.SupportsOcclusionQuery / SupportsCustomEffects (ExpectedCapabilities()) and the SdlGpu_OcclusionQuery_Limitation CTest, against OcclusionQuery::OcclusionQuery(GraphicsDevice&)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-012.html",
   "sources": [
    "modules/graphics/tests/Microsoft/Xna/Framework/Graphics/GraphicsDeviceCapabilityTests.cpp",
    "modules/renderers/sdl-gpu/examples/sdlgpu_occlusionquery_limitation_test.cpp",
    "modules/graphics/src/Xna/OcclusionQuery.cpp",
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp",
    "modules/renderers/sdl-gpu/CMakeLists.txt",
    "modules/renderers/webgpu/src/WebGPURenderer.cpp",
    "plans/plan_pre_sdlgpu_closeout.md",
    "plans/plan_street_sdlgpu.md"
   ],
   "related": [
    "deep-dives/renderers/sdl-gpu-resources-and-frame-recovery.html",
    "development/handbook/fix-a-renderer-bug.html",
    "development/internals/graphics/device.html",
    "development/internals/graphics/sdl-gpu.html",
    "development/testing/architecture.html",
    "docs/rendering-backends.html"
   ]
  },
  {
   "id": "CNA-BUG-016",
   "class": "bug",
   "title": "The .cnj JSON parser (CNA::Internal::ParseJson) recurses without a nesting limit, so a small crafted document overflows the stack",
   "summary": "JsonParser recurses once per nesting level with no ceiling; a document of 100,000 nested arrays (200,000 bytes) crashed a probe with SIGSEGV instead of throwing JsonParseException, and with the default 8 MiB stack at -O0 about 13,400 levels (27 KB) are already enough.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "open",
   "severity": "medium",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "CNA::Internal::ParseJson - documented to throw JsonParseException for malformed input; reached by every .cnj load, the .cnj compilers and the gamer-services local store",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-016.html",
   "sources": [
    "modules/content/include/CNA/Internal/Json.hpp",
    "modules/content/include/CNA/Internal/CnjEnvelope.hpp",
    "modules/gamer-services/src/Internal/LocalGamerServicesStore.cpp",
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentReader.hpp"
   ],
   "related": [
    "development/internals/content/runtime.html",
    "development/internals/modules/gamer-services.html",
    "docs/content-manager.html"
   ]
  },
  {
   "id": "CNA-BUG-017",
   "class": "bug",
   "title": "XnbReadLimits::maxFileSize is not applied to ContentManager's whole-file .xnb reads",
   "summary": "The 64 MiB maxFileSize ceiling is enforced by the decompressors and the build-time canonical read, but ContentManager reads a run-time .xnb of up to INT32_MAX bytes and the manifest scan reads any size.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Internal::Xnb::XnbReadLimits::maxFileSize (\"Largest .xnb file this reader will attempt to open, in bytes\") as applied by ContentManager::Load",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-017.html",
   "sources": [
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentManager.hpp",
    "modules/content/include/CNA/Internal/Xnb/XnbReadLimits.hpp",
    "modules/content/src/Xnb/XnbDecompression.cpp"
   ],
   "related": [
    "development/internals/content/runtime.html",
    "docs/cnb-format.html",
    "docs/content-pipeline-xnb.html"
   ]
  },
  {
   "id": "CNA-BUG-021",
   "class": "bug",
   "title": "ContentManager::Unload() only clears the cache; it disposes none of the assets it loaded",
   "summary": "Unload() is loadedAssets_.clear(): no IDisposable is tracked or disposed, so assets a game still references stay alive and undisposed, where XNA's Unload disposes everything the manager loaded.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager::Unload(), ContentManager::Dispose() and the protected ContentManager::ReadAsset (its recordDisposableObject contract)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-021.html",
   "sources": [
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentReader.hpp",
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentManager.hpp",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/GraphicsResource.hpp"
   ],
   "related": [
    "development/architecture/content.html",
    "development/internals/content/runtime.html",
    "docs/content-manager.html"
   ]
  },
  {
   "id": "CNA-BUG-022",
   "class": "bug",
   "title": "ReflectiveTypeReader has no TypeVersion, so an XNA .xnb for a [ContentSerializerTypeVersion] type is rejected",
   "summary": "Reader versions must match exactly, as in XNA, but a reflective reader always reports version 0 and ReflectiveTypeReaderBuilder cannot declare the version XNA's ReflectiveReader takes from the attribute.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ReflectiveTypeReader and ReflectiveTypeReaderBuilder (ContentTypeReaderBase::getTypeVersionProperty / SupportsVersion); XNA 4.0 ReflectiveReader.TypeVersion",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-022.html",
   "sources": [
    "modules/content/src/Xna/ContentReader.cpp",
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentTypeReader.hpp",
    "modules/content/include/Microsoft/Xna/Framework/Content/ReflectiveTypeReader.hpp"
   ],
   "related": [
    "development/internals/content/runtime.html",
    "docs/content-pipeline-xnb.html",
    "docs/tutorials/148-custom-content-type.html"
   ]
  },
  {
   "id": "CNA-BUG-025",
   "class": "bug",
   "title": "PlaneIntersectionType's Doxygen swaps the meaning of Front and Back",
   "summary": "PlaneIntersectionType.hpp documents Front as the negative half-space and Back as the positive one, the opposite of what every CNA classification returns and of XNA's meaning.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::PlaneIntersectionType (Front, Back) as documented in its public header",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-025.html",
   "sources": [
    "modules/math/include/Microsoft/Xna/Framework/PlaneIntersectionType.hpp",
    "modules/math/src/Plane.cpp",
    "modules/math/src/BoundingSphere.cpp",
    "modules/math/src/BoundingBox.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/PlaneIntersectionTypeTests.cpp",
    "modules/c-api/tests/pure_c/GeometrySmoke.c"
   ],
   "related": [
    "development/internals/modules/math.html",
    "development/reference/public-headers.html",
    "docs/math-types.html"
   ]
  },
  {
   "id": "CNA-BUG-026",
   "class": "bug",
   "title": "Matrix::CreatePerspectiveFieldOfView accepts a field of view of exactly MathHelper::Pi",
   "summary": "The upper guard compares against the literal 3.141593f, which rounds to the float one step above MathHelper::Pi, so a field of view of exactly Pi passes validation and builds a degenerate projection instead of throwing as XNA does.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Matrix::CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance) and its output-parameter form; C ABI cna_matrix_create_perspective_field_of_view",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-026.html",
   "sources": [
    "modules/math/src/Matrix.cpp",
    "modules/math/include/Microsoft/Xna/Framework/MathHelper.hpp",
    "modules/math/tests/Microsoft/Xna/Framework/MatrixTests.cpp"
   ],
   "related": [
    "development/handbook/add-a-regression-test.html",
    "development/internals/modules/math.html",
    "docs/math-types.html"
   ]
  },
  {
   "id": "CNA-BUG-027",
   "class": "bug",
   "title": "Vector Clamp, Min and Max resolve inverted ranges and NaN operands differently from XNA",
   "summary": "Vector2/3/4::Clamp use std::min(std::max(v, min), max), so max wins when min > max, whereas XNA's vector Clamp and CNA's MathHelper::Clamp let min win; vector and scalar Min/Max also return a different operand from XNA for NaN inputs.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Vector2::Clamp, Vector3::Clamp, Vector4::Clamp, the vector Min and Max, MathHelper::Min and MathHelper::Max; the matching C ABI vector routes",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-027.html",
   "sources": [
    "modules/math/src/Vector3.cpp",
    "modules/math/src/Vector2.cpp",
    "modules/math/src/Vector4.cpp",
    "modules/math/src/MathHelper.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/Vector3Tests.cpp",
    "modules/c-api/src/CnaCApiVectors.cpp"
   ],
   "related": [
    "development/handbook/change-public-xna-behavior.html",
    "development/internals/modules/math.html",
    "docs/math-types.html"
   ]
  },
  {
   "id": "CNA-BUG-028",
   "class": "bug",
   "title": "Curve::ComputeTangent Smooth tangents test the key spacing against two different epsilons, where XNA tests the value difference against one",
   "summary": "For CurveTangent::Smooth, ComputeTangent zeroes the in tangent when the neighbour span is below 2^-24 but the out tangent only below the smallest denormal, while XNA zeroes both when the neighbours' value difference is below FLT_EPSILON.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "Curve::ComputeTangent(int, CurveTangent, CurveTangent), ComputeTangents (all overloads) with CurveTangent::Smooth; the C ABI cna_curve_compute_tangent* routes",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-028.html",
   "sources": [
    "modules/math/src/Curve.cpp",
    "modules/math/src/MathHelper.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/CurveTests.cpp",
    "modules/c-api/src/CnaCApiCurve.cpp"
   ],
   "related": [
    "development/handbook/add-a-regression-test.html",
    "development/internals/modules/math.html",
    "docs/math-types.html"
   ]
  },
  {
   "id": "CNA-BUG-029",
   "class": "bug",
   "title": "Copying a GraphicsResource bypasses GraphicsDevice resource tracking (copies of Texture2D and TextureCube escape device disposal)",
   "summary": "A copy-constructed Texture2D or TextureCube is never registered with its GraphicsDevice, so device disposal neither disposes it nor releases the renderer texture it shares, and a cross-device copy assignment leaves a stale registration behind.",
   "subsystem": "Graphics & renderers",
   "status": "narrowed",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Graphics::GraphicsResource copy constructor and copy assignment; Texture2D(const Texture2D&), TextureCube(const TextureCube&); GraphicsDevice::AddResourceReference / GraphicsDevice::Dispose()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-029.html",
   "sources": [
    "modules/graphics/src/Xna/GraphicsResource.cpp",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/GraphicsResource.hpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/GraphicsDevice.hpp",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/Texture2D.hpp",
    "modules/graphics/src/Xna/Texture2D.cpp",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/TextureCube.hpp",
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentManager.hpp"
   ],
   "related": [
    "development/architecture/graphics.html",
    "development/handbook/debug-shutdown-and-lifetime.html",
    "development/internals/graphics/resources.html",
    "development/internals/runtime/shutdown.html",
    "development/takeover/ownership.html",
    "docs/content-manager.html",
    "docs/tutorials/71-memory-management.html"
   ]
  },
  {
   "id": "CNA-BUG-035",
   "class": "bug",
   "title": "devices-tests.yml's exact-name gtest filters skip seven Microsoft::Devices suites and never match the FileDialog and MessageBox suites",
   "summary": "DEVICES_GTEST_FILTER misses 29 of 474 TEST definitions under modules/devices/tests, and CNA_DEVICES_GTEST_FILTER names FileDialogTests.* and MessageBoxTests.*, which match no suite, so the 12 FileDialog and MessageBox cases run in no CI job.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": ".github/workflows/devices-tests.yml: DEVICES_GTEST_FILTER (documented as every TEST(...) under modules/devices/tests/Microsoft/Devices/, no more and no fewer) and CNA_DEVICES_GTEST_FILTER (the modules/devices-ext/tests/CNA/Devices/ scope, REMED-BUILD-011)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-035.html",
   "sources": [
    ".github/workflows/devices-tests.yml",
    "modules/devices-ext/tests/CNA/Devices/FileDialogTests.cpp",
    "modules/devices-ext/tests/CNA/Devices/MessageBoxTests.cpp",
    "modules/devices/tests/Microsoft/Devices/Detail/DevicesShutdownCoordinatorTests.cpp",
    "docs/devices-build.md",
    "CMakePresets.json",
    "docs/devices-thread-safety.md",
    "modules/devices/tests/Microsoft/Devices/Sensors/Detail/NativeDiagnosticTests.cpp"
   ],
   "related": [
    "development/internals/modules/devices.html",
    "development/testing/architecture.html",
    "development/workflows.html",
    "docs/sensors.html",
    "docs/tutorials/117-devices-layer.html"
   ]
  },
  {
   "id": "CNA-BUG-036",
   "class": "bug",
   "title": "run-all-renderer-smoke-tests.sh ignores the build's exit status, and its '-- -k' build flag aborts every Ninja build, so smoke verdicts can come from stale binaries",
   "summary": "The orchestrator runs cmake --build <dir> -j4 -- -k and discards the result; -k without a count is a make option that Ninja rejects, so in a Ninja tree nothing is rebuilt and ctest runs whatever executables the tree already holds.",
   "subsystem": "Testing & evidence",
   "status": "narrowed",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "scripts/run-all-renderer-smoke-tests.sh (default, --tier and --multi modes): a renderer that configures and builds but fails its smoke test fails the run",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-036.html",
   "sources": [
    "scripts/run-all-renderer-smoke-tests.sh",
    "CMakePresets.json",
    "docs/runtime-renderer-selection.md"
   ],
   "related": [
    "development/internals/graphics/selection.html",
    "development/testing/architecture.html",
    "docs/runtime-renderer-selection.html"
   ]
  },
  {
   "id": "CNA-BUG-041",
   "class": "bug",
   "title": "ContentManager resolves a relative RootDirectory against the working directory, not TitleLocation, and its .cnb and loose tiers cannot see Android packaged assets",
   "summary": "TitleContainer now has consumers and the .xnb tier reaches Android packaged assets, but ContentManager never consults TitleLocation::Path, and its .cnb and loose tiers gate on std::filesystem::exists.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "narrowed",
   "severity": "medium",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "ContentManager::RootDirectory and ContentManager::Load path resolution (XNA resolves through TitleContainer.OpenStream, relative to the title location)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-041.html",
   "sources": [
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentManager.hpp",
    "modules/runtime/src/TitleContainer.cpp",
    "modules/runtime/src/TitleLocation.cpp",
    "modules/graphics/src/Internal/ImageLoader.cpp",
    "docs/apple-platforms.md"
   ],
   "related": [
    "deep-dives/platforms/android-and-apple-platforms.html",
    "development/internals/content/runtime.html",
    "docs/content-manager.html",
    "docs/platforms.html"
   ]
  },
  {
   "id": "CNA-BUG-045",
   "class": "bug",
   "title": "THIRD_PARTY_NOTICES.md still omits the vendored cgltf and stb image headers (and ENet and dr_libs)",
   "summary": "Draco and stb_vorbis now have notices, but cgltf, stb_image/stb_image_write, ENet and dr_flac/dr_mp3, all vendored under third_party/ and compiled into CNA libraries, are not listed.",
   "subsystem": "Documentation & release tooling",
   "status": "narrowed",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "THIRD_PARTY_NOTICES.md as CNA's record of third-party licences for code it compiles in",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-045.html",
   "sources": [
    "THIRD_PARTY_NOTICES.md",
    "third_party/cgltf/LICENSE",
    "third_party/enet/LICENSE",
    "modules/content/src/GltfImport/GltfImportCore.cpp",
    "modules/graphics/src/Internal/ImageLoader.cpp",
    "modules/audio/src/Backend/CnaMixer/DrLibs.cpp"
   ],
   "related": [
    "development/internals/content/runtime.html",
    "development/repository/source-ownership.html",
    "docs/tutorials/100-shipping.html"
   ]
  },
  {
   "id": "CNA-BUG-047",
   "class": "bug",
   "title": "StorageContainer::GetFileNames/GetDirectoryNames(searchPattern): GlobMatch treats ? as one byte and compares case-sensitively on every host",
   "summary": "The hand-written matcher behind the pattern overloads matches ? against one UTF-8 byte rather than one character and compares bytes case-sensitively even on Windows, where XNA's Directory.GetFiles matching is not; only star patterns over ASCII names are exercised by any test, and only through the C ABI smoke test.",
   "subsystem": "Storage",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Storage::StorageContainer::GetFileNames(const std::string& searchPattern) and GetDirectoryNames(const std::string& searchPattern); the C name-count and name-copy routes that take a search_pattern",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-047.html",
   "sources": [
    "modules/storage/src/StorageContainer.cpp",
    "modules/storage/include/Microsoft/Xna/Framework/Storage/StorageContainer.hpp",
    "modules/c-api/src/CnaCApiStorage.cpp",
    "modules/storage/tests/Microsoft/Xna/Framework/Storage/StorageDeviceTests.cpp",
    "modules/c-api/tests/pure_c/StorageSmoke.c"
   ],
   "related": [
    "development/internals/modules/storage.html",
    "docs/storage.html"
   ]
  },
  {
   "id": "CNA-BUG-049",
   "class": "bug",
   "title": "Accelerometer, Gyroscope, Compass and Motion declare Dispose(bool) public, so an external Dispose(false) marks the sensor disposed without cleanup",
   "summary": "SensorBase declares Dispose(bool) protected, but the four sensor classes redeclare it public; Dispose(false) sets the disposed flag without Stop, unregistration or releasing the platform lease, and the destructor then skips cleanup.",
   "subsystem": "Input",
   "status": "narrowed",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Devices::Sensors::Accelerometer::Dispose(bool), Gyroscope::Dispose(bool), Compass::Dispose(bool) and Motion::Dispose(bool); the IDisposable pattern of SensorBase<T>",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-049.html",
   "sources": [
    "modules/devices/include/Microsoft/Devices/Sensors/Accelerometer.hpp",
    "modules/devices/include/Microsoft/Devices/Sensors/Gyroscope.hpp",
    "modules/devices/include/Microsoft/Devices/Sensors/Compass.hpp",
    "modules/devices/include/Microsoft/Devices/Sensors/Motion.hpp",
    "modules/devices/include/Microsoft/Devices/Sensors/SensorBase.hpp",
    "modules/devices/src/Sensors/Accelerometer.cpp",
    "modules/devices/include/Microsoft/Devices/Sensors/Detail/PlatformSensorSubsystem.hpp",
    "modules/gamer-services/include/Microsoft/Xna/Framework/GamerServices/AvatarRenderer.hpp",
    "remediation/MASTER_REMEDIATION_PLAN.md"
   ],
   "related": [
    "deep-dives/services/sensors-and-vibration.html",
    "development/internals/modules/devices.html",
    "docs/sensors.html"
   ]
  },
  {
   "id": "CNA-BUG-050",
   "class": "bug",
   "title": "Guide message-box and keyboard-input results cannot be waited on: GamerServicesDispatcher::Update pumps nothing and their AsyncWaitHandle is signalled before completion",
   "summary": "The dispatcher's Update advances nothing and UpdateAsync only reports whether Initialize has run, and the Guide results that stay pending expose an already-signalled wait handle, so a pump loop on a pending Guide result spins forever and WaitOne returns before End can succeed.",
   "subsystem": "Networking & gamer services",
   "status": "narrowed",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GamerServicesDispatcher::Update(), GamerServicesDispatcher::UpdateAsync(); getAsyncWaitHandleProperty() and getIsCompletedProperty() of the IAsyncResult returned by Guide::BeginShowMessageBox and Guide::BeginShowKeyboardInput",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-050.html",
   "sources": [
    "modules/gamer-services/src/Xna/GamerServicesDispatcher.cpp",
    "modules/gamer-services/src/Xna/Guide.cpp",
    "modules/gamer-services/include/Microsoft/Xna/Framework/GamerServices/Guide.hpp",
    "modules/gamer-services/src/Xna/GamerServicesComponent.cpp",
    "modules/net/src/Xna/NetworkSession.cpp",
    "modules/gamer-services/src/Xna/SignedInGamer.cpp",
    "modules/net/tests/CNA/Internal/Net/GamerServicesDispatcherHangRegressionTest.cpp"
   ],
   "related": [
    "deep-dives/services/gamer-services-contract.html",
    "development/internals/modules/gamer-services.html",
    "docs/tutorials/123-achievements.html"
   ]
  },
  {
   "id": "CNA-BUG-052",
   "class": "bug",
   "title": "SongTypeReader and MediaLibraryIndex offer song formats (.opus, .aac, .wma) that no CNA-configured mixer decodes",
   "summary": "Load<Song> resolves .opus, .aac and .wma files and the media library indexes .opus, but neither the vendored SDL3_mixer build nor CNA's ALSA mixer decodes them, so such songs load and then silently fail to play.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "low",
   "confidence": "strong",
   "tests_present": true,
   "public_contract": "ContentManager::Load<Media::Song> (loose-file tier, SongTypeReader::GetExtensions) and MediaLibrary::getSongsProperty (MediaLibraryIndex scan)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-052.html",
   "sources": [
    "modules/content/src/Xna/ContentManager.cpp",
    "cmake/ThirdPartySDL.cmake",
    "modules/audio/src/Backend/CnaMixer/CnaMixerDecoders.cpp",
    "modules/audio/src/Backend/Sdl3Mixer/MixerEngine.cpp",
    "modules/media/src/Xna/MediaPlayer.cpp",
    "modules/media/src/Internal/MediaLibraryIndex.cpp",
    "modules/media/include/CNA/Internal/Media/MediaLibraryIndex.hpp",
    "modules/audio/tests/Microsoft/Xna/Framework/Audio/CnaMixerXnaTests.cpp",
    "modules/media/tests/Microsoft/Xna/Framework/Media/MediaLibraryTests.cpp"
   ],
   "related": [
    "deep-dives/services/media-contract.html",
    "development/internals/audio/engine.html",
    "development/internals/modules/media.html",
    "docs/audio.html",
    "docs/content-manager.html",
    "docs/tutorials/122-media-library.html"
   ]
  },
  {
   "id": "CNA-BUG-054",
   "class": "bug",
   "title": "HEADLESS reports occlusion-query support and a precise pixel count while its query always answers 1",
   "summary": "HEADLESS inherits OcclusionQuery = true and the default isPixelCountPreciseEXT() = true, but HeadlessOcclusionQueryRenderer completes at once and returns PixelCount() == 1 whatever was drawn.",
   "subsystem": "Graphics & renderers",
   "status": "narrowed",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::GraphicsCapability::OcclusionQuery and OcclusionQuery::isPixelCountPreciseEXT() on the HEADLESS renderer",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-054.html",
   "sources": [
    "modules/renderers/headless/src/HeadlessRenderer.cpp",
    "modules/renderers/headless/include/CNA/Internal/Renderers/Headless/HeadlessRenderer.hpp",
    "modules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp",
    "modules/graphics/include/CNA/GraphicsCapability.hpp",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/OcclusionQuery.hpp",
    "modules/graphics/tests/Microsoft/Xna/Framework/Graphics/OcclusionQueryPixelCountPrecisionTests.cpp",
    "modules/graphics/tests/Microsoft/Xna/Framework/Graphics/GraphicsDeviceCapabilityTests.cpp"
   ],
   "related": [
    "development/architecture/graphics.html",
    "development/internals/graphics/headless.html",
    "development/testing/architecture.html",
    "docs/rendering-backends.html"
   ]
  },
  {
   "id": "CNA-BUG-055",
   "class": "bug",
   "title": "Stale whole-registry renderer counts survive outside check_renderer_identities.py's list: the C API's CORE.md and FEATURE_MATRIX.md say 50, core_ext.h says 46, ModuleProbes.cmake says 42, and CHANGELOG says 49 for a 50-identity release",
   "summary": "CNA has 25 public renderer identities, yet the C API's backend-classification contract, a public C header's Doxygen, a CMake test header and the alpha.1 release notes still state obsolete totals that no count gate reads.",
   "subsystem": "Documentation & release tooling",
   "status": "narrowed",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Documentation of cna_graphics_backend_get_category / cna_graphics_backend_get_maturity (docs/c-api/CORE.md, docs/c-api/FEATURE_MATRIX.md), of cna_graphics_renderer_get_is_available_ext (CNA/C/core_ext.h), and the CHANGELOG release notes",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-055.html",
   "sources": [
    "docs/c-api/CORE.md",
    "docs/c-api/FEATURE_MATRIX.md",
    "modules/c-api/include/CNA/C/core_ext.h",
    "cmake/Tests/ModuleProbes.cmake",
    "CHANGELOG.md",
    "scripts/check_renderer_identities.py",
    "docs/c-api/LIMITATIONS.md",
    "tools/c-api/limitations.json",
    "tools/c-api/compatibility_matrix.json",
    "cmake/RendererIdentities.cmake"
   ],
   "related": [
    "development/handbook/update-the-c-api.html",
    "development/internals/modules/core.html",
    "development/repository/index.html",
    "docs/c-api.html"
   ]
  },
  {
   "id": "CNA-BUG-056",
   "class": "bug",
   "title": "docs/c-api/FEATURE_MATRIX.md and docs/c-api/README.md still present the C ABI as version 0.1.0 while abi.h declares 0.29.0",
   "summary": "The release gate now reads its ABI label from abi.h, but the C API feature matrix is titled '0.1 Feature Matrix' with an ABI row of 'Experimental version 0.1.0', and the C API README describes the library as 0.1.0.",
   "subsystem": "Documentation & release tooling",
   "status": "narrowed",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "cna_get_abi_version and the ABI identity declared in CNA/C/abi.h (CNA_ABI_VERSION_MAJOR / MINOR / PATCH), as documented under docs/c-api",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-056.html",
   "sources": [
    "docs/c-api/FEATURE_MATRIX.md",
    "docs/c-api/README.md",
    "modules/c-api/include/CNA/C/abi.h",
    "tools/c-api/check_release_gate.py"
   ],
   "related": [
    "development/handbook/update-the-c-api.html",
    "development/internals/bindings/c-api-internals.html",
    "docs/c-api.html"
   ]
  },
  {
   "id": "CNA-BUG-057",
   "class": "bug",
   "title": "RegisterAllBuiltInXnbReaders() documentation still calls the general EffectReader a known-unsupported placeholder",
   "summary": "XnbBuiltInReaders.hpp says the function registers \"the known-unsupported placeholder (the general EffectReader, XNB-32A)\", but it registers the implemented EffectReader and the placeholder hook registers nothing.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Internal::Xnb::RegisterAllBuiltInXnbReaders() (doc comment in XnbBuiltInReaders.hpp)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-057.html",
   "sources": [
    "modules/content/include/CNA/Internal/Xnb/XnbBuiltInReaders.hpp",
    "modules/content/src/Xnb/XnbBuiltInReaders.cpp",
    "modules/content/src/Xnb/EffectContentTypeReader.cpp",
    "modules/content/src/Xna/KnownUnsupportedContentTypeReader.cpp"
   ],
   "related": [
    "development/internals/content/runtime.html",
    "docs/content-pipeline-xnb.html",
    "docs/tutorials/147-xnb-interop.html"
   ]
  },
  {
   "id": "CNA-BUG-058",
   "class": "bug",
   "title": "LIMITATIONS.md omits the 468 planned C API symbols and RELEASE_GATE.md still attributes 654 declarations to CBIND-117",
   "summary": "The generated C API limitations document partitions 8,887 of the 9,355 declarations it counts and never mentions the 468 planned ones, and the release-gate note still says the Content Pipeline task owns 654 declarations where the plan records 134.",
   "subsystem": "Documentation & release tooling",
   "status": "narrowed",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "docs/c-api/LIMITATIONS.md (generated by tools/c-api/generate_limitations.py) and docs/c-api/RELEASE_GATE.md (generated from tools/c-api/release_gate.json)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-058.html",
   "sources": [
    "docs/c-api/LIMITATIONS.md",
    "tools/c-api/generate_limitations.py",
    "docs/c-api/RELEASE_GATE.md",
    "tools/c-api/release_gate.json",
    "plans/plan_binding.md",
    "docs/c-api/COVERAGE.md"
   ],
   "related": [
    "development/handbook/update-the-c-api.html",
    "docs/c-api.html"
   ]
  },
  {
   "id": "CNA-BUG-061",
   "class": "bug",
   "title": "README.md, docs/coverage.md and docs/xna-4-api-coverage.md still report 3,467/3,627 runtime members and 160 gaps; the generated report says 3,627/3,627",
   "summary": "CNA's root README and two coverage documents print the pre-closure XNA runtime member figure (3,467 of 3,627, 95.59%, 160 gaps), while the generated member report they point to records 3,627 of 3,627 represented and none missing.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "README.md project-status headline and the documents that restate it; docs/xna-4-runtime-member-coverage.md (generated by tools/audit_xna_runtime_surface.py)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-061.html",
   "sources": [
    "README.md",
    "docs/xna-4-api-coverage.md",
    "docs/coverage.md",
    "docs/xna-4-runtime-member-coverage.md",
    "docs/xna-4-runtime-member-coverage.json",
    "tools/audit_xna_runtime_surface.py"
   ],
   "related": [
    "deep-dives/foundations/compatibility-and-evidence.html",
    "docs/verification.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-BUG-062",
   "class": "bug",
   "title": "MODULE_SCOPE in generate_coverage_inventory.py leaves design, diagnostics and inspector unclassified, so every C API inventory gate stops",
   "summary": "The C API coverage generator refuses to run because three public modules are missing from MODULE_SCOPE, so the coverage, limitations, scope-model and release-gate checks fail at this snapshot and the committed coverage numbers cannot be re-derived.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "medium",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "tools/c-api/generate_coverage_inventory.py --check (MODULE_SCOPE, validate_module_scope) and the CTests CApiCoverageMatrix, CApiCoverageScopeModel, CApiLimitations and CApiReleaseGate",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-062.html",
   "sources": [
    "tools/c-api/generate_coverage_inventory.py",
    "tools/c-api/generate_limitations.py",
    "tools/c-api/check_release_gate.py",
    "tools/c-api/release_gate.json",
    "tools/c-api/test_coverage_scope.py",
    "cmake/Tests/ModuleProbes.cmake",
    ".github/workflows/general-tests-ci.yml",
    ".github/workflows/c-api-coverage-gate.yml",
    "modules/design/include/Microsoft/Xna/Framework/Design.hpp",
    "modules/diagnostics/include/CNA/Diagnostics/Diagnostics.hpp",
    "modules/inspector/include/CNA/Inspector/Agent.hpp",
    "plans/plan_capi_smoke_stability.md"
   ],
   "related": [
    "development/handbook/update-the-c-api.html",
    "development/internals/bindings/c-api-internals.html",
    "development/testing/architecture.html",
    "docs/c-api.html",
    "docs/roadmap.html"
   ]
  },
  {
   "id": "CNA-BUG-063",
   "class": "bug",
   "title": "Vector3::Length, LengthSquared, Distance and DistanceSquared accumulate in float, not at the width CNA measured XNA to use",
   "summary": "CNA's own measurement of the XNA 4.0 runtime found Vector3.Distance summed at extended precision (a float sum matched none of 200 pairs), and BoundingSphere.cpp follows that rule, but the public Vector3 length and distance functions still sum in float.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "recorded-by-cna",
   "tests_present": true,
   "public_contract": "Vector3::Length(), LengthSquared(), Vector3::Distance and Vector3::DistanceSquared (all overloads); the matching C ABI vector routes",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-063.html",
   "sources": [
    "modules/math/src/Vector3.cpp",
    "modules/math/src/BoundingSphere.cpp",
    "plans/plan_xna_sample_xnb_sweep.md",
    "modules/math/tests/Microsoft/Xna/Framework/BoundingSphereOracleTests.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/Vector3Tests.cpp"
   ],
   "related": [
    "deep-dives/foundations/compatibility-and-evidence.html",
    "development/internals/modules/math.html",
    "docs/math-types.html",
    "docs/verification.html"
   ]
  },
  {
   "id": "CNA-BUG-064",
   "class": "bug",
   "title": "Curve::Evaluate reads the wrong key for Step continuity away from position 1 and for a Linear post-loop",
   "summary": "A Step segment returns the next key's value whenever the evaluated position is at least 1.0 (an absolute constant) instead of at the segment's end, and a Linear post-loop extrapolates with the first key's TangentOut instead of the last key's; XNA does neither.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "float Curve::Evaluate(float position) const with CurveContinuity::Step keys or CurveLoopType::Linear post-loop; C ABI cna_curve_evaluate",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-064.html",
   "sources": [
    "modules/math/src/Curve.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/CurveTests.cpp",
    "modules/c-api/tests/pure_c/CurveSmoke.c",
    "modules/c-api/src/CnaCApiCurve.cpp",
    "modules/content/src/Xnb/CurveContentTypeReader.cpp"
   ],
   "related": [
    "development/handbook/add-a-regression-test.html",
    "development/handbook/change-public-xna-behavior.html",
    "development/internals/modules/math.html",
    "docs/math-types.html"
   ]
  },
  {
   "id": "CNA-BUG-065",
   "class": "bug",
   "title": "Curve::Evaluate divides by zero for coincident key positions, returning NaN and converting infinity to int in the cyclic loop modes",
   "summary": "GetNumberOfCycle and GetCurvePosition divide by the key span and the segment width without a guard, so curves with coincident keys yield NaN or undefined behaviour where XNA returns the first key's value.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Curve::Evaluate(float) for curves whose keys share positions (accepted by CurveKeyCollection::Add); C ABI cna_curve_evaluate",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-065.html",
   "sources": [
    "modules/math/src/Curve.cpp",
    "modules/math/src/CurveKeyCollection.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/CurveTests.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/CurveKeyCollectionTests.cpp"
   ],
   "related": [
    "development/handbook/add-a-regression-test.html",
    "development/internals/modules/math.html",
    "docs/math-types.html"
   ]
  },
  {
   "id": "CNA-BUG-066",
   "class": "bug",
   "title": "BoundingFrustum::Contains(Vector3) answers Intersects for a point exactly on a plane and skips the remaining planes",
   "summary": "BoundingFrustum::Contains(point) returns Disjoint for any positive plane distance and, for a distance of exactly zero, Intersects without testing the remaining planes; XNA never answers Intersects for a point and uses a 1e-5 tolerance.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContainmentType BoundingFrustum::Contains(Vector3) const and its output-parameter form; C ABI cna_bounding_frustum_contains_point",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-066.html",
   "sources": [
    "modules/math/src/BoundingFrustum.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/BoundingFrustumTests.cpp",
    "modules/c-api/tests/pure_c/GeometrySmoke.c",
    "modules/c-api/src/CnaCApiGeometry.cpp"
   ],
   "related": [
    "development/handbook/add-a-regression-test.html",
    "development/internals/modules/math.html",
    "docs/math-types.html"
   ]
  },
  {
   "id": "CNA-BUG-067",
   "class": "bug",
   "title": "Math argument failures throw a mix of Sharp Runtime and std:: exception types that differs between near-identical functions",
   "summary": "BoundingBox throws Sharp Runtime ArgumentException types as XNA does, but BoundingSphere::CreateFromPoints, BoundingFrustum::GetCorners and the perspective builders throw std::invalid_argument or std::out_of_range.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The exception types thrown by the math module's argument checks (CreateFromPoints, GetCorners, the Matrix::CreatePerspective* builders and the indexed overloads)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-067.html",
   "sources": [
    "modules/math/src/BoundingBox.cpp",
    "modules/math/src/BoundingSphere.cpp",
    "modules/math/src/BoundingFrustum.cpp",
    "modules/math/src/Matrix.cpp",
    "CHECKLIST.md",
    "modules/c-api/src/CnaCApiDetail.hpp"
   ],
   "related": [
    "deep-dives/framework/game-class-and-lifecycle.html",
    "development/internals/bindings/c-api-internals.html",
    "development/internals/modules/math.html"
   ]
  },
  {
   "id": "CNA-BUG-068",
   "class": "bug",
   "title": "Vector2/3/4 and Matrix division by a scalar divide every component where XNA 4.0 multiplies by one reciprocal",
   "summary": "Divide(v, s), operator/(v, s) and Matrix::Divide(m, s) divide per component where XNA multiplies by 1/s, so results can differ in the last bit; Vector3::operator/= alone uses the reciprocal.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Vector2/Vector3/Vector4::Divide(value, float), operator/(value, float), operator/=(float); Matrix::Divide(const Matrix&, float, Matrix&)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-068.html",
   "sources": [
    "modules/math/src/Vector3.cpp",
    "modules/math/src/Vector2.cpp",
    "modules/math/src/Vector4.cpp",
    "modules/math/src/Matrix.cpp"
   ],
   "related": [
    "deep-dives/framework/vector-matrix-numerics.html",
    "development/internals/modules/math.html"
   ]
  },
  {
   "id": "CNA-BUG-069",
   "class": "bug",
   "title": "Ray::Intersects(BoundingBox) and Ray::Intersects(BoundingSphere) differ from XNA 4.0 on degenerate and boundary rays",
   "summary": "A zero-direction ray inside a box returns no hit (XNA: 0), axis parallelism uses a 2^-24 threshold where XNA uses 1e-6, and a ray starting exactly on a sphere and pointing outward returns no hit (XNA: 0, because XNA's inside test is <=).",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Ray::Intersects(BoundingBox) and Ray::Intersects(BoundingSphere) (and the out-parameter overloads)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-069.html",
   "sources": [
    "modules/math/src/Ray.cpp",
    "modules/math/src/MathHelper.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/RayTests.cpp"
   ],
   "related": [
    "deep-dives/framework/bounding-volumes-and-intersections.html",
    "development/internals/modules/math.html"
   ]
  },
  {
   "id": "CNA-BUG-070",
   "class": "bug",
   "title": "BoundingSphere::Contains(Vector3) and Contains(BoundingSphere) return different ContainmentType values from XNA 4.0",
   "summary": "A point exactly on the surface is Intersects in CNA (XNA: Disjoint), and Contains(BoundingSphere) tests d^2 <= (R - r)^2, losing the sign of R - r, so a small sphere reports that it Contains a larger concentric sphere (XNA: Intersects).",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::BoundingSphere::Contains(Vector3), Contains(BoundingSphere) and their out-parameter overloads",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-070.html",
   "sources": [
    "modules/math/src/BoundingSphere.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/BoundingSphereTests.cpp"
   ],
   "related": [
    "deep-dives/framework/bounding-volumes-and-intersections.html",
    "development/internals/modules/math.html"
   ]
  },
  {
   "id": "CNA-BUG-071",
   "class": "bug",
   "title": "BoundingFrustum::Intersects differs from XNA 4.0: box and sphere overloads use a conservative plane test, and the Plane overload counts an on-plane corner as Intersecting",
   "summary": "The box and sphere overloads report true for volumes just outside an edge or corner where XNA's exact GJK query reports false, and the Plane overload treats a zero corner distance as Intersecting (XNA: Back).",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::BoundingFrustum::Intersects(BoundingBox), Intersects(BoundingSphere), Intersects(Plane); BoundingBox/BoundingSphere::Intersects(BoundingFrustum)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-071.html",
   "sources": [
    "modules/math/src/BoundingFrustum.cpp",
    "modules/math/src/BoundingBox.cpp",
    "modules/graphics-ext/src/FrustumCullerEXT.cpp"
   ],
   "related": [
    "deep-dives/framework/bounding-volumes-and-intersections.html",
    "development/internals/modules/math.html"
   ]
  },
  {
   "id": "CNA-BUG-072",
   "class": "bug",
   "title": "BoundingBox::ToString and Ray::ToString emit literal doubled braces ({{Min:... }}) where XNA 4.0 prints single braces",
   "summary": "Both copy FNA's string concatenation of '{{' and '}}'; XNA builds the same text with string.Format, whose escaped '{{' yields one brace. BoundingBoxTest.ToStringMatchesFNAFormat pins the FNA form.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::BoundingBox::ToString(), Ray::ToString()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-072.html",
   "sources": [
    "modules/math/src/BoundingBox.cpp",
    "modules/math/src/Ray.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/BoundingBoxTests.cpp"
   ],
   "related": [
    "deep-dives/framework/math-value-types-and-layout.html"
   ]
  },
  {
   "id": "CNA-BUG-073",
   "class": "bug",
   "title": "Math ToString methods print floats with six significant digits and the C++ global locale, where XNA 4.0 uses Single.ToString(CurrentCulture)",
   "summary": "The math ToString methods stream floats through a default std::ostringstream (6 digits, global locale), while .NET's Single.ToString prints up to 7 significant digits in the current culture.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "strong",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Vector2/Vector3/Vector4/Quaternion/Matrix/Plane::ToString()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-073.html",
   "sources": [
    "modules/math/src/Vector3.cpp",
    "modules/math/src/Matrix.cpp"
   ],
   "related": [
    "deep-dives/framework/math-value-types-and-layout.html"
   ]
  },
  {
   "id": "CNA-BUG-074",
   "class": "bug",
   "title": "Vector, Matrix, Quaternion and CurveKey hash codes use raw float bits, so +0.0f and -0.0f components compare equal but hash differently",
   "summary": "FloatHash returns the IEEE bit pattern, so Equals and GetHashCode disagree for values with a negative-zero component; .NET's Single.GetHashCode returns 0 for both zeros, keeping XNA's hashes consistent with Equals.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GetHashCode() of Vector2, Vector3, Vector4, Matrix, Quaternion and CurveKey",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-074.html",
   "sources": [
    "modules/math/src/Vector3.cpp",
    "modules/math/src/Matrix.cpp",
    "modules/math/src/Quaternion.cpp"
   ],
   "related": [
    "deep-dives/framework/math-value-types-and-layout.html"
   ]
  },
  {
   "id": "CNA-BUG-075",
   "class": "bug",
   "title": "Point declares +, -, * and / operators that XNA 4.0's Point does not have, without the CNAEXT marker, and / has no divide-by-zero guard",
   "summary": "CNA_STRICT_XNA_API cannot flag these extensions because they are not marked CNAEXT, and Point / Point with a zero component is an integer division by zero.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Point operator+, operator-, operator*, operator/",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-075.html",
   "sources": [
    "modules/math/include/Microsoft/Xna/Framework/Point.hpp",
    "modules/math/src/Point.cpp"
   ],
   "related": [
    "deep-dives/framework/rectangle-point-and-color.html",
    "deep-dives/reference/cnaext-catalog.html"
   ]
  },
  {
   "id": "CNA-BUG-076",
   "class": "bug",
   "title": "Color::FromNonPremultiplied(int r, int g, int b, int a) multiplies in 32-bit int, so large arguments overflow (undefined behaviour)",
   "summary": "CNA computes r * a / 255 in int; XNA 4.0 widens to 64-bit long before multiplying and clamps the result, so arguments whose product exceeds INT_MAX are defined in XNA and undefined in CNA.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Color::FromNonPremultiplied(intcs r, intcs g, intcs b, intcs a)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-076.html",
   "sources": [
    "modules/math/src/Color.cpp"
   ],
   "related": [
    "deep-dives/framework/rectangle-point-and-color.html"
   ]
  },
  {
   "id": "CNA-BUG-077",
   "class": "bug",
   "title": "An invalid CNA_GRAPHICS_RENDERER value (or Module.cnaPreferredRenderer) terminates the process during static initialisation",
   "summary": "The renderer registry publishes the compiled-in set from a namespace-scope initialiser that consults the environment, so an unknown or not-linked renderer name throws out of that initialiser and ends the process through std::terminate before main.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The CNA_GRAPHICS_RENDERER environment variable and the Emscripten Module.cnaPreferredRenderer page property as inputs to CNA::GraphicsRendererSelection",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-077.html",
   "sources": [
    "cmake/templates/CnaRendererRegistry.generated.cpp.in",
    "modules/core/src/GraphicsRendererSelection.cpp",
    "modules/core/include/CNA/GraphicsRendererSelection.hpp",
    "modules/core/src/GraphicsRendererSelectionEmscripten.cpp",
    "modules/graphics/tests/CNA/GraphicsRendererSelectionTests.cpp"
   ],
   "related": [
    "development/internals/graphics/selection.html",
    "development/internals/modules/core.html",
    "docs/runtime-renderer-selection.html"
   ]
  },
  {
   "id": "CNA-BUG-078",
   "class": "bug",
   "title": "Game::PollEvents fires the renderer's test-only context-loss hooks on F9/F10 in every build",
   "summary": "A non-repeated F9 or F10 press in any CNA game calls the renderer's DebugSimulateContextLoss() or DebugRestoreContext(), a channel CNA itself describes as a test seam, with no build, option or opt-out guard.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Game::Run() / Tick() (through the private PollEvents); CNA::Internal::Renderers::IGraphicsRenderer::DebugSimulateContextLoss() and DebugRestoreContext()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-078.html",
   "sources": [
    "modules/runtime/src/Game.cpp",
    "modules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp",
    "modules/renderers/easygl/src/EasyGLRenderer.cpp",
    "modules/renderers/directx11/src/DirectX11Renderer.cpp",
    "modules/renderers/webgpu/src/WebGPURenderer.cpp",
    "modules/runtime/tests/Microsoft/Xna/Framework/GameEventSemanticsGoldenTests.cpp"
   ],
   "related": [
    "deep-dives/framework/game-class-and-lifecycle.html",
    "development/architecture/runtime.html",
    "development/debugging.html",
    "development/internals/runtime/frame.html",
    "docs/input.html"
   ]
  },
  {
   "id": "CNA-BUG-080",
   "class": "bug",
   "title": "The Emscripten Game loop (EmscriptenMainLoopCallback) does not implement Game's loop contract",
   "summary": "In the browser, Game ignores IsFixedTimeStep = false, SuppressDraw and ResetElapsedTime, uses FNA's clock order instead of the XNA rule the desktop loop implements, and turns a frame exception into a normal return from Run() without Exiting.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Game::Run() under Emscripten; IsFixedTimeStep, SuppressDraw(), ResetElapsedTime(), GameTime, the Exiting event",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-080.html",
   "sources": [
    "modules/runtime/src/Game.cpp",
    "modules/runtime/tests/Microsoft/Xna/Framework/GameClockFirstUpdateTests.cpp"
   ],
   "related": [
    "deep-dives/framework/game-class-and-lifecycle.html",
    "deep-dives/framework/game-time-and-timestep.html",
    "deep-dives/platforms/web-build-and-main-loop.html",
    "development/architecture/runtime.html",
    "development/internals/runtime/frame.html",
    "docs/game-loop.html"
   ]
  },
  {
   "id": "CNA-BUG-081",
   "class": "bug",
   "title": "Game::InactiveSleepTime is stored and validated but the loop never sleeps while the game is inactive",
   "summary": "InactiveSleepTime is documented in Game.hpp and the C API as how long the loop sleeps while the game is inactive, but nothing in Tick, RunLoop or the browser frame reads it, so an unfocused game keeps its full frame rate.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Game::getInactiveSleepTimeProperty() / setInactiveSleepTimeProperty(); cna_game_get_inactive_sleep_time_ticks / cna_game_set_inactive_sleep_time_ticks",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-081.html",
   "sources": [
    "modules/runtime/src/Game.cpp",
    "modules/runtime/include/Microsoft/Xna/Framework/Game.hpp",
    "modules/c-api/include/CNA/C/runtime.h",
    "modules/c-api/src/CnaCApiGameProperties.cpp"
   ],
   "related": [
    "deep-dives/framework/game-class-and-lifecycle.html",
    "development/architecture/runtime.html",
    "development/internals/runtime/module.html",
    "docs/game-loop.html"
   ]
  },
  {
   "id": "CNA-BUG-082",
   "class": "bug",
   "title": "GraphicsDeviceManager leaves dangling references when its lifetime is not nested inside its Game",
   "summary": "Game never clears its cached manager and service pointers, the manager never removes its ClientSizeChanged handler, and ~GraphicsDeviceManager dereferences its Game, so a manager that dies before or after its game is a use-after-free.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::GraphicsDeviceManager(Game*), ~GraphicsDeviceManager(), GraphicsDeviceManager::Dispose(); Game::getGraphicsDeviceProperty(), Game::BeginDraw()/EndDraw(), Game::Dispose()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-082.html",
   "sources": [
    "modules/runtime/src/GraphicsDeviceManager.cpp",
    "modules/runtime/src/Game.cpp",
    "modules/runtime/include/Microsoft/Xna/Framework/GraphicsDeviceManager.hpp",
    "modules/c-api/src/CnaCApiGraphicsDeviceManager.cpp"
   ],
   "related": [
    "deep-dives/framework/exit-and-shutdown-semantics.html",
    "development/internals/runtime/module.html",
    "development/internals/runtime/shutdown.html",
    "development/takeover/ownership.html",
    "docs/game-loop.html"
   ]
  },
  {
   "id": "CNA-BUG-083",
   "class": "bug",
   "title": "PhoneApplicationService::getCurrentProperty()'s static instance detaches from an already-destroyed Game during static destruction",
   "summary": "The process-wide PhoneApplicationService is a function-local static holding a borrowed Game*; attached to a Game that is destroyed first, its destructor calls DetachEXT on the dead game's events.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Phone::Shell::PhoneApplicationService::getCurrentProperty(), AttachEXT(Game&), DetachEXT() and ~PhoneApplicationService()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-083.html",
   "sources": [
    "modules/phone/src/PhoneApplicationService.cpp",
    "modules/phone/include/Microsoft/Phone/Shell/PhoneApplicationService.hpp",
    "modules/phone/tests/Microsoft/Phone/Shell/PhoneApplicationServiceTests.cpp"
   ],
   "related": [
    "development/handbook/debug-shutdown-and-lifetime.html",
    "development/internals/modules/phone.html",
    "development/takeover/ownership.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-BUG-085",
   "class": "bug",
   "title": "GameTime.IsRunningSlowly follows FNA's lag counter, not XNA 4.0's rule",
   "summary": "CNA sets IsRunningSlowly after five accumulated extra steps and clears it when the lag counter returns to zero; XNA 4.0 reports it when two multi-step ticks occur within 20 ticks and assigns it before each Update, so the flag differs tick by tick.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "Microsoft::Xna::Framework::GameTime::IsRunningSlowly as set by Game::Tick",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-085.html",
   "sources": [
    "modules/runtime/src/Game.cpp",
    "modules/runtime/tests/Microsoft/Xna/Framework/GameTimeTests.cpp"
   ],
   "related": [
    "deep-dives/framework/game-time-and-timestep.html",
    "development/internals/runtime/frame.html"
   ]
  },
  {
   "id": "CNA-BUG-086",
   "class": "bug",
   "title": "GameComponent::Dispose(true) does not remove the component from Game.Components",
   "summary": "XNA 4.0's GameComponent.Dispose(bool) removes the component from its Game's Components before raising Disposed; CNA only raises Disposed, so a component disposed to retire it keeps being updated and drawn.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "Microsoft::Xna::Framework::GameComponent::Dispose(bool) (and DrawableGameComponent::Dispose(bool), which calls it)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-086.html",
   "sources": [
    "modules/runtime/src/GameComponent.cpp",
    "modules/runtime/src/DrawableGameComponent.cpp"
   ],
   "related": [
    "deep-dives/framework/services-and-components.html",
    "development/takeover/case-study-components.html"
   ]
  },
  {
   "id": "CNA-BUG-087",
   "class": "bug",
   "title": "Game::Dispose(true) walks Components by live index, so a component that removes itself or another during Dispose makes the loop skip one",
   "summary": "XNA 4.0 copies the collection to an array before disposing; CNA re-reads the count and indexes the live collection, so a removal during a component's Dispose shifts later entries and the next component is never disposed by that pass.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "Microsoft::Xna::Framework::Game::Dispose(bool)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-087.html",
   "sources": [
    "modules/runtime/src/Game.cpp"
   ],
   "related": [
    "deep-dives/framework/exit-and-shutdown-semantics.html",
    "deep-dives/reference/verification-tiers.html",
    "development/internals/runtime/shutdown.html"
   ]
  },
  {
   "id": "CNA-BUG-088",
   "class": "bug",
   "title": "In variable-step mode Game gives its first updates a non-zero ElapsedGameTime where XNA 4.0 reports zero",
   "summary": "The zero-first-update rule exists only on the fixed-step path; in variable step the first Update gets the time since Run() began, while XNA values recorded by CNA show zero elapsed for the first two updates.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Game::Tick (variable time step) / GameTime.ElapsedGameTime",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-088.html",
   "sources": [
    "modules/runtime/src/Game.cpp",
    "modules/runtime/tests/Microsoft/Xna/Framework/GameClockFirstUpdateTests.cpp"
   ],
   "related": [
    "deep-dives/framework/game-time-and-timestep.html"
   ]
  },
  {
   "id": "CNA-BUG-090",
   "class": "bug",
   "title": "GraphicsDeviceInformation accepts a null Adapter, and GraphicsDeviceManager then binds a reference through that null pointer",
   "summary": "XNA's documentation says the GraphicsDeviceInformation.Adapter setter throws ArgumentNullException for a null value (the shipped IL only tests the stored adapter, so the first null slips through in real XNA). CNA's setter stores any pointer, and applyToExistingRenderer then passes *gdi.getAdapterProperty() to GraphicsDevice::Reset, which is undefined behaviour for a null adapter; in practice the device keeps its previous adapter.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::GraphicsDeviceInformation::setAdapterProperty; PreparingDeviceSettings handlers",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-090.html",
   "sources": [
    "modules/runtime/src/GraphicsDeviceInformation.cpp",
    "modules/runtime/src/GraphicsDeviceManager.cpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp"
   ],
   "related": [
    "deep-dives/framework/window-and-device-manager.html",
    "development/internals/runtime/module.html"
   ]
  },
  {
   "id": "CNA-BUG-091",
   "class": "bug",
   "title": "GameWindow keeps a raw pointer to the platform window owned by the Game's GraphicsDevice, and nothing clears it when the game disposes that device",
   "summary": "Game's constructor hands GraphicsDevice_.GetPlatformWindowInternal() to Window_.setWindowInternal; GraphicsDevice::Dispose destroys the platform window (destroyNativeResources resets platformWindow_), after which GameWindow members dereference freed memory.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "Microsoft::Xna::Framework::GameWindow members after an explicit GraphicsDevice::Dispose() on the Game's device",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-091.html",
   "sources": [
    "modules/runtime/src/Game.cpp",
    "modules/runtime/src/GameWindow.cpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp"
   ],
   "related": [
    "deep-dives/framework/window-and-device-manager.html",
    "development/internals/runtime/shutdown.html"
   ]
  },
  {
   "id": "CNA-BUG-092",
   "class": "bug",
   "title": "Public non-XNA members Texture::GetFormatSizeEXT, GetBlockSizeSquaredEXT, GetPixelStoreAlignment, ValidateGetDataFormat and GameWindow's IsBorderlessEXT accessors carry no CNAEXT marker",
   "summary": "Four public static Texture helpers and the GameWindow borderless getter and setter are not XNA 4.0 API but are not tagged CNAEXT, so a CNA_STRICT_XNA_API build compiles calls to them silently.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "CNAEXT marker rule; Texture::GetBlockSizeSquaredEXT, Texture::GetFormatSizeEXT, Texture::GetPixelStoreAlignment, Texture::ValidateGetDataFormat, GameWindow::getIsBorderlessEXTProperty, GameWindow::setIsBorderlessEXTProperty",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-092.html",
   "sources": [
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/Texture.hpp",
    "modules/runtime/include/Microsoft/Xna/Framework/GameWindow.hpp",
    "modules/core/include/CNA/CNAHelper.hpp",
    "CHECKLIST.md"
   ],
   "related": [
    "deep-dives/foundations/language-conventions.html",
    "deep-dives/reference/cnaext-catalog.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-BUG-093",
   "class": "bug",
   "title": "HeadlessRenderer::GetLastFrameStatistics() reports the frame in progress, not the finished frame its documentation names",
   "summary": "GetLastFrameStatistics() is documented as the statistics of the frame ending at the most recent Present(), but it subtracts the snapshot taken at that Present from the running totals, and a test pins that behaviour.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Internal::Renderers::Headless::HeadlessRenderer::GetLastFrameStatistics() (HEADLESS debugging API)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-093.html",
   "sources": [
    "modules/renderers/headless/include/CNA/Internal/Renderers/Headless/HeadlessRenderer.hpp",
    "modules/renderers/headless/src/HeadlessRenderer.cpp",
    "modules/renderers/headless/examples/headless_coverage_gaps_test.cpp",
    "docs/headless-renderer.md"
   ],
   "related": [
    "development/internals/graphics/headless.html",
    "development/testing/architecture.html"
   ]
  },
  {
   "id": "CNA-BUG-094",
   "class": "bug",
   "title": "SDL_GPU claims compute and SPIR-V shader intake on every device, including Direct3D 12 and Metal drivers that cannot take raw SPIR-V",
   "summary": "SupportsComputeShadersEXT() and SupportsShaderLanguageEXT(SpirV) answer true whenever a device exists, but compute pipelines and ShaderEffect SPIR-V payloads reach SDL_gpu as raw SPIR-V, which its Direct3D 12 and Metal drivers reject.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "strong",
   "tests_present": true,
   "public_contract": "GraphicsDevice::SupportsCapability(GraphicsCapability::ComputeShaders), GraphicsDevice::SupportsShaderLanguageEXT and CNA::Graphics::ComputeShader on SDL_GPU",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-094.html",
   "sources": [
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp",
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp",
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp",
    "modules/renderers/sdl-gpu/src/SdlGpuModern.cpp",
    "cmake/RendererSelection.cmake",
    "modules/renderers/sdl-gpu/CMakeLists.txt",
    "modules/graphics-ext/src/ComputeShader.cpp"
   ],
   "related": [
    "development/internals/graphics/sdl-gpu.html",
    "docs/cnaext-engine.html",
    "docs/rendering-backends.html"
   ]
  },
  {
   "id": "CNA-BUG-095",
   "class": "bug",
   "title": "A GraphicsDevice constructor that fails after renderer resolution leaves the selection latched to the renderer it destroyed",
   "summary": "The GraphicsDevice constructor latches the selection inside resolveRenderer(), then updates the viewport and pushes default states; if one of those throws, the catch block destroys the renderer without unlatching, so SetPreferred is refused.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice construction failure path and CNA::GraphicsRendererSelection::SetPreferred / IsLatched / GetActive",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-095.html",
   "sources": [
    "modules/graphics/src/Xna/GraphicsDevice.cpp",
    "modules/core/src/GraphicsRendererSelection.cpp",
    "modules/graphics/tests/CNA/GraphicsRendererFallbackTests.cpp"
   ],
   "related": [
    "deep-dives/graphics/graphicsdevice-contract.html",
    "development/internals/graphics/device.html",
    "development/internals/graphics/selection.html",
    "docs/runtime-renderer-selection.html"
   ]
  },
  {
   "id": "CNA-BUG-096",
   "class": "bug",
   "title": "VulkanRenderer's constructor leaks the Vulkan handles it created when a later construction step throws",
   "summary": "VulkanRenderer::VulkanRenderer creates the instance, debug messenger, device, swapchain and other raw handles in sequence with no cleanup path, so a throw from a later step such as PickPhysicalDevice leaves them undestroyed.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice construction on VULKAN, including runtime fallback from VULKAN to another renderer",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-096.html",
   "sources": [
    "modules/renderers/vulkan/src/VulkanRenderer.cpp",
    "modules/renderers/vulkan/include/CNA/Internal/Renderers/Vulkan/VulkanRenderer.hpp",
    "modules/renderers/vulkan/examples/vulkan_unavailable_device_skip.cpp"
   ],
   "related": [
    "development/handbook/debug-shutdown-and-lifetime.html",
    "development/internals/graphics/vulkan.html",
    "docs/runtime-renderer-selection.html"
   ]
  },
  {
   "id": "CNA-BUG-097",
   "class": "bug",
   "title": "RenderPipeline::releaseDeviceResourcesEXT() keeps the Bloom, SSAO and volumetric-fog target pools, and the memory estimate never counts them",
   "summary": "The DeviceReset handler documented to drop every target the pipeline owns resets only the scene target and the chain's pool; the private pools of BloomPass, SsaoPass and VolumetricFogPass survive, and getGpuMemoryEstimateBytes() excludes them.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Graphics::RenderPipeline::releaseDeviceResourcesEXT() and getGpuMemoryEstimateBytes() / FrameStatistics::gpuMemoryEstimateBytes (CNAEXT)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-097.html",
   "sources": [
    "modules/graphics-ext/src/RenderPipeline.cpp",
    "modules/graphics-ext/include/CNA/Graphics/RenderPipeline.hpp",
    "modules/graphics-ext/src/BloomPass.cpp",
    "modules/graphics-ext/src/SsaoPass.cpp",
    "modules/graphics-ext/include/CNA/Graphics/VolumetricFogPass.hpp",
    "modules/graphics-ext/tests/CNA/Graphics/DeviceLifecycleTests.cpp"
   ],
   "related": [
    "development/architecture/graphics.html",
    "development/internals/modules/graphics-ext.html",
    "docs/cnaext-engine.html"
   ]
  },
  {
   "id": "CNA-BUG-098",
   "class": "bug",
   "title": "A throwing shadow-caster or transparent-phase callback leaves RenderPipeline and its ShadowMap in an unrecoverable state",
   "summary": "RenderPipeline::begin() raises frameOpen_ before running the shadow-caster callback between ShadowMap::begin and end, and end() lowers it before the transparent callback; an exception from either skips the cleanup that pass exceptions get.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Graphics::RenderPipeline::begin()/end() with callbacks registered through setShadowScene and setTransparentScene (CNAEXT)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-098.html",
   "sources": [
    "modules/graphics-ext/src/RenderPipeline.cpp",
    "modules/graphics-ext/src/ShadowMap.cpp",
    "modules/graphics-ext/include/CNA/Graphics/RenderPipeline.hpp",
    "modules/graphics-ext/tests/CNA/Graphics/PipelineDiagnosticsTests.cpp"
   ],
   "related": [
    "development/handbook/debug-shutdown-and-lifetime.html",
    "development/internals/modules/graphics-ext.html",
    "docs/cnaext-engine.html"
   ]
  },
  {
   "id": "CNA-BUG-099",
   "class": "bug",
   "title": "24 classic SDL_GPU CTests still fail in CNA's latest recorded run; CNA's records name a cause for only three of them",
   "summary": "CNA's SDL_GPU records list 26 classic ^SdlGpu CTests still failing just before TARGET; two are analysed in their own entries. Of the other 24, covering formats, render targets, render state and recovery, the records give a cause for two (a test that clears depth on a DepthFormat::None device, and a double free in the constructor failure path), a guess for a third, and nothing for the other 21.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "medium",
   "confidence": "recorded-by-cna",
   "tests_present": true,
   "public_contract": "SDL_GPU renderer behaviour pinned by the classic ^SdlGpu CTest set (renderer examples, shared parity fixtures, EasyGL oracle cases and SdlGpuIndexedDrawRangeTest)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-099.html",
   "sources": [
    "plans/plan_pre_sdlgpu_closeout.md",
    "plans/plan_street_sdlgpu.md",
    "plans/plan_sdlgpu_modern_graphics.md",
    "plans/plan_sdlgpu.md",
    "modules/renderers/sdl-gpu/examples/CMakeLists.txt",
    "modules/graphics/tests/Microsoft/Xna/Framework/Graphics/SdlGpuIndexedDrawRangeTests.cpp",
    "modules/core/include/CNA/GraphicsBackendMaturity.hpp"
   ],
   "related": [
    "deep-dives/renderers/native-gpu-evidence-tiers.html",
    "deep-dives/renderers/sdl-gpu-pipeline-state-and-draw-order.html",
    "deep-dives/renderers/sdl-gpu-resources-and-frame-recovery.html",
    "development/handbook/fix-a-renderer-bug.html",
    "development/internals/graphics/sdl-gpu.html",
    "development/testing/architecture.html",
    "docs/verification.html"
   ]
  },
  {
   "id": "CNA-BUG-101",
   "class": "bug",
   "title": "GraphicsDevice::Reset rolls back only the window and virtual-resolution stage; a later renderer failure leaves the new PresentationParameters stored and DeviceReset unraised",
   "summary": "An exception from UpdatePresentationFormatEXT, ApplyMultiSampleCount or SetSwapInterval escapes after the new parameters are stored and render targets were unbound, and after DeviceResetting was raised, so the device reports settings it may not have applied.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Graphics::GraphicsDevice::Reset(const PresentationParameters&, GraphicsAdapter*) and its three shorter overloads",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-101.html",
   "sources": [
    "modules/graphics/src/Xna/GraphicsDevice.cpp"
   ],
   "related": [
    "deep-dives/graphics/device-reset-and-lifetime.html",
    "development/internals/graphics/device.html"
   ]
  },
  {
   "id": "CNA-BUG-102",
   "class": "bug",
   "title": "On DIRECTX9, SetContextRecoveryEnabled and SetStringMarkerEXT throw 'not yet implemented', and GraphicsDevice has already changed the recovery flag when the first one throws",
   "summary": "DirectX9Renderer overrides both hooks with NotYetImplemented (std::runtime_error); GraphicsDevice::SetContextRecoveryEnabled stores the flag before forwarding, so the device's Texture2D shadow policy changes even though the call failed.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "GraphicsDevice::SetContextRecoveryEnabled(bool) and GraphicsDevice::SetStringMarkerEXT(const std::string&) on the DIRECTX9 renderer",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-102.html",
   "sources": [
    "modules/renderers/directx9/src/DirectX9Renderer.cpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp",
    "modules/graphics/src/Xna/Texture2D.cpp"
   ],
   "related": [
    "deep-dives/renderers/direct3d9-xna-fidelity.html",
    "development/internals/graphics/backends.html"
   ]
  },
  {
   "id": "CNA-BUG-103",
   "class": "bug",
   "title": "VULKAN clears every colour attachment of a multiple-render-target set, so PreserveContents targets lose their contents when bound as part of an MRT set",
   "summary": "GetOrCreateMRTRenderPass begins each colour attachment with LOAD_OP_CLEAR from an undefined layout (except split-pass continuations), and its cache key has no usage flag, unlike the single-target pass that honours DiscardContents versus PreserveContents.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice::SetRenderTargets with two or more RenderTarget2D bindings whose RenderTargetUsage is PreserveContents, on VULKAN",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-103.html",
   "sources": [
    "modules/renderers/vulkan/src/VulkanRenderer.cpp"
   ],
   "related": [
    "deep-dives/renderers/render-targets-clears-and-viewports.html",
    "deep-dives/renderers/vulkan-deferred-state-and-descriptors.html",
    "development/internals/graphics/vulkan.html"
   ]
  },
  {
   "id": "CNA-BUG-104",
   "class": "bug",
   "title": "DIRECTX9 reports AnisotropicFiltering and MultiSampleAntiAliasing unconditionally and writes MaxAnisotropy to the sampler without clamping to the device cap",
   "summary": "DirectX9Renderer inherits the interface's default true capability answers, and its fixed-function/stock ApplySamplerState passes the requested MaxAnisotropy straight to D3DSAMP_MAXANISOTROPY, although its compiled-effect path clamps to D3DCAPS9::MaxAnisotropy.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "GraphicsDevice::SupportsCapability(AnisotropicFiltering / MultiSampleAntiAliasing) and SamplerState.MaxAnisotropy on DIRECTX9",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-104.html",
   "sources": [
    "modules/renderers/directx9/src/DirectX9Renderer.cpp",
    "modules/renderers/directx9/src/D3D9CompiledEffect.cpp"
   ],
   "related": [
    "deep-dives/graphics/state-objects.html",
    "deep-dives/renderers/direct3d9-xna-fidelity.html"
   ]
  },
  {
   "id": "CNA-BUG-105",
   "class": "bug",
   "title": "SDL_RENDERER clips to any non-empty ScissorRectangle even when RasterizerState.ScissorTestEnable is false",
   "summary": "SdlRenderer::SetScissorRect installs SDL_SetRenderClipRect for every non-empty rectangle and the renderer has no ApplyRasterizerState override, so a game that sets a scissor rectangle but draws with the test disabled is still clipped.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice.ScissorRectangle together with RasterizerState.ScissorTestEnable on SDL_RENDERER",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-105.html",
   "sources": [
    "modules/renderers/sdl-renderer/src/SdlRenderer.cpp",
    "modules/renderers/sdl-renderer/include/CNA/Internal/Renderers/SdlRenderer/SdlRenderer.hpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp"
   ],
   "related": [
    "deep-dives/graphics/spritebatch-semantics.html",
    "deep-dives/renderers/sdl-renderer-2d-contract.html"
   ]
  },
  {
   "id": "CNA-BUG-106",
   "class": "bug",
   "title": "ShaderEffect, PbrEffect, SkinnedPbrEffect and ColorMatrixEffect clone a disposed source instead of throwing ObjectDisposedException",
   "summary": "The five XNA stock effects, SpriteEffect and the compiled Effect::Clone() refuse a disposed source since SOFTWARE-259, but ShaderEffect::Clone rebuilds from its retained source strings, and the CNA extension effects PbrEffect, SkinnedPbrEffect and ColorMatrixEffect copy-construct through Effect(device), so none of the four checks.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA ShaderEffect::Clone()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-106.html",
   "sources": [
    "modules/graphics/src/Xna/ShaderEffect.cpp",
    "modules/graphics/src/Xna/Effect.cpp",
    "modules/graphics/tests/Microsoft/Xna/Framework/Graphics/StockEffectCloneConstructorTests.cpp"
   ],
   "related": [
    "deep-dives/graphics/effect-object-model.html"
   ]
  },
  {
   "id": "CNA-BUG-107",
   "class": "bug",
   "title": "DIRECTX9 draws a 3D ShaderEffect with the stock BasicEffect shader (16-byte vertices) or fails with a BasicEffect vertex-layout error instead of using or refusing the custom effect",
   "summary": "DIRECTX9 compiles ShaderEffect HLSL and runs it for SpriteBatch, but its 3D dispatch never reads GpuDrawParams::customEffectRenderer or customEffectRequested, so a 3D ShaderEffect draw is drawn with the stock vertex-colour BasicEffect shader (16-byte vertices) or fails with a BasicEffect vertex-layout runtime_error that does not name the custom effect.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ShaderEffect (CNA extension) with GraphicsDevice::DrawPrimitives/DrawIndexedPrimitives on DIRECTX9; GraphicsCapability::CustomEffects; RendererCapabilityProfile",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-107.html",
   "sources": [
    "modules/renderers/directx9/src/DirectX9Renderer.cpp",
    "modules/renderers/directx9/src/D3D9EffectDraw.cpp",
    "modules/renderers/directx9/src/D3D9SpriteBatch.cpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp"
   ],
   "related": [
    "deep-dives/renderers/direct3d-shadereffect-contract.html",
    "deep-dives/renderers/direct3d9-xna-fidelity.html"
   ]
  },
  {
   "id": "CNA-BUG-109",
   "class": "bug",
   "title": "The engine layer's capability-name table has no IndirectDraw entry, although its comment says a missing capability fails to compile",
   "summary": "nameOfCapability in graphics-ext's RequireCapability.cpp names 18 of the 19 GraphicsCapability members and returns 'an unrecognised capability' for IndirectDraw; the switch has no default but a missing case is at most a compiler warning.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Graphics::detail::nameOfCapability (refusal messages of the graphics-ext RequireCapability helpers)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-109.html",
   "sources": [
    "modules/graphics-ext/src/RequireCapability.cpp",
    "modules/graphics/include/CNA/GraphicsCapability.hpp"
   ],
   "related": [
    "deep-dives/graphics/capability-model-and-evidence.html",
    "development/internals/modules/graphics-ext.html"
   ]
  },
  {
   "id": "CNA-BUG-110",
   "class": "bug",
   "title": "Stock-effect state is captured at draw time, so a property changed after EffectPass::Apply() affects the next draw, unlike XNA",
   "summary": "GraphicsDevice calls currentEffect_->FillGpuDrawParams() inside every draw, reading the stock effect's current World, colours and so on; XNA commits effect state at Apply() and a later property change only marks the effect dirty for the next Apply.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "BasicEffect and the other stock effects' properties between EffectPass::Apply() and GraphicsDevice::Draw*Primitives",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-110.html",
   "sources": [
    "modules/graphics/src/Xna/GraphicsDevice.cpp",
    "modules/graphics/src/Xna/Effect.cpp"
   ],
   "related": [
    "deep-dives/graphics/effect-object-model.html"
   ]
  },
  {
   "id": "CNA-BUG-111",
   "class": "bug",
   "title": "ShaderEffect::SetTexture(int, Texture2D&), SetTexture(int, TextureCube&) and SetTexture(int, Texture3D&) evaluate *renderer_ of a disposed texture (an empty shared_ptr) and forward a null pointer instead of throwing ObjectDisposedException",
   "summary": "All three SetTexture overloads pass &texture.GetRenderer(), and GetRenderer() returns *renderer_. Dispose resets renderer_, so a disposed texture yields a reference formed from an empty shared_ptr (formally undefined behaviour) and a null pointer reaches IEffectRenderer::BindTexture, BindTextureCube or BindTexture3D.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA ShaderEffect::SetTexture(int, TextureCube&), SetTexture(int, Texture3D&)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-111.html",
   "sources": [
    "modules/graphics/src/Xna/ShaderEffect.cpp",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/TextureCube.hpp",
    "modules/graphics/src/Xna/TextureCube.cpp"
   ],
   "related": [
    "deep-dives/graphics/shader-routes-four-answers.html"
   ]
  },
  {
   "id": "CNA-BUG-112",
   "class": "bug",
   "title": "On VULKAN SpriteBatch draws are never tagged with the active OcclusionQuery: a sprite-only Begin/End span reports PixelCount 0, and sprites in a mixed span are counted only by record order",
   "summary": "Only 3D draws are tagged with the active query (PushPending3DDraw is the only tagging site), so a query whose span holds only SpriteBatch draws reports 0: taggedDraws_ stays 0 and IsComplete answers complete with zero pixels without asking the GPU. Sprite batches never open or close a query bracket, so whether one is counted depends on where it lands among the tagged 3D draws.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Graphics::OcclusionQuery with SpriteBatch draws on VULKAN",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-112.html",
   "sources": [
    "modules/renderers/vulkan/src/VulkanRenderer.cpp"
   ],
   "related": [
    "deep-dives/renderers/vulkan-deferred-state-and-descriptors.html",
    "development/internals/graphics/vulkan.html"
   ]
  },
  {
   "id": "CNA-BUG-113",
   "class": "bug",
   "title": "An enabled zero-area ScissorRectangle draws unclipped on VULKAN and SDL_GPU, while WEBGPU clips everything and METAL suppresses the draw",
   "summary": "Vulkan's computeScissor and SDL_GPU's ApplyScissorForRef treat a zero width or height like a disabled scissor and use the full target; XNA's contract (rasterise only inside the rectangle) means nothing is drawn.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "medium",
   "confidence": "recorded-by-cna",
   "tests_present": true,
   "public_contract": "GraphicsDevice.ScissorRectangle with zero width or height and RasterizerState.ScissorTestEnable = true",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-113.html",
   "sources": [
    "modules/renderers/vulkan/src/VulkanRenderer.cpp",
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp",
    "modules/renderers/webgpu/src/WebGPURenderer.cpp"
   ],
   "related": [
    "deep-dives/graphics/state-objects.html",
    "deep-dives/renderers/render-targets-clears-and-viewports.html"
   ]
  },
  {
   "id": "CNA-BUG-114",
   "class": "bug",
   "title": "WEBGPU always creates a Depth24PlusStencil8 back-buffer depth attachment but PresentationParameters keeps the requested DepthFormat",
   "summary": "RecreateDepthTexture always uses Depth24PlusStencil8 and the renderer has no applied-format override, so PresentationParameters.DepthStencilFormat reports the requested format instead of the attachment that exists.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "PresentationParameters.DepthStencilFormat after device creation/Reset on WEBGPU (and SDL_RENDERER)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-114.html",
   "sources": [
    "modules/renderers/webgpu/src/WebGPURenderer.cpp",
    "modules/renderers/webgpu/include/CNA/Internal/Renderers/WebGPU/WebGPURenderer.hpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp"
   ],
   "related": [
    "deep-dives/renderers/vulkan-presentation-and-readback.html",
    "deep-dives/renderers/webgpu-renderer-semantics.html"
   ]
  },
  {
   "id": "CNA-BUG-115",
   "class": "bug",
   "title": "DIRECTX9 requests D3DPRESENT_INTERVAL_TWO without checking device support, and a failing Reset is then retried on every Present",
   "summary": "PresentInterval::Two becomes D3DPRESENT_INTERVAL_TWO without a caps or windowed-mode check, and when Reset rejects it the renderer releases its default-pool resources and retries on every Present while still reporting Two.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "probable",
   "tests_present": true,
   "public_contract": "PresentationParameters.PresentationInterval = PresentInterval::Two on DIRECTX9",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-115.html",
   "sources": [
    "modules/renderers/directx9/src/DirectX9Renderer.cpp"
   ],
   "related": [
    "deep-dives/renderers/direct3d-presentation-and-state.html"
   ]
  },
  {
   "id": "CNA-BUG-116",
   "class": "bug",
   "title": "DIRECTX9 never resolves multisampled render targets bound as a multiple-render-target set",
   "summary": "SetRenderTargets binds each MSAA target's multisample surface but does not track an MRT set, so when the set is unbound no StretchRect resolve runs and the textures keep stale contents.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice::SetRenderTargets with two or more multisampled RenderTarget2D bindings on DIRECTX9",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-116.html",
   "sources": [
    "modules/renderers/directx9/src/DirectX9Renderer.cpp",
    "modules/renderers/directx9/include/CNA/Internal/Renderers/DirectX9/D3D9RenderTargets.hpp",
    "modules/renderers/directx9/src/D3D9RenderTargets.cpp"
   ],
   "related": [
    "deep-dives/renderers/direct3d9-xna-fidelity.html"
   ]
  },
  {
   "id": "CNA-BUG-117",
   "class": "bug",
   "title": "The SdlRenderer constructor maps any positive swap interval to 1, so a device constructed with PresentInterval::Two runs at interval 1 until the next reset",
   "summary": "The constructor calls SDL_SetRenderVSync(renderer, swapInterval > 0 ? 1 : 0), while SetSwapInterval (Task 713) passes 2 through and falls back only if the driver refuses it.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice construction with PresentationParameters.PresentationInterval = Two on SDL_RENDERER",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-117.html",
   "sources": [
    "modules/renderers/sdl-renderer/src/SdlRenderer.cpp"
   ],
   "related": [
    "deep-dives/renderers/presentation-and-backbuffer-readback.html"
   ]
  },
  {
   "id": "CNA-BUG-118",
   "class": "bug",
   "title": "GraphicsDevice::GetMaxTextureDimension() is documented as the renderer's real maximum, but most renderers return an unqueried 16384 that the capability profile marks as known",
   "summary": "Only VULKAN, DIRECT2D and GDI report a real or bounded limit; the other families inherit a constant 16384 (no code in the repository queries GL_MAX_TEXTURE_SIZE), which the renderer capability profile nevertheless reports as a known limit.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice::GetMaxTextureDimension() (CNAEXT); RendererLimit::MaxTextureDimension in the renderer capability profile",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-118.html",
   "sources": [
    "modules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp",
    "modules/renderers/vulkan/src/VulkanRenderer.cpp",
    "modules/renderers/direct2d/src/Direct2DRenderer.cpp",
    "modules/renderers/gdi/src/GdiRenderer.cpp",
    "modules/graphics/src/Xna/Texture2D.cpp"
   ],
   "related": [
    "deep-dives/content/content-robustness.html",
    "deep-dives/graphics/capability-model-and-evidence.html",
    "development/internals/graphics/device.html"
   ]
  },
  {
   "id": "CNA-BUG-119",
   "class": "bug",
   "title": "The XNB type-reader registry is process-wide and unsynchronised, and every reader construction writes to it",
   "summary": "Every ContentTypeReader constructor writes the unlocked process-wide TargetTypeNames map during each .xnb load, so two XNB loads on different threads race unless a GL renderer's context lease happens to serialise them; XNA and FNA lock this registry.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Content::ContentManager::Load<T>() / ReadAsset<T>() for .xnb assets on more than one thread; ContentTypeReaderManager",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-119.html",
   "sources": [
    "modules/content/src/Xna/ContentTypeReaderManager.cpp",
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentTypeReader.hpp",
    "modules/content/src/Xna/ContentReader.cpp",
    "modules/content/include/CNA/Content/Cnb/CnbLoaderRegistry.hpp"
   ],
   "related": [
    "development/architecture/content.html",
    "development/internals/content/runtime.html",
    "development/takeover/threading.html",
    "docs/tutorials/77-async-loading.html"
   ]
  },
  {
   "id": "CNA-BUG-120",
   "class": "bug",
   "title": "ContentManager::LoadXnbAssetUntyped lacks LoadXnbAsset<T>'s compressed-header guard and refuses LZ4",
   "summary": "The untyped decoder behind EffectMaterial external references reads the 4-byte size at offset 10 without the 14-byte check, over-reading a 10-13-byte compressed file, and refuses LZ4 that the typed load path decodes.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentReader::ReadExternalReference() (untyped, CNAEXT; @throws ContentLoadException if the referenced compiled asset cannot be loaded) via ContentManager::LoadUntypedXnbReference / LoadXnbAssetUntyped",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-120.html",
   "sources": [
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentManager.hpp",
    "modules/content/src/Xna/ContentReader.cpp",
    "modules/content/src/Xnb/EffectMaterialContentTypeReaders.cpp",
    "modules/content/src/Xnb/XnbDecompression.cpp"
   ],
   "related": [
    "development/internals/content/runtime.html",
    "docs/content-pipeline-xnb.html"
   ]
  },
  {
   "id": "CNA-BUG-121",
   "class": "bug",
   "title": "ContentManager::Load<T> never calls the virtual OpenStream, so ResourceContentManager::Load<T> ignores its resource family",
   "summary": "OpenStream is documented as the seam every .xnb load goes through, but the public Load template reads files with TryReadAssetBytes; only the protected ReadAsset calls it, so an OpenStream override is bypassed.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager::Load and the protected virtual ContentManager::OpenStream; ResourceContentManager constructed with a System::Resources::ResourceManager",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-121.html",
   "sources": [
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentManager.hpp",
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/src/Xna/ResourceContentManager.cpp",
    "modules/content/include/Microsoft/Xna/Framework/Content/ResourceContentManager.hpp"
   ],
   "related": [
    "development/internals/content/runtime.html",
    "docs/content-manager.html",
    "docs/content-pipeline-xnb.html"
   ]
  },
  {
   "id": "CNA-BUG-122",
   "class": "bug",
   "title": "ContentManager::Load<T> leaks non-XNA exception types: std::bad_any_cast for a wrong .xnb type, unwrapped Load<SoundEffect> errors, std::runtime_error when disposed",
   "summary": "ContentManager::Load wraps loose-reader failures in ContentLoadException, but its .xnb tier lets std::bad_any_cast escape, the SoundEffect specialization wraps nothing, and a disposed manager throws std::runtime_error.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager::Load (documented to throw ContentLoadException) and its SoundEffect specialization; XNA ContentManager.Load (ObjectDisposedException, ContentLoadException including BadXnbWrongType)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-122.html",
   "sources": [
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentReader.hpp",
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentManager.hpp",
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/audio/src/Xna/SoundEffect.cpp"
   ],
   "related": [
    "deep-dives/reference/verification-tiers.html",
    "development/handbook/modify-contentmanager.html",
    "development/internals/content/runtime.html",
    "docs/content-pipeline-xnb.html"
   ]
  },
  {
   "id": "CNA-BUG-123",
   "class": "bug",
   "title": "ContentManager has no in-progress guard, so an .xnb external-reference cycle recurses until the stack overflows",
   "summary": "Load<T> and LoadUntypedXnbReference cache an asset only after it has loaded, so an asset whose external reference leads back to itself re-enters the loader without bound and crashes instead of throwing ContentLoadException.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager::Load<T>(const std::string&), ContentManager::LoadUntypedXnbReference, ContentReader::ReadExternalReference<T>() and ContentReader::ReadExternalReference()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-123.html",
   "sources": [
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentManager.hpp",
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/src/Xna/ContentReader.cpp",
    "modules/content/src/Xnb/EffectMaterialContentTypeReaders.cpp"
   ],
   "related": [
    "deep-dives/content/content-robustness.html",
    "development/internals/content/runtime.html",
    "docs/content-manager.html"
   ]
  },
  {
   "id": "CNA-BUG-124",
   "class": "bug",
   "title": "ContentManager::Load<T> holds a plain reference to the loose-file reader, so RegisterTypeReader<T> during that reader's Read destroys it mid-call",
   "summary": "Load<T> binds a LooseFileContentTypeReader<T>& to the object owned by the shared_ptr in typeReaders_; registering another reader for the same T while that Read runs releases the only owner.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "ContentManager::RegisterTypeReader<T>(std::unique_ptr<LooseFileContentTypeReader<T>>) and ContentManager::Load<T>",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-124.html",
   "sources": [
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentManager.hpp",
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentManager.hpp"
   ],
   "related": [
    "development/internals/content/runtime.html",
    "docs/content-manager.html"
   ]
  },
  {
   "id": "CNA-BUG-125",
   "class": "bug",
   "title": "DecompressXnbPayload grows the LZX output without bound and checks it against the declared size only after the last block",
   "summary": "The LZX loop appends up to 64 KiB per block into an unbounded MemoryStream, so XnbReadLimits::maxDecompressedSize bounds only the declared size, not the memory the decoder actually allocates.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Internal::Xnb::DecompressXnbPayload and XnbReadLimits::maxDecompressedSize",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-125.html",
   "sources": [
    "modules/content/src/Xnb/XnbDecompression.cpp",
    "modules/content/include/CNA/Internal/Xnb/XnbReadLimits.hpp",
    "modules/content/src/Xnb/LzxDecoder.cpp"
   ],
   "related": [
    "deep-dives/content/content-robustness.html",
    "deep-dives/content/xnb-container-and-object-graph.html",
    "development/internals/content/runtime.html"
   ]
  },
  {
   "id": "CNA-BUG-126",
   "class": "bug",
   "title": "ContentReader::InnerReadObjectAny bypasses the object-nesting depth guard, so nested object-typed values recurse without limit",
   "summary": "maxObjectNestingDepth is enforced only by the typed InnerReadObject<T>; Dictionary<String,Object> values, Model tags, shared resources and untyped roots dispatch through InnerReadObjectAny, which never counts depth.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentReader::ReadObject() (untyped), ContentReader::ReadAsset() (untyped), ContentReader::ReadSharedResources and XnbReadLimits::maxObjectNestingDepth",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-126.html",
   "sources": [
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentReader.hpp",
    "modules/content/src/Xna/ContentReader.cpp",
    "modules/content/src/Xnb/EffectMaterialContentTypeReaders.cpp",
    "modules/content/tests/Microsoft/Xna/Framework/Content/ContentReaderTests.cpp"
   ],
   "related": [
    "deep-dives/content/content-robustness.html",
    "development/internals/content/runtime.html",
    "docs/content-manager.html"
   ]
  },
  {
   "id": "CNA-BUG-128",
   "class": "bug",
   "title": "Model::Draw indexes its bone scratch buffer with bone 0 even for a model with no bones",
   "summary": "Model's three-argument constructor accepts an empty bone list, but Draw then reads sharedDrawBoneMatrices_[0] for every mesh without growing the thread-local vector, an unchecked out-of-range read or a stale matrix from an earlier model.",
   "subsystem": "Models & glTF",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Model::Draw(const Matrix&, const Matrix&, const Matrix&) and Model::Model(GraphicsDevice*, std::vector<ModelBone*>, std::vector<ModelMesh*>)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-128.html",
   "sources": [
    "modules/graphics/src/Xna/Model.cpp",
    "modules/graphics/src/Xna/Model.cpp",
    "modules/graphics/tests/Microsoft/Xna/Framework/Graphics/ModelTests.cpp"
   ],
   "related": [
    "deep-dives/models/model-mesh-runtime.html",
    "docs/model-loading.html"
   ]
  },
  {
   "id": "CNA-BUG-129",
   "class": "bug",
   "title": "BlendMorphTargetsEXT indexes NormalDeltas and every per-vertex delta array without checking their lengths",
   "summary": "The function validates only the weight count; a hand-built MorphTargetDataEXT whose NormalDeltas has fewer entries than targets, or whose delta arrays are shorter than the vertex count, is read out of range.",
   "subsystem": "Models & glTF",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Graphics::BlendMorphTargetsEXT(const MorphTargetDataEXT&, const std::vector<float>&) and ApplyMorphWeightsEXT",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-129.html",
   "sources": [
    "modules/graphics/src/Xna/MorphTargetEXT.cpp",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/MorphTargetEXT.hpp",
    "modules/graphics/tests/Microsoft/Xna/Framework/Graphics/MorphTargetEXTTests.cpp"
   ],
   "related": [
    "deep-dives/models/skinning-and-animation.html",
    "docs/model-loading.html"
   ]
  },
  {
   "id": "CNA-BUG-130",
   "class": "bug",
   "title": "The .cnj Model reader truncates vertex and index sidecar sizes and never range-checks indices, where the SkinnedModel reader refuses the same input",
   "summary": "ModelTypeReader and BuildModelMeshPartGeometryEXT derive vertex and index counts by integer division, discarding trailing bytes, and build the index buffer without checking indices against the vertex count; the SkinnedModel reader in the same file throws ContentLoadException for both. A mesh with a non-positive vertexStride is silently skipped, as it is in the SkinnedModel reader.",
   "subsystem": "Models & glTF",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager::Load<Model> on .cnj Model documents (ModelTypeReader, BuildModelMeshPartGeometryEXT)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-130.html",
   "sources": [
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/src/Xna/ContentManager.cpp"
   ],
   "related": [
    "deep-dives/content/cnj-documents.html",
    "deep-dives/models/cnj-toolchain.html",
    "docs/model-loading.html"
   ]
  },
  {
   "id": "CNA-BUG-131",
   "class": "bug",
   "title": "The .cnj Model bones parser accepts forward or self parent indices and turns a malformed transform into identity",
   "summary": "ParseCnjBoneArrayEXT keeps a transform only when it has exactly 16 numbers and the bone loop checks only that a parent index is in range, so a bone can name a later bone (or itself) as parent and CopyAbsoluteBoneTransformsTo reads an uncomputed slot.",
   "subsystem": "Models & glTF",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager::Load<Model> on .cnj Model documents with a bones array; Model::CopyAbsoluteBoneTransformsTo",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-131.html",
   "sources": [
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/graphics/src/Xna/Model.cpp"
   ],
   "related": [
    "deep-dives/models/cnj-toolchain.html",
    "deep-dives/models/model-mesh-runtime.html"
   ]
  },
  {
   "id": "CNA-BUG-132",
   "class": "bug",
   "title": "FNA_KEYBOARD_USE_SCANCODES does not make Keyboard::GetState layout-independent; only the input bridge and GetKeyFromScancodeEXT honour it",
   "summary": "CNA documents scancode mode as FNA's layout-independent key polling, but Keyboard::GetState reads the platform snapshot, which always resolves keys through the current layout, while GetKeyFromScancodeEXT switches to returning keys unchanged.",
   "subsystem": "Input",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Keyboard::GetState() and Keyboard::GetKeyFromScancodeEXT(Keys) under the FNA_KEYBOARD_USE_SCANCODES=1 environment switch",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-132.html",
   "sources": [
    "modules/input/src/Internal/SdlInputBridge.cpp",
    "modules/input/src/Xna/Keyboard.cpp",
    "modules/platform/src/Sdl3/Sdl3InputServices.cpp",
    "docs/platform-input-notes.md",
    "docs/input-fna-fidelity.md",
    "modules/input/tests/CNA/Internal/Input/SdlInputBridgeKeyboardTests.cpp",
    "modules/input/tests/Microsoft/Xna/Framework/Input/KeyboardInputTests.cpp"
   ],
   "related": [
    "deep-dives/services/input-model.html",
    "development/internals/input/events.html",
    "docs/input.html"
   ]
  },
  {
   "id": "CNA-BUG-133",
   "class": "bug",
   "title": "DIRECTX11, DIRECTX12, FREEDIRECT and METAL implement the window-to-logical transform but never register for their window, so mouse and touch input ignore it",
   "summary": "Input looks renderers up by window id through IGraphicsRenderer::GetForWindow; these four renderers never call RegisterForWindow, so Mouse::GetState, Mouse::SetPosition and touch pass raw window coordinates through under a virtual resolution, letterbox or display scale.",
   "subsystem": "Input",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Mouse::GetState(), Mouse::SetPosition(int, int) and TouchPanel positions on the DIRECTX11, DIRECTX12, FREEDIRECT and METAL renderers",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-133.html",
   "sources": [
    "modules/renderers/directx11/src/DirectX11Renderer.cpp",
    "modules/renderers/directx12/src/DirectX12Renderer.cpp",
    "modules/renderers/freedirect/src/FreeDirectRenderer.cpp",
    "modules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp",
    "modules/input/src/Xna/Mouse.cpp",
    "modules/input/src/Internal/SdlInputBridge.cpp",
    "modules/renderers/metal/src/MetalRenderer.mm"
   ],
   "related": [
    "deep-dives/services/input-model.html",
    "development/internals/input/events.html",
    "docs/input.html"
   ]
  },
  {
   "id": "CNA-BUG-134",
   "class": "bug",
   "title": "Inside a letterbox bar, Mouse::GetState reports the raw window coordinate on renderers whose transform declines the point",
   "summary": "EasyGL (every GL-family identity), OPENGL4, SDL_GPU, WEBGPU, SVG_DOM, HTML_DOM and GDI decline points outside the presented rectangle, and Mouse and the input bridge then report the untransformed window coordinate, which can look like a valid game position. The presented rectangle is smaller than the window only under CnaPresentationMode::Letterbox (the default mode) when the window aspect differs from the back buffer's; Overscan, Stretch, NativeBackBuffer and FixedHeightDynamicWidth present a rectangle that covers the whole window, so only a pointer outside the window itself is declined there.",
   "subsystem": "Input",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Mouse::GetState() and touch positions under a letterboxed or overscanned presentation",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-134.html",
   "sources": [
    "modules/graphics/include/CNA/Internal/Renderers/Common/GlPresentationSurfaceState.hpp",
    "modules/input/src/Xna/Mouse.cpp",
    "modules/input/src/Internal/SdlInputBridge.cpp",
    "modules/renderers/vulkan/src/VulkanRenderer.cpp"
   ],
   "related": [
    "deep-dives/services/input-model.html",
    "development/internals/input/events.html",
    "docs/input.html"
   ]
  },
  {
   "id": "CNA-BUG-135",
   "class": "bug",
   "title": "Mouse::SetCaptureEXT, GetGlobalPositionEXT and WarpGlobalEXT let PlatformNotSupportedException escape on Wayland and the terminal platform",
   "summary": "The Wayland and terminal mouse services throw PlatformNotSupportedException from SetCapture, TryGetGlobalPosition and SetGlobalPosition, and the Mouse wrappers do not catch it, although they document false (or (0, 0)) for an unsupported platform.",
   "subsystem": "Input",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Mouse::SetCaptureEXT(bool), Mouse::GetGlobalPositionEXT(int&, int&), Mouse::WarpGlobalEXT(int, int)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-135.html",
   "sources": [
    "modules/input/src/Xna/Mouse.cpp",
    "modules/input/include/Microsoft/Xna/Framework/Input/Mouse.hpp",
    "modules/platform/src/Wayland/WaylandMouse.cpp",
    "modules/platform/src/Terminal/TerminalMouse.cpp",
    "modules/platform/include/CNA/Platform/Input/IPlatformMouse.hpp"
   ],
   "related": [
    "deep-dives/services/input-model.html",
    "development/internals/input/events.html",
    "docs/input.html"
   ]
  },
  {
   "id": "CNA-BUG-137",
   "class": "bug",
   "title": "MediaPlayer::Play(Song*) reads and writes a destroyed Song when given a Song that the queue owns",
   "summary": "Play(Song*) clears the queue before it copies and plays the given song, so passing the queue's own song, such as getQueueProperty().getActiveSongProperty(), is a heap use-after-free.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "high",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "MediaPlayer::Play(Song*) given a pointer obtained from MediaQueue::getActiveSongProperty() or MediaQueue::operator[]",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-137.html",
   "sources": [
    "modules/media/src/Xna/MediaPlayer.cpp",
    "modules/media/src/Xna/MediaQueue.cpp",
    "modules/media/include/Microsoft/Xna/Framework/Media/MediaQueue.hpp",
    "modules/media/tests/Microsoft/Xna/Framework/Media/MediaPlayerTests.cpp"
   ],
   "related": [
    "deep-dives/services/media-contract.html",
    "development/internals/modules/media.html",
    "docs/tutorials/122-media-library.html"
   ]
  },
  {
   "id": "CNA-BUG-138",
   "class": "bug",
   "title": "MediaPlayer flags ActiveSongChanged on every Play(Song*), even for the same song, and never for Play(const SongCollection&[, index])",
   "summary": "Play(Song*) compares the queue's copy with the caller's pointer, so the event fires on every call, while playing a collection never raises it even when the active song changes.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "MediaPlayer::ActiveSongChanged as raised by MediaPlayer::Play(Song*), Play(const SongCollection&) and Play(const SongCollection&, intcs)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-138.html",
   "sources": [
    "modules/media/src/Xna/MediaPlayer.cpp",
    "modules/media/include/Microsoft/Xna/Framework/Media/MediaPlayer.hpp",
    "modules/media/src/Xna/Song.cpp",
    "modules/media/tests/Microsoft/Xna/Framework/Media/MediaPlayerTests.cpp"
   ],
   "related": [
    "deep-dives/services/media-contract.html",
    "development/internals/modules/media.html"
   ]
  },
  {
   "id": "CNA-BUG-139",
   "class": "bug",
   "title": "MediaPlayer::Play(Song*) records Duration and PlayCount on the caller's Song instead of the queued copy, and Stop never resets that PlayCount",
   "summary": "Play(Song*) hands the caller's Song to PlaySong, so the mixer duration and a PlayCount increment land on the library or content Song while the queue's active copy keeps zero, contrary to MediaLibrary.cpp's comment.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Song::getDurationProperty() and Song::getPlayCountProperty() of the caller's Song and of MediaQueue::getActiveSongProperty() after MediaPlayer::Play(Song*)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-139.html",
   "sources": [
    "modules/media/src/Xna/MediaPlayer.cpp",
    "modules/media/src/Xna/MediaLibrary.cpp"
   ],
   "related": [
    "deep-dives/services/media-contract.html",
    "development/internals/modules/media.html"
   ]
  },
  {
   "id": "CNA-BUG-140",
   "class": "bug",
   "title": "MediaPlayer::Play reports no error when a song cannot be played and can leave the player Playing with no track",
   "summary": "A mixer load, track or start failure makes PlaySong return silently after the previous track was destroyed, so the state may stay Playing indefinitely, and a vanished file or a missing audio device throws non-XNA exceptions after the queue was replaced.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "MediaPlayer::Play(Song*), Play(const SongCollection&), Play(const SongCollection&, intcs), MoveNext and MovePrevious: failure behaviour",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-140.html",
   "sources": [
    "modules/media/src/Xna/MediaPlayer.cpp",
    "modules/audio/src/Backend/Sdl3Mixer/MixerEngine.cpp",
    "modules/audio/src/Backend/CnaMixer/MixerEngine.cpp",
    "modules/audio/src/Backend/Sdl3Mixer/AudioMixer.cpp",
    "modules/media/src/Xna/Song.cpp",
    "modules/audio/src/Xna/SoundEffect.cpp"
   ],
   "related": [
    "deep-dives/services/media-contract.html",
    "development/internals/audio/engine.html",
    "development/internals/modules/media.html",
    "docs/audio.html"
   ]
  },
  {
   "id": "CNA-BUG-141",
   "class": "bug",
   "title": "MediaPlayer::ProgramExit is documented as called at application exit, but nothing in CNA calls it",
   "summary": "Unlike FNA, which hooks ProcessExit, CNA never calls MediaPlayer::ProgramExit outside an explicit C API export, so the music track is not released by CNA at exit and the header's statement is false.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "MediaPlayer::ProgramExit() (CNAEXT) and the release of MediaPlayer's music track at exit",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-141.html",
   "sources": [
    "modules/media/include/Microsoft/Xna/Framework/Media/MediaPlayer.hpp",
    "modules/media/src/Xna/MediaPlayer.cpp",
    "modules/c-api/src/CnaCApiMediaPlayer.cpp"
   ],
   "related": [
    "development/handbook/debug-shutdown-and-lifetime.html",
    "development/internals/modules/media.html"
   ]
  },
  {
   "id": "CNA-BUG-142",
   "class": "bug",
   "title": "Without a mixer (SDL2 or NULL audio) songs never end: queued copies carry no Duration, so the elapsed-time fallback never fires",
   "summary": "LoadSong copies only a Song's file and name, so every queued Song has a zero Duration and, in builds without SOUND_ENABLED, DetectSongEndedByElapsedTime never reports an end: MediaPlayer stays Playing and the queue never advances.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "MediaPlayer::Update() (via FrameworkDispatcher::Update), MediaState, ActiveSongChanged and queue advance under CNA_AUDIO_PLATFORM=SDL2 or NULL",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-142.html",
   "sources": [
    "modules/media/src/Xna/MediaPlayer.cpp",
    "modules/media/include/Microsoft/Xna/Framework/Media/MediaPlayer.hpp",
    "modules/CMakeLists.txt",
    "modules/media/tests/Microsoft/Xna/Framework/Media/MediaPlayerTests.cpp"
   ],
   "related": [
    "deep-dives/services/media-contract.html",
    "development/internals/audio/engine.html",
    "development/internals/modules/media.html",
    "docs/platforms.html"
   ]
  },
  {
   "id": "CNA-BUG-143",
   "class": "bug",
   "title": "VideoPlayer and Video keep raw pointers to each other, so destroying a Video before its player is stopped writes to freed memory",
   "summary": "VideoPlayer stores a borrowed Video* and Video a borrowed VideoPlayer* parent; CloseDecoder, run by Stop, Dispose and the destructor, writes through the stored Video*, and no header states the ordering rule.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "medium",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "VideoPlayer::Play(Video*), Stop(), Dispose(), ~VideoPlayer(), getVideoProperty(); Video::SetAudioTrackEXT and SetVideoTrackEXT",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-143.html",
   "sources": [
    "modules/media/src/Xna/Video/VideoPlayer.cpp",
    "modules/media/src/Xna/Video/Video.cpp",
    "modules/media/include/Microsoft/Xna/Framework/Media/Video/Video.hpp",
    "modules/media/include/Microsoft/Xna/Framework/Media/Video/VideoPlayer.hpp"
   ],
   "related": [
    "deep-dives/services/media-contract.html",
    "development/handbook/debug-shutdown-and-lifetime.html",
    "development/internals/modules/media.html",
    "docs/video-playback.html"
   ]
  },
  {
   "id": "CNA-BUG-144",
   "class": "bug",
   "title": "VideoPlayer::GetTexture lets the decoder's std::runtime_error escape, undocumented, and leaves the player Playing",
   "summary": "A decode, packet, resample or I/O error mid-stream is thrown by VideoDecoder::NextFrame as std::runtime_error through GetTexture, whose header documents only ObjectDisposedException, and the player stays Playing so the next call tries again.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "VideoPlayer::GetTexture() exceptions and the player state after a mid-stream decode failure",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-144.html",
   "sources": [
    "modules/media/src/Xna/Video/VideoPlayer.cpp",
    "modules/video-ffmpeg/src/VideoDecoder.cpp",
    "modules/media/include/Microsoft/Xna/Framework/Media/Video/VideoPlayer.hpp",
    "modules/media/tests/CNA/Internal/Media/VideoDecoderTests.cpp"
   ],
   "related": [
    "deep-dives/services/media-contract.html",
    "development/internals/modules/media.html",
    "development/internals/modules/video-ffmpeg.html",
    "docs/video-playback.html"
   ]
  },
  {
   "id": "CNA-BUG-145",
   "class": "bug",
   "title": "VideoDecoder::SetVideoStream switches to another video stream mid-playback without seeking, so decoding resumes at a non-keyframe position",
   "summary": "A genuine SetVideoTrackEXT switch during playback opens a fresh codec context at the demuxer's current position without a seek or flush; CNA's own comment explains that such a context fails on the next non-keyframe.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "low",
   "confidence": "strong",
   "tests_present": true,
   "public_contract": "VideoPlayer::SetVideoTrackEXT(intcs) and Video::SetVideoTrackEXT(intcs) during playback",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-145.html",
   "sources": [
    "modules/video-ffmpeg/src/VideoDecoder.cpp",
    "modules/media/src/Xna/Video/VideoPlayer.cpp",
    "modules/media/tests/CNA/Internal/Media/VideoDecoderTests.cpp"
   ],
   "related": [
    "deep-dives/services/media-contract.html",
    "development/internals/modules/video-ffmpeg.html",
    "docs/video-playback.html"
   ]
  },
  {
   "id": "CNA-BUG-146",
   "class": "bug",
   "title": "VideoDecoder converts every YUV frame with one full-range BT.601 matrix: limited-range and BT.709 video decode with wrong levels and colours",
   "summary": "The planar and NV12 converters ignore the frame's colour range and matrix, so ordinary limited-range video keeps black at 16 and white at 235, and BT.709 content is decoded with BT.601 coefficients.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "medium",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "VideoPlayer::GetTexture() frame contents (CNA::Internal::Media::VideoDecoder::NextFrame RGBA output)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-146.html",
   "sources": [
    "modules/video-ffmpeg/src/VideoDecoder.cpp",
    "modules/media/tests/CNA/Internal/Media/VideoDecoderTests.cpp",
    "tests/assets/media/video/manifest.json"
   ],
   "related": [
    "development/internals/modules/video-ffmpeg.html",
    "docs/video-playback.html"
   ]
  },
  {
   "id": "CNA-BUG-147",
   "class": "bug",
   "title": "SoundBank::PlayCue destroys a fire-and-forget cue that is still playing five minutes after it started",
   "summary": "SweepFireAndForget, run by every AudioEngine::Update and every PlayCue, removes still-playing or paused fire-and-forget cues older than kFireAndForgetSafetyNet (5 minutes), which stops long or looping cues such as music started with PlayCue.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "SoundBank::PlayCue(const std::string&) and PlayCue(name, listener, emitter)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-147.html",
   "sources": [
    "modules/audio/src/Xna/SoundBank.cpp",
    "modules/audio/src/Xna/AudioEngine.cpp",
    "modules/audio/tests/Microsoft/Xna/Framework/Audio/SoundBankTests.cpp"
   ],
   "related": [
    "deep-dives/services/xact-runtime.html",
    "docs/audio.html"
   ]
  },
  {
   "id": "CNA-BUG-148",
   "class": "bug",
   "title": "DynamicSoundEffectInstance::SubmitBuffer accepts empty and non-frame-aligned buffers that XNA rejects",
   "summary": "CNA checks only that offset and count lie inside the buffer; XNA throws ArgumentException for an empty buffer, a length, offset or count that is not block-aligned, or a count of zero. Such submissions are queued without error, then dropped by SDL3 audio or played shifted by CNA's ALSA mixer. SubmitFloatBufferEXT (an FNA extension with no XNA contract) has the same gap for channel frames.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "DynamicSoundEffectInstance::SubmitBuffer(const std::vector<bytecs>&[, int offset, int count]) and SubmitFloatBufferEXT",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-148.html",
   "sources": [
    "modules/audio/src/Xna/DynamicSoundEffectInstance.cpp",
    "plans/plan_audio.md"
   ],
   "related": [
    "deep-dives/services/sound-effects-and-streaming.html",
    "development/internals/audio/engine.html",
    "docs/audio.html"
   ]
  },
  {
   "id": "CNA-BUG-149",
   "class": "bug",
   "title": "Microphone::Start reports Started even when the capture device could not be opened",
   "summary": "Start swallows every exception from opening the device and ignores an unusable negotiated format, then sets State to Started; XNA's Start surfaces the native error as an exception.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microphone::Start() and Microphone::getStateProperty()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-149.html",
   "sources": [
    "modules/audio/src/Xna/Microphone.cpp"
   ],
   "related": [
    "deep-dives/services/sound-effects-and-streaming.html",
    "docs/audio.html"
   ]
  },
  {
   "id": "CNA-BUG-150",
   "class": "bug",
   "title": "StorageDevice::EnsureStorageRoot publishes its initialised flag before the root, without synchronisation",
   "summary": "The process-wide storage root is latched by a plain bool that is set before the path is computed, so a second thread that touches storage during the first resolution receives an empty root.",
   "subsystem": "Storage",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Storage::StorageDevice::GetStorageRootEXT() (“Absolute path to the storage root”) and every storage operation that resolves the root",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-150.html",
   "sources": [
    "modules/storage/src/StorageDevice.cpp",
    "modules/storage/include/Microsoft/Xna/Framework/Storage/StorageDevice.hpp"
   ],
   "related": [
    "development/internals/modules/storage.html",
    "development/takeover/case-study-storage.html",
    "development/takeover/threading.html",
    "docs/storage.html"
   ]
  },
  {
   "id": "CNA-BUG-151",
   "class": "bug",
   "title": "StorageDevice::EnsureStorageRoot latches an empty root after a failed resolution, and storage then operates in the working directory",
   "summary": "The initialised flag is set before the root is resolved, so after a failed directory creation every call returns an empty root, which the path helpers treat as '.', and containers and DeleteContainer then act in the working directory.",
   "subsystem": "Storage",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Storage::StorageDevice::GetStorageRootEXT() (documented as the absolute storage root), SetAppNameEXT, EndOpenContainer, DeleteContainer and the device properties after a failed root resolution",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-151.html",
   "sources": [
    "modules/storage/src/StorageDevice.cpp",
    "modules/storage/include/Microsoft/Xna/Framework/Storage/StorageDevice.hpp",
    "modules/core/include/CNA/Internal/PathContainment.hpp",
    "modules/core/tests/CNA/Internal/PathContainmentTests.cpp",
    "modules/gamer-services/src/Internal/LocalGamerServicesStore.cpp"
   ],
   "related": [
    "development/internals/modules/storage.html",
    "development/takeover/case-study-storage.html",
    "docs/storage.html"
   ]
  },
  {
   "id": "CNA-BUG-152",
   "class": "bug",
   "title": "StorageDevice::getFreeSpaceProperty, getTotalSpaceProperty and getIsConnectedProperty pass the UTF-8 root to std::filesystem through the narrow path constructor",
   "summary": "The three device properties hand the UTF-8 root string straight to fs::exists, fs::space and fs::path, which on Windows reinterpret it in the ANSI code page, so with a non-ASCII root they query a different path.",
   "subsystem": "Storage",
   "status": "open",
   "severity": "low",
   "confidence": "strong",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Storage::StorageDevice::getFreeSpaceProperty(), getTotalSpaceProperty() and getIsConnectedProperty()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-152.html",
   "sources": [
    "modules/storage/src/StorageDevice.cpp",
    "modules/core/include/CNA/Internal/PathUtf8.hpp",
    "docs/filesystem-path-model.md"
   ],
   "related": [
    "development/internals/modules/core.html",
    "development/internals/modules/storage.html",
    "docs/storage.html"
   ]
  },
  {
   "id": "CNA-BUG-153",
   "class": "bug",
   "title": "StorageContainer::DeleteFile removes an empty directory and DeleteDirectory removes a file",
   "summary": "Both methods call std::filesystem::remove on the resolved path without checking the entry type, so each deletes the other kind of entry, and a missing directory is a silent no-op where XNA throws.",
   "subsystem": "Storage",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Storage::StorageContainer::DeleteFile(const std::string&) and DeleteDirectory(const std::string&)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-153.html",
   "sources": [
    "modules/storage/src/StorageContainer.cpp",
    "modules/storage/include/Microsoft/Xna/Framework/Storage/StorageContainer.hpp"
   ],
   "related": [
    "development/internals/modules/storage.html",
    "docs/storage.html"
   ]
  },
  {
   "id": "CNA-BUG-154",
   "class": "bug",
   "title": "A save container titled GamerServices shares its directory with the gamer-services store, so DeleteContainer(\"GamerServices\") deletes local achievements and leaderboards",
   "summary": "The gamer-services store lives at <root>/GamerServices, where a StorageContainer titled GamerServices is also created, so deleting that title removes every persisted achievement and leaderboard entry.",
   "subsystem": "Storage",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "StorageDevice::DeleteContainer(const std::string& titleName) and BeginOpenContainer/EndOpenContainer with the title GamerServices; the gamer-services local store under StorageDevice::GetStorageRootEXT()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-154.html",
   "sources": [
    "modules/gamer-services/src/Internal/LocalGamerServicesStore.cpp",
    "modules/storage/src/StorageDevice.cpp",
    "modules/storage/src/StorageContainer.cpp"
   ],
   "related": [
    "deep-dives/services/gamer-services-contract.html",
    "development/internals/modules/gamer-services.html",
    "development/internals/modules/storage.html"
   ]
  },
  {
   "id": "CNA-BUG-155",
   "class": "bug",
   "title": "StorageContainer members keep working after Dispose instead of throwing ObjectDisposedException",
   "summary": "No StorageContainer member checks the disposed flag, so file and directory operations, name listings and the DisplayName and StorageDevice getters succeed after Dispose, where XNA 4.0 throws ObjectDisposedException.",
   "subsystem": "Storage",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Storage::StorageContainer after Dispose(): every path method, GetFileNames/GetDirectoryNames, getDisplayNameProperty() and getStorageDeviceProperty()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-155.html",
   "sources": [
    "modules/storage/src/StorageContainer.cpp",
    "modules/storage/include/Microsoft/Xna/Framework/Storage/StorageContainer.hpp",
    "modules/c-api/src/CnaCApiStorage.cpp"
   ],
   "related": [
    "development/internals/modules/storage.html",
    "docs/storage.html"
   ]
  },
  {
   "id": "CNA-BUG-156",
   "class": "bug",
   "title": "HttpNotificationChannel answers length-less, chunked and truncated pushes with 200 and reads request bodies of unbounded size",
   "summary": "ReadRequestBody's comment says unreadable pushes are refused rather than delivered truncated, but a request without Content-Length gets 200 and is dropped, a short body gets 200 and is queued truncated, and the length is never bounded.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Phone::Notification::HttpNotificationChannel listener: the HTTP status a push sender receives and the bytes raised as HttpNotificationReceived",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-156.html",
   "sources": [
    "modules/phone/src/HttpNotificationChannel.cpp",
    "modules/phone/tests/Microsoft/Phone/Notification/HttpNotificationChannelTests.cpp"
   ],
   "related": [
    "development/internals/modules/phone.html",
    "development/takeover/threading.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-BUG-157",
   "class": "bug",
   "title": "HttpNotificationChannel::Close and the channel destructor block indefinitely while a connected peer sends nothing",
   "summary": "The single listener thread reads each accepted connection with a blocking recv and no timeout; Close shuts down only the listening socket and then joins that thread, so a silent peer stalls Close and the destructor.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Phone::Notification::HttpNotificationChannel::Close() and ~HttpNotificationChannel()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-157.html",
   "sources": [
    "modules/phone/src/HttpNotificationChannel.cpp",
    "modules/phone/include/Microsoft/Phone/Notification/HttpNotificationChannel.hpp"
   ],
   "related": [
    "development/handbook/debug-shutdown-and-lifetime.html",
    "development/internals/modules/phone.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-BUG-158",
   "class": "bug",
   "title": "RawPushNotificationMessage::SendAsync and ToastPushNotificationMessage::SendAsync return true for a push the receiver rejected",
   "summary": "Both SendAsync methods are documented to return true when the receiver accepted the notification, but they return true whenever the whole request was written; the reply is read and discarded, so an HTTP 400 still yields true.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Phone::Notification::RawPushNotificationMessage::SendAsync(const System::Uri&) and ToastPushNotificationMessage::SendAsync(const System::Uri&)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-158.html",
   "sources": [
    "modules/phone/src/PushNotificationSender.cpp",
    "modules/phone/include/Microsoft/Phone/Notification/PushNotificationSender.hpp"
   ],
   "related": [
    "development/internals/modules/phone.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-BUG-159",
   "class": "bug",
   "title": "ToastPushNotificationMessage::SendAsync inserts Title and SubTitle into the toast XML without escaping",
   "summary": "The toast body is built by string concatenation, so a Title or SubTitle containing an ampersand, a less-than sign or markup produces malformed or altered XML; the channel delivers the bytes unparsed.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Phone::Notification::ToastPushNotificationMessage::Title, SubTitle and SendAsync(const System::Uri&)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-159.html",
   "sources": [
    "modules/phone/src/PushNotificationSender.cpp"
   ],
   "related": [
    "development/internals/modules/phone.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-BUG-160",
   "class": "bug",
   "title": "Two open HttpNotificationChannel objects with the same name leave Find unable to locate one that is still open",
   "summary": "Open assigns the registry entry for the name without checking for an existing channel, and when the later channel closes first it erases the name while the earlier one is still listening, so Find returns null for a live channel.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Phone::Notification::HttpNotificationChannel constructor, Open(), Close() and static Find(const std::string&)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-160.html",
   "sources": [
    "modules/phone/src/HttpNotificationChannel.cpp",
    "modules/phone/include/Microsoft/Phone/Notification/HttpNotificationChannel.hpp"
   ],
   "related": [
    "development/internals/modules/phone.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-BUG-161",
   "class": "bug",
   "title": "A handler that throws during HttpNotificationChannel::DispatchPendingNotificationsEXT discards every remaining notification of that batch",
   "summary": "DispatchPendingNotificationsEXT moves the whole queue into a local vector before raising; an exception from a HttpNotificationReceived handler propagates and destroys the notifications not yet raised.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Phone::Notification::HttpNotificationChannel::DispatchPendingNotificationsEXT() and HttpNotificationReceived",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-161.html",
   "sources": [
    "modules/phone/src/HttpNotificationChannel.cpp"
   ],
   "related": [
    "development/internals/modules/phone.html",
    "development/takeover/threading.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-BUG-162",
   "class": "bug",
   "title": "The phone notification channel and sender never initialise Winsock, cannot detect INVALID_SOCKET and have no Windows test",
   "summary": "modules/phone calls no WSAStartup, compares the unsigned SOCKET with zero and names no Winsock library, and its socket tests are compiled out on WIN32, so on Windows Open and SendAsync work only if something else initialised Winsock.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "medium",
   "confidence": "strong",
   "tests_present": false,
   "public_contract": "HttpNotificationChannel::Open() and RawPushNotificationMessage / ToastPushNotificationMessage::SendAsync on Windows",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-162.html",
   "sources": [
    "modules/phone/src/HttpNotificationChannel.cpp",
    "modules/phone/src/PushNotificationSender.cpp",
    "modules/phone/CMakeLists.txt",
    "modules/inspector/src/InternalSocket.cpp",
    "cmake/UnitTests.cmake"
   ],
   "related": [
    "development/internals/modules/phone.html",
    "docs/platforms.html"
   ]
  },
  {
   "id": "CNA-BUG-163",
   "class": "bug",
   "title": "HttpNotificationChannel writes its reply with ::send flags 0, so a peer that aborts its connection mid-request can end the process with SIGPIPE",
   "summary": "The listener's 200 or 400 reply is written with no MSG_NOSIGNAL or SO_NOSIGPIPE, unlike CNA's other socket code. After a peer's abortive close has been reported to the worker as a receive error, Linux delivers SIGPIPE on that write, and the default action terminates the game. The push sender omits the flag too, but its single first write did not raise SIGPIPE in the modelled cases.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "medium",
   "confidence": "strong",
   "tests_present": true,
   "public_contract": "HttpNotificationChannel's listener thread (Listen) and the internal Post behind both SendAsync methods",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-163.html",
   "sources": [
    "modules/phone/src/HttpNotificationChannel.cpp",
    "modules/phone/src/PushNotificationSender.cpp",
    "modules/inspector/src/InternalSocket.cpp"
   ],
   "related": [
    "development/internals/modules/phone.html",
    "development/takeover/threading.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-BUG-164",
   "class": "bug",
   "title": "HttpNotificationChannel's listener reads listenSocket_ unsynchronised while Close resets it, and spins without backoff on a persistent accept error",
   "summary": "listenSocket_ is a plain int that the worker reads for every accept while Close closes the descriptor and writes -1 from another thread, a data race; a persistent accept failure such as EMFILE makes the worker loop at full speed.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "HttpNotificationChannel::Close() and the channel's internal listener thread",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-164.html",
   "sources": [
    "modules/phone/src/HttpNotificationChannel.cpp",
    "modules/phone/include/Microsoft/Phone/Notification/HttpNotificationChannel.hpp"
   ],
   "related": [
    "development/internals/modules/phone.html",
    "development/takeover/threading.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-BUG-165",
   "class": "bug",
   "title": "LeaderboardReader::Read, PageDown and PageUp never delete the LeaderboardAction their Begin call allocates",
   "summary": "The three synchronous Read overloads and PageDown/PageUp call their Begin*/End* pair and drop the heap-allocated IAsyncResult, leaking one LeaderboardAction per call, unlike Gamer::GetProfile and SignedInGamer::GetAchievements.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::GamerServices::LeaderboardReader::Read (all three overloads), PageDown() and PageUp(); the C routes cna_leaderboard_reader_page_down and cna_leaderboard_reader_page_up",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-165.html",
   "sources": [
    "modules/gamer-services/src/Xna/LeaderboardReader.cpp",
    "modules/gamer-services/src/Xna/Gamer.cpp",
    "modules/gamer-services/src/Xna/SignedInGamer.cpp",
    "modules/c-api/src/CnaCApiLeaderboards.cpp",
    "modules/gamer-services/tests/Microsoft/Xna/Framework/GamerServices/GamerServicesGamerTests.cpp"
   ],
   "related": [
    "deep-dives/services/gamer-services-contract.html",
    "development/internals/modules/gamer-services.html",
    "docs/tutorials/123-achievements.html"
   ]
  },
  {
   "id": "CNA-BUG-166",
   "class": "bug",
   "title": "GamerServicesDispatcher::Initialize deletes every SignedInGamer in the installed collection, including gamers the application created",
   "summary": "Initialize frees whatever gamers Gamer::getSignedInGamersProperty() currently holds before creating its four stub gamers, so gamers a game published with setSignedInGamersProperty, the pattern leaderboard reads require, are deleted behind their owner's back.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GamerServicesDispatcher::Initialize(System::IServiceProvider&) (also reached through GamerServicesComponent::Initialize) together with Gamer::setSignedInGamersProperty(SignedInGamerCollection*)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-166.html",
   "sources": [
    "modules/gamer-services/src/Xna/GamerServicesDispatcher.cpp",
    "modules/gamer-services/include/Microsoft/Xna/Framework/GamerServices/GamerCollection.hpp",
    "modules/gamer-services/include/Microsoft/Xna/Framework/GamerServices/Gamer.hpp",
    "modules/gamer-services/src/Xna/GamerServicesComponent.cpp",
    "modules/gamer-services/examples/demo_leaderboard_viewer/src/LeaderboardGame.cpp",
    "modules/gamer-services/tests/Microsoft/Xna/Framework/GamerServices/GamerServicesGamerTests.cpp"
   ],
   "related": [
    "deep-dives/services/gamer-services-contract.html",
    "development/internals/modules/gamer-services.html",
    "development/takeover/ownership.html"
   ]
  },
  {
   "id": "CNA-BUG-167",
   "class": "bug",
   "title": "LocalGamerServicesStore rounds 64-bit values through double and renames an unchecked temporary write over the store file",
   "summary": "Achievement ticks, leaderboard ratings and Int64, DateTime and TimeSpan columns are stored as JSON doubles and lose low bits above 2^53, and WriteJsonFile ignores stream and directory errors, so a failed temporary write can replace a good store file.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Internal::GamerServices::SaveEarnedAchievementEXT/LoadEarnedAchievementsEXT and the leaderboard entry and column persistence behind SignedInGamer::AwardAchievement, GetAchievements and LeaderboardEntry::setRatingProperty",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-167.html",
   "sources": [
    "modules/gamer-services/include/CNA/Internal/GamerServices/LocalGamerServicesStore.hpp",
    "modules/gamer-services/src/Internal/LocalGamerServicesStore.cpp",
    "modules/content/include/CNA/Internal/Json.hpp"
   ],
   "related": [
    "deep-dives/services/gamer-services-contract.html",
    "development/internals/modules/gamer-services.html",
    "docs/tutorials/123-achievements.html"
   ]
  },
  {
   "id": "CNA-BUG-168",
   "class": "bug",
   "title": "LocalGamerServicesStore maps distinct gamertags to one achievements file when they differ only in characters outside A-Z, a-z, 0-9, '.', '_' and '-'",
   "summary": "SanitizeStoreFileNameComponent replaces every other byte with an underscore, so gamertags such as \"Ann B\" and \"Ann_B\", or two same-length non-ASCII names, share one achievements file and see each other's achievements.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "SignedInGamer::AwardAchievement and GetAchievements persistence (CNA::Internal::GamerServices::SaveEarnedAchievementEXT, LoadEarnedAchievementsEXT, SanitizeStoreFileNameComponent)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-168.html",
   "sources": [
    "modules/gamer-services/src/Internal/LocalGamerServicesStore.cpp",
    "modules/gamer-services/src/Xna/SignedInGamer.cpp"
   ],
   "related": [
    "deep-dives/services/gamer-services-contract.html",
    "development/internals/modules/gamer-services.html"
   ]
  },
  {
   "id": "CNA-BUG-169",
   "class": "bug",
   "title": "NetworkSession::GamerJoined reports a gamer added with AddLocalGamer twice to a handler subscribed between that call and the next Update",
   "summary": "AddLocalGamer inserts the new gamer into AllGamers at once and queues its GamerJoin event for the next Update, while subscribing replays GamerJoined for every gamer already in AllGamers, so a handler subscribed in that window is called twice for the new gamer.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Net::NetworkSession::GamerJoined (subscription replay) with NetworkSession::AddLocalGamer and the transport's AddRemoteGamer",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-169.html",
   "sources": [
    "modules/net/src/Xna/NetworkSession.cpp",
    "modules/net/tests/Microsoft/Xna/Framework/Net/NetworkSessionTests.cpp"
   ],
   "related": [
    "deep-dives/services/network-sessions.html",
    "development/internals/modules/net.html"
   ]
  },
  {
   "id": "CNA-BUG-170",
   "class": "bug",
   "title": "A joined SystemLink session answers LAN discovery for itself and handles ClientHello as if it were the host",
   "summary": "Every SystemLink session, including a joined one, registers with discovery and ReplyToQuery ignores IsHost, so Find lists a session once per member and joining through a client's entry attaches to that client instead of the host.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Net::NetworkSession::Find and Join for NetworkSessionType::SystemLink (ENetDiscoveryService::RegisterHost and ReplyToQuery; ENetBackend::StartHosting and HandleClientHello)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-170.html",
   "sources": [
    "modules/net/src/Xna/NetworkSession.cpp",
    "modules/net/src/Internal/ENetBackend.cpp",
    "modules/net/src/Internal/ENetDiscoveryService.cpp",
    "modules/net/tests/CNA/Internal/Net/ENetDiscoveryServiceTests.cpp",
    "modules/net/tests/CNA/Internal/Net/TwoProcessLoopbackTest.cpp"
   ],
   "related": [
    "deep-dives/services/network-sessions.html",
    "development/internals/modules/net.html",
    "docs/tutorials/97-networking.html"
   ]
  },
  {
   "id": "CNA-BUG-171",
   "class": "bug",
   "title": "LocalNetworkGamer::ReceiveData(PacketReader&, NetworkGamer*&) does not resize the reader, so a reused reader keeps the previous packet's Length and trailing bytes",
   "summary": "The overload writes the packet at position 0 of the reader's MemoryStream without truncating it, so after a longer packet a reused PacketReader reports the old Length and exposes stale bytes past the new packet, where XNA resizes the reader to the packet.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Net::LocalNetworkGamer::ReceiveData(PacketReader&, NetworkGamer*&); PacketReader::getLengthProperty() and getPositionProperty()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-171.html",
   "sources": [
    "modules/net/src/Xna/LocalNetworkGamer.cpp",
    "modules/net/src/Xna/PacketReader.cpp",
    "modules/net/include/Microsoft/Xna/Framework/Net/LocalNetworkGamer.hpp",
    "modules/net/tests/Microsoft/Xna/Framework/Net/LocalNetworkGamerTests.cpp"
   ],
   "related": [
    "deep-dives/services/network-sessions.html",
    "development/internals/modules/net.html"
   ]
  },
  {
   "id": "CNA-BUG-172",
   "class": "bug",
   "title": "A joined SystemLink session reports MaxGamers 31 and PrivateGamerSlots 4 instead of the host's values",
   "summary": "EndJoin constructs the client's NetworkSession with the placeholders MaxSupportedGamers and 4 that FNA marks FIXME, and nothing in the handshake updates them, so a client's MaxGamers, PrivateGamerSlots and session-full check disagree with the host.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Net::NetworkSession::getMaxGamersProperty() and getPrivateGamerSlotsProperty() on a session obtained from Join, and the client-side session-full check in AddRemoteGamer",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-172.html",
   "sources": [
    "modules/net/src/Xna/NetworkSession.cpp",
    "modules/net/src/Internal/ENetBackend.cpp",
    "modules/net/src/Internal/NetPacketCodec.cpp",
    "modules/net/tests/Microsoft/Xna/Framework/Net/NetworkSessionTests.cpp"
   ],
   "related": [
    "deep-dives/services/network-sessions.html",
    "development/internals/modules/net.html",
    "docs/tutorials/97-networking.html"
   ]
  },
  {
   "id": "CNA-BUG-173",
   "class": "bug",
   "title": "GamerPresence maps a presence mode to its display string through an alphabetically ordered table indexed by the enum ordinal",
   "summary": "setPresenceModeProperty selects presenceModeStrings_[static_cast<size_t>(mode)], but the 60-entry table is sorted by name while GamerPresenceMode follows XNA's declaration order, so None maps to 'Arcade Mode'; the string is not yet observable.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GamerPresence::setPresenceModeProperty(GamerPresenceMode) and GamerPresence::SetPresenceModeStringEXT(const std::string&)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-173.html",
   "sources": [
    "modules/gamer-services/src/Xna/GamerPresence.cpp",
    "modules/gamer-services/include/Microsoft/Xna/Framework/GamerServices/GamerPresenceMode.hpp"
   ],
   "related": [
    "deep-dives/services/gamer-services-contract.html",
    "development/internals/modules/gamer-services.html"
   ]
  },
  {
   "id": "CNA-BUG-174",
   "class": "bug",
   "title": "LocalNetworkGamer::ReceiveData(PacketReader&, NetworkGamer*&) always returns 0 instead of the packet size",
   "summary": "The PacketReader overload keeps FNA's never-updated length variable and returns 0 whether or not a packet was received, where XNA returns the number of bytes read.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "LocalNetworkGamer::ReceiveData(PacketReader&, NetworkGamer*&)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-174.html",
   "sources": [
    "modules/net/src/Xna/LocalNetworkGamer.cpp",
    "modules/net/include/Microsoft/Xna/Framework/Net/LocalNetworkGamer.hpp",
    "modules/net/tests/Microsoft/Xna/Framework/Net/LocalNetworkGamerTests.cpp"
   ],
   "related": [
    "deep-dives/services/network-sessions.html",
    "development/internals/modules/net.html"
   ]
  },
  {
   "id": "CNA-BUG-175",
   "class": "bug",
   "title": "The bundled procedural avatar's garment shells interpenetrate its body, leaving the collar and cuffs visible through the skin",
   "summary": "CNA's own avatar record measures shirt, pants and shoe vertices inside the body (shirt 64 of 228) in both rest and wave poses; four remedies were implemented, measured and reverted, and the defect is open.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "recorded-by-cna",
   "tests_present": false,
   "public_contract": "The bundled avatar content produced by tools/avatar_builder and drawn by AvatarRenderer's real-rendering extension",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-175.html",
   "sources": [
    "NEXTnet.md",
    "tools/avatar_builder/generate_clothes_meshcraft.py",
    "tools/avatar_builder/diagnose_avatar_mesh.py"
   ],
   "related": [
    "deep-dives/services/avatars.html"
   ]
  },
  {
   "id": "CNA-BUG-176",
   "class": "bug",
   "title": "Setting Game::IsMouseVisible throws PlatformException on the terminal platform when the terminal reports mouse input",
   "summary": "Game::setIsMouseVisibleProperty forwards to IPlatformMouse::SetCursorVisible whenever a window and a mouse service exist; the terminal platform supplies a TerminalMouse whenever stdin and stdout are both terminals (TerminalCapabilities::canQuery is isatty(stdin), independent of whether the emulator answers any query), and that mouse always throws.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Game::setIsMouseVisibleProperty(bool); CNA::Platform::IPlatformMouse::SetCursorVisible(bool) on the terminal platform",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-176.html",
   "sources": [
    "modules/runtime/src/Game.cpp",
    "modules/platform/src/Terminal/TerminalMouse.cpp",
    "modules/platform/src/Terminal/TerminalPlatform.cpp",
    "modules/platform/include/CNA/Platform/Input/IPlatformMouse.hpp",
    "modules/runtime/tests/Microsoft/Xna/Framework/GamePlatformTimingTests.cpp"
   ],
   "related": [
    "deep-dives/framework/game-class-and-lifecycle.html",
    "development/architecture/platform.html",
    "development/internals/platforms/terminal.html",
    "development/internals/runtime/module.html",
    "docs/input.html"
   ]
  },
  {
   "id": "CNA-BUG-177",
   "class": "bug",
   "title": "The Headless and Terminal window constructors accept BorderlessFullscreen although their own SetFullscreenMode refuses it",
   "summary": "Both capability-minimal windows store WindowDescription::fullscreenMode directly at construction instead of routing it through SetFullscreenMode, so a window created in BorderlessFullscreen reports that mode though the platform's capability is false.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Platform::IPlatform::CreateWindow(const WindowDescription&) and IPlatformWindow::GetFullscreenMode()/SetFullscreenMode() on the Headless and Terminal platforms",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-177.html",
   "sources": [
    "modules/platform/src/Headless/HeadlessPlatform.cpp",
    "modules/platform/src/Terminal/TerminalPlatform.cpp",
    "modules/platform/tests/CNA/Platform/PlatformConformanceTests.cpp"
   ],
   "related": [
    "development/architecture/platform.html",
    "development/internals/platforms/headless.html",
    "development/internals/platforms/terminal.html",
    "docs/platforms.html"
   ]
  },
  {
   "id": "CNA-BUG-178",
   "class": "bug",
   "title": "The SDL2 backend negates a flipped mouse wheel while SDL3 passes SDL's adjusted value through, so the two report opposite signs under natural scrolling",
   "summary": "Sdl2Platform negates wheel x/y on SDL_MOUSEWHEEL_FLIPPED, undoing the host's natural-scrolling preference, while Sdl3EventMapper passes SDL's adjusted value through; MouseWheelEvent is documented as the post-preference value.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Platform::MouseWheelEvent::x / y (\"scroll amount after the host's scrolling-direction preference\")",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-178.html",
   "sources": [
    "modules/platform/src/Sdl2/Sdl2Platform.cpp",
    "modules/platform/src/Sdl3/Sdl3EventMapper.cpp",
    "modules/platform/include/CNA/Platform/PlatformEvent.hpp"
   ],
   "related": [
    "deep-dives/services/input-model.html",
    "development/internals/input/events.html",
    "development/internals/platforms/sdl2.html",
    "docs/input.html"
   ]
  },
  {
   "id": "CNA-BUG-179",
   "class": "bug",
   "title": "Win32 EnterExclusiveFullscreen fails silently yet GetFullscreenMode reports ExclusiveFullscreen",
   "summary": "EnterExclusiveFullscreen returns silently when a monitor-info, EnumDisplaySettingsW or ChangeDisplaySettingsExW step fails, though its comment says a refusal is reported; SetFullscreenMode still records ExclusiveFullscreen, so GetFullscreenMode misreports it.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Platform::Win32::Win32Window::SetFullscreenMode(WindowFullscreenMode::ExclusiveFullscreen) and GetFullscreenMode()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-179.html",
   "sources": [
    "modules/platform/src/Win32/Win32Window.cpp"
   ],
   "related": [
    "development/handbook/modify-a-platform-backend.html",
    "development/internals/platforms/win32.html",
    "docs/native-platforms.html"
   ]
  },
  {
   "id": "CNA-BUG-180",
   "class": "bug",
   "title": "Win32GlContext ignores multisample and per-channel format requests and reports the requested description as if it were granted",
   "summary": "DescribeFormat ignores GlContextDescription's per-channel and multisample fields, and GetContextAttributes returns the requested description verbatim, so a legacy fallback context is reported as the requested version.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Platform::IPlatformGlContext::CreateContext and GetContextAttributes on the Win32 backend",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-180.html",
   "sources": [
    "modules/platform/src/Win32/Win32GraphicsServices.cpp",
    "modules/platform/src/Win32/Win32Window.cpp",
    "modules/platform/include/CNA/Platform/IPlatformGlContext.hpp"
   ],
   "related": [
    "development/handbook/modify-a-platform-backend.html",
    "development/internals/platforms/win32.html",
    "docs/native-platforms.html"
   ]
  },
  {
   "id": "CNA-BUG-181",
   "class": "bug",
   "title": "Sdl3Platform reports the nativeFileDialog capability on iOS and web builds, where SDL has no usable file-dialog backend",
   "summary": "The SDL3 platform sets nativeFileDialog unconditionally, so on iOS and the web the platform says a dialog can be shown while FileDialog::getIsSupportedProperty says it cannot, and FileDialog::Show* reach SDL, which fails the request.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "low",
   "confidence": "strong",
   "tests_present": true,
   "public_contract": "CNA::Platform::PlatformCapabilities::nativeFileDialog as reported by the SDL3 platform (Sdl3Platform::GetCapabilities); CNA::Devices::FileDialog::getIsSupportedProperty and ShowOpenFile, ShowSaveFile, ShowOpenFolder",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-181.html",
   "sources": [
    "modules/platform/src/Sdl3/Sdl3Platform.cpp",
    "modules/platform/include/CNA/Platform/PlatformCapabilities.hpp",
    "modules/devices-ext/src/FileDialog.cpp",
    "modules/devices-ext/include/CNA/Devices/FileDialog.hpp",
    "modules/platform/src/Sdl3/Sdl3SystemServices.cpp"
   ],
   "related": [
    "deep-dives/services/host-devices.html",
    "development/internals/modules/devices-ext.html",
    "docs/cnaext-engine.html"
   ]
  },
  {
   "id": "CNA-BUG-182",
   "class": "bug",
   "title": "Win32Dialogs file dialogs run modally inside Show* and invoke the callback before returning, contrary to the IPlatformDialogs timing contract",
   "summary": "On the native WIN32 platform the three file dialogs run modally on the calling thread and call the result callback before returning, while IPlatformDialogs and FileDialog promise an asynchronous callback after the call returns.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Platform::IPlatformDialogs::ShowOpenFileDialog, ShowSaveFileDialog and ShowOpenFolderDialog on the WIN32 platform, and through them CNA::Devices::FileDialog::ShowOpenFile, ShowSaveFile and ShowOpenFolder",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-182.html",
   "sources": [
    "modules/platform/src/Win32/Win32SystemServices.cpp",
    "modules/platform/include/CNA/Platform/IPlatformSystemServices.hpp",
    "modules/devices-ext/include/CNA/Devices/FileDialog.hpp",
    "modules/platform/tests/CNA/Platform/Win32SystemServicesTests.cpp",
    "modules/platform/tests/CNA/Platform/X11DesktopPortalTests.cpp",
    "modules/platform/tests/CNA/Platform/WaylandDesktopPortalTests.cpp"
   ],
   "related": [
    "deep-dives/services/host-devices.html",
    "development/internals/modules/devices-ext.html",
    "development/internals/platforms/win32.html",
    "development/takeover/threading.html",
    "docs/tutorials/88-device-layer.html"
   ]
  },
  {
   "id": "CNA-BUG-183",
   "class": "bug",
   "title": "The SDL3 file-dialog and tray-entry trampolines call application callbacks without a try/catch, so a throwing handler unwinds through SDL's C code",
   "summary": "ResultTrampoline and EntryClickTrampoline invoke the application's std::function directly from SDL C callbacks, so an exception escaping it crosses SDL frames (undefined behaviour, typically std::terminate).",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "low",
   "confidence": "reproduced",
   "tests_present": false,
   "public_contract": "CNA::Devices::FileDialog result callbacks and CNA::Devices::SystemTray entry-click callbacks on the SDL3 platform",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-183.html",
   "sources": [
    "modules/platform/src/Sdl3/Sdl3SystemServices.cpp",
    "modules/platform/src/Sdl3/Sdl3Tray.cpp",
    "modules/devices-ext/include/CNA/Devices/FileDialog.hpp"
   ],
   "related": [
    "deep-dives/services/host-devices.html",
    "development/internals/modules/devices-ext.html"
   ]
  },
  {
   "id": "CNA-BUG-184",
   "class": "bug",
   "title": "Core's build files still carry dependencies its sources dropped: -lembind on Emscripten and a link probe that tolerates SDL3",
   "summary": "modules/core/CMakeLists.txt still adds -lembind for every Emscripten consumer although the browser preference reader was rewritten with EM_JS to avoid embind, and probe_core still permits SDL3 although core no longer uses SDL.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The link interface of cna_core (CNA::Core) on Emscripten, and the probe_core link-closure check",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-184.html",
   "sources": [
    "modules/core/CMakeLists.txt",
    "modules/core/src/GraphicsRendererSelectionEmscripten.cpp",
    "modules/core/src/GraphicsRendererSelection.cpp",
    "cmake/Tests/ModuleProbes.cmake"
   ],
   "related": [
    "development/internals/modules/core.html",
    "development/testing/architecture.html",
    "docs/runtime-renderer-selection.html"
   ]
  },
  {
   "id": "CNA-BUG-185",
   "class": "bug",
   "title": "Stub_Smoke links SDL3::SDL3 unconditionally, so STUB + tests cannot be configured with CNA_ENABLE_SDL=OFF",
   "summary": "The STUB renderer's smoke-test macro links SDL3::SDL3 in both branches and its source includes the SDL3 header, while CNA_ENABLE_SDL=OFF is a supported configuration; with STUB selected and tests on, the SDL-free configuration has no SDL3 target to link.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA_GRAPHICS_RENDERER=STUB with CNA_BUILD_TESTS=ON and CNA_ENABLE_SDL=OFF",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-185.html",
   "sources": [
    "modules/renderers/stub/examples/CMakeLists.txt",
    "modules/renderers/stub/examples/stub_smoke_test.cpp",
    "cmake/SdlAvailability.cmake",
    "modules/renderers/headless/examples/CMakeLists.txt",
    "modules/renderers/software/examples/CMakeLists.txt",
    "modules/renderers/stub/CMakeLists.txt"
   ],
   "related": [
    "development/build/architecture.html",
    "development/internals/graphics/stub.html",
    "development/reference/test-targets.html"
   ]
  },
  {
   "id": "CNA-BUG-186",
   "class": "bug",
   "title": "CNA_ENABLE_VIDEO=AUTO accepts any pkg-config FFmpeg, but VideoDecoder.cpp needs the FFmpeg 5.1 channel-layout API",
   "summary": "The FFmpeg probe states no minimum version while VideoDecoder.cpp uses AVCodecContext::ch_layout and swr_alloc_set_opts2, so a host with older FFmpeg development packages enables video at configure time and then fails to compile.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "strong",
   "tests_present": true,
   "public_contract": "CMake option CNA_ENABLE_VIDEO (AUTO, the default, and ON) and the cna_video_ffmpeg target",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-186.html",
   "sources": [
    "modules/CMakeLists.txt",
    "modules/video-ffmpeg/src/VideoDecoder.cpp",
    "modules/video-ffmpeg/CMakeLists.txt",
    ".github/workflows/general-tests-ci.yml"
   ],
   "related": [
    "development/internals/modules/video-ffmpeg.html",
    "docs/building.html",
    "docs/video-playback.html"
   ]
  },
  {
   "id": "CNA-BUG-189",
   "class": "bug",
   "title": "The GDI renderer's configure message hard-codes '3 GDI-owned units' while modules/renderers/gdi/src compiles four",
   "summary": "modules/renderers/gdi/CMakeLists.txt reports the GDI archive as the shared CPU-2D source count plus a literal 3, but cna_add_renderer globs four GDI translation units, so the reported total is one short.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "The configure-time STATUS line 'CNA: GDI renderer archive = N shared CPU-2D sources + 3 GDI-owned units = M translation units' (GDI-078)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-189.html",
   "sources": [
    "modules/renderers/gdi/CMakeLists.txt",
    "modules/renderers/CMakeLists.txt",
    "modules/renderers/gdi/src/GdiRendererDescriptor.cpp"
   ],
   "related": [
    "development/build/architecture.html",
    "development/repository/module-graph.html"
   ]
  },
  {
   "id": "CNA-BUG-190",
   "class": "bug",
   "title": "modules/renderers/CMakeLists.txt enters common/d3d, the GDI software sources and the Metal renderer target only when the default identity matches, so a multi-renderer set that lists DIRECTX11, DIRECTX12, GDI or METAL without the matching default passes the combination rules and then cannot build",
   "summary": "Three helper directories are entered by testing the default identity instead of set membership, yet the combination rules accept sets such as HEADLESS;DIRECTX11 (or DIRECTX9;DIRECTX11), whose DIRECTX11 family then links an undefined cna_renderer_d3dcommon. A DIRECTX11 or DIRECTX12 default does enter common/d3d for both, so the D3D condition bites only when the default is neither.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "strong",
   "tests_present": true,
   "public_contract": "CNA_GRAPHICS_RENDERERS multi-renderer mode and cna_validate_renderer_combination (cmake/RendererCombinations.cmake): incompatible sets are rejected at configure time with a reason, never left to surface as a build error",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-190.html",
   "sources": [
    "modules/renderers/CMakeLists.txt",
    "modules/renderers/directx11/CMakeLists.txt",
    "modules/renderers/software/CMakeLists.txt",
    "modules/renderers/metal/CMakeLists.txt",
    "cmake/RendererCombinations.cmake",
    "modules/renderers/directx12/CMakeLists.txt",
    "modules/renderers/common/d3d/CMakeLists.txt",
    "modules/renderers/gdi/CMakeLists.txt"
   ],
   "related": [
    "development/internals/graphics/selection.html",
    "development/repository/module-graph.html",
    "docs/runtime-renderer-selection.html"
   ]
  },
  {
   "id": "CNA-BUG-191",
   "class": "bug",
   "title": "cna_configure_vendored_enet tells the user to run 'git submodule update --init third_party/enet', but ENet is committed in the tree, not a submodule",
   "summary": "When third_party/enet/CMakeLists.txt is missing, cmake/ThirdPartyENet.cmake fails with advice to initialise a submodule that does not exist; ENet is ordinary tracked source, so the advice cannot restore it.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "cmake/ThirdPartyENet.cmake cna_configure_vendored_enet (CNA_ENABLE_NET builds): the FATAL_ERROR shown when the vendored ENet source is absent",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-191.html",
   "sources": [
    "cmake/ThirdPartyENet.cmake",
    ".gitmodules"
   ],
   "related": [
    "development/build/architecture.html",
    "development/internals/modules/net.html"
   ]
  },
  {
   "id": "CNA-BUG-192",
   "class": "bug",
   "title": "metal-macos-ci.yml's push path filter names three CMake files that no longer exist and omits the files that now register the Metal tests",
   "summary": "The Metal workflow's push filter lists three removed CMake files, while edits to modules/renderers/metal/CMakeLists.txt or its examples/CMakeLists.txt, where the Metal_* CTests are registered, do not trigger it.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": ".github/workflows/metal-macos-ci.yml, on.push.paths",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-192.html",
   "sources": [
    ".github/workflows/metal-macos-ci.yml",
    "modules/renderers/metal/examples/CMakeLists.txt",
    "modules/renderers/metal/CMakeLists.txt"
   ],
   "related": [
    "deep-dives/renderers/native-gpu-evidence-tiers.html",
    "development/testing/architecture.html",
    "development/workflows.html",
    "docs/platforms.html"
   ]
  },
  {
   "id": "CNA-BUG-193",
   "class": "bug",
   "title": "general-tests-ci.yml still allowlists EasyGL_GraphicsDevice_ReferenceStencil as a known failure after REMED-GFX-236 fixed it, so a regression of that test cannot turn the job red",
   "summary": "The only unfiltered CI job classifies failures against a one-entry KNOWN_FAILURES list whose entry is the EasyGL ReferenceStencil test, which CNA's own record says now passes; if EasyGL's ReferenceStencil override breaks again, the job stays green.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": ".github/workflows/general-tests-ci.yml, step 'Classify failures (known pre-existing vs. genuinely new regressions)': KNOWN_FAILURES",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-193.html",
   "sources": [
    ".github/workflows/general-tests-ci.yml",
    "modules/renderers/easygl/examples/easygl_graphicsdevice_reference_stencil_test.cpp",
    "modules/renderers/easygl/src/EasyGLRenderer.cpp",
    "plans/plan_postaudit.md",
    "remediation/REMEDIATION_PROGRESS.md",
    "modules/renderers/easygl/examples/CMakeLists.txt"
   ],
   "related": [
    "development/testing/architecture.html",
    "development/workflows.html",
    "docs/verification.html"
   ]
  },
  {
   "id": "CNA-BUG-194",
   "class": "bug",
   "title": "The SDL2-only configuration guard recommends VULKAN, which the SDL2 platform cannot run",
   "summary": "Sdl2OnlyConfiguration.cmake's error text lists VULKAN among the SDL-independent renderers to choose, but Sdl2Platform::GetVulkanSurface returns null, so a VULKAN build on SDL2 can only fail later at GraphicsDevice construction.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "cmake/Sdl2OnlyConfiguration.cmake's diagnostic recommending SDL-independent renderers",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-194.html",
   "sources": [
    "cmake/Sdl2OnlyConfiguration.cmake",
    "modules/platform/src/Sdl2/Sdl2Platform.cpp",
    "modules/graphics/include/CNA/Internal/Renderers/Common/PlatformVulkanRendererState.hpp"
   ],
   "related": [
    "development/handbook/change-build-configuration.html",
    "development/internals/platforms/sdl2.html",
    "docs/platforms.html"
   ]
  },
  {
   "id": "CNA-BUG-195",
   "class": "bug",
   "title": "The SDL2-only guard inspects only CNA_GRAPHICS_RENDERER, so a multi-renderer list containing an SDL3-linked family is not refused",
   "summary": "Sdl2OnlyConfiguration.cmake checks the scalar CNA_GRAPHICS_RENDERER but never the CNA_GRAPHICS_RENDERERS list, so an SDL2-only build whose list includes an SDL3-linked family passes the guard meant to keep two SDL majors apart.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "cmake/Sdl2OnlyConfiguration.cmake's protection against linking SDL2 and SDL3 into one binary",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-195.html",
   "sources": [
    "cmake/Sdl2OnlyConfiguration.cmake",
    "cmake/SdlAvailability.cmake",
    "cmake/RendererCombinations.cmake"
   ],
   "related": [
    "development/handbook/change-build-configuration.html",
    "development/internals/platforms/sdl2.html",
    "docs/platforms.html"
   ]
  },
  {
   "id": "CNA-BUG-196",
   "class": "bug",
   "title": "CNA_X11_HAVE_VULKAN_HEADERS is defined by the X11 CMake but read by no source, so the dependency summary implies a Vulkan-header gate that does not exist",
   "summary": "PlatformX11.cmake defines CNA_X11_HAVE_VULKAN_HEADERS and lists Vulkan headers as an optional dependency, but no X11 source reads the macro; the X11 Vulkan surface is created unconditionally and resolves its entry point at run time.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "cmake/PlatformX11.cmake's CNA_X11_HAVE_VULKAN_HEADERS definition and the X11 dependency summary",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-196.html",
   "sources": [
    "cmake/PlatformX11.cmake",
    "modules/platform/src/X11/X11GraphicsServices.cpp",
    "modules/platform/src/X11/X11Platform.cpp"
   ],
   "related": [
    "development/handbook/modify-a-platform-backend.html",
    "development/internals/platforms/x11.html",
    "docs/native-platforms.html"
   ]
  },
  {
   "id": "CNA-BUG-197",
   "class": "bug",
   "title": "cmake/toolchains/mingw-w64.cmake falls back to the i686 compiler but keeps CMAKE_SYSTEM_PROCESSOR x86_64, so the persistent SDL install key mislabels a 32-bit build",
   "summary": "When x86_64-w64-mingw32-gcc is missing the toolchain silently selects i686-w64-mingw32 yet still declares x86_64, which becomes part of the .sdl-prebuilt-Windows-x86_64 cache key; its header comment also still requires a pre-built SDL on CMAKE_PREFIX_PATH.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "cmake/toolchains/mingw-w64.cmake (MinGW-w64 cross toolchain file)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-197.html",
   "sources": [
    "cmake/toolchains/mingw-w64.cmake",
    "cmake/ThirdPartySDL.cmake"
   ],
   "related": [
    "deep-dives/platforms/windows-cross-compiling-and-wine.html",
    "development/build/architecture.html"
   ]
  },
  {
   "id": "CNA-BUG-198",
   "class": "bug",
   "title": "Link-closure tests pass --build-dir ${CMAKE_BINARY_DIR}, so when CNA is added as a subproject they look for link.txt in the consumer's build root and always skip",
   "summary": "The probe targets are defined in CNA's own root directory, whose binary directory is a subdirectory of the consumer's build tree; the checker is pointed at the top-level build root instead and never finds CMakeFiles/<probe>.dir/link.txt.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "cmake/Tests/ModuleProbes.cmake ModuleLinkClosure_* --build-dir argument",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-198.html",
   "sources": [
    "cmake/Tests/ModuleProbes.cmake",
    "CMakeLists.txt"
   ],
   "related": [
    "deep-dives/build/dependency-boundaries.html"
   ]
  },
  {
   "id": "CNA-BUG-199",
   "class": "bug",
   "title": "Six CI workflows pin August 2026 sharp-runtime commits that lack components CNA's default closure requests (Xml.Serialization off Windows, Resources everywhere), so they stop at configure",
   "summary": "CNA's default sharp-runtime component closure has requested Xml.Serialization on non-Windows targets since 2026-09-06 and Resources on every target since 2026-09-20. The workflows pinned to sharp-runtime bc8dbf41, f23ded28 or df1b42ab check out revisions that register neither, and sharp-runtime ends configuration with 'Unknown Sharp Runtime component'. The five non-Windows lanes have therefore failed at configure since 2026-09-06; only the Windows content-pipeline lane is broken solely by Resources.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "htmldom-ci.yml, devices-tests.yml, emscripten-multi-renderer-ci.yml, apple-ci.yml, metal-macos-ci.yml and content-pipeline-windows-ci.yml; SHARP_RUNTIME_COMPONENTS",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-199.html",
   "sources": [
    "cmake/SharpRuntimeConsumption.cmake",
    "CMakeLists.txt",
    ".github/workflows/htmldom-ci.yml",
    ".github/workflows/devices-tests.yml",
    ".github/workflows/emscripten-multi-renderer-ci.yml",
    ".github/workflows/apple-ci.yml",
    ".github/workflows/metal-macos-ci.yml",
    ".github/workflows/content-pipeline-windows-ci.yml",
    "scripts/ci/clone_siblings.sh"
   ],
   "related": [
    "deep-dives/build/third-party-dependencies.html",
    "deep-dives/foundations/ecosystem.html",
    "deep-dives/platforms/android-and-apple-platforms.html",
    "deep-dives/platforms/cross-platform-contract.html",
    "deep-dives/platforms/web-build-and-main-loop.html",
    "deep-dives/reference/verification-tiers.html",
    "deep-dives/sharp-runtime/components-and-consumption.html",
    "development/testing/architecture.html",
    "development/testing/index.html",
    "docs/building.html",
    "docs/tutorials/105-browser-renderers.html",
    "docs/verification.html"
   ]
  },
  {
   "id": "CNA-BUG-200",
   "class": "bug",
   "title": "The registered CTest CNAEXT_NoPosixSetenv fails at this snapshot: twelve Wayland setenv/unsetenv call lines trip the gate",
   "summary": "scripts/check_no_posix_setenv.py forbids POSIX setenv/unsetenv under modules/, tools/ and tests/, but the native Wayland backend and its tests added twelve such lines on 2026-09-15 and 2026-09-16, so the gate CNA registers in every test-enabled tree has exited 1 since 2026-09-15.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "medium",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "CTest CNAEXT_NoPosixSetenv (modules/graphics-ext/examples/CMakeLists.txt, label CnaExt)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-200.html",
   "sources": [
    "scripts/check_no_posix_setenv.py",
    "modules/graphics-ext/examples/CMakeLists.txt",
    "modules/platform/src/Wayland/WaylandPlatform.cpp",
    "modules/platform/tests/CNA/Platform/WaylandProtocolTests.cpp",
    "modules/platform/tests/CNA/Platform/WaylandTestEnvironment.cpp",
    "modules/platform/tests/CNA/Platform/WaylandDesktopPortalTests.cpp",
    "modules/platform/tests/CNA/Platform/WaylandTestCompositor.cpp",
    ".github/workflows/general-tests-ci.yml",
    "docs/opengl4-renderer.md"
   ],
   "related": [
    "deep-dives/verification/test-populations-and-gates.html",
    "development/internals/platforms/wayland.html",
    "development/testing/index.html"
   ]
  },
  {
   "id": "CNA-BUG-201",
   "class": "bug",
   "title": "StorageDeviceDeleteContainerTest writes to and deletes inside the developer's real per-user data directory",
   "summary": "The StorageDevice deletion tests resolve their fixture root from the real XDG_DATA_HOME/LOCALAPPDATA/HOME environment, remove_all() it in TearDown, and then recreate the default game's save directory, while a comment still reasons about an SDL preference path.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "StorageDeviceDeleteContainerTest fixture (SetUp, TearDown) in CnaTests",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-201.html",
   "sources": [
    "modules/storage/tests/Microsoft/Xna/Framework/Storage/StorageDeviceTests.cpp",
    "modules/storage/src/StorageDevice.cpp",
    "modules/gamer-services/tests/Microsoft/Xna/Framework/GamerServices/GamerServicesGamerTests.cpp",
    "modules/gamer-services/src/Internal/LocalGamerServicesStore.cpp",
    "cmake/UnitTests.cmake",
    "modules/c-api/CMakeLists.txt"
   ],
   "related": [
    "development/internals/modules/storage.html",
    "development/takeover/case-study-storage.html",
    "development/takeover/validation.html",
    "development/testing/index.html",
    "docs/storage.html"
   ]
  },
  {
   "id": "CNA-BUG-202",
   "class": "bug",
   "title": "In a multi-renderer build, non-default renderers' example CTests are registered but run under the default renderer",
   "summary": "The SDL_GPU, SOFTWARE, STUB and VULKAN example blocks are entered for a non-default member of CNA_GRAPHICS_RENDERERS, yet their registrations select no renderer, so each executable runs under the build default.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Renderer example CTests (SdlGpu_*, Software_*, Stub_Smoke, Vulkan_*) in a CNA_GRAPHICS_RENDERERS build, including CNA's multi-renderer preset",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-202.html",
   "sources": [
    "modules/renderers/CMakeLists.txt",
    "modules/renderers/sdl-gpu/examples/CMakeLists.txt",
    "modules/renderers/software/examples/CMakeLists.txt",
    "modules/renderers/stub/examples/CMakeLists.txt",
    "modules/renderers/stub/examples/stub_smoke_test.cpp",
    "modules/renderers/vulkan/examples/CMakeLists.txt",
    "modules/renderers/headless/examples/CMakeLists.txt",
    "cmake/TestHelpers.cmake",
    "CMakePresets.json",
    "modules/renderers/opengl4/examples/opengl4_smoke_test.cpp"
   ],
   "related": [
    "development/handbook/change-build-configuration.html",
    "development/internals/graphics/selection.html",
    "development/internals/graphics/software.html",
    "development/internals/graphics/stub.html",
    "development/testing/architecture.html",
    "docs/runtime-renderer-selection.html"
   ]
  },
  {
   "id": "CNA-BUG-203",
   "class": "bug",
   "title": "SdlGpu_2D_HeadlessDriver forces headless mode under the x11 video driver that the SDL_GPU constructor refuses for it",
   "summary": "On non-Windows hosts the SDL_GPU headless registrations reuse the ordinary test environment (SDL_VIDEODRIVER=x11 by default), but SdlGpu_2D_HeadlessDriver also sets CNA_SDLGPU_TEST_FORCE_HEADLESS=1, which the constructor accepts only under dummy or offscreen.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "low",
   "confidence": "recorded-by-cna",
   "tests_present": true,
   "public_contract": "The SdlGpu_2D_HeadlessDriver CTest (SDLGPU-102) and the CNA_SDLGPU_TEST_VIDEO_DRIVER cache option",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-203.html",
   "sources": [
    "modules/renderers/sdl-gpu/examples/CMakeLists.txt",
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp",
    "modules/renderers/sdl-gpu/examples/sdlgpu_2d_test.cpp",
    "plans/plan_pre_sdlgpu_closeout.md",
    "plans/plan_street_sdlgpu.md"
   ],
   "related": [
    "development/internals/graphics/sdl-gpu.html",
    "development/testing/architecture.html",
    "docs/verification.html"
   ]
  },
  {
   "id": "CNA-BUG-204",
   "class": "bug",
   "title": "CnjEffectTest.LoadsRealCnjFixture and CnjStockEffectTest.CustomGlslEffectStillWorks expect a valid GLSL ES effect on any renderer that executes shader source under a non-HLSL dialect, which WebGPU (WGSL only) and SDL_GPU with libshaderc (Vulkan-rule GLSL) refuse",
   "summary": "The two tests carry the same expectation helper, which returns Valid for a renderer that reports CustomEffects, executes shader source and does not declare HLSL. WebGPU (Wgsl) and SDL_GPU with libshaderc (SpirV) match that description, yet both refuse the #version 300 es fixtures, so a CnaTests run defaulting to either renderer would fail both tests.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "low",
   "confidence": "strong",
   "tests_present": true,
   "public_contract": "modules/content/tests CnjEffectTest.LoadsRealCnjFixture (ExpectedGlslEffectValidity)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-204.html",
   "sources": [
    "modules/content/tests/Microsoft/Xna/Framework/Content/CnjEffectTests.cpp",
    "modules/renderers/sdl-gpu/include/CNA/Internal/Renderers/SdlGpu/SdlGpuRenderer.hpp",
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp"
   ],
   "related": [
    "deep-dives/content/cnj-documents.html",
    "deep-dives/renderers/sdl-gpu-pipeline-state-and-draw-order.html"
   ]
  },
  {
   "id": "CNA-BUG-205",
   "class": "bug",
   "title": "SDL_Renderer_ClearOptions_Audit encodes Clear semantics that no longer exist and catches the wrong exception type, so it cannot pass at this snapshot",
   "summary": "Clear now throws System::InvalidOperationException for any missing depth or stencil aspect, but the test expects Stencil-only clears not to throw and catches only std::runtime_error, which that exception does not derive from.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "modules/renderers/sdl-renderer/examples/sdlrenderer_clearoptions_audit_test.cpp (CTest SDL_Renderer_ClearOptions_Audit)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-205.html",
   "sources": [
    "modules/renderers/sdl-renderer/examples/sdlrenderer_clearoptions_audit_test.cpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp",
    "modules/renderers/sdl-renderer/include/CNA/Internal/Renderers/SdlRenderer/SdlRenderer.hpp"
   ],
   "related": [
    "deep-dives/graphics/graphicsdevice-contract.html",
    "deep-dives/renderers/sdl-renderer-2d-contract.html"
   ]
  },
  {
   "id": "CNA-BUG-206",
   "class": "bug",
   "title": "Software_XnaLineCoverage passes when a scene differs from the XNA reference: run-oracle-corpus-diff-software.sh fails only on render errors",
   "summary": "The CTest described as the exact Software regression for the two aliased-line scenes runs a script that prints DIFF for a pixel mismatch and still exits 0; only a missing reference or a failed render makes it fail.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "low",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "CTest Software_XnaLineCoverage (modules/renderers/software/examples/CMakeLists.txt)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-206.html",
   "sources": [
    "scripts/run-oracle-corpus-diff-software.sh",
    "modules/renderers/software/examples/CMakeLists.txt",
    "scripts/run-oracle-corpus-diff-easygl.sh"
   ],
   "related": [
    "deep-dives/renderers/native-gpu-evidence-tiers.html",
    "deep-dives/verification/oracles-and-engagement.html",
    "development/internals/graphics/software.html"
   ]
  },
  {
   "id": "CNA-BUG-207",
   "class": "bug",
   "title": "Delta-maintained diagnostics gauges such as Audio/AllocatedVoices drift after a runtime OFF window",
   "summary": "GaugeHandle::Add discards deltas while the runtime mode is OFF, so a gauge kept with GAUGE_ADD(+1/-1), such as Audio/AllocatedVoices, stays wrong (too high, or negative) after statistics are re-enabled, until mixer shutdown resets it.",
   "subsystem": "Diagnostics & Inspector",
   "status": "open",
   "severity": "low",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "CNA::Diagnostics::GaugeHandle::Add and CNA_DIAGNOSTICS_GAUGE_ADD across SetRuntimeMode(Mode::Off); the documented meaning of Audio/AllocatedVoices",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-207.html",
   "sources": [
    "modules/diagnostics/src/Diagnostics.cpp",
    "modules/diagnostics/include/CNA/Diagnostics/Instrumentation.hpp",
    "modules/audio/src/Backend/CnaMixer/MixerEngine.cpp",
    "modules/audio/src/Backend/Sdl3Mixer/MixerEngine.cpp",
    "docs/diagnostics.md",
    "modules/diagnostics/tests/CNA/Diagnostics/DiagnosticsTests.cpp"
   ],
   "related": [
    "development/internals/modules/diagnostics.html",
    "docs/diagnostics.html"
   ]
  },
  {
   "id": "CNA-BUG-208",
   "class": "bug",
   "title": "On Emscripten a diagnostics frame excludes the requestAnimationFrame wait, so FrameSample.framesPerSecond is a work rate there",
   "summary": "The web loop opens the frame scope inside EmscriptenMainLoopCallback and waits for the next animation frame after it returns, so web frame durations and FPS exclude pacing, unlike the native Tick the documentation describes.",
   "subsystem": "Diagnostics & Inspector",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Diagnostics::FrameSample (durationNs, framesPerSecond) as published by Game's frame scope",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-208.html",
   "sources": [
    "modules/runtime/src/Game.cpp",
    "modules/diagnostics/src/Diagnostics.cpp",
    "docs/diagnostics.md"
   ],
   "related": [
    "development/internals/modules/diagnostics.html",
    "development/internals/runtime/frame.html",
    "docs/diagnostics.html"
   ]
  },
  {
   "id": "CNA-BUG-209",
   "class": "bug",
   "title": "Inspector ServerHello.graphicsRenderer reports the compile-time default renderer, not the one GraphicsRendererSelection actually created",
   "summary": "The Inspector session names the build's default renderer identity, so in a multi-renderer build where a preference, the environment variable or a fallback selects another renderer, the Session view shows the wrong one.",
   "subsystem": "Diagnostics & Inspector",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Inspector::HelloResponse::graphicsRenderer (the Session view's renderer) versus CNA::GraphicsRendererSelection::GetActive()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-209.html",
   "sources": [
    "modules/inspector/src/Agent.cpp",
    "modules/core/include/CNA/GraphicsRendererType.hpp",
    "modules/core/include/CNA/GraphicsRendererSelection.hpp",
    "cmake/RendererSelection.cmake",
    "docs/inspector.md"
   ],
   "related": [
    "development/internals/graphics/selection.html",
    "development/internals/modules/inspector.html",
    "docs/inspector.html"
   ]
  },
  {
   "id": "CNA-BUG-210",
   "class": "bug",
   "title": "A diagnostics name or resource label longer than 4,096 bytes makes every Inspector snapshot or event batch that contains it fail with LimitExceeded",
   "summary": "Diagnostics accepts names up to 1 MiB and labels of any length, but the Inspector protocol caps strings at 4,096 bytes and refuses the whole response, so one long name breaks the affected Inspector views for the rest of the process.",
   "subsystem": "Diagnostics & Inspector",
   "status": "open",
   "severity": "low",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "CNA::Inspector protocol v1 SnapshotResponse and EventsResponse encoding (ProtocolCodec::Encode) over diagnostics provider v1 data",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-210.html",
   "sources": [
    "modules/diagnostics/src/Diagnostics.cpp",
    "modules/inspector/src/Protocol.cpp",
    "modules/inspector/src/Agent.cpp",
    "docs/inspector.md"
   ],
   "related": [
    "development/internals/modules/inspector.html",
    "docs/inspector.html"
   ]
  },
  {
   "id": "CNA-BUG-211",
   "class": "bug",
   "title": "Agent::Stop can wait up to about six seconds for a connection that the accept loop takes around the time Stop runs",
   "summary": "Stop shuts down only a client already published as activeClient_, and the worker never re-checks stopping_ after accepting. A connection accepted just before Stop, or during the accept poll of up to 200 ms that follows Stop setting stopping_, is therefore never shut down, and join waits on that client's handshake reads, up to 3 s for the header and 3 s for the payload.",
   "subsystem": "Diagnostics & Inspector",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Inspector::Agent::Stop() and ~Agent()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-211.html",
   "sources": [
    "modules/inspector/src/Agent.cpp",
    "modules/inspector/src/InternalSocket.cpp"
   ],
   "related": [
    "development/internals/modules/inspector.html",
    "docs/inspector.html"
   ]
  },
  {
   "id": "CNA-BUG-212",
   "class": "bug",
   "title": "cna_graphics_resource_get_graphics_device returns CNA_RESULT_INVALID_HANDLE for every resource created on a caller-created GraphicsDevice",
   "summary": "A resource made on a device from cna_graphics_device_create carries that device's handle as its owner token, and the route passes it to the game-only BorrowGameGraphicsDevice, so asking such a valid resource for its device always fails.",
   "subsystem": "C API & bindings",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "cna_graphics_resource_get_graphics_device(CNA_Handle resource, CNA_Handle* out_graphics_device) (CNA/C/graphics_resource.h) for resources created on a cna_graphics_device_create device",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-212.html",
   "sources": [
    "modules/c-api/src/CnaCApiGraphicsResource.cpp",
    "modules/c-api/src/CnaCApiRuntime.cpp",
    "modules/c-api/src/CnaCApiDisplay.cpp",
    "modules/c-api/src/CnaCApiDetail.hpp",
    "modules/c-api/include/CNA/C/graphics_resource.h",
    "modules/c-api/include/CNA/C/graphics_device.h",
    "modules/c-api/src/CnaCApiRuntimeDetail.hpp"
   ],
   "related": [
    "development/internals/bindings/c-api-internals.html",
    "docs/c-api.html"
   ]
  },
  {
   "id": "CNA-BUG-213",
   "class": "bug",
   "title": "audio.h and AUDIO.md call cna_dynamic_sound_effect_instance_submit_buffer safe from a producer thread, but every call off the creation thread returns CNA_RESULT_THREAD",
   "summary": "The submission routes resolve the instance through HandleRegistry::Get, which refuses any thread other than the handle's creation thread, so the documented canonical producer-thread usage fails; AUDIO.md's own threading section states the stricter rule.",
   "subsystem": "C API & bindings",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "cna_dynamic_sound_effect_instance_submit_buffer, cna_dynamic_sound_effect_instance_submit_float_buffer_ext",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-213.html",
   "sources": [
    "modules/c-api/src/CnaCApiAudio.cpp",
    "modules/c-api/src/CnaCApiDetail.hpp",
    "modules/c-api/include/CNA/C/audio.h",
    "docs/c-api/AUDIO.md",
    "modules/c-api/tests/pure_c/AudioStreamingSmoke.c"
   ],
   "related": [
    "deep-dives/services/sound-effects-and-streaming.html",
    "development/internals/bindings/c-api-internals.html",
    "docs/c-api.html"
   ]
  },
  {
   "id": "CNA-BUG-214",
   "class": "bug",
   "title": "docs/c-api/HANDLES.md documents CNA_RESULT_SHUTTING_DOWN for a closing or closed runtime, but no C API route ever returns it",
   "summary": "abi.h defines CNA_RESULT_SHUTTING_DOWN and HANDLES.md maps a closing runtime to it, but no route returns it and the registry has no shutdown state, so a stale handle answers CNA_RESULT_INVALID_HANDLE.",
   "subsystem": "C API & bindings",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA_RESULT_SHUTTING_DOWN (abi.h); the HANDLES.md validation table",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-214.html",
   "sources": [
    "docs/c-api/HANDLES.md",
    "modules/c-api/include/CNA/C/abi.h",
    "modules/c-api/src/CnaCApiDetail.cpp"
   ],
   "related": [
    "development/internals/bindings/c-api-internals.html",
    "docs/c-api.html"
   ]
  },
  {
   "id": "CNA-BUG-215",
   "class": "bug",
   "title": "GraphicsRendererSelection::IsLatched() is documented to latch when the first GraphicsDevice begins construction; it latches only on successful resolution",
   "summary": "The header comment on IsLatched() says the selection latches when the first GraphicsDevice begins construction, but GraphicsDevice::resolveRenderer latches only after a renderer has been created, so a resolution that fails before any renderer exists leaves the choice open. (A constructor that fails after resolution has already latched: CNA-BUG-095.)",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::GraphicsRendererSelection::IsLatched() as documented in CNA/GraphicsRendererSelection.hpp",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-215.html",
   "sources": [
    "modules/core/include/CNA/GraphicsRendererSelection.hpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp",
    "modules/core/src/GraphicsRendererSelection.cpp",
    "modules/graphics/tests/CNA/GraphicsRendererFallbackTests.cpp"
   ],
   "related": [
    "development/internals/graphics/selection.html",
    "development/internals/modules/core.html",
    "docs/runtime-renderer-selection.html"
   ]
  },
  {
   "id": "CNA-BUG-216",
   "class": "bug",
   "title": "MathTypeConverter::supportStringConvert's comment names three converters that clear it; six do",
   "summary": "The Doxygen comment says only the BoundingBox, BoundingSphere and Ray converters clear supportStringConvert and that the matrix and rectangle converters leave it set; the Rectangle, Matrix, BoundingBox, BoundingSphere, Plane and Ray converters all clear it.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The protected field Microsoft::Xna::Framework::Design::MathTypeConverter::supportStringConvert as documented in MathTypeConverter.hpp",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-216.html",
   "sources": [
    "modules/design/include/Microsoft/Xna/Framework/Design/MathTypeConverter.hpp",
    "modules/design/src/Converters.cpp",
    "modules/design/tests/Microsoft/Xna/Framework/Design/FrameworkDesignTests.cpp",
    "docs/framework-design.md"
   ],
   "related": [
    "development/internals/modules/design.html",
    "docs/design-converters.html"
   ]
  },
  {
   "id": "CNA-BUG-217",
   "class": "bug",
   "title": "docs/framework-design.md says the Framework.Design registration associates the twelve value types with ordered descriptor collections; registerConverter registers only converter factories",
   "summary": "registerConverter registers only a TypeConverterAttribute for each of the twelve math types, while CNA's design note says the registration associates the types with converter factories and ordered descriptor collections. The ordered descriptors exist only inside each converter, so the sentence overstates what the registration does.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The registration described in docs/framework-design.md, and System::ComponentModel::TypeDescriptor::GetProperties for the XNA math value types",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-217.html",
   "sources": [
    "modules/design/src/Registration.cpp",
    "docs/framework-design.md",
    "modules/design/include/CNA/Internal/Design/Registration.hpp",
    "modules/design/tests/Microsoft/Xna/Framework/Design/FrameworkDesignTests.cpp"
   ],
   "related": [
    "development/internals/modules/design.html",
    "docs/design-converters.html"
   ]
  },
  {
   "id": "CNA-BUG-218",
   "class": "bug",
   "title": "content_readers.h documentation names cna_get_last_error_message, which does not exist",
   "summary": "The Doxygen of cna_object_dictionary_ext_copy_value tells callers to read 'the message cna_get_last_error_message returns', a function declared nowhere; the C API's error accessors are the cna_error_* functions in core.h.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "cna_object_dictionary_ext_copy_value documentation in CNA/C/content_readers.h",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-218.html",
   "sources": [
    "modules/c-api/include/CNA/C/content_readers.h",
    "modules/c-api/include/CNA/C/core.h"
   ],
   "related": [
    "development/debugging.html",
    "development/internals/bindings/c-api-internals.html",
    "docs/c-api.html"
   ]
  },
  {
   "id": "CNA-BUG-220",
   "class": "bug",
   "title": "cna_game_destroy's comment says Shutdown has disposed the canonical graphics device; it has not",
   "summary": "A comment in cna_game_destroy claims CGame::Shutdown already disposed the game's canonical GraphicsDevice so C subscribers saw its Disposing event, but Game::Dispose(true) never disposes the Game-owned device.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "cna_game_destroy teardown order (maintainer documentation in CnaCApiRuntime.cpp)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-220.html",
   "sources": [
    "modules/c-api/src/CnaCApiRuntime.cpp",
    "modules/c-api/src/CnaCApiRuntimeDetail.hpp",
    "modules/runtime/src/Game.cpp",
    "modules/runtime/src/GraphicsDeviceManager.cpp",
    "modules/c-api/include/CNA/C/graphics_device.h"
   ],
   "related": [
    "development/internals/bindings/c-api-internals.html",
    "development/internals/runtime/shutdown.html",
    "development/takeover/ownership.html",
    "docs/c-api.html"
   ]
  },
  {
   "id": "CNA-BUG-221",
   "class": "bug",
   "title": "RunContentCompiler documentation says XNB output writers are registered only for --format xnb; they are registered on every run",
   "summary": "ContentCompiler.hpp ties the coordinator's XNB writer registration to '--format xnb', but tools/content/content.cpp registers them unconditionally before freezing the registry.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Content::Pipeline::RunContentCompiler (both overloads: pre-built registry and registry factory)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-221.html",
   "sources": [
    "modules/content/include/CNA/Content/Pipeline/ContentCompiler.hpp",
    "tools/content/content.cpp",
    "modules/content/src/Pipeline/ContentPipeline.cpp"
   ],
   "related": [
    "development/internals/content/pipeline.html",
    "docs/content-pipeline.html"
   ]
  },
  {
   "id": "CNA-BUG-222",
   "class": "bug",
   "title": "Audio comments describe behaviour the code does not have: SoundEffect::Play's instance limit, FireAndForgetPanState freeing, the is3D_ latch and SoundEffectReader's WAV route",
   "summary": "SoundEffect.hpp promises that Play returns false at an instance limit CNA does not implement, and three internal comments in the audio and content modules contradict the code next to them.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "SoundEffect::Play() and SoundEffect::Play(float, float, float) documentation; maintainer comments in SoundEffect.cpp, SoundEffectInstance.hpp and SoundEffectContentTypeReader.hpp",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-222.html",
   "sources": [
    "modules/audio/include/Microsoft/Xna/Framework/Audio/SoundEffect.hpp",
    "modules/audio/src/Xna/SoundEffect.cpp",
    "modules/audio/include/Microsoft/Xna/Framework/Audio/SoundEffectInstance.hpp",
    "modules/audio/src/Xna/SoundEffectInstance.cpp",
    "modules/content/include/CNA/Internal/Xnb/SoundEffectContentTypeReader.hpp",
    "modules/content/src/Xnb/SoundEffectContentTypeReader.cpp"
   ],
   "related": [
    "deep-dives/services/sound-effects-and-streaming.html",
    "development/internals/audio/engine.html",
    "docs/audio.html"
   ]
  },
  {
   "id": "CNA-BUG-223",
   "class": "bug",
   "title": "docs/input-backend.md names a SdlInputBridge ProcessEvent overload and src/Input/... paths that do not exist at TARGET",
   "summary": "docs/input-backend.md describes a raw SdlInputBridge::ProcessEvent overload that the SDL-shaped test-double retirement (PLAT-90) removed, and cites src/Input/Internal/ and src/Input/Xna/ paths; the input sources live under modules/input/src. (The comments naming a nonexistent Game::UpdateInput() in the SDL3 and X11 platforms are published separately as CNA-BUG-237.)",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "Maintainer documentation of the input pump: the EnsureControllerSubsystem comments in the SDL3 and X11 platforms, and docs/input-backend.md",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-223.html",
   "sources": [
    "modules/platform/src/Sdl3/Sdl3Platform.cpp",
    "modules/platform/src/X11/X11Platform.cpp",
    "modules/runtime/src/Game.cpp",
    "docs/input-backend.md",
    "modules/input/include/CNA/Internal/Input/SdlInputBridge.hpp",
    "modules/input/include/CNA/Internal/Input/PlatformInputBridge.hpp"
   ],
   "related": [
    "development/internals/input/events.html",
    "development/internals/runtime/frame.html"
   ]
  },
  {
   "id": "CNA-BUG-224",
   "class": "bug",
   "title": "GraphicsDevice's DeviceLost documentation and device-status comments still say only Direct3D 9 reports device loss",
   "summary": "The DeviceLost Doxygen says the event is never raised on desktop, and three maintainer comments say only Direct3D 9 calls the device-event callback, while five renderer families raise DeviceLost from their real error paths at TARGET; a sixth, WebGPU, raises it only from its debug hooks.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice::DeviceLost and GraphicsDevice::getGraphicsDeviceStatusProperty() documentation",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-224.html",
   "sources": [
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/GraphicsDevice.hpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp",
    "modules/renderers/vulkan/src/VulkanRenderer.cpp",
    "modules/renderers/directx11/src/DirectX11Renderer.cpp",
    "modules/renderers/directx12/src/DirectX12Renderer.cpp",
    "modules/renderers/direct2d/src/Direct2DRenderer.cpp",
    "modules/renderers/webgpu/src/WebGPURenderer.cpp"
   ],
   "related": [
    "development/architecture/graphics.html",
    "development/internals/graphics/device.html",
    "docs/rendering-backends.html"
   ]
  },
  {
   "id": "CNA-BUG-225",
   "class": "bug",
   "title": "Two EasyGL comments still describe runtime GL profiles (phase P11) as future work",
   "summary": "EasyGLRendererDescriptor.cpp's file header and the CNA_RENDERER_SHARED_EASYGL comment in RendererCombinations.cmake say a runtime GL profile is still to come, although both files implement or record it.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Maintainer comments in EasyGLRendererDescriptor.cpp and cmake/RendererCombinations.cmake (EasyGL identities sharing one binary)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-225.html",
   "sources": [
    "modules/renderers/easygl/src/EasyGLRendererDescriptor.cpp",
    "cmake/RendererCombinations.cmake",
    "scripts/check_renderer_combinations.py",
    "docs/runtime-renderer-selection.md"
   ],
   "related": [
    "development/internals/graphics/easygl.html",
    "development/internals/graphics/selection.html",
    "docs/rendering-backends.html"
   ]
  },
  {
   "id": "CNA-BUG-227",
   "class": "bug",
   "title": "StubTextureRenderer's comment says GetData() is accepted and discarded, but the inherited default refuses the read",
   "summary": "The class comment on StubTextureRenderer says SetData()/GetData() are accepted no-op defaults, while the ITextureRenderer::GetData default it inherits returns false, which the shared Texture2D layer turns into NotSupportedException.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Maintainer comment on CNA::Internal::Renderers::Stub::StubTextureRenderer",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-227.html",
   "sources": [
    "modules/renderers/stub/include/CNA/Internal/Renderers/Stub/StubRenderer.hpp",
    "modules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp",
    "modules/graphics/src/Xna/Texture2D.cpp"
   ],
   "related": [
    "development/internals/graphics/resources.html",
    "development/internals/graphics/stub.html"
   ]
  },
  {
   "id": "CNA-BUG-228",
   "class": "bug",
   "title": "xnb.md still says 'Status: planning document only. Nothing described here is implemented yet.' directly beneath a banner that records the XNB reader phases complete",
   "summary": "The root design document for CNA's .xnb reader records the reader MVP, LZX and the SpriteFont/effect/audio readers as done, then states that nothing it describes is implemented; its banner also calls the Model phase unstarted although a Model reader ships.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "xnb.md (repository root), the design and status document of the ContentManager / ContentTypeReaderManager .xnb reader",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-228.html",
   "sources": [
    "xnb.md",
    "modules/content/src/Xnb/XnbBuiltInReaders.cpp",
    "modules/content/tests/CNA/Internal/Xnb/XnbBuiltInReaderRegistrationTests.cpp"
   ],
   "related": [
    "development/internals/content/runtime.html",
    "docs/content-pipeline-xnb.html"
   ]
  },
  {
   "id": "CNA-BUG-229",
   "class": "bug",
   "title": "docs/graphics-renderer-feature-matrix.md calls itself up to date but still says EasyGL's ReferenceStencil gap (Task 872) is open and lists its test as a known failure, contradicting its own table row",
   "summary": "The matrix's ReferenceStencil row says EasyGL passes (remeasured 2026-09-09), but its failure baseline and Vulkan bottom line still call the gap open, although REMED-GFX-236 fixed EasyGL on 2026-08-29.",
   "subsystem": "Documentation & release tooling",
   "status": "narrowed",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "docs/graphics-renderer-feature-matrix.md ('Master, up-to-date cross-renderer feature matrix') and the documented status of GraphicsDevice::setReferenceStencilProperty on the EasyGL family",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-229.html",
   "sources": [
    "docs/graphics-renderer-feature-matrix.md",
    "modules/renderers/easygl/src/EasyGLRenderer.cpp",
    "modules/renderers/easygl/examples/easygl_graphicsdevice_reference_stencil_test.cpp",
    "modules/renderers/easygl/examples/CMakeLists.txt",
    "plans/plan_graphics.md",
    "plans/plan_postaudit.md"
   ],
   "related": [
    "deep-dives/renderers/vulkan-deferred-state-and-descriptors.html",
    "development/internals/graphics/easygl.html",
    "docs/graphics-state.html"
   ]
  },
  {
   "id": "CNA-BUG-230",
   "class": "bug",
   "title": "cna_define_shared_runtime_deferred's comment says cna_graphics_ext and cna_devices_ext exist only with CNA_CNAEXT; modules/CMakeLists.txt always creates both",
   "summary": "The shared-library composition keeps an if(TARGET) filter justified by a comment that the extension targets are optional, but both are defined unconditionally, so the comment misstates the module model.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "cmake/SharedRuntimeLibrary.cmake cna_define_shared_runtime_deferred (composition of libcna.so under CNA_SHARED_LIBRARY)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-230.html",
   "sources": [
    "cmake/SharedRuntimeLibrary.cmake",
    "modules/CMakeLists.txt",
    "modules/graphics-ext/CMakeLists.txt",
    "modules/devices-ext/CMakeLists.txt"
   ],
   "related": [
    "development/build/architecture.html",
    "development/repository/module-graph.html"
   ]
  },
  {
   "id": "CNA-BUG-231",
   "class": "bug",
   "title": "CHECKLIST.md's per-file port checklist still says 'FNA still wins on semantics', contradicting the rule in CLAUDE.md that XNA wins where the two disagree",
   "summary": "The checklist every ported file is reviewed against keeps the old tie-break, while CNA's contributor rules record the owner decision of 2026-09-04 that measured XNA behaviour wins over FNA's.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "CHECKLIST.md (per-file port checklist, XNA 4.0 API compliance section) and the behaviour-authority rule in CLAUDE.md",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-231.html",
   "sources": [
    "CHECKLIST.md",
    "CLAUDE.md"
   ],
   "related": [
    "deep-dives/foundations/cna-and-xna.html",
    "development/handbook/conventions.html"
   ]
  },
  {
   "id": "CNA-BUG-232",
   "class": "bug",
   "title": "docs/physical-modules.md has no row for modules/platform, omits the platform and diagnostics edges of runtime, input, audio and devices-ext, and says top-level examples/ holds only examples/golden",
   "summary": "CNA's physical-module map, which check_renderer_identities.py keeps under count control, never mentions the platform module that input, runtime, audio and devices-ext link, and misdescribes the top-level examples directory.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "docs/physical-modules.md, the Framework modules table (direct CNA dependencies and Sharp Runtime components per module) and its description of the repository layout",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-232.html",
   "sources": [
    "docs/physical-modules.md",
    "modules/CMakeLists.txt",
    "modules/runtime/CMakeLists.txt",
    "modules/input/CMakeLists.txt",
    "modules/audio/CMakeLists.txt",
    "modules/devices-ext/CMakeLists.txt",
    "examples/xvfb_screenshot_demo.cpp"
   ],
   "related": [
    "development/handbook/conventions.html",
    "development/repository/index.html",
    "development/repository/module-graph.html"
   ]
  },
  {
   "id": "CNA-BUG-233",
   "class": "bug",
   "title": "CLAUDE.md's Platform Boundary lists WIN32 as a reserved identifier that fails configuration, but cmake/PlatformSelection.cmake implements CNA_PLATFORM=WIN32 on Windows",
   "summary": "CNA's contributor instructions name SDL3, SDL2, X11, WAYLAND, HEADLESS and TERMINAL as the platforms and SDL12/WIN32/EMSCRIPTEN as reserved; the build offers WIN32 on Windows and reserves TERMINAL there.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "CNA_PLATFORM values as documented in CLAUDE.md (Platform Boundary) versus cmake/PlatformSelection.cmake",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-233.html",
   "sources": [
    "CLAUDE.md",
    "cmake/PlatformSelection.cmake"
   ],
   "related": [
    "development/build/index.html",
    "development/internals/platforms/win32.html",
    "docs/native-platforms.html"
   ]
  },
  {
   "id": "CNA-BUG-234",
   "class": "bug",
   "title": "CLAUDE.md's 'WebGPU Is Active' section still gives the current WEBGPU baseline as clear/present, Texture2D, buffer uploads and SpriteBatch, contradicting its own renderer paragraph, which describes a real 3D route with render targets",
   "summary": "The renderer paragraph and the 'WebGPU Is Active' section of CNA's CLAUDE.md disagree about what WEBGPU implements. The section's 'current baseline' list and its 'remaining shader, state, effect, render-target ... tasks' clause date from the 2026-07-12 activation; the paragraph was refreshed on 2026-08-26, AGENTS.md's copy of the section already says WebGPU is well past the initial 2D slice, and WebGPURenderer::SupportsCapability reports multiple render targets, occlusion queries, wireframe and multi-stream vertex input. The section's caution against calling WebGPU Vulkan-level or full XNA 3D parity is not itself contradicted.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "WEBGPU renderer status as described in CLAUDE.md",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-234.html",
   "sources": [
    "CLAUDE.md",
    "modules/renderers/webgpu/src/WebGPURenderer.cpp",
    "docs/webgpu-renderer.md"
   ],
   "related": [
    "deep-dives/renderers/webgpu-renderer-semantics.html",
    "docs/rendering-backends.html"
   ]
  },
  {
   "id": "CNA-BUG-235",
   "class": "bug",
   "title": "docs/physical-modules.md's Sharp Runtime column omits components that four modules link: Uri for phone and media, Collections.Core for input, Resources for content",
   "summary": "CNA's module table gives phone Core.Base and Collections.Core, input Core.Base, and media and content Core.Base and IO, while the modules' CMake files link Uri (phone, media), Collections.Core (input) and Resources (content, plus Security.Cryptography privately).",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "docs/physical-modules.md module table, Sharp Runtime column (rows modules/phone, input, media and content)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-235.html",
   "sources": [
    "docs/physical-modules.md",
    "modules/phone/CMakeLists.txt",
    "modules/input/CMakeLists.txt",
    "modules/media/CMakeLists.txt",
    "modules/content/CMakeLists.txt"
   ],
   "related": [
    "development/internals/modules/phone.html",
    "development/reference/modules.html"
   ]
  },
  {
   "id": "CNA-BUG-236",
   "class": "bug",
   "title": "docs/platform-abstraction.md's Implementations table lists five backends and omits X11 and Wayland",
   "summary": "CNA's platform-abstraction document lists SDL3, SDL2, WIN32, HEADLESS and TERMINAL in its Implementations table, but PlatformSelection.cmake offers seven implementations, adding the native X11 and WAYLAND backends.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "docs/platform-abstraction.md, the Implementations table",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-236.html",
   "sources": [
    "docs/platform-abstraction.md",
    "cmake/PlatformSelection.cmake"
   ],
   "related": [
    "development/architecture/platform.html",
    "development/internals/platforms/index.html",
    "docs/native-platforms.html"
   ]
  },
  {
   "id": "CNA-BUG-237",
   "class": "bug",
   "title": "Comments in Sdl3Platform.cpp and X11Platform.cpp refer to a Game::UpdateInput() that does not exist",
   "summary": "Both native backends explain their lazy controller-subsystem start by saying Game::UpdateInput() pumps the input services only once the subsystem is initialised, but Game has no UpdateInput(); the per-frame controller pump lives in Game::PollEvents.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Source comments in CNA::Platform::Sdl3::Sdl3Platform::EnsureControllerSubsystem and CNA::Platform::X11::X11Platform::EnsureControllerSubsystem",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-237.html",
   "sources": [
    "modules/platform/src/Sdl3/Sdl3Platform.cpp",
    "modules/platform/src/X11/X11Platform.cpp",
    "modules/runtime/src/Game.cpp"
   ],
   "related": [
    "development/handbook/modify-a-platform-backend.html",
    "development/internals/platforms/sdl3.html",
    "development/internals/platforms/x11.html",
    "docs/input.html"
   ]
  },
  {
   "id": "CNA-BUG-238",
   "class": "bug",
   "title": "Win32Window's CnaPlatformWindow.Owned property is written and removed but never read, and its comment misdescribes AdoptWindowHandle",
   "summary": "The kOwnedWindowProperty is set on every CNA-created HWND and removed on destroy but read nowhere; its comment says it lets AdoptWindowHandle refuse an owned window, whereas adoption returns a borrowed wrapper sharing the owner's id.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The CnaPlatformWindow.Owned window property and its documentation in CNA::Platform::Win32::Win32Window",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-238.html",
   "sources": [
    "modules/platform/src/Win32/Win32Window.cpp",
    "modules/platform/src/Win32/Win32Platform.cpp",
    "modules/platform/tests/CNA/Platform/Win32WindowTests.cpp"
   ],
   "related": [
    "development/handbook/modify-a-platform-backend.html",
    "development/internals/platforms/win32.html",
    "docs/native-platforms.html"
   ]
  },
  {
   "id": "CNA-BUG-239",
   "class": "bug",
   "title": "Two stale comments in the Win32 backend: a nonexistent spike path and a wrong Windows version",
   "summary": "Win32DirectXIntegrationTests.cpp says real device and swapchain creation on the platform's handle is proved by spikes/win32-directx-spike/, a directory that has never existed (spikes/win32-spike covers window, message pump, DPI and QPC only, not a graphics device), and Win32Common.hpp's comment says it targets Windows 10 1703 while it defines _WIN32_WINNT and WINVER as 0x0603, which is Windows 8.1.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Source comments in modules/platform/tests/CNA/Platform/Win32DirectXIntegrationTests.cpp and modules/platform/src/Win32/Win32Common.hpp",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-239.html",
   "sources": [
    "modules/platform/tests/CNA/Platform/Win32DirectXIntegrationTests.cpp",
    "modules/platform/src/Win32/Win32Common.hpp"
   ],
   "related": [
    "development/handbook/modify-a-platform-backend.html",
    "development/internals/platforms/win32.html",
    "docs/native-platforms.html"
   ]
  },
  {
   "id": "CNA-BUG-240",
   "class": "bug",
   "title": "X11 header comments misdescribe the connection lifetime, the service accessors and the Xlib locking",
   "summary": "X11Connection's comment says the connection opens on the first Video acquisition, but the platform opens it in its constructor; the accessor comments call services null before Video and AcquireSubsystem a thrower of PlatformNotSupportedException, neither of which holds; and the X11Platform class comment says every Xlib call goes through one per-instance mutex, when the backend's only mutex is the process-wide X error-policy mutex.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Class and accessor documentation in CNA::Platform::X11::X11Platform and X11Connection (X11Platform.hpp, X11Display.hpp)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-240.html",
   "sources": [
    "modules/platform/src/X11/X11Display.hpp",
    "modules/platform/src/X11/X11Platform.hpp",
    "modules/platform/src/X11/X11Platform.cpp",
    "modules/platform/src/X11/X11Error.cpp"
   ],
   "related": [
    "development/handbook/modify-a-platform-backend.html",
    "development/internals/platforms/x11.html",
    "docs/native-platforms.html"
   ]
  },
  {
   "id": "CNA-BUG-241",
   "class": "bug",
   "title": "docs/devices-event-contract.md and docs/devices-thread-safety.md describe sensor behaviour the code no longer has",
   "summary": "The event contract says the Android bridge swallows handler exceptions silently, and the thread-safety document misnames the counter guard for two sensors and calls same-instance Start/Dispose safe while its known-gap section says otherwise.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "docs/devices-event-contract.md section 6 (exception semantics) and docs/devices-thread-safety.md (per-class guarantees and the known gap)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-241.html",
   "sources": [
    "docs/devices-event-contract.md",
    "docs/devices-thread-safety.md",
    "modules/devices/src/Sensors/Detail/AndroidSensorBridge.cpp",
    "modules/devices/tests/Microsoft/Devices/Sensors/Detail/NativeDiagnosticTests.cpp",
    "modules/devices/src/Sensors/Accelerometer.cpp",
    "modules/devices/src/Sensors/Compass.cpp"
   ],
   "related": [
    "deep-dives/services/sensors-and-vibration.html",
    "development/internals/modules/devices.html",
    "development/takeover/threading.html"
   ]
  },
  {
   "id": "CNA-BUG-242",
   "class": "bug",
   "title": "Source comments still say StorageDevice reaches the platform or the SDL preference path",
   "summary": "IPlatformFileSystem::GetPreferencesPath is documented as backing StorageDevice and several comments cite storage as a reason for the ambient platform, but storage has no platform dependency and GetPreferencesPath has no production caller.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Doxygen of CNA::Platform::IPlatformFileSystem::GetPreferencesPath, CNA::Platform::GetCurrentPlatform, Game::GetPlatformEXT, the X11 and Wayland platform constructors, and the CApi_StorageSmoke registration comment",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-242.html",
   "sources": [
    "modules/platform/include/CNA/Platform/IPlatformSystemServices.hpp",
    "modules/platform/include/CNA/Platform/CurrentPlatform.hpp",
    "modules/runtime/include/Microsoft/Xna/Framework/Game.hpp",
    "modules/platform/src/X11/X11Platform.hpp",
    "modules/platform/src/Wayland/WaylandPlatform.hpp",
    "modules/c-api/CMakeLists.txt",
    "modules/storage/CMakeLists.txt",
    "modules/storage/src/StorageDevice.cpp"
   ],
   "related": [
    "development/internals/modules/storage.html",
    "development/internals/platforms/index.html"
   ]
  },
  {
   "id": "CNA-BUG-243",
   "class": "bug",
   "title": "docs/gltf-limitations.md says CNA reverses the winding of mirrored glTF placements; the importer leaves it unchanged",
   "summary": "The limitations table's mirrored-transform row says 'CNA reverses it and marks the placement', while ContentManager.cpp, the import report (mirrored-winding-unapplied) and GltfMirroringTests.cpp all establish that the winding is not reversed.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "docs/gltf-limitations.md (section 2, the 'A mirrored node transform' row)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-243.html",
   "sources": [
    "docs/gltf-limitations.md",
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/src/GltfImport/GltfImportCore.cpp",
    "modules/content/tests/CNA/Internal/GltfImport/GltfMirroringTests.cpp"
   ],
   "related": [
    "deep-dives/models/vertex-packing-and-strides.html"
   ]
  },
  {
   "id": "CNA-BUG-244",
   "class": "bug",
   "title": "README.md's Usage Example does not compile (nonexistent Graphics/GraphicsDeviceManager.hpp include, unqualified CornflowerBlue) and presents every frame twice",
   "summary": "The README's game skeleton includes a nonexistent header path, writes CornflowerBlue without Color::, and calls device.Present() in Draw although EndDraw() already presents, so the copied program fails to compile and, once repaired, presents twice per frame.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "medium",
   "confidence": "reproduced",
   "tests_present": true,
   "public_contract": "README.md section 10 (Usage Example): the minimal Game skeleton; Microsoft/Xna/Framework/GraphicsDeviceManager.hpp, Color::CornflowerBlue and the Game::Draw / EndDraw presentation contract",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-244.html",
   "sources": [
    "README.md",
    "modules/runtime/include/Microsoft/Xna/Framework/GraphicsDeviceManager.hpp",
    "modules/math/include/Microsoft/Xna/Framework/Color.hpp",
    "modules/runtime/src/GraphicsDeviceManager.cpp",
    "modules/runtime/src/Game.cpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp",
    "modules/renderers/stub/examples/stub_smoke_test.cpp"
   ],
   "related": [
    "deep-dives/foundations/compatibility-and-evidence.html",
    "deep-dives/framework/first-game-walkthrough.html",
    "development/internals/runtime/frame.html",
    "docs/game-loop.html",
    "docs/getting-started.html"
   ]
  },
  {
   "id": "CNA-BUG-245",
   "class": "bug",
   "title": "misc/cnj.md and xnb.md say the content manifest services ResolveAssetPath's existence checks; ContentManager still probes the live filesystem on every Load",
   "summary": "CNA's CNJ and XNB design notes describe the startup content-manifest scan as the cache that replaces ResolveAssetPath's std::filesystem::exists calls, but at TARGET the manifest is an introspection snapshot that Load<T> never consults.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager::Load<T> / ResolveAssetPath resolution and ContentManager::GetContentManifest / RefreshContentManifest, as described by misc/cnj.md and xnb.md",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-245.html",
   "sources": [
    "misc/cnj.md",
    "xnb.md",
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentManager.hpp",
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/tests/Microsoft/Xna/Framework/Content/ContentManagerManifestTests.cpp"
   ],
   "related": [
    "deep-dives/content/contentmanager-resolution-rules.html",
    "development/internals/content/runtime.html",
    "docs/content-manager.html"
   ]
  },
  {
   "id": "CNA-BUG-246",
   "class": "bug",
   "title": "docs/graphics-resource-lifetime.md says existing XNA resources hold a unique_ptr renderer and names a non-existent ITexture2DRenderer; Texture2D, Texture3D and TextureCube hold shared_ptr renderers and Texture2D's public copies share one",
   "summary": "The document's Ownership Model gives unique_ptr renderer ownership for existing XNA resources, a list its scope sentence extends to Texture2D and RenderTarget2D, and knows only one kind of sharing: an internal record on non-copyable modern resources. Texture2D, Texture3D and TextureCube hold shared_ptr renderers, and Texture2D's public defaulted copies share the renderer and CPU shadow.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "docs/graphics-resource-lifetime.md section 1 (Ownership Model) against Microsoft::Xna::Framework::Graphics::Texture2D (copy constructor, copy assignment, GetRendererWeak, GetCpuPixelsWeak), Texture3D and TextureCube",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-246.html",
   "sources": [
    "docs/graphics-resource-lifetime.md",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/Texture2D.hpp",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/Texture3D.hpp",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/TextureCube.hpp",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/VertexBuffer.hpp",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/IndexBuffer.hpp",
    "modules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp"
   ],
   "related": [
    "deep-dives/graphics/texture-data-transfer.html",
    "development/internals/graphics/resources.html",
    "docs/3d-rendering.html"
   ]
  },
  {
   "id": "CNA-BUG-247",
   "class": "bug",
   "title": "The EasyGL L7 policy and report justify zero tolerance with 'all 137 renderable assets' while the report's own fields record 140 captured, byte-identical assets",
   "summary": "The EasyGL L7 policy's justification, copied into its report, cites 137 renderable assets while the report records 148 assets, 140 byte-identical captures and 8 rejections, and misc/FUTURE.md repeats 137 plus 8.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "tests/gltf-l7/easygl-policy.json and docs/gltf-l7-corpus-report.json goldenComparison.justification (the OPENGLES3/EasyGL L7 tolerance rationale); misc/FUTURE.md Phase 5 row",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-247.html",
   "sources": [
    "tests/gltf-l7/easygl-policy.json",
    "docs/gltf-l7-corpus-report.json",
    "scripts/gltf-l7-corpus.py",
    "docs/gltf-conformance.md",
    "misc/FUTURE.md",
    "tests/gltf-l7/software-policy.json"
   ],
   "related": [
    "deep-dives/models/gltf-conformance.html",
    "development/testing/architecture.html",
    "docs/verification.html"
   ]
  },
  {
   "id": "CNA-BUG-248",
   "class": "bug",
   "title": "PacketReader::ReadColor and PacketWriter::Write(Color) doc comments still say ReadColor reads four floats and is not the inverse of Write(Color)",
   "summary": "Since c4561fd2b ReadColor reads the four bytes Write(Color) writes and a test asserts the round trip, but both public header comments and a test-file comment still describe a four-float asymmetry preserved from 'upstream', which XNA 4.0 itself does not have.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Net::PacketReader::ReadColor() and PacketWriter::Write(Color) Doxygen",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-248.html",
   "sources": [
    "modules/net/include/Microsoft/Xna/Framework/Net/PacketReader.hpp",
    "modules/net/include/Microsoft/Xna/Framework/Net/PacketWriter.hpp",
    "modules/net/src/Xna/PacketReader.cpp",
    "modules/net/tests/Microsoft/Xna/Framework/Net/PacketReaderWriterTests.cpp"
   ],
   "related": [
    "deep-dives/services/network-sessions.html",
    "development/internals/modules/net.html",
    "docs/tutorials/97-networking.html"
   ]
  },
  {
   "id": "CNA-BUG-249",
   "class": "bug",
   "title": "misc/CNAEXT.md's 'Renderer shader coverage for PBR' table omits OPENGL4 and METAL and still says WebGPU has no SkinnedPbrEffect path",
   "summary": "The table lists six rows covering seven renderers (EasyGL, Vulkan, SdlGpu, WebGPU, D3D11, D3D9/D3D12) plus a fallback row, but OPENGL4 and METAL implement both PBR effects, WebGPU implements skinned PBR, and FNA3D and PORTABLEGL refuse PBR draws by name; the table shows none of this.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "misc/CNAEXT.md section 3.1, 'Renderer shader coverage for PBR' (PbrEffect / SkinnedPbrEffect per renderer)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-249.html",
   "sources": [
    "misc/CNAEXT.md",
    "modules/renderers/opengl4/src/OpenGL4StockDraw.cpp",
    "modules/renderers/metal/src/MetalRenderer.mm",
    "modules/renderers/webgpu/src/WebGPURenderer.cpp",
    "modules/renderers/webgpu/src/WebGPURendererModern.cpp",
    "modules/renderers/fna3d/src/Fna3dDraw.cpp",
    "modules/renderers/portablegl/src/PortableGLRenderer.cpp",
    "misc/FUTURE.md"
   ],
   "related": [
    "deep-dives/graphics/effect-object-model.html",
    "development/internals/graphics/backends.html",
    "docs/effects.html",
    "docs/tutorials/114-pbr-materials.html"
   ]
  },
  {
   "id": "CNA-BUG-250",
   "class": "bug",
   "title": "LocalNetworkGamer::SendData in a Local or LocalWithLeaderboards session silently drops every packet, so neither the sender nor another local gamer ever receives it",
   "summary": "NetworkSession::Update raises PacketSend events only when real networking is enabled (SystemLink), so SendData in a Local or LocalWithLeaderboards session reports success and delivers nothing, although SendData is documented to reach every gamer in the session, the sender included.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Net::LocalNetworkGamer::SendData, ReceiveData and getIsDataAvailableProperty in a NetworkSession of type Local or LocalWithLeaderboards",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-250.html",
   "sources": [
    "modules/net/src/Xna/NetworkSession.cpp",
    "modules/net/src/Internal/ENetBackend.cpp",
    "modules/net/src/Xna/LocalNetworkGamer.cpp",
    "modules/net/tests/Microsoft/Xna/Framework/Net/LocalNetworkGamerTests.cpp",
    "modules/net/tests/CNA/Internal/Net/NetworkSessionTypePolicyTests.cpp",
    "misc/known_gaps.md"
   ],
   "related": [
    "deep-dives/services/network-sessions.html",
    "development/internals/modules/net.html",
    "docs/tutorials/97-networking.html"
   ]
  },
  {
   "id": "CNA-BUG-251",
   "class": "bug",
   "title": "BoundingSphere(Vector3 center, float radius) accepts a negative radius, where XNA 4.0 throws ArgumentException",
   "summary": "CNA's BoundingSphere(Vector3, float) constructor stores any radius, while XNA 4.0's throws ArgumentException for radius < 0, so a negative radius is silently accepted.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::BoundingSphere::BoundingSphere(Vector3 center, float radius) (Microsoft::Xna::Framework::BoundingSphere)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-251.html",
   "sources": [
    "modules/math/src/BoundingSphere.cpp",
    "modules/math/include/Microsoft/Xna/Framework/BoundingSphere.hpp",
    "modules/math/tests/Microsoft/Xna/Framework/BoundingSphereTests.cpp"
   ],
   "related": [
    "deep-dives/framework/bounding-volumes-and-intersections.html",
    "development/internals/modules/math.html",
    "docs/math-types.html"
   ]
  },
  {
   "id": "CNA-BUG-252",
   "class": "bug",
   "title": "Vector3, Vector4, Quaternion and Matrix GetHashCode add raw int bit patterns with signed arithmetic, which overflows (undefined behaviour) for ordinary values",
   "summary": "The four GetHashCode functions sum FloatHash results as int with plain +; three 1.0f components already exceed INT_MAX, so the sum is signed-overflow undefined behaviour, while Vector2::GetHashCode already sums as unsigned to avoid it.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "low",
   "confidence": "recorded-by-cna",
   "tests_present": true,
   "public_contract": "CNA::Vector3::GetHashCode, Vector4::GetHashCode, Quaternion::GetHashCode and Matrix::GetHashCode (Microsoft::Xna::Framework)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-252.html",
   "sources": [
    "modules/math/src/Vector3.cpp",
    "modules/math/src/Vector4.cpp",
    "modules/math/src/Quaternion.cpp",
    "modules/math/src/Matrix.cpp",
    "modules/math/src/Vector2.cpp"
   ],
   "related": [
    "deep-dives/framework/math-value-types-and-layout.html",
    "deep-dives/reference/verification-tiers.html",
    "development/internals/modules/math.html",
    "docs/math-types.html"
   ]
  },
  {
   "id": "CNA-BUG-253",
   "class": "bug",
   "title": "SdlGpu_ConstructorExceptionSafety aborts with a double free, a defect CNA's own record calls real and leaves unfixed",
   "summary": "CNA's own record says the classic SDL_GPU constructor-failure test aborts with 'free(): double free detected in tcache 2', identically on the unmodified sources, and calls it a real bug to fix later; CNA-BUG-099 quotes the same record inside its cluster of 24 failing classic tests, and this entry isolates the double free as its own defect.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "medium",
   "confidence": "recorded-by-cna",
   "tests_present": true,
   "public_contract": "CNA::Internal::Renderers::SdlGpu::SdlGpuRenderer construction, under the transactional-construction contract REMED-GFX-028 states for it",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-253.html",
   "sources": [
    "modules/renderers/sdl-gpu/examples/CMakeLists.txt",
    "modules/renderers/sdl-gpu/examples/sdlgpu_constructor_exception_safety_test.cpp",
    "plans/plan_sdlgpu_modern_graphics.md"
   ],
   "related": [
    "development/handbook/fix-a-renderer-bug.html",
    "development/internals/graphics/sdl-gpu.html",
    "docs/verification.html"
   ]
  },
  {
   "id": "CNA-BUG-254",
   "class": "bug",
   "title": "docs/directx9-renderer.md says the DIRECTX9 custom ShaderEffect phase (D9-11) has not been started; plans/plan_dx9.md records it fully closed on 2026-07-15",
   "summary": "The DIRECTX9 renderer document lists custom ShaderEffect (D9-11) as not started, while the plan it points to records D9-110, D9-111 and D9-112 all closed on 2026-07-15.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "docs/directx9-renderer.md, the gap list of the DIRECTX9 renderer document",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-254.html",
   "sources": [
    "docs/directx9-renderer.md",
    "plans/plan_dx9.md"
   ],
   "related": [
    "deep-dives/renderers/direct3d9-xna-fidelity.html",
    "development/internals/graphics/backends.html",
    "docs/rendering-backends.html"
   ]
  },
  {
   "id": "CNA-BUG-255",
   "class": "bug",
   "title": "EasyGL family: ClearColorAndStencil leaves the stencil write mask forced to all ones, so a later draw ignores StencilWriteMask",
   "summary": "GraphicsDevice::Clear with Target and Stencil reaches EasyGLRenderer::ClearColorAndStencil, which forces the GL stencil mask open and never restores it, unlike the other EasyGL clears (REMED-GFX-237). A later StencilWriteMask-limited draw is not limited.",
   "subsystem": "Graphics & renderers",
   "status": "narrowed",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice::Clear(ClearOptions::Target | ClearOptions::Stencil, ...) on the EasyGL renderer family (EasyGLRenderer::ClearColorAndStencil)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-255.html",
   "sources": [
    "modules/renderers/easygl/src/EasyGLRenderer.cpp",
    "modules/renderers/easygl/include/CNA/Internal/Renderers/EasyGL/EasyGLRenderer.hpp",
    "modules/renderers/opengl4/src/OpenGL4Renderer.cpp",
    "modules/renderers/easygl/examples/easygl_graphicsdevice_clear_stencil_test.cpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp"
   ],
   "related": [
    "deep-dives/renderers/easygl-state-and-resource-semantics.html",
    "development/internals/graphics/easygl.html",
    "docs/graphics-state.html"
   ]
  },
  {
   "id": "CNA-BUG-256",
   "class": "bug",
   "title": "docs/model-content-pipeline-support.md still says CNA has no binary .xnb model reader and lists Model loader gaps that the code has closed",
   "summary": "Below a short update note, the document says no .xnb Model can be loaded and that the .cnj Model loader has one bone, no ParentBone, no BoundingSphere and no tests. ModelReader, the bone hierarchy, parent bones, bounding spheres and CnjModelTests exist.",
   "subsystem": "Documentation & release tooling",
   "status": "narrowed",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "docs/model-content-pipeline-support.md and docs/xna-4-api-coverage.md, the statements about Model loading",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-256.html",
   "sources": [
    "docs/model-content-pipeline-support.md",
    "docs/xna-4-api-coverage.md",
    "docs/xnb-content-pipeline-support.md",
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/src/Xnb/ModelContentTypeReaders.cpp",
    "modules/content/tests/Microsoft/Xna/Framework/Content/CnjModelTests.cpp",
    "modules/content/tests/CNA/Internal/Xnb/ModelContentTypeReaderTests.cpp"
   ],
   "related": [
    "development/internals/content/runtime.html",
    "docs/model-loading.html"
   ]
  },
  {
   "id": "CNA-BUG-257",
   "class": "bug",
   "title": "PORTABLEGL depth clears force glDepthMask(GL_TRUE) and never restore it, although their own comment says both masks are restored as EasyGL does",
   "summary": "ClearColorAndDepth, ClearDepth, ClearDepthAndStencil and ClearColorDepthAndStencil call glDepthMask(GL_TRUE) and never put the depth write mask back; only the colour mask is restored.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice::Clear with a depth option on the PORTABLEGL renderer (PortableGLRenderer::ClearColorAndDepth, ClearDepth, ClearDepthAndStencil, ClearColorDepthAndStencil)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-257.html",
   "sources": [
    "modules/renderers/portablegl/src/PortableGLRenderer.cpp",
    "modules/renderers/easygl/include/CNA/Internal/Renderers/EasyGL/EasyGLRenderer.hpp"
   ],
   "related": [
    "development/internals/graphics/backends.html",
    "docs/graphics-state.html"
   ]
  },
  {
   "id": "CNA-BUG-258",
   "class": "bug",
   "title": "LocalNetworkGamer::ReceiveData(byte buffer, offset) dequeues and silently truncates a packet larger than the buffer, where XNA throws ArgumentException without dequeuing",
   "summary": "The byte-array overload pops the next packet, copies min(packet size, buffer size) bytes and returns the packet's data as if it had fit; XNA peeks first and throws ArgumentException (PacketArrayTooSmall) without consuming the packet.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::LocalNetworkGamer::ReceiveData(std::vector<byte>& data, int offset, NetworkGamer*& sender) and the overload without an offset (Microsoft::Xna::Framework::Net::LocalNetworkGamer)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-258.html",
   "sources": [
    "modules/net/src/Xna/LocalNetworkGamer.cpp"
   ],
   "related": [
    "deep-dives/services/network-sessions.html",
    "development/internals/modules/net.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-BUG-259",
   "class": "bug",
   "title": "Matrix::Decompose follows FNA's algorithm, not XNA 4.0's: a mirrored matrix decomposes to positive scales and a non-unit quaternion, and a sheared matrix reports success",
   "summary": "Matrix::Decompose never checks the determinant: a mirrored matrix returns positive scales, a non-unit quaternion and true where XNA 4.0 negates the largest scale, and a sheared matrix returns true where XNA returns false.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Matrix::Decompose(Vector3& scale, Quaternion& rotation, Vector3& translation)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-259.html",
   "sources": [
    "modules/math/src/Matrix.cpp",
    "modules/math/src/Quaternion.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/MatrixTests.cpp",
    "modules/math/include/Microsoft/Xna/Framework/Matrix.hpp",
    "CLAUDE.md"
   ],
   "related": [
    "development/internals/modules/math.html",
    "docs/math-types.html",
    "docs/tutorials/42-matrix-ops.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-BUG-260",
   "class": "bug",
   "title": "ExitingEventArgs is documented as the data of Game.Exiting but nothing delivers it, and this non-XNA type carries no CNAEXT marker",
   "summary": "The header says ExitingEventArgs provides data for Game.Exiting, yet Game::Exiting is typed with plain EventArgs, nothing constructs the type, and it is not tagged CNAEXT although XNA 4.0 has no such class.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::ExitingEventArgs (ExitingEventArgs.hpp) and Game::Exiting",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-260.html",
   "sources": [
    "modules/runtime/include/Microsoft/Xna/Framework/ExitingEventArgs.hpp",
    "modules/runtime/include/Microsoft/Xna/Framework/Game.hpp",
    "tools/c-api/coverage_mappings.json"
   ],
   "related": [
    "deep-dives/framework/game-class-and-lifecycle.html",
    "docs/game-loop.html"
   ]
  },
  {
   "id": "CNA-BUG-261",
   "class": "bug",
   "title": "Comments and docs say GpuDrawParams::specularEnabled is read by no renderer and DIRECTX9's specular variants are blocked, but D3D9EffectDraw and Fna3dDraw read it",
   "summary": "IGraphicsRenderer.hpp says no renderer reads GpuDrawParams::specularEnabled, and two DirectX9 headers and docs/directx9-renderer.md call the specular and per-pixel-lighting variants unreachable, although DIRECTX9 and FNA3D read the fields.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "GpuDrawParams::specularEnabled and preferPerPixelLighting (IGraphicsRenderer.hpp) and the DIRECTX9 shader-dispatch documentation",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-261.html",
   "sources": [
    "modules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp",
    "modules/renderers/directx9/include/CNA/Internal/Renderers/DirectX9/D3D9ShaderDispatch.hpp",
    "modules/renderers/directx9/include/CNA/Internal/Renderers/DirectX9/DirectX9Renderer.hpp",
    "modules/renderers/directx9/src/D3D9EffectDraw.cpp",
    "modules/renderers/fna3d/src/Fna3dDraw.cpp",
    "docs/directx9-renderer.md"
   ],
   "related": [
    "deep-dives/graphics/stock-effects-semantics.html",
    "development/internals/graphics/backends.html",
    "docs/effects.html"
   ]
  },
  {
   "id": "CNA-BUG-262",
   "class": "bug",
   "title": "CnaTests is linked with both -sJSPI=1 and -sASYNCIFY=1 on Emscripten; emcc lets the later flag win, so the JSPI its CMake comment relies on is silently replaced by Asyncify",
   "summary": "UnitTests.cmake adds -sJSPI=1 to CnaTests, but BuildPerformance.cmake then adds -sASYNCIFY=1 through cna_emscripten_asyncify; emcc keeps the later flag, so CnaTests is Asyncify-linked and the comment's reason (no Asyncify with wasm exceptions) is stale.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "strong",
   "tests_present": false,
   "public_contract": "CnaTests' Emscripten link options (cmake/UnitTests.cmake and cmake/BuildPerformance.cmake)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-262.html",
   "sources": [
    "cmake/UnitTests.cmake",
    "cmake/BuildPerformance.cmake"
   ],
   "related": [
    "deep-dives/platforms/web-build-and-main-loop.html",
    "development/internals/runtime/frame.html"
   ]
  },
  {
   "id": "CNA-BUG-263",
   "class": "bug",
   "title": "TerminalMouse::SetPosition throws PlatformException although IPlatformMouse::SetPosition documents no exception, so XNA's Mouse.SetPosition throws on the terminal platform",
   "summary": "IPlatformMouse::SetPosition documents no exception, but TerminalMouse::SetPosition always throws PlatformException and Mouse::SetPosition calls it unguarded, so the XNA re-centre-the-cursor idiom throws once the terminal platform reports mouse input.",
   "subsystem": "Input",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Input::Mouse::SetPosition(int, int) on the terminal platform (TerminalMouse::SetPosition)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-263.html",
   "sources": [
    "modules/platform/src/Terminal/TerminalMouse.cpp",
    "modules/platform/include/CNA/Platform/Input/IPlatformMouse.hpp",
    "modules/input/src/Xna/Mouse.cpp",
    "modules/platform/tests/CNA/Platform/TerminalMouseTests.cpp"
   ],
   "related": [
    "development/internals/platforms/terminal.html",
    "docs/input.html"
   ]
  },
  {
   "id": "CNA-BUG-264",
   "class": "bug",
   "title": "Vulkan passes XNA's normalised RasterizerState.DepthBias to vkCmdSetDepthBias unscaled, so a realistic bias has no effect",
   "summary": "VulkanRenderer hands DepthBias to vkCmdSetDepthBias raw, but that constant factor counts minimum depth steps; EasyGL, OpenGL4, SDL_GPU and Direct3D 11/12 scale XNA's normalised value by the depth format, so -0.0001 offsets nothing on Vulkan.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Graphics::RasterizerState::DepthBias and SlopeScaleDepthBias on the VULKAN renderer (VulkanRenderer::ApplyRasterizerState)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-264.html",
   "sources": [
    "modules/renderers/vulkan/src/VulkanRenderer.cpp",
    "modules/renderers/vulkan/examples/vulkan_depth_bias_test.cpp",
    "modules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp",
    "modules/renderers/opengl4/src/OpenGL4Renderer.cpp",
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp",
    "docs/easygl_bugs.md"
   ],
   "related": [
    "deep-dives/renderers/vulkan-deferred-state-and-descriptors.html",
    "development/internals/graphics/vulkan.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-BUG-265",
   "class": "bug",
   "title": "SignedInGamer::SignedIn does not replay already signed-in gamers to a late subscriber, unlike XNA 4.0",
   "summary": "XNA 4.0 raises SignedIn during Update and its add accessor replays each already signed-in gamer to a new handler; CNA raises it inside Initialize on a plain event, so a handler added afterwards never hears about the four stub gamers.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::GamerServices::SignedInGamer::SignedIn (event) and GamerServicesDispatcher::Initialize/Update",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-265.html",
   "sources": [
    "modules/gamer-services/src/Xna/SignedInGamer.cpp",
    "modules/gamer-services/src/Xna/GamerServicesDispatcher.cpp",
    "modules/gamer-services/include/Microsoft/Xna/Framework/GamerServices/SignedInGamer.hpp",
    "modules/net/src/Xna/NetworkSession.cpp",
    "modules/c-api/src/CnaCApiGamers.cpp",
    "modules/gamer-services/examples/demo_gamerservices_signin_presence/src/PresenceGame.cpp",
    "modules/gamer-services/tests/Microsoft/Xna/Framework/GamerServices/GamerServicesGamerTests.cpp",
    "CLAUDE.md"
   ],
   "related": [
    "deep-dives/services/gamer-services-contract.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-BUG-266",
   "class": "bug",
   "title": "GamerServicesDispatcher::Initialize re-initialises silently when gamer services are already initialised, where XNA 4.0 throws InvalidOperationException",
   "summary": "XNA 4.0's GamerServicesDispatcher.Initialize throws InvalidOperationException (GamerServicesAlreadyInitialized) when IsInitialized is true; CNA's Initialize follows FNA, frees the earlier stub gamers and installs four new ones, so a second call succeeds.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::GamerServices::GamerServicesDispatcher::Initialize(System::IServiceProvider&)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-266.html",
   "sources": [
    "modules/gamer-services/src/Xna/GamerServicesDispatcher.cpp"
   ],
   "related": [
    "deep-dives/services/gamer-services-contract.html"
   ]
  },
  {
   "id": "CNA-BUG-267",
   "class": "bug",
   "title": "A join beyond MaxGamers is not refused: the host sends ServerWelcome, AddRemoteGamer throws Session is full!, and the receive path's catch-all drops it, so SessionFull is never raised",
   "summary": "HandleClientHello sends ServerWelcome and registers wire ids before AddRemoteGamer checks capacity; the receive path swallows the exception, so an over-capacity client stays connected and NetworkSessionJoinError::SessionFull is never produced.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Net::NetworkSession::Join on a full host (ENetBackend HandleClientHello, NetworkSession::AddRemoteGamer, NetworkSessionJoinError::SessionFull)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-267.html",
   "sources": [
    "modules/net/src/Internal/ENetBackend.cpp",
    "modules/net/src/Xna/NetworkSession.cpp",
    "modules/net/include/Microsoft/Xna/Framework/Net/NetworkSessionJoinError.hpp"
   ],
   "related": [
    "deep-dives/services/network-sessions.html",
    "development/internals/modules/net.html"
   ]
  },
  {
   "id": "CNA-BUG-268",
   "class": "bug",
   "title": "A NetworkSession BeginCreate, BeginFind or BeginJoin callback that calls the matching End* frees the action and the closure that is executing, and Begin* returns the freed pointer",
   "summary": "InvokeActiveActionCallback runs the AsyncCallback inline from BeginCreate, BeginFind and BeginJoin; the matching End* deletes the action, including the std::function that is executing, so captures read after End* and the IAsyncResult* that Begin* then returns point at freed memory. BeginJoinInvited always refuses and never invokes a callback.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "medium",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Net::NetworkSession::BeginCreate/BeginFind/BeginJoin/BeginJoinInvited with a callback that calls the matching End*",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-268.html",
   "sources": [
    "modules/net/src/Xna/NetworkSession.cpp"
   ],
   "related": [
    "deep-dives/services/network-sessions.html"
   ]
  },
  {
   "id": "CNA-BUG-269",
   "class": "bug",
   "title": "cna_validate_renderer_identity_selection says it checks the per-identity CNA_RENDERER_<X> switches, but only retired names are checked: a misspelled or unknown switch is never read and the platform's default renderer is configured silently",
   "summary": "The validator's comment promises to check the CNA_RENDERER_<X> switches, but it only loops over retired names; -DCNA_RENDERER_D3D9=ON or a typo is neither an error nor honoured, and the platform's default renderer is configured without a diagnostic.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "cmake/RendererIdentities.cmake::cna_validate_renderer_identity_selection and the per-identity CNA_RENDERER_<X> configure switches",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-269.html",
   "sources": [
    "cmake/RendererIdentities.cmake",
    "cmake/RendererSelection.cmake",
    "cmake/Tests/RendererRetiredIdentityCase.cmake"
   ],
   "related": [
    "deep-dives/reference/glossary.html",
    "docs/building.html"
   ]
  },
  {
   "id": "CNA-BUG-270",
   "class": "bug",
   "title": "The @param lines of cna_post_process_chain_add_owned_pass and cna_skybox_set_owned_environment say the consumed handle is invalid on return even when the call fails, but both routes release it only after every check that can fail",
   "summary": "engine_layer.h says the pass and environment handles are 'invalid on return whether or not the call succeeded', but both routes release them only after their checks pass, so a binding that follows the @param line leaks the handle after a refused call.",
   "subsystem": "C API & bindings",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "cna_post_process_chain_add_owned_pass and cna_skybox_set_owned_environment (CNA/C/engine_layer.h)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-270.html",
   "sources": [
    "modules/c-api/include/CNA/C/engine_layer.h",
    "modules/c-api/src/CnaCApiEngineLayer.cpp",
    "docs/c-api/OWNERSHIP.md"
   ],
   "related": [
    "deep-dives/reference/native-c-api.html",
    "docs/c-api.html"
   ]
  },
  {
   "id": "CNA-BUG-271",
   "class": "bug",
   "title": "known_bugs.md still lists the FNA3D dangling-device use-after-free as OPEN and a lost repeated SpriteBatch Begin/End as a live symptom, although the source has fixed both",
   "summary": "CNA's own known-bug list keeps two entries whose fixes are in the source and pinned by registered tests: FNA3D resource renderers now hold a shared device state that the renderer clears (Fna3d_Device_Lifetime), and repeated SpriteBatch Begin()/End() cycles on VULKAN are pinned by Vulkan_SpriteBatch_MultiBeginEnd.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "known_bugs.md, the entries for FNA3D resource renderers that outlive their device and for several SpriteBatch Begin/End cycles in one frame",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-271.html",
   "sources": [
    "known_bugs.md",
    "modules/renderers/fna3d/src/Fna3dResources.cpp",
    "modules/renderers/fna3d/examples/fna3d_device_lifetime_test.cpp",
    "modules/renderers/vulkan/examples/CMakeLists.txt"
   ],
   "related": [
    "deep-dives/graphics/resource-lifetime.html",
    "deep-dives/graphics/spritebatch-semantics.html",
    "development/internals/graphics/backends.html",
    "development/internals/graphics/vulkan.html",
    "docs/rendering-backends.html"
   ]
  },
  {
   "id": "CNA-BUG-272",
   "class": "bug",
   "title": "misc/cnj.md's native-extension table omits .gltf and .glb, its sourceFile matrix omits Texture3D, AnimationClip and Curve, and one sentence says CNA has no JSON object type although Json.hpp defines JsonValue",
   "summary": "CNA's .cnj design note lists no glTF extension although ModelTypeReader accepts .gltf and .glb, lists only three of the six readers that reject sourceFile in its capability matrix, and says CNA has no JSON object type, only hand-rolled helpers, although CNA/Internal/Json.hpp is a complete JsonValue parser that the note's own status block names.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "misc/cnj.md: the native-extension table, the sourceFile capability matrix and the statements that CNA has no general JSON library or JSON object type",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-272.html",
   "sources": [
    "misc/cnj.md",
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/include/CNA/Internal/Json.hpp"
   ],
   "related": [
    "deep-dives/content/cnj-documents.html",
    "deep-dives/content/contentmanager-resolution-rules.html",
    "development/internals/content/runtime.html",
    "docs/content-manager.html"
   ]
  },
  {
   "id": "CNA-BUG-273",
   "class": "bug",
   "title": "CLAUDE.md and AGENTS.md tell contributors to throw std::runtime_error after disposal, while the public layer throws System::ObjectDisposedException at 51 sites in the graphics module alone",
   "summary": "CNA's contributor instruction files give one rule for a disposed object (throw std::runtime_error), while the graphics, audio, media and net modules throw System::ObjectDisposedException, XNA's exception for that case.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "CLAUDE.md and AGENTS.md, the IDisposable section (\"throw std::runtime_error if used after disposal\")",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-273.html",
   "sources": [
    "CLAUDE.md",
    "AGENTS.md",
    "modules/graphics/src/Xna/SpriteBatch.cpp"
   ],
   "related": [
    "deep-dives/foundations/language-conventions.html",
    "deep-dives/graphics/resource-lifetime.html",
    "development/handbook/conventions.html"
   ]
  },
  {
   "id": "CNA-BUG-274",
   "class": "bug",
   "title": "README.md calls the CNAEXT purity check \"a dedicated CMake build option\", but CNA_STRICT_XNA_API is a compile definition on two harness targets and no CMake option exists",
   "summary": "The README describes the compile-time CNAEXT purity check as a dedicated CMake build option; cmake/Harnesses.cmake only sets the CNA_STRICT_XNA_API compile definition on two check targets, and passing -DCNA_STRICT_XNA_API=ON to CMake does nothing.",
   "subsystem": "Documentation & release tooling",
   "status": "open",
   "severity": "low",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "README.md, the Verification methodology bullet on the CNAEXT purity check",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/bugs/cna-bug-274.html",
   "sources": [
    "README.md",
    "cmake/Harnesses.cmake",
    "modules/core/include/CNA/CNAHelper.hpp"
   ],
   "related": [
    "deep-dives/foundations/compatibility-and-evidence.html",
    "deep-dives/reference/cnaext-catalog.html",
    "docs/building.html",
    "docs/cnaext-engine.html"
   ]
  },
  {
   "id": "CNA-GAP-001",
   "class": "functional-gap",
   "title": "ContentLoadException derives from std::runtime_error, not System::Exception, so no Sharp Runtime catch clause spans CNA's XNA exceptions",
   "summary": "Unlike XNA, where every framework exception is a System.Exception, CNA's ContentLoadException (deliberately) derives from std::runtime_error, so catch (const System::Exception&) misses content-load failures; only std::exception spans the framework.",
   "subsystem": "Core & runtime",
   "status": "narrowed",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Content::ContentLoadException and the catchability of CNA exceptions through System::Exception",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-001.html",
   "sources": [
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentLoadException.hpp",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/DeviceLostException.hpp",
    "modules/platform/include/CNA/Platform/PlatformException.hpp",
    "modules/graphics/tests/Microsoft/Xna/Framework/Graphics/GraphicsExceptionTests.cpp",
    "modules/content/tests/Microsoft/Xna/Framework/Content/ContentRuntimeContractTests.cpp",
    "modules/c-api/src/CnaCApiDetail.hpp"
   ],
   "related": [
    "deep-dives/framework/game-class-and-lifecycle.html",
    "deep-dives/reference/verification-tiers.html",
    "development/internals/content/runtime.html",
    "development/internals/modules/core.html",
    "docs/content-manager.html"
   ]
  },
  {
   "id": "CNA-GAP-002",
   "class": "functional-gap",
   "title": "CNA::Logger serialises writes but not level changes, and a sink must not call back into the logger",
   "summary": "minimumLevel_ is read and written without synchronisation and the sink runs under a non-recursive mutex, so changing the level while other threads log is a data race and a sink that logs deadlocks; the header states neither limit.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Logger::SetMinimumLevel, GetMinimumLevel, Log and its helpers, SetSink and ResetSink",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-002.html",
   "sources": [
    "modules/core/src/Logger.cpp",
    "modules/core/include/CNA/Logger.hpp",
    "modules/core/tests/CNA/LoggerTests.cpp"
   ],
   "related": [
    "development/debugging.html",
    "development/internals/modules/core.html",
    "development/testing/architecture.html"
   ]
  },
  {
   "id": "CNA-GAP-003",
   "class": "functional-gap",
   "title": "CNA::Runtime and CNA::RuntimeOptions are declared in CNA/Misc.hpp but not implemented",
   "summary": "The runtime module's public include path declares a CNA::Runtime subsystem facade with documented behaviour, but no translation unit defines it, so any call fails to link; CNA knows and guards the fact with a CMake check.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Runtime::Initialize(const RuntimeOptions&), Shutdown(), IsGraphicsEnabled(), IsAudioEnabled(), IsInputEnabled(); CNA::RuntimeOptions",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-003.html",
   "sources": [
    "modules/runtime/include/CNA/Misc.hpp",
    "modules/c-api/cmake/CheckUnimplementedRuntimeFacade.cmake",
    "tools/c-api/coverage_mappings.json"
   ],
   "related": [
    "development/architecture/runtime.html",
    "development/internals/runtime/module.html",
    "development/reference/public-headers.html"
   ]
  },
  {
   "id": "CNA-GAP-004",
   "class": "functional-gap",
   "title": "Game::ShowMissingRequirementMessage is a virtual hook that nothing in CNA calls",
   "summary": "XNA 4.0's Game.Run catches NoSuitableGraphicsDeviceException and NoAudioHardwareException and offers them to ShowMissingRequirementMessage before rethrowing; CNA declares the virtual but Game::Run never invokes it, so an override has no effect.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "virtual bool Microsoft::Xna::Framework::Game::ShowMissingRequirementMessage(const std::exception&)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-004.html",
   "sources": [
    "modules/runtime/src/Game.cpp",
    "modules/runtime/include/Microsoft/Xna/Framework/Game.hpp"
   ],
   "related": [
    "deep-dives/framework/game-class-and-lifecycle.html"
   ]
  },
  {
   "id": "CNA-GAP-005",
   "class": "functional-gap",
   "title": "DrawableGameComponent loads content once in Initialize and never follows the graphics device service",
   "summary": "It never subscribes to IGraphicsDeviceService.DeviceCreated/DeviceDisposing (OnDeviceCreated is dead code), whereas XNA 4.0 requires the service, reloads on DeviceCreated and unloads on DeviceDisposing.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "Microsoft::Xna::Framework::DrawableGameComponent::Initialize(), LoadContent(), UnloadContent()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-005.html",
   "sources": [
    "modules/runtime/src/DrawableGameComponent.cpp",
    "modules/runtime/src/GraphicsDeviceManager.cpp"
   ],
   "related": [
    "deep-dives/framework/services-and-components.html"
   ]
  },
  {
   "id": "CNA-GAP-006",
   "class": "functional-gap",
   "title": "GraphicsDeviceManager never calls its FindBestDevice, RankDevices or CanResetDevice virtuals",
   "summary": "The three XNA selection hooks are implemented (as a default GDI, a no-op and 'device exists') but CreateDevice and ApplyChanges do not consult them, so overriding them has no effect on device selection or reset.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "Microsoft::Xna::Framework::GraphicsDeviceManager::FindBestDevice(bool), RankDevices(std::vector<GraphicsDeviceInformation>&), CanResetDevice(const GraphicsDeviceInformation&)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-006.html",
   "sources": [
    "modules/runtime/src/GraphicsDeviceManager.cpp"
   ],
   "related": [
    "deep-dives/framework/window-and-device-manager.html"
   ]
  },
  {
   "id": "CNA-GAP-007",
   "class": "functional-gap",
   "title": "CNA public headers export Sharp Runtime's unprefixed property macros (YES, NO, nothing, ref1, getter1, CONTAINS, INTERNAL and others)",
   "summary": "99 headers under modules/*/include include SharpRuntime/Prop.hpp or SharpRuntimeHelper.hpp, which define 33 short unprefixed macros, so a game translation unit that includes such a CNA header cannot use those spellings as identifiers.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "Any CNA public header that includes SharpRuntime/Prop.hpp or SharpRuntime/SharpRuntimeHelper.hpp (for example Viewport.hpp, ContentManager.hpp, SoundEffect.hpp)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-007.html",
   "sources": [
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/Viewport.hpp",
    "modules/content/include/Microsoft/Xna/Framework/Content/ContentManager.hpp",
    "modules/audio/include/Microsoft/Xna/Framework/Audio/SoundEffect.hpp"
   ],
   "related": [
    "deep-dives/foundations/language-conventions.html",
    "deep-dives/sharp-runtime/components-and-consumption.html"
   ]
  },
  {
   "id": "CNA-GAP-008",
   "class": "functional-gap",
   "title": "SDL_GPU ShaderEffect draws bind only the first vertex stream, and the limitation report misstates ShaderEffect instancing",
   "summary": "SDL_GPU's custom-effect draw takes its attributes from the first vertex buffer and binds slot 0 only, so other streams are never consumed, while its limitation text calls ShaderEffect instancing unimplemented although instance-indexed draws work.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice::DrawInstancedPrimitives / DrawIndexedPrimitives with a CNAEXT ShaderEffect applied, on SDL_GPU; GraphicsDevice::GetRendererCapabilityReportEXT()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-008.html",
   "sources": [
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp",
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp",
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp",
    "modules/renderers/webgpu/src/WebGPURenderer.cpp"
   ],
   "related": [
    "deep-dives/renderers/sdl-gpu-resources-and-frame-recovery.html",
    "development/internals/graphics/sdl-gpu.html",
    "docs/shader-effects.html"
   ]
  },
  {
   "id": "CNA-GAP-009",
   "class": "functional-gap",
   "title": "Sub-pixel SpriteBatch destinations reach only EasyGL, OPENGL4 and SOFTWARE; every other renderer truncates them to whole pixels",
   "summary": "SpriteBatch forwards float destinations through ISpriteBatchRenderer's sub-pixel Draw overload, whose default truncates toward zero into an integer Rectangle; only the EasyGL, OPENGL4 and SOFTWARE sprite renderers override it.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "SpriteBatch::Draw / DrawString with fractional positions or scales; ISpriteBatchRenderer::Draw(texture, float x, float y, float w, float h, ...)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-009.html",
   "sources": [
    "modules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp",
    "modules/graphics/src/Xna/SpriteBatch.cpp",
    "modules/renderers/opengl4/src/OpenGL4SpriteBatch.cpp"
   ],
   "related": [
    "deep-dives/graphics/spritebatch-semantics.html"
   ]
  },
  {
   "id": "CNA-GAP-010",
   "class": "functional-gap",
   "title": "SpriteSortMode::Immediate does not submit each sprite as it is drawn on VULKAN, SDL_GPU, the Direct3D families and WEBGPU, which still batch below the renderer seam",
   "summary": "On those renderers a texture rewritten between two Draw calls of an Immediate batch is rasterised with its final contents; CNA documents the VULKAN divergence as deliberate (VULKAN-057), while EasyGL, OPENGL4, FNA3D and SOFTWARE submit per Draw.",
   "subsystem": "Graphics & renderers",
   "status": "narrowed",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Graphics::SpriteBatch with SpriteSortMode::Immediate",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-010.html",
   "sources": [
    "docs/xna-4-api-coverage.md",
    "modules/graphics/examples/spritebatch_sort_mode_semantics_test.cpp",
    "modules/renderers/easygl/src/EasyGLRenderer.cpp",
    "modules/renderers/opengl4/src/OpenGL4SpriteBatch.cpp",
    "modules/renderers/fna3d/src/Fna3dSpriteBatch.cpp"
   ],
   "related": [
    "deep-dives/graphics/spritebatch-sorting-and-batching.html"
   ]
  },
  {
   "id": "CNA-GAP-011",
   "class": "functional-gap",
   "title": "PresentationParameters.RenderTargetUsage is stored, cloned and exposed but never consulted by GraphicsDevice",
   "summary": "Only a render target's own usage is read (in SetRenderTargets); the back buffer's RenderTargetUsage has no effect when SetRenderTargets returns to the back buffer.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Graphics::PresentationParameters::RenderTargetUsage",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-011.html",
   "sources": [
    "modules/graphics/src/Xna/PresentationParameters.cpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp"
   ],
   "related": [
    "deep-dives/graphics/render-target-semantics.html"
   ]
  },
  {
   "id": "CNA-GAP-012",
   "class": "functional-gap",
   "title": "On HEADLESS, TextureCube::SetData throws NotSupportedException because the headless cube renderer stores no pixels, so cube-map content cannot be loaded",
   "summary": "HeadlessTextureCubeRenderer::SetData validates and traces the upload and returns false by design (REMED-GFX-135); TextureCube::SetData turns that into NotSupportedException, and the XNB TextureCube reader uploads through SetData.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Graphics::TextureCube::SetData and ContentManager::Load<TextureCube> on HEADLESS",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-012.html",
   "sources": [
    "modules/renderers/headless/include/CNA/Internal/Renderers/Headless/HeadlessRenderer.hpp",
    "modules/graphics/src/Xna/TextureCube.cpp",
    "modules/content/src/Xnb/TextureCubeContentTypeReader.cpp"
   ],
   "related": [
    "deep-dives/graphics/texture-data-transfer.html",
    "development/internals/graphics/headless.html"
   ]
  },
  {
   "id": "CNA-GAP-013",
   "class": "functional-gap",
   "title": "METAL refuses a large part of the graphics API until it has macOS evidence: MRT, custom effects, occlusion queries, instancing, multi-stream input, back-buffer readback and several sampler/blend states",
   "summary": "MetalRenderer throws NotSupportedException for MRT, custom effects, occlusion queries, instancing, multi-stream input, back-buffer readback and some sampler/blend states, and applies every MSAA request as none.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice and resource APIs on the METAL renderer",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-013.html",
   "sources": [
    "modules/renderers/metal/src/MetalRenderer.mm",
    "modules/renderers/metal/include/CNA/Internal/Renderers/Metal/MetalPolicy.hpp",
    "modules/renderers/metal/examples/CMakeLists.txt",
    "modules/renderers/metal/examples/metal_spritebatch_customeffect_test.cpp"
   ],
   "related": [
    "deep-dives/renderers/native-gpu-evidence-tiers.html",
    "development/internals/graphics/draw-call.html"
   ]
  },
  {
   "id": "CNA-GAP-014",
   "class": "functional-gap",
   "title": "CANVAS and FREEDIRECT ignore GraphicsDevice.Viewport and ScissorRectangle, and SDL_RENDERER ignores Viewport",
   "summary": "The renderers leave the no-op IGraphicsRenderer::SetViewport (and, on CANVAS and FREEDIRECT, SetScissorRect) in place, so a custom viewport never offsets drawing and a scissor rectangle never clips there.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice.Viewport and GraphicsDevice.ScissorRectangle (with RasterizerState.ScissorTestEnable) on CANVAS, FREEDIRECT and SDL_RENDERER",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-014.html",
   "sources": [
    "modules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp",
    "modules/renderers/canvas/src/CanvasRenderer.cpp",
    "modules/renderers/freedirect/src/FreeDirectRenderer.cpp",
    "modules/renderers/sdl-renderer/include/CNA/Internal/Renderers/SdlRenderer/SdlRenderer.hpp"
   ],
   "related": [
    "deep-dives/renderers/render-targets-clears-and-viewports.html",
    "deep-dives/renderers/sdl-renderer-2d-contract.html"
   ]
  },
  {
   "id": "CNA-GAP-015",
   "class": "functional-gap",
   "title": "Only BasicEffect exposes XNA's parameter graph and technique name; the other stock effects publish partial, hand-built parameter tables",
   "summary": "AlphaTestEffect lacks Texture, DualTextureEffect lacks Texture/Texture2, EnvironmentMapEffect lacks Texture/EnvironmentMap/DirLight*, SkinnedEffect lacks Texture/DirLight*; these effects carry a 'Default' technique and some parameter shapes differ from XNA's.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Effect::getParametersProperty() and CurrentTechnique of AlphaTestEffect, DualTextureEffect, EnvironmentMapEffect, SkinnedEffect",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-015.html",
   "sources": [
    "modules/graphics/src/Xna/AlphaTestEffect.cpp",
    "modules/graphics/src/Xna/EnvironmentMapEffect.cpp",
    "modules/graphics/src/Xna/SkinnedEffect.cpp",
    "modules/graphics/src/Xna/BasicEffect.cpp"
   ],
   "related": [
    "deep-dives/graphics/effect-object-model.html"
   ]
  },
  {
   "id": "CNA-GAP-016",
   "class": "functional-gap",
   "title": "Several live GraphicsDevices share process-wide window and input slots with last-writer semantics",
   "summary": "The window-to-renderer registry is a static, unsynchronised map with no ownership check, and TextInputEXT and Mouse keep one process-wide window slot, so two devices overwrite each other's registry entries and input target.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "IGraphicsRenderer::RegisterForWindow/UnregisterForWindow/GetForWindow; TextInputEXT and Mouse window binding with more than one GraphicsDevice",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-016.html",
   "sources": [
    "modules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp",
    "modules/graphics/tests/CNA/Internal/Renderers/Common/IGraphicsRendererWindowRegistryTests.cpp"
   ],
   "related": [
    "deep-dives/renderers/presentation-and-backbuffer-readback.html"
   ]
  },
  {
   "id": "CNA-GAP-017",
   "class": "functional-gap",
   "title": "PresentationMode is stored but not honoured by FREEDIRECT (always letterbox), CANVAS (only FixedHeightDynamicWidth changes output) and DIRECTX9 (never read)",
   "summary": "The selected presentation mode reaches these renderers, but FREEDIRECT's presenter always letterboxes, CANVAS acts only on FixedHeightDynamicWidth, and DIRECTX9 stores the mode and virtual resolution without reading them.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA PresentationMode (GraphicsDeviceManager::PreferredPresentationMode, GraphicsDevice::SetPresentationMode) on FREEDIRECT, CANVAS and DIRECTX9",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-017.html",
   "sources": [
    "modules/renderers/freedirect/src/FreeDirectRenderer.cpp",
    "modules/renderers/canvas/src/CanvasRenderer.cpp",
    "modules/renderers/directx9/src/DirectX9Renderer.cpp"
   ],
   "related": [
    "deep-dives/renderers/direct3d-presentation-and-state.html",
    "deep-dives/renderers/presentation-and-backbuffer-readback.html"
   ]
  },
  {
   "id": "CNA-GAP-018",
   "class": "functional-gap",
   "title": "EasyGL does not register Texture3D with its context-loss recovery, so volume texture contents are lost after a real WebGL/GLES context loss",
   "summary": "EasyGLTexture3DRenderer is not a RecoverableResource, unlike EasyGL's 2D textures, cube textures, render targets, buffers and queries.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Texture3D on EasyGL profiles with context loss (WebGL2, GLES)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-018.html",
   "sources": [
    "modules/renderers/easygl/include/CNA/Internal/Renderers/EasyGL/EasyGLRenderer.hpp",
    "modules/renderers/easygl/src/EasyGLRenderer.cpp"
   ],
   "related": [
    "deep-dives/renderers/easygl-state-and-resource-semantics.html"
   ]
  },
  {
   "id": "CNA-GAP-019",
   "class": "functional-gap",
   "title": "A VULKAN occlusion query counts only the first contiguous run of its tagged draws per frame",
   "summary": "Draws inside one Begin/End span that are separated by another query's draws or land in a later render pass after a boundary are not summed, by an approved 'reject additional spans' policy.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Graphics::OcclusionQuery::PixelCount on VULKAN",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-019.html",
   "sources": [
    "modules/renderers/vulkan/src/VulkanRenderer.cpp"
   ],
   "related": [
    "deep-dives/renderers/vulkan-deferred-state-and-descriptors.html"
   ]
  },
  {
   "id": "CNA-GAP-020",
   "class": "functional-gap",
   "title": "SDL_GPU accepts ShaderEffect GLSL only in Vulkan-rule form (#version 450, explicit locations and SDL_gpu sets), so the shared GLSL ES 3.00 .cnj effect fixture does not load there",
   "summary": "SdlGpuEffectRenderer::CompileProgram passes GLSL to libshaderc for SPIR-V, which rejects GLSL ES 3.00 sources and implicit uniform bindings; CNA's portable .cnj effect fixture is written in GLSL ES 3.00.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "recorded-by-cna",
   "tests_present": true,
   "public_contract": "ShaderEffect construction from GLSL source and ContentManager::Load of GLSL .cnj effects on SDL_GPU",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-020.html",
   "sources": [
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp",
    "modules/content/tests/Microsoft/Xna/Framework/Content/CnjEffectTests.cpp"
   ],
   "related": [
    "deep-dives/renderers/sdl-gpu-pipeline-state-and-draw-order.html"
   ]
  },
  {
   "id": "CNA-GAP-021",
   "class": "functional-gap",
   "title": "DIRECTX9 BasicEffect reaches only 12 of its 32 shader variants; other combinations throw 'no matching CNA vertex layout'",
   "summary": "DirectX9Renderer::DrawBasicEffectEXT accepts only four fixed stride and flag shapes (stride 16 vertex colour, 20 texture, 24 vertex colour plus texture, 32 lit plus texture), which reach 12 of BasicEffect's 32 ShaderIndex values; position-only, position+normal and colour+normal inputs, including untextured per-pixel lighting, throw.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "BasicEffect draws on DIRECTX9",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-021.html",
   "sources": [
    "modules/renderers/directx9/src/D3D9EffectDraw.cpp"
   ],
   "related": [
    "deep-dives/renderers/direct3d9-xna-fidelity.html"
   ]
  },
  {
   "id": "CNA-GAP-022",
   "class": "functional-gap",
   "title": "DIRECTX9 ignores mipMap for RenderTarget2D (single level, GetData above level 0 throws) and ignores the MSAA request for RenderTargetCube",
   "summary": "CreateRenderTarget2D discards the mipMap argument and CreateRenderTargetCube discards mipMap and multiSampleCount, so mip chains are never generated and cube targets are never multisampled on DIRECTX9.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "RenderTarget2D(mipMap = true) and RenderTargetCube(multiSampleCount > 0) on DIRECTX9",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-022.html",
   "sources": [
    "modules/renderers/directx9/src/DirectX9Renderer.cpp",
    "modules/renderers/directx9/src/D3D9RenderTargets.cpp"
   ],
   "related": [
    "deep-dives/renderers/direct3d9-xna-fidelity.html"
   ]
  },
  {
   "id": "CNA-GAP-023",
   "class": "functional-gap",
   "title": "On DIRECTX9 a Texture2D can only be created with SurfaceFormat::Color",
   "summary": "DIRECTX9 leaves ClassifySurfaceFormatEXT at its Defer default, so Texture2D creation falls back to a Color-only check although the renderer maps D3D formats internally; DXT XNB textures still load because the reader converts them to RGBA, but XNB textures stored in any other non-Color format do not.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Texture2D constructors with a SurfaceFormat other than Color on DIRECTX9",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-023.html",
   "sources": [
    "modules/graphics/src/Xna/Texture2D.cpp",
    "modules/graphics/src/Xna/Texture.cpp",
    "modules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp"
   ],
   "related": [
    "deep-dives/graphics/surface-formats.html"
   ]
  },
  {
   "id": "CNA-GAP-024",
   "class": "functional-gap",
   "title": "DIRECTX11 and DIRECTX12 never use DXGI exclusive full screen: SetFullscreenState is not called and exclusiveFullscreen_ is dead state",
   "summary": "Neither renderer calls IDXGISwapChain::SetFullscreenState, and exclusiveFullscreen_ is declared and read (it disables tearing) but never set. Full screen is applied by the platform window instead, so the swap chain always stays a windowed flip-model chain and never learns that the platform switched the display mode.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "GraphicsDeviceManager.IsFullScreen / ToggleFullScreen on DIRECTX11 and DIRECTX12",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-024.html",
   "sources": [
    "modules/renderers/directx11/src/DirectX11Renderer.cpp",
    "modules/renderers/directx12/include/CNA/Internal/Renderers/DirectX12/DirectX12Renderer.hpp"
   ],
   "related": [
    "deep-dives/renderers/direct3d-presentation-and-state.html"
   ]
  },
  {
   "id": "CNA-GAP-025",
   "class": "functional-gap",
   "title": "DIRECT2D refuses additive blending (SourceAlpha/One and One/One) and other asymmetric or non-Add blend states, and reports AdditiveBlending false",
   "summary": "BlendStateToDirect2DBlendMode throws NotSupportedException for BlendState::Additive and One/One and std::runtime_error for asymmetric or non-Add combinations, because Direct2D's composite modes have no matching operation.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "SpriteBatch.Begin(..., BlendState::Additive or custom BlendState, ...) on DIRECT2D",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-025.html",
   "sources": [
    "modules/renderers/direct2d/src/Direct2DRenderer.cpp"
   ],
   "related": [
    "deep-dives/renderers/windows-2d-renderers.html"
   ]
  },
  {
   "id": "CNA-GAP-026",
   "class": "functional-gap",
   "title": "SDL_RENDERER cannot honour TextureAddressMode.Wrap or Mirror for SpriteBatch; a Wrap draw silently shows clamped pixels",
   "summary": "SDL_RenderTexture's source-rectangle sampling has one fixed edge-clamping behaviour, SetSamplerAddressMode is not overridden, and CNA records the Wrap/Mirror decision (Tasks 686/687) as blocked.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "recorded-by-cna",
   "tests_present": true,
   "public_contract": "SamplerState.AddressU/AddressV = Wrap or Mirror with SpriteBatch source rectangles beyond the texture on SDL_RENDERER",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-026.html",
   "sources": [
    "modules/renderers/sdl-renderer/examples/sdlrenderer_texture_address_mode_clamp_test.cpp",
    "docs/sdl-renderer-2d-completeness.md",
    "modules/renderers/sdl-renderer/include/CNA/Internal/Renderers/SdlRenderer/SdlRenderer.hpp"
   ],
   "related": [
    "deep-dives/renderers/sdl-renderer-2d-contract.html"
   ]
  },
  {
   "id": "CNA-GAP-027",
   "class": "functional-gap",
   "title": "HTML_DOM and SVG_DOM refuse back-buffer readback",
   "summary": "GetBackBufferData throws on these renderers because their back buffer is a live DOM subtree that no browser API rasterises; only bound render targets can be read.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice::GetBackBufferData on HTML_DOM and SVG_DOM",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-027.html",
   "sources": [
    "modules/renderers/html-dom/src/HtmlDomRenderer.cpp",
    "modules/renderers/svg-dom/src/SvgDomRenderer.cpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp"
   ],
   "related": [
    "deep-dives/renderers/browser-dom-renderers.html",
    "deep-dives/renderers/presentation-and-backbuffer-readback.html"
   ]
  },
  {
   "id": "CNA-GAP-028",
   "class": "functional-gap",
   "title": "The METAL renderer applies KHR_materials_specular factors only and samples neither specular texture",
   "summary": "Every other PBR renderer samples specularTexture and specularColorTexture; METAL reads the factor and colour but not the two maps, which the renderer-policy test pins as factor-only.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "PbrEffect rendering of KHR_materials_specular materials on the METAL renderer",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-028.html",
   "sources": [
    "modules/content/tests/CNA/Internal/GltfImport/GltfRendererPbrFallbackPolicyTests.cpp",
    "docs/gltf-limitations.md"
   ],
   "related": [
    "deep-dives/models/gltf-conformance.html"
   ]
  },
  {
   "id": "CNA-GAP-029",
   "class": "functional-gap",
   "title": "EasyGL GPU timers read 32-bit nanosecond results and cannot detect GL disjoint events",
   "summary": "EasyGLGpuTimerRenderer reads GL_TIME_ELAPSED as a 32-bit value because meta-gl exposes only glGetQueryObjectuiv, not a 64-bit query-object read, and it never queries GL_GPU_DISJOINT_EXT, so results saturate near 4.29 s and only an all-ones result is rejected as undefined.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Graphics::GpuTimer and RenderPipeline pass timings (CNAEXT) on the EasyGL GL profiles",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-029.html",
   "sources": [
    "modules/renderers/easygl/src/EasyGLRenderer.cpp",
    "modules/graphics-ext/src/GpuTimer.cpp"
   ],
   "related": [
    "deep-dives/siblings/easygl-and-metagl.html",
    "development/internals/graphics/easygl.html"
   ]
  },
  {
   "id": "CNA-GAP-030",
   "class": "functional-gap",
   "title": "FREEDIRECT keeps presenting at the old physical scale after a virtual-resolution change once the first Present has happened",
   "summary": "FreeDirectRenderer::SetVirtualResolution recreates the surfaces and the display mode, but free-direct applies its SDL logical-presentation rectangle only once, so output after a change made following the first Present keeps the old logical size and scale. That FREEDIRECT always letterboxes whatever presentation mode is requested is published as CNA-GAP-017.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice presentation mode and virtual-resolution changes on FREEDIRECT",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-030.html",
   "sources": [
    "modules/renderers/freedirect/src/FreeDirectRenderer.cpp",
    "docs/freedirect-renderer.md"
   ],
   "related": [
    "deep-dives/siblings/freedirect-and-freeapi.html"
   ]
  },
  {
   "id": "CNA-GAP-031",
   "class": "functional-gap",
   "title": "ClusteredForwardEffect binds no material textures: many punctual lights cannot be combined with a texture set",
   "summary": "The CNAEXT ClusteredForwardEffect consumes scalar material inputs only (base colour, metallic, roughness, IOR and the scalar clearcoat, sheen, iridescence and subsurface lobes) and binds no material textures, so a game that needs many lights gives up PbrEffect's texture set and shadowed punctual light, as the effect's own header states.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Graphics::ClusteredForwardEffect (CNAEXT engine layer)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-031.html",
   "sources": [
    "modules/graphics-ext/include/CNA/Graphics/ClusteredForwardEffect.hpp"
   ],
   "related": [
    "development/internals/modules/graphics-ext.html",
    "docs/cnaext-engine.html"
   ]
  },
  {
   "id": "CNA-GAP-032",
   "class": "functional-gap",
   "title": "Engine-layer PBR limits: one punctual light per PbrEffect draw, 8-bit environment cubes, no back-face normal flip for double-sided materials, no alpha-tested shadow casters",
   "summary": "PbrEffect takes one punctual light, EnvironmentProcessor builds its cubes as SurfaceFormat::Color, no stock or engine-layer shader reads a front-facing input to flip normals, and the shadow-caster shaders write depth without an alpha test.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "PbrEffect::setPunctualLightEXT; CNA::Graphics::EnvironmentProcessor; PbrEffect::getDoubleSidedEXTProperty; the engine layer's shadow-caster passes",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-032.html",
   "sources": [
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/PbrEffect.hpp",
    "docs/cnaext-engine-layer.md",
    "modules/graphics-ext/src/EnvironmentProcessor.cpp",
    "docs/gltf-limitations.md",
    "modules/graphics-ext/src/shaders/shadow_caster/directional.desktop.frag.glsl"
   ],
   "related": [
    "deep-dives/models/gltf-conformance.html",
    "docs/cnaext-engine.html"
   ]
  },
  {
   "id": "CNA-GAP-033",
   "class": "functional-gap",
   "title": "CNA has no counterpart of XNA's MissingVertexShaderInput draw check, and renderers resolve a stock-effect draw that lacks an input differently",
   "summary": "XNA refuses a draw whose vertex declaration lacks a semantic the shader reads; CNA has no such check, so EasyGL/OPENGL4 feed neutral values, WEBGPU substitutes, SDL_GPU throws and VULKAN aliases TEXCOORD1.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice::DrawPrimitives / DrawIndexedPrimitives / DrawUserPrimitives with a stock effect whose required vertex semantic is missing from the VertexDeclaration",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-033.html",
   "sources": [
    "modules/graphics/src/Xna/GraphicsDevice.cpp",
    "modules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp",
    "modules/renderers/easygl/src/EasyGLRenderer.cpp",
    "modules/renderers/opengl4/src/OpenGL4StockDraw.cpp",
    "modules/renderers/webgpu/src/WebGPURenderer.cpp",
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp",
    "modules/renderers/vulkan/src/VulkanRenderer.cpp"
   ],
   "related": [
    "deep-dives/graphics/stock-effects-semantics.html",
    "deep-dives/graphics/vertex-streams-and-declarations.html",
    "deep-dives/renderers/renderer-contract.html",
    "docs/effects.html",
    "docs/graphics-state.html"
   ]
  },
  {
   "id": "CNA-GAP-034",
   "class": "functional-gap",
   "title": "The XNB DateTime reader discards the two DateTimeKind bits, so Utc and Local values load as plain tick counts",
   "summary": "DateTimeReader masks off the two kind bits and returns System::DateTime(ticks) with an unspecified kind, and it does not convert a Local-kind value to local time as XNA does. The header justifies the deviation by System::DateTime not modelling a kind, but System::DateTime has a (ticks, DateTimeKind) constructor at TARGET, so that reason is stale.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "XNB DateTime values read through ContentReader (DateTimeReader)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-034.html",
   "sources": [
    "modules/content/include/CNA/Internal/Xnb/DecimalDateTimeContentTypeReaders.hpp",
    "modules/content/tests/CNA/Internal/Xnb/DecimalDateTimeContentTypeReaderTests.cpp"
   ],
   "related": [
    "deep-dives/content/xnb-type-readers.html",
    "development/internals/content/runtime.html"
   ]
  },
  {
   "id": "CNA-GAP-035",
   "class": "functional-gap",
   "title": "Only the direct glTF route fills Model::CamerasEXT; models loaded from .cnj or .cnb carry no cameras",
   "summary": "ReadGltfModel extracts the file's cameras into Model::CamerasEXT, but the offline gltf_to_cnj/gltf_to_cnb tools only count camera nodes, so a converted model arrives without its authored framing.",
   "subsystem": "Models & glTF",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Model::getCamerasEXTProperty() on models loaded through .cnj and .cnb",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-035.html",
   "sources": [
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/graphics/include/Microsoft/Xna/Framework/Graphics/Model.hpp",
    "tools/gltf_to_cnj/gltf_to_cnj.cpp"
   ],
   "related": [
    "deep-dives/models/cnj-toolchain.html",
    "deep-dives/models/gltf-import.html",
    "docs/model-loading.html"
   ]
  },
  {
   "id": "CNA-GAP-036",
   "class": "functional-gap",
   "title": "Runtime glTF import has no unit-scale option; only the offline converters can rescale a model",
   "summary": "ContentManager's glTF reader always imports at unitScale 1.0, so a file not authored in metres must go through the offline converters: cna_tool_gltf_to_cnb --unit-scale, or the optional unitScale argument of cna_tool_gltf_to_cnj.",
   "subsystem": "Models & glTF",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "ContentManager::Load<Model> on .gltf/.glb",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-036.html",
   "sources": [
    "modules/content/src/Xna/ContentManager.cpp",
    "tools/gltf_to_cnb/gltf_to_cnb.cpp",
    "tools/gltf_to_cnj/gltf_to_cnj.cpp"
   ],
   "related": [
    "deep-dives/models/gltf-import.html",
    "docs/model-loading.html"
   ]
  },
  {
   "id": "CNA-GAP-037",
   "class": "functional-gap",
   "title": "EXT_mesh_gpu_instancing is not imported: each node keeps one placement and its per-instance transforms are dropped",
   "summary": "A node declaring EXT_mesh_gpu_instancing is imported with its own single transform, so the file renders one copy where it describes many; the drop is reported per file (gpu-instancing-dropped).",
   "subsystem": "Models & glTF",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager::Load<Model> on glTF files using EXT_mesh_gpu_instancing",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-037.html",
   "sources": [
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/src/GltfImport/GltfImportCore.cpp",
    "docs/gltf-limitations.md"
   ],
   "related": [
    "deep-dives/models/gltf-conformance.html",
    "deep-dives/models/gltf-import.html",
    "docs/model-loading.html"
   ]
  },
  {
   "id": "CNA-GAP-038",
   "class": "functional-gap",
   "title": "Mirrored glTF placements keep the shared winding, so under the default cull mode they render back-facing",
   "summary": "A placement whose world transform has a negative determinant is detected and reported (mirrored-winding-unapplied) but CNA neither reverses its winding nor changes cull state, and exposes no per-mesh flag for the application to do it.",
   "subsystem": "Models & glTF",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager::Load<Model> on glTF files with negatively scaled or mirroring node transforms; Model::Draw",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-038.html",
   "sources": [
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/src/GltfImport/GltfImportCore.cpp",
    "modules/content/tests/CNA/Internal/GltfImport/GltfMirroringTests.cpp"
   ],
   "related": [
    "deep-dives/models/gltf-import.html",
    "deep-dives/models/vertex-packing-and-strides.html",
    "docs/model-loading.html"
   ]
  },
  {
   "id": "CNA-GAP-039",
   "class": "functional-gap",
   "title": "The glTF vertex ABI carries two UV channels, one joint-influence set and one colour set; further sets are dropped and reported",
   "summary": "TEXCOORD sets beyond the first two sampled ones, JOINTS_1/WEIGHTS_1 and later, and COLOR_1 and later are not imported; each loss is named in the import report.",
   "subsystem": "Models & glTF",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager::Load<Model> and the offline converters on glTF primitives with extra attribute sets",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-039.html",
   "sources": [
    "modules/content/src/GltfImport/GltfImportCore.cpp",
    "docs/gltf-limitations.md"
   ],
   "related": [
    "deep-dives/models/gltf-import.html",
    "deep-dives/models/vertex-packing-and-strides.html"
   ]
  },
  {
   "id": "CNA-GAP-040",
   "class": "functional-gap",
   "title": "A skinned glTF model cannot also carry rigid scene-node animation: tracks not driven by its skins are dropped",
   "summary": "Model::Tag holds SkinningData for a skinned model, so scene-node clips whose tracks are not carried by a skin palette are dropped with the rigid-animation-dropped-on-skinned-model diagnostic.",
   "subsystem": "Models & glTF",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager::Load<Model> on glTF files that animate non-joint nodes of a skinned model",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-040.html",
   "sources": [
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/src/GltfImport/GltfImportCore.cpp"
   ],
   "related": [
    "deep-dives/models/skinning-and-animation.html",
    "docs/model-loading.html"
   ]
  },
  {
   "id": "CNA-GAP-041",
   "class": "functional-gap",
   "title": "A glTF mesh placed by several nodes takes its morph-weight animation from the first of them only",
   "summary": "ExtractMorphWeightTrack resolves a mesh to the first node in file order that instances it, so every placement plays that node's weights channel and channels on the other nodes are ignored.",
   "subsystem": "Models & glTF",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager::Load<Model> on glTF files that animate morph weights of a multiply-instanced mesh",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-041.html",
   "sources": [
    "modules/content/src/GltfImport/GltfImportCore.cpp",
    "modules/content/include/CNA/Internal/GltfImport/GltfImportCore.hpp"
   ],
   "related": [
    "deep-dives/models/skinning-and-animation.html"
   ]
  },
  {
   "id": "CNA-GAP-042",
   "class": "functional-gap",
   "title": "CUBICSPLINE bone and node channels are sampled at key times and played back linearly between them",
   "summary": "BuildTrack evaluates each channel's Hermite curve only at the union of key times, and AnimationPlayer then lerps/slerps between those keys, so the curve's shape between keys is lost.",
   "subsystem": "Models & glTF",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "AnimationPlayer and SkinnedModelEXT playback of glTF clips with CUBICSPLINE interpolation",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-042.html",
   "sources": [
    "modules/content/src/GltfImport/GltfImportCore.cpp",
    "modules/graphics/src/Xna/AnimationPlayer.cpp",
    "docs/gltf-limitations.md"
   ],
   "related": [
    "deep-dives/models/skinning-and-animation.html"
   ]
  },
  {
   "id": "CNA-GAP-043",
   "class": "functional-gap",
   "title": "glTF skins with more than 72 joints are refused at import",
   "summary": "BuildSkeleton throws for a skin above the 72-matrix GPU palette (SkinnedEffect::MaxBones), naming the joint count, instead of truncating it.",
   "subsystem": "Models & glTF",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager::Load<Model> and the offline converters on glTF skins with more than 72 joints",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-043.html",
   "sources": [
    "modules/content/src/GltfImport/GltfImportCore.cpp"
   ],
   "related": [
    "deep-dives/models/skinning-and-animation.html"
   ]
  },
  {
   "id": "CNA-GAP-044",
   "class": "functional-gap",
   "title": "glTF punctual lights are approximated as at most three directional lights; point and spot lights have no native support",
   "summary": "KHR_lights_punctual is imported into XNA's three-directional-light model: point and spot lights become directional lights aimed at the origin, ranges and cones are ignored, and lights beyond three are dropped and counted.",
   "subsystem": "Models & glTF",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager::Load<Model> on glTF files using KHR_lights_punctual; the imported lights applied to BasicEffect/PbrEffect",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-044.html",
   "sources": [
    "modules/content/src/GltfImport/GltfImportCore.cpp",
    "docs/gltf-limitations.md",
    "plans/plan_gltf.md"
   ],
   "related": [
    "deep-dives/models/gltf-conformance.html",
    "deep-dives/models/gltf-import.html"
   ]
  },
  {
   "id": "CNA-GAP-045",
   "class": "functional-gap",
   "title": "XACT features FAudio never finished are unimplemented: QUEUE and REPLACE_QUIETEST limits, band-pass track filters, reverb sends and DSP-preset RPCs",
   "summary": "CNA reproduces FAudio's shipped behaviour: QUEUE and REPLACE_QUIETEST evict the oldest cue, a cue-level limit picks its victim from the whole bank, band-pass filters cannot be decoded, and reverb and DSP-preset RPC targets do nothing.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "AudioEngine category and cue instance limits; XACT sound-bank track filters; Cue RPC evaluation; SoundEffectInstance reverb",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-045.html",
   "sources": [
    "modules/audio/src/Xna/AudioEngine.cpp",
    "modules/audio/src/Internal/XactParser.cpp",
    "modules/audio/src/Xna/Cue.cpp",
    "modules/audio/src/Xna/SoundEffectInstance.cpp"
   ],
   "related": [
    "deep-dives/services/xact-runtime.html",
    "docs/audio.html",
    "docs/tutorials/120-xact.html"
   ]
  },
  {
   "id": "CNA-GAP-046",
   "class": "functional-gap",
   "title": "CNA has no sound-instance limit: InstancePlayLimitException is declared but never thrown",
   "summary": "XNA throws InstancePlayLimitException when too many sound instances play and SoundEffect.Play returns false for it; CNA declares the type but no code path raises it.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "SoundEffectInstance::Play(), SoundEffect::Play() and InstancePlayLimitException",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-046.html",
   "sources": [
    "modules/audio/include/Microsoft/Xna/Framework/Audio/InstancePlayLimitException.hpp",
    "modules/audio/src/Xna/SoundEffect.cpp"
   ],
   "related": [
    "deep-dives/services/sound-effects-and-streaming.html",
    "development/internals/audio/engine.html",
    "docs/audio.html"
   ]
  },
  {
   "id": "CNA-GAP-047",
   "class": "functional-gap",
   "title": "XACT wave-bank entries compressed as XMA/XMA2 or WMA produce no sound",
   "summary": "WaveBank::GetSoundEffect returns null for XMA and WMA entries after printing a diagnostic to stderr, so cues using them are silent.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "WaveBank loading and playback of XMA/XMA2 and WMA (xWMA) wave entries",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-047.html",
   "sources": [
    "modules/audio/src/Xna/WaveBank.cpp"
   ],
   "related": [
    "deep-dives/services/xact-runtime.html",
    "docs/audio.html"
   ]
  },
  {
   "id": "CNA-GAP-048",
   "class": "functional-gap",
   "title": "StorageContainer::OpenFile(file, mode, access, share) ignores its FileShare argument",
   "summary": "The four-argument OpenFile accepts a FileShare value and discards it, because the Sharp Runtime FileStream it constructs has no share mode, so FileShare::None does not keep a second writer out.",
   "subsystem": "Storage",
   "status": "narrowed",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Storage::StorageContainer::OpenFile(const std::string& file, FileMode, FileAccess, FileShare), the two shorter OpenFile overloads that forward to it, and the C route cna_storage_container_open_file_share",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-048.html",
   "sources": [
    "modules/storage/src/StorageContainer.cpp",
    "modules/storage/include/Microsoft/Xna/Framework/Storage/StorageContainer.hpp",
    "modules/c-api/src/CnaCApiStorage.cpp",
    "modules/storage/tests/Microsoft/Xna/Framework/Storage/StorageDeviceTests.cpp"
   ],
   "related": [
    "development/internals/modules/storage.html",
    "development/takeover/case-study-storage.html",
    "docs/storage.html"
   ]
  },
  {
   "id": "CNA-GAP-049",
   "class": "functional-gap",
   "title": "StorageDevice::DeviceChanged is declared but never raised",
   "summary": "The static event exists for API compatibility, but nothing in the snapshot raises it; genuine XNA 4.0 raises it through FrameworkCallbackLinker.StorageDeviceChanged when a storage device changes, and CNA's desktop storage root has no such change source.",
   "subsystem": "Storage",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Storage::StorageDevice::DeviceChanged",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-049.html",
   "sources": [
    "modules/storage/src/StorageDevice.cpp",
    "modules/storage/include/Microsoft/Xna/Framework/Storage/StorageDevice.hpp"
   ],
   "related": [
    "development/internals/modules/storage.html",
    "docs/storage.html"
   ]
  },
  {
   "id": "CNA-GAP-051",
   "class": "functional-gap",
   "title": "Guide's fourteen Show* shell entry points and DelayNotifications are empty no-ops",
   "summary": "ShowSignIn, ShowFriends, ShowMarketplace, ShowMessages, ShowComposeMessage, ShowGamerCard, ShowParty, ShowPartySessions, ShowPlayers, ShowPlayerReview, ShowFriendRequest, ShowGameInvite (both) and ShowAchievementsEXT do nothing.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Guide::Show* (fourteen overloads) and Guide::DelayNotifications",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-051.html",
   "sources": [
    "modules/gamer-services/src/Xna/Guide.cpp"
   ],
   "related": [
    "deep-dives/services/gamer-services-contract.html"
   ]
  },
  {
   "id": "CNA-GAP-052",
   "class": "functional-gap",
   "title": "Local gamer services have no catalogue, presence or profile data: achievement metadata is empty, Achievement::GetPicture throws, presence is never published and privileges are a fixed permissive constant",
   "summary": "Achievements come back with only key, earned state and time; GetPicture throws NotImplementedException; SetPresenceModeStringEXT does nothing; GamerPrivileges allows everything and nothing enforces it; GamerProfile is synthetic except Region.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Achievement (Name, Description, GamerScore, DisplayBeforeEarned, GetPicture), GamerPresence, GamerPrivileges, GamerProfile",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-052.html",
   "sources": [
    "modules/gamer-services/src/Xna/SignedInGamer.cpp",
    "modules/gamer-services/src/Xna/Achievement.cpp",
    "modules/gamer-services/src/Xna/GamerPresence.cpp",
    "modules/gamer-services/src/Xna/GamerPrivileges.cpp",
    "modules/gamer-services/src/Xna/GamerProfile.cpp"
   ],
   "related": [
    "deep-dives/services/gamer-services-contract.html",
    "development/internals/modules/gamer-services.html"
   ]
  },
  {
   "id": "CNA-GAP-053",
   "class": "functional-gap",
   "title": "Voice chat, party invites, NetworkMachine::RemoveFromSession, arbitration/TrueSkill events and QualityOfService bandwidth are not implemented",
   "summary": "EnableSendVoice and SendPartyInvites are no-ops, RemoveFromSession throws NotImplementedException, the leaderboard and TrueSkill write events are never raised, and QualityOfService's bandwidth fields stay 0.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "LocalNetworkGamer::EnableSendVoice, LocalNetworkGamer::SendPartyInvites, NetworkMachine::RemoveFromSession, NetworkSession leaderboard/TrueSkill events, QualityOfService",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-053.html",
   "sources": [
    "modules/net/src/Xna/LocalNetworkGamer.cpp",
    "modules/net/src/Xna/NetworkMachine.cpp",
    "modules/net/include/Microsoft/Xna/Framework/Net/NetworkSession.hpp",
    "modules/net/src/Xna/QualityOfService.cpp"
   ],
   "related": [
    "deep-dives/services/network-sessions.html"
   ]
  },
  {
   "id": "CNA-GAP-054",
   "class": "functional-gap",
   "title": "The terminal window title is stored but never emitted, so SetTitle has no visible effect",
   "summary": "TerminalWindow::SetTitle records the title and defers the OSC emission to the session, but the session prologue emits no title sequence and nothing else writes one, so a terminal window title is never shown.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Platform::IPlatformWindow::SetTitle(const std::string&) on the terminal platform",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-054.html",
   "sources": [
    "modules/platform/src/Terminal/TerminalPlatform.cpp",
    "modules/platform/src/Terminal/TerminalSession.cpp",
    "modules/platform/tests/CNA/Platform/TerminalPlatformTests.cpp"
   ],
   "related": [
    "development/handbook/modify-a-platform-backend.html",
    "development/internals/platforms/terminal.html",
    "docs/platforms.html"
   ]
  },
  {
   "id": "CNA-GAP-055",
   "class": "functional-gap",
   "title": "TerminalSession does not restore or re-establish the terminal on job-control stop and continue (SIGTSTP/SIGCONT)",
   "summary": "The session's restoring signal set covers termination and crash signals but not SIGTSTP/SIGCONT, so a Ctrl-Z that suspends a terminal game leaves the terminal in raw mode, the alternate screen and mouse reporting until the process is resumed.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Platform::Terminal::TerminalSession terminal restoration on job-control signals",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-055.html",
   "sources": [
    "modules/platform/src/Terminal/TerminalSession.cpp"
   ],
   "related": [
    "development/handbook/modify-a-platform-backend.html",
    "development/internals/platforms/terminal.html",
    "docs/platforms.html"
   ]
  },
  {
   "id": "CNA-GAP-056",
   "class": "functional-gap",
   "title": "A foreign HWND adopted by handle is not subclassed and is absent from windows_, so the Win32 GL, Vulkan, relative-mouse and text-input services refuse it",
   "summary": "AdoptWindowHandle wraps a foreign HWND without subclassing it or adding it to windows_, so it raises no CNA events and FindWindow cannot resolve its id; the WGL, Vulkan, relative-mouse and text-input services then reject it.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Platform::Win32::Win32Platform::AdoptWindowHandle(std::uintptr_t) for a window CNA did not create",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-056.html",
   "sources": [
    "modules/platform/src/Win32/Win32Platform.cpp",
    "modules/platform/src/Win32/Win32Window.cpp",
    "modules/platform/src/Win32/Win32GraphicsServices.cpp"
   ],
   "related": [
    "development/handbook/modify-a-platform-backend.html",
    "development/internals/platforms/win32.html",
    "docs/native-platforms.html"
   ]
  },
  {
   "id": "CNA-GAP-057",
   "class": "functional-gap",
   "title": "CNA::Devices host dialogs are minimal: message boxes are unparented with no default or cancel button, tray icons have no image API, and UrlLauncher passes any string to the OS",
   "summary": "MessageBox passes a null parent window and SDL buttons without RETURNKEY/ESCAPEKEY defaults, SystemTray offers only a tooltip and menu, and UrlLauncher::Open forwards its argument unvalidated to the platform (ShellExecuteW 'open' on Win32).",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Devices::MessageBox::Show, CNA::Devices::SystemTray, CNA::Devices::UrlLauncher::Open",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-057.html",
   "sources": [
    "modules/devices-ext/src/MessageBox.cpp",
    "modules/platform/src/Sdl3/Sdl3SystemServices.cpp",
    "modules/devices-ext/include/CNA/Devices/SystemTray.hpp",
    "modules/devices-ext/src/UrlLauncher.cpp",
    "modules/platform/src/Win32/Win32SystemServices.cpp"
   ],
   "related": [
    "deep-dives/services/host-devices.html",
    "development/internals/modules/devices-ext.html"
   ]
  },
  {
   "id": "CNA-GAP-058",
   "class": "functional-gap",
   "title": "The native Win32 platform backend has no gamepad support, no IME composition events and no file drop",
   "summary": "Win32Platform reports gamepad, joystick, haptics and IME as deliberately unsupported, handles no WM_IME_* message or Imm* call, and never raises GameWindow's FileDropEXT; raw mouse input and per-monitor DPI are implemented.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA_PLATFORM=WIN32: GamePad, text input composition, GameWindow::FileDropEXT",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-058.html",
   "sources": [
    "modules/platform/src/Win32/Win32Platform.cpp",
    "modules/platform/src/Win32/Win32InputServices.cpp",
    "modules/platform/src/Win32/Win32Window.cpp",
    "modules/platform/src/Win32/Win32DpiSupport.cpp"
   ],
   "related": [
    "deep-dives/platforms/cross-platform-contract.html",
    "deep-dives/platforms/windows-cross-compiling-and-wine.html",
    "development/internals/platforms/win32.html",
    "docs/platforms.html"
   ]
  },
  {
   "id": "CNA-GAP-059",
   "class": "functional-gap",
   "title": "In a MinGW-w64 cross tree CnaTests gets a Wine CROSSCOMPILING_EMULATOR only when the default renderer is DIRECTX9/11/12 or DIRECT2D is compiled in",
   "summary": "For any other default renderer (for example SDL_RENDERER, the toolchain file's own usage example) gtest discovery (DISCOVERY_MODE PRE_TEST) and ctest try to execute the Windows CnaTests binary directly on the Linux host.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "cmake/UnitTests.cmake CnaTests CROSSCOMPILING_EMULATOR chain; cross-compiled CTest runs",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-059.html",
   "sources": [
    "cmake/UnitTests.cmake",
    "cmake/toolchains/mingw-w64.cmake"
   ],
   "related": [
    "deep-dives/platforms/windows-cross-compiling-and-wine.html",
    "development/testing/architecture.html"
   ]
  },
  {
   "id": "CNA-GAP-060",
   "class": "functional-gap",
   "title": "No renderer or subsystem registers an IDiagnosticsSource, and nothing registers ResourceKind::AudioVoice resources",
   "summary": "The diagnostics source seam for GPU timings and renderer statistics has no production implementation and no engine code registers audio-voice resource metadata, so those diagnostics and Inspector views stay empty at this snapshot.",
   "subsystem": "Diagnostics & Inspector",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Diagnostics::IDiagnosticsSource / RegisterSource and CNA::Diagnostics::ResourceKind::AudioVoice",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-060.html",
   "sources": [
    "modules/diagnostics/include/CNA/Diagnostics/Diagnostics.hpp",
    "modules/diagnostics/src/Diagnostics.cpp",
    "modules/inspector/src/WebBridge.cpp",
    "docs/diagnostics.md"
   ],
   "related": [
    "development/internals/modules/diagnostics.html",
    "docs/diagnostics.html",
    "docs/inspector.html"
   ]
  },
  {
   "id": "CNA-GAP-061",
   "class": "functional-gap",
   "title": "No renderer implements IResourcePreviewProvider, and the seam cannot cancel a preview ticket the agent abandons",
   "summary": "Resource previews are unavailable in every real Inspector session because no CNA renderer installs a preview provider, and when a client disconnects the agent drops its pending tickets without telling the provider.",
   "subsystem": "Diagnostics & Inspector",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Inspector::IResourcePreviewProvider (RequestPreview, PollPreview) and AgentConfiguration::previewProvider",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-061.html",
   "sources": [
    "modules/inspector/include/CNA/Inspector/Agent.hpp",
    "modules/inspector/src/Agent.cpp",
    "docs/inspector.md"
   ],
   "related": [
    "development/internals/modules/inspector.html",
    "docs/inspector.html"
   ]
  },
  {
   "id": "CNA-GAP-062",
   "class": "functional-gap",
   "title": "The C ABI has no route for 468 public C++ declarations that the coverage inventory records as planned",
   "summary": "COVERAGE.md records 468 in-scope public C++ declarations without a C mapping (320 runtime surface added after the binding campaign, 134 CNB Model-v2 surface, 14 smaller seams), which is why the C ABI release gate reads Not ready.",
   "subsystem": "C API & bindings",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA C ABI 0.29.0 (modules/c-api/include/CNA/C) against the public C++ surface of the modules it links",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-062.html",
   "sources": [
    "docs/c-api/COVERAGE.md",
    "plans/plan_binding.md",
    "docs/c-api/RELEASE_GATE.md",
    "tools/c-api/generate_coverage_inventory.py",
    "tools/c-api/check_release_gate.py"
   ],
   "related": [
    "development/handbook/update-the-c-api.html",
    "docs/c-api.html"
   ]
  },
  {
   "id": "CNA-GAP-063",
   "class": "functional-gap",
   "title": "A fixed-step TargetElapsedTime above 500 ms never produces an Update from Game::Tick, essentially the same ceiling XNA 4.0 has",
   "summary": "With IsFixedTimeStep true, Game::Tick clamps the accumulator to MaxElapsedTime (500 ms) before its update loop, so a TargetElapsedTime above 500 ms is never reached: Update does not run while Draw keeps running, at about 1 / (target - 500 ms) per second (twice a second for a one-second target). XNA 4.0's Tick has essentially the same ceiling (about 508 ms, because of its 1/64 snap), but neither updates nor draws above it, so the limit is inherited; the setter accepts such a value silently.",
   "subsystem": "Core & runtime",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Game::setTargetElapsedTimeProperty(const System::TimeSpan&) with IsFixedTimeStep true; Game::Tick()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-063.html",
   "sources": [
    "modules/runtime/src/Game.cpp",
    "modules/runtime/include/Microsoft/Xna/Framework/Game.hpp"
   ],
   "related": [
    "deep-dives/framework/game-time-and-timestep.html",
    "development/architecture/runtime.html",
    "development/internals/runtime/frame.html",
    "docs/game-loop.html",
    "docs/tutorials/48-timestep.html"
   ]
  },
  {
   "id": "CNA-GAP-064",
   "class": "functional-gap",
   "title": "WEBGPU does not propagate a real device loss: OnDeviceLost only logs, so DeviceLost, the device status and the draw gate react only to the debug hooks",
   "summary": "WebGPURenderer sets its lost flag, closes CanBeginDrawEXT() and raises DeviceLost only inside DebugSimulateContextLoss; the callback registered for a real loss only writes to stderr. CNA's own plan (WEBGPU-182) records the driver-reported path as not done and unverified, so this is an incomplete feature rather than a broken contract.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDevice::DeviceLost / DeviceReset, getGraphicsDeviceStatusProperty() and the CanBeginDrawEXT() gate behind GraphicsDeviceManager::BeginDraw, on the WEBGPU renderer",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-064.html",
   "sources": [
    "modules/renderers/webgpu/src/WebGPURenderer.cpp",
    "modules/renderers/webgpu/src/WebGPURenderer.cpp",
    "modules/renderers/webgpu/include/CNA/Internal/Renderers/WebGPU/WebGPURenderer.hpp",
    "docs/webgpu-renderer.md",
    "modules/renderers/webgpu/examples/webgpu_context_recovery_test.cpp"
   ],
   "related": [
    "development/architecture/graphics.html",
    "development/internals/graphics/device.html",
    "docs/rendering-backends.html"
   ]
  },
  {
   "id": "CNA-GAP-065",
   "class": "functional-gap",
   "title": "The renderer capability profile has no feature for pre-compiled SPIR-V payloads, so SDL_GPU and VULKAN report every source-dialect feature Unsupported",
   "summary": "BuildRendererCapabilityProfileEXT maps a renderer's declared dialect onto six source-dialect features (desktop GLSL, GLSL ES, Vulkan GLSL, HLSL, MSL, WGSL). SDL_GPU and VULKAN declare SpirV, which CNA documents as already-compiled bytecode rather than source text, so all six read Unsupported by design and the profile has no entry that says a SPIR-V payload is accepted.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::RendererCapabilityProfile ShaderDialect* features (GraphicsDevice::GetRendererCapabilityProfileEXT)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-065.html",
   "sources": [
    "modules/graphics/src/Xna/GraphicsDevice.cpp",
    "modules/renderers/sdl-gpu/include/CNA/Internal/Renderers/SdlGpu/SdlGpuRenderer.hpp",
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp",
    "modules/renderers/vulkan/examples/vulkan_capability_snapshot_test.cpp"
   ],
   "related": [
    "deep-dives/graphics/shader-routes-four-answers.html",
    "deep-dives/renderers/sdl-gpu-pipeline-state-and-draw-order.html"
   ]
  },
  {
   "id": "CNA-GAP-066",
   "class": "functional-gap",
   "title": "A runtime .cnj Texture2D colorKey leaves keyed texels as straight-alpha (key RGB, alpha 0), so they are invisible only under a non-premultiplied blend state",
   "summary": "The loose-tier .cnj Texture2D reader writes Color(keyR, keyG, keyB, 0) into a straight-alpha texture, deliberately: plans/plan_cnj.md CNB-9 defines the result as transparent with alpha 0, and CnjSourceFileTests pins it. Under SpriteBatch's default premultiplied AlphaBlend such a texel adds the key colour instead of vanishing; the compiled route premultiplies after keying and clears it.",
   "subsystem": "Content & XNB/CNB/CNJ",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager::Load<Texture2D>(name) for a .cnj Texture2D document with colorKey; SpriteBatch::Begin() default BlendState::AlphaBlend",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-066.html",
   "sources": [
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/src/Pipeline/Texture2DContentPipeline.cpp",
    "modules/content/src/Internal/CnjCanonicalRead.cpp"
   ],
   "related": [
    "deep-dives/content/cnj-documents.html",
    "deep-dives/practice/porting-case-studies.html",
    "docs/content-manager.html"
   ]
  },
  {
   "id": "CNA-GAP-067",
   "class": "functional-gap",
   "title": "ScrollWheelValue granularity depends on the platform backend: SDL3 drops sub-notch wheel motion, Win32 and Wayland keep it",
   "summary": "The SDL3 platform truncates every wheel event to whole notches before scaling by 120 (a deliberate FNA-parity rule recorded in docs/input-fna-fidelity.md), so high-resolution wheels and touchpads can scroll without changing ScrollWheelValue, while the Win32 and Wayland backends accumulate 1/120 units as XNA does. SDL delivers the fractional amounts and CNA discards them, so this is a narrower contract on the SDL3 backend, not a host constraint.",
   "subsystem": "Input",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "MouseState::getScrollWheelValueProperty() and getHorizontalScrollWheelValueEXTProperty() as reported by Mouse::GetState()",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-067.html",
   "sources": [
    "modules/platform/src/Sdl3/Sdl3InputServices.cpp",
    "modules/platform/src/Sdl3/Sdl3EventMapper.cpp",
    "modules/platform/src/Win32/Win32EventMapper.cpp",
    "modules/platform/src/Wayland/WaylandMouse.cpp",
    "modules/platform/src/X11/X11Mouse.cpp",
    "docs/input-fna-fidelity.md",
    "modules/platform/tests/CNA/Platform/Sdl3InputServicesTests.cpp",
    "modules/platform/tests/CNA/Platform/WaylandMappingTests.cpp"
   ],
   "related": [
    "deep-dives/services/input-model.html",
    "development/internals/input/events.html",
    "docs/input.html"
   ]
  },
  {
   "id": "CNA-GAP-068",
   "class": "functional-gap",
   "title": "Video playback is unavailable on Windows, MinGW, Emscripten, Android and iOS: CNA has no FFmpeg integration for those targets yet",
   "summary": "modules/CMakeLists.txt marks those targets as outside the FFmpeg integration, so CNA_ENABLE_VIDEO=AUTO falls back to the no-video backend and ON fails configuration; Video probing and VideoPlayer::Play then throw NotSupportedException. docs/video-backend.md describes this as 'no target-native FFmpeg integration or decode verification yet' (MEDIA-192 to MEDIA-195), so it is unfinished CNA work rather than a constraint of those platforms.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Video, VideoPlayer and Load<Video> on WIN32/MinGW, Emscripten, Android and iOS builds",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-068.html",
   "sources": [
    "modules/CMakeLists.txt"
   ],
   "related": [
    "deep-dives/services/media-contract.html",
    "development/internals/modules/video-ffmpeg.html"
   ]
  },
  {
   "id": "CNA-GAP-069",
   "class": "functional-gap",
   "title": "Windows builds leave out Sharp Runtime's Xml.Serialization, so the XmlSerializationEXT surface of the math and input types is unavailable there",
   "summary": "On every Windows target CNA leaves Xml.Serialization out of its Sharp Runtime closure and drops both XmlSerializationEXTTests. The exclusion was added to avoid an unguarded <poll.h> in sharp-runtime's Diagnostics, which has since been fixed upstream; it no longer avoids that dependency, because CNA's closure already contains Xml, which depends on Diagnostics, so the surface is unavailable on Windows only because the build condition was left in place.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft/Xna/Framework/XmlSerializationEXT.hpp (math) and Microsoft/Xna/Framework/Input/XmlSerializationEXT.hpp on Windows targets",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-069.html",
   "sources": [
    "cmake/SharpRuntimeConsumption.cmake",
    "cmake/UnitTests.cmake",
    "modules/math/include/Microsoft/Xna/Framework/XmlSerializationEXT.hpp",
    "modules/input/include/Microsoft/Xna/Framework/Input/XmlSerializationEXT.hpp"
   ],
   "related": [
    "deep-dives/sharp-runtime/components-and-consumption.html",
    "docs/platforms.html"
   ]
  },
  {
   "id": "CNA-GAP-070",
   "class": "functional-gap",
   "title": "NetworkSession's Begin/End pairs are synchronous: the result is complete and the callback has run when Begin returns, and End does the work on the caller's thread",
   "summary": "NetworkSession's BeginCreate, BeginFind and BeginJoin each return an already-completed IAsyncResult (CompletedSynchronously still false) and run their AsyncCallback inline; End* then blocks the caller: 150 ms for a native SystemLink Find, up to 5 s for a native Join. BeginJoinInvited is not part of this: it refuses outright.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Net::NetworkSession::BeginCreate/BeginFind/BeginJoin/BeginJoinInvited and the matching End* methods",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-070.html",
   "sources": [
    "modules/net/src/Xna/NetworkSession.cpp",
    "modules/net/include/Microsoft/Xna/Framework/Net/NetworkSession.hpp",
    "modules/net/src/Internal/ENetDiscoveryService.cpp"
   ],
   "related": [
    "deep-dives/services/network-sessions.html",
    "development/internals/modules/net.html"
   ]
  },
  {
   "id": "CNA-GAP-071",
   "class": "functional-gap",
   "title": "GraphicsDevice is single-threaded: its resource registry has no lock and only EasyGL and OpenGL4 lease a context, so resource creation from a loading thread is supported only for ContentManager loads on those two",
   "summary": "GraphicsDevice has no lock: GraphicsResource construction and disposal update its resource registry, and only EasyGL and OpenGL4 return a context lease (taken by frames and ContentManager loads), while XNA 4.0 creates its device D3DCREATE_MULTITHREADED.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Graphics::GraphicsDevice and GraphicsResource: creating or disposing resources from a thread other than the game thread",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/gaps/cna-gap-071.html",
   "sources": [
    "modules/graphics/src/Xna/GraphicsDevice.cpp",
    "modules/graphics/src/Xna/GraphicsResource.cpp",
    "modules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp",
    "modules/content/src/Xna/ContentReader.cpp",
    "modules/runtime/src/GraphicsDeviceManager.cpp",
    "modules/renderers/easygl/src/EasyGLRenderer.cpp",
    "modules/renderers/opengl4/src/OpenGL4Renderer.cpp",
    "modules/renderers/vulkan/examples/vulkan_thread_context_lease_test.cpp"
   ],
   "related": [
    "deep-dives/renderers/renderer-contract.html",
    "development/takeover/threading.html"
   ]
  },
  {
   "id": "CNA-PLAT-001",
   "class": "platform-limitation",
   "title": "CANVAS, FREEDIRECT, SDL_RENDERER, HTML_DOM and SVG_DOM throw for any Texture2D mip level above 0, so mipmapped textures (including XNB textures with mip chains) cannot be uploaded there",
   "summary": "The texture renderers of CANVAS, FREEDIRECT, SDL_RENDERER, HTML_DOM and SVG_DOM throw std::runtime_error from UpdatePixelsLevel for level > 0 because Canvas 2D, DirectDraw, SDL_Renderer and DOM surfaces have no mip chain; the XNB Texture2D reader uploads every level it reads.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Texture2D::SetData(level > 0, ...) and ContentManager::Load<Texture2D> of mipmapped assets on CANVAS and FREEDIRECT",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/limitations/cna-plat-001.html",
   "sources": [
    "modules/renderers/canvas/src/CanvasTextureRenderer.cpp",
    "modules/renderers/freedirect/src/FreeDirectRenderer.cpp",
    "modules/content/src/Xnb/Texture2DContentTypeReader.cpp"
   ],
   "related": [
    "deep-dives/graphics/texture-data-transfer.html",
    "deep-dives/renderers/browser-dom-renderers.html"
   ]
  },
  {
   "id": "CNA-PLAT-002",
   "class": "platform-limitation",
   "title": "SDL_GPU ignores BlendState.MultiSampleMask because SDL_gpu reserves its sample-mask fields",
   "summary": "SDL 3.5.0 documents SDL_GPUMultisampleState::sample_mask/enable_mask as reserved (must be 0/false), so SdlGpuRenderer::ApplyBlendState drops the mask and a partial MultiSampleMask renders all samples without an error.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "BlendState.MultiSampleMask / GraphicsDevice.MultiSampleMask on SDL_GPU",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/limitations/cna-plat-002.html",
   "sources": [
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp",
    "modules/renderers/sdl-gpu/examples/CMakeLists.txt"
   ],
   "related": [
    "deep-dives/graphics/state-objects.html",
    "deep-dives/renderers/sdl-gpu-pipeline-state-and-draw-order.html"
   ]
  },
  {
   "id": "CNA-PLAT-003",
   "class": "platform-limitation",
   "title": "EasyGL on GLES/WebGL contexts without GL_NV_polygon_mode or WEBGL_polygon_mode refuses wireframe triangle draws",
   "summary": "FillMode::WireFrame triangle draws throw NotSupportedException there instead of being approximated with lines; GraphicsCapability::WireFrame reports false so a game can choose Solid.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "RasterizerState.FillMode = WireFrame on the GLES and WebGL EasyGL profiles",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/limitations/cna-plat-003.html",
   "sources": [
    "modules/renderers/easygl/src/EasyGLRenderer.cpp"
   ],
   "related": [
    "deep-dives/renderers/easygl-state-and-resource-semantics.html"
   ]
  },
  {
   "id": "CNA-PLAT-004",
   "class": "platform-limitation",
   "title": "On OpenGL ES 3.0 and WebGL 2 contexts OcclusionQuery::PixelCount is boolean (0 or 1)",
   "summary": "ES 3.0 and WebGL 2 only offer GL_ANY_SAMPLES_PASSED, so EasyGL reports whether any sample passed rather than how many; the public OcclusionQuery::isPixelCountPreciseEXT() reports which kind of count is in effect, but only after the first query has begun.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Graphics::OcclusionQuery::PixelCount on EasyGL GLES/WebGL profiles",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/limitations/cna-plat-004.html",
   "sources": [
    "modules/renderers/easygl/src/EasyGLRenderer.cpp"
   ],
   "related": [
    "deep-dives/renderers/easygl-state-and-resource-semantics.html"
   ]
  },
  {
   "id": "CNA-PLAT-005",
   "class": "platform-limitation",
   "title": "SDL_GPU cannot create OcclusionQuery objects because SDL_gpu 3.5.0 has no occlusion-query commands",
   "summary": "SdlGpuRenderer::CreateOcclusionQuery throws NotSupportedException: SDL_gpu exposes no query pools, and its fences report only command-buffer completion.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Graphics::OcclusionQuery on SDL_GPU",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/limitations/cna-plat-005.html",
   "sources": [
    "modules/renderers/sdl-gpu/src/SdlGpuRenderer.cpp"
   ],
   "related": [
    "deep-dives/renderers/sdl-gpu-resources-and-frame-recovery.html"
   ]
  },
  {
   "id": "CNA-PLAT-006",
   "class": "platform-limitation",
   "title": "Under Wine or Proton, Direct2D lacks the ColorMatrix effect and ignores bounded-copy and Porter-Duff composite modes, so tinted or NonPremultiplied RenderTarget2D sprite sources throw there",
   "summary": "The Direct2D parity test skips its render-target decoration and advanced-blend matrices on those runtimes, and a tinted or NonPremultiplied RenderTarget2D sprite source throws NotSupportedException there (D2D-85).",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "recorded-by-cna",
   "tests_present": true,
   "public_contract": "SpriteBatch drawing a RenderTarget2D with a tint or NonPremultiplied blend on DIRECT2D under Wine/Proton",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/limitations/cna-plat-006.html",
   "sources": [
    "modules/renderers/direct2d/examples/CMakeLists.txt",
    "modules/renderers/direct2d/src/Direct2DRenderer.cpp"
   ],
   "related": [
    "deep-dives/renderers/windows-2d-renderers.html"
   ]
  },
  {
   "id": "CNA-PLAT-007",
   "class": "platform-limitation",
   "title": "On browsers without mix-blend-mode: plus-lighter, HTML_DOM and SVG_DOM draw BlendState.Additive as ordinary composition without an error",
   "summary": "The renderers set mix-blend-mode to plus-lighter for additive sprites; a browser that does not support it ignores the value, and only the memoised AdditiveBlending capability (CSS.supports) reveals the difference.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "SpriteBatch with BlendState::Additive on HTML_DOM and SVG_DOM",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/limitations/cna-plat-007.html",
   "sources": [
    "modules/renderers/html-dom/src/HtmlDomSpriteBatchRenderer.cpp",
    "modules/renderers/html-dom/src/HtmlDomRenderer.cpp",
    "modules/renderers/svg-dom/src/SvgDomRenderer.cpp"
   ],
   "related": [
    "deep-dives/renderers/browser-dom-renderers.html"
   ]
  },
  {
   "id": "CNA-PLAT-009",
   "class": "platform-limitation",
   "title": "Android Compass and Motion: stopping waits at most five seconds for the sensor worker, after which the bridge is abandoned for good and a handler still running can outlive its owner",
   "summary": "AndroidSensorBridge::Stop gives a wedged worker five seconds and then detaches it, marking the bridge permanently unable to start; a Compass or Motion destroyed after such a timeout, while a callback is still inside it, is an unsupported window.",
   "subsystem": "Input",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Devices::Sensors::Compass and Motion on Android (AndroidCompassBackend and AndroidMotionBackend over Detail::AndroidSensorBridge): Start(), Stop(), Dispose() and destruction",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/limitations/cna-plat-009.html",
   "sources": [
    "modules/devices/src/Sensors/Detail/AndroidSensorBridge.cpp",
    "modules/devices/include/Microsoft/Devices/Sensors/Detail/SensorOwnerControlBlock.hpp",
    "modules/devices/src/Sensors/Compass.cpp",
    "modules/devices/src/Sensors/Motion.cpp",
    "modules/devices/include/Microsoft/Devices/Sensors/Detail/AndroidCompassBackend.hpp"
   ],
   "related": [
    "deep-dives/services/sensors-and-vibration.html",
    "development/internals/modules/devices.html",
    "development/takeover/threading.html"
   ]
  },
  {
   "id": "CNA-PLAT-011",
   "class": "platform-limitation",
   "title": "Under Emscripten nothing mounts a persistent file system, so saves and the local gamer-services store are lost on page reload",
   "summary": "No IDBFS mount or FS.syncfs call exists in the tree, so storage writes go to Emscripten's in-memory file system.",
   "subsystem": "Storage",
   "status": "open",
   "severity": "n/a",
   "confidence": "strong",
   "tests_present": false,
   "public_contract": "StorageDevice/StorageContainer and LocalGamerServicesStore in Emscripten builds",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/limitations/cna-plat-011.html",
   "sources": [
    "modules/storage/src/StorageContainer.cpp",
    "modules/storage/src/StorageDevice.cpp"
   ],
   "related": [
    "deep-dives/platforms/web-build-and-main-loop.html",
    "docs/storage.html"
   ]
  },
  {
   "id": "CNA-PLAT-012",
   "class": "platform-limitation",
   "title": "Under Emscripten, SystemLink discovery is empty, hosting binds the fixed port 61191 and Join returns before the handshake",
   "summary": "The web build stubs out discovery (Find returns nothing), hosts on a fixed port only a Node.js relay can use, rebuilds a joining session as an outbound-only client and returns from Join before the server welcome; Node.js-run unit tests cover discovery and loopback handshakes, but no browser or two-process test exists.",
   "subsystem": "Networking & gamer services",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Net::NetworkSession Create, Find, Join and Update for NetworkSessionType::SystemLink in Emscripten builds",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/limitations/cna-plat-012.html",
   "sources": [
    "modules/net/src/Internal/ENetDiscoveryService.cpp",
    "modules/net/src/Internal/ENetBackend.cpp",
    "modules/net/src/Xna/NetworkSession.cpp",
    "cmake/UnitTests.cmake",
    "modules/net/examples/CMakeLists.txt"
   ],
   "related": [
    "deep-dives/services/network-sessions.html",
    "development/internals/modules/net.html",
    "docs/tutorials/97-networking.html"
   ]
  },
  {
   "id": "CNA-PLAT-013",
   "class": "platform-limitation",
   "title": "Wayland gives no desktop pointer position, and browsers hide gamepads until a button press and gate pointer lock on a user gesture",
   "summary": "On native Wayland the global-pointer functions are unsupported; on the web a gamepad appears only after the player presses a button on it, and relative mouse mode engages only after a click.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Mouse::GetGlobalPositionEXT / WarpGlobalEXT / SetCaptureEXT on Wayland; GamePad connection and Mouse relative mode in Emscripten builds",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/limitations/cna-plat-013.html",
   "sources": [
    "modules/platform/src/Wayland/WaylandMouse.cpp",
    "docs/platform-input-notes.md"
   ],
   "related": [
    "deep-dives/services/input-model.html",
    "docs/input.html"
   ]
  },
  {
   "id": "CNA-PLAT-014",
   "class": "platform-limitation",
   "title": "Compass and Motion work only on Android; desktop sensors come only through the SDL3 platform, and web targets are refused",
   "summary": "Compass::IsSupported and Motion::IsSupported are false everywhere except Android because SDL3 exposes no magnetometer or fused-orientation API; Accelerometer and Gyroscope are supported on Android, iOS and desktop but never in a browser.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Compass, Motion, Accelerometer and Gyroscope IsSupported per target",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/limitations/cna-plat-014.html",
   "sources": [
    "modules/devices/src/Sensors/Compass.cpp",
    "modules/devices/src/Sensors/Motion.cpp",
    "modules/devices/src/Sensors/Accelerometer.cpp"
   ],
   "related": [
    "deep-dives/services/sensors-and-vibration.html",
    "docs/sensors.html"
   ]
  },
  {
   "id": "CNA-VGAP-001",
   "class": "verification-gap",
   "title": "Matrix camera builders have no XNA oracle and no full-matrix value test",
   "summary": "CreateLookAt and the perspective and orthographic builders are asserted only on single terms and covered indirectly by consumer tests; CNA's XNA matrix oracle does not include them.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Matrix::CreateLookAt, CreatePerspective, CreatePerspectiveFieldOfView, CreatePerspectiveOffCenter, CreateOrthographic and CreateOrthographicOffCenter",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-001.html",
   "sources": [
    "modules/math/src/Matrix.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/MatrixTests.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/MatrixOracleTests.cpp",
    "tests/reference/xna40/framework/matrix-oracle.txt",
    "modules/c-api/tests/pure_c/MatrixSmoke.c",
    "modules/graphics/tests/Microsoft/Xna/Framework/Graphics/ViewportTests.cpp"
   ],
   "related": [
    "deep-dives/foundations/compatibility-and-evidence.html",
    "development/internals/modules/math.html",
    "development/testing/architecture.html",
    "docs/verification.html"
   ]
  },
  {
   "id": "CNA-VGAP-002",
   "class": "verification-gap",
   "title": "BoundingSphere::CreateFromBoundingBox and the SmoothStep/Hermite/CatmullRom helpers use different arithmetic from XNA 4.0, and no oracle measures last-bit agreement",
   "summary": "CreateFromBoundingBox and the SmoothStep/Hermite/CatmullRom helpers compute with formulas or precision that differ from XNA's, and only CreateFromPoints has an XNA oracle.",
   "subsystem": "Math & geometry",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "BoundingSphere::CreateFromBoundingBox; MathHelper::SmoothStep, Hermite, CatmullRom; Vector2/3/4::SmoothStep and Hermite",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-002.html",
   "sources": [
    "modules/math/src/BoundingSphere.cpp",
    "modules/math/src/MathHelper.cpp",
    "modules/math/src/Vector3.cpp",
    "modules/math/tests/Microsoft/Xna/Framework/BoundingSphereOracleTests.cpp"
   ],
   "related": [
    "deep-dives/framework/vector-matrix-numerics.html",
    "development/internals/modules/math.html"
   ]
  },
  {
   "id": "CNA-VGAP-003",
   "class": "verification-gap",
   "title": "No test pins EffectParameter's divergences for CNA-constructed parameters, including a SetValue(Texture*) that GetValueTexture2D() does not read back",
   "summary": "Parameters without compiled storage keep separate base and typed texture slots and refuse numeric access only for Object-class parameters; the C API smoke test exercises the lenient string, numeric and texture setters, but no test pins that a texture set through the base overload reads back as null, or that the numeric refusal is by class rather than by storage.",
   "subsystem": "Graphics & renderers",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Graphics::EffectParameter SetValue/GetValue on stock-effect and standalone parameters",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-003.html",
   "sources": [
    "modules/graphics/src/Xna/EffectParameter.cpp",
    "tests/support/CNA/TestSupport/CompiledEffectConformance.hpp"
   ],
   "related": [
    "deep-dives/graphics/effect-object-model.html"
   ]
  },
  {
   "id": "CNA-VGAP-004",
   "class": "verification-gap",
   "title": "The Linux evdev controller-mapping reader is tested only on hand-written entries in CI; the real-database test always skips",
   "summary": "LinuxEvdevMapping.EveryEntryOfADatabaseFileIsRead skips unless CNA_TEST_GAMECONTROLLERDB names a file, no workflow sets it, and mapped-pad behaviour with physical generic HID pads has no recorded evidence.",
   "subsystem": "Input",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA_GAMECONTROLLERCONFIG_FILE / CNA_GAMECONTROLLERCONFIG on the X11 and Wayland evdev gamepad hub",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-004.html",
   "sources": [
    "modules/platform/tests/CNA/Platform/LinuxEvdevMappingTests.cpp",
    "modules/platform/src/Linux/EvdevMapping.cpp"
   ],
   "related": [
    "deep-dives/services/gamepads-and-haptics.html",
    "docs/input.html"
   ]
  },
  {
   "id": "CNA-VGAP-005",
   "class": "verification-gap",
   "title": "The XNA audio facade on CNA's own ALSA mixer is covered by seven facade tests plus the XACT category suite; the SoundEffect, instance, dynamic-instance, Cue, SoundBank and WaveBank suites run only on SDL3",
   "summary": "Under CNA_AUDIO_PLATFORM=ALSA, eight SDL3_mixer-bound suites (about 440 test definitions) are filtered out, so SoundEffect, SoundEffectInstance and DynamicSoundEffectInstance behaviour on CNA's mixer rests on seven facade cases, and Cue, SoundBank and WaveBank playback on the twelve AudioCategoryTests cases that play cues from real banks.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Xna::Framework::Audio (SoundEffect, SoundEffectInstance, DynamicSoundEffectInstance, AudioEngine, Cue, SoundBank, WaveBank) under CNA_AUDIO_PLATFORM=ALSA",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-005.html",
   "sources": [
    "cmake/UnitTests.cmake",
    "modules/audio/tests/Microsoft/Xna/Framework/Audio/CnaMixerXnaTests.cpp",
    "modules/audio/tests/CNA/Internal/Audio/CnaMixerTests.cpp",
    "modules/audio/src/Backend/CnaMixer/MixerEngine.cpp",
    ".github/workflows/platform-ci.yml"
   ],
   "related": [
    "deep-dives/services/sound-effects-and-streaming.html",
    "development/internals/audio/engine.html",
    "development/testing/architecture.html",
    "docs/audio.html",
    "docs/tutorials/137-alsa-audio.html"
   ]
  },
  {
   "id": "CNA-VGAP-006",
   "class": "verification-gap",
   "title": "Media paths without tests: the natural song end on SDL3_mixer, the failed visualization install, MediaLibrary accessors after Dispose and SavePicture's IOException",
   "summary": "The song-ended callback path on the default SDL3 audio, the visualization branch where no tap can be installed, MediaLibrary disposal semantics and SavePicture's write-failure exception are implemented but untested.",
   "subsystem": "Audio & media",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "MediaPlayer::Update end-of-song handling, MediaPlayer::setIsVisualizationEnabledProperty, MediaLibrary::Dispose and MediaLibrary::SavePicture",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-006.html",
   "sources": [
    "modules/media/src/Xna/MediaPlayer.cpp",
    "modules/media/tests/Microsoft/Xna/Framework/Media/MediaPlayerTests.cpp",
    "modules/media/src/Xna/MediaLibrary.cpp",
    "modules/media/tests/Microsoft/Xna/Framework/Media/MediaLibraryTests.cpp",
    "modules/media/tests/CNA/Internal/Media/SavedPictureStoreTests.cpp"
   ],
   "related": [
    "development/internals/modules/media.html",
    "development/testing/architecture.html"
   ]
  },
  {
   "id": "CNA-VGAP-007",
   "class": "verification-gap",
   "title": "The SDL3 camera provider, system-tray icon and file-dialog result path have no test that drives them",
   "summary": "Sdl3Camera.cpp, Sdl3Tray.cpp and the SDL3 dialog trampoline are exercised by no test beyond capability presence and empty-callback refusal, and the CNA::Devices suites above them use canned platforms.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The SDL3 camera provider and sessions, tray icons and file dialogs (Sdl3CameraProvider, Sdl3Tray, Sdl3Dialogs) behind CNA::Devices::Camera, SystemTray and FileDialog",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-007.html",
   "sources": [
    "modules/platform/src/Sdl3/Sdl3Camera.cpp",
    "modules/platform/src/Sdl3/Sdl3Tray.cpp",
    "modules/platform/src/Sdl3/Sdl3SystemServices.cpp",
    "modules/platform/tests/CNA/Platform/Sdl3PlatformTests.cpp",
    "modules/platform/tests/CNA/Platform/Sdl3SystemServicesTests.cpp",
    "modules/devices-ext/tests/CNA/Devices/CameraTests.cpp",
    "modules/platform/tests/CNA/Platform/X11TrayTests.cpp"
   ],
   "related": [
    "deep-dives/services/host-devices.html",
    "development/internals/modules/devices-ext.html",
    "development/internals/platforms/sdl3.html"
   ]
  },
  {
   "id": "CNA-VGAP-008",
   "class": "verification-gap",
   "title": "Android and iOS have no device evidence at this snapshot: no Android workflow, one iOS simulator frame, and lifecycle and packaged-content loading untested on a device",
   "summary": "Android has no preset or workflow, iOS evidence is a device final-link plus a one-frame simulator launch, lifecycle is tested only with scripted host events, and no test loads packaged content on a device.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Android and iOS as CNA targets (Game lifecycle, ContentManager with a relative root, TitleLocation)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-008.html",
   "sources": [
    "docs/devices-build.md",
    ".github/workflows/apple-ci.yml",
    "cmake/ApplePlatform.cmake",
    "modules/runtime/tests/Microsoft/Xna/Framework/GameTests.cpp",
    "tests/apple/apple_smoke.cpp",
    "modules/runtime/src/TitleLocation.cpp",
    "modules/devices/examples/demo_devices/android/com.openeggbert.cna.demodevices/app/jni/CMakeLists.txt",
    "modules/devices/examples/demo_devices/android/com.openeggbert.cna.demodevices/app/build.gradle",
    "CMakePresets.json",
    ".github/workflows/devices-tests.yml"
   ],
   "related": [
    "deep-dives/platforms/android-and-apple-platforms.html",
    "docs/platforms.html"
   ]
  },
  {
   "id": "CNA-VGAP-009",
   "class": "verification-gap",
   "title": "GraphicsDeviceManager's iOS/Android back-buffer orientation branch has no test",
   "summary": "On iOS and Android GraphicsDeviceManager reshapes the preferred back buffer by DisplayOrientation and forwards SupportedOrientations to the window; the desktop test skips itself on those platforms, and the only run that reaches the branch is the iOS simulator smoke application, which asserts that a frame completes but not the back-buffer shape or the forwarded orientations.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "GraphicsDeviceManager::PreferredBackBufferWidth/Height and SupportedOrientations on iOS and Android",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-009.html",
   "sources": [
    "modules/runtime/src/GraphicsDeviceManager.cpp",
    "modules/runtime/tests/Microsoft/Xna/Framework/GraphicsDeviceManagerPlatformTests.cpp"
   ],
   "related": [
    "deep-dives/framework/window-and-device-manager.html",
    "deep-dives/platforms/android-and-apple-platforms.html"
   ]
  },
  {
   "id": "CNA-VGAP-010",
   "class": "verification-gap",
   "title": "No CI workflow builds or tests the OPENGL4 renderer",
   "summary": "OPENGL4, declared Supported and merged at this snapshot with several hundred family CTests, is named by none of the 20 workflows, so its evidence is CNA's recorded runs on one Radeon 780M under Mesa, and Windows and macOS are unvalidated.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The OPENGL4 renderer identity (GraphicsBackendMaturity::Supported) and its CTest suites",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-010.html",
   "sources": [
    "docs/opengl4-renderer.md",
    "modules/core/include/CNA/GraphicsBackendMaturity.hpp",
    "modules/renderers/opengl4/examples/CMakeLists.txt",
    "cmake/TestHelpers.cmake",
    "CMakePresets.json",
    "plans/plan_opengl4_modern_graphics.md"
   ],
   "related": [
    "development/internals/graphics/opengl4.html",
    "development/testing/architecture.html",
    "docs/verification.html"
   ]
  },
  {
   "id": "CNA-VGAP-011",
   "class": "verification-gap",
   "title": "No test exercises PlatformSelection.cmake's reserved-identifier and unknown-name refusal paths",
   "summary": "PlatformSelection.cmake fails configure for SDL12, EMSCRIPTEN, WIN32 off Windows, TERMINAL on Windows and unknown names, but the only platform-selection configure test, CnaWaylandPlatformSelection, covers Wayland alone.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "cmake/PlatformSelection.cmake configure-time refusals for reserved and unknown CNA_PLATFORM values",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-011.html",
   "sources": [
    "cmake/PlatformSelection.cmake",
    "cmake/UnitTests.cmake",
    "cmake/Tests/WaylandPlatformSelection.cmake"
   ],
   "related": [
    "development/handbook/change-build-configuration.html",
    "development/internals/platforms/index.html",
    "development/testing/architecture.html",
    "docs/platforms.html"
   ]
  },
  {
   "id": "CNA-VGAP-012",
   "class": "verification-gap",
   "title": "No CI workflow selects CNA_PLATFORM=WAYLAND, so the native Wayland backend's suites run only on a developer's machine",
   "summary": "The Wayland ctest suites are registered only under CNA_PLATFORM=WAYLAND and launched through tools/platform/wayland_test_server.sh, but no GitHub workflow configures that platform, so the native Wayland backend has no continuous integration.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Continuous-integration coverage of the CNA::Platform::Wayland backend",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-012.html",
   "sources": [
    ".github/workflows/platform-ci.yml",
    "cmake/UnitTests.cmake",
    "tools/platform/wayland_test_server.sh"
   ],
   "related": [
    "development/internals/platforms/wayland.html",
    "development/testing/architecture.html",
    "docs/native-platforms.html"
   ]
  },
  {
   "id": "CNA-VGAP-013",
   "class": "verification-gap",
   "title": "No gate checks include reachability or compiles each public C++ header alone; the two scripts that did are stale campaign tools wired to nothing",
   "summary": "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.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "modularization/tools/check_include_reachability.py; modularization/tools/check_header_self_containment.py; the physical module include contract",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-013.html",
   "sources": [
    "modularization/tools/check_include_reachability.py",
    "modularization/tools/check_header_self_containment.py",
    "docs/physical-modules.md",
    "modules/platform/tests/CNA/Platform/ContractIsSdlFreeTests.cpp",
    "cmake/Tests/ModuleProbes.cmake"
   ],
   "related": [
    "deep-dives/build/dependency-boundaries.html",
    "development/repository/module-graph.html"
   ]
  },
  {
   "id": "CNA-VGAP-014",
   "class": "verification-gap",
   "title": "The physical source-partition validator checks only *.cpp/*.mm path prefixes, so headers, C sources and a TU in a renderer's src/ subdirectory (never compiled) all pass it",
   "summary": "modules/CMakeLists.txt's no-loss ownership gate globs only .cpp and .mm and compares path prefixes, while cna_add_renderer globs src/*.cpp non-recursively, so a new TU under src/<subdir>/ passes configure and is silently not built.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "modules/CMakeLists.txt physical source-partition validator; modules/renderers/CMakeLists.txt cna_add_renderer",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-014.html",
   "sources": [
    "modules/CMakeLists.txt",
    "modules/renderers/CMakeLists.txt"
   ],
   "related": [
    "deep-dives/build/module-architecture.html"
   ]
  },
  {
   "id": "CNA-VGAP-015",
   "class": "verification-gap",
   "title": "CNA records and checks no easy-gl or meta-gl revision, although the snapshot needs meta-gl 20c8b2dc or later and easy-gl deda7a42 or later",
   "summary": "EasyGLRenderer.cpp needs meta-gl's InternalFormat::Rgba16 (from 20c8b2dc) and RendererSelection.cmake relies on easy-gl's exception-model variable (from deda7a42), yet nothing pins or checks either sibling revision.",
   "subsystem": "Build & CI",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": false,
   "public_contract": "GL-family builds (OPENGLES2, OPENGLES3, OPENGL33, WEBGL1, WEBGL2) consuming ../easy-gl and ../meta-gl",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-015.html",
   "sources": [
    "modules/renderers/easygl/src/EasyGLRenderer.cpp",
    "cmake/RendererSelection.cmake",
    "cmake/BuildPerformance.cmake",
    "scripts/ci/clone_siblings.sh",
    "integration/FINAL_RECONCILIATION.md"
   ],
   "related": [
    "deep-dives/build/third-party-dependencies.html",
    "deep-dives/siblings/easygl-and-metagl.html",
    "docs/building.html"
   ]
  },
  {
   "id": "CNA-VGAP-016",
   "class": "verification-gap",
   "title": "A plain ctest run of the tests preset is not a trustworthy result",
   "summary": "CNA's own tests preset records that ctest reports unbuilt display-dependent smoke executables as failed and races tests that share hard-coded /tmp fixture paths across processes, so only a direct CnaTests run is authoritative.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "recorded-by-cna",
   "tests_present": true,
   "public_contract": "ctest over a build of the tests preset (CMakePresets.json)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-016.html",
   "sources": [
    "CMakePresets.json",
    "cmake/UnitTests.cmake"
   ],
   "related": [
    "development/takeover/validation.html",
    "development/testing/architecture.html",
    "development/testing/index.html"
   ]
  },
  {
   "id": "CNA-VGAP-017",
   "class": "verification-gap",
   "title": "graphics-ext shader-package drift guards have holes: no reproducibility check for shadow_caster, none run in CI, desktop clustered-forward fragment unpinned",
   "summary": "Two checked-in packages (shadow_caster and the test package modern_resource_interop) have no ShaderPackageReproducibility CTest, CI installs no shaderc so every such CTest skips, and only the ES clustered-forward fragment is pinned to the public GLSL helpers.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Checked-in shader packages of modules/graphics-ext (package.json plus generated header) used by ShadowMap, SpotShadowMap and ClusteredForwardEffect",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-017.html",
   "sources": [
    "cmake/Tests/ModuleProbes.cmake",
    "modules/graphics-ext/src/shaders/shadow_caster/package.json",
    "modules/graphics-ext/src/ShadowCasterShaderPackages.cpp",
    "modules/graphics-ext/tests/CNA/Graphics/shaders/modern_resource_interop/package.json",
    "tools/shader_package/generate_shader_package.py",
    "modules/graphics-ext/tests/CNA/Graphics/ClusteredForwardEffectTests.cpp",
    "modules/graphics-ext/src/shaders/clustered_forward/forward.desktop.frag.glsl"
   ],
   "related": [
    "development/internals/modules/graphics-ext.html",
    "development/testing/architecture.html",
    "docs/cnaext-engine.html"
   ]
  },
  {
   "id": "CNA-VGAP-018",
   "class": "verification-gap",
   "title": "No test asserts RenderPipeline's fixed post-process order; the order-named tests only count passes",
   "summary": "RenderPipeline::end() adds up to fourteen built-in passes and the user passes in a deliberate order, but the three tests named after that order assert only getLastFramePassCount(), so any permutation passes.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Built-in pass order of CNA::Graphics::RenderPipeline::end() (CNAEXT engine layer)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-018.html",
   "sources": [
    "modules/graphics-ext/src/RenderPipeline.cpp",
    "modules/graphics-ext/tests/CNA/Graphics/RenderPipelineTests.cpp",
    "modules/graphics-ext/tests/CNA/Graphics/PassTimingTests.cpp"
   ],
   "related": [
    "development/internals/modules/graphics-ext.html",
    "development/testing/architecture.html",
    "docs/cnaext-engine.html"
   ]
  },
  {
   "id": "CNA-VGAP-019",
   "class": "verification-gap",
   "title": "ModuleLinkClosure_* link-closure gates report CTest SKIP in every Ninja tree, so no Ninja-preset run and no CI job ever evaluates them",
   "summary": "check_module_link_closure.py reads the make-only CMakeFiles/<target>.dir/link.txt and exits 77 when it is missing; the Ninja presets and every CI job either use Ninja or never run these tests, so CNA's module dependency contracts are not checked automatically.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The ModuleLinkClosure_* CTests registered by cmake/Tests/ModuleProbes.cmake (cna_add_module_probe and the CnaExtComposition, NetHasENet, NativeSdkFree_*, GraphicsNativeSdkFree and VulkanRendererClosure probes)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-019.html",
   "sources": [
    "scripts/check_module_link_closure.py",
    "cmake/Tests/ModuleProbes.cmake",
    "CMakePresets.json",
    ".github/workflows/general-tests-ci.yml"
   ],
   "related": [
    "deep-dives/reference/verification-tiers.html",
    "development/handbook/conventions.html",
    "development/reference/test-targets.html",
    "development/repository/index.html",
    "development/testing/architecture.html"
   ]
  },
  {
   "id": "CNA-VGAP-020",
   "class": "verification-gap",
   "title": "The hand-written CnaPlatformTests filter misses TerminalPresenterThroughPlatformTest and eight other platform suites, so the platform CI cells never select them",
   "summary": "CnaPlatformTests selects suites by hand-written name tokens: TerminalPresenter.* misses TerminalPresenterThroughPlatformTest, and eight more platform suites (key codes, scancodes, filesystem, sensor session, SDL3 device services, SDL3 input devices, SDL3 exit under lock) match no platform filter. Only four of their cases are selected, by the input filter's case-name tokens.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "cmake/UnitTests.cmake CnaPlatformTests filter coverage of the platform suites (the terminal presenter through-the-platform case and eight others)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-020.html",
   "sources": [
    "cmake/UnitTests.cmake",
    "modules/platform/tests/CNA/Platform/TerminalPresenterTests.cpp"
   ],
   "related": [
    "development/internals/platforms/terminal.html",
    "development/testing/architecture.html",
    "docs/platforms.html"
   ]
  },
  {
   "id": "CNA-VGAP-021",
   "class": "verification-gap",
   "title": "No SpriteFont/DrawString pixel test exists for DIRECTX9, DIRECT2D, GDI, METAL, CANVAS, SVG_DOM, PORTABLEGL or FNA3D",
   "summary": "SpriteFont/DrawString reach pixels in a registered test on EasyGL, OPENGL4, SOFTWARE, SDL_RENDERER, VULKAN, SDL_GPU and WEBGPU (the latter two through the shared sprite_font parity fixture), the DIRECTX11/12 parity set, FREEDIRECT and, in its browser suite, HTML_DOM. Eight families rely on shared glyph-layout code without any text pixel test.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "SpriteBatch::DrawString / SpriteFont rendering per renderer",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-021.html",
   "sources": [
    "cmake/DirectXParityTests.cmake",
    "modules/renderers/opengl4/examples/EasyGLParityCorpus.cmake"
   ],
   "related": [
    "deep-dives/graphics/spritefont-text-layout.html"
   ]
  },
  {
   "id": "CNA-VGAP-022",
   "class": "verification-gap",
   "title": "No test measures presentation cadence: PresentInterval::Two against ordinary vsync, or Vulkan's FIFO_RELAXED late-frame behaviour",
   "summary": "The registered interval tests on EasyGL, SDL_RENDERER, SDL_GPU, VULKAN and the shared forwarding contract check storage, forwarding and the selected present mode, not the resulting frame timing.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "PresentationParameters.PresentationInterval (One, Two, Immediate) and the renderers' swap-interval / present-mode mapping",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-022.html",
   "sources": [
    "modules/renderers/vulkan/examples/vulkan_swap_interval_test.cpp",
    "modules/graphics/examples/swap_interval_forwarding_contract_test.cpp"
   ],
   "related": [
    "deep-dives/framework/game-time-and-timestep.html",
    "deep-dives/renderers/vulkan-presentation-and-readback.html"
   ]
  },
  {
   "id": "CNA-VGAP-023",
   "class": "verification-gap",
   "title": "Most browser renderer paths are never executed automatically: WEBGL1/WEBGL2 have no test registrations, CANVAS has no registered browser run, and SVG_DOM runs only through a manual script",
   "summary": "WebGL identities have no test registrations and CI only builds a WEBGL2 bundle, CANVAS test programs are not registered, and the DOM host-contract suites are opt-in with no workflow; only HTML_DOM has a CI browser run.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "WEBGL1, WEBGL2, CANVAS, SVG_DOM (and HTML_DOM host contracts) renderer identities",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-023.html",
   "sources": [
    "modules/renderers/easygl/examples/CMakeLists.txt",
    "modules/renderers/canvas/examples/CMakeLists.txt",
    "modules/renderers/CMakeLists.txt",
    "scripts/run-svgdom-browser-test.sh",
    ".github/workflows/emscripten-multi-renderer-ci.yml",
    ".github/workflows/htmldom-ci.yml",
    "scripts/run-htmldom-test-suite.sh"
   ],
   "related": [
    "deep-dives/platforms/web-build-and-main-loop.html",
    "deep-dives/renderers/browser-dom-renderers.html"
   ]
  },
  {
   "id": "CNA-VGAP-024",
   "class": "verification-gap",
   "title": "METAL's CI lane proves construction, clear/present and capability reporting but no representative 3D pixels",
   "summary": "metal-macos-ci.yml runs only ctest -R '^Metal' (Metal_Smoke, Metal_Capabilities, Metal_PortableHelpers) and the compile-definition tests; no textured, lit or depth-tested 3D output is checked on macOS.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The METAL renderer's 3D pipeline (stock effects, depth, textures) on macOS",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-024.html",
   "sources": [
    ".github/workflows/metal-macos-ci.yml",
    "modules/renderers/metal/examples/CMakeLists.txt"
   ],
   "related": [
    "deep-dives/renderers/native-gpu-evidence-tiers.html"
   ]
  },
  {
   "id": "CNA-VGAP-025",
   "class": "verification-gap",
   "title": "No CI workflow selects WEBGPU or SDL_GPU; WebGPU evidence is local Linux and scripted headless Chrome, and SDL_GPU's Direct3D 12 and Metal driver routes have no native execution evidence",
   "summary": "Neither identity appears in any workflow; WEBGPU's native evidence is Linux x86_64 only, and SDL_GPU's Direct3D 12 route has only Wine/vkd3d-proton runs while its Metal route has none.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "WEBGPU and SDL_GPU renderer identities (and SDL_GPU's Direct3D 12 and Metal driver routes)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-025.html",
   "sources": [
    "scripts/run-wine-vkd3d-headless.sh",
    "modules/renderers/sdl-gpu/examples/CMakeLists.txt",
    "modules/renderers/webgpu/examples/CMakeLists.txt",
    ".github/workflows/gltf-renderer-stride-ci.yml",
    "modules/renderers/opengl4/examples/CMakeLists.txt"
   ],
   "related": [
    "deep-dives/renderers/native-gpu-evidence-tiers.html",
    "development/internals/graphics/sdl-gpu.html"
   ]
  },
  {
   "id": "CNA-VGAP-026",
   "class": "verification-gap",
   "title": "The Windows renderer families have no automatic native Windows execution: DIRECTX9 has no CI job, the DIRECTX11/12, DIRECT2D and GDI lanes are manual, and Direct2D's release gate is blocked",
   "summary": "The Direct3D and GDI Windows workflows run only on manual dispatch, no workflow selects DIRECTX9, GDI tests are not registered in cross builds, DXGI device removal is only simulated, and the Direct2D release gate is blocked.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "DIRECTX9, DIRECTX11, DIRECTX12, DIRECT2D and GDI renderer identities on native Windows",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-026.html",
   "sources": [
    ".github/workflows/d3d-windows-ci.yml",
    ".github/workflows/gdi-windows-ci.yml",
    "modules/renderers/gdi/examples/CMakeLists.txt",
    "docs/direct2d-release-gate.md",
    ".github/workflows/platform-ci.yml"
   ],
   "related": [
    "deep-dives/renderers/direct3d-evidence-and-wine.html",
    "deep-dives/renderers/windows-2d-renderers.html"
   ]
  },
  {
   "id": "CNA-VGAP-027",
   "class": "verification-gap",
   "title": "No workflow runs the roughly eighty SDL_Renderer_* renderer CTests, and they are not registered on Windows or Emscripten",
   "summary": "The SDL_RENDERER example tests are registered only when NOT EMSCRIPTEN AND NOT WIN32; input-ci.yml builds SDL_RENDERER but runs ctest -L input, and apple-ci.yml runs CnaTests directly.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "SDL_RENDERER renderer identity (its SDL_Renderer_* CTests)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-027.html",
   "sources": [
    "modules/renderers/sdl-renderer/examples/CMakeLists.txt",
    ".github/workflows/input-ci.yml",
    ".github/workflows/apple-ci.yml"
   ],
   "related": [
    "deep-dives/renderers/sdl-renderer-2d-contract.html"
   ]
  },
  {
   "id": "CNA-VGAP-028",
   "class": "verification-gap",
   "title": "Several XNB runtime readers are never exercised with externally produced files, although genuine XNA 4.0 outputs for some of them are already in the tree",
   "summary": "Texture3D, Curve, Video, DXT1/DXT5 Texture2D, container-version-4 textures and four of the five stock effects are read in tests only from CNA-written or hand-built bytes; the XNA-built differential corpus is used only by pipeline tests.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The XNB type readers for Texture3D, Curve, Video, Texture2D (DXT1/DXT5, version 4) and AlphaTestEffect, DualTextureEffect, EnvironmentMapEffect and SkinnedEffect",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-028.html",
   "sources": [
    "tests/assets/xnb/cna/windows/uncompressed/fixtures.json",
    "tests/reference/xna40/differential/differential-oracle.json",
    "modules/content-pipeline/tests/CNA/Content/Pipeline/XnaXmlSourceRouteTests.cpp",
    "tests/assets/xnb/monogame/windows/uncompressed/SampleCube64DXT1Mips.xnb.manifest.json"
   ],
   "related": [
    "deep-dives/content/xnb-type-readers.html",
    "docs/content-pipeline-xnb.html"
   ]
  },
  {
   "id": "CNA-VGAP-029",
   "class": "verification-gap",
   "title": "No fuzz target covers .cnj documents or the JSON parser, and .cnj files are read whole with no size bound",
   "summary": "The content fuzz suites cover the XNB container, LZX, XNB writer input and the CNB container; ContentManager's ReadTextFile reads any .cnj into memory before parsing, with no counterpart of XnbReadLimits.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ContentManager's .cnj tier (ReadTextFile, ParseCnjEnvelope and the per-type .cnj readers)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-029.html",
   "sources": [
    "modules/content/src/Xna/ContentManager.cpp",
    "modules/content/tests/CNA/Internal/Xnb/XnbContainerFuzzTests.cpp",
    "modules/content/tests/CNA/Content/Cnb/CnbContainerFuzzTests.cpp"
   ],
   "related": [
    "deep-dives/content/cnj-documents.html",
    "deep-dives/content/content-robustness.html"
   ]
  },
  {
   "id": "CNA-VGAP-030",
   "class": "verification-gap",
   "title": "Model drawing on VULKAN, SOFTWARE and the Direct3D renderers is checked in CI only at the stride draw boundary; the shared Model programs and the whole-corpus L7 rung run in CI for OPENGLES3 only",
   "summary": "The EasyGL Model draw, hierarchy, two-mesh, skinned-playback and .cnj reader programs are reused verbatim as CTests on SOFTWARE, VULKAN, SDL_GPU, OPENGL4 and the DirectX parity set, but no workflow runs those registrations; the whole-corpus L7 image campaigns for VULKAN, SOFTWARE and DIRECTX11 are committed reports from one earlier commit, not CI jobs.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "ModelMesh::Draw / Model::Draw on each 3D renderer; the glTF L7 image comparison",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-030.html",
   "sources": [
    ".github/workflows/gltf-renderer-stride-ci.yml",
    "docs/gltf-l7-vulkan-corpus-report.json",
    "docs/gltf-l7-software-corpus-report.json",
    "docs/gltf-l7-directx11-report.json",
    "modules/renderers/easygl/examples/easygl_model_draw_test.cpp"
   ],
   "related": [
    "deep-dives/models/gltf-conformance.html",
    "deep-dives/models/model-mesh-runtime.html"
   ]
  },
  {
   "id": "CNA-VGAP-031",
   "class": "verification-gap",
   "title": "The real-world Khronos comparison matrix passes on three renderers; the planned fourth (GLTF ROBUST row 12) is open",
   "summary": "Gate C's retake matrix (Fox, DamagedHelmet, Sponza and the sparse cases against the Khronos sample renderer) passes on OPENGLES3, VULKAN and DIRECTX11; the fourth renderer the plan requires is not qualified.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "recorded-by-cna",
   "tests_present": true,
   "public_contract": "glTF import and rendering compared with the Khronos glTF-Sample-Renderer on real assets",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-031.html",
   "sources": [
    "plans/plan_gltf.md",
    "docs/gltf-viewer-retake-report.json"
   ],
   "related": [
    "deep-dives/models/gltf-conformance.html"
   ]
  },
  {
   "id": "CNA-VGAP-032",
   "class": "verification-gap",
   "title": "Input behaviour on real hardware is unverified: the 15-task manual hardware checklist is blocked, and the focus-loss keyboard test checks only the bridge's accumulator",
   "summary": "Controllers, touch, IME, non-US layouts, joysticks and host sensors are recorded as unverified on hardware, and the focus-loss keyboard test reads InputManager's legacy state through a local shim, not the public Keyboard::GetState.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Keyboard::GetState across focus loss; GamePad, TouchPanel, text input/IME and device input on real hardware",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-032.html",
   "sources": [
    "plans/plan_input.md",
    "docs/input-manual-verification-results.md",
    "modules/input/tests/CNA/Internal/Input/SdlInputBridgeKeyboardTests.cpp"
   ],
   "related": [
    "deep-dives/services/input-model.html"
   ]
  },
  {
   "id": "CNA-VGAP-033",
   "class": "verification-gap",
   "title": "The three user-reported audio release blockers (high pitch, missing files, distortion) have never been compared against the original game",
   "summary": "plans/plan_audio.md keeps its three user-reported release blockers unchecked; one hypothesis class was ruled out offline, but no capture of the affected game under XNA and CNA exists.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Audio playback rate, pitch and loading fidelity for real XNA games",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-033.html",
   "sources": [
    "plans/plan_audio.md",
    "modules/audio/tests/Microsoft/Xna/Framework/Audio/OfflineAudioRendererTests.cpp"
   ],
   "related": [
    "deep-dives/services/sound-effects-and-streaming.html",
    "development/internals/audio/engine.html",
    "docs/audio.html"
   ]
  },
  {
   "id": "CNA-VGAP-034",
   "class": "verification-gap",
   "title": "CNA's audio plan carries two undiagnosed test-suite crashes (AUD-15-021, AUD-15-022) that have not been re-run at this snapshot",
   "summary": "An intermittent segfault in AudioMixerSpecOverrideTest within the full audio filter and a heap-corruption abort at teardown after CueTest.*:DynamicSoundEffectInstanceTest.* are recorded as open, blocked on gdb/valgrind.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "recorded-by-cna",
   "tests_present": true,
   "public_contract": "The audio test suites (CueTest, DynamicSoundEffectInstanceTest, AudioMixerSpecOverrideTest) and the code they exercise",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-034.html",
   "sources": [
    "plans/plan_audio.md",
    "NEXTaudio.md",
    "modules/audio/tests/Microsoft/Xna/Framework/Audio/CueTests.cpp"
   ],
   "related": [
    "deep-dives/services/sound-effects-and-streaming.html",
    "development/internals/audio/engine.html",
    "docs/audio.html"
   ]
  },
  {
   "id": "CNA-VGAP-035",
   "class": "verification-gap",
   "title": "DynamicSoundEffectInstance's PendingBufferCount accounting is untested when the stream resamples",
   "summary": "PendingBufferCount compares submitted chunk sizes with the stream's queued-byte count; every test uses a 44,100 Hz source matching the mixer, so the accounting under rate or format conversion is unestablished.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "DynamicSoundEffectInstance::getPendingBufferCountProperty() and the BufferNeeded event",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-035.html",
   "sources": [
    "modules/audio/src/Xna/DynamicSoundEffectInstance.cpp",
    "modules/audio/tests/Microsoft/Xna/Framework/Audio/DynamicSoundEffectInstanceTests.cpp"
   ],
   "related": [
    "deep-dives/services/sound-effects-and-streaming.html",
    "development/internals/audio/engine.html",
    "docs/audio.html"
   ]
  },
  {
   "id": "CNA-VGAP-036",
   "class": "verification-gap",
   "title": "Android sensor conventions are unverified on hardware, and the default landscape remap is a reflection, not a rotation",
   "summary": "No hardware QA record exists for Microsoft::Devices; CNA's own MOT2-001 analysis found the default-on landscape remap negates one axis (determinant -1), and the Android compass/motion sign conventions and demo copy are unverified or stale.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Accelerometer, Gyroscope, Compass and Motion readings on Android; SetAndroidLandscapeRemapEnabled",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-036.html",
   "sources": [
    "modules/devices/include/Microsoft/Devices/Sensors/Detail/AndroidSensorOrientation.hpp",
    "modules/devices/include/Microsoft/Devices/Sensors/Detail/AndroidMotionMath.hpp",
    "docs/devices-hardware-checklist.md",
    "modules/devices/examples/demo_devices/src/DevicesDemo.cpp"
   ],
   "related": [
    "deep-dives/services/sensors-and-vibration.html",
    "development/internals/modules/devices.html"
   ]
  },
  {
   "id": "CNA-VGAP-037",
   "class": "verification-gap",
   "title": "CNA::Devices extension tests use canned platforms or check only that the host call does not fail, and exist only in a CNA_DEVICES=ON build",
   "summary": "Camera, FileDialog, MessageBox and SystemTray tests drive canned platform services; the Clipboard, DisplayInfo, Locale, PowerInfo, SystemInfo and UrlLauncher tests call the host but mostly assert only that nothing crashes; every body is wrapped in #ifdef CNA_DEVICES (default OFF), so only the devices workflow's ON build runs them.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Devices (Camera, Clipboard, DisplayInfo, FileDialog, Locale, MessageBox, PowerInfo, SystemInfo, SystemTray, UrlLauncher)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-037.html",
   "sources": [
    "CMakeLists.txt",
    "modules/devices-ext/tests/CNA/Devices/PowerInfoTests.cpp",
    ".github/workflows/devices-tests.yml"
   ],
   "related": [
    "deep-dives/services/host-devices.html",
    "development/internals/modules/devices-ext.html"
   ]
  },
  {
   "id": "CNA-VGAP-038",
   "class": "verification-gap",
   "title": "No C++ storage test writes bytes through a StorageContainer stream and reads them back",
   "summary": "StorageDeviceTests.cpp checks containment, directory operations and file existence; the only byte round trip is the C ABI smoke test, which runs only in builds with the C API.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "StorageContainer::CreateFile / OpenFile streams",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-038.html",
   "sources": [
    "modules/storage/tests/Microsoft/Xna/Framework/Storage/StorageDeviceTests.cpp",
    "modules/c-api/tests/pure_c/StorageSmoke.c"
   ],
   "related": [
    "development/internals/modules/storage.html",
    "docs/storage.html"
   ]
  },
  {
   "id": "CNA-VGAP-039",
   "class": "verification-gap",
   "title": "The process-spawning networking tests are compiled out on Windows, Emscripten, Android and iOS, and multi-machine behaviour has no test evidence",
   "summary": "TwoProcessLoopbackTest.cpp and GamerServicesDispatcherHangRegressionTest.cpp are filtered out for WIN32, EMSCRIPTEN, ANDROID and iOS; several-machine behaviour, Windows shared-port binding and browser sessions have no test evidence, and host migration is tested only on POSIX hosts.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "NetworkSession over ENet (SystemLink) on every target",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-039.html",
   "sources": [
    "cmake/UnitTests.cmake",
    "modules/net/tests/CNA/Internal/Net/TwoProcessLoopbackTest.cpp"
   ],
   "related": [
    "development/internals/modules/net.html"
   ]
  },
  {
   "id": "CNA-VGAP-040",
   "class": "verification-gap",
   "title": "Avatar rendering evidence uses a synthetic one-bone quad; no renderer test draws the bundled 19-bone avatar content",
   "summary": "The three avatar pixel programs build their own one-bone quad and run on EasyGL, Vulkan and (through the EasyGL parity corpus) OpenGL4; no renderer test draws the shipped avatar meshes, skeleton or animations.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "AvatarRenderer real rendering (EnableRealRenderingEXT/DrawRealEXT) with the bundled content",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-040.html",
   "sources": [
    "modules/gamer-services/examples/avatar_real_render_integration_test.cpp",
    "modules/renderers/easygl/examples/CMakeLists.txt",
    "modules/renderers/vulkan/examples/CMakeLists.txt",
    "modules/renderers/opengl4/examples/EasyGLParityCorpus.cmake"
   ],
   "related": [
    "deep-dives/services/avatars.html"
   ]
  },
  {
   "id": "CNA-VGAP-041",
   "class": "verification-gap",
   "title": "The CNA_STRICT_XNA_API purity check compiles only the Microsoft::Devices sensor surface",
   "summary": "cna_strict_xna_api_check and its must-fail twin include only Microsoft::Devices and Sensors headers, so no automated check covers strict-mode purity or marker completeness of the graphics, content, input, audio, media or runtime surfaces.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA_STRICT_XNA_API and the CNAEXT marker (StrictXnaApiSurfaceCheck_Compile_Run, StrictXnaApiSurfaceLeakCheck_MustFailToCompile)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-041.html",
   "sources": [
    "cmake/Harnesses.cmake",
    "tools/devices/StrictXnaApiSurfaceCheck.cpp",
    "tools/devices/StrictXnaApiSurfaceLeakCheck.cpp"
   ],
   "related": [
    "deep-dives/reference/cnaext-catalog.html",
    "deep-dives/verification/test-populations-and-gates.html"
   ]
  },
  {
   "id": "CNA-VGAP-042",
   "class": "verification-gap",
   "title": "FREEDIRECT is built and tested by no workflow, has been verified on Linux only, and its free-direct and free-api siblings are unpinned",
   "summary": "No workflow selects FREEDIRECT or clones free-direct, so its 21 CTests (registered only in a non-Windows, non-Emscripten test build with FREEDIRECT as the default renderer) run only locally, and CNA's own status document leaves Windows and macOS unverified.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The FREEDIRECT renderer identity",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-042.html",
   "sources": [
    "modules/renderers/freedirect/examples/CMakeLists.txt",
    "cmake/RendererSelection.cmake",
    "docs/freedirect-renderer.md"
   ],
   "related": [
    "deep-dives/siblings/freedirect-and-freeapi.html",
    "docs/rendering-backends.html"
   ]
  },
  {
   "id": "CNA-VGAP-044",
   "class": "verification-gap",
   "title": "Wine test routes and the DIRECTX12 Proton route do not prove which Direct3D or Direct2D implementation served a run",
   "summary": "CnaTests' Wine emulator skips the DXVK/vkd3d-proton engagement gate, every Wine-runtime Direct2D registration skips it with no d2d1 marker, and the DIRECTX12 Proton route uses a moving Proton build with no log gate; the Direct2D Proton route is pinned and records its runtime identity.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CTest routes for DIRECTX9, DIRECTX11, DIRECTX12 and DIRECT2D in MinGW cross trees",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-044.html",
   "sources": [
    "cmake/UnitTests.cmake",
    "modules/renderers/direct2d/examples/CMakeLists.txt",
    "scripts/run-wine-direct2d.sh",
    "scripts/run-proton-vkd3d.sh",
    "cmake/DirectXParityTests.cmake"
   ],
   "related": [
    "deep-dives/platforms/windows-cross-compiling-and-wine.html",
    "deep-dives/renderers/direct3d-evidence-and-wine.html"
   ]
  },
  {
   "id": "CNA-VGAP-046",
   "class": "verification-gap",
   "title": "No workflow runs the XNA reference-image corpus comparisons or the FNA value-differential harness, and the one reachable image check runs in a workflow that installs no Pillow",
   "summary": "D3D9_XNA_Diff, Fna3d_XNA_Oracle and Software_XnaLineCoverage are in no workflow's test selection, the one reachable image-oracle CTest runs in a workflow that installs no Pillow, and the FNA value-differential harness is manual because it needs mono and a built FNA.dll.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The XNA reference-image corpus CTests and the FNA value-differential harness (tools/fna-reference, cna_reference_dump, scripts/compare-fna-reference.py)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-046.html",
   "sources": [
    "modules/renderers/directx9/examples/CMakeLists.txt",
    "modules/renderers/fna3d/examples/CMakeLists.txt",
    "scripts/xna-diff.py",
    "cmake/Harnesses.cmake",
    "scripts/compare-fna-reference.py"
   ],
   "related": [
    "deep-dives/renderers/direct3d9-xna-fidelity.html",
    "deep-dives/verification/oracles-and-engagement.html",
    "docs/verification.html"
   ]
  },
  {
   "id": "CNA-VGAP-047",
   "class": "verification-gap",
   "title": "Test strength is never measured automatically: no coverage build, no scheduled fuzzing campaign, and the Direct2D mutation checker only dry-runs",
   "summary": "No workflow or CMake option enables coverage instrumentation, the libFuzzer-capable harnesses are not CTests and no job or schedule runs them (their large recorded campaigns were manual, one-time runs), and direct2d_mutation_check.py runs only as --dry-run in a manual workflow.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA's test-strength instruments: coverage, fuzzing, mutation checking",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-047.html",
   "sources": [
    "cmake/Harnesses.cmake",
    "modules/c-api/CMakeLists.txt",
    "docs/cnaext-coverage.md",
    "scripts/direct2d_mutation_check.py",
    ".github/workflows/d3d-windows-ci.yml"
   ],
   "related": [
    "deep-dives/verification/test-populations-and-gates.html",
    "docs/verification.html"
   ]
  },
  {
   "id": "CNA-VGAP-049",
   "class": "verification-gap",
   "title": "The XNA API census (331/331 types, 3,627/3,627 members) measures representation only and is a manually run script",
   "summary": "Every member row of docs/xna-4-runtime-member-coverage.json records behavior_assessed false, and tools/audit_xna_runtime_surface.py is run by no workflow or CTest, so behavioural evidence exists only for the subsets named by individual tests and oracles.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "docs/xna-4-runtime-member-coverage.json and tools/audit_xna_runtime_surface.py",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-049.html",
   "sources": [
    "docs/xna-4-runtime-member-coverage.json",
    "tools/audit_xna_runtime_surface.py"
   ],
   "related": [
    "deep-dives/foundations/compatibility-and-evidence.html",
    "deep-dives/practice/xna-api-surface-auditing.html",
    "docs/xna-compatibility.html"
   ]
  },
  {
   "id": "CNA-VGAP-051",
   "class": "verification-gap",
   "title": "No CI configuration builds diagnostics at STATS or FULL or enables CNA_BUILD_INSPECTOR, so most Diagnostics tests and every Inspector test are never compiled in CI",
   "summary": "CNA_DIAGNOSTICS and CNA_BUILD_INSPECTOR default to OFF and no workflow or preset changes either, so 38 of 40 DiagnosticsTests, the seven audio and graphics diagnostics tests and all 27 Inspector tests run only in local builds.",
   "subsystem": "Diagnostics & Inspector",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The STATS/FULL diagnostics implementation (CNA_DIAGNOSTICS) and the optional Inspector (CNA_BUILD_INSPECTOR) with their test suites",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-051.html",
   "sources": [
    "CMakeLists.txt",
    "CMakePresets.json",
    "modules/diagnostics/tests/CNA/Diagnostics/DiagnosticsTests.cpp",
    "modules/audio/tests/CNA/AudioDiagnosticsTests.cpp",
    "modules/graphics/tests/Microsoft/Xna/Framework/Graphics/GraphicsDiagnosticsTests.cpp",
    "cmake/UnitTests.cmake",
    "modules/inspector/CMakeLists.txt",
    "modules/inspector/tests/CNA/Inspector/InspectorTests.cpp"
   ],
   "related": [
    "development/internals/modules/diagnostics.html",
    "development/internals/modules/inspector.html",
    "development/testing/architecture.html",
    "docs/diagnostics.html",
    "docs/inspector.html"
   ]
  },
  {
   "id": "CNA-VGAP-052",
   "class": "verification-gap",
   "title": "The Inspector's WebBridge security checks and Agent::Stop paths have no automated test",
   "summary": "No test drives the HTTP bridge (Host check, UI-token gate, 32-connection cap, request parsing, response headers), and no test calls Agent::Stop directly, stops an agent with a client attached, or starts an agent again after stopping one.",
   "subsystem": "Diagnostics & Inspector",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Inspector::Detail::WebBridge (the cna-inspector browser bridge) and CNA::Inspector::Agent::Stop",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-052.html",
   "sources": [
    "modules/inspector/tests/CNA/Inspector/InspectorTests.cpp",
    "modules/inspector/src/WebBridge.cpp",
    "modules/inspector/src/Agent.cpp",
    "modules/inspector/include/CNA/Inspector/Agent.hpp",
    "docs/inspector.md"
   ],
   "related": [
    "development/internals/modules/inspector.html",
    "docs/inspector.html"
   ]
  },
  {
   "id": "CNA-VGAP-053",
   "class": "verification-gap",
   "title": "No CI workflow builds the C API library or runs its tests",
   "summary": "No workflow at this snapshot configures CNA_BUILD_C_API=ON; the C API workflows only run generators, inventories, a release gate and a header compile matrix, so the library and its tests are verified only in local builds.",
   "subsystem": "C API & bindings",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The C API library (CNA_BUILD_C_API) and its test suites under modules/c-api/tests",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-053.html",
   "sources": [
    ".github/workflows/c-api-limitations.yml",
    ".github/workflows/c-api-compat-matrix.yml",
    ".github/workflows/c-api-release-gate.yml",
    "modules/c-api/CMakeLists.txt",
    "CMakeLists.txt",
    "CMakePresets.json",
    "tools/c-api/check_release_gate.py",
    "tools/c-api/generate_compatibility_matrix.py"
   ],
   "related": [
    "development/internals/bindings/c-api-internals.html",
    "development/takeover/uncertainty.html",
    "development/testing/architecture.html",
    "docs/c-api.html"
   ]
  },
  {
   "id": "CNA-VGAP-054",
   "class": "verification-gap",
   "title": "Destroying a caller-created GraphicsDevice while resources on it are still live is allowed by cna_graphics_device_destroy but untested",
   "summary": "graphics_device.h says resources on a caller-created device are released with it and the destroy route checks no child count, but every C test destroys the resources first, so what later calls on those resource handles do rests on reading.",
   "subsystem": "C API & bindings",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "cna_graphics_device_create / cna_graphics_device_destroy (CNA/C/graphics_device.h) and the resource handles created on a caller-created device",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-054.html",
   "sources": [
    "modules/c-api/src/CnaCApiDisplay.cpp",
    "modules/c-api/include/CNA/C/graphics_device.h",
    "modules/c-api/src/CnaCApiRuntimeDetail.hpp",
    "modules/c-api/src/CnaCApiRuntime.cpp",
    "modules/graphics/src/Xna/GraphicsDevice.cpp",
    "modules/graphics/src/Xna/GraphicsResource.cpp",
    "modules/c-api/tests/pure_c/OwnedGraphicsDeviceSmoke.c"
   ],
   "related": [
    "development/handbook/update-the-c-api.html",
    "development/internals/bindings/c-api-internals.html",
    "development/internals/graphics/device.html",
    "docs/c-api.html"
   ]
  },
  {
   "id": "CNA-VGAP-055",
   "class": "verification-gap",
   "title": "Process exit with live EasyGL-family resources whose creating thread has already ended is untested; a binding recorded SIGABRT on an earlier CNA revision",
   "summary": "cna-java recorded that a process exiting with a live vertex buffer whose creating thread had ended aborts on the EasyGL renderer identities; CNA's own process-exit teardown test runs on one thread, so this case has no evidence at this snapshot.",
   "subsystem": "C API & bindings",
   "status": "open",
   "severity": "n/a",
   "confidence": "probable",
   "tests_present": true,
   "public_contract": "Process-exit teardown of live C API handles (the runtime handle registry) on the renderer identities served by EasyGL",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-055.html",
   "sources": [
    "modules/c-api/tests/pure_c/TeardownLifetimeSmoke.c",
    "modules/graphics/src/Xna/VertexBuffer.cpp",
    "modules/renderers/easygl/src/EasyGLRenderer.cpp",
    "plans/plan_capi_smoke_stability.md"
   ],
   "related": [
    "development/internals/bindings/java.html",
    "development/internals/graphics/easygl.html",
    "development/internals/runtime/shutdown.html"
   ]
  },
  {
   "id": "CNA-VGAP-056",
   "class": "verification-gap",
   "title": "The checked-in shader bytecode headers of VULKAN, SDL_GPU and the Direct3D renderers come from generators that no CTest or workflow runs and that have no --check mode",
   "summary": "spirv_shaders.hpp (VULKAN, SDL_GPU), hlsl_shaders.hpp (DIRECTX11/12) and the d3d9_*shaders.hpp headers come from hand-run generators with no --check mode and no CTest or workflow, so a shader source edit without regeneration would go unnoticed.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "The checked-in generated shader headers of the classic renderers (spirv_shaders.hpp for VULKAN and SDL_GPU, hlsl_shaders.hpp for DIRECTX11/12, d3d9_*shaders.hpp for DIRECTX9) and the generators that produce them",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-056.html",
   "sources": [
    "modules/renderers/vulkan/src/shaders/compile_shaders.py",
    "modules/renderers/sdl-gpu/src/shaders/compile_shaders.py",
    "modules/renderers/common/d3d/src/shaders/compile_shaders_hlsl.py",
    "modules/renderers/directx9/src/shaders/compile_shaders_sm2.py",
    "scripts/verify_d3d_shaders_reproducible.sh",
    "scripts/verify_hlsl_shaders_native_msvc.py",
    "cmake/Tests/ModuleProbes.cmake"
   ],
   "related": [
    "development/internals/modules/graphics-ext.html",
    "development/testing/architecture.html",
    "docs/cnaext-engine.html"
   ]
  },
  {
   "id": "CNA-VGAP-057",
   "class": "verification-gap",
   "title": "EasyGL: a full-backbuffer SpriteBatch draw before a frame's first 3D draw is listed as open (Task 933) but has never been reproduced, and the reported scene is untested",
   "summary": "docs/migration-guide.md still lists Task 933 as a currently open EasyGL caveat. Four isolated repros and a dedicated fixture pass, so the original scene (bound target, file texture, real frame loop) is untested and the report is neither confirmed nor closed.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "docs/migration-guide.md's open EasyGL caveat (Task 933): a full-backbuffer SpriteBatch draw before the first 3D draw of a frame",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-057.html",
   "sources": [
    "docs/migration-guide.md",
    "plans/plan_graphics.md",
    "plans/plan_vulkan.md",
    "modules/graphics/examples/fullscreen_spritebatch_then_3d_test.cpp",
    "modules/renderers/easygl/examples/easygl_spritebatch_blendstate_leak_test.cpp",
    "modules/renderers/easygl/examples/CMakeLists.txt"
   ],
   "related": [
    "development/internals/graphics/easygl.html",
    "docs/verification.html"
   ]
  },
  {
   "id": "CNA-VGAP-058",
   "class": "verification-gap",
   "title": "No dedicated test drives the production audio shutdown path (static destruction of the SDL3 device at exit with callbacks in flight): the teardown tests call DestroyMixer, and plan item AUD-15-016 is unchecked",
   "summary": "DestroyMixer has no production caller, so a game's audio ends through g_audioDevice's static destructor at exit, but the dedicated teardown tests drive DestroyMixer, and plans/plan_audio.md item AUD-15-016 (shutdown with callbacks in flight) is unchecked.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Shutdown of the SDL3 audio device at process exit (Sdl3AudioDevice::Close from static destruction) with mixer callbacks in flight",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-058.html",
   "sources": [
    "modules/audio/include/CNA/Internal/Audio/AudioMixer.hpp",
    "modules/audio/src/Backend/Sdl3Mixer/AudioMixer.cpp",
    "modules/audio/src/Platform/Sdl3/Sdl3AudioDevice.cpp",
    "modules/audio/tests/CNA/Audio/Platform/Sdl3AudioDeviceTests.cpp",
    "modules/audio/tests/CNA/Internal/Audio/AudioMixerTests.cpp",
    "tools/audio/mixer_destroy_active_static_voice_harness.cpp",
    "tools/audio/audio_no_hardware_harness.cpp",
    "plans/plan_audio.md"
   ],
   "related": [
    "deep-dives/services/sound-effects-and-streaming.html",
    "development/takeover/threading.html"
   ]
  },
  {
   "id": "CNA-VGAP-059",
   "class": "verification-gap",
   "title": "The VibrateController shutdown-ordering tests never open a haptic device or destroy a Game-owned SDL3 platform after SDL_Quit, and CNA's own plan keeps SDLCORE-011 open for that reason",
   "summary": "The ordering test spawns a harness that probes the controller and calls SDL_Quit, but no haptic device is opened and the platform is the immortal lazy default, so the SDL_CloseHaptic-after-SDL_Quit path stays reasoned from source only.",
   "subsystem": "Testing & evidence",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "Microsoft::Devices::VibrateController shutdown ordering (DevicesShutdownCoordinator, Sdl3Haptics::CloseAll) relative to SDL_Quit",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-059.html",
   "sources": [
    "tools/devices/shutdown_ordering_harness.cpp",
    "modules/devices/tests/Microsoft/Devices/Detail/DevicesShutdownOrderingTests.cpp",
    "plans/plan_devices.md",
    "modules/platform/src/Sdl3/Sdl3DeviceServices.cpp",
    "modules/platform/src/Sdl3/Sdl3Platform.cpp",
    "modules/platform/src/CurrentPlatform.cpp",
    "cmake/UnitTests.cmake",
    "modules/devices/src/Detail/PlatformVibrateBackend.cpp"
   ],
   "related": [
    "deep-dives/services/sensors-and-vibration.html",
    "development/internals/modules/devices.html"
   ]
  },
  {
   "id": "CNA-VGAP-060",
   "class": "verification-gap",
   "title": "HeadlessPlatform::InjectEvent, the display-free event seam, has no caller and no test",
   "summary": "HeadlessPlatform::InjectEvent is documented as the way to test input, runtime and lifecycle behaviour with no display, yet nothing calls it and no test covers inject-then-PollEvents delivery; the only refill test drives a test-local FakePlatform.",
   "subsystem": "Platforms",
   "status": "open",
   "severity": "n/a",
   "confidence": "verified-by-reading",
   "tests_present": true,
   "public_contract": "CNA::Platform HeadlessPlatform::InjectEvent (the display-free event-injection seam, plans/plan_platform.md PLAT-115)",
   "verified_against": "009d40f5dd085c4e674d3479675fac84b12b3e0a",
   "detail": "known-issues/verification-gaps/cna-vgap-060.html",
   "sources": [
    "modules/platform/src/Headless/HeadlessPlatform.hpp",
    "modules/platform/src/Headless/HeadlessPlatform.cpp",
    "modules/platform/tests/CNA/Platform/PlatformConformanceTests.cpp",
    "modules/platform/tests/CNA/Platform/IPlatformTests.cpp",
    "plans/plan_platform.md",
    "cmake/UnitTests.cmake"
   ],
   "related": [
    "development/testing/architecture.html"
   ]
  }
 ]
}
