test: fix two base-gate flake races (mcp-inject pre-start kill; session-handoff wait-depth) - #814
Merged
Merged
Conversation
… reap The timeout test read the child's pid file unconditionally after the conversion's 3s-deadline fallback — but under heavy parallel load (the workspace gate; WSL fork latency) the deadline can kill the child BEFORE its fork+exec ever runs, so the pid file legitimately never exists and the read panicked (the third origin/main base-gate flake, 2026-09-19 rust phase, mcp_inject_tests.rs:505). The pid file is written as the script's FIRST statement, so its absence at read time deterministically means the child never started: a pre-start kill+wait IS the reap (the property under test holds by construction), while the leak this test guards against (a started sleep surviving the timeout) always leaves the file behind for the kill -0 assertion. The Err arm returns as a valid outcome instead of panicking. Mutation pair: with the conversion deadline forced to zero (the deterministic pre-start kill), the old test panics at :505 — the exact gate failure — and the fixed test passes; under the real 3s deadline the normal timeout+reap+kill-0 path is unchanged (3.01s).
… not the first match The r27 F2 test's bounded-poll broke on ANY matching binding row, but an interim unfenced row (observed pair None) can land before the runner's under-ticket adoption — the row the assertions read. When the interim row won the race the test asserted None against Some(generation) and panicked (isolated ~13% failure rate; the pre-push/base-gate flake). Wait for the row that actually satisfies the contract — one stamped with the supplied handoff (epoch, generation) pair — so the assertions never read an interim row. The regression the test guards against (the adoption writing None and never the pair) still fails at the deadline, now with the full bindings dump. Post-fix: 0/40 isolated runs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Two more load-race flakes surfaced by the origin/main base gate, both fixed test-side with structural reasoning, no widened timeouts:
1. mcp_inject: the pre-start kill of a timed-out conversion IS the reap
live_wslpath_timeout_falls_back_and_reaps_the_childread the child's pid file unconditionally after the conversion's 3s-deadline fallback. Under heavy parallel load (the workspace gate; WSL fork latency) the deadline can kill the child BEFORE its fork+exec runs — the pid file legitimately never exists, and the read panicked (mcp_inject_tests.rs:505, the rust-phase failure of the 2026-09-19 base gate).The pid file is written as the script's FIRST statement, so its absence at read time deterministically means the child never started: a pre-start kill+wait IS the reap, while the leak this test guards against (a started
sleepsurviving) always leaves the file for thekill -0assertion. TheErrarm now returns as a valid outcome.Mutation pair: with the conversion deadline forced to zero (the deterministic pre-start kill), the old test panics at :505 — the exact gate failure — and the fixed test passes. Under the real 3s deadline the normal path is unchanged.
2. session-handoff: wait for the SETTLED under-ticket binding row
the_claude_handoff_target_binding_carries_the_handoff_generationpolled until ANY matching binding row existed, but an interim unfenced row (observed pair None) can land before the runner's under-ticket adoption — the row the assertions read. When the interim row won, the test asserted None against Some(generation) and panicked (isolated ~13% failure rate, 4/30; it blocked this branch's first pre-push gate).The poll now requires the row that satisfies the contract (stamped with the supplied handoff pair). The r27 regression the test guards against still fails at the deadline — now with a full bindings dump. Post-fix: 0/40 isolated runs (pre-fix ~13%).
Evidence
cargo fmtclean; pre-push gate passed.