@series-inc/rundot-syncplay 5.24.0-beta.2 → 5.25.0-beta.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 (224) hide show
  1. package/LICENSE.md +211 -0
  2. package/README.md +62 -736
  3. package/dist/authority-room.d.ts +11 -1
  4. package/dist/authority-room.js +38 -1
  5. package/dist/browser.d.ts +7 -26
  6. package/dist/browser.js +3 -14
  7. package/dist/creator.d.ts +5 -11
  8. package/dist/creator.js +2 -6
  9. package/dist/index.d.ts +10 -27
  10. package/dist/index.js +5 -14
  11. package/dist/instant-replay.d.ts +5 -5
  12. package/dist/instant-replay.js +3 -12
  13. package/dist/local-authority-wire.d.ts +13 -123
  14. package/dist/local-authority-wire.js +105 -1439
  15. package/dist/match-log.d.ts +2 -11
  16. package/dist/match-log.js +46 -55
  17. package/dist/networked-client.d.ts +10 -9
  18. package/dist/networked-client.js +56 -17
  19. package/dist/node.d.ts +4 -15
  20. package/dist/node.js +2 -11
  21. package/dist/physics3d-solver.d.ts +7 -0
  22. package/dist/physics3d-solver.js +38 -0
  23. package/dist/physics3d.d.ts +1 -0
  24. package/dist/physics3d.js +53 -0
  25. package/dist/r3f-render-adapter.d.ts +2 -2
  26. package/dist/r3f-render-adapter.js +38 -28
  27. package/dist/replay-inspect.d.ts +11 -41
  28. package/dist/replay-inspect.js +36 -207
  29. package/dist/replay-scoring.d.ts +2 -13
  30. package/dist/replay-scoring.js +3 -32
  31. package/dist/replay.d.ts +12 -14
  32. package/dist/replay.js +185 -308
  33. package/dist/runtime-session.d.ts +56 -0
  34. package/dist/runtime-session.js +333 -0
  35. package/dist/runtime-support.d.ts +3 -4
  36. package/dist/runtime-support.js +6 -7
  37. package/dist/sample-scenes.js +17 -33
  38. package/dist/schema-artifacts.js +3 -3
  39. package/dist/schema-codegen.js +4 -4
  40. package/dist/schema.d.ts +1 -1
  41. package/dist/schema.js +1 -1
  42. package/dist/sdk-session.d.ts +5 -53
  43. package/dist/sdk-session.js +28 -161
  44. package/dist/secret-client.d.ts +3 -2
  45. package/dist/session-promotion.d.ts +11 -26
  46. package/dist/session-promotion.js +48 -53
  47. package/dist/session-snapshot.d.ts +10 -9
  48. package/dist/session-snapshot.js +54 -6
  49. package/dist/session-wire.d.ts +10 -5
  50. package/dist/session-wire.js +54 -6
  51. package/dist/synctest.d.ts +7 -12
  52. package/dist/synctest.js +66 -145
  53. package/dist/testing.d.ts +0 -53
  54. package/dist/testing.js +0 -45
  55. package/dist/tools/index.d.ts +2 -2
  56. package/dist/tools/index.js +1 -2
  57. package/dist/types.d.ts +5 -118
  58. package/package.json +20 -125
  59. package/dist/certification.d.ts +0 -484
  60. package/dist/certification.js +0 -1940
  61. package/dist/chaos-certification.d.ts +0 -56
  62. package/dist/chaos-certification.js +0 -1397
  63. package/dist/checksum-basis.d.ts +0 -4
  64. package/dist/checksum-basis.js +0 -17
  65. package/dist/cjs/animation.js +0 -495
  66. package/dist/cjs/asset-cooking.js +0 -372
  67. package/dist/cjs/authority-room.js +0 -751
  68. package/dist/cjs/bot-documents.js +0 -556
  69. package/dist/cjs/bot-primitives.js +0 -482
  70. package/dist/cjs/browser.js +0 -291
  71. package/dist/cjs/canonical.js +0 -299
  72. package/dist/cjs/certification.js +0 -1945
  73. package/dist/cjs/chaos-certification.js +0 -1402
  74. package/dist/cjs/checksum-basis.js +0 -22
  75. package/dist/cjs/collections.js +0 -36
  76. package/dist/cjs/collider-cooking.js +0 -834
  77. package/dist/cjs/collision.js +0 -154
  78. package/dist/cjs/commands.js +0 -987
  79. package/dist/cjs/config-bundle.js +0 -491
  80. package/dist/cjs/cosmetic-physics3d.js +0 -201
  81. package/dist/cjs/creator.js +0 -56
  82. package/dist/cjs/deterministic-primitives.js +0 -134
  83. package/dist/cjs/deterministic-session.js +0 -1412
  84. package/dist/cjs/ecs-lite.js +0 -155
  85. package/dist/cjs/effects-adapter.js +0 -97
  86. package/dist/cjs/engine-complete.js +0 -2509
  87. package/dist/cjs/engine-core-proof.js +0 -70
  88. package/dist/cjs/engine-parity-matrix.js +0 -921
  89. package/dist/cjs/engine-parity.js +0 -3186
  90. package/dist/cjs/engine-runtime.js +0 -3141
  91. package/dist/cjs/errors.js +0 -22
  92. package/dist/cjs/events.js +0 -247
  93. package/dist/cjs/examples/counter-duel.js +0 -157
  94. package/dist/cjs/examples/fixed-arena.js +0 -368
  95. package/dist/cjs/index.js +0 -328
  96. package/dist/cjs/input-authority.js +0 -214
  97. package/dist/cjs/input-button.js +0 -256
  98. package/dist/cjs/input-timeline.js +0 -418
  99. package/dist/cjs/instant-replay.js +0 -61
  100. package/dist/cjs/lag-compensation3d.js +0 -837
  101. package/dist/cjs/local-authority-server-runner.js +0 -1123
  102. package/dist/cjs/local-authority-wire.js +0 -1516
  103. package/dist/cjs/local-authority.js +0 -817
  104. package/dist/cjs/local-ws-adapter.js +0 -150
  105. package/dist/cjs/match-log.js +0 -88
  106. package/dist/cjs/math.js +0 -514
  107. package/dist/cjs/mock-network-adapter.js +0 -26
  108. package/dist/cjs/movement.js +0 -703
  109. package/dist/cjs/movement3d.js +0 -1491
  110. package/dist/cjs/multiclient-authority.js +0 -308
  111. package/dist/cjs/multiplayer-service.js +0 -434
  112. package/dist/cjs/navigation.js +0 -347
  113. package/dist/cjs/navmesh.js +0 -1437
  114. package/dist/cjs/networked-client.js +0 -774
  115. package/dist/cjs/networked-input-authority.js +0 -443
  116. package/dist/cjs/node.js +0 -73
  117. package/dist/cjs/noise.js +0 -58
  118. package/dist/cjs/number-lab.js +0 -78
  119. package/dist/cjs/offline-session.js +0 -398
  120. package/dist/cjs/package.json +0 -1
  121. package/dist/cjs/pause-resume.js +0 -43
  122. package/dist/cjs/physics-cert.js +0 -572
  123. package/dist/cjs/physics2d.js +0 -757
  124. package/dist/cjs/physics3d-destruction-cert.js +0 -279
  125. package/dist/cjs/physics3d-heightfield.js +0 -51
  126. package/dist/cjs/physics3d-hull.js +0 -381
  127. package/dist/cjs/physics3d-joints.js +0 -843
  128. package/dist/cjs/physics3d-mass.js +0 -131
  129. package/dist/cjs/physics3d-recipes.js +0 -197
  130. package/dist/cjs/physics3d-shared.js +0 -298
  131. package/dist/cjs/physics3d-solver.js +0 -2161
  132. package/dist/cjs/physics3d-stacking.js +0 -154
  133. package/dist/cjs/physics3d-toi.js +0 -274
  134. package/dist/cjs/physics3d-vehicle.js +0 -492
  135. package/dist/cjs/physics3d-voxel.js +0 -94
  136. package/dist/cjs/physics3d.js +0 -3511
  137. package/dist/cjs/prediction-culling.js +0 -203
  138. package/dist/cjs/protocol-lab.js +0 -1299
  139. package/dist/cjs/r3f-render-adapter.js +0 -209
  140. package/dist/cjs/random.js +0 -108
  141. package/dist/cjs/replay-bundle.js +0 -1705
  142. package/dist/cjs/replay-inspect.js +0 -236
  143. package/dist/cjs/replay-scoring.js +0 -68
  144. package/dist/cjs/replay.js +0 -380
  145. package/dist/cjs/reports.js +0 -181
  146. package/dist/cjs/rollback-history.js +0 -251
  147. package/dist/cjs/runtime-guards.js +0 -111
  148. package/dist/cjs/runtime-support.js +0 -71
  149. package/dist/cjs/sample-lab.js +0 -145
  150. package/dist/cjs/sample-scenes.js +0 -755
  151. package/dist/cjs/schema-artifacts.js +0 -359
  152. package/dist/cjs/schema-codegen.js +0 -544
  153. package/dist/cjs/schema-dsl-binary.js +0 -655
  154. package/dist/cjs/schema.js +0 -319
  155. package/dist/cjs/sdk-offline.js +0 -81
  156. package/dist/cjs/sdk-session.js +0 -165
  157. package/dist/cjs/secret-authority.js +0 -647
  158. package/dist/cjs/secret-client.js +0 -615
  159. package/dist/cjs/secret-command-classification.js +0 -8
  160. package/dist/cjs/secret-config.js +0 -211
  161. package/dist/cjs/secret-crypto.js +0 -208
  162. package/dist/cjs/secret-protocol.js +0 -238
  163. package/dist/cjs/session-build.js +0 -45
  164. package/dist/cjs/session-promotion.js +0 -74
  165. package/dist/cjs/session-snapshot.js +0 -265
  166. package/dist/cjs/session-wire.js +0 -222
  167. package/dist/cjs/signals.js +0 -103
  168. package/dist/cjs/sparse-set.js +0 -169
  169. package/dist/cjs/synctest.js +0 -185
  170. package/dist/cjs/system-lifecycle.js +0 -286
  171. package/dist/cjs/testing.js +0 -110
  172. package/dist/cjs/timers.js +0 -61
  173. package/dist/cjs/tools/static-checker.js +0 -1516
  174. package/dist/cjs/types.js +0 -2
  175. package/dist/cjs/venus-mp-budget.js +0 -125
  176. package/dist/cjs/ws-frame.js +0 -255
  177. package/dist/cli.d.ts +0 -2
  178. package/dist/cli.js +0 -11596
  179. package/dist/deterministic-session.d.ts +0 -197
  180. package/dist/deterministic-session.js +0 -1403
  181. package/dist/engine-complete.d.ts +0 -45
  182. package/dist/engine-complete.js +0 -2504
  183. package/dist/engine-parity-matrix.d.ts +0 -300
  184. package/dist/engine-parity-matrix.js +0 -916
  185. package/dist/engine-parity.d.ts +0 -74
  186. package/dist/engine-parity.js +0 -3181
  187. package/dist/examples/counter-duel.d.ts +0 -43
  188. package/dist/examples/counter-duel.js +0 -150
  189. package/dist/examples/fixed-arena.d.ts +0 -110
  190. package/dist/examples/fixed-arena.js +0 -356
  191. package/dist/input-timeline.d.ts +0 -65
  192. package/dist/input-timeline.js +0 -412
  193. package/dist/local-authority-server-runner.d.ts +0 -80
  194. package/dist/local-authority-server-runner.js +0 -1119
  195. package/dist/local-authority.d.ts +0 -160
  196. package/dist/local-authority.js +0 -810
  197. package/dist/local-ws-adapter.d.ts +0 -14
  198. package/dist/local-ws-adapter.js +0 -146
  199. package/dist/mock-network-adapter.d.ts +0 -13
  200. package/dist/mock-network-adapter.js +0 -23
  201. package/dist/multiplayer-service.d.ts +0 -153
  202. package/dist/multiplayer-service.js +0 -429
  203. package/dist/networked-input-authority.d.ts +0 -51
  204. package/dist/networked-input-authority.js +0 -439
  205. package/dist/offline-session.d.ts +0 -2
  206. package/dist/offline-session.js +0 -395
  207. package/dist/pause-resume.d.ts +0 -48
  208. package/dist/pause-resume.js +0 -40
  209. package/dist/protocol-lab.d.ts +0 -115
  210. package/dist/protocol-lab.js +0 -1295
  211. package/dist/replay-bundle.d.ts +0 -189
  212. package/dist/replay-bundle.js +0 -1692
  213. package/dist/reports.d.ts +0 -181
  214. package/dist/reports.js +0 -174
  215. package/dist/sample-lab.d.ts +0 -32
  216. package/dist/sample-lab.js +0 -134
  217. package/dist/sdk-offline.d.ts +0 -38
  218. package/dist/sdk-offline.js +0 -78
  219. package/dist/session-build.d.ts +0 -37
  220. package/dist/session-build.js +0 -42
  221. package/dist/tools/vite-plugin.d.ts +0 -77
  222. package/dist/tools/vite-plugin.js +0 -257
  223. package/dist/venus-mp-budget.d.ts +0 -29
  224. package/dist/venus-mp-budget.js +0 -122
package/README.md CHANGED
@@ -1,759 +1,85 @@
1
1
  # RUN Syncplay
2
2
 
3
- Offline-first deterministic multiplayer engine for RUN.world. You author a
4
- **deterministic** game (`defineSyncplayGame`, `DeterministicSystem`,
5
- `DeterministicRandom`) and Syncplay runs it — input authority, prediction, and
6
- rollback with no game-specific server logic.
3
+ Syncplay is the orchestration layer over a signed Kinetix runtime. Kinetix owns
4
+ deterministic state, RNG streams, stepping, opaque checkpoints, serialization,
5
+ hydration, and checksums. Syncplay owns inputs, prediction, confirmation,
6
+ rollback policy, replay logs, late join, secrets, and transport.
7
7
 
8
- This package is intentionally standalone. It does not depend on Venus MP,
9
- Cloud Run, React Three Fiber, Rapier, Firebase, or the SDK bridge.
8
+ ## Ownership boundary
10
9
 
11
- ## Public and private projections
10
+ | Concern | Owner |
11
+ |---|---|
12
+ | Committed source capture, upload authority, build lifecycle | Pack API + CLI |
13
+ | Compilation, exact product schema, runtime identity | Kinetix compiler/baker |
14
+ | Artifact immutability, signing, key trust, catalog eligibility | Pack service + KMS/GCS/Firestore |
15
+ | Deterministic state, RNG streams, step, checkpoint bytes, canonical checksum | Kinetix runtime |
16
+ | Inputs, prediction, confirmation, rollback policy, replay log, late join, secrets, transport | Syncplay |
17
+ | Rendering/interpolation/effects | Presentation adapters outside authoritative state |
12
18
 
13
- The deterministic session remains a shared public projection: every client
14
- applies the same confirmed inputs and authority commands. Optional secret
15
- systems add a separate authority-owned projection for simultaneous choices,
16
- cryptographic random draws, decks, bags, and roles. Private values go only to
17
- their owners; signed public consequences join exactly one confirmed frame and
18
- therefore survive rollback, replay, reconnect, and match-log verification.
19
-
20
- The RUN room authority is trusted and can see secret values. SHA-256
21
- commitments, hash chains, Merkle proofs, and Ed25519 receipts prevent peers or
22
- tampered logs from forging outcomes; they do not hide a player's own values
23
- from that player's browser or make the authority zero-knowledge. Public donated
24
- snapshots remain secret-free, while server-only secret state restores against a
25
- cryptographic configuration hash.
26
-
27
- ## BETA Status
28
-
29
- The standalone engine, certification CLI, curated public entrypoints, SDK bridge,
30
- generic input authority, replay verification, and hosted multiplayer path are in
31
- active development. Syncplay has not gone live. Package publication, production
32
- rollout, and 1.0 graduation are separate release decisions; this build remains
33
- explicitly BETA.
34
-
35
- ## State Ownership Contract
36
-
37
- `step` must not mutate the state object it receives or anything reachable from
38
- it. Copy every array, map, set, typed array, or object before modifying it.
39
- Sharing unmodified structure with the prior state is expected, and returning the
40
- same state unchanged is legal.
41
-
42
- Syncplay retains each returned state object in the snapshot ring by reference
43
- and hands it back on rollback without copying. This makes snapshot and restore
44
- O(1); violating the contract corrupts rollback history. Run
45
- `runSyncplaySynctest` in CI: its `aliasing`, `hydration`, and `codec` phases catch
46
- mutation, normalization-dependent behavior, and lossy codecs.
47
-
48
- For large, slowly changing state, keep an incremental running hash in immutable
49
- state and expose it through `config.checksum`. Recorded checksums can then be
50
- O(1) and interval-gated. Wire snapshots still serialize and checksum full state
51
- on demand; never treat `config.checksum` as the late-join checksum. See
52
- [`docs/syncplay-state-contract.md`](../../docs/syncplay-state-contract.md) for
53
- the worked pattern and validation-latency tradeoff.
54
-
55
- ## Testing
56
-
57
- `test:core` is the confidence surface. It runs the behavioral suites that pin
58
- the engine's observable multiplayer behavior — authority room, offline/session
59
- wire, snapshot late-join, crash restore, latency/loss convergence,
60
- replay-verified scoring, bot backfill, time-sync pacing, match logs,
61
- spectators, synctest, instant replay, session promotion, and pause/resume —
62
- and it is the PR gate: `ci-syncplay.yml` runs `npm run build` + `npm run
63
- test:core` on every PR that touches `packages/syncplay/`.
64
-
65
- The other subsystem test files (physics, navigation, animation, bots, schema,
66
- and similar) were reduced to determinism + rollback tripwires: same inputs
67
- twice must produce identical checksums, and snapshot → advance → restore →
68
- resimulate must match the uninterrupted run. They are regression alarms, not
69
- coverage suites; their per-subsystem (near-)100% coverage shards were removed,
70
- and the remaining `coverage:package:*` shards cover the core modules only.
71
-
72
- The netcode surface has its own behavioral suites: `pumpPaced` pacing with
73
- ping-adaptive input delay and client `netStats`, desync detection/response,
74
- match logs via `matchLog`, spectator support, and `runSyncplaySynctest` for
75
- creators. See `docs/syncplay-netcode-observability.md`,
76
- `docs/syncplay-replay-verified-leaderboards.md`, and
77
- `docs/syncplay-wire-format.md`.
78
-
79
- Deployability is gated by build-time certification, not by stamped proof
80
- artifacts. The deployable preflight is `project:check` with the
81
- `static-determinism` section required — it proves the simulation is a real,
82
- file-backed, replayable module before upload. The optional deploy-check
83
- commands (`project:deploy-check` / `project:deploy-check-verify`) remain as a
84
- local, internal-consistency **receipt** — they prove the bundle they describe is
85
- the bundle that was checked — but they are **not** a cryptographic signature,
86
- provenance proof, or a backend admission gate. Venus upload validation and
87
- room-server startup accept a bare `deterministic: true` room and never read
88
- these artifacts.
89
-
90
- CI lanes:
91
-
92
- - `ci-syncplay.yml` — PR gate: build + `test:core` on engine changes.
93
- - `ci-syncplay-services.yml` — mp-room-server deterministic room/gateway tests
94
- plus the SDK syncplay bridge tests.
95
- - `ops-syncplay-nightly.yml` — cross-VM replay verification in Chromium and
96
- WebKit, plus the 128-player/100k-frame stress soak
97
- (`certify:deterministic-stress`).
98
-
99
- Heavier local lanes: `npm run verify:deterministic-backend` (repo root) after
100
- touching the Venus upload/runtime integration, and `npm run test:certification`
101
- + `npm run certify:standalone-complete` before a deterministic engine release.
102
- The full certification path intentionally includes 128-player and 100k-frame
103
- stress runs; keep it out of ordinary PR auto-testing.
104
-
105
- ## Current Surface
19
+ There is one session factory:
106
20
 
107
21
  ```ts
108
- import {
109
- createSyncplayGameRuntime,
110
- createSyncplayClient,
111
- createDeterministicR3fAdapter,
112
- verifyDeterministicReplay,
113
- } from '@series-inc/rundot-syncplay/browser';
114
- import { createDeterministicAuthorityServer } from '@series-inc/rundot-syncplay/node';
115
- import { rundotSyncplayPlugin } from '@series-inc/rundot-syncplay/tools';
22
+ import { createSyncplaySession } from '@series-inc/rundot-syncplay/browser';
23
+ import { createFixed1000Runtime } from '@series-inc/rundot-kinetix/runtime';
24
+
25
+ const runtime = createFixed1000Runtime({
26
+ product,
27
+ sessionConfigBytes,
28
+ });
29
+
30
+ const session = createSyncplaySession(runtime, {
31
+ playerCount: 4,
32
+ defaultInput: { throttle: 0, steer: 0, brake: false },
33
+ snapshotBufferSize: 256,
34
+ checksumIntervalFrames: 30,
35
+ });
116
36
  ```
117
37
 
118
- > The `@series-inc/rundot-syncplay/testing` entry (and its SDK mirror
119
- > `@series-inc/rundot-game-sdk/syncplay/testing`) exposes internal labs,
120
- > examples, fixtures, certification harnesses, and mocks for this repo's tests,
121
- > prototypes, and the syncplay CLI. It is **unsupported** — anything there may be
122
- > renamed or removed without notice, and it is deliberately excluded from the
123
- > export-surface goldens. Game code must import from the package root, `/browser`,
124
- > or `/creator` instead.
125
-
126
- The SDK bridge re-exports a browser-safe subset for games that already depend on
127
- `@series-inc/rundot-game-sdk`:
38
+ The runtime must implement `@series-inc/rundot-kinetix/runtime`. Syncplay never
39
+ accepts an initial state, reducer, or creator-authored step callback. There is no
40
+ compatibility mode for the removed reducer API.
128
41
 
129
- ```ts
130
- import {
131
- createSyncplayGameRuntime,
132
- createSyncplayClient,
133
- createDeterministicR3fAdapter,
134
- verifyDeterministicReplay,
135
- } from '@series-inc/rundot-game-sdk/syncplay/browser';
136
- import { createDeterministicAuthorityServer } from '@series-inc/rundot-game-sdk/syncplay/node';
137
- ```
42
+ ## Runtime and snapshot contract
138
43
 
139
- Implemented:
44
+ Live play retains opaque Kinetix checkpoint handles. Rollback restores those
45
+ handles directly; it does not serialize or hydrate them. A v2 promotion or
46
+ late-join snapshot contains one opaque `runtimeBytes` payload plus the signed
47
+ runtime identity, canonical session-config digest, frame, and checksum. The
48
+ destination validates all of those values before mutating its live session.
140
49
 
141
- - Fixed-tick offline runner.
142
- - 1 to 128 local input slots.
143
- - Replay export and Node replay verification.
144
- - Metrics-only replay mode for long performance runs.
145
- - Bounded snapshots and restore-to-frame.
146
- - Deterministic RNG, RNG forking, and fixed-point math helpers.
147
- - Deterministic collection helpers for stable sorted keys, stable indexed maps,
148
- and seeded shuffles.
149
- - Deterministic frame timer helpers for frame/ms conversion, cooldown counters,
150
- and scheduled frame events.
151
- - Public ECS-lite world API with stable entity IDs, component add/remove,
152
- singleton state, deterministic queries, snapshot/restore, and checksums.
153
- - Runtime guard opt-in for blocked globals during simulation.
154
- - Static checker CLI and Vite-compatible no-dependency plugin/config helpers,
155
- including diagnostics for random/time/timers/I/O, unordered iteration, random
156
- sort comparators, render-object mutation, and uncertified physics stepping.
157
- - AST-backed deterministic static analysis using TypeScript syntax trees, with
158
- regex scanning retained only as a parser-unavailable fallback.
159
- - SDK-shaped offline runtime helper that exposes frame subscriptions, replay
160
- export, schema-backed checksums, and no server dependency.
161
- - Stable game-facing browser names for the offline runtime, R3F adapter, replay
162
- verification, and multiplayer client facade.
163
- - Stable node/server name for an in-process local authority server facade over
164
- the local authority runtime.
165
- - Stable multiplayer facade methods for normalized scalar input submission,
166
- command-channel submission, command polling, command timeline snapshots,
167
- reconnect, late join, spectator state, bot-controlled slot metadata, and
168
- checksum convergence.
169
- - Stable authority certification artifact export plus a verifier that replays
170
- recorded lifecycle/input history and recomputes snapshot, command timeline,
171
- and checksum evidence for CLI certification.
172
- - Render-only r3f-compatible adapter that emits frozen predicted/verified frame
173
- props, provides normalized input bindings, and blocks render subscribers from
174
- mutating checksummed session state.
175
- - Render-only interpolation helpers and immutable debug overlay data for
176
- predicted frame, verified frame, checksum, and correction count.
177
- - SDK test-app r3f visual sample that renders Fixed Arena frame props through
178
- React Three Fiber and verifies deterministic status, r3f metrics, and a
179
- visible non-empty WebGL canvas with Playwright.
180
- - Full SDK subpath export at
181
- `@series-inc/rundot-game-sdk/syncplay`, verified by SDK Jest
182
- tests, `build:sdk`, and built `dist` import checks.
183
- - Curated creator subpath export at
184
- `@series-inc/rundot-game-sdk/syncplay/creator` for
185
- browser-safe offline runtime, descriptors, commands, schema artifacts,
186
- replay verification, and deterministic 3D physics (world create/step/edit,
187
- voxel-chunk collider cooking, impulses, queries, vehicles) without Node
188
- tooling, local servers, certification labs, render adapters, or engine
189
- internals.
190
- - Manifest-driven H5 creator entrypoint certification that requires game code
191
- to import the safe `/creator` runtime surface and rejects broad SDK, Node,
192
- tooling, lab, certification, r3f, and internal runtime imports before release
193
- evidence is written.
194
- - H5 browser release proof that opens the built `dist/index.html`, steps the
195
- starter app through its deterministic UI, and records frame, score, checksum,
196
- and `index.html` hash evidence alongside browser replay verification.
197
- - Deterministic project release bundle manifests that inventory release
198
- evidence, project manifests, certification artifacts, replay bundles, browser
199
- proofs, and recursive `dist/` files with byte counts and checksums, plus a
200
- fail-closed bundle verifier for creator CI, deploy tooling, and Venus upload
201
- proof validation.
202
- - Local mock network adapter over the protocol lab with delay/loss/duplicate
203
- settings, rollback metrics, and deterministic replay artifact export.
204
- - Local WebSocket harness with `/health`, `/protocol`, CLI server/client
205
- commands, result comparison against the in-memory protocol lab, and a
206
- Node-only SDK subpath so browser bundles stay free of Node `http`/`crypto`.
207
- - `lab:venus-mp-budget` compatibility gate for current Venus MP defaults
208
- (`ROOM_DEFAULT_MAX_PLAYERS=10`, 30 msg/s, 16 KB messages) and explicit
209
- 128-player adapter settings.
210
- - `mp-room-server` worker-harness compatibility test that runs a deterministic
211
- room bundle through `RoomManager`, the worker sandbox, room broadcast, and
212
- `StateStore.save` without Firestore or Venus MP gateway dependencies.
213
- - `mp-room-server` WebSocket gateway compatibility test that authenticates
214
- single-use `TicketStore` tickets, joins real `/ws` clients, sends
215
- deterministic input, broadcasts `rdm:confirmed`, and verifies persisted
216
- checksum state.
217
- - POST `/tickets` compatibility test that mocks Firebase token/profile
218
- dependencies, mints deterministic-room tickets over HTTP, uses those tickets
219
- on the real `/ws` gateway, and verifies deterministic confirmation plus
220
- persisted checksum state.
221
- - In-memory rollback protocol lab with delay, duplication, reordering, loss,
222
- disconnect/reconnect, resend, retry cancellation, and desync injection.
223
- - Late join, asymmetric latency, input-delay sweeps, deterministic bot slots,
224
- and actual bundled input delivery in the protocol lab.
225
- - Protocol lab game adapters for the synthetic lab shape and Counter Duel.
226
- - `lab:netcode` 128-player measurement wrapper for input-minimal,
227
- moderate-state, and command-burst shapes, with RTT/jitter/loss mapping,
228
- payload estimates, event metrics, and pass/warn/fail classification.
229
- - `lab:prediction-culling` local-area AOI lab with predicted/verified execution
230
- checksums, restore/resim proof, visible-correction metrics, and hidden
231
- authoritative interaction failures.
232
- - Descriptor validation for deterministic input/state/event/asset/config/system
233
- schemas with stable replay identity ids.
234
- - Descriptor artifact helpers, descriptor-backed replay inspection, and
235
- `schema:dump` for schema-aware input/state/command serialization,
236
- deserialization, canonicalization, replay metadata, cooked asset manifests,
237
- checksums, and frame dumps.
238
- - `schema:types` TypeScript interface generation for descriptor-declared input,
239
- state, commands, event payloads, event unions, replay metadata, cooked asset
240
- manifests, replay identity constants, default input factories, and stable
241
- serializer helpers.
242
- - Rollback-safe event timeline primitives for predicted, confirmed, canceled,
243
- and verified-only view events.
244
- - Stable JSON report emission for protocol rollback lab runs.
245
- - Manifest-driven `certify` CLI orchestrator for the v1 deterministic
246
- multiplayer certification suite, with stable per-fixture JSON artifacts,
247
- deterministic budget gates, required Node replay verification, and optional
248
- browser replay groups kept outside the offline core gate.
249
- - `certify:v1` includes a fixed-foundation fixture with stable golden checksums
250
- for fixed math, fixed collision vectors, seeded RNG, frame timers, scheduled
251
- frame events, stable maps/sets, and deterministic shuffles.
252
- - `certify:v1` includes a protocol-matrix fixture for delay/jitter, loss,
253
- duplicates, reordering, reconnect, late join, asymmetric latency, input
254
- delay, bot slots, command bursts, expected desync artifacts, and frame-model
255
- rollback/correction metrics.
256
- - `certify:v1` includes static-analysis, schema-tooling, event-callbacks,
257
- built-in physics, and prediction-culling fixtures so existing deterministic
258
- authoring, replay/debug, callback, physics, and AOI behavior is validated from
259
- one offline CLI command.
260
- - Descriptor replay identity includes command-channel schema IDs and
261
- prototype/entity-template schema IDs, and `certify:v1` verifies those identity
262
- fields through the schema-tooling fixture.
263
- - `certify:v1` includes an external-physics policy gate that keeps
264
- `rapier2d-compat` blocked from checksummed gameplay until its snapshot,
265
- restore, query-order, callback, snapshot-hash, and version-identity gates pass.
266
- - `certify:v1` includes headless ECS-lite, KCC-lite, projectile/hitscan,
267
- bot-replacement, and genre-like 128-player top-down bot workload fixtures
268
- before any r3f, Venus MP, or browser dependency enters the verification path.
269
- - `certify:v1` includes deterministic grid navigation/pathfinding with stable
270
- query order, unreachable-target detection, slot-ordered avoidance, rollback
271
- equality, and checksum convergence.
272
- - Public deterministic navigation primitives for cooked graph assets, stable
273
- A*, region disabling, dynamic blockers, off-mesh links, flow fields, tilemap
274
- graph cooking, deterministic avoidance ordering, and rollback-equivalent
275
- agent stepping.
276
- - Public deterministic bot primitives for typed stable blackboards, HFSM,
277
- Behavior Tree, Utility selection, deterministic bot asset cooking, mixed-style
278
- simulation, rollback equivalence, and 128-player bot replacement metrics.
279
- - `certify:v1` includes headless reference-sample category coverage for
280
- asteroids-basic, platform-shooter-2d, simple-fps, twin-stick-shooter,
281
- arena-brawler, racer-25d, and turn-flow-mini-golf mechanics.
282
- - Protocol reports include bounded predicted/confirmed/canceled event timeline
283
- summaries.
284
- - Replay verification first-mismatch diagnostics, replay frame inspect,
285
- checksum explain tables, and replay diff CLI commands for lab replay frame
286
- dumps.
287
- - `certify:v2 -- --profile chaos` fixture coverage for locally provable
288
- multiplayer failure modes: resync snapshot-tail recovery, disconnect
289
- recovery, rollback buffer boundaries, hostile protocol rejection, command
290
- idempotency, event exactly-once semantics, replay identity failures, random
291
- rollback, tick catch-up guards, asset/config mismatches, physics/movement
292
- rollback boundaries, and 128-player command-burst chaos.
293
- - Fixed-point collision primitives and a Fixed Arena package-local example with
294
- 128-player replay verification and render projection output.
295
- - `lab:physics-cert` built-in fixed physics certification for fixed-arena and
296
- 128-slot load shapes with snapshot/restore, stable collision/query ordering,
297
- and timing metrics.
298
- - `lab:physics-cert -- --engine builtin-rigid` certifies the 3D rigid-body
299
- solver (settling stack + hinge motor + grab + speculative CCD arena) against
300
- the same four determinism gates; the contact/joint caches round-trip through
301
- the snapshot as canonical state.
302
- - `lab:physics-cert -- --engine rapier2d-compat` certification for
303
- `@dimforge/rapier2d-compat@0.19.3`; the current pinned cert reproduces
304
- snapshot/restore nondeterminism, so Rapier remains render/prototype-only for
305
- checksummed gameplay.
306
- - **Production-grade 3D rigid-body dynamics.** A warm-started sequential-impulse
307
- solver (SAT + face-clipping manifolds → accumulated normal/friction impulses →
308
- split-impulse position correction → island-based sleeping) delivers stable
309
- stacking, full 6-DOF tumbling props, per-body axis locks (Box2D-class 2D games
310
- on the 3D solver), impulse-based joints (`ball`, `hinge` with limits + motor,
311
- `weld`, `distance`/rope, `spring` (soft point-to-point via
312
- `frequencyHz`/`dampingRatio`, Box2D soft-constraint math), and the `grab`
313
- gravity-gun/carry primitive),
314
- speculative-contact CCD, and compound colliders. Opt-in per body via
315
- `orientation`/`angularVel`/`mass`/`ccd`/locks; bodies without these solve as
316
- rotation-locked rigid bodies through the same pipeline. New step options
317
- `joints` and `velocityIterations`; mutation helpers
318
- `applyDeterministicImpulse3D` / `setDeterministicBodyVelocity3D`; contact
319
- events carry `normalImpulse`. The contact/joint caches live in the world and
320
- are therefore checksummed and rollback-safe.
321
- - **Render-only cosmetic 3D physics.** `createDeterministicCosmeticPhysicsWorld3D`
322
- accepts dynamic cosmetic bodies plus static/kinematic authoritative proxies
323
- and resolves contacts against the cosmetics only. Proxy state and impulses
324
- are never written back, and the cosmetic layer has no checksum or participation
325
- in Syncplay state, snapshots, replays, or network traffic.
326
- - **Deterministic raycast-wheel vehicles.** `stepDeterministicVehicle3D` drives
327
- a single dynamic chassis with N suspension raycasts (wheels are rays, not
328
- bodies — Bullet/Godot raycast-vehicle lineage): spring-damper suspension,
329
- friction-circle tire forces (drive/steer/brake from integer deci-unit input),
330
- steering through the fixed-point `createDeterministicMath()` trig, and an
331
- iterated Gauss-Seidel tire solve. The stateless controller returns quantized
332
- impulses the game applies before the next physics step (the KCC pattern) —
333
- use the batched `applyDeterministicImpulses3D` (one canonical-world rebuild
334
- per frame; the per-impulse singular form costs an O(bodies) rebuild per
335
- call); the checksum covers only load-bearing outputs
336
- (impulses, grounded flags, compressions), never cosmetic telemetry. v1 targets
337
- static ground with flat/axis-aligned contact normals; certified by the
338
- required `physics-rigid-vehicle` fixture, a car in the `builtin-rigid` cert
339
- arena, a rollback-every-frame synctest scene, and a 100%-coverage
340
- `coverage:package:physics-vehicle` shard.
341
- - **Accelerated deterministic queries.** Raycast, overlap, and shape-cast run
342
- through a per-world static AABB tree (BVH) built lazily on first query and
343
- memoized by world identity — pure derived data that never enters canonical
344
- state, with bit-identical results to a full scan (the tree only prunes;
345
- narrow-phase tests and id-tiebroken ordering are unchanged, proven by a
346
- merged-single-body-world oracle test). Query cost is flat in world size:
347
- 128 wheel-length raycasts cost ~0.2 ms whether the world holds 17 or 1,000
348
- bodies (previously ~72 ms at 1,000).
349
- - Public deterministic 2D physics primitives for static/dynamic/kinematic AABB
350
- bodies, sensors/triggers, enter/stay/exit callbacks, layer masks,
351
- deterministic AABB and ray queries, material response (now including real
352
- tangential friction), simple fixed/distance/spring/motor constraints,
353
- rollback-equivalent stepping, and budget metrics.
354
- - Public deterministic movement primitives for KCC-like slopes, steps, ledges,
355
- moving platforms, elevators, one-way platforms, wall slides, jump buffering,
356
- coyote time, top-down acceleration/drag/sliding, nav steering, quantized FPS
357
- aim, deterministic recoil, lag-compensated target rewind, and rollback
358
- equivalence.
359
- - Public headless sample-scene fixtures for Asteroids, Simple FPS, Twin Stick,
360
- Platform Shooter, Arena Brawler, Vehicle, Mini Golf, Waiting Room, Boat/Water,
361
- and Animator mechanics, each with named counters, rollback-equivalent
362
- checksums, and CLI-certified mechanic invariants.
363
- - Counter Duel package-local example with replay verification and event output.
50
+ The networked client receives the authority's exact runtime identity and
51
+ session-config bytes, asks the game for a matching runtime through its runtime
52
+ factory, and rejects a locally loaded pack mismatch before frame 0. Replays use
53
+ the same identity/config/factory path.
364
54
 
365
- ## Deterministic Standard Library
55
+ ## Public projections and secrets
366
56
 
367
- The determinism static checker blocks the entire transcendental family
368
- (`Math.sin/cos/tan/atan2/sqrt/hypot/pow/...`), `Math.random`, and `Date.now`
369
- inside simulation code those can differ in low bits across JS engines and
370
- desync a lockstep match. Every simulation surface these primitives cover is
371
- provided as a pure-integer, byte-identical replacement. **Never hand-roll fixed
372
- math or reach for `Math.*`; use these.**
57
+ Every peer applies the same confirmed inputs and authority commands. Optional
58
+ secret systems add an authority-owned projection for choices, random draws,
59
+ decks, bags, and roles. Private values go only to their owners; signed public
60
+ consequences enter one confirmed frame and therefore survive rollback, replay,
61
+ reconnect, and match-log verification.
373
62
 
374
- `ctx.math` (`createDeterministicMath`, wired into every step context):
63
+ ## Reference backend and future acceleration
375
64
 
376
- - **Scalar:** `sqrt` (throws on negative), `abs`, `sign`, `min`, `max`, `lerp`,
377
- `mod` (Euclidean; throws on modulus 0), `inverseLerp`, `remap`, `smoothstep`,
378
- `exp`, `log`/`log2Fixed` (throw on non-positive). `exp`/`log` are ≤1% over
379
- their fixed-representable range; `sqrt` is exact-to-a-unit.
380
- - **Trig & angles (unit is TURNS, one revolution == `fixedScale`):** accurate
381
- `sinTurns`/`cosTurns` (5th-order minimax, exact at cardinal turns, ≤5e-3 sweep
382
- error), `tanTurns`, `atan2(y, x)` → turns in `[0, fixedScale)` CCW from +x
383
- (`atan2(0,0) === 0`), `wrapTurns`, `angleDeltaTurns` (shortest signed),
384
- `turnsToRadians`/`radiansToTurns`. `createDeterministicMath` requires
385
- `fixedScale % 4 === 0`.
386
- - **Vectors:** vec2 `sub/scale/dot/cross/lengthSq/length/distanceSq/distance/
387
- normalize` (zero → `{0,0}`), `hypot`, `perp/negate/rotate/fromAngleTurns/
388
- angleTurns`; vec3 core `add/sub/scale/dot/cross/lengthSq/length/distance/
389
- normalize/lerp/negate`.
390
- - **Domains & overflow:** domain violations (`sqrt(neg)`, `log(≤0)`, `mod(_,0)`,
391
- non-integer fixed inputs) fail fast. Vector/`abs`/`sign`/negation ops saturate
392
- at `±maxFixed` rather than throw. `mul`/`div` are integer-exact only while
393
- `|a·b| ≤ 2^53` (~95k real units at the default `fixedScale` 1000).
65
+ `createKinetixWorldRuntime` is the correctness/reference backend. Its current
66
+ checkpoints deep-copy world snapshots, so it is not presented as the final
67
+ high-performance backend. The batched runtime ABI is the stable insertion point
68
+ for optimized JS, WASM, or native implementations.
394
69
 
395
- `ctx.random` (`DeterministicRandom`) seeded, reproducible sampling on top of
396
- the existing `nextInt/nextFixed/fork`: `nextBool`, `nextRangeFixed`,
397
- `nextAngleTurns`, `pickOne` (throws on empty), `weighted` (throws on length
398
- mismatch / non-positive total), `gaussian(math)` (Box-Muller).
70
+ A WASM backend is justified only after end-to-end runtime/session profiling
71
+ shows simulation is at least 30% of frame cost and a prototype beats optimized
72
+ JS by at least 20%, including checkpoint copies and boundary overhead, while
73
+ producing identical per-frame checksums in Chromium and WebKit.
399
74
 
400
- Segment geometry (imported from the package, like the AABB/circle primitives):
401
- `orientation`, `pointOnSegment`, `segmentsIntersect`, `closestPointOnSegment`,
402
- `segmentPointDistance`, `segmentSegmentDistance` (the distance/closest ops take a
403
- `DeterministicMath` for their `sqrt`).
404
-
405
- Hash & value noise (`noise.ts`, pure importable functions — replaces the
406
- cross-engine `Math.sin`-hash desync class): `hashUint32`, `hash2` (integer
407
- avalanche hashes), `valueNoise1D`/`valueNoise2D` (smooth, in `[-fixedScale,
408
- fixedScale]`), `fbm2D`.
409
-
410
- ## Commands
75
+ ## Validation
411
76
 
412
77
  ```bash
413
- npm test
414
- npm run build
415
-
416
- npm run project:scaffold -- ./deterministic-game --name "Arena Test"
417
- npm run project:certify -- ./deterministic-game/syncplay.project.json --require descriptor,assets,config,replay-runtime,static-determinism --frames 32 --out-dir ./deterministic-game/artifacts/deterministic --json ./deterministic-game/artifacts/deterministic/project-certification.json
418
- npm run project:summary -- ./deterministic-game/artifacts/deterministic/project-certification.json --out ./deterministic-game/artifacts/deterministic/project-certification-summary.md --json ./deterministic-game/artifacts/deterministic/project-certification-summary.json
419
- npm run project:preflight -- ./deterministic-game/syncplay.project.json --certification ./deterministic-game/artifacts/deterministic/project-certification.json --summary ./deterministic-game/artifacts/deterministic/project-certification-summary.md --dist ./deterministic-game/dist --out ./deterministic-game/artifacts/deterministic/project-preflight.md --json ./deterministic-game/artifacts/deterministic/project-preflight.json
420
- npm run project:check -- ./deterministic-game/syncplay.project.json --require descriptor,assets,config,replay-runtime,static-determinism --frames 32 --out-dir ./deterministic-game/artifacts/deterministic --dist ./deterministic-game/dist --out ./deterministic-game/artifacts/deterministic/project-check.md --json ./deterministic-game/artifacts/deterministic/project-check.json --junit ./deterministic-game/artifacts/deterministic/project-check.xml --release-json ./deterministic-game/artifacts/deterministic/project-release-evidence.json
421
- npm run project:release-verify -- ./deterministic-game/artifacts/deterministic/project-release-evidence.json --json ./deterministic-game/artifacts/deterministic/project-release-verification.json
422
- npm run project:release-bundle -- ./deterministic-game/artifacts/deterministic/project-release-evidence.json --json ./deterministic-game/artifacts/deterministic/project-release-bundle.json
423
- npm run project:release-bundle-verify -- ./deterministic-game/artifacts/deterministic/project-release-bundle.json --out ./deterministic-game/artifacts/deterministic/project-release-bundle-verification.md --json ./deterministic-game/artifacts/deterministic/project-release-bundle-verification.json --junit ./deterministic-game/artifacts/deterministic/project-release-bundle-verification.xml
424
- npm run project:release-bundle-schema -- --json artifacts/reports/project-release-bundle-schema.json
425
- npm run project:ci-workflow -- --out .github/workflows/syncplay-ci.yml --json artifacts/reports/project-ci-workflow.json
426
- npm run project:scaffold -- ./deterministic-h5 --name "H5 Arena" --template h5 --sdk-version ^0.8.0 --deterministic-version ^0.3.0
427
- npm run project:check -- ./deterministic-h5/syncplay.project.json --require descriptor,assets,config,replay-runtime,creator-boundary,static-determinism --frames 32 --out-dir ./deterministic-h5/artifacts/deterministic --dist ./deterministic-h5/dist --out ./deterministic-h5/artifacts/deterministic/project-check-browser.md --json ./deterministic-h5/artifacts/deterministic/project-check-browser.json --junit ./deterministic-h5/artifacts/deterministic/project-check-browser.xml --release-json ./deterministic-h5/artifacts/deterministic/project-release-evidence-browser.json --browser-runtime chromium --browser-json ./deterministic-h5/artifacts/deterministic/project-browser-proof-chromium.json
428
- npm run project:release-verify -- ./deterministic-h5/artifacts/deterministic/project-release-evidence-browser.json --require-browser-proof --json ./deterministic-h5/artifacts/deterministic/project-release-verification-browser.json
429
- npm run project:release-bundle -- ./deterministic-h5/artifacts/deterministic/project-release-evidence-browser.json --require-browser-proof --json ./deterministic-h5/artifacts/deterministic/project-release-bundle-browser.json
430
- npm run project:release-bundle-verify -- ./deterministic-h5/artifacts/deterministic/project-release-bundle-browser.json --out ./deterministic-h5/artifacts/deterministic/project-release-bundle-verification-browser.md --json ./deterministic-h5/artifacts/deterministic/project-release-bundle-verification-browser.json --junit ./deterministic-h5/artifacts/deterministic/project-release-bundle-verification-browser.xml
431
- npm run project:doctor -- ./deterministic-h5/syncplay.project.json --require-browser-proof --json ./deterministic-h5/artifacts/deterministic/project-doctor-ci.json --junit ./deterministic-h5/artifacts/deterministic/project-doctor-ci.xml
432
- npm run --prefix ./deterministic-h5 build
433
- npm run project:scaffold -- ./deterministic-systems --name "Systems Test" --template systems
434
- npm run project:certify -- ./deterministic-systems/syncplay.project.json --require all --frames 12 --agents 4 --slots 1,2 --out-dir ./deterministic-systems/artifacts/deterministic --json ./deterministic-systems/artifacts/deterministic/project-certification-full.json
435
- npm run project:summary -- ./deterministic-systems/artifacts/deterministic/project-certification-full.json --out ./deterministic-systems/artifacts/deterministic/project-certification-summary.md --json ./deterministic-systems/artifacts/deterministic/project-certification-summary.json
436
- npm run project:certify -- ./deterministic-game/syncplay.project.json --require all --frames 128 --agents 128 --out-dir ./deterministic-game/artifacts/deterministic --json ./deterministic-game/artifacts/deterministic/project-certification-full.json
437
- npm run certify:v1
438
- npm run certify:v1 -- --json artifacts/certification/suite.json
439
- npm run certify:v2 -- --profile required-full --json artifacts/certification/v2-full.json
440
- npm run certify:v2 -- --profile chaos --json artifacts/certification/chaos.json --junit artifacts/certification/chaos.xml
441
- npm run certify:v2 -- --profile chaos --filter resync --json artifacts/certification/chaos-resync.json
442
- npm run certify:v2 -- --profile chaos --filter hostile --json artifacts/certification/chaos-hostile.json
443
- npm run certify:v2 -- --profile chaos --filter rollback-boundary --json artifacts/certification/chaos-rollback-boundary.json
444
- npm run certify:v2 -- --profile chaos --filter replay-identity --json artifacts/certification/chaos-replay-identity.json
445
- npm run certify:v2 -- --profile chaos --filter commands --json artifacts/certification/chaos-commands.json
446
- npm run certify:v2 -- --profile chaos --filter events --json artifacts/certification/chaos-events.json
447
- npm run certify:v2 -- --profile chaos --filter input-policy --json artifacts/certification/chaos-input-policy.json
448
- npm run certify:v2 -- --profile chaos --filter network --json artifacts/certification/chaos-network.json
449
- npm run certify:v2 -- --profile chaos --filter random --json artifacts/certification/chaos-random.json
450
- npm run certify:v2 -- --profile chaos --filter tick --json artifacts/certification/chaos-tick.json
451
- npm run certify:v2 -- --profile chaos --filter assets --json artifacts/certification/chaos-assets.json
452
- npm run certify:v2 -- --profile chaos --filter physics --json artifacts/certification/chaos-physics.json
453
- npm run certify:v2 -- --profile chaos --filter movement --json artifacts/certification/chaos-movement.json
454
- npm run certify:v2 -- --profile chaos --filter scale-128 --json artifacts/certification/chaos-scale-128.json
455
- npm run certify:v2 -- --profile chaos --explain-fixture resync.snapshot-tail
456
- npm run static:determinism -- --json artifacts/certification/static-determinism.json --junit artifacts/certification/static-determinism.xml
457
- npm run test:pack-smoke
458
- npm run certify:standalone-complete
459
- npm run certify:engine-complete -- --players 128 --frames 5000 --seed 71 --json artifacts/certification/engine-complete.json --junit artifacts/certification/engine-complete.xml
460
- npm run benchmark:engine-complete -- --players 128 --frames 100000 --seed 71 --enforce-thresholds --json artifacts/certification/engine-complete-stress.json --junit artifacts/certification/engine-complete-stress.xml
461
- npm run certify:v2 -- --profile required-full --players 128 --frames 1000 --seed 71 --json artifacts/certification/engine-parity-required-full.json --junit artifacts/certification/engine-parity-required-full.xml
462
- npm run benchmark:engine-parity -- --profile stress --players 128 --frames 100000 --seed 71 --json artifacts/certification/engine-parity-stress-100k.json --junit artifacts/certification/engine-parity-stress-100k.xml
463
- npm run report:engine-parity-matrix:certified
464
- npm run static:determinism -- --json artifacts/certification/static-engine-current.json
465
- npm run certify:v2 -- --runtime chromium --filter browser-boundary --json artifacts/certification/engine-parity-v2-browser-runtime.json
466
- npm run certify:v2 -- --stress --filter performance-128 --frames 1000 --json artifacts/certification/engine-parity-v2-stress-shortcut.json
467
- npm run report:diff -- artifacts/certification/engine-parity-required-full.json artifacts/certification/engine-parity-stress-100k.json --max-differences 20 --json artifacts/certification/engine-parity-benchmark-diff.json
468
- npm run check -- tests/fixtures/pass --strict
469
- { npm run check -- tests/fixtures/fail --strict; test "$?" -eq 1; }
470
-
471
- npm run lab:offline-replay -- --players 128 --frames 100000 --seed 3
472
- npm run lab:offline-replay -- --players 4 --frames 1000 --seed 7 --out artifacts/replays/browser-p4-seed7.json
473
- npm run lab:replay-inspect -- artifacts/replays/browser-p4-seed7.json --frame 120 --explain-checksum --out artifacts/reports/browser-p4-frame120.json
474
- { npm run lab:replay-diff -- artifacts/replays/lab-p4-seed11.json artifacts/replays/lab-p4-seed12.json --frame 60 --max-differences 20 --json; test "$?" -eq 1; }
475
78
  npm run build
476
- npm run lab:replay-verify-browser -- artifacts/replays/browser-p4-seed7.json --runtime chromium
477
- npm run lab:replay-verify-browser -- artifacts/replays/browser-p4-seed7.json --runtime webkit
478
- npm run lab:protocol-rollback -- --players 128 --frames 1000 --seed 19 --min-delay 1 --max-delay 8 --duplicate-permille 100 --loss-permille 100 --resend-interval 9 --max-resend-attempts 14 --disconnect-start 100 --disconnect-end 130
479
- npm run lab:protocol-rollback -- --players 8 --frames 300 --seed 47 --min-delay 1 --max-delay 6 --bundle-size 5 --json artifacts/reports/protocol-p8.json
480
- npm run lab:protocol-rollback -- --players 4 --frames 120 --seed 57 --min-delay 1 --max-delay 5 --duplicate-permille 100 --event-timeline-limit 3
481
- npm run lab:protocol-rollback -- --game counter-duel --players 4 --frames 300 --seed 53 --min-delay 1 --max-delay 7 --duplicate-permille 100 --json artifacts/reports/counter-duel-protocol-p4.json
482
- npm run lab:netcode -- --shape input-minimal --players 128 --hz 10 --frames 1000 --rtt 200 --jitter 100 --loss 2 --duplicate-permille 100 --event-timeline-limit 0 --json artifacts/reports/netcode-p128-input-minimal.json
483
- npm run lab:netcode -- --shape moderate-state --players 128 --hz 10 --frames 1000 --rtt 200 --jitter 100 --loss 2 --duplicate-permille 100 --event-timeline-limit 0 --json artifacts/reports/netcode-p128-moderate-state.json
484
- npm run lab:netcode -- --shape command-bursts --players 128 --hz 10 --frames 1000 --rtt 200 --jitter 100 --loss 2 --duplicate-permille 100 --event-timeline-limit 0 --json artifacts/reports/netcode-p128-command-bursts.json
485
- npm run lab:prediction-culling -- --mode off --players 128 --objects-per-player 8 --frames 1000 --seed 19 --radius 180 --json artifacts/reports/prediction-culling-off-p128.json
486
- npm run lab:prediction-culling -- --mode local-area --players 128 --objects-per-player 8 --frames 1000 --seed 19 --radius 180 --json artifacts/reports/prediction-culling-local-area-p128.json
487
- npm run lab:netcode -- --shape moderate-state --players 128 --hz 10 --frames 1000 --rtt 200 --jitter 100 --loss 2 --duplicate-permille 100 --prediction-culling local-area --objects-per-player 8 --prediction-radius 180 --event-timeline-limit 0 --json artifacts/reports/netcode-p128-moderate-state-culling.json
488
- npm run lab:local-ws-server -- --port 9301 &
489
- server_pid=$!
490
- trap 'kill $server_pid' EXIT
491
- npm run lab:wait-for-url -- --url http://127.0.0.1:9301/health --timeout-ms 10000
492
- npm run lab:ws-adapter-test -- --url ws://127.0.0.1:9301/protocol --players 4 --frames 120 --seed 17 --min-delay 1 --max-delay 5 --loss-permille 10 --duplicate-permille 100
493
- npm run lab:r3f-render-adapter -- --players 4 --frames 120 --seed 9
494
- { npm run lab:venus-mp-budget -- --players 128 --hz 30 --frames-per-message 1 --max-players 10 --json; test "$?" -eq 1; }
495
- npm run lab:venus-mp-budget -- --players 128 --hz 30 --frames-per-message 3 --max-players 128 --json
496
- npm run lab:physics-cert -- --engine builtin-fixed --shape fixed-arena --players 8 --frames 1000 --seed 7 --snapshot-every 1 --json artifacts/reports/physics-builtin-fixed-arena-p8.json
497
- npm run lab:physics-cert -- --engine builtin-fixed --shape slot-load --players 128 --frames 1000 --seed 11 --snapshot-every 8 --json artifacts/reports/physics-builtin-slot-load-p128.json
498
- { npm run lab:physics-cert -- --engine rapier2d-compat --shape fixed-arena --players 4 --frames 60 --seed 17 --snapshot-every 2 --json artifacts/reports/physics-rapier2d-compat-known-fail.json; test "$?" -eq 1; }
499
- npm run lab:number -- --mode fixed-q16 --frames 100000 --seed 7
500
- npm run lab:number-browser -- --mode fixed-q16 --frames 100000 --seed 7 --runtime chromium --json artifacts/certification/number-fixed-q16-chromium.json
501
- npm run lab:number-browser -- --mode integer --frames 100000 --seed 7 --runtime chromium --json artifacts/certification/number-integer-chromium.json
502
- npm run lab:number-browser -- --mode fixed-q16 --frames 100000 --seed 7 --runtime webkit --json artifacts/certification/number-fixed-q16-webkit.json
503
- npm run lab:number-browser -- --mode integer --frames 100000 --seed 7 --runtime webkit --json artifacts/certification/number-integer-webkit.json
504
- npm run lab:replay-verify-browser -- artifacts/replays/browser-p4-seed7.json --runtime chromium --playwright-module /tmp/rdm-missing-playwright --json artifacts/certification/browser-replay-skip-proof.json
505
- npm run lab:number-browser -- --mode fixed-q16 --frames 10 --seed 7 --runtime chromium --playwright-module /tmp/rdm-missing-playwright --json artifacts/certification/number-browser-skip-proof.json
506
- npm run example:counter-duel -- --players 4 --frames 300 --seed 3 --verify --out artifacts/replays/counter-duel-p4.json --json artifacts/reports/counter-duel-p4.json
507
- npm run example:fixed-arena -- --players 128 --frames 240 --seed 19 --verify --out artifacts/replays/fixed-arena-p128.json --json artifacts/reports/fixed-arena-p128.json
508
- npm run schema:validate -- tests/fixtures/descriptors/pass
509
- npm run schema:dump -- tests/fixtures/descriptors/pass/counter-duel.json --state tests/fixtures/descriptors/state/counter-duel-state.json --frame 42 --out artifacts/reports/counter-duel-schema-frame42.json
510
- npm run schema:types -- tests/fixtures/descriptors/pass/counter-duel.json --name CounterDuel --out artifacts/reports/counter-duel-types.ts
511
- npm run schema:binary -- tests/fixtures/descriptors/pass/counter-duel.json --name CounterDuel --out artifacts/reports/counter-duel-binary.ts --json artifacts/reports/counter-duel-binary.json
512
- cd ../../server/mp-room-server && npm run build
513
- cd ../../server/mp-room-server && npm test -- --run src/rooms/deterministicMultiplayerRoom.integration.test.ts
514
- cd ../../server/mp-room-server && npm test -- --run src/routes/deterministicTicketsGateway.integration.test.ts
79
+ npm run test:core
515
80
  ```
516
81
 
517
- Generated project scaffolds include a `.gitignore` for `node_modules/`, `dist/`,
518
- and generated `artifacts/`; keep certification/release evidence with CI logs
519
- unless your project has a separate artifact archive policy.
520
-
521
- ## Report Schema
522
-
523
- All CLI reports are stable JSON intended for terminal review and CI parsing.
524
- Certification reports include `schemaVersion`, `result`, `failures`, category or
525
- fixture records, invariant maps, metrics, checksums, and profile/seed/frame
526
- identity. Replay reports include aggregate file/frame/checksum counts plus
527
- per-file mismatch records. Asset-cook reports include per-file expected/actual
528
- outcomes, stable asset DB hashes, schema hashes, dependency hashes, lookup
529
- hashes, stable dependency ordering, stable recook checks, prototype-spawn
530
- checks, and stale manifest rejection checks.
531
-
532
- TypeScript report types are exported for certification, chaos certification,
533
- Engine-parity certification, protocol rollback reports, replay inspect/diff
534
- reports, asset cooking, static determinism suppressions, and generic report
535
- diffs. Use `report:diff` for category-level artifact regression review and
536
- `lab:replay-diff` for frame-level replay state diffs.
537
-
538
- ## Asset Cooking
539
-
540
- `cook:syncplay-assets -- --verify fixtures/assets --json <path>` cooks every
541
- valid asset fixture and expects every invalid fixture to fail. The command proves
542
- byte-stable recooking under reordered source assets, stable asset DB and lookup
543
- hashes, stable schema hashes, stable dependency hashes, deterministic dependency
544
- ordering, prototype spawn identity, duplicate ID rejection, unresolved reference
545
- rejection, unquantized float rejection, schema mismatch rejection,
546
- nondeterministic dependency rejection, stale engine rejection, and stale asset
547
- database hash rejection.
548
-
549
- Runtime code can call `cookDeterministicAssets`,
550
- `materializePrototypeEntities`, and `assertAssetManifestMatches` directly. Asset
551
- manifests should be treated as replay identity inputs: changing the asset DB
552
- hash or deterministic asset engine version invalidates old replays unless a
553
- migration explicitly maps the old identity to the new one.
554
-
555
- ## Replay Debugging
556
-
557
- `replay:verify` verifies single replay files or directories, supports frame
558
- ranges, emits aggregate and per-file mismatch counts, and returns first-mismatch
559
- diagnostics. `lab:offline-replay` can export small replay artifacts for browser
560
- or debugger use and refuses oversized materialized transcripts; use metrics-only
561
- long runs for 128-player/100,000-frame stress proofs. `lab:replay-inspect`
562
- dumps a stable frame state, and `lab:replay-diff` emits capped state-path
563
- differences between two replay frames.
564
-
565
- Snapshot-tail reconstruction is covered by chaos certification for late
566
- spectator, killcam, and resync-style workflows. Corrupted replay fixtures under
567
- `fixtures/replays/corrupt` are expected failures and must stay deterministic.
568
-
569
- ## Static Determinism
570
-
571
- `static:determinism` runs the static checker against known-good package fixtures
572
- and known-bad fixtures, writes JSON and JUnit, and fails if package source emits
573
- strict errors or if known-bad fixtures stop failing. Diagnostics include
574
- remediation text. Valid suppressions must use
575
- `// rdm-ignore-next-line <rule-id>: <reason>` and are reported with file, line,
576
- rule, and reason; invalid suppressions are errors.
577
-
578
- `static:determinism` with explicit paths (`--entry`, `--paths`) follows the
579
- import graph transitively by default (`--no-follow-imports` opts out); the
580
- JSON artifact records `requestedPaths` (CLI inputs), `checkedPaths` (files
581
- actually checked, post-traversal), `followImports`, and `unresolvedImports`
582
- (relative imports that resolve to no file — unchecked holes). Bare package
583
- specifiers are never followed; if your simulation uses tsconfig path aliases,
584
- pass `--project tsconfig.json` so aliased imports resolve and get checked —
585
- without it they are skipped like package imports. Package self-certification
586
- (no explicit paths) checks its curated source list without following imports.
587
-
588
- The checker covers host random/time, timers, async simulation work, I/O,
589
- unordered object iteration, random sort comparators, render-object mutation,
590
- uncertified physics stepping, and descriptor-declared state-field access.
591
-
592
- ## Browser Certification
593
-
594
- Browser replay and number labs run through Playwright when the requested browser
595
- runtime is available. Chromium pass artifacts are required when Chromium is
596
- installed; WebKit writes either a pass artifact or an explicit skip artifact.
597
- Standalone provisioning can pass `--playwright-module`; missing tooling writes
598
- clean skip artifacts instead of fabricating checksum or value matches.
599
-
600
- The optional browser profile checks package and SDK-facing browser-safe exports
601
- for Node-only module imports, filesystem APIs, local server APIs, and
602
- certification-only APIs. Node WebSocket helpers remain available only through
603
- the `./node` subpath. V2 certification accepts `--runtime node|chromium|webkit`
604
- and records the selected runtime in the suite and category reports; actual
605
- browser execution remains in the browser replay and number lab commands.
606
-
607
- ## Performance And Stress
608
-
609
- `benchmark:engine-parity` emits diffable 128-player metrics for input-minimal,
610
- moderate-state, protocol, bot, projectile/sample, replay, and performance
611
- workloads. Timing thresholds are reported but non-blocking unless
612
- `--enforce-thresholds` is set. The opt-in stress profile supports
613
- 100,000-frame/128-player runs and fails on desync, missing rollback history, or
614
- corrupted replay output. `certify:v2 -- --stress` is a shortcut for selecting
615
- the stress profile when no explicit `--profile` is provided.
616
-
617
- Use the generated benchmark and stress artifacts with `report:diff` to review
618
- regressions from the terminal. Long stress runs should stay opt-in for local and
619
- CI workflows unless a separate CI policy requires them.
620
-
621
- Use `certify:standalone-complete` to refresh the standalone proof contract in
622
- the required order. It regenerates `engine-complete`,
623
- `engine-complete-stress`, `engine-parity-required-full`,
624
- `engine-parity-stress-100k`, the evidence-backed parity matrix, and the static
625
- determinism audit. Use `report:engine-parity-matrix:certified` after refreshing
626
- individual artifacts manually; it loads evidence from
627
- `artifacts/certification`, enforces zero required CLI-verifiable gaps, and
628
- writes the canonical `engine-parity-matrix.json` artifact consumed by
629
- `static:determinism`.
630
-
631
- ## Parity Claims
632
-
633
- The parity claim is standalone, headless, CLI-verifiable deterministic
634
- multiplayer parity for the locally provable deterministic engine engine capabilities:
635
- rollback, replay, fixed numerics, deterministic authoring checks, asset
636
- cooking, protocol delay/fault handling, browser runtime parity, and 128-player
637
- stress readiness.
638
-
639
- This does not include Venus MP integration, production backend certification,
640
- or renderer/r3f parity. Working with third-party game engines is not a goal. Navigation
641
- and bot parity are headless exported runtime primitives, not external engine
642
- project importers, visual editors, production cloud services, or polished
643
- creator-facing sample scenes.
644
-
645
- ## Chaos Certification
646
-
647
- The chaos profile is CLI-only and standalone. It does not use Venus MP, Cloud
648
- Run, Firebase, r3f, browser rendering, or production room servers. It is meant
649
- to prove rollback/resync protocol behavior before external adapters make
650
- failures harder to isolate.
651
-
652
- Chaos fixtures are nested under the normal `certify:v2` report model as a
653
- single `chaos` category. Each fixture has a stable `fixtureId`, `category`,
654
- `expectedResult`, seed, players, frames, network model, invariant map, metrics,
655
- artifact path, checksum, and result. `expected-failure` means the fixture passes
656
- only when the bad input, corrupted replay, evicted rollback history, or config
657
- mismatch is detected deterministically.
658
-
659
- Fixture categories are `resync`, `hostile`, `rollback-boundary`,
660
- `replay-identity`, `commands`, `events`, `input-policy`, `network`, `random`,
661
- `tick`, `assets`, `physics`, `movement`, and `scale-128`. Use `--filter` with
662
- any category or fixture id to run a focused subset. Use `--explain-fixture` to
663
- print what a fixture proves, its expected result mode, artifact path, and pass
664
- invariants.
665
-
666
- `static:determinism` remains the prerequisite source-text lint proof for chaos
667
- certification. The chaos profile intentionally focuses on runtime protocol,
668
- replay, rollback, and asset/config behavior rather than duplicating static
669
- analysis.
670
-
671
- Use `report:diff` for benchmark, certification, and chaos JSON artifacts. It
672
- compares stable report JSON by path, emits capped differences, and exits
673
- nonzero when reports differ. Use `lab:replay-diff` for frame-level replay state
674
- diffs.
675
-
676
- ## r3f Boundary
677
-
678
- r3f is a view layer for this package. Simulation state remains plain
679
- checksummed data, the r3f adapter projects a frozen render frame, and React
680
- components render that frame without mutating session state.
681
-
682
- Input should be captured in DOM/r3f/UI code, normalized through
683
- `bindInput(slot, normalize)`, and submitted as descriptor-shaped deterministic
684
- input before the next fixed tick. React render timing, Three.js objects,
685
- materials, vectors, and interpolation floats stay outside replay checksums.
686
-
687
- ## Known Gaps
688
-
689
- - Browser replay verification passes locally in Chromium and WebKit for the lab
690
- replay when Playwright browser runtimes are available. The optional browser
691
- profile also checks that package and SDK-facing browser-safe exports exclude
692
- Node-only modules, local servers, filesystem APIs, and certification-only APIs.
693
- Browser replay and browser number labs accept `--playwright-module` for
694
- standalone provisioning tests and emit explicit skip artifacts when Playwright
695
- is unavailable.
696
- Package-local fixtures under `fixtures/assets`, `fixtures/replays`,
697
- `fixtures/static`, and `fixtures/browser-safe` are the reusable corpus for
698
- asset cooking, replay verification, static determinism, and browser-boundary
699
- certification.
700
- `tests/apps/android-webview-deterministic` currently provides an Android
701
- WebView APK harness, but Android emulator/logcat verification is not part of
702
- the required local proof set.
703
- - Vite plugin/config helpers intentionally use structural Vite-compatible types
704
- instead of importing Vite, so creator projects can gate builds without a Vite
705
- peer dependency from the deterministic package.
706
- - Static checker can optionally load a descriptor and fail strict mode for
707
- undeclared `state.foo`/`state["foo"]` references in simulation code.
708
- - Schema descriptors validate shape and identity, produce schema-aware
709
- serializers/deserializers and frame dumps, and generate TypeScript types plus
710
- default input factories. `schema:binary` emits separate descriptor-derived
711
- binary serializer source with an embedded schema hash and round-trip proof.
712
- - Replay inspect/diff and `verifyReplayWithDescriptor` support descriptor-backed
713
- arbitrary game replays when the caller supplies the game step/default input.
714
- - Protocol rollback reports include bounded event timeline summaries, and
715
- generic r3f/audio/UI/custom effect consumers can read frozen event payloads.
716
- - The r3f-compatible adapter is verified as a render boundary, Fixed Arena
717
- exports a creator-facing r3f reference view model, and the SDK test-app
718
- renders that view in a visual sample.
719
- - Prediction culling is a local AOI execution lab, not a production-optimized
720
- partial resimulation scheduler yet.
721
- - Reference sample certification is headless mechanics coverage, not polished
722
- creator-facing r3f sample scenes yet.
723
- - Sample-scene fixtures expose reusable headless mechanics counters for CLI
724
- certification. They are not polished game templates, rendered examples, or
725
- creator-facing r3f scenes yet.
726
- - Navigation primitives include cooked graph assets, A*, regions, blockers,
727
- off-mesh links, flow fields, tilemap graphs, and deterministic agent stepping.
728
- They do not yet include deterministic navmesh import/baking from DCC or r3f
729
- scene geometry.
730
- - Bot primitives include typed blackboards, HFSM, Behavior Tree, Utility
731
- selection, deterministic asset hashes, and rollback tests. They do not yet
732
- include a visual bot authoring editor or creator-facing bot asset pipeline.
733
- - Movement primitives cover the CLI-verifiable mechanics needed by platformer,
734
- top-down, simple-FPS, and 3D KCC fixtures, including rollback-safe capsule
735
- movement, slopes, steps, moving platforms, and physics queries. They do not
736
- yet include authored r3f scene collision import or visual controller tooling.
737
- - `mp-room-server` compatibility currently proves worker harness and
738
- `RoomManager` behavior, direct `TicketStore` `/ws` auth, and mocked-auth
739
- POST `/tickets` ticket minting. SDK transport compatibility proves public
740
- `WsMultiplayerApi` deterministic input/confirmation traffic plus forced
741
- reconnect with a fresh ticket. Gateway negative-path coverage proves expired
742
- tickets, unauthenticated deterministic messages, auth timeout, stale socket
743
- replacement, and server pre-timeout reconnect instructions. When Firebase
744
- Auth and Firestore emulators are configured, the optional Firebase integration
745
- test covers Auth ID-token verification and Firestore `profiles/{uid}` lookup
746
- through the same POST `/tickets` and `/ws` deterministic gateway path.
747
- - Built-in fixed physics certification includes package-local 2D/2.5D and 3D
748
- deterministic worlds with sensors/triggers, queries, layer masks, callbacks,
749
- constraints, CCD helpers, boxes, spheres, capsules, mesh static bounds,
750
- deterministic angular state, and 128/512/2048-body stress samples; the
751
- `builtin-rigid` lane additionally certifies the sequential-impulse rigid-body
752
- solver (stacking, joints, CCD) under the four determinism gates. Remaining
753
- limits are visual collision authoring/import, convex-hull decomposition,
754
- dynamic mesh-vs-mesh collision, ragdolls in checksummed state, and replacing
755
- external physics engines; the ≤2 ms/step 128-body budget awaits an
756
- allocation-free solver pass. Rapier cert currently fails with
757
- `knownIssueRapier910=reproduced`,
758
- `uninterruptedChecksum=916fe725ae2e3215`, and
759
- `restoredChecksum=9e42622842bffff6`.
82
+ The core suite covers checkpoint ownership/release, frame-zero rollback, v2
83
+ snapshot hydration, replay verification, authority persistence, latency/loss
84
+ convergence, late join, spectators, bots, secrets, and a real Kinetix world
85
+ driven through `createSyncplaySession`.