@oasys/oecs 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. package/CHANGELOG.md +553 -0
  2. package/README.md +42 -31
  3. package/dist/core/ecs/access_check.d.cts +77 -0
  4. package/dist/core/ecs/access_check.d.ts +8 -8
  5. package/dist/core/ecs/access_check.d.ts.map +1 -1
  6. package/dist/core/ecs/archetype.d.cts +486 -0
  7. package/dist/core/ecs/archetype.d.ts +23 -11
  8. package/dist/core/ecs/archetype.d.ts.map +1 -1
  9. package/dist/core/ecs/archetype_graph.d.cts +96 -0
  10. package/dist/core/ecs/archetype_graph.d.ts +96 -0
  11. package/dist/core/ecs/archetype_graph.d.ts.map +1 -0
  12. package/dist/core/ecs/builtin_relations.d.cts +43 -0
  13. package/dist/core/ecs/builtin_relations.d.ts +8 -8
  14. package/dist/core/ecs/builtin_relations.d.ts.map +1 -1
  15. package/dist/core/ecs/command_log.d.cts +116 -0
  16. package/dist/core/ecs/command_log.d.ts +13 -10
  17. package/dist/core/ecs/command_log.d.ts.map +1 -1
  18. package/dist/core/ecs/component.d.cts +176 -0
  19. package/dist/core/ecs/component.d.ts +75 -5
  20. package/dist/core/ecs/component.d.ts.map +1 -1
  21. package/dist/core/ecs/compute_backend.d.cts +37 -0
  22. package/dist/core/ecs/compute_backend.d.ts +2 -2
  23. package/dist/core/ecs/debug_names.d.cts +7 -0
  24. package/dist/core/ecs/debug_names.d.ts +7 -0
  25. package/dist/core/ecs/debug_names.d.ts.map +1 -0
  26. package/dist/core/ecs/deferred_commands.d.cts +55 -0
  27. package/dist/core/ecs/deferred_commands.d.ts +55 -0
  28. package/dist/core/ecs/deferred_commands.d.ts.map +1 -0
  29. package/dist/core/ecs/dispatch_trace.d.cts +93 -0
  30. package/dist/core/ecs/dispatch_trace.d.ts +3 -3
  31. package/dist/core/ecs/ecs.d.cts +562 -0
  32. package/dist/core/ecs/ecs.d.ts +314 -285
  33. package/dist/core/ecs/ecs.d.ts.map +1 -1
  34. package/dist/core/ecs/ecs_memory.d.cts +179 -0
  35. package/dist/core/ecs/ecs_memory.d.ts +1 -1
  36. package/dist/core/ecs/entity.d.cts +34 -0
  37. package/dist/core/ecs/entity.d.ts +7 -1
  38. package/dist/core/ecs/entity.d.ts.map +1 -1
  39. package/dist/core/ecs/entity_allocator.d.cts +59 -0
  40. package/dist/core/ecs/entity_allocator.d.ts +59 -0
  41. package/dist/core/ecs/entity_allocator.d.ts.map +1 -0
  42. package/dist/core/ecs/event.d.cts +79 -0
  43. package/dist/core/ecs/event.d.ts +36 -11
  44. package/dist/core/ecs/event.d.ts.map +1 -1
  45. package/dist/core/ecs/event_registry.d.cts +22 -0
  46. package/dist/core/ecs/event_registry.d.ts +22 -0
  47. package/dist/core/ecs/event_registry.d.ts.map +1 -0
  48. package/dist/core/ecs/facades.d.cts +158 -0
  49. package/dist/core/ecs/facades.d.ts +158 -0
  50. package/dist/core/ecs/facades.d.ts.map +1 -0
  51. package/dist/core/ecs/frame_stepper.d.cts +58 -0
  52. package/dist/core/ecs/frame_stepper.d.ts +58 -0
  53. package/dist/core/ecs/frame_stepper.d.ts.map +1 -0
  54. package/dist/core/ecs/frame_trace.d.cts +133 -0
  55. package/dist/core/ecs/frame_trace.d.ts +5 -5
  56. package/dist/core/ecs/frame_trace.d.ts.map +1 -1
  57. package/dist/core/ecs/host_commands.d.cts +274 -0
  58. package/dist/core/ecs/host_commands.d.ts +53 -31
  59. package/dist/core/ecs/host_commands.d.ts.map +1 -1
  60. package/dist/core/ecs/index.d.cts +46 -0
  61. package/dist/core/ecs/index.d.ts +45 -40
  62. package/dist/core/ecs/index.d.ts.map +1 -1
  63. package/dist/core/ecs/observer.d.cts +173 -0
  64. package/dist/core/ecs/observer.d.ts +43 -12
  65. package/dist/core/ecs/observer.d.ts.map +1 -1
  66. package/dist/core/ecs/query.d.cts +718 -0
  67. package/dist/core/ecs/query.d.ts +251 -90
  68. package/dist/core/ecs/query.d.ts.map +1 -1
  69. package/dist/core/ecs/ref.d.cts +31 -0
  70. package/dist/core/ecs/ref.d.ts +3 -3
  71. package/dist/core/ecs/relation.d.cts +243 -0
  72. package/dist/core/ecs/relation.d.ts +26 -14
  73. package/dist/core/ecs/relation.d.ts.map +1 -1
  74. package/dist/core/ecs/relation_service.d.cts +235 -0
  75. package/dist/core/ecs/relation_service.d.ts +235 -0
  76. package/dist/core/ecs/relation_service.d.ts.map +1 -0
  77. package/dist/core/ecs/resource.d.cts +53 -0
  78. package/dist/core/ecs/resource.d.ts +25 -5
  79. package/dist/core/ecs/resource.d.ts.map +1 -1
  80. package/dist/core/ecs/resource_registry.d.cts +20 -0
  81. package/dist/core/ecs/resource_registry.d.ts +20 -0
  82. package/dist/core/ecs/resource_registry.d.ts.map +1 -0
  83. package/dist/core/ecs/resume.d.cts +85 -0
  84. package/dist/core/ecs/resume.d.ts +6 -6
  85. package/dist/core/ecs/resume.d.ts.map +1 -1
  86. package/dist/core/ecs/run_condition.d.cts +81 -0
  87. package/dist/core/ecs/run_condition.d.ts +15 -9
  88. package/dist/core/ecs/run_condition.d.ts.map +1 -1
  89. package/dist/core/ecs/schedule.d.cts +142 -0
  90. package/dist/core/ecs/schedule.d.ts +15 -6
  91. package/dist/core/ecs/schedule.d.ts.map +1 -1
  92. package/dist/core/ecs/snapshot_service.d.cts +94 -0
  93. package/dist/core/ecs/snapshot_service.d.ts +94 -0
  94. package/dist/core/ecs/snapshot_service.d.ts.map +1 -0
  95. package/dist/core/ecs/sparse_store.d.cts +110 -0
  96. package/dist/core/ecs/sparse_store.d.ts +5 -2
  97. package/dist/core/ecs/sparse_store.d.ts.map +1 -1
  98. package/dist/core/ecs/store.d.cts +950 -0
  99. package/dist/core/ecs/store.d.ts +143 -342
  100. package/dist/core/ecs/store.d.ts.map +1 -1
  101. package/dist/core/ecs/store_layout_listener.d.cts +23 -0
  102. package/dist/core/ecs/system.d.cts +250 -0
  103. package/dist/core/ecs/system.d.ts +138 -22
  104. package/dist/core/ecs/system.d.ts.map +1 -1
  105. package/dist/{utils/arrays.d.ts → core/ecs/utils/arrays.d.cts} +1 -0
  106. package/dist/core/ecs/utils/error.d.cts +61 -0
  107. package/dist/core/ecs/utils/error.d.ts +12 -2
  108. package/dist/core/ecs/utils/error.d.ts.map +1 -1
  109. package/dist/core/store/action_ring.d.cts +136 -0
  110. package/dist/core/store/allocator.d.cts +238 -0
  111. package/dist/core/store/allocator.d.ts.map +1 -1
  112. package/dist/core/store/buffer_backed_column.d.cts +69 -0
  113. package/dist/core/store/buffer_backed_column.d.ts +2 -2
  114. package/dist/core/store/column_store.d.cts +273 -0
  115. package/dist/core/store/column_store.d.ts +18 -10
  116. package/dist/core/store/column_store.d.ts.map +1 -1
  117. package/dist/core/store/command_dispatch.d.cts +52 -0
  118. package/dist/core/store/command_ring.d.cts +107 -0
  119. package/dist/core/store/descriptor.d.cts +80 -0
  120. package/dist/core/store/descriptor.d.ts +1 -1
  121. package/dist/core/store/descriptor.d.ts.map +1 -1
  122. package/dist/core/store/entity_index.d.cts +108 -0
  123. package/dist/core/store/event_ring.d.cts +95 -0
  124. package/dist/core/store/extend.d.cts +39 -0
  125. package/dist/core/store/extend.d.ts +3 -73
  126. package/dist/core/store/extend.d.ts.map +1 -1
  127. package/dist/core/store/grow.d.cts +34 -0
  128. package/dist/core/store/grow.d.ts +4 -9
  129. package/dist/core/store/grow.d.ts.map +1 -1
  130. package/dist/core/store/header.d.cts +64 -0
  131. package/dist/core/store/header.d.ts +1 -1
  132. package/dist/core/store/header.d.ts.map +1 -1
  133. package/dist/core/store/index.d.cts +17 -0
  134. package/dist/core/store/index.d.ts +16 -15
  135. package/dist/core/store/index.d.ts.map +1 -1
  136. package/dist/core/store/layout_ops.d.cts +152 -0
  137. package/dist/core/store/layout_ops.d.ts +152 -0
  138. package/dist/core/store/layout_ops.d.ts.map +1 -0
  139. package/dist/core/store/region_table.d.cts +74 -0
  140. package/dist/core/store/region_table.d.ts +1 -1
  141. package/dist/core/store/region_table.d.ts.map +1 -1
  142. package/dist/core/store/snapshot.d.cts +43 -0
  143. package/dist/core/store/snapshot.d.ts +2 -2
  144. package/dist/core/store/state_hash.d.cts +38 -0
  145. package/dist/core/store/state_hash.d.ts +1 -1
  146. package/dist/core/store/store_regions.d.cts +38 -0
  147. package/dist/core/store/store_regions.d.ts +1 -1
  148. package/dist/core/store/vendored_abi/abi.d.ts +43 -0
  149. package/dist/core/store/{__generated__ → vendored_abi}/abi.d.ts.map +1 -1
  150. package/dist/dev_flag.d.cts +17 -0
  151. package/dist/dev_flag.d.ts +17 -0
  152. package/dist/dev_flag.d.ts.map +1 -0
  153. package/dist/extensions/editor/editor.d.cts +170 -0
  154. package/dist/extensions/editor/editor.d.ts +43 -22
  155. package/dist/extensions/editor/editor.d.ts.map +1 -1
  156. package/dist/extensions/editor/field_handle.d.cts +40 -0
  157. package/dist/extensions/editor/field_handle.d.ts +8 -3
  158. package/dist/extensions/editor/field_handle.d.ts.map +1 -1
  159. package/dist/extensions/editor/index.cjs +1 -1
  160. package/dist/extensions/editor/index.d.cts +21 -0
  161. package/dist/extensions/editor/index.d.ts +2 -2
  162. package/dist/extensions/editor/index.js +116 -88
  163. package/dist/extensions/reactive/ecs_sync.d.cts +214 -0
  164. package/dist/extensions/reactive/ecs_sync.d.ts +26 -22
  165. package/dist/extensions/reactive/ecs_sync.d.ts.map +1 -1
  166. package/dist/extensions/reactive/index.cjs +1 -1
  167. package/dist/extensions/reactive/index.d.cts +23 -0
  168. package/dist/extensions/reactive/index.d.ts +1 -1
  169. package/dist/extensions/reactive/index.js +106 -116
  170. package/dist/extensions/solid/index.cjs +1 -1
  171. package/dist/extensions/solid/index.d.cts +6 -0
  172. package/dist/extensions/solid/index.d.ts +2 -2
  173. package/dist/extensions/solid/index.js +8 -4
  174. package/dist/extensions/solid/kernel_solid.d.cts +45 -0
  175. package/dist/extensions/solid/kernel_solid.d.ts +6 -3
  176. package/dist/extensions/solid/kernel_solid.d.ts.map +1 -1
  177. package/dist/host_commands-BF8QMi3c.cjs +1 -0
  178. package/dist/host_commands-i4cAeyL5.js +2318 -0
  179. package/dist/index.cjs +1 -2
  180. package/dist/index.d.cts +66 -0
  181. package/dist/index.d.ts +50 -1
  182. package/dist/index.d.ts.map +1 -1
  183. package/dist/index.js +4469 -5933
  184. package/dist/internal.cjs +2 -0
  185. package/dist/internal.d.cts +20 -0
  186. package/dist/internal.d.ts +20 -0
  187. package/dist/internal.d.ts.map +1 -0
  188. package/dist/internal.js +141 -0
  189. package/dist/primitives.cjs +1 -1
  190. package/dist/primitives.d.cts +18 -0
  191. package/dist/primitives.d.ts +6 -6
  192. package/dist/primitives.js +24 -23
  193. package/dist/reactive/array.d.ts +24 -0
  194. package/dist/reactive/array.d.ts.map +1 -0
  195. package/dist/reactive/index.cjs +1 -0
  196. package/dist/reactive/index.d.cts +11 -0
  197. package/dist/reactive/index.d.ts +11 -0
  198. package/dist/reactive/index.d.ts.map +1 -0
  199. package/dist/reactive/index.js +18 -0
  200. package/dist/reactive/interop.d.cts +19 -0
  201. package/dist/{core/reactive → reactive}/interop.d.ts +1 -1
  202. package/dist/reactive/interop.d.ts.map +1 -0
  203. package/dist/reactive/kernel.d.cts +73 -0
  204. package/dist/{core/reactive → reactive}/kernel.d.ts +5 -3
  205. package/dist/reactive/kernel.d.ts.map +1 -0
  206. package/dist/reactive/map.d.ts +16 -0
  207. package/dist/reactive/map.d.ts.map +1 -0
  208. package/dist/reactive/shallow.d.cts +11 -0
  209. package/dist/reactive/shallow.d.ts +11 -0
  210. package/dist/reactive/shallow.d.ts.map +1 -0
  211. package/dist/reactive/struct.d.cts +10 -0
  212. package/dist/{core/reactive → reactive}/struct.d.ts +1 -1
  213. package/dist/reactive/struct.d.ts.map +1 -0
  214. package/dist/shallow-DQ8aG51_.cjs +1 -0
  215. package/dist/shallow-DfnAm9vG.js +150 -0
  216. package/dist/shared-BU1Cd40h.js +103 -0
  217. package/dist/shared-BymrGTyR.cjs +1 -0
  218. package/dist/shared.cjs +1 -1
  219. package/dist/shared.d.cts +22 -0
  220. package/dist/shared.d.ts +2 -2
  221. package/dist/shared.js +1 -1
  222. package/dist/topological_sort-BDvEyb9W.cjs +1 -0
  223. package/dist/topological_sort-DK6EjpWa.js +135 -0
  224. package/dist/type_primitives/assertions.d.cts +32 -0
  225. package/dist/type_primitives/assertions.d.ts +13 -1
  226. package/dist/type_primitives/assertions.d.ts.map +1 -1
  227. package/dist/type_primitives/binary_heap/binary_heap.d.cts +37 -0
  228. package/dist/type_primitives/bitset/bitset.d.cts +54 -0
  229. package/dist/type_primitives/brand.d.cts +23 -0
  230. package/dist/type_primitives/error.d.cts +16 -0
  231. package/dist/type_primitives/error.d.ts +4 -3
  232. package/dist/type_primitives/error.d.ts.map +1 -1
  233. package/dist/type_primitives/index.d.cts +13 -0
  234. package/dist/type_primitives/index.d.ts +9 -9
  235. package/dist/type_primitives/sparse_map/sparse_map.d.cts +30 -0
  236. package/dist/type_primitives/sparse_set/sparse_set.d.cts +28 -0
  237. package/dist/type_primitives/topological_sort/topological_sort.d.cts +29 -0
  238. package/dist/type_primitives/typed_arrays/typed_arrays.d.cts +127 -0
  239. package/dist/typed_arrays-BcXcnzB4.js +258 -0
  240. package/dist/typed_arrays-D3NmwtCG.cjs +1 -0
  241. package/dist/utils/error.d.cts +6 -0
  242. package/dist/version.d.cts +10 -0
  243. package/dist/version.d.ts +10 -0
  244. package/dist/version.d.ts.map +1 -0
  245. package/package.json +102 -19
  246. package/dist/array-CxbPyiHO.cjs +0 -1
  247. package/dist/array-uFR7Q8fU.js +0 -132
  248. package/dist/core/reactive/array.d.ts.map +0 -1
  249. package/dist/core/reactive/index.cjs +0 -1
  250. package/dist/core/reactive/index.d.ts +0 -10
  251. package/dist/core/reactive/index.d.ts.map +0 -1
  252. package/dist/core/reactive/index.js +0 -17
  253. package/dist/core/reactive/interop.d.ts.map +0 -1
  254. package/dist/core/reactive/kernel.d.ts.map +0 -1
  255. package/dist/core/reactive/map.d.ts.map +0 -1
  256. package/dist/core/reactive/struct.d.ts.map +0 -1
  257. package/dist/log/console_sink.d.ts +0 -4
  258. package/dist/log/console_sink.d.ts.map +0 -1
  259. package/dist/log/index.d.ts +0 -3
  260. package/dist/log/index.d.ts.map +0 -1
  261. package/dist/log/logger.d.ts +0 -27
  262. package/dist/log/logger.d.ts.map +0 -1
  263. package/dist/shared-BXSZnxx4.cjs +0 -1
  264. package/dist/shared-C678TAPY.js +0 -99
  265. package/dist/topological_sort-DlRpSrxu.js +0 -391
  266. package/dist/topological_sort-WAT-VHb-.cjs +0 -1
  267. package/dist/utils/arrays.d.ts.map +0 -1
  268. package/dist/utils/constants.d.ts.map +0 -1
  269. /package/dist/{utils/constants.d.ts → core/ecs/utils/constants.d.cts} +0 -0
  270. /package/dist/core/store/{__generated__/abi.d.ts → vendored_abi/abi.d.cts} +0 -0
  271. /package/dist/{core/reactive/array.d.ts → reactive/array.d.cts} +0 -0
  272. /package/dist/{core/reactive/map.d.ts → reactive/map.d.cts} +0 -0
@@ -0,0 +1,176 @@
1
+ import { Brand, TypedArrayTag } from '../../type_primitives/index.cjs';
2
+ export type ComponentID = Brand<number, "component_id">;
3
+ export declare const asComponentId: (value: number) => ComponentID;
4
+ /** Core schema type: maps field names to typed array tags. */
5
+ export type ComponentSchema = Readonly<Record<string, TypedArrayTag>>;
6
+ /** Compile-time tag → TypedArray mapping. */
7
+ export type TagToTypedArray = {
8
+ f32: Float32Array;
9
+ f64: Float64Array;
10
+ i8: Int8Array;
11
+ i16: Int16Array;
12
+ i32: Int32Array;
13
+ u8: Uint8Array;
14
+ u16: Uint16Array;
15
+ u32: Uint32Array;
16
+ };
17
+ /** Maps schema fields to their value object: { x: number, y: number }. */
18
+ export type FieldValues<S extends ComponentSchema> = {
19
+ readonly [K in keyof S]: number;
20
+ };
21
+ /**
22
+ * Values argument tuple for attaching a component of schema `S` — empty for a
23
+ * tag, a single optional partial-values map otherwise. A tag schema
24
+ * (`Record<string, never>`) would otherwise degenerate: `keyof` an
25
+ * index-signature record is `string`, so `Partial<FieldValues<…>>` collapses to
26
+ * `Record<string, number>` and `Frozen({ anything: 1 })` compiles. The
27
+ * conditional forbids values on tags outright; a schema-erased `ComponentDef`
28
+ * falls into the valued branch, so untyped call sites keep the loose shape.
29
+ */
30
+ export type ValuesArg<S extends ComponentSchema> = S extends Record<string, never> ? [] : [values?: Partial<FieldValues<S>>];
31
+ /**
32
+ * `FieldValues` for APIs where the values object is required and complete
33
+ * (`addComponent`'s valued overload, the host-seam `SpawnEntry`). Guards the
34
+ * same tag degeneracy as `ValuesArg`: a tag accepts only the empty object
35
+ * (`Record<string, never>` — every property typed `never`), so
36
+ * `addComponent(e, Frozen, { x: 1 })` is a compile error while the
37
+ * tag-overload-less call sites can still pass `{}`.
38
+ */
39
+ export type CompleteFieldValues<S extends ComponentSchema> = S extends Record<string, never> ? Record<string, never> : FieldValues<S>;
40
+ /**
41
+ * Trailing-argument tuple for the attach surfaces (`ctx.commands.add`'s
42
+ * explicit-values form, `ctx.addSparse`): a tag takes NO values argument, a valued schema REQUIRES a
43
+ * complete one. Encodes the former tag/valued overload pair as one signature,
44
+ * which the typed system seam needs — its `def` parameter is a single
45
+ * declared-access-constrained type param, and per-schema overloads would
46
+ * re-introduce the tag-vs-valued split on top of it.
47
+ */
48
+ export type AttachValuesArg<S extends ComponentSchema> = S extends Record<string, never> ? [] : [values: CompleteFieldValues<S>];
49
+ /** Maps schema fields to their specific typed array columns. */
50
+ export type ColumnsForSchema<S extends ComponentSchema> = {
51
+ readonly [K in keyof S]: TagToTypedArray[S[K]];
52
+ };
53
+ /**
54
+ * Mutable sibling of `ColumnsForSchema` — the field-keyed column group handed
55
+ * back by `eachChunk`'s `cols.mut(def)` (no `readonly`, since the whole point
56
+ * is in-place writes). The change-tick is stamped once when the group is
57
+ * resolved, so the per-row loop is plain typed-array indexing (§eachChunk).
58
+ */
59
+ export type MutableColumnsForSchema<S extends ComponentSchema> = {
60
+ [K in keyof S]: TagToTypedArray[S[K]];
61
+ };
62
+ declare const __schema: unique symbol;
63
+ /**
64
+ * A component handle. **Callable**: `Pos({ x, y })` produces a `Bundle` (omitted
65
+ * fields zero-fill at attach), so one varargs shape — `spawn(Pos({x,y}),
66
+ * Vel({vx:1}), IsEnemy)` — replaces the older incompatible attach shapes. A bare
67
+ * `Pos` (uncalled) still stands in for a tag / all-zero values wherever a
68
+ * `BundleOrDef` is accepted.
69
+ *
70
+ * The numeric component id lives on `.id` (registration order). Consumers treat
71
+ * the def as an opaque handle; internal code reads `def.id` where it needs the
72
+ * raw id. The call signature's `S` makes `ComponentDef<{x:"f64"}>` distinct from
73
+ * `ComponentDef<{vx:"f64"}>`.
74
+ *
75
+ * The optional `[__schema]` slot never exists at runtime; it re-states `S` in a
76
+ * covariant tuple position so that a TAG def type is not a universal assignment
77
+ * sink. Through the call signature alone every def is assignable to
78
+ * `ComponentDef<Record<string, never>>` (the tag callable takes no required
79
+ * args and any `Bundle` satisfies its return), which would let ONE tag in a
80
+ * system's declared-access union admit every component at compile time
81
+ * (§typestate — `DeclaredRead` and friends in system.ts). With the slot, a
82
+ * valued schema is not assignable to the tag schema (`"f64" ⊀ never`), while
83
+ * schema erasure (`ComponentDef<S>` → bare `ComponentDef`) still works because
84
+ * every schema is assignable to `ComponentSchema`.
85
+ *
86
+ * Build one with `makeComponentDef`; never construct by hand.
87
+ */
88
+ export interface ComponentDef<S extends ComponentSchema = ComponentSchema> {
89
+ (...values: ValuesArg<S>): Bundle<S>;
90
+ readonly id: ComponentID;
91
+ readonly [__schema]?: [S];
92
+ }
93
+ /**
94
+ * Recover a def's schema type: `SchemaOf<typeof Pos>` is `{x:"f64", y:"f64"}`.
95
+ * The typed `SystemContext` methods (§typestate) constrain their `def`
96
+ * parameter to the system's declared-access union and use this to type the
97
+ * field argument, in place of taking `ComponentDef<S>` directly.
98
+ */
99
+ export type SchemaOf<D> = D extends ComponentDef<infer S extends ComponentSchema> ? S : never;
100
+ /**
101
+ * `unknown` if `D` is one of the query's declared terms, else an error tuple —
102
+ * the query-seam sibling of system.ts's `DeclaredRead` (§typestate,
103
+ * POLISH_AUDIT #6). `Query.eachChunk`'s cursor and `ArchetypeView`'s column
104
+ * accessors intersect this into their `def` parameter so fetching a component
105
+ * that is NOT a term of the iterating query fails to compile (previously
106
+ * caught only by the dev-mode access check, and only when the system's
107
+ * declaration was itself wrong). Same encoding rules as the system asserts:
108
+ * stable `D extends ComponentDef<any>` constraints keep instantiations
109
+ * mutually assignable, and the conditional keys on the signature's own `D`.
110
+ */
111
+ export type DeclaredQueryTerm<Defs extends readonly ComponentDef<any>[], D> = [D] extends [
112
+ Defs[number]
113
+ ] ? unknown : ["component is not a term of this query — add it with .and(...)", D];
114
+ /** Options bag accepted by `registerComponent` / `registerSparseComponent`. */
115
+ export interface ComponentRegisterOptions {
116
+ /** Debug label for diagnostics — errors then read `'Pos' (component 5)`
117
+ * instead of `component 5`. Never affects behaviour, layout, or hashing. */
118
+ readonly name?: string;
119
+ }
120
+ /**
121
+ * Schema-erased component handle — just the `.id`. Internal, schema-agnostic
122
+ * code (access checks, dirty-set notes, field-id lookup) takes this instead of
123
+ * `ComponentDef`: the callable signature makes `ComponentDef<S>` *invariant* in
124
+ * `S` (a generic `ComponentDef<S>` is not assignable to `ComponentDef`), but
125
+ * every `ComponentDef<S>` is assignable to `ComponentHandle` because it carries
126
+ * `.id`. Use it wherever only the id is read.
127
+ */
128
+ export type ComponentHandle = {
129
+ readonly id: ComponentID;
130
+ };
131
+ /**
132
+ * Mint a callable `ComponentDef` for a freshly-registered component id. The
133
+ * returned function produces a `Bundle` when called (`Pos({x,y})`) and carries
134
+ * its numeric id on a non-enumerable `.id` (invisible to spreads / `JSON`).
135
+ * The single cast bridges the function value to the branded handle type — the
136
+ * `.id` is installed at runtime by `defineProperty` (§10c branded-ID boundary).
137
+ */
138
+ export declare function makeComponentDef<S extends ComponentSchema>(id: ComponentID): ComponentDef<S>;
139
+ export interface Bundle<S extends ComponentSchema = ComponentSchema> {
140
+ readonly def: ComponentDef<S>;
141
+ readonly values: Partial<FieldValues<S>>;
142
+ }
143
+ /** Either a populated bundle or a bare def (tag / all-fields-zero). */
144
+ export type BundleOrDef<S extends ComponentSchema = ComponentSchema> = Bundle<S> | ComponentDef<S>;
145
+ /** Pair a component def with field values to attach. Omitted fields zero-fill;
146
+ * a tag def takes no values (see `ValuesArg`). */
147
+ export declare function bundle<S extends ComponentSchema>(def: ComponentDef<S>, ...values: ValuesArg<S>): Bundle<S>;
148
+ /** Extract the def from a `BundleOrDef`. A bare def is the callable; a bundle a plain object. */
149
+ export declare function bundleDef(item: BundleOrDef): ComponentDef;
150
+ /** Extract the values from a `BundleOrDef` (a bare def contributes no values). */
151
+ export declare function bundleValues(item: BundleOrDef): Readonly<Record<string, number>>;
152
+ /**
153
+ * Compile-time readonly view of a typed array column. Blocks index writes at
154
+ * the type layer.
155
+ *
156
+ * **Advisory, not a runtime barrier:** the value behind this type is the live
157
+ * mutable backing `TypedArray` (`Archetype.getColumnRead` returns
158
+ * `.buf as unknown as ReadonlyColumn`), so a §10c-policed cast can still write
159
+ * through. For mutation use the mutable `Archetype.getColumn` (tick-bumping).
160
+ * Enforced by the escape-hatch lint, not the runtime.
161
+ */
162
+ export interface ReadonlyColumn {
163
+ readonly [index: number]: number;
164
+ readonly length: number;
165
+ }
166
+ /**
167
+ * Compile-time readonly view of a Uint32Array. Blocks index writes at the type
168
+ * layer. **Advisory, not a runtime barrier** — same caveat as `ReadonlyColumn`:
169
+ * the underlying value is the live mutable buffer.
170
+ */
171
+ export interface ReadonlyUint32Array {
172
+ readonly [index: number]: number;
173
+ readonly length: number;
174
+ }
175
+ export {};
176
+ //# sourceMappingURL=component.d.ts.map
@@ -1,4 +1,4 @@
1
- import { Brand, TypedArrayTag } from '../../type_primitives';
1
+ import { Brand, TypedArrayTag } from '../../type_primitives/index.js';
2
2
  export type ComponentID = Brand<number, "component_id">;
3
3
  export declare const asComponentId: (value: number) => ComponentID;
4
4
  /** Core schema type: maps field names to typed array tags. */
@@ -18,6 +18,34 @@ export type TagToTypedArray = {
18
18
  export type FieldValues<S extends ComponentSchema> = {
19
19
  readonly [K in keyof S]: number;
20
20
  };
21
+ /**
22
+ * Values argument tuple for attaching a component of schema `S` — empty for a
23
+ * tag, a single optional partial-values map otherwise. A tag schema
24
+ * (`Record<string, never>`) would otherwise degenerate: `keyof` an
25
+ * index-signature record is `string`, so `Partial<FieldValues<…>>` collapses to
26
+ * `Record<string, number>` and `Frozen({ anything: 1 })` compiles. The
27
+ * conditional forbids values on tags outright; a schema-erased `ComponentDef`
28
+ * falls into the valued branch, so untyped call sites keep the loose shape.
29
+ */
30
+ export type ValuesArg<S extends ComponentSchema> = S extends Record<string, never> ? [] : [values?: Partial<FieldValues<S>>];
31
+ /**
32
+ * `FieldValues` for APIs where the values object is required and complete
33
+ * (`addComponent`'s valued overload, the host-seam `SpawnEntry`). Guards the
34
+ * same tag degeneracy as `ValuesArg`: a tag accepts only the empty object
35
+ * (`Record<string, never>` — every property typed `never`), so
36
+ * `addComponent(e, Frozen, { x: 1 })` is a compile error while the
37
+ * tag-overload-less call sites can still pass `{}`.
38
+ */
39
+ export type CompleteFieldValues<S extends ComponentSchema> = S extends Record<string, never> ? Record<string, never> : FieldValues<S>;
40
+ /**
41
+ * Trailing-argument tuple for the attach surfaces (`ctx.commands.add`'s
42
+ * explicit-values form, `ctx.addSparse`): a tag takes NO values argument, a valued schema REQUIRES a
43
+ * complete one. Encodes the former tag/valued overload pair as one signature,
44
+ * which the typed system seam needs — its `def` parameter is a single
45
+ * declared-access-constrained type param, and per-schema overloads would
46
+ * re-introduce the tag-vs-valued split on top of it.
47
+ */
48
+ export type AttachValuesArg<S extends ComponentSchema> = S extends Record<string, never> ? [] : [values: CompleteFieldValues<S>];
21
49
  /** Maps schema fields to their specific typed array columns. */
22
50
  export type ColumnsForSchema<S extends ComponentSchema> = {
23
51
  readonly [K in keyof S]: TagToTypedArray[S[K]];
@@ -31,6 +59,7 @@ export type ColumnsForSchema<S extends ComponentSchema> = {
31
59
  export type MutableColumnsForSchema<S extends ComponentSchema> = {
32
60
  [K in keyof S]: TagToTypedArray[S[K]];
33
61
  };
62
+ declare const __schema: unique symbol;
34
63
  /**
35
64
  * A component handle. **Callable**: `Pos({ x, y })` produces a `Bundle` (omitted
36
65
  * fields zero-fill at attach), so one varargs shape — `spawn(Pos({x,y}),
@@ -41,13 +70,52 @@ export type MutableColumnsForSchema<S extends ComponentSchema> = {
41
70
  * The numeric component id lives on `.id` (registration order). Consumers treat
42
71
  * the def as an opaque handle; internal code reads `def.id` where it needs the
43
72
  * raw id. The call signature's `S` makes `ComponentDef<{x:"f64"}>` distinct from
44
- * `ComponentDef<{vx:"f64"}>`, so no phantom field is needed for nominal typing.
73
+ * `ComponentDef<{vx:"f64"}>`.
74
+ *
75
+ * The optional `[__schema]` slot never exists at runtime; it re-states `S` in a
76
+ * covariant tuple position so that a TAG def type is not a universal assignment
77
+ * sink. Through the call signature alone every def is assignable to
78
+ * `ComponentDef<Record<string, never>>` (the tag callable takes no required
79
+ * args and any `Bundle` satisfies its return), which would let ONE tag in a
80
+ * system's declared-access union admit every component at compile time
81
+ * (§typestate — `DeclaredRead` and friends in system.ts). With the slot, a
82
+ * valued schema is not assignable to the tag schema (`"f64" ⊀ never`), while
83
+ * schema erasure (`ComponentDef<S>` → bare `ComponentDef`) still works because
84
+ * every schema is assignable to `ComponentSchema`.
45
85
  *
46
86
  * Build one with `makeComponentDef`; never construct by hand.
47
87
  */
48
88
  export interface ComponentDef<S extends ComponentSchema = ComponentSchema> {
49
- (values?: Partial<FieldValues<S>>): Bundle<S>;
89
+ (...values: ValuesArg<S>): Bundle<S>;
50
90
  readonly id: ComponentID;
91
+ readonly [__schema]?: [S];
92
+ }
93
+ /**
94
+ * Recover a def's schema type: `SchemaOf<typeof Pos>` is `{x:"f64", y:"f64"}`.
95
+ * The typed `SystemContext` methods (§typestate) constrain their `def`
96
+ * parameter to the system's declared-access union and use this to type the
97
+ * field argument, in place of taking `ComponentDef<S>` directly.
98
+ */
99
+ export type SchemaOf<D> = D extends ComponentDef<infer S extends ComponentSchema> ? S : never;
100
+ /**
101
+ * `unknown` if `D` is one of the query's declared terms, else an error tuple —
102
+ * the query-seam sibling of system.ts's `DeclaredRead` (§typestate,
103
+ * POLISH_AUDIT #6). `Query.eachChunk`'s cursor and `ArchetypeView`'s column
104
+ * accessors intersect this into their `def` parameter so fetching a component
105
+ * that is NOT a term of the iterating query fails to compile (previously
106
+ * caught only by the dev-mode access check, and only when the system's
107
+ * declaration was itself wrong). Same encoding rules as the system asserts:
108
+ * stable `D extends ComponentDef<any>` constraints keep instantiations
109
+ * mutually assignable, and the conditional keys on the signature's own `D`.
110
+ */
111
+ export type DeclaredQueryTerm<Defs extends readonly ComponentDef<any>[], D> = [D] extends [
112
+ Defs[number]
113
+ ] ? unknown : ["component is not a term of this query — add it with .and(...)", D];
114
+ /** Options bag accepted by `registerComponent` / `registerSparseComponent`. */
115
+ export interface ComponentRegisterOptions {
116
+ /** Debug label for diagnostics — errors then read `'Pos' (component 5)`
117
+ * instead of `component 5`. Never affects behaviour, layout, or hashing. */
118
+ readonly name?: string;
51
119
  }
52
120
  /**
53
121
  * Schema-erased component handle — just the `.id`. Internal, schema-agnostic
@@ -74,8 +142,9 @@ export interface Bundle<S extends ComponentSchema = ComponentSchema> {
74
142
  }
75
143
  /** Either a populated bundle or a bare def (tag / all-fields-zero). */
76
144
  export type BundleOrDef<S extends ComponentSchema = ComponentSchema> = Bundle<S> | ComponentDef<S>;
77
- /** Pair a component def with field values to attach. Omitted fields zero-fill. */
78
- export declare function bundle<S extends ComponentSchema>(def: ComponentDef<S>, values?: Partial<FieldValues<S>>): Bundle<S>;
145
+ /** Pair a component def with field values to attach. Omitted fields zero-fill;
146
+ * a tag def takes no values (see `ValuesArg`). */
147
+ export declare function bundle<S extends ComponentSchema>(def: ComponentDef<S>, ...values: ValuesArg<S>): Bundle<S>;
79
148
  /** Extract the def from a `BundleOrDef`. A bare def is the callable; a bundle a plain object. */
80
149
  export declare function bundleDef(item: BundleOrDef): ComponentDef;
81
150
  /** Extract the values from a `BundleOrDef` (a bare def contributes no values). */
@@ -103,4 +172,5 @@ export interface ReadonlyUint32Array {
103
172
  readonly [index: number]: number;
104
173
  readonly length: number;
105
174
  }
175
+ export {};
106
176
  //# sourceMappingURL=component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/component.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { Brand } from '../../type_primitives/index.cjs';
2
+ import { StoreLayoutListener } from './store_layout_listener.cjs';
3
+ /**
4
+ * An opaque token identifying one of a backend's entry points (one
5
+ * "backend-system"). The engine **never interprets** it — the backend mints it
6
+ * and is the only thing that maps it back to a concrete computation. Carried on
7
+ * `SystemConfig.backendHandle` and handed verbatim to `ComputeBackend.run`.
8
+ *
9
+ * Branded so a stray `number` can't be mistaken for a handle; consumers mint
10
+ * one by casting (the backend owns the id space, like flecs's `run` function
11
+ * pointer or a small index into the backend's entry table).
12
+ */
13
+ export type BackendSystemHandle = Brand<number, "backend_system_handle">;
14
+ /**
15
+ * The engine-side contract a compute backend implements. Composes
16
+ * `StoreLayoutListener` (the already-clean SAB handshake — `setLayout` is called
17
+ * once on attach to seed the layout and again after every SAB grow/extend) with
18
+ * a single generic `run` entry point.
19
+ *
20
+ * A backend is attached opt-in via `ECS.attachBackend(backend)`, which also
21
+ * subscribes it as a layout listener, so a backend re-walks the layout on attach
22
+ * and republish for free.
23
+ */
24
+ export interface ComputeBackend extends StoreLayoutListener {
25
+ /**
26
+ * Execute the backend-system identified by `handle`. Called by the
27
+ * `Schedule` in place of the system's `fn` closure, inside the same
28
+ * `accessCheck` span — so the system's declared `writes` authorise whatever
29
+ * shared-memory columns the backend mutates, exactly as a TS body that calls
30
+ * out to the backend would be authorised today.
31
+ *
32
+ * `handle` is opaque to the engine; it is one the backend minted and the
33
+ * engine merely round-trips from `SystemConfig.backendHandle`.
34
+ */
35
+ run(handle: BackendSystemHandle): void;
36
+ }
37
+ //# sourceMappingURL=compute_backend.d.ts.map
@@ -1,5 +1,5 @@
1
- import { Brand } from '../../type_primitives';
2
- import { StoreLayoutListener } from './store_layout_listener';
1
+ import { Brand } from '../../type_primitives/index.js';
2
+ import { StoreLayoutListener } from './store_layout_listener.js';
3
3
  /**
4
4
  * An opaque token identifying one of a backend's entry points (one
5
5
  * "backend-system"). The engine **never interprets** it — the backend mints it
@@ -0,0 +1,7 @@
1
+ import { ComponentHandle } from './component.cjs';
2
+ export declare function setComponentDebugName(def: ComponentHandle, name: string): void;
3
+ /** The raw registration name (`"Pos"`), or `undefined` when the def is unnamed. */
4
+ export declare function componentDebugName(def: ComponentHandle): string | undefined;
5
+ /** `'Pos' (component 5)` when named at registration, else `component 5`. */
6
+ export declare function componentLabel(def: ComponentHandle): string;
7
+ //# sourceMappingURL=debug_names.d.ts.map
@@ -0,0 +1,7 @@
1
+ import { ComponentHandle } from './component.js';
2
+ export declare function setComponentDebugName(def: ComponentHandle, name: string): void;
3
+ /** The raw registration name (`"Pos"`), or `undefined` when the def is unnamed. */
4
+ export declare function componentDebugName(def: ComponentHandle): string | undefined;
5
+ /** `'Pos' (component 5)` when named at registration, else `component 5`. */
6
+ export declare function componentLabel(def: ComponentHandle): string;
7
+ //# sourceMappingURL=debug_names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug_names.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/debug_names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;KAWK;AAEL,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAE9E;AAED,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,GAAG,SAAS,CAE3E;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAG3D"}
@@ -0,0 +1,55 @@
1
+ import { ComponentDef } from './component.cjs';
2
+ import { EntityID } from './entity.cjs';
3
+ import { StructuralObserverEvents } from './store.cjs';
4
+ /** What the drain policy needs from `Store` — closure-injected (the
5
+ * `RelationServiceHost` style) so nothing new goes public on `Store`. All
6
+ * calls are flush-granularity, never per-entity. */
7
+ export interface DeferredCommandHost {
8
+ /** Drain + apply the pending component additions. Each applier fully
9
+ * drains its buffer(s) and owns its dirty/0-crossing bookkeeping. */
10
+ readonly applyAdds: () => void;
11
+ readonly applyRemoves: () => void;
12
+ readonly applyDestroys: () => void;
13
+ readonly applyToggles: () => void;
14
+ /** Hot-path gates — live counts of observed components (#531 / #677).
15
+ * While both are 0 the flush takes the byte-for-byte fast path. */
16
+ readonly structuralObserverCount: () => number;
17
+ readonly toggleObserverCount: () => number;
18
+ /** The observer-registry dispatch hook, or null (ECS installs it after
19
+ * construction, so it is re-read per flush). */
20
+ readonly structuralObserverHook: () => ((ev: StructuralObserverEvents) => void) | null;
21
+ }
22
+ export declare class DeferredCommandBuffer {
23
+ readonly destroyIds: EntityID[];
24
+ readonly addIds: EntityID[];
25
+ readonly addDefs: ComponentDef[];
26
+ readonly addValues: Record<string, number>[];
27
+ readonly removeIds: EntityID[];
28
+ readonly removeDefs: ComponentDef[];
29
+ readonly toggleIds: EntityID[];
30
+ readonly toggleDisable: boolean[];
31
+ /** Re-entrancy guard for the observed fixed-point loop. An observer
32
+ * callback must enqueue and let the loop settle it — a nested
33
+ * `ctx.flush()` becomes a no-op; the outer loop drains whatever the
34
+ * callback queued. */
35
+ private _flushing;
36
+ private readonly host;
37
+ /** Shared effective-event scratch, reset per observed round and handed to
38
+ * the dispatch hook. Owned by `Store` (its appliers collect into it). */
39
+ private readonly obsEvents;
40
+ constructor(host: DeferredCommandHost, obsEvents: StructuralObserverEvents);
41
+ queueDestroy(id: EntityID): void;
42
+ queueAdd(id: EntityID, def: ComponentDef, values: Record<string, number>): void;
43
+ queueRemove(id: EntityID, def: ComponentDef): void;
44
+ queueToggle(id: EntityID, disable: boolean): void;
45
+ get destroyCount(): number;
46
+ get structuralCount(): number;
47
+ get toggleCount(): number;
48
+ /** Drain buffered destroys outside the structural flush. No-ops while the
49
+ * observed fixed point owns the flush — the loop drains destroys itself,
50
+ * and a re-entrant call would collect into the shared event scratch
51
+ * mid-dispatch and corrupt it (mirrors the `flushStructural` guard). */
52
+ flushDestroyed(): void;
53
+ flushStructural(): void;
54
+ }
55
+ //# sourceMappingURL=deferred_commands.d.ts.map
@@ -0,0 +1,55 @@
1
+ import { ComponentDef } from './component.js';
2
+ import { EntityID } from './entity.js';
3
+ import { StructuralObserverEvents } from './store.js';
4
+ /** What the drain policy needs from `Store` — closure-injected (the
5
+ * `RelationServiceHost` style) so nothing new goes public on `Store`. All
6
+ * calls are flush-granularity, never per-entity. */
7
+ export interface DeferredCommandHost {
8
+ /** Drain + apply the pending component additions. Each applier fully
9
+ * drains its buffer(s) and owns its dirty/0-crossing bookkeeping. */
10
+ readonly applyAdds: () => void;
11
+ readonly applyRemoves: () => void;
12
+ readonly applyDestroys: () => void;
13
+ readonly applyToggles: () => void;
14
+ /** Hot-path gates — live counts of observed components (#531 / #677).
15
+ * While both are 0 the flush takes the byte-for-byte fast path. */
16
+ readonly structuralObserverCount: () => number;
17
+ readonly toggleObserverCount: () => number;
18
+ /** The observer-registry dispatch hook, or null (ECS installs it after
19
+ * construction, so it is re-read per flush). */
20
+ readonly structuralObserverHook: () => ((ev: StructuralObserverEvents) => void) | null;
21
+ }
22
+ export declare class DeferredCommandBuffer {
23
+ readonly destroyIds: EntityID[];
24
+ readonly addIds: EntityID[];
25
+ readonly addDefs: ComponentDef[];
26
+ readonly addValues: Record<string, number>[];
27
+ readonly removeIds: EntityID[];
28
+ readonly removeDefs: ComponentDef[];
29
+ readonly toggleIds: EntityID[];
30
+ readonly toggleDisable: boolean[];
31
+ /** Re-entrancy guard for the observed fixed-point loop. An observer
32
+ * callback must enqueue and let the loop settle it — a nested
33
+ * `ctx.flush()` becomes a no-op; the outer loop drains whatever the
34
+ * callback queued. */
35
+ private _flushing;
36
+ private readonly host;
37
+ /** Shared effective-event scratch, reset per observed round and handed to
38
+ * the dispatch hook. Owned by `Store` (its appliers collect into it). */
39
+ private readonly obsEvents;
40
+ constructor(host: DeferredCommandHost, obsEvents: StructuralObserverEvents);
41
+ queueDestroy(id: EntityID): void;
42
+ queueAdd(id: EntityID, def: ComponentDef, values: Record<string, number>): void;
43
+ queueRemove(id: EntityID, def: ComponentDef): void;
44
+ queueToggle(id: EntityID, disable: boolean): void;
45
+ get destroyCount(): number;
46
+ get structuralCount(): number;
47
+ get toggleCount(): number;
48
+ /** Drain buffered destroys outside the structural flush. No-ops while the
49
+ * observed fixed point owns the flush — the loop drains destroys itself,
50
+ * and a re-entrant call would collect into the shared event scratch
51
+ * mid-dispatch and corrupt it (mirrors the `flushStructural` guard). */
52
+ flushDestroyed(): void;
53
+ flushStructural(): void;
54
+ }
55
+ //# sourceMappingURL=deferred_commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deferred_commands.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/deferred_commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AASxD;;oDAEoD;AACpD,MAAM,WAAW,mBAAmB;IACnC;yEACqE;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,IAAI,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,IAAI,CAAC;IAClC,QAAQ,CAAC,aAAa,EAAE,MAAM,IAAI,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,MAAM,IAAI,CAAC;IAClC;uEACmE;IACnE,QAAQ,CAAC,uBAAuB,EAAE,MAAM,MAAM,CAAC;IAC/C,QAAQ,CAAC,mBAAmB,EAAE,MAAM,MAAM,CAAC;IAC3C;oDACgD;IAChD,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC,EAAE,EAAE,wBAAwB,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;CACvF;AAED,qBAAa,qBAAqB;IAMjC,SAAgB,UAAU,EAAE,QAAQ,EAAE,CAAM;IAC5C,SAAgB,MAAM,EAAE,QAAQ,EAAE,CAAM;IACxC,SAAgB,OAAO,EAAE,YAAY,EAAE,CAAM;IAC7C,SAAgB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAM;IACzD,SAAgB,SAAS,EAAE,QAAQ,EAAE,CAAM;IAC3C,SAAgB,UAAU,EAAE,YAAY,EAAE,CAAM;IAIhD,SAAgB,SAAS,EAAE,QAAQ,EAAE,CAAM;IAC3C,SAAgB,aAAa,EAAE,OAAO,EAAE,CAAM;IAE9C;;;0BAGsB;IACtB,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAsB;IAC3C;6EACyE;IACzE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA2B;gBAEzC,IAAI,EAAE,mBAAmB,EAAE,SAAS,EAAE,wBAAwB;IAKnE,YAAY,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI;IAIhC,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAM/E,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,YAAY,GAAG,IAAI;IAKlD,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAKxD,IAAW,YAAY,IAAI,MAAM,CAEhC;IAED,IAAW,eAAe,IAAI,MAAM,CAEnC;IAED,IAAW,WAAW,IAAI,MAAM,CAE/B;IAED;;;4EAGwE;IACjE,cAAc,IAAI,IAAI;IAKtB,eAAe,IAAI,IAAI;CA0F9B"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Dev-mode dispatch tracer.
3
+ *
4
+ * Singleton buffer that captures `(callsite, channel, op, key)` per ECS /
5
+ * action dispatch when `VISUAL_INTEL_TRACE=1` is set in the environment.
6
+ * Compile-time gated by `DEV`, so production builds dead-code-eliminate
7
+ * every record() call. Output is a deterministic JSON snapshot the
8
+ * `visual-intel` service can ingest as a third channel of evidence
9
+ * alongside the existing static + symbol-propagation scans.
10
+ *
11
+ * Identity model. The engine has no access to source-level binding names
12
+ * (`ContactEvent`, `ConfigRes`) at runtime — `eventKey("Contact")` returns
13
+ * `Symbol("Contact")` and the variable name is erased. The tracer records the
14
+ * runtime-available identifier:
15
+ *
16
+ * - ECS events / resources → the Symbol description (`label`).
17
+ * - Actions → the numeric `def.id`.
18
+ *
19
+ * Resolution back to bindings happens in `visual-intel`, which already
20
+ * extracts `{ binding, label }` declarations for events / resources and
21
+ * `{ binding, id_expr }` for actions; the matching there is unambiguous.
22
+ *
23
+ * Callsite resolution. `new Error().stack` inside `record()`, walk the
24
+ * frames, drop everything inside `packages/engine/src/core/ecs/` (this
25
+ * file + the dispatcher seam), return the first repo-relative path. Stack-
26
+ * line strings are cached so repeat dispatches from the same site are
27
+ * O(1) after the first hit. The walk itself lives in the pure
28
+ * `resolveCallsiteFromStack()` helper so it can be driven by a synthetic
29
+ * stack in tests.
30
+ *
31
+ * Activation. `record()` is *unconditional* — it records on every call. The
32
+ * `isActive()` env-var gate is applied by the *callers* (`ecs.ts` /
33
+ * `query.ts`, all `if (DEV && dispatchTrace.isActive())`), not inside
34
+ * `record()`. This keeps the gate in one place — the dispatch hot path —
35
+ * where `DEV === false` dead-code-eliminates the whole branch in prod.
36
+ */
37
+ export type DispatchChannel = "ecs-events" | "actions" | "resources";
38
+ export type EcsEventOp = "emit" | "read";
39
+ export type ActionOp = "send_action" | "handle_action";
40
+ export type ResourceOp = "read" | "write" | "register" | "remove";
41
+ export interface DispatchTraceEntry {
42
+ /** Symbol description (events / resources) or numeric `def.id` (actions). */
43
+ readonly key: string | number;
44
+ /** Repo-relative POSIX path of the calling file. */
45
+ readonly file: string;
46
+ readonly count: number;
47
+ }
48
+ export interface DispatchTraceSnapshot {
49
+ readonly schemaVersion: 1;
50
+ readonly capturedAt: string;
51
+ readonly channels: {
52
+ readonly "ecs-events": Record<EcsEventOp, DispatchTraceEntry[]>;
53
+ readonly actions: Record<ActionOp, DispatchTraceEntry[]>;
54
+ readonly resources: Record<ResourceOp, DispatchTraceEntry[]>;
55
+ };
56
+ }
57
+ declare class DispatchTrace {
58
+ private activeCache;
59
+ private repoRootCache;
60
+ private buf;
61
+ private callsiteCache;
62
+ isActive(): boolean;
63
+ private repoRoot;
64
+ private resolveCallsite;
65
+ private record;
66
+ recordEmit(label: string): void;
67
+ recordRead(label: string): void;
68
+ recordResourceRead(label: string): void;
69
+ recordResourceWrite(label: string): void;
70
+ recordResourceRegister(label: string): void;
71
+ recordResourceRemove(label: string): void;
72
+ recordSendAction(actId: number): void;
73
+ recordHandleAction(actId: number): void;
74
+ snapshot(): DispatchTraceSnapshot;
75
+ reset(): void;
76
+ }
77
+ declare function parseFrameFile(line: string): string | null;
78
+ /**
79
+ * Walk a stack string, drop frames inside the engine ECS package, and return
80
+ * the first non-engine frame as a repo-relative POSIX path (or `null` if the
81
+ * stack has no attributable frame). Pure so tests can drive it with a
82
+ * synthetic stack; the optional `cache` memoises per-line results for the hot
83
+ * dispatch path. Mutates `cache` when supplied.
84
+ */
85
+ declare function resolveCallsiteFromStack(stack: string | null, repoRoot: string, cache?: Map<string, string | null>): string | null;
86
+ export declare const dispatchTrace: DispatchTrace;
87
+ export declare const _dispatchTraceInternals: {
88
+ parseFrameFile: typeof parseFrameFile;
89
+ resolveCallsiteFromStack: typeof resolveCallsiteFromStack;
90
+ create: () => DispatchTrace;
91
+ };
92
+ export {};
93
+ //# sourceMappingURL=dispatch_trace.d.ts.map
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Singleton buffer that captures `(callsite, channel, op, key)` per ECS /
5
5
  * action dispatch when `VISUAL_INTEL_TRACE=1` is set in the environment.
6
- * Compile-time gated by `__DEV__`, so production builds dead-code-eliminate
6
+ * Compile-time gated by `DEV`, so production builds dead-code-eliminate
7
7
  * every record() call. Output is a deterministic JSON snapshot the
8
8
  * `visual-intel` service can ingest as a third channel of evidence
9
9
  * alongside the existing static + symbol-propagation scans.
@@ -30,9 +30,9 @@
30
30
  *
31
31
  * Activation. `record()` is *unconditional* — it records on every call. The
32
32
  * `isActive()` env-var gate is applied by the *callers* (`ecs.ts` /
33
- * `query.ts`, all `if (__DEV__ && dispatchTrace.isActive())`), not inside
33
+ * `query.ts`, all `if (DEV && dispatchTrace.isActive())`), not inside
34
34
  * `record()`. This keeps the gate in one place — the dispatch hot path —
35
- * where `__DEV__ === false` dead-code-eliminates the whole branch in prod.
35
+ * where `DEV === false` dead-code-eliminates the whole branch in prod.
36
36
  */
37
37
  export type DispatchChannel = "ecs-events" | "actions" | "resources";
38
38
  export type EcsEventOp = "emit" | "read";