Skip to content

Stop two tests racing the runner: the legacy-lock reclaim and the inherited-child chain - #9

Merged
Edo771977 merged 2 commits into
mainfrom
claude/focused-carson-khonz0
Sep 18, 2026
Merged

Edo771977 merged 2 commits into
mainfrom
claude/focused-carson-khonz0

Conversation

@Edo771977

@Edo771977 Edo771977 commented Sep 18, 2026 •

Copy link
Copy Markdown
Owner

Two tests that asserted timing instead of causality. Both were found by running the suite, not by guessing: one on main after the Windows batch merged, the other by this PR's own CI run.

328/328, full suite run twice, tsc clean.

1. stale legacy lock without process identity does not follow a reused PID forever

Went red once in a full-suite run on main, passes ten times out of ten on its own. acquireLockSync() checks its deadline after a failed attempt, so a single stalled attempt on a loaded runner expires a 200ms budget in the gap between the reclaim that just succeeded and the retry that would have taken the lock.

The property under test is that a legacy lock whose owner PID still looks alive is reclaimed once it ages past staleMs — not how many milliseconds that takes. The budget goes to 5s against a 30s staleMs, so returning a successor at all still proves the reclaim happened on the spot rather than by aging out. Same fix, same reasoning, as the sibling test a few lines above; this one had been left behind, and tighter.

Still discriminating: removing the legacy-reclaim branch from reclaimAbandonedLock() fails the test.

2. broker rolls back child threads inherited through a failed provisional claim

This PR's first CI run went red on it: "delayed grandchild thread was not created".

The fixture scheduled the child 100ms after turn/start, and created the grandchild only if the resume had already set nestedSubagentRequested by the time that timer fired. So the test passed only when the client got from turn/start through a disconnect, an unsubscribe wait and a fresh connection to the resume in under 100ms — which a loaded runner does not promise. Reproduced exactly by putting a 300ms delay in that gap.

The new with-resume-inherited-subagent behavior drives the whole chain off the resume itself: child, then grandchild under it, then the resume failure — all while that claim is open, which is the scenario the test is about. Nothing in it depends on how fast the client got there.

Verified: passes with a 1500ms delay in that gap where the old version failed at 300ms; the whole file passes five runs in a row; and it still fails when the inherited threads are dropped from the rollback (claim.inheritedThreadIds removed from rollBackClaim()). The other two with-delayed-subagent tests never resume, so their behavior is unchanged.

Neither failure is a regression from the Windows batch — the first touches locking, the second broker subscriptions, and this PR's diff before these fixes was one test file.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UXfvnjSC72HsM6EEPVt2Tg

It failed once in a full-suite run and passes ten times on its own: a
200ms budget was the whole problem. acquireLockSync() checks its deadline
only after a failed attempt, so on a loaded runner a single stalled
attempt expires the budget in the gap between the reclaim that just
succeeded and the retry that would have taken the lock.

The property under test is that a legacy lock whose owner PID looks alive
is reclaimed once it ages past staleMs, not how many milliseconds that
takes. A 5s budget against a 30s staleMs still proves it — and reverting
the reclaim branch still fails the test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXfvnjSC72HsM6EEPVt2Tg
CI caught the second half of the same problem: "broker rolls back child
threads inherited through a failed provisional claim" went red with
"delayed grandchild thread was not created".

The fixture scheduled the child 100ms after turn/start and created the
grandchild only if the resume had already set nestedSubagentRequested by
the time that timer fired. So the test passed only when the client got
from turn/start through a disconnect, an unsubscribe wait and a fresh
connection to the resume in under 100ms. Reproduced exactly by putting a
300ms delay in that gap.

with-resume-inherited-subagent drives the whole chain off the resume
itself: child, then grandchild under it, then the resume failure — all
while that claim is open, which is the scenario the test is about. With
it, the test passes even with a 1500ms delay in that gap, and it still
fails when the inherited threads are dropped from the rollback.

The other two with-delayed-subagent tests never resume, so they keep the
old behavior unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXfvnjSC72HsM6EEPVt2Tg
@Edo771977 Edo771977 changed the title Stop the legacy-lock reclaim test racing the runner Stop two tests racing the runner: the legacy-lock reclaim and the inherited-child chain Sep 18, 2026
@Edo771977
Edo771977 merged commit 7f9aded into main Sep 18, 2026
1 check passed
@Edo771977
Edo771977 deleted the claude/focused-carson-khonz0 branch September 18, 2026 11:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants