2026-06-06T06:42:56.7370000Z Requested labels: self-hosted, Linux, gravity
2026-06-06T06:42:56.7370000Z Job defined at: SaberMage/spt-core/.github/workflows/ci.yml@refs/heads/dev-freeform
2026-06-06T06:42:56.7370000Z Waiting for a runner to pick up this job...
2026-06-06T06:42:56.7360000Z Evaluating twohost-b.if
2026-06-06T06:42:56.7360000Z Evaluating: (success() && (contains(github.event.head_commit.message, '[twohost]')))
2026-06-06T06:42:56.7360000Z Expanded: (true && contains('fix(daemon): M7 [twohost] — responder must let the joiner close first (Done/Seed close race)

First cross-host run of the product-surface join rung (run 27054437482)
failed deterministically: role B completed the ceremony every attempt
(`PAIRED: joiner pinned`) while role A read `connection lost` on the final
length prefix — `pairhost::respond` dropped the connection the instant
`run_responder` returned, and the immediate QUIC CLOSE discarded the
still-unacked Done+Seed frames (`SendStream::finish()` only queues; it
does not deliver). The joiner therefore never persisted the seed, retried
into `AlreadyTrusted` forever, and both roles burned their rig windows.

Fix: after the ceremony (success or failure), the responder waits for the
JOINER to close the connection — the same discipline `meet::serve_once`
already uses — bounded by a 10s CLOSE_GRACE so a vanished peer cannot
park the task; the rate-limiter slot is released before the wait so the
grace ...
2026-06-06T06:42:56.7360000Z Result: true
2026-06-06T06:43:08.7620000Z Job is about to start running on the runner: gravity