Skip to content

fix(vault): a restore settles the reconcile record against the restored bare tables (T13324) - #1982

Merged
kryptobaseddev merged 3 commits into
mainfrom
feat/T13324-carry-bare-accounts
Oct 11, 2026
Merged

kryptobaseddev merged 3 commits into
mainfrom
feat/T13324-carry-bare-accounts

Conversation

@kryptobaseddev

Copy link
Copy Markdown
Owner

Task: T13324 (epic T12323). Stacked on #1980 (T13309). It gets no CI until it is retargeted to main once #1980 merges.

Problem

The store records which bare tables a reconcile carried in _exodus_recovery_bare_accounts (T13320). That table is local-only, and so are the bare legacy tables themselves (tasks, sessions, ...).

On a vault pull, carryMachineState replaced the record with this machine's copy, usually none, while the twins came from the reconciled device. A second device pulling a store whose carried twin rows were later deleted was therefore refused as a strand (E_SYNC_LEGACY_ONLY_STORE).

Change

  • SNAPSHOT_STATE_TABLES (table-classification.ts): a new list of local-only tables that record facts about other rows in the same file. Carry skips them, the same way it skips schema-state tables.
  • settleRestoredBareAccounts (sync/flags.ts) runs at the end of carry, after the bare tables have become this machine's. For each bare table it keeps the first record that still matches that table by row count and key digest, checking the snapshot's record first and then this machine's from before the restore. A record that neither side matches is dropped, so those rows are judged again.
    • On a new machine there are no bare rows, so the record goes and nothing is stranded.
  • Never synced. The table stays local-only and out of the manifest. Bundle export and import already carry it whole, so neither path changes.

A correction to the task premise

The task text says the bare tables "travel in the bundle". They do, but they are classified local-only, so carry replaces them with this machine's on a pull and empties them on a new machine. That is why the record is settled against the bare tables as restored, not just kept as the snapshot had it.

Tests

  • vault-manifest.test.ts:
    • a pull keeps the snapshot's record when this machine's bare table matches it;
    • otherwise it keeps this machine's record;
    • a record whose digest matches neither side is dropped and the strand returns;
    • on a new machine the record is dropped and nothing is stranded;
    • every SNAPSHOT_STATE_TABLES entry is local-only and not in the manifest.
  • nexus-vault.test.ts (fake server, two devices):
    • B holds the project's bare rows and is refused;
    • A reconciles (carries T8 and T9, T9 is deleted since, the run is recorded) and pushes;
    • B pulls, keeps its own bare rows, takes A's record, verifies match, and enables sync.capture without being refused.
  • Falsifier: with the carry change reverted, the e2e test and the two pull tests fail.
  • Not covered: the JOIN step (enableSyncPush / joinStream) only exists in feat(sync): a restored store joins a journaled stream; two-device sync end to end (T13312) #1967, which is still open. The test enables sync with setSyncFlag, which is where the strand refusal lives. A JOIN assertion follows once feat(sync): a restored store joins a journaled stream; two-device sync end to end (T13312) #1967 lands.

Verification (head 468c2f2)

  • pnpm run typecheck and build: clean.
  • Biome: clean.
  • Five affected test files: 295 passed, 2 skipped.
  • Gate 39: passes.
  • Gates 28, 37, 4, 32 and 38 (the last two with --base origin/main): OK.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VjjTKbQXyCFdkLBSeuyKLt

kryptobaseddev and others added 2 commits October 9, 2026 21:18
… restored bare tables

The record of carried bare tables (_exodus_recovery_bare_accounts) is
local-only, so a vault pull replaced it with this machine's (usually none)
while the twins came from the reconciled device, and the pulled store was
refused as a strand. Carry now leaves it out (SNAPSHOT_STATE_TABLES) and,
once the bare tables are this machine's, keeps per bare table the record
(the snapshot's, else this machine's) that still matches by row count and
key digest, dropping one neither matches. It never syncs; bundles already
carry it whole.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjjTKbQXyCFdkLBSeuyKLt
Base automatically changed from fix/T13309-reconcile-partial-strands to main October 10, 2026 05:54
…e-accounts

# Conflicts:
#	packages/core/src/cloud/__tests__/nexus-vault.test.ts
@kryptobaseddev
kryptobaseddev merged commit 96a9060 into main Oct 11, 2026
103 checks passed
@kryptobaseddev
kryptobaseddev deleted the feat/T13324-carry-bare-accounts branch October 11, 2026 15:03
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.

1 participant