@woosh/meep-engine 3.60.4 → 3.60.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (379) hide show
  1. package/CHANGELOG.md +2602 -0
  2. package/CONTRIBUTING.md +7 -0
  3. package/MIGRATION_2_TO_3.md +136 -0
  4. package/SECURITY.md +4 -0
  5. package/editor/EditorCameraNavigation.d.ts +2 -1
  6. package/editor/EditorCameraNavigation.d.ts.map +1 -1
  7. package/editor/EditorCameraNavigation.js +51 -57
  8. package/package.json +6 -2
  9. package/src/engine/EngineHarness.d.ts +3 -9
  10. package/src/engine/EngineHarness.d.ts.map +1 -1
  11. package/src/engine/EngineHarness.js +6 -8
  12. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts +9 -6
  13. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts.map +1 -1
  14. package/src/engine/graphics/camera/makeOrbitalCameraController.js +44 -71
  15. package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts +64 -0
  16. package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts.map +1 -0
  17. package/src/engine/graphics/camera/orbital/MomentumAxis.js +187 -0
  18. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts +86 -0
  19. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts.map +1 -0
  20. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.js +319 -0
  21. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts +34 -10
  22. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts.map +1 -1
  23. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +116 -30
  24. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts +1 -7
  25. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
  26. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +1 -37
  27. package/src/engine/graphics/ecs/water/Water.d.ts +8 -0
  28. package/src/engine/graphics/ecs/water/Water.d.ts.map +1 -1
  29. package/src/engine/graphics/ecs/water/Water.js +8 -0
  30. package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
  31. package/src/engine/graphics3/WaterSystem.js +731 -734
  32. package/src/engine/graphics3/decal/DecalTileShader.d.ts +61 -0
  33. package/src/engine/graphics3/decal/DecalTileShader.d.ts.map +1 -0
  34. package/src/engine/graphics3/decal/DecalTileShader.js +138 -0
  35. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts +10 -4
  36. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts.map +1 -1
  37. package/src/engine/graphics3/decal/GPUDecalRenderer.js +149 -44
  38. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts +25 -0
  39. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts.map +1 -0
  40. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.js +55 -0
  41. package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts +22 -0
  42. package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts.map +1 -0
  43. package/src/engine/graphics3/decal/graph_gather_decal_tiles.js +70 -0
  44. package/src/engine/graphics3/decal/shader_decal_composite.d.ts +7 -5
  45. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  46. package/src/engine/graphics3/decal/shader_decal_composite.js +48 -44
  47. package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts +12 -0
  48. package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts.map +1 -0
  49. package/src/engine/graphics3/decal/shader_decal_tile_copy.js +78 -0
  50. package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts +11 -0
  51. package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts.map +1 -0
  52. package/src/engine/graphics3/decal/shader_gather_decal_tiles.js +80 -0
  53. package/src/engine/input/devices/mouse/MouseEventButtons.d.ts +13 -0
  54. package/src/engine/input/devices/mouse/MouseEventButtons.d.ts.map +1 -0
  55. package/src/engine/input/devices/mouse/MouseEventButtons.js +23 -0
  56. package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts +4 -0
  57. package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts.map +1 -1
  58. package/src/engine/input/ecs/controllers/KeyboardCameraController.js +9 -45
  59. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  60. package/src/shade/playground/water_refraction/README.md +5 -6
  61. package/src/shade/playground/water_refraction/index.html +1 -1
  62. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  63. package/src/shade/renderer/Renderer.js +7 -5
  64. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts +40 -80
  65. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts.map +1 -1
  66. package/src/shade/renderer/camera/orbital/OrbitalCameraController.js +197 -147
  67. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
  68. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
  69. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
  70. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
  71. package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
  72. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +2 -2
  73. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +2 -2
  74. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts +2 -1
  75. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts.map +1 -1
  76. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js +18 -1
  77. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts +31 -0
  78. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts.map +1 -0
  79. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.js +343 -0
  80. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts +17 -0
  81. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts.map +1 -0
  82. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.js +29 -0
  83. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -1
  84. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +7 -13
  85. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  86. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +1 -8
  87. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts +5 -5
  88. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts.map +1 -1
  89. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.js +10 -10
  90. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +1 -4
  91. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  92. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +1 -10
  93. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts +5 -15
  94. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts.map +1 -1
  95. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.js +6 -34
  96. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
  97. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -7
  98. package/src/shade/renderer/hiz/HZBFootprint.d.ts +14 -0
  99. package/src/shade/renderer/hiz/HZBFootprint.d.ts.map +1 -0
  100. package/src/shade/renderer/hiz/HZBFootprint.js +16 -0
  101. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts +10 -0
  102. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts.map +1 -0
  103. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.js +11 -0
  104. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts +10 -0
  105. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts.map +1 -0
  106. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.js +11 -0
  107. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +0 -7
  108. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  109. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +405 -350
  110. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts +12 -0
  111. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts.map +1 -0
  112. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.js +27 -0
  113. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts +12 -0
  114. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts.map +1 -0
  115. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.js +27 -0
  116. package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts +14 -0
  117. package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts.map +1 -0
  118. package/src/shade/renderer/hiz/hzb_footprint_texels.js +34 -0
  119. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts +0 -5
  120. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
  121. package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +37 -57
  122. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts +11 -0
  123. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts.map +1 -0
  124. package/src/shade/renderer/hiz/{shader_hzb_reduce_mip0_clip.js → shader_hzb_reduce_mip0.js} +120 -111
  125. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  126. package/src/shade/renderer/material/GPUMaterialManager.d.ts +7 -0
  127. package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
  128. package/src/shade/renderer/material/GPUMaterialManager.js +11 -0
  129. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts +12 -12
  130. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
  131. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +17 -118
  132. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
  133. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +7 -2
  134. package/src/shade/renderer/water/GPUWaterRenderer.d.ts +0 -6
  135. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  136. package/src/shade/renderer/water/GPUWaterRenderer.js +12 -17
  137. package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts +35 -0
  138. package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts.map +1 -0
  139. package/src/shade/renderer/water/medium/graph_water_meshlets.js +89 -0
  140. package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
  141. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  142. package/src/shade/renderer/water/shader_water.js +22 -13
  143. package/src/shade/renderer/water/shader_water_avboit.d.ts.map +1 -1
  144. package/src/shade/renderer/water/shader_water_avboit.js +7 -7
  145. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts +1 -1
  146. package/src/shade/renderer/water/surface/graph_water_tessellation.js +1 -1
  147. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +9 -1
  148. package/editor/REWORK_PLAN_2026_08.md +0 -692
  149. package/src/CODEC_LAYOUT_VERIFICATION.md +0 -419
  150. package/src/CORRECTNESS_HUNT_2026_07_24.md +0 -142
  151. package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +0 -738
  152. package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +0 -79
  153. package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +0 -93
  154. package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +0 -80
  155. package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +0 -164
  156. package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +0 -69
  157. package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +0 -110
  158. package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +0 -129
  159. package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +0 -72
  160. package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +0 -74
  161. package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +0 -169
  162. package/src/DUPLICATION_AUDIT_2026_08_07.md +0 -254
  163. package/src/DUPLICATION_AUDIT_REMEDIATION.md +0 -250
  164. package/src/DUPLICATION_REVIEW_2026_10_24.md +0 -1072
  165. package/src/REVIEW_2026_08_06/adv-core.md +0 -511
  166. package/src/REVIEW_2026_08_06/adv-gfx.md +0 -480
  167. package/src/REVIEW_2026_08_06/adv-view.md +0 -446
  168. package/src/REVIEW_2026_08_06/api-core.md +0 -296
  169. package/src/REVIEW_2026_08_06/api-engine.md +0 -195
  170. package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +0 -507
  171. package/src/REVIEW_2026_08_06/core-binary.md +0 -348
  172. package/src/REVIEW_2026_08_06/core-collection.md +0 -376
  173. package/src/REVIEW_2026_08_06/core-math.md +0 -221
  174. package/src/REVIEW_2026_08_06/core-process.md +0 -266
  175. package/src/REVIEW_2026_08_06/core-science.md +0 -223
  176. package/src/REVIEW_2026_08_06/engine-ai-nav.md +0 -279
  177. package/src/REVIEW_2026_08_06/engine-animation.md +0 -167
  178. package/src/REVIEW_2026_08_06/engine-asset.md +0 -166
  179. package/src/REVIEW_2026_08_06/engine-ecs.md +0 -920
  180. package/src/REVIEW_2026_08_06/engine-input.md +0 -197
  181. package/src/REVIEW_2026_08_06/engine-misc.md +0 -248
  182. package/src/REVIEW_2026_08_06/engine-terrain.md +0 -52
  183. package/src/REVIEW_2026_08_06/generation.md +0 -176
  184. package/src/REVIEW_2026_08_06/geom-2d.md +0 -434
  185. package/src/REVIEW_2026_08_06/geom-3d.md +0 -117
  186. package/src/REVIEW_2026_08_06/gfx-gi.md +0 -143
  187. package/src/REVIEW_2026_08_06/gfx-render.md +0 -740
  188. package/src/REVIEW_2026_08_06/gfx-texture.md +0 -690
  189. package/src/REVIEW_2026_08_06/prior-criticals.md +0 -49
  190. package/src/REVIEW_2026_08_06/prior-highs.md +0 -138
  191. package/src/REVIEW_2026_08_06/test-gaps.md +0 -364
  192. package/src/REVIEW_2026_08_06/view.md +0 -667
  193. package/src/REVIEW_2026_08_06.md +0 -610
  194. package/src/core/binary/lz4/LZ4_HIGH_COMPRESSION_PLAN_2026_09_14.md +0 -542
  195. package/src/core/bvh2/bvh3/NOTES.md +0 -2
  196. package/src/core/bvh8/NOTES.md +0 -63
  197. package/src/core/cache/wtinylfu/benchmark/CacheWTinylfu.bench.md +0 -243
  198. package/src/core/color/COLOR_FIX_PLAN_2026_08_28.md +0 -417
  199. package/src/core/color/COLOR_REVIEW_2026_08_28.md +0 -779
  200. package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +0 -433
  201. package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +0 -486
  202. package/src/core/geom/3d/atlas/BFF_PLAN.md +0 -174
  203. package/src/core/geom/3d/atlas/REVIEW_02.md +0 -392
  204. package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +0 -146
  205. package/src/core/geom/3d/gjk/NOTES.md +0 -8
  206. package/src/core/geom/3d/topology/TOPO_MESH_RETIREMENT_PLAN.md +0 -135
  207. package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +0 -381
  208. package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +0 -684
  209. package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +0 -554
  210. package/src/core/model/reactive/evaluation/PREDICATE_APPLICABILITY_PROPOSAL.md +0 -446
  211. package/src/engine/REVIEW_2026_07_03.md +0 -211
  212. package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +0 -815
  213. package/src/engine/control/first-person/DESIGN.md +0 -658
  214. package/src/engine/control/first-person/DESIGN_COLLISION.md +0 -382
  215. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +0 -563
  216. package/src/engine/control/first-person/TODO.md +0 -160
  217. package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +0 -531
  218. package/src/engine/ecs/HIERARCHY_REVIEW.md +0 -717
  219. package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +0 -262
  220. package/src/engine/ecs/ik/PLAN.md +0 -179
  221. package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +0 -272
  222. package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +0 -199
  223. package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +0 -521
  224. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +0 -463
  225. package/src/engine/graphics/ecs/camera/pp/NOTES.md +0 -48
  226. package/src/engine/graphics/render/frame_graph/CORRECTNESS_FIXES_2026_09_04.md +0 -659
  227. package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +0 -235
  228. package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +0 -490
  229. package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +0 -466
  230. package/src/engine/input/GAMEPAD_API_PROPOSAL.md +0 -717
  231. package/src/engine/input/ecs/ism/ISM_DESIGN.md +0 -1523
  232. package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +0 -627
  233. package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +0 -661
  234. package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +0 -229
  235. package/src/engine/network/CONGESTION_CONTROL.md +0 -87
  236. package/src/engine/network/MESSAGE_TRANSPORT.md +0 -364
  237. package/src/engine/network/SMOOTHNESS_DESIGN.md +0 -400
  238. package/src/engine/physics/cloth/MEASUREMENTS.md +0 -5304
  239. package/src/engine/physics/cloth/PLAN.md +0 -3056
  240. package/src/engine/physics/fluid/GPU_FLUID_CASCADES_PROPOSAL_2026_10_16.md +0 -1382
  241. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +0 -243
  242. package/src/engine/physics/fluid/solver/NOTES.md +0 -46
  243. package/src/engine/sound/SOUND_EMITTER_RETIREMENT_PLAN.md +0 -536
  244. package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +0 -432
  245. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +0 -250
  246. package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +0 -322
  247. package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +0 -261
  248. package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +0 -121
  249. package/src/engine/sound/sopra/IMPLEMENTATION_PLAN.md +0 -999
  250. package/src/format/image/avif/DECISIONS.md +0 -545
  251. package/src/format/image/jpeg/NOTES.md +0 -3
  252. package/src/format/scene/gltf/MESHOPT_COMPRESSION_PLAN.md +0 -814
  253. package/src/generation/COORDINATES.md +0 -54
  254. package/src/generation/REVIEW_01_ACTION_PLAN.md +0 -628
  255. package/src/generation/foliage/ANNUAL_SHOOTS_BRIEF_2026_10_25.md +0 -220
  256. package/src/generation/foliage/CROWN_FILLING_BRIEF_2026_10_26.md +0 -172
  257. package/src/generation/foliage/CROWN_FULLNESS_BRIEF_2026_10_26.md +0 -86
  258. package/src/generation/foliage/FOLIAGE_DESIGN.md +0 -547
  259. package/src/generation/foliage/FOLIAGE_PLAN.md +0 -198
  260. package/src/generation/foliage/LEAF_ARCHITECTURE_BRIEF_2026_10_26.md +0 -158
  261. package/src/generation/foliage/LOD_REWORK_BRIEF_2026_10_27.md +0 -521
  262. package/src/generation/foliage/REAL_TIME_TREES_BRIEF_2026_10_27.md +0 -86
  263. package/src/generation/foliage/SELF_ORGANIZING_FRAMEWORK_BRIEF_2026_10_26.md +0 -347
  264. package/src/generation/foliage/SHOOT_SYSTEMS_ALL_SPECIES_BRIEF_2026_10_26.md +0 -248
  265. package/src/generation/foliage/SPEEDTREE_COMPARISON_2026_10_24.md +0 -694
  266. package/src/generation/foliage/TWO_FRONT_ENDS_BRIEF_2026_10_28.md +0 -552
  267. package/src/shade/RENDERER_CONTRACT.md +0 -697
  268. package/src/shade/SHADER_F16_PROPOSAL_2026_10_24.md +0 -263
  269. package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +0 -569
  270. package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +0 -755
  271. package/src/shade/device/mock/EXTENSION_PROPOSAL_2026_08_22.md +0 -458
  272. package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +0 -255
  273. package/src/shade/device/mock/REVIEW_2026_08_22.md +0 -527
  274. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +0 -894
  275. package/src/shade/device/timing/profile/SGPT_FORMAT.md +0 -345
  276. package/src/shade/renderer/NOTES.md +0 -78
  277. package/src/shade/renderer/PLAN.md +0 -8
  278. package/src/shade/renderer/animation/ADDITIVE_BLENDING_PLAN.md +0 -145
  279. package/src/shade/renderer/animation/SKINNING_FRAME_PLAN.md +0 -357
  280. package/src/shade/renderer/atmosphere/NOTES.md +0 -6
  281. package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts +0 -76
  282. package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts.map +0 -1
  283. package/src/shade/renderer/camera/orbital/MomentumAxis.js +0 -164
  284. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts +0 -45
  285. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts.map +0 -1
  286. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.js +0 -66
  287. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts +0 -98
  288. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts.map +0 -1
  289. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.js +0 -184
  290. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts +0 -175
  291. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts.map +0 -1
  292. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.js +0 -411
  293. package/src/shade/renderer/camera/orbital/README.md +0 -81
  294. package/src/shade/renderer/camera/orbital/index.d.ts +0 -6
  295. package/src/shade/renderer/camera/orbital/index.d.ts.map +0 -1
  296. package/src/shade/renderer/camera/orbital/index.js +0 -9
  297. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +0 -964
  298. package/src/shade/renderer/fluid/GPU_FLUID_OCCUPANCY_AND_SOTA_REVIEW_2026_10_26.md +0 -361
  299. package/src/shade/renderer/geometry/bvh/BLAS_REFIT_BATCH_PLAN.md +0 -619
  300. package/src/shade/renderer/geometry/meshlet/COMPACTION_PLAN_2026_09_16.md +0 -674
  301. package/src/shade/renderer/geometry/sdf/NOTES.md +0 -6
  302. package/src/shade/renderer/geometry/virtual/ATTRIBUTE_PLAN_2026_09_18.md +0 -540
  303. package/src/shade/renderer/geometry/virtual/MICRON_COMPARISON_2026_08_20.md +0 -305
  304. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +0 -913
  305. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +0 -787
  306. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +0 -481
  307. package/src/shade/renderer/geometry/virtual/VK_LOD_CLUSTERS_COMPARISON_2026_08_20.md +0 -301
  308. package/src/shade/renderer/geometry/virtual/WEDGE_PLAN_2026_09_18.md +0 -448
  309. package/src/shade/renderer/geometry/virtual/runtime/CULL_PLAN_2026_09_16.md +0 -385
  310. package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +0 -656
  311. package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +0 -308
  312. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +0 -657
  313. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN_2026_09_14.md +0 -551
  314. package/src/shade/renderer/geometry/virtual/runtime/SHADOW_PLAN_2026_09_28.md +0 -529
  315. package/src/shade/renderer/global_illumination/lpv/NOTES.md +0 -3
  316. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +0 -4306
  317. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_RAYS_VARIABLE_AND_SORTED_SCOPE_2026_10_30.md +0 -410
  318. package/src/shade/renderer/global_illumination/sharc/NOTES.md +0 -8
  319. package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +0 -1369
  320. package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +0 -202
  321. package/src/shade/renderer/gpu_primitive/indirect/NOTES.md +0 -94
  322. package/src/shade/renderer/hiz/NOTES.md +0 -3
  323. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts +0 -8
  324. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +0 -1
  325. package/src/shade/renderer/light/cluster/NOTES.md +0 -11
  326. package/src/shade/renderer/light/cluster/PROPOSAL_ALGORITHM_2026_10_16.md +0 -524
  327. package/src/shade/renderer/light/cluster/PROPOSAL_HIERARCHICAL_2026_10_16.md +0 -1101
  328. package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts +0 -24
  329. package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts.map +0 -1
  330. package/src/shade/renderer/material/resident/shader_resident_texture_means.js +0 -120
  331. package/src/shade/renderer/particles/DESIGN.md +0 -1011
  332. package/src/shade/renderer/particles/EMITTER_GLOBAL_STATE_PLAN_2026_10_29.md +0 -280
  333. package/src/shade/renderer/particles/ORIENTATION_PLAN_2026_10_15.md +0 -453
  334. package/src/shade/renderer/path_tracer/PATH_TRACED_MEDIA_PLAN_2026_10_02.md +0 -520
  335. package/src/shade/renderer/postprocess/bloom/NOTES.md +0 -6
  336. package/src/shade/renderer/postprocess/fsr/NOTES.md +0 -4
  337. package/src/shade/renderer/postprocess/gtao/NOTES.md +0 -6
  338. package/src/shade/renderer/postprocess/nss/NOTES.md +0 -332
  339. package/src/shade/renderer/postprocess/perspective/NOTES.md +0 -3
  340. package/src/shade/renderer/postprocess/sscs/NOTES.md +0 -5
  341. package/src/shade/renderer/postprocess/ssr/NOTES.md +0 -14
  342. package/src/shade/renderer/postprocess/ssr/REPROJECTION_PROPOSAL.md +0 -286
  343. package/src/shade/renderer/postprocess/ssr/prefilter/NOTES.md +0 -39
  344. package/src/shade/renderer/postprocess/taa/NOTES.md +0 -11
  345. package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +0 -78
  346. package/src/shade/renderer/postprocess/vrs/NOTES.md +0 -4
  347. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_LEDGER.md +0 -1218
  348. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_PLAN_2026_09_03.md +0 -600
  349. package/src/shade/renderer/restir/reservoir/NOTES.md +0 -6
  350. package/src/shade/renderer/shader/chunk/atmosphere/NOTES.md +0 -6
  351. package/src/shade/renderer/shader/chunk/brdf/FRESNEL_BRIEF_2026_10_16.md +0 -391
  352. package/src/shade/renderer/shader/chunk/color/tonemap/ACES_TONE_MAPPING_BRIEF_2026_10_17.md +0 -153
  353. package/src/shade/renderer/shader/chunk/color/tonemap/HDR_TONE_MAPPING_FORMS_BRIEF_2026_10_16.md +0 -322
  354. package/src/shade/renderer/shader/chunk/color/tonemap/SDR_TONE_MAPPING_BRIEF_2026_10_16.md +0 -247
  355. package/src/shade/renderer/shader/chunk/fsr/NOTES.md +0 -3
  356. package/src/shade/renderer/shader/chunk/fsr/spd/NOTES.md +0 -4
  357. package/src/shade/renderer/shader/chunk/geometry/ray/NOTES.md +0 -4
  358. package/src/shade/renderer/shader/chunk/material/MULTISCATTER.md +0 -159
  359. package/src/shade/renderer/shader/chunk/mboit/NOTES.md +0 -38
  360. package/src/shade/renderer/shader/chunk/spherical_harmonics/l1i/NOTES.md +0 -3
  361. package/src/shade/renderer/shader/chunk/spherical_harmonics/sampling/NOTES.md +0 -8
  362. package/src/shade/renderer/shader/compiler/SHADER_SWITCH_PROPOSAL_2026_10_16.md +0 -927
  363. package/src/shade/renderer/shadow/contact/FINDINGS.md +0 -413
  364. package/src/shade/renderer/shadow/map/csm/NOTES.md +0 -5
  365. package/src/shade/renderer/shadow/ray/NOTES.md +0 -31
  366. package/src/shade/renderer/shadow/sdf/NOTES.md +0 -9
  367. package/src/shade/renderer/shadow/sdf/brixelizer/NOTES.md +0 -5
  368. package/src/shade/renderer/shadow/sdf/cascade/NOTES.md +0 -9
  369. package/src/shade/renderer/shadow/vsm/NOTES.md +0 -12
  370. package/src/shade/renderer/shadow/vsm/PLAN.md +0 -442
  371. package/src/shade/renderer/shadow/vsm/REVIEW_LEDGER.md +0 -43
  372. package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +0 -2444
  373. package/src/shade/renderer/texture/mipmaps/NOTES.md +0 -3
  374. package/src/shade/renderer/volumetrics/NOTES.md +0 -1329
  375. package/src/shade/renderer/volumetrics/VOLUMETRIC_NOISE_PLAN_2026_10_15.md +0 -336
  376. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts +0 -23
  377. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +0 -1
  378. package/src/shade/renderer/water/medium/GPUWaterBodies.js +0 -75
  379. package/src/shade/wgsl/NOTES.md +0 -4
@@ -1,446 +0,0 @@
1
- # Adversarial verification — `view.md` (6 CRITICAL + 26 MAJOR) and `engine-misc.md` (13 MAJOR)
2
-
3
- Method: jest 29.7 with `--config jest.conf.json` from `H:/git/moh`, throwaway `__advcheck_*.spec.js` files
4
- (all deleted afterwards, `find app/src -name "__advcheck*"` shows only other agents' files remaining).
5
- jsdom is available (`jest-environment-jsdom` installed); view specs used `@jest-environment jsdom`.
6
-
7
- Two environment facts established up front, both of which matter for several verdicts:
8
-
9
- - **`assert.*` is LIVE under jest.** Stripping is done only by webpack's `UNASSERT_RULE`, which is pushed
10
- only when `argv.mode === "production"` (`H:/git/moh/webpack.config.js:100-106`). `ENV_PRODUCTION` in
11
- `jest.conf.json` is inert — `core/assert.js` never reads it. So where a finding's failure mode is masked
12
- by an assert under test but exposed in prod, I transcribed the post-unassert code instead of running the
13
- original (VIEW-27).
14
- - **`View` base-class facts** (`H:/git/moh/app/src/mir-engine/meep/src/view/View.js`): `View` **does** define
15
- `addChild` (:365), `removeChild` (:433), `removeAllChildren` (:461), `bindSignal` (:610), `isLinked`
16
- getter (:138) and `children` as a plain array class-field (:107). It does **not** define `update`.
17
- `unlink()` calls `clearFlag(ViewFlags.Linked)` at :325 and only then `this.on.unlinked.send0()` at :347 —
18
- confirmed by execution (`isLinked` observed as `false` inside an `on.unlinked` handler). Every finding that
19
- depends on that ordering is therefore correctly grounded, not an assumption.
20
- `Signal.send0` iterates `handlers.values()` of a `Map` (`core/events/signal/Signal.js:389`), so an entry
21
- deleted mid-dispatch by an earlier handler is skipped, and each handler body is wrapped in `try/catch` +
22
- `console.error` (:405-408) — the "swallowed by Signal" claims are accurate.
23
-
24
- ---
25
-
26
- ## `view.md` — CRITICAL
27
-
28
- ### VIEW-1
29
- - **Verdict**: CONFIRMED
30
- - **Evidence**: Executed. Built a real `DomTooltipManager` over a stub tip manager, called
31
- `mgr.manage(button, factory)` on a real `EmptyView`, instrumented `button.el.addEventListener` /
32
- `removeEventListener`. Link → `added=2`. Unlink via `root.removeChild(button)` → `removed=0`.
33
- Re-link → `added=4`. The `mouseenter`/`mouseleave` pair is never detached and a second observer with a
34
- second pair is created on the next link, exactly as described.
35
- Mechanism verified in source: `DomTooltipManager.manage` (`tooltip/DomTooltipManager.js:109-117`)
36
- subscribes its `on.unlinked` handler *before* `observer.link()` subscribes `__handleViewUnlinked`
37
- (`tooltip/DomTooltipObserver.js:152`), so manage's handler runs first, calls `remove()` → `observer.unlink()`
38
- → guard `if (view.isLinked)` at :159 is false (flag already cleared) → teardown skipped, and
39
- `view.on.unlinked.remove(this.__handleViewUnlinked, this)` at :164 deletes the not-yet-visited Map entry.
40
-
41
- ### VIEW-2
42
- - **Verdict**: CONFIRMED
43
- - **Evidence**: Executed `require('./elements/image/SvgImageView.js')` →
44
- `Cannot find module '../../../core/geom/AABB2.js'`. `ls core/geom/AABB2.js` → no such file;
45
- the real path is `core/geom/2d/aabb/AABB2.js`. Part (b) also holds by reading:
46
- `update()` (`SvgImageView.js:64-68`) references the free identifiers `resize` and `self`, both of which are
47
- declared inside the constructor (`:25`, `:39`); `link()` (:70-73) calls `this.update()` unconditionally.
48
-
49
- ### VIEW-3
50
- - **Verdict**: CONFIRMED (accepted from lead reviewer, not re-checked)
51
-
52
- ### VIEW-4
53
- - **Verdict**: CONFIRMED
54
- - **Evidence**: Executed `MinimapTerrainView.prototype.__setTerrain.call(undefined, terrain, null)` →
55
- `ReferenceError: updatePreview is not defined`. And `.call(undefined, null, terrain)` →
56
- `TypeError: Cannot read properties of null (reading 'preview')`. Source confirms
57
- `updatePreview` is a constructor-local function declaration (`minimap/dom/MinimapTerrainView.js:109`) and the
58
- subscription at :126 is `this.terrain.onChanged.add(this.__setTerrain)` with no context argument.
59
-
60
- ### VIEW-5
61
- - **Verdict**: CONFIRMED (accepted from lead reviewer; independently re-executed anyway)
62
- - **Evidence**: `g.remove(view)` threw `TypeError`; `g.connect(c1); g.connect(c2)` left
63
- `c1.children.length === 2` (duplicate) and `c2.children.length === 1`.
64
-
65
- ### VIEW-6
66
- - **Verdict**: CONFIRMED
67
- - **Evidence**: Executed `MinimapView.prototype.clear.call({__cameraViews:[camA,camB], __worldView})` against a
68
- real `EmptyView` world view already holding both cameras: children went 2 → **4** → **6** across two
69
- `clear()` calls. `minimap/Minimap.js:183-188` is `this.__worldView.addChild(v)` under a
70
- "remove all existing markers" comment, called from `unlink()` at :236 *after* `super.unlink()` (so the
71
- `child is already linked` assert does not fire and even the dev build is affected).
72
-
73
- ---
74
-
75
- ## `view.md` — MAJOR
76
-
77
- ### VIEW-7
78
- - **Verdict**: CONFIRMED
79
- - **Evidence**: `task/TaskProgressView.js:129` reads
80
- `const estimate = Number.isNaN(computedEstimate) ? 0 : computedProgressValue;`. Executed the expression with
81
- `computedProgressValue = 0.2`, `computedEstimate = 48` → `estimate === 0.2`, and `(0.2).toFixed(0) === "0"`,
82
- matching the "0 seconds remaining for the whole load" symptom. The label formatter at :100 is `v.toFixed(0)`.
83
-
84
- ### VIEW-8
85
- - **Verdict**: CONFIRMED
86
- - **Evidence**: `elements/ColorPickerView.js:291-293` is `if (_v !== null) { v.onChanged.remove(...) }`.
87
- Executed a literal transcription over two stub colours: after `handler(b, a)` the **old** value `a` still has
88
- 1 listener and the **new** value `b` has 0. `handler(null, b)` threw `TypeError`.
89
-
90
- ### VIEW-9
91
- - **Verdict**: CONFIRMED
92
- - **Evidence**: `writeLocks` is declared `{h,s,l,a}` at `:156-161`; the `colorV` handler tests and sets
93
- `writeLocks.v` (`:215`, `:224`, `:229`); `modelValueChanged` guards on `h||s||l||a` (`:257`). Executed:
94
- with `writeLocks.v = true`, the `modelValueChanged` guard evaluates to "run" — so the model→gauge writeback
95
- is not suppressed while a V write is in flight, and `rgb2hsv(0,0,0)` snaps H and S to 0.
96
-
97
- ### VIEW-10
98
- - **Verdict**: CONFIRMED
99
- - **Evidence**: Executed a real `Vector1Control` linked under a real parent. `c.model.set(new Vector1(5))` →
100
- number field shows 5. External `v1.set(42)` → model is 42, number field is still **5**.
101
- `controller/controls/Vector1Control.js:67` is `v1.onChanged.add(writeBack)` where `writeBack` is the
102
- controller→model direction; `syncForward` is only called once inside `subscribe`.
103
-
104
- ### VIEW-11
105
- - **Verdict**: CONFIRMED
106
- - **Evidence**: Executed a real `ListController` with a stub `GuiControl` factory. After `list.add(item)` the
107
- container had 1 row; after `list.removeOneOf(item)` it still had **1** row in `children` and 1 node in the
108
- DOM. `controller/controls/ListController.js:69` removes `guiControl`, which is a child of the
109
- `vElementContainer` wrapper created at :48, not of `vContainer`.
110
-
111
- ### VIEW-12
112
- - **Verdict**: CONFIRMED
113
- - **Evidence**: Executed `initializeFromElement` on an `<img class="icon" style="filter:grayscale(1)">`:
114
- `el.style.length === 1` but `key.style.length === 0`. `common/HTMLElementCacheKey.js:201` declares an inner
115
- `let i` shadowing the outer `let i = 0` at :189, so the `splice(i, this.style.length - i)` at :217 truncates
116
- from index 0. The attribute loop at :224 uses `for (i = ...)` without `let`, confirming the intent.
117
-
118
- ### VIEW-13
119
- - **Verdict**: CONFIRMED
120
- - **Evidence**: Executed. `new TabbedView({tabs})` → `children.length === 0`, `el.children.length === 0`,
121
- `hasChild(__panelContainer) === false`, `hasChild(__toggleContainer) === false`. With one tab definition and
122
- the view linked under a document-attached parent, `t.el.outerHTML === "<div></div>"`. Renders nothing,
123
- as claimed. Neither the constructor (`common/TabbedView.js:49-57`) nor `link()` (:60-67) attaches the
124
- containers.
125
-
126
- ### VIEW-14
127
- - **Verdict**: CONFIRMED
128
- - **Evidence**: Executed the `enforceAspectRatio` arithmetic. Viewport 200×100 (vAR 0.5), region 100×100:
129
- result 150×100, ratio **0.667** vs target 0.5. Control on the other branch (region 100×25) → exactly 0.5.
130
- The width branch is not the mirror of the height branch, as claimed
131
- (`minimap/gl/MinimapFogOfWar.js:31-35`).
132
-
133
- ### VIEW-15
134
- - **Verdict**: CONFIRMED
135
- - **Evidence**: Executed a real `ListView` with `filter: e => e.visible` over `[A(visible), C(hidden)]`;
136
- `model.insert(1, B)` produced exactly
137
- `TypeError: Cannot read properties of undefined (reading 'el')` inside `insertOne`, logged and swallowed by
138
- `Signal`, leaving DOM order `[A, B]` with B appended rather than inserted. `common/ListView.js:192-194`
139
- dereferences `getChildByElement(nextElement).el` and `getChildByElement` is `this.viewMapping.get(el)`
140
- (:277-279) on a plain `Map` (:124), so it returns `undefined` for a filtered-out element.
141
-
142
- ### VIEW-16
143
- - **Verdict**: CONFIRMED
144
- - **Evidence**: Executed with a stub `ResizeObserver` that records `observe`/`unobserve`. `attach(a); start();`
145
- → observed `[A]`. `attach(b)` → observed still `[A]`, while `o.element === b`.
146
- `util/DomSizeObserver.js:147-153` assigns before unobserving and never calls `observe`.
147
- Note: the impact requires re-attaching while running — the in-repo `DomTooltipObserver` path always attaches
148
- before `start()` — but `attach()` is public and the described defect is literal.
149
-
150
- ### VIEW-17
151
- - **Verdict**: CONFIRMED
152
- - **Evidence**: `elements/SimpleWindow.js:54-57` captures `anchor` on pointer-down (:66) and never advances it,
153
- while the move handler does `view.size.add(position.clone().sub(anchor))`. Executed the arithmetic for a
154
- 10 px drag delivered as 5 moves → width grew by **30 px**, not 10. The sibling
155
- `elements/BottomLeftResizeHandleView.js` does `lastPosition.copy(position)` each move, confirming intent.
156
-
157
- ### VIEW-18
158
- - **Verdict**: CONFIRMED
159
- - **Evidence**: Executed a real `ToastLogView` with two real `NotificationView`-compatible models.
160
- After 1 notification `children.length === 2`; after 2, `children.length === 4` with positions
161
- `[-48, -48, -0, -0]` — i.e. A at −48 instead of −24, exactly the 24 px gap described.
162
- `elements/notify/ToastLogView.js:47` reassigns `this.children = []` and :72/:74 do both `addChild` and a
163
- manual `push`.
164
-
165
- ### VIEW-19
166
- - **Verdict**: CONFIRMED
167
- - **Evidence**: `grep` over `elements/radial/RadialProgressView.js` returns **no** occurrence of `bindSignal`,
168
- `unlink` or `destroy`. The subscriptions at :59, :64-65, :73, :76 are raw `add` calls on caller-supplied
169
- models with no counterpart anywhere in the class.
170
-
171
- ### VIEW-20
172
- - **Verdict**: CONFIRMED
173
- - **Evidence**: `interaction/createInterfaceCommandButton.js:91-95` adds raw `on.added`/`on.removed`
174
- subscriptions, and :98-99 add the same two handlers again via `button.bindSignal`. Verified the `if` is
175
- always taken: `InteractionCommand`'s constructor unconditionally does `this.features = new List(features)`,
176
- so `interaction.features` is never `undefined`. Nothing removes the raw pair.
177
-
178
- ### VIEW-21
179
- - **Verdict**: CONFIRMED
180
- - **Evidence**: (a) `elements/MeshPreview.js:229-233` attaches a fresh `self.pContents.then(...)` inside
181
- `link()`; `pContents` is created once in the constructor (:107) and settles once, so every subsequent link
182
- runs `__addInteraction` again, which constructs a new `PointerDevice` and calls `start()` (:78-79).
183
- `unlink()` (:257-272) releases only the renderer — no `pointer.stop()`, no handler removal.
184
- (b) `this.camera = null` at :45 and is assigned only inside the async asset callback at :142, while
185
- `__update_renderer_size` (:204-210) guards on `this.renderer !== null` and then writes `this.camera.aspect`.
186
- `this.bindSignal(this.size.onChanged, this.__update_renderer_size, this)` (:206) makes that reachable
187
- post-link, pre-load.
188
-
189
- ### VIEW-22
190
- - **Verdict**: CONFIRMED
191
- - **Evidence**: `renderModel.js:85-92` stores `focus: focus, size: size` by reference and `findInCache`
192
- compares `piece.size.equals(size)` (:24). `common/MeshView.js:61` passes `this.size` / `this.focus` directly.
193
- Executed the aliasing: a cache entry holding the caller's live `Vector2` still matches after the caller
194
- mutates it to a different size. No eviction — `cache.push` is the only mutation of `cache`.
195
-
196
- ### VIEW-23
197
- - **Verdict**: CONFIRMED
198
- - **Evidence**: `common/MeshView.js` contains **zero** occurrences of `model.onChanged` (checked over the file
199
- text). `update()` (:72-78) compares only `size` and `focus` against `renderedParams`, and `link()` binds only
200
- `this.size.onChanged`.
201
-
202
- ### VIEW-24
203
- - **Verdict**: CONFIRMED
204
- - **Evidence**: Executed the exact arithmetic from
205
- `elements/progress/RectangularPieProgressView.js:55-107` for `size 100×50, fraction 0.13` (branch 2, right
206
- edge): `segment2_segment_compute_intersection_array_2d` returned **false**, `p` stayed empty, and the path
207
- string was
208
- `M 50 0 L 50 25 L undefined undefined L 100 50 L 0 50 L 0 0 Z`. Control at 64×64 with the same fraction
209
- returned `true` with a valid point. Confirms the thresholds encode a 45° corner that only exists on squares.
210
- (The report itself notes the single in-repo caller sizes it 64×64.)
211
-
212
- ### VIEW-25
213
- - **Verdict**: CONFIRMED
214
- - **Evidence**: Executed `EmptyView.absolute({css:{width:'100px',backgroundColor:'red'}})` →
215
- `el.style.cssText === "position: absolute; top: 0px; left: 0px;"`; `width` and `backgroundColor` are empty.
216
- `elements/EmptyView.js:62-65` is the shorthand `css: { css, ...CSS_ABSOLUTE_POSITIONING }`.
217
-
218
- ### VIEW-26
219
- - **Verdict**: CONFIRMED
220
- - **Evidence**: `elements/tiles2d/TileGrid.js:134-135` are raw `model.tiles.on.added.add(this.addTile, this)` /
221
- `.on.removed.add(...)`. The file contains **no** `unlink()` override, and `grep` finds **no** occurrence of
222
- `removeTarget` or `removeElement` anywhere in it, while `addTarget` (:307) and `addElement` (:381) are called
223
- per slot / per tile. Confirmed the context does not self-clean: `common/dnd/DragAndDropContext.js` exposes
224
- `removeTarget` (:57) and `removeElement` (:91) as explicit calls with no view-lifecycle hook.
225
- `removeTile` (:411-419) passes the result of `findTileView` straight into `removeChild` and
226
- `__hookTileRemoved`, so `undefined` propagates when the tile is unknown.
227
-
228
- ### VIEW-27
229
- - **Verdict**: CONFIRMED
230
- - **Evidence**: `common/LocalizedLabelView.js:122-154`. The `try` covers only :136; :143
231
- (`localization.locale.getValue()`) and the `$el.text(value)` fallback at :146 are outside it.
232
- Because asserts at :130-131 are stripped in production, I executed a post-unassert transcription:
233
- result `TypeError: Cannot read properties of null (reading 'locale')`, **no** text written to the element,
234
- `needsUpdate` left `true`. Reachability verified: `localization=null` is the constructor default of
235
- `TaskProgressView` (`task/TaskProgressView.js:20`) and is forwarded to the `LocalizedLabelView` at :29-33;
236
- `needsUpdate` is initialised `true` at LocalizedLabelView:57 so the `on.linked` handler at :59-68 calls
237
- `update()` on the first link.
238
-
239
- ### VIEW-28
240
- - **Verdict**: CONFIRMED
241
- - **Evidence**: `minimap/gl/MarkerGL.js:57-87`. `updateIcon` releases `this.patch` **before** awaiting
242
- `atlasManager.acquire`, the continuation does `this.patch = patch;` and only then
243
- `if (!this.active) return;` — the freshly acquired reference is never released on that path.
244
- `this.patch = Reference.NULL` initially (:32) and `shutdown()` (:109-118) sets `active = false` and releases
245
- whatever `this.patch` currently is, which on the racing path is still `Reference.NULL`. The overlapping-call
246
- double-release / overwrite variant follows from the same ordering.
247
-
248
- ### VIEW-29
249
- - **Verdict**: CONFIRMED
250
- - **Evidence**: `common/dnd/DropTarget.js:43` subscribes `attachDropValidityIndicators`' `handleDragEnter` to
251
- `dropTarget.on.enter`; that handler (:72-92) creates a fresh `SignalBinding` and pushes into `current`
252
- unconditionally, while `removeDraggable` (:49-66) removes exactly one record per call. The DOM
253
- `handleDragEnter` (:212-221) pushes into `isInState_ENTER` unconditionally and `handleDragLeave` (:227-236)
254
- does `isInState_ENTER.splice(indexOf(e), 1)` with no `-1` check (`splice(-1,1)` removes the last element).
255
- The double-fire premise is real: `common/dnd/Draggable.js:103-106` explicitly routes `dragEnter` to
256
- `self.parent.__eventHandlers.handleDragEnter(event)` in addition to bubbling.
257
-
258
- ### VIEW-30
259
- - **Verdict**: CONFIRMED
260
- - **Evidence**: Executed `TooltipManager.prototype.buildTipView` against a stub GML with a throwing factory:
261
- the call log was `push,set:false` — `popState()` never ran, leaving `depth === 1` and
262
- `getTooltipsEnabled() === false` permanently. `tooltip/TooltipManager.js:132-138` has no `try/finally`,
263
- whereas `tooltip/gml/GMLEngine.js` uses `try { … } finally { this.popState(); }` in both compile paths.
264
-
265
- ### VIEW-31
266
- - **Verdict**: CONFIRMED
267
- - **Evidence**: `elements/radial/RadialMenu.js:194-223`: `init()` body contains `this.elements = []` and
268
- `this.vElementContainer.addChild(element)` and **no** `removeAllChildren`/`removeChild` (verified by slicing
269
- the method body out of the source and matching). `elements/RadialMenuElement.js:70` is
270
- `this.addChild(description.iconView)`, and `View.addChild` re-parents (`View.js:373-380`:
271
- `child.parent = this; this.el.appendChild(child.el)`), so a shared definition's icon is moved between menus.
272
-
273
- ### VIEW-32
274
- - **Verdict**: CONFIRMED-BUT-DOWNGRADED
275
- - **Corrected severity**: MINOR
276
- - **Evidence**: The mechanism is real and executed:
277
- `"button-" + "cancel all now".replace(' ', '-')` → `"button-cancel-all now"`, and
278
- `classList.add("button-cancel-all now")` throws `InvalidCharacterError` in jsdom.
279
- - **Reason** (ground 5, severity inflation): the trigger needs an option `name` containing **two or more**
280
- spaces. Every in-repo construction site passes single-token names — `engine/ui/GUIEngine.js:264-274`
281
- (`"yes"`, `"no"`) and `:352-357` (`"ok"`). Names with one space work fine. This is a latent public-API
282
- hazard, not a MAJOR-blast-radius defect.
283
-
284
- ---
285
-
286
- ## `engine-misc.md` — MAJOR
287
-
288
- ### EMISC-1
289
- - **Verdict**: CONFIRMED
290
- - **Evidence**: `save/storage/IndexedDBStorage.js:98-128`. `store()` attaches `success`/`error` to the
291
- **request** (`idbRequest.addEventListener('success', …)` at :110) and never holds or listens on the
292
- transaction, so a post-request `abort`/`error` at commit time notifies nobody. `remove` (:45-76) has the same
293
- shape. The file header's `TODO add QuotaExceededError handling` corroborates rather than excuses it.
294
-
295
- ### EMISC-2
296
- - **Verdict**: CONFIRMED
297
- - **Evidence**: Executed.
298
- `new Engine(new InMemoryEnginePlatform(), {enableAudio:false, enableGraphics:false})` → `e.sound === undefined`;
299
- `e.start()` threw synchronously with `TypeError: Cannot read properties of undefined (reading 'start')`.
300
- `Engine.js:584` evaluates `this.sound.start()` while building the `Promise.all` array, whereas the
301
- constructor (:290-302) and `#initialize_audio()` (:421-424) both guard.
302
-
303
- ### EMISC-3
304
- - **Verdict**: CONFIRMED
305
- - **Evidence**: Executed. Same engine with `enableGraphics:false` → `e.graphics === undefined`; `e.render()`
306
- threw `TypeError: Cannot read properties of undefined (reading 'autoDraw')`.
307
- `Engine.js:544` reads `graphics.autoDraw` before the `if (graphics && …)` guard at :549.
308
-
309
- ### EMISC-4
310
- - **Verdict**: CONFIRMED (accepted from lead reviewer; independently re-executed)
311
- - **Evidence**: `await engine.stop()` on a freshly constructed engine threw `Error: Not currently running`
312
- from `Ticker.pause()` (`simulation/Ticker.js:261-263`), before any of the four shutdown steps.
313
- Also verified the supporting claims: `Ticker.#isUpdateLoopActive()` requires both handles
314
- (`Ticker.js:114-116`), `Ticker.start()` discards its first `requestAnimationFrame` handle (:250), and
315
- `Engine.js:616-630` stores no handle for `#animation_frame` so it is never cancellable.
316
-
317
- ### EMISC-5
318
- - **Verdict**: CONFIRMED
319
- - **Evidence**: `Engine.js:607-609` — the second argument to `.then` is
320
- `function (e) { logger.error(...) }`, which returns `undefined`. Executed the same shape:
321
- the resulting promise settles **fulfilled with `undefined`**, and the success branch (ticker start at :599,
322
- options load at :603) is skipped.
323
-
324
- ### EMISC-6
325
- - **Verdict**: CONFIRMED
326
- - **Evidence**: Executed against the real `Clock`. `start(); spin 20ms; pause()` → elapsed 0.0194.
327
- `spin 50ms; pause()` again (already paused) → elapsed 0.0693 — 50 ms injected while stopped.
328
- `Clock.js:87-91` calls the module-level `updateElapsedTime(this)` (:8-13), bypassing the `__isRunning` guard
329
- in `Clock.updateElapsedTime()` (:108-113).
330
- Second instance also executed: a fresh `Clock` (elapsed 0, `__lastMeasurement` 0) after a single `pause()`
331
- reports elapsed **0.9917 s** against `current_time_in_seconds() === 0.9917` — i.e. seconds since page load.
332
- `Ticker`'s constructor does exactly this (`simulation/Ticker.js:71-73`), and `Ticker.start()`'s
333
- `getDelta()`/`clock.start()` do not clear it (both leave `elapsedTime` untouched while `__isRunning` is false).
334
-
335
- ### EMISC-7
336
- - **Verdict**: CONFIRMED
337
- - **Evidence**: `achievements/AchievementManager.js:232-238` — `async initialize(engine)` assigns four fields
338
- and never calls `super.initialize(engine)`; `EnginePlugin.initialize` is what calls
339
- `BaseProcess.initialize()` → `__state.set(Initialized)`. `:421-430` — `async startup()` never calls
340
- `super.startup()`. `save/GameStateLoader.js:15-17` — same omission for `startup()`.
341
- Consequences verified in `plugin/PluginReferenceContext.js`: `navigate_to_running` (:72-89) short-circuits
342
- only on `Running`, so a plugin stuck at `New` re-runs `initialize()` **and** `startup()` on every request;
343
- `navigate_to_finalized` (:44-67) returns immediately for `New`, so `shutdown()` never runs.
344
- `plugin/EnginePluginManager.js:75-101` re-requests the transition whenever
345
- `dependency_state !== ProcessState.Running`, which for these plugins is always.
346
- `loadDefinitions` (:239-255) pushes into `this.entries` with no reset, so a second `startup()` duplicates
347
- every achievement.
348
-
349
- ### EMISC-8
350
- - **Verdict**: CONFIRMED
351
- - **Evidence**: `achievements/AchievementManager.js:427` is `this.initializeGateway();` with no `await`,
352
- followed immediately by `this.isStarted.set(true)` at :429. `initializeGateway` sets
353
- `isGatewayInitialized` only after awaiting the gateway read. `unlock()` (:149-160) gates **both**
354
- `deactivateEntry` and `present` on `this.isGatewayInitialized.getValue()`, so an unlock that lands in the gap
355
- is written to storage and blackboard but never presented and never deactivated. `isActive` is
356
- `ReactiveAnd(isStarted, isBlackboardAttached)` (:106-119), which fires `activate()` synchronously on the
357
- `isStarted` write.
358
-
359
- ### EMISC-9
360
- - **Verdict**: CONFIRMED
361
- - **Evidence**: `EngineHarness.js:126` is `new Promise(async function (resolve, reject) { … })` with no
362
- `try/catch` and no use of `reject` anywhere in the body. Executed the same shape: after a throw past the
363
- first `await`, the outer promise state remained **pending** and jest reported the escape as an unhandled
364
- rejection — precisely the "hangs with no error surfaced" symptom. `this.p` memoises the pending promise
365
- (:167-169), so retries hang too.
366
-
367
- ### EMISC-10
368
- - **Verdict**: CONFIRMED
369
- - **Evidence**: Executed a real `GameStateLoader` with a `gameSaves.update()` that rejects. Neither `resolve`
370
- nor `reject` was called (`outcome: pending` after a full microtask+timer flush), and the rejection surfaced
371
- as an unhandled rejection. `save/GameStateLoader.js:128-135` has no second `then` argument and no `.catch`,
372
- unlike `load()` (:110) and `exists()` (:164).
373
-
374
- ### EMISC-11
375
- - **Verdict**: CONFIRMED
376
- - **Evidence**: Executed a real `GameStateLoader` over a real `InMemoryStorage` with empty
377
- `gameSaves.data`: `load('auto-save', …)` **resolved with `undefined`**.
378
- `save/GameStateLoader.js:101-103` falls through to `legacyLoad` → `Storage.loadBinary` (`save/Storage.js:25-28`)
379
- → `InMemoryStorage.load` (`save/storage/InMemoryStorage.js:15`) which resolves `this.#data.get(key)`.
380
- `IndexedDBStorage.load` (:88-90) resolves `event.target.result` with the same sentinel.
381
-
382
- ### EMISC-12
383
- - **Verdict**: CONFIRMED
384
- - **Evidence**: Executed `WebEnginePlatform.prototype.pickDefaultLocale.call({}, ['ru','de'])` with
385
- `navigator.languages === ['ja-JP']` → returned **`'en-gb'`**, which is not among the options.
386
- `platform/WebEnginePlatform.js:81-85` hard-codes it. Secondary claim also executed: with `[]`,
387
- `array_pick_best_element` returns `undefined` (verified in
388
- `core/collection/array/array_pick_best_element.js:21-23`) and `best.score` threw
389
- `TypeError: Cannot read properties of undefined (reading 'score')`.
390
- `platform/EnginePlatform.js:18-22` documents `@param {string[]} options @returns {string}`, i.e. one of the
391
- options.
392
-
393
- ### EMISC-13
394
- - **Verdict**: CONFIRMED
395
- - **Evidence**: `save/GameStateLoader.js:1` imports
396
- `"../../../../view/game/save/GameSaveStateMetadata.js"`, which resolves to
397
- `app/src/mir-engine/view/game/save/GameSaveStateMetadata.js` — verified to exist and to be **outside** the
398
- `meep/` package root. The symbol is referenced only in a JSDoc `@type` at :82, so the runtime import is
399
- gratuitous. `scene/SerializedScene.js:1` imports
400
- `"../../../../model/game/scenes/MirScene.js"` → `app/src/mir-engine/model/game/scenes/MirScene.js`
401
- (verified to exist), and :57 is `export class SerializedScene extends MirScene`, i.e. a hard inheritance
402
- dependency from the engine onto game code. Both escape the published package boundary.
403
-
404
- ---
405
-
406
- ## Tally
407
-
408
- 45 findings checked (6 CRITICAL + 26 MAJOR from `view.md`, 13 MAJOR from `engine-misc.md`).
409
-
410
- - **CONFIRMED: 44**
411
- - **CONFIRMED-BUT-DOWNGRADED: 1** (VIEW-32, MAJOR → MINOR)
412
- - **REFUTED: 0**
413
-
414
- ## Notes on what I looked for and did not find
415
-
416
- I specifically attempted the following refutations and none succeeded:
417
-
418
- - **Misread base-class members.** Checked `View.js` and `DOM.js` in full. `addChild`/`removeChild`/`isLinked`/
419
- `bindSignal` all exist as the reviewer assumed; `View` genuinely has no `update` (VIEW-39's premise, MINOR);
420
- `View.children` is a plain array so the `this.children = []` reassignments in `ToastLogView`/`Group` really do
421
- produce the described double-registration. No mixin, getter or inherited member rescues any of the
422
- "non-functional" claims.
423
- - **The `unlink()` ordering assumption.** Executed rather than assumed: `isLinked` is `false` inside
424
- `on.unlinked`. VIEW-1's teardown-skip is therefore correctly grounded, not inverted.
425
- - **`assert.*` masking.** The one finding where this mattered (VIEW-27) is *worse* in production, not better,
426
- because the guard that would surface the null localisation is unasserted away. No finding depends on an
427
- assert being live.
428
- - **Unconstructable-class overreach.** `TabbedView`, `ToastLogView`, `ListController`, `Vector1Control`,
429
- `MinimapTerrainView`, `RadialMenu` and `EmptyView` all construct fine in jsdom; the claimed defects are
430
- behavioural, and each was reproduced against a real instance rather than inferred.
431
- - **Deliberate-convention defences.** No comment or JSDoc anywhere in the implicated code documents any of the
432
- reported behaviours as intended. In two cases the codebase's own sibling code proves the opposite intent:
433
- `GMLEngine.compile`'s `try/finally` vs `TooltipManager.buildTipView` (VIEW-30), and
434
- `BottomLeftResizeHandleView`'s `lastPosition.copy(position)` vs `SimpleWindow` (VIEW-17).
435
-
436
- ## Reliability of each report
437
-
438
- **`view.md`**: broadly reliable. All 6 CRITICALs and all 26 MAJORs reproduce; 22 of the 32 were reproduced by
439
- executing real code rather than reading. The only overstatement is VIEW-32's severity. The reviewer's own
440
- "Notes on evidence used" preamble (unlink ordering, Signal Map semantics, segment-intersection miss behaviour)
441
- checked out on every point.
442
-
443
- **`engine-misc.md`**: broadly reliable. All 13 MAJORs reproduce; 8 of them by direct execution against real
444
- `Engine`, `Clock`, `GameStateLoader` and `WebEnginePlatform` instances. No severity inflation identified —
445
- EMISC-13 is a packaging rather than runtime defect but genuinely breaks external consumers of a published
446
- package, so MAJOR is defensible.