room-routing-acceptance.json
docs/evidence/room-routing-acceptance.json
1{
2 "recordedAt": "2026-10-25T16:07:22.291600+00:00",
3 "baseCommit": "07462646ffb01d22a1312e74dbb5f5699908975d",
4 "scope": "Regional room selection, private supervised child processes, retained-engine return journeys and single-use WebSocket audience tickets. Full milestones 0\u201318 remain active.",
5 "fullPlanEstimatePercent": 69,
6 "sourceSha256": {
7 ".dockerignore": "787194d1ac2415aa1cea77185841b37efeebba5e3018beacd744d58e66025f0e",
8 ".gitignore": "1e7d3701f5f2a58f5fa3369cd76afab27488a3687241449497459f41138ca9e6",
9 "Dockerfile.rooms": "372bab5485b9c152a02adb187e40c2456b96cc9ef6ae795028fe2fa436a92234",
10 "apps/player/main.ts": "fd5b4045ed565f4ad4dc7113d6b4c27edd1368e923476185f84c8ac39cdcfd7f",
11 "compose.rooms.yaml": "36512221c9a5ee44925b827839221a727ec2be7934cd58461b96c3c6e8c31ecd",
12 "package.json": "031d7e018cf4b18546ebbef13bc20e82207aa40cc4397b1b1bfeb60102c4c4b2",
13 "packages/net/persistent-client.ts": "237061511204af561a1d5722d8fa02c11241d0e3239f1ed67f6ae4d4fa52b8d7",
14 "packages/schema/index.ts": "33bf0615cb15f33782bb9dec05a70c59134c24082200301af10ee71cd465cf77",
15 "playwright.rooms.config.ts": "9f10fdde94114a9771335eeac36d33e77f7eef1bf12f7010205fe60bdd846d6f",
16 "services/engine/registry.ts": "ec7829e191f915aa91b421e2e5533e572167840c002bf9647494e32f6e0f2c3c",
17 "services/engine/runtime.ts": "8bf09f50c075dbd71b7e124e45702a5edd9674f4e46e752d7da39ec2213b0ed7",
18 "services/persistent/main.ts": "43e85be771dd86a153bdcdf25b95545d6d011a50de0f764a37c961844b891037",
19 "services/persistent/server.ts": "12cbeb9516df54abefa0278b441f53674d1bd38f92d12dababee2f08b03c3527",
20 "services/routing/config.ts": "8abb113e348dff6b1e7aac7a4dc46e8601330a5af832957b26c15d1187837366",
21 "services/routing/main.ts": "27024660c200a85ba45f75377ecf25a6a72a4ca4193a196316eee7e3581b9265",
22 "services/routing/pool.ts": "5ac475edf9da6cfaf83a992f347ca479d507c5ffdfc9ad8bf45ca621c2c197d5",
23 "services/routing/server.ts": "dae981ffea82afdd94180343f79a51cd3bb76a5e70afbfab36333accc746ec5b",
24 "services/routing/tickets.ts": "93572df96b86b65bed50a051229f5d7a536bff290abedffc3460f132073cbdc5",
25 "services/routing/welcome.ts": "e5b7d45e6c000a3b1cfd91d11fb68d4f0dbcd1f941a1ae4c02f5778aa831faf3",
26 "tests/browser/room-routing.spec.ts": "7d9da44c0aaaf69b5a7bac36f2c279a8e6e3d53917ccea10d92b4a932e13e4c3",
27 "tests/fixtures/regional-browser-host.ts": "5e12429fb8642348dd6fde4081f7609ab55c04fae7ac8d040cfa909155d7c8fa",
28 "tests/room-routing.test.ts": "85f6ba28224e59229ddfb8961008fa83edb8e673308292e24f674f5053c45db0",
29 "tools/cli/rooms.mjs": "2412b637e0f72b891c840a55f268d61ce0679512ad40bdaad555f4bef24927a4",
30 "tools/cli/test-control.mjs": "aef1e722d2b4b740207a65f88c15f610729d1f334c08f08c5baf3cf18ffeff1c",
31 "tools/cli/test-persistent.mjs": "09456d4a91946f8058c86e3f3e387470ae43ecafa86ad6f88b31ae05fcdd0afb"
32 },
33 "browserEngine": "cf5ec3e0bddc369bc318dd7e81f0c1a4ab739abcd861b02da40f44e981a38629",
34 "newDatabaseMigration": false,
35 "databaseSchema": 5,
36 "routingABI": 1,
37 "typeAndImports": {
38 "command": "npm run check",
39 "result": "passed; 127 package source files"
40 },
41 "headless": {
42 "command": "npm test",
43 "tests": 682,
44 "pass": 632,
45 "fail": 0,
46 "skipped": 50,
47 "log": "room-routing-headless.tap"
48 },
49 "control": {
50 "command": "npm run test:control",
51 "tests": 53,
52 "pass": 53,
53 "fail": 0,
54 "skipped": 0,
55 "log": "room-routing-control.tap"
56 },
57 "regionalBrowser": {
58 "command": "npm run test:browser:rooms",
59 "statistics": {
60 "startTime": "2026-10-25T16:05:21.539Z",
61 "duration": 62939.764,
62 "expected": 1,
63 "skipped": 0,
64 "unexpected": 0,
65 "flaky": 0
66 },
67 "scenarios": [
68 {
69 "title": "a polished doorway places friends together, opens a second room and recovers routed travelers",
70 "durationMs": 61310,
71 "attachments": [
72 {
73 "name": "regional-journey.json",
74 "data": {
75 "roomA": "route:test-west:hearth:1",
76 "roomB": "route:test-west:hearth:2",
77 "players": 3,
78 "capacity": 2,
79 "sharedRoom": true,
80 "isolatedInventory": true,
81 "isolatedStall": true,
82 "routerRestart": true,
83 "keptPages": 2,
84 "returnCredential": true,
85 "addedRoundTripLatencyMs": 150,
86 "errors": []
87 }
88 }
89 ]
90 }
91 ]
92 },
93 "cooperativeLifecycle": {
94 "command": "npm run test:browser:lifecycle:cooperative",
95 "statistics": {
96 "startTime": "2026-10-25T15:57:50.389Z",
97 "duration": 36112.343,
98 "expected": 1,
99 "skipped": 0,
100 "unexpected": 0,
101 "flaky": 0
102 },
103 "scenarios": [
104 {
105 "title": "two travelers recover from graceful restart, lease failure and a stopped runtime without reloading",
106 "durationMs": 34313,
107 "attachments": [
108 {
109 "name": "lifecycle-journey.json",
110 "data": {
111 "profile": "cooperative",
112 "reconnectMs": 1714.058445999999,
113 "stallExitMs": 5922.159797999997,
114 "actor": "20bf66cf-a053-49ae-9b93-e95bf3af6000",
115 "companion": "eb26bb94-ee22-401e-b0f6-40cf108e4146",
116 "keptPage": true,
117 "keptPages": 2,
118 "gracefulExit": 0,
119 "failedExit": 1,
120 "stalledExit": 1,
121 "addedRoundTripLatencyMs": 150,
122 "errors": [],
123 "history": [
124 {
125 "time": 1058.8999999761581,
126 "status": "connecting",
127 "draining": false,
128 "epoch": "0"
129 },
130 {
131 "time": 1234.1000000238419,
132 "status": "connected",
133 "draining": false,
134 "epoch": "1"
135 },
136 {
137 "time": 7454.800000011921,
138 "status": "reconnecting",
139 "draining": true,
140 "epoch": "1"
141 },
142 {
143 "time": 9546.600000023842,
144 "status": "connected",
145 "draining": false,
146 "epoch": "2"
147 },
148 {
149 "time": 14375.399999976158,
150 "status": "reconnecting",
151 "draining": false,
152 "epoch": "2"
153 },
154 {
155 "time": 16188.800000011921,
156 "status": "connected",
157 "draining": false,
158 "epoch": "3"
159 },
160 {
161 "time": 21988.19999998808,
162 "status": "reconnecting",
163 "draining": false,
164 "epoch": "3"
165 },
166 {
167 "time": 23850.30000001192,
168 "status": "connected",
169 "draining": false,
170 "epoch": "4"
171 }
172 ]
173 }
174 }
175 ]
176 }
177 ]
178 },
179 "trustedExploration": {
180 "command": "npm run test:browser:trusted",
181 "statistics": {
182 "startTime": "2026-10-25T15:58:40.810Z",
183 "duration": 101207.193,
184 "expected": 1,
185 "skipped": 0,
186 "unexpected": 0,
187 "flaky": 0
188 },
189 "scenarios": [
190 {
191 "title": "persistent players share objects and restore committed travel without local position saves",
192 "durationMs": 99539,
193 "attachments": [
194 {
195 "name": "persistent-journey.json",
196 "data": {
197 "transport": {
198 "sent": 54,
199 "received": 102,
200 "minSendDelayMs": 75,
201 "minReceiveDelayMs": 75,
202 "droppedCaptures": 0,
203 "closes": []
204 },
205 "privateKeepsakes": 1,
206 "privateTrafficVerified": true,
207 "gardenTravelMs": 5133.51786,
208 "addedRoundTripLatencyMs": 150,
209 "actor": "e1eb47e9-e310-41a5-86c7-e6c0d7ec57b6",
210 "place": "sanctuary",
211 "revision": "20",
212 "inventory": [
213 "keeper-lantern"
214 ],
215 "otherTraveler": "18beefc0-fe1a-47ca-9c52-7f13c0fab3e6",
216 "errors": []
217 }
218 }
219 ]
220 }
221 ]
222 },
223 "compose": {
224 "command": "docker compose -f compose.rooms.yaml config --quiet",
225 "result": "passed with placeholder required environment values; no container execution"
226 },
227 "environment": {
228 "node": "22.23.4",
229 "playwright": "1.56.1",
230 "browser": "Chromium 141.0.7390.37 headless shell; SwiftShader Vulkan",
231 "host": "Linux 7.2.8-9-omarchy x86_64",
232 "database": "isolated local PostgreSQL with fsync and synchronous_commit enabled",
233 "execution": "native production gateway and retained engine; not Docker"
234 },
235 "contracts": [
236 "A PostgreSQL advisory connection owns each region; every child retains its own fenced lease and epoch.",
237 "Concurrent arrivals count live actor identities, tunnels and unexpired reservations without exceeding the configured player cap.",
238 "Rejected capacity requests do not consume unused persistent room slots. Occupied rooms are never evicted; idle parking preserves durable state.",
239 "Origin/passphrase and exact-region admission are checked. Ticket signatures cover every audience field, expire after 30 seconds, invalidate on coordinator restart and can be consumed once.",
240 "The private runtime binds its hello credential to the ticket actor. Cross-room credentials, replay and another actor hello fail.",
241 "A failed child restarts independently; a temporarily unresponsive room is skipped for new arrivals when another compatible room is healthy.",
242 "Existing rooms retain their exact engine after a new candidate is deployed; compatible new arrivals can enter the new release.",
243 "Three real browser travelers exercise two independent rooms with 150 ms added RTT; one stalled child does not stop the other room.",
244 "A gateway restart restores affected travelers on the same pages with their original identity and committed lantern; Continue resumes the saved room."
245 ],
246 "developmentFindings": [
247 "Initial routing browser failure exposed a wrong document-factory contract: raw worlds were passed to an envelope reader. The gateway now constructs documents through each retained engine\u2019s exported factory and routing ABI.",
248 "Final review fixed persistent slot allocation before process-capacity admission; the native test now requires zero new room rows after rejection.",
249 "Concurrent request assertions count per-room occupancy instead of assuming network dispatch order.",
250 "The first full headless attempt was run inside the restricted sandbox; child-process fixtures failed and socket fixtures did not finish. The owned test tree was explicitly terminated. The full rerun with required native/socket access passed.",
251 "The final regional browser run followed routing-only capacity, handshake and card-width fixes. The shared client/runtime source matches the passing standalone lifecycle and exploration runs."
252 ],
253 "visualReview": {
254 "doorway": "room-routing-doorway.png; inspected, labels and layout readable",
255 "recovery": "room-routing-recovered.png; diagnostic only: coincident fixture arrivals obscure the camera with another traveler",
256 "pending": "User-rejected temporary characters and shared arrival/camera composition remain required final polish work."
257 },
258 "limits": [
259 "No numbered milestone closed; 69% is an approximate full-program scope/effort estimate, not a passed-test percentage.",
260 "One coordinator per region/address, bounded fixed instance slots. No automatic geography, cross-region failover, live cross-host transfer or account recovery.",
261 "Client assets and world documents remain public URLs. Passphrases protect participation; private player data uses recipient-filtered replication.",
262 "Older standalone engines remain usable there, but regional admission requires an explicit upgrade to routing ABI 1. Schema 5 is unchanged.",
263 "The pool limits are admission bounds, not measured production capacity. Full operational health telemetry, WAN/load/device qualification, remote CI and production recovery objectives remain open.",
264 "Docker/Coolify execution and automatic container restart timing remain unverified. Compose declares database and retained-engine named volumes.",
265 "Dynamic physics/script state, final character models and arrival/camera polish remain incomplete."
266 ]
267}
268