Follow-on to #10289, filed so the residual gap is not lost when that card closes. #10289 is about the bash-3.2 spin and is genuinely finished by PR #10609; this is the part that card's own follow-up comment explicitly declined to attempt ("Not attempting that fix here — out of scope").
State after PR #10609
That PR makes the wrapper bash-3.2-clean and gives every acquire path a bounded verdict, including a host preflight. On a stock macOS the preflight now fires and the run ends:
VERDICT lock-unusable (exit 99) · never acquired · refused before waiting ·
nothing was built or tested · <command>
That is a strict improvement over an unbounded silent spin — a caller told to read the VERDICT line now finds one, at second zero, and no CPU is burned against the build the lock protects. But the outcome for a macOS dev agent is still "cannot use the shared lock at all."flock is util-linux and is not present on a stock macOS, and it is the only mutual-exclusion primitive the wrapper has.
Two cards have already worked around this by running verification unlocked and declaring it in the PR body (#10219, #10221). That workaround is honest but it is exactly the erosion the lock exists to prevent: while any agent verifies unlocked, the serialization guarantee is gone for everyone in that container.
The decision this needs
Making it work on macOS means introducing a second mutual-exclusion primitive, and that is an architecture call rather than a mechanical fix — which is why it is a separate card. The current design deliberately rests on flock and says so in the file's header:
flock remains the ONLY mutual-exclusion primitive. […] Release still belongs to the fd: this script never hand-rolls a lockfile, and a kill -9 at any point releases the lock the moment the process dies.
That kill-safety property is load-bearing, and it is precisely what a hand-rolled lockfile gives up. Options, none free:
- Require
brew install util-linux and keep refusing until it is present. Zero new mechanism; the refusal is already implemented. Cost: an unenforceable host prerequisite, and the refusal is what agents meet in the meantime. mkdir-based lockfile fallback, macOS only.mkdir is atomic everywhere. Cost: gives up fd-release — a killed holder leaves the lock held, so it needs holder-liveness reaping, which is the stale-lock problem the ticket queue already solves once and would now need solving again for exclusion itself.- A tiny
flock(2) shim (perl's flock is in core and available on stock macOS). Keeps fd semantics and kill-safety; costs a perl dependency on the acquire path and a second implementation of the primitive to keep in step. - Declare the lock Linux-only and give macOS an explicit, declared unlocked mode rather than a refusal, so the degradation is visible in the verdict rather than blocking the agent.
My weak preference is (3) — it is the only option that preserves the kill-9-releases invariant, and perl is already used on the macOS path in #10609 for sub-second arrival stamps, so it is not a new host assumption. But (1) is defensible if macOS is not actually a supported agent host, and that is the question underneath all four: is macOS a host the fleet must support, or is the Linux container the only one that matters? If it is the latter, option 4 is honest and cheap and this card is mostly documentation.
Filed unassigned for triage. No urgency implied — the sharp end (unbounded spin, no verdict, CPU burn) is fixed; what remains is that macOS agents must verify unlocked and say so.
Follow-on to #10289, filed so the residual gap is not lost when that card closes. #10289 is about the bash-3.2 spin and is genuinely finished by PR #10609; this is the part that card's own follow-up comment explicitly declined to attempt ("Not attempting that fix here — out of scope").
State after PR #10609
That PR makes the wrapper bash-3.2-clean and gives every acquire path a bounded verdict, including a host preflight. On a stock macOS the preflight now fires and the run ends:
That is a strict improvement over an unbounded silent spin — a caller told to read the
VERDICTline now finds one, at second zero, and no CPU is burned against the build the lock protects. But the outcome for a macOS dev agent is still "cannot use the shared lock at all."flockis util-linux and is not present on a stock macOS, and it is the only mutual-exclusion primitive the wrapper has.Two cards have already worked around this by running verification unlocked and declaring it in the PR body (#10219, #10221). That workaround is honest but it is exactly the erosion the lock exists to prevent: while any agent verifies unlocked, the serialization guarantee is gone for everyone in that container.
The decision this needs
Making it work on macOS means introducing a second mutual-exclusion primitive, and that is an architecture call rather than a mechanical fix — which is why it is a separate card. The current design deliberately rests on
flockand says so in the file's header:That kill-safety property is load-bearing, and it is precisely what a hand-rolled lockfile gives up. Options, none free:
brew install util-linuxand keep refusing until it is present. Zero new mechanism; the refusal is already implemented. Cost: an unenforceable host prerequisite, and the refusal is what agents meet in the meantime.mkdir-based lockfile fallback, macOS only.mkdiris atomic everywhere. Cost: gives up fd-release — a killed holder leaves the lock held, so it needs holder-liveness reaping, which is the stale-lock problem the ticket queue already solves once and would now need solving again for exclusion itself.flock(2)shim (perl'sflockis in core and available on stock macOS). Keeps fd semantics and kill-safety; costs a perl dependency on the acquire path and a second implementation of the primitive to keep in step.My weak preference is (3) — it is the only option that preserves the kill-
9-releases invariant, and perl is already used on the macOS path in #10609 for sub-second arrival stamps, so it is not a new host assumption. But (1) is defensible if macOS is not actually a supported agent host, and that is the question underneath all four: is macOS a host the fleet must support, or is the Linux container the only one that matters? If it is the latter, option 4 is honest and cheap and this card is mostly documentation.Filed unassigned for triage. No urgency implied — the sharp end (unbounded spin, no verdict, CPU burn) is fixed; what remains is that macOS agents must verify unlocked and say so.