Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/solid-row-snapshot-isolation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@tanstack/solid-db': patch
'@tanstack/db': patch
---

Preserve Collection rows and mutation originals while Solid `useLiveQuery` updates, including nested values, live getters, callable fields, and explicit undefined fields. Keep unchanged nested elements stable and avoid repeated expansion of shared acyclic values.

Preserve enumerable own source fields through Core query selection, including user symbols and inherited-name shadows. Build nested projections without changing borrowed source data or retaining fields the authored object replaces.
149 changes: 149 additions & 0 deletions docs/contributing/oracle-coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -6230,6 +6230,155 @@ bundle erasure, Typedoc generation, tooling GREEN and restored-old-tooling
mutants remain required receiving checks. Generated docs remain CI-owned.


### Framework row snapshot isolation

The **Frameworks** owner judges preservation of borrowed Collection values at
actual framework boundaries. Authority is immutable updates,
`PendingMutation.original`, `ChangeMessage.previousValue`, and the shared
`packages/db/tests/conformance/contract.ts` result law. The shared executable
owner is `packages/db/tests/conformance/row-snapshot-oracle.ts`. Core supplies
admitted source facts before materialization. This relational comparison judges
adapter preservation, not Core draft normalization or prototype policy.

Nine common shapes cross one/two keys, callback/config/supplied Collection
inputs, and sync/optimistic writes: 108 histories per common driver. Solid adds
native stores for 120 histories, plus 60 real local-only histories. React has two
registrations of its derived-identity API, labelled `react` and
`react (dependency list)`; neither is a DbClient receiving driver. Two-key
histories share initial containers and alternate updates. Actual mutable sharing
is asserted before crediting cross-row alias reach: eight common histories and
nine Solid histories per group. The later-object shape starts at null and gets
no mutable-alias credit. Three updates per key distinguish initial and later
admissions, alias split/merge, hidden string data, inherited-name shadows, and
own-undefined/omission. The grammar contains 828 history slots across 45 group tests, including the
duplicate React API registration.

Every receiving group asserts its own reach. The shared comparison checks
complete current framework and source values, retained initial `get()` and
admitted `change.value` references, `previousValue`, and actual transaction
`original` references at every existing cut. Optimistic handlers also have a
held cut. Three isolated source-corruption controls reject damage limited to
current, initial, or newly admitted values. A real Solid fault injection is
rejected at the current-source comparison, even when its detached output is
correct. The local-only driver returns actual mutation receipts.
Alternative legal source-shape policy is accepted. Original-only corruption and
cross-row caching mutants distinguish the extended owner from its predecessor.

Solid's separate receiving owner,
`packages/solid-db/tests/row-materialization-oracle.test.tsx`, judges nested
identity, binding lifetime, current array membership, live nested getters, and
bounded shared-graph work. Its original 85 finite histories include real `For` and effect
consumers, native-store-only writes, reorder, growth/shrink/empty arrays, getter
admission/replacement/omission/readmission, and crossed old/new graph sharing.
The maintainer chose live getters and efficient shared acyclic graphs on
2026-10-30, with cyclic support decided separately. Work counts source and owned
container enumerations against an unchanged 32-per-distinct-container budget.
This is a bounded regression check, not a public SLO or a complexity proof.

The native-store revision skips unchanged source rows and memoizes immutable,
detached nested stores by source identity within each row. Solid setters update
the ordinary stable root row and replace changed nested containers. Consumers
must read the current nested path reactively: a captured old nested proxy does
not follow replacement. Native stores supply getter tracking and notifications.
Explicit root own-key admission handles inherited-name and own-undefined cases.
The complete graph comparison checks mixed paths without imposing alias identity.
Twelve additional controlled-helper histories vary descriptor visibility for
undefined, null, scalar, object, array, and native-store payloads. They observe
captured-root `Object.keys` consumers across unchanged, hidden, visible, and
restored-visibility stages while retaining payload and root identity. The raw/proxy
identity guard fails six container histories before repair. These histories
test only the materializer's internal invariant. Core public row snapshots
normalize root descriptors, so no public descriptor-admission claim follows.
Valid derived array-wrapper prototypes retain source methods, and local-only
original reach requires a nonempty actual receipt. See the
[native revision review](oracle-reviews/2026-10-30-solid-native-store-review.md)
and the historical [materialization](oracle-reviews/2026-10-30-solid-row-materialization-review.md)
and [snapshot](oracle-reviews/2026-10-30-solid-row-snapshot-isolation.md) records.

**Core source-field and destination preservation:** the maintainer authorized
fixing the sibling Core boundary in this PR. The existing context-transport
owner now imports its public-field model/grammar from
`packages/db/tests/conformance/public-field-oracle.ts`. Sixty histories cross
six source keys, root/nested location, four selection forms, five stages, and
ordinary/inherited nested destinations. Root Collection and three correlated
forms supply 1,200 path/stage observations; the original 819 observations remain.
The source admission check precedes result comparisons. Five restored wrong
merge/destination designs fail intended own-field assertions. Real framework
callback/config receivers reuse the same models and comparison for twelve
new destination cells per input. Fourteen groups across seven registrations
supply 168 histories / 840 comparisons. Core creates own enumerable data fields
and own destination containers; unsafe authored alias paths retain rejection.
The final [review record](oracle-reviews/2026-10-30-solid-native-store-review.md)
records RED, GREEN, mutant classifications, reviewer outcomes, and exact code.

The second independent review extends the same public-field owner with thirty
overlap cells. Twenty-four legal expression cells reach every framework input;
six functional controls supply a second Core formulation. A prior outer spread
borrows the destination before a nested spread, literal field, or dotted alias
writes it. Ordinary, inherited-name, and deeper destinations cross writable
configurable/nonconfigurable source data. Authored nested objects replace their
field; dotted aliases preserve siblings without writing through source objects.
The four Core paths supply 120 path histories and 360 result cuts. Fourteen real
framework groups supply another 336 histories and 1,008 result cuts. All compare
current and retained source rows and require the actual source descriptor at
all three stages. Existing 819 and 1,200 observations and the earlier receiving
histories remain. Unkeyed functional projections are not legal derived-identity
framework inputs, so they receive no framework handoff credit. Legal fresh-object
expression controls provide those neighboring receiving comparisons instead.
See the [second review record](oracle-reviews/2026-10-30-solid-oracle-review-round-two.md)
for complete intake, RED gates, GREEN, hostile variants, and bounded closure.

The same review adds six ordinary/subclass-array overlap cells. Dotted writes
select lengths zero, one, and two while current and retained source arrays keep
length three. Core now has 36 overlap cells / 144 path histories / 432 selected
cuts. The fourteen real receiving groups each run thirty cells: 420 histories
and 1,260 selected cuts. Each history independently requires all twelve declared
checkpoints. Post-admission mount errors are recorded and later stages retry
mounting; they cannot escape the shared comparison or supply false reach.

Solid adds 93 actual receiving histories to its original 85: 24 native-parent
identity transitions, 33 tracked callable data/getter histories, eighteen
reserved-field histories, and eighteen inherited array-method histories. All
three public inputs supply their own source admission and tracked consumers.
The reorder comparison now checks complete current/rendered values and every
element identity. A canonical backing-node memo preserves unchanged children
across ordinary/native parent changes; a read facade retains live accessors and
prototype methods while native nodes/setters supply updates. Original-code,
missing-node, accessor/method, and reordered-tail mutants distinguish these
repairs. No output alias topology or public elapsed-time budget is imposed.

The local-only draft driver does not claim top-level symbol-write admission.
Its shared preservation comparison still checks every field actually admitted,
including nested symbols and all actual mutation originals. The proxy-revert
owner excludes top-level symbol writes explicitly; **Drafts and native values**
and [#1820](https://github.com/TanStack/db/issues/1820) own that support decision.
The minimal trace assigns a fresh enumerable root symbol and nested symbol
through `Collection.update`: the root is absent from the modified/source row,
the nested symbol survives. Current and clean-main traces agree. Initial data
admits both. No adapter or Core-selection claim extends through this missing
source premise.

Limits: the stated finite histories and real hosts' settled/held-handler cuts.
Core normalization, arbitrary cycles, arbitrary getter/setter bodies, hidden
symbols, all descriptor-visibility notification combinations, callback atomicity,
other settlement schedules, and real browser rendering are not established.
Core may evaluate root getters before the adapter receives them. The live
getter claim covers nested accessors actually admitted to Solid. Cycle policy
remains a separate maintainer decision, as explicitly requested. Existing
framework, includes, and optimistic-history owners retain other responsibilities.

The **Drafts and native values** owner retains an unresolved Core boundary:
assigning a native Solid store through `Collection.update` can promote hidden
host bookkeeping symbols during Core detachment. Support policy for that
host-proxy assignment needs a maintainer decision before classification as a
product-law violation. The needed receiving witness is actual `createStore`
into `Collection.update`, distinguishing user keys from wrapper metadata in
stored and retained values. Local-only histories use ordinary replacements
after initial admission. Controlled sync histories admit native stores on
every update and cover direct adapter input.



### Distinct collision review extension (2026-10-30)

The existing distinct incrementalization owner now also generates four unequal
Expand Down
Loading
Loading