@oasys/oecs 0.5.2 → 0.5.4

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 (189) hide show
  1. package/CHANGELOG.md +208 -14
  2. package/README.md +198 -145
  3. package/dist/core/ecs/access_check.d.cts +3 -3
  4. package/dist/core/ecs/access_check.d.ts +3 -3
  5. package/dist/core/ecs/archetype.d.cts +103 -43
  6. package/dist/core/ecs/archetype.d.ts +103 -43
  7. package/dist/core/ecs/archetype.d.ts.map +1 -1
  8. package/dist/core/ecs/archetype_graph.d.cts +8 -8
  9. package/dist/core/ecs/archetype_graph.d.ts +8 -8
  10. package/dist/core/ecs/archetype_graph.d.ts.map +1 -1
  11. package/dist/core/ecs/builtin_relations.d.cts +1 -1
  12. package/dist/core/ecs/builtin_relations.d.ts +1 -1
  13. package/dist/core/ecs/command_log.d.cts +4 -4
  14. package/dist/core/ecs/command_log.d.ts +4 -4
  15. package/dist/core/ecs/command_log.d.ts.map +1 -1
  16. package/dist/core/ecs/component.d.cts +4 -4
  17. package/dist/core/ecs/component.d.ts +4 -4
  18. package/dist/core/ecs/deferred_commands.d.cts +1 -1
  19. package/dist/core/ecs/deferred_commands.d.ts +1 -1
  20. package/dist/core/ecs/deferred_commands.d.ts.map +1 -1
  21. package/dist/core/ecs/ecs.d.cts +85 -43
  22. package/dist/core/ecs/ecs.d.ts +85 -43
  23. package/dist/core/ecs/ecs.d.ts.map +1 -1
  24. package/dist/core/ecs/ecs_memory.d.cts +15 -15
  25. package/dist/core/ecs/ecs_memory.d.ts +15 -15
  26. package/dist/core/ecs/ecs_memory.d.ts.map +1 -1
  27. package/dist/core/ecs/entity_allocator.d.cts +6 -6
  28. package/dist/core/ecs/entity_allocator.d.ts +6 -6
  29. package/dist/core/ecs/entity_allocator.d.ts.map +1 -1
  30. package/dist/core/ecs/event.d.cts +2 -2
  31. package/dist/core/ecs/event.d.ts +2 -2
  32. package/dist/core/ecs/event_registry.d.cts +1 -1
  33. package/dist/core/ecs/event_registry.d.ts +1 -1
  34. package/dist/core/ecs/event_registry.d.ts.map +1 -1
  35. package/dist/core/ecs/facades.d.cts +15 -15
  36. package/dist/core/ecs/facades.d.ts +15 -15
  37. package/dist/core/ecs/facades.d.ts.map +1 -1
  38. package/dist/core/ecs/frame_trace.d.cts +2 -2
  39. package/dist/core/ecs/frame_trace.d.ts +2 -2
  40. package/dist/core/ecs/host_commands.d.cts +12 -12
  41. package/dist/core/ecs/host_commands.d.ts +12 -12
  42. package/dist/core/ecs/host_commands.d.ts.map +1 -1
  43. package/dist/core/ecs/index.d.cts +1 -1
  44. package/dist/core/ecs/index.d.ts +1 -1
  45. package/dist/core/ecs/index.d.ts.map +1 -1
  46. package/dist/core/ecs/observer.d.cts +9 -9
  47. package/dist/core/ecs/observer.d.ts +9 -9
  48. package/dist/core/ecs/observer.d.ts.map +1 -1
  49. package/dist/core/ecs/query.d.cts +91 -70
  50. package/dist/core/ecs/query.d.ts +91 -70
  51. package/dist/core/ecs/query.d.ts.map +1 -1
  52. package/dist/core/ecs/ref.d.cts +53 -1
  53. package/dist/core/ecs/ref.d.ts +53 -1
  54. package/dist/core/ecs/ref.d.ts.map +1 -1
  55. package/dist/core/ecs/relation.d.cts +15 -15
  56. package/dist/core/ecs/relation.d.ts +15 -15
  57. package/dist/core/ecs/relation.d.ts.map +1 -1
  58. package/dist/core/ecs/relation_service.d.cts +14 -14
  59. package/dist/core/ecs/relation_service.d.ts +14 -14
  60. package/dist/core/ecs/relation_service.d.ts.map +1 -1
  61. package/dist/core/ecs/resource.d.cts +1 -1
  62. package/dist/core/ecs/resource.d.ts +1 -1
  63. package/dist/core/ecs/resource_registry.d.cts +2 -2
  64. package/dist/core/ecs/resource_registry.d.ts +2 -2
  65. package/dist/core/ecs/resume.d.cts +3 -3
  66. package/dist/core/ecs/resume.d.ts +3 -3
  67. package/dist/core/ecs/resume.d.ts.map +1 -1
  68. package/dist/core/ecs/schedule.d.cts +22 -9
  69. package/dist/core/ecs/schedule.d.ts +22 -9
  70. package/dist/core/ecs/schedule.d.ts.map +1 -1
  71. package/dist/core/ecs/snapshot_service.d.cts +3 -3
  72. package/dist/core/ecs/snapshot_service.d.ts +3 -3
  73. package/dist/core/ecs/sparse_store.d.cts +6 -6
  74. package/dist/core/ecs/sparse_store.d.ts +6 -6
  75. package/dist/core/ecs/sparse_store.d.ts.map +1 -1
  76. package/dist/core/ecs/store.d.cts +189 -110
  77. package/dist/core/ecs/store.d.ts +189 -110
  78. package/dist/core/ecs/store.d.ts.map +1 -1
  79. package/dist/core/ecs/store_layout_listener.d.cts +2 -2
  80. package/dist/core/ecs/store_layout_listener.d.ts +2 -2
  81. package/dist/core/ecs/system.d.cts +8 -8
  82. package/dist/core/ecs/system.d.ts +8 -8
  83. package/dist/core/ecs/system.d.ts.map +1 -1
  84. package/dist/core/ecs/utils/error.d.cts +7 -0
  85. package/dist/core/ecs/utils/error.d.ts +7 -0
  86. package/dist/core/ecs/utils/error.d.ts.map +1 -1
  87. package/dist/core/store/action_ring.d.cts +7 -8
  88. package/dist/core/store/action_ring.d.ts +7 -8
  89. package/dist/core/store/action_ring.d.ts.map +1 -1
  90. package/dist/core/store/allocator.d.cts +58 -35
  91. package/dist/core/store/allocator.d.ts +58 -35
  92. package/dist/core/store/allocator.d.ts.map +1 -1
  93. package/dist/core/store/buffer_backed_column.d.cts +5 -6
  94. package/dist/core/store/buffer_backed_column.d.ts +5 -6
  95. package/dist/core/store/buffer_backed_column.d.ts.map +1 -1
  96. package/dist/core/store/column_store.d.cts +23 -23
  97. package/dist/core/store/column_store.d.ts +23 -23
  98. package/dist/core/store/column_store.d.ts.map +1 -1
  99. package/dist/core/store/command_dispatch.d.cts +1 -1
  100. package/dist/core/store/command_dispatch.d.ts +1 -1
  101. package/dist/core/store/command_ring.d.cts +6 -7
  102. package/dist/core/store/command_ring.d.ts +6 -7
  103. package/dist/core/store/command_ring.d.ts.map +1 -1
  104. package/dist/core/store/descriptor.d.cts +2 -2
  105. package/dist/core/store/descriptor.d.ts +2 -2
  106. package/dist/core/store/entity_index.d.cts +3 -3
  107. package/dist/core/store/entity_index.d.ts +3 -3
  108. package/dist/core/store/event_ring.d.cts +7 -7
  109. package/dist/core/store/event_ring.d.ts +7 -7
  110. package/dist/core/store/extend.d.cts +2 -2
  111. package/dist/core/store/extend.d.ts +2 -2
  112. package/dist/core/store/extend.d.ts.map +1 -1
  113. package/dist/core/store/grow.d.cts +1 -1
  114. package/dist/core/store/grow.d.ts +1 -1
  115. package/dist/core/store/grow.d.ts.map +1 -1
  116. package/dist/core/store/header.d.cts +9 -9
  117. package/dist/core/store/header.d.ts +9 -9
  118. package/dist/core/store/header.d.ts.map +1 -1
  119. package/dist/core/store/layout_ops.d.cts +25 -7
  120. package/dist/core/store/layout_ops.d.ts +25 -7
  121. package/dist/core/store/layout_ops.d.ts.map +1 -1
  122. package/dist/core/store/state_hash.d.cts +3 -3
  123. package/dist/core/store/state_hash.d.ts +3 -3
  124. package/dist/extensions/editor/editor.d.cts +4 -4
  125. package/dist/extensions/editor/editor.d.ts +4 -4
  126. package/dist/extensions/editor/editor.d.ts.map +1 -1
  127. package/dist/extensions/editor/field_handle.d.cts +1 -1
  128. package/dist/extensions/editor/field_handle.d.ts +1 -1
  129. package/dist/extensions/editor/index.d.cts +2 -2
  130. package/dist/extensions/editor/index.d.ts +2 -2
  131. package/dist/extensions/editor/index.development.js +4 -4
  132. package/dist/extensions/editor/index.js +4 -4
  133. package/dist/extensions/reactive/ecs_sync.d.cts +4 -4
  134. package/dist/extensions/reactive/ecs_sync.d.ts +4 -4
  135. package/dist/extensions/reactive/index.d.cts +4 -4
  136. package/dist/extensions/reactive/index.d.ts +4 -4
  137. package/dist/extensions/reactive/index.development.js +3 -3
  138. package/dist/extensions/reactive/index.js +3 -3
  139. package/dist/extensions/solid/index.d.cts +1 -1
  140. package/dist/extensions/solid/index.d.ts +1 -1
  141. package/dist/extensions/solid/index.development.js +1 -1
  142. package/dist/extensions/solid/index.js +1 -1
  143. package/dist/extensions/solid/kernel_solid.d.cts +1 -1
  144. package/dist/extensions/solid/kernel_solid.d.ts +1 -1
  145. package/dist/extensions/solid/kernel_solid.d.ts.map +1 -1
  146. package/dist/{host_commands-BI8pEmjH.js → host_commands-BlR3oZ3x.js} +473 -393
  147. package/dist/host_commands-C2cpU3yC.cjs +1 -0
  148. package/dist/index.cjs +1 -1
  149. package/dist/index.d.cts +2 -2
  150. package/dist/index.d.ts +2 -2
  151. package/dist/index.d.ts.map +1 -1
  152. package/dist/index.development.cjs +1 -1
  153. package/dist/index.development.js +3345 -2963
  154. package/dist/index.js +1496 -1131
  155. package/dist/{internal-BMDgWZbt.js → internal-BoxWl4dG.js} +410 -330
  156. package/dist/internal-CGBEwfeB.cjs +2 -0
  157. package/dist/internal.cjs +1 -1
  158. package/dist/internal.development.cjs +1 -1
  159. package/dist/internal.development.js +1 -1
  160. package/dist/internal.js +1 -1
  161. package/dist/primitives.development.js +1 -1
  162. package/dist/primitives.js +1 -1
  163. package/dist/reactive/index.d.cts +2 -2
  164. package/dist/reactive/index.d.ts +2 -2
  165. package/dist/reactive/index.development.js +1 -1
  166. package/dist/reactive/index.js +1 -1
  167. package/dist/reactive/kernel.d.cts +5 -5
  168. package/dist/reactive/kernel.d.ts +5 -5
  169. package/dist/reactive/shallow.d.cts +1 -1
  170. package/dist/reactive/shallow.d.ts +1 -1
  171. package/dist/{shallow-DfnAm9vG.js → shallow-Bs39EPh1.js} +1 -1
  172. package/dist/{shallow-9S1pY_Iw.js → shallow-CiFC70Dz.js} +1 -1
  173. package/dist/{shared-BU1Cd40h.js → shared-B4v0L1cw.js} +41 -35
  174. package/dist/shared-DU78k0pU.cjs +1 -0
  175. package/dist/shared.cjs +1 -1
  176. package/dist/shared.d.cts +1 -1
  177. package/dist/shared.d.ts +1 -1
  178. package/dist/shared.development.cjs +1 -1
  179. package/dist/shared.development.js +1 -1
  180. package/dist/shared.js +1 -1
  181. package/dist/type_primitives/typed_arrays/typed_arrays.d.cts +2 -2
  182. package/dist/type_primitives/typed_arrays/typed_arrays.d.ts +2 -2
  183. package/dist/{typed_arrays-BcXcnzB4.js → typed_arrays-DIVwVy5_.js} +1 -1
  184. package/dist/version.d.cts +2 -2
  185. package/dist/version.d.ts +2 -2
  186. package/package.json +1 -1
  187. package/dist/host_commands-CxhpzMx9.cjs +0 -1
  188. package/dist/internal-LiTSB_tG.cjs +0 -2
  189. package/dist/shared-BymrGTyR.cjs +0 -1
@@ -1,4 +1,4 @@
1
- import { D as st, h as j, w as Ne, g as rt } from "./shared-BU1Cd40h.js";
1
+ import { D as st, h as j, w as Ne, g as rt } from "./shared-B4v0L1cw.js";
2
2
  import { S as ot, t as it } from "./topological_sort-DK6EjpWa.js";
3
3
  class Ye extends Error {
4
4
  constructor(e, n, r) {
@@ -29,25 +29,25 @@ function at(t, e) {
29
29
  `Unhandled ${e}: ${String(t)}`
30
30
  );
31
31
  }
32
- var p = /* @__PURE__ */ ((t) => (t.EID_MAX_INDEX_OVERFLOW = "EID_MAX_INDEX_OVERFLOW", t.EID_MAX_GEN_OVERFLOW = "EID_MAX_GEN_OVERFLOW", t.COMPONENT_NOT_REGISTERED = "COMPONENT_NOT_REGISTERED", t.COMPONENT_LIMIT_EXCEEDED = "COMPONENT_LIMIT_EXCEEDED", t.ENTITY_NOT_ALIVE = "ENTITY_NOT_ALIVE", t.CIRCULAR_SYSTEM_DEPENDENCY = "CIRCULAR_SYSTEM_DEPENDENCY", t.DUPLICATE_SYSTEM = "DUPLICATE_SYSTEM", t.ARCHETYPE_NOT_FOUND = "ARCHETYPE_NOT_FOUND", t.RESOURCE_NOT_REGISTERED = "RESOURCE_NOT_REGISTERED", t.RESOURCE_ALREADY_REGISTERED = "RESOURCE_ALREADY_REGISTERED", t.EVENT_ALREADY_REGISTERED = "EVENT_ALREADY_REGISTERED", t.EVENT_NOT_REGISTERED = "EVENT_NOT_REGISTERED", t.FIELD_NOT_REGISTERED = "FIELD_NOT_REGISTERED", t.RELATION_NOT_REGISTERED = "RELATION_NOT_REGISTERED", t.RELATION_MODE_INVALID = "RELATION_MODE_INVALID", t.RELATION_MODE_MISMATCH = "RELATION_MODE_MISMATCH", t.RELATION_CYCLE = "RELATION_CYCLE", t.SPARSE_CACHE_KEY_OVERFLOW = "SPARSE_CACHE_KEY_OVERFLOW", t.SPARSE_QUERY_DENSE_PATH = "SPARSE_QUERY_DENSE_PATH", t.HIERARCHY_ALREADY_SET = "HIERARCHY_ALREADY_SET", t.HIERARCHY_INVALID_MAX_DEPTH = "HIERARCHY_INVALID_MAX_DEPTH", t.OBSERVER_NON_CONVERGENT = "OBSERVER_NON_CONVERGENT", t.OBSERVER_INVALID_CONFIG = "OBSERVER_INVALID_CONFIG", t.OBSERVER_ONSET_EMIT = "OBSERVER_ONSET_EMIT", t.INVALID_FIXED_TIMESTEP = "INVALID_FIXED_TIMESTEP", t.INVALID_MAX_FIXED_STEPS = "INVALID_MAX_FIXED_STEPS", t.INVALID_RECORDER_SCHEDULE = "INVALID_RECORDER_SCHEDULE", t.EMPTY_ARCHETYPE_MATERIALIZE = "EMPTY_ARCHETYPE_MATERIALIZE", t.COMPONENT_INDEX_INVARIANT = "COMPONENT_INDEX_INVARIANT", t.OPTIONAL_TERM_NOT_DECLARED = "OPTIONAL_TERM_NOT_DECLARED", t.QUERY_ACCESS_UNDECLARED = "QUERY_ACCESS_UNDECLARED", t.ACCESS_UNDECLARED = "ACCESS_UNDECLARED", t.QUERY_NOT_SINGLETON = "QUERY_NOT_SINGLETON", t.INVALID_RUN_CONDITION = "INVALID_RUN_CONDITION", t.SYSTEM_FN_ARITY = "SYSTEM_FN_ARITY", t.PARTITION_APPEND_NEEDS_ENTITY_ROW = "PARTITION_APPEND_NEEDS_ENTITY_ROW", t.PARTITION_BULK_INTO_DISABLED = "PARTITION_BULK_INTO_DISABLED", t.ENTITY_NOT_DISABLED = "ENTITY_NOT_DISABLED", t.STRUCTURAL_DURING_ITERATION = "STRUCTURAL_DURING_ITERATION", t.BACKEND_ALREADY_ATTACHED = "BACKEND_ALREADY_ATTACHED", t.DETERMINISM_DISABLED = "DETERMINISM_DISABLED", t.NON_DETERMINISTIC_COLUMN_TYPE = "NON_DETERMINISTIC_COLUMN_TYPE", t.INVALID_MEMORY_OPTIONS = "INVALID_MEMORY_OPTIONS", t.STORE_CAP_EXCEEDED = "STORE_CAP_EXCEEDED", t.REGION_NOT_DECLARED = "REGION_NOT_DECLARED", t.COMMAND_LOG_TAG_COLLISION = "COMMAND_LOG_TAG_COLLISION", t.INVALID_FRAME_STEP = "INVALID_FRAME_STEP", t))(p || {});
33
- class y extends Ye {
32
+ var y = /* @__PURE__ */ ((t) => (t.EID_MAX_INDEX_OVERFLOW = "EID_MAX_INDEX_OVERFLOW", t.EID_MAX_GEN_OVERFLOW = "EID_MAX_GEN_OVERFLOW", t.COMPONENT_NOT_REGISTERED = "COMPONENT_NOT_REGISTERED", t.COMPONENT_LIMIT_EXCEEDED = "COMPONENT_LIMIT_EXCEEDED", t.ENTITY_NOT_ALIVE = "ENTITY_NOT_ALIVE", t.CIRCULAR_SYSTEM_DEPENDENCY = "CIRCULAR_SYSTEM_DEPENDENCY", t.DUPLICATE_SYSTEM = "DUPLICATE_SYSTEM", t.ARCHETYPE_NOT_FOUND = "ARCHETYPE_NOT_FOUND", t.RESOURCE_NOT_REGISTERED = "RESOURCE_NOT_REGISTERED", t.RESOURCE_ALREADY_REGISTERED = "RESOURCE_ALREADY_REGISTERED", t.EVENT_ALREADY_REGISTERED = "EVENT_ALREADY_REGISTERED", t.EVENT_NOT_REGISTERED = "EVENT_NOT_REGISTERED", t.FIELD_NOT_REGISTERED = "FIELD_NOT_REGISTERED", t.RELATION_NOT_REGISTERED = "RELATION_NOT_REGISTERED", t.RELATION_MODE_INVALID = "RELATION_MODE_INVALID", t.RELATION_MODE_MISMATCH = "RELATION_MODE_MISMATCH", t.RELATION_CYCLE = "RELATION_CYCLE", t.SPARSE_CACHE_KEY_OVERFLOW = "SPARSE_CACHE_KEY_OVERFLOW", t.SPARSE_QUERY_DENSE_PATH = "SPARSE_QUERY_DENSE_PATH", t.HIERARCHY_ALREADY_SET = "HIERARCHY_ALREADY_SET", t.HIERARCHY_INVALID_MAX_DEPTH = "HIERARCHY_INVALID_MAX_DEPTH", t.OBSERVER_NON_CONVERGENT = "OBSERVER_NON_CONVERGENT", t.OBSERVER_INVALID_CONFIG = "OBSERVER_INVALID_CONFIG", t.OBSERVER_ONSET_EMIT = "OBSERVER_ONSET_EMIT", t.INVALID_FIXED_TIMESTEP = "INVALID_FIXED_TIMESTEP", t.INVALID_MAX_FIXED_STEPS = "INVALID_MAX_FIXED_STEPS", t.INVALID_RECORDER_SCHEDULE = "INVALID_RECORDER_SCHEDULE", t.EMPTY_ARCHETYPE_MATERIALIZE = "EMPTY_ARCHETYPE_MATERIALIZE", t.COMPONENT_INDEX_INVARIANT = "COMPONENT_INDEX_INVARIANT", t.ARCHETYPE_ROW_INVARIANT = "ARCHETYPE_ROW_INVARIANT", t.OPTIONAL_TERM_NOT_DECLARED = "OPTIONAL_TERM_NOT_DECLARED", t.QUERY_ACCESS_UNDECLARED = "QUERY_ACCESS_UNDECLARED", t.ACCESS_UNDECLARED = "ACCESS_UNDECLARED", t.QUERY_NOT_SINGLETON = "QUERY_NOT_SINGLETON", t.INVALID_RUN_CONDITION = "INVALID_RUN_CONDITION", t.SYSTEM_FN_ARITY = "SYSTEM_FN_ARITY", t.PARTITION_APPEND_NEEDS_ENTITY_ROW = "PARTITION_APPEND_NEEDS_ENTITY_ROW", t.PARTITION_BULK_INTO_DISABLED = "PARTITION_BULK_INTO_DISABLED", t.ENTITY_NOT_DISABLED = "ENTITY_NOT_DISABLED", t.STRUCTURAL_DURING_ITERATION = "STRUCTURAL_DURING_ITERATION", t.BACKEND_ALREADY_ATTACHED = "BACKEND_ALREADY_ATTACHED", t.DETERMINISM_DISABLED = "DETERMINISM_DISABLED", t.NON_DETERMINISTIC_COLUMN_TYPE = "NON_DETERMINISTIC_COLUMN_TYPE", t.INVALID_MEMORY_OPTIONS = "INVALID_MEMORY_OPTIONS", t.STORE_CAP_EXCEEDED = "STORE_CAP_EXCEEDED", t.REGION_NOT_DECLARED = "REGION_NOT_DECLARED", t.COMMAND_LOG_TAG_COLLISION = "COMMAND_LOG_TAG_COLLISION", t.INVALID_FRAME_STEP = "INVALID_FRAME_STEP", t))(y || {});
33
+ class T extends Ye {
34
34
  constructor(e, n, r) {
35
35
  super(n ?? e, !0, r), this.category = e;
36
36
  }
37
37
  }
38
- function bn(t) {
39
- return t instanceof y;
38
+ function Cn(t) {
39
+ return t instanceof T;
40
40
  }
41
- const Cn = -1, vn = -1, Un = Object.freeze(/* @__PURE__ */ Object.create(null)), Ln = 2654435769, Mn = 1367130551, F = 1024, $n = 0, ct = 31, Pn = 1 / 60, xn = 4, dt = 0, z = 20, Ge = (1 << z) - 1, $ = Ge, lt = ct - z, oe = (1 << lt) - 1, Bn = oe, Fn = oe - 1, Re = oe << z | $, kn = (t, e) => {
41
+ const bn = -1, vn = -1, Un = Object.freeze(/* @__PURE__ */ Object.create(null)), Ln = 2654435769, Mn = 1367130551, F = 1024, $n = 0, ct = 31, Pn = 1 / 60, xn = 4, dt = 0, z = 20, He = (1 << z) - 1, $ = He, lt = ct - z, oe = (1 << lt) - 1, Bn = oe, Fn = oe - 1, Re = oe << z | $, kn = (t, e) => {
42
42
  {
43
43
  if (t < 0 || t > $)
44
- throw new y(p.EID_MAX_INDEX_OVERFLOW);
44
+ throw new T(y.EID_MAX_INDEX_OVERFLOW);
45
45
  if (e < 0 || e > oe)
46
- throw new y(p.EID_MAX_GEN_OVERFLOW);
46
+ throw new T(y.EID_MAX_GEN_OVERFLOW);
47
47
  }
48
48
  return e << z | t;
49
- }, L = (t) => t & Ge, De = (t) => t >> z, Yn = (t, e, n) => new y(
50
- p.ENTITY_NOT_ALIVE,
49
+ }, L = (t) => t & He, De = (t) => t >> z, Yn = (t, e, n) => new T(
50
+ y.ENTITY_NOT_ALIVE,
51
51
  `${t}: entity ${e} (index ${L(e)}, generation ${De(
52
52
  e
53
53
  )}) is not alive${n ? ` — ${n}` : ""} (destroyed, never created, or a stale handle; guard with isAlive() first)`,
@@ -56,7 +56,7 @@ const Cn = -1, vn = -1, Un = Object.freeze(/* @__PURE__ */ Object.create(null)),
56
56
  function Vn(t, e) {
57
57
  ge.set(t, e);
58
58
  }
59
- function Gn(t) {
59
+ function Hn(t) {
60
60
  return ge.get(t);
61
61
  }
62
62
  function ut(t) {
@@ -98,7 +98,7 @@ const ft = 827148627, ht = 0, ee = 4, _t = 52, m = {
98
98
  function mt(t, e) {
99
99
  t.setUint32(m.magic, e.magic, !0), t.setUint32(m.sim_abi_version, e.simAbiVersion, !0), t.setUint32(m.view_stamp, e.viewStamp, !0), t.setUint32(m.capacity, e.capacity, !0), t.setUint32(m.archetype_count, e.archetypeCount, !0), t.setUint32(m.layout_descriptor_off, e.layoutDescriptorOff, !0), t.setUint32(m.command_ring_off, e.commandRingOff, !0), t.setUint32(m.action_ring_off, e.actionRingOff, !0), t.setUint32(m.entity_index_off, e.entityIndexOff, !0), t.setUint32(m.event_ring_off, e.eventRingOff, !0), t.setUint32(m.region_table_off, e.regionTableOff, !0), t.setUint32(m.region_table_count, e.regionTableCount, !0), t.setUint32(m.bindings_off, e.bindingsOff, !0);
100
100
  }
101
- function Hn(t) {
101
+ function Gn(t) {
102
102
  return {
103
103
  magic: t.getUint32(m.magic, !0),
104
104
  simAbiVersion: t.getUint32(m.sim_abi_version, !0),
@@ -133,7 +133,7 @@ const E = {
133
133
  [E.i32]: 4,
134
134
  [E.f32]: 4,
135
135
  [E.f64]: 8
136
- }), Xn = {
136
+ }), Wn = {
137
137
  u8: E.u8,
138
138
  i8: E.i8,
139
139
  u16: E.u16,
@@ -155,8 +155,8 @@ function Et(t, e) {
155
155
  stride: t.getUint16(e + O.stride, !0)
156
156
  };
157
157
  }
158
- const Wn = ee * 32;
159
- function He(t) {
158
+ const Xn = ee * 32;
159
+ function Ge(t) {
160
160
  return pe + t * Ee;
161
161
  }
162
162
  function pt(t, e, n) {
@@ -204,24 +204,24 @@ function zn(t, e, n) {
204
204
  let s = e;
205
205
  for (let o = 0; o < n; o++) {
206
206
  const i = yt(t, s);
207
- r[o] = i, s += He(i.columns.length);
207
+ r[o] = i, s += Ge(i.columns.length);
208
208
  }
209
209
  return r;
210
210
  }
211
211
  function At(t) {
212
212
  let e = 0;
213
213
  for (let n = 0; n < t.length; n++)
214
- e += He(t[n].columns.length);
214
+ e += Ge(t[n].columns.length);
215
215
  return e;
216
216
  }
217
- const Xe = 16, P = 16, qn = 256, b = {
217
+ const We = 16, P = 16, qn = 256, C = {
218
218
  write_head: 0,
219
219
  read_head: 4,
220
220
  capacity_slots: 8,
221
221
  overflow_flag: 12
222
222
  }, ye = 0;
223
- function be(t) {
224
- return Xe + t * P;
223
+ function Ce(t) {
224
+ return We + t * P;
225
225
  }
226
226
  function It(t) {
227
227
  return t > 0 && (t & t - 1) === 0;
@@ -236,26 +236,26 @@ function wt(t, e, n) {
236
236
  throw new v(
237
237
  `command ring capacity_slots must be a positive power of two (got ${n})`
238
238
  );
239
- t.setUint32(e + b.write_head, 0, !0), t.setUint32(e + b.read_head, 0, !0), t.setUint32(e + b.capacity_slots, n, !0), t.setUint32(e + b.overflow_flag, 0, !0);
239
+ t.setUint32(e + C.write_head, 0, !0), t.setUint32(e + C.read_head, 0, !0), t.setUint32(e + C.capacity_slots, n, !0), t.setUint32(e + C.overflow_flag, 0, !0);
240
240
  }
241
241
  function St(t, e) {
242
- return t.getUint32(e + b.write_head, !0);
242
+ return t.getUint32(e + C.write_head, !0);
243
243
  }
244
244
  function Nt(t, e) {
245
- return t.getUint32(e + b.read_head, !0);
245
+ return t.getUint32(e + C.read_head, !0);
246
246
  }
247
247
  function Rt(t, e) {
248
- return t.getUint32(e + b.capacity_slots, !0);
248
+ return t.getUint32(e + C.capacity_slots, !0);
249
249
  }
250
250
  function Dt(t, e, n) {
251
251
  if (n.byteLength !== P - 1)
252
252
  throw new v(
253
- `out_payload must be ${P - 1} bytes (got ${n.byteLength})`
253
+ `outPayload must be ${P - 1} bytes (got ${n.byteLength})`
254
254
  );
255
255
  const r = St(t, e), s = Nt(t, e);
256
256
  if (r === s) return ye;
257
- const o = Rt(t, e), i = s & o - 1, a = e + Xe + i * P, c = t.getUint8(a), l = new Uint8Array(t.buffer, a + 1, P - 1);
258
- return n.set(l), t.setUint32(e + b.read_head, s + 1 >>> 0, !0), c;
257
+ const o = Rt(t, e), i = s & o - 1, a = e + We + i * P, c = t.getUint8(a), d = new Uint8Array(t.buffer, a + 1, P - 1);
258
+ return n.set(d), t.setUint32(e + C.read_head, s + 1 >>> 0, !0), c;
259
259
  }
260
260
  function Ot(t, e, n) {
261
261
  let r = 0;
@@ -271,38 +271,38 @@ const ie = 16, R = 12, te = {
271
271
  capacity: 4
272
272
  // 8..16: pad to 16-byte alignment so the i32 arrays start aligned.
273
273
  }, U = 1 << 20;
274
- function Ce(t) {
274
+ function be(t) {
275
275
  if (t < 0 || !Number.isInteger(t))
276
- throw new We(
277
- `entity_index capacity must be a non-negative integer (got ${t})`
276
+ throw new Xe(
277
+ `entity index capacity must be a non-negative integer (got ${t})`
278
278
  );
279
279
  return ie + t * R;
280
280
  }
281
- function bt(t) {
281
+ function Ct(t) {
282
282
  return t + ie;
283
283
  }
284
- function Ct(t, e) {
284
+ function bt(t, e) {
285
285
  return t + ie + e * 4;
286
286
  }
287
287
  function vt(t, e) {
288
288
  return t + ie + e * 8;
289
289
  }
290
- class We extends Error {
290
+ class Xe extends Error {
291
291
  constructor(e) {
292
292
  super(e), this.name = "EntityIndexError";
293
293
  }
294
294
  }
295
295
  function Ut(t, e, n) {
296
296
  if (n < 0 || !Number.isInteger(n))
297
- throw new We(
298
- `entity_index capacity must be a non-negative integer (got ${n})`
297
+ throw new Xe(
298
+ `entity index capacity must be a non-negative integer (got ${n})`
299
299
  );
300
300
  t.setUint32(e + te.length, 0, !0), t.setUint32(e + te.capacity, n, !0);
301
301
  }
302
302
  function jn(t, e, n) {
303
303
  return {
304
- generations: new Int32Array(t, bt(e), n),
305
- archetypes: new Int32Array(t, Ct(e, n), n),
304
+ generations: new Int32Array(t, Ct(e), n),
305
+ archetypes: new Int32Array(t, bt(e, n), n),
306
306
  rows: new Int32Array(t, vt(e, n), n)
307
307
  };
308
308
  }
@@ -335,14 +335,14 @@ const Bt = 16, Ft = 16, Qn = 256, V = {
335
335
  read_head: 4,
336
336
  capacity_slots: 8,
337
337
  overflow_flag: 12
338
- }, kt = V.write_head / 4, Yt = V.read_head / 4, Vt = V.capacity_slots / 4, Gt = V.overflow_flag / 4;
339
- function Ht(t, e) {
338
+ }, kt = V.write_head / 4, Yt = V.read_head / 4, Vt = V.capacity_slots / 4, Ht = V.overflow_flag / 4;
339
+ function Gt(t, e) {
340
340
  return new Int32Array(t.buffer, t.byteOffset + e, 4);
341
341
  }
342
342
  function Ue(t) {
343
343
  return Bt + t * Ft;
344
344
  }
345
- function Xt(t) {
345
+ function Wt(t) {
346
346
  return t > 0 && (t & t - 1) === 0;
347
347
  }
348
348
  class Le extends Error {
@@ -350,28 +350,28 @@ class Le extends Error {
350
350
  super(e), this.name = "ActionRingError";
351
351
  }
352
352
  }
353
- function Wt(t, e, n) {
354
- if (!Xt(n))
353
+ function Xt(t, e, n) {
354
+ if (!Wt(n))
355
355
  throw new Le(
356
356
  `action ring capacity_slots must be a positive power of two (got ${n})`
357
357
  );
358
358
  if ((t.byteOffset + e) % 4 !== 0)
359
359
  throw new Le(
360
- `action ring header must be 4-byte aligned for Atomics (view.byteOffset ${t.byteOffset} + ring_off ${e} is not a multiple of 4)`
360
+ `action ring header must be 4-byte aligned for Atomics (view.byteOffset ${t.byteOffset} + ringOff ${e} is not a multiple of 4)`
361
361
  );
362
- const r = Ht(t, e);
363
- Atomics.store(r, kt, 0), Atomics.store(r, Yt, 0), Atomics.store(r, Vt, n), Atomics.store(r, Gt, 0);
362
+ const r = Gt(t, e);
363
+ Atomics.store(r, kt, 0), Atomics.store(r, Yt, 0), Atomics.store(r, Vt, n), Atomics.store(r, Ht, 0);
364
364
  }
365
365
  const K = [
366
366
  {
367
367
  name: "command_ring",
368
368
  headerOff: "command_ring_off",
369
- sizeFromOptions: (t) => t.commandRingCapacitySlots !== void 0 ? be(t.commandRingCapacitySlots) : 0,
369
+ sizeFromOptions: (t) => t.commandRingCapacitySlots !== void 0 ? Ce(t.commandRingCapacitySlots) : 0,
370
370
  init: (t, e, n) => wt(t, e, n.commandRingCapacitySlots),
371
- regionBytes: (t, e) => be(t.getUint32(e + b.capacity_slots, !0)),
371
+ regionBytes: (t, e) => Ce(t.getUint32(e + C.capacity_slots, !0)),
372
372
  readOptions: (t, e, n) => {
373
373
  n.commandRingCapacitySlots = t.getUint32(
374
- e + b.capacity_slots,
374
+ e + C.capacity_slots,
375
375
  !0
376
376
  );
377
377
  }
@@ -379,9 +379,9 @@ const K = [
379
379
  {
380
380
  name: "entity_index",
381
381
  headerOff: "entity_index_off",
382
- sizeFromOptions: (t) => t.entityIndexCapacity !== void 0 ? Ce(t.entityIndexCapacity) : 0,
382
+ sizeFromOptions: (t) => t.entityIndexCapacity !== void 0 ? be(t.entityIndexCapacity) : 0,
383
383
  init: (t, e, n) => Ut(t, e, n.entityIndexCapacity),
384
- regionBytes: (t, e) => Ce(t.getUint32(e + te.capacity, !0)),
384
+ regionBytes: (t, e) => be(t.getUint32(e + te.capacity, !0)),
385
385
  readOptions: (t, e, n) => {
386
386
  n.entityIndexCapacity = t.getUint32(e + te.capacity, !0);
387
387
  }
@@ -403,7 +403,7 @@ const K = [
403
403
  name: "action_ring",
404
404
  headerOff: "action_ring_off",
405
405
  sizeFromOptions: (t) => t.actionRingCapacitySlots !== void 0 ? Ue(t.actionRingCapacitySlots) : 0,
406
- init: (t, e, n) => Wt(t, e, n.actionRingCapacitySlots),
406
+ init: (t, e, n) => Xt(t, e, n.actionRingCapacitySlots),
407
407
  regionBytes: (t, e) => Ue(t.getUint32(e + V.capacity_slots, !0)),
408
408
  readOptions: (t, e, n) => {
409
409
  n.actionRingCapacitySlots = t.getUint32(
@@ -501,7 +501,7 @@ const Ae = 2 ** 31;
501
501
  class je extends Error {
502
502
  constructor(e) {
503
503
  super(
504
- `SAB column layout offset ${e} reaches or exceeds the 2³¹ (${Ae}-byte) ceiling. Past 2 GiB the signed-32-bit bitwise alignment math wraps to negative/misaligned offsets. This is a structural limit independent of the (default 256 MiB) allocator cap — a single SAB cannot back more than ~2 GiB of column data (#382).`
504
+ `SAB column layout offset ${e} reaches or exceeds the 2³¹ (${Ae}-byte) ceiling. Past 2 GiB the signed-32-bit bitwise alignment math wraps to negative/misaligned offsets. This is a structural limit independent of the (default 256 MiB) allocator cap — a single SAB cannot back more than ~2 GiB of column data.`
505
505
  ), this.name = "StoreLayoutOverflowError";
506
506
  }
507
507
  }
@@ -550,10 +550,10 @@ function Jt(t, e, n = 0) {
550
550
  let o = e + s;
551
551
  const i = new Array(t.length);
552
552
  for (let a = 0; a < t.length; a++) {
553
- const c = t[a], l = new Array(c.columns.length);
554
- for (let d = 0; d < c.columns.length; d++) {
555
- const f = c.columns[d], h = Oe[f.typeTag];
556
- o = Ke(o, h), l[d] = {
553
+ const c = t[a], d = new Array(c.columns.length);
554
+ for (let l = 0; l < c.columns.length; l++) {
555
+ const f = c.columns[l], h = Oe[f.typeTag];
556
+ o = Ke(o, h), d[l] = {
557
557
  componentId: f.componentId,
558
558
  fieldId: f.fieldId,
559
559
  typeTag: f.typeTag,
@@ -567,7 +567,7 @@ function Jt(t, e, n = 0) {
567
567
  rowCount: 0,
568
568
  enabledCount: 0,
569
569
  rowCapacity: c.rowCapacity,
570
- columns: l
570
+ columns: d
571
571
  };
572
572
  }
573
573
  if (o > Ae)
@@ -582,8 +582,8 @@ function ns(t, e = st, n = {}) {
582
582
  const r = {};
583
583
  let s = _t;
584
584
  for (let w = 0; w < K.length; w++) {
585
- const C = K[w], H = C.sizeFromOptions(n);
586
- r[C.headerOff] = H === 0 ? 0 : s, s += H;
585
+ const b = K[w], G = b.sizeFromOptions(n);
586
+ r[b.headerOff] = G === 0 ? 0 : s, s += G;
587
587
  }
588
588
  const o = n.regions ?? [];
589
589
  zt(o);
@@ -591,12 +591,12 @@ function ns(t, e = st, n = {}) {
591
591
  s += ze(i);
592
592
  const c = new Array(i);
593
593
  for (let w = 0; w < o.length; w++) {
594
- const C = o[w];
595
- c[w] = { regionId: C.id, byteOffset: s, byteLength: C.bytes }, s += C.bytes;
594
+ const b = o[w];
595
+ c[w] = { regionId: b.id, byteOffset: s, byteLength: b.bytes }, s += b.bytes;
596
596
  }
597
- const l = n.bindingsRegionBytes ?? 0, d = l === 0 ? 0 : s;
598
- s += l;
599
- const f = s, { descriptors: h, totalBytes: g, regionBytes: A } = Jt(
597
+ const d = n.bindingsRegionBytes ?? 0, l = d === 0 ? 0 : s;
598
+ s += d;
599
+ const f = s, { descriptors: h, totalBytes: g, regionBytes: p } = Jt(
600
600
  t,
601
601
  f,
602
602
  n.reservedDescriptorBytes ?? 0
@@ -607,7 +607,7 @@ function ns(t, e = st, n = {}) {
607
607
  capacity: g,
608
608
  archetypeCount: t.length,
609
609
  layoutDescriptorOff: f,
610
- bindingsOff: d,
610
+ bindingsOff: l,
611
611
  regionTableOff: a,
612
612
  regionTableCount: i,
613
613
  // `regionOffsets` stays keyed by the snake ABI field names (it also indexes
@@ -617,10 +617,10 @@ function ns(t, e = st, n = {}) {
617
617
  eventRingOff: r.event_ring_off,
618
618
  actionRingOff: r.action_ring_off
619
619
  };
620
- mt(_, I), l > 0 && new Uint8Array(u, d, l).fill(0);
620
+ mt(_, I), d > 0 && new Uint8Array(u, l, d).fill(0);
621
621
  for (let w = 0; w < K.length; w++) {
622
- const C = K[w], H = r[C.headerOff];
623
- H !== 0 && C.init(_, H, n);
622
+ const b = K[w], G = r[b.headerOff];
623
+ G !== 0 && b.init(_, G, n);
624
624
  }
625
625
  a !== 0 && jt(_, a, c);
626
626
  for (let w = 0; w < o.length; w++)
@@ -632,10 +632,10 @@ function ns(t, e = st, n = {}) {
632
632
  view: _,
633
633
  header: I,
634
634
  archetypes: B,
635
- _regionBytes: A,
635
+ _regionBytes: p,
636
636
  _allocator: e,
637
637
  // Carry the headroom policy with the store so the realloc slow path
638
- // (`optionsFromOld`) can re-reserve the same margin (#541).
638
+ // (`optionsFromOld`) can re-reserve the same margin.
639
639
  _reservedDescriptorBytes: n.reservedDescriptorBytes ?? 0
640
640
  };
641
641
  }
@@ -644,7 +644,7 @@ function en(t, e) {
644
644
  for (let r = 0; r < e.length; r++) {
645
645
  const s = e[r], o = new Array(s.columns.length), i = /* @__PURE__ */ new Map();
646
646
  for (let a = 0; a < s.columns.length; a++) {
647
- const c = s.columns[a], l = {
647
+ const c = s.columns[a], d = {
648
648
  componentId: c.componentId,
649
649
  fieldId: c.fieldId,
650
650
  typeTag: c.typeTag,
@@ -652,7 +652,7 @@ function en(t, e) {
652
652
  stride: c.stride,
653
653
  view: Zt(t, c.typeTag, c.byteOff, s.rowCapacity)
654
654
  };
655
- o[a] = l, i.set(Qt(c.componentId, c.fieldId), l);
655
+ o[a] = d, i.set(Qt(c.componentId, c.fieldId), d);
656
656
  }
657
657
  n.set(s.archetypeId, {
658
658
  archetypeId: s.archetypeId,
@@ -689,13 +689,13 @@ class rs {
689
689
  }
690
690
  /** Live entity indices that hold this component (dense, iteration order is
691
691
  * SparseMap insertion/swap order — NOT canonical). Used by the hot query
692
- * integration path (#469); for the determinism surface use
692
+ * integration path; for the determinism surface use
693
693
  * `canonicalIndices` instead. */
694
694
  get indices() {
695
695
  return this._data.keys;
696
696
  }
697
697
  /** Live entity indices in **canonical** (ascending) order — the determinism
698
- * ordering for `stateHash` + snapshot/restore (ADR-0011, #470). The native
698
+ * ordering for `stateHash` + snapshot/restore. The native
699
699
  * `indices` getter is insertion/swap order and would make two worlds with
700
700
  * identical contents reached by different add/remove histories diverge, so
701
701
  * the cold determinism paths sort here. Allocates a sorted copy each call;
@@ -749,12 +749,12 @@ class rs {
749
749
  return s === void 0 ? !1 : (s[n] = r, !0);
750
750
  }
751
751
  }
752
- class T extends Error {
752
+ class A extends Error {
753
753
  constructor(e) {
754
754
  super(e), this.name = "SparseRestoreError";
755
755
  }
756
756
  }
757
- const Ie = 12, we = 4, G = 8;
757
+ const Ie = 12, we = 4, H = 8;
758
758
  function Se(t, e) {
759
759
  let n = tn;
760
760
  const r = (s) => {
@@ -768,7 +768,7 @@ function os(t) {
768
768
  let e = 4;
769
769
  for (let o = 0; o < t.length; o++) {
770
770
  const i = t[o], a = i.fieldNames.length;
771
- e += Ie + i.size * (we + a * G);
771
+ e += Ie + i.size * (we + a * H);
772
772
  }
773
773
  const n = new Uint8Array(e), r = new DataView(n.buffer);
774
774
  let s = 0;
@@ -776,12 +776,12 @@ function os(t) {
776
776
  for (let o = 0; o < t.length; o++) {
777
777
  const i = t[o], a = i.fieldNames.length, c = i.canonicalIndices();
778
778
  r.setUint32(s, a, !0), s += 4, r.setUint32(s, Se(i.fieldNames, i.fieldTypes), !0), s += 4, r.setUint32(s, c.length, !0), s += 4;
779
- for (let l = 0; l < c.length; l++) {
780
- const d = c[l];
781
- r.setUint32(s, d, !0), s += 4;
782
- const f = i.getRow(d);
779
+ for (let d = 0; d < c.length; d++) {
780
+ const l = c[d];
781
+ r.setUint32(s, l, !0), s += 4;
782
+ const f = i.getRow(l);
783
783
  for (let h = 0; h < a; h++)
784
- r.setFloat64(s, f[h], !0), s += G;
784
+ r.setFloat64(s, f[h], !0), s += H;
785
785
  }
786
786
  }
787
787
  return n;
@@ -791,49 +791,49 @@ function is(t, e) {
791
791
  let s = 0;
792
792
  const o = (a) => {
793
793
  if (s + a > r)
794
- throw new T(
794
+ throw new A(
795
795
  `sparse snapshot truncated: need ${a} more bytes at offset ${s}, have ${r - s}`
796
796
  );
797
797
  };
798
798
  o(4);
799
799
  const i = n.getUint32(s, !0);
800
800
  if (s += 4, i !== t.length)
801
- throw new T(
801
+ throw new A(
802
802
  `sparse store count mismatch: snapshot=${i}, registered=${t.length}`
803
803
  );
804
804
  for (let a = 0; a < t.length; a++) {
805
805
  const c = t[a];
806
806
  o(Ie);
807
- const l = n.getUint32(s, !0);
808
- s += 4;
809
807
  const d = n.getUint32(s, !0);
810
808
  s += 4;
809
+ const l = n.getUint32(s, !0);
810
+ s += 4;
811
811
  const f = n.getUint32(s, !0);
812
- if (s += 4, l !== c.fieldNames.length)
813
- throw new T(
814
- `sparse store ${a} field-count mismatch: snapshot=${l}, registered=${c.fieldNames.length}`
812
+ if (s += 4, d !== c.fieldNames.length)
813
+ throw new A(
814
+ `sparse store ${a} field-count mismatch: snapshot=${d}, registered=${c.fieldNames.length}`
815
815
  );
816
816
  const h = Se(c.fieldNames, c.fieldTypes);
817
- if (d !== h)
818
- throw new T(
819
- `sparse store ${a} schema identity mismatch: snapshot hash=${d}, registered=${h} (same field count, different field names/types — likely a registration-order divergence between the snapshot and restore worlds)`
817
+ if (l !== h)
818
+ throw new A(
819
+ `sparse store ${a} schema identity mismatch: snapshot hash=${l}, registered=${h} (same field count, different field names/types — likely a registration-order divergence between the snapshot and restore worlds)`
820
820
  );
821
821
  c.clear();
822
822
  for (let g = 0; g < f; g++) {
823
- o(we + l * G);
824
- const A = n.getUint32(s, !0);
825
- if (s += 4, A > $)
826
- throw new T(
827
- `sparse store ${a} member ${g} entity index ${A} exceeds MAX_INDEX (${$})`
823
+ o(we + d * H);
824
+ const p = n.getUint32(s, !0);
825
+ if (s += 4, p > $)
826
+ throw new A(
827
+ `sparse store ${a} member ${g} entity index ${p} exceeds MAX_INDEX (${$})`
828
828
  );
829
- const u = new Array(l);
830
- for (let _ = 0; _ < l; _++)
831
- u[_] = n.getFloat64(s, !0), s += G;
832
- c.setRawRow(A, u);
829
+ const u = new Array(d);
830
+ for (let _ = 0; _ < d; _++)
831
+ u[_] = n.getFloat64(s, !0), s += H;
832
+ c.setRawRow(p, u);
833
833
  }
834
834
  }
835
835
  if (s !== r)
836
- throw new T(
836
+ throw new A(
837
837
  `sparse snapshot has ${r - s} trailing bytes after the last store (not a canonical encoding)`
838
838
  );
839
839
  }
@@ -842,45 +842,45 @@ function as(t, e) {
842
842
  let s = 0;
843
843
  const o = (a) => {
844
844
  if (s + a > r)
845
- throw new T(
845
+ throw new A(
846
846
  `sparse snapshot truncated: need ${a} more bytes at offset ${s}, have ${r - s}`
847
847
  );
848
848
  };
849
849
  o(4);
850
850
  const i = n.getUint32(s, !0);
851
851
  if (s += 4, i !== t.length)
852
- throw new T(
852
+ throw new A(
853
853
  `sparse store count mismatch: snapshot=${i}, registered=${t.length}`
854
854
  );
855
855
  for (let a = 0; a < t.length; a++) {
856
856
  const c = t[a];
857
857
  o(Ie);
858
- const l = n.getUint32(s, !0);
859
- s += 4;
860
858
  const d = n.getUint32(s, !0);
861
859
  s += 4;
860
+ const l = n.getUint32(s, !0);
861
+ s += 4;
862
862
  const f = n.getUint32(s, !0);
863
- if (s += 4, l !== c.fieldNames.length)
864
- throw new T(
865
- `sparse store ${a} field-count mismatch: snapshot=${l}, registered=${c.fieldNames.length}`
863
+ if (s += 4, d !== c.fieldNames.length)
864
+ throw new A(
865
+ `sparse store ${a} field-count mismatch: snapshot=${d}, registered=${c.fieldNames.length}`
866
866
  );
867
867
  const h = Se(c.fieldNames, c.fieldTypes);
868
- if (d !== h)
869
- throw new T(
870
- `sparse store ${a} schema identity mismatch: snapshot hash=${d}, registered=${h} (same field count, different field names/types — likely a registration-order divergence between the snapshot and restore worlds)`
868
+ if (l !== h)
869
+ throw new A(
870
+ `sparse store ${a} schema identity mismatch: snapshot hash=${l}, registered=${h} (same field count, different field names/types — likely a registration-order divergence between the snapshot and restore worlds)`
871
871
  );
872
872
  for (let g = 0; g < f; g++) {
873
- o(we + l * G);
874
- const A = n.getUint32(s, !0);
875
- if (s += 4, A > $)
876
- throw new T(
877
- `sparse store ${a} member ${g} entity index ${A} exceeds MAX_INDEX (${$})`
873
+ o(we + d * H);
874
+ const p = n.getUint32(s, !0);
875
+ if (s += 4, p > $)
876
+ throw new A(
877
+ `sparse store ${a} member ${g} entity index ${p} exceeds MAX_INDEX (${$})`
878
878
  );
879
- s += l * G;
879
+ s += d * H;
880
880
  }
881
881
  }
882
882
  if (s !== r)
883
- throw new T(
883
+ throw new A(
884
884
  `sparse snapshot has ${r - s} trailing bytes after the last store (not a canonical encoding)`
885
885
  );
886
886
  }
@@ -895,12 +895,12 @@ class Ze {
895
895
  * multi. Carries membership (and the target, when exclusive). */
896
896
  sparse;
897
897
  /** Cleanup policy applied to this relation's sources when a target is
898
- * destroyed (#473). `orphan` (the default) is a no-op — the link dangles
898
+ * destroyed. `orphan` (the default) is a no-op — the link dangles
899
899
  * safely. `Store` reads this at destroy-flush off `sourcesOf`. */
900
900
  onDeleteTarget;
901
901
  /** The backing sparse store instance. Owned for registration/liveness by
902
902
  * `Store`, but the relation drives the forward/membership rows on it directly
903
- * — that is the cardinality interaction this class now encapsulates (#498). */
903
+ * — that is the cardinality interaction this class now encapsulates. */
904
904
  _store;
905
905
  /** target `EntityID` → set of source `EntityID`s. Keyed by the full id, not
906
906
  * the index, so a recycled target slot can't alias a dead target's sources.
@@ -923,7 +923,7 @@ class Ze {
923
923
  r !== void 0 && (r.delete(n), r.size === 0 && this._reverse.delete(e));
924
924
  }
925
925
  /** Drop every reverse-index entry whose **target** is no longer alive,
926
- * returning the count dropped (#491). The `orphan` policy intentionally
926
+ * returning the count dropped. The `orphan` policy intentionally
927
927
  * leaves a destroyed target's reverse entry intact (the link dangles
928
928
  * safely), so a long-lived source that orphan-points at a stream of
929
929
  * short-lived targets and never re-targets/dies accumulates dead-target keys
@@ -1019,7 +1019,7 @@ class rn extends Ze {
1019
1019
  }
1020
1020
  }
1021
1021
  restoreAddTarget() {
1022
- throw new T(
1022
+ throw new A(
1023
1023
  "exclusive relation has no multi forward sources to restore (snapshot header should have guarded this)"
1024
1024
  );
1025
1025
  }
@@ -1103,9 +1103,9 @@ function ls(t) {
1103
1103
  continue;
1104
1104
  }
1105
1105
  const c = [];
1106
- a.forEachCanonicalTargetSet((l, d) => c.push([l, d])), e[i] = c, n += et;
1107
- for (let l = 0; l < c.length; l++)
1108
- n += tt + c[l][1].length * ne;
1106
+ a.forEachCanonicalTargetSet((d, l) => c.push([d, l])), e[i] = c, n += et;
1107
+ for (let d = 0; d < c.length; d++)
1108
+ n += tt + c[d][1].length * ne;
1109
1109
  }
1110
1110
  const r = new Uint8Array(n), s = new DataView(r.buffer);
1111
1111
  let o = 0;
@@ -1116,10 +1116,10 @@ function ls(t) {
1116
1116
  if (a !== null) {
1117
1117
  s.setUint32(o, a.length, !0), o += 4;
1118
1118
  for (let c = 0; c < a.length; c++) {
1119
- const l = a[c][0], d = a[c][1];
1120
- s.setUint32(o, l, !0), o += 4, s.setUint32(o, d.length, !0), o += 4;
1121
- for (let f = 0; f < d.length; f++)
1122
- s.setFloat64(o, d[f], !0), o += ne;
1119
+ const d = a[c][0], l = a[c][1];
1120
+ s.setUint32(o, d, !0), o += 4, s.setUint32(o, l.length, !0), o += 4;
1121
+ for (let f = 0; f < l.length; f++)
1122
+ s.setFloat64(o, l[f], !0), o += ne;
1123
1123
  }
1124
1124
  }
1125
1125
  }
@@ -1130,7 +1130,7 @@ function us(t, e, n) {
1130
1130
  let o = 0;
1131
1131
  const i = (c) => {
1132
1132
  if (o + c > s)
1133
- throw new T(
1133
+ throw new A(
1134
1134
  `relation snapshot truncated: need ${c} more bytes at offset ${o}, have ${s - o}`
1135
1135
  );
1136
1136
  };
@@ -1138,18 +1138,18 @@ function us(t, e, n) {
1138
1138
  i(4);
1139
1139
  const a = r.getUint32(o, !0);
1140
1140
  if (o += 4, a !== t.length)
1141
- throw new T(
1141
+ throw new A(
1142
1142
  `relation count mismatch: snapshot=${a}, registered=${t.length}`
1143
1143
  );
1144
1144
  for (let c = 0; c < t.length; c++) {
1145
- const l = t[c];
1145
+ const d = t[c];
1146
1146
  i(Je);
1147
- const d = r.getUint32(o, !0);
1148
- if (o += 4, d === 1 === l.exclusive)
1149
- throw new T(
1150
- `relation ${c} cardinality mismatch: snapshot ${d ? "multi" : "exclusive"}, registered ${l.exclusive ? "exclusive" : "multi"}`
1147
+ const l = r.getUint32(o, !0);
1148
+ if (o += 4, l === 1 === d.exclusive)
1149
+ throw new A(
1150
+ `relation ${c} cardinality mismatch: snapshot ${l ? "multi" : "exclusive"}, registered ${d.exclusive ? "exclusive" : "multi"}`
1151
1151
  );
1152
- if (l.exclusive) continue;
1152
+ if (d.exclusive) continue;
1153
1153
  i(et);
1154
1154
  const f = r.getUint32(o, !0);
1155
1155
  o += 4;
@@ -1157,33 +1157,33 @@ function us(t, e, n) {
1157
1157
  i(tt);
1158
1158
  const g = r.getUint32(o, !0);
1159
1159
  o += 4;
1160
- const A = r.getUint32(o, !0);
1160
+ const p = r.getUint32(o, !0);
1161
1161
  if (o += 4, g > $)
1162
- throw new T(
1162
+ throw new A(
1163
1163
  `relation ${c} source index ${g} exceeds MAX_INDEX (${$})`
1164
1164
  );
1165
- i(A * ne);
1165
+ i(p * ne);
1166
1166
  const u = n(g);
1167
- for (let _ = 0; _ < A; _++) {
1167
+ for (let _ = 0; _ < p; _++) {
1168
1168
  const I = r.getFloat64(o, !0);
1169
1169
  o += ne;
1170
1170
  const B = I;
1171
1171
  if (!Number.isInteger(B) || B < 0 || B > Re)
1172
- throw new T(
1172
+ throw new A(
1173
1173
  `relation ${c} target ${B} is not a well-formed packed EntityID (expected an integer in [0, ${Re}])`
1174
1174
  );
1175
- l.restoreAddTarget(g, I, u);
1175
+ d.restoreAddTarget(g, I, u);
1176
1176
  }
1177
1177
  }
1178
1178
  }
1179
1179
  if (o !== s)
1180
- throw new T(
1180
+ throw new A(
1181
1181
  `relation snapshot has ${s - o} trailing bytes after the last relation (not a canonical encoding)`
1182
1182
  );
1183
1183
  }
1184
1184
  const $e = /* @__PURE__ */ new WeakMap();
1185
1185
  function an(t) {
1186
- const e = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), c = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Set(), d = /* @__PURE__ */ new Set();
1186
+ const e = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), c = /* @__PURE__ */ new Set(), d = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Set();
1187
1187
  for (let u = 0; u < t.writes.length; u++) {
1188
1188
  const _ = t.writes[u].id;
1189
1189
  n.add(_), e.add(_), r.add(_);
@@ -1225,12 +1225,12 @@ function an(t) {
1225
1225
  if (g !== void 0)
1226
1226
  for (let u = 0; u < g.length; u++) {
1227
1227
  const _ = g[u];
1228
- d.add(_), l.add(_);
1228
+ l.add(_), d.add(_);
1229
1229
  }
1230
- const A = t.relationReads;
1231
- if (A !== void 0)
1232
- for (let u = 0; u < A.length; u++)
1233
- l.add(A[u]);
1230
+ const p = t.relationReads;
1231
+ if (p !== void 0)
1232
+ for (let u = 0; u < p.length; u++)
1233
+ d.add(p[u]);
1234
1234
  return {
1235
1235
  reads: e,
1236
1236
  writes: n,
@@ -1241,8 +1241,8 @@ function an(t) {
1241
1241
  resourceWrites: i,
1242
1242
  sparseReads: a,
1243
1243
  sparseWrites: c,
1244
- relationReads: l,
1245
- relationWrites: d
1244
+ relationReads: d,
1245
+ relationWrites: l
1246
1246
  };
1247
1247
  }
1248
1248
  function cn(t) {
@@ -1283,17 +1283,17 @@ class un {
1283
1283
  active = null;
1284
1284
  sets = null;
1285
1285
  // The label used in violation messages. Tracks `active` for a system span,
1286
- // but a run-condition span (#576) has no descriptor — only this name — so the
1286
+ // but a run-condition span has no descriptor — only this name — so the
1287
1287
  // failure helpers read the label here rather than off `active`.
1288
1288
  activeName = null;
1289
- // An `exclusive` system (#681) has full world access: every check_* below
1289
+ // An `exclusive` system has full world access: every check_* below
1290
1290
  // passes for the whole span. Kept as an explicit flag (rather than leaving
1291
1291
  // `sets` null) so `isActive()` stays truthful inside the span.
1292
1292
  exclusive = !1;
1293
1293
  enter(e) {
1294
1294
  this.active = e, this.activeName = e.name ?? `system_${e.id}`, this.exclusive = e.exclusive === !0, this.sets = this.exclusive ? null : cn(e);
1295
1295
  }
1296
- /** Open a reads-only span for a run condition (#576). No descriptor — a
1296
+ /** Open a reads-only span for a run condition. No descriptor — a
1297
1297
  * condition can gate a whole SystemSet, so it isn't attributable to one
1298
1298
  * system — just its declared reads/resource_reads and a name for diagnostics.
1299
1299
  * Paired with `leave()`. */
@@ -1325,8 +1325,8 @@ class un {
1325
1325
  checkDestroy() {
1326
1326
  if (this.sets === null || this.sets.hasDespawns) return;
1327
1327
  const e = this.activeName;
1328
- throw new y(
1329
- p.ACCESS_UNDECLARED,
1328
+ throw new T(
1329
+ y.ACCESS_UNDECLARED,
1330
1330
  `system '${e}' called despawn but didn't declare any despawns — declare the components this system removes via despawn in its 'despawns'`,
1331
1331
  { system: e, op: "despawn" }
1332
1332
  );
@@ -1341,7 +1341,7 @@ class un {
1341
1341
  const n = e;
1342
1342
  this.sets.resourceWrites.has(n) || this.failResource("write", e, "resourceWrites");
1343
1343
  }
1344
- // --- Sparse component / relation checks (#496) ---
1344
+ // --- Sparse component / relation checks ---
1345
1345
  // Keyed against the dedicated sparse/relation sets, NOT the dense
1346
1346
  // `reads`/`writes` sets — the id spaces are disjoint by construction (see
1347
1347
  // file header). `def as unknown as number` recovers the SparseComponentID /
@@ -1366,7 +1366,7 @@ class un {
1366
1366
  const n = e;
1367
1367
  this.sets.relationWrites.has(n) || this.failRelation("write", n, "relationWrites");
1368
1368
  }
1369
- /** A `(*, T)` wildcard (`Query.forEachRelatedTo`, #579) reads every
1369
+ /** A `(*, T)` wildcard (`Query.forEachRelatedTo`) reads every
1370
1370
  * relation's reverse index, so it can't name a specific relation — it is
1371
1371
  * authorised by the `ANY_RELATION` sentinel in `relationReads`. Honoured here
1372
1372
  * exactly like a per-relation read, just keyed on the reserved sentinel id
@@ -1378,7 +1378,7 @@ class un {
1378
1378
  "relationReads (as ANY_RELATION)"
1379
1379
  ));
1380
1380
  }
1381
- // --- Optional query-term scope (#592) ---
1381
+ // --- Optional query-term scope ---
1382
1382
  // `Query.forEach` and `ChangedQuery.forEach` push the iterating query's
1383
1383
  // `_optional` term list for the span of the callback;
1384
1384
  // `Archetype.getOptionalColumnRead` then verifies the fetched component was
@@ -1392,7 +1392,7 @@ class un {
1392
1392
  // `query.archetypes` walk can't be attributed to an optional declaration, so it
1393
1393
  // isn't checked — mirroring the unchecked outside-of-system calls in the header.
1394
1394
  //
1395
- // CAVEAT (#594 Task 3): the gate always attributes to the INNERMOST active
1395
+ // CAVEAT: the gate always attributes to the INNERMOST active
1396
1396
  // `forEach`. If you nest `forEach` and call `getOptionalColumnRead` on an
1397
1397
  // OUTER query's archetype inside the inner loop, it is checked against the inner
1398
1398
  // query's terms (a false throw or false pass). Per-query attribution isn't worth
@@ -1411,39 +1411,39 @@ class un {
1411
1411
  const r = this.optionalScopes[n - 1], s = e.id;
1412
1412
  for (let o = 0; o < r.length; o++)
1413
1413
  if (r[o] === s) return;
1414
- throw new y(
1415
- p.OPTIONAL_TERM_NOT_DECLARED,
1414
+ throw new T(
1415
+ y.OPTIONAL_TERM_NOT_DECLARED,
1416
1416
  `getOptionalColumnRead fetched optional component ${s} but the iterating query didn't declare it — add .optional(component) to the query before fetching it`
1417
1417
  );
1418
1418
  }
1419
1419
  failComponent(e, n, r) {
1420
1420
  const s = this.activeName, o = ut(n);
1421
- throw new y(
1422
- p.ACCESS_UNDECLARED,
1421
+ throw new T(
1422
+ y.ACCESS_UNDECLARED,
1423
1423
  `system '${s}' performed ${e} on ${o} but didn't declare it — add it to '${r}' (see docs/api/systems.md)`,
1424
1424
  { system: s, op: e, component: n.id }
1425
1425
  );
1426
1426
  }
1427
1427
  failSparse(e, n, r) {
1428
1428
  const s = this.activeName;
1429
- throw new y(
1430
- p.ACCESS_UNDECLARED,
1429
+ throw new T(
1430
+ y.ACCESS_UNDECLARED,
1431
1431
  `system '${s}' performed ${e} on sparse component ${n} but didn't declare it — add it to '${r}' (see docs/api/systems.md)`,
1432
1432
  { system: s, op: e, sparse: n }
1433
1433
  );
1434
1434
  }
1435
1435
  failRelation(e, n, r) {
1436
1436
  const s = this.activeName;
1437
- throw new y(
1438
- p.ACCESS_UNDECLARED,
1437
+ throw new T(
1438
+ y.ACCESS_UNDECLARED,
1439
1439
  `system '${s}' performed ${e} on relation ${n} but didn't declare it — add it to '${r}' (see docs/api/systems.md)`,
1440
1440
  { system: s, op: e, relation: n }
1441
1441
  );
1442
1442
  }
1443
1443
  failResource(e, n, r) {
1444
1444
  const s = this.activeName, o = n.description ?? "<unnamed>";
1445
- throw new y(
1446
- p.ACCESS_UNDECLARED,
1445
+ throw new T(
1446
+ y.ACCESS_UNDECLARED,
1447
1447
  `system '${s}' performed resource ${e} on '${o}' but didn't declare it — add the resource key to '${r}' (see docs/api/systems.md)`,
1448
1448
  { system: s, op: e, resource: o }
1449
1449
  );
@@ -1511,8 +1511,8 @@ class hn {
1511
1511
  for (const [n, r] of this.buf.entries()) {
1512
1512
  const [s, o, i, a] = n.split(" ");
1513
1513
  if (!s || !o || a === void 0) continue;
1514
- const l = { key: s === "actions" ? Number(i) : i, file: a, count: r }, f = e[s][o];
1515
- f && f.push(l);
1514
+ const d = { key: s === "actions" ? Number(i) : i, file: a, count: r }, f = e[s][o];
1515
+ f && f.push(d);
1516
1516
  }
1517
1517
  for (const n of Object.values(e))
1518
1518
  for (const r of Object.values(n))
@@ -1584,50 +1584,86 @@ function hs(t) {
1584
1584
  function En(t) {
1585
1585
  return !("fn" in t);
1586
1586
  }
1587
- const W = Object.freeze([]);
1587
+ const X = Object.freeze([]);
1588
1588
  function fe(t) {
1589
- return t === void 0 ? W : Array.isArray(t) ? t : [t];
1589
+ return t === void 0 ? X : Array.isArray(t) ? t : [t];
1590
1590
  }
1591
1591
  class _s {
1592
1592
  labelSystems = /* @__PURE__ */ new Map();
1593
+ // Sorted descriptors for a phase, paired with the `systemLastRun` slot of each
1594
+ // — cached together so `runLabel` resolves both with the one `Map.get` it
1595
+ // already paid, and the per-system lookup inside the loop is array indexing.
1593
1596
  sortedCache = /* @__PURE__ */ new Map();
1594
1597
  systemIndex = /* @__PURE__ */ new Map();
1595
- systemLastRun = /* @__PURE__ */ new Map();
1596
- // Only systems carrying a run condition or set membership (#576). The hot
1598
+ // Previous-run tick per scheduled system — a packed array, NOT a `Map` keyed
1599
+ // on the descriptor. `runLabel` reads it and writes it back once per system
1600
+ // per phase. A profile of a dispatch-bound schedule shows that those two `Map`
1601
+ // operations, and not the system bodies, are where most of the phase loop goes
1602
+ // — they hash an object identity twice for each system in each frame.
1603
+ //
1604
+ // Indexed by a SCHEDULE-LOCAL slot, not by `SystemDescriptor.id`. Ids come
1605
+ // from a per-world counter, so two descriptors registered with two different
1606
+ // worlds both get id 0 — scheduling them into a third world would alias them
1607
+ // onto one slot and let the system that runs more often overwrite the other's
1608
+ // last-run tick (silently widening its `changed()` window). Slots are handed
1609
+ // out per Schedule, so identity comes from this schedule's own numbering.
1610
+ systemLastRun = [];
1611
+ // Descriptor → its `systemLastRun` slot. Consulted only by `addSystems` /
1612
+ // `removeSystem`; the run loop never touches it (the slot travels in the
1613
+ // phase plan).
1614
+ //
1615
+ // `removeSystem` MUST delete from this map. It is the only strong reference
1616
+ // the Schedule keeps to a descriptor once its node is gone, and a descriptor
1617
+ // closes over whatever its `fn` captured — leaving the entry behind pins that
1618
+ // for the world's lifetime. (The `Map` this replaced was deleted on remove;
1619
+ // forgetting to do the same here leaked every descriptor ever scheduled.)
1620
+ lastRunSlots = /* @__PURE__ */ new Map();
1621
+ // Slots freed by `removeSystem`, handed back out by `_assignLastRunSlot`.
1622
+ // Without reuse the array would grow by one per `addSystems` call — unbounded
1623
+ // under a workload that toggles systems on and off each frame.
1624
+ freeLastRunSlots = [];
1625
+ // Nesting depth of a drive (`runStartup` / `runUpdate` / `runFixedUpdate`).
1626
+ // Non-zero means a phase plan is live and `runLabel`'s loop may still write
1627
+ // `systemLastRun` through the `slots` array it captured, which is what makes
1628
+ // recycling a freed slot unsafe right now — see `_assignLastRunSlot`.
1629
+ _driveDepth = 0;
1630
+ // Only systems carrying a run condition or set membership. The hot
1597
1631
  // loop skips the per-system gate probe entirely when this is empty, so a
1598
- // schedule that uses no conditions runs byte-for-byte the pre-#576 path.
1632
+ // schedule that uses no conditions runs byte-for-byte the original path.
1599
1633
  gatedSystems = /* @__PURE__ */ new Map();
1600
1634
  // Live set configuration, read at sort time (ordering) and run time
1601
1635
  // (conditions) so `configureSet` is order-independent w.r.t. `addSystems`.
1602
1636
  setConditions = /* @__PURE__ */ new Map();
1603
1637
  setOrdering = /* @__PURE__ */ new Map();
1604
1638
  nextInsertionOrder = 0;
1605
- // The opt-in compute backend (#622), or null (the default — pure-TS). When
1639
+ // The opt-in compute backend, or null (the default — pure-TS). When
1606
1640
  // set, a scheduled system carrying a `backendHandle` runs `backend.run(...)`
1607
- // instead of its `fn`. `null` is the byte-for-byte pre-#622 path: `runLabel`
1641
+ // instead of its `fn`. `null` is the byte-for-byte no-backend path: `runLabel`
1608
1642
  // hoists this to a local and only reads `desc.backendHandle` when non-null,
1609
1643
  // so a no-backend ECS never touches the routing field.
1610
1644
  _backend = null;
1611
1645
  /** Dev-diagnostic sink (`ECSOptions.onWarn`); defaults to `console.warn`.
1612
1646
  * The only schedule diagnostic today is `warnDroppedEdge`. */
1613
1647
  onWarn;
1648
+ /** The `FIXED_UPDATE` node list, held directly for `hasFixedSystems`. */
1649
+ _fixedNodes = [];
1614
1650
  constructor(e) {
1615
1651
  this.onWarn = e ?? ((n) => console.warn(n));
1616
1652
  for (let n = 0; n < le.length; n++)
1617
1653
  this.labelSystems.set(le[n], []);
1618
- this.labelSystems.set("FIXED_UPDATE", []);
1654
+ this.labelSystems.set("FIXED_UPDATE", this._fixedNodes);
1619
1655
  for (let n = 0; n < ue.length; n++)
1620
1656
  this.labelSystems.set(ue[n], []);
1621
1657
  }
1622
1658
  addSystems(e, ...n) {
1623
1659
  for (const r of n) {
1624
- const s = "system" in r, o = s ? r.system : r, i = s ? r.ordering : void 0, a = s ? fe(r.runIf) : W, c = s ? fe(r.set) : W;
1660
+ const s = "system" in r, o = s ? r.system : r, i = s ? r.ordering : void 0, a = s ? fe(r.runIf) : X, c = s ? fe(r.set) : X;
1625
1661
  if (this.systemIndex.has(o))
1626
- throw new y(
1627
- p.DUPLICATE_SYSTEM,
1662
+ throw new T(
1663
+ y.DUPLICATE_SYSTEM,
1628
1664
  `System ${o.name ?? o.id} is already scheduled`
1629
1665
  );
1630
- const l = {
1666
+ const d = {
1631
1667
  descriptor: o,
1632
1668
  insertionOrder: this.nextInsertionOrder++,
1633
1669
  before: new Set(i?.before ?? []),
@@ -1635,11 +1671,11 @@ class _s {
1635
1671
  conditions: a,
1636
1672
  sets: c
1637
1673
  };
1638
- this.labelSystems.get(e).push(l), this.systemIndex.set(o, e), this.systemLastRun.set(o, 0), (a.length > 0 || c.length > 0) && this.gatedSystems.set(o, l), this.sortedCache.delete(e);
1674
+ this.labelSystems.get(e).push(d), this.systemIndex.set(o, e), this._assignLastRunSlot(o), (a.length > 0 || c.length > 0) && this.gatedSystems.set(o, d), this.sortedCache.delete(e);
1639
1675
  }
1640
1676
  }
1641
1677
  /**
1642
- * Configure a `SystemSet` (#576) — its shared run condition(s) and/or
1678
+ * Configure a `SystemSet` — its shared run condition(s) and/or
1643
1679
  * ordering, inherited by every member. Additive and order-independent w.r.t.
1644
1680
  * `addSystems`: conditions accumulate (ANDed), ordering targets union, and
1645
1681
  * a member added before or after this call picks the configuration up.
@@ -1653,45 +1689,72 @@ class _s {
1653
1689
  if (n.before !== void 0 || n.after !== void 0) {
1654
1690
  let s = this.setOrdering.get(e);
1655
1691
  s === void 0 && (s = { before: /* @__PURE__ */ new Set(), after: /* @__PURE__ */ new Set() }, this.setOrdering.set(e, s));
1656
- for (const o of n.before ?? W) s.before.add(o);
1657
- for (const o of n.after ?? W) s.after.add(o);
1692
+ for (const o of n.before ?? X) s.before.add(o);
1693
+ for (const o of n.after ?? X) s.after.add(o);
1658
1694
  this.sortedCache.clear();
1659
1695
  }
1660
1696
  }
1661
1697
  removeSystem(e) {
1662
1698
  const n = this.systemIndex.get(e);
1663
1699
  if (n === void 0) return;
1664
- const r = this.labelSystems.get(n), s = r.findIndex((o) => o.descriptor === e);
1700
+ const r = this.labelSystems.get(n), s = r.findIndex((i) => i.descriptor === e);
1665
1701
  if (s !== -1) {
1666
- const o = r.length - 1;
1667
- s !== o && (r[s] = r[o]), r.pop();
1668
- for (const i of r)
1669
- i.before.delete(e), i.after.delete(e);
1702
+ const i = r.length - 1;
1703
+ s !== i && (r[s] = r[i]), r.pop();
1704
+ for (const a of r)
1705
+ a.before.delete(e), a.after.delete(e);
1670
1706
  }
1671
- this.systemIndex.delete(e), this.systemLastRun.delete(e), this.gatedSystems.delete(e), this.sortedCache.delete(n);
1707
+ this.systemIndex.delete(e);
1708
+ const o = this.lastRunSlots.get(e);
1709
+ o !== void 0 && (this.systemLastRun[o] = 0, this.lastRunSlots.delete(e), this.freeLastRunSlots.push(o)), this.gatedSystems.delete(e), this.sortedCache.clear();
1672
1710
  }
1673
- /** Attach (or, with `null`, detach) the opt-in compute backend (#622). Driven
1711
+ /** Attach (or, with `null`, detach) the opt-in compute backend. Driven
1674
1712
  * by `ECS.attachBackend`; routes any scheduled system carrying a
1675
1713
  * `backendHandle` to `backend.run(handle)` in place of its `fn`. */
1676
1714
  setBackend(e) {
1677
1715
  this._backend = e;
1678
1716
  }
1717
+ // The three drive entry points each bracket their phases with `_driveDepth`,
1718
+ // so `_assignLastRunSlot` will not recycle a `systemLastRun` slot that a phase
1719
+ // plan captured by `runLabel`'s loop may still write to — see the guard there
1720
+ // for the hazard it closes.
1721
+ //
1722
+ // Held across the WHOLE drive, not per phase: one `try`/`finally` per frame
1723
+ // instead of one per phase (three, for an update). The difference is
1724
+ // measurable on a dispatch-bound schedule, where the system bodies do almost
1725
+ // no work. The wider window is also the more
1726
+ // conservative one, and slots still recycle freely between frames — the only
1727
+ // property `freeLastRunSlots` needs to stay bounded. Written out at each of
1728
+ // the three sites rather than wrapped in a helper taking a callback, which
1729
+ // would put a closure allocation and an indirect call on the per-frame path.
1679
1730
  runStartup(e, n) {
1680
- for (const r of le)
1681
- this.runLabel(r, e, dt, n);
1731
+ this._driveDepth++;
1732
+ try {
1733
+ for (const r of le)
1734
+ this.runLabel(r, e, dt, n);
1735
+ } finally {
1736
+ this._driveDepth--;
1737
+ }
1682
1738
  }
1683
1739
  runUpdate(e, n, r) {
1684
- for (const s of ue)
1685
- this.runLabel(s, e, n, r);
1740
+ this._driveDepth++;
1741
+ try {
1742
+ for (const s of ue)
1743
+ this.runLabel(s, e, n, r);
1744
+ } finally {
1745
+ this._driveDepth--;
1746
+ }
1686
1747
  }
1687
1748
  runFixedUpdate(e, n, r) {
1688
- this.runLabel("FIXED_UPDATE", e, n, r);
1749
+ this._driveDepth++;
1750
+ try {
1751
+ this.runLabel("FIXED_UPDATE", e, n, r);
1752
+ } finally {
1753
+ this._driveDepth--;
1754
+ }
1689
1755
  }
1690
1756
  hasFixedSystems() {
1691
- return this.labelSystems.get(
1692
- "FIXED_UPDATE"
1693
- /* FIXED_UPDATE */
1694
- ).length > 0;
1757
+ return this._fixedNodes.length > 0;
1695
1758
  }
1696
1759
  getAllSystems() {
1697
1760
  const e = [];
@@ -1703,28 +1766,43 @@ class _s {
1703
1766
  hasSystem(e) {
1704
1767
  return this.systemIndex.has(e);
1705
1768
  }
1769
+ /** Hand `descriptor` its `systemLastRun` slot, keeping the array packed (no
1770
+ * holes ⇒ no undefined-check on the read in `runLabel`, which is the whole
1771
+ * point of it not being a `Map`). Idempotent for a descriptor already in this
1772
+ * schedule — `getSorted` re-asks for every system it sorts. A descriptor that
1773
+ * was removed and re-added gets a *fresh* slot starting at tick 0, which is
1774
+ * what the previous `Map`-based bookkeeping did (`delete` on remove, `set(…, 0)`
1775
+ * on re-add). */
1776
+ _assignLastRunSlot(e) {
1777
+ let n = this.lastRunSlots.get(e);
1778
+ if (n === void 0) {
1779
+ const r = this._driveDepth === 0 ? this.freeLastRunSlots.pop() : void 0;
1780
+ r !== void 0 ? (n = r, this.systemLastRun[n] = 0) : (n = this.systemLastRun.length, this.systemLastRun.push(0)), this.lastRunSlots.set(e, n);
1781
+ }
1782
+ return n;
1783
+ }
1706
1784
  clear() {
1707
1785
  for (const e of this.labelSystems.values())
1708
1786
  e.length = 0;
1709
- this.sortedCache.clear(), this.systemIndex.clear(), this.systemLastRun.clear(), this.gatedSystems.clear(), this.setConditions.clear(), this.setOrdering.clear();
1787
+ this.sortedCache.clear(), this.systemIndex.clear(), this._driveDepth === 0 ? this.systemLastRun.length = 0 : this.systemLastRun.fill(0), this.lastRunSlots.clear(), this.freeLastRunSlots.length = 0, this.gatedSystems.clear(), this.setConditions.clear(), this.setOrdering.clear();
1710
1788
  }
1711
1789
  runLabel(e, n, r, s) {
1712
- const o = this.getSorted(e), i = this.gatedSystems.size > 0, a = this._backend, c = i ? /* @__PURE__ */ new Map() : void 0;
1713
- for (let l = 0; l < o.length; l++) {
1714
- const d = o[l];
1715
- if (i) {
1716
- const h = this.gatedSystems.get(d);
1717
- if (h !== void 0 && !this.shouldRun(h, n, c)) continue;
1790
+ const o = this.getSorted(e), i = o.sorted, a = o.slots, c = this.gatedSystems.size > 0, d = this._backend, l = c ? /* @__PURE__ */ new Map() : void 0;
1791
+ for (let f = 0; f < i.length; f++) {
1792
+ const h = i[f];
1793
+ if (c) {
1794
+ const p = this.gatedSystems.get(h);
1795
+ if (p !== void 0 && !this.shouldRun(p, n, l)) continue;
1718
1796
  }
1719
- n.lastRunTick = this.systemLastRun.get(d) ?? 0;
1720
- const f = a !== null ? d.backendHandle : void 0;
1721
- Q.enter(d), n._trace?.systemStart(d, e);
1797
+ n.lastRunTick = this.systemLastRun[a[f]];
1798
+ const g = d !== null ? h.backendHandle : void 0;
1799
+ Q.enter(h), n._trace?.systemStart(h, e);
1722
1800
  try {
1723
- f !== void 0 ? a.run(f) : d.fn?.(n, r);
1801
+ g !== void 0 ? d.run(g) : h.fn?.(n, r);
1724
1802
  } finally {
1725
- n._trace?.systemEnd(d), Q.leave();
1803
+ n._trace?.systemEnd(h), Q.leave();
1726
1804
  }
1727
- this.systemLastRun.set(d, s);
1805
+ this.systemLastRun[a[f]] = s;
1728
1806
  }
1729
1807
  n._trace?.flushBegin(e), n.flush(), n._trace?.flushEnd(e), n._trace?.phaseBoundary(e);
1730
1808
  }
@@ -1736,7 +1814,7 @@ class _s {
1736
1814
  * memo lives only for a single `runLabel` pass. Short-circuits on the first
1737
1815
  * `false`. The system's own conditions evaluate per system, in canonical order.
1738
1816
  *
1739
- * #731 SEMANTIC NOTE: this evaluates a set's conditions once-per-set-per-phase
1817
+ * SEMANTIC NOTE: this evaluates a set's conditions once-per-set-per-phase
1740
1818
  * rather than once-per-member. Equivalent for pure RunConditions; observably
1741
1819
  * different only if a set condition reads state mutated earlier in the SAME
1742
1820
  * phase (resources write immediately). That is intentional — the set gates as a
@@ -1776,8 +1854,10 @@ class _s {
1776
1854
  getSorted(e) {
1777
1855
  const n = this.sortedCache.get(e);
1778
1856
  if (n !== void 0) return n;
1779
- const r = this.labelSystems.get(e), s = this.sortSystems(r, e);
1780
- return this.sortedCache.set(e, s), s;
1857
+ const r = this.labelSystems.get(e), s = this.sortSystems(r, e), o = new Int32Array(s.length);
1858
+ for (let a = 0; a < s.length; a++) o[a] = this._assignLastRunSlot(s[a]);
1859
+ const i = { sorted: s, slots: o };
1860
+ return this.sortedCache.set(e, i), i;
1781
1861
  }
1782
1862
  /**
1783
1863
  * Delegates to the shared topologicalSort utility.
@@ -1787,31 +1867,31 @@ class _s {
1787
1867
  sortSystems(e, n) {
1788
1868
  if (e.length === 0) return [];
1789
1869
  const r = [], s = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Map();
1790
- for (const d of e) {
1791
- r.push(d.descriptor), s.set(d.descriptor, d.insertionOrder), o.add(d.descriptor);
1792
- for (let f = 0; f < d.sets.length; f++) {
1793
- const h = d.sets[f];
1870
+ for (const l of e) {
1871
+ r.push(l.descriptor), s.set(l.descriptor, l.insertionOrder), o.add(l.descriptor);
1872
+ for (let f = 0; f < l.sets.length; f++) {
1873
+ const h = l.sets[f];
1794
1874
  let g = i.get(h);
1795
- g === void 0 && (g = [], i.set(h, g)), g.push(d.descriptor);
1875
+ g === void 0 && (g = [], i.set(h, g)), g.push(l.descriptor);
1796
1876
  }
1797
1877
  }
1798
1878
  const a = /* @__PURE__ */ new Map();
1799
- for (const d of e)
1800
- a.set(d.descriptor, []);
1801
- for (const d of e) {
1879
+ for (const l of e)
1880
+ a.set(l.descriptor, []);
1881
+ for (const l of e) {
1802
1882
  this.resolveEdges(
1803
- d.descriptor,
1804
- d.before,
1883
+ l.descriptor,
1884
+ l.before,
1805
1885
  "before",
1806
1886
  o,
1807
1887
  i,
1808
1888
  a,
1809
1889
  n
1810
- ), this.resolveEdges(d.descriptor, d.after, "after", o, i, a, n);
1811
- for (let f = 0; f < d.sets.length; f++) {
1812
- const h = this.setOrdering.get(d.sets[f]);
1890
+ ), this.resolveEdges(l.descriptor, l.after, "after", o, i, a, n);
1891
+ for (let f = 0; f < l.sets.length; f++) {
1892
+ const h = this.setOrdering.get(l.sets[f]);
1813
1893
  h !== void 0 && (this.resolveEdges(
1814
- d.descriptor,
1894
+ l.descriptor,
1815
1895
  h.before,
1816
1896
  "before",
1817
1897
  o,
@@ -1819,7 +1899,7 @@ class _s {
1819
1899
  a,
1820
1900
  n
1821
1901
  ), this.resolveEdges(
1822
- d.descriptor,
1902
+ l.descriptor,
1823
1903
  h.after,
1824
1904
  "after",
1825
1905
  o,
@@ -1829,18 +1909,18 @@ class _s {
1829
1909
  ));
1830
1910
  }
1831
1911
  }
1832
- const c = (d, f) => s.get(d) - s.get(f), l = (d) => d.name ?? `system_${d.id}`;
1912
+ const c = (l, f) => s.get(l) - s.get(f), d = (l) => l.name ?? `system_${l.id}`;
1833
1913
  try {
1834
- return it(r, a, c, l);
1835
- } catch (d) {
1836
- throw d instanceof TypeError ? new y(
1837
- p.CIRCULAR_SYSTEM_DEPENDENCY,
1838
- `Circular system dependency detected in ${n}: ${d.message}`
1839
- ) : d;
1914
+ return it(r, a, c, d);
1915
+ } catch (l) {
1916
+ throw l instanceof TypeError ? new T(
1917
+ y.CIRCULAR_SYSTEM_DEPENDENCY,
1918
+ `Circular system dependency detected in ${n}: ${l.message}`
1919
+ ) : l;
1840
1920
  }
1841
1921
  }
1842
1922
  /**
1843
- * Add the topo edges for one ordering list (#576). For `"before"` the source
1923
+ * Add the topo edges for one ordering list. For `"before"` the source
1844
1924
  * runs before each target (edge source→target); for `"after"` it runs after
1845
1925
  * each target (edge target→source). A `SystemSet` target expands to every
1846
1926
  * member within this phase (self-edges skipped, so a member ordered against
@@ -1851,10 +1931,10 @@ class _s {
1851
1931
  resolveEdges(e, n, r, s, o, i, a) {
1852
1932
  for (const c of n) {
1853
1933
  if (En(c)) {
1854
- const l = o.get(c);
1855
- if (l === void 0) continue;
1856
- for (let d = 0; d < l.length; d++) {
1857
- const f = l[d];
1934
+ const d = o.get(c);
1935
+ if (d === void 0) continue;
1936
+ for (let l = 0; l < d.length; l++) {
1937
+ const f = d[l];
1858
1938
  f !== e && this.addDirectedEdge(e, f, r, i);
1859
1939
  }
1860
1940
  continue;
@@ -1890,11 +1970,11 @@ class _s {
1890
1970
  );
1891
1971
  }
1892
1972
  }
1893
- const se = 1024, re = 1024 * se, xe = 64 * se, X = 256 * re, Be = 3, pn = 64, yn = 8, Fe = 4 * re, ke = (t) => 2 ** Math.ceil(Math.log2(Math.max(1, t))), Z = (t) => 2 ** Math.floor(Math.log2(Math.max(1, t))), k = (t, e, n) => Math.min(n, Math.max(e, t)), S = (t) => t >= re ? `${(t / re).toFixed(1)} MiB` : t >= se ? `${(t / se).toFixed(0)} KiB` : `${t} B`;
1973
+ const se = 1024, re = 1024 * se, xe = 64 * se, W = 256 * re, Be = 3, pn = 64, yn = 8, Fe = 4 * re, ke = (t) => 2 ** Math.ceil(Math.log2(Math.max(1, t))), Z = (t) => 2 ** Math.floor(Math.log2(Math.max(1, t))), k = (t, e, n) => Math.min(n, Math.max(e, t)), S = (t) => t >= re ? `${(t / re).toFixed(1)} MiB` : t >= se ? `${(t / se).toFixed(0)} KiB` : `${t} B`;
1894
1974
  function D(t, e) {
1895
1975
  if (!Number.isInteger(e) || e <= 0)
1896
- throw new y(
1897
- p.INVALID_MEMORY_OPTIONS,
1976
+ throw new T(
1977
+ y.INVALID_MEMORY_OPTIONS,
1898
1978
  `memory.${t} must be a positive integer (got ${e})`
1899
1979
  );
1900
1980
  }
@@ -1903,20 +1983,20 @@ function ms(t) {
1903
1983
  (s) => t !== void 0 && t[s] !== void 0
1904
1984
  );
1905
1985
  if (e.length > 1)
1906
- throw new y(
1907
- p.INVALID_MEMORY_OPTIONS,
1986
+ throw new T(
1987
+ y.INVALID_MEMORY_OPTIONS,
1908
1988
  `memory takes at most one of budget | maxBytes | wasm | allocator | heap | shared (got: ${e.join(", ")})`
1909
1989
  );
1910
1990
  const n = t?.columnCapacity;
1911
- if (n !== void 0 && D("column_capacity", n), t?.budget !== void 0) {
1991
+ if (n !== void 0 && D("columnCapacity", n), t?.budget !== void 0) {
1912
1992
  const { entities: s } = t.budget, o = t.budget.archetypes ?? yn, i = t.budget.bytesPerEntity ?? pn;
1913
- if (D("budget.entities", s), D("budget.archetypes", o), D("budget.bytes_per_entity", i), s > 1 << 20)
1914
- throw new y(
1915
- p.INVALID_MEMORY_OPTIONS,
1993
+ if (D("budget.entities", s), D("budget.archetypes", o), D("budget.bytesPerEntity", i), s > 1 << 20)
1994
+ throw new T(
1995
+ y.INVALID_MEMORY_OPTIONS,
1916
1996
  `memory.budget.entities=${s} exceeds the EntityID index space (1<<20 = ${1 << 20})`
1917
1997
  );
1918
- const a = n ?? k(ke(Math.ceil(s / o)), 64, 1 << 20), c = k(ke(s * 2), 4096, 1 << 20), l = c * R, d = s * i * Be, f = Ke(
1919
- Math.max(l + d, Fe),
1998
+ const a = n ?? k(ke(Math.ceil(s / o)), 64, 1 << 20), c = k(ke(s * 2), 4096, 1 << 20), d = c * R, l = s * i * Be, f = Ke(
1999
+ Math.max(d + l, Fe),
1920
2000
  xe
1921
2001
  );
1922
2002
  return {
@@ -1928,9 +2008,9 @@ function ms(t) {
1928
2008
  intentLabel: `budget of ${s} entities`,
1929
2009
  budgetEntities: s,
1930
2010
  derivation: [
1931
- `column_capacity = ${n !== void 0 ? `${a} (pinned)` : `pow2(${s}/${o} per archetype) = ${a}`}`,
1932
- `entity_index = pow2(2 × ${s}) = ${c} slots × ${R} B = ${S(l)}`,
1933
- `columns = ${s} × ${i} B × ${Be} (double+holes headroom) = ${S(d)}`,
2011
+ `columnCapacity = ${n !== void 0 ? `${a} (pinned)` : `pow2(${s}/${o} per archetype) = ${a}`}`,
2012
+ `entityIndex = pow2(2 × ${s}) = ${c} slots × ${R} B = ${S(d)}`,
2013
+ `columns = ${s} × ${i} B × ${Be} (double+holes headroom) = ${S(l)}`,
1934
2014
  `cap = align64K(max(index + columns, ${S(Fe)} floor)) = ${S(f)}`
1935
2015
  ],
1936
2016
  wasmMemory: null
@@ -1944,7 +2024,7 @@ function ms(t) {
1944
2024
  U
1945
2025
  );
1946
2026
  return {
1947
- source: "max_bytes",
2027
+ source: "maxBytes",
1948
2028
  allocator: j(t.maxBytes),
1949
2029
  columnCapacity: s,
1950
2030
  entityIndexCapacity: o,
@@ -1953,8 +2033,8 @@ function ms(t) {
1953
2033
  budgetEntities: null,
1954
2034
  derivation: [
1955
2035
  `cap = ${S(t.maxBytes)} (caller-declared)`,
1956
- `column_capacity = ${s} (${n !== void 0 ? "pinned" : "default"})`,
1957
- `entity_index = floor_pow2(cap/4 ÷ ${R} B) = ${o} slots`
2036
+ `columnCapacity = ${s} (${n !== void 0 ? "pinned" : "default"})`,
2037
+ `entityIndex = floor_pow2(cap/4 ÷ ${R} B) = ${o} slots`
1958
2038
  ],
1959
2039
  wasmMemory: null
1960
2040
  };
@@ -1963,9 +2043,9 @@ function ms(t) {
1963
2043
  const s = t.wasm, o = n ?? F;
1964
2044
  if (s.memory !== void 0) {
1965
2045
  if (!(s.memory.buffer instanceof SharedArrayBuffer))
1966
- throw new y(
1967
- p.INVALID_MEMORY_OPTIONS,
1968
- "memory.wasm.memory must be constructed with `shared: true` — the SAB substrate requires a SharedArrayBuffer-backed WebAssembly.Memory (ADR-0004 / ADR-0018)"
2046
+ throw new T(
2047
+ y.INVALID_MEMORY_OPTIONS,
2048
+ "memory.wasm.memory must be constructed with `shared: true` — the SAB substrate requires a SharedArrayBuffer-backed WebAssembly.Memory"
1969
2049
  );
1970
2050
  return {
1971
2051
  source: "wasm",
@@ -1979,23 +2059,23 @@ function ms(t) {
1979
2059
  derivation: [
1980
2060
  "backing = wasm_memory_allocator(memory) — zero-copy with the sim (is_in_place ✓)",
1981
2061
  "cap = the Memory's own `maximum` (declared by the caller; not readable from JS)",
1982
- `column_capacity = ${o} (${n !== void 0 ? "pinned" : "default"})`
2062
+ `columnCapacity = ${o} (${n !== void 0 ? "pinned" : "default"})`
1983
2063
  ],
1984
2064
  wasmMemory: s.memory
1985
2065
  };
1986
2066
  }
1987
- D("wasm.maximum_pages", s.maximumPages);
2067
+ D("wasm.maximumPages", s.maximumPages);
1988
2068
  const i = s.initialPages ?? Math.min(32, s.maximumPages);
1989
- if (D("wasm.initial_pages", i), i > s.maximumPages)
1990
- throw new y(
1991
- p.INVALID_MEMORY_OPTIONS,
1992
- `memory.wasm.initial_pages (${i}) exceeds maximum_pages (${s.maximumPages})`
2069
+ if (D("wasm.initialPages", i), i > s.maximumPages)
2070
+ throw new T(
2071
+ y.INVALID_MEMORY_OPTIONS,
2072
+ `memory.wasm.initialPages (${i}) exceeds maximumPages (${s.maximumPages})`
1993
2073
  );
1994
2074
  const a = new WebAssembly.Memory({
1995
2075
  initial: i,
1996
2076
  maximum: s.maximumPages,
1997
2077
  shared: !0
1998
- }), c = s.maximumPages * xe, l = k(
2078
+ }), c = s.maximumPages * xe, d = k(
1999
2079
  Z(c / 4 / R),
2000
2080
  4096,
2001
2081
  U
@@ -2004,27 +2084,27 @@ function ms(t) {
2004
2084
  source: "wasm",
2005
2085
  allocator: Ne(a),
2006
2086
  columnCapacity: o,
2007
- entityIndexCapacity: l,
2087
+ entityIndexCapacity: d,
2008
2088
  capBytes: c,
2009
2089
  intentLabel: `engine-constructed WebAssembly.Memory (max ${s.maximumPages} pages)`,
2010
2090
  budgetEntities: null,
2011
2091
  derivation: [
2012
2092
  `cap = ${s.maximumPages} pages × 64 KiB = ${S(c)} (Memory maximum)`,
2013
2093
  `initial = ${i} pages (${s.initialPages !== void 0 ? "declared" : "default"})`,
2014
- `entity_index = floor_pow2(cap/4 ÷ ${R} B) = ${l} slots`,
2015
- `column_capacity = ${o} (${n !== void 0 ? "pinned" : "default"})`
2094
+ `entityIndex = floor_pow2(cap/4 ÷ ${R} B) = ${d} slots`,
2095
+ `columnCapacity = ${o} (${n !== void 0 ? "pinned" : "default"})`
2016
2096
  ],
2017
2097
  wasmMemory: a
2018
2098
  };
2019
2099
  }
2020
2100
  if (t?.allocator !== void 0) {
2021
2101
  if (t.allocator.isInPlace !== !0)
2022
- throw new y(
2023
- p.INVALID_MEMORY_OPTIONS,
2024
- "memory.allocator must declare `is_in_place: true` (ADR-0008): a live Store's flush loops hoist entity-index views across grows, so a non-in-place allocator (e.g. DEFAULT_SAB_ALLOCATOR) corrupts the entity→row mapping. Use growable_sab_allocator / wasm_memory_allocator; non-in-place allocators are snapshot/test sizing only."
2102
+ throw new T(
2103
+ y.INVALID_MEMORY_OPTIONS,
2104
+ "memory.allocator must declare `isInPlace: true`: a live Store's flush loops hoist entity-index views across grows, so a non-in-place allocator (e.g. DEFAULT_SAB_ALLOCATOR) corrupts the entity→row mapping. Use growableSabAllocator / wasmMemoryAllocator; non-in-place allocators are snapshot/test sizing only."
2025
2105
  );
2026
2106
  const s = n ?? F, o = t.capBytesHint;
2027
- return o !== void 0 && D("cap_bytes_hint", o), {
2107
+ return o !== void 0 && D("capBytesHint", o), {
2028
2108
  source: "allocator",
2029
2109
  allocator: t.allocator,
2030
2110
  columnCapacity: s,
@@ -2035,14 +2115,14 @@ function ms(t) {
2035
2115
  derivation: [
2036
2116
  "backing = caller allocator (is_in_place ✓ checked at construction)",
2037
2117
  o !== void 0 ? `cap = ${S(o)} (caller hint — diagnostics only; the allocator owns the real cap)` : "cap = allocator-owned (no hint)",
2038
- `column_capacity = ${s} (${n !== void 0 ? "pinned" : "default"})`
2118
+ `columnCapacity = ${s} (${n !== void 0 ? "pinned" : "default"})`
2039
2119
  ],
2040
2120
  wasmMemory: null
2041
2121
  };
2042
2122
  }
2043
2123
  if (t?.heap !== void 0) {
2044
2124
  t.heap.maxBytes !== void 0 && D("heap.maxBytes", t.heap.maxBytes);
2045
- const s = t.heap.maxBytes ?? X, o = n ?? F, i = k(
2125
+ const s = t.heap.maxBytes ?? W, o = n ?? F, i = k(
2046
2126
  Z(s / 4 / R),
2047
2127
  4096,
2048
2128
  U
@@ -2056,17 +2136,17 @@ function ms(t) {
2056
2136
  intentLabel: `pure-TS heap backing (${S(s)} growable cap, no SharedArrayBuffer)`,
2057
2137
  budgetEntities: null,
2058
2138
  derivation: [
2059
- `backing = heap_arraybuffer_allocator(${S(s)}) — resizable ArrayBuffer, no SAB / no COOP+COEP (is_in_place ✓)`,
2139
+ `backing = heap_arraybuffer_allocator(${S(s)}) — fixed ArrayBuffer reserved at the cap, no SAB / no COOP+COEP (is_in_place ✓)`,
2060
2140
  "trade-off: no worker offload / no WASM backend (both need a transferable SharedArrayBuffer)",
2061
- `column_capacity = ${o} (${n !== void 0 ? "pinned" : "default"})`,
2062
- `entity_index = floor_pow2(cap/4 ÷ ${R} B) = ${i} slots`
2141
+ `columnCapacity = ${o} (${n !== void 0 ? "pinned" : "default"})`,
2142
+ `entityIndex = floor_pow2(cap/4 ÷ ${R} B) = ${i} slots`
2063
2143
  ],
2064
2144
  wasmMemory: null
2065
2145
  };
2066
2146
  }
2067
2147
  if (t?.shared !== void 0) {
2068
2148
  t.shared.maxBytes !== void 0 && D("shared.maxBytes", t.shared.maxBytes);
2069
- const s = t.shared.maxBytes ?? X, o = n ?? F, i = k(
2149
+ const s = t.shared.maxBytes ?? W, o = n ?? F, i = k(
2070
2150
  Z(s / 4 / R),
2071
2151
  4096,
2072
2152
  U
@@ -2082,8 +2162,8 @@ function ms(t) {
2082
2162
  derivation: [
2083
2163
  `backing = growable_sab_allocator(${S(s)}) — growable SharedArrayBuffer (is_in_place ✓); needs cross-origin isolation`,
2084
2164
  "enables worker offload + a WASM compute backend (transferable SharedArrayBuffer)",
2085
- `column_capacity = ${o} (${n !== void 0 ? "pinned" : "default"})`,
2086
- `entity_index = floor_pow2(cap/4 ÷ ${R} B) = ${i} slots`
2165
+ `columnCapacity = ${o} (${n !== void 0 ? "pinned" : "default"})`,
2166
+ `entityIndex = floor_pow2(cap/4 ÷ ${R} B) = ${i} slots`
2087
2167
  ],
2088
2168
  wasmMemory: null
2089
2169
  };
@@ -2094,13 +2174,13 @@ function ms(t) {
2094
2174
  allocator: j(),
2095
2175
  columnCapacity: r,
2096
2176
  entityIndexCapacity: U,
2097
- capBytes: X,
2098
- intentLabel: `default sizing (${S(X)} growable cap)`,
2177
+ capBytes: W,
2178
+ intentLabel: `default sizing (${S(W)} growable cap)`,
2099
2179
  budgetEntities: null,
2100
2180
  derivation: [
2101
- `cap = ${S(X)} (heap_arraybuffer_allocator default)`,
2102
- `column_capacity = ${r} (${n !== void 0 ? "pinned" : "DEFAULT_COLUMN_CAPACITY"})`,
2103
- `entity_index = ${U} slots (full EntityID space, ~12 MiB virtual)`
2181
+ `cap = ${S(W)} (heap_arraybuffer_allocator default)`,
2182
+ `columnCapacity = ${r} (${n !== void 0 ? "pinned" : "DEFAULT_COLUMN_CAPACITY"})`,
2183
+ `entityIndex = ${U} slots (full EntityID space, ~12 MiB virtual)`
2104
2184
  ],
2105
2185
  wasmMemory: null
2106
2186
  };
@@ -2127,9 +2207,9 @@ function he(t, e) {
2127
2207
  return;
2128
2208
  case "set_field":
2129
2209
  if (!t.hasComponent(e.eid, e.def))
2130
- throw new y(
2131
- p.COMPONENT_NOT_REGISTERED,
2132
- `host set_field on entity ${e.eid} targets a component it does not have. If you added that component via a host command this same frame, the add is deferred to the phase flush while set_field is immediate — carry the value in add_component/spawn_entry instead of a separate set_field, or set it next frame. (#681 host write seam)`
2210
+ throw new T(
2211
+ y.COMPONENT_NOT_REGISTERED,
2212
+ `host set_field on entity ${e.eid} targets a component it does not have. If you added that component via a host command this same frame, the add is deferred to the phase flush while set_field is immediate — carry the value in add_component/spawnEntry instead of a separate set_field, or set it next frame. (host write seam)`
2133
2213
  );
2134
2214
  t.setField(e.eid, e.def, e.field, e.value);
2135
2215
  return;
@@ -2190,7 +2270,7 @@ class Tn {
2190
2270
  get pending() {
2191
2271
  return this.queued.length;
2192
2272
  }
2193
- /** Drop every buffered command without applying it (M15) — e.g. abandoning
2273
+ /** Drop every buffered command without applying it — e.g. abandoning
2194
2274
  * queued edits on a scene unload. Returns how many were dropped. Does not
2195
2275
  * touch commands already drained into the world. */
2196
2276
  clear() {
@@ -2205,7 +2285,7 @@ class Tn {
2205
2285
  * `tap`, when present, is invoked with each command in apply order just before
2206
2286
  * it is applied — the record/replay hook ({@link HostCommandRecorder}). It is
2207
2287
  * an OPT-IN observer: the tap-free path keeps the original tight loop, so an
2208
- * un-recorded drain pays nothing (#702).
2288
+ * un-recorded drain pays nothing.
2209
2289
  */
2210
2290
  drain(e, n) {
2211
2291
  const r = this.queued.length;
@@ -2224,10 +2304,10 @@ const nt = P - 1;
2224
2304
  function An(t) {
2225
2305
  if (t === ye)
2226
2306
  throw new v(
2227
- "cannot bind op_code 0 (reserved as the command-ring empty-slot marker)"
2307
+ "cannot bind opCode 0 (reserved as the command-ring empty-slot marker)"
2228
2308
  );
2229
2309
  if (t < 0 || t > 255 || !Number.isInteger(t))
2230
- throw new v(`command op_code must be a u8 in [1, 255] (got ${t})`);
2310
+ throw new v(`command opCode must be a u8 in [1, 255] (got ${t})`);
2231
2311
  }
2232
2312
  function ae(t) {
2233
2313
  const e = new Uint8Array(nt);
@@ -2265,7 +2345,7 @@ function ps() {
2265
2345
  encode(t) {
2266
2346
  if (t.kind !== "despawn")
2267
2347
  throw new v(
2268
- `ring_despawn_codec encodes a "despawn" command (got "${t.kind}")`
2348
+ `ringDespawnCodec encodes a "despawn" command (got "${t.kind}")`
2269
2349
  );
2270
2350
  return ae(t.eid);
2271
2351
  },
@@ -2277,7 +2357,7 @@ function ys() {
2277
2357
  encode(t) {
2278
2358
  if (t.kind !== "disable")
2279
2359
  throw new v(
2280
- `ring_disable_codec encodes a "disable" command (got "${t.kind}")`
2360
+ `ringDisableCodec encodes a "disable" command (got "${t.kind}")`
2281
2361
  );
2282
2362
  return ae(t.eid);
2283
2363
  },
@@ -2289,7 +2369,7 @@ function Ts() {
2289
2369
  encode(t) {
2290
2370
  if (t.kind !== "enable")
2291
2371
  throw new v(
2292
- `ring_enable_codec encodes an "enable" command (got "${t.kind}")`
2372
+ `ringEnableCodec encodes an "enable" command (got "${t.kind}")`
2293
2373
  );
2294
2374
  return ae(t.eid);
2295
2375
  },
@@ -2314,14 +2394,14 @@ class Is {
2314
2394
  on(e, n) {
2315
2395
  return An(e), this.appliers.set(e, n), this;
2316
2396
  }
2317
- /** Unbind `opCode` (M15). Returns whether a binding was removed; subsequent
2397
+ /** Unbind `opCode`. Returns whether a binding was removed; subsequent
2318
2398
  * slots carrying it hit the unknown-opcode path. */
2319
2399
  off(e) {
2320
2400
  return this.appliers.delete(e);
2321
2401
  }
2322
2402
  /** Bind a `HostCommand` codec to `opCode`: each matching slot is decoded and
2323
2403
  * run through `applyHostCommand` — the SAME dispatch the typed queue uses.
2324
- * A drain-time `tap` (record/replay, #702) sees the decoded command before it
2404
+ * A drain-time `tap` (record/replay) sees the decoded command before it
2325
2405
  * applies, so ring-sourced commands share one log with the typed transport. */
2326
2406
  onCommand(e, n) {
2327
2407
  return this.on(e, (r, s, o) => {
@@ -2332,7 +2412,7 @@ class Is {
2332
2412
  /** Drain every pending slot, dispatching each to its bound applier. Unbound
2333
2413
  * opcodes are skipped (the read head still advances — matching
2334
2414
  * `drainCommandRing` / `CommandDispatcher`). Returns slots drained. `tap`,
2335
- * when present, is forwarded to each applier as the record/replay hook (#702);
2415
+ * when present, is forwarded to each applier as the record/replay hook;
2336
2416
  * only `onCommand`-bound (generic `HostCommand`) opcodes surface to it. */
2337
2417
  drain(e, n, r, s) {
2338
2418
  return Ot(n, r, (o, i) => {
@@ -2357,13 +2437,13 @@ function Ss(t, e) {
2357
2437
  _e.set(n, r);
2358
2438
  const s = e?.name ?? "host_command_apply", o = e?.ring, i = e?.recorder, a = i?.record, c = e?.schedules ?? [x.PRE_STARTUP, x.PRE_UPDATE];
2359
2439
  if (i !== void 0 && c.includes(x.FIXED_UPDATE))
2360
- throw new y(
2361
- p.INVALID_RECORDER_SCHEDULE,
2440
+ throw new T(
2441
+ y.INVALID_RECORDER_SCHEDULE,
2362
2442
  "install_host_command_seam: a recorder cannot drain on SCHEDULE.FIXED_UPDATE — it would log the fixed-step dt instead of the host update(dt) and diverge on replay. Use a variable-update phase (PRE_UPDATE/UPDATE/POST_UPDATE)."
2363
2443
  );
2364
- for (const l of c) {
2365
- const d = !In.has(l), f = t.registerSystem({
2366
- name: `${s}:${l}`,
2444
+ for (const d of c) {
2445
+ const l = !In.has(d), f = t.registerSystem({
2446
+ name: `${s}:${d}`,
2367
2447
  // `reads`/`writes` are required by `SystemConfig` but empty here: the
2368
2448
  // apply system declares nothing because it mutates components not known
2369
2449
  // at registration. Full world access: the host may queue mutations to
@@ -2373,13 +2453,13 @@ function Ss(t, e) {
2373
2453
  writes: [],
2374
2454
  exclusive: !0,
2375
2455
  fn: (h, g) => {
2376
- if (i !== void 0 && d && i.openTick(h.ecsTick, g), n.drain(h, a), o !== void 0) {
2377
- const A = t.columnStore, u = A.header.commandRingOff;
2378
- u !== 0 && o.drain(h, A.view, u, a);
2456
+ if (i !== void 0 && l && i.openTick(h.ecsTick, g), n.drain(h, a), o !== void 0) {
2457
+ const p = t.columnStore, u = p.header.commandRingOff;
2458
+ u !== 0 && o.drain(h, p.view, u, a);
2379
2459
  }
2380
2460
  }
2381
2461
  });
2382
- t.addSystems(l, f), r.push(f);
2462
+ t.addSystems(d, f), r.push(f);
2383
2463
  }
2384
2464
  return n;
2385
2465
  }
@@ -2389,23 +2469,23 @@ export {
2389
2469
  N as B,
2390
2470
  pt as C,
2391
2471
  F as D,
2392
- y as E,
2393
- He as F,
2472
+ T as E,
2473
+ Ge as F,
2394
2474
  ie as G,
2395
2475
  te as H,
2396
2476
  $n as I,
2397
2477
  os as J,
2398
2478
  ls as K,
2399
- T as L,
2479
+ A as L,
2400
2480
  is as M,
2401
2481
  vn as N,
2402
2482
  us as O,
2403
2483
  as as P,
2404
- Xn as Q,
2484
+ Wn as Q,
2405
2485
  nn as R,
2406
2486
  m as S,
2407
2487
  Oe as T,
2408
- Cn as U,
2488
+ bn as U,
2409
2489
  ee as V,
2410
2490
  U as W,
2411
2491
  jn as X,
@@ -2418,8 +2498,8 @@ export {
2418
2498
  Un as a2,
2419
2499
  De as a3,
2420
2500
  Re as a4,
2421
- Ge as a5,
2422
- Wn as a6,
2501
+ He as a5,
2502
+ Xn as a6,
2423
2503
  Vn as a7,
2424
2504
  rs as a8,
2425
2505
  z as a9,
@@ -2450,8 +2530,8 @@ export {
2450
2530
  Tn as aq,
2451
2531
  gs as ar,
2452
2532
  Me as as,
2453
- bn as at,
2454
- X as au,
2533
+ Cn as at,
2534
+ W as au,
2455
2535
  Be as av,
2456
2536
  pn as aw,
2457
2537
  yn as ax,
@@ -2461,19 +2541,19 @@ export {
2461
2541
  ht as c,
2462
2542
  zn as d,
2463
2543
  en as e,
2464
- p as f,
2544
+ y as f,
2465
2545
  L as g,
2466
2546
  Q as h,
2467
2547
  Rn as i,
2468
2548
  Qt as j,
2469
- Gn as k,
2549
+ Hn as k,
2470
2550
  cs as l,
2471
2551
  ds as m,
2472
2552
  Yn as n,
2473
2553
  kn as o,
2474
2554
  Bn as p,
2475
2555
  ns as q,
2476
- Hn as r,
2556
+ Gn as r,
2477
2557
  Ke as s,
2478
2558
  Ae as t,
2479
2559
  On as u,