Development record
The shared file lock's backoff cap limits staging to roughly ten writers a second, so a burst of simultaneous sub-agent completions loses transcripts. The lock helper backs off exponentially to a hundred-millisecond ceiling, so the rate a contended lock admits is set by that ceiling and not by how short the critical section is. Measured here, sixteen simultaneous stages take 2.12 seconds, consistently across three runs. Extrapolating the same rate, a burst past roughly forty to fifty simultaneous completions begins exceeding the five-second staging lock timeout, and a stage that times out is refused: the transcript it carried is not written anywhere, which is the loss the capture work exists to prevent. Sessions that fan out widely are exactly the sessions whose delegated reasoning is most worth keeping, so the ceiling bites hardest where the value is highest. The condition is pre-existing in the locking helper rather than introduced by sub-agent capture, but nothing reached the lock concurrently before, so it was unreachable in practice until now. The remedies are design-shaped and should be chosen rather than assumed: raise the timeout, lower the backoff ceiling, sharded locks keyed per agent, or a lock-free append with reconciliation at drain.
The shared file lock's backoff cap limits staging to roughly ten writers a second, so a burst of simultaneous sub-agent completions loses transcripts. The lock helper backs off exponentially to a hundred-millisecond ceiling, so the rate a contended lock admits is set by that ceiling and not by how short the critical section is. Measured here, sixteen simultaneous stages take 2.12 seconds, consistently across three runs. Extrapolating the same rate, a burst past roughly forty to fifty simultaneous completions begins exceeding the five-second staging lock timeout, and a stage that times out is refused: the transcript it carried is not written anywhere, which is the loss the capture work exists to prevent. Sessions that fan out widely are exactly the sessions whose delegated reasoning is most worth keeping, so the ceiling bites hardest where the value is highest. The condition is pre-existing in the locking helper rather than introduced by sub-agent capture, but nothing reached the lock concurrently before, so it was unreachable in practice until now. The remedies are design-shaped and should be chosen rather than assumed: raise the timeout, lower the backoff ceiling, sharded locks keyed per agent, or a lock-free append with reconciliation at drain.
Grounds
- pursued: a burst of 64 simultaneous distinct-agent stages all succeed and a held agent lock blocks only that agent; a stage refused with lock contention during a fan-out, or an empty lock file per sub-agent accumulating in staging/locks, would show it wrong
Frontmatter
| id | iss-2609090828371674 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | major |
.abcd/work/issues/resolved/iss-2609090828371674-the-shared-file-lock-s-backoff-cap.md
open on GitHub ↗ · commit history ↗
mentions2
- dcn-26092300000000012026-09-23 — The product thinker ruled on the owed items of the autonomous run of 2026-09-23 in one interview, one question at a time (07:51Z to 09:32Z, while the run was paused): two release blockers, two intents, the 35 major captures routed to the product thinker, and two older owed rulings. The release waits for two things: version-stamped plugin payloads (iss-2609230733497536, built by a run lane, with no criterion amended and no deferral) and a release press release composed at the cut from the shipped intents' press releases, which is a new capability and gets an intent and its planning interview before any lane builds it. The run may approve the release environment itself once every gate is green; that agenda line is written in the release commit, not here. itd-4's AC3 is built as written, the `--issue-drift` check and the rename of the back-links to `related_issues` / `related_intents` together, and spc-6 closes only when both land (the 2026-07-17 ruling stands). itd-43's third criterion is moot and dropped, so spc-8 closes. The guard contract is extended to read a host-supplied per-call working directory (iss-2609212142557657, option A), after a probe of what the host does when none is supplied. Four majors are ruled to a build (iss-2608231120121681 write-path smoke, iss-2608290810036869 preflight before the push connects, iss-2609090828371674 per-agent staging locks, iss-2609120505141653 the provenance comment) and do not hold the tag. The rulings that set a rule each have their own entry below; every other routed major is deferred past v0.9.0 with its ruling as the `deferral_reason`, and the 168 routed minor and nitpick captures take the run's default deferral. The product thinker also asked that the interview be kept as autonomous-run experiment data, towards making a run transparent to the person it serves; the observations feed the run's end-of-run research note. Rejected, as the frame: the run taking any of these rulings itself.
- iss-2610051434156079On the v0.13.1 release PR's merge-queue run, the macOS race lane failed TestHookSubagentStopConcurrentCompletionsAllStage: 12 simultaneous subagent-stop hooks all exited 0 but only 10 transcripts were staged (internal/surface/cli/hook_subagent_stop_test.go:336). The same suite passed on the PR's own run and on every queue run earlier that day, so the loss appears only under a slow, race-instrumented host, but it is a silent loss: the hook reports success and the transcript never reaches the store. It is the defect iss-2609090828371674 resolved (the shared lock's backoff ceiling capping staging throughput), shown not to hold under load.