Repository navigation
🪲 Answer from a finished holder's publication when elected late - #665
Merged
Merged
Conversation
A recovery attempt waiting behind a live ticket polls the published tree only between election passes, while a holder marks its ticket done only after publishing. When the publication and the release both landed in the window between one poll and the next election pass, the waiter was elected and entered the recovery cleanup a second time — harmless to durable state, because the in-lock re-check removed nothing, but a violation of the contract that an attempt which did not do the recovery answers from what the holder published, and the intermittent failure AM19 caught under Bun (#664). An elected attempt now checks the published tree before entering the cleanup: ticket order guarantees a finished holder's publication is visible by election time, so being elected behind one means the answer is already on disk. AM20 produces the exact window deterministically through a new election-pass observer and fails without the fix. Closes #664 Claude-Session: https://claude.ai/code/session_015PmPc8yC6AJKQiu9F9d2ru
PR #665: 🪲 Answer from a finished holder's publication when elected late2 files, +67 / -1 Scope✅ PR scope looks good. StructuralOxlint structural signals:
Slop✅ Slop indicators look low. Static AnalysisOxlint: 5 diagnostics across 1 file (3 rules) no-array-sort (2): packages/acp/src/adapter-snapshots.ts Correctnessadapter-snapshots.ts, signal cluster, multiple Oxlint rules fired, Are the lint violations in this file clustered due to generated or unreviewed code? |
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.
Why
AM19 failed intermittently under Bun on
mainat 879c4ff (run 33318388159, attempt 1), opening #663. The identical revision passed on re-run, and the commit touched nothing underpackages/acp, so this is the flake tracked by #664 — but the cause is a real ordering gap in the recovery election, not a defective assertion.What changes
Before:
A recovery attempt waiting behind a live ticket polled the published tree only between election passes, while a holder marked its ticket
doneonly after publishing. When the publication and the release both landed between one poll and the next election pass, the waiter was elected and entered the recovery cleanup a second time. The in-lock re-check removed nothing, so durable state stayed correct — butbeforeRecoveryCleanupobserved a second entry, violating the module's contract that an attempt which did not do the recovery answers from what the holder published.After:
An elected attempt checks the published tree before entering the cleanup. Ticket order guarantees a finished holder's publication is visible by election time —
doneis written only after the rename that publishes — so being elected behind a finished holder means the answer is already on disk, and the attempt settles on it without entering the cleanup.How it works
What must stay true
publishedcheck, and checked by AM19 (statistical) and AM20 (deterministic).beforeRecoveryCleanupis unchanged, and AM8 still proves it.How to verify it
beforeRecoveryElectionobserver — publishes a donor tree and finishes that ticket in the exact window after the attempt's lastpublishedpoll and before its next election pass. It proves the elected attempt answers from the publication (cleanupsstays 0, donor bytes intact) and fails withcleanups = 1when the pre-cleanup check is removed (mutation-checked locally).packages/acp/tests/adapter-materialization.test.tsfile (22 tests) passes under all three runtimes at a744280:deno task test packages/acp/tests/adapter-materialization.test.tsbun test --timeout=300000 packages/acp/tests/adapter-materialization.test.tspnpm exec tsx --tsconfig tsconfig.node.json --test packages/acp/tests/adapter-materialization.test.tsdeno task lintanddeno task checkpass.Scope
Included
publishedcheck inrecover().beforeRecoveryElectiontest observer and AM20.Intentionally unchanged
publishedre-check inside the cleanup: publication can still appear after election (a rename can replace an empty target directory), so the pre-check does not subsume it.New abstractions
EmbeddedAdapterObservers.beforeRecoveryElectionexists because the racing window cannot otherwise be produced deterministically — the same reasonbeforeRecoveryCleanupexists, and AM20 is its consumer.Scope confirmation
Closes #664
https://claude.ai/code/session_015PmPc8yC6AJKQiu9F9d2ru