@woosh/meep-engine 3.0.2 → 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 (1823) hide show
  1. package/LICENSE +188 -188
  2. package/README.md +152 -145
  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/grid/grid2transform/GridPosition2TransformSystem.d.ts +2 -2
  1072. package/src/engine/grid/grid2transform/GridPosition2TransformSystem.d.ts.map +1 -1
  1073. package/src/engine/input/GAMEPAD_API_PROPOSAL.md +717 -717
  1074. package/src/engine/input/analog/apply_radial_dead_zone.js +38 -38
  1075. package/src/engine/input/devices/GamepadDevice.js +466 -466
  1076. package/src/engine/input/devices/ManualInputDevice.js +152 -152
  1077. package/src/engine/input/devices/PointerCoordinates.js +26 -26
  1078. package/src/engine/input/devices/events/GamepadEvents.js +10 -10
  1079. package/src/engine/input/devices/gamepad/GamepadAxes.js +19 -19
  1080. package/src/engine/input/devices/gamepad/GamepadButtons.js +29 -29
  1081. package/src/engine/input/devices/gamepad/GamepadCoordinates.js +17 -17
  1082. package/src/engine/input/devices/gamepad/GamepadDeviceLayout.js +323 -323
  1083. package/src/engine/input/devices/gamepad/GamepadHandle.js +286 -286
  1084. package/src/engine/input/devices/gamepad/GamepadLayout.js +160 -160
  1085. package/src/engine/input/devices/gamepad/GamepadStandardMapping.js +31 -31
  1086. package/src/engine/input/devices/gamepad/GamepadStick.js +169 -169
  1087. package/src/engine/input/devices/gamepad/GamepadStickCalibration.js +119 -119
  1088. package/src/engine/input/devices/gamepad/GamepadStickCalibrator.js +250 -250
  1089. package/src/engine/input/devices/gamepad/gamepad_layout_database.js +144 -144
  1090. package/src/engine/input/devices/gamepad/gamepad_read_hat_axis.js +61 -61
  1091. package/src/engine/input/devices/gamepad/gamepad_write_dpad_vector.js +30 -30
  1092. package/src/engine/input/devices/gamepad/prototypeGamepadTester.js +2124 -2124
  1093. package/src/engine/input/devices/mouse/MouseButtons.js +22 -22
  1094. package/src/engine/input/ecs/components/Input.js +118 -118
  1095. package/src/engine/input/ecs/components/InputController.js +78 -78
  1096. package/src/engine/input/ecs/ism/ISM_DESIGN.md +1523 -1523
  1097. package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +627 -627
  1098. package/src/engine/input/ecs/ism/InputActionEvent.js +40 -40
  1099. package/src/engine/input/ecs/ism/InputBinding.js +71 -71
  1100. package/src/engine/input/ecs/ism/InputCoordinateKind.js +25 -25
  1101. package/src/engine/input/ecs/ism/InputCoordinateSource.js +86 -86
  1102. package/src/engine/input/ecs/ism/InputDirection.js +33 -33
  1103. package/src/engine/input/ecs/ism/InputMapProgram.js +236 -236
  1104. package/src/engine/input/ecs/ism/InputMapSystem.js +976 -976
  1105. package/src/engine/input/ecs/ism/InputOcclusion.js +31 -31
  1106. package/src/engine/input/ecs/ism/InputSource.js +67 -67
  1107. package/src/engine/input/ecs/ism/InputSourceTable.js +107 -107
  1108. package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannel.js +93 -93
  1109. package/src/engine/input/ecs/ism/coordinate/InputCoordinateChannelType.js +11 -11
  1110. package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.js +153 -153
  1111. package/src/engine/input/ecs/ism/coordinate/InputCoordinateSwitches.js +160 -160
  1112. package/src/engine/input/ecs/ism/device/GAMEPAD_INPUT_DEVICE_ID.js +9 -9
  1113. package/src/engine/input/ecs/ism/device/GamepadInputDeviceAdapter.js +88 -88
  1114. package/src/engine/input/ecs/ism/device/InputDeviceAdapter.js +72 -72
  1115. package/src/engine/input/ecs/ism/device/KEYBOARD_INPUT_DEVICE_ID.js +9 -9
  1116. package/src/engine/input/ecs/ism/device/KeyboardInputDeviceAdapter.js +63 -63
  1117. package/src/engine/input/ecs/ism/device/ManualInputDeviceAdapter.js +55 -55
  1118. package/src/engine/input/ecs/ism/device/POINTER_INPUT_DEVICE_ID.js +9 -9
  1119. package/src/engine/input/ecs/ism/device/PointerInputDeviceAdapter.js +160 -160
  1120. package/src/engine/input/ecs/ism/map/InputBinding.js +88 -88
  1121. package/src/engine/input/ecs/ism/map/InputCoordinateBinding.js +102 -102
  1122. package/src/engine/input/ecs/ism/map/InputLayer.js +220 -220
  1123. package/src/engine/input/ecs/ism/map/InputMap.js +331 -331
  1124. package/src/engine/input/ecs/ism/prototypeInputMap.js +309 -309
  1125. package/src/engine/input/ecs/ism/trigger/InputTrigger.js +148 -148
  1126. package/src/engine/input/ecs/ism/trigger/InputTriggerChord.js +173 -173
  1127. package/src/engine/input/ecs/ism/trigger/InputTriggerGamepadButton.js +37 -37
  1128. package/src/engine/input/ecs/ism/trigger/InputTriggerHold.js +176 -176
  1129. package/src/engine/input/ecs/ism/trigger/InputTriggerKey.js +39 -39
  1130. package/src/engine/input/ecs/ism/trigger/InputTriggerMouseButton.js +38 -38
  1131. package/src/engine/input/ecs/ism/trigger/InputTriggerRelease.js +120 -120
  1132. package/src/engine/input/ecs/ism/trigger/InputTriggerSequence.js +315 -315
  1133. package/src/engine/input/ecs/ism/trigger/InputTriggerSwitch.js +105 -105
  1134. package/src/engine/input/ecs/ism/trigger/InputTriggerType.js +17 -17
  1135. package/src/engine/input/ecs/systems/InputControllerSystem.js +253 -253
  1136. package/src/engine/input/ecs/systems/InputSystem.js +162 -162
  1137. package/src/engine/intelligence/behavior/primitive/FailingBehaviorSerializationAdapter.js +25 -25
  1138. package/src/engine/intelligence/behavior/primitive/SucceedingBehaviorSerializationAdapter.js +26 -26
  1139. package/src/engine/intelligence/behavior/util/AsynchronousDelayAction.js +55 -55
  1140. package/src/engine/interpolation/BinaryInterpolationAdapter.js +56 -56
  1141. package/src/engine/interpolation/Interpoland.js +49 -49
  1142. package/src/engine/interpolation/Interpolated.js +149 -149
  1143. package/src/engine/interpolation/PoseInterpolationAdapter.js +61 -61
  1144. package/src/engine/interpolation/TransformPoseSerializationAdapter.js +57 -57
  1145. package/src/engine/interpolation/pose_interpoland.js +27 -27
  1146. package/src/engine/navigation/ecs/path_following/PathFollower.js +222 -222
  1147. package/src/engine/navigation/mesh/NavigationMesh.js +145 -145
  1148. package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +661 -0
  1149. package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +229 -229
  1150. package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.d.ts.map +1 -1
  1151. package/src/engine/navigation/mesh/build/clip_soup_against_overhangs.js +628 -520
  1152. package/src/engine/network/CONGESTION_CONTROL.md +87 -87
  1153. package/src/engine/network/README.md +52 -52
  1154. package/src/engine/network/adapters/QuaternionInterpolationAdapter.js +43 -43
  1155. package/src/engine/network/adapters/TransformInterpolationAdapter.js +84 -84
  1156. package/src/engine/network/adapters/TransformReplicationAdapter.js +87 -87
  1157. package/src/engine/network/adapters/Vector3InterpolationAdapter.js +46 -46
  1158. package/src/engine/network/convertPathToURL.js +2 -2
  1159. package/src/engine/network/core/MalformedPacketError.js +26 -26
  1160. package/src/engine/network/core/quantize/quantize_float.js +73 -73
  1161. package/src/engine/network/core/quantize/quantize_position.js +65 -65
  1162. package/src/engine/network/core/sequence/ack_bitfield.js +77 -77
  1163. package/src/engine/network/core/sequence/seq16.js +69 -69
  1164. package/src/engine/network/core/sequence/seq32.js +73 -73
  1165. package/src/engine/network/ecs/NetworkSystem.js +84 -84
  1166. package/src/engine/network/ecs/components/NetworkIdentity.js +73 -73
  1167. package/src/engine/network/ecs/owner_authorization.js +55 -55
  1168. package/src/engine/network/ecs/serialization/NetworkIdentitySerializationAdapter.js +64 -64
  1169. package/src/engine/network/replication/ScopeFilter.js +71 -71
  1170. package/src/engine/network/sim/ActionLog.js +152 -152
  1171. package/src/engine/network/sim/SimAction.js +273 -273
  1172. package/src/engine/network/sim/Snapshotter.js +222 -222
  1173. package/src/engine/network/state/FrameBufferRing.js +168 -168
  1174. package/src/engine/network/state/InputRing.js +134 -134
  1175. package/src/engine/network/state/PriorityAccumulator.js +180 -180
  1176. package/src/engine/network/time/TimeDilation.js +62 -62
  1177. package/src/engine/network/transport/Channel.js +336 -336
  1178. package/src/engine/network/transport/Transport.js +203 -203
  1179. package/src/engine/network/transport/adapters/NodeUDPTransport.js +186 -186
  1180. package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +105 -105
  1181. package/src/engine/network/transport/fragments/fragment_send.js +147 -147
  1182. package/src/engine/network/transport/fragments/packet_size.js +101 -101
  1183. package/src/engine/network/xhr.js +23 -23
  1184. package/src/engine/physics/BULLET_REVIEW.md +945 -945
  1185. package/src/engine/physics/CANNON_REVIEW.md +1300 -1300
  1186. package/src/engine/physics/CONSTRAINT_SOLVER_BENCH_LOG.md +208 -208
  1187. package/src/engine/physics/CONSTRAINT_SOLVER_IMPROVEMENTS_PLAN.md +364 -364
  1188. package/src/engine/physics/INTEPOLATION_SYSTEM_PLAN.md +287 -287
  1189. package/src/engine/physics/JOLT_REVIEW.md +913 -913
  1190. package/src/engine/physics/PLAN.md +1120 -1094
  1191. package/src/engine/physics/RAPIER_REVIEW.md +934 -934
  1192. package/src/engine/physics/REVIEW_001_ACTION_PLAN.md +642 -642
  1193. package/src/engine/physics/REVIEW_002.md +151 -151
  1194. package/src/engine/physics/REVIEW_003.md +166 -166
  1195. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +97 -97
  1196. package/src/engine/physics/constraint/DofMode.js +35 -35
  1197. package/src/engine/physics/constraint/solve_constraints.js +1 -1
  1198. package/src/engine/physics/contact/combine_material.js +35 -35
  1199. package/src/engine/physics/ecs/BodyKind.js +29 -29
  1200. package/src/engine/physics/ecs/Collider.js +177 -177
  1201. package/src/engine/physics/ecs/ColliderFlags.js +15 -15
  1202. package/src/engine/physics/ecs/ColliderSerializationAdapter.js +37 -37
  1203. package/src/engine/physics/ecs/Joint.js +475 -475
  1204. package/src/engine/physics/ecs/JointSerializationAdapter.js +72 -72
  1205. package/src/engine/physics/ecs/PhysicsSystem.d.ts +3 -0
  1206. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  1207. package/src/engine/physics/ecs/PhysicsSystem.js +7 -2
  1208. package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.js +37 -37
  1209. package/src/engine/physics/ecs/SleepState.js +12 -12
  1210. package/src/engine/physics/ecs/find_non_finite_physics_state.js +76 -76
  1211. package/src/engine/physics/fluid/FluidField.js +867 -867
  1212. package/src/engine/physics/fluid/FluidSimulator.js +832 -832
  1213. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +243 -243
  1214. package/src/engine/physics/fluid/SliceVisualiser.js +190 -190
  1215. package/src/engine/physics/fluid/ecs/FluidComponent.js +239 -239
  1216. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.js +89 -89
  1217. package/src/engine/physics/fluid/ecs/FluidObstacle.js +97 -97
  1218. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.js +348 -348
  1219. package/src/engine/physics/fluid/ecs/FluidSystem.js +142 -142
  1220. package/src/engine/physics/fluid/ecs/FluidWorkerCore.js +123 -123
  1221. package/src/engine/physics/fluid/ecs/WorkerFluidSystem.js +395 -395
  1222. package/src/engine/physics/fluid/ecs/fluid.worker.js +12 -12
  1223. package/src/engine/physics/fluid/ecs/fluid_build_world_to_grid.js +32 -32
  1224. package/src/engine/physics/fluid/ecs/fluid_gather_visible_effectors.js +47 -47
  1225. package/src/engine/physics/fluid/ecs/fluid_reanchor_field.js +85 -85
  1226. package/src/engine/physics/fluid/ecs/fluid_sync_effectors_from_transform.js +16 -16
  1227. package/src/engine/physics/fluid/ecs/fluid_worker_protocol.js +111 -111
  1228. package/src/engine/physics/fluid/ecs/makeFluidWorker.js +18 -18
  1229. package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +81 -81
  1230. package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +202 -202
  1231. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +257 -257
  1232. package/src/engine/physics/fluid/effector/WakeFluidEffector.js +405 -405
  1233. package/src/engine/physics/fluid/prototype.js +126 -126
  1234. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.js +143 -143
  1235. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.js +162 -162
  1236. package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.js +107 -107
  1237. package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.js +131 -131
  1238. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +90 -90
  1239. package/src/engine/physics/fluid/solver/v3_grid_limit8_at_indices.js +38 -38
  1240. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.js +77 -77
  1241. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.js +113 -113
  1242. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.js +92 -92
  1243. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.js +107 -107
  1244. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +135 -135
  1245. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +511 -511
  1246. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +108 -108
  1247. package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.js +317 -317
  1248. package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.js +236 -236
  1249. package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.js +217 -217
  1250. package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.js +174 -174
  1251. package/src/engine/physics/fluid/solver/v3_mac_clip_trace.js +95 -95
  1252. package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.js +77 -77
  1253. package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.js +131 -131
  1254. package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.js +104 -104
  1255. package/src/engine/physics/inertia/world_inverse_inertia.js +160 -160
  1256. package/src/engine/physics/integration/integrate_position.js +97 -97
  1257. package/src/engine/physics/narrowphase/box_box_manifold.js +681 -681
  1258. package/src/engine/physics/narrowphase/box_triangle_contact.js +906 -906
  1259. package/src/engine/physics/narrowphase/capsule_triangle_contact.js +395 -395
  1260. package/src/engine/physics/narrowphase/compute_penetration.js +369 -369
  1261. package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.js +55 -55
  1262. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.js +37 -37
  1263. package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.js +117 -117
  1264. package/src/engine/physics/narrowphase/narrowphase_step.js +1738 -1738
  1265. package/src/engine/physics/narrowphase/reduce_manifold_contacts.js +74 -74
  1266. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts +12 -11
  1267. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -1
  1268. package/src/engine/physics/narrowphase/refine_ray_hit.js +228 -36
  1269. package/src/engine/physics/narrowphase/sphere_sphere_contact.js +52 -52
  1270. package/src/engine/physics/narrowphase/sphere_triangle_contact.js +138 -138
  1271. package/src/engine/physics/persistence/solver_caches.js +309 -309
  1272. package/src/engine/physics/queries/overlap_shape.js +187 -187
  1273. package/src/engine/physics/queries/raycast.d.ts +7 -4
  1274. package/src/engine/physics/queries/raycast.d.ts.map +1 -1
  1275. package/src/engine/physics/queries/raycast.js +11 -5
  1276. package/src/engine/physics/queries/shape_cast.js +417 -417
  1277. package/src/engine/physics/solver/apply_impulse_to_body.js +86 -86
  1278. package/src/engine/physics/solver/friction_cone.js +37 -37
  1279. package/src/engine/physics/solver/solve_contacts.js +1 -1
  1280. package/src/engine/platform/WebEnginePlatform.d.ts.map +1 -1
  1281. package/src/engine/platform/WebEnginePlatform.js +1 -2
  1282. package/src/engine/scene/SerializedScene.d.ts +2 -2
  1283. package/src/engine/scene/SerializedScene.d.ts.map +1 -1
  1284. package/src/engine/scene/transitionToScene.js +121 -121
  1285. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  1286. package/src/engine/simulation/Ticker.js +33 -0
  1287. package/src/engine/sound/ecs/audio/LiveEmitterSet.js +345 -345
  1288. package/src/engine/sound/ecs/audio/SpatialAudioIndex.js +140 -140
  1289. package/src/engine/sound/simulation/AcousticSimulator.js +646 -646
  1290. package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +432 -432
  1291. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +250 -250
  1292. package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +322 -322
  1293. package/src/engine/sound/simulation/README.md +277 -277
  1294. package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +261 -261
  1295. package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +121 -121
  1296. package/src/engine/sound/simulation/configureAcousticSimulation.js +48 -48
  1297. package/src/engine/sound/simulation/core/AcousticMedium.js +113 -113
  1298. package/src/engine/sound/simulation/core/AcousticMediumSerializationAdapter.js +27 -27
  1299. package/src/engine/sound/simulation/core/AcousticOccluderIndex.js +312 -312
  1300. package/src/engine/sound/simulation/core/AcousticRegionIndex.js +159 -159
  1301. package/src/engine/sound/simulation/core/AcousticSolution.js +90 -90
  1302. package/src/engine/sound/simulation/core/AcousticSourceState.js +109 -109
  1303. package/src/engine/sound/simulation/core/AcousticVolumeRegion.js +73 -73
  1304. package/src/engine/sound/simulation/core/OcclusionSolver.js +112 -112
  1305. package/src/engine/sound/simulation/core/RayHit.js +50 -50
  1306. package/src/engine/sound/simulation/core/VolumeField.js +149 -149
  1307. package/src/engine/sound/simulation/definition/AcousticDirectivity.js +114 -114
  1308. package/src/engine/sound/simulation/definition/AcousticDirectivitySerializationAdapter.js +30 -30
  1309. package/src/engine/sound/simulation/definition/AcousticMaterial.js +122 -122
  1310. package/src/engine/sound/simulation/definition/AcousticMaterialSerializationAdapter.js +32 -32
  1311. package/src/engine/sound/simulation/ecs/AcousticBody.js +48 -48
  1312. package/src/engine/sound/simulation/ecs/AcousticBodySerializationAdapter.js +34 -34
  1313. package/src/engine/sound/simulation/ecs/AcousticProbeFieldSystem.js +64 -64
  1314. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +75 -75
  1315. package/src/engine/sound/simulation/ecs/AcousticVolume.js +74 -74
  1316. package/src/engine/sound/simulation/ecs/AcousticVolumeSerializationAdapter.js +37 -37
  1317. package/src/engine/sound/simulation/ecs/AcousticVolumeSystem.js +66 -66
  1318. package/src/engine/sound/simulation/probe/AcousticProbeField.js +578 -578
  1319. package/src/engine/sound/simulation/probe/AcousticProbeFieldSerializationAdapter.js +60 -60
  1320. package/src/engine/sound/simulation/probe/ProbeFieldPathingSolution.js +64 -64
  1321. package/src/engine/sound/simulation/probe/ProbeVisibilityRecheck.js +132 -132
  1322. package/src/engine/sound/simulation/probe/acoustic_probe_transfer.js +103 -103
  1323. package/src/engine/sound/simulation/probe/acoustic_trace_energy.js +136 -136
  1324. package/src/engine/sound/simulation/probe/bakeProbeField.js +169 -169
  1325. package/src/engine/sound/simulation/probe/bakeProbeReflectors.js +110 -110
  1326. package/src/engine/sound/simulation/probe/bakeReverbBands.js +110 -110
  1327. package/src/engine/sound/simulation/probe/bakeVisibility.js +148 -148
  1328. package/src/engine/sound/simulation/probe/echogram_band_rt60.js +83 -83
  1329. package/src/engine/sound/simulation/probe/probe_delaunay_edges.js +215 -215
  1330. package/src/engine/sound/simulation/probe/probe_densify_portals.js +140 -140
  1331. package/src/engine/sound/simulation/probe/probe_detect_portals.js +196 -196
  1332. package/src/engine/sound/simulation/probe/probe_edge_key.js +38 -38
  1333. package/src/engine/sound/simulation/probe/probe_edge_visible.js +41 -41
  1334. package/src/engine/sound/simulation/probe/probe_place_sdf_cover.js +82 -82
  1335. package/src/engine/sound/simulation/probe/probe_refine_connectivity.js +181 -181
  1336. package/src/engine/sound/simulation/probe/probe_sdf_grid.js +171 -171
  1337. package/src/engine/sound/simulation/probe/probe_visibility_augment.js +146 -146
  1338. package/src/engine/sound/simulation/probe/probe_visibility_bridge_components.js +167 -167
  1339. package/src/engine/sound/simulation/render/FoaProbeReverbRenderer.js +354 -354
  1340. package/src/engine/sound/simulation/render/ProbeReverbRenderer.js +231 -231
  1341. package/src/engine/sound/simulation/render/foaReverbImpulseResponse.js +105 -105
  1342. package/src/engine/sound/simulation/render/reverbImpulseResponse.js +66 -66
  1343. package/src/engine/sound/simulation/render/reverb_band_tails.js +93 -93
  1344. package/src/engine/sound/simulation/serialization/populateAcousticSerializationRegistry.js +25 -25
  1345. package/src/engine/sound/sopra/README.md +643 -643
  1346. package/src/engine/sound/sopra/SopraEngine.js +432 -432
  1347. package/src/engine/sound/sopra/asset/AssetManagerBufferProvider.js +71 -71
  1348. package/src/engine/sound/sopra/asset/BufferProvider.js +29 -29
  1349. package/src/engine/sound/sopra/asset/StubBufferProvider.js +58 -58
  1350. package/src/engine/sound/sopra/definition/BusDefinition.js +142 -142
  1351. package/src/engine/sound/sopra/definition/BusDefinitionSerializationAdapter.js +54 -54
  1352. package/src/engine/sound/sopra/definition/DuckingRule.js +106 -106
  1353. package/src/engine/sound/sopra/definition/DuckingRuleSerializationAdapter.js +31 -31
  1354. package/src/engine/sound/sopra/definition/EventDescription.js +262 -262
  1355. package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +55 -55
  1356. package/src/engine/sound/sopra/definition/MixerSnapshot.js +83 -83
  1357. package/src/engine/sound/sopra/definition/MixerSnapshotSerializationAdapter.js +39 -39
  1358. package/src/engine/sound/sopra/definition/ParameterDefinition.js +117 -117
  1359. package/src/engine/sound/sopra/definition/ParameterDefinitionSerializationAdapter.js +31 -31
  1360. package/src/engine/sound/sopra/definition/VoiceStealMode.js +18 -18
  1361. package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.js +109 -109
  1362. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.js +185 -185
  1363. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClipSerializationAdapter.js +59 -59
  1364. package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.js +128 -128
  1365. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.js +226 -226
  1366. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClipSerializationAdapter.js +54 -54
  1367. package/src/engine/sound/sopra/definition/clip/SampleAudioClip.js +191 -191
  1368. package/src/engine/sound/sopra/definition/clip/SampleAudioClipSerializationAdapter.js +39 -39
  1369. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.js +79 -79
  1370. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClipSerializationAdapter.js +42 -42
  1371. package/src/engine/sound/sopra/definition/clip/SilenceAudioClip.js +77 -77
  1372. package/src/engine/sound/sopra/definition/clip/SilenceAudioClipSerializationAdapter.js +27 -27
  1373. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts +5 -0
  1374. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts.map +1 -1
  1375. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.js +125 -125
  1376. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClipSerializationAdapter.js +41 -41
  1377. package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.js +24 -24
  1378. package/src/engine/sound/sopra/definition/effect/CompressorEffect.js +120 -120
  1379. package/src/engine/sound/sopra/definition/effect/CompressorEffectSerializationAdapter.js +31 -31
  1380. package/src/engine/sound/sopra/definition/effect/EqEffect.js +128 -128
  1381. package/src/engine/sound/sopra/definition/effect/EqEffectSerializationAdapter.js +29 -29
  1382. package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +113 -113
  1383. package/src/engine/sound/sopra/definition/effect/ReverbEffectSerializationAdapter.js +25 -25
  1384. package/src/engine/sound/sopra/runtime/BusGraph.js +231 -231
  1385. package/src/engine/sound/sopra/runtime/ParameterStore.js +98 -98
  1386. package/src/engine/sound/sopra/runtime/SopraPlaybackContext.js +68 -68
  1387. package/src/engine/sound/sopra/runtime/Voice.js +145 -145
  1388. package/src/engine/sound/sopra/runtime/VoiceManager.js +136 -136
  1389. package/src/engine/sound/sopra/runtime/VoicePool.js +17 -17
  1390. package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.js +42 -42
  1391. package/src/engine/sound/sopra/serialization/sopraJSON.js +99 -99
  1392. package/src/engine/sound/sopra/serialization/sopraSerializationHarness.js +49 -49
  1393. package/src/engine/sound/sopra/util/MockAudioContext.js +224 -224
  1394. package/src/engine/sound/sopra/util/fadeOutAndStop.js +60 -60
  1395. package/src/engine/ui/DraggableAspect.js +115 -115
  1396. package/src/engine/ui/apply_pointer_tilt_3d.js +50 -50
  1397. package/src/generation/COORDINATES.md +54 -54
  1398. package/src/generation/GridGenerationResource.js +24 -24
  1399. package/src/generation/GridTaskGroup.js +214 -214
  1400. package/src/generation/REVIEW_01_ACTION_PLAN.md +628 -628
  1401. package/src/generation/automata/CaveGeneratorCellularAutomata.js +79 -79
  1402. package/src/generation/automata/CellularAutomata.js +22 -22
  1403. package/src/generation/compute_writes_union.js +25 -25
  1404. package/src/generation/filtering/CellFilter.js +117 -117
  1405. package/src/generation/filtering/core/CellFilterBinaryOperation.js +37 -37
  1406. package/src/generation/filtering/core/CellFilterOperationTertiary.js +43 -43
  1407. package/src/generation/filtering/core/CellFilterUnaryOperation.js +29 -29
  1408. package/src/generation/filtering/numeric/process/computeCellFilterSobel.js +36 -36
  1409. package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.js +42 -42
  1410. package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.js +18 -18
  1411. package/src/generation/filtering/numeric/util/write_cell_filter_to_sampler2d.js +47 -47
  1412. package/src/generation/filtering/util/cell_filter_weights_pick.js +54 -54
  1413. package/src/generation/grid/GridData.js +233 -233
  1414. package/src/generation/grid/coords/grid_to_texel.js +10 -10
  1415. package/src/generation/grid/coords/texel_to_grid.js +10 -10
  1416. package/src/generation/grid/generation/GridTaskApplyActionToCells.js +90 -90
  1417. package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.js +388 -388
  1418. package/src/generation/grid/generation/GridTaskExecuteRuleTimes.js +127 -127
  1419. package/src/generation/grid/generation/GridTaskSequence.js +58 -58
  1420. package/src/generation/grid/generation/NoopGridTaskGenerator.js +12 -12
  1421. package/src/generation/grid/generation/discrete/GridTaskActionRuleSet.js +48 -48
  1422. package/src/generation/grid/generation/discrete/GridTaskCellularAutomata.js +146 -146
  1423. package/src/generation/grid/generation/discrete/GridTaskConnectRooms.js +540 -540
  1424. package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +222 -222
  1425. package/src/generation/grid/generation/grid/GridTaskAddNodesFixed.js +44 -44
  1426. package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +614 -614
  1427. package/src/generation/markers/GridCellActionPlaceMarker.js +244 -244
  1428. package/src/generation/markers/GridCellActionPlaceMarkerGroup.js +86 -86
  1429. package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.js +266 -266
  1430. package/src/generation/markers/emitter/MarkerNodeEmitterGridCellAction.js +49 -49
  1431. package/src/generation/placement/GridCellActionTransformNearbyMarkers.js +120 -120
  1432. package/src/generation/placement/action/GridCellAction.js +45 -45
  1433. package/src/generation/placement/action/GridCellActionPlaceTags.js +140 -140
  1434. package/src/generation/placement/action/GridCellActionWriteFilterToLayer.js +89 -89
  1435. package/src/generation/placement/action/random/CellActionSelectRandom.js +69 -69
  1436. package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.js +91 -91
  1437. package/src/generation/placement/action/util/GridCellActionSequence.js +61 -61
  1438. package/src/generation/placement/action/util/GridCellDisplacedAction.js +61 -61
  1439. package/src/generation/rules/cell/CellMatcherRemovalPreservesConnectivity.js +183 -183
  1440. package/src/generation/theme/ThemeEngine.js +666 -666
  1441. package/src/shade/RENDERER_CONTRACT.md +568 -0
  1442. package/src/shade/descriptor/texture/format/gpu_texture_format_info.js +267 -267
  1443. package/src/shade/device/ShadeDeviceFailure.js +104 -104
  1444. package/src/shade/device/ShadeDeviceFailureReason.js +41 -41
  1445. package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +255 -255
  1446. package/src/shade/device/mock/REVIEW_2026_08_22.md +527 -527
  1447. package/src/shade/device/mock/SoftwareGPUBindGroup.js +23 -23
  1448. package/src/shade/device/mock/SoftwareGPUBindGroupLayout.js +22 -22
  1449. package/src/shade/device/mock/SoftwareGPUError.js +63 -63
  1450. package/src/shade/device/mock/SoftwareGPUPipeline.js +75 -75
  1451. package/src/shade/device/mock/SoftwareGPUQuerySet.js +113 -113
  1452. package/src/shade/device/mock/SoftwareGPUSampler.js +30 -30
  1453. package/src/shade/device/mock/SoftwareGPUShaderModule.js +32 -32
  1454. package/src/shade/device/mock/SoftwareGPUTextureView.js +22 -22
  1455. package/src/shade/device/mock/SoftwareGPUUncapturedErrorEvent.js +23 -23
  1456. package/src/shade/device/mock/normalize_dynamic_offsets.js +26 -26
  1457. package/src/shade/device/mock/texture_copy.js +287 -287
  1458. package/src/shade/device/timing/GPUTimer.js +285 -285
  1459. package/src/shade/device/timing/GPUTimerArray.js +205 -205
  1460. package/src/shade/playground/add_random_lights.js +49 -49
  1461. package/src/shade/playground/add_random_meshes.js +83 -83
  1462. package/src/shade/playground/animation_prototype.js +508 -508
  1463. package/src/shade/playground/animation_prototype_skinning.js +647 -647
  1464. package/src/shade/playground/animation_prototype_stress.js +765 -765
  1465. package/src/shade/playground/enable_picker.js +59 -59
  1466. package/src/shade/playground/gltf_skinned_prototype.js +560 -560
  1467. package/src/shade/playground/gltf_skinned_stress_prototype.js +387 -387
  1468. package/src/shade/playground/gltf_viewer.js +282 -282
  1469. package/src/shade/playground/load_default_environment.js +19 -19
  1470. package/src/shade/playground/main.js +2727 -2727
  1471. package/src/shade/playground/make_animated_instances.js +117 -117
  1472. package/src/shade/playground/prototype_virtual_texture.js +274 -274
  1473. package/src/shade/playground/prototype_volumetrics_01.js +206 -206
  1474. package/src/shade/playground/sample.js +234 -234
  1475. package/src/shade/playground/sample_load_gltf.js +102 -102
  1476. package/src/shade/playground/spread_node3d_grid.js +19 -19
  1477. package/src/shade/renderer/Renderer.js +2436 -2436
  1478. package/src/shade/renderer/ShadeIndirectLightingMode.js +14 -14
  1479. package/src/shade/renderer/animation/ShadeAnimationChannel.js +414 -414
  1480. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.js +531 -531
  1481. package/src/shade/renderer/animation/pose/PosePlayback.js +55 -55
  1482. package/src/shade/renderer/animation/pose/pose_evaluate_local.js +179 -179
  1483. package/src/shade/renderer/animation/pose/pose_evaluate_world.js +76 -76
  1484. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +1024 -1024
  1485. package/src/shade/renderer/animation/skinning/SKINNING_BINDING_STRUCT.js +79 -79
  1486. package/src/shade/renderer/animation/skinning/chunk_skin_blend_mesh_local.js +56 -56
  1487. package/src/shade/renderer/binding/BindGroupManager.js +282 -282
  1488. package/src/shade/renderer/binding/adapt_cache_capacity.js +25 -25
  1489. package/src/shade/renderer/buffer/GPUBufferAllocator.js +116 -116
  1490. package/src/shade/renderer/buffer/buffer_pool_ops.js +123 -123
  1491. package/src/shade/renderer/buffer/table/GPU_DATABASE_PAGE_SIZE.js +9 -9
  1492. package/src/shade/renderer/buffer/table/GPU_DATABASE_UPLOAD_BUFFER_LIMIT.js +8 -8
  1493. package/src/shade/renderer/buffer/table/PageBufferPool.js +71 -71
  1494. package/src/shade/renderer/buffer/table/PageSlotAllocator.js +95 -95
  1495. package/src/shade/renderer/camera/Camera.js +281 -281
  1496. package/src/shade/renderer/camera/GPUCameraContext.js +233 -233
  1497. package/src/shade/renderer/camera/orbital/README.md +84 -84
  1498. package/src/shade/renderer/deferred/shader_composite_volumetrics.js +75 -75
  1499. package/src/shade/renderer/dynamic/DYNAMIC_MESH_VERTEX.js +25 -25
  1500. package/src/shade/renderer/dynamic/GPUDynamicMeshRenderer.js +342 -342
  1501. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +167 -167
  1502. package/src/shade/renderer/dynamic/shader_dynamic_mesh.js +170 -170
  1503. package/src/shade/renderer/extension/FrameContext.js +263 -263
  1504. package/src/shade/renderer/extension/FramePhase.js +104 -104
  1505. package/src/shade/renderer/extension/FrameRecord.js +126 -126
  1506. package/src/shade/renderer/extension/GBufferTextures.js +83 -83
  1507. package/src/shade/renderer/extension/PresentTarget.js +34 -34
  1508. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +918 -918
  1509. package/src/shade/renderer/extension/RenderExtension.js +69 -69
  1510. package/src/shade/renderer/extension/RenderExtensionRegistry.js +319 -319
  1511. package/src/shade/renderer/extension/SceneColor.js +40 -40
  1512. package/src/shade/renderer/extension/ViewTextures.js +78 -78
  1513. package/src/shade/renderer/fow/GPUFogOfWarRenderer.js +182 -182
  1514. package/src/shade/renderer/geometry/Geometry.js +608 -608
  1515. package/src/shade/renderer/geometry/geometry_build_from_meshlet_geometry.js +342 -342
  1516. package/src/shade/renderer/geometry/meshlet_geometry_transfer.js +41 -41
  1517. package/src/shade/renderer/geometry/primitives/make_box_geometry.js +153 -153
  1518. package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.js +240 -240
  1519. package/src/shade/renderer/geometry/primitives/make_plane_geometry.js +145 -145
  1520. package/src/shade/renderer/geometry/primitives/make_polyhedron_geometry.js +327 -327
  1521. package/src/shade/renderer/geometry/primitives/make_torus_geometry.js +107 -107
  1522. package/src/shade/renderer/geometry/primitives/make_torus_knot_geometry.js +165 -165
  1523. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +607 -607
  1524. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +66 -66
  1525. package/src/shade/renderer/geometry/virtual/build/VGeoBuildResult.js +32 -32
  1526. package/src/shade/renderer/geometry/virtual/build/VGeoFaceGraph.js +103 -103
  1527. package/src/shade/renderer/geometry/virtual/build/VGeoGatheredFaces.js +25 -25
  1528. package/src/shade/renderer/geometry/virtual/build/VGeoLevel.js +33 -33
  1529. package/src/shade/renderer/geometry/virtual/build/VGeoLevelOptions.js +62 -62
  1530. package/src/shade/renderer/geometry/virtual/build/VGeoLevelSummary.js +49 -49
  1531. package/src/shade/renderer/geometry/virtual/build/VGeoSubmesh.js +20 -20
  1532. package/src/shade/renderer/geometry/virtual/build/VirtualGeometryMesh.js +214 -214
  1533. package/src/shade/renderer/geometry/virtual/build/gltf/GltfByteSource.js +122 -122
  1534. package/src/shade/renderer/geometry/virtual/build/gltf/GltfCollectReport.js +29 -29
  1535. package/src/shade/renderer/geometry/virtual/build/gltf/GltfDocument.js +210 -210
  1536. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometry.js +48 -48
  1537. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometryInstance.js +25 -25
  1538. package/src/shade/renderer/geometry/virtual/build/gltf/GltfGeometrySelection.js +28 -28
  1539. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_collect_geometries.js +296 -296
  1540. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_open_document.js +166 -166
  1541. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_read_geometry.js +199 -199
  1542. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +173 -173
  1543. package/src/shade/renderer/geometry/virtual/build/vgeo_bounding_sphere.js +28 -28
  1544. package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +200 -200
  1545. package/src/shade/renderer/geometry/virtual/build/vgeo_build_levels.js +1786 -1786
  1546. package/src/shade/renderer/geometry/virtual/build/vgeo_build_page_nodes.js +157 -157
  1547. package/src/shade/renderer/geometry/virtual/build/vgeo_build_root_group.js +26 -26
  1548. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_normals.js +75 -75
  1549. package/src/shade/renderer/geometry/virtual/build/vgeo_compute_vertex_tangents.js +143 -143
  1550. package/src/shade/renderer/geometry/virtual/build/vgeo_containing_sphere.js +44 -44
  1551. package/src/shade/renderer/geometry/virtual/build/vgeo_extract_submesh.js +41 -41
  1552. package/src/shade/renderer/geometry/virtual/build/vgeo_gather_faces.js +71 -71
  1553. package/src/shade/renderer/geometry/virtual/build/vgeo_graph_components.js +123 -123
  1554. package/src/shade/renderer/geometry/virtual/build/vgeo_narrow_indices.js +26 -26
  1555. package/src/shade/renderer/geometry/virtual/build/vgeo_normalize_source.js +112 -112
  1556. package/src/shade/renderer/geometry/virtual/build/vgeo_partition_graph.js +56 -56
  1557. package/src/shade/renderer/geometry/virtual/build/vgeo_sphere_inflate_to_contain.js +70 -70
  1558. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set.js +187 -187
  1559. package/src/shade/renderer/geometry/virtual/build/vgeo_split_face_set_packed.js +207 -207
  1560. package/src/shade/renderer/geometry/virtual/format/VGEO_DEFECT.js +18 -18
  1561. package/src/shade/renderer/geometry/virtual/format/VGeoDefect.js +38 -38
  1562. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +64 -64
  1563. package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTE.js +13 -13
  1564. package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTES.js +50 -50
  1565. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_allocate.js +28 -28
  1566. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attribute_mask.js +23 -23
  1567. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.js +31 -31
  1568. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_copy_vertex.js +32 -32
  1569. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_declare.js +46 -46
  1570. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_like.js +19 -19
  1571. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.js +27 -27
  1572. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_asset_id_preimage.js +62 -62
  1573. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_asset_id.js +13 -13
  1574. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_directory_block_checksum.js +41 -41
  1575. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_frame_checksum.js +41 -41
  1576. package/src/shade/renderer/geometry/virtual/format/checksum/vgeo_compute_header_checksum.js +25 -25
  1577. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_OFFSET.js +20 -20
  1578. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_CLUSTER_RECORD_SIZE.js +5 -5
  1579. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CHILD_REF.js +5 -5
  1580. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_TRIANGLE_COUNT.js +5 -5
  1581. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_MAX_CLUSTER_VERTEX_COUNT.js +5 -5
  1582. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_CHILD.js +5 -5
  1583. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_NO_GROUP.js +5 -5
  1584. package/src/shade/renderer/geometry/virtual/format/cluster/VGEO_SAME_PAGE.js +6 -6
  1585. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryCluster.js +81 -81
  1586. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryGroup.js +37 -37
  1587. package/src/shade/renderer/geometry/virtual/format/dag/VirtualGeometryPageNode.js +55 -55
  1588. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_BLOCK_RECORDS.js +5 -5
  1589. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_FLAG_ROOT_PAGE.js +5 -5
  1590. package/src/shade/renderer/geometry/virtual/format/directory/VGEO_DIRECTORY_RECORD_SIZE.js +5 -5
  1591. package/src/shade/renderer/geometry/virtual/format/directory/vgeo_directory_block_count.js +12 -12
  1592. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_OFFSET.js +11 -11
  1593. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CHILD_TABLE_ENTRY_SIZE.js +5 -5
  1594. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_LZ4.js +11 -11
  1595. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_CODEC_RAW.js +5 -5
  1596. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_ALIGNMENT.js +5 -5
  1597. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_HEADER_SIZE.js +5 -5
  1598. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_FRAME_OFFSET.js +13 -13
  1599. package/src/shade/renderer/geometry/virtual/format/frame/VGEO_PAGE_MAGIC.js +5 -5
  1600. package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameBlob.js +21 -21
  1601. package/src/shade/renderer/geometry/virtual/format/frame/VGeoFrameExtent.js +59 -59
  1602. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_codec_name.js +27 -27
  1603. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_decode_frame_blob.js +84 -84
  1604. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_encode_frame_blob.js +56 -56
  1605. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_frame_decode_bound.js +35 -35
  1606. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_scan_frames.js +74 -74
  1607. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FORMAT_VERSION.js +6 -6
  1608. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HASH_ALGO_XXH3.js +5 -5
  1609. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_OFFSET.js +31 -31
  1610. package/src/shade/renderer/geometry/virtual/format/header/VGEO_HEADER_SIZE.js +5 -5
  1611. package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_OFFSET.js +20 -20
  1612. package/src/shade/renderer/geometry/virtual/format/header/VGEO_LEVEL_RECORD_SIZE.js +9 -9
  1613. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MAGIC.js +5 -5
  1614. package/src/shade/renderer/geometry/virtual/format/header/VGEO_MIN_READER_VERSION.js +5 -5
  1615. package/src/shade/renderer/geometry/virtual/format/header/VGEO_PAYLOAD_ENCODING_SHADE_MESHLET_V1.js +5 -5
  1616. package/src/shade/renderer/geometry/virtual/format/header/VGeoLevelRecord.js +41 -41
  1617. package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_RECORD_SIZE.js +5 -5
  1618. package/src/shade/renderer/geometry/virtual/format/page/VGEO_MAX_GROUP_CLUSTER_COUNT.js +6 -6
  1619. package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_OFFSET.js +21 -21
  1620. package/src/shade/renderer/geometry/virtual/format/page/VGEO_METRIC_SIZE.js +5 -5
  1621. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FANOUT.js +9 -9
  1622. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_FLAG_LEAF.js +5 -5
  1623. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_OFFSET.js +10 -10
  1624. package/src/shade/renderer/geometry/virtual/format/page/VGEO_NODE_RECORD_SIZE.js +5 -5
  1625. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_HEADER_SIZE.js +5 -5
  1626. package/src/shade/renderer/geometry/virtual/format/page/VGEO_PAGE_OFFSET.js +16 -16
  1627. package/src/shade/renderer/geometry/virtual/format/payload/VGEO_ENCODING_FLAGS_MASK.js +6 -6
  1628. package/src/shade/renderer/geometry/virtual/format/payload/VGeoEncodedPayload.js +18 -18
  1629. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.js +200 -200
  1630. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_attribute_offset.js +39 -39
  1631. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_payload_size.js +20 -20
  1632. package/src/shade/renderer/geometry/virtual/format/prototypeVGEOFormatViewer.js +2063 -2063
  1633. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +1622 -1622
  1634. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +485 -485
  1635. package/src/shade/renderer/gpu_primitive/sort/ffx/graph_radix_sort.js +115 -115
  1636. package/src/shade/renderer/gpu_primitive/sort/one_sweep/verify_radix_sort_one_sweep.js +110 -110
  1637. package/src/shade/renderer/light/environment/octahedral_resample_kernel.js +50 -50
  1638. package/src/shade/renderer/light/environment/octahedral_uv_to_direction.js +30 -30
  1639. package/src/shade/renderer/light/environment/resample_cube_to_octahedral.js +157 -157
  1640. package/src/shade/renderer/light/make_sunlight.js +35 -35
  1641. package/src/shade/renderer/light/model/io/light_record_point.js +39 -39
  1642. package/src/shade/renderer/loader/gltf/GLTF_PRIMITIVE_MODE.js +23 -23
  1643. package/src/shade/renderer/loader/gltf/MESHOPT_COMPRESSION_PLAN.md +793 -793
  1644. package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtension.js +54 -54
  1645. package/src/shade/renderer/loader/gltf/ext/GltfBufferViewExtensionSet.js +109 -109
  1646. package/src/shade/renderer/loader/gltf/ext/gltf_apply_buffer_view_extensions.js +69 -69
  1647. package/src/shade/renderer/loader/gltf/ext/gltf_buffer_view_extensions.js +22 -22
  1648. package/src/shade/renderer/loader/gltf/ext/gltf_geometry_extensions.js +39 -39
  1649. package/src/shade/renderer/loader/gltf/ext/meshopt/MeshoptBufferViewExtension.js +301 -301
  1650. package/src/shade/renderer/loader/gltf/gltf_component_type.js +223 -223
  1651. package/src/shade/renderer/loader/gltf/gltf_node_world_matrices.js +137 -137
  1652. package/src/shade/renderer/loader/gltf/gltf_parse_container.js +241 -241
  1653. package/src/shade/renderer/loader/gltf/gltf_read_accessor.js +294 -294
  1654. package/src/shade/renderer/loader/gltf/gltf_used_image_indices.js +49 -49
  1655. package/src/shade/renderer/loader/gltf/load_gltf.js +1253 -1253
  1656. package/src/shade/renderer/loader/gltf/tiny-gltf.js +646 -646
  1657. package/src/shade/renderer/loader/usd/UsdError.js +33 -33
  1658. package/src/shade/renderer/loader/usd/UsdExtensionRegistry.js +69 -69
  1659. package/src/shade/renderer/loader/usd/load_usd.js +226 -226
  1660. package/src/shade/renderer/loader/usd/parse_usda.js +931 -931
  1661. package/src/shade/renderer/loader/usd/unpack_usdz.js +106 -106
  1662. package/src/shade/renderer/loader/usd/usd_build_scene.js +658 -658
  1663. package/src/shade/renderer/loader/usd/usd_compose_transform.js +258 -258
  1664. package/src/shade/renderer/loader/usd/usd_decode_image.js +384 -384
  1665. package/src/shade/renderer/loader/usd/usd_lz4.js +182 -182
  1666. package/src/shade/renderer/loader/usd/usd_triangulate.js +159 -159
  1667. package/src/shade/renderer/material/ShadeMaterial.d.ts +2 -2
  1668. package/src/shade/renderer/material/ShadeMaterial.js +2 -2
  1669. package/src/shade/renderer/material/standard/fragment_gbuffer.js +334 -334
  1670. package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
  1671. package/src/shade/renderer/material/standard/material_gbuffer_vertex.js +45 -45
  1672. package/src/shade/renderer/material/standard_material_to_struct.js +23 -23
  1673. package/src/shade/renderer/particles/prototypeParticleSystem.js +450 -450
  1674. package/src/shade/renderer/particles/runtime/spawn_request_encoding.js +52 -52
  1675. package/src/shade/renderer/pool/TransientResourcePool.js +392 -392
  1676. package/src/shade/renderer/postprocess/bloom/bloom_chain_resolution.js +29 -29
  1677. package/src/shade/renderer/postprocess/bloom/graph_bloom_downsample.js +109 -109
  1678. package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.js +155 -155
  1679. package/src/shade/renderer/postprocess/cas/shader_ffx_rcas.js +114 -114
  1680. package/src/shade/renderer/postprocess/dof/DOF_AUTOFOCUS_PARAMS_STRUCT.js +25 -25
  1681. package/src/shade/renderer/postprocess/dof/DOF_FOCUS_STATE_STRUCT.js +23 -23
  1682. package/src/shade/renderer/postprocess/dof/DOF_PRESETS.js +27 -27
  1683. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_diameter.js +41 -41
  1684. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_band_radius.js +32 -32
  1685. package/src/shade/renderer/postprocess/dof/chunk_dof_coc_coefficient.js +26 -26
  1686. package/src/shade/renderer/postprocess/dof/compute_dof_autofocus_params.js +64 -64
  1687. package/src/shade/renderer/postprocess/dof/compute_dof_uniform.js +54 -54
  1688. package/src/shade/renderer/postprocess/dof/gather/DOF2_CONFIG.js +91 -91
  1689. package/src/shade/renderer/postprocess/dof/gather/DOF2_PRESETS.js +9 -9
  1690. package/src/shade/renderer/postprocess/dof/gather/DOF2_SETTINGS_STRUCT.js +66 -66
  1691. package/src/shade/renderer/postprocess/dof/gather/DOF2_TEXTURE_FORMAT.js +22 -22
  1692. package/src/shade/renderer/postprocess/dof/gather/DepthOfFieldU.js +292 -292
  1693. package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_coc_to_near_far.js +25 -25
  1694. package/src/shade/renderer/postprocess/dof/gather/chunk_dof2_gather_weight.js +30 -30
  1695. package/src/shade/renderer/postprocess/dof/gather/compute_dof2_uniform.js +54 -54
  1696. package/src/shade/renderer/postprocess/dof/gather/graph_postprocess_dof2.js +194 -194
  1697. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_fill.js +68 -68
  1698. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_far.js +140 -140
  1699. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_gather_near.js +142 -142
  1700. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_recombine.js +99 -99
  1701. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_setup.js +102 -102
  1702. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_dilate.js +75 -75
  1703. package/src/shade/renderer/postprocess/dof/gather/shader_dof2_tile_max.js +73 -73
  1704. package/src/shade/renderer/postprocess/dof/raymarch/DOF_SETTINGS_STRUCT.js +49 -49
  1705. package/src/shade/renderer/postprocess/dof/raymarch/DepthOfField.js +298 -298
  1706. package/src/shade/renderer/postprocess/dof/raymarch/graph_postprocess_dof.js +244 -244
  1707. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_composite.js +91 -91
  1708. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_firefly_cleanup.js +61 -61
  1709. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_prefilter.js +90 -90
  1710. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_raymarch_compute.js +267 -267
  1711. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_slice_compute.js +271 -271
  1712. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_dilate.js +70 -70
  1713. package/src/shade/renderer/postprocess/dof/raymarch/shader_dof_tile_max.js +72 -72
  1714. package/src/shade/renderer/postprocess/dof/shader_dof_autofocus.js +99 -99
  1715. package/src/shade/renderer/postprocess/gtao/generate_magic_square_noise.js +51 -51
  1716. package/src/shade/renderer/postprocess/motion_blur/MotionBlur.js +56 -56
  1717. package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +78 -78
  1718. package/src/shade/renderer/postprocess/upscale-dither/UpscaleDither.js +95 -95
  1719. package/src/shade/renderer/postprocess/upscale-dither/fragment_shader_upscale_dither.js +204 -204
  1720. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.js +58 -58
  1721. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +230 -230
  1722. package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.js +278 -278
  1723. package/src/shade/renderer/rasterize/native/oit/chunk_material_side_should_draw.js +26 -26
  1724. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +178 -178
  1725. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +235 -235
  1726. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +208 -208
  1727. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +206 -206
  1728. package/src/shade/renderer/scene/DynamicMesh.js +70 -70
  1729. package/src/shade/renderer/scene/DynamicMeshBatch.js +90 -90
  1730. package/src/shade/renderer/scene/GPUSceneContext.js +901 -901
  1731. package/src/shade/renderer/scene/SceneNodeBinding.js +56 -56
  1732. package/src/shade/renderer/scene/SkinnedMesh.js +55 -55
  1733. package/src/shade/renderer/scene/TransformAuthority.js +33 -33
  1734. package/src/shade/renderer/scene/optimization/deduplicate_geometries.js +38 -38
  1735. package/src/shade/renderer/scene/optimization/deduplicate_images.js +93 -93
  1736. package/src/shade/renderer/scene/optimization/geometry/internal/match_refit_validate.js +127 -127
  1737. package/src/shade/renderer/scene/optimization/geometry/internal/match_solve_transform.js +492 -492
  1738. package/src/shade/renderer/scene/optimization/optimize_texture_set.js +81 -81
  1739. package/src/shade/renderer/scene/optimization/source_to_sampler2d.js +21 -21
  1740. package/src/shade/renderer/scene/serialization/STANDARD_MATERIAL_SERIALIZED_BYTE_SIZE.js +12 -12
  1741. package/src/shade/renderer/shader/chunk/geometry/quaternion/dual/chunk_dual_quat_transform_point.js +26 -26
  1742. package/src/shade/renderer/shader/chunk/noise/chunk_interleaved_gradient_noise.js +20 -20
  1743. package/src/shade/renderer/shader/chunk/spherical_harmonics/dering/chunk_sh2_dering_optimize_positive.js +61 -61
  1744. package/src/shade/renderer/shader/chunk/texture/chunk_texture_filter_fxaa_lite.js +225 -225
  1745. package/src/shade/renderer/shader/chunk/texture/dither/chunk_dither_color_8bit_gradient_noise.js +25 -25
  1746. package/src/shade/renderer/shadow/map/DirectionalLightShadowmap.js +384 -384
  1747. package/src/shade/renderer/shadow/map/PointLightShadowmap.js +105 -105
  1748. package/src/shade/renderer/shadow/map/SpotLightShadowmap.js +63 -63
  1749. package/src/shade/renderer/shadow/map/TetrahedronPointLightShadowmap.js +89 -89
  1750. package/src/shade/renderer/shadow/map/shadowmap_update_score.js +232 -232
  1751. package/src/shade/renderer/texture/GPUTextureAllocator.js +85 -85
  1752. package/src/shade/renderer/texture/texture_pool_ops.js +171 -171
  1753. package/src/shade/renderer/texture/virtual/PageTableQuadAllocator.js +253 -253
  1754. package/src/shade/renderer/texture/virtual/README.md +276 -276
  1755. package/src/shade/renderer/texture/virtual/VTPageTable.js +330 -330
  1756. package/src/shade/renderer/texture/virtual/VTPhysicalCache.js +349 -349
  1757. package/src/shade/renderer/texture/virtual/VT_CONSTANTS.js +154 -154
  1758. package/src/shade/renderer/texture/virtual/VT_STACK_INFO_STRUCT.js +20 -20
  1759. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +1276 -1276
  1760. package/src/shade/renderer/texture/virtual/VirtualTextureStack.js +106 -106
  1761. package/src/shade/renderer/texture/virtual/build_chunk_vt_lookup.js +150 -150
  1762. package/src/shade/renderer/texture/virtual/build_shader_vt_feedback.js +232 -232
  1763. package/src/shade/renderer/texture/virtual/chunk_vt_request_key.js +28 -28
  1764. package/src/shade/renderer/texture/virtual/source/VTSourceImage.js +207 -207
  1765. package/src/shade/renderer/texture/virtual/source/VTSourceProcedural.js +135 -135
  1766. package/src/shade/renderer/texture/virtual/source/VTSourceTiled.js +132 -132
  1767. package/src/shade/renderer/water/GPUWaterRenderer.js +167 -167
  1768. package/src/shade/renderer/water/shader_water.js +246 -246
  1769. package/src/shade/renderer/water/water_height_texture_from_sampler.js +56 -56
  1770. package/src/shade/vitest.setup.mjs +89 -89
  1771. package/src/shade/wgsl/validate_wgsl_source.js +316 -316
  1772. package/src/view/controller/controls/NumericIntervalControl.js +90 -90
  1773. package/src/view/controller/controls/Vector2Control.js +83 -83
  1774. package/src/view/controller/controls/Vector3Control.js +90 -90
  1775. package/src/view/elements/Group.js +56 -56
  1776. package/src/view/elements/drawCheckers.js +33 -33
  1777. package/src/view/elements/windrose/WindRoseDiagram.js +369 -369
  1778. package/src/view/graphics/WebGLContextFailureView.js +76 -76
  1779. package/src/view/layout/DockPanel.js +51 -51
  1780. package/src/view/layout/SplitView.js +365 -365
  1781. package/src/view/layout/show_popup_menu.js +81 -81
  1782. package/src/view/minimap/MinimapCanvasView.js +411 -411
  1783. package/src/view/minimap/MinimapImageCache.js +88 -88
  1784. package/src/view/minimap/MinimapMarkerCollection.d.ts +0 -1
  1785. package/src/view/minimap/MinimapMarkerCollection.d.ts.map +1 -1
  1786. package/src/view/minimap/MinimapMarkerCollection.js +180 -180
  1787. package/src/view/minimap/dom/MinimapCameraView.js +206 -206
  1788. package/src/view/minimap/minimap_focus_area.js +97 -97
  1789. package/editor/process/symbolic/SocketsSymbolicDisplay.js +0 -192
  1790. package/src/core/geom/3d/topology/struct/binary/io/moved_tests.txt +0 -37
  1791. package/src/engine/ecs/attachment/Attachment.d.ts +0 -40
  1792. package/src/engine/ecs/attachment/Attachment.d.ts.map +0 -1
  1793. package/src/engine/ecs/attachment/Attachment.js +0 -57
  1794. package/src/engine/ecs/attachment/AttachmentBinding.d.ts +0 -28
  1795. package/src/engine/ecs/attachment/AttachmentBinding.d.ts.map +0 -1
  1796. package/src/engine/ecs/attachment/AttachmentBinding.js +0 -41
  1797. package/src/engine/ecs/attachment/AttachmentSystem.d.ts +0 -61
  1798. package/src/engine/ecs/attachment/AttachmentSystem.d.ts.map +0 -1
  1799. package/src/engine/ecs/attachment/AttachmentSystem.js +0 -307
  1800. package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts +0 -27
  1801. package/src/engine/ecs/attachment/BoneAttachmentBinding.d.ts.map +0 -1
  1802. package/src/engine/ecs/attachment/BoneAttachmentBinding.js +0 -69
  1803. package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts +0 -4
  1804. package/src/engine/ecs/attachment/TransformAttachmentBinding.d.ts.map +0 -1
  1805. package/src/engine/ecs/attachment/TransformAttachmentBinding.js +0 -51
  1806. package/src/engine/ecs/sockets/AttachmentSocket.d.ts +0 -32
  1807. package/src/engine/ecs/sockets/AttachmentSocket.d.ts.map +0 -1
  1808. package/src/engine/ecs/sockets/AttachmentSocket.js +0 -60
  1809. package/src/engine/ecs/sockets/AttachmentSocketType.d.ts +0 -6
  1810. package/src/engine/ecs/sockets/AttachmentSocketType.d.ts.map +0 -1
  1811. package/src/engine/ecs/sockets/AttachmentSocketType.js +0 -8
  1812. package/src/engine/ecs/sockets/AttachmentSockets.d.ts +0 -57
  1813. package/src/engine/ecs/sockets/AttachmentSockets.d.ts.map +0 -1
  1814. package/src/engine/ecs/sockets/AttachmentSockets.js +0 -130
  1815. package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts +0 -29
  1816. package/src/engine/ecs/sockets/BoneAttachmentSocket.d.ts.map +0 -1
  1817. package/src/engine/ecs/sockets/BoneAttachmentSocket.js +0 -56
  1818. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts +0 -6
  1819. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts.map +0 -1
  1820. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.js +0 -19
  1821. package/src/shade/renderer/animation/_dump_resolve.d.mts +0 -2
  1822. package/src/shade/renderer/animation/_dump_resolve.d.mts.map +0 -1
  1823. 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.