Status: Accepted
Date: 2026-10-12
Deciders: Stijn Dejongh (owner).
Technical Story: #6062
(agent action implement hung holding the machine-wide pre-review-gate lock), fixed in
PR #6068. Related: #2493 (the gate lock).
Context and Problem Statement
agent action implement ran the project's configured baseline test suite synchronously before it
returned. That run reused the for_review gate's head runner, which wrapped every launch in
pre-review-gate-run.lock, the machine-wide lock that serializes concurrent for_review head
runs (#2493). A claim therefore acquired, or queued on, a lock scoped to a different transition.
The claim could wedge (exit 124 under a timeout, about 0% CPU) and could block another lane's
for_review gate.
The baseline is still needed: the pre-review gate diffs head failures against it so that failures that already existed on the base are not reported as regressions.
Decision Drivers
- A claim must return promptly after the lane worktree exists and the work package is
doing. - The baseline must describe the code the lane started from, not whatever the base is by the time the work package reaches review.
- Capture must not couple to a lock that belongs to another transition.
- A capture fault must never refuse a
for_reviewmove.
Decision Outcome
Test-baseline capture runs capture-if-missing on the in_progress -> for_review edge, at the
lane's merge-base with its base branch, lock-free and fail-open; the claim never runs the suite.
- The claim path does not capture.
implement_capture_baselinebecamecapture_and_commit_baselinebecause it is no longer implement-only. move-task --to for_reviewcaptures when nobaseline-tests.jsonexists. A rework cycle finds the committed artifact and does nothing; an unconfiguredreview.test_commandcaptures nothing.- The capture ref is
git merge-base <lane HEAD> <base>(local refs only, no fetch). If it cannot be resolved, the base tip is used and a warning is logged. - Capture runs through
_run_raw_command(serialize=False)in its own detached worktree, keeping the group-safe launch and reap, without the gate lock. - Any fault in capture preparation or the run degrades to no baseline; the gate then reports
UNVERIFIED_BASELINEas a warning, exactly as for a never-captured baseline.
Consequences
- The baseline reflects the fork point. The artifact's
base_commitrecords the SHA it was taken at, so a reader can detect a stale baseline. - Concurrent captures from different lanes do not serialize on the gate lock.
- The
for_reviewhead run still serializes on the gate lock (#2493), so afor_reviewmove can wait on another lane's head run, but never because of a baseline capture. - The configured suite now runs at the first
for_reviewof a work package, where blocking is acceptable, instead of at claim time. The firstfor_reviewmove is slower by one suite run.