@woosh/meep-engine 3.60.4 → 3.60.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (379) hide show
  1. package/CHANGELOG.md +2602 -0
  2. package/CONTRIBUTING.md +7 -0
  3. package/MIGRATION_2_TO_3.md +136 -0
  4. package/SECURITY.md +4 -0
  5. package/editor/EditorCameraNavigation.d.ts +2 -1
  6. package/editor/EditorCameraNavigation.d.ts.map +1 -1
  7. package/editor/EditorCameraNavigation.js +51 -57
  8. package/package.json +6 -2
  9. package/src/engine/EngineHarness.d.ts +3 -9
  10. package/src/engine/EngineHarness.d.ts.map +1 -1
  11. package/src/engine/EngineHarness.js +6 -8
  12. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts +9 -6
  13. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts.map +1 -1
  14. package/src/engine/graphics/camera/makeOrbitalCameraController.js +44 -71
  15. package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts +64 -0
  16. package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts.map +1 -0
  17. package/src/engine/graphics/camera/orbital/MomentumAxis.js +187 -0
  18. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts +86 -0
  19. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts.map +1 -0
  20. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.js +319 -0
  21. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts +34 -10
  22. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts.map +1 -1
  23. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +116 -30
  24. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts +1 -7
  25. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
  26. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +1 -37
  27. package/src/engine/graphics/ecs/water/Water.d.ts +8 -0
  28. package/src/engine/graphics/ecs/water/Water.d.ts.map +1 -1
  29. package/src/engine/graphics/ecs/water/Water.js +8 -0
  30. package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
  31. package/src/engine/graphics3/WaterSystem.js +731 -734
  32. package/src/engine/graphics3/decal/DecalTileShader.d.ts +61 -0
  33. package/src/engine/graphics3/decal/DecalTileShader.d.ts.map +1 -0
  34. package/src/engine/graphics3/decal/DecalTileShader.js +138 -0
  35. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts +10 -4
  36. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts.map +1 -1
  37. package/src/engine/graphics3/decal/GPUDecalRenderer.js +149 -44
  38. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts +25 -0
  39. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts.map +1 -0
  40. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.js +55 -0
  41. package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts +22 -0
  42. package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts.map +1 -0
  43. package/src/engine/graphics3/decal/graph_gather_decal_tiles.js +70 -0
  44. package/src/engine/graphics3/decal/shader_decal_composite.d.ts +7 -5
  45. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  46. package/src/engine/graphics3/decal/shader_decal_composite.js +48 -44
  47. package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts +12 -0
  48. package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts.map +1 -0
  49. package/src/engine/graphics3/decal/shader_decal_tile_copy.js +78 -0
  50. package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts +11 -0
  51. package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts.map +1 -0
  52. package/src/engine/graphics3/decal/shader_gather_decal_tiles.js +80 -0
  53. package/src/engine/input/devices/mouse/MouseEventButtons.d.ts +13 -0
  54. package/src/engine/input/devices/mouse/MouseEventButtons.d.ts.map +1 -0
  55. package/src/engine/input/devices/mouse/MouseEventButtons.js +23 -0
  56. package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts +4 -0
  57. package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts.map +1 -1
  58. package/src/engine/input/ecs/controllers/KeyboardCameraController.js +9 -45
  59. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  60. package/src/shade/playground/water_refraction/README.md +5 -6
  61. package/src/shade/playground/water_refraction/index.html +1 -1
  62. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  63. package/src/shade/renderer/Renderer.js +7 -5
  64. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts +40 -80
  65. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts.map +1 -1
  66. package/src/shade/renderer/camera/orbital/OrbitalCameraController.js +197 -147
  67. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
  68. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
  69. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
  70. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
  71. package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
  72. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +2 -2
  73. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +2 -2
  74. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts +2 -1
  75. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts.map +1 -1
  76. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js +18 -1
  77. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts +31 -0
  78. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts.map +1 -0
  79. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.js +343 -0
  80. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts +17 -0
  81. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts.map +1 -0
  82. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.js +29 -0
  83. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -1
  84. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +7 -13
  85. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  86. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +1 -8
  87. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts +5 -5
  88. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts.map +1 -1
  89. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.js +10 -10
  90. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +1 -4
  91. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  92. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +1 -10
  93. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts +5 -15
  94. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts.map +1 -1
  95. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.js +6 -34
  96. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
  97. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -7
  98. package/src/shade/renderer/hiz/HZBFootprint.d.ts +14 -0
  99. package/src/shade/renderer/hiz/HZBFootprint.d.ts.map +1 -0
  100. package/src/shade/renderer/hiz/HZBFootprint.js +16 -0
  101. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts +10 -0
  102. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts.map +1 -0
  103. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.js +11 -0
  104. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts +10 -0
  105. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts.map +1 -0
  106. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.js +11 -0
  107. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +0 -7
  108. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  109. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +405 -350
  110. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts +12 -0
  111. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts.map +1 -0
  112. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.js +27 -0
  113. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts +12 -0
  114. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts.map +1 -0
  115. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.js +27 -0
  116. package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts +14 -0
  117. package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts.map +1 -0
  118. package/src/shade/renderer/hiz/hzb_footprint_texels.js +34 -0
  119. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts +0 -5
  120. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
  121. package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +37 -57
  122. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts +11 -0
  123. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts.map +1 -0
  124. package/src/shade/renderer/hiz/{shader_hzb_reduce_mip0_clip.js → shader_hzb_reduce_mip0.js} +120 -111
  125. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  126. package/src/shade/renderer/material/GPUMaterialManager.d.ts +7 -0
  127. package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
  128. package/src/shade/renderer/material/GPUMaterialManager.js +11 -0
  129. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts +12 -12
  130. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
  131. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +17 -118
  132. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
  133. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +7 -2
  134. package/src/shade/renderer/water/GPUWaterRenderer.d.ts +0 -6
  135. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  136. package/src/shade/renderer/water/GPUWaterRenderer.js +12 -17
  137. package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts +35 -0
  138. package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts.map +1 -0
  139. package/src/shade/renderer/water/medium/graph_water_meshlets.js +89 -0
  140. package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
  141. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  142. package/src/shade/renderer/water/shader_water.js +22 -13
  143. package/src/shade/renderer/water/shader_water_avboit.d.ts.map +1 -1
  144. package/src/shade/renderer/water/shader_water_avboit.js +7 -7
  145. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts +1 -1
  146. package/src/shade/renderer/water/surface/graph_water_tessellation.js +1 -1
  147. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +9 -1
  148. package/editor/REWORK_PLAN_2026_08.md +0 -692
  149. package/src/CODEC_LAYOUT_VERIFICATION.md +0 -419
  150. package/src/CORRECTNESS_HUNT_2026_07_24.md +0 -142
  151. package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +0 -738
  152. package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +0 -79
  153. package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +0 -93
  154. package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +0 -80
  155. package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +0 -164
  156. package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +0 -69
  157. package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +0 -110
  158. package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +0 -129
  159. package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +0 -72
  160. package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +0 -74
  161. package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +0 -169
  162. package/src/DUPLICATION_AUDIT_2026_08_07.md +0 -254
  163. package/src/DUPLICATION_AUDIT_REMEDIATION.md +0 -250
  164. package/src/DUPLICATION_REVIEW_2026_10_24.md +0 -1072
  165. package/src/REVIEW_2026_08_06/adv-core.md +0 -511
  166. package/src/REVIEW_2026_08_06/adv-gfx.md +0 -480
  167. package/src/REVIEW_2026_08_06/adv-view.md +0 -446
  168. package/src/REVIEW_2026_08_06/api-core.md +0 -296
  169. package/src/REVIEW_2026_08_06/api-engine.md +0 -195
  170. package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +0 -507
  171. package/src/REVIEW_2026_08_06/core-binary.md +0 -348
  172. package/src/REVIEW_2026_08_06/core-collection.md +0 -376
  173. package/src/REVIEW_2026_08_06/core-math.md +0 -221
  174. package/src/REVIEW_2026_08_06/core-process.md +0 -266
  175. package/src/REVIEW_2026_08_06/core-science.md +0 -223
  176. package/src/REVIEW_2026_08_06/engine-ai-nav.md +0 -279
  177. package/src/REVIEW_2026_08_06/engine-animation.md +0 -167
  178. package/src/REVIEW_2026_08_06/engine-asset.md +0 -166
  179. package/src/REVIEW_2026_08_06/engine-ecs.md +0 -920
  180. package/src/REVIEW_2026_08_06/engine-input.md +0 -197
  181. package/src/REVIEW_2026_08_06/engine-misc.md +0 -248
  182. package/src/REVIEW_2026_08_06/engine-terrain.md +0 -52
  183. package/src/REVIEW_2026_08_06/generation.md +0 -176
  184. package/src/REVIEW_2026_08_06/geom-2d.md +0 -434
  185. package/src/REVIEW_2026_08_06/geom-3d.md +0 -117
  186. package/src/REVIEW_2026_08_06/gfx-gi.md +0 -143
  187. package/src/REVIEW_2026_08_06/gfx-render.md +0 -740
  188. package/src/REVIEW_2026_08_06/gfx-texture.md +0 -690
  189. package/src/REVIEW_2026_08_06/prior-criticals.md +0 -49
  190. package/src/REVIEW_2026_08_06/prior-highs.md +0 -138
  191. package/src/REVIEW_2026_08_06/test-gaps.md +0 -364
  192. package/src/REVIEW_2026_08_06/view.md +0 -667
  193. package/src/REVIEW_2026_08_06.md +0 -610
  194. package/src/core/binary/lz4/LZ4_HIGH_COMPRESSION_PLAN_2026_09_14.md +0 -542
  195. package/src/core/bvh2/bvh3/NOTES.md +0 -2
  196. package/src/core/bvh8/NOTES.md +0 -63
  197. package/src/core/cache/wtinylfu/benchmark/CacheWTinylfu.bench.md +0 -243
  198. package/src/core/color/COLOR_FIX_PLAN_2026_08_28.md +0 -417
  199. package/src/core/color/COLOR_REVIEW_2026_08_28.md +0 -779
  200. package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +0 -433
  201. package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +0 -486
  202. package/src/core/geom/3d/atlas/BFF_PLAN.md +0 -174
  203. package/src/core/geom/3d/atlas/REVIEW_02.md +0 -392
  204. package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +0 -146
  205. package/src/core/geom/3d/gjk/NOTES.md +0 -8
  206. package/src/core/geom/3d/topology/TOPO_MESH_RETIREMENT_PLAN.md +0 -135
  207. package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +0 -381
  208. package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +0 -684
  209. package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +0 -554
  210. package/src/core/model/reactive/evaluation/PREDICATE_APPLICABILITY_PROPOSAL.md +0 -446
  211. package/src/engine/REVIEW_2026_07_03.md +0 -211
  212. package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +0 -815
  213. package/src/engine/control/first-person/DESIGN.md +0 -658
  214. package/src/engine/control/first-person/DESIGN_COLLISION.md +0 -382
  215. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +0 -563
  216. package/src/engine/control/first-person/TODO.md +0 -160
  217. package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +0 -531
  218. package/src/engine/ecs/HIERARCHY_REVIEW.md +0 -717
  219. package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +0 -262
  220. package/src/engine/ecs/ik/PLAN.md +0 -179
  221. package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +0 -272
  222. package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +0 -199
  223. package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +0 -521
  224. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +0 -463
  225. package/src/engine/graphics/ecs/camera/pp/NOTES.md +0 -48
  226. package/src/engine/graphics/render/frame_graph/CORRECTNESS_FIXES_2026_09_04.md +0 -659
  227. package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +0 -235
  228. package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +0 -490
  229. package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +0 -466
  230. package/src/engine/input/GAMEPAD_API_PROPOSAL.md +0 -717
  231. package/src/engine/input/ecs/ism/ISM_DESIGN.md +0 -1523
  232. package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +0 -627
  233. package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +0 -661
  234. package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +0 -229
  235. package/src/engine/network/CONGESTION_CONTROL.md +0 -87
  236. package/src/engine/network/MESSAGE_TRANSPORT.md +0 -364
  237. package/src/engine/network/SMOOTHNESS_DESIGN.md +0 -400
  238. package/src/engine/physics/cloth/MEASUREMENTS.md +0 -5304
  239. package/src/engine/physics/cloth/PLAN.md +0 -3056
  240. package/src/engine/physics/fluid/GPU_FLUID_CASCADES_PROPOSAL_2026_10_16.md +0 -1382
  241. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +0 -243
  242. package/src/engine/physics/fluid/solver/NOTES.md +0 -46
  243. package/src/engine/sound/SOUND_EMITTER_RETIREMENT_PLAN.md +0 -536
  244. package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +0 -432
  245. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +0 -250
  246. package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +0 -322
  247. package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +0 -261
  248. package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +0 -121
  249. package/src/engine/sound/sopra/IMPLEMENTATION_PLAN.md +0 -999
  250. package/src/format/image/avif/DECISIONS.md +0 -545
  251. package/src/format/image/jpeg/NOTES.md +0 -3
  252. package/src/format/scene/gltf/MESHOPT_COMPRESSION_PLAN.md +0 -814
  253. package/src/generation/COORDINATES.md +0 -54
  254. package/src/generation/REVIEW_01_ACTION_PLAN.md +0 -628
  255. package/src/generation/foliage/ANNUAL_SHOOTS_BRIEF_2026_10_25.md +0 -220
  256. package/src/generation/foliage/CROWN_FILLING_BRIEF_2026_10_26.md +0 -172
  257. package/src/generation/foliage/CROWN_FULLNESS_BRIEF_2026_10_26.md +0 -86
  258. package/src/generation/foliage/FOLIAGE_DESIGN.md +0 -547
  259. package/src/generation/foliage/FOLIAGE_PLAN.md +0 -198
  260. package/src/generation/foliage/LEAF_ARCHITECTURE_BRIEF_2026_10_26.md +0 -158
  261. package/src/generation/foliage/LOD_REWORK_BRIEF_2026_10_27.md +0 -521
  262. package/src/generation/foliage/REAL_TIME_TREES_BRIEF_2026_10_27.md +0 -86
  263. package/src/generation/foliage/SELF_ORGANIZING_FRAMEWORK_BRIEF_2026_10_26.md +0 -347
  264. package/src/generation/foliage/SHOOT_SYSTEMS_ALL_SPECIES_BRIEF_2026_10_26.md +0 -248
  265. package/src/generation/foliage/SPEEDTREE_COMPARISON_2026_10_24.md +0 -694
  266. package/src/generation/foliage/TWO_FRONT_ENDS_BRIEF_2026_10_28.md +0 -552
  267. package/src/shade/RENDERER_CONTRACT.md +0 -697
  268. package/src/shade/SHADER_F16_PROPOSAL_2026_10_24.md +0 -263
  269. package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +0 -569
  270. package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +0 -755
  271. package/src/shade/device/mock/EXTENSION_PROPOSAL_2026_08_22.md +0 -458
  272. package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +0 -255
  273. package/src/shade/device/mock/REVIEW_2026_08_22.md +0 -527
  274. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +0 -894
  275. package/src/shade/device/timing/profile/SGPT_FORMAT.md +0 -345
  276. package/src/shade/renderer/NOTES.md +0 -78
  277. package/src/shade/renderer/PLAN.md +0 -8
  278. package/src/shade/renderer/animation/ADDITIVE_BLENDING_PLAN.md +0 -145
  279. package/src/shade/renderer/animation/SKINNING_FRAME_PLAN.md +0 -357
  280. package/src/shade/renderer/atmosphere/NOTES.md +0 -6
  281. package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts +0 -76
  282. package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts.map +0 -1
  283. package/src/shade/renderer/camera/orbital/MomentumAxis.js +0 -164
  284. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts +0 -45
  285. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts.map +0 -1
  286. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.js +0 -66
  287. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts +0 -98
  288. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts.map +0 -1
  289. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.js +0 -184
  290. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts +0 -175
  291. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts.map +0 -1
  292. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.js +0 -411
  293. package/src/shade/renderer/camera/orbital/README.md +0 -81
  294. package/src/shade/renderer/camera/orbital/index.d.ts +0 -6
  295. package/src/shade/renderer/camera/orbital/index.d.ts.map +0 -1
  296. package/src/shade/renderer/camera/orbital/index.js +0 -9
  297. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +0 -964
  298. package/src/shade/renderer/fluid/GPU_FLUID_OCCUPANCY_AND_SOTA_REVIEW_2026_10_26.md +0 -361
  299. package/src/shade/renderer/geometry/bvh/BLAS_REFIT_BATCH_PLAN.md +0 -619
  300. package/src/shade/renderer/geometry/meshlet/COMPACTION_PLAN_2026_09_16.md +0 -674
  301. package/src/shade/renderer/geometry/sdf/NOTES.md +0 -6
  302. package/src/shade/renderer/geometry/virtual/ATTRIBUTE_PLAN_2026_09_18.md +0 -540
  303. package/src/shade/renderer/geometry/virtual/MICRON_COMPARISON_2026_08_20.md +0 -305
  304. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +0 -913
  305. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +0 -787
  306. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +0 -481
  307. package/src/shade/renderer/geometry/virtual/VK_LOD_CLUSTERS_COMPARISON_2026_08_20.md +0 -301
  308. package/src/shade/renderer/geometry/virtual/WEDGE_PLAN_2026_09_18.md +0 -448
  309. package/src/shade/renderer/geometry/virtual/runtime/CULL_PLAN_2026_09_16.md +0 -385
  310. package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +0 -656
  311. package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +0 -308
  312. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +0 -657
  313. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN_2026_09_14.md +0 -551
  314. package/src/shade/renderer/geometry/virtual/runtime/SHADOW_PLAN_2026_09_28.md +0 -529
  315. package/src/shade/renderer/global_illumination/lpv/NOTES.md +0 -3
  316. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +0 -4306
  317. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_RAYS_VARIABLE_AND_SORTED_SCOPE_2026_10_30.md +0 -410
  318. package/src/shade/renderer/global_illumination/sharc/NOTES.md +0 -8
  319. package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +0 -1369
  320. package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +0 -202
  321. package/src/shade/renderer/gpu_primitive/indirect/NOTES.md +0 -94
  322. package/src/shade/renderer/hiz/NOTES.md +0 -3
  323. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts +0 -8
  324. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +0 -1
  325. package/src/shade/renderer/light/cluster/NOTES.md +0 -11
  326. package/src/shade/renderer/light/cluster/PROPOSAL_ALGORITHM_2026_10_16.md +0 -524
  327. package/src/shade/renderer/light/cluster/PROPOSAL_HIERARCHICAL_2026_10_16.md +0 -1101
  328. package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts +0 -24
  329. package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts.map +0 -1
  330. package/src/shade/renderer/material/resident/shader_resident_texture_means.js +0 -120
  331. package/src/shade/renderer/particles/DESIGN.md +0 -1011
  332. package/src/shade/renderer/particles/EMITTER_GLOBAL_STATE_PLAN_2026_10_29.md +0 -280
  333. package/src/shade/renderer/particles/ORIENTATION_PLAN_2026_10_15.md +0 -453
  334. package/src/shade/renderer/path_tracer/PATH_TRACED_MEDIA_PLAN_2026_10_02.md +0 -520
  335. package/src/shade/renderer/postprocess/bloom/NOTES.md +0 -6
  336. package/src/shade/renderer/postprocess/fsr/NOTES.md +0 -4
  337. package/src/shade/renderer/postprocess/gtao/NOTES.md +0 -6
  338. package/src/shade/renderer/postprocess/nss/NOTES.md +0 -332
  339. package/src/shade/renderer/postprocess/perspective/NOTES.md +0 -3
  340. package/src/shade/renderer/postprocess/sscs/NOTES.md +0 -5
  341. package/src/shade/renderer/postprocess/ssr/NOTES.md +0 -14
  342. package/src/shade/renderer/postprocess/ssr/REPROJECTION_PROPOSAL.md +0 -286
  343. package/src/shade/renderer/postprocess/ssr/prefilter/NOTES.md +0 -39
  344. package/src/shade/renderer/postprocess/taa/NOTES.md +0 -11
  345. package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +0 -78
  346. package/src/shade/renderer/postprocess/vrs/NOTES.md +0 -4
  347. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_LEDGER.md +0 -1218
  348. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_PLAN_2026_09_03.md +0 -600
  349. package/src/shade/renderer/restir/reservoir/NOTES.md +0 -6
  350. package/src/shade/renderer/shader/chunk/atmosphere/NOTES.md +0 -6
  351. package/src/shade/renderer/shader/chunk/brdf/FRESNEL_BRIEF_2026_10_16.md +0 -391
  352. package/src/shade/renderer/shader/chunk/color/tonemap/ACES_TONE_MAPPING_BRIEF_2026_10_17.md +0 -153
  353. package/src/shade/renderer/shader/chunk/color/tonemap/HDR_TONE_MAPPING_FORMS_BRIEF_2026_10_16.md +0 -322
  354. package/src/shade/renderer/shader/chunk/color/tonemap/SDR_TONE_MAPPING_BRIEF_2026_10_16.md +0 -247
  355. package/src/shade/renderer/shader/chunk/fsr/NOTES.md +0 -3
  356. package/src/shade/renderer/shader/chunk/fsr/spd/NOTES.md +0 -4
  357. package/src/shade/renderer/shader/chunk/geometry/ray/NOTES.md +0 -4
  358. package/src/shade/renderer/shader/chunk/material/MULTISCATTER.md +0 -159
  359. package/src/shade/renderer/shader/chunk/mboit/NOTES.md +0 -38
  360. package/src/shade/renderer/shader/chunk/spherical_harmonics/l1i/NOTES.md +0 -3
  361. package/src/shade/renderer/shader/chunk/spherical_harmonics/sampling/NOTES.md +0 -8
  362. package/src/shade/renderer/shader/compiler/SHADER_SWITCH_PROPOSAL_2026_10_16.md +0 -927
  363. package/src/shade/renderer/shadow/contact/FINDINGS.md +0 -413
  364. package/src/shade/renderer/shadow/map/csm/NOTES.md +0 -5
  365. package/src/shade/renderer/shadow/ray/NOTES.md +0 -31
  366. package/src/shade/renderer/shadow/sdf/NOTES.md +0 -9
  367. package/src/shade/renderer/shadow/sdf/brixelizer/NOTES.md +0 -5
  368. package/src/shade/renderer/shadow/sdf/cascade/NOTES.md +0 -9
  369. package/src/shade/renderer/shadow/vsm/NOTES.md +0 -12
  370. package/src/shade/renderer/shadow/vsm/PLAN.md +0 -442
  371. package/src/shade/renderer/shadow/vsm/REVIEW_LEDGER.md +0 -43
  372. package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +0 -2444
  373. package/src/shade/renderer/texture/mipmaps/NOTES.md +0 -3
  374. package/src/shade/renderer/volumetrics/NOTES.md +0 -1329
  375. package/src/shade/renderer/volumetrics/VOLUMETRIC_NOISE_PLAN_2026_10_15.md +0 -336
  376. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts +0 -23
  377. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +0 -1
  378. package/src/shade/renderer/water/medium/GPUWaterBodies.js +0 -75
  379. package/src/shade/wgsl/NOTES.md +0 -4
@@ -1,308 +0,0 @@
1
- # Virtual Geometry runtime — review ledger
2
-
3
- An adversarial review of `runtime/` on 2026-09-11, immediately after it was written. Twelve
4
- reviewers over disjoint dimensions, every non-nit finding attacked by three verifiers (refute /
5
- reproduce / scope) and kept only if two failed to refute it, then a completeness critic and a second
6
- pass on the gaps it named. 251 agents, 61 survivors, ~35 distinct after the critic's dedup.
7
-
8
- **Worked to closure on 2026-09-12, and the closure re-checked the same day.** Every C and M row
9
- below is closed or reclassified against the commit that closed it. Twenty-one reintroductions of
10
- those defects are now caught by the spec their row cites, run mechanically, one at a time: ten were
11
- when the campaign ended, and the other eleven are the re-review's work. See
12
- [Re-review 2026-09-12](#re-review-2026-09-12) for what the first pass claimed that was not true —
13
- including one defect that was still live — and for the two things it could not prove below the
14
- headless drive, which are written down there rather than counted as closed. The status column is
15
- the record; the prose under each section is what it cost to get there.
16
-
17
- | | |
18
- |---|---|
19
- | `90b0b4b46` | fixed-stride page slots, and a tier that answers its own activation question |
20
- | `7d993a083` | the collect pass gets an oracle, and four defects with it |
21
- | `51b9d9cdc` | the feedback loop gets a spec, and stops being three kinds of wrong |
22
- | `6fa44985f` | the prose catches up with the code |
23
- | `61cee96b6` | the singular-instance guard was a test of the wrong number, and only worked axis-aligned |
24
- | `88f92a07c` | eight closures that no spec could have noticed being undone, and three that were wrong |
25
-
26
- **What the campaign changed about the shape of the thing**, rather than about a line of it:
27
-
28
- 1. **The VRAM tier answers its own residency questions.** Selectability, the bytes an eviction
29
- refunds, and eviction's child rule were each taken from the *RAM* tier, and each is a different
30
- answer over a different set. C1 is the one that broke the guarantee the whole design is arranged
31
- around, and the fix is not a patch to the publisher — it is the group row carrying its parent
32
- count so the rule can be evaluated where the residency it is about lives.
33
- 2. **Fixed-stride page slots**, which DESIGN §6 asked for and FORMAT §11.14 finally permitted. Four
34
- defects stopped existing, the page table stopped being a binding, and the traversal came down
35
- from nine storage buffers to eight against the engine's floor of ten.
36
- 3. **A readback is about a frame that has gone.** The layout it is decoded with and the identity of
37
- every page row it names belong to that frame; both are snapshotted when the reading is scheduled.
38
- 4. **The proof tiers are not interchangeable.** Nothing below the headless drive exercises the
39
- engine-integration path, and 18,569 green specs did not notice the playground failing to boot.
40
- The drive is a required check, and it reproduces the README's numbers on a real adapter after
41
- every change here.
42
-
43
- ---
44
-
45
- ## Critical
46
-
47
- | id | defect | status |
48
- |---|---|---|
49
- | C1 | **Selectability was a RAM-tier answer; the cut descends the VRAM tier.** `#refresh_selectable` published `reader.is_selectable(page, group)` — true when the ancestor cone is in *RAM* — into the flag `vg_group_selectable` reads, while descent is gated on `vg_lookup`, which is *VRAM* and a strict subset. So a group could be flagged selectable while a page holding one of its parents had no row, and that parent's own ancestor clamped and drew a coarse stand-in over the same surface. Reachable three ways on the normal path: a refused install, the feedback loop's per-frame promotion budget, and evicting a parent page while its child is not yet resident. Reproduced against the real kernels: 18 drawn ancestor/descendant pairs. | **closed** `90b0b4b46` — the group row carries `group_parent_count`, and `VGeoRuntimeTables.refresh_selectable` computes the rule over this tier's arena and lookup with no reader involved. The agreement spec gained a `vram_withheld` set and a fixpoint oracle over an arbitrary residency set; it was red on the old code |
50
- | C2 | **`MESHLET_BASE` was cached across a meshlet-pool compaction.** A page row stores `batch.metadata.offset`; `GPUMeshletManager.compact()` relocates allocations and fires `record.changed`. The pool subscribed to nothing, so after a compaction every VG page row pointed at another page's clusters — silently, and undetectably from inside the runtime, because every index involved is still in range. | **closed** `90b0b4b46` — the pool subscribes per batch and republishes the slot's `MESHLET_BASE`. **Not a defect of the arena's allocator**, as the note below claimed: it is the *meshlet* pool's compaction, and fixed slots do nothing about it |
51
- | C3 | **`#ensure_arena` tested total capacity, not free space**, so a full-but-large arena never grew and `install` then threw and was refused forever. The second clause grew on *byte* pressure, which arena pressure does not follow. And `arena_word_ceiling` defaulted to 1<<26 words = 256 MiB against a 128 MiB default binding limit, so the last doubling threw in `#create`. | **gone** `90b0b4b46` — there is no arena growth. The arena is `page_capacity` slots from the first frame to the last, and the binding limit is checked once at construction |
52
- | C4 | **`resident_bytes` drifted upward permanently.** `evict()` subtracted `page?.decoded_size ?? 0`, re-derived from the RAM reader; if the RAM tier had dropped that page the subtraction was zero, and the VRAM budget then refused every install forever. | **closed** `90b0b4b46` — the slot header carries `DECODED_SIZE`, so the tier that charged the budget refunds the number it charged |
53
- | C5 | **The feedback readback was parsed with the wrong frame's layout.** `#apply` re-read `runtime.feedback_layout`, but `begin_frame` recomputes it every frame from `page_row_capacity` and `lookup_word_count`, both of which move as pages install. A readback landing a frame or two later decoded with bases that had shifted — wants and touches read out of the stamp region. | **closed** `51b9d9cdc` — the layout is closed over in `read()`, and `VGeoFeedbackLoop.spec.js` grows the tier underneath an outstanding reading |
54
- | C6 | **Two `.vgeo` assets collapsed onto one geometry record.** `VirtualGeometry` inherited `MeshletGeometry`'s `hash()`/`equals()`, which are `this.meshlets.hash()` over an **empty** `MeshletBatch`. `GPUGeometryManager.add` keys `#records_by_content` by content, so the second VG asset registered became another name for the first's record and drew the first's cut. | **closed** `51b9d9cdc` — identity is the container. `VirtualGeometry.spec.js` holds two assets to two rows, and two handles on one reader to one |
55
- | C7 | **The seed kernel trusted `ROOT_PAGE_ROW`, guarded only by a stripped assert.** `register()` used `assert.notEqual(page_row, -1)`, and this engine strips `assert.*` in the shipped build, so a failed root install left `VGEO_PAGE_ROW_NONE` in the geometry row; the seed kernel read it as a u32 index and the multiply wrapped into a live stat word. | **closed** `90b0b4b46`, the kernel half tested `88f92a07c` — `register` throws and rolls the geometry back, and the kernel checks the sentinel in one compare that no build strips. The compare itself had no test: the agreement spec now runs the seed pass alone against a record carrying the sentinel, and asserts nothing is enqueued, nothing is claimed and not one word of the frame's counters moves |
56
-
57
- ## Major — correctness
58
-
59
- | id | defect | status |
60
- |---|---|---|
61
- | M1 | **Plane 4 was the far plane, not the near one.** The collect pass extracted `row_w + row_z`; the engine's own `construct_frustum_planes` uses `w − z` for near under reverse-Z, and `w + z` is the degenerate row an infinite projection makes useless. | **closed** `7d993a083` — a sign, and a test that holds all five planes against `Camera.construct_frustum_planes` on the same matrix rather than re-deriving them |
62
- | M2 | **Frustum culling is on by default and was tested by nothing.** `cull_enabled = true`; the agreement spec ran only with it off. M1 shipped precisely because the default path had no oracle. | **closed** `7d993a083` — it cannot be compared to the CPU cut, because a culled node leaves a real hole, so it is held to §4.4's claim instead: culling removes only clusters whose own sphere is outside the frustum, and never one inside it |
63
- | M3 | **A singular instance transform produced a NaN eye**, and NaN makes every comparison in `vg_project` and the frustum test fail *open* — one zero-scaled instance drew its whole resident set. | **closed** `61cee96b6`. `7d993a083` tested the smallest singular value, which is a degeneracy test in exact arithmetic and not in f32 — it closed the axis-aligned flatten the spec used and left the rotated one open, NaN eye and all, for thirty-six of forty. The test is the **determinant** now, which is the number `mat4_inverse` divides by and is exactly zero at every rotation |
64
- | M4 | **The scale correction was not conservative under shear.** `max/min` of the column lengths is not the singular-value ratio; under shear it under-refines, which three comments and two docs called conservative. | **closed** `7d993a083` — `chunk_mat3_singular_values`, closed form, and **exactly 1** for a uniform scale, which a conservative bound would not have been |
65
- | M5 | **The instance slot was an unbounded `atomicAdd` with no capacity check anywhere.** Every other append in the cut is bounded; this one was missed. | **closed** `7d993a083` — bounded and counted. As the seam is wired it cannot fire, and that is recorded where the check is: the invariant is a call away and the buffer is made here |
66
- | M6 | **`meshlet_capacity` was a frame-scoped constant (1<<20) unrelated to the collection the cut writes into** — the engine's default is 2e5, so `vg_draw` bounds-checked against five times the buffer it was writing into. | **closed** `7d993a083`, the seam half tested `88f92a07c` — both capacities are declared by the expansion site that was handed the collections, and a frame with several sites takes the minimum. The campaign tested the runtime's minimum and not the declaration, so deleting the call from the seam left the suite green |
67
- | M7 | **A broken `child_ref` resolved to page index 0** in `vgeo_runtime_write_page_block` and the cluster was silently dropped, where the CPU reference draws it as a leaf and counts it. Page 0 is the root, which is pinned and therefore always resident. | **closed** `90b0b4b46` — it becomes a leaf and is counted, as `vgeo_select_cut` does with the same input |
68
- | M8 | **Queue overflow and `max_iterations` exhaustion were silent** — the one degradation the design admits costs holes rather than coarseness, and the counters RUNTIME_PLAN promises for it did not exist. | **closed** `51b9d9cdc` for the kernel, `88f92a07c` for the seam — `QUEUE_REMAINING` and `WAVEFRONTS`, the first left behind by one extra prepare pass the seam records after the wavefront loop. That pass was bound to `queue_a`, which holds the produced work only when the iteration count is even; at an odd `max_iterations` it reported the count of work already done and zeroed the count of what was left. The loop carries the roles rather than the buffers now. Measured on a device: fourteen wavefronts at τ = 0.5, nothing outstanding at any threshold |
69
- | M9 | **`evictable()`'s child rule disabled itself when the RAM page was gone**, orphaning VRAM-resident children under an evicted parent. | **closed** `90b0b4b46` — the rule reads this tier's own arena, so a page whose RAM copy has gone still knows its VRAM children |
70
- | M10 | **A recycled page row was resolved with no identity check.** Feedback is at least a frame behind; a row freed and re-used between the cut and the readback makes a want whose page index and byte range come from different pages, and a touch that reroutes both tiers' LRU to the wrong page. | **closed** `51b9d9cdc` — `VGeoRuntimeTables.generation_of(row)`, snapshotted when the reading is scheduled and compared when it lands. CPU-side, which is where it belongs: nothing on the device needs it |
71
- | M11 | **`install_wants` was fire-and-forget** — no `AbortSignal`, no limit, no cross-frame dedup, and an empty catch. The shared `ConcurrencyGate` accumulated stale closures and the RAM budget was charged once per frame per still-wanted page. | **closed** `51b9d9cdc` and `88f92a07c`. Four parts, one of which had a test: the dedup. Of the other three, two were also wrong. The limit was documented "across every reader" and applied per reader, so a frame seeing eight assets issued eight times it — one budget now, ranked across readers because a want's priority is pixels of error and comparable across assets. The failure report sat on a `.catch` and a failed fetch never arrives as one: `VGeoResidencyManager` catches it per page, because the cut stands without any page — so it reads the reader's quarantine now. The signal was right and unexercised; `destroy()` is the verb, and see U1 for who calls it |
72
- | M12 | **Nothing advanced the RAM tier's clock outside the playground.** `VGeoResidencyManager.advance_frame()` had exactly one non-spec caller, so in any real host the protect window never moved and `evict_to_budget` was a permanent no-op. The RAM tier was unbounded. | **closed** `51b9d9cdc` — `VGeoFeedbackLoop.read` winds it, before its own early returns: a frame whose feedback is skipped is still a frame |
73
- | M13 | **Every shadow-map face ran a full cut at the main camera's projection scale.** `GPUSceneShadowmapContext` calls `graph_rasterize_scene_fast_raw`, which carries the seam; the shadow graph is a different `FrameGraph`, so `runtime.feedback` is a cross-graph handle there. | **closed** `7d993a083`, tested `88f92a07c` — the runtime records the graph its frame was opened on and the seam skips any other. The campaign's test compared `runtime.frame_graph` to a graph, which is the getter and not the check; `graph_vgeo_expand.spec.js` calls the seam on a second graph and holds it to recording no passes at all |
74
- | M14 | **Alpha-tested and transparent VG instances are silently invisible**, and DESIGN §9 — cited in the code as the authority for it — did not say so. | **closed** `51b9d9cdc`, tested `88f92a07c` — §9 says it now, and `GPUSceneRows.attach_mesh` says it out loud when such a mesh is attached. Held to the console the way `cloth_collision.spec.js` and `cloth_rig.spec.js` hold theirs: a real `.vgeo` container, a blended material, and the warning read where it is written. The path itself stays out of scope: the bucket path is handed a scene and a camera resource, not a view context |
75
- | M15 | **No unregister or teardown anywhere.** Geometry rows, lookup allocations, pinned root pages, meshlet batches and all four GPU buffers leaked; `#geometry_allocations` was written and never read. | **closed** `90b0b4b46` — `GPUVirtualGeometryPool.unregister` gives back pages, batches, the lookup block and the row, and `destroy` runs it for every registered container. Geometry rows are recycled too |
76
- | M16 | **Arena growth mutated the shadow before the buffer existed** — `grow_arena` then `#create`, so a create that exceeded the binding limit left shadow and device permanently desynchronized. | **gone** `90b0b4b46` — with C3 |
77
- | M17 | **A full page-row table never triggered eviction** — `#make_room` looped on bytes only, so row exhaustion was a permanent cliff independent of the budget. | **closed** `90b0b4b46` — slots and rows are the same thing now, and `#make_room` evicts on whichever budget is short |
78
- | M18 | **Defaults were far short of the design's scale.** `claim_word_capacity` (1<<14 words) covered ~0.5 M (instance, page) pairs — 512 instances of a 1,024-slot tier — against the design's thousands of instances × thousands of pages. | **closed for the claim, reclassified for the queue** `51b9d9cdc`, tested `88f92a07c`. `claim_word_capacity` is derived from the pool's own capacity and a stated `visible_instance_hint`, so it follows the tier it indexes into. `queue_capacity` is left where it is and the reason is written down: the worst case is unbounded, a queue is two buffers of `capacity × 16` bytes per expansion site, and running out is no longer silent — `QUEUE_REMAINING` is non-zero exactly when it costs a hole |
79
-
80
- ## Major — the proof was weaker than it looked
81
-
82
- The agreement spec is the campaign's central claim. It is a real test and it did constrain the
83
- kernel, but it proved less than RUNTIME_PLAN §7 said.
84
-
85
- | id | defect | status |
86
- |---|---|---|
87
- | P1 | Every assertion was conditioned on **VRAM set == RAM set** — `residency_to_tables` mirrored the reader exactly — which is the one state the pool does not maintain, and is why C1 was invisible to it. | **closed** `90b0b4b46` — `vram_withheld`, a fixpoint oracle over an arbitrary residency set, and a direct antichain assertion that needs no oracle at all: no drawn cluster is a descendant of another |
88
- | P2 | `shader_vgeo_cut_collect`, the **only producer of the instance record**, was compile-only. The spec fabricated the record it would have written, so M1, M3, M4 and M5 were all outside its reach. | **closed** `7d993a083` — it runs under the emulator against a scene database built through `SceneManager`, and the cut selected from its own record is held to `vgeo_select_cut` |
89
- | P3 | Every test registered **exactly one** VG geometry, so `lookup_base` was always 0 and every use of it a verified no-op. | **closed** `7d993a083` — two containers in one tier, each held to its own oracle |
90
- | P4 | The device-facing half — `VGeoFeedbackLoop`, `GPUVirtualGeometryRuntime`, the seam — **had no spec at all**. | **closed** `51b9d9cdc` for the first two, `88f92a07c` for the third — `VGeoFeedbackLoop.spec.js` is a real frame graph, a readback that lands, and a feedback image written the way the kernel writes it. Its three seam tests read the runtime's getters and never called the seam, so P4 was closed with a third of it still untested; `graph_vgeo_expand.spec.js` records the seam and asserts what came out |
91
- | P5 | Every overflow and degradation branch was **provably dead** in the suite, so §4.5's "degrades in one direction" was untested. | **closed** `7d993a083` — draw records, the wavefront queue and the want list are each driven to their bound, and each shown to lose work rather than invent it or write past the end |
92
- | P6 | The blocked-group search's guard rejected nothing, so **which case it exercised was chosen by the kernel under test**. | **closed** `7d993a083` — a candidate has to be a page the traversal still enters *and still draws from another group of*, which is the mixed page the own-group term exists for. A page with one drawn group can never be one |
93
- | P7 | RUNTIME_PLAN §7's step-4 row claimed the seam was proved by "4,667 engine specs green" — those specs exercise **no line** of the seam. | **closed** `6fa44985f`, and again `88f92a07c` — the row says so, and names the tier that does exercise it. A row of a proof table has to name a test that would go red |
94
-
95
- ## Major — claims in prose the code did not honour
96
-
97
- All eight corrected in `6fa44985f`, except where a commit is named.
98
-
99
- - **D1** §4.7/§4.5 named queue-exhaustion counters that did not exist — they exist (`51b9d9cdc`), and
100
- §4.5 now says which reading means a hole.
101
- - **D2** §6 described the agreement fixture as the very fixture that cannot exercise its headline
102
- case. It is built at 64 KB, and §6 records the measurement: at 8 KB this torus puts one group in
103
- every page, so no page is ever mixed and the own-group term is unreachable.
104
- - **D3** "all four expansion sites" — three did. §5 says three, names the fourth, and points at
105
- DESIGN §9 for why it is not four.
106
- - **D4** §4.5 claimed FORMAT §10's in-flight pin was closed; nothing pins anything and §10 still
107
- marks it open. Both documents now say the same thing: the cut names the source page, which is what
108
- §10 was blocked on, and the pin itself is not implemented.
109
- - **D5** §4.9's binding list named `stamps`, which is a *region of* `feedback` rather than a buffer,
110
- and omitted `vg_lookup`, which the descent is gated on. Corrected, and
111
- `vgeo_cut_shaders.compile.spec.js` asserts the exact count of every kernel so the list cannot
112
- drift again.
113
- - **D6** `grow_arena`'s comment described a 9/8 margin the code never applied to a request — gone
114
- with `grow_arena` (`90b0b4b46`).
115
- - **D7** VGEO_FORMAT said the reader decodes neither the node table nor the metric. It decodes both;
116
- the node table has a consumer and the metric does not, for the reason §4.8 gives.
117
- - **D8** the reader's documented per-page RAM overhead, and §2's own measurement gate, which was
118
- never discharged. Measured and tabled in §2: **six per cent of the decoded bytes**, flat across
119
- page size, 0.2–33.9 KB per page at 544 KB pages. The audit's "6.4–11.9 KB" is the mean of that
120
- distribution and not its range.
121
-
122
- ## What the review itself got wrong
123
-
124
- Recorded because the next reviewer will otherwise repeat it.
125
-
126
- - **The range was wrong, and more wrong than it looked.** Reviewers were given
127
- `git diff master..HEAD` — a two-dot, tip-to-tip diff — while master had moved past the merge base
128
- (`f07c9f741`). Master's own work was reported as this branch's regressions, including an apparent
129
- version downgrade and two "re-introduced" dangling doc links. By the next day master was
130
- **thirty-six** commits ahead, not the three the review counted, and had deleted the scene graph.
131
- Use `master...HEAD` or `$(git merge-base master HEAD)..HEAD`, and take the count at the moment you
132
- read it — in this repo it is stale within the day.
133
- - **Nobody was pointed at the integration target.** Master's newest commit added a per-row generation
134
- token for exactly the recycled-row identity hazard M10 describes. A reviewer looking at what this
135
- branch must merge into would have found the shape of the fix already written.
136
- - **Twelve dimensions, all spatial.** They partition the code by subsystem and by one-shot
137
- correctness. None asked what happens on the hundredth frame or under a moving camera — the regime
138
- a streaming LOD runtime exists for. The second pass caught some of it; it should have been in the
139
- first.
140
- - **Two verifier failures.** A refutation of M12 contradicted a one-line grep, and the shadow-path
141
- defect (M13) was refuted twice and confirmed once as minor. Three verdicts on one fact means none
142
- of them is a verdict. M13 was re-checked on 2026-09-12 and stood.
143
- - **Nobody asked what the change did not use.** Twelve reviewers audited the code that exists; none
144
- asked which engine primitive it re-implemented. A "what should this have reused" lens belongs in
145
- the next sweep — and see the two notes below for how that lens went wrong when it was finally
146
- applied.
147
- - **The C2/C3/M16/M17 grouping was half right.** "They are what the arena's `OffsetAllocator` costs"
148
- is true of C3, M16 and M17 and false of C2, which is `GPUMeshletManager.compact()` relocating a
149
- batch and has nothing to do with the VG arena. Converting to slots closed three of the four and
150
- left C2 exactly where it was; it took a subscription to the meshlet pool's own `changed` signal.
151
- - **The `GPUDatabase` note's binding claim was wrong, and the conclusion was right for another
152
- reason.** "A database binds as one `array<u32>`, so `vg_pages` + `vg_geometries` collapse to one"
153
- — but `vg_geometries` is bound by the *collect* pass and `vg_pages` by the *traversal*, which are
154
- different shaders with different budgets, so collapsing them buys the traversal nothing. What
155
- actually bought the binding was folding the page header into its own arena slot, which is a
156
- consequence of the fixed-stride conversion rather than of adopting a table.
157
-
158
- `GPUTypedTable` was **not** adopted for the page or geometry rows, and the rest of the case for it
159
- does not survive the conversion either. Its partial-write path stages into an upload buffer and
160
- scatters with a compute pass, where a slot install is one contiguous `writeBuffer` of one range;
161
- its paged growth is the growth DESIGN §6 asks this tier not to have; and `track_generations()` is
162
- ten lines when the table is one array you own. What the note was right about is that the
163
- generation token was the answer to M10, and that nobody had looked.
164
-
165
- ---
166
-
167
- ## Re-review 2026-09-12
168
-
169
- The campaign above closed every C and M row and claimed each one had been "red first against a
170
- reintroduction of exactly its own defect". That claim was checked the way it is written: reintroduce
171
- one defect, run the spec the row cites, restore, next. Twenty-one reintroductions, one at a time,
172
- scripted rather than done by hand so that the filter is proved to select real tests on the clean
173
- tree before the edit is applied — a name filter that matches nothing fails the run for the wrong
174
- reason and reads exactly like a catch.
175
-
176
- **Ten went red. Eleven did not**, and one of the eleven was not a testing gap at all: it was the
177
- defect, still there, closed against the one case that could not see it.
178
-
179
- | # | what the first pass got wrong | closed by | proved by |
180
- |---|---|---|---|
181
- | 1 | **M3 was closed for an axis-aligned zero scale only, and the defect was live.** `!(σ_min > 0)` is a degeneracy test in exact arithmetic. In f32 it holds only on the closed form's diagonal branch, which is the branch `placed([0, 0, 0], [1, 0, 1])` takes. Rotate the flatten and the trigonometric branch computes σ_min as a difference of nearly equal numbers, with an absolute error of about `sqrt(eps_f32)·σ_max ≈ 3.4e-4` — an f32 model of the chunk over four thousand rotated flattens puts the worst σ_min/σ_max at 3.7e-4, which is why a relative threshold cannot be set safely (see below). Of forty rotated zero-scale instances under the emulator, **thirty-six were not dropped**, every one with a NaN eye, the largest projection scale reaching the traversal at **6.2e10** against an intended 540. | `61cee96b6` | agreement spec (emulator) |
182
- | 2 | **The seam had no spec.** P4 was closed against `VGeoFeedbackLoop.spec.js`, whose three seam tests read `runtime.frame_graph`, `runtime.meshlet_capacity` and `runtime.instance_capacity` and never call `graph_vgeo_expand_if_enabled`. Deleting the graph check (M13) or the `declare_collections` call (M6) left the whole suite green. | `88f92a07c` | `graph_vgeo_expand.spec.js` (software device) |
183
- | 3 | **M8's seam half was a live bug, found by writing that spec.** The extra prepare pass exists for one number and the seam bound it to `queue_a`, which holds the produced work only when the iteration count is even. At an odd `max_iterations` it reported the count of work already done and zeroed the count of what was left — `QUEUE_REMAINING`, the one reading that means a hole. | `88f92a07c` | `graph_vgeo_expand.spec.js`, both parities |
184
- | 4 | **C7's kernel compare had no test.** The host half was covered; deleting the sentinel compare from the seed kernel left the suite green. | `88f92a07c` | agreement spec (emulator) |
185
- | 5 | **M11 had one test for four parts, and two of the other three were also wrong.** The frame limit is documented "across every reader" and was applied per reader. The failure report sat on a `.catch`, and a failed fetch never arrives as a rejection — `VGeoResidencyManager` catches it per page, because the cut stands without any one page — so the sentence the fix claimed ("a reader that has quarantined everything asked of it is a fact somebody has to be able to see") was still false. The `AbortSignal` was correct and unexercised. | `88f92a07c` | `VGeoFeedbackLoop.spec.js` |
186
- | 6 | **M18 had no test.** Putting `1 << 14` back left the suite green. | `88f92a07c` | `VGeoFeedbackLoop.spec.js` |
187
- | 7 | **M14 had no test.** Replacing the warning's condition with `false` left all 163 scene specs green. | `88f92a07c` | `GPUSceneRows.spec.js`, reading the console the way the cloth specs read theirs |
188
- | 8 | **The commit table cited a hash that is not in the history.** `c5fc435f0` is a dangling pre-amend of `6fa44985f` — same parent, three lines of this file apart, no branch containing it. It would have resolved on this machine and nowhere else. | this commit | `git branch --contains` |
189
- | 9 | **RUNTIME_PLAN §6 tier 3 still listed "the arena's growth"** among what the software device exercises. There has been no arena growth since `90b0b4b46` (C3). | this commit | reading it |
190
-
191
- And one thing the first pass fixed too weakly. P7 replaced "4,667 engine specs green" with the
192
- headless drive, which is closer and still not a test that goes red on one line: the drive is a
193
- whole-system check on one adapter that cannot be run per commit, and finding 3 above is exactly a
194
- seam defect its six numbers do not move — `max_iterations` defaults to 64, which is even.
195
- RUNTIME_PLAN §7's step-4 row names `graph_vgeo_expand.spec.js` now, and the drive stays what it is.
196
-
197
- **The drive was re-run after both commits** — the collect kernel's guard is a shader change and the
198
- seam's queue bookkeeping is a seam change — on the nvidia/lovelace adapter, and every row of
199
- `playground/vgeo_runtime/README.md`'s τ table is identical: 50/31/18/17/9/8 clusters drawn over
200
- 9/8/6/6/5/5 pages, nothing clamped, 14/14/11/11/8/8 wavefronts, nothing left queued. Residency
201
- settles at 9 of 13 pages and 230 KB. `determinant()` therefore compiles and runs under Dawn as well
202
- as under the emulator, which is the only tier that can say so.
203
-
204
- ### Not closed, recorded
205
-
206
- Two things this pass could not prove below the drive, written down rather than counted as closed.
207
-
208
- - **U1 — `VGeoFeedbackLoop` has no engine-side owner, so its teardown has nowhere to be wired.**
209
- `abort()` had no caller anywhere in the tree, and the reason turns out not to be an oversight in
210
- a teardown path: nothing in the engine constructs a feedback loop at all.
211
- `GPUSceneContext.enable_virtual_geometry` hands back a runtime and a pool, and the host is
212
- expected to build the loop over them — so the whole population of hosts is
213
- `playground/vgeo_runtime/`, which now calls `destroy()` on `pagehide`. The spec proves the signal
214
- reaches the residency manager and that a page arriving after an abort installs nothing. It cannot
215
- prove that a host tears the loop down, because there is one host and it is a demo. This is M12's
216
- shape exactly, and it stays open until an engine-side owner exists.
217
-
218
- **Closed, in two halves (2026-09-28).** *Ownership*, `28035083b`: the scene context constructs the
219
- loop and the renderer opens and closes each VG frame (SHADOW_PLAN_2026_09_28 §2.1). *Teardown*,
220
- `7a9e14fea`: `GPUSceneContext.destroy()` releases everything `enable_virtual_geometry` built, in
221
- dependency order — the loop and the residency, the fetcher and its workers (the context made it,
222
- so the residency never released it), then the runtime's feedback buffer (through the runtime's
223
- new `destroy()`) and the pool — idempotently, and as a no-op when VG was never enabled. The
224
- scene's own TLAS, volumetrics, volumetric light map and probe-volume mesh BVH were not released
225
- either way, which was not VG's and predated it; `fab3fd38e` (2026-09-29) releases them, and
226
- `3685e5bec` stops the scene's teardown giving its rows back one at a time. The hosts' `pagehide`
227
- stops the frame loop and destroys the renderer and then its device, and nothing VG-specific
228
- (`87add5e70`, `f9107e835`).
229
-
230
- What it took besides, each red first:
231
- - `c3fe2bf3f`: a fetch still queued in the residency's gate started after its container was
232
- unregistered, and behind a destroyed fetcher it spawned the worker pool again.
233
- - An adversarial review of the above found four more. `e82476c26`: a reading in flight at
234
- teardown landed on destroyed views and an emptied residency, or was logged as a failed readback;
235
- a destroyed loop now drops it. `1beafcb9e`: a throw partway through `enable_virtual_geometry`
236
- left a runtime with no loop, and `destroy()` then threw before the rest of the scene; the four
237
- are installed together now. `3d241c331`: a destroyed fetcher's next `fetch()` spawned the pool
238
- again; it refuses now. `f9107e835`: the hosts released neither the loop nor the device.
239
-
240
- Tested by `scene/GPUSceneContext.destroy.spec.js` (buffers on the software device, aborted reads,
241
- terminated workers, a failed enable, a second destroy) and the residency, loop and fetcher specs'
242
- own tests. Each teardown call removed in turn turns a spec red except the scene's call to the
243
- loop's `destroy()`: the scene spec schedules no reading, and the loop's spec is what holds that
244
- method. Tier 4: `vgeo_runtime` under headless Chrome, 126 frames and 7 worker fetches in, a
245
- `pagehide` left no VG, no feedback buffer, no resident page, nothing in flight and a frame counter
246
- that stopped.
247
- - **U2 — nothing below the drive executes a cut through the seam.** The software device runs copies
248
- and not shaders, so `graph_vgeo_expand.spec.js` proves what the seam *records* — the passes, the
249
- resource behind each handle, the version chain, the capacities that reach the runtime — and
250
- nothing about what a pass callback binds when it runs. Renaming a binding, or swapping two buffers
251
- of the same type inside one `bindings` object, would pass every spec in this tree and fail only at
252
- tier 4. That is the same gap P4 was about, one level in, and the drive is the only thing that
253
- covers it.
254
-
255
- ### What this pass got wrong, or nearly did
256
-
257
- - **A reintroduction script has to prove the clean run first.** The first version applied the edit,
258
- ran the spec, and called a non-zero exit RED. A mistyped `-t` filter matches no tests, exits
259
- non-zero, and reads as a catch — which would have certified rows that no test touches, which is
260
- the exact failure being investigated. Every row now runs clean-then-dirty and reports the clean
261
- pass count beside the verdict.
262
- - **The obvious fix for M3 was the wrong one.** A relative threshold — drop when
263
- `σ_min / σ_max < eps` — is what the arithmetic seems to ask for, and it cannot be set safely: the
264
- noise reaches 3.7e-4 of σ_max in a four-thousand-sample f32 model and a legitimately flat instance
265
- (a plate a thousand times wider than it is thick) sits at 1e-3, so any threshold with real
266
- headroom over the noise also drops real geometry. The determinant has no such tension, because it is not an estimate of anything — it is the number the
267
- inverse divides by, and it is exactly zero for a flattened instance at every rotation.
268
- - **`max_wants_per_frame` was the second option in this tree documented as a global budget and
269
- implemented as a per-reader one.** `VGeoResidencyManager`'s own doc records the first being
270
- measured at 48 concurrent range requests against a cap of six, and that is why its gate is shared.
271
- Worth a grep the next time a limit is added: the reader-shaped one is the easy one to write.
272
-
273
- ## 2026-09-14 — the remainder counter never worked
274
-
275
- `QUEUE_REMAINING` read zero at every iteration budget, including the ones where the descent drew
276
- nothing at all. M8 added the counter and a spec for it, and both were right about a frame with one
277
- cut in it; the engine has never recorded a frame with one cut in it.
278
-
279
- Measured on `zorah-2026-13-09/bdf6f9615ae672d54bfb70cde904f5c2.vgeo` (28M faces, 17,172 pages)
280
- through the playground on a 4090, sweeping `max_iterations` at tau = 1:
281
-
282
- | `max_iterations` | pages | drawn | remaining, before | after |
283
- | --- | --- | --- | --- | --- |
284
- | 40 | 1593 | 10177 | 0 | 0 |
285
- | 39 | 1593 | 10177 | 0 | 0 |
286
- | 38 | 1593 | 10170 | 0 | 7 |
287
- | 32 | 1315 | 2115 | 0 | 4556 |
288
- | 20 | 25 | 0 | 0 | 75 |
289
-
290
- Two causes, and they cancelled into a plausible number:
291
-
292
- - **The prepare pass wrote it, and the prepare pass runs between wavefronts.** What it could report
293
- is the frontier of an iteration, not a remainder, and the next iteration overwrote it. Only a pass
294
- after the last wavefront is looking at the right thing.
295
- - **It was a plain store, and a frame has more than one cut.** The two-way HZB filter gives every
296
- view two expansion sites and a scene routinely has all of its virtual geometry in one of them, so
297
- the *empty* bucket ran last and stored its own zero over the other's truncation. Every other stat
298
- in `VGEO_CUT_STAT` is an add across the frame's cuts; this one was not.
299
-
300
- `shader_vgeo_cut_queue_remainder` is the tail now — three bindings, one workgroup, an `atomicAdd` —
301
- and the prepare pass no longer binds the feedback buffer at all. The spec that missed it ran one
302
- cut against one feedback buffer, which is the only arrangement in which a last-writer-wins race has
303
- no second writer; the new one runs a truncated cut and an empty cut against the buffer
304
- `begin_frame` would have given them both.
305
-
306
- **What this unblocks.** `max_iterations` defaults to 64 and the descent on this asset converges at
307
- 39, so 89 of the 128 traverse dispatches a frame records are empty — and until now nothing could
308
- say whether a smaller budget was safe. It can now: 39 is exact and 40 is free.