Repository navigation
Stop waiting for replication confirmation on writes that replicate nothing (audit: false, localOnly, copy-apply) - #3423
Merged
Conversation
Contributor
There was a problem hiding this comment.
Code Review
This pull request refactors replication confirmation logic to avoid waiting on writes that append nothing to replicate, such as unaudited, local-only, or copy-apply operations. It introduces a stagedAudit property on TransactionWrite and a helper function confirmsNothing to determine eligibility, alongside updating transaction handling, table staging, and adding comprehensive unit tests. One review comment suggests ensuring robust null-entry guards when iterating over DatabaseTransaction.writes to prevent potential runtime TypeErrors.
kriszyp
force-pushed
the
fix/appendedto-only-when-audit-appended
branch
from
October 23, 2026 02:42
30c1af2 to
5278eed
Compare
This was referenced Oct 23, 2026
…entry An unaudited put/create/patch/invalidate/relocate, an unaudited delete on a delete-tracking table, and a localOnly write append nothing a peer will receive, yet staging stamped them appendedTo and left them confirmation- eligible, so a replicatedConfirmation commit waited on a log key nothing replicated until it timed out (504), on both engines. recordUpdater, which alone decides whether an audit entry is appended and whether it is LOCAL_ONLY, now records that on the owning write (passed as its `write` option). Each fresh staging clears and re-derives it (RocksDB save(), LMDB doWrite), stamping appendedTo only on an actual append and excluding a write that replicates nothing from feasibility, target and residency checks. The early residency refusal applies the same rule, and the NoAudit-delete call-site flag is no longer needed. Dispatch-Task: harper-appendedto-only-when-audit-appended Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ri2uUp4SAKFrCCL8nyxYpr
…staged A commit handler may return a promise and append after an awaited dependency; deriving replicatesNothing when the handler returned would then skip confirmation for a write that did append. The fresh staging now resets stagedAudit to 'none' and the confirmation checks read it directly. recordUpdater notes the append after the audit put accepts it, and the test waits for the confirmation hook instead of a fixed delay. Dispatch-Task: harper-appendedto-only-when-audit-appended Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ri2uUp4SAKFrCCL8nyxYpr
…mment Dispatch-Task: harper-appendedto-only-when-audit-appended Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ri2uUp4SAKFrCCL8nyxYpr
… a coordinated retry A coordinated retry's put appends nothing, so it no longer reports an append, and a fresh staging that was skipped clears stagedAudit instead of the check reading skipped live, which a retry round can flip. Dispatch-Task: harper-appendedto-only-when-audit-appended Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ri2uUp4SAKFrCCL8nyxYpr
Dispatch-Task: harper-appendedto-only-when-audit-appended Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ri2uUp4SAKFrCCL8nyxYpr
…ited put is not confirmed The reload-marker test confirmed a put on an audit: false table, which replicates nothing (on LMDB it confirmed undefined). Its point is that a trailing write that replicates nothing does not suppress confirmation for a replicable write staged before it, so the put now goes to the audited table. Dispatch-Task: harper-appendedto-only-when-audit-appended Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ri2uUp4SAKFrCCL8nyxYpr
resources/DESIGN.md is already over its 1000-line budget on main; fold the eligibility paragraph into the preceding one so this change adds no lines. Dispatch-Task: pr-maint-355475e820ee481125db34713182ae84 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Use the shared staging predicate before LMDB reads candidate positions. Exercise the production confirmation registry and context count, including mixed local-only commits in both orders. Dispatch-Task: pr-maint-355475e820ee481125db34713182ae84 Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Dispatch-Task: pr-maint-355475e820ee481125db34713182ae84 Co-Authored-By: GPT-5 Codex <noreply@openai.com>
…tests Dispatch-Task: pr-maint-355475e820ee481125db34713182ae84 Co-Authored-By: GPT-5 Codex <noreply@openai.com>
…ertion message Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Dispatch-Task: pr-maint-355475e820ee481125db34713182ae84
kriszyp
force-pushed
the
fix/appendedto-only-when-audit-appended
branch
from
October 26, 2026 14:11
efae636 to
37eaf6a
Compare
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.
⊙ Problem
With
replicatedConfirmationrequested, unaudited, local-only and RocksDB copy-apply writes can wait until timeout (504) despite sending nothing to peers. This affects put, create, patch, invalidate, relocate, and tracked deletes on both engines.🤔 Should these writes succeed rather than refuse the confirmation?
Yes: nothing about them replicates, so there is nothing to confirm. A 400 would break callers that set one count for every write. The catch: a successful confirmation no longer always means a peer acknowledged the write.
💡 Solution
Unaudited, local-only and copy-apply writes now resolve without peer checks. Audited writes still wait, including mixed commits. The encoder records whether staging appended a replicable audit entry; confirmation uses that result on both engines, including the LMDB position selector from #3392.
🤔 Should a write that lost to an unreplicated entry stop waiting too?
Not here. A skipped write, or a RocksDB validation no-op, appended nothing and confirms on the entry that beat it. When that entry is itself unaudited or local-only, the wait still times out. Fixing it means judging the survivor's replicability, a separate rule: #3387.
⚖️ Alternatives
skipReplicationConfirmationin each commit handler — the decision would be repeated in seven handlers. The two earlier fixes of this kind each missed sibling paths.🤔 Should
replicate: falsetables be exempt too?Not here. harper-pro's sender skips them by policy core cannot see; its
confirmationFeasibilityhook should exempt or refuse them (#3399).🤔 What about a commit handler that appends without reporting its write?
It would skip confirmation. None exists: all seven managed handlers pass their write, and the two direct appenders are LOCAL_ONLY or opted out;
DESIGN.mdstates the rule. A typed handler return would enforce it, but changes every handler's signature for no current case.🔧 Changes
resources/RecordEncoder.ts—noteStagedAuditrecords'replicable'or'local'onoptions.writeafter each audit put returns. It ignores a RocksDB coordinated retry, whose put appends nothing.resources/DatabaseTransaction.ts:TransactionWrite.stagedAuditfield, and thecommitcontract that a handler stages its audit entry before it returns;save()resets it to'none'on each fresh staging, clears it when the staging is skipped (the Confirm a transaction whose only write is a losing relocation on the stored entry, not an unwritten log key #3183 fallback still applies), and stampsappendedTo/appendedAuditEntryonly after a real append. A retry keeps the fresh staging's value;confirmsNothingis the single eligibility test used byconfirmationTarget,residentPeerLists,refuseUnconfirmableand LMDB'sconfirmationPosition.resources/LMDBTransaction.ts—doWriteresetsstagedAuditbefore each attempt and clears it when the attempt is skipped.confirmationPosition(newestlocalTimeover the commit's writes) now skips writes that confirm nothing; before, a local-only write'slocalTimewas eligible.resources/Table.ts— the seven managedupdateRecordcalls pass their write. The early residency refusal now applies only to writes that will append a replicable entry. The delete handler's per-round reset and manualskipReplicationConfirmationare removed.resources/DESIGN.md— the eligibility rule and remaining residuals, and the commit-handler guidance.✅ Verification
unreplicatedWriteConfirmation.test.jsruns on both engines; withreloadMarker.test.js: 32 passing on RocksDB, 27 passing + 5 engine skips on LMDB. On the old base, all 12 non-replicating cases hang on both engines; reverting only the LMDB selector filter fails the local-only put case.reloadMarkernow asserts confirmation with an audited put.test:unit:resources:coreat37eaf6a's code: RocksDB 4135 passing, 0 failing; LMDB 3227 passing, 2 failing inreplicationDirectiveAuthorization.test.js(setReplicationConfirmation is not a function). Main fails the same 2 since Make replicatedConfirmation wait for peers on LMDB #3392 removed that LMDB export.test:unit:mainand integration not rerun locally; CI covers them.replicatedConfirmationresolves without peer acknowledgement for writes that replicate nothing.Test cases
enableAuditing(), which appends nothing (RocksDB)enableAuditing()🤔 Pin the entry-less fallback branch directly?
No. The fallback reads
getEntry(key)?.version, so a write with no stored entry is passed over. Only a skipped write on an already-missing key reaches it; that fixture costs more than the one optional chain it would cover.Refs replicatedConfirmation of a write that lost to an unreplicated entry waits until timeout (the skipped-write and validation no-op cases) and replicatedConfirmation on a table the sender never replicates waits until timeout (
replicate: false)🤖 Generated by Claude Code and OpenAI Codex; posted via @kriszyp.
Release target: main — fixes confirmation behavior on main; no customer report asks for a backport
Related PRs: #3392 overlaps (merged; this PR is rebased onto it and filters its LMDB selector with
confirmsNothing), #3411 overlaps (merged skipped-write fallback), #3429 overlaps (merged prose pruning reused here), #3430 overlaps (prunes the same guide), #3506 overlaps (open; new_writeUpdateearly returns must pass their write or mark skipped), #3527 overlaps (open; new commit handlers must pass their write), 7 others independentComplexity: complicated
Deferred findings
20082fcd75892557major correctness —resources/DatabaseTransaction.ts— LMDB selects a trailing skipped write's stale entry ahead of an earlier replicable append — filed LMDB replicatedConfirmation can confirm on a skipped trailing write's older entry #34254aa5385c5e4048b2major correctness —resources/DatabaseTransaction.ts— Validation no-op remains eligible for confirmation on RocksDB — filed replicatedConfirmation of a write that lost to an unreplicated entry waits until timeout #338774aa46a29a0859c8major correctness —resources/DatabaseTransaction.ts— Skipped writes confirm on unreplicated surviving entries — filed replicatedConfirmation of a write that lost to an unreplicated entry waits until timeout #3387e8379c0bd7b6be90major correctness —resources/RecordEncoder.ts— Audited replicate:false writes may wait on sender-excluded entries — filed replicatedConfirmation on a table the sender never replicates waits until timeout #3399f4c59d5f8c122869nit test-coverage —unitTests/resources/reloadMarker.test.js— Entry-less confirmation fallback lacks direct branch coverage — NOT FILEDDispatch: task
harper-appendedto-only-when-audit-appended· queued by unknown · ran by claude/opus/high · worker kzyp-xps-1Late Grok findings
7 surviving (highest major) — Grok reviewed efae636
resources/DatabaseTransaction.ts:2307— A no-change patch on an unaudited RocksDB table can still request confirmation of an unreplicated stored versionresources/RecordEncoder.ts:1166— An auditedreplicate:falsewrite remains confirmable; if the sender excludes its table without advancing acknowledgements, confirmation times outresources/DatabaseTransaction.ts:1981— LMDB put(A) followed by skipped B can confirm B’s stale position before peers receive Aresources/DatabaseTransaction.ts:2371— A losing write over an unaudited or local-only survivor regains confirmation eligibility and can wait on unreplicated dataunitTests/resources/reloadMarker.test.js:176— The trailing unaudited delete is filtered before entry lookup, leaving entry-less fallback regressions undetectedresources/DatabaseTransaction.ts:764— Successful confirmation without peer acknowledgement deserves a release-facing caveat for unaudited writesresources/DatabaseTransaction.ts:702— Trim staging narration and overlapping explanation, includingresources/DatabaseTransaction.ts:1970-1976andunitTests/resources/reloadMarker.test.js:167-168Not standing: none. Grok ran 20m (20m from launch to report); the fold adjudication (
cursor-grok@efae6363e6fe-361a26b6, codex) took 4m.Late Grok findings
7 surviving (highest major) — Grok reviewed a30a2cd
resources/DatabaseTransaction.ts:2321— A non-exempt handler appending without reporting its write bypasses confirmation; the named built-in control writers explicitly opt outresources/DatabaseTransaction.ts:2295— An empty patch on an unaudited RocksDB row remains confirmation-eligible and can wait on an unreplicated versionresources/DatabaseTransaction.ts:2359— A skipped write over an unreplicated surviving row regains eligibility and can wait for acknowledgement that cannot arriveresources/RecordEncoder.ts:1193— An audited replicate:false write remains eligible; if the sender excludes that table, confirmation can time outresources/DESIGN.md:967— Unaudited, local-only and copy-apply writes now succeed without requested peer acknowledgements; the supplied explanation is internalunitTests/resources/reloadMarker.test.js:174— The mixed-write test bypasses the entry-less fallback, leaving that branch unpinnedresources/DatabaseTransaction.ts:707— Added staging comments repeat implementation details and overstate the runtime-auditing rationaleNot standing: none. Grok ran 17m (17m from launch to report); the fold adjudication (
cursor-grok@a30a2cd9f38b-454dca39, codex) took 5m.Review-Coverage: authored=codex; ran=cursor-composer,gemini,claude; adjudicated=domain; declined=cursor-grok,muse; rounds=12; full=4 @ 37eaf6a
Review-Attention: study ~20m (critical: DatabaseTransaction.ts, LMDBTransaction.ts +2; decisions: do-less-alternative, confirmation-without-replicable-work) @ 37eaf6a