Repository navigation
fix(succession): re-check a predecessor live only for its quiet time (MUS-93) - #200
Merged
Merged
Conversation
…(MUS-93) A Claude session restarted before its MCP shim bound leaves a row with no client, which verdict() calls live while it was active inside the quiet time. The sweep scheduled a late check only for a live client or waiter (MUS-92), so that verdict was never checked again and the new session kept its fresh nickname for good, though the same rule calls the row dead seconds later. That's the line in every failed cell of #194's conformance runs. Such a predecessor is now checked again until its quiet time has passed (succession::quiet_until), a tick after, never past the swap window, through the same pending check. A sibling that keeps signalling moves its own time on and keeps its name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…edicate (MUS-93) From the watchman's read of #200: quiet_until restated verdict's unobservable branch, so the two could drift apart. Both now decide it through judged_by_quiet_time, and the Codex guard is one function. No change in behaviour; the existing verdict tests and the new ones pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…en PRs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…MUS-113) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
MUS-93: this is the cause of the conformance failure on #194.
What failed. In both of #194's runs (42324052913 and 42330531873), the only cell that failed the suite was
claude×unread-mail-follows-a-restart.claude×restart-keeps-identityalso failed once, though it's onFLAKYand doesn't fail the suite. Every pi, opencode and prime-agent failure in those runs is already listed as known (MUS-81, MUS-82, MUS-89). In each failed cell the daemon logged:Why.
FakeClaude::startruns the session-start hook and then starts the MCP shim, which binds its client asynchronously. A cell that restarts soon after starting can kill the old shim before it binds. The old row then has no client, andverdict()calls it live inside the quiet time. The sweep'sLivearm callscheck_againonly for a live client or waiter (MUS-92), so this verdict is never checked again, even though the same rule calls the row dead seconds later. The new session keeps its fresh nickname, and the cell times out at 20 s. A real Claude session restarted before its MCP shim attaches would lose its nickname the same way.The fix. A new pure function,
succession::quiet_until, gives the time at which such a predecessor would count as dead by the same rule: its last signal plusquiet_ms. It returnsNonewhen the predecessor is live for any other reason. TheLivearm then callscheck_again(min(dead_at + tick, registered + window)). This uses the existing pending check, with no second timer (robust-warbler's ask). Applying the rule again later doesn't loosen it. A sibling that keeps signalling moves its own time on, and keeps its name once the window ends.Tests.
a_quiet_row_says_when_it_would_count_as_dead: the time it returns is exactly whereverdictturns from live to dead. A sibling that signals again moves the time on. A waiter, a bound or dropped client, a Codex row before MUS-77, or no row at all givesNone.crates/daemon/tests/identity_quiet.rs: a predecessor that was active inside its quiet time is taken over by a late check once the quiet time passes. A sibling that keeps signalling through the swap window keeps its name. This test fails without the fix: I removed thecheck_againline and it failed at the takeover assertion.CONFORMANCE_ONLY=restartpasses locally, andfollows-a-restartpassed 3 of 3. Caveat: locally the MCP shim always bound in time, so the takeovers came from an observed client drop and the new path never fired. The local pass shows nothing broke. It doesn't reproduce the race; CI's slower runner is where that shows.cargo fmt --checkandclippy -D warningsare clean. Everymuster-daemontest passes.Not done: no new
FLAKYentry, per robust-warbler and the watchman. The existing MUS-93FLAKYcells stay until they pass in CI on three PRs in a row, as MUS-93's done-when says. Theclaude-tlscells' earlier failures predate any daemon log, so this doesn't show whether they share the cause.docs/roadmap.mdanddocs/stable-identity.mdare updated.🤖 Generated with Claude Code