TanStack

Content temporarily unavailable

Pooled live query and flat change tracking oracle review

Reviewed state and claim

Base: 84b828c7e, merged with origin/main at 18abceee4. This record reviews the Git tree that contains it; the final commit or pull request identifies that tree.

The pooled live query oracle claims that a live query filtered only by eq(field, literal) on one eager, non-persisted source, served from an equality partition, publishes what its live-query Collection would: the same rows in key order, values, and status. That holds through sync transactions, optimistic writes confirmed or rolled back, peer mounts and unmounts, and source cleanup and restart. The claim excludes on-demand and persisted sources, DbClient hydration, Suspense, and every clause beyond eq conjuncts, which keep the live-query Collection.

The flat change tracking oracle claims that, for a row whose own fields are all primitives or functions with a plain or null prototype and no symbol keys, the flat tracker reports the same change set as the draft proxy and an independent model, with 0 and -0 equal. Nested values, Dates, Maps, Sets, class instances, and symbol keys are outside it, except that they must fall back to the proxy.

Both oracles use mockSyncCollectionOptions or plain rows; neither claims a real sync adapter's behavior.

RED and GREEN evidence

Mutants ran through each oracle file alone on the reviewed tree. Each file was restored after each run. Every outcome below is an assertion failure.

MutantOracleTests failed
Partition ignores a row's previous groupPooled6 of 9
Groups keep rows in arrival orderPooled3 of 9
Literals and fields compared without eq normalizationPooled4 of 9
Partition skips the source's initial statePooled8 of 9
View reports the source's status after cleanupPooled4 of 9
Partition never terminates on cleanupPooled4 of 9
Partition keys groups by the first field onlyPooled5 of 9
Update published as delete then insertPooled3 of 9 (0 of 7 before payload checks)
Update carries a stale previousValuePooled3 of 9 (0 of 7 before)
Update carries the old row as its valuePooled3 of 9 (0 of 7 before)
Within-group updates droppedPooled3 of 9
Partition built on a cleaned-up source starts terminalPooled3 of 9 (0 of 7 before)
Frozen peers drop pending optimistic rowsPooled3 of 9 (0 of 7 before)
Flat diff with !==Flat3 of 17
Flat diff with Object.is aloneFlat3 of 17
Flat diff without deletionsFlat5 of 17
Draft proxy without the added-field revert fixFlatpinned history and both campaigns
Flat diff ignores whether the row owns a fieldFlat4 of 17
Flat drafts edit the rows in placeFlat9 of 17
Assigned objects not detachedFlat1 of 17 (detach witness)
Frozen rows sent to the proxyFlat3 of 17
Proxy ignores accessors defined in the callbackFlat3 of 17
Proxy reports a field defined back to its own valueFlat4 of 17
Proxy accepts a getter-only field's own valueFlat3 of 17
Proxy reports a written hidden field's deleteFlat3 of 17
Flat compares a hidden object field by identityFlat3 of 17

Every pooled and flat mutant above fails its pinned history and both campaigns. The pooled grammar delivers initial rows in key order or in reverse and weights a pending insert most peers see before cleanup; the flat grammar weights runs that write and delete a hidden field, write an equal object over a hidden object field, assign a getter-only field its own value, and write the opposite-signed zero over each zero field. Before that weighting, arrival order and frozen optimistic rows escaped about one random campaign in three, and the three descriptor mutants escaped both campaigns. The Object.is-alone flat mutant escaped about one random campaign in two until the zero-flip run.

The pooled oracle found that a pooled view followed its source's status after cleanup instead of entering the live query's terminal error; the repair makes the partition terminate. The flat oracle found that the draft proxy dropped a field added as undefined when another field reverted, on main as well; the repair treats a field the original lacks as changed. The grammar now weights that run, so both campaigns also kill the unrepaired proxy.

The loss audit then widened both oracles. The pooled granular observer had been checked by key membership only, so the payload and lifecycle mutants marked "0 of 7 before" survived it. The flat grammar gained frozen rows, non-enumerable fields, accessor and data defineProperty, stored drafts, and throwing callbacks. Four shapes split the trackers, three of them on main's proxy too. The adopted rule is that defining a field acts as assigning it, and that a non-enumerable field is row data only once the callback writes it. The proxy now records accessors and data defines through the assignment path, rejects a getter-only write of its own value, and ignores the delete of a hidden field it wrote. The flat tracker now compares a hidden object field by contents.

Local-only direct writes are compared with a local-only Collection whose handlers resolve, across mixed multi-key batches, failing batches, schema rejection, and every fallback for insert, update, and delete. Mutants that ignore handler types, drop the pending or persisting check, drop the whole transaction check, run before the ambient branch, write only the first mutation, or never complete the transaction fail 4, 4, 4, 8, 12, 1, and 9 tests.

Two shared conformance scenarios, eq-filter-rows and eq-filter-peers, run the pooled path under React, Vue, Solid, Svelte, and Angular. A partition that ignores a row's previous group fails both under every adapter. eq-filter-peers also checks the source's public subscriberCount: an adapter that declares pooledEqFilters must share one subscription for two queries on the same fields. Disabling pooling or using one partition per query fails it under React; before this check the first passed. Each adapter's driver declares pooledEqFilters.

The loss audit found that a partition released its source one second after its last listener, whatever gcTime its views had. A focused release-timing test, pooled-live-query-gc.test.ts, now compares pooled and live-query Collection release times. A fixed delay failed 5 of 10 cases, a missing 50 ms floor for unsubscribed queries 1, a last-gcTime-wins rule 1, and releasing at gcTime 0 2. Release timing is resource lifetime, so the publication oracle does not observe it.

Pooling later admitted residual conjuncts: any where conjunct that reads only the query's own row, beside at least one eq, is evaluated per view with the compiler's evaluator. Peers may add not(eq(g, literal)), which the model evaluates itself, and a pinned history moves rows in and out of a view within one group. A view that ignores the residual, reports unfiltered entries, or sends a row entering or leaving it as an update fails the pinned history and both campaigns. Hiding part of a group makes some earlier histories rarer, so in one full run the arrival-order, normalization, delete-plus-insert, and dropped in-group update mutants escaped the random campaign; the fixed campaign and their pinned histories still kill each. Peers' literals were weighted toward the normalized values to keep the normalization mutant in the fixed campaign.

Pooled live query oracle

RequirementOutcome
ORC-001 Contract authority and limitsPass. The eq operand rules come from src/query/compiler/evaluators.ts; the pooled boundary and the terminal-error rule come from the live-query architecture document's pooled section and cleanup law. The opening prose lists the omissions.
ORC-002 Independent judgmentPass. expectedKeys uses a local eq over plain values. Order, values, and status come from a live-query Collection, which compiles a D2 pipeline and does not use the partition.
ORC-003 Distinguishable responsibilitiesPass. Contract, model, grammar, driver, and refinement check are separate marked sections.
ORC-004 Generated-history controlsPass. Reconstruction: every pinned history uses only domain values and step kinds. Ablation, run per axis on the campaigns with pinned cases skipped: without Dates, NaN, and -0 the normalization mutant survives; without optimistic steps, frozen peers dropping optimistic rows survives; without mounts and unmounts, the terminal-at-creation mutant survives; without cleanup-restart, the status, termination, and both pending-cleanup mutants survive; without the second conjunct, first-field grouping survives. Range: at most four rows, three peers, eight steps, and ids 0 through 3; field values weight toward the literal so rows update within their group. Exclusion: an optimistic update to an equal value, an insert of an existing id, and an update or delete of a missing id are dropped.
ORC-005 Production path and observationPass. createPooledLiveQuery and createLiveQueryObserver, the adapter seam, run in wholesale and granular mode; the conformance scenarios run through React's useLiveQuery. Rows, keyed state, status, layout revision, and non-materialization are observed after every step, and granular changes are compared with a reference observer by type, key, value, and previous value, then replayed against the model.
ORC-006 Checker calibrationPass. Thirteen mutants, classified above.
ORC-007 Fixed/random replayPass. Fixed seed 44_502_001, an unseeded campaign, and a replay entry share one property and budget; the file is in test:oracles.
ORC-008 Stateful-model minimalityPass. The model keeps source rows and, per mounted peer, the frozen keys at cleanup. The pinned cleanup history distinguishes a frozen peer from one mounted after the restart.
ORC-009 Vocabulary mappingPass. Equality partition, partition group, and pooled live query are glossary terms; a peer is one mounted pooled live query.
ORC-010 Failure fidelity and cleanupPass. withOracleCleanup releases observers, references, and the source and keeps the check failure.
ORC-011 Independent second formulationPass. The live-query Collection is the second formulation for order, values, and status.
ORC-012 Review evidenceThis record; the coverage map links it.
ORC-013 Reusable boundary lawPass. Normalization is rejected by the Date history, arrival order by the key-order history, and following the source's status by the cleanup history.
ORC-014 Controlled-premise handoffNot triggered. The claim is limited to the mock source's sync transactions and lifecycle.

Flat change tracking oracle

RequirementOutcome
ORC-001 Contract authority and limitsPass. The change-set rules come from src/proxy.ts's getChanges contract: changed fields with their final value and deleted fields as undefined.
ORC-002 Independent judgmentPass. expectedChanges folds the operations over a plain copy and does not import either tracker.
ORC-003 Distinguishable responsibilitiesPass. Contract, model, grammar, driver, and refinement check are separate marked sections.
ORC-004 Generated-history controlsPass. Reconstruction: every pinned history uses domain values and operations. Ablation: removing NaN, -0, reverts, or deletions each loses a mutant. Range: one to three rows, three fields plus one added and one non-enumerable field, frozen or not, up to six operations per row including data and accessor defines, stored drafts, and a throw. Exclusion: none in generation; non-flat rows are rejected by the fallback witness.
ORC-005 Production path and observationPass. withFlatChangeTracking, withArrayChangeTracking, and withChangeTracking run the same callbacks; the result change sets are observed. collection.update selects between them.
ORC-006 Checker calibrationPass. Thirteen mutants, classified above.
ORC-007 Fixed/random replayPass. Fixed seed 44_502_101, an unseeded campaign, and a replay entry; the file is in test:oracles.
ORC-008 Stateful-model minimalityNot triggered. The model recomputes from the operations.
ORC-009 Vocabulary mappingPass. Draft, change set, and revert follow the proxy's terms.
ORC-010 Failure fidelity and cleanupNot triggered. The oracle holds no resources.
ORC-011 Independent second formulationPass. The draft proxy is the second formulation.
ORC-012 Review evidenceThis record; the coverage map links it.
ORC-013 Reusable boundary lawPass. !== is rejected by the NaN history, Object.is by the -0 history, and missing deletions by the deleted-field history.
ORC-014 Controlled-premise handoffNot triggered. No provider is involved.

Open work

  • Svelte's suite reads @tanstack/db from its built dist, so a mutant must type-check and be rebuilt before Svelte can observe it.