## Fix Both `twohost-a` and `twohost-b` now use `needs: [test, n1-gate]`. Both test/n1 matrices finish before either role becomes eligible on the single-slot runners. This removes the within-run scheduling race; it does not guarantee scheduler simultaneity or eliminate unrelated runner contention. - Keep `!cancelled()` and the explicit manual opt-out unchanged: unrelated upstream failures must not erase independent seam evidence. - Keep the **900s rendezvous budget** unchanged; no product/test-body changes or budget widening. - Update the workflow explanation and `docs/GOLDEN-CI.md` operating procedure. - Add **IR-142, BUILT-pending-golden**, with the RCA as origin and the successor acceptance gate. IR-142 was unused at apply; allocated as requested by Doyle. The base register ends at IR-137; no unrelated entries are copied from the assembled golden line. Symmetry is necessary: adding n1-gate only to A would still release B early. Depending on n1-gate without test would permit the mirrored ordering failure. Related: https://github.com/BigscreenVR/spt-bs-releases/issues/307 Origin: `.spt/preserved/307/golden-35313912102/RCA-twohost-b.md`, read in full; adjacent `twohost-b-105517287374.log` records the failed pairing rung. ## Existing negative control — golden 35313912102 | Job | startedAt (UTC) | |---|---| | twohost-b / kitsubito | 2026-09-18T07:22:22Z | | twohost-a / hfenduleam | 2026-09-18T07:33:01Z | **639s skew.** n1-gate Windows ran between test and A, 07:22:22Z–07:32:59Z. B's 900s rendezvous wait expired before A's build/bring-up completed (test wall 900.48s). This is CI shape, separate from the resume/reconcile product race in the same golden. ## Local verification — structural only Receipts: `.spt/preserved/307/twohost-barrier/`. - PyYAML 6.0.2 parsed the workflow; the dependency DAG is valid with no missing job references. - Parsed comparison with base: exactly two semantic changes, the roles' `needs` values. All other workflow values, conditions, steps and timeouts are unchanged. - All four matrix-completion combinations checked: neither role passes the dependency barrier until both matrices finish, then both do. - `traceable-reqs check --json`: **926/926 complete, zero findings**, exit 0. - No cargo, runner mutation or same-SHA golden rerun. Actionlint is not installed; no actionlint execution claimed. These checks do not prove cross-host pairing. ## Successor golden acceptance — PENDING Thin CI cannot pair the hosts. The successor golden must include both this repair and todlando's resume/reconcile repair, with deployah reshaping once on top of both. Acceptance requires starts **within seconds of one another AND both jobs green**. | Successor evidence | twohost-a | twohost-b | |---|---|---| | startedAt (UTC) | Not yet observed | Not yet observed | | conclusion | Not yet observed | Not yet observed | Update this PR body/gate receipt with the successor run URL, candidate SHA, both exact `startedAt` timestamps and both conclusions when observed. IR-142 remains BUILT-pending-golden until that evidence exists; the historical timestamps above are the negative control, not successor proof. Doyle owns fast-forward order. Base is `0ab1e48b7c4cf4c16e0e46c14b415ff28bbc8f5c`; whichever repair lands second rebases before merge. No merge or golden dispatch performed by this lane. Co-authored by: hertz ## Golden #3 observed evidence — IR-142 NOT MET Run [35349501073](https://github.com/BigscreenVR/spt-bs-core/actions/runs/35349501073), candidate `b25b2b770e8fadb3e08356032bab3eb335538599`. This observation supersedes the unobserved successor fields above; it is not acceptance. | Job | Job ID | startedAt (UTC) | Observed conclusion/status | |---|---|---|---| | twohost-b | 105643668371 | 2026-09-18T14:48:21Z | failure; completed 15:05:35Z | | twohost-a | 105643668339 | 2026-09-18T15:15:29Z | failure (terminal, deployah KDNU4LF5) | Start skew **27m08s (1628s)**. A started **9m54s after B completed**. Timing acceptance fails regardless of A's eventual result. B's preserved log shows `two_host_ladder_role_b` failing the pairing rung (`A rostered via the daemon-hosted responder`) after **900.61s**, **exit101**, two tests passed and one failed. This is not the earlier predicted 40-minute timeout VOID. Doyle's occupant observations (`LATI7DJN`, `MHGGT7BL`) identify PR#235 run35353733267 Windows unit starting14:48:20Z after A queued14:48:19Z: **INTERLEAVE-SKEW**, cross-workflow single-slot scheduling, not a failed within-run dependency barrier. The separately recorded kitsubito outage ended with unit restart14:26:07Z / GitHub online observation14:26:59Z; it is not conflated with these starts. Preserved proof: `.spt/preserved/307/twohost-barrier/golden3-pairing-evidence.json`; log `golden3-twohost-b-105643668371.log`, 78581 bytes, SHA256 `f26ef48b95683cbf86291ee5f08d0c6fae7874ab1237f7f967e43c4b8bb7f305`. IR-142 remains BUILT-pending-golden, not DONE. Per Doyle, next acceptance attempt is golden#4 with raised caps and an empty queue; still requires paired starts within seconds and both jobs green. Terminal evidence from deployah `KDNU4LF5`: both twohost jobs concluded **failure**. Final metadata: `.spt/preserved/307/deployah-intake-r3/golden-final.json`; A log: `.spt/preserved/307/golden-35349501073/deployah-twohost-a.log`. The27m08s start gap and **IR-142 NOT_MET** verdict are unchanged. Golden#4 awaits empty-queue/reservation admission.