REPOSITORY SOURCE

host-lifecycle-acceptance.json

docs/evidence/host-lifecycle-acceptance.json

1{
2  "recordedAt": "2026-10-25T15:20:12.547141+00:00",
3  "baseCommit": "e80ee79b02c19f97cdcc8dd453643808ea6434ed",
4  "scope": "Graceful persistent host draining, conservative lease expiry, failure process supervision, and same-page traveler recovery. Full milestones remain open.",
5  "fullPlanEstimatePercent": 68,
6  "sourceSha256": {
7    "apps/player/main.ts": "5542eff9a511594420316dc28685288a6ef095c87f85ef1de67dde7ecebef194",
8    "apps/player/simulation.worker.ts": "af5f7b706f0fb130a02374bc87c3b3b01a8effb40bfccbf5600adc9c9085f602",
9    "package.json": "45a34a98d6b5c7fb94e762b66c57cb0b0f38300500c03d5ca65db8a8b4263bed",
10    "packages/net/persistent-client.ts": "5b26e2436386e87079c13e4b1534ba8ab8cfc922e9e200c05894033b0635db83",
11    "packages/net/protocol.ts": "df83254c48a66299fd40cefdc3397a36d1f3fed73f2a83b8de01dd330524322e",
12    "playwright.persistent-lifecycle.config.ts": "4e76f806b22737edba480075c2865172af72f80aa339a0b7251c6d25cdc62927",
13    "services/persistent/lifecycle.ts": "d4692cd084f80fa08fa176e44561bfdcb0382119e9291559ae21520ad60b80e8",
14    "services/persistent/main.ts": "2568d12f692da2d665a8fa821d3d490fe63110845dd05d49119b7c336370b411",
15    "services/persistent/server.ts": "ad8cc684bbd6116991294ade2131a0d3b72791d5a1483b992de930f0259ddf77",
16    "services/sim-host/motion.ts": "786cbd7af6b3d5619b5687a9e56847d5f2cc2f7b5e04698c2d94ca52b69decdf",
17    "tests/browser/persistent-lifecycle.spec.ts": "d6f2282484fbe2ed036fba556557df53864a4024ab9d7c9c4e2bd711ba2a1351",
18    "tests/browser/trusted-latency.ts": "34cd9b6f52745788fdd284f83be5b7a4c20ced517525595ff9bb1578ed54375d",
19    "tests/fixtures/persistent-room-process.ts": "084de67b5c2afac35e581ad30802e934a9af91b53cf485db61d42d1e883e5510",
20    "tests/fixtures/persistent-upgrade-host.ts": "d2a27dea14acd1dbd2cdd872dbfad68548abbd0eadf5627b288d1bb6ccdbdafd",
21    "tests/host-lifecycle.test.ts": "1ffb1df9a48f82c16966dee610e089e03ef8fedc902f882b821ca45292e2c655",
22    "tools/cli/test-control.mjs": "bd4908424f2806e7744eb60a8579a0f41e71685d41da0fa40e71db56eb6557d1",
23    "tools/cli/test-persistent.mjs": "ad490e790f79cb006b75f1dba6b39857f486a560a737f9b1d46a0abf8e311af5"
24  },
25  "databaseSchema": 5,
26  "newDatabaseMigration": false,
27  "headless": {
28    "tests": 662,
29    "pass": 620,
30    "fail": 0,
31    "skipped": 42
32  },
33  "control": {
34    "tests": 43,
35    "pass": 43,
36    "fail": 0,
37    "skipped": 0
38  },
39  "typeAndImports": "passed, 127 source files",
40  "trustedLifecycle": {
41    "durationMs": 28856.926,
42    "journey": {
43      "profile": "trusted",
44      "reconnectMs": 3265.8211499999998,
45      "actor": "57f43a7d-2fb6-48c2-8c85-c3935ddf5282",
46      "companion": "65feb158-2be7-4d70-a6c9-220149f82952",
47      "keptPage": true,
48      "keptPages": 2,
49      "gracefulExit": 0,
50      "failedExit": 1,
51      "addedRoundTripLatencyMs": 150,
52      "errors": [],
53      "history": [
54        {
55          "time": 1053.699999988079,
56          "status": "connecting",
57          "draining": false,
58          "epoch": "0"
59        },
60        {
61          "time": 1461.3999999761581,
62          "status": "connecting",
63          "draining": false,
64          "epoch": "0"
65        },
66        {
67          "time": 1512.5999999642372,
68          "status": "connected",
69          "draining": false,
70          "epoch": "1"
71        },
72        {
73          "time": 7892.599999964237,
74          "status": "reconnecting",
75          "draining": true,
76          "epoch": "1"
77        },
78        {
79          "time": 11224.199999988079,
80          "status": "connected",
81          "draining": false,
82          "epoch": "2"
83        },
84        {
85          "time": 15734.599999964237,
86          "status": "reconnecting",
87          "draining": false,
88          "epoch": "2"
89        },
90        {
91          "time": 18338.80000001192,
92          "status": "connected",
93          "draining": false,
94          "epoch": "3"
95        },
96        {
97          "time": 19069.599999964237,
98          "status": "reconnecting",
99          "draining": false,
100          "epoch": "3"
101        },
102        {
103          "time": 20640.399999976158,
104          "status": "connected",
105          "draining": false,
106          "epoch": "3"
107        }
108      ]
109    }
110  },
111  "cooperativeLifecycle": {
112    "durationMs": 29078.602,
113    "journey": {
114      "profile": "cooperative",
115      "reconnectMs": 1749.4057030000004,
116      "actor": "cd64aa2c-2330-443f-acaa-359a33697408",
117      "companion": "3b83000e-d1c3-49f9-a863-14981a1695f9",
118      "keptPage": true,
119      "keptPages": 2,
120      "gracefulExit": 0,
121      "failedExit": 1,
122      "addedRoundTripLatencyMs": 150,
123      "errors": [],
124      "history": [
125        {
126          "time": 1076.7000000476837,
127          "status": "connecting",
128          "draining": false,
129          "epoch": "0"
130        },
131        {
132          "time": 1254.300000011921,
133          "status": "connected",
134          "draining": false,
135          "epoch": "1"
136        },
137        {
138          "time": 7813.300000011921,
139          "status": "reconnecting",
140          "draining": true,
141          "epoch": "1"
142        },
143        {
144          "time": 10133.700000047684,
145          "status": "connected",
146          "draining": false,
147          "epoch": "2"
148        },
149        {
150          "time": 18510.700000047684,
151          "status": "connecting",
152          "draining": false,
153          "epoch": "0"
154        },
155        {
156          "time": 18784.80000001192,
157          "status": "connected",
158          "draining": false,
159          "epoch": "3"
160        }
161      ]
162    }
163  },
164  "trustedExplorationRegression": {
165    "durationMs": 97925.05099999999,
166    "journey": {
167      "transport": {
168        "sent": 64,
169        "received": 122,
170        "minSendDelayMs": 75,
171        "minReceiveDelayMs": 75,
172        "droppedCaptures": 0,
173        "closes": []
174      },
175      "privateKeepsakes": 1,
176      "privateTrafficVerified": true,
177      "gardenTravelMs": 4474.439673000001,
178      "addedRoundTripLatencyMs": 150,
179      "actor": "68ca791e-e420-4fc1-8283-e1a515651dd6",
180      "place": "sanctuary",
181      "revision": "19",
182      "inventory": [
183        "keeper-lantern"
184      ],
185      "otherTraveler": "93702291-200c-4fab-84eb-a667d9c2ca94",
186      "errors": []
187    }
188  },
189  "shutdownBoundsMs": {
190    "drain": 10000,
191    "socketHandshake": 250,
192    "process": 15000,
193    "composeGrace": 20000
194  },
195  "verifiedFaults": [
196    "admitted interaction finishes during drain and final motion commits before socket close",
197    "admitted gateway finishes and destination motor is saved",
198    "late cooperative pose survives an older interaction commit",
199    "accepted cooperative interaction updates stale presence before final save",
200    "drain deadline returns failure without acknowledging blocked work; successor fences stale writer",
201    "storage failure during an already-started normal drain cannot report success",
202    "lease and real PostgreSQL loss cause process exit 1; replacement restores acknowledged ownership",
203    "event-loop stall beyond lease TTL yields no late authoritative motion",
204    "trusted and cooperative browser pages freeze while unavailable and reconnect under a higher epoch without reload"
205  ],
206  "priorFailures": [
207    {
208      "log": "/tmp/dw-lifecycle-control.log",
209      "reason": "Cooperative fixture stopped immediately after sending a pose, before server admission. It now waits for observed presence before asserting final admitted motion."
210    },
211    {
212      "log": "/tmp/dw-lifecycle-control-full.log",
213      "reason": "Graceful drain exposed stale cooperative presence after a committed interaction. Per-connection pose versioning now updates accepted interaction positions without overwriting newer movement."
214    }
215  ],
216  "limits": [
217    "one process per room; no room directory, regional routing or live host-to-host handoff",
218    "position and durable ledger recovery, not in-flight velocity or dynamic script/physics state",
219    "abrupt kills retain the existing four-second motion autosave window",
220    "restart requires a deployment supervisor; browser harness explicitly starts the replacement",
221    "measurements are native local fixtures, not production RTO guarantees",
222    "Docker/Coolify execution, remote CI, capacity and broad hardware remain unqualified",
223    "character model redesign remains deferred to final polish"
224  ]
225}
226