@oasys/oecs 0.3.1 → 0.4.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 (204) hide show
  1. package/README.md +196 -267
  2. package/dist/array-CxbPyiHO.cjs +1 -0
  3. package/dist/array-uFR7Q8fU.js +132 -0
  4. package/dist/core/ecs/access_check.d.ts +77 -0
  5. package/dist/core/ecs/access_check.d.ts.map +1 -0
  6. package/dist/core/ecs/archetype.d.ts +474 -0
  7. package/dist/core/ecs/archetype.d.ts.map +1 -0
  8. package/dist/core/ecs/builtin_relations.d.ts +43 -0
  9. package/dist/core/ecs/builtin_relations.d.ts.map +1 -0
  10. package/dist/core/ecs/command_log.d.ts +113 -0
  11. package/dist/core/ecs/command_log.d.ts.map +1 -0
  12. package/dist/core/ecs/component.d.ts +106 -0
  13. package/dist/core/ecs/component.d.ts.map +1 -0
  14. package/dist/core/ecs/compute_backend.d.ts +37 -0
  15. package/dist/core/ecs/compute_backend.d.ts.map +1 -0
  16. package/dist/core/ecs/dispatch_trace.d.ts +93 -0
  17. package/dist/core/ecs/dispatch_trace.d.ts.map +1 -0
  18. package/dist/core/ecs/ecs.d.ts +533 -0
  19. package/dist/core/ecs/ecs.d.ts.map +1 -0
  20. package/dist/core/ecs/ecs_memory.d.ts +179 -0
  21. package/dist/core/ecs/ecs_memory.d.ts.map +1 -0
  22. package/dist/core/ecs/entity.d.ts +28 -0
  23. package/dist/core/ecs/entity.d.ts.map +1 -0
  24. package/dist/core/ecs/event.d.ts +54 -0
  25. package/dist/core/ecs/event.d.ts.map +1 -0
  26. package/dist/core/ecs/frame_trace.d.ts +133 -0
  27. package/dist/core/ecs/frame_trace.d.ts.map +1 -0
  28. package/dist/core/ecs/host_commands.d.ts +252 -0
  29. package/dist/core/ecs/host_commands.d.ts.map +1 -0
  30. package/dist/core/ecs/index.d.ts +41 -0
  31. package/dist/core/ecs/index.d.ts.map +1 -0
  32. package/dist/core/ecs/observer.d.ts +142 -0
  33. package/dist/core/ecs/observer.d.ts.map +1 -0
  34. package/dist/core/ecs/query.d.ts +557 -0
  35. package/dist/core/ecs/query.d.ts.map +1 -0
  36. package/dist/core/ecs/ref.d.ts +31 -0
  37. package/dist/core/ecs/ref.d.ts.map +1 -0
  38. package/dist/core/ecs/relation.d.ts +231 -0
  39. package/dist/core/ecs/relation.d.ts.map +1 -0
  40. package/dist/core/ecs/resource.d.ts +33 -0
  41. package/dist/core/ecs/resource.d.ts.map +1 -0
  42. package/dist/core/ecs/resume.d.ts +85 -0
  43. package/dist/core/ecs/resume.d.ts.map +1 -0
  44. package/dist/core/ecs/run_condition.d.ts +75 -0
  45. package/dist/core/ecs/run_condition.d.ts.map +1 -0
  46. package/dist/core/ecs/schedule.d.ts +133 -0
  47. package/dist/core/ecs/schedule.d.ts.map +1 -0
  48. package/dist/core/ecs/sparse_store.d.ts +107 -0
  49. package/dist/core/ecs/sparse_store.d.ts.map +1 -0
  50. package/dist/core/ecs/store.d.ts +1149 -0
  51. package/dist/core/ecs/store.d.ts.map +1 -0
  52. package/dist/core/ecs/store_layout_listener.d.ts +23 -0
  53. package/dist/core/ecs/store_layout_listener.d.ts.map +1 -0
  54. package/dist/core/ecs/system.d.ts +134 -0
  55. package/dist/core/ecs/system.d.ts.map +1 -0
  56. package/dist/core/ecs/utils/arrays.d.ts +7 -0
  57. package/dist/core/ecs/utils/arrays.d.ts.map +1 -0
  58. package/dist/core/ecs/utils/constants.d.ts +12 -0
  59. package/dist/core/ecs/utils/constants.d.ts.map +1 -0
  60. package/dist/core/ecs/utils/error.d.ts +51 -0
  61. package/dist/core/ecs/utils/error.d.ts.map +1 -0
  62. package/dist/core/reactive/array.d.ts +24 -0
  63. package/dist/core/reactive/array.d.ts.map +1 -0
  64. package/dist/core/reactive/index.cjs +1 -0
  65. package/dist/core/reactive/index.d.ts +10 -0
  66. package/dist/core/reactive/index.d.ts.map +1 -0
  67. package/dist/core/reactive/index.js +17 -0
  68. package/dist/core/reactive/interop.d.ts +19 -0
  69. package/dist/core/reactive/interop.d.ts.map +1 -0
  70. package/dist/core/reactive/kernel.d.ts +71 -0
  71. package/dist/core/reactive/kernel.d.ts.map +1 -0
  72. package/dist/core/reactive/map.d.ts +16 -0
  73. package/dist/core/reactive/map.d.ts.map +1 -0
  74. package/dist/core/reactive/struct.d.ts +10 -0
  75. package/dist/core/reactive/struct.d.ts.map +1 -0
  76. package/dist/core/store/__generated__/abi.d.ts +43 -0
  77. package/dist/core/store/__generated__/abi.d.ts.map +1 -0
  78. package/dist/core/store/action_ring.d.ts +136 -0
  79. package/dist/core/store/action_ring.d.ts.map +1 -0
  80. package/dist/core/store/allocator.d.ts +238 -0
  81. package/dist/core/store/allocator.d.ts.map +1 -0
  82. package/dist/core/store/buffer_backed_column.d.ts +69 -0
  83. package/dist/core/store/buffer_backed_column.d.ts.map +1 -0
  84. package/dist/core/store/column_store.d.ts +265 -0
  85. package/dist/core/store/column_store.d.ts.map +1 -0
  86. package/dist/core/store/command_dispatch.d.ts +52 -0
  87. package/dist/core/store/command_dispatch.d.ts.map +1 -0
  88. package/dist/core/store/command_ring.d.ts +107 -0
  89. package/dist/core/store/command_ring.d.ts.map +1 -0
  90. package/dist/core/store/descriptor.d.ts +80 -0
  91. package/dist/core/store/descriptor.d.ts.map +1 -0
  92. package/dist/core/store/entity_index.d.ts +108 -0
  93. package/dist/core/store/entity_index.d.ts.map +1 -0
  94. package/dist/core/store/event_ring.d.ts +95 -0
  95. package/dist/core/store/event_ring.d.ts.map +1 -0
  96. package/dist/core/store/extend.d.ts +109 -0
  97. package/dist/core/store/extend.d.ts.map +1 -0
  98. package/dist/core/store/grow.d.ts +39 -0
  99. package/dist/core/store/grow.d.ts.map +1 -0
  100. package/dist/core/store/header.d.ts +64 -0
  101. package/dist/core/store/header.d.ts.map +1 -0
  102. package/dist/core/store/index.d.ts +16 -0
  103. package/dist/core/store/index.d.ts.map +1 -0
  104. package/dist/core/store/region_table.d.ts +74 -0
  105. package/dist/core/store/region_table.d.ts.map +1 -0
  106. package/dist/core/store/snapshot.d.ts +43 -0
  107. package/dist/core/store/snapshot.d.ts.map +1 -0
  108. package/dist/core/store/state_hash.d.ts +38 -0
  109. package/dist/core/store/state_hash.d.ts.map +1 -0
  110. package/dist/core/store/store_regions.d.ts +38 -0
  111. package/dist/core/store/store_regions.d.ts.map +1 -0
  112. package/dist/extensions/editor/editor.d.ts +149 -0
  113. package/dist/extensions/editor/editor.d.ts.map +1 -0
  114. package/dist/extensions/editor/field_handle.d.ts +35 -0
  115. package/dist/extensions/editor/field_handle.d.ts.map +1 -0
  116. package/dist/extensions/editor/index.cjs +1 -0
  117. package/dist/extensions/editor/index.d.ts +21 -0
  118. package/dist/extensions/editor/index.d.ts.map +1 -0
  119. package/dist/extensions/editor/index.js +209 -0
  120. package/dist/extensions/reactive/ecs_sync.d.ts +210 -0
  121. package/dist/extensions/reactive/ecs_sync.d.ts.map +1 -0
  122. package/dist/extensions/reactive/index.cjs +1 -0
  123. package/dist/extensions/reactive/index.d.ts +23 -0
  124. package/dist/extensions/reactive/index.d.ts.map +1 -0
  125. package/dist/extensions/reactive/index.js +225 -0
  126. package/dist/extensions/solid/index.cjs +1 -0
  127. package/dist/extensions/solid/index.d.ts +6 -0
  128. package/dist/extensions/solid/index.d.ts.map +1 -0
  129. package/dist/extensions/solid/index.js +32 -0
  130. package/dist/extensions/solid/kernel_solid.d.ts +42 -0
  131. package/dist/extensions/solid/kernel_solid.d.ts.map +1 -0
  132. package/dist/index.cjs +2 -1
  133. package/dist/index.d.ts +16 -12
  134. package/dist/index.d.ts.map +1 -1
  135. package/dist/index.js +8565 -1310
  136. package/dist/interop-CT-REx0W.cjs +1 -0
  137. package/dist/interop-CcY6ASQc.js +18 -0
  138. package/dist/kernel-DgyrLFjW.js +227 -0
  139. package/dist/kernel-yWV3XnAb.cjs +1 -0
  140. package/dist/log/console_sink.d.ts +4 -0
  141. package/dist/log/console_sink.d.ts.map +1 -0
  142. package/dist/log/index.d.ts +3 -0
  143. package/dist/log/index.d.ts.map +1 -0
  144. package/dist/log/logger.d.ts +27 -0
  145. package/dist/log/logger.d.ts.map +1 -0
  146. package/dist/primitives.cjs +1 -0
  147. package/dist/primitives.d.ts +18 -0
  148. package/dist/primitives.d.ts.map +1 -0
  149. package/dist/primitives.js +44 -0
  150. package/dist/shared-BXSZnxx4.cjs +1 -0
  151. package/dist/shared-C678TAPY.js +99 -0
  152. package/dist/shared.cjs +1 -0
  153. package/dist/shared.d.ts +22 -0
  154. package/dist/shared.d.ts.map +1 -0
  155. package/dist/shared.js +7 -0
  156. package/dist/topological_sort-DlRpSrxu.js +391 -0
  157. package/dist/topological_sort-WAT-VHb-.cjs +1 -0
  158. package/dist/type_primitives/assertions.d.ts +12 -8
  159. package/dist/type_primitives/assertions.d.ts.map +1 -1
  160. package/dist/type_primitives/binary_heap/binary_heap.d.ts +6 -2
  161. package/dist/type_primitives/binary_heap/binary_heap.d.ts.map +1 -1
  162. package/dist/type_primitives/bitset/bitset.d.ts +16 -4
  163. package/dist/type_primitives/bitset/bitset.d.ts.map +1 -1
  164. package/dist/type_primitives/brand.d.ts +6 -1
  165. package/dist/type_primitives/brand.d.ts.map +1 -1
  166. package/dist/type_primitives/error.d.ts +4 -0
  167. package/dist/type_primitives/error.d.ts.map +1 -1
  168. package/dist/type_primitives/index.d.ts +3 -0
  169. package/dist/type_primitives/index.d.ts.map +1 -1
  170. package/dist/type_primitives/sparse_map/sparse_map.d.ts +7 -3
  171. package/dist/type_primitives/sparse_map/sparse_map.d.ts.map +1 -1
  172. package/dist/type_primitives/sparse_set/sparse_set.d.ts +4 -0
  173. package/dist/type_primitives/sparse_set/sparse_set.d.ts.map +1 -1
  174. package/dist/type_primitives/topological_sort/topological_sort.d.ts +7 -3
  175. package/dist/type_primitives/topological_sort/topological_sort.d.ts.map +1 -1
  176. package/dist/type_primitives/typed_arrays/typed_arrays.d.ts +53 -16
  177. package/dist/type_primitives/typed_arrays/typed_arrays.d.ts.map +1 -1
  178. package/dist/utils/arrays.d.ts +1 -1
  179. package/dist/utils/arrays.d.ts.map +1 -1
  180. package/dist/utils/error.d.ts +2 -20
  181. package/dist/utils/error.d.ts.map +1 -1
  182. package/package.json +36 -9
  183. package/dist/archetype.d.ts +0 -108
  184. package/dist/archetype.d.ts.map +0 -1
  185. package/dist/component.d.ts +0 -45
  186. package/dist/component.d.ts.map +0 -1
  187. package/dist/ecs.d.ts +0 -104
  188. package/dist/ecs.d.ts.map +0 -1
  189. package/dist/entity.d.ts +0 -11
  190. package/dist/entity.d.ts.map +0 -1
  191. package/dist/event.d.ts +0 -30
  192. package/dist/event.d.ts.map +0 -1
  193. package/dist/query.d.ts +0 -94
  194. package/dist/query.d.ts.map +0 -1
  195. package/dist/ref.d.ts +0 -23
  196. package/dist/ref.d.ts.map +0 -1
  197. package/dist/resource.d.ts +0 -23
  198. package/dist/resource.d.ts.map +0 -1
  199. package/dist/schedule.d.ts +0 -45
  200. package/dist/schedule.d.ts.map +0 -1
  201. package/dist/store.d.ts +0 -118
  202. package/dist/store.d.ts.map +0 -1
  203. package/dist/system.d.ts +0 -16
  204. package/dist/system.d.ts.map +0 -1
@@ -0,0 +1,113 @@
1
+ import { ECS } from './ecs';
2
+ import { HostCommand, HostCommandQueue, HostCommandSink } from './host_commands';
3
+ /** One recorded update tick: the commands the apply system drained at this
4
+ * tick's update-phase head, plus the `dt` passed to `world.update(dt)`. Replay
5
+ * MUST re-issue `update(dt)` for every recorded tick — even an empty one — since
6
+ * `dt` itself drives the sim (movement, timers), not just the commands. */
7
+ export interface RecordedTick {
8
+ /** The ECS tick (`ctx.ecsTick`) this bucket belongs to. */
9
+ readonly tick: number;
10
+ /** The `dt` `world.update(dt)` was called with for this tick. */
11
+ readonly dt: number;
12
+ /** Commands applied this tick, in apply order (typed queue first, then ring),
13
+ * `onSpawned` stripped. */
14
+ readonly commands: readonly HostCommand[];
15
+ }
16
+ /**
17
+ * A recorded session: the `seed` it ran under, the seed-time commands drained at
18
+ * startup, and the per-tick command stream. Plain, serializable data — the
19
+ * record-side mirror of the typed `HostCommand` vocabulary. Replay it with
20
+ * {@link replayCommandLog}; persist it with {@link serializeCommandLog}.
21
+ */
22
+ export interface CommandLog {
23
+ /** Session seed — the implementer's deterministic input (e.g. an RNG seed).
24
+ * Opaque to the engine (the core tick takes only `dt`); carried so a replay
25
+ * rebuilds the world the same way the original was built. */
26
+ readonly seed: number;
27
+ /** Commands drained at the PRE_STARTUP head (seed-time edits), applied before
28
+ * the first update tick. Enqueued BEFORE `world.startup()` on replay. */
29
+ readonly startup: readonly HostCommand[];
30
+ /** One entry per update tick, in order. */
31
+ readonly ticks: readonly RecordedTick[];
32
+ }
33
+ /**
34
+ * The record side of record/replay: a {@link HostCommandSink} the apply system
35
+ * feeds. Construct one with the session `seed`, hand it to
36
+ * `installHostCommandSeam(world, { recorder })`, and it accumulates the
37
+ * command stream as the ECS ticks. Read it back with {@link log} (a live view,
38
+ * ready to {@link serializeCommandLog serialize}).
39
+ *
40
+ * Bucketing: STARTUP-phase drains (which never call {@link openTick}) append to
41
+ * the {@link startup} bucket; each update-phase drain {@link openTick}s its tick
42
+ * — multiple update-phase drains in one tick reuse the same bucket (keyed by the
43
+ * ECS tick), so a frame's commands stay together. The apply system runs every
44
+ * tick, so every tick's `dt` is recorded even when no commands were applied.
45
+ *
46
+ * One recorder per session — don't share across worlds.
47
+ */
48
+ export declare class HostCommandRecorder implements HostCommandSink {
49
+ /** Session seed, echoed into the produced {@link CommandLog}. */
50
+ readonly seed: number;
51
+ private readonly _startup;
52
+ private readonly _ticks;
53
+ /** Where {@link record} appends. Defaults to the startup bucket (seed-time
54
+ * drains happen before any `openTick`); each `openTick` repoints it. */
55
+ private sink;
56
+ constructor(seed?: number);
57
+ openTick(tick: number, dt: number): void;
58
+ readonly record: (cmd: HostCommand) => void;
59
+ /** A live {@link CommandLog} view over the accumulated stream — not a copy.
60
+ * Serialize it (which deep-copies through JSON) before mutating the world
61
+ * further if you need a stable snapshot. */
62
+ log(): CommandLog;
63
+ }
64
+ /** Serialize a {@link CommandLog} to a JSON string. `EntityID` is a plain number
65
+ * and round-trips as-is; a `ComponentDef` is a callable, so the replacer writes
66
+ * it as `{ [DEF_TAG]: id }`. (The recorder already stripped `onSpawned`, the
67
+ * only other non-serializable member.)
68
+ *
69
+ * Throws {@link ECS_ERROR.COMMAND_LOG_TAG_COLLISION} if any non-def object in the
70
+ * log (i.e. a command's `values` map) owns a field named {@link DEF_TAG}: the
71
+ * reviver tags defs in-band, so such a value would be silently revived as a def,
72
+ * dropping the real field data. Field names are arbitrary, so this is reachable;
73
+ * failing here keeps the round-trip lossless instead of corrupting on parse. */
74
+ export declare function serializeCommandLog(log: CommandLog): string;
75
+ /** Parse a {@link CommandLog} from {@link serializeCommandLog} output. */
76
+ export declare function deserializeCommandLog(json: string): CommandLog;
77
+ /** Outcome of {@link replayCommandLog}. */
78
+ export interface ReplayResult {
79
+ /** Seed-time commands re-applied before the first tick. */
80
+ readonly startupCommands: number;
81
+ /** Update ticks replayed. */
82
+ readonly ticks: number;
83
+ /** Per-tick `stateHash` captured after each `update`, in tick order — empty
84
+ * unless the world is deterministic (or `hash` was forced). Compare against
85
+ * the original run's per-tick hashes to prove the replay matched (ADR-0020). */
86
+ readonly stateHashes: readonly number[];
87
+ }
88
+ /** Options for {@link replayCommandLog}. */
89
+ export interface ReplayOptions {
90
+ /** Capture `world.stateHash()` after each tick. Defaults to the world's
91
+ * `deterministic` flag — a deterministic world is hashed, a non-deterministic
92
+ * one is not (its `stateHash` would throw, ADR-0020). Force `true` only on a
93
+ * deterministic world. */
94
+ readonly hash?: boolean;
95
+ }
96
+ /**
97
+ * Replay a recorded {@link CommandLog} against `world`, reproducing the original
98
+ * session tick-for-tick. `world` must be FRESH and NOT yet started, built
99
+ * identically to the recorded run (same components registered in the same order,
100
+ * same systems, same `seed` from `log.seed`) and seam-installed — pass the
101
+ * `HostCommandQueue` `installHostCommandSeam` returned as `queue`. The driver
102
+ * owns startup: it enqueues the seed-time commands, calls `world.startup()`
103
+ * (which drains them at PRE_STARTUP), then for each recorded tick enqueues that
104
+ * tick's commands and calls `world.update(dt)` with the recorded `dt`.
105
+ *
106
+ * Determinism (ADR-0020): with `{ deterministic: true }` the per-tick
107
+ * `stateHashes` this returns must equal the original run's — that equality is
108
+ * replay fidelity. Identity caveat (§85): a despawned-then-respawned entity gets
109
+ * a fresh id, but because spawn order is reproduced, every recorded id still
110
+ * resolves to the same entity on replay.
111
+ */
112
+ export declare function replayCommandLog(world: ECS, queue: HostCommandQueue, log: CommandLog, opts?: ReplayOptions): ReplayResult;
113
+ //# sourceMappingURL=command_log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command_log.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/command_log.ts"],"names":[],"mappings":"AAyCA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEtF;;;2EAG2E;AAC3E,MAAM,WAAW,YAAY;IAC5B,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;+BAC2B;IAC3B,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;CAC1C;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IAC1B;;iEAE6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;6EACyE;IACzE,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;CACxC;AAiBD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,mBAAoB,YAAW,eAAe;IAC1D,iEAAiE;IACjE,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C;4EACwE;IACxE,OAAO,CAAC,IAAI,CAAgC;gBAEhC,IAAI,SAAI;IAIpB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAaxC,QAAQ,CAAC,MAAM,QAAS,WAAW,KAAG,IAAI,CAExC;IAEF;;gDAE4C;IAC5C,GAAG,IAAI,UAAU;CAGjB;AAYD;;;;;;;;;gFASgF;AAChF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAqB3D;AAED,0EAA0E;AAC1E,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAW9D;AAED,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC5B,2DAA2D;IAC3D,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,6BAA6B;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;oFAEgF;IAChF,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC7B;;;8BAG0B;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC/B,KAAK,EAAE,GAAG,EACV,KAAK,EAAE,gBAAgB,EACvB,GAAG,EAAE,UAAU,EACf,IAAI,CAAC,EAAE,aAAa,GAClB,YAAY,CAcd"}
@@ -0,0 +1,106 @@
1
+ import { Brand, TypedArrayTag } from '../../type_primitives';
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
+ /** Maps schema fields to their specific typed array columns. */
22
+ export type ColumnsForSchema<S extends ComponentSchema> = {
23
+ readonly [K in keyof S]: TagToTypedArray[S[K]];
24
+ };
25
+ /**
26
+ * Mutable sibling of `ColumnsForSchema` — the field-keyed column group handed
27
+ * back by `eachChunk`'s `cols.mut(def)` (no `readonly`, since the whole point
28
+ * is in-place writes). The change-tick is stamped once when the group is
29
+ * resolved, so the per-row loop is plain typed-array indexing (§eachChunk).
30
+ */
31
+ export type MutableColumnsForSchema<S extends ComponentSchema> = {
32
+ [K in keyof S]: TagToTypedArray[S[K]];
33
+ };
34
+ /**
35
+ * A component handle. **Callable**: `Pos({ x, y })` produces a `Bundle` (omitted
36
+ * fields zero-fill at attach), so one varargs shape — `spawn(Pos({x,y}),
37
+ * Vel({vx:1}), IsEnemy)` — replaces the older incompatible attach shapes. A bare
38
+ * `Pos` (uncalled) still stands in for a tag / all-zero values wherever a
39
+ * `BundleOrDef` is accepted.
40
+ *
41
+ * The numeric component id lives on `.id` (registration order). Consumers treat
42
+ * the def as an opaque handle; internal code reads `def.id` where it needs the
43
+ * 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.
45
+ *
46
+ * Build one with `makeComponentDef`; never construct by hand.
47
+ */
48
+ export interface ComponentDef<S extends ComponentSchema = ComponentSchema> {
49
+ (values?: Partial<FieldValues<S>>): Bundle<S>;
50
+ readonly id: ComponentID;
51
+ }
52
+ /**
53
+ * Schema-erased component handle — just the `.id`. Internal, schema-agnostic
54
+ * code (access checks, dirty-set notes, field-id lookup) takes this instead of
55
+ * `ComponentDef`: the callable signature makes `ComponentDef<S>` *invariant* in
56
+ * `S` (a generic `ComponentDef<S>` is not assignable to `ComponentDef`), but
57
+ * every `ComponentDef<S>` is assignable to `ComponentHandle` because it carries
58
+ * `.id`. Use it wherever only the id is read.
59
+ */
60
+ export type ComponentHandle = {
61
+ readonly id: ComponentID;
62
+ };
63
+ /**
64
+ * Mint a callable `ComponentDef` for a freshly-registered component id. The
65
+ * returned function produces a `Bundle` when called (`Pos({x,y})`) and carries
66
+ * its numeric id on a non-enumerable `.id` (invisible to spreads / `JSON`).
67
+ * The single cast bridges the function value to the branded handle type — the
68
+ * `.id` is installed at runtime by `defineProperty` (§10c branded-ID boundary).
69
+ */
70
+ export declare function makeComponentDef<S extends ComponentSchema>(id: ComponentID): ComponentDef<S>;
71
+ export interface Bundle<S extends ComponentSchema = ComponentSchema> {
72
+ readonly def: ComponentDef<S>;
73
+ readonly values: Partial<FieldValues<S>>;
74
+ }
75
+ /** Either a populated bundle or a bare def (tag / all-fields-zero). */
76
+ 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>;
79
+ /** Extract the def from a `BundleOrDef`. A bare def is the callable; a bundle a plain object. */
80
+ export declare function bundleDef(item: BundleOrDef): ComponentDef;
81
+ /** Extract the values from a `BundleOrDef` (a bare def contributes no values). */
82
+ export declare function bundleValues(item: BundleOrDef): Readonly<Record<string, number>>;
83
+ /**
84
+ * Compile-time readonly view of a typed array column. Blocks index writes at
85
+ * the type layer.
86
+ *
87
+ * **Advisory, not a runtime barrier:** the value behind this type is the live
88
+ * mutable backing `TypedArray` (`Archetype.getColumnRead` returns
89
+ * `.buf as unknown as ReadonlyColumn`), so a §10c-policed cast can still write
90
+ * through. For mutation use the mutable `Archetype.getColumn` (tick-bumping).
91
+ * Enforced by the escape-hatch lint, not the runtime.
92
+ */
93
+ export interface ReadonlyColumn {
94
+ readonly [index: number]: number;
95
+ readonly length: number;
96
+ }
97
+ /**
98
+ * Compile-time readonly view of a Uint32Array. Blocks index writes at the type
99
+ * layer. **Advisory, not a runtime barrier** — same caveat as `ReadonlyColumn`:
100
+ * the underlying value is the live mutable buffer.
101
+ */
102
+ export interface ReadonlyUint32Array {
103
+ readonly [index: number]: number;
104
+ readonly length: number;
105
+ }
106
+ //# sourceMappingURL=component.d.ts.map
@@ -0,0 +1 @@
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';
2
+ import { StoreLayoutListener } from './store_layout_listener';
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute_backend.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/compute_backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAEnE;;;;;;;;;GASG;AACH,MAAM,MAAM,mBAAmB,GAAG,KAAK,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;AAEzE;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAe,SAAQ,mBAAmB;IAC1D;;;;;;;;;OASG;IACH,GAAG,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACvC"}
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch_trace.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/dispatch_trace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAOH,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,CAAC;AACrE,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AACzC,MAAM,MAAM,QAAQ,GAAG,aAAa,GAAG,eAAe,CAAC;AACvD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;AAElE,MAAM,WAAW,kBAAkB;IAClC,6EAA6E;IAC7E,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,oDAAoD;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE;QAClB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,UAAU,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAChE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACzD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,kBAAkB,EAAE,CAAC,CAAC;KAC7D,CAAC;CACF;AAID,cAAM,aAAa;IAClB,OAAO,CAAC,WAAW,CAAwB;IAC3C,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,GAAG,CAA6B;IACxC,OAAO,CAAC,aAAa,CAAoC;IAEzD,QAAQ,IAAI,OAAO;IAWnB,OAAO,CAAC,QAAQ;IAMhB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,MAAM;IAOd,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAG/B,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAG/B,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAGvC,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAGxC,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAG3C,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAGzC,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAGrC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIvC,QAAQ,IAAI,qBAAqB;IAmCjC,KAAK,IAAI,IAAI;CAMb;AAMD,iBAAS,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOnD;AAED;;;;;;GAMG;AACH,iBAAS,wBAAwB,CAChC,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,GAChC,MAAM,GAAG,IAAI,CA0Bf;AAeD,eAAO,MAAM,aAAa,EAAE,aAAmC,CAAC;AAIhE,eAAO,MAAM,uBAAuB;;;;CAInC,CAAC"}