startup-failure-capture-ci-multiplayer.json
docs/evidence/startup-failure-capture-ci-multiplayer.json
1{
2 "source": "ada53d27bfdb94f8155a81d22cea11a23cacaaf6",
3 "run": 40160551106,
4 "url": "https://github.com/jasona/darkwind-web/actions/runs/40160551106",
5 "job": 121071001872,
6 "stats": {
7 "startTime": "2026-10-25T04:05:23.558Z",
8 "duration": 537889.386,
9 "expected": 7,
10 "skipped": 0,
11 "unexpected": 1,
12 "flaky": 0
13 },
14 "tests": [
15 {
16 "title": "startup failure diagnostics identify the held second player instead of its healthy observer",
17 "status": "passed",
18 "durationMs": 41885,
19 "errors": []
20 },
21 {
22 "title": "two real browsers share doors and chat, then the guest takes over when the host leaves",
23 "status": "passed",
24 "durationMs": 70678,
25 "errors": []
26 },
27 {
28 "title": "simultaneous real-browser pickups grant one lantern, including across host handoff",
29 "status": "passed",
30 "durationMs": 77525,
31 "errors": []
32 },
33 {
34 "title": "travelers see each other move in the rendered world",
35 "status": "passed",
36 "durationMs": 58561,
37 "errors": []
38 },
39 {
40 "title": "rigged travelers walk, settle when pose delivery stalls, and resume without leaking actors",
41 "status": "passed",
42 "durationMs": 95546,
43 "errors": []
44 },
45 {
46 "title": "travelers keep walking with slow GPU completion and settle when real movement stops",
47 "status": "passed",
48 "durationMs": 70533,
49 "errors": []
50 },
51 {
52 "title": "graphics recovery keeps the shared room and receives door changes during restoration",
53 "status": "failed",
54 "durationMs": 74001,
55 "errors": [
56 "Error: expect(locator).toHaveAttribute(expected) failed\n\nLocator: locator('canvas')\nExpected: \"ready\"\nReceived: \"failed\"\nTimeout: 30000ms\n\nCall log:\n - Expect \"toHaveAttribute\" with timeout 30000ms\n - waiting for locator('canvas')\n 19 \u00d7 locator resolved to <canvas id=\"world\" width=\"960\" height=\"640\" tabindex=\"-1\" data-simulation-paused=\"true\" data-canonical-entities=\"1482\" data-presentation-source=\"ecs\" data-render-placement=\"worker\" data-graphics-recovery=\"recovering\" aria-label=\"Darkwind 3D world. Use WASD to walk, mouse or arrow keys to look, and E to interact.\"></canvas>\n - unexpected value \"recovering\"\n 14 \u00d7 locator resolved to <canvas id=\"world\" width=\"960\" height=\"640\" tabindex=\"-1\" data-simulation-paused=\"true\" data-canonical-entities=\"1482\" data-presentation-source=\"ecs\" data-render-placement=\"worker\" data-graphics-recovery=\"failed\" aria-label=\"Darkwind 3D world. Use WASD to walk, mouse or arrow keys to look, and E to interact.\"></canvas>\n - unexpected value \"failed\"\n\n\n 132 | await loseGraphics(a,true);await expect(a.locator('#panel-title')).toHaveText('Rekindling the light.');await expect(a.locator('canvas')).toHaveAttribute('data-simulation-paused','true');\n 133 | await expect(b.locator('#interaction-label')).toHaveText('Open the garden door');await b.keyboard.press('KeyE');await expect.poll(async()=>(await saved(a)).doors['front-door']).toBe(true);await expect(b.locator('#save-status')).toContainText('2 travelers');\n> 134 | await releaseGraphics(a);await expect(a.locator('canvas')).toHaveAttribute('data-graphics-recovery','ready',{timeout:30000});const restored=await graphicsState(a);expect(restored.workers).toBe(1);expect(restored.room).toEqual(initial);expect(admissions).toBe(1);\n | ^\n 135 | await a.locator('#resume').click();await a.keyboard.press('F2');await expect(a.locator('#metrics')).toContainText('Rigged travelers1');await a.keyboard.press('F2');await expect(a.locator('#interaction-label')).toHaveText('Close the garden door');await a.keyboard.press('KeyE');await expect.poll(async()=>(await saved(b)).doors['front-door']).toBe(false);await attachPlaytestReport(a,'shared-recovery-before-capture.json');await a.screenshot({path:'test-results/graphics-recovery-shared.png'});await attachPlaytestReport(a,'shared-recovery-after-capture.json');\n 136 | await attachRuntimeProbe(a,'recovery-observed-events.json');await attachRuntimeProbe(b,'recovery-peer-events.json');\n 137 | }catch(error){\n at /home/runner/work/darkwind-web/darkwind-web/tests/browser/multiplayer.spec.ts:134:62"
57 ]
58 },
59 {
60 "title": "direct scenes advance during withheld UI receipts and a blocked page task",
61 "status": "passed",
62 "durationMs": 42887,
63 "errors": []
64 }
65 ],
66 "reports": {
67 "startup-failed-page.json": {
68 "engine": "0.1.0",
69 "world": "darkwind",
70 "release": "lantern-house.1",
71 "time": "2026-10-25T04:06:01.825Z",
72 "browser": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/141.0.7390.37 Safari/537.36",
73 "webgpu": true,
74 "quality": "high",
75 "startupStages": {
76 "started": 286.79999999998836,
77 "admission": 695.7999999999884,
78 "graphics": null,
79 "simulation": 2871.2999999999884,
80 "presentation": null,
81 "room": 2950.2999999999884,
82 "ready": null,
83 "failed": 20313.400000000023
84 },
85 "graphicsLifecycle": [
86 {
87 "stage": "probe",
88 "generation": 0,
89 "at": 290.9000000000233
90 },
91 {
92 "stage": "device",
93 "generation": 1,
94 "at": 10059.700048828148
95 }
96 ],
97 "viewport": [
98 960,
99 640,
100 1
101 ],
102 "place": "lantern-house",
103 "tick": "100",
104 "position": [
105 1.7000000476837158,
106 0.8500000238418579,
107 1.399999976158142
108 ],
109 "frameInterval": {
110 "p50": 0,
111 "p95": 0
112 },
113 "tickMs": 0,
114 "renderObservedAtMs": 30960.20000000001,
115 "presentationTransport": {
116 "route": "main",
117 "received": 0,
118 "returned": 0,
119 "capacity": 0
120 },
121 "graphicsRecovery": {
122 "status": "idle",
123 "attempts": 0,
124 "limit": 2,
125 "timeoutMs": 20000,
126 "inFlight": false
127 },
128 "graphicsIncidents": [],
129 "canonicalEntities": 1482,
130 "save": "local",
131 "room": {
132 "status": "connected",
133 "players": 2,
134 "epoch": "1",
135 "revision": "0"
136 },
137 "knownLimits": [
138 "Trusted cooperative beta",
139 "Single relay process",
140 "Original traveler rig; environment uses procedural geometry",
141 "Desktop WebGPU only"
142 ]
143 },
144 "startup-failed-page-state.json": {
145 "url": "http://localhost:5174/",
146 "error": "The room took too long to start. Check the local relay and retry.",
147 "room": "2 travelers \u00b7 Connected",
148 "placement": null
149 },
150 "recovery-failed-report.json": {
151 "engine": "0.1.0",
152 "world": "darkwind",
153 "release": "lantern-house.1",
154 "time": "2026-10-25T04:13:25.314Z",
155 "browser": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/141.0.7390.37 Safari/537.36",
156 "webgpu": true,
157 "quality": "high",
158 "startupStages": {
159 "started": 88.59999999997672,
160 "admission": 197.19999999995343,
161 "graphics": 1952.2999999999302,
162 "simulation": 1056.7999999999302,
163 "presentation": 1954.0999999999767,
164 "room": 1084.3999999999069,
165 "ready": 1954.0999999999767,
166 "failed": null
167 },
168 "graphicsLifecycle": [
169 {
170 "stage": "probe",
171 "generation": 0,
172 "at": 89.69999999995343
173 },
174 {
175 "stage": "device",
176 "generation": 1,
177 "at": 728.1001464844448
178 },
179 {
180 "stage": "catalog",
181 "generation": 1,
182 "at": 1102.900146484375
183 },
184 {
185 "stage": "actors",
186 "generation": 1,
187 "at": 1620.5001464844681
188 },
189 {
190 "stage": "ready",
191 "generation": 1,
192 "at": 1951.7001464844216
193 },
194 {
195 "stage": "device",
196 "generation": 2,
197 "at": 25825.100146484445
198 },
199 {
200 "stage": "catalog",
201 "generation": 2,
202 "at": 42437.400146484375
203 }
204 ],
205 "viewport": [
206 960,
207 640,
208 1
209 ],
210 "place": "lantern-house",
211 "tick": "808",
212 "position": [
213 1.017440581563278e-06,
214 0.7448275685310364,
215 -4.649999618530273
216 ],
217 "frameInterval": {
218 "p50": 2616.5999999999985,
219 "p95": 3000.0000000000005
220 },
221 "tickMs": 0,
222 "renderObservedAtMs": 61949.09999999998,
223 "presentationTransport": {
224 "route": "direct",
225 "received": 145,
226 "returned": 145,
227 "capacity": 4194304
228 },
229 "graphicsRecovery": {
230 "status": "failed",
231 "attempts": 1,
232 "limit": 2,
233 "timeoutMs": 20000,
234 "inFlight": false
235 },
236 "graphicsIncidents": [
237 {
238 "atMs": 25812.699999999953,
239 "kind": "device-lost",
240 "reason": "Device was destroyed.",
241 "render": {
242 "instances": 0,
243 "triangles": 0,
244 "visibleInstances": 0,
245 "shadowInstances": 0,
246 "visibleTriangles": 0,
247 "shadowTriangles": 0,
248 "drawCalls": 0,
249 "buffers": 0,
250 "textures": 0,
251 "targetBytes": 0,
252 "targetGeneration": 1,
253 "width": 960,
254 "height": 640,
255 "frameMs": 20.20000000006985,
256 "submittedFrames": 9,
257 "completedFrames": 8,
258 "failedFrames": 0,
259 "cancelledFrames": 1,
260 "pendingFrames": 0,
261 "skippedFrames": 1325,
262 "completionWaitMs": 3006,
263 "maxCompletionWaitMs": 3045.29999999993,
264 "lastSubmittedAtMs": 23403.500146484468,
265 "lastCompletedAtMs": 23377.8001464844
266 }
267 }
268 ],
269 "canonicalEntities": 1482,
270 "save": "local",
271 "room": {
272 "status": "connected",
273 "players": 2,
274 "epoch": "17",
275 "revision": "7"
276 },
277 "knownLimits": [
278 "Trusted cooperative beta",
279 "Single relay process",
280 "Original traveler rig; environment uses procedural geometry",
281 "Desktop WebGPU only"
282 ]
283 }
284 },
285 "recoveryTraceCommands": [
286 {
287 "operation": "lose-held-device",
288 "startMs": 443500.713,
289 "endMs": 443516.44
290 },
291 {
292 "operation": "release-held-device",
293 "startMs": 450576.463,
294 "endMs": 450581.423
295 }
296 ],
297 "findings": [
298 "Seven of eight multiplayer scenarios pass, including the deliberate startup-failure capture; no ordinary startup failure occurs in this run.",
299 "The only failure is shared graphics recovery reaching its unchanged 20-second deadline.",
300 "Generation 2 enters device creation at 25825.100ms and catalog restoration at 42437.400ms on the page clock; actors/ready are absent. The device stage includes the intentionally held request, not just native GPU work.",
301 "The test requests release approximately 7.076 seconds after requesting held loss. Native adapter, device, pipeline, initial-upload and catalog subphases are not distinguished by this report.",
302 "The failed observer runtime attachment falls back to the page after the render worker terminates; its main placement label is not evidence of a main-thread renderer fallback.",
303 "Earlier all-startup-failure runs remain unresolved; this test-only source does not establish a production fix or hardware equivalence."
304 ],
305 "next": "Measure bounded native initialization/catalog subphases before selecting an optimization; preserve quality and existing deadlines."
306}
307