@woosh/meep-engine 3.1.0 → 3.2.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 (1822) hide show
  1. package/LICENSE +188 -188
  2. package/README.md +152 -152
  3. package/editor/Editor.js +598 -598
  4. package/editor/EditorCameraNavigation.js +205 -205
  5. package/editor/EditorKeyMap.js +182 -182
  6. package/editor/SelectionVisualizer.js +127 -127
  7. package/editor/actions/concrete/ActionInvalidateSampler.js +27 -27
  8. package/editor/actions/concrete/PatchTerrainHeightAction.js +85 -85
  9. package/editor/camera/camera_framing.js +104 -104
  10. package/editor/clipboard.js +184 -184
  11. package/editor/ecs/component/editors/ObservedIntegerEditor.js +22 -22
  12. package/editor/ecs/component/editors/ObservedStringEditor.js +34 -34
  13. package/editor/ecs/component/editors/common/two_way_sync.js +50 -50
  14. package/editor/ecs/component/editors/ecs/GridObstacleEditor.js +19 -19
  15. package/editor/ecs/component/editors/ecs/ParameterLookupTableEditor.js +35 -35
  16. package/editor/ecs/component/editors/ecs/ParameterTrackEditor.js +17 -17
  17. package/editor/ecs/component/editors/ecs/SGMeshEditor.js +24 -24
  18. package/editor/ecs/component/editors/ecs/ShadedGeometryEditor.js +33 -33
  19. package/editor/ecs/component/editors/ecs/Trail3DEditor.js +45 -45
  20. package/editor/ecs/component/editors/ecs/buildGridObstaclePreview.js +19 -19
  21. package/editor/ecs/component/editors/ecs/terrain/TerrainEditor.js +72 -72
  22. package/editor/ecs/component/editors/shade/MeshletGeometryEditor.js +30 -30
  23. package/editor/ecs/component/editors/shade/ShadeImageEditor.js +70 -70
  24. package/editor/ecs/component/editors/shade/ShadeMaterialEditor.js +34 -34
  25. package/editor/ecs/component/editors/shade/ShadeTextureEditor.js +46 -46
  26. package/editor/ecs/component/editors/shade/StandardShadeMaterialEditor.js +24 -24
  27. package/editor/ecs/component/prototypeObjectEditor.js +265 -265
  28. package/editor/ecs/component/registerBasicTypeEditors.js +100 -100
  29. package/editor/ecs/component/registerEngineComponentEditors.js +95 -95
  30. package/editor/entity_world_bounds.js +27 -27
  31. package/editor/particles/lut_ops.js +148 -148
  32. package/editor/particles/particleEditEvents.js +12 -12
  33. package/editor/particles/rebuildParticleEmitter.js +31 -31
  34. package/editor/persistence/EditorLayoutStore.js +71 -71
  35. package/editor/persistence/SceneMetadata.js +52 -52
  36. package/editor/persistence/SceneSlotManager.js +144 -144
  37. package/editor/persistence/buildNewSceneDataset.js +67 -67
  38. package/editor/persistence/files.js +68 -68
  39. package/editor/persistence/scene_import.js +143 -143
  40. package/editor/persistence/scene_serialization.js +79 -79
  41. package/editor/persistence/string_buffer_codec.js +41 -41
  42. package/editor/process/GridDisplayProcess.js +125 -125
  43. package/editor/process/SymbolicDisplayProcess.js +106 -108
  44. package/editor/process/symbolic/CameraSymbolicDisplay.js +146 -146
  45. package/editor/process/symbolic/LightSymbolicDisplay.js +172 -172
  46. package/editor/process/symbolic/PathSymbolicDisplay.js +118 -118
  47. package/editor/process/symbolic/PositionedMarkerSymbolicDisplay.js +79 -79
  48. package/editor/process/symbolic/SoundEmitterSymbolicDisplay.js +57 -57
  49. package/editor/process/symbolic/SymbolicDisplay.js +62 -62
  50. package/editor/process/symbolic/gizmo_draw_wire_box_oriented.js +85 -85
  51. package/editor/process/symbolic/gizmo_draw_wire_circle.js +53 -53
  52. package/editor/prototypeEditorShell.js +156 -156
  53. package/editor/selection/editor_pick.js +130 -130
  54. package/editor/selection/screen_rect_frustum.js +119 -119
  55. package/editor/style/controls.scss +168 -168
  56. package/editor/style/inspector.scss +223 -223
  57. package/editor/templates/entity_templates.js +167 -167
  58. package/editor/tools/GridPaintTool.js +273 -273
  59. package/editor/tools/SelectionTool.js +307 -307
  60. package/editor/tools/TransformToolV2.js +378 -378
  61. package/editor/tools/engine/ToolEngine.js +188 -188
  62. package/editor/tools/paint/TerrainTexturePaintTool.js +250 -250
  63. package/editor/tools/v2/BlenderCameraOrientationGizmo.js +501 -501
  64. package/editor/tools/v2/TransformControls.js +971 -971
  65. package/editor/tools/v2/handle/gizmo_drag_plane.js +141 -141
  66. package/editor/tools/v2/handle/gizmo_draw.js +399 -399
  67. package/editor/tools/v2/handle/gizmo_handles.js +364 -364
  68. package/editor/tools/v2/handle/gizmo_ray_shapes.js +239 -239
  69. package/editor/view/ecs/HierarchicalEntityListView.js +339 -339
  70. package/editor/view/ecs/components/DatGuiController.js +2 -2
  71. package/editor/view/ecs/components/common/AutoCanvasView.js +100 -100
  72. package/editor/view/ecs/components/common/TextController.js +59 -59
  73. package/editor/view/library/MeshLibraryView.js +175 -175
  74. package/editor/view/library/mesh_library_drag.js +63 -63
  75. package/editor/view/library/model_thumbnail_source.js +86 -86
  76. package/editor/view/makeEntityDecorators.js +125 -125
  77. package/editor/view/node-graph/NodeGraphSelection.js +89 -89
  78. package/editor/view/node-graph/NodeView.js +211 -211
  79. package/editor/view/node-graph/actions/ConnectionDeleteAction.js +36 -36
  80. package/editor/view/node-graph/actions/NodesMoveAction.js +41 -41
  81. package/editor/view/node-graph/connection_wire_geometry.js +107 -107
  82. package/editor/view/particles/ColorLutGradientView.js +291 -291
  83. package/editor/view/particles/ScalarLutCurveView.js +279 -279
  84. package/editor/view/prepareMeshLibrary.js +188 -188
  85. package/editor/view/shell/SceneTreePanelView.js +119 -119
  86. package/editor/view/v2/SplitView.js +2 -2
  87. package/package.json +94 -94
  88. package/samples/generation/generators/interactive/mir_generator_place_buff_objects.js +362 -362
  89. package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +738 -738
  90. package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +79 -79
  91. package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +93 -93
  92. package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +80 -80
  93. package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +164 -164
  94. package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +69 -69
  95. package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +102 -102
  96. package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +129 -129
  97. package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +72 -72
  98. package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +74 -74
  99. package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +169 -169
  100. package/src/DUPLICATION_AUDIT_2026_08_07.md +254 -254
  101. package/src/DUPLICATION_AUDIT_REMEDIATION.md +250 -250
  102. package/src/REVIEW_2026_08_06/adv-core.md +511 -511
  103. package/src/REVIEW_2026_08_06/adv-gfx.md +480 -480
  104. package/src/REVIEW_2026_08_06/adv-view.md +446 -446
  105. package/src/REVIEW_2026_08_06/api-core.md +296 -296
  106. package/src/REVIEW_2026_08_06/api-engine.md +195 -195
  107. package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +507 -507
  108. package/src/REVIEW_2026_08_06/core-binary.md +348 -348
  109. package/src/REVIEW_2026_08_06/core-collection.md +376 -376
  110. package/src/REVIEW_2026_08_06/core-math.md +221 -221
  111. package/src/REVIEW_2026_08_06/core-process.md +266 -266
  112. package/src/REVIEW_2026_08_06/core-science.md +223 -223
  113. package/src/REVIEW_2026_08_06/engine-ai-nav.md +279 -279
  114. package/src/REVIEW_2026_08_06/engine-animation.md +167 -167
  115. package/src/REVIEW_2026_08_06/engine-asset.md +166 -166
  116. package/src/REVIEW_2026_08_06/engine-ecs.md +920 -920
  117. package/src/REVIEW_2026_08_06/engine-input.md +197 -197
  118. package/src/REVIEW_2026_08_06/engine-misc.md +248 -248
  119. package/src/REVIEW_2026_08_06/engine-terrain.md +52 -52
  120. package/src/REVIEW_2026_08_06/generation.md +176 -176
  121. package/src/REVIEW_2026_08_06/geom-2d.md +434 -434
  122. package/src/REVIEW_2026_08_06/geom-3d.md +117 -117
  123. package/src/REVIEW_2026_08_06/gfx-gi.md +143 -143
  124. package/src/REVIEW_2026_08_06/gfx-render.md +740 -740
  125. package/src/REVIEW_2026_08_06/gfx-texture.md +690 -690
  126. package/src/REVIEW_2026_08_06/prior-criticals.md +49 -49
  127. package/src/REVIEW_2026_08_06/prior-highs.md +138 -138
  128. package/src/REVIEW_2026_08_06/test-gaps.md +364 -364
  129. package/src/REVIEW_2026_08_06/view.md +667 -667
  130. package/src/REVIEW_2026_08_06.md +610 -610
  131. package/src/avif/codec/dec/avif_dec.cpp +233 -233
  132. package/src/avif/codec/dec/avif_dec.js +16 -16
  133. package/src/core/binary/BitImage2.js +246 -246
  134. package/src/core/binary/align_32.js +21 -21
  135. package/src/core/binary/data_view/DataType2DataViewReaders.js +23 -23
  136. package/src/core/binary/data_view/DataType2DataViewWriters.js +25 -25
  137. package/src/core/binary/hash/XXH128Hash.js +55 -55
  138. package/src/core/binary/hash/XXH3_SECRET.js +25 -25
  139. package/src/core/binary/hash/xxh3_128.js +341 -341
  140. package/src/core/binary/hash/xxh3_64.js +241 -241
  141. package/src/core/binary/hash/xxh3_common.js +476 -476
  142. package/src/core/binary/lz4/LZ4_MAX_INPUT_SIZE.js +9 -9
  143. package/src/core/binary/lz4/lz4_compress_block.js +385 -385
  144. package/src/core/binary/lz4/lz4_compress_bound.js +25 -25
  145. package/src/core/binary/lz4/lz4_decompress_block.js +139 -139
  146. package/src/core/binary/lz4/lz4_decompress_bound.js +30 -30
  147. package/src/core/binary/meshopt/MESHOPT_GROUP_SIZE.js +18 -18
  148. package/src/core/binary/meshopt/MeshoptCompressionFilter.js +30 -30
  149. package/src/core/binary/meshopt/MeshoptCompressionMode.js +21 -21
  150. package/src/core/binary/meshopt/__meshopt_test_streams.js +237 -237
  151. package/src/core/binary/meshopt/meshopt_decode.js +73 -73
  152. package/src/core/binary/meshopt/meshopt_decode_byte_group.js +67 -67
  153. package/src/core/binary/meshopt/meshopt_decode_data_block.js +59 -59
  154. package/src/core/binary/meshopt/meshopt_decode_filter_color.js +69 -69
  155. package/src/core/binary/meshopt/meshopt_decode_filter_exponential.js +43 -43
  156. package/src/core/binary/meshopt/meshopt_decode_filter_octahedral.js +60 -60
  157. package/src/core/binary/meshopt/meshopt_decode_filter_quaternion.js +71 -71
  158. package/src/core/binary/meshopt/meshopt_decode_index_buffer.js +294 -294
  159. package/src/core/binary/meshopt/meshopt_decode_index_sequence.js +115 -115
  160. package/src/core/binary/meshopt/meshopt_decode_vertex_buffer.js +381 -381
  161. package/src/core/binary/meshopt/meshopt_read_uint_var.js +59 -59
  162. package/src/core/binary/reinterpret_float32_as_uint32.js +13 -13
  163. package/src/core/binary/reinterpret_uint32_as_float32.js +14 -14
  164. package/src/core/binary/type/DataType2TypedArrayConstructorMapping.js +35 -35
  165. package/src/core/bvh2/bvh3/ebvh_geometry_query_any_triangle_ray.js +149 -149
  166. package/src/core/bvh2/bvh3/ebvh_sort_for_traversal_depth_first.js +96 -96
  167. package/src/core/bvh2/bvh3/query/bvh_query_depth_range_in_frustum.js +101 -101
  168. package/src/core/bvh2/bvh3/query/bvh_query_leaves_generic.js +77 -77
  169. package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray.js +90 -90
  170. package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray_segment.js +94 -94
  171. package/src/core/bvh2/bvh3/query/bvh_query_user_data_generic.js +86 -86
  172. package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_capsule.js +101 -101
  173. package/src/core/bvh2/bvh3/query/bvh_query_user_data_intersects_sphere.js +92 -92
  174. package/src/core/bvh2/bvh3/query/bvh_query_user_data_ray.js +96 -96
  175. package/src/core/bvh2/bvh3/query/bvh_query_user_data_ray_segment.js +100 -100
  176. package/src/core/bvh2/visual/BVHGeometry.js +131 -131
  177. package/src/core/bvh8/BVH8.js +436 -436
  178. package/src/core/bvh8/aabb3_round_to_float32.js +22 -22
  179. package/src/core/bvh8/build/BVH8Converter.js +588 -588
  180. package/src/core/bvh8/build/TriangleCluster.js +122 -122
  181. package/src/core/bvh8/build/aabb3_compute_merge_cost.js +28 -28
  182. package/src/core/bvh8/build/aabb3_from_triangle_by_index.js +17 -17
  183. package/src/core/bvh8/build/bvh8_build_for_geometry.js +303 -303
  184. package/src/core/bvh8/build/bvh8_from_proxy.js +256 -256
  185. package/src/core/bvh8/build/byte.js +9 -9
  186. package/src/core/bvh8/build/encode_bounds_e.js +11 -11
  187. package/src/core/bvh8/bvh8_convert_to_dot.js +132 -132
  188. package/src/core/bvh8/bvh8_count_primitives.js +98 -98
  189. package/src/core/bvh8/bvh8_geometry_validate.js +138 -138
  190. package/src/core/bvh8/bvh8_geometry_validate_indirect.js +166 -166
  191. package/src/core/bvh8/bvh8_get_node_bounds.js +34 -34
  192. package/src/core/bvh8/bvh8_get_node_child_bounds.js +52 -52
  193. package/src/core/bvh8/bvh8_node_child_surface_area.js +18 -18
  194. package/src/core/bvh8/bvh8_node_count_triangles.js +27 -27
  195. package/src/core/bvh8/bvh8_quality.js +72 -72
  196. package/src/core/bvh8/bvh8_validate_structure.js +87 -87
  197. package/src/core/clipboard/obtainClipBoard.js +29 -29
  198. package/src/core/clipboard/safeClipboardReadText.js +55 -55
  199. package/src/core/clipboard/safeClipboardWriteText.js +23 -23
  200. package/src/core/collection/array/typed/typed_array_value_denormalize.js +52 -52
  201. package/src/core/collection/array/typed/typed_array_value_normalize.js +51 -51
  202. package/src/core/collection/union-find/union_find.js +79 -79
  203. package/src/core/color/YCoCg/rgb_to_ycocg.js +20 -20
  204. package/src/core/color/YCoCg/ycocg_to_rgb.js +17 -17
  205. package/src/core/color/colormap/MAGMA_LUT.js +26 -26
  206. package/src/core/color/illuminant/D65_TRISTIMULUS_XYZ.js +19 -19
  207. package/src/core/color/lab/lab_apply_hunt_adjustment.js +27 -27
  208. package/src/core/color/lab/lab_distance_hyab.js +23 -23
  209. package/src/core/color/lab/xyz_to_lab.js +62 -62
  210. package/src/core/color/operations/color_darken.js +24 -24
  211. package/src/core/color/operations/color_desaturate.js +24 -24
  212. package/src/core/color/operations/color_lighten.js +24 -24
  213. package/src/core/color/operations/color_saturate.js +24 -24
  214. package/src/core/color/operations/color_scale_okhsv_channel.js +45 -45
  215. package/src/core/color/tonemap/tonemap_aces.js +41 -41
  216. package/src/core/color/ycxcz/xyz_to_ycxcz.js +28 -28
  217. package/src/core/color/ycxcz/ycxcz_to_xyz.js +19 -19
  218. package/src/core/dom/isImageBitmap.js +12 -12
  219. package/src/core/function/frameThrottle.js +23 -23
  220. package/src/core/geom/2d/aabb/aabb2_array_combine.js +7 -7
  221. package/src/core/geom/2d/aabb/aabb2_compute_area.js +7 -7
  222. package/src/core/geom/2d/aabb/aabb2_compute_center_from_multiple.js +7 -7
  223. package/src/core/geom/2d/aabb/aabb2_compute_overlap.js +7 -7
  224. package/src/core/geom/2d/aabb/aabb2_from_v2_array.js +7 -7
  225. package/src/core/geom/2d/aabb/aabb2_intersects_point.js +7 -7
  226. package/src/core/geom/2d/aabb/aabb2_overlap_exists.js +7 -7
  227. package/src/core/geom/2d/circle/circle_compute_circle_intersection.js +7 -7
  228. package/src/core/geom/2d/circle/circle_compute_circle_penetration.js +7 -7
  229. package/src/core/geom/2d/circle/circle_intersects_point.js +7 -7
  230. package/src/core/geom/2d/compute_polygon_area_2d.js +7 -7
  231. package/src/core/geom/2d/convex-hull/fixed_convex_hull_humus.js +7 -7
  232. package/src/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.js +7 -7
  233. package/src/core/geom/2d/convex-hull/orientation3_array.js +7 -7
  234. package/src/core/geom/2d/intersect_ray_2d.js +7 -7
  235. package/src/core/geom/2d/line/line2_distance_to_point_sqr.js +7 -7
  236. package/src/core/geom/2d/line/line2_segment_intersection_fraction_2d.js +44 -44
  237. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_2d.js +7 -7
  238. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_array_2d.js +7 -7
  239. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_2d.js +7 -7
  240. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_array_2d.js +7 -7
  241. package/src/core/geom/2d/line/line_segment_intersection_fraction_2d.js +7 -7
  242. package/src/core/geom/2d/line/line_segment_line_segment_intersection_exists_2d.js +7 -7
  243. package/src/core/geom/2d/line/segment2_intersects_segment2_2d.js +25 -25
  244. package/src/core/geom/2d/line/segment2_segment_compute_intersection_array_2d.js +46 -46
  245. package/src/core/geom/2d/line/segment2_segment_intersection_fractions.js +52 -52
  246. package/src/core/geom/2d/oriented-box/min_area_rect_2d.js +69 -69
  247. package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +433 -433
  248. package/src/core/geom/2d/polygon/polygon2_clip_axis_halfplane.js +51 -51
  249. package/src/core/geom/2d/polygon/polygon2_clip_halfplane.js +50 -50
  250. package/src/core/geom/2d/polygon/polygon2_is_counter_clockwise.js +84 -84
  251. package/src/core/geom/2d/polygon/polygon2_signed_area.js +52 -52
  252. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.js +86 -86
  253. package/src/core/geom/2d/polygon/polygon2_triangulate.js +1280 -1280
  254. package/src/core/geom/2d/polygon/polygon2_triangulation_deviation.js +77 -77
  255. package/src/core/geom/2d/quad-tree/qt_collect_by_circle.js +39 -39
  256. package/src/core/geom/2d/quad-tree/qt_match_data_by_circle.js +101 -101
  257. package/src/core/geom/2d/quad-tree/qt_query_data_nearest_to_point.js +7 -7
  258. package/src/core/geom/2d/rectangle_to_aabb.js +7 -7
  259. package/src/core/geom/2d/spline_bezier2_2d.js +7 -7
  260. package/src/core/geom/2d/triangle/tri2_rasterize_conservative.js +99 -99
  261. package/src/core/geom/2d/triangle/tri2_signed_area.js +35 -35
  262. package/src/core/geom/2d/triangle2d_compute_area.js +7 -7
  263. package/src/core/geom/2d/triangle2d_contains_point.js +7 -7
  264. package/src/core/geom/2d/triangle2d_get_barycentric.js +7 -7
  265. package/src/core/geom/2d/v2_morton_encode.js +23 -23
  266. package/src/core/geom/3d/aabb/aabb3_array_intersects_frustum_degree.js +7 -7
  267. package/src/core/geom/3d/aabb/aabb3_box_surface_area_2.js +7 -7
  268. package/src/core/geom/3d/aabb/aabb3_build_frustum.js +5 -5
  269. package/src/core/geom/3d/aabb/aabb3_closest_point_on_surface.js +57 -57
  270. package/src/core/geom/3d/aabb/aabb3_combined_surface_area.js +7 -7
  271. package/src/core/geom/3d/aabb/aabb3_compute_half_surface_area.js +7 -7
  272. package/src/core/geom/3d/aabb/aabb3_compute_projected_area.js +7 -7
  273. package/src/core/geom/3d/aabb/aabb3_compute_surface_area.js +7 -7
  274. package/src/core/geom/3d/aabb/aabb3_detailed_volume_intersection.js +7 -7
  275. package/src/core/geom/3d/aabb/aabb3_estimate_projected_area2.js +7 -7
  276. package/src/core/geom/3d/aabb/aabb3_from_threejs_geometry.js +7 -7
  277. package/src/core/geom/3d/aabb/aabb3_from_triangle_group.js +46 -46
  278. package/src/core/geom/3d/aabb/aabb3_intersects_frustum_degree.js +7 -7
  279. package/src/core/geom/3d/aabb/aabb3_intersects_line_segment.js +7 -7
  280. package/src/core/geom/3d/aabb/aabb3_near_distance_to_intersection_ray_segment.js +7 -7
  281. package/src/core/geom/3d/aabb/aabb3_nearest_point_on_surface.js +7 -7
  282. package/src/core/geom/3d/aabb/aabb3_ray_segment_entry_distance.js +95 -95
  283. package/src/core/geom/3d/aabb/aabb3_raycast.js +7 -7
  284. package/src/core/geom/3d/aabb/aabb3_transform_oriented.js +93 -93
  285. package/src/core/geom/3d/aabb/aabb3_transform_oriented_inverse.js +82 -82
  286. package/src/core/geom/3d/aabb/compute_aabb_from_points.js +7 -7
  287. package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.js +7 -7
  288. package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +486 -486
  289. package/src/core/geom/3d/atlas/BFF_PLAN.md +174 -174
  290. package/src/core/geom/3d/atlas/Chart.js +77 -77
  291. package/src/core/geom/3d/atlas/REVIEW_02.md +392 -392
  292. package/src/core/geom/3d/atlas/atlas_bench_lib.js +315 -315
  293. package/src/core/geom/3d/atlas/atlas_chart_type.js +16 -16
  294. package/src/core/geom/3d/atlas/atlas_compute_charts.js +188 -188
  295. package/src/core/geom/3d/atlas/atlas_extract_chart.js +107 -107
  296. package/src/core/geom/3d/atlas/atlas_generate.js +50 -50
  297. package/src/core/geom/3d/atlas/atlas_test_fixtures.js +266 -266
  298. package/src/core/geom/3d/atlas/atlas_write_chart_uvs.js +36 -36
  299. package/src/core/geom/3d/atlas/data/atlas_build_edge_dihedrals.js +62 -62
  300. package/src/core/geom/3d/atlas/data/atlas_build_edge_lengths.js +33 -33
  301. package/src/core/geom/3d/atlas/data/atlas_build_face_areas.js +50 -50
  302. package/src/core/geom/3d/atlas/io/atlas_mesh_weld_colocals.js +39 -39
  303. package/src/core/geom/3d/atlas/io/bt_loop_uv.js +35 -35
  304. package/src/core/geom/3d/atlas/pack/ChartPlacement.js +46 -46
  305. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.js +269 -269
  306. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.js +209 -209
  307. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_ortho.js +38 -38
  308. package/src/core/geom/3d/atlas/param/atlas_chart_stretch_metric.js +86 -86
  309. package/src/core/geom/3d/atlas/param/atlas_piecewise_resegment.js +183 -183
  310. package/src/core/geom/3d/atlas/param/fit_plane_basis.js +66 -66
  311. package/src/core/geom/3d/atlas/segment/RegionGraph.js +40 -40
  312. package/src/core/geom/3d/atlas/segment/atlas_build_region_graph.js +136 -136
  313. package/src/core/geom/3d/atlas/segment/atlas_chart_roundness_delta.js +30 -30
  314. package/src/core/geom/3d/atlas/segment/atlas_compute_planar_regions.js +77 -77
  315. package/src/core/geom/3d/atlas/segment/atlas_merge_charts.js +116 -116
  316. package/src/core/geom/3d/atlas/segment/atlas_segment_charts.js +271 -271
  317. package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.js +191 -191
  318. package/src/core/geom/3d/box/box3_projected_half_extent.js +35 -35
  319. package/src/core/geom/3d/capsule/capsule_intersects_aabb3_closed.js +67 -67
  320. package/src/core/geom/3d/capsule/capsule_intersects_aabb3_iterative.js +137 -137
  321. package/src/core/geom/3d/compute_circle_bounding_box.js +7 -7
  322. package/src/core/geom/3d/cone/computeConeBoundingBox.js +7 -7
  323. package/src/core/geom/3d/cone/computeConePlaneSide.js +7 -7
  324. package/src/core/geom/3d/cone/compute_bounding_cone_of_2_cones.js +7 -7
  325. package/src/core/geom/3d/cylinder/cylinder3_raycast.d.ts +38 -0
  326. package/src/core/geom/3d/cylinder/cylinder3_raycast.d.ts.map +1 -0
  327. package/src/core/geom/3d/cylinder/cylinder3_raycast.js +105 -0
  328. package/src/core/geom/3d/equirectangular/equirectangular_direction_to_uv.js +18 -18
  329. package/src/core/geom/3d/equirectangular/equirectangular_uv_to_direction.js +24 -24
  330. package/src/core/geom/3d/frustum/clipping_volume_matrix4_project.js +7 -7
  331. package/src/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +7 -7
  332. package/src/core/geom/3d/frustum/frustum3_compute_closest_point.js +117 -117
  333. package/src/core/geom/3d/frustum/frustum_matrix4_project.js +7 -7
  334. package/src/core/geom/3d/frustum/hexahedron_from_aabb.js +7 -7
  335. package/src/core/geom/3d/frustum/read_frustum_corner.js +17 -17
  336. package/src/core/geom/3d/frustum/read_three_planes_to_array.js +7 -7
  337. package/src/core/geom/3d/frustum/slice_frustum_linear_to_points.js +7 -7
  338. package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +146 -146
  339. package/src/core/geom/3d/gjk/gjk.js +430 -430
  340. package/src/core/geom/3d/gjk/gjk_epa_penetration.js +520 -520
  341. package/src/core/geom/3d/gjk/minkowski_support.js +71 -71
  342. package/src/core/geom/3d/gjk/mpr.js +368 -368
  343. package/src/core/geom/3d/line/line3_closest_points_segment_segment.js +7 -7
  344. package/src/core/geom/3d/line/line3_compute_nearest_point_to_point.js +7 -7
  345. package/src/core/geom/3d/line/line3_compute_point_segment_point_distance_unfolded.js +64 -64
  346. package/src/core/geom/3d/line/line3_compute_segment_closest_point_to_aabb3_t.js +153 -153
  347. package/src/core/geom/3d/line/line3_compute_segment_nearest_point_to_aabb3_t.js +7 -7
  348. package/src/core/geom/3d/line/line3_compute_segment_nearest_point_to_point_t.js +7 -7
  349. package/src/core/geom/3d/line/line3_compute_segment_segment_closest_points.js +88 -88
  350. package/src/core/geom/3d/line/line3_segment_segment_closest_point_pair.js +71 -71
  351. package/src/core/geom/3d/line/segment3_point_distance_to_segments.js +25 -25
  352. package/src/core/geom/3d/mat4/allocate_m4.js +7 -7
  353. package/src/core/geom/3d/mat4/apply_mat4_transform_to_direction_v3_array.js +7 -7
  354. package/src/core/geom/3d/mat4/apply_mat4_transform_to_v3_array.js +7 -7
  355. package/src/core/geom/3d/mat4/compose_matrix4_array.js +7 -7
  356. package/src/core/geom/3d/mat4/decompose_matrix_4_array.js +7 -7
  357. package/src/core/geom/3d/mat4/eulerAnglesFromMatrix.js +7 -7
  358. package/src/core/geom/3d/mat4/m4_compose.js +22 -22
  359. package/src/core/geom/3d/mat4/m4_compute_normal_matrix3.js +7 -7
  360. package/src/core/geom/3d/mat4/m4_decompose.js +64 -64
  361. package/src/core/geom/3d/mat4/m4_decompose_array.js +157 -157
  362. package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale.js +32 -32
  363. package/src/core/geom/3d/mat4/m4_from_rotation_translation_scale_scalar.js +67 -67
  364. package/src/core/geom/3d/mat4/m4_linear_matrix3.js +29 -29
  365. package/src/core/geom/3d/mat4/m4_look_at.js +96 -96
  366. package/src/core/geom/3d/mat4/m4_make_rotation_x.js +47 -47
  367. package/src/core/geom/3d/mat4/m4_make_rotation_y.js +47 -47
  368. package/src/core/geom/3d/mat4/m4_make_rotation_z.js +47 -47
  369. package/src/core/geom/3d/mat4/m4_normal_matrix3.js +39 -39
  370. package/src/core/geom/3d/mat4/m4_perspective.js +66 -66
  371. package/src/core/geom/3d/mat4/m4_transpose.js +48 -48
  372. package/src/core/geom/3d/morton/mortonEncode_LUT.js +7 -7
  373. package/src/core/geom/3d/morton/mortonEncode_magicbits.js +7 -7
  374. package/src/core/geom/3d/normal/hemioct/encode_unit3_hemioct.js +5 -5
  375. package/src/core/geom/3d/normal/hemioct/encode_unit_to_hemioct.js +28 -28
  376. package/src/core/geom/3d/normal/lambert_azimuth/decode_azimuth_to_unit.js +30 -30
  377. package/src/core/geom/3d/normal/lambert_azimuth/encode_unit_to_azimuth.js +19 -19
  378. package/src/core/geom/3d/normal/spherical/decode_spheremap_to_unit.js +38 -38
  379. package/src/core/geom/3d/normal/spherical/encode_unit_to_spheremap.js +30 -30
  380. package/src/core/geom/3d/plane/is_point_within_planes.js +7 -7
  381. package/src/core/geom/3d/plane/orient3d_fast_point.js +47 -47
  382. package/src/core/geom/3d/plane/plane3_compute_convex_3_plane_intersection.js +7 -7
  383. package/src/core/geom/3d/plane/plane3_compute_plane_intersection.js +7 -7
  384. package/src/core/geom/3d/plane/plane3_intersect_plane.js +7 -7
  385. package/src/core/geom/3d/plane/plane3_three_compute_convex_3_plane_intersection.js +7 -7
  386. package/src/core/geom/3d/point/point3_raycast.d.ts +33 -0
  387. package/src/core/geom/3d/point/point3_raycast.d.ts.map +1 -0
  388. package/src/core/geom/3d/point/point3_raycast.js +47 -0
  389. package/src/core/geom/3d/polygon/polygon3_compute_normal.js +60 -60
  390. package/src/core/geom/3d/polygon/polygon3_triangulate.js +94 -94
  391. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.d.ts +40 -0
  392. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.d.ts.map +1 -0
  393. package/src/core/geom/3d/polyhedron/convex_polyhedron3_raycast.js +94 -0
  394. package/src/core/geom/3d/quadric/QUADRIC3_SIZE.js +14 -14
  395. package/src/core/geom/3d/quadric/Quadric3.js +282 -282
  396. package/src/core/geom/3d/quadric/quadric3_add.js +33 -33
  397. package/src/core/geom/3d/quadric/quadric3_clear.js +25 -25
  398. package/src/core/geom/3d/quadric/quadric3_copy.js +27 -27
  399. package/src/core/geom/3d/quadric/quadric3_distance.js +36 -36
  400. package/src/core/geom/3d/quadric/quadric3_evaluate.js +25 -25
  401. package/src/core/geom/3d/quadric/quadric3_optimize.js +45 -45
  402. package/src/core/geom/3d/quadric/quadric3_scale.js +32 -32
  403. package/src/core/geom/3d/quadric/quadric3_set_from_plane_through_point.js +30 -30
  404. package/src/core/geom/3d/quadric/quadric3_set_from_vector4.js +35 -35
  405. package/src/core/geom/3d/quadric/quadric3_sub.js +36 -36
  406. package/src/core/geom/3d/quadric/quadric3_to_tensor_m3.js +28 -28
  407. package/src/core/geom/3d/quadric/quadric3_to_tensor_m3_inverse.js +56 -56
  408. package/src/core/geom/3d/quadric/quadric3_to_vector3.js +19 -19
  409. package/src/core/geom/3d/quaternion/quat3_createFromAxisAngle.js +7 -7
  410. package/src/core/geom/3d/quaternion/quat3_integrate.js +62 -62
  411. package/src/core/geom/3d/quaternion/quat3_multiply.js +31 -31
  412. package/src/core/geom/3d/quaternion/quat3_nlerp.js +72 -72
  413. package/src/core/geom/3d/quaternion/quat3_to_matrix3.js +69 -69
  414. package/src/core/geom/3d/quaternion/quat_decode_from_uint32.js +7 -7
  415. package/src/core/geom/3d/quaternion/quat_encode_to_uint32.js +7 -7
  416. package/src/core/geom/3d/ray/ray3_array_compose.js +7 -7
  417. package/src/core/geom/3d/ray/ray3_compute_nearest_point_to_point.js +7 -7
  418. package/src/core/geom/3d/ray/ray3_distance_to_point.js +7 -7
  419. package/src/core/geom/3d/ray/ray3_shift_origin_along_direction.js +7 -7
  420. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts +17 -0
  421. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
  422. package/src/core/geom/3d/shape/ConvexHullShape3D.js +43 -0
  423. package/src/core/geom/3d/shape/CylinderShape3D.d.ts +1 -0
  424. package/src/core/geom/3d/shape/CylinderShape3D.d.ts.map +1 -1
  425. package/src/core/geom/3d/shape/CylinderShape3D.js +21 -0
  426. package/src/core/geom/3d/shape/PointShape3D.d.ts +7 -0
  427. package/src/core/geom/3d/shape/PointShape3D.d.ts.map +1 -1
  428. package/src/core/geom/3d/shape/PointShape3D.js +88 -63
  429. package/src/core/geom/3d/shape/PosedShape3D.d.ts +6 -0
  430. package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
  431. package/src/core/geom/3d/shape/PosedShape3D.js +27 -0
  432. package/src/core/geom/3d/shape/TransformedShape3D.d.ts +10 -0
  433. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  434. package/src/core/geom/3d/shape/TransformedShape3D.js +13 -0
  435. package/src/core/geom/3d/shape/Triangle3D.d.ts +1 -0
  436. package/src/core/geom/3d/shape/Triangle3D.d.ts.map +1 -1
  437. package/src/core/geom/3d/shape/Triangle3D.js +26 -0
  438. package/src/core/geom/3d/shape/UnionShape3D.d.ts +6 -0
  439. package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
  440. package/src/core/geom/3d/shape/UnionShape3D.js +7 -0
  441. package/src/core/geom/3d/shape/UnitCubeShape3D.js +45 -45
  442. package/src/core/geom/3d/shape/UnitSphereShape3D.js +44 -44
  443. package/src/core/geom/3d/shape/shape3_mesh_from_geometry.js +64 -64
  444. package/src/core/geom/3d/shape/shape_mesh_from_geometry.js +7 -7
  445. package/src/core/geom/3d/shape/util/compute_signed_distance_gradient_by_sampling.js +51 -51
  446. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.js +7 -7
  447. package/src/core/geom/3d/sphere/compute_bounding_sphere_of_2_spheres.js +7 -7
  448. package/src/core/geom/3d/sphere/harmonics/sh3_convolve_with_zh.js +53 -53
  449. package/src/core/geom/3d/sphere/harmonics/sh3_ggx_zh.js +30 -30
  450. package/src/core/geom/3d/sphere/harmonics/sh3_rotate_bl.js +7 -7
  451. package/src/core/geom/3d/sphere/harmonics/sh_compute_K.js +7 -7
  452. package/src/core/geom/3d/sphere/sphere_array_intersects_point.js +7 -7
  453. package/src/core/geom/3d/sphere/sphere_array_intersects_ray.js +7 -7
  454. package/src/core/geom/3d/sphere/sphere_intersects_point.js +7 -7
  455. package/src/core/geom/3d/sphere/sphere_matrix4_transform.js +5 -5
  456. package/src/core/geom/3d/sphere/sphere_projected_sphere_radius_sqr.js +7 -7
  457. package/src/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.js +7 -7
  458. package/src/core/geom/3d/sphere/spherical_from_cartesian.js +7 -7
  459. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.js +174 -174
  460. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.js +7 -7
  461. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_volume.js +7 -7
  462. package/src/core/geom/3d/tetrahedra/delaunay/fill_in_a_cavity.js +7 -7
  463. package/src/core/geom/3d/tetrahedra/graphics/build_tetrahedral_mesh_geometry.js +39 -39
  464. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.js +48 -48
  465. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js +173 -173
  466. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_compute_tet_quality.js +22 -22
  467. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.js +146 -146
  468. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.js +232 -232
  469. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.js +255 -255
  470. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.js +387 -387
  471. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js +140 -140
  472. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_tet_get_neighbours.js +7 -7
  473. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js +97 -97
  474. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.js +66 -66
  475. package/src/core/geom/3d/tetrahedra/triangle/triangle_decode_depth.js +59 -59
  476. package/src/core/geom/3d/tetrahedra/triangle/triangle_rasterized_depth_sample_index.js +54 -54
  477. package/src/core/geom/3d/tetrahedra/validate_neighbour.js +70 -70
  478. package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.js +314 -314
  479. package/src/core/geom/3d/topology/struct/binary/BinaryDataLayer.js +364 -364
  480. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +567 -567
  481. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.js +1085 -1085
  482. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.js +73 -73
  483. package/src/core/geom/3d/topology/struct/binary/io/bt_loop_kill.js +35 -35
  484. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_append.js +119 -119
  485. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +84 -84
  486. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.js +172 -172
  487. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_face_normals.js +56 -56
  488. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadratics.js +7 -7
  489. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compute_vertex_quadrics.js +227 -227
  490. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.js +161 -161
  491. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_island_erode.js +490 -490
  492. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.js +120 -120
  493. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_from_indexed_geometry.js +120 -120
  494. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_collapse.js +52 -52
  495. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.js +115 -115
  496. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_flip.js +142 -142
  497. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.js +21 -21
  498. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.js +92 -92
  499. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_split.js +179 -179
  500. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_swap_vertex_slots.js +28 -28
  501. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_kill_only_edge.js +8 -8
  502. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_fuse_duplicate_edges.js +83 -83
  503. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.js +89 -89
  504. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_kill.js +25 -25
  505. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_poke.js +127 -127
  506. package/src/core/geom/3d/topology/struct/binary/io/face/bt_face_triangulate.js +268 -268
  507. package/src/core/geom/3d/topology/struct/binary/io/face/bt_kill_only_face.js +8 -8
  508. package/src/core/geom/3d/topology/struct/binary/io/face/bt_mesh_kill_degenerate_faces.js +72 -72
  509. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_kill_only_vert.js +7 -7
  510. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_merge_verts_by_distance.js +7 -7
  511. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_relative_merge_distance.js +48 -48
  512. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_split_pinched_vertices.js +256 -256
  513. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_mesh_vertex_merge_distance.js +77 -77
  514. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vert_fuse_duplicate_edges.js +7 -7
  515. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vert_kill.js +7 -7
  516. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_fuse_duplicate_edges.js +148 -148
  517. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_kill_only.js +7 -7
  518. package/src/core/geom/3d/topology/struct/binary/query/bt_collect_boundary_segments.js +29 -29
  519. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_collapse_breaks_link_condition.js +107 -107
  520. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_flip_is_legal.js +41 -41
  521. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_flip_would_fold.js +120 -120
  522. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.js +42 -42
  523. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_is_boundary.js +20 -20
  524. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_read_diamond.js +96 -96
  525. package/src/core/geom/3d/topology/struct/binary/query/bt_face_compute_newell_normal.js +72 -72
  526. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_attached_faces.js +7 -7
  527. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_edge_adjacent_faces.js +39 -39
  528. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_edge_adjacent_faces_weighted.js +93 -93
  529. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_neighbour_faces.js +7 -7
  530. package/src/core/geom/3d/topology/struct/binary/query/bt_face_get_shared_loop.js +48 -48
  531. package/src/core/geom/3d/topology/struct/binary/query/bt_face_island_flood_fill.js +45 -45
  532. package/src/core/geom/3d/topology/struct/binary/query/bt_face_read_triangle.js +66 -66
  533. package/src/core/geom/3d/topology/struct/binary/query/bt_faces_shared_loop.js +7 -7
  534. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_assert_valid.js +44 -44
  535. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_build_boundary_euclidean_distance_field.js +32 -32
  536. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_compute_face_islands.js +53 -53
  537. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path.js +703 -703
  538. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js +181 -181
  539. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_segment_penetrates_surface.js +133 -133
  540. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_surface_ray_parity.js +82 -82
  541. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_validate.js +599 -599
  542. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.js +108 -108
  543. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.js +7 -7
  544. package/src/core/geom/3d/triangle/computeTriangleClosestPointToPointBarycentric.js +7 -7
  545. package/src/core/geom/3d/triangle/computeTriangleRayIntersection.js +7 -7
  546. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentric.js +7 -7
  547. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricEdge.js +7 -7
  548. package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricGeometry.js +7 -7
  549. package/src/core/geom/3d/triangle/compute_triangle_area_3d.js +7 -7
  550. package/src/core/geom/3d/triangle/compute_triangle_normal.js +7 -7
  551. package/src/core/geom/3d/triangle/rayTriangleIntersection.js +7 -7
  552. package/src/core/geom/3d/triangle/tri3_closest_point.js +65 -65
  553. package/src/core/geom/3d/triangle/tri3_closest_point_barycentric.js +171 -171
  554. package/src/core/geom/3d/triangle/tri3_flatten_isometric.js +79 -79
  555. package/src/core/geom/3d/triangle/tri3_ray_intersection.js +160 -160
  556. package/src/core/geom/3d/triangle/tri3_ray_intersection_barycentric.js +96 -96
  557. package/src/core/geom/3d/triangle/tri3_raycast.d.ts +42 -0
  558. package/src/core/geom/3d/triangle/tri3_raycast.d.ts.map +1 -0
  559. package/src/core/geom/3d/triangle/tri3_raycast.js +94 -0
  560. package/src/core/geom/3d/triangle/triangle3_incenter.js +7 -7
  561. package/src/core/geom/3d/triangle/triangle_compute_plane_side.js +7 -7
  562. package/src/core/geom/3d/triangle/triangle_compute_signed_volume.js +7 -7
  563. package/src/core/geom/3d/triangle/triangle_intersects_clipping_volume.js +7 -7
  564. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.js +7 -7
  565. package/src/core/geom/3d/triangle/v3_compute_triangle_normal.js +7 -7
  566. package/src/core/geom/3d/util/make_justified_point_grid.js +7 -7
  567. package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +381 -381
  568. package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +684 -684
  569. package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +554 -554
  570. package/src/core/geom/mat3/m3_cm_from_translation.js +7 -7
  571. package/src/core/geom/mat3/m3_cm_invert.js +7 -7
  572. package/src/core/geom/mat3/m3_make_rotation.js +5 -5
  573. package/src/core/geom/mat3/m3_make_rotation_TBN.js +31 -31
  574. package/src/core/geom/mat3/m3_multiply_vec3.js +7 -7
  575. package/src/core/geom/packing/computeBoundingSphereOfSpheres.js +7 -7
  576. package/src/core/geom/packing/max-rect/cost/costByBestShortSide.js +7 -7
  577. package/src/core/geom/packing/max-rect/cost/costByRemainingArea.js +7 -7
  578. package/src/core/geom/packing/max-rect/cutArea.js +7 -7
  579. package/src/core/geom/packing/max-rect/findBestContainer.js +7 -7
  580. package/src/core/geom/packing/max-rect/packMaxRectangles.js +7 -7
  581. package/src/core/geom/packing/max-rect/packOneBox.js +7 -7
  582. package/src/core/geom/packing/max-rect/removeRedundantBoxes.js +7 -7
  583. package/src/core/geom/packing/max-rect/removeRedundantBoxesArray.js +7 -7
  584. package/src/core/geom/random/randomPointInBox.js +7 -7
  585. package/src/core/geom/random/randomPointInCircle.js +7 -7
  586. package/src/core/geom/random/randomPointInPoint.js +7 -7
  587. package/src/core/geom/random/randomPointInSphere.js +7 -7
  588. package/src/core/geom/random/randomPointOnBox.js +7 -7
  589. package/src/core/geom/random/randomPointOnSphere.js +7 -7
  590. package/src/core/geom/random/random_orthonormal_basis.js +31 -31
  591. package/src/core/geom/vec/vector_axpy.js +15 -15
  592. package/src/core/geom/vec/vector_axpy_offset.js +20 -20
  593. package/src/core/geom/vec/vector_copy.js +7 -7
  594. package/src/core/geom/vec/vector_dot_offset.js +25 -25
  595. package/src/core/geom/vec/vector_scale_array.js +7 -7
  596. package/src/core/geom/vec2/v2_rotate.js +21 -21
  597. package/src/core/geom/vec2/v2_rotate_cos_sin.js +21 -21
  598. package/src/core/geom/vec3/v3_angle_atan2_between.js +7 -7
  599. package/src/core/geom/vec3/v3_angle_between.js +7 -7
  600. package/src/core/geom/vec3/v3_angle_cos_between.js +7 -7
  601. package/src/core/geom/vec3/v3_array_add_in_place.js +7 -7
  602. package/src/core/geom/vec3/v3_array_centroid.js +7 -7
  603. package/src/core/geom/vec3/v3_array_copy.js +7 -7
  604. package/src/core/geom/vec3/v3_array_displace_in_direction.js +7 -7
  605. package/src/core/geom/vec3/v3_array_equals.js +7 -7
  606. package/src/core/geom/vec3/v3_array_immediate_add.js +7 -7
  607. package/src/core/geom/vec3/v3_array_matrix4_rotate.js +7 -7
  608. package/src/core/geom/vec3/v3_array_normalize.js +7 -7
  609. package/src/core/geom/vec3/v3_array_scale.js +7 -7
  610. package/src/core/geom/vec3/v3_compute_interior_angle.js +7 -7
  611. package/src/core/geom/vec3/v3_cotangent.js +33 -33
  612. package/src/core/geom/vec3/v3_dot_array_array.js +7 -7
  613. package/src/core/geom/vec3/v3_matrix3_multiply.js +30 -30
  614. package/src/core/geom/vec3/v3_matrix3_rotate.js +49 -49
  615. package/src/core/geom/vec3/v3_matrix4_rotate.js +7 -7
  616. package/src/core/geom/vec3/v3_multiply.js +23 -23
  617. package/src/core/geom/vec3/v3_multiply_scalar.js +7 -7
  618. package/src/core/geom/vec3/v3_orthonormal_matrix_from_normal.js +49 -49
  619. package/src/core/geom/vec3/v3_quat3_apply.js +7 -7
  620. package/src/core/geom/vec3/v3_quat3_apply_inverse.js +7 -7
  621. package/src/core/geom/vec3/v3_quaternion_apply.js +39 -39
  622. package/src/core/geom/vec3/v3_quaternion_apply_inverse.js +41 -41
  623. package/src/core/geom/vec3/v3_reflect.js +24 -24
  624. package/src/core/geom/vec3/v3_scale_array.js +18 -18
  625. package/src/core/geom/vec3/v3_triple_cross.js +45 -45
  626. package/src/core/geom/vec3/v3_triple_cross_product.js +7 -7
  627. package/src/core/geom/vec3/v3_uniform_sample_cone.js +21 -21
  628. package/src/core/geom/vec4/v4_multiply_mat4.js +7 -7
  629. package/src/core/graph/csr/csr_graph_build_distance_field.js +112 -112
  630. package/src/core/graph/csr/csr_graph_find_edge.js +25 -25
  631. package/src/core/graph/csr/csr_graph_find_shortest_path.js +105 -105
  632. package/src/core/graph/csr/csr_graph_from_undirected_edge_list.js +94 -94
  633. package/src/core/graph/graph_k_means_cluster.js +250 -250
  634. package/src/core/graph/layout/CircleLayout.js +1 -1
  635. package/src/core/graph/layout/box/BoxLayouter.js +1 -1
  636. package/src/core/graph/layout/graph_peel_topological_layer.js +45 -45
  637. package/src/core/graph/metis/BinaryTopologyFaceGraph.js +49 -49
  638. package/src/core/graph/metis/bt_mesh_build_face_graph.js +111 -111
  639. package/src/core/graph/metis/cluster_mesh_metis.js +137 -137
  640. package/src/core/graph/metis/native/bisection/bisect_graph.js +100 -100
  641. package/src/core/graph/metis/native/bisection/compute_2way_params.js +86 -86
  642. package/src/core/graph/metis/native/bisection/fm_2way.js +297 -297
  643. package/src/core/graph/metis/native/bisection/grow_bisection.js +137 -137
  644. package/src/core/graph/metis/native/bisection/split_graph_two_way.js +119 -119
  645. package/src/core/graph/metis/native/coarsen/coarsen_graph.js +94 -94
  646. package/src/core/graph/metis/native/coarsen/create_coarse_graph.js +158 -158
  647. package/src/core/graph/metis/native/coarsen/match_shem.js +175 -175
  648. package/src/core/graph/metis/native/initial/initial_kway_bfs.js +122 -122
  649. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.js +170 -170
  650. package/src/core/graph/metis/native/metis_partition_kway.js +126 -126
  651. package/src/core/graph/metis/native/refine/RefinementScratch.js +53 -53
  652. package/src/core/graph/metis/native/refine/fm_kway.js +487 -487
  653. package/src/core/graph/metis/native/refine/project_kway.js +43 -43
  654. package/src/core/graph/metis/native/refine/refine_kway.js +43 -43
  655. package/src/core/lang/reactive/pegjs/parser.js +3458 -3458
  656. package/src/core/math/complex/complex_horner_eval.js +31 -31
  657. package/src/core/math/computeWholeDivisorLow.js +33 -33
  658. package/src/core/math/f32_next_down.js +24 -24
  659. package/src/core/math/f32_next_up.js +27 -27
  660. package/src/core/math/hash/hash_mix2.js +22 -22
  661. package/src/core/math/hash/hash_mix3.js +19 -19
  662. package/src/core/math/linalg/cg/cg_solve.js +106 -106
  663. package/src/core/math/linalg/cg/cg_solve_normal_equations.js +59 -59
  664. package/src/core/math/linalg/cubic_residual_times_derivative_accumulate.js +43 -43
  665. package/src/core/math/linalg/eigen/matrix_householder_in_place.js +122 -122
  666. package/src/core/math/linalg/eigen/matrix_qr_in_place.js +190 -190
  667. package/src/core/math/linalg/eigen/matrix_symmetric_3x3_eigen.js +117 -117
  668. package/src/core/math/linalg/givens/givens_apply_rows.js +28 -28
  669. package/src/core/math/linalg/givens/givens_apply_rows_offset.js +30 -30
  670. package/src/core/math/linalg/givens/givens_rotation_coefficients.js +39 -39
  671. package/src/core/math/linalg/lu_factor_linear_system.js +108 -108
  672. package/src/core/math/linalg/lu_solve_linear_system.js +53 -53
  673. package/src/core/math/linalg/polynomial_add_into.js +29 -29
  674. package/src/core/math/linalg/polynomial_complex_roots_aberth_ehrlich.js +159 -159
  675. package/src/core/math/linalg/polynomial_cubic_derivative_eval.js +16 -16
  676. package/src/core/math/linalg/polynomial_cubic_horner_eval.js +19 -19
  677. package/src/core/math/linalg/polynomial_cubic_second_derivative_eval.js +14 -14
  678. package/src/core/math/linalg/polynomial_multiply.js +41 -41
  679. package/src/core/math/linalg/polynomial_real_roots_in_interval.js +211 -211
  680. package/src/core/math/linalg/polynomial_root_bound_cauchy.js +30 -30
  681. package/src/core/math/linalg/polynomial_scale_into.js +17 -17
  682. package/src/core/math/linalg/polynomial_sub_into.js +29 -29
  683. package/src/core/math/linalg/solve_linear_system_GEPP_2x2.js +96 -96
  684. package/src/core/math/linalg/sor_optimal_omega.js +42 -42
  685. package/src/core/math/linalg/sparse/SparseMatrixCSR.js +88 -88
  686. package/src/core/math/linalg/sparse/spm_matvec.js +22 -22
  687. package/src/core/math/linalg/sparse/spm_matvec_transpose.js +29 -29
  688. package/src/core/math/lookup/LUT_HEATMAP.js +30 -30
  689. package/src/core/math/lookup/ParameterLookupTable.js +495 -495
  690. package/src/core/math/lookup/ParameterLookupTableFlags.js +6 -6
  691. package/src/core/math/noise/curl_noise_3d.js +18 -18
  692. package/src/core/math/physics/brdf/cone_cosine_from_roughness.js +28 -28
  693. package/src/core/math/physics/brdf/reflection_sample_weight.js +48 -48
  694. package/src/core/math/physics/kinematics/computeInterceptPoint.js +79 -79
  695. package/src/core/math/random/randomSeed.js +16 -16
  696. package/src/core/math/random/random_pick_weighted_index.js +26 -26
  697. package/src/core/math/round_half_away_from_zero.js +13 -13
  698. package/src/core/math/spline/spline3_hermite_apply_transform.js +107 -107
  699. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_1d.js +125 -125
  700. package/src/core/math/spline/spline3_hermite_intersects_spline3_hermite.js +50 -50
  701. package/src/core/math/spline/spline3_hermite_reverse.js +49 -49
  702. package/src/core/math/spline/spline3_hermite_to_monomial.js +37 -37
  703. package/src/core/math/statistics/hammersley_sequence.js +53 -53
  704. package/src/core/model/reactive/model/util/createRandomReactiveExpression.js +185 -185
  705. package/src/core/path/convertPathToURL.js +107 -107
  706. package/src/core/process/delay.js +16 -16
  707. package/src/core/science/units/MEASUREMENT_UNITS_SCIENTIFIC.js +87 -87
  708. package/src/core/science/units/MEASUREMENT_UNITS_SI.js +17 -17
  709. package/src/core/science/units/NamedUnit.js +48 -48
  710. package/src/core/science/units/UNIT_DIMENSION_MAPPING.js +29 -29
  711. package/src/core/science/units/UnitDimension.js +28 -28
  712. package/src/core/science/units/format_quantity.js +74 -74
  713. package/src/core/science/units/magnitude_prefix.js +127 -127
  714. package/src/core/science/units/si/AMPERE.js +13 -13
  715. package/src/core/science/units/si/CANDELA.js +13 -13
  716. package/src/core/science/units/si/DIMENSIONLESS.js +14 -14
  717. package/src/core/science/units/si/KELVIN.js +13 -13
  718. package/src/core/science/units/si/KILOGRAM.js +13 -13
  719. package/src/core/science/units/si/METER.js +13 -13
  720. package/src/core/science/units/si/MOLE.js +13 -13
  721. package/src/core/science/units/si/SECOND.js +13 -13
  722. package/src/core/science/units/si/derived/BECQUEREL.js +16 -16
  723. package/src/core/science/units/si/derived/COULOMB.js +13 -13
  724. package/src/core/science/units/si/derived/FARAD.js +13 -13
  725. package/src/core/science/units/si/derived/GRAY.js +16 -16
  726. package/src/core/science/units/si/derived/HENRY.js +13 -13
  727. package/src/core/science/units/si/derived/HERTZ.js +16 -16
  728. package/src/core/science/units/si/derived/JOULE.js +13 -13
  729. package/src/core/science/units/si/derived/KATAL.js +13 -13
  730. package/src/core/science/units/si/derived/LUMEN.js +14 -14
  731. package/src/core/science/units/si/derived/LUX.js +13 -13
  732. package/src/core/science/units/si/derived/NEWTON.js +13 -13
  733. package/src/core/science/units/si/derived/OHM.js +13 -13
  734. package/src/core/science/units/si/derived/PASCAL.js +13 -13
  735. package/src/core/science/units/si/derived/SIEMENS.js +13 -13
  736. package/src/core/science/units/si/derived/SIEVERT.js +16 -16
  737. package/src/core/science/units/si/derived/TESLA.js +13 -13
  738. package/src/core/science/units/si/derived/VOLT.js +13 -13
  739. package/src/core/science/units/si/derived/WATT.js +13 -13
  740. package/src/core/science/units/si/derived/WEBER.js +13 -13
  741. package/src/core/science/units/unit_matrix_to_string.js +403 -403
  742. package/src/engine/Engine.js +726 -726
  743. package/src/engine/EngineHarness.js +590 -590
  744. package/src/engine/REVIEW_2026_07_03.md +211 -211
  745. package/src/engine/animation/AnimatedActions.js +81 -81
  746. package/src/engine/animation/AnimationUtils.js +252 -252
  747. package/src/engine/animation/async/TimeSeries.js +300 -300
  748. package/src/engine/animation/curve/animation_curve_binary_codec.js +60 -60
  749. package/src/engine/animation/curve/draw/canvas_point_to_curve.js +22 -22
  750. package/src/engine/animation/curve/draw/curve_point_to_canvas.js +38 -38
  751. package/src/engine/animation/curve/draw/position_canvas_to_curve.js +22 -22
  752. package/src/engine/animation/curve/draw/position_curve_to_canvas.js +22 -22
  753. package/src/engine/asset/GameAssetType.d.ts +0 -1
  754. package/src/engine/asset/GameAssetType.js +0 -1
  755. package/src/engine/asset/load_model_scene_bundle.js +27 -27
  756. package/src/engine/asset/loaders/font/FontAsset.js +21 -21
  757. package/src/engine/asset/loaders/font/FontAssetLoader.js +20 -20
  758. package/src/engine/asset/loaders/gltf_test_fixtures.js +358 -358
  759. package/src/engine/asset/loaders/image/ImageBitmapAssetLoader.js +52 -52
  760. package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +94 -94
  761. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterAverage.js +59 -59
  762. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterNone.js +55 -55
  763. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterPaeth.js +74 -74
  764. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterSub.js +34 -34
  765. package/src/engine/asset/loaders/image/png/filter/png_filter_unFilterUp.js +46 -46
  766. package/src/engine/control/first-person/DESIGN.md +640 -640
  767. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +563 -563
  768. package/src/engine/control/first-person/FirstPersonMotionPhase.js +134 -134
  769. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +2045 -2045
  770. package/src/engine/control/first-person/mastery/DecisionPoint.js +30 -30
  771. package/src/engine/control/first-person/math/Spring.js +71 -71
  772. package/src/engine/control/first-person/math/computeJumpFromApex.js +23 -23
  773. package/src/engine/control/first-person/math/computeLRCBreathRate.js +41 -41
  774. package/src/engine/control/first-person/math/computeMassRatios.js +44 -44
  775. package/src/engine/control/first-person/math/criticallyDampedSpring.js +34 -34
  776. package/src/engine/control/first-person/math/dampedSpringStep.js +72 -72
  777. package/src/engine/control/first-person/math/jumpDynamics.js +108 -108
  778. package/src/engine/control/first-person/math/stepTowards.js +20 -20
  779. package/src/engine/control/first-person/pose/FirstPersonPose.js +137 -137
  780. package/src/engine/control/first-person/pose/FirstPersonPosture.js +27 -27
  781. package/src/engine/control/first-person/test/buildTestPlayer.js +36 -36
  782. package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +531 -531
  783. package/src/engine/ecs/EntityManager.d.ts +7 -3
  784. package/src/engine/ecs/EntityManager.d.ts.map +1 -1
  785. package/src/engine/ecs/EntityManager.js +10 -5
  786. package/src/engine/ecs/HIERARCHY_REVIEW.md +717 -717
  787. package/src/engine/ecs/async/SystemWorkerHost.js +329 -329
  788. package/src/engine/ecs/async/SystemWorkerLoopback.js +143 -143
  789. package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +246 -246
  790. package/src/engine/ecs/async/WorkerSystem.js +702 -702
  791. package/src/engine/ecs/async/WorkerSystemProtocol.js +150 -150
  792. package/src/engine/ecs/fow/FogOfWar.js +707 -707
  793. package/src/engine/ecs/fow/FogOfWarEdgeMode.js +40 -40
  794. package/src/engine/ecs/fow/fog_of_war_mask_world_bounds.js +24 -24
  795. package/src/engine/ecs/fow/fog_of_war_uv_transform.js +30 -30
  796. package/src/engine/ecs/gui/hud/testHudEdgeStick.js +132 -134
  797. package/src/engine/ecs/hierarchy/EntityChildIndex.js +140 -140
  798. package/src/engine/ecs/ik/IKProblem.js +42 -42
  799. package/src/engine/ecs/ik/InverseKinematicsSystem.js +193 -193
  800. package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +134 -134
  801. package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +97 -97
  802. package/src/engine/ecs/ik/ik_bone_chain.js +85 -85
  803. package/src/engine/ecs/ik/ik_probe_terrain_contact.js +119 -119
  804. package/src/engine/ecs/parent/EntityNode.d.ts +1 -1
  805. package/src/engine/ecs/parent/EntityNode.js +2 -2
  806. package/src/engine/ecs/parent/ParentEntitySystem.js +255 -255
  807. package/src/engine/ecs/speaker/VoiceSystem.d.ts +2 -2
  808. package/src/engine/ecs/speaker/VoiceSystem.d.ts.map +1 -1
  809. package/src/engine/ecs/speaker/VoiceSystem.js +13 -7
  810. package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +269 -269
  811. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectDeSerializer.js +315 -315
  812. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectSerializer.js +331 -331
  813. package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +199 -199
  814. package/src/engine/ecs/storage/binary/object-v2/ObjectBinaryFormat.js +57 -57
  815. package/src/engine/ecs/storage/binary/object-v2/ObjectSerializationAdapter.js +56 -56
  816. package/src/engine/ecs/storage/binary/object-v2/README.md +110 -110
  817. package/src/engine/ecs/storage/binary/object-v2/objectStringCodec.js +48 -48
  818. package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.js +44 -44
  819. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +265 -265
  820. package/src/engine/ecs/terrain/TerrainClouds.js +97 -97
  821. package/src/engine/ecs/terrain/ecs/StubTerrainBuildWorker.js +65 -65
  822. package/src/engine/ecs/terrain/ecs/Terrain.d.ts +4 -0
  823. package/src/engine/ecs/terrain/ecs/Terrain.d.ts.map +1 -1
  824. package/src/engine/ecs/terrain/ecs/Terrain.js +790 -790
  825. package/src/engine/ecs/terrain/ecs/TerrainSystem.js +209 -209
  826. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +316 -316
  827. package/src/engine/ecs/terrain/ecs/layers/TerrainLayers.js +416 -416
  828. package/src/engine/ecs/terrain/ecs/splat/SplatMapping.js +525 -525
  829. package/src/engine/ecs/terrain/overlay/TerrainOverlay.js +302 -302
  830. package/src/engine/ecs/terrain/tiles/TerrainTile.js +561 -561
  831. package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +896 -896
  832. package/src/engine/ecs/terrain/tiles/tile_geometry_to_meshlets.js +36 -36
  833. package/src/engine/ecs/terrain/util/loadVisibleTerrainTiles.js +129 -129
  834. package/src/engine/ecs/transform/Transform64.js +814 -814
  835. package/src/engine/ecs/transform/t64_copy_from_transform.js +35 -35
  836. package/src/engine/ecs/transform/t64_equals_transform.js +55 -55
  837. package/src/engine/ecs/transform/t64_look_rotation.js +36 -36
  838. package/src/engine/ecs/transform/t64_transform_direction.js +25 -25
  839. package/src/engine/ecs/transform/transform_copy_from_t64.js +28 -28
  840. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +345 -345
  841. package/src/engine/ecs/transform-attachment/transform_attachment_find_descendant_by_name.js +65 -65
  842. package/src/engine/ecs/transform-attachment/transform_attachment_parent_of.js +24 -24
  843. package/src/engine/ecs/util/hideEntityGracefully.js +208 -208
  844. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +446 -446
  845. package/src/engine/graphics/FULL_SCREEN_QUAD_VERTEX_SHADER.js +14 -14
  846. package/src/engine/graphics/FrameThrottle.js +2 -2
  847. package/src/engine/graphics/ecs/animation/animator/graph/AnimationState.js +207 -207
  848. package/src/engine/graphics/ecs/animation/animator/graph/AnimationTransition.js +151 -151
  849. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.js +22 -22
  850. package/src/engine/graphics/ecs/camera/Camera.js +165 -165
  851. package/src/engine/graphics/ecs/camera/camera_active_frustum.js +25 -25
  852. package/src/engine/graphics/ecs/camera/camera_find_active.js +28 -28
  853. package/src/engine/graphics/ecs/camera/camera_traverse_active.js +18 -18
  854. package/src/engine/graphics/ecs/camera/pp/PerfectPanner.js +170 -170
  855. package/src/engine/graphics/ecs/camera/serialization/CameraSerializationAdapter.js +68 -68
  856. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +296 -296
  857. package/src/engine/graphics/ecs/decal/v2/Decal.js +220 -220
  858. package/src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.js +56 -56
  859. package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_0_1.js +38 -38
  860. package/src/engine/graphics/ecs/light/shadow/compute_view_frustum_aabb_in_space.js +62 -62
  861. package/src/engine/graphics/ecs/light/shadow/extend_shadow_camera_near_for_casters.js +77 -77
  862. package/src/engine/graphics/ecs/make_bvh_depth_range_computer.js +33 -33
  863. package/src/engine/graphics/ecs/mesh-v2/DeferredBoundsQueue.js +88 -88
  864. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +428 -428
  865. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.js +303 -303
  866. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.d.ts +1 -1
  867. package/src/engine/graphics/ecs/mesh-v2/aggregate/serialization/SGMeshSerializationAdapter.js +39 -39
  868. package/src/engine/graphics/ecs/mesh-v2/sg_hierarchy_compute_bounding_box_via_parent_entity.js +36 -36
  869. package/src/engine/graphics/ecs/path/tube/build/GeometryStream.js +94 -94
  870. package/src/engine/graphics/ecs/path/tube/build/build_stream_catmullrom.js +310 -310
  871. package/src/engine/graphics/ecs/path/tube/build/build_stream_linear.js +73 -73
  872. package/src/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +199 -199
  873. package/src/engine/graphics/ecs/path/tube/build/makeTubeStream.js +217 -217
  874. package/src/engine/graphics/ecs/path/tube/build/make_cap.js +340 -340
  875. package/src/engine/graphics/ecs/path/tube/build/make_ring_faces.js +40 -40
  876. package/src/engine/graphics/ecs/path/tube/build/make_ring_vertices.js +153 -153
  877. package/src/engine/graphics/ecs/render_layers_compute_depth_range.js +64 -64
  878. package/src/engine/graphics/ecs/trail3d/Trail3D.js +483 -483
  879. package/src/engine/graphics/ecs/trail3d/Trail3DFlags.js +26 -26
  880. package/src/engine/graphics/ecs/trail3d/advance_trail.js +42 -42
  881. package/src/engine/graphics/ecs/trail3d/make_gradient_stroke.js +58 -58
  882. package/src/engine/graphics/ecs/trail3d/seed_trail_stroke.js +90 -90
  883. package/src/engine/graphics/ecs/trail3d/seed_trail_tube.js +75 -75
  884. package/src/engine/graphics/ecs/trail3d/trail_head_position.js +19 -19
  885. package/src/engine/graphics/ecs/water/Water.js +104 -104
  886. package/src/engine/graphics/geometry/AttributeData.js +84 -84
  887. package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals_indexed.js +49 -49
  888. package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +288 -288
  889. package/src/engine/graphics/geometry/buffered/query/nearest_point_on_triangle_record.js +87 -87
  890. package/src/engine/graphics/geometry/buffered/read_triangle_vertices.js +102 -102
  891. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_buffered_geometry.js +52 -52
  892. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_indexed_geometry.js +20 -20
  893. package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_unindexed_geometry.js +19 -19
  894. package/src/engine/graphics/geometry/optimization/geometry_optimize_uv_tension.js +135 -135
  895. package/src/engine/graphics/impostors/voxel/README.md +149 -149
  896. package/src/engine/graphics/impostors/voxel/VoxelImpostorDescription.js +141 -141
  897. package/src/engine/graphics/particles/node-based/codegen/glsl/getTypeByteSize.js +20 -20
  898. package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts +2 -0
  899. package/src/engine/graphics/particles/node-based/nodes/FloatConstant.d.ts.map +1 -1
  900. package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts +2 -0
  901. package/src/engine/graphics/particles/node-based/nodes/ReadFloatUniform.d.ts.map +1 -1
  902. package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts +2 -0
  903. package/src/engine/graphics/particles/node-based/nodes/ReadVelocity.d.ts.map +1 -1
  904. package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts +1 -2
  905. package/src/engine/graphics/particles/node-based/nodes/ShaderNode.d.ts.map +1 -1
  906. package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts +2 -0
  907. package/src/engine/graphics/particles/node-based/nodes/Vector3Constant.d.ts.map +1 -1
  908. package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts +2 -0
  909. package/src/engine/graphics/particles/node-based/nodes/Vector3Merge.d.ts.map +1 -1
  910. package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts +2 -0
  911. package/src/engine/graphics/particles/node-based/nodes/Vector3Split.d.ts.map +1 -1
  912. package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts +2 -0
  913. package/src/engine/graphics/particles/node-based/nodes/WriteVelocity.d.ts.map +1 -1
  914. package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts +2 -0
  915. package/src/engine/graphics/particles/node-based/nodes/attribute/ReadVector3Attribute.d.ts.map +1 -1
  916. package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts +2 -0
  917. package/src/engine/graphics/particles/node-based/nodes/attribute/WriteVector3Attribute.d.ts.map +1 -1
  918. package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts +2 -0
  919. package/src/engine/graphics/particles/node-based/nodes/math/AddFloatNode.d.ts.map +1 -1
  920. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts +2 -0
  921. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Add.d.ts.map +1 -1
  922. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts +2 -0
  923. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Divide.d.ts.map +1 -1
  924. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts +2 -0
  925. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Multiply.d.ts.map +1 -1
  926. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts +2 -0
  927. package/src/engine/graphics/particles/node-based/nodes/math/Vector3Subtract.d.ts.map +1 -1
  928. package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts +2 -0
  929. package/src/engine/graphics/particles/node-based/nodes/noise/CurlNoiseNode.d.ts.map +1 -1
  930. package/src/engine/graphics/particles/node-based/nodes/particle_data_type_component_count.js +45 -45
  931. package/src/engine/graphics/particles/particular/engine/ParticularEngine.js +229 -229
  932. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts +2 -10
  933. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts.map +1 -1
  934. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +1149 -1149
  935. package/src/engine/graphics/particles/particular/engine/emitter/ParticlePool.js +472 -472
  936. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +2 -2
  937. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.js +2 -2
  938. package/src/engine/graphics/particles/particular/engine/parameter/ParameterSet.d.ts.map +1 -1
  939. package/src/engine/graphics/particles/particular/engine/parameter/ParameterSet.js +3 -5
  940. package/src/engine/graphics/particles/particular/engine/shader/ShaderManager.js +135 -135
  941. package/src/engine/graphics/particles/particular/engine/utils/distribute_points_on_indexed_triangles.js +168 -168
  942. package/src/engine/graphics/render/forward_plus/plugin/forwardPlusMaterialMarker.js +18 -18
  943. package/src/engine/graphics/render/forward_plus/read_frustum_corner.js +2 -2
  944. package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +219 -219
  945. package/src/engine/graphics/render/frame_graph/FrameGraph.js +900 -900
  946. package/src/engine/graphics/render/frame_graph/FrameGraphScope.js +72 -72
  947. package/src/engine/graphics/render/frame_graph/FrameGraphState.js +39 -39
  948. package/src/engine/graphics/render/frame_graph/ResourceEntry.js +96 -96
  949. package/src/engine/graphics/render/gizmo/GizmoShapeBuffer.js +105 -105
  950. package/src/engine/graphics/render/gizmo/GizmoShapeRenderingInterface.js +162 -162
  951. package/src/engine/graphics/render/layers/RenderLayer.js +95 -95
  952. package/src/engine/graphics/sh3/build_injected_shader.js +56 -56
  953. package/src/engine/graphics/sh3/grid_dilate_average.js +175 -175
  954. package/src/engine/graphics/sh3/path_tracer/BufferedGeometryBVH.js +506 -506
  955. package/src/engine/graphics/sh3/path_tracer/PathTracedMesh.js +161 -161
  956. package/src/engine/graphics/sh3/path_tracer/PathTracedRenderer.js +205 -205
  957. package/src/engine/graphics/sh3/path_tracer/PathTracedScene.js +698 -698
  958. package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +490 -490
  959. package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.js +2 -2
  960. package/src/engine/graphics/sh3/path_tracer/make_sky_hosek.js +45 -45
  961. package/src/engine/graphics/sh3/path_tracer/populate_path_traced_scene_from_ecd.js +73 -73
  962. package/src/engine/graphics/sh3/path_tracer/ray_hit_apply_transform.js +32 -32
  963. package/src/engine/graphics/sh3/path_tracer/texture/apply_texture_clamping_to_coordinate.js +28 -28
  964. package/src/engine/graphics/sh3/path_tracer/texture/sample_material.js +142 -142
  965. package/src/engine/graphics/sh3/sky/hosek/render_hosek_sky_to_equirectangular.js +70 -70
  966. package/src/engine/graphics/sh3/sky/hosek/sky_hosek_compute_irradiance_by_direction.js +388 -388
  967. package/src/engine/graphics/shaders/chunks/glsl_octahedral_impostor.js +277 -277
  968. package/src/engine/graphics/shaders/chunks/glsl_voxel_impostor_splat.js +57 -57
  969. package/src/engine/graphics/shadows/vsm.glsl.js +43 -43
  970. package/src/engine/graphics/texture/3d/scs3d_sample_linear3.js +81 -81
  971. package/src/engine/graphics/texture/EnvironmentTextureProjection.js +15 -15
  972. package/src/engine/graphics/texture/channel_count_to_format_prefix.js +26 -26
  973. package/src/engine/graphics/texture/isImageBitmap.js +2 -2
  974. package/src/engine/graphics/texture/reflection/convolve_equirectangular_reflection.js +189 -189
  975. package/src/engine/graphics/texture/reflection/equirectangular_reflection_roughness.js +51 -51
  976. package/src/engine/graphics/texture/sampler/HarmonicDiffusionGrid.js +145 -145
  977. package/src/engine/graphics/texture/sampler/Sampler2DArray.js +172 -172
  978. package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +466 -466
  979. package/src/engine/graphics/texture/sampler/compare/flip/FlipParameters.js +18 -18
  980. package/src/engine/graphics/texture/sampler/compare/flip/FlipPooling.js +33 -33
  981. package/src/engine/graphics/texture/sampler/compare/flip/flip_build_feature_kernel.js +147 -147
  982. package/src/engine/graphics/texture/sampler/compare/flip/flip_build_spatial_kernel.js +177 -177
  983. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_color_difference.js +104 -104
  984. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_feature_difference.js +76 -76
  985. package/src/engine/graphics/texture/sampler/compare/flip/flip_compute_pixels_per_degree.js +34 -34
  986. package/src/engine/graphics/texture/sampler/compare/flip/flip_constants.js +77 -77
  987. package/src/engine/graphics/texture/sampler/compare/flip/flip_filter_feature.js +48 -48
  988. package/src/engine/graphics/texture/sampler/compare/flip/flip_filter_spatial.js +86 -86
  989. package/src/engine/graphics/texture/sampler/compare/flip/flip_pool.js +71 -71
  990. package/src/engine/graphics/texture/sampler/compare/flip/flip_srgb_to_ycxcz.js +55 -55
  991. package/src/engine/graphics/texture/sampler/compare/flip/sampler2d_flip_ldr.js +80 -80
  992. package/src/engine/graphics/texture/sampler/filter/SeparableKernel.js +82 -82
  993. package/src/engine/graphics/texture/sampler/filter/sampler2d_convolve_separable.js +122 -122
  994. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.js +148 -148
  995. package/src/engine/graphics/texture/sampler/sampler2d_channel_apply_lut.js +82 -82
  996. package/src/engine/graphics/texture/sampler/sampler2d_combine.js +67 -67
  997. package/src/engine/graphics/texture/sampler/sampler2d_linear_f16_to_srgb_u8.js +54 -54
  998. package/src/engine/graphics/texture/sampler/sampler2d_sample_equirectangular_direction.js +63 -63
  999. package/src/engine/graphics/texture/sampler/sampler2d_srgb_to_linear.js +33 -33
  1000. package/src/engine/graphics/texture/sampler/sampler2d_srgb_u8_to_linear_f16.js +68 -68
  1001. package/src/engine/graphics/texture/shade_image_preview.js +103 -103
  1002. package/src/engine/graphics/trail/TrailSpawnMode.js +20 -20
  1003. package/src/engine/graphics/trail/tube/TubeX.js +573 -573
  1004. package/src/engine/graphics/trail/tube/TubeXMaterialSpec.js +58 -58
  1005. package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.js +34 -34
  1006. package/src/engine/graphics/trail/tube/tube_attributes_spec.js +69 -69
  1007. package/src/engine/graphics/trail/tube/tube_frame.js +83 -83
  1008. package/src/engine/graphics3/AnimationGraphSystem3.js +329 -329
  1009. package/src/engine/graphics3/AnimationSystem3.js +352 -352
  1010. package/src/engine/graphics3/CameraSystem3.js +170 -170
  1011. package/src/engine/graphics3/DecalSystem3.js +441 -441
  1012. package/src/engine/graphics3/FogOfWarSystem3.js +265 -265
  1013. package/src/engine/graphics3/GraphicsEngine3.js +776 -776
  1014. package/src/engine/graphics3/HighlightSystem3.js +241 -241
  1015. package/src/engine/graphics3/LightSystem3.js +211 -211
  1016. package/src/engine/graphics3/MeshSystem3.js +646 -646
  1017. package/src/engine/graphics3/ParticleEmitterSystem3.js +289 -289
  1018. package/src/engine/graphics3/PathDisplaySystem3.js +309 -309
  1019. package/src/engine/graphics3/PickingQuery.js +48 -48
  1020. package/src/engine/graphics3/PickingResult.js +47 -47
  1021. package/src/engine/graphics3/PickingSystem3.js +273 -273
  1022. package/src/engine/graphics3/ShadeCameraAdapter.js +55 -55
  1023. package/src/engine/graphics3/ShadedGeometrySystem3.js +169 -169
  1024. package/src/engine/graphics3/TerrainSystem3.js +566 -566
  1025. package/src/engine/graphics3/TooltipComponentSystem3.js +328 -328
  1026. package/src/engine/graphics3/Trail3DSystem3.js +221 -221
  1027. package/src/engine/graphics3/WaterSystem3.js +293 -293
  1028. package/src/engine/graphics3/animation/ClipPlayback.js +84 -84
  1029. package/src/engine/graphics3/animation/wrap_clip_time.js +23 -23
  1030. package/src/engine/graphics3/animation/write_graph_playback.js +48 -48
  1031. package/src/engine/graphics3/camera_sync_from_transform.js +29 -29
  1032. package/src/engine/graphics3/debug/gizmo_view_from_camera.js +48 -48
  1033. package/src/engine/graphics3/decal/DECAL_CLUSTER.js +61 -61
  1034. package/src/engine/graphics3/decal/DECAL_GPU_RECORD.js +117 -117
  1035. package/src/engine/graphics3/decal/DecalAtlas.js +194 -194
  1036. package/src/engine/graphics3/decal/DecalAtlasFill.js +32 -32
  1037. package/src/engine/graphics3/decal/GPUDecalRenderer.js +360 -360
  1038. package/src/engine/graphics3/decal/chunk_decal_intersects_frustum.js +59 -59
  1039. package/src/engine/graphics3/decal/chunk_decal_sampling_info.js +57 -57
  1040. package/src/engine/graphics3/decal/chunk_decal_surface_frame.js +54 -54
  1041. package/src/engine/graphics3/decal/decal_atlas_border.js +69 -69
  1042. package/src/engine/graphics3/decal/decal_gpu_records.js +120 -120
  1043. package/src/engine/graphics3/decal/decal_material_samplers.js +109 -109
  1044. package/src/engine/graphics3/decal/graph_build_decal_clusters.js +212 -212
  1045. package/src/engine/graphics3/decal/shader_cluster_assign_decals.js +207 -207
  1046. package/src/engine/graphics3/decal/shader_cull_decals_frustum.js +108 -108
  1047. package/src/engine/graphics3/highlight/GPUHighlightRenderer.js +151 -151
  1048. package/src/engine/graphics3/highlight/HIGHLIGHT_OUTLINE.js +23 -23
  1049. package/src/engine/graphics3/highlight/chunk_highlight_lookup.js +53 -53
  1050. package/src/engine/graphics3/highlight/pack_highlight_color.js +44 -44
  1051. package/src/engine/graphics3/highlight/pack_highlight_table.js +74 -74
  1052. package/src/engine/graphics3/highlight/shader_highlight_outline.js +150 -150
  1053. package/src/engine/graphics3/load_cube_environment.js +68 -68
  1054. package/src/engine/graphics3/make_default_environment.js +107 -107
  1055. package/src/engine/graphics3/particles/particle_gpu_records.js +221 -221
  1056. package/src/engine/graphics3/path/build_tube_path_streams.js +98 -98
  1057. package/src/engine/graphics3/path/tube_stream_write_geometry.js +90 -90
  1058. package/src/engine/graphics3/preview/ModelPreviewFraming.js +35 -35
  1059. package/src/engine/graphics3/preview/make_model_preview_scene.js +154 -154
  1060. package/src/engine/graphics3/preview/make_model_thumbnail.js +48 -48
  1061. package/src/engine/graphics3/preview/model_preview_framing.js +70 -70
  1062. package/src/engine/graphics3/shade_bundle_bounds.js +55 -55
  1063. package/src/engine/graphics3/shade_camera_projection_ray.js +77 -77
  1064. package/src/engine/graphics3/shade_node_to_entity_composition.js +84 -84
  1065. package/src/engine/graphics3/terrain/GPUTerrainSplatRenderer.js +481 -481
  1066. package/src/engine/graphics3/terrain/chunk_terrain_grid_overlay.js +61 -61
  1067. package/src/engine/graphics3/terrain/chunk_terrain_splat_mix.js +66 -66
  1068. package/src/engine/graphics3/terrain/pack_terrain_row_table.js +53 -53
  1069. package/src/engine/graphics3/terrain/shader_terrain_splat.js +215 -215
  1070. package/src/engine/graphics3/trail/trail_tube_write_geometry.js +158 -158
  1071. package/src/engine/input/GAMEPAD_API_PROPOSAL.md +717 -717
  1072. package/src/engine/input/analog/apply_radial_dead_zone.js +38 -38
  1073. package/src/engine/input/devices/GamepadDevice.js +466 -466
  1074. package/src/engine/input/devices/ManualInputDevice.js +152 -152
  1075. package/src/engine/input/devices/PointerCoordinates.js +26 -26
  1076. package/src/engine/input/devices/events/GamepadEvents.js +10 -10
  1077. package/src/engine/input/devices/gamepad/GamepadAxes.js +19 -19
  1078. package/src/engine/input/devices/gamepad/GamepadButtons.js +29 -29
  1079. package/src/engine/input/devices/gamepad/GamepadCoordinates.js +17 -17
  1080. package/src/engine/input/devices/gamepad/GamepadDeviceLayout.js +323 -323
  1081. package/src/engine/input/devices/gamepad/GamepadHandle.js +286 -286
  1082. package/src/engine/input/devices/gamepad/GamepadLayout.js +160 -160
  1083. package/src/engine/input/devices/gamepad/GamepadStandardMapping.js +31 -31
  1084. package/src/engine/input/devices/gamepad/GamepadStick.js +169 -169
  1085. package/src/engine/input/devices/gamepad/GamepadStickCalibration.js +119 -119
  1086. package/src/engine/input/devices/gamepad/GamepadStickCalibrator.js +250 -250
  1087. package/src/engine/input/devices/gamepad/gamepad_layout_database.js +144 -144
  1088. package/src/engine/input/devices/gamepad/gamepad_read_hat_axis.js +61 -61
  1089. package/src/engine/input/devices/gamepad/gamepad_write_dpad_vector.js +30 -30
  1090. package/src/engine/input/devices/gamepad/prototypeGamepadTester.js +2124 -2124
  1091. package/src/engine/input/devices/mouse/MouseButtons.js +22 -22
  1092. package/src/engine/input/ecs/components/Input.js +118 -118
  1093. package/src/engine/input/ecs/components/InputController.js +78 -78
  1094. package/src/engine/input/ecs/ism/ISM_DESIGN.md +1523 -1523
  1095. package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +627 -627
  1096. package/src/engine/input/ecs/ism/InputActionEvent.js +40 -40
  1097. package/src/engine/input/ecs/ism/InputBinding.js +71 -71
  1098. package/src/engine/input/ecs/ism/InputCoordinateKind.js +25 -25
  1099. package/src/engine/input/ecs/ism/InputCoordinateSource.js +86 -86
  1100. package/src/engine/input/ecs/ism/InputDirection.js +33 -33
  1101. package/src/engine/input/ecs/ism/InputMapProgram.js +236 -236
  1102. package/src/engine/input/ecs/ism/InputMapSystem.js +976 -976
  1103. package/src/engine/input/ecs/ism/InputOcclusion.js +31 -31
  1104. package/src/engine/input/ecs/ism/InputSource.js +67 -67
  1105. package/src/engine/input/ecs/ism/InputSourceTable.js +107 -107
  1106. package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannel.js +93 -93
  1107. package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannelType.js +11 -11
  1108. package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.js +153 -153
  1109. package/src/engine/input/ecs/ism/coordinate/InputCoordinateSwitches.js +160 -160
  1110. package/src/engine/input/ecs/ism/device/GAMEPAD_INPUT_DEVICE_ID.js +9 -9
  1111. package/src/engine/input/ecs/ism/device/GamepadInputDeviceAdapter.js +88 -88
  1112. package/src/engine/input/ecs/ism/device/InputDeviceAdapter.js +72 -72
  1113. package/src/engine/input/ecs/ism/device/KEYBOARD_INPUT_DEVICE_ID.js +9 -9
  1114. package/src/engine/input/ecs/ism/device/KeyboardInputDeviceAdapter.js +63 -63
  1115. package/src/engine/input/ecs/ism/device/ManualInputDeviceAdapter.js +55 -55
  1116. package/src/engine/input/ecs/ism/device/POINTER_INPUT_DEVICE_ID.js +9 -9
  1117. package/src/engine/input/ecs/ism/device/PointerInputDeviceAdapter.js +160 -160
  1118. package/src/engine/input/ecs/ism/map/InputBinding.js +88 -88
  1119. package/src/engine/input/ecs/ism/map/InputCoordinateBinding.js +102 -102
  1120. package/src/engine/input/ecs/ism/map/InputLayer.js +220 -220
  1121. package/src/engine/input/ecs/ism/map/InputMap.js +331 -331
  1122. package/src/engine/input/ecs/ism/prototypeInputMap.js +309 -309
  1123. package/src/engine/input/ecs/ism/trigger/InputTrigger.js +148 -148
  1124. package/src/engine/input/ecs/ism/trigger/InputTriggerChord.js +173 -173
  1125. package/src/engine/input/ecs/ism/trigger/InputTriggerGamepadButton.js +37 -37
  1126. package/src/engine/input/ecs/ism/trigger/InputTriggerHold.js +176 -176
  1127. package/src/engine/input/ecs/ism/trigger/InputTriggerKey.js +39 -39
  1128. package/src/engine/input/ecs/ism/trigger/InputTriggerMouseButton.js +38 -38
  1129. package/src/engine/input/ecs/ism/trigger/InputTriggerRelease.js +120 -120
  1130. package/src/engine/input/ecs/ism/trigger/InputTriggerSequence.js +315 -315
  1131. package/src/engine/input/ecs/ism/trigger/InputTriggerSwitch.js +105 -105
  1132. package/src/engine/input/ecs/ism/trigger/InputTriggerType.js +17 -17
  1133. package/src/engine/input/ecs/systems/InputControllerSystem.js +253 -253
  1134. package/src/engine/input/ecs/systems/InputSystem.js +162 -162
  1135. package/src/engine/intelligence/behavior/primitive/FailingBehaviorSerializationAdapter.js +25 -25
  1136. package/src/engine/intelligence/behavior/primitive/SucceedingBehaviorSerializationAdapter.js +26 -26
  1137. package/src/engine/intelligence/behavior/util/AsynchronousDelayAction.js +55 -55
  1138. package/src/engine/interpolation/BinaryInterpolationAdapter.js +56 -56
  1139. package/src/engine/interpolation/Interpoland.js +49 -49
  1140. package/src/engine/interpolation/Interpolated.js +149 -149
  1141. package/src/engine/interpolation/PoseInterpolationAdapter.js +61 -61
  1142. package/src/engine/interpolation/TransformPoseSerializationAdapter.js +57 -57
  1143. package/src/engine/interpolation/pose_interpoland.js +27 -27
  1144. package/src/engine/navigation/ecs/path_following/PathFollower.js +222 -222
  1145. package/src/engine/navigation/mesh/NavigationMesh.js +145 -145
  1146. package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +661 -0
  1147. package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +229 -229
  1148. package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.d.ts.map +1 -1
  1149. package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.js +628 -520
  1150. package/src/engine/network/CONGESTION_CONTROL.md +87 -87
  1151. package/src/engine/network/README.md +52 -52
  1152. package/src/engine/network/adapters/QuaternionInterpolationAdapter.js +43 -43
  1153. package/src/engine/network/adapters/TransformInterpolationAdapter.js +84 -84
  1154. package/src/engine/network/adapters/TransformReplicationAdapter.js +87 -87
  1155. package/src/engine/network/adapters/Vector3InterpolationAdapter.js +46 -46
  1156. package/src/engine/network/convertPathToURL.js +2 -2
  1157. package/src/engine/network/core/MalformedPacketError.js +26 -26
  1158. package/src/engine/network/core/quantize/quantize_float.js +73 -73
  1159. package/src/engine/network/core/quantize/quantize_position.js +65 -65
  1160. package/src/engine/network/core/sequence/ack_bitfield.js +77 -77
  1161. package/src/engine/network/core/sequence/seq16.js +69 -69
  1162. package/src/engine/network/core/sequence/seq32.js +73 -73
  1163. package/src/engine/network/ecs/NetworkSystem.js +84 -84
  1164. package/src/engine/network/ecs/components/NetworkIdentity.js +73 -73
  1165. package/src/engine/network/ecs/owner_authorization.js +55 -55
  1166. package/src/engine/network/ecs/serialization/NetworkIdentitySerializationAdapter.js +64 -64
  1167. package/src/engine/network/replication/ScopeFilter.js +71 -71
  1168. package/src/engine/network/sim/ActionLog.js +152 -152
  1169. package/src/engine/network/sim/SimAction.js +273 -273
  1170. package/src/engine/network/sim/Snapshotter.js +222 -222
  1171. package/src/engine/network/state/FrameBufferRing.js +168 -168
  1172. package/src/engine/network/state/InputRing.js +134 -134
  1173. package/src/engine/network/state/PriorityAccumulator.js +180 -180
  1174. package/src/engine/network/time/TimeDilation.js +62 -62
  1175. package/src/engine/network/transport/Channel.js +336 -336
  1176. package/src/engine/network/transport/Transport.js +203 -203
  1177. package/src/engine/network/transport/adapters/NodeUDPTransport.js +186 -186
  1178. package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +105 -105
  1179. package/src/engine/network/transport/fragments/fragment_send.js +147 -147
  1180. package/src/engine/network/transport/fragments/packet_size.js +101 -101
  1181. package/src/engine/network/xhr.js +23 -23
  1182. package/src/engine/physics/BULLET_REVIEW.md +945 -945
  1183. package/src/engine/physics/CANNON_REVIEW.md +1300 -1300
  1184. package/src/engine/physics/CONSTRAINT_SOLVER_BENCH_LOG.md +208 -208
  1185. package/src/engine/physics/CONSTRAINT_SOLVER_IMPROVEMENTS_PLAN.md +364 -364
  1186. package/src/engine/physics/INTEPOLATION_SYSTEM_PLAN.md +287 -287
  1187. package/src/engine/physics/JOLT_REVIEW.md +913 -913
  1188. package/src/engine/physics/PLAN.md +1120 -1094
  1189. package/src/engine/physics/RAPIER_REVIEW.md +934 -934
  1190. package/src/engine/physics/REVIEW_001_ACTION_PLAN.md +642 -642
  1191. package/src/engine/physics/REVIEW_002.md +151 -151
  1192. package/src/engine/physics/REVIEW_003.md +166 -166
  1193. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +97 -97
  1194. package/src/engine/physics/constraint/DofMode.js +35 -35
  1195. package/src/engine/physics/constraint/solve_constraints.js +1 -1
  1196. package/src/engine/physics/contact/combine_material.js +35 -35
  1197. package/src/engine/physics/ecs/BodyKind.js +29 -29
  1198. package/src/engine/physics/ecs/Collider.js +177 -177
  1199. package/src/engine/physics/ecs/ColliderFlags.js +15 -15
  1200. package/src/engine/physics/ecs/ColliderSerializationAdapter.js +37 -37
  1201. package/src/engine/physics/ecs/Joint.js +475 -475
  1202. package/src/engine/physics/ecs/JointSerializationAdapter.js +72 -72
  1203. package/src/engine/physics/ecs/PhysicsSystem.d.ts +3 -0
  1204. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  1205. package/src/engine/physics/ecs/PhysicsSystem.js +7 -2
  1206. package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.js +37 -37
  1207. package/src/engine/physics/ecs/SleepState.js +12 -12
  1208. package/src/engine/physics/ecs/find_non_finite_physics_state.js +76 -76
  1209. package/src/engine/physics/fluid/FluidField.js +867 -867
  1210. package/src/engine/physics/fluid/FluidSimulator.js +832 -832
  1211. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +243 -243
  1212. package/src/engine/physics/fluid/SliceVisualiser.js +190 -190
  1213. package/src/engine/physics/fluid/ecs/FluidComponent.js +239 -239
  1214. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.js +89 -89
  1215. package/src/engine/physics/fluid/ecs/FluidObstacle.js +97 -97
  1216. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  1217. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.js +348 -348
  1218. package/src/engine/physics/fluid/ecs/FluidSystem.js +142 -142
  1219. package/src/engine/physics/fluid/ecs/FluidWorkerCore.js +123 -123
  1220. package/src/engine/physics/fluid/ecs/WorkerFluidSystem.js +395 -395
  1221. package/src/engine/physics/fluid/ecs/fluid.worker.js +12 -12
  1222. package/src/engine/physics/fluid/ecs/fluid_build_world_to_grid.js +32 -32
  1223. package/src/engine/physics/fluid/ecs/fluid_gather_visible_effectors.js +47 -47
  1224. package/src/engine/physics/fluid/ecs/fluid_reanchor_field.js +85 -85
  1225. package/src/engine/physics/fluid/ecs/fluid_sync_effectors_from_transform.js +16 -16
  1226. package/src/engine/physics/fluid/ecs/fluid_worker_protocol.js +111 -111
  1227. package/src/engine/physics/fluid/ecs/makeFluidWorker.js +18 -18
  1228. package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +81 -81
  1229. package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +202 -202
  1230. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +257 -257
  1231. package/src/engine/physics/fluid/effector/WakeFluidEffector.js +405 -405
  1232. package/src/engine/physics/fluid/prototype.js +126 -126
  1233. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.js +143 -143
  1234. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.js +162 -162
  1235. package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.js +107 -107
  1236. package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.js +131 -131
  1237. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +90 -90
  1238. package/src/engine/physics/fluid/solver/v3_grid_limit8_at_indices.js +38 -38
  1239. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.js +77 -77
  1240. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.js +113 -113
  1241. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.js +92 -92
  1242. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.js +107 -107
  1243. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +135 -135
  1244. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +511 -511
  1245. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +108 -108
  1246. package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.js +317 -317
  1247. package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.js +236 -236
  1248. package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.js +217 -217
  1249. package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.js +174 -174
  1250. package/src/engine/physics/fluid/solver/v3_mac_clip_trace.js +95 -95
  1251. package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.js +77 -77
  1252. package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.js +131 -131
  1253. package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.js +104 -104
  1254. package/src/engine/physics/inertia/world_inverse_inertia.js +160 -160
  1255. package/src/engine/physics/integration/integrate_position.js +97 -97
  1256. package/src/engine/physics/narrowphase/box_box_manifold.js +681 -681
  1257. package/src/engine/physics/narrowphase/box_triangle_contact.js +906 -906
  1258. package/src/engine/physics/narrowphase/capsule_triangle_contact.js +395 -395
  1259. package/src/engine/physics/narrowphase/compute_penetration.js +369 -369
  1260. package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.js +55 -55
  1261. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.js +37 -37
  1262. package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.js +117 -117
  1263. package/src/engine/physics/narrowphase/narrowphase_step.js +1738 -1738
  1264. package/src/engine/physics/narrowphase/reduce_manifold_contacts.js +74 -74
  1265. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts +12 -11
  1266. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -1
  1267. package/src/engine/physics/narrowphase/refine_ray_hit.js +228 -36
  1268. package/src/engine/physics/narrowphase/sphere_sphere_contact.js +52 -52
  1269. package/src/engine/physics/narrowphase/sphere_triangle_contact.js +138 -138
  1270. package/src/engine/physics/persistence/solver_caches.js +309 -309
  1271. package/src/engine/physics/queries/overlap_shape.js +187 -187
  1272. package/src/engine/physics/queries/raycast.d.ts +7 -4
  1273. package/src/engine/physics/queries/raycast.d.ts.map +1 -1
  1274. package/src/engine/physics/queries/raycast.js +11 -5
  1275. package/src/engine/physics/queries/shape_cast.js +417 -417
  1276. package/src/engine/physics/solver/apply_impulse_to_body.js +86 -86
  1277. package/src/engine/physics/solver/friction_cone.js +37 -37
  1278. package/src/engine/physics/solver/solve_contacts.js +1 -1
  1279. package/src/engine/platform/WebEnginePlatform.d.ts.map +1 -1
  1280. package/src/engine/platform/WebEnginePlatform.js +1 -2
  1281. package/src/engine/scene/SerializedScene.d.ts +2 -2
  1282. package/src/engine/scene/SerializedScene.d.ts.map +1 -1
  1283. package/src/engine/scene/transitionToScene.js +121 -121
  1284. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  1285. package/src/engine/simulation/Ticker.js +33 -0
  1286. package/src/engine/sound/ecs/audio/LiveEmitterSet.js +345 -345
  1287. package/src/engine/sound/ecs/audio/SpatialAudioIndex.js +140 -140
  1288. package/src/engine/sound/simulation/AcousticSimulator.js +646 -646
  1289. package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +432 -432
  1290. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +250 -250
  1291. package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +322 -322
  1292. package/src/engine/sound/simulation/README.md +277 -277
  1293. package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +261 -261
  1294. package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +121 -121
  1295. package/src/engine/sound/simulation/configureAcousticSimulation.js +48 -48
  1296. package/src/engine/sound/simulation/core/AcousticMedium.js +113 -113
  1297. package/src/engine/sound/simulation/core/AcousticMediumSerializationAdapter.js +27 -27
  1298. package/src/engine/sound/simulation/core/AcousticOccluderIndex.js +312 -312
  1299. package/src/engine/sound/simulation/core/AcousticRegionIndex.js +159 -159
  1300. package/src/engine/sound/simulation/core/AcousticSolution.js +90 -90
  1301. package/src/engine/sound/simulation/core/AcousticSourceState.js +109 -109
  1302. package/src/engine/sound/simulation/core/AcousticVolumeRegion.js +73 -73
  1303. package/src/engine/sound/simulation/core/OcclusionSolver.js +112 -112
  1304. package/src/engine/sound/simulation/core/RayHit.js +50 -50
  1305. package/src/engine/sound/simulation/core/VolumeField.js +149 -149
  1306. package/src/engine/sound/simulation/definition/AcousticDirectivity.js +114 -114
  1307. package/src/engine/sound/simulation/definition/AcousticDirectivitySerializationAdapter.js +30 -30
  1308. package/src/engine/sound/simulation/definition/AcousticMaterial.js +122 -122
  1309. package/src/engine/sound/simulation/definition/AcousticMaterialSerializationAdapter.js +32 -32
  1310. package/src/engine/sound/simulation/ecs/AcousticBody.js +48 -48
  1311. package/src/engine/sound/simulation/ecs/AcousticBodySerializationAdapter.js +34 -34
  1312. package/src/engine/sound/simulation/ecs/AcousticProbeFieldSystem.js +64 -64
  1313. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +75 -75
  1314. package/src/engine/sound/simulation/ecs/AcousticVolume.js +74 -74
  1315. package/src/engine/sound/simulation/ecs/AcousticVolumeSerializationAdapter.js +37 -37
  1316. package/src/engine/sound/simulation/ecs/AcousticVolumeSystem.js +66 -66
  1317. package/src/engine/sound/simulation/probe/AcousticProbeField.js +578 -578
  1318. package/src/engine/sound/simulation/probe/AcousticProbeFieldSerializationAdapter.js +60 -60
  1319. package/src/engine/sound/simulation/probe/ProbeFieldPathingSolution.js +64 -64
  1320. package/src/engine/sound/simulation/probe/ProbeVisibilityRecheck.js +132 -132
  1321. package/src/engine/sound/simulation/probe/acoustic_probe_transfer.js +103 -103
  1322. package/src/engine/sound/simulation/probe/acoustic_trace_energy.js +136 -136
  1323. package/src/engine/sound/simulation/probe/bakeProbeField.js +169 -169
  1324. package/src/engine/sound/simulation/probe/bakeProbeReflectors.js +110 -110
  1325. package/src/engine/sound/simulation/probe/bakeReverbBands.js +110 -110
  1326. package/src/engine/sound/simulation/probe/bakeVisibility.js +148 -148
  1327. package/src/engine/sound/simulation/probe/echogram_band_rt60.js +83 -83
  1328. package/src/engine/sound/simulation/probe/probe_delaunay_edges.js +215 -215
  1329. package/src/engine/sound/simulation/probe/probe_densify_portals.js +140 -140
  1330. package/src/engine/sound/simulation/probe/probe_detect_portals.js +196 -196
  1331. package/src/engine/sound/simulation/probe/probe_edge_key.js +38 -38
  1332. package/src/engine/sound/simulation/probe/probe_edge_visible.js +41 -41
  1333. package/src/engine/sound/simulation/probe/probe_place_sdf_cover.js +82 -82
  1334. package/src/engine/sound/simulation/probe/probe_refine_connectivity.js +181 -181
  1335. package/src/engine/sound/simulation/probe/probe_sdf_grid.js +171 -171
  1336. package/src/engine/sound/simulation/probe/probe_visibility_augment.js +146 -146
  1337. package/src/engine/sound/simulation/probe/probe_visibility_bridge_components.js +167 -167
  1338. package/src/engine/sound/simulation/render/FoaProbeReverbRenderer.js +354 -354
  1339. package/src/engine/sound/simulation/render/ProbeReverbRenderer.js +231 -231
  1340. package/src/engine/sound/simulation/render/foaReverbImpulseResponse.js +105 -105
  1341. package/src/engine/sound/simulation/render/reverbImpulseResponse.js +66 -66
  1342. package/src/engine/sound/simulation/render/reverb_band_tails.js +93 -93
  1343. package/src/engine/sound/simulation/serialization/populateAcousticSerializationRegistry.js +25 -25
  1344. package/src/engine/sound/sopra/README.md +643 -643
  1345. package/src/engine/sound/sopra/SopraEngine.js +432 -432
  1346. package/src/engine/sound/sopra/asset/AssetManagerBufferProvider.js +71 -71
  1347. package/src/engine/sound/sopra/asset/BufferProvider.js +29 -29
  1348. package/src/engine/sound/sopra/asset/StubBufferProvider.js +58 -58
  1349. package/src/engine/sound/sopra/definition/BusDefinition.js +142 -142
  1350. package/src/engine/sound/sopra/definition/BusDefinitionSerializationAdapter.js +54 -54
  1351. package/src/engine/sound/sopra/definition/DuckingRule.js +106 -106
  1352. package/src/engine/sound/sopra/definition/DuckingRuleSerializationAdapter.js +31 -31
  1353. package/src/engine/sound/sopra/definition/EventDescription.js +262 -262
  1354. package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +55 -55
  1355. package/src/engine/sound/sopra/definition/MixerSnapshot.js +83 -83
  1356. package/src/engine/sound/sopra/definition/MixerSnapshotSerializationAdapter.js +39 -39
  1357. package/src/engine/sound/sopra/definition/ParameterDefinition.js +117 -117
  1358. package/src/engine/sound/sopra/definition/ParameterDefinitionSerializationAdapter.js +31 -31
  1359. package/src/engine/sound/sopra/definition/VoiceStealMode.js +18 -18
  1360. package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.js +109 -109
  1361. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.js +185 -185
  1362. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClipSerializationAdapter.js +59 -59
  1363. package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.js +128 -128
  1364. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.js +226 -226
  1365. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClipSerializationAdapter.js +54 -54
  1366. package/src/engine/sound/sopra/definition/clip/SampleAudioClip.js +191 -191
  1367. package/src/engine/sound/sopra/definition/clip/SampleAudioClipSerializationAdapter.js +39 -39
  1368. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.js +79 -79
  1369. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClipSerializationAdapter.js +42 -42
  1370. package/src/engine/sound/sopra/definition/clip/SilenceAudioClip.js +77 -77
  1371. package/src/engine/sound/sopra/definition/clip/SilenceAudioClipSerializationAdapter.js +27 -27
  1372. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts +5 -0
  1373. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts.map +1 -1
  1374. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.js +125 -125
  1375. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClipSerializationAdapter.js +41 -41
  1376. package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.js +24 -24
  1377. package/src/engine/sound/sopra/definition/effect/CompressorEffect.js +120 -120
  1378. package/src/engine/sound/sopra/definition/effect/CompressorEffectSerializationAdapter.js +31 -31
  1379. package/src/engine/sound/sopra/definition/effect/EqEffect.js +128 -128
  1380. package/src/engine/sound/sopra/definition/effect/EqEffectSerializationAdapter.js +29 -29
  1381. package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +113 -113
  1382. package/src/engine/sound/sopra/definition/effect/ReverbEffectSerializationAdapter.js +25 -25
  1383. package/src/engine/sound/sopra/runtime/BusGraph.js +231 -231
  1384. package/src/engine/sound/sopra/runtime/ParameterStore.js +98 -98
  1385. package/src/engine/sound/sopra/runtime/SopraPlaybackContext.js +68 -68
  1386. package/src/engine/sound/sopra/runtime/Voice.js +145 -145
  1387. package/src/engine/sound/sopra/runtime/VoiceManager.js +136 -136
  1388. package/src/engine/sound/sopra/runtime/VoicePool.js +17 -17
  1389. package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.js +42 -42
  1390. package/src/engine/sound/sopra/serialization/sopraJSON.js +99 -99
  1391. package/src/engine/sound/sopra/serialization/sopraSerializationHarness.js +49 -49
  1392. package/src/engine/sound/sopra/util/MockAudioContext.js +224 -224
  1393. package/src/engine/sound/sopra/util/fadeOutAndStop.js +60 -60
  1394. package/src/engine/ui/DraggableAspect.js +115 -115
  1395. package/src/engine/ui/apply_pointer_tilt_3d.js +50 -50
  1396. package/src/generation/COORDINATES.md +54 -54
  1397. package/src/generation/GridGenerationResource.js +24 -24
  1398. package/src/generation/GridTaskGroup.js +214 -214
  1399. package/src/generation/REVIEW_01_ACTION_PLAN.md +628 -628
  1400. package/src/generation/automata/CaveGeneratorCellularAutomata.js +79 -79
  1401. package/src/generation/automata/CellularAutomata.js +22 -22
  1402. package/src/generation/compute_writes_union.js +25 -25
  1403. package/src/generation/filtering/CellFilter.js +117 -117
  1404. package/src/generation/filtering/core/CellFilterBinaryOperation.js +37 -37
  1405. package/src/generation/filtering/core/CellFilterOperationTertiary.js +43 -43
  1406. package/src/generation/filtering/core/CellFilterUnaryOperation.js +29 -29
  1407. package/src/generation/filtering/numeric/process/computeCellFilterSobel.js +36 -36
  1408. package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.js +42 -42
  1409. package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.js +18 -18
  1410. package/src/generation/filtering/numeric/util/write_cell_filter_to_sampler2d.js +47 -47
  1411. package/src/generation/filtering/util/cell_filter_weights_pick.js +54 -54
  1412. package/src/generation/grid/GridData.js +233 -233
  1413. package/src/generation/grid/coords/grid_to_texel.js +10 -10
  1414. package/src/generation/grid/coords/texel_to_grid.js +10 -10
  1415. package/src/generation/grid/generation/GridTaskApplyActionToCells.js +90 -90
  1416. package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.js +388 -388
  1417. package/src/generation/grid/generation/GridTaskExecuteRuleTimes.js +127 -127
  1418. package/src/generation/grid/generation/GridTaskSequence.js +58 -58
  1419. package/src/generation/grid/generation/NoopGridTaskGenerator.js +12 -12
  1420. package/src/generation/grid/generation/discrete/GridTaskActionRuleSet.js +48 -48
  1421. package/src/generation/grid/generation/discrete/GridTaskCellularAutomata.js +146 -146
  1422. package/src/generation/grid/generation/discrete/GridTaskConnectRooms.js +540 -540
  1423. package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +222 -222
  1424. package/src/generation/grid/generation/grid/GridTaskAddNodesFixed.js +44 -44
  1425. package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +614 -614
  1426. package/src/generation/markers/GridCellActionPlaceMarker.js +244 -244
  1427. package/src/generation/markers/GridCellActionPlaceMarkerGroup.js +86 -86
  1428. package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.js +266 -266
  1429. package/src/generation/markers/emitter/MarkerNodeEmitterGridCellAction.js +49 -49
  1430. package/src/generation/placement/GridCellActionTransformNearbyMarkers.js +120 -120
  1431. package/src/generation/placement/action/GridCellAction.js +45 -45
  1432. package/src/generation/placement/action/GridCellActionPlaceTags.js +140 -140
  1433. package/src/generation/placement/action/GridCellActionWriteFilterToLayer.js +89 -89
  1434. package/src/generation/placement/action/random/CellActionSelectRandom.js +69 -69
  1435. package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.js +91 -91
  1436. package/src/generation/placement/action/util/GridCellActionSequence.js +61 -61
  1437. package/src/generation/placement/action/util/GridCellDisplacedAction.js +61 -61
  1438. package/src/generation/rules/cell/CellMatcherRemovalPreservesConnectivity.js +183 -183
  1439. package/src/generation/theme/ThemeEngine.js +666 -666
  1440. package/src/shade/RENDERER_CONTRACT.md +568 -568
  1441. package/src/shade/descriptor/texture/format/gpu_texture_format_info.js +267 -267
  1442. package/src/shade/device/ShadeDeviceFailure.js +104 -104
  1443. package/src/shade/device/ShadeDeviceFailureReason.js +41 -41
  1444. package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +255 -255
  1445. package/src/shade/device/mock/REVIEW_2026_08_22.md +527 -527
  1446. package/src/shade/device/mock/SoftwareGPUBindGroup.js +23 -23
  1447. package/src/shade/device/mock/SoftwareGPUBindGroupLayout.js +22 -22
  1448. package/src/shade/device/mock/SoftwareGPUError.js +63 -63
  1449. package/src/shade/device/mock/SoftwareGPUPipeline.js +75 -75
  1450. package/src/shade/device/mock/SoftwareGPUQuerySet.js +113 -113
  1451. package/src/shade/device/mock/SoftwareGPUSampler.js +30 -30
  1452. package/src/shade/device/mock/SoftwareGPUShaderModule.js +32 -32
  1453. package/src/shade/device/mock/SoftwareGPUTextureView.js +22 -22
  1454. package/src/shade/device/mock/SoftwareGPUUncapturedErrorEvent.js +23 -23
  1455. package/src/shade/device/mock/normalize_dynamic_offsets.js +26 -26
  1456. package/src/shade/device/mock/texture_copy.js +287 -287
  1457. package/src/shade/device/timing/GPUTimer.js +285 -285
  1458. package/src/shade/device/timing/GPUTimerArray.js +205 -205
  1459. package/src/shade/playground/add_random_lights.js +49 -49
  1460. package/src/shade/playground/add_random_meshes.js +83 -83
  1461. package/src/shade/playground/animation_prototype.js +508 -508
  1462. package/src/shade/playground/animation_prototype_skinning.js +647 -647
  1463. package/src/shade/playground/animation_prototype_stress.js +765 -765
  1464. package/src/shade/playground/enable_picker.js +59 -59
  1465. package/src/shade/playground/gltf_skinned_prototype.js +560 -560
  1466. package/src/shade/playground/gltf_skinned_stress_prototype.js +387 -387
  1467. package/src/shade/playground/gltf_viewer.js +282 -282
  1468. package/src/shade/playground/load_default_environment.js +19 -19
  1469. package/src/shade/playground/main.js +2727 -2727
  1470. package/src/shade/playground/make_animated_instances.js +117 -117
  1471. package/src/shade/playground/prototype_virtual_texture.js +274 -274
  1472. package/src/shade/playground/prototype_volumetrics_01.js +206 -206
  1473. package/src/shade/playground/sample.js +234 -234
  1474. package/src/shade/playground/sample_load_gltf.js +102 -102
  1475. package/src/shade/playground/spread_node3d_grid.js +19 -19
  1476. package/src/shade/renderer/Renderer.js +2436 -2436
  1477. package/src/shade/renderer/ShadeIndirectLightingMode.js +14 -14
  1478. package/src/shade/renderer/animation/ShadeAnimationChannel.js +414 -414
  1479. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.js +531 -531
  1480. package/src/shade/renderer/animation/pose/PosePlayback.js +55 -55
  1481. package/src/shade/renderer/animation/pose/pose_evaluate_local.js +179 -179
  1482. package/src/shade/renderer/animation/pose/pose_evaluate_world.js +76 -76
  1483. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +1024 -1024
  1484. package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.js +79 -79
  1485. package/src/shade/renderer/animation/skinning/chunk_skin_blend_mesh_local.js +56 -56
  1486. package/src/shade/renderer/binding/BindGroupManager.js +282 -282
  1487. package/src/shade/renderer/binding/adapt_cache_capacity.js +25 -25
  1488. package/src/shade/renderer/buffer/GPUBufferAllocator.js +116 -116
  1489. package/src/shade/renderer/buffer/buffer_pool_ops.js +123 -123
  1490. package/src/shade/renderer/buffer/table/GPU_DATABASE_PAGE_SIZE.js +9 -9
  1491. package/src/shade/renderer/buffer/table/GPU_DATABASE_UPLOAD_BUFFER_LIMIT.js +8 -8
  1492. package/src/shade/renderer/buffer/table/PageBufferPool.js +71 -71
  1493. package/src/shade/renderer/buffer/table/PageSlotAllocator.js +95 -95
  1494. package/src/shade/renderer/camera/Camera.js +281 -281
  1495. package/src/shade/renderer/camera/GPUCameraContext.js +233 -233
  1496. package/src/shade/renderer/camera/orbital/README.md +84 -84
  1497. package/src/shade/renderer/deferred/shader_composite_volumetrics.js +75 -75
  1498. package/src/shade/renderer/dynamic/DYNAMIC_MESH_VERTEX.js +25 -25
  1499. package/src/shade/renderer/dynamic/GPUDynamicMeshRenderer.js +342 -342
  1500. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +167 -167
  1501. package/src/shade/renderer/dynamic/shader_dynamic_mesh.js +170 -170
  1502. package/src/shade/renderer/extension/FrameContext.js +263 -263
  1503. package/src/shade/renderer/extension/FramePhase.js +104 -104
  1504. package/src/shade/renderer/extension/FrameRecord.js +126 -126
  1505. package/src/shade/renderer/extension/GBufferTextures.js +83 -83
  1506. package/src/shade/renderer/extension/PresentTarget.js +34 -34
  1507. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +918 -918
  1508. package/src/shade/renderer/extension/RenderExtension.js +69 -69
  1509. package/src/shade/renderer/extension/RenderExtensionRegistry.js +319 -319
  1510. package/src/shade/renderer/extension/SceneColor.js +40 -40
  1511. package/src/shade/renderer/extension/ViewTextures.js +78 -78
  1512. package/src/shade/renderer/fow/GPUFogOfWarRenderer.js +182 -182
  1513. package/src/shade/renderer/geometry/Geometry.js +608 -608
  1514. package/src/shade/renderer/geometry/geometry_build_from_meshlet_geometry.js +342 -342
  1515. package/src/shade/renderer/geometry/meshlet_geometry_transfer.js +41 -41
  1516. package/src/shade/renderer/geometry/primitives/make_box_geometry.js +153 -153
  1517. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.js +240 -240
  1518. package/src/shade/renderer/geometry/primitives/make_plane_geometry.js +145 -145
  1519. package/src/shade/renderer/geometry/primitives/make_polyhedron_geometry.js +327 -327
  1520. package/src/shade/renderer/geometry/primitives/make_torus_geometry.js +107 -107
  1521. package/src/shade/renderer/geometry/primitives/make_torus_knot_geometry.js +165 -165
  1522. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +607 -607
  1523. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +66 -66
  1524. package/src/shade/renderer/geometry/virtual/build/VGeoBuildResult.js +32 -32
  1525. package/src/shade/renderer/geometry/virtual/build/VGeoFaceGraph.js +103 -103
  1526. package/src/shade/renderer/geometry/virtual/build/VGeoGatheredFaces.js +25 -25
  1527. package/src/shade/renderer/geometry/virtual/build/VGeoLevel.js +33 -33
  1528. package/src/shade/renderer/geometry/virtual/build/VGeoLevelOptions.js +62 -62
  1529. package/src/shade/renderer/geometry/virtual/build/VGeoLevelSummary.js +49 -49
  1530. package/src/shade/renderer/geometry/virtual/build/VGeoSubmesh.js +20 -20
  1531. package/src/shade/renderer/geometry/virtual/build/VirtualGeometryMesh.js +214 -214
  1532. package/src/shade/renderer/geometry/virtual/build/gltf/GltfByteSource.js +122 -122
  1533. package/src/shade/renderer/geometry/virtual/build/gltf/GltfCollectReport.js +29 -29
  1534. package/src/shade/renderer/geometry/virtual/build/gltf/GltfDocument.js +210 -210
  1535. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometry.js +48 -48
  1536. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometryInstance.js +25 -25
  1537. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometrySelection.js +28 -28
  1538. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_collect_geometries.js +296 -296
  1539. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_open_document.js +166 -166
  1540. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_read_geometry.js +199 -199
  1541. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +173 -173
  1542. package/src/shade/renderer/geometry/virtual/build/vgeo_bounding_sphere.js +28 -28
  1543. package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +200 -200
  1544. package/src/shade/renderer/geometry/virtual/build/vgeo_build_levels.js +1786 -1786
  1545. package/src/shade/renderer/geometry/virtual/build/vgeo_build_page_nodes.js +157 -157
  1546. package/src/shade/renderer/geometry/virtual/build/vgeo_build_root_group.js +26 -26
  1547. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_normals.js +75 -75
  1548. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_tangents.js +143 -143
  1549. package/src/shade/renderer/geometry/virtual/build/vgeo_containing_sphere.js +44 -44
  1550. package/src/shade/renderer/geometry/virtual/build/vgeo_extract_submesh.js +41 -41
  1551. package/src/shade/renderer/geometry/virtual/build/vgeo_gather_faces.js +71 -71
  1552. package/src/shade/renderer/geometry/virtual/build/vgeo_graph_components.js +123 -123
  1553. package/src/shade/renderer/geometry/virtual/build/vgeo_narrow_indices.js +26 -26
  1554. package/src/shade/renderer/geometry/virtual/build/vgeo_normalize_source.js +112 -112
  1555. package/src/shade/renderer/geometry/virtual/build/vgeo_partition_graph.js +56 -56
  1556. package/src/shade/renderer/geometry/virtual/build/vgeo_sphere_inflate_to_contain.js +70 -70
  1557. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set.js +187 -187
  1558. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set_packed.js +207 -207
  1559. package/src/shade/renderer/geometry/virtual/format/VGEO_DEFECT.js +18 -18
  1560. package/src/shade/renderer/geometry/virtual/format/VGeoDefect.js +38 -38
  1561. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +64 -64
  1562. package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTE.js +13 -13
  1563. package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTES.js +50 -50
  1564. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_allocate.js +28 -28
  1565. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_mask.js +23 -23
  1566. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.js +31 -31
  1567. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_vertex.js +32 -32
  1568. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_declare.js +46 -46
  1569. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_like.js +19 -19
  1570. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.js +27 -27
  1571. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_asset_id_preimage.js +62 -62
  1572. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_asset_id.js +13 -13
  1573. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_directory_block_checksum.js +41 -41
  1574. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_frame_checksum.js +41 -41
  1575. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_header_checksum.js +25 -25
  1576. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET.js +20 -20
  1577. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_RECORD_SIZE.js +5 -5
  1578. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CHILD_REF.js +5 -5
  1579. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_TRIANGLE_COUNT.js +5 -5
  1580. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_VERTEX_COUNT.js +5 -5
  1581. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_CHILD.js +5 -5
  1582. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_GROUP.js +5 -5
  1583. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_SAME_PAGE.js +6 -6
  1584. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.js +81 -81
  1585. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryGroup.js +37 -37
  1586. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryPageNode.js +55 -55
  1587. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_BLOCK_RECORDS.js +5 -5
  1588. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_FLAG_ROOT_PAGE.js +5 -5
  1589. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_RECORD_SIZE.js +5 -5
  1590. package/src/shade/renderer/geometry/virtual/format/directory/vgeo_directory_block_count.js +12 -12
  1591. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_OFFSET.js +11 -11
  1592. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_TABLE_ENTRY_SIZE.js +5 -5
  1593. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_LZ4.js +11 -11
  1594. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_RAW.js +5 -5
  1595. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_ALIGNMENT.js +5 -5
  1596. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_HEADER_SIZE.js +5 -5
  1597. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_OFFSET.js +13 -13
  1598. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_PAGE_MAGIC.js +5 -5
  1599. package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameBlob.js +21 -21
  1600. package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameExtent.js +59 -59
  1601. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_codec_name.js +27 -27
  1602. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_decode_frame_blob.js +84 -84
  1603. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.js +56 -56
  1604. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_frame_decode_bound.js +35 -35
  1605. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_scan_frames.js +74 -74
  1606. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.js +6 -6
  1607. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HASH_ALGO_XXH3.js +5 -5
  1608. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_OFFSET.js +31 -31
  1609. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_SIZE.js +5 -5
  1610. package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_OFFSET.js +20 -20
  1611. package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_RECORD_SIZE.js +9 -9
  1612. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MAGIC.js +5 -5
  1613. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MIN_READER_VERSION.js +5 -5
  1614. package/src/shade/renderer/geometry/virtual/format/header/VGEO_PAYLOAD_ENCODING_SHADE_MESHLET_V1.js +5 -5
  1615. package/src/shade/renderer/geometry/virtual/format/header/VGeoLevelRecord.js +41 -41
  1616. package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_RECORD_SIZE.js +5 -5
  1617. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_GROUP_CLUSTER_COUNT.js +6 -6
  1618. package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_OFFSET.js +21 -21
  1619. package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_SIZE.js +5 -5
  1620. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FANOUT.js +9 -9
  1621. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FLAG_LEAF.js +5 -5
  1622. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_OFFSET.js +10 -10
  1623. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_RECORD_SIZE.js +5 -5
  1624. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_HEADER_SIZE.js +5 -5
  1625. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.js +16 -16
  1626. package/src/shade/renderer/geometry/virtual/format/payload/VGEO_ENCODING_FLAGS_MASK.js +6 -6
  1627. package/src/shade/renderer/geometry/virtual/format/payload/VGeoEncodedPayload.js +18 -18
  1628. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.js +200 -200
  1629. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_attribute_offset.js +39 -39
  1630. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_size.js +20 -20
  1631. package/src/shade/renderer/geometry/virtual/format/prototypeVGEOFormatViewer.js +2063 -2063
  1632. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +1622 -1622
  1633. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +485 -485
  1634. package/src/shade/renderer/gpu_primitive/sort/ffx/graph_radix_sort.js +115 -115
  1635. package/src/shade/renderer/gpu_primitive/sort/one_sweep/verify_radix_sort_one_sweep.js +110 -110
  1636. package/src/shade/renderer/light/environment/octahedral_resample_kernel.js +50 -50
  1637. package/src/shade/renderer/light/environment/octahedral_uv_to_direction.js +30 -30
  1638. package/src/shade/renderer/light/environment/resample_cube_to_octahedral.js +157 -157
  1639. package/src/shade/renderer/light/make_sunlight.js +35 -35
  1640. package/src/shade/renderer/light/model/io/light_record_point.js +39 -39
  1641. package/src/shade/renderer/loader/gltf/GLTF_PRIMITIVE_MODE.js +23 -23
  1642. package/src/shade/renderer/loader/gltf/MESHOPT_COMPRESSION_PLAN.md +793 -793
  1643. package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtension.js +54 -54
  1644. package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtensionSet.js +109 -109
  1645. package/src/shade/renderer/loader/gltf/ext/gltf_apply_buffer_view_extensions.js +69 -69
  1646. package/src/shade/renderer/loader/gltf/ext/gltf_buffer_view_extensions.js +22 -22
  1647. package/src/shade/renderer/loader/gltf/ext/gltf_geometry_extensions.js +39 -39
  1648. package/src/shade/renderer/loader/gltf/ext/meshopt/MeshoptBufferViewExtension.js +301 -301
  1649. package/src/shade/renderer/loader/gltf/gltf_component_type.js +223 -223
  1650. package/src/shade/renderer/loader/gltf/gltf_node_world_matrices.js +137 -137
  1651. package/src/shade/renderer/loader/gltf/gltf_parse_container.js +241 -241
  1652. package/src/shade/renderer/loader/gltf/gltf_read_accessor.js +294 -294
  1653. package/src/shade/renderer/loader/gltf/gltf_used_image_indices.js +49 -49
  1654. package/src/shade/renderer/loader/gltf/load_gltf.js +1253 -1253
  1655. package/src/shade/renderer/loader/gltf/tiny-gltf.js +646 -646
  1656. package/src/shade/renderer/loader/usd/UsdError.js +33 -33
  1657. package/src/shade/renderer/loader/usd/UsdExtensionRegistry.js +69 -69
  1658. package/src/shade/renderer/loader/usd/load_usd.js +226 -226
  1659. package/src/shade/renderer/loader/usd/parse_usda.js +931 -931
  1660. package/src/shade/renderer/loader/usd/unpack_usdz.js +106 -106
  1661. package/src/shade/renderer/loader/usd/usd_build_scene.js +658 -658
  1662. package/src/shade/renderer/loader/usd/usd_compose_transform.js +258 -258
  1663. package/src/shade/renderer/loader/usd/usd_decode_image.js +384 -384
  1664. package/src/shade/renderer/loader/usd/usd_lz4.js +182 -182
  1665. package/src/shade/renderer/loader/usd/usd_triangulate.js +159 -159
  1666. package/src/shade/renderer/material/ShadeMaterial.d.ts +2 -2
  1667. package/src/shade/renderer/material/ShadeMaterial.js +2 -2
  1668. package/src/shade/renderer/material/standard/fragment_gbuffer.js +334 -334
  1669. package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
  1670. package/src/shade/renderer/material/standard/material_gbuffer_vertex.js +45 -45
  1671. package/src/shade/renderer/material/standard_material_to_struct.js +23 -23
  1672. package/src/shade/renderer/particles/prototypeParticleSystem.js +450 -450
  1673. package/src/shade/renderer/particles/runtime/spawn_request_encoding.js +52 -52
  1674. package/src/shade/renderer/pool/TransientResourcePool.js +392 -392
  1675. package/src/shade/renderer/postprocess/bloom/bloom_chain_resolution.js +29 -29
  1676. package/src/shade/renderer/postprocess/bloom/graph_bloom_downsample.js +109 -109
  1677. package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.js +155 -155
  1678. package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.js +114 -114
  1679. package/src/shade/renderer/postprocess/dof/DOF_AUTOFOCUS_PARAMS_STRUCT.js +25 -25
  1680. package/src/shade/renderer/postprocess/dof/DOF_FOCUS_STATE_STRUCT.js +23 -23
  1681. package/src/shade/renderer/postprocess/dof/DOF_PRESETS.js +27 -27
  1682. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_diameter.js +41 -41
  1683. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_radius.js +32 -32
  1684. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_coefficient.js +26 -26
  1685. package/src/shade/renderer/postprocess/dof/compute_dof_autofocus_params.js +64 -64
  1686. package/src/shade/renderer/postprocess/dof/compute_dof_uniform.js +54 -54
  1687. package/src/shade/renderer/postprocess/dof/gather/DOF2_CONFIG.js +91 -91
  1688. package/src/shade/renderer/postprocess/dof/gather/DOF2_PRESETS.js +9 -9
  1689. package/src/shade/renderer/postprocess/dof/gather/DOF2_SETTINGS_STRUCT.js +66 -66
  1690. package/src/shade/renderer/postprocess/dof/gather/DOF2_TEXTURE_FORMAT.js +22 -22
  1691. package/src/shade/renderer/postprocess/dof/gather/DepthOfFieldU.js +292 -292
  1692. package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_coc_to_near_far.js +25 -25
  1693. package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_gather_weight.js +30 -30
  1694. package/src/shade/renderer/postprocess/dof/gather/compute_dof2_uniform.js +54 -54
  1695. package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.js +194 -194
  1696. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_fill.js +68 -68
  1697. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.js +140 -140
  1698. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.js +142 -142
  1699. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.js +99 -99
  1700. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.js +102 -102
  1701. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_dilate.js +75 -75
  1702. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_max.js +73 -73
  1703. package/src/shade/renderer/postprocess/dof/raymarch/DOF_SETTINGS_STRUCT.js +49 -49
  1704. package/src/shade/renderer/postprocess/dof/raymarch/DepthOfField.js +298 -298
  1705. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +244 -244
  1706. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.js +91 -91
  1707. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_firefly_cleanup.js +61 -61
  1708. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.js +90 -90
  1709. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +267 -267
  1710. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +271 -271
  1711. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_dilate.js +70 -70
  1712. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_max.js +72 -72
  1713. package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.js +99 -99
  1714. package/src/shade/renderer/postprocess/gtao/generate_magic_square_noise.js +51 -51
  1715. package/src/shade/renderer/postprocess/motion_blur/MotionBlur.js +56 -56
  1716. package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +78 -78
  1717. package/src/shade/renderer/postprocess/upscale-dither/UpscaleDither.js +95 -95
  1718. package/src/shade/renderer/postprocess/upscale-dither/fragment_shader_upscale_dither.js +204 -204
  1719. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.js +58 -58
  1720. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +230 -230
  1721. package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.js +278 -278
  1722. package/src/shade/renderer/rasterize/native/oit/chunk_material_side_should_draw.js +26 -26
  1723. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +178 -178
  1724. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +235 -235
  1725. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +208 -208
  1726. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +206 -206
  1727. package/src/shade/renderer/scene/DynamicMesh.js +70 -70
  1728. package/src/shade/renderer/scene/DynamicMeshBatch.js +90 -90
  1729. package/src/shade/renderer/scene/GPUSceneContext.js +901 -901
  1730. package/src/shade/renderer/scene/SceneNodeBinding.js +56 -56
  1731. package/src/shade/renderer/scene/SkinnedMesh.js +55 -55
  1732. package/src/shade/renderer/scene/TransformAuthority.js +33 -33
  1733. package/src/shade/renderer/scene/optimization/deduplicate_geometries.js +38 -38
  1734. package/src/shade/renderer/scene/optimization/deduplicate_images.js +93 -93
  1735. package/src/shade/renderer/scene/optimization/geometry/internal/match_refit_validate.js +127 -127
  1736. package/src/shade/renderer/scene/optimization/geometry/internal/match_solve_transform.js +492 -492
  1737. package/src/shade/renderer/scene/optimization/optimize_texture_set.js +81 -81
  1738. package/src/shade/renderer/scene/optimization/source_to_sampler2d.js +21 -21
  1739. package/src/shade/renderer/scene/serialization/STANDARD_MATERIAL_SERIALIZED_BYTE_SIZE.js +12 -12
  1740. package/src/shade/renderer/shader/chunk/geometry/quaternion/dual/chunk_dual_quat_transform_point.js +26 -26
  1741. package/src/shade/renderer/shader/chunk/noise/chunk_interleaved_gradient_noise.js +20 -20
  1742. package/src/shade/renderer/shader/chunk/spherical_harmonics/dering/chunk_sh2_dering_optimize_positive.js +61 -61
  1743. package/src/shade/renderer/shader/chunk/texture/chunk_texture_filter_fxaa_lite.js +225 -225
  1744. package/src/shade/renderer/shader/chunk/texture/dither/chunk_dither_color_8bit_gradient_noise.js +25 -25
  1745. package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.js +384 -384
  1746. package/src/shade/renderer/shadow/map/PointLightShadowmap.js +105 -105
  1747. package/src/shade/renderer/shadow/map/SpotLightShadowmap.js +63 -63
  1748. package/src/shade/renderer/shadow/map/TetrahedronPointLightShadowmap.js +89 -89
  1749. package/src/shade/renderer/shadow/map/shadowmap_update_score.js +232 -232
  1750. package/src/shade/renderer/texture/GPUTextureAllocator.js +85 -85
  1751. package/src/shade/renderer/texture/texture_pool_ops.js +171 -171
  1752. package/src/shade/renderer/texture/virtual/PageTableQuadAllocator.js +253 -253
  1753. package/src/shade/renderer/texture/virtual/README.md +276 -276
  1754. package/src/shade/renderer/texture/virtual/VTPageTable.js +330 -330
  1755. package/src/shade/renderer/texture/virtual/VTPhysicalCache.js +349 -349
  1756. package/src/shade/renderer/texture/virtual/VT_CONSTANTS.js +154 -154
  1757. package/src/shade/renderer/texture/virtual/VT_STACK_INFO_STRUCT.js +20 -20
  1758. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +1276 -1276
  1759. package/src/shade/renderer/texture/virtual/VirtualTextureStack.js +106 -106
  1760. package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.js +150 -150
  1761. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +232 -232
  1762. package/src/shade/renderer/texture/virtual/chunk_vt_request_key.js +28 -28
  1763. package/src/shade/renderer/texture/virtual/source/VTSourceImage.js +207 -207
  1764. package/src/shade/renderer/texture/virtual/source/VTSourceProcedural.js +135 -135
  1765. package/src/shade/renderer/texture/virtual/source/VTSourceTiled.js +132 -132
  1766. package/src/shade/renderer/water/GPUWaterRenderer.js +167 -167
  1767. package/src/shade/renderer/water/shader_water.js +246 -246
  1768. package/src/shade/renderer/water/water_height_texture_from_sampler.js +56 -56
  1769. package/src/shade/vitest.setup.mjs +89 -89
  1770. package/src/shade/wgsl/validate_wgsl_source.js +316 -316
  1771. package/src/view/controller/controls/NumericIntervalControl.js +90 -90
  1772. package/src/view/controller/controls/Vector2Control.js +83 -83
  1773. package/src/view/controller/controls/Vector3Control.js +90 -90
  1774. package/src/view/elements/Group.js +56 -56
  1775. package/src/view/elements/drawCheckers.js +33 -33
  1776. package/src/view/elements/windrose/WindRoseDiagram.js +369 -369
  1777. package/src/view/graphics/WebGLContextFailureView.js +76 -76
  1778. package/src/view/layout/DockPanel.js +51 -51
  1779. package/src/view/layout/SplitView.js +365 -365
  1780. package/src/view/layout/show_popup_menu.js +81 -81
  1781. package/src/view/minimap/MinimapCanvasView.js +411 -411
  1782. package/src/view/minimap/MinimapImageCache.js +88 -88
  1783. package/src/view/minimap/MinimapMarkerCollection.d.ts +0 -1
  1784. package/src/view/minimap/MinimapMarkerCollection.d.ts.map +1 -1
  1785. package/src/view/minimap/MinimapMarkerCollection.js +180 -180
  1786. package/src/view/minimap/dom/MinimapCameraView.js +206 -206
  1787. package/src/view/minimap/minimap_focus_area.js +97 -97
  1788. package/editor/process/symbolic/SocketsSymbolicDisplay.js +0 -192
  1789. package/src/core/geom/3d/topology/struct/binary/io/moved_tests.txt +0 -37
  1790. package/src/engine/ecs/attachment/Attachment.d.ts +0 -40
  1791. package/src/engine/ecs/attachment/Attachment.d.ts.map +0 -1
  1792. package/src/engine/ecs/attachment/Attachment.js +0 -57
  1793. package/src/engine/ecs/attachment/AttachmentBinding.d.ts +0 -28
  1794. package/src/engine/ecs/attachment/AttachmentBinding.d.ts.map +0 -1
  1795. package/src/engine/ecs/attachment/AttachmentBinding.js +0 -41
  1796. package/src/engine/ecs/attachment/AttachmentSystem.d.ts +0 -61
  1797. package/src/engine/ecs/attachment/AttachmentSystem.d.ts.map +0 -1
  1798. package/src/engine/ecs/attachment/AttachmentSystem.js +0 -307
  1799. package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts +0 -27
  1800. package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts.map +0 -1
  1801. package/src/engine/ecs/attachment/BoneAttachmentBinding.js +0 -69
  1802. package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts +0 -4
  1803. package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts.map +0 -1
  1804. package/src/engine/ecs/attachment/TransformAttachmentBinding.js +0 -51
  1805. package/src/engine/ecs/sockets/AttachmentSocket.d.ts +0 -32
  1806. package/src/engine/ecs/sockets/AttachmentSocket.d.ts.map +0 -1
  1807. package/src/engine/ecs/sockets/AttachmentSocket.js +0 -60
  1808. package/src/engine/ecs/sockets/AttachmentSocketType.d.ts +0 -6
  1809. package/src/engine/ecs/sockets/AttachmentSocketType.d.ts.map +0 -1
  1810. package/src/engine/ecs/sockets/AttachmentSocketType.js +0 -8
  1811. package/src/engine/ecs/sockets/AttachmentSockets.d.ts +0 -57
  1812. package/src/engine/ecs/sockets/AttachmentSockets.d.ts.map +0 -1
  1813. package/src/engine/ecs/sockets/AttachmentSockets.js +0 -130
  1814. package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts +0 -29
  1815. package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts.map +0 -1
  1816. package/src/engine/ecs/sockets/BoneAttachmentSocket.js +0 -56
  1817. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts +0 -6
  1818. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts.map +0 -1
  1819. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.js +0 -19
  1820. package/src/shade/renderer/animation/_dump_resolve.d.mts +0 -2
  1821. package/src/shade/renderer/animation/_dump_resolve.d.mts.map +0 -1
  1822. package/src/shade/renderer/animation/_dump_resolve.mjs +0 -5
@@ -1,610 +1,610 @@
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).
572
-
573
- ## 12. Review of the round-1 and round-2 commits
574
-
575
- A pass over all 34 commits, in `62047e542..a0e4b9dbc` plus the round-1 range. The point was to find defects in the remediation itself, so what follows leads with those.
576
-
577
- ### 12.1 Verified rather than assumed
578
-
579
- - **Particle compaction** — the swap plan was brute-forced against a reference over every victim subset for arrays up to 12 elements: 8178 cases, 0 mismatches.
580
- - **Camera 0→1 and Path 2→3 upgraders** — executed end to end; see §12.3, which turned this into a standing harness.
581
- - **Both new upgraders are registered** in `GameBinarySerializationRegistry.js` (`3ecf5c16`, `8b8df83a`). A version bump without registration silently breaks every existing save, and that was the failure worth checking.
582
- - **`ServerAuthoritativeClient`** — `Uint32Map.get` does return −1 for absent; network ids come off a free list, so the watermark map is bounded by peak concurrent entities rather than leaking; and a recycled id inherits a watermark that is always behind the current server frame, so reuse cannot drop state.
583
- - **Physics hot paths** — `solve_constraints`, `convex_convex_manifold`, `raycast`, `ManifoldStore`, `quat3_multiply`: zero executable changes across the whole range, JSDoc only.
584
- - **`BiMap`** — the argument swap is names-only; identical behaviour for the same positional call.
585
- - **`Engine` lifecycle** — `Ticker.start` re-adds its lifecycle listeners, so `stop()`→`start()` is clean; the one consumer testing `graphics === undefined` also tests for null; and `start()` already returned a promise before it became `async`.
586
- - **The round-trip harness is not vacuous** — deleting a field's restoration from an adapter turns it red on exactly that adapter.
587
-
588
- ### 12.2 Defects found in the remediation, and fixed
589
-
590
- - **`IndexedDBStorage.store` rejected up to three times for one failure.** `resolve`/`reject` there are the caller's own callbacks, not promise settle functions, and a failed write raises `error` on the request, bubbles to `error` on the transaction, then aborts it — with a listener on each. In-tree callers wrap the call in a promise, which hides it; `Storage` is published API, so an external consumer saw one lost save reported three times. Now it rejects on `abort` alone, which is the event that always fires for a transaction that will not commit, and it carries `transaction.error` as the reason. The storage classes had no specs at all; they have one now.
591
- - **The Lanczos `weight_sum === 0` fallback was unreachable.** Swept over every downscale ratio from 1 to 40 at 2 and 3 lobes, the weight sum was never zero, never negative, and never below 1. The NaN it claimed to prevent came from the *old* `if (weight <= 0) continue`, which discarded the negative lobes — and the rewrite had already removed that. Keeping the whole kernel makes the sum the integral of the kernel over the footprint, which stays near 1. Removed: it was precisely the defensive guard for a can't-happen condition this project rejects, and its comment described a failure the new code cannot produce.
592
-
593
- ### 12.3 The gap that mattered most: upgraders were never executed
594
-
595
- `upgrader_chain_contract.spec.js` checks that a path from every historical version to the current one *exists*. That catches a missing upgrader, which is what it was built for. It does not catch an upgrader that is present and emits the wrong layout — and at load time that is the worse failure, because the deserializer then reads real bytes at wrong offsets instead of failing loudly. Its own docblock admitted this and left it outstanding.
596
-
597
- `upgrader_execution_contract.spec.js` closes it. Each covered upgrader gets a source buffer in the layout it reads, the chain runs to the current version through `executeBinaryClassUpgraderChain` — the same executor production uses — and the current adapter deserializes the result. The assertion that does the work is the byte count: the adapter must consume exactly what the chain produced.
598
-
599
- Two properties make it honest rather than decorative:
600
-
601
- - **It is a check of what an upgrader *writes*, not what it reads.** The golden describes the start version's layout, which is derived from the upgrader's own reads. The adapter that originally wrote that layout is gone, so there is nothing left to check the read side against, and the spec says so instead of implying otherwise.
602
- - **Coverage is enumerated, not assumed.** 9 of 23 upgraders have goldens; the other 14 are listed in `WITHOUT_GOLDEN`, and a new upgrader that appears in neither list fails the spec. Each entry is a save-format version nothing verifies can still be read.
603
-
604
- Mutation-verified in both directions: making an upgrader emit one extra field, and making it omit one, each turns its own case red.
605
-
606
- ### 12.4 Left open, deliberately
607
-
608
- - **The Lanczos rewrite changed the filter shape** from radial (`sqrt(fx²+fy²)`) to separable (`L(x)·L(y)`). Separable is the correct Lanczos and it is cheaper — O(rx+ry) transcendental evaluations per output pixel instead of O(rx·ry) — but every downscaled texture now differs from before, and the commit framed it purely as a NaN fix. Recorded here rather than reverted; the old behaviour was not worth preserving.
609
- - **`sampler2d_scale_down_lanczos` throws "source is larger than destination"** when the condition, `source_width < d_w`, means the source is *smaller*. Pre-existing, and left alone rather than folded into an unrelated change.
610
- - **`IndexedDBStorage.remove` still reports success off the request** rather than the transaction commit — the same durability gap `store` had. Not touched here because it is a separate defect from the triple-reject this pass was fixing, and it deserves its own change.
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).
572
+
573
+ ## 12. Review of the round-1 and round-2 commits
574
+
575
+ A pass over all 34 commits, in `62047e542..a0e4b9dbc` plus the round-1 range. The point was to find defects in the remediation itself, so what follows leads with those.
576
+
577
+ ### 12.1 Verified rather than assumed
578
+
579
+ - **Particle compaction** — the swap plan was brute-forced against a reference over every victim subset for arrays up to 12 elements: 8178 cases, 0 mismatches.
580
+ - **Camera 0→1 and Path 2→3 upgraders** — executed end to end; see §12.3, which turned this into a standing harness.
581
+ - **Both new upgraders are registered** in `GameBinarySerializationRegistry.js` (`3ecf5c16`, `8b8df83a`). A version bump without registration silently breaks every existing save, and that was the failure worth checking.
582
+ - **`ServerAuthoritativeClient`** — `Uint32Map.get` does return −1 for absent; network ids come off a free list, so the watermark map is bounded by peak concurrent entities rather than leaking; and a recycled id inherits a watermark that is always behind the current server frame, so reuse cannot drop state.
583
+ - **Physics hot paths** — `solve_constraints`, `convex_convex_manifold`, `raycast`, `ManifoldStore`, `quat3_multiply`: zero executable changes across the whole range, JSDoc only.
584
+ - **`BiMap`** — the argument swap is names-only; identical behaviour for the same positional call.
585
+ - **`Engine` lifecycle** — `Ticker.start` re-adds its lifecycle listeners, so `stop()`→`start()` is clean; the one consumer testing `graphics === undefined` also tests for null; and `start()` already returned a promise before it became `async`.
586
+ - **The round-trip harness is not vacuous** — deleting a field's restoration from an adapter turns it red on exactly that adapter.
587
+
588
+ ### 12.2 Defects found in the remediation, and fixed
589
+
590
+ - **`IndexedDBStorage.store` rejected up to three times for one failure.** `resolve`/`reject` there are the caller's own callbacks, not promise settle functions, and a failed write raises `error` on the request, bubbles to `error` on the transaction, then aborts it — with a listener on each. In-tree callers wrap the call in a promise, which hides it; `Storage` is published API, so an external consumer saw one lost save reported three times. Now it rejects on `abort` alone, which is the event that always fires for a transaction that will not commit, and it carries `transaction.error` as the reason. The storage classes had no specs at all; they have one now.
591
+ - **The Lanczos `weight_sum === 0` fallback was unreachable.** Swept over every downscale ratio from 1 to 40 at 2 and 3 lobes, the weight sum was never zero, never negative, and never below 1. The NaN it claimed to prevent came from the *old* `if (weight <= 0) continue`, which discarded the negative lobes — and the rewrite had already removed that. Keeping the whole kernel makes the sum the integral of the kernel over the footprint, which stays near 1. Removed: it was precisely the defensive guard for a can't-happen condition this project rejects, and its comment described a failure the new code cannot produce.
592
+
593
+ ### 12.3 The gap that mattered most: upgraders were never executed
594
+
595
+ `upgrader_chain_contract.spec.js` checks that a path from every historical version to the current one *exists*. That catches a missing upgrader, which is what it was built for. It does not catch an upgrader that is present and emits the wrong layout — and at load time that is the worse failure, because the deserializer then reads real bytes at wrong offsets instead of failing loudly. Its own docblock admitted this and left it outstanding.
596
+
597
+ `upgrader_execution_contract.spec.js` closes it. Each covered upgrader gets a source buffer in the layout it reads, the chain runs to the current version through `executeBinaryClassUpgraderChain` — the same executor production uses — and the current adapter deserializes the result. The assertion that does the work is the byte count: the adapter must consume exactly what the chain produced.
598
+
599
+ Two properties make it honest rather than decorative:
600
+
601
+ - **It is a check of what an upgrader *writes*, not what it reads.** The golden describes the start version's layout, which is derived from the upgrader's own reads. The adapter that originally wrote that layout is gone, so there is nothing left to check the read side against, and the spec says so instead of implying otherwise.
602
+ - **Coverage is enumerated, not assumed.** 9 of 23 upgraders have goldens; the other 14 are listed in `WITHOUT_GOLDEN`, and a new upgrader that appears in neither list fails the spec. Each entry is a save-format version nothing verifies can still be read.
603
+
604
+ Mutation-verified in both directions: making an upgrader emit one extra field, and making it omit one, each turns its own case red.
605
+
606
+ ### 12.4 Left open, deliberately
607
+
608
+ - **The Lanczos rewrite changed the filter shape** from radial (`sqrt(fx²+fy²)`) to separable (`L(x)·L(y)`). Separable is the correct Lanczos and it is cheaper — O(rx+ry) transcendental evaluations per output pixel instead of O(rx·ry) — but every downscaled texture now differs from before, and the commit framed it purely as a NaN fix. Recorded here rather than reverted; the old behaviour was not worth preserving.
609
+ - **`sampler2d_scale_down_lanczos` throws "source is larger than destination"** when the condition, `source_width < d_w`, means the source is *smaller*. Pre-existing, and left alone rather than folded into an unrelated change.
610
+ - **`IndexedDBStorage.remove` still reports success off the request** rather than the transaction commit — the same durability gap `store` had. Not touched here because it is a separate defect from the triple-reject this pass was fixing, and it deserves its own change.