You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
lane-handoff reads the lane lifecycle through a pipeline whose awk exits early, so under pipefail the read dies of SIGPIPE (exit 141) now and then and the handoff records no transition #280
lane-handoff reads the lane's lifecycle through a pipeline that can die of SIGPIPE.
The pipeline:lane-handoff:1490-1491 and :1505-1506 at 670a852 pipe lanes-edit.sh lane-state "$lane" into awk -F"\t" '$1 == "state" { print $2; exit }', and the second one into the same filter for operation.
The race: the script runs under set -uo pipefail (lane-handoff:120). awk exits as soon as it has printed its one field. If lanes-edit.sh writes again after that, the write gets SIGPIPE, lanes-edit.sh dies with 141, and under pipefail the whole substitution's status is 141.
What the handoff does then:case "$lcb_rc" in 0 | 8) takes 141 as a failed read. The handoff prints "the lane lifecycle could not be read (… lane-state … exited 141), so this handoff records no RUNNING -> SWAPPING -> SWAPPED transition", and returns from the lifecycle block. It records no fence, takes no inventory, and makes no transition.
It fails safe: the swap still goes on, and the lane is read later as a lane with no recorded swap.
But it is wrong, and it depends on timing alone. The read did not fail: the reader stopped listening.
The failure: 1 failed, 2742 passed, in tests/test_triad_lane_tooling_handoff.py::test_t018_the_handoff_reports_a_leg_git_cannot_read_as_the_sweep_counts_it (:600 → :553).
The handoff's stderr says … lanes-edit.sh lane-state triad-1 exited 141.
So the expected line, "the worktree inventory entry for … was NOT written: the assembly has 1 unreadable leg(s) …", is never printed.
It is intermittent: the same test passed on the same code one prefix down (q4e, run 39322369835) and in every run before it.
The runner image was the one that started rolling out on 2026-10-19 (ubuntu-latest moving to Ubuntu 26, git 2.55.0). It may change the timing, but not the cause.
Where else
The same shape occurs elsewhere: a command whose output is read by a consumer that stops early (awk … exit, head -1), under pipefail. At 670a852, by grep:
lane-handoff: 32 | awk … exit } pipelines and 2 | head -1;
lanes-edit.sh: 18 and 27;
lane-start: 19 and 1;
lane-end: 0 and 1.
Only the ones whose producer writes in several pieces can race. A producer that writes its whole output in one write finishes before the reader exits.
The fix
For the lifecycle reads, read the whole output first, then parse it: lcb_raw="$(… lane-state "$lane" 2>/dev/null)" || lcb_rc=$?, then awk on printf '%s\n' "$lcb_raw". The read's status is then the producer's own, and nothing can end the producer early.
For the other sites, audit each pipeline fed by a command. Do the same where the producer can write after the consumer exits, and leave the rest.
Test it deterministically: a lane-state that prints the state line, then writes again after a short pause, makes the old pipeline exit 141 every time.
Why now
Every PR's tests job runs the T018 test, so the race can turn any PR's CI red at random. It can also flake the candidate suites of the triad migration's rehearsal (#186). Lane openRepoTools-3, which owns the lane tooling, is fixing it now, to land before the rehearsal's freeze.
CLAIMED — lane openRepoTools-3, session 83619980-06bb-4469-ae73-2a8c5e61981a@Eagle, 2026-10-19T22:42:17Z, for #280
Logged in lanes/log/openRepoTools-3.md at 28b38c12debd47140496fb16081dcf979d53736c.
The three reads (lane-collision-protocol Rule 1):
1. existing `CLAIMED —` comments on opensoft/openRepoTools#280:
none
2. `gh pr list --repo opensoft/openRepoTools --state all --search "#280"`, kept where the row or its body names `#280`:
none
3. `git ls-remote --heads git@github.com:opensoft/openRepoTools` branches naming `280` as a whole token:
none
Lane openRepoTools-3, 2026-10-20T00:5xZ: a correction to this issue, the fix's state, and a follow-up.
Correction. The runner was not "Ubuntu 26".
The failed job's log says image ubuntu-24.04 20261012.334.1, which is Ubuntu 24.04.5.
Its awk is gawk. The image's manifest lists gawk, which registers as /usr/bin/awk at a higher priority than mawk.
gawk returns at the first record, so awk … exit closes the pipe while lanes-edit.sh is still writing. That is the race.
Eagle's default awk is mawk 1.3.4 20240123, which reads to the end of a small input, so the race does not show there without help.
The fix is fc061fe, on fix/280-lane-state-sigpipe. It reads lane-state whole, takes the status from it alone, and then parses the value.
An independent review found it correct: old and new code behave identically in 28 cases. Its verdict is LAND.
The review raised one SHOULD: the new test's premise rested on a 0.3 s pause. Its writer is now replacing the pause with padding past the 64 KiB pipe buffer, so the test no longer depends on timing.
RELEASED — lane openRepoTools-3, session 83619980-06bb-4469-ae73-2a8c5e61981a@Eagle, 2026-10-20T03:44:03Z, for #280 — #283 landed as 677acc0 and closed #280
Activity
brettheap commentedon Oct 19, 2026
CLAIMED — lane openRepoTools-3, session 83619980-06bb-4469-ae73-2a8c5e61981a@Eagle, 2026-10-19T22:42:17Z, for #280
Logged in
lanes/log/openRepoTools-3.mdat28b38c12debd47140496fb16081dcf979d53736c.The three reads (lane-collision-protocol Rule 1):
brettheap commentedon Oct 20, 2026
Lane openRepoTools-3, 2026-10-20T00:5xZ: a correction to this issue, the fix's state, and a follow-up.
ubuntu-24.0420261012.334.1, which is Ubuntu 24.04.5./usr/bin/awkat a higher priority than mawk.awk … exitcloses the pipe whilelanes-edit.shis still writing. That is the race.fc061fe, onfix/280-lane-state-sigpipe. It readslane-statewhole, takes the status from it alone, and then parses the value.lane-start, which runs underset -euo pipefail. In a few sites a 141 ends it with no message. At:2156, a 141 takes the minted-transcript branch for a session that is already recorded.lanes-edit.shhas nopipefail, and none oflane-end's sites can race.Lane: openRepoTools-3
lane-handoff reads the lane lifecycle whole and parses it afterwards,…
brettheap commentedon Oct 20, 2026
RELEASED — lane openRepoTools-3, session 83619980-06bb-4469-ae73-2a8c5e61981a@Eagle, 2026-10-20T03:44:03Z, for #280 — #283 landed as 677acc0 and closed #280
The v1.1.0 notes take lane 3's review of #293, put #209 in the lane a…
The v1.1.0 notes now say that the fixes for #255 and #280 are part of…
Case 6's comment on #280's race says the two red runs ran on ubuntu-2…