You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(persistence): preserve run-only metadata on peer reloads - #2303
This PR fixes metadata loss after a named peer notice reloads an on-demand persisted Collection. It also strengthens the session oracle and its native receiving fixtures.
An inner transaction can delete a row, then write metadata M while the row is missing. An enclosing update can later recreate that row without a metadata write. Decision 16 requires the sync run to retain M, while decisions 9 and 18 keep M nondurable. Previously, an unrelated peer notice reloaded the row and replaced M with absent stored metadata.
The wrapper now distinguishes local metadata from a named peer replacement. Known reloads retain local metadata. Same-key peer writes replace it, unknown-write reloads follow decision 15, and source deletes or truncates clear it. The storage format and public API stay compatible.
The failing CI campaign also exposed a reference-model error. The model incorrectly revived nondurable metadata when a keeping update recreated its row. The model now separates durable row existence from source metadata retained in the run. This correction follows the accepted decisions and leaves the comparisons intact.
Instrument improvements
The oracle checks source reads and durable metadata at completed action cuts. The controlled adapter records durable snapshots between queued commits, so later fix cannot hide an earlier wrong write. Recovery facts become available only after their storage read and successful application.
The native fixture serializes unrelated SQL calls, supports savepoints and active transaction reentry, and revokes reentry when the transaction ends. Its reusable conformance suite exposed and fixed a detached callback that retained an ended transaction's privileges.
Permanent controls challenge intermediate durable corruption, wrong reload reads, stale reads after cleanup, missing recovery application and empty replays. A shared recovery grammar constructs all 18 response/read/application × seed/peer/cleanup × bare/non-bare schedules. Both receiving drivers use the same independent session model and comparison.
Related work
The earlier materialization diagnosis under #2281 stays withdrawn. This new retention defect has its own failing history and fix. It does not establish a common cause with #2281's broader row-loss reports, #2317/P8 or #2298. The native witness contributes bounded evidence toward #2272. This PR closes none of those issues.
🔬 Oracle Coverage
Primary owner: packages/db/tests/sync-metadata-session-oracle.ts. The companion recovery grammar is packages/db/tests/sync-metadata-recovery-oracle.ts.
The fix record binds the final sources, both CI findings and the ORC-001–016 audit. The instrument audit preserves the earlier fixture work. The original evaluation preserves the previous review dispositions.
Law: Decisions 9/18 distinguish keeping metadata from writing it. Decision 16 retains missing-row metadata in the run. Decisions 11/15 govern named replacements and unknown-write observations. Authority: the accepted session decisions. No product law changes.
Reach: The new grammar constructs twelve cases across partial/full/on-demand lanes on both controlled storage and native SQLite. All 36 states per host reach eight times in each fixed/random campaign. Cases include keeping/explicit writes, core holds, a prior source truncate, named replacements, unknown writes and clears. Existing 108-state receiving, 18-state recovery and 40-run campaigns retain their budgets and guards.
RED: Before the production edit, all four receiving campaigns fail at the intended source-metadata comparison. Four on-demand keeping states fail, while the other 32 states pass in the reached batches. The original CI seed/path separately reproduces the model's false durable expectation.
GREEN: 1,443 relevant tests pass across the scoped commands, with 49 existing expected failures and one todo in the broad persisted owner. Both guarded seed/path replays pass with one nonzero selected execution each. Source-mapped types, formatting, scoped ESLint, changed-file oracle lint and run-budget checks pass. Scoped ESLint reports zero errors and zero warnings across the seven changed TypeScript files.
Mutant: Three isolated retention policies fail the shared source-read assertions on both hosts: original policy, retaining after named replacement, and retaining after unknown writes. The restored isolated baseline passes. Native seed 2220037/path 0 reproduces the original-policy mismatch and passes with the fix. Earlier seven fixture/checker mutations remain documented as historical calibration evidence.
Limits: One sync run, serialized authored actions, one-process native SQLite, two Browser coordinators and Node BroadcastChannel/Web Locks. Recovery schedules contain one recovery each. Arbitrary overlap, claim expiry/generation rotation, leadership/transport loss, restart, Chromium OPFS and Electron IPC remain outside the evidence. Read-hold/abandonment lacks the peer/store-held lanes' direct durable trace. The coverage map retains the owner and needed witness.
Run the new receiving campaigns from packages/db-sqlite-persistence-core:
pnpm exec vitest run tests/sync-metadata-missing-row.test.ts \
--maxWorkers=1 --coverage.enabled=false --typecheck.enabled=false
The fix record includes the original CI replay and the broader verification commands. The retained instrument suites cover controlled/native sessions, recovery, calibrations, recorder guards, native SQL conformance and deterministic write work.
The full workspace command was not run locally. The earlier 253/279-test totals and 12/8-warning totals refer to earlier revisions and scopes. The current fix results appear above.
Formal reviews cover 9eef6525d and adf6a07f9. The mutable CodeRabbit summary last covers ef5c66ed2, and automatic review remains paused. Those reviews do not cover semantic instrument commit 60ace06b or this production fix. The maintainer authorized merge with that known review limit. Final publication-head CI remains a separate merge requirement.
🚀 Release Impact
This change affects published code and includes a patch changeset for @tanstack/db-sqlite-persistence-core.
This change is docs/CI/dev-only (no release).
No protocol, stored-format, package-manifest or lockfile change accompanies this fix. Local verification uses this branch. Current-head CI must supply integration evidence against the PR base.
Snapshot accepted row metadata for durable inserts that omit explicit metadata
writes. Keep explicit metadata writes authoritative and avoid attributing the
preserved metadata to the source. Share completed-reach classification between
the controlled and native SQLite receiving drivers.
Law: Sync metadata session decisions4,5,6,8,9,14,15,18 in
docs/contributing/oracle-reviews/2026-10-22-sync-metadata-session.md, the implicit
row-metadata rules, and glossary hydration-seed contract. An inner equal
re-insert preserves accepted metadata through persistence and peer reload.
Reach: Each controlled/native host campaign completes40 histories in each of
three lanes. Fixed seed527962096 reaches2 completed bare-key1 implicit keeps
and2 completed non-bare keeps per lane, with21 named/19 fullreload notices.
RED: M01 controlled extended owner fails unchanged parent production at
seed2281001/path7:0; M06/M07 native SQLite receiving replays/property fail the
same metadata law, generated path7:0:0.
GREEN: M08/M09 paired40-run campaigns and receiving replays pass. H02 repeats
both hosts with the shared helper; H01b proves final-helper equivalence over
2304 histories/102912 comparisons. Final types/lint/format pass.
Mutant: Original durable-metadata map and always-delete rival both fail the
shared metadata comparison in controlled/native generated histories. An
all-explicit-inner grammar ablation fails the completed implicit-keep reaches.
Limits: One process/native SQLite with two production coordinators. No OPFS,
Electron IPC, transport-loss/leadership-turnover or broader2272 claim. Random
scarce reach is measured; fixed guards enforce both scarce branches. Host runs
precede only an explicit terminal undefined return, linked by exact equivalence.
It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.
Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 2 remain after this review.
Walkthrough
This change revises the sync-metadata session oracle and adds generated histories for metadata durability, seed re-insertion, reload, and queued repairs. It adds persisted-adapter and SQLite/coordinator test coverage, and updates documentation with verification results and coverage limits.
Changes: Sync Metadata Oracle and Receiving Coverage
Layer / File(s)
Summary
Define metadata rules and session histories packages/db/tests/sync-metadata-session-oracle.ts, packages/db/tests/sync-metadata-session.test.ts
The oracle distinguishes metadata retained locally from metadata written durably. It records unknown-storage observations and recovery inputs, compares durable metadata, and adds generated histories for seed reload, durability, and queued repairs. A runner test verifies that recovery input is consumed before an authored action.
Persisted-adapter campaigns cover seed re-insertion, reload, metadata durability, and queued repairs across peer lanes. The registry and replay manifest include the new properties. Write-work tests check generated-history reachability and metadata mutations after repeated refreshes.
Run SQLite-backed coordinator histories packages/db-sqlite-persistence-core/tests/sync-metadata-sqlite-driver.ts, packages/db-sqlite-persistence-core/tests/sync-metadata-sqlite-driver.test.ts, packages/db-sqlite-persistence-core/tests/sync-metadata-session-sqlite.test.ts
A SQLite driver serializes root operations and scopes nested transactions. Session tests run histories through two coordinators and compare notices, recovery inputs, and durable metadata with the oracle.
Record evidence and coverage boundaries docs/contributing/oracle-coverage.md, docs/contributing/oracle-reviews/*
The coverage guide and review records document metadata rules, campaign results, bounded receiving schedules, and excluded scenarios. They state that the earlier production diagnosis was withdrawn.
No merge-blocking issue is established for this wording update; normal checks can proceed.
Pre-merge checks: 4 · 1
Failed checks: 1 warning
Check name
Status
Explanation
Resolution
Title check
The title claims a production fix, but the supplied summaries and objectives describe test, oracle, and documentation changes with no production-source change. It does not accurately summarize the mai…
Retitle the pull request to describe the actual test, oracle, and documentation changes, or include the production implementation that the current title claims.
Passed checks: 4 passed
Check name
Status
Explanation
Docstring Coverage
Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Linked Issues check
Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check
Check skipped because no linked issues were found for this pull request.
Description check
The description includes all required template sections and provides detailed change context, oracle coverage, verification results, known limits, checklist status, and release impact.
Full details: Docstring Coverage
Explanation
Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 9 functions across 10 files. (1 skipped: 1 unsupported.)
Full details: Title check
Explanation
The title claims a production fix, but the supplied summaries and objectives describe test, oracle, and documentation changes with no production-source change. It does not accurately summarize the main changeset.
Resolution
Retitle the pull request to describe the actual test, oracle, and documentation changes, or include the production implementation that the current title claims.
Finishing Touches
Generate unit tests (beta)
Commit to this branch
Create a new PR
Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comparing 3af8447cb (this PR) against 9be51e037 (base). Write times are per-write medians over 100 iterations (20 warmup writes). Cold hydrate is one timed first load of each query.
Overall median write time vs base: 1.02× · cold hydrate time: 1.07× (geometric mean of per-case ratios; lower is faster).
Writes: No significant changes (threshold: ±20% and >0.05ms).
Cold hydrate: 3 regression(s), 1 improvement(s) (threshold: ±50% and >5ms).
Per-case flags are noisy on shared runners. Read the geometric means first.
Writes
Query
Δ median write time (geomean)
Best case
Worst case
Flags
list: newest 50 open
+2.4%
-5.8%
+13.0%
—
list + author
-0.1%
-22.9%
+9.8%
—
list + comment count
+2.8%
-4.4%
+18.0%
—
list + 3 recent comments
+2.9%
-1.1%
+11.0%
—
issue detail + comments
+1.6%
-10.7%
+6.5%
—
Cold hydrate
Query
Δ cold hydrate time (geomean)
Best case
Worst case
Flags
list: newest 50 open
+12.3%
-27.9%
+476.1%
1 🔴
list + author
+2.7%
-25.0%
+147.4%
1 🔴
list + comment count
+6.1%
-52.4%
+117.9%
1 🔴 1 🟢
list + 3 recent comments
+1.3%
-30.4%
+49.2%
—
issue detail + comments
+9.4%
-23.6%
+31.1%
—
Each row aggregates the 14.4 scale/index/write-mode configurations of that query; per-configuration tables below.
Runner: node v24.8.0, linux 7.0.0-1017-azure, AMD EPYC 7763 64-Core Processor. Timings on shared CI runners are noisy; treat small deltas as indicative only.
Law: Decisions 9 and 18 keep tab-local seed metadata separate from durable
writes. Decision 15 permits unknown-author storage observations to adopt
differing durable metadata; named current-run writes follow decision 11.
Reach: Both hosts reach all 36 constructive case/lane states eight times
per fixed and random campaign. Native recovery is reached 96 times each.
Existing 40-run campaigns and fixed completed-branch guards are preserved.
RED: No production defect is claimed on a3c4d06. The original PR diagnosis
is withdrawn. Both hosts reject the old serializer materialization at the
settled durable metadata comparison, seed 2220031, path 0:0:0.
GREEN: 74 controlled and 12 native/helper/work tests pass after extraction;
92 core tests passed before the mechanics-only extraction. Direct replay,
scoped types, formatting and lint pass (12 general ESLint warnings).
Mutant: All five controls reject the intended assertion: materialization
on each host, omitted model recovery input, dropped explicit writes and
unscoped root SQL. Temporary edits are restored byte-for-byte.
Limits: One-process native SQLite with two Browser coordinators and a
bounded correlated notice/recovery schedule. No arbitrary recovery timing,
transport/leadership loss, Chromium OPFS, Electron IPC or restart proof.
Broader #2281/#2272 and the separate #2317/P8 witness remain open.
See docs/contributing/oracle-reviews/2026-11-02-p6-metadata-closeout.md.
Preserve the published PR ancestry. The replacement tree retains main production unchanged and removes the withdrawn materialization and release note. The reviewed test/model/fixture candidate supersedes the older proposal.
KyleAMathews
changed the title
fix(persistence): preserve metadata on implicit equal re-inserts
test(persistence): separate local metadata keeps from durable writes
Nov 2, 2026
32-32: Minor · Maintainability & Code Quality · Quick win
Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.
Use precise wording for the pullSince(0) result.
real successful uses real as an adverb and makes the evidence sentence informal. Replace it with A successful \pullSince(0)` response returned row version 2 without transaction replay details.` (raw.githubusercontent.com)
Source: Linters/SAST tools
Review info
Run configuration
Source mode: Auto
Repository: Unavailable
Branch: Unavailable
File: No configuration file from this repository applied
Commit: Unavailable
Layers: defaults
Review profile: CHILL
Plan: Advanced
Run ID: 3ed59fa4-c60c-44d6-b630-04d05cc92c4b
Commits
Reviewing files that changed from the base of the PR and between ea769ec and 9eef652.
Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review.
335-335: Minor · Maintainability & Code Quality · Quick win
Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.
Clarify the transaction modifier.
The phrase two open authored transactions is ambiguous. Rewrite it as while two authored transactions remained open or use two open-authored transactions if that is the intended term.
Source: Linters/SAST tools
Review info
Run configuration
Source mode: Auto
Repository: Unavailable
Branch: Unavailable
File: No configuration file from this repository applied
Commit: Unavailable
Layers: defaults
Review profile: CHILL
Plan: Advanced
Run ID: a6979e72-dc82-4552-81c8-435843a70315
Commits
Reviewing files that changed from the base of the PR and between d0c4d0d and adf6a07.
Files skipped from review as they are similar to previous changes: 1
docs/contributing/oracle-coverage.md
Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 3 remain after this review.
KyleAMathews
changed the title
test(persistence): separate local metadata keeps from durable writes
fix(persistence): preserve run-only metadata on peer reloads
Nov 2, 2026
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
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.
🎯 Changes
This PR fixes metadata loss after a named peer notice reloads an on-demand persisted Collection. It also strengthens the session oracle and its native receiving fixtures.
An inner transaction can delete a row, then write metadata M while the row is missing. An enclosing update can later recreate that row without a metadata write. Decision 16 requires the sync run to retain M, while decisions 9 and 18 keep M nondurable. Previously, an unrelated peer notice reloaded the row and replaced M with absent stored metadata.
The wrapper now distinguishes local metadata from a named peer replacement. Known reloads retain local metadata. Same-key peer writes replace it, unknown-write reloads follow decision 15, and source deletes or truncates clear it. The storage format and public API stay compatible.
The failing CI campaign also exposed a reference-model error. The model incorrectly revived nondurable metadata when a keeping update recreated its row. The model now separates durable row existence from source metadata retained in the run. This correction follows the accepted decisions and leaves the comparisons intact.
Instrument improvements
The oracle checks source reads and durable metadata at completed action cuts. The controlled adapter records durable snapshots between queued commits, so later fix cannot hide an earlier wrong write. Recovery facts become available only after their storage read and successful application.
The native fixture serializes unrelated SQL calls, supports savepoints and active transaction reentry, and revokes reentry when the transaction ends. Its reusable conformance suite exposed and fixed a detached callback that retained an ended transaction's privileges.
Permanent controls challenge intermediate durable corruption, wrong reload reads, stale reads after cleanup, missing recovery application and empty replays. A shared recovery grammar constructs all 18 response/read/application × seed/peer/cleanup × bare/non-bare schedules. Both receiving drivers use the same independent session model and comparison.
Related work
The earlier materialization diagnosis under #2281 stays withdrawn. This new retention defect has its own failing history and fix. It does not establish a common cause with #2281's broader row-loss reports, #2317/P8 or #2298. The native witness contributes bounded evidence toward #2272. This PR closes none of those issues.
🔬 Oracle Coverage
Primary owner:
packages/db/tests/sync-metadata-session-oracle.ts. The companion recovery grammar ispackages/db/tests/sync-metadata-recovery-oracle.ts.The fix record binds the final sources, both CI findings and the ORC-001–016 audit. The instrument audit preserves the earlier fixture work. The original evaluation preserves the previous review dispositions.
Run the new receiving campaigns from
packages/db-sqlite-persistence-core:pnpm exec vitest run tests/sync-metadata-missing-row.test.ts \ --maxWorkers=1 --coverage.enabled=false --typecheck.enabled=falseReplay the native sibling directly:
The fix record includes the original CI replay and the broader verification commands. The retained instrument suites cover controlled/native sessions, recovery, calibrations, recorder guards, native SQL conformance and deterministic write work.
✅ Checklist
pnpm test.The full workspace command was not run locally. The earlier 253/279-test totals and 12/8-warning totals refer to earlier revisions and scopes. The current fix results appear above.
Formal reviews cover
9eef6525dandadf6a07f9. The mutable CodeRabbit summary last coversef5c66ed2, and automatic review remains paused. Those reviews do not cover semantic instrument commit60ace06bor this production fix. The maintainer authorized merge with that known review limit. Final publication-head CI remains a separate merge requirement.🚀 Release Impact
@tanstack/db-sqlite-persistence-core.No protocol, stored-format, package-manifest or lockfile change accompanies this fix. Local verification uses this branch. Current-head CI must supply integration evidence against the PR base.