REPOSITORY SOURCE

host-watchdog-acceptance.json

docs/evidence/host-watchdog-acceptance.json

1{
2  "recordedAt": "2026-10-25T15:36:57.355660+00:00",
3  "baseCommit": "8cde5a22b7f089358030b86f6b2258afa6a09733",
4  "scope": "External persistent-runtime liveness supervision and bounded-prediction client reconnect. Full engine milestones remain open.",
5  "fullPlanEstimatePercent": 68,
6  "sourceSha256": {
7    "services/persistent/watchdog.ts": "c67461df82bb6818809392b875191413e1658e024ce227740886492d0330fe57",
8    "services/persistent/bootstrap.ts": "c5413fe0a54c75857e8f09537ee7757c1d5f6949ebbc76214cfaab076765329e",
9    "services/persistent/lifecycle.ts": "d4692cd084f80fa08fa176e44561bfdcb0382119e9291559ae21520ad60b80e8",
10    "packages/net/motion.ts": "b0207968de877cf1ae4a790712f77dd77573afdd9d7cc13a5fb563b6bfd8634f",
11    "packages/net/persistent-client.ts": "13bb92808506998634325d19c228e7bdecb85bc4fe6cf8f060c69146aa043345",
12    "apps/player/simulation.worker.ts": "90b0b4402c01aa436883f7b9cf2b6acb36e0876ace53dbca1e07192537b1eae7",
13    "tests/host-watchdog.test.ts": "b6e08239007cc523e9567c8399b272be1a20e300f2207be0a8d4dc139c36a373",
14    "tests/fixtures/watchdog-runtime.mjs": "e2a5c8df5d4faf4b7e51f0b38b73f697b6c6098654ae8d29fe5806bd51d6ac50",
15    "tests/fixtures/watchdog-parent.ts": "463c7be2c1e236209ebb88634581dc990d69197aa350f01f56a64abf3af5629a",
16    "tests/trusted-room.test.ts": "29dde76319b7136f5b91c93f81dc99155f8f1903f57fe1ab34f97deac4965645",
17    "tests/fixtures/persistent-upgrade-host.ts": "e629111cd10d89476e54c5b964048f6fc903127e72c136fb12a03f235a59f687",
18    "tests/browser/persistent-lifecycle.spec.ts": "547dcf75401b1ffb0ba4912fa0d91bae7a97a890afe9e38f49240ac144acb5ef",
19    "tests/browser/trusted-latency.ts": "34cd9b6f52745788fdd284f83be5b7a4c20ced517525595ff9bb1578ed54375d",
20    "playwright.persistent-lifecycle.config.ts": "4e76f806b22737edba480075c2865172af72f80aa339a0b7251c6d25cdc62927",
21    "Dockerfile.persistent": "fbd317729b749683196382b65896e3c01ff57c6af9e1bca67700b1a256804bd1",
22    "compose.persistent.yaml": "affc8220923d0746b9d4ab163f9a02c1c134b22f01192a9221ca64f25729f1d1"
23  },
24  "newDatabaseMigration": false,
25  "databaseSchema": 5,
26  "typeAndImports": "passed; 127 package source files",
27  "headless": {
28    "tests": 673,
29    "pass": 630,
30    "fail": 0,
31    "skipped": 43
32  },
33  "control": {
34    "tests": 44,
35    "pass": 44,
36    "fail": 0,
37    "skipped": 0
38  },
39  "nativeWatchdog": {
40    "tests": 10,
41    "pass": 10,
42    "fail": 0,
43    "skipped": 0
44  },
45  "trustedLifecycle": [
46    {
47      "title": "two travelers recover from graceful restart, lease failure and a stopped runtime without reloading",
48      "durationMs": 42854,
49      "attachments": [
50        {
51          "name": "lifecycle-journey.json",
52          "data": {
53            "profile": "trusted",
54            "reconnectMs": 3310.054438000001,
55            "stallExitMs": 6942.055272999998,
56            "actor": "b5972ca3-7e30-41d6-bb20-9b5329a8221a",
57            "companion": "59f658dd-2066-4173-867a-7bc22d529b97",
58            "keptPage": true,
59            "keptPages": 2,
60            "gracefulExit": 0,
61            "failedExit": 1,
62            "stalledExit": 1,
63            "addedRoundTripLatencyMs": 150,
64            "errors": [],
65            "history": [
66              {
67                "time": 1071.9000000357628,
68                "status": "connecting",
69                "draining": false,
70                "epoch": "0"
71              },
72              {
73                "time": 1509.300000011921,
74                "status": "connecting",
75                "draining": false,
76                "epoch": "0"
77              },
78              {
79                "time": 1558.7000000476837,
80                "status": "connected",
81                "draining": false,
82                "epoch": "1"
83              },
84              {
85                "time": 8218.900000035763,
86                "status": "reconnecting",
87                "draining": true,
88                "epoch": "1"
89              },
90              {
91                "time": 12452.900000035763,
92                "status": "connected",
93                "draining": false,
94                "epoch": "2"
95              },
96              {
97                "time": 16795.200000047684,
98                "status": "reconnecting",
99                "draining": false,
100                "epoch": "2"
101              },
102              {
103                "time": 19195,
104                "status": "connected",
105                "draining": false,
106                "epoch": "3"
107              },
108              {
109                "time": 21880.5,
110                "status": "reconnecting",
111                "draining": false,
112                "epoch": "3"
113              },
114              {
115                "time": 29258.200000047684,
116                "status": "connected",
117                "draining": false,
118                "epoch": "4"
119              },
120              {
121                "time": 30034.5,
122                "status": "reconnecting",
123                "draining": false,
124                "epoch": "4"
125              },
126              {
127                "time": 31478.80000001192,
128                "status": "connected",
129                "draining": false,
130                "epoch": "4"
131              }
132            ]
133          }
134        }
135      ]
136    }
137  ],
138  "cooperativeLifecycle": [
139    {
140      "title": "two travelers recover from graceful restart, lease failure and a stopped runtime without reloading",
141      "durationMs": 38591,
142      "attachments": [
143        {
144          "name": "lifecycle-journey.json",
145          "data": {
146            "profile": "cooperative",
147            "reconnectMs": 2229.7697040000003,
148            "stallExitMs": 5907.993060000001,
149            "actor": "a7999894-e9d9-43ae-8b00-356d43e99e13",
150            "companion": "1d8f1e56-be9b-4149-8c3e-ab6721dba9e7",
151            "keptPage": true,
152            "keptPages": 2,
153            "gracefulExit": 0,
154            "failedExit": 1,
155            "stalledExit": 1,
156            "addedRoundTripLatencyMs": 150,
157            "errors": [],
158            "history": [
159              {
160                "time": 1116.2000000476837,
161                "status": "connecting",
162                "draining": false,
163                "epoch": "0"
164              },
165              {
166                "time": 1291,
167                "status": "connected",
168                "draining": false,
169                "epoch": "1"
170              },
171              {
172                "time": 10095.700000047684,
173                "status": "reconnecting",
174                "draining": true,
175                "epoch": "1"
176              },
177              {
178                "time": 12703.100000023842,
179                "status": "connected",
180                "draining": false,
181                "epoch": "2"
182              },
183              {
184                "time": 16911.80000001192,
185                "status": "reconnecting",
186                "draining": false,
187                "epoch": "2"
188              },
189              {
190                "time": 18739.700000047684,
191                "status": "connected",
192                "draining": false,
193                "epoch": "3"
194              },
195              {
196                "time": 24505.400000035763,
197                "status": "reconnecting",
198                "draining": false,
199                "epoch": "3"
200              },
201              {
202                "time": 27221.200000047684,
203                "status": "connected",
204                "draining": false,
205                "epoch": "4"
206              }
207            ]
208          }
209        }
210      ]
211    }
212  ],
213  "trustedExploration": [
214    {
215      "title": "persistent players share objects and restore committed travel without local position saves",
216      "durationMs": 100713,
217      "attachments": [
218        {
219          "name": "persistent-garden-report.json",
220          "data": {
221            "engine": "0.1.0",
222            "world": "darkwind",
223            "release": "lantern-house.storage.1",
224            "playtest": null,
225            "pinnedEngine": null,
226            "development": null,
227            "time": "2026-10-25T15:33:53.143Z",
228            "browser": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/141.0.7390.37 Safari/537.36",
229            "webgpu": true,
230            "quality": "high",
231            "startupStages": {
232              "started": 181.5,
233              "admission": 556.3000000119209,
234              "graphics": 4353.600000023842,
235              "simulation": 2075.5,
236              "presentation": 4356.800000011921,
237              "room": 2717.600000023842,
238              "ready": 5021.300000011921,
239              "failed": null
240            },
241            "graphicsLifecycle": [
242              {
243                "stage": "probe",
244                "generation": 0,
245                "at": 556
246              },
247              {
248                "stage": "device",
249                "generation": 1,
250                "at": 1690.699999988079
251              },
252              {
253                "stage": "adapter-request",
254                "generation": 1,
255                "at": 1690.8999999761581
256              },
257              {
258                "stage": "device-request",
259                "generation": 1,
260                "at": 1693
261              },
262              {
263                "stage": "resources",
264                "generation": 1,
265                "at": 1695.3999999761581
266              },
267              {
268                "stage": "shader-modules",
269                "generation": 1,
270                "at": 1704.5
271              },
272              {
273                "stage": "shader-validation",
274                "generation": 1,
275                "at": 1704.5999999642372
276              },
277              {
278                "stage": "shader-pipelines",
279                "generation": 1,
280                "at": 1716.5
281              },
282              {
283                "stage": "shader-identity",
284                "generation": 1,
285                "at": 2371.099999964237
286              },
287              {
288                "stage": "initial-upload",
289                "generation": 1,
290                "at": 2371.699999988079
291              },
292              {
293                "stage": "catalog",
294                "generation": 1,
295                "at": 2376.399999976158
296              },
297              {
298                "stage": "model-prepare",
299                "generation": 1,
300                "at": 2376.7999999523163
301              },
302              {
303                "stage": "model-allocate",
304                "generation": 1,
305                "at": 3310.199999988079
306              },
307              {
308                "stage": "model-upload",
309                "generation": 1,
310                "at": 3320.7999999523163
311              },
312              {
313                "stage": "model-install",
314                "generation": 1,
315                "at": 3591.099999964237
316              },
317              {
318                "stage": "actors",
319                "generation": 1,
320                "at": 3591.599999964237
321              },
322              {
323                "stage": "ready",
324                "generation": 1,
325                "at": 4352.799999952316
326              }
327            ],
328            "renderPlacement": "worker",
329            "viewport": [
330              960,
331              640,
332              1
333            ],
334            "place": "garden",
335            "tick": "56",
336            "position": [
337              -1.1043014637834858e-05,
338              0.7850872278213501,
339              5.9999847412109375
340            ],
341            "frameInterval": {
342              "p50": 216.69999999999982,
343              "p95": 300
344            },
345            "tickMs": 2.099999964237213,
346            "renderObservedAtMs": 7629.600000023842,
347            "render": {
348              "instances": 578,
349              "triangles": 91980,
350              "visibleInstances": 367,
351              "shadowInstances": 578,
352              "visibleTriangles": 61044,
353              "shadowTriangles": 91980,
354              "drawCalls": 9,
355              "buffers": 53,
356              "textures": 4,
357              "targetBytes": 24150016,
358              "targetGeneration": 1,
359              "width": 960,
360              "height": 640,
361              "frameMs": 4.5,
362              "submittedFrames": 7,
363              "completedFrames": 7,
364              "failedFrames": 0,
365              "cancelledFrames": 0,
366              "pendingFrames": 0,
367              "skippedFrames": 182,
368              "completionWaitMs": 479.4000000357628,
369              "maxCompletionWaitMs": 532.3000000119209,
370              "lastSubmittedAtMs": 6998.099999964237,
371              "lastCompletedAtMs": 7477.5
372            },
373            "actors": {
374              "states": {},
375              "rigged": 0,
376              "walking": 0,
377              "airborne": 0,
378              "stalled": 0,
379              "samples": 0,
380              "matrices": 0
381            },
382            "audio": {
383              "context": "inactive",
384              "enabled": false,
385              "paused": false,
386              "levels": {
387                "master": 0.65,
388                "music": 0.7,
389                "ambience": 0.6,
390                "dialogue": 1,
391                "effects": 0.7
392              }
393            },
394            "controller": {
395              "connected": false,
396              "active": false
397            },
398            "presentationTransport": {
399              "route": "direct",
400              "received": 1,
401              "returned": 1,
402              "capacity": 4194304
403            },
404            "renderGraph": {
405              "plan": {
406                "textures": [
407                  {
408                    "name": "depth",
409                    "format": "depth24plus",
410                    "extent": {
411                      "kind": "viewport"
412                    },
413                    "external": false,
414                    "sampled": false,
415                    "attachment": true,
416                    "firstUse": 1,
417                    "lastUse": 1,
418                    "writer": "scene"
419                  },
420                  {
421                    "name": "hdr",
422                    "format": "rgba16float",
423                    "extent": {
424                      "kind": "viewport"
425                    },
426                    "external": false,
427                    "sampled": true,
428                    "attachment": true,
429                    "firstUse": 1,
430                    "lastUse": 2,
431                    "writer": "scene"
432                  },
433                  {
434                    "name": "output",
435                    "format": "bgra8unorm",
436                    "extent": {
437                      "kind": "viewport"
438                    },
439                    "external": true,
440                    "sampled": false,
441                    "attachment": true,
442                    "firstUse": 2,
443                    "lastUse": 2,
444                    "writer": "post"
445                  },
446                  {
447                    "name": "shadow",
448                    "format": "depth32float",
449                    "extent": {
450                      "kind": "fixed",
451                      "width": 2048,
452                      "height": 2048
453                    },
454                    "external": false,
455                    "sampled": true,
456                    "attachment": true,
457                    "firstUse": 0,
458                    "lastUse": 1,
459                    "writer": "shadow"
460                  }
461                ],
462                "passes": [
463                  {
464                    "name": "shadow",
465                    "after": [],
466                    "reads": [],
467                    "colors": [],
468                    "depth": {
469                      "resource": "shadow",
470                      "load": "clear",
471                      "store": "store"
472                    }
473                  },
474                  {
475                    "name": "scene",
476                    "after": [],
477                    "reads": [
478                      "shadow"
479                    ],
480                    "colors": [
481                      {
482                        "resource": "hdr",
483                        "load": "clear",
484                        "store": "store"
485                      }
486                    ],
487                    "depth": {
488                      "resource": "depth",
489                      "load": "clear",
490                      "store": "discard"
491                    }
492                  },
493                  {
494                    "name": "post",
495                    "after": [],
496                    "reads": [
497                      "hdr"
498                    ],
499                    "colors": [
500                      {
501                        "resource": "output",
502                        "load": "clear",
503                        "store": "store"
504                      }
505                    ]
506                  }
507                ]
508              },
509              "census": {
510                "generation": 1,
511                "textures": 3,
512                "estimatedBytes": 24150016,
513                "width": 960,
514                "height": 640
515              }
516            },
517            "shaders": {
518              "requestedRevision": "1",
519              "activeRevision": "1",
520              "hash": "039684b97282110739cbee452249807ac2ff2e2cbcefe32a87cf2da1454a8297",
521              "compilingRevision": null,
522              "pendingRevision": null,
523              "retainedSourceBytes": 0,
524              "disposed": false,
525              "last": {
526                "revision": "1",
527                "status": "applied",
528                "diagnostics": []
529              }
530            },
531            "graphicsRecovery": {
532              "status": "idle",
533              "attempts": 0,
534              "limit": 2,
535              "timeoutMs": 20000,
536              "inFlight": false
537            },
538            "graphicsIncidents": [],
539            "simulationWatchdog": {
540              "status": "healthy",
541              "probes": 5,
542              "acknowledged": 5,
543              "graceResets": 0
544            },
545            "simulationRecovery": {
546              "status": "idle",
547              "attempts": 0,
548              "limit": 2,
549              "timeoutMs": 45000,
550              "inFlight": false
551            },
552            "simulationCheckpoint": {
553              "available": true,
554              "tick": "23",
555              "received": 6688.199999988079,
556              "captureMs": 157.20000004768372,
557              "pending": false,
558              "issue": ""
559            },
560            "canonicalEntities": 1500,
561            "modelResidency": {
562              "hash": "c27f3b6d1093484b36e2263b8f7deffdc9fb50d8583f122cb4dba0d9fb77c6f9",
563              "buffers": 47,
564              "bytes": 1981492,
565              "textures": 1,
566              "update": {
567                "status": "ready",
568                "attempts": 1,
569                "limit": 1,
570                "timeoutMs": 20000,
571                "inFlight": false
572              }
573            },
574            "save": "postgresql",
575            "room": {
576              "status": "connected",
577              "players": 2,
578              "peerRows": 1,
579              "interest": {
580                "place": "garden",
581                "sequence": "32",
582                "total": 2
583              },
584              "epoch": "1",
585              "revision": "17",
586              "durableRelease": "0aba01a4d84ad6f176cc7f3f801ef03aef7f3a566452a3c891309c8197fafcd0",
587              "playerRevision": "11"
588            },
589            "knownLimits": [
590              "Trusted static-world preview",
591              "Single room process",
592              "Original traveler rig; environment uses procedural geometry",
593              "Desktop WebGPU only"
594            ]
595          }
596        },
597        {
598          "name": "persistent-journey.json",
599          "data": {
600            "transport": {
601              "sent": 63,
602              "received": 134,
603              "minSendDelayMs": 75,
604              "minReceiveDelayMs": 75,
605              "droppedCaptures": 0,
606              "closes": []
607            },
608            "privateKeepsakes": 1,
609            "privateTrafficVerified": true,
610            "gardenTravelMs": 3976.278308000001,
611            "addedRoundTripLatencyMs": 150,
612            "actor": "ae493474-eb90-444f-914b-1e55af264043",
613            "place": "sanctuary",
614            "revision": "20",
615            "inventory": [
616              "keeper-lantern"
617            ],
618            "otherTraveler": "fc329c27-b6e1-48af-a345-9291dbde09cd",
619            "errors": []
620          }
621        }
622      ]
623    }
624  ],
625  "environment": {
626    "node": "22.23.4",
627    "browser": "Chromium 141.0.7390.37 headless shell; SwiftShader Vulkan",
628    "database": "isolated local PostgreSQL; fsync and synchronous_commit enabled",
629    "execution": "native packaged production bootstrap/retained engine, not Docker"
630  },
631  "contracts": [
632    "One owned child, one matching unpredictable IPC challenge, 1s observation interval and 5s reply window.",
633    "Node preloads the main-loop responder without modifying the retained entry; a legacy entry with no heartbeat API remains live and unchanged.",
634    "Startup/runtime permanent blocks and stale repeated replies are killed; sibling processes remain live.",
635    "Normal exit codes propagate; a blocked stop handler is killed by the independent 18s production deadline (short injected deadlines in native fixture).",
636    "Observer suspension causes a new challenge and full reply window; a still-blocked child is then killed.",
637    "Both real browser travelers recover on newer ownership epochs after SIGSTOP of the exact retained child, keeping page identity and committed inventory.",
638    "Prediction saturation pauses input and reconnects; old socket callbacks are fenced even if its close handshake stalls.",
639    "Existing exact durable retries, graceful drain, reward privacy, backup and upgrade behavior remain covered by control and exploration regressions."
640  ],
641  "developmentFindings": [
642    "Initial browser attempts killed the stalled server but exposed a pre-existing fatal prediction-overflow path: the 60-input cap threw, worker recovery fetched while the host was unavailable, and the page remained on its old epoch. The cap remains enforced; client saturation now requests a reconnect and the worker skips unaccepted input steps. Both profiles then passed.",
643    "The browser assertion now waits explicitly for each traveler to observe a newer ownership epoch, so an old connected status cannot count as recovery.",
644    "The initial type check found an untyped test inventory callback; corrected before final verification."
645  ],
646  "limits": [
647    "No milestone closed; approximate full-program estimate remains 68%.",
648    "Bootstrap supervision works for old retained entries, but updated prediction recovery is packaged client code and requires a new room or explicit engine upgrade.",
649    "The observer itself, asynchronous logical deadlocks, memory limits and malicious creator code are not supervised by this mechanism.",
650    "A responsive orphan exits on IPC disconnect; a blocked orphan needs the OS/container supervisor.",
651    "Docker/Coolify execution, automatic deployment restart timing, remote CI, WAN/load/device qualification and production recovery objectives are not proven here.",
652    "SIGKILL cannot promise a final movement save; the existing four-second autosave and fenced/idempotent ledger define abrupt recovery.",
653    "Room routing, live cross-host transfer, general dynamic state and final character art remain open."
654  ]
655}
656