@woosh/meep-engine 2.168.0 → 2.169.0

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 (295) hide show
  1. package/README.md +2 -2
  2. package/build/bundle-worker-image-decoder.js +1 -1
  3. package/package.json +1 -1
  4. package/src/REVIEW_2026_08_06/adv-core.md +511 -0
  5. package/src/REVIEW_2026_08_06/adv-gfx.md +480 -0
  6. package/src/REVIEW_2026_08_06/adv-view.md +446 -0
  7. package/src/REVIEW_2026_08_06/api-core.md +296 -0
  8. package/src/REVIEW_2026_08_06/api-engine.md +195 -0
  9. package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +507 -0
  10. package/src/REVIEW_2026_08_06/core-binary.md +348 -0
  11. package/src/REVIEW_2026_08_06/core-collection.md +376 -0
  12. package/src/REVIEW_2026_08_06/core-math.md +221 -0
  13. package/src/REVIEW_2026_08_06/core-process.md +266 -0
  14. package/src/REVIEW_2026_08_06/core-science.md +223 -0
  15. package/src/REVIEW_2026_08_06/engine-ai-nav.md +279 -0
  16. package/src/REVIEW_2026_08_06/engine-animation.md +167 -0
  17. package/src/REVIEW_2026_08_06/engine-asset.md +166 -0
  18. package/src/REVIEW_2026_08_06/engine-ecs.md +920 -0
  19. package/src/REVIEW_2026_08_06/engine-input.md +197 -0
  20. package/src/REVIEW_2026_08_06/engine-misc.md +248 -0
  21. package/src/REVIEW_2026_08_06/engine-terrain.md +52 -0
  22. package/src/REVIEW_2026_08_06/generation.md +176 -0
  23. package/src/REVIEW_2026_08_06/geom-2d.md +434 -0
  24. package/src/REVIEW_2026_08_06/geom-3d.md +117 -0
  25. package/src/REVIEW_2026_08_06/gfx-gi.md +143 -0
  26. package/src/REVIEW_2026_08_06/gfx-render.md +740 -0
  27. package/src/REVIEW_2026_08_06/gfx-texture.md +690 -0
  28. package/src/REVIEW_2026_08_06/prior-criticals.md +49 -0
  29. package/src/REVIEW_2026_08_06/prior-highs.md +138 -0
  30. package/src/REVIEW_2026_08_06/test-gaps.md +364 -0
  31. package/src/REVIEW_2026_08_06/view.md +667 -0
  32. package/src/REVIEW_2026_08_06.md +571 -0
  33. package/src/core/binary/BinaryBuffer.d.ts.map +1 -1
  34. package/src/core/binary/BinaryBuffer.js +12 -1
  35. package/src/core/binary/BitImage2.d.ts +5 -1
  36. package/src/core/binary/BitImage2.d.ts.map +1 -1
  37. package/src/core/binary/BitImage2.js +5 -1
  38. package/src/core/bvh8/build/NodeProxy.d.ts.map +1 -1
  39. package/src/core/bvh8/build/NodeProxy.js +314 -308
  40. package/src/core/collection/list/List.d.ts +15 -0
  41. package/src/core/collection/list/List.d.ts.map +1 -1
  42. package/src/core/collection/list/List.js +34 -0
  43. package/src/core/collection/list/SortedListProjection.d.ts.map +1 -1
  44. package/src/core/collection/list/SortedListProjection.js +4 -1
  45. package/src/core/collection/map/BiMap.d.ts +25 -2
  46. package/src/core/collection/map/BiMap.d.ts.map +1 -1
  47. package/src/core/collection/map/BiMap.js +57 -3
  48. package/src/core/debug/matchers/IsAnything.d.ts.map +1 -1
  49. package/src/core/debug/matchers/IsAnything.js +5 -1
  50. package/src/core/events/signal/Signal.d.ts.map +1 -1
  51. package/src/core/events/signal/Signal.js +3 -1
  52. package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +433 -0
  53. package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.d.ts +31 -0
  54. package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.d.ts.map +1 -0
  55. package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.js +84 -0
  56. package/src/core/geom/2d/polygon/polygon2_signed_area.d.ts +24 -2
  57. package/src/core/geom/2d/polygon/polygon2_signed_area.d.ts.map +1 -1
  58. package/src/core/geom/2d/polygon/polygon2_signed_area.js +52 -34
  59. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.d.ts +28 -0
  60. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.d.ts.map +1 -0
  61. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.js +86 -0
  62. package/src/core/geom/2d/polygon/polygon2_triangulate.d.ts +40 -0
  63. package/src/core/geom/2d/polygon/polygon2_triangulate.d.ts.map +1 -0
  64. package/src/core/geom/2d/polygon/polygon2_triangulate.js +1280 -0
  65. package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.d.ts +28 -0
  66. package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.d.ts.map +1 -0
  67. package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.js +77 -0
  68. package/src/core/geom/2d/triangle/tri2_rasterize_conservative.d.ts +6 -3
  69. package/src/core/geom/2d/triangle/tri2_rasterize_conservative.d.ts.map +1 -1
  70. package/src/core/geom/2d/triangle/tri2_rasterize_conservative.js +26 -13
  71. package/src/core/geom/2d/triangle/tri2_signed_area.d.ts +17 -1
  72. package/src/core/geom/2d/triangle/tri2_signed_area.d.ts.map +1 -1
  73. package/src/core/geom/2d/triangle/tri2_signed_area.js +35 -23
  74. package/src/core/geom/2d/v2_morton_encode.d.ts +20 -0
  75. package/src/core/geom/2d/v2_morton_encode.d.ts.map +1 -0
  76. package/src/core/geom/2d/v2_morton_encode.js +23 -0
  77. package/src/core/geom/3d/atlas/segment/atlas_merge_charts.d.ts.map +1 -1
  78. package/src/core/geom/3d/atlas/segment/atlas_merge_charts.js +4 -1
  79. package/src/core/geom/3d/polygon/polygon3_compute_normal.d.ts +27 -0
  80. package/src/core/geom/3d/polygon/polygon3_compute_normal.d.ts.map +1 -0
  81. package/src/core/geom/3d/polygon/polygon3_compute_normal.js +60 -0
  82. package/src/core/geom/3d/polygon/polygon3_triangulate.d.ts +34 -0
  83. package/src/core/geom/3d/polygon/polygon3_triangulate.d.ts.map +1 -0
  84. package/src/core/geom/3d/polygon/polygon3_triangulate.js +94 -0
  85. package/src/core/geom/3d/quaternion/quat3_multiply.d.ts +8 -2
  86. package/src/core/geom/3d/quaternion/quat3_multiply.d.ts.map +1 -1
  87. package/src/core/geom/3d/quaternion/quat3_multiply.js +8 -2
  88. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
  89. package/src/core/geom/3d/shape/ConvexHullShape3D.js +32 -2
  90. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.d.ts +23 -6
  91. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.d.ts.map +1 -1
  92. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.js +268 -124
  93. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.d.ts +17 -0
  94. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.d.ts.map +1 -0
  95. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.js +44 -0
  96. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_count_edge_faces.d.ts +20 -0
  97. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_count_edge_faces.d.ts.map +1 -0
  98. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_count_edge_faces.js +40 -0
  99. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_closed.d.ts +19 -0
  100. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_closed.d.ts.map +1 -0
  101. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_closed.js +34 -0
  102. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_manifold.d.ts +22 -0
  103. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_manifold.d.ts.map +1 -0
  104. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_is_manifold.js +37 -0
  105. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.d.ts +87 -0
  106. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.d.ts.map +1 -0
  107. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.js +599 -0
  108. package/src/core/geom/3d/triangle/tri3_compute_signed_volume.d.ts +32 -0
  109. package/src/core/geom/3d/triangle/tri3_compute_signed_volume.d.ts.map +1 -1
  110. package/src/core/geom/3d/triangle/tri3_compute_signed_volume.js +66 -7
  111. package/src/core/geom/3d/triangle/tri3_mesh_compute_signed_volume.d.ts +22 -1
  112. package/src/core/geom/3d/triangle/tri3_mesh_compute_signed_volume.d.ts.map +1 -1
  113. package/src/core/geom/3d/triangle/tri3_mesh_compute_signed_volume.js +83 -38
  114. package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +554 -0
  115. package/src/core/geom/vec3/v3_cotangent.d.ts +6 -2
  116. package/src/core/geom/vec3/v3_cotangent.d.ts.map +1 -1
  117. package/src/core/geom/vec3/v3_cotangent.js +6 -2
  118. package/src/core/geom/vec3/v3_cross.d.ts +6 -2
  119. package/src/core/geom/vec3/v3_cross.d.ts.map +1 -1
  120. package/src/core/geom/vec3/v3_cross.js +6 -2
  121. package/src/core/geom/vec3/v3_multiply.d.ts +6 -2
  122. package/src/core/geom/vec3/v3_multiply.d.ts.map +1 -1
  123. package/src/core/geom/vec3/v3_multiply.js +6 -2
  124. package/src/core/geom/vec3/v3_subtract.d.ts +6 -2
  125. package/src/core/geom/vec3/v3_subtract.d.ts.map +1 -1
  126. package/src/core/geom/vec3/v3_subtract.js +6 -2
  127. package/src/core/localization/Localization.js +1 -1
  128. package/src/core/math/random/randomSeed.d.ts +13 -0
  129. package/src/core/math/random/randomSeed.d.ts.map +1 -0
  130. package/src/core/math/random/randomSeed.js +16 -0
  131. package/src/core/math/spline/spline3_hermite_apply_transform.d.ts +50 -0
  132. package/src/core/math/spline/spline3_hermite_apply_transform.d.ts.map +1 -0
  133. package/src/core/math/spline/spline3_hermite_apply_transform.js +107 -0
  134. package/src/core/math/spline/spline3_hermite_reverse.d.ts +34 -0
  135. package/src/core/math/spline/spline3_hermite_reverse.d.ts.map +1 -0
  136. package/src/core/math/spline/spline3_hermite_reverse.js +49 -0
  137. package/src/core/math/statistics/hammersley_sequence.d.ts +17 -4
  138. package/src/core/math/statistics/hammersley_sequence.d.ts.map +1 -1
  139. package/src/core/math/statistics/hammersley_sequence.js +25 -16
  140. package/src/core/process/Future.d.ts.map +1 -1
  141. package/src/core/process/Future.js +12 -0
  142. package/src/core/process/PromiseWatcher.d.ts.map +1 -1
  143. package/src/core/process/PromiseWatcher.js +9 -2
  144. package/src/core/process/executor/ConcurrentExecutor.d.ts.map +1 -1
  145. package/src/core/process/executor/ConcurrentExecutor.js +12 -2
  146. package/src/core/process/worker/WorkerProxy.d.ts.map +1 -1
  147. package/src/core/process/worker/WorkerProxy.js +5 -2
  148. package/src/core/process/worker/extractTransferables.d.ts.map +1 -1
  149. package/src/core/process/worker/extractTransferables.js +4 -1
  150. package/src/engine/Engine.d.ts +12 -12
  151. package/src/engine/Engine.d.ts.map +1 -1
  152. package/src/engine/Engine.js +149 -10
  153. package/src/engine/EngineHarness.d.ts.map +1 -1
  154. package/src/engine/EngineHarness.js +4 -1
  155. package/src/engine/asset/loaders/ArrayBufferLoader.d.ts.map +1 -1
  156. package/src/engine/asset/loaders/ArrayBufferLoader.js +7 -0
  157. package/src/engine/ecs/speaker/lines/sets/LineSetDescription.d.ts.map +1 -1
  158. package/src/engine/ecs/speaker/lines/sets/LineSetDescription.js +3 -1
  159. package/src/engine/ecs/terrain/ecs/TerrainSystem.d.ts.map +1 -1
  160. package/src/engine/ecs/terrain/ecs/TerrainSystem.js +4 -1
  161. package/src/engine/ecs/terrain/tiles/TerrainTileManager.d.ts +29 -0
  162. package/src/engine/ecs/terrain/tiles/TerrainTileManager.d.ts.map +1 -1
  163. package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +84 -23
  164. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +446 -0
  165. package/src/engine/graphics/GraphicsEngine.d.ts +56 -7
  166. package/src/engine/graphics/GraphicsEngine.d.ts.map +1 -1
  167. package/src/engine/graphics/GraphicsEngine.js +196 -24
  168. package/src/engine/graphics/context/WebGLContextFailureReason.d.ts +9 -0
  169. package/src/engine/graphics/context/WebGLContextFailureReason.d.ts.map +1 -0
  170. package/src/engine/graphics/context/WebGLContextFailureReason.js +17 -0
  171. package/src/engine/graphics/context/WebGLContextMonitor.d.ts +106 -0
  172. package/src/engine/graphics/context/WebGLContextMonitor.d.ts.map +1 -0
  173. package/src/engine/graphics/context/WebGLContextMonitor.js +341 -0
  174. package/src/engine/graphics/context/WebGLContextState.d.ts +14 -0
  175. package/src/engine/graphics/context/WebGLContextState.d.ts.map +1 -0
  176. package/src/engine/graphics/context/WebGLContextState.js +24 -0
  177. package/src/engine/graphics/context/testWebGLContextLoss.d.ts +2 -0
  178. package/src/engine/graphics/context/testWebGLContextLoss.d.ts.map +1 -0
  179. package/src/engine/graphics/context/testWebGLContextLoss.js +696 -0
  180. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationAdapter.d.ts.map +1 -1
  181. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationAdapter.js +68 -32
  182. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationUpgrader_0_1.d.ts +14 -0
  183. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationUpgrader_0_1.d.ts.map +1 -0
  184. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationUpgrader_0_1.js +41 -0
  185. package/src/engine/graphics/ecs/decal/v2/FPDecalSystem.js +1 -1
  186. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.d.ts.map +1 -1
  187. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +5 -0
  188. package/src/engine/graphics/ecs/trail2d/Trail2D.d.ts +5 -1
  189. package/src/engine/graphics/ecs/trail2d/Trail2D.d.ts.map +1 -1
  190. package/src/engine/graphics/ecs/trail2d/Trail2D.js +15 -0
  191. package/src/engine/graphics/ecs/trail2d/Trail2DSystem.d.ts +1 -1
  192. package/src/engine/graphics/ecs/trail2d/Trail2DSystem.d.ts.map +1 -1
  193. package/src/engine/graphics/ecs/trail2d/Trail2DSystem.js +2 -1
  194. package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts +4 -1
  195. package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts.map +1 -1
  196. package/src/engine/graphics/ecs/trail3d/Trail3D.js +488 -476
  197. package/src/engine/graphics/ecs/trail3d/Trail3DSystem.d.ts +1 -1
  198. package/src/engine/graphics/ecs/trail3d/Trail3DSystem.d.ts.map +1 -1
  199. package/src/engine/graphics/ecs/trail3d/Trail3DSystem.js +280 -253
  200. package/src/engine/graphics/geometry/MikkT/BuildNeighborsFast.d.ts.map +1 -1
  201. package/src/engine/graphics/geometry/MikkT/BuildNeighborsFast.js +3 -2
  202. package/src/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.d.ts.map +1 -1
  203. package/src/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.js +3 -1
  204. package/src/engine/graphics/geometry/computeMeshSurfaceArea.js +1 -1
  205. package/src/engine/graphics/load_and_set_cubemap_v0.d.ts +5 -0
  206. package/src/engine/graphics/load_and_set_cubemap_v0.d.ts.map +1 -1
  207. package/src/engine/graphics/load_and_set_cubemap_v0.js +26 -21
  208. package/src/engine/graphics/particles/particular/group/ParticleGroup.d.ts.map +1 -1
  209. package/src/engine/graphics/particles/particular/group/ParticleGroup.js +19 -8
  210. package/src/engine/graphics/particles/particular/group/optimizeCommandQueue.js +1 -1
  211. package/src/engine/graphics/texture/atlas/AtlasLookupTexture.d.ts.map +1 -1
  212. package/src/engine/graphics/texture/atlas/AtlasLookupTexture.js +10 -3
  213. package/src/engine/graphics/texture/atlas/TextureAtlas.d.ts.map +1 -1
  214. package/src/engine/graphics/texture/atlas/TextureAtlas.js +4 -1
  215. package/src/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.d.ts.map +1 -1
  216. package/src/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.js +11 -0
  217. package/src/engine/graphics/texture/cubemap/load_environment_map.d.ts.map +1 -1
  218. package/src/engine/graphics/texture/cubemap/load_environment_map.js +5 -2
  219. package/src/engine/graphics/texture/sampler/distance/computeSignedDistanceField_Chamfer.d.ts.map +1 -1
  220. package/src/engine/graphics/texture/sampler/distance/computeSignedDistanceField_Chamfer.js +26 -18
  221. package/src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.d.ts +15 -2
  222. package/src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.d.ts.map +1 -1
  223. package/src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.js +29 -3
  224. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.d.ts +11 -1
  225. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.d.ts.map +1 -1
  226. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.js +158 -171
  227. package/src/engine/graphics/texture/sampler/sampler2d_paint.js +1 -1
  228. package/src/engine/graphics/texture/sampler/util/bitSet2Sampler2D.js +2 -2
  229. package/src/engine/input/ecs/util/TopDownCameraControllerHelper.d.ts.map +1 -1
  230. package/src/engine/input/ecs/util/TopDownCameraControllerHelper.js +10 -3
  231. package/src/engine/navigation/ecs/components/PathSerializationUpgrader_2_3.d.ts +14 -0
  232. package/src/engine/navigation/ecs/components/PathSerializationUpgrader_2_3.d.ts.map +1 -0
  233. package/src/engine/navigation/ecs/components/PathSerializationUpgrader_2_3.js +38 -0
  234. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
  235. package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +433 -425
  236. package/src/engine/physics/constraint/solve_constraints.d.ts +4 -1
  237. package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
  238. package/src/engine/physics/constraint/solve_constraints.js +38 -13
  239. package/src/engine/physics/contact/ManifoldStore.d.ts +15 -3
  240. package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -1
  241. package/src/engine/physics/contact/ManifoldStore.js +15 -3
  242. package/src/engine/physics/ecs/Joint.d.ts +7 -4
  243. package/src/engine/physics/ecs/Joint.d.ts.map +1 -1
  244. package/src/engine/physics/ecs/Joint.js +7 -4
  245. package/src/engine/physics/ecs/PhysicsSystem.d.ts +14 -0
  246. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  247. package/src/engine/physics/ecs/PhysicsSystem.js +16 -0
  248. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  249. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
  250. package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts +15 -7
  251. package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts.map +1 -1
  252. package/src/engine/physics/narrowphase/convex_convex_manifold.js +33 -10
  253. package/src/engine/physics/narrowphase/refine_ray_concave.d.ts +6 -2
  254. package/src/engine/physics/narrowphase/refine_ray_concave.d.ts.map +1 -1
  255. package/src/engine/physics/narrowphase/refine_ray_concave.js +6 -2
  256. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts +6 -2
  257. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -1
  258. package/src/engine/physics/narrowphase/refine_ray_hit.js +6 -2
  259. package/src/engine/physics/queries/raycast.d.ts.map +1 -1
  260. package/src/engine/physics/queries/raycast.js +11 -4
  261. package/src/engine/save/storage/IndexedDBStorage.d.ts.map +1 -1
  262. package/src/engine/save/storage/IndexedDBStorage.js +21 -3
  263. package/src/engine/simulation/Ticker.d.ts +12 -0
  264. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  265. package/src/engine/simulation/Ticker.js +18 -0
  266. package/src/engine/sound/simulation/AcousticSimulator.d.ts.map +1 -1
  267. package/src/engine/sound/simulation/AcousticSimulator.js +9 -1
  268. package/src/engine/sound/simulation/core/VolumeField.d.ts +6 -2
  269. package/src/engine/sound/simulation/core/VolumeField.d.ts.map +1 -1
  270. package/src/engine/sound/simulation/core/VolumeField.js +6 -2
  271. package/src/engine/sound/simulation/probe/AcousticProbeField.d.ts +6 -2
  272. package/src/engine/sound/simulation/probe/AcousticProbeField.d.ts.map +1 -1
  273. package/src/engine/sound/simulation/probe/AcousticProbeField.js +6 -2
  274. package/src/engine/sound/simulation/probe/acoustic_probe_transfer.d.ts +6 -2
  275. package/src/engine/sound/simulation/probe/acoustic_probe_transfer.d.ts.map +1 -1
  276. package/src/engine/sound/simulation/probe/acoustic_probe_transfer.js +6 -2
  277. package/src/engine/sound/simulation/probe/bakeProbeReflectors.d.ts +3 -1
  278. package/src/engine/sound/simulation/probe/bakeProbeReflectors.d.ts.map +1 -1
  279. package/src/engine/sound/simulation/probe/bakeProbeReflectors.js +3 -1
  280. package/src/engine/ui/GUIEngine.d.ts.map +1 -1
  281. package/src/engine/ui/GUIEngine.js +8 -1
  282. package/src/generation/theme/TerrainTheme.d.ts.map +1 -1
  283. package/src/generation/theme/TerrainTheme.js +2 -1
  284. package/src/generation/theme/ThemeEngine.d.ts.map +1 -1
  285. package/src/generation/theme/ThemeEngine.js +6 -5
  286. package/src/view/ViewGroup.d.ts.map +1 -1
  287. package/src/view/ViewGroup.js +9 -7
  288. package/src/view/graphics/WebGLContextFailureView.d.ts +19 -0
  289. package/src/view/graphics/WebGLContextFailureView.d.ts.map +1 -0
  290. package/src/view/graphics/WebGLContextFailureView.js +76 -0
  291. package/src/view/minimap/Minimap.d.ts +8 -0
  292. package/src/view/minimap/Minimap.d.ts.map +1 -1
  293. package/src/view/minimap/Minimap.js +16 -3
  294. package/src/view/minimap/dom/MinimapMarkerView.d.ts.map +1 -1
  295. package/src/view/minimap/dom/MinimapMarkerView.js +3 -1
@@ -0,0 +1,571 @@
1
+ # meep engine — deep correctness / API / test review (2026-08-06)
2
+
3
+ **Scope:** `app/src/mir-engine/meep/` — the whole engine library. The `editor/` tree is **out of scope** by request.
4
+ Also excluded: `prototype*.js` (internal tools), `*.spec.js` (used as evidence only), `.d.ts` (deliberately unmaintained here).
5
+
6
+ **Subject:** `@woosh/meep-engine` v2.168.1 — a *published* library. `package.json` exposes `./src/*` and there are **no barrel/index files**, so **every module path is public API surface**. That materially raises the stakes on public-surface defects: a broken exported helper is a shipped defect even when nothing in this repo calls it.
7
+
8
+ **Ground rules applied to every finding** (these are the project's standing conventions):
9
+ - Correctness only — logical errors and real bugs. No style, naming, taste, or performance opinions.
10
+ - Every finding requires a **concrete failure scenario**: specific inputs → specific wrong output, crash, hang, or data loss.
11
+ - `assert.*` is **compiled out of production**. Nothing is reported that depends on an assert firing, and no fix is proposed as an assert.
12
+ - No "defensive guard" findings for conditions that cannot happen.
13
+ - No re-entrancy findings without a named, concrete triggering caller in this repo. (A prior review had four withdrawn on exactly this basis; that precedent was enforced here.)
14
+ - Unreferenced exports are **public surface, not dead code**.
15
+
16
+ > **Methodological note on `assert.*` and jest.** Stripping is a webpack-production transform, so `assert.*` is **live under jest**. A defect reproduced in a spec is therefore running in a *more* guarded environment than production. This cuts one way only: a repro that merely trips an assert is **not** a production finding and was excluded, while a defect that reproduces despite live asserts is, if anything, worse in production. One finding (VIEW-27) is explicitly in that second category.
17
+
18
+ ---
19
+
20
+ ## 1. Method
21
+
22
+ Fan-out review: specialist agents over disjoint slices of the tree, each with a strict correctness-only brief and the exclusion list above, followed by an adversarial verification pass and lead-reviewer spot-checks against source.
23
+
24
+ Two workstreams ran that previous reviews did not include:
25
+ 1. **Re-verification of every prior finding.** `engine/REVIEW_2026_07_03.md` (21 CRITICAL, ~61 HIGH) and `CORRECTNESS_HUNT_2026_07_24.md` were re-checked line by line against current source, because a review's value depends on whether its remediation actually landed.
26
+ 2. **API-gap and test-gap analysis**, with objective inclusion bars (see §5 and §6) designed to keep out wish-list items.
27
+
28
+ ### Test baseline (measured at review time)
29
+
30
+ Full suite, run from `H:/git/moh` via `node_modules/.bin/jest --config jest.conf.json`:
31
+
32
+ ```
33
+ Test Suites: 31 skipped, 1542 passed, 1542 of 1573 total
34
+ Tests: 136 skipped, 9337 passed, 9473 total
35
+ ```
36
+
37
+ **The suite is green.** The four `WallRunScenarios` failures recorded in the 2026-07-24 hunt are gone. Every defect in this document therefore ships green today — none of them is caught by an existing test.
38
+
39
+ Adjacent-spec coverage (a crude but useful proxy — a file counts as covered if a `<name>.spec.js` sits beside it):
40
+
41
+ | | source files | with adjacent spec | none |
42
+ |---|---:|---:|---:|
43
+ | **total** | 3701 | 1405 (38%) | 2296 |
44
+
45
+ Worst packages: `engine/metrics` 0/6, `engine/save` 0/6, `view/elements` 0/34, `view/minimap` 0/12, `view/controller` 0/10, `core/debug` 2/23, `core/science` 6/40, `engine/graphics` 139/856, `engine/ecs` 46/204.
46
+
47
+ **The single strongest predictor of a defect in this review was the absence of an adjacent spec.** Nearly every agent reported the same clustering independently.
48
+
49
+ ---
50
+
51
+ ## 2. Status of the previous review — the headline finding
52
+
53
+ The 2026-07-03 review's remediation **landed only partially, and the split is not by severity or effort — it is arbitrary.**
54
+
55
+ | Prior review | Fixed | **Still open** | Unclear |
56
+ |---|---:|---:|---:|
57
+ | CRITICAL (C1–C22) | 17 | **4** | 0 |
58
+ | HIGH + §2 recurring patterns | 34 | **32** | 1 |
59
+
60
+ The four CRITICALs still open, all verified against current source:
61
+
62
+ | ID | Location | Defect |
63
+ |---|---|---|
64
+ | **C5** | `engine/graphics/ecs/decal/v2/FPDecalSystem.js:216` | `unlink()` calls `transform.subscribe(...)` where `unsubscribe` was meant, *after* nulling `__fp_decal` → next transform change calls `.setTransform` on `null` → crash + listener leak. |
65
+ | **C13** | `engine/ecs/terrain/tiles/TerrainTileManager.js:566` | `stitchTile` floors `gridSize` while `initializeTiles` ceils it → partial edge tiles are never seam-stitched → lighting crease on every non-multiple terrain boundary. |
66
+ | **C17** | `engine/graphics/geometry/MikkT/BuildNeighborsFast.js:116` | `i1_B` and `edgenum_B` both read `temp_edge_B[2]`; `i1_B` should read `[0]`. The match test compares a vertex index against an edge number (0–2), so it effectively never succeeds → face neighbours are never assigned → **per-face (faceted) tangents on every real mesh** → normal-map seams. *(Verified first-hand.)* |
67
+ | **C18** | `engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.js:79` | `pass * 257 + (key >> shift) & 0xff` — JS binds `+` tighter than `&`, so the mask applies to the whole sum. Correct only for `pass === 0`; every later pass bins wrongly → **vertex welding fails** for any mesh whose hash exceeds 8 bits. *(Verified first-hand.)* |
68
+
69
+ **None of the four open items has a regression spec.** Every *fixed* finding except one shipped with a spec whose test name cites the finding ID. That asymmetry is strong evidence these four were never worked, rather than fixed-and-untested.
70
+
71
+ `C17` and `C18` deserve emphasis: they are both on the tangent-generation path, and the only spec in that directory (`MikkTSpace.spec.js`) covers empty geometry and a single triangle — neither case reaches edge pairing or vertex welding. **Both defects are structurally invisible to the current suite**, which is why they survived two reviews.
72
+
73
+ ---
74
+
75
+ ## 3. Recurring patterns — fix the class, not the instance
76
+
77
+ Independent agents reviewing unrelated subsystems converged on the same four root causes. Each is worth a targeted sweep, because fixing instances one at a time will not stop them recurring.
78
+
79
+ ### 3.1 Lifecycle asymmetry — the single largest class
80
+
81
+ Something acquired in `link`/`startup`/`build` is not released in `unlink`/`shutdown`/`dispose`. Variants seen: subscribing to the wrong signal; passing a handler without its context so `remove` silently no-ops; removing from a *different* signal than the one subscribed; and GPU/DOM resources never disposed.
82
+
83
+ The characteristic failure is **not** a slow leak — it is that **the second time you do anything, it breaks**. A level reload, a scene swap, or an engine restart is the trigger. `ShadedGeometrySystem` is the sharpest example: it registers a render layer at startup and never removes it, and `RenderLayerManager.add()` *throws* on a duplicate name — so the second load throws outright.
84
+
85
+ Why it is systemic here: there is no test anywhere that asserts listener symmetry across a `link`/`unlink` cycle, so every instance of this class is invisible to CI.
86
+
87
+ ### 3.2 Serialization divergence
88
+
89
+ For a given class, three sources of truth disagree: the field initialiser, the `toJSON`/`fromJSON` pair, and the `toBinary`/`fromBinary` pair. Observed variants: a field persisted in one path and dropped in the other; a `fromJSON` default that differs from the field initialiser (`ClingToTerrain.rotationSpeed` defaults to `Infinity` in JSON and `3` in the field); a flag field truncated from 32 bits to 8; a `toJSON` key that `fromJSON` does not read.
90
+
91
+ These are silent — the object loads, it is just *wrong*. No component anywhere has a round-trip test asserting `field-init == fromJSON(toJSON()) == fromBinary(toBinary())`, which is why the whole class survives.
92
+
93
+ ### 3.3 Promises that never settle
94
+
95
+ A code path that neither resolves nor rejects, so the caller waits forever. Found in the task executor (a task blocked on a *failed* dependency is never failed and never resolved), the undo processor, the worker proxy (a failed `postMessage` drops the request), asset loaders (a stream error mid-download), `GameStateLoader.count()`, and the engine bootstrapper (an `async` Promise executor swallows its own rejection).
96
+
97
+ The related sub-pattern is **failure reported as success**: `Engine.start()` logs a startup rejection and resolves anyway; `GameStateLoader` resolves `undefined` for a missing save; `SVGAssetLoader` resolves on a `<parsererror>` document.
98
+
99
+ ### 3.4 Sentinels consumed as data
100
+
101
+ A function returns a placeholder for a degenerate input, and its caller uses that placeholder as if it were a real value. The clearest case is `tri3_compute_normal`, which writes `(0,1,0)` with the comment *"degenerate triangle, provide arbitrary invalid result"* — and `compute_face_normal_change_dot_product` dots it against the original normal, so the mesh-simplifier's flip-rejection test silently becomes "does this face point downward". Same shape elsewhere: `Team`'s `INT32_MAX` aliasing an `Infinity` sentinel, and `indexOf`'s `-1` reaching a `splice`.
102
+
103
+ This class is worth calling out separately because the *producer* is behaving as documented. The defect is the missing contract at the boundary, and the fix is to make failure signalled rather than encoded in the return value.
104
+
105
+ ### 3.5 Two mechanical classes worth a grep sweep
106
+
107
+ - **JS semantics traps**: `pass * 257 + (key >> shift) & 0xff` (`+` binds tighter than `&`, so the mask hits the whole sum); `>>` where `>>>` is required; `x|0` used as `floor` (it truncates toward zero, so it is wrong for every negative coordinate); bare `.sort()` on numbers (lexicographic).
108
+ - **Axis / variable copy-paste**: `size.y` written twice, `a.height` compared against `b.width`, `i1_B` and `edgenum_B` both reading slot `[2]`, vertex C's Y read from the wrong offset. These hide behind square and identity-transform test fixtures.
109
+
110
+ ---
111
+
112
+ ## 4. New correctness findings
113
+
114
+ **436 new findings: 50 CRITICAL, 235 MAJOR, 151 MINOR.** Per-finding detail — defect, concrete failure scenario, fix, confidence — is in `REVIEW_2026_08_06/<area>.md`.
115
+
116
+ Severity here means: **CRITICAL** = crash, corruption, hang, or wrong result on a common or default path. **MAJOR** = wrong result or crash in a real but specific configuration. **MINOR** = edge case only.
117
+
118
+ | Area | CRIT | MAJOR | MINOR | total | Verdict |
119
+ |---|---:|---:|---:|---:|---|
120
+ | `graphics/texture` + particles + geometry | 13 | 42 | 21 | 76 | Core algorithms sound; the *seams* (type/format pairing, attribute interleaving, draw-range bookkeeping) are not |
121
+ | `view/` | 6 | 26 | 10 | 42 | Worst area in the engine. Several files cannot be constructed |
122
+ | `core/process` + graph + debug | 6 | 16 | 5 | 27 | Graph algorithms clean; `debug` matchers and `undo` are not |
123
+ | `engine/ecs` | 3 | 23 | 25 | 51 | Core structurally sound; edges leak |
124
+ | `core/collection` + cache + events | 3 | 8 | 6 | 17 | Typed-array core solid; the unspecced projections are broken |
125
+ | `engine/input` + control | 3 | 7 | 5 | 15 | Control maths well-reasoned; device shutdown paths unfinished |
126
+ | `bvh2/8` + unspecced physics/sound/net | 2 | 16 | 9 | 27 | Cores confirmed clean; defects in the unspecced bridge |
127
+ | `core/binary` + parser + model | 2 | 15 | 13 | 30 | Bit-twiddling solid; string/serialization edges are not |
128
+ | `engine/asset` | 2 | 7 | 6 | 15 | `AssetManager` solid; loaders and decoders weak |
129
+ | `graphics/sh3` GI + material + impostors | 2 | 7 | 0 | 9 | SH maths sound; three-r136 drift at the seams |
130
+ | `core/math` | 2 | 6 | 2 | 10 | Broadly sound; defects where specs test only half the domain |
131
+ | `generation` | 2 | 4 | 3 | 9 | Algorithms clean, no nondeterminism; seed *plumbing* broken |
132
+ | `graphics/render` + ECS bindings | 1 | 17 | 13 | 31 | Froxel/cluster maths correct; five lifecycle leaks |
133
+ | `engine/intelligence` + navigation + grid | 1 | 9 | 5 | 15 | Pathfinding correct; BT lifecycle bookkeeping is not |
134
+ | `engine/animation` + interpolation | 1 | 5 | 1 | 7 | New spline layer correct; older `keyed2` playback is not |
135
+ | `core/geom/3d` | 1 | 2 | 4 | 7 | New xatlas/BinaryTopology work good; old `simplify` path bad |
136
+ | `engine` misc (save, Engine, UI, logging) | 0 | 13 | 8 | 21 | Save durability and engine lifecycle are the weak points |
137
+ | `core/geom/2d` + primitives | 0 | 6 | 8 | 14 | New triangulator verified by fuzzing; old ray/hull code weak |
138
+ | `core/science` + color | 0 | 3 | 4 | 7 | Colour science verified to reference precision; app layer leaks alpha |
139
+ | `engine/ecs/terrain` (second pass) | 0 | 3 | 3 | 6 | — |
140
+ | **TOTAL** | **50** | **235** | **151** | **436** | |
141
+
142
+ ### 4.1 The consistent shape of this review
143
+
144
+ Every agent, independently, reported the same split: **the algorithmic cores are correct and the seams around them are not.**
145
+
146
+ Verified clean under direct scrutiny: the physics solver and narrowphase, the acoustic simulator, the fluid MAC solver, colour science (reproduced to reference precision, including a CMF×D65 integration landing on xy = 0.31273, 0.32902 against a standard 0.31272, 0.32903), the BVH traversal and froxel/cluster geometry, SH irradiance evaluation, the earcut port (700 fuzz cases, zero area deviation), Polyanya navmesh pathing, grid A*, MikkTSpace's group/subgroup machinery, the max-rect packer, and the ECS occupancy/stride arithmetic and recursion-safe dispatcher.
147
+
148
+ That is a real and unusual strength. **The defects are not in the hard parts.** They are in type/format pairings, lifecycle teardown, serialization adapters, and device shutdown — the code that is easy to write, boring to test, and therefore untested.
149
+
150
+ ### 4.2 The most severe individual findings
151
+
152
+ Ranked by blast radius, all verified first-hand by the lead reviewer:
153
+
154
+ 1. **`BinaryBuffer.writeUTF8String` silently destroys non-ASCII strings** (`core/binary/BinaryBuffer.js`). The pre-reservation is `1.5 × len + 7` bytes, but Cyrillic encodes at 2 B/char and CJK at 3, so the buffer grows mid-write — and `setCapacity` copies only up to `this.position`, which the write loop does not update until it finishes. Everything written so far is zeroed. **Reproduced: a 20,000-char Cyrillic or CJK string round-trips to `""`.** ASCII is unaffected, which is exactly why nothing caught it. This is silent, total data loss in the binary serializer, and the game ships Russian.
155
+ 2. **`ThemeEngine` seed plumbing makes the whole theme layer seed-invariant** (`generation/theme/ThemeEngine.js:212`). A float in `[0,1)` is passed as a child seed; Mulberry32 does `_seed += 0x6D2B79F5` then applies bitwise ops, which coerce to int32 and **discard the fraction** — so every seed in `[0,1)` produces byte-identical output to seed `0`. Different world seeds give identical themed results. A green suite can never see this, because every run agrees with every other run.
156
+ 3. **`AtlasLookupTexture` never allocates storage for the first 32 patches** (`graphics/texture/atlas/AtlasLookupTexture.js:58`). The constructor makes a **1×1** `DataTexture` backed by a 4-element array; `update()` guards on `image.height < expected_row_count`, and with `__row_size = 32` any atlas of 1–32 patches gives `expected_row_count === 1`, so `1 < 1` is false and no reallocation happens. The loop writes `patch_count * 4` entries into a 4-element array and typed-array semantics discard everything past patch 0. *This also means the C10 fix landed in 2026-07 only ever affects patch 0.* (`format = RGBAIntegerFormat` is also paired with `internalFormat = 'RGB16UI'`.)
157
+ 4. **`ShadedGeometrySystem` never removes its render layer** (`graphics/ecs/mesh-v2/ShadedGeometrySystem.js:254`), and `RenderLayerManager.add()` **throws** on a duplicate name — so the second engine start throws outright. Three more MAJOR lifecycle leaks share that same level-reload trigger.
158
+ 5. **The mesh simplifier's flip-rejection test is nonsense on exactly the collapses it exists to reject** (`core/geom/3d/topology/simplify/`). `tri3_compute_normal` writes `(0,1,0)` for a degenerate triangle — its comment says *"provide arbitrary invalid result"* — and `compute_face_normal_change_dot_product` dots it against the original normal, so the test degenerates to `original_normal.y < 0`, i.e. "does this face point downward".
159
+ 6. **`view/` contains classes that cannot run at all.** `MinimapMarkerView` reads `this` before `super()` (guaranteed `ReferenceError`); `ViewGroup.remove()` calls `.remove()` on a native `Set`; `ViewGroup.disconnect()` calls `addChild` where `removeChild` is meant; `TabbedView` renders a literal empty `<div></div>`.
160
+ 7. **`PromiseWatcher.add()` leaks an unhandled rejection** (`core/process/PromiseWatcher.js:45`). It discards the promise returned by `.finally()`, which rejects with the same reason — so watching any promise that rejects produces an unhandled rejection *even when the caller has attached its own `.catch()`*. Under Node's default this terminates the process. Its whole spec suite is skipped as "TODO broken tests"; **the tests are right and the code is wrong.**
161
+ 8. **`sampler2d_scale_down_lanczos` returns `NaN`.** Its spec is `describe.skip("currently broken")` and it genuinely is: for a 3×1→1×1 downscale every sample lands in the kernel's negative lobe, `if (weight <= 0) continue` discards them all, `weight_sum` is 0, and `0 * Infinity = NaN`. A 2×2→1×1 box returns `4` instead of `2.5`. Three independent defects — discarding negative lobes (the point of Lanczos), a radial rather than separable kernel, and a pixel-centre convention error (`f = i - center` where `i + 0.5 - center` is meant).
162
+
163
+ ---
164
+
165
+ ## 5. API gaps
166
+
167
+ Both API passes used a deliberately strict inclusion bar — an item qualifies only if it is **(A)** half of a broken pair, **(B)** a member one sibling has and its peer lacks for no reason, **(C)** an omission from a concept's universal contract, or **(D)** documented but absent. Wish-list items, naming, and taste were excluded, and every claimed absence was grepped under several plausible names first.
168
+
169
+ **The headline result is that the API is in good shape.** Both agents independently reported that most "obvious" absences they chased turned out to exist under a prototype alias or in a sibling file. The core is described as "unusually disciplined about pairs". This is the strongest area of the review.
170
+
171
+ ### 5.1 Where the real gaps cluster
172
+
173
+ Two clusters, both explicable:
174
+
175
+ 1. **Recently-added typed-array containers, written to exactly one call site and never given the read-back half of their interface.** `Uint32Map` and `PairUint32Map` are Map-like but cannot be enumerated (no `forEach`, no iterator). `IndexedFloatMinHeap`/`MaxHeap` have no `peek` although every sibling heap does. `CSRGraph` exposes a getter that advertises worker transfer but has no `fromArrayBuffer` receiver. `BitImage2` can `set(x,y)` but only clear the whole image.
176
+ 2. **Older classes that predate the conventions their newer siblings follow.** `BiMap` aliases `add`/`set` to the Map API but has **no `delete`** — entries can never be removed. `Stack` has no `size`. `ArraySet` has `addAll` but no `removeAll`. `List` has `some()` but no `every()`, and **no `[Symbol.iterator]`** — so `for...of` and spread do not work on the most-used collection in the codebase, while `HashMap`, `HashSet` and `Deque` all support them.
177
+
178
+ ### 5.2 Engine-side gaps
179
+
180
+ Only one sits on a path a typical game hits:
181
+
182
+ - **`PhysicsSystem` has `setLinearVelocity` but no `setAngularVelocity`** — and this is not cosmetic: `setLinearVelocity` *wakes the body*, whereas the direct field write a user is forced into does not. The workaround is silently wrong.
183
+ - `Terrain.addLayer` with no `removeLayer`, though both lower tiers support removal.
184
+ - `engine/save`'s `GameStateLoader` imports from outside the package, so the save layer **cannot be loaded standalone from the published library** — and there is no delete.
185
+
186
+ ### 5.3 Two README claims are not reachable
187
+
188
+ The README is otherwise accurate — instantaneous component queries, ECS scene-graph hierarchy, clustered forward+, 1M+ decals, 256-layer terrain, the path tracer, deterministic physics with CCD, the raycast vehicle and the kinematic FPS controller were each traced to a real entry point. Two are not:
189
+
190
+ | Claim | Reality |
191
+ |---|---|
192
+ | navmesh **"with agents"** | `NavigationMeshAgent` is an **empty stub**. There is a stateless `find_path` and nothing else — no agent state, steering, or avoidance. |
193
+ | **runtime obstacle carving** | No obstacle primitive exists. Carving is build-time only; the sole way to change the navmesh at runtime is a full rebuild. |
194
+
195
+ One caveat rather than a gap: *"Tiered API Access — low-level raw typed arrays"* holds for physics, geometry and transforms, but **not for the ECS store itself** — `EntityComponentDataset.components` is `Object[][]` and marked `@private`. The ECS low tier is index-based, not array-based.
196
+
197
+ ---
198
+
199
+ ## 6. Functional test gaps
200
+
201
+ The suite is green and large (9,337 tests). The question this section answers is not "is coverage high" but **"where would a real defect ship undetected?"** Benchmarks behind `test.skip` are deliberate and were excluded.
202
+
203
+ **The suite genuinely protects the numerical cores** — physics solver and narrowphase, the acoustic simulator, colour science, the BVHs, the fluid MAC solver, spline/Hermite maths, the path tracer. Those areas have standing gates and this review found almost nothing in them, which is exactly what good tests buy.
204
+
205
+ **It does not protect serialization, lifecycle, or startup/shutdown at all.** That is precisely where §3's recurring patterns live — the correlation is not a coincidence, it is cause and effect.
206
+
207
+ ### 6.1 The critical gaps
208
+
209
+ | ID | Gap | What ships broken |
210
+ |---|---|---|
211
+ | **TG-1** | `engine/save/**` — 6 files, **zero specs** | Durability is never verified. Nothing asserts a save actually committed. |
212
+ | **TG-2** | Only **one** component in the entire engine has ever round-tripped through the binary save format | Any field silently dropped, reordered, or read at the wrong width. |
213
+ | **TG-3** | 121 classes implement `toJSON`/`fromJSON`; ~77 also have a binary adapter. **Nothing compares the two.** | A component authored in a JSON blueprint and the same component restored from a save disagree — silently. |
214
+ | **TG-4** | **21 binary format upgraders, zero specs** | The backward-compatibility path for old saves is entirely unverified. An upgrader's only contract is "read exactly the old layout, write exactly the new" — and nothing checks it. |
215
+ | **TG-5** | Transient-entity and non-serializable-component exclusion is structurally unreachable by the suite | Invert either gate and you either persist entities that must not be persisted, or silently drop ones that must be. |
216
+ | **TG-6** | `Engine.js` is 682 lines; `Engine.spec.js` is **15 lines** ("constructor does not throw"). `EnginePluginManager` (319 lines) has no spec; `EngineHarness` (548 lines) is referenced by zero specs. | Every startup-ordering and shutdown defect in §4 — including `Engine.stop()` throwing before it tears anything down. |
217
+
218
+ TG-2, TG-3 and TG-4 are one gap wearing three hats, and they explain §3.2 completely.
219
+
220
+ ### 6.2 The highest-value MAJOR gaps
221
+
222
+ - **TG-7 — `link`/`unlink` symmetry is never asserted for any System**, despite `System.js` documenting it as *the* contract. 70 `*System.js` implementations; deleting a single `signal.remove(...)` or `scene.remove(object3d)` turns no test red. This is why §3.1 is the largest defect class in the review.
223
+ - **TG-9 — `view/View.spec.js` is a 6-line smoke test** standing in for `View.js` (804 lines) and 54 subclasses. This is why `view/` contains classes that cannot even be constructed.
224
+ - **TG-11 — `Signal` has nine hand-copied dispatch implementations (`send0`…`send8`); only `dispatch()` is behaviourally tested.** `Signal.merge` forwarding the `arguments` object instead of the arguments was found by this review and sits in exactly that untested band.
225
+ - **TG-10 — eleven of twelve asset loaders are untested**; the `AssetManager` contract ("call exactly one of `callback`/`failure`") is only ever proven against stubs, never against a real loader. Both asset CRITICALs are settlement-contract violations.
226
+ - **TG-12 — grid↔world conversion tests only one direction, never the round trip**, and never on a non-square grid.
227
+
228
+ ### 6.3 The cheapest closing move by far
229
+
230
+ Three generic, table-driven harnesses would close TG-2, TG-3, TG-4 and most of §3.2 at once:
231
+
232
+ 1. **Triple round-trip**, driven by the registered-class list: assert `field-init == fromJSON(toJSON()) == fromBinary(toBinary())` for every registered component. Covers ~121 classes in one spec.
233
+ 2. **Per-upgrader golden bytes**: hand-construct the old-version buffer, run the upgrader, assert the exact new bytes. 21 small specs.
234
+ 3. **`link`/`unlink` symmetry harness**: build a real `EntityComponentDataset`, link a system, unlink it, assert no residual subscriptions. Applies to 70 systems.
235
+
236
+ These are worth more than any individual fix in this review, because they convert an entire recurring class from invisible to caught.
237
+
238
+ ### 6.4 Stale skips
239
+
240
+ Three skipped suites are not benchmarks and should be resolved rather than left:
241
+
242
+ - `core/process/PromiseWatcher.spec.js` — **whole suite** skipped as "TODO broken tests". Un-skipping it crashes the Node worker with an unhandled rejection, because `PromiseWatcher.add()` discards the promise returned by `.finally()`. **The tests are right and the code is wrong.**
243
+ - `engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.spec.js` — skipped as "currently broken". Verified: **still broken** (see §4).
244
+ - `core/binary/BitSet.spec.js` "resizing up and down" — verified: **now passes**. Just un-skip it.
245
+
246
+ ---
247
+
248
+ ## 7. Adversarial review
249
+
250
+ Every CRITICAL, plus every MAJOR making a total-failure claim ("never works", "always throws", "renders nothing"), was handed to independent verifiers **instructed to refute it**, defaulting to REFUTED under uncertainty. They were given six explicit grounds for rejection: the code does not say what the finding claims; the trigger cannot occur; `assert.*` confusion; deliberate documented behaviour; severity inflation; already fixed. Verifiers preferred *execution* over reading — writing throwaway specs, running them, and deleting them.
251
+
252
+ **174 findings checked: 160 confirmed, 2 refuted, 12 downgraded.**
253
+
254
+ | Pass | Checked | Confirmed | Refuted | Downgraded |
255
+ |---|---:|---:|---:|---:|
256
+ | core (collection, binary, process, math, science) | 67 | 58 | 0 | 9 |
257
+ | view + engine misc | 45 | 44 | 0 | 1 |
258
+ | graphics, geom, ecs, asset | 62 | 58 | 2 | 2 |
259
+
260
+ ### What this tells us
261
+
262
+ **Factual accuracy was high; severity calibration was not.** Verifiers reported that claims "reproduced exactly, often to the digit". Only two findings were factually wrong, both in the same report (`gfx-gi`) and both resting on incorrect premises about three.js r136 — checked against the *installed* `node_modules/three`, not from memory:
263
+
264
+ - **GFXG-3 REFUTED** — r136 `ShaderMaterial` defaults `fog = false`, so the block claimed to fail compilation is unreachable.
265
+ - **GFXG-4 REFUTED** — `computeMaterialEquality` returns false for all `ShaderMaterial`s, so the claimed bad dedup cannot happen.
266
+
267
+ The 12 downgrades share **one** cause, and it is the most important calibration lesson in this review: *a total break of public API surface that no shipped code path reaches.* `SortedListProjection`, `Signal.merge`, `BiMap`, `hammersley_sequence`, `extractTransferables` and `IsAnything` are genuinely broken — reproduced — but nothing in the shipping game calls them.
268
+
269
+ This is a real tension with the project's standing convention that unreferenced exports are public surface, not dead code. **Both things are true**: they are real bugs in a published library and must be fixed, *and* they cannot break the game today. The proposal in §8 resolves this by separating **"breaks the shipping product"** from **"breaks a published API"**, rather than collapsing them into one severity axis.
270
+
271
+ ### Post-adversarial totals
272
+
273
+ | | CRITICAL | MAJOR | MINOR | total |
274
+ |---|---:|---:|---:|---:|
275
+ | Raw | 50 | 237 | 153 | 440 |
276
+ | **After adversarial adjustment** | **42** | **239** | **157** | **438** |
277
+
278
+ **Confidence.** 174 of 438 findings (40%) were independently verified, weighted toward the severe end — every CRITICAL was checked. In that sample the factual error rate was **1.1%** (2/174). Unverified MINORs carry the source reports' reliability rather than a verifier's; the risk there is severity, not fabrication.
279
+
280
+ ### One test-reliability note
281
+
282
+ `engine/simulation/Ticker.spec.js` → *"no ticks are dispatched while the page is hidden"* failed once in a full-suite run under heavy CPU contention, and passed 9/9 in three isolated runs and in a clean full re-run. It is **timing-flaky under load**, not a regression. Worth pinning to fake timers before it erodes trust in the suite.
283
+
284
+ ---
285
+
286
+ ## 8. Proposal
287
+
288
+ Tagged **CRITICAL / MAJOR / MINOR**. Because a published library has two distinct failure surfaces, each item also carries a reach marker:
289
+
290
+ - **[product]** — breaks the shipping game today.
291
+ - **[library]** — breaks a published API; no in-repo caller, so invisible to the game but live for any consumer.
292
+
293
+ Phases are ordered by value-per-effort, not by severity alone.
294
+
295
+ ### Phase 0 — Silent data loss and cannot-run-twice · **CRITICAL**
296
+
297
+ Small, well-understood, high blast radius. Land each with a red-before-green regression test.
298
+
299
+ | Item | Tag | Reach |
300
+ |---|---|---|
301
+ | `BinaryBuffer.writeUTF8String` zeroes the body on mid-write growth. Fix: advance `this.position` as the loop writes, or copy to `cursor` rather than `position` in `setCapacity`. | **CRITICAL** | product |
302
+ | `ThemeEngine`/`TerrainTheme` pass a `[0,1)` float as a child seed; Mulberry32 truncates it to a constant. Fix: derive integer child seeds. Restores all seed variation in the theme layer. | **CRITICAL** | product |
303
+ | `ShadedGeometrySystem` never removes its render layer; second engine start throws. Fix teardown, plus the three sibling leaks (`CameraSystem.rebuild`, `LightSystem` cache, `LightManager.dispose`). | **CRITICAL** | product |
304
+ | `AtlasLookupTexture` allocates no storage for the first 32 patches. Fix the reallocation guard and the `RGBA`/`RGB16UI` format mismatch. | **CRITICAL** | product |
305
+ | `WebGLTextureAtlas.add` never records patch size; `TextureAtlas.repack()` clears `Packed` twice and never `Painted`. | **CRITICAL** | product |
306
+ | `ParticleGroup` reuses one swap source for every deletion; `optimizeCommandQueue`'s comparator never returns `+1`. Corrupts particle data on any multi-delete frame. | **CRITICAL** | product |
307
+ | BVH8 `NodeProxy` loop runs at `j = -1`, emitting structurally invalid nodes on ~0.2% of ordinary builds. | **CRITICAL** | product |
308
+ | `ServerAuthoritativeClient` reconcile watermark is per-frame not per-entity — a client owning >1 predicted entity reconciles exactly one, forever. | **CRITICAL** | product |
309
+ | The four **unfixed 2026-07-03 CRITICALs**: `C5` decal `subscribe`/`unsubscribe`, `C13` terrain seam floor-vs-ceil, `C17`+`C18` MikkTSpace (faceted tangents + failed vertex welding on every real mesh). | **CRITICAL** | product |
310
+ | `Engine.stop()` throws before tearing anything down; `Engine.start()` swallows startup failure and resolves. | **CRITICAL** | product |
311
+ | `save/IndexedDBStorage` resolves on request success rather than transaction commit — a save can be reported successful and not committed. | **CRITICAL** | product |
312
+
313
+ ### Phase 1 — Three generic harnesses · **CRITICAL**
314
+
315
+ **This is the highest-value work in the review**, and it should be done *before* the long tail of individual fixes. Each converts an entire recurring class from invisible to caught, and each is one parameterised spec.
316
+
317
+ | Harness | Closes | Tag |
318
+ |---|---|---|
319
+ | **Triple round-trip** over the registered-class list: `field-init == fromJSON(toJSON()) == fromBinary(toBinary())`. ~121 classes. | TG-2, TG-3, and the whole of §3.2 | **CRITICAL** |
320
+ | **Per-upgrader golden bytes**: construct the old buffer, run the upgrader, assert exact new bytes. 21 upgraders, currently zero specs — this is the old-save migration path. | TG-4 | **CRITICAL** |
321
+ | **`link`/`unlink` symmetry**: real dataset, link a system, unlink, assert no residual subscriptions. 70 systems. | TG-7, and most of §3.1 | **CRITICAL** |
322
+
323
+ Without these, Phase 2 is a treadmill: the same classes will regrow.
324
+
325
+ ### Phase 2 — Pattern sweeps · **MAJOR**
326
+
327
+ Fix the class, not the instance. Each is a mechanical pass now that a harness exists to hold it.
328
+
329
+ - **[MAJOR, product]** Lifecycle sweep — every `link`/`startup` subscription needs a matching removal on the *same* signal with the *same* context; every GPU/DOM resource acquired needs disposal. Largest single defect class.
330
+ - **[MAJOR, product]** Serialization sweep — reconcile JSON, binary, and field-initialiser defaults per component. Includes point lights losing `distance`, water losing 7 of 9 fields, `SerializationMetadata` truncated to 8 bits, `Team`'s `INT32_MAX`/`Infinity` aliasing.
331
+ - **[MAJOR, product]** Promise-terminal sweep — `ConcurrentExecutor`, `ActionProcessor.doMany`, `WorkerProxy`, `ArrayBufferLoader`, `SVGAssetLoader`, `GameStateLoader`, `EngineHarness`. Every path must settle exactly once; failure must not resolve.
332
+ - **[MAJOR, product]** Sentinel-boundary sweep — make degenerate results *signalled* rather than encoded. `tri3_compute_normal` is the model case; it also drives `GFXT-45`.
333
+ - **[MAJOR, product]** Grep sweep for the mechanical classes: `& 0xff` precedence, `>>` vs `>>>`, `x|0` as floor, bare `.sort()` on numbers.
334
+ - **[MAJOR, product]** Device shutdown/cancellation — `PointerDevice` and `KeyboardDevice` leave input latched down after `stop()`, blur, or `pointercancel`.
335
+
336
+ ### Phase 3 — Area rehabilitation · **MAJOR**
337
+
338
+ - **[MAJOR, product]** `view/` — 42 findings, 6 of them classes that cannot run. Two root patterns cover most of it: raw `Signal.add` on caller-owned models instead of `bindSignal`, and teardown gated on `view.isLinked` *after* `View.unlink()` has already cleared it. Pair with TG-9 (a real `View` lifecycle spec) or it will regress.
339
+ - **[MAJOR, product]** `graphics/texture` — 76 findings. The algorithms are fine; the type/format pairings are not (`Uint8ClampedArray`, `Float16`, integer-vs-normalized internal formats, interleaved attributes, the `normalized` flag).
340
+ - **[MAJOR, library]** `core/debug` matcher library — `anything()` matches nothing, `nothing()` matches everything, the template formatter never substitutes. Broken as published; nothing in-repo reaches it.
341
+ - **[MAJOR, library]** `ActionProcessor` — two independent ways to permanently brick itself (redo crash after undo→do→redo; `doMany` failure deadlocks every later call).
342
+ - **[MAJOR, product]** Behaviour-tree lifecycle — `initialize`/`finalize` pairing across `ParallelBehavior`, `ConditionalBehavior`, `RepeatBehavior`.
343
+ - **[MAJOR, product]** `sampler2d_scale_down_lanczos` — needs a real rewrite (separable kernel, keep negative lobes, pixel-centre convention), then un-skip its spec.
344
+
345
+ ### Phase 4 — API and documentation · **MINOR**
346
+
347
+ - **[MAJOR, product]** `PhysicsSystem.setAngularVelocity` — the only API gap on a hot path, and the workaround is *silently wrong* because the direct field write does not wake the body.
348
+ - **[MAJOR, library]** `BiMap` has no `delete`; `List` has no `[Symbol.iterator]` or `every()`; `Uint32Map`/`PairUint32Map` cannot be enumerated; `IndexedFloat*Heap` has no `peek`; `CSRGraph` has no `fromArrayBuffer` receiver.
349
+ - **[MAJOR, product]** Correct the README, or build the features: **navmesh "with agents"** (`NavigationMeshAgent` is an empty stub) and **runtime obstacle carving** (no obstacle primitive exists) are advertised and absent. Also soften *"low-level raw typed arrays"* for the ECS store, which is `Object[][]` and `@private`.
350
+ - **[MINOR, library]** `engine/save` cannot be loaded standalone from the published package (`GameStateLoader` imports outside the package). Also no delete.
351
+ - **[MINOR]** Resolve the three stale skips: un-skip `BitSet` "resizing" (now passes), fix `PromiseWatcher` (the tests are right, the code is wrong), fix Lanczos then un-skip.
352
+ - **[MINOR]** Pin `Ticker.spec.js`'s hidden-page test to fake timers.
353
+
354
+ ### Sequencing
355
+
356
+ Phase 0 and Phase 1 are independent and can run in parallel; **Phase 1 should not be deferred behind Phase 0**, because it is what stops Phases 2–3 from regressing. Phases 2–3 are large but mechanical once the harnesses exist. Phase 4 is cheap and can be slotted anywhere.
357
+
358
+ **The single most valuable decision available** is to build the three harnesses in Phase 1. This review found 438 defects in a codebase with a green 9,337-test suite; the gap is not effort or skill, it is that the engine's *edges* have no contract tests, so defects there are structurally invisible. Fixing 438 bugs without closing that gap buys a snapshot. Closing it buys a ratchet.
359
+
360
+
361
+ ---
362
+
363
+ ## 9. Remediation outcome
364
+
365
+ The proposal above was executed. This section records what actually landed, and — more usefully — where the review's own conclusions turned out to be wrong.
366
+
367
+ **23 commits. Suite: 1554 suites / 9507 tests green, up from 1542 / 9337. Skips down from 136 to 129.**
368
+
369
+ ### Phase 0 — the CRITICALs on the Phase 0 list
370
+
371
+ **Not every CRITICAL in this document.** Section 8's Phase 0 was a curated
372
+ subset chosen for blast radius; the review found 50 CRITICALs in total and
373
+ **14 of them are fixed**, alongside the 4 outstanding CRITICALs inherited from
374
+ the 2026-07-03 review (C5, C13, C17, C18). **36 discovered CRITICALs remain
375
+ open**, listed at the end of this section.
376
+
377
+ `writeUTF8String` data loss · theme seed invariance · MikkTSpace edge pairing and vertex welding (C17/C18) · decal `subscribe`/`unsubscribe` (C5) · terrain seam floor-vs-ceil (C13) · three broken atlas paths · particle compaction · BVH8 `triangles[-1]` · engine headless/failure lifecycle · save durability · network per-entity reconcile.
378
+
379
+ Two shipped without a regression gate and were flagged as such: the decal fix (its context needs the whole Forward+ plugin) — now gated by the teardown contract — and IndexedDB durability, which has no IDB implementation available to the suite.
380
+
381
+ ### Phase 1 — three contract harnesses
382
+
383
+ | Harness | Covers | Found |
384
+ |---|---|---|
385
+ | binary round-trip | 48 of 77 adapters meaningfully exercised, the rest reported with reasons | Camera losing its entire lens; flags dropped by four components |
386
+ | teardown contract | every source in the tree | proven against the real decal defect |
387
+ | upgrader chain | 21 upgraders | **Path writes version 3 with no 2→3 upgrader — every older save unloadable** |
388
+
389
+ A fourth (runtime link/unlink symmetry) was prototyped and **dropped**: it reached only 7 of ~70 systems and reported four leaks that could not be attributed to either the system or the harness. Baselining unexplained results would record noise as signal.
390
+
391
+ ### Phases 2–4
392
+
393
+ Serialization: Camera v1 with upgrader. Promise terminals: `ConcurrentExecutor` no longer drops a task whose dependency failed, `Future` settles once, `PromiseWatcher` no longer leaks an unhandled rejection. Areas: the Lanczos downscaler rewritten (it returned `NaN`), `ViewGroup` and `MinimapMarkerView` made constructible, `anything()`/`nothing()` un-inverted. API: `setAngularVelocity`, `List.every`/iterator, `BiMap` removal. README corrected on navmesh agents and runtime obstacle carving.
394
+
395
+ ### Corrections to this document
396
+
397
+ Adversarial review of the implementation refuted several of the findings above. Recorded because a review that only accumulates is not trustworthy:
398
+
399
+ - **`optimizeCommandQueue` was downgraded on false grounds.** The first fix claimed the missing `+1` branch could not be shown to change V8's output. Wrong — the sample inputs were too small. Every permutation of a five-operation multiset finds orderings where a write sorts ahead of a remove.
400
+ - **The round-trip harness's first baseline was ~30 entries of the harness's own making.** It claimed Light and Water lose their colours entirely. They do not: the perturber assigned colour channels outside the 0..1 domain, and the 8-bit pack clamped them. What survives is narrower — `Color.toUint()` is RGB-only, so alpha is dropped by design.
401
+ - **`TransformPose` declaring `klass = Transform` is deliberate**, not a collision: it is a second, local interpolation format. A name-keyed chain check mistakes it for the save adapter.
402
+ - **`BiMap`'s inverted stores are load-bearing.** Flipping `add` to match its parameter names would have broken `EncodingBinaryBuffer`'s string interning. The names were corrected instead.
403
+ - Three Phase 0 fixes stopped one step short of the defect they named (`WebGLTextureAtlas` position, the lone-surrogate desync, `Engine.stop` leaving the render loop running), and one introduced a regression (an empty atlas allocating a 32×0 texture).
404
+
405
+ ### CRITICALs still open
406
+
407
+ ```
408
+ AI-1 ANIM-1 ASSET-1 ASSET-2 BIN-2 COLL-1 COLL-3 ECS-1 ECS-14 ECS-40 GEN-2
409
+ GEOM3-1 GFXG-1 GFXG-2 GFXR-11 GFXT-1 GFXT-2 GFXT-3 GFXT-4 GFXT-32 GFXT-40
410
+ GFXT-68 GFXT-69 INPUT-1 INPUT-2 INPUT-3 MATH-1 MATH-2 PROC-10 PROC-11
411
+ PROC-19 PROC-20 VIEW-1 VIEW-2 VIEW-4 VIEW-6
412
+ ```
413
+
414
+ Worth pulling out, because they are cheap relative to their reach:
415
+
416
+ - **GFXR-11** `ShadedGeometrySystem` never removes its render layer, and
417
+ `RenderLayerManager.add()` throws on a duplicate — the *second* engine start
418
+ throws. This was named in the Phase 0 list and never implemented.
419
+ - **GEOM3-1** the mesh simplifier's flip test degenerates to "does this face
420
+ point downward", via `tri3_compute_normal`'s `(0,1,0)` sentinel.
421
+ - **PROC-10 / PROC-11** `ActionProcessor` has two independent ways to brick
422
+ itself permanently.
423
+ - **INPUT-2** pointer "down" state can never be cleared — no `pointercancel`
424
+ or blur handling.
425
+ - **VIEW-1 / VIEW-2 / VIEW-4 / VIEW-6** four more `view/` classes that throw or
426
+ silently do nothing.
427
+
428
+ ### What remains
429
+
430
+ The bulk of the 438 findings — most MAJORs and nearly all MINORs — is untouched. The `KNOWN_DIVERGENCE` baseline in the round-trip harness is the honest ledger for the serialization class: each entry deleted is one component that survives a save. Golden-bytes verification of what each upgrader *emits* is still outstanding; the chain check only proves a path exists.
431
+
432
+ ---
433
+
434
+ ## 10. Round 2 proposal
435
+
436
+ Selection rule for this round: **only work where the correct behaviour is not a design decision.** A fix qualifies if the current code is wrong against a contract that already exists elsewhere in the tree — a sibling that does it right, a documented convention, a method that does not exist, a promise that cannot settle. Anything requiring a judgement call about intended behaviour is deferred, not because it matters less but because guessing at intent is how a review turns into a rewrite.
437
+
438
+ Second constraint: **performance characteristics are load-bearing.** Two candidates below sit on hot paths and are called out individually; neither is worth a correctness fix that costs a per-frame allocation or a per-sample branch.
439
+
440
+ ### 10.1 Batch A — wrong identifier, no behavioural judgement (12)
441
+
442
+ Each is a single wrong token whose correct value is fixed by the surrounding code. No design latitude, no perf surface.
443
+
444
+ | ID | Site | Wrong | Right |
445
+ |---|---|---|---|
446
+ | GFXT-1 | `sampler2d_paint.js:68` | `x + sourceY` | `x + sourceX` |
447
+ | GFXT-40 | `computeMeshSurfaceArea.js:40` | vertex C's Y read from the Z slot | `points[c3 + 1]` |
448
+ | GFXT-2 | `bitSet2Sampler2D.js:35,37` | `target.set(...)` — `Sampler2D` has no `set` | `target.write(...)` |
449
+ | GFXT-3 | `computeSignedDistanceField_Chamfer.js:72` | stale `v`, stores last instead of min | assign `v = vN` after each write |
450
+ | GFXT-68 | `Ribbon.js:143` | tip vertices on opposite sides | negate the cross to match the degenerate branch |
451
+ | GFXT-69 | `load_environment_map.js:57` | `EXRLoader` asked for `UnsignedByteType` | `HalfFloatType` |
452
+ | ECS-40 | `LineSetDescription.js:56` | walks `set.children`, unbounded loop | `set.sets` |
453
+ | ECS-14 | `TerrainTileManager.js:461` | reads the vertical axis as a grid row | index by `v3[0]`/`v3[2]` |
454
+ | COLL-3 | `Signal.js:797` | dispatches the `arguments` object | spread it |
455
+ | BIN-2 | `Localization.js:140` | trailing-slash trim never terminates | slice, do not re-test |
456
+ | INPUT-1 | `TopDownCameraControllerHelper.js:45` | geometry classes never imported | import them |
457
+ | GFXR-11 | `ShadedGeometrySystem.js:254` | render layer never removed; second start throws | remove it in `shutdown` |
458
+
459
+ ### 10.2 Batch B — a promise that cannot settle (3)
460
+
461
+ The contract is not in question: a path that neither resolves nor rejects is a hang.
462
+
463
+ - **PROC-20** `WorkerProxy` — a failed `postMessage` drops the request without rejecting.
464
+ - **ASSET-2** `ArrayBufferLoader` — a fetch stream error mid-download never reaches the consumer; `pump()` has no rejection handler.
465
+ - **PROC-19** `extractTransferables(null)` throws while the inline duplicate a few lines away guards for exactly that.
466
+
467
+ ### 10.3 Batch C — hot path, correctness *and* cost (2)
468
+
469
+ Both are real defects. Both sit somewhere the naive fix is unacceptable, so each carries a required approach.
470
+
471
+ - **MATH-1** — `sdnoise` computes its lattice cell with `x | 0`, which truncates toward zero and is therefore wrong for every negative coordinate. This is the inner loop of noise generation. `Math.floor` is the obvious fix and must be **measured, not assumed**: if it costs anything measurable, use the branchless `(x | 0) - (x < 0 ? 1 : 0)` form instead. Correctness is not negotiable; which of the two lands is a measurement.
472
+ - **INPUT-3** — `InputControllerSystem` mutates its binding array mid-dispatch, so destroying an entity from an input handler throws. The stated fix is "iterate a snapshot", but dispatch runs per input event and a per-dispatch `slice()` is a per-event allocation in a zero-allocation engine. Prefer a reverse walk or an index-stable removal that needs no copy.
473
+
474
+ ### 10.4 Explicitly deferred, with reasons
475
+
476
+ Not "lower priority" — genuinely not unambiguous:
477
+
478
+ - **ANIM-1**, **GEOM3-1** — the fix changes which result the algorithm considers best. That is a behavioural change needing a decision, not a repair.
479
+ - **ECS-1**, **GEN-2**, **VIEW-1/2/4**, **PROC-10/11** — each needs a lifecycle or task-graph restructure with more than one defensible shape.
480
+ - **GFXG-1**, **GFXG-2**, **GFXT-4** — GPU-side or shared-buffer ownership; cannot be verified from the suite, and `GFXT-4`'s fix trades a mutation for a copy, which is a perf decision.
481
+ - **ASSET-1** (Adam7), **INPUT-2** (`pointercancel`), **MATH-2**, **COLL-1**, **AI-1**, **GFXT-32** — each is likely correct as written up, but each needs a fixture or a browser behaviour I cannot confirm here, and shipping an unverified fix to a CRITICAL is worse than leaving it listed.
482
+
483
+ ### 10.5 Revision after adversarial review of the proposal
484
+
485
+ The proposal was reviewed before any of it was written. Three items were wrong, one was missing, and two deferrals were unjustified.
486
+
487
+ **Removed from the plan:**
488
+
489
+ - **GFXT-68** (`Ribbon`) — *not unambiguous.* With `normal = -Z` the unnegated branch already agrees; the correct sign depends on a winding convention that is not stated anywhere in the tree. Negating on a guess would invert every ribbon. Deferred.
490
+ - **INPUT-3** — *the prescribed fix is wrong.* A reverse walk inverts binding priority order, and does nothing about `registerBinding`'s re-sort, which is the actual source of the mutation. Deferred until the dispatch/registration interaction is understood.
491
+
492
+ **Corrected:**
493
+
494
+ - **MATH-1** — the fallback this document proposed, `(x | 0) - (x < 0 ? 1 : 0)`, **is not floor**: it over-subtracts at exact negative integers (`floor(-1) = -1`, the form yields `-2`). Measurement also shows no penalty for `Math.floor` — across warmed runs the two are indistinguishable, and the variance between repeats of the *same* function exceeds the difference between them. So the fix is plainly `Math.floor`. Separately, it turns a currently-green spec red, which has to be resolved on its merits: a spec that pins truncation is pinning the defect.
495
+ - **ECS-14** — the table lost the load-bearing half of the fix. The divisors matter: index by `v3[0] / scale.x` and `v3[2] / scale.y`. `scale.y` really is the right divisor for the Z axis (the terrain's scale is 2D).
496
+
497
+ **Added — it was missing from both lists:**
498
+
499
+ - **VIEW-6** `Minimap.clear()` calls `addChild` where `removeChild` is meant, from `unlink()`. One wrong token, intent fixed by the method name. It belongs in Batch A and was simply dropped.
500
+
501
+ **Promoted out of "deferred" — the stated reason was false:**
502
+
503
+ - **COLL-1** `SortedListProjection` — deferred as needing a fixture; it reproduces in plain node in seconds, and the `where + 1` insert is forced by `binarySearchLowIndex`'s contract.
504
+ - **MATH-2** `hammersley_sequence` — deferred for the same false reason; it is pure maths with a sibling (`halton_sequence`) as the reference and no callers to break.
505
+
506
+ **Two items are sound but cannot take the red-test-first protocol**, and are marked as such rather than pretended otherwise: **GFXT-69** (no `.exr` fixture exists) and **BIN-2** (the red test wedges the jest worker synchronously, because the bug is an infinite loop).
507
+
508
+ ## 11. Round 2 outcome
509
+
510
+ Landed across `1c13a74ae`, `18f627741`, `62047e542`, with a self-review after each. Every item below is pinned by a test that was verified red against the unfixed code, except where stated.
511
+
512
+ ### 11.1 What landed
513
+
514
+ **Batch A — wrong identifier (11 of 12).**
515
+
516
+ | ID | Site | Pinned by |
517
+ |---|---|---|
518
+ | GFXT-1 | `sampler2d_paint` read the source column from `sourceY` | `sampler2d_paint.spec.js` |
519
+ | GFXT-40 | `computeMeshSurfaceArea` read vertex C's Y from the Z slot | `computeMeshSurfaceArea.spec.js` |
520
+ | GFXT-2 | `bitSet2Sampler2D` called `target.set`, which does not exist | existing sampler specs |
521
+ | GFXT-3 | chamfer SDF compared each candidate against the original, not the running minimum | `computeSignedDistanceField_Chamfer.spec.js` |
522
+ | GFXT-69 | `EXRLoader` asked for `UnsignedByteType` | *not pinned — no `.exr` fixture* |
523
+ | ECS-40 | `LineSetDescription.collect` re-walked the root's children forever | `LineSetDescription.spec.js` (times out unfixed) |
524
+ | ECS-14 | `TerrainTileManager` world lookup: vertical axis read as a grid row, grid scale not divided out | `TerrainTileManager.spec.js` |
525
+ | COLL-3 | `Signal.merge` dispatched the `arguments` object as one argument | `Signal.spec.js` |
526
+ | BIN-2 | `Localization` trailing-slash trim discarded the slice and never terminated | `Localization.spec.js` |
527
+ | INPUT-1 | `TopDownCameraControllerHelper` used geometry classes it never imported | import resolution |
528
+ | GFXR-11 | `ShadedGeometrySystem` never released its render layer, so a second startup threw | `RenderLayerManager.spec.js` (contract only) |
529
+
530
+ GFXT-68 (`Ribbon`) stayed deferred, per §10.5.
531
+
532
+ **Batch B — a promise that cannot settle (3 of 3).** `WorkerProxy` (failed `postMessage` dropped the request), `ArrayBufferLoader` (stream failure never reached the consumer), `extractTransferables` (threw on `null`). All three pinned; the first two time out against the unfixed code.
533
+
534
+ **Batch C.** `MATH-1` deferred — see §11.3. `INPUT-3` deferred per §10.5.
535
+
536
+ **Promoted out of "deferred".** `COLL-1` (`SortedListProjection` insert position) and `MATH-2` (`hammersley_sequence`), both pinned. `hammersley_sequence` also lost its `count` parameter: the radical inverse does not depend on the size of the set, no version of the body ever read it, and the function has no callers in the tree — it is pure published surface, so a parameter documented as permanently unused is worse for a library consumer than a clean two-argument signature.
537
+
538
+ ### 11.2 What the self-review of this round caught
539
+
540
+ The round-2 work was itself reviewed, and it found four defects in the fixes and three false statements. Recording both, because a review that only records the wins is not a review.
541
+
542
+ **Defects in the round-2 work, since fixed in `62047e542`:**
543
+
544
+ - **`hammersley_sequence` — a regression I introduced.** Correcting the accumulator turned the incremental formulation numerically unstable: base 3 produced **13 distinct values over 512 samples**. The spec tested base 2 only, so it stayed green. Rewritten to the closed-form radical inverse that the sibling `halton_sequence` already uses — O(log i) instead of O(i), stable for any base — and the spec now cross-validates against `halton_sequence` for bases 2/3/5/7/11 and asserts 512-sample distinctness. **The missing distinctness check is the reason this got through, and it is the durable part of the fix.**
545
+ - **ECS-14 landed half-done.** §10.5 explicitly called the scale divisors "the load-bearing half", and the implementation applied the axis fix without them. Wrong tile for every terrain whose `gridScale` is not 1.
546
+ - **`ArrayBufferLoader` was still one throw away from a hang.** The rejection handler went in as the second argument to `.then`, which cannot see a throw from its own fulfilment path — so a throwing caller-supplied `progress` callback still wedged the load forever. Now `.catch`, and pinned.
547
+ - **`Minimap.clear()` was justified with a comment about the wrong array, and stopped short of the real defect.** `removeChild` does not mutate the array the `.slice()` was defending, and `removeObserver(observer, true)` has usually emptied `__cameraViews` before `clear()` runs — so as written the fix was close to inert. The array is assigned **in the constructor**, not in `link()`, and `link()` re-registers the observer with `notify = true`; leaving stale entries in it therefore breaks the second `link()` after an `unlink()` — the same cannot-run-twice shape as GFXR-11. `clear()` now drops the entries too.
548
+
549
+ **False statements, corrected:**
550
+
551
+ - **Two Batch A items were listed as landed and were not: BIN-2 and GFXT-69.** Both have since landed. GFXT-69 was worse than the table said — `EXRLoader` does not merely prefer float types, it falls through to a `default` branch that never allocates the output buffer, so *no* `.exr` environment map could load at all.
552
+ - **The chamfer commit claimed the fix meant "fewer stores".** Measured, it is **13% more stores and about 2% slower**. The fix is still correct and still lands; the justification was invented. Cost, measured: negligible against a two-pass sweep that is memory-bound anyway.
553
+ - **The MATH-1 deferral reasoning was not honest** — see below.
554
+
555
+ ### 11.3 MATH-1, restated honestly
556
+
557
+ The deferral was argued on the grounds that `FASTFLOOR` is "neither truncation nor floor, so the correct target is unclear". That is false, and the argument does not survive contact with the code:
558
+
559
+ - `FASTFLOOR` **equals `Math.floor` at every non-integer input**, and differs only at exact negative integers.
560
+ - `x | 0` differs from **both** at every negative coordinate — it is the one form that is wrong everywhere below zero.
561
+ - `create_simplex_noise_2d.js`, in the same directory, **already made this exact fix and has a regression spec for it.** The convention is settled in the tree.
562
+
563
+ So MATH-1 is unambiguous on its merits and belongs in Batch A. The one real reason to hold it is unchanged and sufficient on its own: **`sdnoise` feeds procedural generation, and changing lattice cell selection re-rolls every generated map from a given seed.** That is a content decision with a migration cost, not a code decision — it needs a deliberate call about whether existing seeds are allowed to change, and it should land on its own so the diff in generated output is attributable.
564
+
565
+ Measurement, since the original proposal asked for it: `Math.floor` and `x | 0` are indistinguishable across warmed runs — repeat-to-repeat variance on the *same* function exceeds the gap between them. **There is no performance argument on either side.** The proposal's suggested branchless fallback `(x | 0) - (x < 0 ? 1 : 0)` is not floor at all (it yields `-2` for `floor(-1)`) and must not be used.
566
+
567
+ ### 11.4 Standing state
568
+
569
+ Round 2 closed 16 items. The CRITICALs listed as still open in §9 are unchanged by this round except for ECS-14 and BIN-2 — round 2 deliberately took the unambiguous work, and the open CRITICALs are open precisely because they are not.
570
+
571
+ The three durable additions from this round are worth more than the individual fixes: the `hammersley` distinctness check, the `ArrayBufferLoader` settle-under-failure specs, and `Localization`'s first spec (which drives a real `AssetManager` through a real loader, the pattern the rest of the loader tests should follow).
@@ -1 +1 @@
1
- {"version":3,"file":"BinaryBuffer.d.ts","sourceRoot":"","sources":["../../../../src/core/binary/BinaryBuffer.js"],"names":[],"mappings":"AA+BA;;;;;;;;;;;;;;;;;;GAkBG;AACH;IAivCI;;;;OAIG;IACH,4BAHW,UAAU,GACT,YAAY,CAUvB;IAED;;;;OAIG;IACH,0BAHW,WAAW,GACV,YAAY,CAQvB;IAED;;;;;OAKG;IACH,8BAJW,YAAY,UACZ,YAAY,GACV,MAAM,CAQlB;IAED;;;;;OAKG;IACH,2BAJW,YAAY,UACZ,YAAY,GACV,MAAM,CAQlB;IAED;;;;;OAKG;IACH,yBAJW,YAAY,UACZ,YAAY,GACV,MAAM,CAQlB;IAED;;;;;OAKG;IACH,0BAJW,YAAY,UACZ,YAAY,GACV,MAAM,CAQlB;IAED;;;;;OAKG;IACH,0BAJW,YAAY,UACZ,YAAY,GACV,MAAM,CAQlB;IAED;;;;;OAKG;IACH,2BAJW,YAAY,UACZ,YAAY,GACV,MAAM,CAQlB;IAED;;;;;OAKG;IACH,2BAJW,YAAY,UACZ,YAAY,GACV,MAAM,CAQlB;IAED;;;;;;OAMG;IACH,yBALW,YAAY,UACZ,YAAY,UACZ,MAAM,GACJ,UAAU,CActB;IAh4CD;;;;;OAKG;IACH,YAFU,UAAU,GAAC,OAAO,CAES;IAErC;;;;;OAKG;IACH,UAFU,MAAM,CAEH;IASb;;OAEG;IACH,sBAEC;IAZD;;OAEG;IACH,mBAEC;IASD;;;OAGG;IACH,UAFU,MAAM,CAEgB;IAEhC;;;;;;OAMG;IACH,aAA6C;IAE7C;;;;OAIG;IACH,iBAAmC;IAEnC;;;;OAIG;IACH,qBAAyC;IAEzC;;;;OAIG;IACH,qBAAmB;IAEnB;;;OAGG;IACH,4BAEC;IAED;;;;;;OAMG;IACH,sBAFW,WAAW,QAYrB;IAED;;;;OAIG;IACH,QAFa,YAAY,CAMxB;IAED;;;;OAIG;IACH,iBAFW,MAAM,QAMhB;IAED;;;;;;;;OAQG;IACH,sBAJW,MAAM,QAqChB;IAED;;;OAGG;IACH,6BAFW,MAAM,QAuBhB;IAED;;;OAGG;IACH,eAFa,MAAM,CAMlB;IAED;;;OAGG;IACH,eAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,eAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,YAFY,MAAM,CAQjB;IAED;;;OAGG;IACH,aAFY,MAAM,CAQjB;IAED;;;OAGG;IACH,aAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,aAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,aAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,cAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,gBAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,gBAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,cAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,gBAFa,MAAM,CAUlB;IAED;;;OAGG;IACH,gBAFa,MAAM,CAUlB;IAED;;;OAGG;IACH,cAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,gBAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,gBAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,cAFa,MAAM,CAQlB;IAED;;;;;OAKG;IACH,4BAFW,UAAU,sBAFV,MAAM,UACN,MAAM,QAOhB;IAED;;;;;OAKG;IACH,6BAFW,WAAW,sBAFX,MAAM,UACN,MAAM,QAOhB;IAED;;;;;OAKG;IACH,6BAFW,WAAW,GAAC,MAAM,EAAE,GAAC,UAAU,MAAM,CAAC,sBAFtC,MAAM,UACN,MAAM,QAOhB;IAED;;;;;OAKG;IACH,2BAFW,SAAS,sBAFT,MAAM,UACN,MAAM,QAOhB;IAED;;;;;OAKG;IACH,4BAFW,UAAU,sBAFV,MAAM,UACN,MAAM,QAOhB;IAED;;;;;OAKG;IACH,4BAFW,UAAU,sBAFV,MAAM,UACN,MAAM,QAOhB;IAED;;;;;OAKG;IACH,8BAFW,YAAY,GAAC,MAAM,EAAE,sBAFrB,MAAM,UACN,MAAM,QAOhB;IAED;;;;;OAKG;IACH,8BAFW,YAAY,sBAFZ,MAAM,UACN,MAAM,QAOhB;IAED;;;;;OAKG;IACH,0BAFW,YAAY,GAAC,MAAM,EAAE,iBAFrB,MAAM,UACN,MAAM,QAUhB;IAED;;;;;OAKG;IACH,0BAFW,YAAY,GAAC,MAAM,EAAE,iBAFrB,MAAM,UACN,MAAM,QAUhB;IAED;;;;;OAKG;IACH,8BAFW,YAAY,GAAC,MAAM,EAAE,sBAFrB,MAAM,UACN,MAAM,QAOhB;IAED;;;OAGG;IACH,oBAFW,MAAM,QAMhB;IAED;;;OAGG;IACH,oBAFW,MAAM,QAShB;IAED;;;OAGG;IACH,oBAFW,MAAM,QAShB;IAED;;;OAGG;IACH,iBAFW,MAAM,QAShB;IAED;;;OAGG;IACH,kBAFW,MAAM,QAShB;IAED;;;OAGG;IACH,kBAFW,MAAM,QAShB;IAED;;;OAGG;IACH,kBAFW,MAAM,QAShB;IAED;;;;;OAKG;IACH,uBAJW,SAAS,GAAC,MAAM,EAAE,GAAC,UAAU,MAAM,CAAC,iBACpC,MAAM,UACN,MAAM,QAYhB;IAED;;;;;OAKG;IACH,wBAJW,UAAU,GAAC,MAAM,EAAE,GAAC,UAAU,MAAM,CAAC,iBACrC,MAAM,UACN,MAAM,QAYhB;IAED;;;;;OAKG;IACH,wBAJW,UAAU,GAAC,MAAM,EAAE,GAAC,UAAU,MAAM,CAAC,iBACrC,MAAM,UACN,MAAM,QAYhB;IAED;;;OAGG;IACH,kBAFW,MAAM,QAShB;IAED;;;;;OAKG;IACH,wBAJW,UAAU,GAAC,MAAM,EAAE,iBACnB,MAAM,UACN,MAAM,QAQhB;IAED;;;OAGG;IACH,mBAFW,MAAM,QAShB;IAED;;;OAGG;IACH,qBAFW,MAAM,QAShB;IAED;;;OAGG;IACH,qBAFW,MAAM,QAShB;IAED;;;;;OAKG;IACH,yBAJW,WAAW,GAAC,MAAM,EAAE,iBACpB,MAAM,UACN,MAAM,QAQhB;IAED;;;OAGG;IACH,mBAFW,MAAM,QAQhB;IAED;;;OAGG;IACH,qBAFW,MAAM,QAgBhB;IAED;;;OAGG;IACH,qBAFW,MAAM,QAgBhB;IAED;;;;;;OAMG;IACH,oBAFW,MAAM,QAuBhB;IAED;;;OAGG;IACH,eAFa,MAAM,CAqBlB;IAED;;;OAGG;IACH,mBAFW,MAAM,QAShB;IAED;;;OAGG;IACH,qBAFW,MAAM,QAShB;IAED;;;OAGG;IACH,qBAFW,MAAM,QAShB;IAED;;;OAGG;IACH,mBAFW,MAAM,QAShB;IAED;;;;;OAKG;IACH,yBAJW,WAAW,GAAC,MAAM,EAAE,GAAC,UAAU,MAAM,CAAC,iBACtC,MAAM,UACN,MAAM,QAYhB;IAED;;;;;OAKG;IACH,kBAJW,UAAU,GAAC,iBAAiB,iBAC5B,MAAM,UACN,MAAM,QAgChB;IAED;;;;;OAKG;IACH,uBAJW,UAAU,sBACV,MAAM,UACN,MAAM,QAiBhB;IAED;;;OAGG;IACH,wBAFW,MAAM,QAqFhB;IAED;;;OAGG;IACH,kBAFa,MAAM,CAuElB;IAED;;;;;;;;OAQG;IACH,yBAFW,MAAM,QAuBhB;IAED;;;;;;;;;OASG;IACH,4BAJW,MAAM,oBACN,OAAO,GACL,MAAM,CAoBlB;IAED;;;;OAIG;IACH,YAFY,MAAM,CAIjB;IAED;;;;;;;;;;;OAWG;IACH,eAFY,MAAM,CAcjB;IAsJL;;;OAGG;IACH,yBAFU,OAAO,CAEoB;CANpC;2BA76C0B,iBAAiB"}
1
+ {"version":3,"file":"BinaryBuffer.d.ts","sourceRoot":"","sources":["../../../../src/core/binary/BinaryBuffer.js"],"names":[],"mappings":"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"}