diff --git a/AGENTS.md b/AGENTS.md index 291016d97d..501260520a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,11 +32,11 @@ Read these stable entry points before the narrower owner: required above. - For Collection mutation admission, subscription ownership, replay, publication, or disposal, read - `packages/db/tests/collection-subscription-lifecycle-grammar.ts`. + `packages/db/tests/collection-subscription-lifecycle-grammar-oracle.ts`. - For optimistic snapshots and settlement, read `packages/db/tests/optimistic-history-oracle.ts`. - For opaque cursor pagination, read - `packages/query-db-collection/tests/cursor-pagination/model.ts`. + `packages/query-db-collection/tests/cursor-pagination/model-oracle.ts`. - For TrailBase lifecycle work, read `packages/trailbase-db-collection/tests/ORACLE.md`. - For cross-framework behavior, read the shared contract under @@ -509,6 +509,21 @@ oracle fails without the fix and passes with it. Keep valuable unit tests, but do not treat them as a substitute for applicable oracle coverage. If an oracle is not practical for the behavior, explain why a focused test is sufficient. +### Name Oracle Files for Discovery + +Include `oracle` in filenames that own an independent reference computation, +state model, differential or metamorphic comparison, or reusable law checker. +Modules that define the model, checker, or its history grammar also qualify. +Identify the actual mechanism before renaming a file. A coverage-map entry, +contract comment, or collection of fixed assertions is not sufficient evidence. + +Ordinary example tests, type assertions, fixtures, registration wrappers, and +runner utilities keep their ordinary names. A module that only drives production +or records observations is not an oracle definition. Report oracle owners and +definitions separately from supporting files; a file count is not an oracle count. +Preserve runner suffixes and update imports, commands, replay selectors, and +current documentation whenever an oracle file moves. + ### Name Tests After Behavior Test names should state the behavior they prove. Do not put issue or pull diff --git a/docs/contributing/glossary.md b/docs/contributing/glossary.md index c7012c5eb6..5d36345438 100644 --- a/docs/contributing/glossary.md +++ b/docs/contributing/glossary.md @@ -20,7 +20,7 @@ production queues, caches, or semantic helpers merely to share their names. | source Collection | A Collection read by a query or adapter. | Source relation when the value is a public Collection. | | live-query Collection | A Collection whose rows are produced by a live query. | Query, observer, or result set. | | pooled live query | A live query on one source Collection whose `where` has at least one `eq(field, literal)` conjunct and otherwise reads only the row, optionally ordered by the row's own fields without a limit, served from an equality partition; its live-query Collection is built only when read. | Cached query or shared live-query Collection. | -| equality partition | Source rows grouped by the `eq`-normalized values of one set of fields, shared by every pooled live query that filters on those fields. | Index or bucket relation. | +| equality partition | Source rows grouped by the `eq`-normalized values of one set of fields, shared by pooled live queries on the same source Collection with the same equality fields and order terms, including resolved comparison options. | Index or bucket relation. | | partition group | The rows of an equality partition whose fields equal one tuple of literals. | Bucket or active bucket. | | relation | An internal weighted multiset maintained by D2. | Collection. | | row | One keyed public Collection value or one relation value. Qualify source row, relation row, or public row when more than one kind appears. | Event or transaction. | @@ -57,8 +57,10 @@ and a provider-qualified `provider session` for a remote lifecycle. | Term | Meaning | | --- | --- | -| `deletion-pending` | The mutation function fulfilled; only acknowledged outbox deletion remains before caller success. A restart must not call the mutation function again. | -| `rejection-pending` | The mutation function failed permanently; the caller rejects with that failure. A restart removes the marked row without calling the mutation function again or restoring its optimistic state. | +| offline executor restart | Replacing an executor with a fresh one over retained durable outbox state. This does not restart a Collection sync run. | +| outbox replay | Resuming unfinished durable offline transaction work, including outbox reconciliation and permitted mutation execution or terminal-phase deletion. This is separate from truncate replay and oracle replay. | +| `deletion-pending` | The mutation function fulfilled; only acknowledged outbox deletion remains before caller success. An offline executor restart must not call the mutation function again. | +| `rejection-pending` | The mutation function failed permanently; the caller rejects with that failure. An offline executor restart removes the marked row without calling the mutation function again or restoring its optimistic state. | ## Demand and pagination terms @@ -130,6 +132,17 @@ See for bucket relations, bucket values, arrangements, reductions, and the normative materialization laws. +## Value comparison terms + +Equality depends on the declared comparison domain. Qualify the term when +crossing subsystem boundaries; these comparisons are not interchangeable. + +| Term | Meaning | +| --- | --- | +| D2 value identity | The value domain compared by `hash` and `equalHashValues`, including their documented reference leaves. A matching hash digest alone does not establish identity. The [identity oracle](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/hash-identity-oracle.property.test.ts) defines its bounded value rules. Map/Set insertion-order sensitivity is pinned current behavior, not a universal D2 operator contract. | +| change-event equality | The `deepEquals` comparison used for Collection change-event suppression. Its supported domain ignores Map/Set insertion order, RegExp `lastIndex`, and array holes versus `undefined`. The [change-event equality oracle](https://github.com/TanStack/db/blob/main/packages/db/tests/utils-oracle.property.test.ts) defines its value-class rules. | +| draft equality | The comparison that recognizes a reverted draft value. Its [revert oracle](https://github.com/TanStack/db/blob/main/packages/db/tests/proxy-revert-oracle.property.test.ts) preserves Map/Set insertion order, RegExp `lastIndex`, and array holes, with explicit snapshot rules for class instances. Native mutator methods have separate change-tracking laws. | + ## Oracle and model terms | Term | Meaning | diff --git a/docs/contributing/oracle-coverage.md b/docs/contributing/oracle-coverage.md index 35f8e3302c..d0e3fbbb92 100644 --- a/docs/contributing/oracle-coverage.md +++ b/docs/contributing/oracle-coverage.md @@ -107,7 +107,7 @@ passing type assertions do not prove runtime parsing, I/O, or publication. The shared-driver fairness owner now distinguishes K=1 from K=2 at the second hydrate and checks full logical persist FIFO order in its Node seam. The -[Chromium OPFS receiving spec](https://github.com/TanStack/db/blob/main/packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness.opfs.spec.ts) +[Chromium OPFS receiving spec](https://github.com/TanStack/db/blob/main/packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness-oracle.opfs.spec.ts) checks a cold SQL read, the K=1 hydrate bound, public rows, the pending persist backlog at the second hydrate, and all five logical persist completion IDs in FIFO order during one held-BEGIN storm through the real worker. This closes the @@ -165,11 +165,11 @@ accepting, rejecting, and absent outer predicates; a materialized-Collection formulation supplies matching and nonmatching controls. Other `singleResult` forms, join forms, and scheduling cuts remain outside these owners. -The offline scheduler owner (`packages/offline-transactions/tests/KeyScheduler.property.test.ts`) +The offline scheduler owner (`packages/offline-transactions/tests/KeyScheduler-oracle.property.test.ts`) checks FIFO eligibility and retry order at the scheduler boundary. It does not observe the executor's awaited outbox update between `updateTransaction` and `markFailed`, or public caller settlement. Those receiving cuts belong with -`packages/offline-transactions/tests/transaction-settlement.property.test.ts`. +`packages/offline-transactions/tests/transaction-settlement-oracle.property.test.ts`. The transaction serializer owner uses controlled Temporal constructors and fake storage; a claim about native Temporal or browser storage needs a receiving witness in those runtimes. @@ -217,7 +217,7 @@ does not award oracle credit for a filename alone. | PR | Classification | Permanent authority and campaign | | ------------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [#1831](https://github.com/TanStack/db/pull/1831) | Explicit oracle | PowerSync's `packages/powersync-db-collection/tests/correctness-oracle.test.ts` crosses real PowerSync receipts and native SQLite behavior. It runs in the package test campaign and the focused `test:oracles` campaign; portable declarations retain compiler authority. | -| [#1832](https://github.com/TanStack/db/pull/1832) | Equivalent specialized authority | `packages/electric-db-collection/e2e/sql-predicate-semantics.e2e.test.ts` and `packages/electric-db-collection/e2e/subset-sql-acceptance.e2e.test.ts` run through the package's real-provider `test:e2e` campaign. Compiler unit tests are collateral, not substitutes for either service boundary. | +| [#1832](https://github.com/TanStack/db/pull/1832) | Equivalent specialized authority | `packages/electric-db-collection/e2e/sql-predicate-semantics-oracle.e2e.test.ts` and `packages/electric-db-collection/e2e/subset-sql-acceptance.e2e.test.ts` run through the package's real-provider `test:e2e` campaign. Compiler unit tests are collateral, not substitutes for either service boundary. | | [#1833](https://github.com/TanStack/db/pull/1833) | Explicit oracle | `packages/db/tests/query/pagination-oracle.property.test.ts` owns inherited collection collation, actual `item2`/`item10` order, exact request options, hostile lexical/numeric controls, and both scan and auto-index paths. It runs in `@tanstack/db`'s `test:oracles` campaign. | | [#1834](https://github.com/TanStack/db/pull/1834) | Explicit oracle | `packages/db/tests/query/cold-join-reconciliation-oracle.test.ts` owns join/predicate equality equivalence across the established value domains, binary/string and nullish controls, replacement histories, raw lazy demand, and scan/auto-index paths. It runs in `@tanstack/db`'s `test:oracles` campaign. | | [#1835](https://github.com/TanStack/db/pull/1835) | Explicit oracle | The existing `packages/db/tests/collection-state-retention-oracle.property.test.ts` and `packages/db/tests/optimistic-transaction-oracle.property.test.ts` owners cover separate collection-state and transaction-history laws. Both were already registered in `@tanstack/db`'s `test:oracles` campaign; focused storage/local-only tests remain collateral. | @@ -239,15 +239,15 @@ comment and the current API/architecture contract before extending its model. | Surface | Primary executable owners | Independent judgment and important limit | | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Ordered relations and BTree | [top-K relation oracle](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/operators/topk-relation-oracle.test.ts), [fractional-index window moves](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/operators/topKWithFractionalIndex.test.ts), [BTree/Map](https://github.com/TanStack/db/blob/main/packages/db/tests/btree-map-oracle.test.ts), [incrementalization laws](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/incrementalization-law.property.test.ts) | Independent ordered relations and cumulative signed output. Top-K consolidation compares same-key values without hashing, including cyclic replacements and fresh transient cancellation. The fractional-index test checks an empty output message for a window move after all rows retract; it does not prove downstream lazy acquisition. Other hash-based operators retain hashing's declared domain. Algebra does not specify client readiness. The BTree/Map oracle checks point operations, neighbor pairs, and full, partial, boundary, exclusive-high, and empty range scans for integer keys and node sizes 4–8. It does not check balance or space, and it assumes consistent comparators ([code-weight BTree review](oracle-reviews/code-weight-btree-trim.md)). | +| Ordered relations and BTree | [top-K relation oracle](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/operators/topk-relation-oracle.test.ts), [fractional-index window moves](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/operators/topKWithFractionalIndex-oracle.test.ts), [BTree/Map](https://github.com/TanStack/db/blob/main/packages/db/tests/btree-map-oracle.test.ts), [incrementalization laws](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/incrementalization-law-oracle.property.test.ts) | Independent ordered relations and cumulative signed output. Top-K consolidation compares same-key values without hashing, including cyclic replacements and fresh transient cancellation. The fractional-index test checks an empty output message for a window move after all rows retract; it does not prove downstream lazy acquisition. Other hash-based operators retain hashing's declared domain. Algebra does not specify client readiness. The BTree/Map oracle checks point operations, neighbor pairs, and full, partial, boundary, exclusive-high, and empty range scans for integer keys and node sizes 4–8. It does not check balance or space, and it assumes consistent comparators ([code-weight BTree review](oracle-reviews/code-weight-btree-trim.md)). | | Includes and publication | [cross-formulation](https://github.com/TanStack/db/blob/main/packages/db/tests/query/includes-cross-formulation-oracle.property.test.ts), [temporal](https://github.com/TanStack/db/blob/main/packages/db/tests/query/includes-temporal-oracle.test.ts), [Collection includes](https://github.com/TanStack/db/blob/main/packages/db/tests/query/includes-collection-oracle.property.test.ts), [architecture and complete suite map](https://github.com/TanStack/db/blob/main/packages/db/src/query/live/ARCHITECTURE.md#executable-contracts) | Per-parent/flat-join/partition relations, callback-time rows, nested values, and route histories. Fragmented lazy-demand consolidation covers delta growth and successful, rejected/retried, and obsolete replacements at the Collection request boundary; it observes exact key unions and abort checkpoints. A compiled-includes fixture makes adapter unload evict owned child rows and proves a rejected union cannot remove established public child rows. Retry after that terminal live-query failure remains covered at the acquisition boundary; no automatic in-place recovery is claimed. Observe raw promised order; fresh queries do not establish continuous publication safety. | -| Collection lifecycle | [mutation startup](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-mutation-startup-oracle.test.ts), [change-event history](https://github.com/TanStack/db/blob/main/packages/db/tests/change-event-history-oracle.test.ts), [history](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-subscription-lifecycle-history.property.test.ts), [publication](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-subscription-lifecycle-publication.property.test.ts), [replay](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-subscription-replay-oracle.property.test.ts), [effect disposal](https://github.com/TanStack/db/blob/main/packages/db/tests/effect-disposal-oracle.test.ts), [PR #1902 review](oracle-reviews/pr-1902-change-event-history.md), [batch-order decision review](oracle-reviews/change-event-batch-order.md), [absent-key insert review](oracle-reviews/2026-10-02-insert-for-absent-key.md) | Core Collection `insert`/`update`/`delete` admission while `startSync:false` is idle; complete public-row/change-message agreement across bounded one- and two-key histories plus replayable four-key campaigns, where every message must be valid for a strict consumer (insert only for an absent key, update or delete only for a present one; [absent-key insert review](oracle-reviews/2026-10-02-insert-for-absent-key.md)); a two-key deferred sync history checks each key's causal insert/update/delete trace while allowing any cross-key interleaving. Reversing all deferred messages fails that check; reversing each sync transaction's distinct-key messages passes. Queued duplicate admission and cancellation, ownership and phase histories, exact caller/error/publication evidence, and late completion and restart have separate witnesses. Generated deferred histories with cancellation or reentrant callbacks need a witness in the change-event history owner before claiming general batch-shape coverage. Query write utilities and effect self-dependent disposal remain separate contracts. | +| Collection lifecycle | [mutation startup](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-mutation-startup-oracle.test.ts), [change-event history](https://github.com/TanStack/db/blob/main/packages/db/tests/change-event-history-oracle.test.ts), [history](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-subscription-lifecycle-history-oracle.property.test.ts), [publication](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-subscription-lifecycle-publication-oracle.property.test.ts), [replay](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-subscription-replay-oracle.property.test.ts), [effect disposal](https://github.com/TanStack/db/blob/main/packages/db/tests/effect-disposal-oracle.test.ts), [PR #1902 review](oracle-reviews/pr-1902-change-event-history.md), [batch-order decision review](oracle-reviews/change-event-batch-order.md), [absent-key insert review](oracle-reviews/2026-10-02-insert-for-absent-key.md) | Core Collection `insert`/`update`/`delete` admission while `startSync:false` is idle; complete public-row/change-message agreement across bounded one- and two-key histories plus replayable four-key campaigns, where every message must be valid for a strict consumer (insert only for an absent key, update or delete only for a present one; [absent-key insert review](oracle-reviews/2026-10-02-insert-for-absent-key.md)); a two-key deferred sync history checks each key's causal insert/update/delete trace while allowing any cross-key interleaving. Reversing all deferred messages fails that check; reversing each sync transaction's distinct-key messages passes. Queued duplicate admission and cancellation, ownership and phase histories, exact caller/error/publication evidence, and late completion and restart have separate witnesses. Generated deferred histories with cancellation or reentrant callbacks need a witness in the change-event history owner before claiming general batch-shape coverage. Query write utilities and effect self-dependent disposal remain separate contracts. | | Paced mutations | [virtual-clock oracle](https://github.com/TanStack/db/blob/main/packages/db/tests/paced-mutations-oracle.test.ts) | `createPacedMutations` with queue front/back options, bounded waiting capacity at zero and one, cleanup draining in FIFO/LIFO order after a held write, cleanup timing at the configured wait for immediate writes, admitted writes after separate Collection cleanup, debounce and throttle schedules with explicit and omitted options, and first-leading throttle execution at epoch zero. Finite histories compare optimistic rows, returned transaction identity and receipt outcome, execution order and virtual-clock time. Held writes verify queue serialization. Leading-only throttle and debounce witnesses reject skipped calls immediately with their named dropped-call errors, including omitted edges, both edges disabled, and same-row rollback while a prior write is held. Capacity witnesses cover overflow rejection, distinct-key optimistic rollback, same-key admitted-write survival, and in-flight versus waiting admission. Cleanup witnesses check repeated queue cleanup, eventual admitted receipt settlement, direct queue strategy rejection of new callbacks, public post-cleanup rollback with `QueueDisposedError`, pending debounce transactions that wait until the last call's quiet edge after separate Collection cleanup, and a trailing throttle timer that runs at its regular edge after separate Collection cleanup. Deferred custom queue and batch callbacks check compatibility with `void` and `false` execute results, respectively. Frozen options verify factory non-mutation; a mutable option witness checks that debounce uses its construction-time trailing setting. New debounce/throttle admission after cleanup, failed persistence, broader capacities and schedules remain outside this owner. | -| Optimistic state | [history model](https://github.com/TanStack/db/blob/main/packages/db/tests/optimistic-history-oracle.ts), [generated histories](https://github.com/TanStack/db/blob/main/packages/db/tests/optimistic-transaction-oracle.property.test.ts), [truncate capture ownership](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-truncate-ownership-oracle.property.test.ts), [outcomes](https://github.com/TanStack/db/blob/main/packages/db/tests/optimistic-history-outcomes.test.ts), [publication](https://github.com/TanStack/db/blob/main/packages/db/tests/optimistic-history-publication.test.ts) | Independent whole-row snapshots, rollback dependencies, captured truncate ownership, metadata and prior-value events. A raw subscriber without initial state checks that each truncate batch inserts a key once ([2026-10-02 review](oracle-reviews/2026-10-02-truncate-raw-subscriber.md)). Never rebase a pending snapshot merely to simplify the model. Generated histories also write source batches inside mutation handlers, before they return; the Collection must own the request by then ([handler source batch review](oracle-reviews/2026-10-01-handler-source-batch.md)). The same-key transaction lane also authors a delete followed by a reinsert, which must be visible optimistically and net to the truth-table request ([state mutation round 2](oracle-reviews/2026-10-02-state-mutation-round-2.md)). Source rows are written as `insert` for a key the source lacks, and batches may delete keys the source holds ([state-stack mutation gaps](oracle-reviews/2026-10-02-state-stack-mutant-gaps.md)). Open: a source delete for a key the source lacks is never generated; its effect on an optimistic layer for that key needs a contract and a witness. | -| Drafts and native values | [proxy](https://github.com/TanStack/db/blob/main/packages/db/tests/proxy.test.ts), [detachment](https://github.com/TanStack/db/blob/main/packages/db/tests/proxy-detachment-contract.test.ts), [iteration](https://github.com/TanStack/db/blob/main/packages/db/tests/proxy-iteration-contract.test.ts), [revert](https://github.com/TanStack/db/blob/main/packages/db/tests/proxy-revert-oracle.property.test.ts), [native methods](https://github.com/TanStack/db/blob/main/packages/db/tests/proxy-native-methods.property.test.ts) | Native-operation controls, exact patches and actual stored rows; alias/cycle/adversarial-key histories. Set and Map reorder histories check draft patches and stored iteration order after replacement and clear-and-readd; RegExp replacement/reversion histories check `lastIndex`. General native-mutator and symbol-write support is not established by a plain-object oracle. The revert owner generates assignment, revert, delete, nested, symbol-key, and `for...of` histories and checks `getChanges()` and the draft against an independent draft-equality model: ordered Map and Set contents (including Sets inside Map values), RegExp `lastIndex`, array holes, and symbol keys inside nested values. Mutator methods (`push`, `set`, `add`) and top-level symbol writes are outside its grammar. The proxy owner's stored-function law checks, against a native row, that a function stored as data reads back as stored by every read path and that a stored method sees the draft as `this`, so its writes are tracked. The detachment owner pins which key classes a draft copies: enumerable string keys and every symbol key. The revert owner also generates typed arrays (including a subclass that does not forward its constructor argument), URLs, and a class with only private state as written values, with a property that writes two of them over one field. The native-methods owner generates rows (holes, `undefined`, duplicates, nested arrays, empty rows, typed `-0` and `NaN`) and calls every method of `Array.prototype` and `TypedArray.prototype`, in fixed and random campaigns with replay; it compares the result, whether the method returned the array itself, the identity of each original object, and the published row with native values, and a new built-in method fails until it has arguments. The proxy owner's `defineProperty`, stored-function, and frozen-draft laws are bounded tables against native rows. Its `defineProperty` law compares result, value, descriptor, and changes, for values and accessors. The iteration owner checks that array iterators see a push, removal, index write, or length cut made while they are open. Open: a draft reads a class instance of the original row as a plain object, so private-field getters read `undefined`, and a built-in method called through `this` on a nested Map or Set draft rejects the Proxy receiver; a mutator that changes nothing publishes an equal value; reading an object under a frozen draft key counts that key as changed, writing back a keyless class instance of the original row is a change, and `DataView` setters are untracked ([draft proxy review](oracle-reviews/code-weight-draft-proxy.md)). | -| Query DB and observer | [ownership](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/ownership-lifecycle.oracle.test.ts), [load lifecycle](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/load-subset-lifecycle-oracle.test.ts), [observer histories](https://github.com/TanStack/db/blob/main/packages/db/tests/live-query-observer-history.property.test.ts) | Real QueryClient boundary, applied-settlement barriers for existing and cached demand, mutation-handler Collection identity, terminal fetch-record lifecycle, and a per-listener eligibility ledger, not a duplicate dispatch queue. The bounded handler grammar crosses insert, update, delete, parameter and mutation-alias access, refetch, and clearError. A held clearError retry retains the prior public error through initial, background, and Collection application failures; success clears it, failure advances the count, including a repeated error at clock time zero. An intermediate Query retry attempt does not recount the previous background error; a held final attempt can succeed or fail. A held application after successful Query fetch keeps the error visible until the applied result. A mocked persisted-baseline scan holds an older success while a newer terminal Query failure arrives; the newer public error and count survive application, including when the Error object and clock tick repeat. Native SQLite persistence, concurrent retries across multiple tracked Queries, mutation-handler fetch-boundary settlement, and deferred result application remain outside this witness. The mutation overlap grammar crosses both start orders. Check reentry, peer survival, FIFO and disposal independently of final rows. | +| Optimistic state | [history model](https://github.com/TanStack/db/blob/main/packages/db/tests/optimistic-history-oracle.ts), [generated histories](https://github.com/TanStack/db/blob/main/packages/db/tests/optimistic-transaction-oracle.property.test.ts), [truncate capture ownership](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-truncate-ownership-oracle.property.test.ts), [outcomes](https://github.com/TanStack/db/blob/main/packages/db/tests/optimistic-history-outcomes-oracle.test.ts), [publication](https://github.com/TanStack/db/blob/main/packages/db/tests/optimistic-history-publication-oracle.test.ts) | Independent whole-row snapshots, rollback dependencies, captured truncate ownership, metadata and prior-value events. A raw subscriber without initial state checks that each truncate batch inserts a key once ([2026-10-02 review](oracle-reviews/2026-10-02-truncate-raw-subscriber.md)). Never rebase a pending snapshot merely to simplify the model. Generated histories also write source batches inside mutation handlers, before they return; the Collection must own the request by then ([handler source batch review](oracle-reviews/2026-10-01-handler-source-batch.md)). The same-key transaction lane also authors a delete followed by a reinsert, which must be visible optimistically and net to the truth-table request ([state mutation round 2](oracle-reviews/2026-10-02-state-mutation-round-2.md)). Source rows are written as `insert` for a key the source lacks, and batches may delete keys the source holds ([state-stack mutation gaps](oracle-reviews/2026-10-02-state-stack-mutant-gaps.md)). Open: a source delete for a key the source lacks is never generated; its effect on an optimistic layer for that key needs a contract and a witness. | +| Drafts and native values | [proxy](https://github.com/TanStack/db/blob/main/packages/db/tests/proxy-oracle.test.ts), [detachment](https://github.com/TanStack/db/blob/main/packages/db/tests/proxy-detachment-contract-oracle.test.ts), [iteration](https://github.com/TanStack/db/blob/main/packages/db/tests/proxy-iteration-contract-oracle.test.ts), [revert](https://github.com/TanStack/db/blob/main/packages/db/tests/proxy-revert-oracle.property.test.ts), [native methods](https://github.com/TanStack/db/blob/main/packages/db/tests/proxy-native-methods-oracle.property.test.ts) | Native-operation controls, exact patches and actual stored rows; alias/cycle/adversarial-key histories. Set and Map reorder histories check draft patches and stored iteration order after replacement and clear-and-readd; RegExp replacement/reversion histories check `lastIndex`. General native-mutator and symbol-write support is not established by a plain-object oracle. The revert owner generates assignment, revert, delete, nested, symbol-key, and `for...of` histories and checks `getChanges()` and the draft against an independent draft-equality model: ordered Map and Set contents (including Sets inside Map values), RegExp `lastIndex`, array holes, and symbol keys inside nested values. Mutator methods (`push`, `set`, `add`) and top-level symbol writes are outside its grammar. The proxy owner's stored-function law checks, against a native row, that a function stored as data reads back as stored by every read path and that a stored method sees the draft as `this`, so its writes are tracked. The detachment owner pins which key classes a draft copies: enumerable string keys and every symbol key. The revert owner also generates typed arrays (including a subclass that does not forward its constructor argument), URLs, and a class with only private state as written values, with a property that writes two of them over one field. The native-methods owner generates rows (holes, `undefined`, duplicates, nested arrays, empty rows, typed `-0` and `NaN`) and calls every method of `Array.prototype` and `TypedArray.prototype`, in fixed and random campaigns with replay; it compares the result, whether the method returned the array itself, the identity of each original object, and the published row with native values, and a new built-in method fails until it has arguments. The proxy owner's `defineProperty`, stored-function, and frozen-draft laws are bounded tables against native rows. Its `defineProperty` law compares result, value, descriptor, and changes, for values and accessors. The iteration owner checks that array iterators see a push, removal, index write, or length cut made while they are open. Open: a draft reads a class instance of the original row as a plain object, so private-field getters read `undefined`, and a built-in method called through `this` on a nested Map or Set draft rejects the Proxy receiver; a mutator that changes nothing publishes an equal value; reading an object under a frozen draft key counts that key as changed, writing back a keyless class instance of the original row is a change, and `DataView` setters are untracked ([draft proxy review](oracle-reviews/code-weight-draft-proxy.md)). | +| Query DB and observer | [ownership](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/ownership-lifecycle.oracle.test.ts), [load lifecycle](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/load-subset-lifecycle-oracle.test.ts), [observer histories](https://github.com/TanStack/db/blob/main/packages/db/tests/live-query-observer-history-oracle.property.test.ts) | Real QueryClient boundary, applied-settlement barriers for existing and cached demand, mutation-handler Collection identity, terminal fetch-record lifecycle, and a per-listener eligibility ledger, not a duplicate dispatch queue. The bounded handler grammar crosses insert, update, delete, parameter and mutation-alias access, refetch, and clearError. A held clearError retry retains the prior public error through initial, background, and Collection application failures; success clears it, failure advances the count, including a repeated error at clock time zero. An intermediate Query retry attempt does not recount the previous background error; a held final attempt can succeed or fail. A held application after successful Query fetch keeps the error visible until the applied result. A mocked persisted-baseline scan holds an older success while a newer terminal Query failure arrives; the newer public error and count survive application, including when the Error object and clock tick repeat. Native SQLite persistence, concurrent retries across multiple tracked Queries, mutation-handler fetch-boundary settlement, and deferred result application remain outside this witness. The mutation overlap grammar crosses both start orders. Check reentry, peer survival, FIFO and disposal independently of final rows. | | Query DB SSR dehydration | `packages/query-db-collection/tests/ssr-dehydration-oracle.test.ts`, [review record](oracle-reviews/issue-1950-ssr-dehydration.md) | A plain Query cache control, a live on-demand compound predicate, a signal-only request, and an ordered cursor with a custom comparator all retain their row through QueryClient dehydration, reconstruction of Seroval's emitted stream payload, and Query Core hydration from that payload. The on-demand query functions still receive the original IR, comparator, and signal; serialized metadata retains enumerable user metadata but excludes request options. The original implementation fails the compound and signal cases at the stream checkpoint. A serializable stream-only request-options leak passes the former chunk-count check but fails the current payload assertion. This owner covers successful Query cache entries at the installed Query Core 5.90.20 and Seroval 1.5.0 versions. A TanStack Start integration owner still needs the reporter's Router 1.171.33 and Seroval 1.6.8 path, browser Collection resume/refetch, and request cancellation across SSR. Query subset and pagination oracles remain owners of predicate/order/cursor meaning and supported value types. The issue's `shouldDehydrateQuery` workaround replaces Query Core's success-only default and admits pending/error queries; any documented workaround must preserve that default filter. | -| Ordered acquisition | [pagination](https://github.com/TanStack/db/blob/main/packages/db/tests/query/pagination-oracle.property.test.ts), [ordered work](https://github.com/TanStack/db/blob/main/packages/db/tests/query/ordered-work-oracle.property.test.ts), [ordered lifecycle](https://github.com/TanStack/db/blob/main/packages/db/tests/query/ordered-lifecycle-oracle.property.test.ts), [ordered loader state](https://github.com/TanStack/db/blob/main/packages/db/tests/query/ordered-source-loader-state.test.ts), [graph scheduler](https://github.com/TanStack/db/blob/main/packages/db/tests/query/scheduler.test.ts), [issue #1880 ordered-repair review](oracle-reviews/issue-1880-ordered-repair.md), [issue #1882 custom local collation review](oracle-reviews/issue-1882-custom-local-collation.md), [issue #1898 relation-filter review](oracle-reviews/issue-1898-relation-filter.md), [PR #1909 external review](oracle-reviews/pr-1909-external-review.md) | Complete finite provider results, inherited locale and bounded/unbounded custom collation with exact request options, query-level inheritance across source aliases, real lexical/numeric disagreement, custom comparator ties, scan/index paths, pending windows, ties/nulls, lease ownership, Effect callback gates, including an indexed source update during Effect startup, and documented repair timing. Direct LEFT-joined filters cover local finite prefixes, pending child demand, child removal, and anti-join publication with custom full-source and unindexed fallback loading; unrelated include demand cannot stall the root continuation, and an empty joined replay wakes held Effect callbacks; remote relation hints remain outside this owner. Graph scheduler checks coalescing, dependency order, synchronous loader input, and repeated-alias failure ownership. The ordered-work oracle checks that a synchronous root refill reaches D2 before joined publication; a mutant that omitted the post-loader graph step failed at the second child demand. Custom collation proves local full-source acquisition only; it does not establish provider cursor capability or backend collation fidelity. Sibling-source input during a synchronous ordered continuation returns to graph work before another ordered acquisition. Request completion is not proof of unrequested source extent. A window move during existing joined demand waits for its root continuation, including an independently held root request; current demand failure rejects the move, while retirement and an obsolete rejection do not. A bounded ordered repair resumes its refill after joined demand settles. The ordered-source-loader state test checks that an explicit failed-request retry blocked by joined demand retains its generation until it can issue a request. Multiple simultaneously pending joined plans during a window move and a public-query failed-retry overlap still need dedicated witnesses. | +| Ordered acquisition | [pagination](https://github.com/TanStack/db/blob/main/packages/db/tests/query/pagination-oracle.property.test.ts), [ordered work](https://github.com/TanStack/db/blob/main/packages/db/tests/query/ordered-work-oracle.property.test.ts), [ordered lifecycle](https://github.com/TanStack/db/blob/main/packages/db/tests/query/ordered-lifecycle-oracle.property.test.ts), [ordered loader state](https://github.com/TanStack/db/blob/main/packages/db/tests/query/ordered-source-loader-state-oracle.test.ts), [graph scheduler](https://github.com/TanStack/db/blob/main/packages/db/tests/query/scheduler.test.ts), [issue #1880 ordered-repair review](oracle-reviews/issue-1880-ordered-repair.md), [issue #1882 custom local collation review](oracle-reviews/issue-1882-custom-local-collation.md), [issue #1898 relation-filter review](oracle-reviews/issue-1898-relation-filter.md), [PR #1909 external review](oracle-reviews/pr-1909-external-review.md) | Complete finite provider results, inherited locale and bounded/unbounded custom collation with exact request options, query-level inheritance across source aliases, real lexical/numeric disagreement, custom comparator ties, scan/index paths, pending windows, ties/nulls, lease ownership, Effect callback gates, including an indexed source update during Effect startup, and documented repair timing. Direct LEFT-joined filters cover local finite prefixes, pending child demand, child removal, and anti-join publication with custom full-source and unindexed fallback loading; unrelated include demand cannot stall the root continuation, and an empty joined replay wakes held Effect callbacks; remote relation hints remain outside this owner. Graph scheduler checks coalescing, dependency order, synchronous loader input, and repeated-alias failure ownership. The ordered-work oracle checks that a synchronous root refill reaches D2 before joined publication; a mutant that omitted the post-loader graph step failed at the second child demand. Custom collation proves local full-source acquisition only; it does not establish provider cursor capability or backend collation fidelity. Sibling-source input during a synchronous ordered continuation returns to graph work before another ordered acquisition. Request completion is not proof of unrequested source extent. A window move during existing joined demand waits for its root continuation, including an independently held root request; current demand failure rejects the move, while retirement and an obsolete rejection do not. A bounded ordered repair resumes its refill after joined demand settles. The ordered-source-loader state test checks that an explicit failed-request retry blocked by joined demand retains its generation until it can issue a request. Multiple simultaneously pending joined plans during a window move and a public-query failed-retry overlap still need dedicated witnesses. | | Indexed predicate filtering | `packages/db/tests/query/index-path-collision-oracle.test.ts` | A bounded cross product of numeric values checks exact public keys before and after adding a nested-field BTree index. Direct predicates vary argument order, bound inclusivity, reversed operands, and bound field. Public Collection subscription and live-query callbacks run with and without the index. Selected-field ordering compares a direct JavaScript sort with a public `$selected` callback; restoring the dotted-key proxy cache made that comparison fail. The original compound grouping failed four indexed cases while scan controls passed. The original callback proxy caches also failed both unindexed public routes. A hostile cleanup control preserves the primary mismatch and secondary release error. Arbitrary path segments, nullish values, custom collation, and incremental publication need separate witnesses if claimed. | | Lazy target path identity | `packages/db/tests/query/compiler/lazy-targets.test.ts` | A focused same-source `UnionFrom`/`coalesce` witness requires both [`a.b`] and [`a`, `b`] demand targets. Restoring dotted-string deduplication drops the second target at the compiler boundary. A public on-demand adapter and row-publication history still need a separate witness. | | Correlated include path identity | `packages/db/tests/query/includes-context-transport-oracle.test.ts` | A flat parent field and nested parent field reach one-level and nested `toArray` results independently; dotted ancestor aliases remain distinct through a grandchild route. Initial results and parent updates have exact public-value checks. A conditional projection gives [`a.b`] and [`a`, `b`] different include results and checks parent-key changes plus later child inserts. Removing the compiler's unique route-key allocator loses a public child result; restoring dotted-string deduplication at either builder site loses a distinct parent value. These fixed witnesses do not establish arbitrary path segments, every recursive source form, or every materialization form. | @@ -255,27 +255,27 @@ comment and the current API/architecture contract before extending its model. | Join equality and cold acquisition | `packages/db/tests/query/cold-join-reconciliation-oracle.test.ts` | Independent recomputation for cold acquisition plus direct join/predicate equivalence across established equality domains. Binary/string and nullish classes, replacement histories, raw on-demand values, and both scan/auto-index paths are explicit; compound join syntax is not claimed. | | Query optimizer semantics | `packages/db/tests/query/optimizer-semantics-oracle.test.ts`, [aggregate review](oracle-reviews/2026-09-28-optimizer-aggregate-pushdown.md), [QueryRef repair](oracle-reviews/2026-09-30-queryref-publication-repair.md), [residual review](oracle-reviews/2026-10-01-pr-1977-residual-convergence.md) | Independent sum recomputation and a materialized-Collection formulation check the first public snapshot of a nested aggregate under a left join. Direct, arithmetic-wrapped, and conditional aggregates distinguish safe from unsafe pushdown; a grouped-key control covers the grouped boundary. Matching and nonmatching global aggregates also cross a nested QueryRef inner join with absent, accepting, and rejecting outer predicates. The matching initial cases fail on the pre-repair revision and pass after the computed-projection lookup repair. A separate fixed residual-convergence grammar checks exact predicate and outer WHERE clause counts at `optimizeQuery` return and after re-optimization: LEFT, RIGHT, INNER, and FULL joins; equality, greater-than, nullable-field `isUndefined`, same-source OR, cross-source equality, clause order, separate/AND form, two active predicates, two residual sources, and an existing residual marker. Plain-array LEFT/RIGHT and three-source join models check first public rows, including unmatched rows. Arbitrary expressions, more complex join chains, and incremental optimizer/publication histories remain outside this owner. | | QueryRef operators and user-value boundaries | `packages/db/tests/query/subquery-user-value-oracle.test.ts`, `packages/db/tests/transactions.test.ts`, [repair record](oracle-reviews/2026-09-30-queryref-publication-repair.md) | A finite array/Set model checks the compiled output bag for a joined DISTINCT subquery with an outer WHERE. Live-query drivers check selected containers, no-select, functional, and predicate-literal user objects with IR-like fields, top-level and aggregate-subquery proxy-shaped fields, arrays of selected references, outer virtual-field filters on joined DISTINCT and nested aggregate QueryRefs, and a renamed no-select source. The transaction suite documents the existing development-browser duplicate-load guard. The bounded cases run in `test:oracles` or the full DB suite. Joined DISTINCT, nested and flat aggregate source-update histories pass. Ordered joined `findOne()` checks initial, singleton, empty, restored, and changed-join-key cuts; an unordered `findOne()` QueryRef on either side of a join checks default-key candidate deletion and reinsertion. A materialized joined `findOne()` supplies a separate receiving formulation. Other `singleResult` forms, join forms, schedules, and cross-copy value handling outside the duplicate-load guard remain unproved. | -| Opaque backend pagination | [window oracle](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/cursor-pagination.oracle.test.ts), [cache histories](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/cursor-pagination.cache-oracle.test.ts), [cache publication](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/cursor-pagination.publication-oracle.test.ts), [browser acquisition boundaries](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/cursor-pagination.boundary-oracle.test.ts), [QueryCollection integration](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/cursor-pagination.integration.test.ts) | Full filter/sort/slice reference, opaque token transport, actual Query cache expiry/invalidation/GC, forced refresh during growth, protocol failure publication/recovery, bounded slice work, nested cancellation/replacement, reader abort, browser retry defaults, manual-write cache isolation, and production window publications. Stable backend sequences; not snapshot guarantees for changing endpoints. Peek-ahead remains enabled. | -| Electric and TrailBase | [Electric histories](https://github.com/TanStack/db/blob/main/packages/electric-db-collection/tests/electric-oracle.property.test.ts), [recovery histories](https://github.com/TanStack/db/blob/main/packages/electric-db-collection/tests/electric-recovery-oracle.test.ts), [held resume snapshots](https://github.com/TanStack/db/blob/main/packages/electric-db-collection/tests/electric-resume-snapshot-races.test.ts), [PostgreSQL semantics](https://github.com/TanStack/db/blob/main/packages/electric-db-collection/e2e/sql-predicate-semantics.e2e.test.ts), [TrailBase contract](https://github.com/TanStack/db/blob/main/packages/trailbase-db-collection/tests/ORACLE.md) | Installed SDK delivery/framing, independent predicates, exact subscription arguments, restart/reset lineage, held certification and durability races, source-order publication before durability, and late errors. The queued-presence property runs identical fixed/random generators plus isolated seed-and-path replay across insert, update, delete, and truncate callbacks. The recovery fixtures use a mocked ShapeStream; they do not establish live Electric-service framing or native persistence-host behavior. | +| Opaque backend pagination | [window oracle](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/cursor-pagination.oracle.test.ts), [cache histories](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/cursor-pagination.cache-oracle.test.ts), [cache publication](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/cursor-pagination.publication-oracle.test.ts), [browser acquisition boundaries](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/cursor-pagination.boundary-oracle.test.ts), [QueryCollection integration](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/cursor-pagination-oracle.integration.test.ts) | Full filter/sort/slice reference, opaque token transport, actual Query cache expiry/invalidation/GC, forced refresh during growth, protocol failure publication/recovery, bounded slice work, nested cancellation/replacement, reader abort, browser retry defaults, manual-write cache isolation, and production window publications. Stable backend sequences; not snapshot guarantees for changing endpoints. Peek-ahead remains enabled. | +| Electric and TrailBase | [Electric histories](https://github.com/TanStack/db/blob/main/packages/electric-db-collection/tests/electric-oracle.property.test.ts), [recovery histories](https://github.com/TanStack/db/blob/main/packages/electric-db-collection/tests/electric-recovery-oracle.test.ts), [held resume snapshots](https://github.com/TanStack/db/blob/main/packages/electric-db-collection/tests/electric-resume-snapshot-races.test.ts), [PostgreSQL semantics](https://github.com/TanStack/db/blob/main/packages/electric-db-collection/e2e/sql-predicate-semantics-oracle.e2e.test.ts), [TrailBase contract](https://github.com/TanStack/db/blob/main/packages/trailbase-db-collection/tests/ORACLE.md) | Installed SDK delivery/framing, independent predicates, exact subscription arguments, restart/reset lineage, held certification and durability races, source-order publication before durability, and late errors. The queued-presence property runs identical fixed/random generators plus isolated seed-and-path replay across insert, update, delete, and truncate callbacks. The recovery fixtures use a mocked ShapeStream; they do not establish live Electric-service framing or native persistence-host behavior. | | PowerSync | [tests](https://github.com/TanStack/db/tree/main/packages/powersync-db-collection/tests), `tests/correctness-oracle.test.ts` | Applied receipt positions crossed with held peers, native SQLite/SDK and cleanup evidence. A metadata-bearing `Collection.update` passes through an observed SDK watcher callback to the public and SQLite rows and an exact queued CRUD patch. Held callback ordering and synthetic zero-field cases remain controlled-only, and remote upload has no receiving fixture here. Run the focused owner with the package's `test:oracles` command. A timeout mutant proves a progress failure, not every value assertion. | -| SQLite persistence and native hosts | [persisted histories](https://github.com/TanStack/db/blob/main/packages/db-sqlite-persistence-core/tests/persisted.test.ts), [reset/resume histories](https://github.com/TanStack/db/blob/main/packages/db-sqlite-persistence-core/tests/sqlite-core-adapter.test.ts), [dual-adapter resume snapshots](https://github.com/TanStack/db/blob/main/packages/db-sqlite-persistence-core/tests/sqlite-resume-snapshot.test.ts), [Browser composed-owner histories](https://github.com/TanStack/db/blob/main/packages/browser-db-sqlite-persistence/tests/per-collection-coordinator-oracle.test.ts), [Browser coordinator RPC](https://github.com/TanStack/db/blob/main/packages/browser-db-sqlite-persistence/tests/browser-coordinator.test.ts), [shared-driver fairness](https://github.com/TanStack/db/blob/main/packages/browser-db-sqlite-persistence/tests/shared-driver-fairness-oracle.test.ts), [driver contracts](https://github.com/TanStack/db/blob/main/packages/db-sqlite-persistence-core/tests/contracts/sqlite-driver-contract.ts), [Node shared-handle scheduling](https://github.com/TanStack/db/blob/main/packages/node-db-sqlite-persistence/tests/node-driver.test.ts), [OP-SQLite shared-handle scheduling](https://github.com/TanStack/db/blob/main/packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver.test.ts), [browser OPFS lifecycle](https://github.com/TanStack/db/blob/main/packages/browser-db-sqlite-persistence/tests/opfs-page-lifecycle-oracle.test.ts), [worker diagnostics](https://github.com/TanStack/db/blob/main/packages/browser-db-sqlite-persistence/tests/opfs-worker-diagnostics-oracle.test.ts), [Electron IPC and composed owner](https://github.com/TanStack/db/blob/main/packages/electron-db-sqlite-persistence/tests/electron-ipc.test.ts), [113-law manifest](https://github.com/TanStack/db/blob/main/packages/db-collection-e2e/src/fixtures/persisted-conformance-manifest.ts) | Core cache/remote rejection/peer/reopen histories, atomic reset/resume lineage, key-set evidence, dual-adapter races, queued coordinator reload/gap notifications during startup, unscheduled startup/reset overlap, and exact driver results. The shared core-adapter contract checks custom local comparator dispatch for ascending, descending, and comparator-equal public-key ordering at `loadSubset` completion. Host packages register this contract, but the local sqlite3 CLI run does not prove native host execution. Browser composes public source commits with per-collection elected-owner routing and covers the complete committed-transaction wire partition through deterministic Node transport seams. Remote-subset histories distinguish logical demand, physical acquisitions, exact acquisition leases, and released replay tombstones. Electron composes source commits with a per-collection renderer owner, IPC adapter, real SQLite, and reopen checks. The shared-driver fairness owner checks K=1 complete-logical-hydrate scheduling with identical fixed, random, and seed-plus-path campaigns. It records public rows, raw dequeue reach, and a persist-first FIFO hostile control. Its Chromium OPFS fixture refines the provider boundary but does not establish a browser matrix, elapsed-time latency, unbounded eventuality, or multi-process coordination. Same-handle Node and OP-SQLite tests cover transaction admission. Controlled OPFS page/worker histories cover ownership and diagnostic-cause retention. The reset/resume owners use sqlite3 CLI and in-memory node:sqlite seams; they do not prove multi-process WAL, mobile/Tauri, or other native-device execution. Distinct database handles rely on SQLite lock admission rather than one in-process queue. React Native hosts without async-context propagation must use the transaction driver supplied to the callback for nested work. Fake workers and synthetic page events do not prove native handle release or real bfcache admission. The Browser composed seams are not real multi-context/OPFS-worker execution; the Electron harness is not an actual Electron process unless its explicit runtime-bridge mode runs. An ownerless elected node suppresses core routing, while a follower may route demand to the elected owner; host coordinators retry only classified transport or admission failures while demand remains retained. The manifest excludes progressive and move suites; registration and shim runs are not device execution. | +| SQLite persistence and native hosts | [persisted histories](https://github.com/TanStack/db/blob/main/packages/db-sqlite-persistence-core/tests/persisted-oracle.test.ts), [reset/resume histories](https://github.com/TanStack/db/blob/main/packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-oracle.test.ts), [dual-adapter resume snapshots](https://github.com/TanStack/db/blob/main/packages/db-sqlite-persistence-core/tests/sqlite-resume-snapshot-oracle.test.ts), [Browser composed-owner histories](https://github.com/TanStack/db/blob/main/packages/browser-db-sqlite-persistence/tests/per-collection-coordinator-oracle.test.ts), [Browser coordinator RPC](https://github.com/TanStack/db/blob/main/packages/browser-db-sqlite-persistence/tests/browser-coordinator-oracle.test.ts), [shared-driver fairness](https://github.com/TanStack/db/blob/main/packages/browser-db-sqlite-persistence/tests/shared-driver-fairness-oracle.test.ts), [driver contracts](https://github.com/TanStack/db/blob/main/packages/db-sqlite-persistence-core/tests/contracts/sqlite-driver-contract.ts), [Node shared-handle scheduling](https://github.com/TanStack/db/blob/main/packages/node-db-sqlite-persistence/tests/node-driver.test.ts), [OP-SQLite shared-handle scheduling](https://github.com/TanStack/db/blob/main/packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver-oracle.test.ts), [browser OPFS lifecycle](https://github.com/TanStack/db/blob/main/packages/browser-db-sqlite-persistence/tests/opfs-page-lifecycle-oracle.test.ts), [worker diagnostics](https://github.com/TanStack/db/blob/main/packages/browser-db-sqlite-persistence/tests/opfs-worker-diagnostics-oracle.test.ts), [Electron IPC and composed owner](https://github.com/TanStack/db/blob/main/packages/electron-db-sqlite-persistence/tests/electron-ipc.test.ts), [113-law manifest](https://github.com/TanStack/db/blob/main/packages/db-collection-e2e/src/fixtures/persisted-conformance-manifest.ts) | Core cache/remote rejection/peer/reopen histories, atomic reset/resume lineage, key-set evidence, dual-adapter races, queued coordinator reload/gap notifications during startup, unscheduled startup/reset overlap, and exact driver results. The shared core-adapter contract checks custom local comparator dispatch for ascending, descending, and comparator-equal public-key ordering at `loadSubset` completion. Host packages register this contract, but the local sqlite3 CLI run does not prove native host execution. Browser composes public source commits with per-collection elected-owner routing and covers the complete committed-transaction wire partition through deterministic Node transport seams. Remote-subset histories distinguish logical demand, physical acquisitions, exact acquisition leases, and released replay tombstones. Electron composes source commits with a per-collection renderer owner, IPC adapter, real SQLite, and reopen checks. The shared-driver fairness owner checks K=1 complete-logical-hydrate scheduling with identical fixed, random, and seed-plus-path campaigns. It records public rows, raw dequeue reach, and a persist-first FIFO hostile control. Its Chromium OPFS fixture refines the provider boundary but does not establish a browser matrix, elapsed-time latency, unbounded eventuality, or multi-process coordination. Same-handle Node and OP-SQLite tests cover transaction admission. Controlled OPFS page/worker histories cover ownership and diagnostic-cause retention. The reset/resume owners use sqlite3 CLI and in-memory node:sqlite seams; they do not prove multi-process WAL, mobile/Tauri, or other native-device execution. Distinct database handles rely on SQLite lock admission rather than one in-process queue. React Native hosts without async-context propagation must use the transaction driver supplied to the callback for nested work. Fake workers and synthetic page events do not prove native handle release or real bfcache admission. The Browser composed seams are not real multi-context/OPFS-worker execution; the Electron harness is not an actual Electron process unless its explicit runtime-bridge mode runs. An ownerless elected node suppresses core routing, while a follower may route demand to the elected owner; host coordinators retry only classified transport or admission failures while demand remains retained. The manifest excludes progressive and move suites; registration and shim runs are not device execution. | | SQLite expression-index planning | [Node expression-index oracle](https://github.com/TanStack/db/blob/main/packages/node-db-sqlite-persistence/tests/expression-index-oracle.test.ts) | RFC #1659 invariant 8 owns identical persisted-index and runtime-expression shapes. Independent expected keys are checked against direct captured SQL, adapter results, and named-index plans. Generated BigInts use SQLite's signed range; one fixed case checks legacy oversized-value reads. Other limits: bounded unqualified JSON paths/scalars, Node BetterSQLite, and no null, arbitrary raw SQL, or native-host planning. Run the package's `test:oracles` campaign. | -| Offline execution | [scheduler](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/KeyScheduler.property.test.ts), [leadership](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/leadership-replay.property.test.ts), [settlement](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/transaction-settlement.property.test.ts), [serialization](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/transaction-serializer.property.test.ts), [web connectivity replay](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/connectivity-replay-oracle.test.ts), [review record](oracle-reviews/pr-1879-visible-replay.md) | Declarative FIFO eligibility, per-transaction outcomes, durable state and typed wire trees. The web connectivity owner checks a persisted write under a false browser online hint, then visible replay by event or explicit retry, at provider-call, outbox, and caller-settlement cuts. It uses controlled browser globals and fake storage; it does not prove actual browser network detection, genuine offline retry timing, multi-tab leadership transfer, or React Native behavior. Issued work may finish after ownership loss, but new work must not start. Exactly-once network execution is not promised. | +| Offline execution | [scheduler](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/KeyScheduler-oracle.property.test.ts), [leadership](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/leadership-replay-oracle.property.test.ts), [settlement](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/transaction-settlement-oracle.property.test.ts), [serialization](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/transaction-serializer-oracle.property.test.ts), [web connectivity replay](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/connectivity-replay-oracle.test.ts), [review record](oracle-reviews/pr-1879-visible-replay.md) | Declarative FIFO eligibility, per-transaction outcomes, durable state and typed wire trees. The web connectivity owner checks a persisted write under a false browser online hint, then visible replay by event or explicit retry, at provider-call, outbox, and caller-settlement cuts. It uses controlled browser globals and fake storage; it does not prove actual browser network detection, genuine offline retry timing, multi-tab leadership transfer, or React Native behavior. Issued work may finish after ownership loss, but new work must not start. Exactly-once network execution is not promised. | | Frameworks | [React conformance](https://github.com/TanStack/db/blob/main/packages/react-db/tests/conformance.test.tsx), [React pagination](https://github.com/TanStack/db/blob/main/packages/react-db/tests/infinite-query-conformance.test.tsx), [shared suites](https://github.com/TanStack/db/tree/main/packages/db-collection-e2e/src/suites), [Vue synchronous publication](https://github.com/TanStack/db/blob/main/packages/vue-db/tests/useLiveQuery-publication-oracle.test.ts) | Exact exposed rows/pages and each framework's own lifecycle cuts. Vue's synchronous watcher checks insert, update, and nonterminal delete through supplied Collection and identity query inputs; it does not cover an empty final result, multiple changes in one transaction, or query recompilation. A React witness does not prove Vue/Solid/Angular/Svelte scheduling. Preserve their receiving registrations. | -| Window-controller overlap | [shared infinite-query conformance](https://github.com/TanStack/db/blob/main/packages/db/tests/conformance/infinite-suite.ts), [React driver](https://github.com/TanStack/db/blob/main/packages/react-db/tests/infinite-query-conformance.test.tsx), [Vue driver](https://github.com/TanStack/db/blob/main/packages/vue-db/tests/infinite-query-conformance.test.ts), [Svelte driver](https://github.com/TanStack/db/blob/main/packages/svelte-db/tests/infinite-query-conformance.svelte.test.ts), [review record](oracle-reviews/dec-03-window-overlap.md) | Four or five ordered source rows, two window-settlement orders, and public snapshots after each settlement, a subscribed observer update, a detached controller read, and explicit recovery. Insertion and removal of the fifth row distinguish both continuation directions while an earlier error remains visible. The detached read follows a source change with no controller subscriber; its preloaded Collection retains the five-row window. The exact overlap uses the exported DB controller in each package realm. Framework hooks expose no controller preload, so this cell does not establish a hook scheduling path; direct hook paging remains in the adjacent shared scenarios. An unsubscribed controller has no notification claim. | -| Structural values and ordered primitives | [hash values](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/hash.property.test.ts), [hash identity](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/hash-identity-oracle.property.test.ts), [MultiSet consolidation](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/multiset-consolidate-oracle.property.test.ts), [hash graphs](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/hash-graph.property.test.ts), [mixed hash graphs](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/hash-mixed-graph.property.test.ts), [hash retry](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/hash-failure-retry.property.test.ts), [comparison](https://github.com/TanStack/db/blob/main/packages/db/tests/comparison.property.test.ts), [deep equality](https://github.com/TanStack/db/blob/main/packages/db/tests/utils.property.test.ts), [cursor](https://github.com/TanStack/db/blob/main/packages/db/tests/cursor.property.test.ts), [indexes](https://github.com/TanStack/db/blob/main/packages/db/tests/index-update.property.test.ts), [BTree Map](https://github.com/TanStack/db/blob/main/packages/db/tests/btree-map-oracle.test.ts), [query identity](https://github.com/TanStack/db/blob/main/packages/db/tests/query/identity-output-shape-oracle.test.ts), [LIKE semantics](https://github.com/TanStack/db/blob/main/packages/db/tests/query/compiler/evaluators.test.ts) | Independent flat values, graph topology, algebraic laws, Map/group/sort recomputation, expression denotation, custom comparator dispatch/reference identity/index compatibility, LIKE wildcard refinement, compiled output bags, declared value-pair agreement between D2 equality keys and IR equality operands, and Collection collation with exact public scan/index order and one-index reuse across repeated reads. The auto-index cells cross BasicIndex and BTreeIndex; scan cells omit indexes. Both paths cover lexical and numeric `en-US` locale defaults plus an explicit ordinary locale override of a numeric default. An unindexed six-row work cell bounds Collection collation resolution to at most two reads per ordered scan: one index-path check and one scan clause. Other locales and ordered histories are outside this owner. The identity pair grammar covers primitives, signed zero, NaN/invalid Date, valid Date/timestamp, binary/Buffer, Temporal, nested references, symbols, and functions; fixed and sampled pairs do not prove every JavaScript value or hash collision freedom. Ref proxies are expressions rather than literal values in this lane. The deep-equality owner also pins that `deepEquals` ignores Map and Set insertion order, RegExp `lastIndex`, array holes, and typed-array class, the rules draft equality keeps. It also pins that objects of another class differ, that plain and null-prototype objects are one class, that a class instance without enumerable keys equals only itself, that URLs compare by `href`, and that typed-array elements compare like numbers. The hash-values owner samples Set/object and Map/object type-marker distinctions in fixed and random campaigns with seed-and-path replay; collision freedom is not promised. The hash-identity owner checks `hash` and `equalHashValues` against one spec-level identity model: primitives with signed zero, NaN, and bigint; reference leaves (functions, registered handles, `File`, binary over 128 bytes); Date, binary, Temporal, and RegExp headers; array length and holes; Map and Set insertion order; and object keys in any order, for acyclic values and for cycles through arrays, Map values, Sets, and plain objects. Map/Set order sensitivity is pinned current behavior, not a promise. Arrays from another realm, RegExps with a `NaN` `lastIndex`, getters, proxies, other cycle carriers, and pairs that differ only in a back-edge target are outside its grammar; pinned cases keep equality's cross-realm length check and strict RegExp field comparison. `hash-work.test.ts` pins how visited values and array/RegExp headers count toward the structural work cap, and that equality copies a shared Map's entries once per distinct pair ([code-weight hash dispatch review](oracle-reviews/code-weight-hash-dispatch.md)). Custom string indexes do not optimize ordinary ranges, and custom cursors remain unsupported. The LIKE owner covers boolean string matching and bounded work, not nullish three-valued logic or a general Unicode collation contract. Unsupported composite cursors reject. The MultiSet consolidation owner checks keyed, single-type, and structural identity, signed zero and NaN in keyed and single-number data, the retained first record, zero-sum removal, and input record contents. It does not assert output order. Its keyed grammar includes cross-type key and value collisions, non-finite numeric keys, the `\|` delimiter, symbol and function identity, and a direct-object/object-tuple delimiter control from #1948. Eight named collision witnesses and both generated campaigns are RED on `c879ba6d` and GREEN with the repair ([#1948 review record](oracle-reviews/issue-1948-keyed-consolidation.md)); the [code-weight consolidation review](oracle-reviews/code-weight-multiset-consolidation.md) records the earlier exclusion. The keyed reference uses direct value/reference equality, including SameValueZero for numeric keys. The unkeyed fallback keeps its original key and value domains. The direct `MultiSet` owner does not prove which `@tanstack/db` query shapes produce primitive keyed values or mixed-type source keys; that needs a live-query production witness. The index owner enforces one invalid-comparator law across both BasicIndex and BTreeIndex: for each comparator, accepted numeric prefix (including the empty prefix), and probe operation (add, update, eq/range lookup, take, build), the operation throws exactly when it receives a `NaN` or non-number result and never when every comparison is valid. A `signed infinity` comparator is the valid control, and a custom collation `compare` supplied through `compareOptions` is checked the same way. Two BTree Map split histories check inserted-key reads, exact whole-range payloads/order, size, and extrema, proving split placement follows the insertion index without a post-mutation comparison. A rejected index add or remove leaves the index refining its accepted rows; update and build are not atomic. At the Collection boundary, both index types and both write paths (optimistic insert, sync commit) crash the collection: status becomes `error` and the next mutation throws, so a usable collection never holds rows its subscribers were not told about. Open: a sync source can still commit writes on a collection in `error` state, which stores unpublished rows; this is existing `markError` behavior and needs a lifecycle-owner witness. Comparator transitivity is outside this evidence. | +| Window-controller overlap | [shared infinite-query conformance](https://github.com/TanStack/db/blob/main/packages/db/tests/conformance/infinite-suite-oracle.ts), [React driver](https://github.com/TanStack/db/blob/main/packages/react-db/tests/infinite-query-conformance.test.tsx), [Vue driver](https://github.com/TanStack/db/blob/main/packages/vue-db/tests/infinite-query-conformance.test.ts), [Svelte driver](https://github.com/TanStack/db/blob/main/packages/svelte-db/tests/infinite-query-conformance.svelte.test.ts), [review record](oracle-reviews/dec-03-window-overlap.md) | Four or five ordered source rows, two window-settlement orders, and public snapshots after each settlement, a subscribed observer update, a detached controller read, and explicit recovery. Insertion and removal of the fifth row distinguish both continuation directions while an earlier error remains visible. The detached read follows a source change with no controller subscriber; its preloaded Collection retains the five-row window. The exact overlap uses the exported DB controller in each package realm. Framework hooks expose no controller preload, so this cell does not establish a hook scheduling path; direct hook paging remains in the adjacent shared scenarios. An unsubscribed controller has no notification claim. | +| Structural values and ordered primitives | [hash values](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/hash-oracle.property.test.ts), [hash identity](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/hash-identity-oracle.property.test.ts), [MultiSet consolidation](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/multiset-consolidate-oracle.property.test.ts), [hash graphs](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/hash-graph-oracle.property.test.ts), [mixed hash graphs](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/hash-mixed-graph-oracle.property.test.ts), [hash retry](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/hash-failure-retry-oracle.property.test.ts), [comparison](https://github.com/TanStack/db/blob/main/packages/db/tests/comparison-oracle.property.test.ts), [deep equality](https://github.com/TanStack/db/blob/main/packages/db/tests/utils-oracle.property.test.ts), [cursor](https://github.com/TanStack/db/blob/main/packages/db/tests/cursor-oracle.property.test.ts), [indexes](https://github.com/TanStack/db/blob/main/packages/db/tests/index-update-oracle.property.test.ts), [BTree Map](https://github.com/TanStack/db/blob/main/packages/db/tests/btree-map-oracle.test.ts), [query identity](https://github.com/TanStack/db/blob/main/packages/db/tests/query/identity-output-shape-oracle.test.ts), [LIKE semantics](https://github.com/TanStack/db/blob/main/packages/db/tests/query/compiler/evaluators-oracle.test.ts) | Independent flat values, graph topology, algebraic laws, Map/group/sort recomputation, expression denotation, custom comparator dispatch/reference identity/index compatibility, LIKE wildcard refinement, compiled output bags, declared value-pair agreement between D2 equality keys and IR equality operands, and Collection collation with exact public scan/index order and one-index reuse across repeated reads. The auto-index cells cross BasicIndex and BTreeIndex; scan cells omit indexes. Both paths cover lexical and numeric `en-US` locale defaults plus an explicit ordinary locale override of a numeric default. An unindexed six-row work cell bounds Collection collation resolution to at most two reads per ordered scan: one index-path check and one scan clause. Other locales and ordered histories are outside this owner. The identity pair grammar covers primitives, signed zero, NaN/invalid Date, valid Date/timestamp, binary/Buffer, Temporal, nested references, symbols, and functions; fixed and sampled pairs do not prove every JavaScript value or hash collision freedom. Ref proxies are expressions rather than literal values in this lane. The deep-equality owner also pins that `deepEquals` ignores Map and Set insertion order, RegExp `lastIndex`, array holes, and typed-array class, the rules draft equality keeps. It also pins that objects of another class differ, that plain and null-prototype objects are one class, that a class instance without enumerable keys equals only itself, that URLs compare by `href`, and that typed-array elements compare like numbers. The hash-values owner samples Set/object and Map/object type-marker distinctions in fixed and random campaigns with seed-and-path replay; collision freedom is not promised. The hash-identity owner checks `hash` and `equalHashValues` against one spec-level identity model: primitives with signed zero, NaN, and bigint; reference leaves (functions, registered handles, `File`, binary over 128 bytes); Date, binary, Temporal, and RegExp headers; array length and holes; Map and Set insertion order; and object keys in any order, for acyclic values and for cycles through arrays, Map values, Sets, and plain objects. Map/Set order sensitivity is pinned current behavior, not a promise. Arrays from another realm, RegExps with a `NaN` `lastIndex`, getters, proxies, other cycle carriers, and pairs that differ only in a back-edge target are outside its grammar; pinned cases keep equality's cross-realm length check and strict RegExp field comparison. `hash-work.test.ts` pins how visited values and array/RegExp headers count toward the structural work cap, and that equality copies a shared Map's entries once per distinct pair ([code-weight hash dispatch review](oracle-reviews/code-weight-hash-dispatch.md)). Custom string indexes do not optimize ordinary ranges, and custom cursors remain unsupported. The LIKE owner covers boolean string matching and bounded work, not nullish three-valued logic or a general Unicode collation contract. Unsupported composite cursors reject. The MultiSet consolidation owner checks keyed, single-type, and structural identity, signed zero and NaN in keyed and single-number data, the retained first record, zero-sum removal, and input record contents. It does not assert output order. Its keyed grammar includes cross-type key and value collisions, non-finite numeric keys, the `\|` delimiter, symbol and function identity, and a direct-object/object-tuple delimiter control from #1948. Eight named collision witnesses and both generated campaigns are RED on `c879ba6d` and GREEN with the repair ([#1948 review record](oracle-reviews/issue-1948-keyed-consolidation.md)); the [code-weight consolidation review](oracle-reviews/code-weight-multiset-consolidation.md) records the earlier exclusion. The keyed reference uses direct value/reference equality, including SameValueZero for numeric keys. The unkeyed fallback keeps its original key and value domains. The direct `MultiSet` owner does not prove which `@tanstack/db` query shapes produce primitive keyed values or mixed-type source keys; that needs a live-query production witness. The index owner enforces one invalid-comparator law across both BasicIndex and BTreeIndex: for each comparator, accepted numeric prefix (including the empty prefix), and probe operation (add, update, eq/range lookup, take, build), the operation throws exactly when it receives a `NaN` or non-number result and never when every comparison is valid. A `signed infinity` comparator is the valid control, and a custom collation `compare` supplied through `compareOptions` is checked the same way. Two BTree Map split histories check inserted-key reads, exact whole-range payloads/order, size, and extrema, proving split placement follows the insertion index without a post-mutation comparison. A rejected index add or remove leaves the index refining its accepted rows; update and build are not atomic. At the Collection boundary, both index types and both write paths (optimistic insert, sync commit) crash the collection: status becomes `error` and the next mutation throws, so a usable collection never holds rows its subscribers were not told about. Open: a sync source can still commit writes on a collection in `error` state, which stores unpublished rows; this is existing `markError` behavior and needs a lifecycle-owner witness. Comparator transitivity is outside this evidence. | | WHERE predicate publication | [WHERE predicate publication oracle](https://github.com/TanStack/db/blob/main/packages/db/tests/query/where-predicate-publication-oracle.property.test.ts) | An independent Kleene evaluator judges `eq`/`not`/`and`/`or` predicates over strings, a normalization-prefixed string, booleans, numbers, `NaN`, a valid Date, `null`, a missing field, and virtual fields. Snapshot histories with pending optimistic inserts compare a live query, direct subscribers with and without initial state, and `currentStateAsChanges`; change histories apply multi-key sync transactions, including reinsertion of a key deleted earlier, and compare every consumer's key set after each commit, on scan and `BasicIndex` paths. Peer subscribers share one field with different literals, plus one on a virtual field, so every published change must reach exactly the subscribers whose predicate it can satisfy; routing mutants that ignored the previous value, ignored the field, delivered a change twice, or routed while stale published rows awaited reconciliation fail here. Fixed witnesses cover a layout-only publication reaching a filtered subscriber as one empty batch, a filtered subscriber's empty Collection-readiness batch, retraction of a vanished row after eager cleanup and restart, and the new row plus exact subscriber update payload when a same-key row stays TRUE. A stale-live-value mutant survives the generated membership checks but fails the payload witness. A focused [property-visibility test](https://github.com/TanStack/db/blob/main/packages/db/tests/query/where-prefilter-property-visibility.test.ts) compares the public unindexed snapshot with the enriched-row contract for inherited, non-enumerable, enumerable-own, and nested getter paths; the pre-fix stored-row shortcut failed three of its four controls. Other property-descriptor and stateful-getter histories remain outside those fixed controls. Hostile mutants for FALSE-for-UNKNOWN `eq`, `or` or number-literal subscription prefilters, a prefilter that ignores the previous value, a skipped readiness batch, a skip while stale published rows await reconciliation, and an unindexed snapshot scan that reads only synced rows while an optimistic insert or delete changes visibility passed the prior `@tanstack/db` suite and fail here. Change routing withholds a dropped row from an `eq` subscription before its sent key could be recorded, so a mutant that records dropped rows as sent is equivalent for routed predicates in this oracle. A focused `collection-subscription.test.ts` witness checks that a dropped insert or update, alone or beside a matching change, cannot advance a limited subscription's page offset under a routed `eq` and an unrouted `or` predicate; the unrouted cases beside a matching change kill that mutant, and the unrouted `alone` case does not. A loose-equality prefilter is an equivalent mutant: it only skips less. Skipping during truncate replay also survives; the replay's baseline diff re-derives the same retraction, so the guard keeps the prior dataflow without its own witness. Generated cleanup and restart histories for filtered subscribers remain open for the lifecycle publication owner. No-op updates, other comparison operators, Temporal and binary operands, joins, ordering, optimistic updates, and truncate are outside this owner. It runs in `@tanstack/db`'s `test:oracles` campaign. The [2026-09-30 review](https://github.com/TanStack/db/blob/main/docs/contributing/oracle-reviews/2026-09-30-where-predicate-and-join-keys.md) records each ORC outcome. Change routing was later removed in favor of pooled live queries; the routing mutants above are historical, and the same peer laws now check plain subscription dispatch. The unindexed snapshot prefilter was restored for compiled queries as one stored-row `eq` test on a string or boolean literal. Its property-visibility test also covers the reverse direction: a stored row with an inherited or non-enumerable field must still match `isUndefined` on that field, which a scan that evaluated the full predicate on stored rows fails. | | Joined result keys | [Joined result key oracle](https://github.com/TanStack/db/blob/main/packages/db/tests/query/join-result-key-oracle.property.test.ts) | A nested-loop model recomputes the pair set of an inner, left, or full join over source keys drawn from plain, comma-bearing, bracket-bearing, and quoted strings, numbers beside the strings that print the same, both infinities, and `NaN`. After preload and each synced group change, the published rows must equal the model's pairs and the result key count must equal the row count. The comma-joined key encoding fails its two pinned histories and both campaigns; plain `JSON.stringify`, which prints infinities as the missing-side `null`, fails the pinned infinity history and both campaigns. A pinned history in which a `NaN`-keyed pair leaves and re-forms fails when the join index compares source-key prefixes with `===`. Joins over subqueries, more than two sources, custom `getKey`, and optimistic mutations are outside this owner. It runs in `@tanstack/db`'s `test:oracles` campaign. The [2026-09-30 review](https://github.com/TanStack/db/blob/main/docs/contributing/oracle-reviews/2026-09-30-where-predicate-and-join-keys.md) records each ORC outcome. | | D2 Index storage | [Index refinement oracle](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/index-refinement-oracle.property.test.ts) | A plain-`Map` model sums multiplicities under a type-and-value identity in which `NaN` equals `NaN` and `-0` equals `0`. Histories of up to twelve additions to two keys mix prefixed arrays with `NaN`, `0`, `-0`, `1`, `'1'`, `1n`, and `'a'` prefixes and unprefixed values, with cancellation and reappearance. After each addition, `get` and `has` must equal the model. Comparing prefixes with `===`, which disagrees with the `Map` that holds them, fails three pinned histories and both campaigns; the `-0` control passes under both. Compaction, presence tracking, and structural payloads are outside this owner; the join operator tests and incrementalization law own operator behavior. | -| Pooled live queries | [pooled live query oracle](https://github.com/TanStack/db/blob/main/packages/db/tests/query/pooled-live-query-oracle.property.test.ts) | An independent `eq` model (nullish UNKNOWN, Date as timestamp, `NaN` equal to `NaN`, `-0` equal to `0`) gives membership; a live-query Collection compiled for the same query gives order, values, and status. Histories mix sync transactions, optimistic writes confirmed or rolled back, peer mounts and unmounts, and source cleanup and restart, including cleanup while a write is pending and a mount between cleanup and restart. Wholesale observers must match after every step, granular changes must match a reference observer by type, key, value, and previous value and replay to the model's rows, the layout revision must advance when keys reorder, and observing must never build the live-query Collection. Peers may add a residual `not(eq(...))` conjunct, which the model evaluates itself; a view that ignores it, reports an unfiltered `entries()`, or delivers a row entering or leaving it as an update fails it. Other residual operators use the same compiler evaluator but are not generated. Peers may also order their rows by `id` or by a `g` that can be null, with explicit `nulls`; order comes from the reference. A comparator that ignores direction or `nulls`, an order left out of the partition key, and key order instead of the query's order each fail the pinned reorder history and both campaigns. A partition that ignores a row's previous group, orders by arrival, skips normalization, skips the initial snapshot, follows the source's status after cleanup, or never terminates fails it. Two shared conformance scenarios (`eq-filter-rows`, `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, and `eq-filter-peers` checks through `subscriberCount` that each adapter shares one source subscription per partition. A focused [release-timing test](https://github.com/TanStack/db/blob/main/packages/db/tests/query/pooled-live-query-gc.test.ts) compares when a pooled query and a live-query Collection release their sources across `gcTime` 1, 100, 0, and `Infinity`, with and without a subscriber, and with no `gcTime`, where both use the live-query Collection default, checks that a partition waits for its views' longest `gcTime`, checks that a view resubscribed after its partition released follows later source writes as its live-query Collection does, including a view with a residual conjunct, and checks that a partition that subscribes again still serves new mounts from one source subscription. Further focused witnesses check that a partition keeps groups only for values that have rows or watchers, that a detached reader never sees a dropped group's revision reused, keep a pooled query's public Collection live while the view is observed, accept it as a query source, and check that a pooled query turns terminal when source cleanup starts while the adapter's cleanup is still pending, as a live-query Collection does. A pinned oracle witness checks that an `eq` path whose getter throws excludes the row on both paths; a pooled path that rethrows fails it. The pooled oracle's grammar never releases a partition, so release and resubscribe histories rely on these fixed witnesses; a fixed delay, a missing unsubscribed floor, a last-`gcTime`-wins rule, and releasing at `gcTime` 0 each fail it. The [2026-10-01 review](oracle-reviews/2026-10-01-pooled-live-queries.md) records each ORC outcome. | +| Pooled live queries | [pooled live query oracle](https://github.com/TanStack/db/blob/main/packages/db/tests/query/pooled-live-query-oracle.property.test.ts) | An independent `eq` model (nullish UNKNOWN, Date as timestamp, `NaN` equal to `NaN`, `-0` equal to `0`) gives membership; a live-query Collection compiled for the same query gives order, values, and status. Histories mix sync transactions, optimistic writes confirmed or rolled back, peer mounts and unmounts, and source cleanup and restart, including cleanup while a write is pending and a mount between cleanup and restart. Wholesale observers must match after every step, granular changes must match a reference observer by type, key, value, and previous value and replay to the model's rows, the layout revision must advance when keys reorder, and observing must never build the live-query Collection. Peers may add a residual `not(eq(...))` conjunct, which the model evaluates itself; a view that ignores it, reports an unfiltered `entries()`, or delivers a row entering or leaving it as an update fails it. Other residual operators use the same compiler evaluator but are not generated. Peers may also order their rows by `id` or by a `g` that can be null, with explicit `nulls`; order comes from the reference. A comparator that ignores direction or `nulls`, an order left out of the partition key, and key order instead of the query's order each fail the pinned reorder history and both campaigns. A partition that ignores a row's previous group, orders by arrival, skips normalization, skips the initial snapshot, follows the source's status after cleanup, or never terminates fails it. Two shared conformance scenarios (`eq-filter-rows`, `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, and `eq-filter-peers` checks through `subscriberCount` that each adapter shares one source subscription per partition. A focused [release-timing test](https://github.com/TanStack/db/blob/main/packages/db/tests/query/pooled-live-query-gc-oracle.test.ts) compares when a pooled query and a live-query Collection release their sources across `gcTime` 1, 100, 0, and `Infinity`, with and without a subscriber, and with no `gcTime`, where both use the live-query Collection default, checks that a partition waits for its views' longest `gcTime`, checks that a view resubscribed after its partition released follows later source writes as its live-query Collection does, including a view with a residual conjunct, and checks that a partition that subscribes again still serves new mounts from one source subscription. Further focused witnesses check that a partition keeps groups only for values that have rows or watchers, that a detached reader never sees a dropped group's revision reused, keep a pooled query's public Collection live while the view is observed, accept it as a query source, and check that a pooled query turns terminal when source cleanup starts while the adapter's cleanup is still pending, as a live-query Collection does. A pinned oracle witness checks that an `eq` path whose getter throws excludes the row on both paths; a pooled path that rethrows fails it. The pooled oracle's grammar never releases a partition, so release and resubscribe histories rely on these fixed witnesses; a fixed delay, a missing unsubscribed floor, a last-`gcTime`-wins rule, and releasing at `gcTime` 0 each fail it. The [2026-10-01 review](oracle-reviews/2026-10-01-pooled-live-queries.md) records each ORC outcome. | | Flat-row change tracking | [flat change tracking oracle](https://github.com/TanStack/db/blob/main/packages/db/tests/flat-change-tracking-oracle.property.test.ts) | Generated callbacks over flat rows, frozen or not and with or without a non-enumerable field (assignments of `0`, `-0`, `NaN`, `undefined`, functions, and fresh objects; reverts; deletions; added fields; data and accessor `defineProperty`; stored drafts; throws), run through the flat tracker, the draft proxy, and an independent model, which must report the same change sets with `0` and `-0` equal, or throw the same error and leave the rows unchanged. Defining a field acts as assigning it, and a non-enumerable field is row data only once written; the proxy broke three of those laws on `main` and the flat tracker one. Diffs using `!==`, `Object.is` alone, or no deletions fail it. It found that the proxy dropped a field added as `undefined` when another field reverted; the pinned history and both campaigns fail without that fix. Non-flat rows must fall back. The [2026-10-01 review](oracle-reviews/2026-10-01-pooled-live-queries.md) records each ORC outcome. | | Virtual props cache | [cache laws](https://github.com/TanStack/db/blob/main/packages/db/tests/virtual-props-cache.test.ts) | Focused laws for the per-key cache of rows read with virtual props: a change's published value is the row later `get` and `toArray` reads return, for every subscriber, after sync and local writes, and a key that is deleted or rolled back leaves the cache. Enriching the value before the previous value fails the first two; skipping the drop on delete events fails the third. Rows read with virtual props through other paths, such as joins, are outside these laws. | -| Local-only direct writes | [direct write witnesses](https://github.com/TanStack/db/blob/main/packages/db/tests/local-only-direct-write.test.ts) | Focused witnesses pin when a local-only direct write skips the optimistic stage: a completed transaction and one publication per write, and the fallbacks for a pending, persisting, or ambient transaction and a user handler, for insert, update, and delete. Each history also runs on a local-only Collection whose handlers resolve, which must match its rows, change batches, errors, and transaction states, across mixed multi-key batches, a batch that fails midway, schema rejection, and handler rollback. Mutants that drop each guard, write only the first mutation, or never complete the transaction fail them. The change-event history oracle drives the direct path through generated histories (about two thousand writes per run); removing the guard, or guarding only persisting transactions, fails these witnesses. | +| Local-only direct writes | [direct write witnesses](https://github.com/TanStack/db/blob/main/packages/db/tests/local-only-direct-write-oracle.test.ts) | Focused witnesses pin when a local-only direct write skips the optimistic stage: a completed transaction and one publication per write, and the fallbacks for a pending, persisting, or ambient transaction and a user handler, for insert, update, and delete. Each history also runs on a local-only Collection whose handlers resolve, which must match its rows, change batches, errors, and transaction states, across mixed multi-key batches, a batch that fails midway, schema rejection, and handler rollback. Mutants that drop each guard, write only the first mutation, or never complete the transaction fail them. The change-event history oracle drives the direct path through generated histories (about two thousand writes per run); removing the guard, or guarding only persisting transactions, fails these witnesses. | | Reused sync row objects | [reused row witness](https://github.com/TanStack/db/blob/main/packages/db/tests/sync-reused-row.test.ts) | Focused witnesses for a sync source that changes a stored row object in place: in development, writing it again as an update without `previousValue` throws, while the same write with `previousValue`, or with a new object, moves the row out of an `eq` live query. Production skips the check. The check compares a shallow snapshot taken when the object was written, so it misses changes to nested fields; a write that names `previousValue` and a row whose fields throw on read are not checked. | | Index suggestions | [collection-size suggestion oracle](https://github.com/TanStack/db/blob/main/packages/db/tests/index-suggestion-oracle.test.ts) | A public filtered live-query Collection checks manual/default, eager, threshold, matching-index, and unrelated-index cases against the documented collection-size suggestion policy. The original manual-silence/eager-noise implementation failed two expected observations. The owner does not judge repeated-query warning volume, slow-query timing, query work, production-build suppression, or every query shape. It runs in `@tanstack/db`'s `test:oracles` campaign. | | Minified DB public API | [consumer bundle check](https://github.com/TanStack/db/blob/main/scripts/test-minified-db.mjs) | CI builds `@tanstack/db`, then bundles its built `dist` entry with db-ivm inlined through esbuild `minify: true`. The build renames TypeScript-private members from `packages/db/mangle-cache.json`, so this lane runs against the renamed output that consumers install. It rejects a `dist` that is older than `src`, the cache, or the package's build configuration. `pnpm --filter @tanstack/db test:dist` also runs five db test files against the built `dist`, chosen for coverage of the modules with the most renamed members. `pnpm check:mangle` fails when a cached name is used other than as a private member in db src, is read by another package, appears as a string, or has a short name that collides with a source identifier ([private-member mangling review](oracle-reviews/code-weight-private-member-mangling.md)). It checks every exported error class's current public `name`, the built-in `BasicIndex` resolver name in index metadata and its event, complete query rows (after removing the four documented virtual fields) against an independent array filter/sort/projection, and one live update. The `new.target.name`, public-member mangle, and extra-output-field calibration modes fail at the intended observations. This fixed slice does not replace the unminified generated oracles, exercise framework adapters, or establish stable names for custom index resolvers. | | Boundary refinements | [cleanup/restart](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-cleanup-restart-oracle.test.ts), [idle cleanup](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-idle-cleanup.test.ts), [issue #1891 async-cleanup review](oracle-reviews/issue-1891-async-cleanup.md), [issue #1891 cleanup-start follow-up](oracle-reviews/issue-1891-cleanup-start-followup.md), [metadata publication](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-metadata-publication-oracle.property.test.ts), [state retention](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-state-retention-oracle.property.test.ts), [acquisition cells](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-subscription-lifecycle-oracle.test.ts), [D2 source reconciliation](https://github.com/TanStack/db/blob/main/packages/db/tests/d2-source-reconciliation-oracle.property.test.ts), [top-K support windows](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/operators/topk-support-window-oracle.test.ts), [nested Query work](https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/includes-work-counter-oracle.test.ts) | Explicit lifecycle products, independent source maps and weighted relations, exact publication cuts, support/multiplicity, and value-plus-work observations. These refine the larger subsystem models; they do not replace them. | -| Small structures and test mechanics | [SortedMap](https://github.com/TanStack/db/blob/main/packages/db/tests/SortedMap.test.ts), [cleanup queue](https://github.com/TanStack/db/blob/main/packages/db/tests/cleanup-queue.property.test.ts), [live-query GC clock](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-gc-clock.test.ts), [guarded replay](https://github.com/TanStack/db/blob/main/packages/db/tests/oracle-replay.test.ts) | Map/full-sort and elapsed appointment-list models with executed target/seed/path checks. SortedMap also checks deferred bulk writes, array-movement work, scan reuse, live iterators, runtime `undefined` keys, and public single-transaction and queued-transaction Collection sync paths. It does not settle the contract for comparator-observed values mutated after publication or every legal iterator/mutation interleaving. Wall-clock steps do not move due times, and a focused public witness checks source subscription release. Callback-reentrant scheduling, OS suspend/resume, environments without `performance.now()`, and fake/real Performance clock replacement while GC is pending remain outside this coverage. Tests must drain or reset pending GC before switching timer providers. | +| Small structures and test mechanics | [SortedMap](https://github.com/TanStack/db/blob/main/packages/db/tests/SortedMap-oracle.test.ts), [cleanup queue](https://github.com/TanStack/db/blob/main/packages/db/tests/cleanup-queue-oracle.property.test.ts), [live-query GC clock](https://github.com/TanStack/db/blob/main/packages/db/tests/collection-gc-clock.test.ts), [guarded replay](https://github.com/TanStack/db/blob/main/packages/db/tests/oracle-replay.test.ts) | Map/full-sort and elapsed appointment-list models with executed target/seed/path checks. SortedMap also checks deferred bulk writes, array-movement work, scan reuse, live iterators, runtime `undefined` keys, and public single-transaction and queued-transaction Collection sync paths. It does not settle the contract for comparator-observed values mutated after publication or every legal iterator/mutation interleaving. Wall-clock steps do not move due times, and a focused public witness checks source subscription release. Callback-reentrant scheduling, OS suspend/resume, environments without `performance.now()`, and fake/real Performance clock replacement while GC is pending remain outside this coverage. Tests must drain or reset pending GC before switching timer providers. | The Query ownership oracle checks that a direct-write promise stays pending while a controlled persisted adapter holds its sync commit and settles after @@ -492,7 +492,7 @@ installed Electric SDK. It checks distinct per-Collection schema versions, unchanged public and durable rows when a follower opens, leadership transfer with later source rows, and recovery of partial-row loss or a fully empty pre-key-ledger baseline with a stale resume marker. A wrapped source-commit -test in `packages/browser-db-sqlite-persistence/tests/browser-coordinator.test.ts` +test in `packages/browser-db-sqlite-persistence/tests/browser-coordinator-oracle.test.ts` checks scheduler entry before the writer-lock request; the old bypass fails at that order assertion. The live recovery histories also guard the resulting progress. These bounded histories do not prove Firefox/Zen, @@ -508,7 +508,7 @@ begins an Electric source transaction during that hold; and the row-bearing commit is released only after the hydration scope exits. It checks the old row before release and the exact new public and durable row afterward, then after follower takeover and reopen. A late-buffer mutant leaves the old row in both -observations. The [core persistence tests](https://github.com/TanStack/db/blob/main/packages/db-sqlite-persistence-core/tests/persisted.test.ts) +observations. The [core persistence tests](https://github.com/TanStack/db/blob/main/packages/db-sqlite-persistence-core/tests/persisted-oracle.test.ts) own the adjacent during/straddling/after settlement, FIFO, abort, and failure histories. The live oracle does not prove eager-startup overlap, other mutation shapes, arbitrary Electric fetch schedules, Firefox/Zen, React rendering, or @@ -520,11 +520,11 @@ preserves the live-host and mutant evidence. The post-merge review added three missing domains to existing owners: -- [Top-K batch contracts](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/operators/topk-batch-contract.test.ts) +- [Top-K batch contracts](https://github.com/TanStack/db/blob/main/packages/db-ivm/tests/operators/topk-batch-contract-oracle.test.ts) cross sparse-array length/holes and RegExp source/flags/position with equal controls, replacement order, hash consolidation, and actual retained graph output. Ordinary replacements also run without the global `File` constructor. -- [Leadership replay](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/leadership-replay.property.test.ts) +- [Leadership replay](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/leadership-replay-oracle.property.test.ts) holds real storage-read delivery across successful and permanently rejected durable removals, with bounded scans, concurrent loads, and unfinished peers. This is distinct from exactly-once execution across independent owners. @@ -581,7 +581,7 @@ Core guarded replay is run from `packages/db`, for example: TANSTACK_DB_ORACLE_SEED=1813 TANSTACK_DB_ORACLE_PATH=0 \ TANSTACK_DB_ORACLE_PROPERTY=live-query-observer.granular-history \ node --import tsx tests/oracle-replay.ts \ - tests/live-query-observer-history.property.test.ts \ + tests/live-query-observer-history-oracle.property.test.ts \ -t 'granular listeners follow the eligibility ledger with a random or replayed seed' \ --coverage.enabled=false --typecheck.enabled=false ``` @@ -632,24 +632,24 @@ a hostile wrong-answer control, and an explicit statement of remaining limits. row-dropping hostile control prove the shim accepts those envelopes without mutating them. Owner: `packages/react-native-db-sqlite-persistence/tests/fixtures/op-sqlite-provider-results.ts` - and `packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver.test.ts`. + and `packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver-oracle.test.ts`. Native device/host execution remains a separate runtime receipt. - [x] **Minimal ambiguity and name invariance.** Generate one-field and otherwise minimally distinguishable results. Renaming a selected column to a structural-looking alias must not turn a data row into a write envelope. - Owner: `packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver.test.ts`. + Owner: `packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver-oracle.test.ts`. - [x] **Carrier coexistence and representation symmetry.** Cross `rows`, `rawRows`, `columnNames`, and supported result containers, including legal coexistence. Equivalent array and object forms must agree on rows or on the documented rejection. Owner: - `packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver.test.ts` + `packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver-oracle.test.ts` and the shared SQLite driver contract. - [x] **Shared-handle transaction admission.** Concurrent driver wrappers for one provider database handle serialize root transactions. Nested work must use the transaction driver supplied to the callback on hosts without async context propagation. Owners: `packages/node-db-sqlite-persistence/tests/node-driver.test.ts` and - `packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver.test.ts`. + `packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver-oracle.test.ts`. - [x] **Transitions at every relevant await.** Hold each coordination boundary, then change leadership, remote-subset ownership, abort state, cleanup, or restart generation before release. Owners: browser/electron coordinator, @@ -671,7 +671,7 @@ a hostile wrong-answer control, and an explicit statement of remaining limits. the sync-absent `forceReloadSubset` route crosses the same startup evidence states but records baseline visibility as unobserved because that API does not expose baseline hydration. Owner: - `packages/db-sqlite-persistence-core/tests/persisted.test.ts`. + `packages/db-sqlite-persistence-core/tests/persisted-oracle.test.ts`. - [x] **Deterministic value-and-work laws.** Pair row correctness with stable statement, scan, trigger, or queue-cardinality observations where the subsystem promises bounded work. Owners: SQLite resume snapshots, Electric @@ -696,7 +696,7 @@ a hostile wrong-answer control, and an explicit statement of remaining limits. on-demand subsets. A sound implementation needs an atomic multi-subset API; loading all rows or accepting a metadata/row torn pair is not equivalent. RED evidence and the deferred executable placeholder live in - `packages/db-sqlite-persistence-core/tests/persisted.test.ts` under R5-007. + `packages/db-sqlite-persistence-core/tests/persisted-oracle.test.ts` under R5-007. - [x] **Joined aggregate and `singleResult` subquery histories.** `packages/db/tests/query/subquery-user-value-oracle.test.ts` checks flat and diff --git a/docs/contributing/oracle-reviews/2026-10-02-glossary-alignment.json b/docs/contributing/oracle-reviews/2026-10-02-glossary-alignment.json new file mode 100644 index 0000000000..9cccf4a5b0 --- /dev/null +++ b/docs/contributing/oracle-reviews/2026-10-02-glossary-alignment.json @@ -0,0 +1,1159 @@ +{ + "reviewedCommit": "f993daf838da4905d3a327cf6c66d8bdf16d106b", + "implementationBase": "b940a363a7631c49e14dc67e2adeda0a96dc366c", + "auditCommit": "06cab6fc7b808acfbfb3af1eb2fc1fdc3c9f0fa8", + "scope": "Glossary alignment and filename discovery. This is not a full ORC-001–014 conformance audit or a runtime bug-class closure claim.", + "findings": [ + { + "id": "01_collection-1", + "severity": "medium", + "kind": "meaning-conflict", + "term": "private replacement / retirement / publication", + "evidence": "\"Failure retires that replacement. Independent live source work remains public.\" The model instead sets replacement.failed and returns while the publication barrier remains open (lines 299–315); source writes continue into replacement.rows (431–434). The pinned test \"keeps later source changes private after a failed replay\" (1948–1967) demonstrates the opposite boundary, while retirement is tested only after final owner release (1970 onward).", + "glossary": "Runtime terms: private replacement is source/graph state withheld while authoritative replay or repair is incomplete; public snapshot is the last coherent exposed rows; publication makes the coherent result observable. ARCHITECTURE.md normative publication law keeps the prior public result and later partial changes private after failure.", + "recommendation": "State that replay failure keeps the replacement and later source changes private while retaining the last public snapshot. State separately that final logical-demand retirement can retire the replacement barrier without publishing it. Preserve the current model and tests.", + "relatedPaths": [ + "packages/db/tests/collection-subscription-lifecycle-grammar.ts", + "packages/db/tests/collection-subscription-replay-oracle.property.test.ts", + "packages/db/src/query/live/ARCHITECTURE.md" + ], + "auditPath": "packages/db/tests/collection-subscription-lifecycle-publication.property.test.ts", + "auditLine": 30, + "auditEndLine": 32, + "currentPath": "packages/db/tests/collection-subscription-lifecycle-publication-oracle.property.test.ts", + "resolution": "Failed truncate replay retains private replacement and later source changes. Final logical-owner retirement can discard the barrier without publication.", + "status": "resolved within terminology scope" + }, + { + "id": "01_collection-2", + "severity": "medium", + "kind": "meaning-conflict", + "term": "sync run / unsubscribe", + "evidence": "\"`restart`, `cleanup`, and `unsubscribe` change the enclosing sync run.\" In the unsubscribe branch (584–589), the reducer releases this subscription's attempts, clears owners, and sets unsubscribed; it leaves active, syncRunGeneration and collectionStatus untouched. Cleanup and restart are separately allowed after unsubscribe (353–365), proving the sync run outlives that subscription.", + "glossary": "Runtime terms: sync run is one Collection sync invocation and installed resources until cleanup invalidates them; subscription is a consumer with its own demands/lifecycle; cleanup ends the current sync run; restart starts another.", + "recommendation": "Split the sentence: cleanup ends the current sync run; restart starts a new sync run; unsubscribe ends this subscription and retires its logical subset owners/acquisition leases without itself ending the Collection sync run.", + "relatedPaths": [ + "packages/db/tests/collection-subscription-lifecycle-history.property.test.ts", + "packages/db/tests/collection-subscription-lifecycle-publication.property.test.ts" + ], + "auditPath": "packages/db/tests/collection-subscription-lifecycle-grammar.ts", + "auditLine": 17, + "auditEndLine": 18, + "currentPath": "packages/db/tests/collection-subscription-lifecycle-grammar-oracle.ts", + "resolution": "Cleanup ends a sync run, restart starts another, and unsubscribe ends its subscription and ownership claims.", + "status": "resolved within terminology scope" + }, + { + "id": "01_collection-3", + "severity": "medium", + "kind": "missing-mapping", + "term": "PhysicalAcquisitionState / starting", + "evidence": "The contract calls this \"a small physical-acquisition state\" (19), and PhysicalAcquisitionState includes \"starting\". The driver records starting:release/starting:cleanup even for outcome === throw (1143–1161), while targetStarted explicitly excludes throws and cleanup-invalidated startup (1137), and no unload is expected (1168–1169). Thus the state domain also covers tentative acquisition attempts before any physical acquisition or lease exists.", + "glossary": "Demand/pagination terms: acquisition attempt starts at adapter invocation; only acceptance establishes physical acquisition and acquisition lease. Model alignment rules require explicit mappings for combined/split production concepts.", + "recommendation": "Name this domain AcquisitionLifecycleState (or another explicitly model-only abstraction), and document none=no accepted work, starting=tentative acquisition attempt, active=accepted physical acquisition/lease, obsolete=retired work, failed-release=release already attempted. Distinguish attempt cancellation from acquisition release in the interaction labels. This preserves the finite model without copying production machinery.", + "relatedPaths": [ + "packages/db/src/collection/subscription.ts", + "packages/db/tests/collection-subscription-lifecycle-grammar.ts" + ], + "auditPath": "packages/db/tests/collection-subscription-lifecycle-oracle.test.ts", + "auditLine": 185, + "auditEndLine": 199, + "currentPath": "packages/db/tests/collection-subscription-lifecycle-oracle.test.ts", + "resolution": "AcquisitionLifecycleState explicitly combines tentative attempts, accepted acquisitions, and release states. Its retire action maps each case.", + "status": "resolved within terminology scope" + }, + { + "id": "02_optimistic_values-1", + "severity": "medium", + "kind": "meaning-conflict", + "term": "publication / published row", + "evidence": "\"const published = (changes as Partial).items\" and \"published row, ${context}\" label a field returned by withChangeTracking as a publication. The driver at lines 216–218 only extracts changes from a plain draft; it creates no Collection and observes no read/event/downstream publication. The opening contract likewise says the draft \"publishes what the native row now holds\" (11–12). The same conflation occurs for typed arrays (386–391), proxy-iteration extraction-only checks (15, 152–161, 298–325), proxy-detachment's extraction-only alias check (749–760), and proxy-revert's \"before the draft publishes\" checkpoint (33–36).", + "glossary": "Runtime terms: publication is the boundary that makes one coherent result observable to reads, events, and downstream queries. Model alignment rule forbids giving a narrower model-only boundary the name of a stronger production concept.", + "recommendation": "Call these results a detached change set, detached field value, or reconstructed draft row; call the checkpoint change extraction or callback return. Use publication for the existing tests that actually observe a public Collection. Update the small source comment in proxy.ts:273 that uses publication for the same detachment operation, or explicitly map draft extraction as a prerequisite of later Collection publication.", + "relatedPaths": [ + "packages/db/tests/proxy-iteration-contract.test.ts", + "packages/db/tests/proxy-detachment-contract.test.ts", + "packages/db/tests/proxy-revert-oracle.property.test.ts", + "packages/db/src/proxy.ts" + ], + "auditPath": "packages/db/tests/proxy-native-methods.property.test.ts", + "auditLine": 223, + "auditEndLine": 228, + "currentPath": "packages/db/tests/proxy-native-methods-oracle.property.test.ts", + "resolution": "Draft extraction produces detached changes and values. Publication refers to observable Collection state.", + "status": "resolved within terminology scope" + }, + { + "id": "02_optimistic_values-2", + "severity": "low", + "kind": "meaning-conflict", + "term": "fault injection", + "evidence": "\"Fault injection proves those observations can reject wrong keys, partial batches, stale previous values, and transient fields.\" The mechanism explicitly says \"Faults act on a copy of a real callback, never on production state\" (639); for example lines 644–650 change a captured key to String(change.key). These are deliberately wrong observed answers supplied to the checker, not failures, delays, cancellations or malformed provider responses injected into the runtime.", + "glossary": "Oracle and model terms: mutant is a deliberate wrong answer or implementation used to test oracle sensitivity; fault injection is a deliberate runtime failure, delay, cancellation, or malformed response used to test a system boundary.", + "recommendation": "Change the opening claim to \"Wrong-answer mutants calibrate these observations\" or \"Captured-observation corruption proves checker sensitivity.\" Optionally rename the local fault parameter to observationMutant/corruption; retain fault injection for actual runtime boundary failures.", + "relatedPaths": [ + "packages/db/tests/optimistic-history-publication.test.ts", + "packages/db/tests/optimistic-history-outcomes.test.ts", + "packages/db/tests/optimistic-transaction-oracle.property.test.ts" + ], + "auditPath": "packages/db/tests/optimistic-history-oracle.ts", + "auditLine": 37, + "auditEndLine": 39, + "currentPath": "packages/db/tests/optimistic-history-oracle.ts", + "resolution": "Copied callback corruptions are observation mutants. Runtime fault injection remains a separate concept.", + "status": "resolved within terminology scope" + }, + { + "id": "03_includes-1", + "severity": "medium", + "kind": "meaning-conflict", + "term": "startup settlement / resolveSync / rejectSync", + "evidence": "The helper promises 'atomic source batches and explicit startup settlement.' It exports resolveSync/rejectSync (23–24) and directly aliases mockSyncCollectionOptions.utils (64–65). That utility resolves/rejects syncPendingPromise (utils.ts 328–355), which is awaited by onInsert/onUpdate/onDelete (383–393). Default source startup instead commits initialData and calls markReady synchronously (359–374). The includes optimistic driver uses source.resolveSync followed by transaction.isPersisted.promise (includes-optimistic-oracle.property.test.ts 513–514). Therefore these controls settle optimistic mutation persistence; they do not settle startup, end a sync run, or represent a sync transaction's applied receipt.", + "glossary": "Runtime terms distinguish optimistic transaction, sync transaction, sync run and qualified readiness. Demand and pagination terms define settlement as a named promise fulfilling/rejecting and applied receipt as commit()'s visibility receipt. Grammar rules require qualification of the boundary that settled.", + "recommendation": "Replace 'explicit startup settlement' with 'explicit optimistic mutation-handler fulfillment or rejection'. At this helper boundary, expose fulfillMutationPersistence/rejectMutationPersistence (or add an explicit mapping for the inherited resolveSync/rejectSync names) and state that startup publishes initial rows and marks the Collection ready synchronously. Keep source write batches and mutation persistence as separate driver operations.", + "relatedPaths": [ + "packages/db/tests/query/includes-collection-oracle.property.test.ts", + "packages/db/tests/query/includes-optimistic-oracle.property.test.ts", + "packages/db/tests/query/includes-oracle.property.test.ts", + "packages/db/tests/query/includes-publication-oracle.test.ts", + "packages/db/tests/utils.ts" + ], + "mergedFrom": [ + "02_optimistic_values-3" + ], + "additionalEvidence": "\"resolveSync: () => { syncPendingResolve!() }\" and \"rejectSync: (error: Error) => { syncPendingReject!(error) }\" settle the gate consumed by onInsert/onUpdate/onDelete via awaitSync (383–393). They do not complete the sync run, commit a sync transaction, or acknowledge source rows. The no-initial-state helper duplicates the same names (454–485). A concrete consumer in virtual-props-cache.test.ts:84 calls rejectSync solely to reject an optimistic insert's isPersisted promise.", + "auditPath": "packages/db/tests/query/includes-oracle-helpers.ts", + "auditLine": 7, + "auditEndLine": 7, + "currentPath": "packages/db/tests/query/includes-oracle-helpers.ts", + "resolution": "Legacy resolveSync/rejectSync helpers control mutation-handler settlement. Startup rows and Collection readiness occur separately.", + "status": "resolved within terminology scope" + }, + { + "id": "03_includes-2", + "severity": "medium", + "kind": "meaning-conflict", + "term": "route / active bucket / Collection facade", + "evidence": "The contract says 'Parents on the same active route share one facade' and \"Moving a parent route gives it the destination route's facade\". The actual sharing witness constructs parents { id: 1, group: 1 } and { id: 2, group: 1 }, asserts their child handles are identical, then removes each parent independently (1777–1798). These are different materialization cells and hence different route links to one shared bucket. The same opening comment later distinguishes route and bucket state (64–65), so route is not declared as a local synonym for the bucket.", + "glossary": "Live-query materialization terms: route relation = weighted links from bucket keys to materialization cells; materialization cell = one include field on one parent-row occurrence; Collection facade = stable public Collection shared by parents routed to one active bucket. ARCHITECTURE.md 546–560 gives exactly this distinction.", + "recommendation": "Write 'Parents routed to the same active bucket share one facade' and 'Moving a parent route gives it the destination bucket’s facade.' Use 'shared bucket' in the associated contract/grammar descriptions where the intended common identity is the correlation partition; retain route for the individual parent-cell link.", + "relatedPaths": [ + "packages/db/src/query/live/ARCHITECTURE.md", + "packages/db/tests/query/includes-oracle.property.test.ts" + ], + "auditPath": "packages/db/tests/query/includes-collection-oracle.property.test.ts", + "auditLine": 44, + "auditEndLine": 46, + "currentPath": "packages/db/tests/query/includes-collection-oracle.property.test.ts", + "resolution": "Parents routed to one active bucket share a Collection facade. Individual parent links remain routes.", + "status": "resolved within terminology scope" + }, + { + "id": "03_includes-3", + "severity": "low", + "kind": "ambiguous-term", + "term": "demand settlement / initial readiness", + "evidence": "The laws say 'Every reachable child demand must settle before initial readiness' and 'An obsolete demand cannot publish rows or settle a later incarnation.' Yet 51–53 correctly define demand incarnation as an interval of active logical demand that need not map to one acquisition. The matching driver resolves requests[0].deferred, awaits requests[0].outcome, and still expects preload.preloadSettled and live.isReady() false; resolving requests[1] allows preload to finish (1754–1782). Thus acquisition promises settle while logical demand remains active, and the asserted consumer is the live query. The progressive lane repeats 'before demand settles' (2289 and 2719).", + "glossary": "Demand and pagination terms: demand is logical need that may outlive physical work; settlement is a promise becoming fulfilled or rejected. Runtime readiness must be qualified as Collection, subscription or initial-query readiness. Grammar rules: a demand becomes active or retires, and a promise settles.", + "recommendation": "State that current acquisitions covering reachable demand must fulfill with their establishing writes applied before initial-query readiness; retiring demand removes its blocking participation. Say an obsolete acquisition's settlement cannot satisfy current demand or complete the current preload. Retain the useful demand-incarnation mapping and rename the affected test descriptions/comments consistently.", + "relatedPaths": [ + "packages/db/tests/query/includes-temporal-oracle.test.ts" + ], + "auditPath": "packages/db/tests/query/includes-temporal-oracle.test.ts", + "auditLine": 39, + "auditEndLine": 41, + "currentPath": "packages/db/tests/query/includes-temporal-oracle.test.ts", + "resolution": "Initial-query readiness, current acquisition fulfillment, applied writes, and preload settlement have explicit boundaries.", + "status": "resolved within terminology scope" + }, + { + "id": "04_acquisition-1", + "severity": "medium", + "kind": "meaning-conflict", + "term": "applied receipt / acquisition result", + "evidence": "`function requirePendingAppliedReceipt(receipt: LoadSubsetRequestResult)` accepts the subset-load result. At line 566, `const receipt = source._sync.loadSubset({})` feeds it. The asynchronous driver wraps `applyRow()` and awaits its actual commit receipt (lines 539–549), so the observed load promise can include delivery plus application; it is not necessarily the SyncAppliedReceipt returned by commit().", + "glossary": "Demand and pagination: applied receipt is specifically the SyncAppliedReceipt returned by commit(); an acquisition can establish its result through multiple sync transactions and receipts.", + "recommendation": "Rename the helper to requirePendingLoadSubsetResult and its argument/local variables to loadResult or acquisitionResult. Keep appliedReceipt for the result of commit(), and state that this fixture's load result awaits its establishing applied receipt.", + "relatedPaths": [], + "auditPath": "packages/db/tests/query/load-subset-oracle.property.test.ts", + "auditLine": 80, + "auditEndLine": 86, + "currentPath": "packages/db/tests/query/load-subset-oracle.property.test.ts", + "resolution": "loadSubset returns a load result. Only commit() returns the applied receipt.", + "status": "resolved within terminology scope" + }, + { + "id": "04_acquisition-3", + "severity": "medium", + "kind": "missing-mapping", + "term": "before-settlement / after-success / acquisition outcome", + "evidence": "`delivery: 'before-settlement' | 'after-success'` is described as an acquisition control dimension, and line 547 says `Deferred application happens only after a live attempt succeeds.` In the driver, gate.promise settles at lines 336–346, then the after-success branch awaits apply() at line 347 before the actual loadSubset promise returned at lines 333–348 fulfills. Thus after-success is after a controlled response gate, not after successful acquisition settlement.", + "glossary": "Applied settlement requires a successful subset load to wait for every establishing applied receipt; settlement must identify what promise settled. Model alignment rule requires an explicit mapping for a split production concept.", + "recommendation": "Name this controlled gate providerResponse (or modelResponseGate) and define its mapping beside Scenario. Use before-provider-response/after-provider-response or apply-before-response/apply-after-response and say both branches await application before acquisition fulfillment.", + "relatedPaths": [], + "auditPath": "packages/db/tests/query/ordered-lifecycle-oracle.property.test.ts", + "auditLine": 91, + "auditEndLine": 93, + "currentPath": "packages/db/tests/query/ordered-lifecycle-oracle.property.test.ts", + "resolution": "The controlled provider-response gate is distinct from acquisition fulfillment after establishing applied receipts.", + "status": "resolved within terminology scope" + }, + { + "id": "04_acquisition-4", + "severity": "medium", + "kind": "missing-mapping", + "term": "boundary request", + "evidence": "`const isPage = options.orderBy !== undefined` followed by `kind: isPage ? 'page' : 'boundary'` classifies every unordered acquisition as boundary. The custom-collation full-source lane explicitly expects this kind to be boundary (lines 3502–3508), with no cursor, limit or offset. The opening contract correctly says custom collation uses one full-source request, so the recorder gives that distinct concept a continuation-boundary name.", + "glossary": "Demand and pagination: boundary is the last value safely established for ordered continuation; tie group is the equal-order rows at that boundary. Architecture distinguishes tie-boundary acquisition from authoritative full-source acquisition. A combined model abstraction must name and list what it combines.", + "recommendation": "Use neutral ordered/unordered request-shape categories and explicitly map unordered to tie or full-source, or preserve page/prefix/tie-boundary/full-source as separate observations. Update the custom-collation assertion to call its request full-source.", + "relatedPaths": [ + "packages/db/tests/query/ordered-lifecycle-oracle.property.test.ts" + ], + "auditPath": "packages/db/tests/query/ordered-work-oracle.property.test.ts", + "auditLine": 347, + "auditEndLine": 350, + "currentPath": "packages/db/tests/query/ordered-work-oracle.property.test.ts", + "resolution": "with-order and without-order describe request shape. Comments map each category to its actual acquisition scope.", + "status": "resolved within terminology scope" + }, + { + "id": "04_acquisition-2", + "severity": "low", + "kind": "meaning-conflict", + "term": "settle / settled", + "evidence": "The title says `does not settle a window move after its sync run is cleaned up`, but line 4447 requires `await expect(move).rejects.toMatchObject({ name: 'AbortError' })`: rejection is settlement. The same conflict appears in load-subset-oracle.property.test.ts:1787 (`does not settle a demand...`) while line 1078 asserts rejection. In that file, lines 576–584 set `settled` only on fulfillment. Pagination's separate driver field `request.settled = true` at line 1991 is set before writes and before resolving the promise at line 2026; actual settlement is independently recorded in physicallySettled at 1852–1855.", + "glossary": "Demand and pagination and grammar rules: settlement means fulfillment or rejection; a promise settles, while demand becomes active or retires. Use success only for fulfillment.", + "recommendation": "Say the window promise rejects on cleanup and cannot fulfill afterward. Say an aborted load establishes no successful coverage rather than that demand cannot settle. Rename success-only flags to fulfilled; rename the pagination driver's early bookkeeping flag to responseStarted/handled, leaving settled for actual promise settlement.", + "relatedPaths": [ + "packages/db/tests/query/load-subset-oracle.property.test.ts" + ], + "auditPath": "packages/db/tests/query/pagination-oracle.property.test.ts", + "auditLine": 4385, + "auditEndLine": 4385, + "currentPath": "packages/db/tests/query/pagination-oracle.property.test.ts", + "resolution": "Success-only observations use fulfilled. responseStarted records provider response processing through delivery or rejection.", + "status": "resolved within terminology scope" + }, + { + "id": "04_acquisition-5", + "severity": "low", + "kind": "meaning-conflict", + "term": "source reports ready", + "evidence": "The test is named `publishes a replay replacement before its source reports ready`, but it installs `sourceSubscription!.on('status:ready', ...)` at line 645. This observes the source subscription's readiness transition; it does not observe the source Collection reporting ready (the adapter already calls markReady at startup).", + "glossary": "Runtime: Collection status and subscription status are distinct; readiness must be qualified as Collection readiness, subscription readiness or initial-query readiness.", + "recommendation": "Rename the test to publishes a truncate-replay replacement before its source subscription reports ready, and keep that qualification in any summary of this witness.", + "relatedPaths": [], + "auditPath": "packages/db/tests/query/load-subset-replay-refinement-oracle.test.ts", + "auditLine": 596, + "auditEndLine": 596, + "currentPath": "packages/db/tests/query/load-subset-replay-refinement-oracle.test.ts", + "resolution": "The replay witness explicitly observes source subscription readiness.", + "status": "resolved within terminology scope" + }, + { + "id": "05_query-2", + "severity": "medium", + "kind": "glossary-gap", + "term": "equality partition", + "evidence": "Glossary says an equality partition is \"shared by every pooled live query that filters on those fields\". Pooled oracle lines 6–7 instead says sharing requires \"the same `eq` fields and order\". Architecture lines 1256–1258 says \"Queries with different orders use different partitions\", and pooled-live-query.ts:417–418 explicitly adds orderKey to shapeKey. The oracle reflects actual architecture, while the glossary definition implies wider sharing.", + "glossary": "Runtime terms, equality partition: source rows grouped by eq-normalized values of one field set, shared by every pooled live query filtering on those fields.", + "recommendation": "Update the glossary definition to say an equality partition is shared for the same source Collection, equality-field set, and compatible query order (including its comparison/null-order options). Preserve the oracle wording and order-sensitive partition key.", + "relatedPaths": [ + "packages/db/tests/query/pooled-live-query-oracle.property.test.ts", + "packages/db/tests/query/pooled-live-query-gc.test.ts", + "packages/db/src/query/live/ARCHITECTURE.md", + "packages/db/src/query/pooled-live-query.ts" + ], + "auditPath": "docs/contributing/glossary.md", + "auditLine": 23, + "auditEndLine": 23, + "currentPath": "docs/contributing/glossary.md", + "resolution": "The glossary defines equality partitions by source Collection, equality fields, order terms, and resolved comparison options.", + "status": "resolved within terminology scope" + }, + { + "id": "05_query-1", + "severity": "low", + "kind": "meaning-conflict", + "term": "fault injection / mutant", + "evidence": "\"function injectDeliveryFault\" copies actual observations into \"const corrupted = [...actual]\", then removes a peer delivery or inserts a duplicate bootstrap. It is passed to assertHistory at lines 563–568. The opening calls these \"injected faults\" (82). These are deliberate wrong answers after observing production, not runtime failures. The same pattern occurs in identity-output-shape (40–41 and 271–276: \"shared-wrong-output\" replaces both result bags) and cold-join (34–35; 215 alters the observed amount and 219 hides acquisition records).", + "glossary": "Oracle and model terms: mutant = deliberate wrong answer or implementation used to test oracle sensitivity; fault injection = deliberate runtime failure, delay, cancellation, or malformed response used to test a system boundary.", + "recommendation": "Call these result/observation mutants: DeliveryMutant, applyDeliveryMutant, and mutant parameters; use \"wrong-result controls\" or \"mutants\" in the two query contracts. Keep genuinely thrown listener failures and controlled runtime rejection called fault injection.", + "relatedPaths": [ + "packages/db/tests/query/identity-output-shape-oracle.test.ts", + "packages/db/tests/query/cold-join-reconciliation-oracle.test.ts" + ], + "auditPath": "packages/db/tests/live-query-observer-history.property.test.ts", + "auditLine": 348, + "auditEndLine": 363, + "currentPath": "packages/db/tests/live-query-observer-history-oracle.property.test.ts", + "resolution": "Result and observation corruptions use mutant terminology. Runtime listener failures retain fault terminology.", + "status": "resolved within terminology scope" + }, + { + "id": "05_query-3", + "severity": "low", + "kind": "ambiguous-term", + "term": "settle / settlement", + "evidence": "The test is titled \"runs join live queries once after their parent queries settle\". All preloads finish at 1221–1225; the relevant operations are synchronous tx.mutate calls at 1233–1236 and 1243–1250, immediately followed by row and graph-run-count assertions. The transaction has autoCommit:false and is rolled back only at 1256. Thus \"settle\" here means parent graph jobs finish and publish, not a promise fulfillment/rejection. The similarly named test at 507 also only checks synchronous dependent rows after commit throws.", + "glossary": "Demand and pagination terms: settlement is a promise becoming fulfilled or rejected; qualify what settled. Architecture says scheduler dependency order waits on queued jobs in the same context, while source demand/ordered-load settlement barriers are separate.", + "recommendation": "Name the graph cut explicitly, e.g. \"runs the joined graph once after both parent graphs publish in the same scheduler context\"; rename the line-507 test to \"publishes dependent live-query rows before reporting an earlier source-listener failure\". Retain settlement wording where an actual preload or other promise is asserted, such as the test at line 860.", + "relatedPaths": [ + "packages/db/src/query/live/ARCHITECTURE.md" + ], + "auditPath": "packages/db/tests/query/scheduler.test.ts", + "auditLine": 1159, + "auditEndLine": 1159, + "currentPath": "packages/db/tests/query/scheduler-oracle.test.ts", + "resolution": "Scheduler descriptions name graph publication. Actual promise observations retain settlement terminology.", + "status": "resolved within terminology scope" + }, + { + "id": "06_ivm-1", + "severity": "medium", + "kind": "missing-mapping", + "term": "messages / messageCount versus weighted delta", + "evidence": "`addMessage(message: MultiSet) { this.messages.push(...message.getInner()) }` and `messageCount: this.messages.length` count flattened [row, weight] records. One MultiSet containing three weighted deltas counts as three messages, and an empty MultiSet counts as zero. In contrast, d2-work-oracle.test.ts:59 and topKWithFractionalIndex.test.ts:1203-1204 preserve each MultiSet envelope; the latter expects one empty message at line 1219. The same term therefore denotes different work observations across these oracles. KeyedMessageTracker repeats the mapping at lines 147-165.", + "glossary": "Live-query materialization terms: weighted delta = a positive or negative change to a relation row. Runtime terms distinguish a Collection change message. Model alignment rules 2 and 3 require an explicit mapping when a model combines or splits production concepts.", + "recommendation": "Rename the flattened fields to weightedDeltas/deltaCount (and the corresponding work assertions), or explicitly document that these model fields count flattened weighted deltas, not D2 MultiSet message envelopes or Collection change messages. Keep envelope counts separate where empty messages matter.", + "relatedPaths": [ + "packages/db-ivm/tests/operators/topKWithFractionalIndex.test.ts", + "packages/db-ivm/tests/operators/topk-relation-oracle.ts", + "packages/db-ivm/tests/d2-work-oracle.test.ts" + ], + "auditPath": "packages/db-ivm/tests/test-utils.ts", + "auditLine": 123, + "auditEndLine": 136, + "currentPath": "packages/db-ivm/tests/test-utils.ts", + "resolution": "Flattened D2 tracker entries use weightedDeltas and deltaCount. Actual MultiSet envelopes remain messages.", + "status": "resolved within terminology scope" + }, + { + "id": "06_ivm-2", + "severity": "low", + "kind": "ambiguous-term", + "term": "published", + "evidence": "`function published(index: Index, key: string)` only iterates `index.get(key)` and sums returned multiplicities. The driver invokes it immediately after `index.addValue` at lines 194-198. It observes an internal Index and never crosses a Collection publication boundary.", + "glossary": "Runtime terms: publication is the boundary making one coherent result observable to reads, events and downstream queries; public snapshot is the coherent set exposed there. Oracle terms call a recorded fact an observation.", + "recommendation": "Rename the helper to observedMultiplicities or indexContents. Keep the checkpoint wording `after addition`; this owner does not need a publication concept.", + "relatedPaths": [], + "auditPath": "packages/db-ivm/tests/index-refinement-oracle.property.test.ts", + "auditLine": 179, + "auditEndLine": 188, + "currentPath": "packages/db-ivm/tests/index-refinement-oracle.property.test.ts", + "resolution": "The Index oracle names its direct reads observedMultiplicities.", + "status": "resolved within terminology scope" + }, + { + "id": "06_ivm-3", + "severity": "low", + "kind": "missing-mapping", + "term": "settled local-snapshot cut", + "evidence": "The contract says `two public Collection rows at the settled local-snapshot cut`. The actual driver awaits `collection.preload()` at line 144 and reads `collection.currentStateAsChanges(...)` at lines 150-165. The named cut does not identify which promise settled, and local snapshot does not map to the glossary public snapshot despite reading the public Collection rows.", + "glossary": "Runtime terms: public snapshot is the last coherent set of rows exposed to reads/events/downstream queries. Demand terms: settlement is a promise becoming fulfilled or rejected and must be qualified; it is not publication or success. Model alignment requires canonical shared concepts or an explicit abstraction mapping.", + "recommendation": "Say `the ordered public snapshot read after collection.preload() fulfills` and name the currentStateAsChanges return as the comparison cut. Update the nearby local-snapshot comment/test name, or explicitly define that shorthand once.", + "relatedPaths": [], + "auditPath": "packages/db/tests/cursor.property.test.ts", + "auditLine": 25, + "auditEndLine": 28, + "currentPath": "packages/db/tests/cursor-oracle.property.test.ts", + "resolution": "The snapshot owner names the read after preload fulfillment and the currentStateAsChanges observation cut.", + "status": "resolved within terminology scope" + }, + { + "id": "06_ivm-4", + "severity": "low", + "kind": "glossary-gap", + "term": "structural equality / value identity", + "evidence": "The deepEquals owner promises `structural equality`; its lines 942-945 explicitly ignore Map/Set insertion order, RegExp lastIndex and array holes for change-event suppression. The hash-identity owner also calls its concept `structural equality` (line 14), but lines 30-34 retain all three distinctions. Both owners locally state their intended rules, so this is an absent shared vocabulary distinction rather than evidence that either oracle computes the wrong answer.", + "glossary": "The glossary introduction owns terms crossing subsystem boundaries and requires one term for one concept, but contains no entries distinguishing D2 structural value identity, deepEquals change-event equality, or draft equality.", + "recommendation": "Add qualified glossary entries such as D2 value identity and change-event equality, linked to their owners; require qualified headings when discussing both. Preserve the differing product semantics and the independent models. Include draft equality through its owning reviewer if the portfolio consolidates this gap.", + "relatedPaths": [ + "packages/db-ivm/tests/hash-identity-oracle.property.test.ts", + "packages/db-ivm/tests/hash.property.test.ts", + "packages/db-ivm/tests/operators/topk-batch-contract.test.ts", + "packages/db/tests/proxy-revert-oracle.property.test.ts" + ], + "auditPath": "packages/db/tests/utils.property.test.ts", + "auditLine": 7, + "auditEndLine": 10, + "currentPath": "packages/db/tests/utils-oracle.property.test.ts", + "resolution": "The glossary and oracle headings distinguish D2 value identity, change-event equality, and draft equality.", + "status": "resolved within terminology scope" + }, + { + "id": "07_query_adapter-4", + "severity": "medium", + "kind": "missing-mapping", + "term": "query-succeeded / refresh-succeeded / applied", + "evidence": "An applicable query-succeeded action with no deferOn immediately sets phase: terminal and outcome: applied (183–193); refresh-succeeded does the same (162–173). The opening mapping only says applicable combines validation and the ability to materialize (57–60). The empty-result driver submits query-succeeded after awaiting public refetch (3680–3691), so the action represents a compressed successful fetch plus completed result application, rather than Query fetch fulfillment alone.", + "glossary": "Demand graph and grammar distinguish provider completion, settlement, sync application, and publication. Model alignment rule requires an abstraction that combines production concepts to list what it combines.", + "recommendation": "Add an explicit mapping beside ResultSettlementModelAction: for a nondeferred applicable result, these actions combine Query fetch fulfillment, completed Collection application/applied settlement, and the terminal public-refetch checkpoint; deferred/invalid variants instead describe their named alternative outcomes. Alternatively give the compressed action a name that states that stronger boundary. Keep the independent coarse model.", + "relatedPaths": [], + "auditPath": "packages/query-db-collection/tests/ownership-lifecycle.oracle.test.ts", + "auditLine": 183, + "auditEndLine": 193, + "currentPath": "packages/query-db-collection/tests/ownership-lifecycle.oracle.test.ts", + "resolution": "Compressed result-settlement actions explicitly combine Query fetch fulfillment, Collection application, and the terminal refetch checkpoint.", + "status": "resolved within terminology scope" + }, + { + "id": "07_query_adapter-2", + "severity": "low", + "kind": "ambiguous-term", + "term": "acquisition", + "evidence": "“shares acquisitions across readers without letting one abort cancel its peer” drives two createCursorPager readers against a shared QueryClient and fetchPage transport. No Collection, loadSubset attempt, or acquisition lease exists in this history. In the implementation the local acquisition variable is query.promise (src/cursor-pagination.ts:181), whereas the adjacent load-subset lifecycle oracle explicitly models two acquisition leases sharing one Query transport (lines 1060–1140).", + "glossary": "Demand and pagination terms: physical acquisition is request-scoped work accepted by a sync adapter; transport is provider work and need not map one-to-one to a physical acquisition. Model alignment requires explicit mappings for different or combined concepts.", + "recommendation": "Use shared Query fetch consistently in pager-only oracle prose and test names. The README already qualifies this local acquisition concept and excludes cross-owner cancellation leases, so no new reference-model mapping is required.", + "relatedPaths": [ + "packages/query-db-collection/tests/cursor-pagination/README.md", + "packages/query-db-collection/tests/cursor-pagination.oracle.test.ts", + "packages/query-db-collection/tests/cursor-pagination.publication-oracle.test.ts", + "packages/query-db-collection/tests/cursor-pagination.boundary-oracle.test.ts", + "packages/query-db-collection/src/cursor-pagination.ts", + "packages/query-db-collection/tests/load-subset-lifecycle-oracle.test.ts" + ], + "adjudication": "The README already qualifies Query shared acquisition and excludes cross-owner cancellation leases. Standardize its local name, without claiming the conceptual mapping is absent.", + "auditPath": "packages/query-db-collection/tests/cursor-pagination.cache-oracle.test.ts", + "auditLine": 575, + "auditEndLine": 598, + "currentPath": "packages/query-db-collection/tests/cursor-pagination.cache-oracle.test.ts", + "resolution": "Pager owners use Query fetch for work that does not establish the acquisition leases modeled by lifecycle owners.", + "status": "resolved within terminology scope" + }, + { + "id": "07_query_adapter-3", + "severity": "low", + "kind": "ambiguous-term", + "term": "sync generations", + "evidence": "“sync generations order competing results” does not identify its clock. The same-run histories include overlapping defer barriers (4892–5026) and post-write result authority (4067–4182); production advances postWriteRefetchGenerations when a write demands newer authority (src/query.ts:966–983), independently of cleanup/restart. Calling those result-ordering clocks sync generations invites a sync-run interpretation.", + "glossary": "generation must qualify the clock it fences, such as sync-run or post-write-refetch generation. sync run is one sync-function invocation and is not a synonym for generation.", + "recommendation": "Replace the umbrella phrase sync generations with qualified sync-run, post-write-refetch and defer-result authorities as appropriate. Preserve the existing local mappings and independent model.", + "relatedPaths": [ + "packages/query-db-collection/src/query.ts" + ], + "adjudication": "Local defer and post-write clock mappings are present. The umbrella phrase sync generations is the remaining qualification problem.", + "auditPath": "packages/query-db-collection/tests/ownership-lifecycle.oracle.test.ts", + "auditLine": 45, + "auditEndLine": 47, + "currentPath": "packages/query-db-collection/tests/ownership-lifecycle.oracle.test.ts", + "resolution": "Ownership prose qualifies sync-run fences, post-write-refetch generations, and defer-result barriers.", + "status": "resolved within terminology scope" + }, + { + "id": "07_query_adapter-5", + "severity": "low", + "kind": "meaning-conflict", + "term": "settled", + "evidence": "“let settled = false; void refetch.then(() => { settled = true })” tracks fulfillment only; rejection leaves settled false. The cursor integration owner similarly increments settled only in fulfillment handlers (445–450). Both use that value at a pending-work checkpoint, even though glossary settlement includes rejection.", + "glossary": "settlement is a promise becoming fulfilled or rejected; grammar says a promise settles, fulfills, or rejects.", + "recommendation": "Rename these local observations to fulfilled / fulfilledPreloads if they intentionally measure success. If the assertion intends to establish that the promises are still pending, record both fulfillment and rejection with an explicit outcome.", + "relatedPaths": [ + "packages/query-db-collection/tests/cursor-pagination.integration.test.ts" + ], + "auditPath": "packages/query-db-collection/tests/load-subset-lifecycle-oracle.test.ts", + "auditLine": 603, + "auditEndLine": 606, + "currentPath": "packages/query-db-collection/tests/load-subset-lifecycle-oracle.test.ts", + "resolution": "Fulfillment-only flags and preload counters use fulfilled terminology.", + "status": "resolved within terminology scope" + }, + { + "id": "08_providers-1", + "severity": "medium", + "kind": "meaning-conflict", + "term": "session / sync run", + "evidence": "The test says \"discards tag state when the same collection starts a fresh session\", then executes \"await collection.cleanup()\" and \"collection.startSyncImmediate()\". This is exactly termination of one local sync run and restart of the same Collection. ORACLE_MUTATIONS.md:117-118 says \"every sync session\" and :203-205 says \"retire a session\" / \"new-session waiters\" for the same local ownership boundary.", + "glossary": "Runtime terms: sync run is one Collection sync-function invocation and its resources until cleanup invalidates them; provider session is a provider-defined remote lifetime, always provider-qualified, and is not a synonym for sync run.", + "recommendation": "Use \"new sync run\" in the test, \"every sync run\" in the ledger and \"retire a sync run\" / \"replacement-sync-run waiters\" for callback reentry. Preserve Electric provider stream terminology for actual remote/SDK resources.", + "relatedPaths": [ + "packages/electric-db-collection/tests/ORACLE_MUTATIONS.md", + "packages/electric-db-collection/tests/electric-oracle.property.test.ts" + ], + "auditPath": "packages/electric-db-collection/tests/electric-descriptor-isolation.test.ts", + "auditLine": 867, + "auditEndLine": 873, + "currentPath": "packages/electric-db-collection/tests/electric-descriptor-isolation-oracle.test.ts", + "resolution": "Local Collection lifetimes use sync run. Provider session remains provider-qualified.", + "status": "resolved within terminology scope" + }, + { + "id": "08_providers-2", + "severity": "medium", + "kind": "meaning-conflict", + "term": "settled", + "evidence": "\"let settled = false\" becomes true only in \".then(() => { settled = true })\" on applyTransaction. The same fulfillment-only observation occurs at :476-481. A rejected promise is settled by the glossary but leaves these variables false. The file itself uses the genuinely two-outcome \"persistenceState.settled\" at :761-770 with .finally(), so the same name represents two ideas within one oracle.", + "glossary": "Demand and pagination terms / Grammar rules: settlement means a promise becoming fulfilled or rejected; use success only for fulfillment.", + "recommendation": "Rename the two success-only flags to \"persistenceFulfilled\" (and corresponding assertions), or use an explicit pending/fulfilled/rejected outcome observer if the intended observation really is settlement. Leave the .finally()-based settlement flag named settled.", + "relatedPaths": [], + "auditPath": "packages/powersync-db-collection/tests/correctness-oracle.test.ts", + "auditLine": 308, + "auditEndLine": 315, + "currentPath": "packages/powersync-db-collection/tests/correctness-oracle.test.ts", + "resolution": "Fulfillment-only persistence flags use persistenceFulfilled. Both-outcome observations retain settled.", + "status": "resolved within terminology scope" + }, + { + "id": "08_providers-3", + "severity": "medium", + "kind": "ambiguous-term", + "term": "commit", + "evidence": "SchedulerEvent has \"| `commit`\", whose driver creates \"const commit = createDeferred()\" (:2623) and awaits \"commit.promise\" before invoking the persistence adapter applyCommittedTx (:2638-2641). In the same file, designMessage instead maps \"token.operation === `commit`\" to the Electric \"upToDate\" message (:2219-2222). Thus the same grammar action names persistence-write release and provider up-to-date delivery, neither of which alone denotes Collection sync application/publication.", + "glossary": "Runtime terms distinguish sync transaction, publication and provider completion; demand graph distinguishes commit(sync transaction), applied receipt and publication. Model alignment requires naming a differing abstraction and declaring what production concepts it combines or splits.", + "recommendation": "Name the scheduler action \"release-persistence-apply\" (or equally precise persistence-qualified wording) and the design action \"deliver-up-to-date\". Add one short mapping that provider controls may cause sync commit, whose applied receipt and later durability are separate boundaries. Do not change the independent state computations.", + "relatedPaths": [], + "auditPath": "packages/electric-db-collection/tests/electric-oracle.property.test.ts", + "auditLine": 2162, + "auditEndLine": 2167, + "currentPath": "packages/electric-db-collection/tests/electric-oracle.property.test.ts", + "resolution": "Electric actions name deliver-up-to-date, deliver-subset-end, and release-persistence-apply at their actual boundaries.", + "status": "resolved within terminology scope" + }, + { + "id": "09_sqlite_core-2", + "severity": "medium", + "kind": "meaning-conflict", + "term": "restart", + "evidence": "\"Same-schema restarts preserve metadata\" and \"same-schema restart ... restarts on either side\". observeResetResumeHistory instead constructs a new SQLiteCorePersistenceAdapter on the same harness.driver (457–462, repeated at 485–493); it creates no Collection and ends or starts no sync run. The observation is nevertheless named after-persistence-transition-restart (521).", + "glossary": "Runtime terms: restart is starting a new sync run after the prior sync run has ended.", + "recommendation": "Use adapter reopen/reconstruction in the law, test title, local restarted variable, and checkpoint (for example after-persistence-transition-reopen). If a process restart abstraction is intended, explicitly state that adapter reconstruction models only persistence reopening and does not cover the Collection restart boundary.", + "relatedPaths": [], + "auditPath": "packages/db-sqlite-persistence-core/tests/sqlite-core-adapter.test.ts", + "auditLine": 1787, + "auditEndLine": 1795, + "currentPath": "packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-oracle.test.ts", + "resolution": "Reconstruction of a persistence adapter uses adapter reopen, separate from Collection restart.", + "status": "resolved within terminology scope" + }, + { + "id": "09_sqlite_core-1", + "severity": "low", + "kind": "ambiguous-term", + "term": "applied receipt / wrapped sync receipt", + "evidence": "\"Publication precedes durability, but a rejected durability boundary must reject its applied receipt\". The witness at 4112–4123 observes receipt pending while the row is public; 4154–4164 observes that receipt rejected while the same row remains public and is not durable. Production separately awaits core application and persistence before resolveApplied (src/persisted.ts:2736–2758). Thus this receipt combines application and durable persistence rather than denoting the glossary application boundary alone.", + "glossary": "Demand and pagination terms: applied receipt settles when the sync transaction writes/events become visible, or rejects if abandoned; settlement is not application/publication. Model alignment rule requires a declared mapping for combined concepts.", + "recommendation": "Use wrapped sync receipt in the opening where the wrapper waits for both core application and durability. The stronger behavior is already declared and tested. Preserve its API type and assertions; a new glossary term is optional.", + "relatedPaths": [ + "packages/db-sqlite-persistence-core/src/persisted.ts", + "packages/db/src/types.ts", + "docs/contributing/glossary.md" + ], + "adjudication": "The stronger application-plus-durability behavior is explicitly declared and called wrapped sync receipt in its witness. The introduction should use that qualified name; a new glossary entry is not required.", + "auditPath": "packages/db-sqlite-persistence-core/tests/persisted.test.ts", + "auditLine": 63, + "auditEndLine": 65, + "currentPath": "packages/db-sqlite-persistence-core/tests/persisted-oracle.test.ts", + "resolution": "The persistence owner calls its durability-qualified result a wrapped sync receipt.", + "status": "resolved within terminology scope" + }, + { + "id": "09_sqlite_core-3", + "severity": "low", + "kind": "ambiguous-term", + "term": "network readiness", + "evidence": "\"Initial rendering prefers network readiness\"; the test \"uses network readiness before the fallback deadline\" (710) implements markNetworkReady = markReady (723–725) and finally asserts persisted.status is ready (748). The actual evidence is Collection readiness signaled by the upstream adapter, not a separate network-readiness state.", + "glossary": "Runtime terms: readiness must name the consumer (Collection, subscription, initial-query); network-first initial render prefers Collection readiness before its fallback condition.", + "recommendation": "Say upstream-signaled Collection readiness in the contract and test title, then use Collection readiness consistently. Rename markNetworkReady to markCollectionReady or add a first-use explicit mapping; retain network failure and the public network-first strategy name.", + "relatedPaths": [], + "auditPath": "packages/db-sqlite-persistence-core/tests/persisted-readiness-oracle.test.ts", + "auditLine": 148, + "auditEndLine": 149, + "currentPath": "packages/db-sqlite-persistence-core/tests/persisted-readiness-oracle.test.ts", + "resolution": "The owner qualifies upstream-signaled Collection readiness and its preload observations.", + "status": "resolved within terminology scope" + }, + { + "id": "10_browser_sqlite-1", + "severity": "medium", + "kind": "missing-mapping", + "term": "same lease / public acquisition", + "evidence": "The test says 'reacquires the same Browser lease after leadership retirement', but explicitly calls releaseInboundRemoteSubsetAcquisitions, observes one unload, ensures again, and expects two loads/two unloads (5588–5597). Electron repeats this at 3135–3164. The composed owner calls the retained operation 'one public acquisition' (1876; 1956–1957), while its ledger says leadership transfer 'releases retired-owner acquisitions and establishes replacements only for surviving demand' (1656–1658). The nested Collection-level claim and owner-level physical acquisitions are not explicitly mapped, so 'same lease' appears to survive a boundary that already fulfilled its release obligation.", + "glossary": "Demand and pagination: demand may outlive/replace physical work; each accepted physical acquisition creates an acquisition lease requiring one release. A lease must name its resource. Model alignment requires explicit mappings for combined/split concepts.", + "recommendation": "Rename the retirement tests to 'establishes a replacement acquisition for retained demand after leadership retirement'. Add one shared explanation distinguishing the still-retained Collection/persisted-adapter claim from the old and replacement remote-owner acquisitions and their separate acquisition leases. Qualify 'public acquisition' with that layer if it intentionally names the outer acquisition.", + "relatedPaths": [ + "packages/electron-db-sqlite-persistence/tests/electron-ipc.test.ts", + "packages/browser-db-sqlite-persistence/tests/per-collection-coordinator-oracle.test.ts" + ], + "auditPath": "packages/browser-db-sqlite-persistence/tests/browser-coordinator.test.ts", + "auditLine": 5569, + "auditEndLine": 5597, + "currentPath": "packages/browser-db-sqlite-persistence/tests/browser-coordinator-oracle.test.ts", + "resolution": "Mappings distinguish outer Collection acquisition, retained coordinator demand, and remote-owner acquisition leases.", + "status": "resolved within terminology scope" + }, + { + "id": "10_browser_sqlite-2", + "severity": "low", + "kind": "ambiguous-term", + "term": "publications", + "evidence": "`let publications = 0` increments when observeBroadcastMessage sees a `tx:committed` transport payload. The same observation recurs at 1614–1620 and 3134–3140. It measures coordinator message emission, without observing Collection reads/events/downstream-query coherence. The literal coordinator.publish API is valid; the unqualified observation name is the ambiguity.", + "glossary": "Runtime: publication is the boundary that makes one coherent result observable to reads, events, and downstream queries; it is not sync commit by itself. Overloaded observations must be qualified.", + "recommendation": "Rename these counters to committedMessagePosts (or coordinatorBroadcasts) and retain publish as the actual API name. If publication is used in prose for the transport API, explicitly say 'coordinator message publication' and distinguish it from Collection publication.", + "relatedPaths": [], + "auditPath": "packages/browser-db-sqlite-persistence/tests/browser-coordinator.test.ts", + "auditLine": 656, + "auditEndLine": 668, + "currentPath": "packages/browser-db-sqlite-persistence/tests/browser-coordinator-oracle.test.ts", + "resolution": "Transport counters use committedMessagePosts for tx:committed broadcasts.", + "status": "resolved within terminology scope" + }, + { + "id": "10_browser_sqlite-3", + "severity": "low", + "kind": "missing-mapping", + "term": "subsetDemandSettled", + "evidence": "`Promise.resolve(collection._sync.loadSubset(subsetDemand)).then(() => collection._sync.unloadSubset(subsetDemand)).catch(...).finally(() => { reach.subsetDemandSettled = true })` marks settlement of a combined load, success-path unload, and error-handling chain. The spec waits on this marker at line 190. A logical demand itself does not settle, and this is a later cut than settlement of the load promise alone.", + "glossary": "Demand is a logical need; demand retirement and acquisition release are separate transitions. Settlement means a named promise becoming fulfilled or rejected. Model-only combined observations must list their components.", + "recommendation": "Name the marker subsetLoadAndReleaseChainSettled and document that it is a fixture-only checkpoint after the load plus success-path unload/error handling. If the desired observation is load-promise settlement alone, record that separately rather than implying the logical demand settles.", + "relatedPaths": [ + "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.spec.ts" + ], + "auditPath": "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.ts", + "auditLine": 317, + "auditEndLine": 325, + "currentPath": "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle-oracle.opfs.ts", + "resolution": "The browser reach marker names the entire subset-load-and-release promise chain.", + "status": "resolved within terminology scope" + }, + { + "id": "11_offline-1", + "severity": "medium", + "kind": "missing-mapping", + "term": "success / application / caller fulfillment", + "evidence": "The opening declares that the README authorizes 'Success applies its server rows and, after outbox removal, fulfills both promises.' In this driver the mutationFn explicitly calls env.applyMutations (line 184); harness.ts updates serverState and submits a sync transaction. README.md:218–222 instead says successful settlement establishes mutationFn return plus acknowledged deletion, and establishes server confirmation or exposure only if mutationFn waits for that provider observation. The model's coupled application-and-fulfillment premise is not identified as the fixture's stronger premise in the opening law.", + "glossary": "Demand and pagination: settlement is promise fulfillment or rejection, not application. Runtime: publication is not provider return/request settlement. Offline outbox: deletion-pending follows mutation-function fulfillment, not a universal server-application guarantee.", + "recommendation": "State the general boundary as mutationFn fulfillment plus acknowledged outbox deletion. Add an explicit model mapping: in this fixture, successful mutationFn also updates the modeled server rows and submits their sync writes before returning; the row assertions are conditional on that controlled behavior.", + "relatedPaths": [ + "packages/offline-transactions/tests/harness.ts", + "packages/offline-transactions/README.md", + "packages/offline-transactions/src/executor/TransactionExecutor.ts" + ], + "auditPath": "packages/offline-transactions/tests/transaction-settlement.property.test.ts", + "auditLine": 18, + "auditEndLine": 22, + "currentPath": "packages/offline-transactions/tests/transaction-settlement-oracle.property.test.ts", + "resolution": "Caller success requires mutationFn fulfillment and acknowledged outbox deletion. The fixture states its stronger server-application premise.", + "status": "resolved within terminology scope" + }, + { + "id": "11_offline-2", + "severity": "low", + "kind": "meaning-conflict", + "term": "FaultInjection", + "evidence": "'type FaultInjection = { commandIndex: number; apply: (snapshot: Snapshot) => Snapshot }'. At lines 506–509 the scheduler has already run, and the helper replaces its recorded observation immediately before assertSnapshot. Examples set runningCount to 2 or fabricate a next transaction. These are deliberate wrong answers used to calibrate the oracle, not runtime failure/delay/cancellation/malformed-provider-response injection.", + "glossary": "Oracle and model terms: mutant is a deliberate wrong answer or implementation used to test oracle sensitivity; fault injection is a deliberate runtime failure, delay, cancellation, or malformed response testing a system boundary.", + "recommendation": "Rename this helper ObservationMutant (or WrongObservation) and call its cases observation mutants / wrong-result controls. Keep runtime fault injection for failures applied to the actual system boundary.", + "relatedPaths": [], + "auditPath": "packages/offline-transactions/tests/KeyScheduler.property.test.ts", + "auditLine": 383, + "auditEndLine": 390, + "currentPath": "packages/offline-transactions/tests/KeyScheduler-oracle.property.test.ts", + "resolution": "Snapshot substitutions use ObservationMutant and observationMutant.", + "status": "resolved within terminology scope" + }, + { + "id": "11_offline-3", + "severity": "low", + "kind": "glossary-gap", + "term": "offline executor restart / outbox replay", + "evidence": "Both outbox phase definitions say 'A restart...' while the glossary's sole restart entry at line 39 means starting a new Collection sync run. The serializer oracle says 'A restart has different object and collection IDs' (transaction-serializer.property.test.ts:186) and constructs new Collections. The settlement oracle disposes one executor and constructs a fresh test environment with the same storage (transaction-settlement.property.test.ts:1360–1375). Its restored marked rows retry deletion without invoking mutationFn. This is a separate offline lifecycle, not Collection sync restart or oracle seed/path replay.", + "glossary": "Runtime restart is a new sync run after the previous run ends; oracle replay reruns a recorded failure. Offline outbox currently defines phase markers but does not name fresh-executor recovery or persisted-outbox replay.", + "recommendation": "Add qualified offline terms: 'offline executor restart' for constructing a fresh executor over retained durable outbox state, and 'outbox replay' for loading/reconciling that state and resuming permitted work. Use 'offline executor restart' in phase definitions and 'application restart' / 'fresh serializer and Collection reconstruction' where the serialization fixture simulates process recreation. Reserve oracle replay for recorded test reproduction.", + "relatedPaths": [ + "packages/offline-transactions/tests/transaction-serializer.property.test.ts", + "packages/offline-transactions/tests/transaction-settlement.property.test.ts", + "packages/offline-transactions/tests/leadership-replay.property.test.ts", + "packages/offline-transactions/tests/connectivity-replay-oracle.test.ts" + ], + "auditPath": "docs/contributing/glossary.md", + "auditLine": 60, + "auditEndLine": 61, + "currentPath": "docs/contributing/glossary.md", + "resolution": "The glossary and local mappings distinguish offline executor restart, outbox replay, serializer reconstruction, and Collection lifecycle.", + "status": "resolved within terminology scope" + }, + { + "id": "11_offline-4", + "severity": "low", + "kind": "ambiguous-term", + "term": "resolved", + "evidence": "The outcome enum is '`pending` | `resolved` | `rejected`', and only the fulfillment callback of promise.then assigns 'resolved'. This observation means fulfilled, while promise resolution in JavaScript can also adopt an unsettled promise. Other offline owners use fulfilled for the same observed outcome.", + "glossary": "Grammar rules: a promise settles; it fulfills or rejects. Settlement is fulfillment or rejection.", + "recommendation": "Use fulfilled for the local outcome state and matching expectation at line 95. Preserve actual IndexedDB event names onsuccess/oncomplete and public API method names.", + "relatedPaths": [ + "packages/offline-transactions/tests/connectivity-replay-oracle.test.ts", + "packages/offline-transactions/tests/transaction-settlement.property.test.ts" + ], + "auditPath": "packages/offline-transactions/tests/indexeddb-write-settlement.test.ts", + "auditLine": 51, + "auditEndLine": 57, + "currentPath": "packages/offline-transactions/tests/indexeddb-write-settlement-oracle.test.ts", + "resolution": "The IndexedDB promise outcome uses fulfilled instead of resolved.", + "status": "resolved within terminology scope" + }, + { + "id": "12_frameworks-1", + "severity": "low", + "kind": "missing-mapping", + "term": "demand generation", + "evidence": "\"changing the query, collection, or page shape creates a new demand generation.\" This is the shared model description, but no demand-generation token is modeled or mapped. It groups input Collection/query identity replacement with reactive page-option updates; the latter preserves committed page depth (infinite-suite.ts:895-919). The receiving controller fences window operations with windowGeneration (packages/db/src/live-query-window-controller.ts:851).", + "glossary": "Demand and pagination: generation is a monotonic token that rejects obsolete asynchronous work and must name the clock it fences; demand is the logical need for source data. Model alignment rules 2 and 4 require explicit mapping of combined or model-only concepts.", + "recommendation": "Replace \"creates a new demand generation\" with direct observable wording about replacing input identity or requesting the updated window; alternatively declare this a model-only input epoch and map query/Collection replacement separately from window-operation generations and retained page depth.", + "relatedPaths": [ + "packages/db/tests/conformance/infinite-suite.ts", + "packages/react-db/tests/infinite-query-conformance.test.tsx", + "packages/vue-db/tests/infinite-query-conformance.test.ts", + "packages/svelte-db/tests/infinite-query-conformance.svelte.test.ts" + ], + "auditPath": "packages/db/tests/conformance/infinite-contract.ts", + "auditLine": 4, + "auditEndLine": 6, + "currentPath": "packages/db/tests/conformance/infinite-contract-oracle.ts", + "resolution": "The shared infinite-query contract names input identity replacement and window/page changes without inventing a generation clock.", + "status": "resolved within terminology scope" + }, + { + "id": "12_frameworks-2", + "severity": "low", + "kind": "meaning-conflict", + "term": "settled / fulfillment", + "evidence": "\"A settled page extends the committed prefix\" is implemented as \"const pageCount = pageSucceeded ? 2 : 1\"; rejected work also settles but does not advance this prefix. The same file calls a fulfillment-only observation \"settled\" at lines 518-520: \"let settled = false\" followed by a fulfillment-only .then setting it true. The failure-preservation rules and assertions are otherwise explicit, so this is vocabulary drift, not an established behavior defect.", + "glossary": "Demand and pagination: settlement is a Promise becoming fulfilled or rejected, not success. Grammar rules: use settled for either outcome and success only for fulfillment.", + "recommendation": "Say \"A fulfilled page fetch advances the committed prefix\" and rename the local fulfilled-only flag to fetchFulfilled. If the intended observation truly is settlement, record both fulfillment and rejection while retaining the outcome separately.", + "relatedPaths": [], + "auditPath": "packages/db/tests/conformance/infinite-suite.ts", + "auditLine": 33, + "auditEndLine": 45, + "currentPath": "packages/db/tests/conformance/infinite-suite-oracle.ts", + "resolution": "The page-prefix rule names fulfilled page fetches. The historical scenario key remains stable.", + "status": "resolved within terminology scope" + } + ], + "oracleOwnersAndDedicatedCompanions": [ + "packages/angular-db/tests/conformance-oracle.test.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle-oracle.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle-oracle.opfs.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-immediate-reload-oracle.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-immediate-reload-oracle.opfs.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-resume-two-tab-oracle.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-resume-two-tab-oracle.opfs.ts", + "packages/browser-db-sqlite-persistence/e2e/open-timeout-oracle.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/remote-subset-two-tab-oracle.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/remote-subset-two-tab-oracle.opfs.ts", + "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness-oracle.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness-oracle.opfs.ts", + "packages/browser-db-sqlite-persistence/tests/browser-coordinator-oracle.test.ts", + "packages/browser-db-sqlite-persistence/tests/opfs-page-lifecycle-oracle.test.ts", + "packages/browser-db-sqlite-persistence/tests/opfs-worker-diagnostics-oracle.test.ts", + "packages/browser-db-sqlite-persistence/tests/per-collection-coordinator-oracle.test.ts", + "packages/browser-db-sqlite-persistence/tests/shared-driver-fairness-oracle.test.ts", + "packages/browser-db-sqlite-persistence/tests/shared-driver-fairness-oracle.ts", + "packages/capacitor-db-sqlite-persistence/e2e/capacitor-persisted-collection-conformance-suite-oracle.ts", + "packages/capacitor-db-sqlite-persistence/e2e/shared/register-persisted-collection-conformance-suite-oracle.ts", + "packages/db-collection-e2e/src/fixtures/persisted-conformance-manifest-oracle.ts", + "packages/db-collection-e2e/src/suites/collation-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/deduplication-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/joins-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/live-updates-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/moves-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/mutations-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/pagination-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/predicates-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/progressive-oracle.suite.ts", + "packages/db-collection-e2e/src/utils/assertions-oracle.ts", + "packages/db-collection-e2e/src/utils/notification-laws-oracle.ts", + "packages/db-ivm/tests/d2-work-oracle.test.ts", + "packages/db-ivm/tests/hash-failure-retry-oracle.property.test.ts", + "packages/db-ivm/tests/hash-graph-oracle.property.test.ts", + "packages/db-ivm/tests/hash-identity-oracle.property.test.ts", + "packages/db-ivm/tests/hash-mixed-graph-oracle.property.test.ts", + "packages/db-ivm/tests/hash-oracle.property.test.ts", + "packages/db-ivm/tests/hash-session-oracle.ts", + "packages/db-ivm/tests/hash-session-replay-oracle.test.ts", + "packages/db-ivm/tests/hash-work-oracle.test.ts", + "packages/db-ivm/tests/incrementalization-law-oracle.property.test.ts", + "packages/db-ivm/tests/incrementalization-law-oracle.ts", + "packages/db-ivm/tests/index-refinement-oracle.property.test.ts", + "packages/db-ivm/tests/multiset-consolidate-oracle.property.test.ts", + "packages/db-ivm/tests/operators/topKWithFractionalIndex-oracle.test.ts", + "packages/db-ivm/tests/operators/topKWithIndex-oracle.test.ts", + "packages/db-ivm/tests/operators/topk-batch-contract-oracle.test.ts", + "packages/db-ivm/tests/operators/topk-relation-oracle.test.ts", + "packages/db-ivm/tests/operators/topk-relation-oracle.ts", + "packages/db-ivm/tests/operators/topk-support-window-oracle.test.ts", + "packages/db-ivm/tests/temporal-group-key-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/contracts/driver-admission-laws-oracle.ts", + "packages/db-sqlite-persistence-core/tests/contracts/persisted-collection-conformance-contract-oracle.ts", + "packages/db-sqlite-persistence-core/tests/contracts/runtime-bridge-e2e-contract-oracle.ts", + "packages/db-sqlite-persistence-core/tests/contracts/runtime-persistence-contract-oracle.ts", + "packages/db-sqlite-persistence-core/tests/contracts/sqlite-core-adapter-contract-oracle.ts", + "packages/db-sqlite-persistence-core/tests/contracts/sqlite-driver-contract-oracle.ts", + "packages/db-sqlite-persistence-core/tests/persisted-options-type-oracle.test-d.ts", + "packages/db-sqlite-persistence-core/tests/persisted-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/persisted-readiness-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/persisted-real-adapter-lifecycle-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/runtime-restart-checker-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/shared-logical-scheduling-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/sqlite-driver-admission-laws-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/sqlite-resume-snapshot-oracle.test.ts", + "packages/db/tests/SortedMap-oracle.test.ts", + "packages/db/tests/adapter-schema-transform-conformance-oracle.test-d.ts", + "packages/db/tests/btree-map-oracle.test.ts", + "packages/db/tests/change-event-history-oracle.test.ts", + "packages/db/tests/cleanup-queue-oracle.property.test.ts", + "packages/db/tests/collection-cleanup-restart-oracle.test.ts", + "packages/db/tests/collection-gc-clock-oracle.test.ts", + "packages/db/tests/collection-idle-cleanup-oracle.test.ts", + "packages/db/tests/collection-metadata-publication-oracle.property.test.ts", + "packages/db/tests/collection-mutation-startup-oracle.test.ts", + "packages/db/tests/collection-state-retention-oracle.property.test.ts", + "packages/db/tests/collection-subscription-lifecycle-grammar-oracle.ts", + "packages/db/tests/collection-subscription-lifecycle-history-oracle.property.test.ts", + "packages/db/tests/collection-subscription-lifecycle-oracle.test.ts", + "packages/db/tests/collection-subscription-lifecycle-publication-oracle.property.test.ts", + "packages/db/tests/collection-subscription-reentrancy-oracle.test.ts", + "packages/db/tests/collection-subscription-replay-oracle.property.test.ts", + "packages/db/tests/collection-sync-reentrancy-oracle.test.ts", + "packages/db/tests/collection-truncate-ownership-oracle.property.test.ts", + "packages/db/tests/comparison-oracle.property.test.ts", + "packages/db/tests/conformance-disabled-laws-oracle.test.ts", + "packages/db/tests/conformance-infinite-calibration-oracle.test.ts", + "packages/db/tests/conformance-infinite-demand-oracle.test.ts", + "packages/db/tests/conformance-page-laws-oracle.test.ts", + "packages/db/tests/conformance-registration-oracle.test.ts", + "packages/db/tests/conformance-result-laws-oracle.test.ts", + "packages/db/tests/conformance-scenario-lifetime-oracle.test.ts", + "packages/db/tests/conformance-scenario-sources-oracle.test.ts", + "packages/db/tests/conformance-scope-setup-oracle.test.ts", + "packages/db/tests/conformance/contract-oracle.ts", + "packages/db/tests/conformance/disabled-laws-oracle.ts", + "packages/db/tests/conformance/infinite-contract-oracle.ts", + "packages/db/tests/conformance/infinite-on-demand-oracle.ts", + "packages/db/tests/conformance/infinite-suite-oracle.ts", + "packages/db/tests/conformance/page-laws-oracle.ts", + "packages/db/tests/conformance/result-laws-oracle.ts", + "packages/db/tests/conformance/suite-oracle.ts", + "packages/db/tests/cursor-oracle.property.test.ts", + "packages/db/tests/d2-source-reconciliation-oracle.property.test.ts", + "packages/db/tests/db-client-hydration-authority-oracle.test.ts", + "packages/db/tests/db-client-oracle.test-d.ts", + "packages/db/tests/db-client-oracle.test.ts", + "packages/db/tests/effect-disposal-oracle.test.ts", + "packages/db/tests/flat-change-tracking-oracle.property.test.ts", + "packages/db/tests/index-suggestion-oracle.test.ts", + "packages/db/tests/index-update-oracle.property.test.ts", + "packages/db/tests/live-query-observer-history-oracle.property.test.ts", + "packages/db/tests/live-query-observer-oracle.test.ts", + "packages/db/tests/local-only-direct-write-oracle.test.ts", + "packages/db/tests/mutation-handler-type-oracle.test-d.ts", + "packages/db/tests/notification-laws-oracle.test.ts", + "packages/db/tests/observer-cleanup-restart-oracle.test.ts", + "packages/db/tests/optimistic-composition-oracle.test.ts", + "packages/db/tests/optimistic-history-oracle.ts", + "packages/db/tests/optimistic-history-outcomes-oracle.test.ts", + "packages/db/tests/optimistic-history-publication-oracle.test.ts", + "packages/db/tests/optimistic-settlement-boundaries-oracle.test.ts", + "packages/db/tests/optimistic-transaction-oracle.property.test.ts", + "packages/db/tests/oracle-replay.test.ts", + "packages/db/tests/paced-mutations-oracle.test.ts", + "packages/db/tests/proxy-detachment-contract-oracle.test.ts", + "packages/db/tests/proxy-iteration-contract-oracle.test.ts", + "packages/db/tests/proxy-native-methods-oracle.property.test.ts", + "packages/db/tests/proxy-oracle.test.ts", + "packages/db/tests/proxy-revert-oracle.property.test.ts", + "packages/db/tests/query/aggregate-value-contracts-oracle.test-d.ts", + "packages/db/tests/query/builder/ref-proxy-oracle.test.ts", + "packages/db/tests/query/cold-join-reconciliation-oracle.test.ts", + "packages/db/tests/query/compiler/evaluators-oracle.test.ts", + "packages/db/tests/query/compiler/lazy-targets-oracle.test.ts", + "packages/db/tests/query/derived-delete-reconciliation-oracle.test.ts", + "packages/db/tests/query/identity-output-shape-oracle.test.ts", + "packages/db/tests/query/includes-collection-oracle.property.test.ts", + "packages/db/tests/query/includes-context-transport-oracle.test.ts", + "packages/db/tests/query/includes-cross-formulation-oracle.property.test.ts", + "packages/db/tests/query/includes-functional-input-boundary-oracle.test.ts", + "packages/db/tests/query/includes-functional-projection-oracle.test.ts", + "packages/db/tests/query/includes-optimistic-oracle.property.test.ts", + "packages/db/tests/query/includes-oracle-helpers.ts", + "packages/db/tests/query/includes-oracle.property.test.ts", + "packages/db/tests/query/includes-publication-oracle.test.ts", + "packages/db/tests/query/includes-query-shape-oracle.test.ts", + "packages/db/tests/query/includes-scope-identity-oracle.ts", + "packages/db/tests/query/includes-space-oracle.test.ts", + "packages/db/tests/query/includes-temporal-oracle.test.ts", + "packages/db/tests/query/includes-work-counter-oracle.test.ts", + "packages/db/tests/query/index-path-collision-oracle.test.ts", + "packages/db/tests/query/ir-stable-identity-oracle.test.ts", + "packages/db/tests/query/join-result-key-oracle.property.test.ts", + "packages/db/tests/query/load-subset-oracle.property.test.ts", + "packages/db/tests/query/load-subset-replay-refinement-oracle.test.ts", + "packages/db/tests/query/load-subset-source-readiness-refinement-oracle.test.ts", + "packages/db/tests/query/load-subset-transaction-refinement-oracle.test.ts", + "packages/db/tests/query/optimizer-semantics-oracle.test.ts", + "packages/db/tests/query/ordered-default-work-oracle.test.ts", + "packages/db/tests/query/ordered-demand-retirement-oracle.test.ts", + "packages/db/tests/query/ordered-lifecycle-oracle.property.test.ts", + "packages/db/tests/query/ordered-source-loader-oracle.test.ts", + "packages/db/tests/query/ordered-source-loader-state-oracle.test.ts", + "packages/db/tests/query/ordered-work-oracle.property.test.ts", + "packages/db/tests/query/pagination-oracle.property.test.ts", + "packages/db/tests/query/pooled-live-query-gc-oracle.test.ts", + "packages/db/tests/query/pooled-live-query-oracle.property.test.ts", + "packages/db/tests/query/public-container-copy-oracle.test.ts", + "packages/db/tests/query/query-api-type-algebra-oracle.test-d.ts", + "packages/db/tests/query/query-api-type-algebra-oracle.test.ts", + "packages/db/tests/query/replay-failure-boundary-oracle.test.ts", + "packages/db/tests/query/scheduler-oracle.test.ts", + "packages/db/tests/query/subquery-user-value-oracle.test.ts", + "packages/db/tests/query/validate-aliases-oracle.test.ts", + "packages/db/tests/query/virtual-row-fields-oracle.test-d.ts", + "packages/db/tests/query/virtual-row-fields-oracle.test.ts", + "packages/db/tests/query/where-predicate-publication-oracle.property.test.ts", + "packages/db/tests/query/where-prefilter-property-visibility-oracle.test.ts", + "packages/db/tests/reference-expression-oracle.ts", + "packages/db/tests/replay-publication-storage-oracle.test.ts", + "packages/db/tests/single-row-ref-proxy-oracle.test-d.ts", + "packages/db/tests/sync-reused-row-oracle.test.ts", + "packages/db/tests/trace-runner-oracle.ts", + "packages/db/tests/transactions-oracle.test.ts", + "packages/db/tests/utils-oracle.property.test.ts", + "packages/db/tests/virtual-props-cache-oracle.test.ts", + "packages/db/tests/virtual-row-legacy-guard-oracle.test-d.ts", + "packages/electric-db-collection/e2e/sql-predicate-semantics-oracle.e2e.test.ts", + "packages/electric-db-collection/e2e/subset-sql-acceptance-oracle.e2e.test.ts", + "packages/electric-db-collection/tests/ORACLE_MUTATIONS.md", + "packages/electric-db-collection/tests/electric-descriptor-isolation-oracle.test.ts", + "packages/electric-db-collection/tests/electric-oracle-lifecycle.test.ts", + "packages/electric-db-collection/tests/electric-oracle-lifecycle.ts", + "packages/electric-db-collection/tests/electric-oracle.property.test.ts", + "packages/electric-db-collection/tests/electric-recovery-oracle.test.ts", + "packages/electric-db-collection/tests/electric-resume-snapshot-races-oracle.test.ts", + "packages/electric-db-collection/tests/electric-sdk-delivery-oracle.property.test.ts", + "packages/electric-db-collection/tests/electric-sdk-framing-oracle.test.ts", + "packages/electric-db-collection/tests/pg-serializer-oracle.property.test.ts", + "packages/electric-db-collection/tests/schema-transform-conformance-oracle.test-d.ts", + "packages/electron-db-sqlite-persistence/tests/electron-ipc-oracle.test.ts", + "packages/expo-db-sqlite-persistence/e2e/mobile-persisted-collection-conformance-suite-oracle.ts", + "packages/node-db-sqlite-persistence/tests/cached-upstream-history-oracle.test.ts", + "packages/node-db-sqlite-persistence/tests/expression-index-oracle.test.ts", + "packages/node-db-sqlite-persistence/tests/node-driver-oracle.test.ts", + "packages/node-db-sqlite-persistence/tests/node-persistence-oracle.test.ts", + "packages/node-db-sqlite-persistence/tests/node-sqlite-core-adapter-contract-oracle.test.ts", + "packages/offline-transactions/tests/KeyScheduler-oracle.property.test.ts", + "packages/offline-transactions/tests/connectivity-replay-oracle.test.ts", + "packages/offline-transactions/tests/fifo-retry-oracle.property.test.ts", + "packages/offline-transactions/tests/filtered-replay-work-oracle.test.ts", + "packages/offline-transactions/tests/indexeddb-write-settlement-oracle.test.ts", + "packages/offline-transactions/tests/leadership-replay-oracle.property.test.ts", + "packages/offline-transactions/tests/oracle-lifecycle.test.ts", + "packages/offline-transactions/tests/storage-delete-settlement-oracle.test.ts", + "packages/offline-transactions/tests/transaction-serializer-oracle.property.test.ts", + "packages/offline-transactions/tests/transaction-settlement-oracle.property.test.ts", + "packages/powersync-db-collection/tests/correctness-oracle.test.ts", + "packages/powersync-db-collection/tests/schema-transform-conformance-oracle.test-d.ts", + "packages/query-db-collection/tests/cursor-pagination-oracle.integration.test.ts", + "packages/query-db-collection/tests/cursor-pagination-oracle.no-peek.integration.test.ts", + "packages/query-db-collection/tests/cursor-pagination-oracle.no-peek.test.ts", + "packages/query-db-collection/tests/cursor-pagination.boundary-oracle.test.ts", + "packages/query-db-collection/tests/cursor-pagination.cache-oracle.test.ts", + "packages/query-db-collection/tests/cursor-pagination.oracle.test.ts", + "packages/query-db-collection/tests/cursor-pagination.publication-oracle.test.ts", + "packages/query-db-collection/tests/cursor-pagination/model-oracle.ts", + "packages/query-db-collection/tests/cursor-pagination/no-peek-oracle.ts", + "packages/query-db-collection/tests/includes-work-counter-oracle.test.ts", + "packages/query-db-collection/tests/load-subset-lifecycle-oracle.test.ts", + "packages/query-db-collection/tests/ownership-lifecycle.oracle.test.ts", + "packages/query-db-collection/tests/query-oracle.test-d.ts", + "packages/query-db-collection/tests/ssr-dehydration-oracle.test.ts", + "packages/react-db/tests/conformance-oracle.test.tsx", + "packages/react-db/tests/infinite-query-conformance-oracle.test.tsx", + "packages/react-native-db-sqlite-persistence/e2e/mobile-persisted-collection-conformance-suite-oracle.ts", + "packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver-oracle.test.ts", + "packages/react-native-db-sqlite-persistence/tests/react-native-persistence-oracle.test.ts", + "packages/rxdb-db-collection/tests/schema-transform-conformance-oracle.test-d.ts", + "packages/solid-db/tests/conformance-oracle.test.tsx", + "packages/svelte-db/tests/conformance-oracle.svelte.test.ts", + "packages/svelte-db/tests/infinite-query-conformance-oracle.svelte.test.ts", + "packages/tauri-db-sqlite-persistence/e2e/shared/register-persisted-collection-conformance-suite-oracle.ts", + "packages/trailbase-db-collection/tests/ORACLE.md", + "packages/trailbase-db-collection/tests/lifecycle-oracle.property.test.ts", + "packages/vue-db/tests/conformance-oracle.test.ts", + "packages/vue-db/tests/infinite-query-conformance-oracle.test.ts", + "packages/vue-db/tests/useLiveQuery-publication-oracle.test.ts" + ], + "excludedGenericSupport": [ + "packages/db-ivm/tests/test-utils.ts", + "packages/db/tests/utils.ts", + "packages/query-db-collection/tests/cursor-pagination/README.md", + "packages/query-db-collection/tests/cursor-pagination/backend.ts", + "packages/query-db-collection/tests/cursor-pagination/no-peek-transport.ts" + ], + "renames": { + "packages/angular-db/tests/conformance.test.ts": "packages/angular-db/tests/conformance-oracle.test.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.spec.ts": "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle-oracle.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.ts": "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle-oracle.opfs.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-immediate-reload.opfs.spec.ts": "packages/browser-db-sqlite-persistence/e2e/electric-immediate-reload-oracle.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-immediate-reload.opfs.ts": "packages/browser-db-sqlite-persistence/e2e/electric-immediate-reload-oracle.opfs.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-resume-two-tab.opfs.spec.ts": "packages/browser-db-sqlite-persistence/e2e/electric-resume-two-tab-oracle.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-resume-two-tab.opfs.ts": "packages/browser-db-sqlite-persistence/e2e/electric-resume-two-tab-oracle.opfs.ts", + "packages/browser-db-sqlite-persistence/e2e/open-timeout.opfs.spec.ts": "packages/browser-db-sqlite-persistence/e2e/open-timeout-oracle.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/remote-subset-two-tab.opfs.spec.ts": "packages/browser-db-sqlite-persistence/e2e/remote-subset-two-tab-oracle.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/remote-subset-two-tab.opfs.ts": "packages/browser-db-sqlite-persistence/e2e/remote-subset-two-tab-oracle.opfs.ts", + "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness.opfs.spec.ts": "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness-oracle.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness.opfs.ts": "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness-oracle.opfs.ts", + "packages/browser-db-sqlite-persistence/tests/browser-coordinator.test.ts": "packages/browser-db-sqlite-persistence/tests/browser-coordinator-oracle.test.ts", + "packages/capacitor-db-sqlite-persistence/e2e/capacitor-persisted-collection-conformance-suite.ts": "packages/capacitor-db-sqlite-persistence/e2e/capacitor-persisted-collection-conformance-suite-oracle.ts", + "packages/capacitor-db-sqlite-persistence/e2e/shared/register-persisted-collection-conformance-suite.ts": "packages/capacitor-db-sqlite-persistence/e2e/shared/register-persisted-collection-conformance-suite-oracle.ts", + "packages/db-collection-e2e/src/fixtures/persisted-conformance-manifest.ts": "packages/db-collection-e2e/src/fixtures/persisted-conformance-manifest-oracle.ts", + "packages/db-collection-e2e/src/suites/collation.suite.ts": "packages/db-collection-e2e/src/suites/collation-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/deduplication.suite.ts": "packages/db-collection-e2e/src/suites/deduplication-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/joins.suite.ts": "packages/db-collection-e2e/src/suites/joins-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/live-updates.suite.ts": "packages/db-collection-e2e/src/suites/live-updates-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/moves.suite.ts": "packages/db-collection-e2e/src/suites/moves-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/mutations.suite.ts": "packages/db-collection-e2e/src/suites/mutations-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/pagination.suite.ts": "packages/db-collection-e2e/src/suites/pagination-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/predicates.suite.ts": "packages/db-collection-e2e/src/suites/predicates-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/progressive.suite.ts": "packages/db-collection-e2e/src/suites/progressive-oracle.suite.ts", + "packages/db-collection-e2e/src/utils/assertions.ts": "packages/db-collection-e2e/src/utils/assertions-oracle.ts", + "packages/db-collection-e2e/src/utils/notification-laws.ts": "packages/db-collection-e2e/src/utils/notification-laws-oracle.ts", + "packages/db-ivm/tests/hash-failure-retry.property.test.ts": "packages/db-ivm/tests/hash-failure-retry-oracle.property.test.ts", + "packages/db-ivm/tests/hash-graph.property.test.ts": "packages/db-ivm/tests/hash-graph-oracle.property.test.ts", + "packages/db-ivm/tests/hash-mixed-graph.property.test.ts": "packages/db-ivm/tests/hash-mixed-graph-oracle.property.test.ts", + "packages/db-ivm/tests/hash-session-replay.test.ts": "packages/db-ivm/tests/hash-session-replay-oracle.test.ts", + "packages/db-ivm/tests/hash-session.ts": "packages/db-ivm/tests/hash-session-oracle.ts", + "packages/db-ivm/tests/hash-work.test.ts": "packages/db-ivm/tests/hash-work-oracle.test.ts", + "packages/db-ivm/tests/hash.property.test.ts": "packages/db-ivm/tests/hash-oracle.property.test.ts", + "packages/db-ivm/tests/incrementalization-law.property.test.ts": "packages/db-ivm/tests/incrementalization-law-oracle.property.test.ts", + "packages/db-ivm/tests/incrementalization-law.ts": "packages/db-ivm/tests/incrementalization-law-oracle.ts", + "packages/db-ivm/tests/operators/topKWithFractionalIndex.test.ts": "packages/db-ivm/tests/operators/topKWithFractionalIndex-oracle.test.ts", + "packages/db-ivm/tests/operators/topKWithIndex.test.ts": "packages/db-ivm/tests/operators/topKWithIndex-oracle.test.ts", + "packages/db-ivm/tests/operators/topk-batch-contract.test.ts": "packages/db-ivm/tests/operators/topk-batch-contract-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/contracts/driver-admission-laws.ts": "packages/db-sqlite-persistence-core/tests/contracts/driver-admission-laws-oracle.ts", + "packages/db-sqlite-persistence-core/tests/contracts/persisted-collection-conformance-contract.ts": "packages/db-sqlite-persistence-core/tests/contracts/persisted-collection-conformance-contract-oracle.ts", + "packages/db-sqlite-persistence-core/tests/contracts/runtime-bridge-e2e-contract.ts": "packages/db-sqlite-persistence-core/tests/contracts/runtime-bridge-e2e-contract-oracle.ts", + "packages/db-sqlite-persistence-core/tests/contracts/runtime-persistence-contract.ts": "packages/db-sqlite-persistence-core/tests/contracts/runtime-persistence-contract-oracle.ts", + "packages/db-sqlite-persistence-core/tests/contracts/sqlite-core-adapter-contract.ts": "packages/db-sqlite-persistence-core/tests/contracts/sqlite-core-adapter-contract-oracle.ts", + "packages/db-sqlite-persistence-core/tests/contracts/sqlite-driver-contract.ts": "packages/db-sqlite-persistence-core/tests/contracts/sqlite-driver-contract-oracle.ts", + "packages/db-sqlite-persistence-core/tests/persisted-real-adapter-lifecycle.test.ts": "packages/db-sqlite-persistence-core/tests/persisted-real-adapter-lifecycle-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/persisted.test.ts": "packages/db-sqlite-persistence-core/tests/persisted-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/runtime-restart-checker.test.ts": "packages/db-sqlite-persistence-core/tests/runtime-restart-checker-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/shared-logical-scheduling.test.ts": "packages/db-sqlite-persistence-core/tests/shared-logical-scheduling-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/sqlite-core-adapter.test.ts": "packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/sqlite-driver-admission-laws.test.ts": "packages/db-sqlite-persistence-core/tests/sqlite-driver-admission-laws-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/sqlite-resume-snapshot.test.ts": "packages/db-sqlite-persistence-core/tests/sqlite-resume-snapshot-oracle.test.ts", + "packages/db/tests/SortedMap.test.ts": "packages/db/tests/SortedMap-oracle.test.ts", + "packages/db/tests/adapter-schema-transform-conformance.test-d.ts": "packages/db/tests/adapter-schema-transform-conformance-oracle.test-d.ts", + "packages/db/tests/cleanup-queue.property.test.ts": "packages/db/tests/cleanup-queue-oracle.property.test.ts", + "packages/db/tests/collection-gc-clock.test.ts": "packages/db/tests/collection-gc-clock-oracle.test.ts", + "packages/db/tests/collection-idle-cleanup.test.ts": "packages/db/tests/collection-idle-cleanup-oracle.test.ts", + "packages/db/tests/collection-subscription-lifecycle-grammar.ts": "packages/db/tests/collection-subscription-lifecycle-grammar-oracle.ts", + "packages/db/tests/collection-subscription-lifecycle-history.property.test.ts": "packages/db/tests/collection-subscription-lifecycle-history-oracle.property.test.ts", + "packages/db/tests/collection-subscription-lifecycle-publication.property.test.ts": "packages/db/tests/collection-subscription-lifecycle-publication-oracle.property.test.ts", + "packages/db/tests/collection-sync-reentrancy.test.ts": "packages/db/tests/collection-sync-reentrancy-oracle.test.ts", + "packages/db/tests/comparison.property.test.ts": "packages/db/tests/comparison-oracle.property.test.ts", + "packages/db/tests/conformance-disabled-laws.test.ts": "packages/db/tests/conformance-disabled-laws-oracle.test.ts", + "packages/db/tests/conformance-infinite-calibration.test.ts": "packages/db/tests/conformance-infinite-calibration-oracle.test.ts", + "packages/db/tests/conformance-infinite-demand.test.ts": "packages/db/tests/conformance-infinite-demand-oracle.test.ts", + "packages/db/tests/conformance-page-laws.test.ts": "packages/db/tests/conformance-page-laws-oracle.test.ts", + "packages/db/tests/conformance-registration.test.ts": "packages/db/tests/conformance-registration-oracle.test.ts", + "packages/db/tests/conformance-result-laws.test.ts": "packages/db/tests/conformance-result-laws-oracle.test.ts", + "packages/db/tests/conformance-scenario-lifetime.test.ts": "packages/db/tests/conformance-scenario-lifetime-oracle.test.ts", + "packages/db/tests/conformance-scenario-sources.test.ts": "packages/db/tests/conformance-scenario-sources-oracle.test.ts", + "packages/db/tests/conformance-scope-setup.test.ts": "packages/db/tests/conformance-scope-setup-oracle.test.ts", + "packages/db/tests/conformance/contract.ts": "packages/db/tests/conformance/contract-oracle.ts", + "packages/db/tests/conformance/disabled-laws.ts": "packages/db/tests/conformance/disabled-laws-oracle.ts", + "packages/db/tests/conformance/infinite-contract.ts": "packages/db/tests/conformance/infinite-contract-oracle.ts", + "packages/db/tests/conformance/infinite-on-demand.ts": "packages/db/tests/conformance/infinite-on-demand-oracle.ts", + "packages/db/tests/conformance/infinite-suite.ts": "packages/db/tests/conformance/infinite-suite-oracle.ts", + "packages/db/tests/conformance/page-laws.ts": "packages/db/tests/conformance/page-laws-oracle.ts", + "packages/db/tests/conformance/result-laws.ts": "packages/db/tests/conformance/result-laws-oracle.ts", + "packages/db/tests/conformance/suite.ts": "packages/db/tests/conformance/suite-oracle.ts", + "packages/db/tests/cursor.property.test.ts": "packages/db/tests/cursor-oracle.property.test.ts", + "packages/db/tests/db-client.test-d.ts": "packages/db/tests/db-client-oracle.test-d.ts", + "packages/db/tests/db-client.test.ts": "packages/db/tests/db-client-oracle.test.ts", + "packages/db/tests/index-update.property.test.ts": "packages/db/tests/index-update-oracle.property.test.ts", + "packages/db/tests/live-query-observer-history.property.test.ts": "packages/db/tests/live-query-observer-history-oracle.property.test.ts", + "packages/db/tests/live-query-observer.test.ts": "packages/db/tests/live-query-observer-oracle.test.ts", + "packages/db/tests/local-only-direct-write.test.ts": "packages/db/tests/local-only-direct-write-oracle.test.ts", + "packages/db/tests/notification-laws.test.ts": "packages/db/tests/notification-laws-oracle.test.ts", + "packages/db/tests/observer-cleanup-restart.test.ts": "packages/db/tests/observer-cleanup-restart-oracle.test.ts", + "packages/db/tests/optimistic-composition.test.ts": "packages/db/tests/optimistic-composition-oracle.test.ts", + "packages/db/tests/optimistic-history-outcomes.test.ts": "packages/db/tests/optimistic-history-outcomes-oracle.test.ts", + "packages/db/tests/optimistic-history-publication.test.ts": "packages/db/tests/optimistic-history-publication-oracle.test.ts", + "packages/db/tests/optimistic-settlement-boundaries.test.ts": "packages/db/tests/optimistic-settlement-boundaries-oracle.test.ts", + "packages/db/tests/proxy-detachment-contract.test.ts": "packages/db/tests/proxy-detachment-contract-oracle.test.ts", + "packages/db/tests/proxy-iteration-contract.test.ts": "packages/db/tests/proxy-iteration-contract-oracle.test.ts", + "packages/db/tests/proxy-native-methods.property.test.ts": "packages/db/tests/proxy-native-methods-oracle.property.test.ts", + "packages/db/tests/proxy.test.ts": "packages/db/tests/proxy-oracle.test.ts", + "packages/db/tests/query/aggregate-value-contracts.test-d.ts": "packages/db/tests/query/aggregate-value-contracts-oracle.test-d.ts", + "packages/db/tests/query/builder/ref-proxy.test.ts": "packages/db/tests/query/builder/ref-proxy-oracle.test.ts", + "packages/db/tests/query/compiler/evaluators.test.ts": "packages/db/tests/query/compiler/evaluators-oracle.test.ts", + "packages/db/tests/query/compiler/lazy-targets.test.ts": "packages/db/tests/query/compiler/lazy-targets-oracle.test.ts", + "packages/db/tests/query/derived-delete-reconciliation.test.ts": "packages/db/tests/query/derived-delete-reconciliation-oracle.test.ts", + "packages/db/tests/query/includes-functional-input-boundary.test.ts": "packages/db/tests/query/includes-functional-input-boundary-oracle.test.ts", + "packages/db/tests/query/ir-stable-identity.test.ts": "packages/db/tests/query/ir-stable-identity-oracle.test.ts", + "packages/db/tests/query/ordered-default-work.test.ts": "packages/db/tests/query/ordered-default-work-oracle.test.ts", + "packages/db/tests/query/ordered-demand-retirement.test.ts": "packages/db/tests/query/ordered-demand-retirement-oracle.test.ts", + "packages/db/tests/query/ordered-source-loader-state.test.ts": "packages/db/tests/query/ordered-source-loader-state-oracle.test.ts", + "packages/db/tests/query/ordered-source-loader.test.ts": "packages/db/tests/query/ordered-source-loader-oracle.test.ts", + "packages/db/tests/query/pooled-live-query-gc.test.ts": "packages/db/tests/query/pooled-live-query-gc-oracle.test.ts", + "packages/db/tests/query/public-container-copy.test.ts": "packages/db/tests/query/public-container-copy-oracle.test.ts", + "packages/db/tests/query/query-api-type-algebra.test-d.ts": "packages/db/tests/query/query-api-type-algebra-oracle.test-d.ts", + "packages/db/tests/query/query-api-type-algebra.test.ts": "packages/db/tests/query/query-api-type-algebra-oracle.test.ts", + "packages/db/tests/query/replay-failure-boundary.test.ts": "packages/db/tests/query/replay-failure-boundary-oracle.test.ts", + "packages/db/tests/query/scheduler.test.ts": "packages/db/tests/query/scheduler-oracle.test.ts", + "packages/db/tests/query/validate-aliases.test.ts": "packages/db/tests/query/validate-aliases-oracle.test.ts", + "packages/db/tests/query/where-prefilter-property-visibility.test.ts": "packages/db/tests/query/where-prefilter-property-visibility-oracle.test.ts", + "packages/db/tests/reference-expression.ts": "packages/db/tests/reference-expression-oracle.ts", + "packages/db/tests/replay-publication-storage.test.ts": "packages/db/tests/replay-publication-storage-oracle.test.ts", + "packages/db/tests/single-row-ref-proxy.test-d.ts": "packages/db/tests/single-row-ref-proxy-oracle.test-d.ts", + "packages/db/tests/sync-reused-row.test.ts": "packages/db/tests/sync-reused-row-oracle.test.ts", + "packages/db/tests/trace-runner.ts": "packages/db/tests/trace-runner-oracle.ts", + "packages/db/tests/transactions.test.ts": "packages/db/tests/transactions-oracle.test.ts", + "packages/db/tests/utils.property.test.ts": "packages/db/tests/utils-oracle.property.test.ts", + "packages/db/tests/virtual-props-cache.test.ts": "packages/db/tests/virtual-props-cache-oracle.test.ts", + "packages/electric-db-collection/e2e/sql-predicate-semantics.e2e.test.ts": "packages/electric-db-collection/e2e/sql-predicate-semantics-oracle.e2e.test.ts", + "packages/electric-db-collection/e2e/subset-sql-acceptance.e2e.test.ts": "packages/electric-db-collection/e2e/subset-sql-acceptance-oracle.e2e.test.ts", + "packages/electric-db-collection/tests/electric-descriptor-isolation.test.ts": "packages/electric-db-collection/tests/electric-descriptor-isolation-oracle.test.ts", + "packages/electric-db-collection/tests/electric-resume-snapshot-races.test.ts": "packages/electric-db-collection/tests/electric-resume-snapshot-races-oracle.test.ts", + "packages/electric-db-collection/tests/electric-sdk-delivery.property.test.ts": "packages/electric-db-collection/tests/electric-sdk-delivery-oracle.property.test.ts", + "packages/electric-db-collection/tests/electric-sdk-framing.test.ts": "packages/electric-db-collection/tests/electric-sdk-framing-oracle.test.ts", + "packages/electric-db-collection/tests/pg-serializer.property.test.ts": "packages/electric-db-collection/tests/pg-serializer-oracle.property.test.ts", + "packages/electric-db-collection/tests/schema-transform-conformance.test-d.ts": "packages/electric-db-collection/tests/schema-transform-conformance-oracle.test-d.ts", + "packages/electron-db-sqlite-persistence/tests/electron-ipc.test.ts": "packages/electron-db-sqlite-persistence/tests/electron-ipc-oracle.test.ts", + "packages/expo-db-sqlite-persistence/e2e/mobile-persisted-collection-conformance-suite.ts": "packages/expo-db-sqlite-persistence/e2e/mobile-persisted-collection-conformance-suite-oracle.ts", + "packages/node-db-sqlite-persistence/tests/cached-upstream-history.test.ts": "packages/node-db-sqlite-persistence/tests/cached-upstream-history-oracle.test.ts", + "packages/node-db-sqlite-persistence/tests/node-driver.test.ts": "packages/node-db-sqlite-persistence/tests/node-driver-oracle.test.ts", + "packages/node-db-sqlite-persistence/tests/node-persistence.test.ts": "packages/node-db-sqlite-persistence/tests/node-persistence-oracle.test.ts", + "packages/node-db-sqlite-persistence/tests/node-sqlite-core-adapter-contract.test.ts": "packages/node-db-sqlite-persistence/tests/node-sqlite-core-adapter-contract-oracle.test.ts", + "packages/offline-transactions/tests/KeyScheduler.property.test.ts": "packages/offline-transactions/tests/KeyScheduler-oracle.property.test.ts", + "packages/offline-transactions/tests/fifo-retry.property.test.ts": "packages/offline-transactions/tests/fifo-retry-oracle.property.test.ts", + "packages/offline-transactions/tests/filtered-replay-work.test.ts": "packages/offline-transactions/tests/filtered-replay-work-oracle.test.ts", + "packages/offline-transactions/tests/indexeddb-write-settlement.test.ts": "packages/offline-transactions/tests/indexeddb-write-settlement-oracle.test.ts", + "packages/offline-transactions/tests/leadership-replay.property.test.ts": "packages/offline-transactions/tests/leadership-replay-oracle.property.test.ts", + "packages/offline-transactions/tests/storage-delete-settlement.test.ts": "packages/offline-transactions/tests/storage-delete-settlement-oracle.test.ts", + "packages/offline-transactions/tests/transaction-serializer.property.test.ts": "packages/offline-transactions/tests/transaction-serializer-oracle.property.test.ts", + "packages/offline-transactions/tests/transaction-settlement.property.test.ts": "packages/offline-transactions/tests/transaction-settlement-oracle.property.test.ts", + "packages/powersync-db-collection/tests/schema-transform-conformance.test-d.ts": "packages/powersync-db-collection/tests/schema-transform-conformance-oracle.test-d.ts", + "packages/query-db-collection/tests/cursor-pagination.integration.test.ts": "packages/query-db-collection/tests/cursor-pagination-oracle.integration.test.ts", + "packages/query-db-collection/tests/cursor-pagination.no-peek.integration.test.ts": "packages/query-db-collection/tests/cursor-pagination-oracle.no-peek.integration.test.ts", + "packages/query-db-collection/tests/cursor-pagination.no-peek.test.ts": "packages/query-db-collection/tests/cursor-pagination-oracle.no-peek.test.ts", + "packages/query-db-collection/tests/cursor-pagination/model.ts": "packages/query-db-collection/tests/cursor-pagination/model-oracle.ts", + "packages/query-db-collection/tests/cursor-pagination/no-peek.ts": "packages/query-db-collection/tests/cursor-pagination/no-peek-oracle.ts", + "packages/query-db-collection/tests/query.test-d.ts": "packages/query-db-collection/tests/query-oracle.test-d.ts", + "packages/react-db/tests/conformance.test.tsx": "packages/react-db/tests/conformance-oracle.test.tsx", + "packages/react-db/tests/infinite-query-conformance.test.tsx": "packages/react-db/tests/infinite-query-conformance-oracle.test.tsx", + "packages/react-native-db-sqlite-persistence/e2e/mobile-persisted-collection-conformance-suite.ts": "packages/react-native-db-sqlite-persistence/e2e/mobile-persisted-collection-conformance-suite-oracle.ts", + "packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver.test.ts": "packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver-oracle.test.ts", + "packages/react-native-db-sqlite-persistence/tests/react-native-persistence.test.ts": "packages/react-native-db-sqlite-persistence/tests/react-native-persistence-oracle.test.ts", + "packages/rxdb-db-collection/tests/schema-transform-conformance.test-d.ts": "packages/rxdb-db-collection/tests/schema-transform-conformance-oracle.test-d.ts", + "packages/solid-db/tests/conformance.test.tsx": "packages/solid-db/tests/conformance-oracle.test.tsx", + "packages/svelte-db/tests/conformance.svelte.test.ts": "packages/svelte-db/tests/conformance-oracle.svelte.test.ts", + "packages/svelte-db/tests/infinite-query-conformance.svelte.test.ts": "packages/svelte-db/tests/infinite-query-conformance-oracle.svelte.test.ts", + "packages/tauri-db-sqlite-persistence/e2e/shared/register-persisted-collection-conformance-suite.ts": "packages/tauri-db-sqlite-persistence/e2e/shared/register-persisted-collection-conformance-suite-oracle.ts", + "packages/vue-db/tests/conformance.test.ts": "packages/vue-db/tests/conformance-oracle.test.ts", + "packages/vue-db/tests/infinite-query-conformance.test.ts": "packages/vue-db/tests/infinite-query-conformance-oracle.test.ts" + }, + "namingInventoryRetraction": {"record": "2026-10-03-oracle-naming-scope.md", "reason": "The original owner/companion inventory mixed oracle mechanisms with ordinary tests and support. Use the corrected classification and path map.", "retainedPrRenames": 63, "reversedPrRenames": 101} +} diff --git a/docs/contributing/oracle-reviews/2026-10-02-glossary-alignment.md b/docs/contributing/oracle-reviews/2026-10-02-glossary-alignment.md new file mode 100644 index 0000000000..01dd4ce4fc --- /dev/null +++ b/docs/contributing/oracle-reviews/2026-10-02-glossary-alignment.md @@ -0,0 +1,123 @@ +# Oracle glossary alignment — 2026-10-02 + +Reviewed implementation: [f993daf838da4905d3a327cf6c66d8bdf16d106b](https://github.com/TanStack/db/commit/f993daf838da4905d3a327cf6c66d8bdf16d106b). +Implementation base: `b940a363a7631c49e14dc67e2adeda0a96dc366c`. Original glossary audit: `06cab6fc7b808acfbfb3af1eb2fc1fdc3c9f0fa8`. + +This review resolves 39 retained terminology findings: 18 substantive and 21 minor. +The inventory contains 251 executable oracle owners and dedicated companions. +All filenames contain `oracle`, after 164 moves. Generic fixtures and utilities retain their existing names. + +The [companion ledger](2026-10-02-glossary-alignment.json) preserves every retained finding, its original evidence, +its resolution, the complete owner inventory, and the old-to-new path map. +Original line numbers refer to the audit revision. Current paths refer to the reviewed implementation. +Historical review records and immutable revision links remain unchanged. +Later changes require a new record or an append-only entry tied to their own revision. + +## Scope and result + +Shared terms now name the same boundaries in model declarations, driver observations, and glossary prose. +Model abstractions explicitly describe combined or split production concepts. +The changes preserve model rules, assertions, grammar domains, and campaign budgets. +They also update imports, test commands, replay selectors, coverage links, and browser entry modules after the moves. +Production runtime behavior is unchanged. The only production TypeScript edit corrects a draft-extraction comment. + +This is an ORC-009 vocabulary review and a filename-discovery change. +It does not reassess full ORC-001–014 conformance or close any runtime bug class. +Earlier coverage gaps and review findings outside terminology retain their prior status. +Two stack-checkpoint regexes now match their renamed comparison and Electric SDK oracle filenames. +Their existing checkpoint and shrinking tests verify those path adjustments. + +## Resolution map + +| Domain | Findings | Canonical distinctions | +| --- | ---: | --- | +| Collection lifecycle | 3 | Failed replay versus publication, unsubscribe versus sync run, tentative versus accepted acquisition | +| Optimistic state and values | 2 | Draft extraction versus publication, observation mutant versus runtime fault | +| Includes | 3 | Mutation-handler gate versus startup, bucket versus route, acquisition fulfillment versus initial-query readiness | +| Acquisition and pagination | 5 | Load result versus applied receipt, response processing versus fulfillment, request shape, subscription readiness | +| Core query | 3 | Mutants, equality-partition identity, graph publication versus promise settlement | +| D2 and comparison | 4 | Weighted deltas versus messages, index observations, snapshot cut, comparison domains | +| Query DB | 4 | Compressed model actions, Query fetch versus acquisition, qualified generations, fulfillment-only observations | +| Providers | 3 | Sync run versus provider session, persistence fulfillment, provider control and persistence boundaries | +| SQLite core | 3 | Wrapped sync receipt, adapter reopen, Collection readiness | +| Browser and Electron | 3 | Layered acquisition ownership, committed-message posts, composite promise chain | +| Offline transactions | 4 | Caller success boundary, observation mutants, executor restart and outbox replay, promise fulfillment | +| Frameworks | 2 | Input/window changes and fulfilled page fetches | + +## Validation + +These are unique runtime results from package runs, except the selected framework receiving suites. +The final DB run includes its renamed replay, checkpoint, and oracle files. + +| Package or receiving suites | Passing tests | Files | Result | +| --- | ---: | ---: | --- | +| DB | 7,962 | 210 | Passed | +| DB IVM | 704 | 44 | Passed | +| Offline transactions | 242 | 18 | Passed | +| SQLite persistence core | 375 | 9 | Passed, one todo | +| Node SQLite persistence | 109 | 5 | Passed | +| Browser SQLite persistence | 242 | 9 | Passed | +| Electron SQLite persistence | 97 | 3 | Passed | +| Electric | 629 | 13 | Passed | +| TrailBase | 67 | 3 | Passed | +| PowerSync | 176 | 9 | Passed with local native SQLite | +| Query DB | 557 | 16 | One intermittent baseline failure | +| React, Vue, Solid, Svelte, Angular receiving suites | 290 | 9 | Passed | + +The final supplementary no-peek model rename also passed its 18 affected tests across two files. +The Electric SDK checkpoint follow-up passed all nine tests in that file. +These focused repeats are not additional unique test counts. + +Builds passed for DB, IVM, Offline, Query DB, SQLite core, Node, Browser, Electron, Electric, TrailBase, and PowerSync. +Standalone TypeScript checks passed for IVM, Offline, and Query DB. +Selected framework runs reported no type errors. They were not full framework-package campaigns. +ESLint checked the changed TypeScript files directly in package groups. +Scoped formatting and `git diff --check` passed. +Static checks covered all renamed paths, relative imports, explicit commands, replay targets, and browser script entries. + +### Commands and environment + +Validation used the installed Node, Vite, Vitest, TypeScript, and ESLint entrypoints directly. +The shell hook invokes pnpm, which attempted dependency installation with the reused dependency tree. +The equivalent scoped ESLint check ran directly before commit instead. +Runtime reruns used the following arguments from each package directory: + +```sh +node /vitest.mjs run --coverage.enabled=false --typecheck.enabled=false --maxWorkers=1 --reporter=dot +node /bin/vite.js build +node /bin/tsc --noEmit +``` + +DB used two workers. IVM, Offline, and selected framework runs retained their normal integrated typecheck setting. +The environment used Node 24.19.0, Vitest 3.2.4, TypeScript 5.9.3, and Vite 7.3.2. +The package mirror refused some locked dependencies, and the public registry was unavailable. +Validation reused installed dependencies with workspace links directed at the isolated implementation checkout. +For example, installed Seroval was 1.5.0 while the lockfile requires 1.6.8. The lockfile is unchanged. + +### Limits and baseline evidence + +Default integrated Vitest typecheck lanes are not green under the available dependencies. +They report cross-package `rootDir` diagnostics against unchanged source/configuration boundaries. +Some persistence lanes also report existing generic-cast diagnostics in `persisted.ts` at lines 4976 and 5098. +Those sources remain unchanged. No full baseline typecheck campaign establishes their root cause. +Runtime-only passes do not establish type correctness for those lanes. + +Query DB's unchanged `awaits persisted server responses in update handlers` test intermittently fails its terminal-row assertion. +It expects revision 3 and `$synced: true`, but observes revision 2 and `$synced: false`. +The complete original test file reproduces the same failure under the installed dependencies. +A full original-package control passes 558 tests, and the isolated original test also passes. +The changed-package repeat passes 557 tests with that same failure. All Query DB oracle suites pass. +The test executes before the changed oracle files, and the original-file control fails independently of those files. +This supports an intermittent baseline classification. Its root cause remains unestablished. +The baseline copy preserves original sources and filenames, with four external helper imports adapted to their renamed paths. + +No external-provider, browser-host, Electron-process, or native-device E2E campaign ran. +Local SQLite paths and controlled runtime fixtures executed within the package suites. +Static entrypoint checks establish path consistency only. + +## Retraction of naming inventory — 2026-10-03 + +The 251-file owner/companion classification above is withdrawn. It included ordinary examples, fixtures, harness tests, and documentation. +The [corrected naming review](2026-10-03-oracle-naming-scope.md) classifies each file from executable evidence and supersedes that inventory. +It restores 101 original filenames and retains 63 justified PR renames. The original 39 terminology resolutions remain intact. +The earlier validation results describe the exact implementation revision stated above; they are not a current owner-count claim. diff --git a/docs/contributing/oracle-reviews/2026-10-03-oracle-naming-scope.json b/docs/contributing/oracle-reviews/2026-10-03-oracle-naming-scope.json new file mode 100644 index 0000000000..a981dfb858 --- /dev/null +++ b/docs/contributing/oracle-reviews/2026-10-03-oracle-naming-scope.json @@ -0,0 +1,5189 @@ +{ + "reviewedImplementation": "fe40ab59191d046bda12cc9563cdc4a82b5fd97c", + "classificationEvidenceRevision": "134b7e8bacce5999ab7e06da96d5dbe9989820f5", + "supersedesNamingInventory": "2026-10-02-glossary-alignment.json", + "scope": "Conservative naming classification of the 251 previously inventoried files. Counts are files, not distinct oracle mechanisms. This is not a repository-wide registry or a new guide-conformance audit.", + "counts": { + "driver-or-fixture": 34, + "example-test": 67, + "oracle-owner": 121, + "oracle-definition": 10, + "harness-test": 17, + "documentation": 2 + }, + "retainedPrRenames": { + "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness.opfs.spec.ts": "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness-oracle.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/tests/browser-coordinator.test.ts": "packages/browser-db-sqlite-persistence/tests/browser-coordinator-oracle.test.ts", + "packages/db-collection-e2e/src/suites/joins.suite.ts": "packages/db-collection-e2e/src/suites/joins-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/live-updates.suite.ts": "packages/db-collection-e2e/src/suites/live-updates-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/moves.suite.ts": "packages/db-collection-e2e/src/suites/moves-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/pagination.suite.ts": "packages/db-collection-e2e/src/suites/pagination-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/predicates.suite.ts": "packages/db-collection-e2e/src/suites/predicates-oracle.suite.ts", + "packages/db-collection-e2e/src/utils/notification-laws.ts": "packages/db-collection-e2e/src/utils/notification-laws-oracle.ts", + "packages/db-ivm/tests/hash-failure-retry.property.test.ts": "packages/db-ivm/tests/hash-failure-retry-oracle.property.test.ts", + "packages/db-ivm/tests/hash-graph.property.test.ts": "packages/db-ivm/tests/hash-graph-oracle.property.test.ts", + "packages/db-ivm/tests/hash-mixed-graph.property.test.ts": "packages/db-ivm/tests/hash-mixed-graph-oracle.property.test.ts", + "packages/db-ivm/tests/hash.property.test.ts": "packages/db-ivm/tests/hash-oracle.property.test.ts", + "packages/db-ivm/tests/incrementalization-law.property.test.ts": "packages/db-ivm/tests/incrementalization-law-oracle.property.test.ts", + "packages/db-ivm/tests/incrementalization-law.ts": "packages/db-ivm/tests/incrementalization-law-oracle.ts", + "packages/db-ivm/tests/operators/topKWithFractionalIndex.test.ts": "packages/db-ivm/tests/operators/topKWithFractionalIndex-oracle.test.ts", + "packages/db-ivm/tests/operators/topk-batch-contract.test.ts": "packages/db-ivm/tests/operators/topk-batch-contract-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/persisted.test.ts": "packages/db-sqlite-persistence-core/tests/persisted-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/shared-logical-scheduling.test.ts": "packages/db-sqlite-persistence-core/tests/shared-logical-scheduling-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/sqlite-core-adapter.test.ts": "packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-oracle.test.ts", + "packages/db-sqlite-persistence-core/tests/sqlite-resume-snapshot.test.ts": "packages/db-sqlite-persistence-core/tests/sqlite-resume-snapshot-oracle.test.ts", + "packages/db/tests/SortedMap.test.ts": "packages/db/tests/SortedMap-oracle.test.ts", + "packages/db/tests/cleanup-queue.property.test.ts": "packages/db/tests/cleanup-queue-oracle.property.test.ts", + "packages/db/tests/collection-subscription-lifecycle-grammar.ts": "packages/db/tests/collection-subscription-lifecycle-grammar-oracle.ts", + "packages/db/tests/collection-subscription-lifecycle-history.property.test.ts": "packages/db/tests/collection-subscription-lifecycle-history-oracle.property.test.ts", + "packages/db/tests/collection-subscription-lifecycle-publication.property.test.ts": "packages/db/tests/collection-subscription-lifecycle-publication-oracle.property.test.ts", + "packages/db/tests/collection-sync-reentrancy.test.ts": "packages/db/tests/collection-sync-reentrancy-oracle.test.ts", + "packages/db/tests/comparison.property.test.ts": "packages/db/tests/comparison-oracle.property.test.ts", + "packages/db/tests/conformance/infinite-suite.ts": "packages/db/tests/conformance/infinite-suite-oracle.ts", + "packages/db/tests/conformance/page-laws.ts": "packages/db/tests/conformance/page-laws-oracle.ts", + "packages/db/tests/cursor.property.test.ts": "packages/db/tests/cursor-oracle.property.test.ts", + "packages/db/tests/index-update.property.test.ts": "packages/db/tests/index-update-oracle.property.test.ts", + "packages/db/tests/live-query-observer-history.property.test.ts": "packages/db/tests/live-query-observer-history-oracle.property.test.ts", + "packages/db/tests/local-only-direct-write.test.ts": "packages/db/tests/local-only-direct-write-oracle.test.ts", + "packages/db/tests/notification-laws.test.ts": "packages/db/tests/notification-laws-oracle.test.ts", + "packages/db/tests/optimistic-composition.test.ts": "packages/db/tests/optimistic-composition-oracle.test.ts", + "packages/db/tests/optimistic-history-outcomes.test.ts": "packages/db/tests/optimistic-history-outcomes-oracle.test.ts", + "packages/db/tests/optimistic-history-publication.test.ts": "packages/db/tests/optimistic-history-publication-oracle.test.ts", + "packages/db/tests/optimistic-settlement-boundaries.test.ts": "packages/db/tests/optimistic-settlement-boundaries-oracle.test.ts", + "packages/db/tests/proxy-detachment-contract.test.ts": "packages/db/tests/proxy-detachment-contract-oracle.test.ts", + "packages/db/tests/proxy-iteration-contract.test.ts": "packages/db/tests/proxy-iteration-contract-oracle.test.ts", + "packages/db/tests/proxy-native-methods.property.test.ts": "packages/db/tests/proxy-native-methods-oracle.property.test.ts", + "packages/db/tests/proxy.test.ts": "packages/db/tests/proxy-oracle.test.ts", + "packages/db/tests/query/compiler/evaluators.test.ts": "packages/db/tests/query/compiler/evaluators-oracle.test.ts", + "packages/db/tests/query/derived-delete-reconciliation.test.ts": "packages/db/tests/query/derived-delete-reconciliation-oracle.test.ts", + "packages/db/tests/query/ir-stable-identity.test.ts": "packages/db/tests/query/ir-stable-identity-oracle.test.ts", + "packages/db/tests/query/ordered-source-loader.test.ts": "packages/db/tests/query/ordered-source-loader-oracle.test.ts", + "packages/db/tests/query/ordered-source-loader-state.test.ts": "packages/db/tests/query/ordered-source-loader-state-oracle.test.ts", + "packages/db/tests/query/pooled-live-query-gc.test.ts": "packages/db/tests/query/pooled-live-query-gc-oracle.test.ts", + "packages/db/tests/reference-expression.ts": "packages/db/tests/reference-expression-oracle.ts", + "packages/db/tests/utils.property.test.ts": "packages/db/tests/utils-oracle.property.test.ts", + "packages/electric-db-collection/e2e/sql-predicate-semantics.e2e.test.ts": "packages/electric-db-collection/e2e/sql-predicate-semantics-oracle.e2e.test.ts", + "packages/electric-db-collection/tests/electric-descriptor-isolation.test.ts": "packages/electric-db-collection/tests/electric-descriptor-isolation-oracle.test.ts", + "packages/electric-db-collection/tests/electric-sdk-delivery.property.test.ts": "packages/electric-db-collection/tests/electric-sdk-delivery-oracle.property.test.ts", + "packages/electric-db-collection/tests/pg-serializer.property.test.ts": "packages/electric-db-collection/tests/pg-serializer-oracle.property.test.ts", + "packages/offline-transactions/tests/KeyScheduler.property.test.ts": "packages/offline-transactions/tests/KeyScheduler-oracle.property.test.ts", + "packages/offline-transactions/tests/fifo-retry.property.test.ts": "packages/offline-transactions/tests/fifo-retry-oracle.property.test.ts", + "packages/offline-transactions/tests/leadership-replay.property.test.ts": "packages/offline-transactions/tests/leadership-replay-oracle.property.test.ts", + "packages/offline-transactions/tests/transaction-serializer.property.test.ts": "packages/offline-transactions/tests/transaction-serializer-oracle.property.test.ts", + "packages/offline-transactions/tests/transaction-settlement.property.test.ts": "packages/offline-transactions/tests/transaction-settlement-oracle.property.test.ts", + "packages/query-db-collection/tests/cursor-pagination.integration.test.ts": "packages/query-db-collection/tests/cursor-pagination-oracle.integration.test.ts", + "packages/query-db-collection/tests/cursor-pagination.no-peek.integration.test.ts": "packages/query-db-collection/tests/cursor-pagination-oracle.no-peek.integration.test.ts", + "packages/query-db-collection/tests/cursor-pagination/model.ts": "packages/query-db-collection/tests/cursor-pagination/model-oracle.ts", + "packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver.test.ts": "packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver-oracle.test.ts" + }, + "reversedPrRenames": { + "packages/angular-db/tests/conformance-oracle.test.ts": "packages/angular-db/tests/conformance.test.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle-oracle.opfs.spec.ts": "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle-oracle.opfs.ts": "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-immediate-reload-oracle.opfs.spec.ts": "packages/browser-db-sqlite-persistence/e2e/electric-immediate-reload.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-immediate-reload-oracle.opfs.ts": "packages/browser-db-sqlite-persistence/e2e/electric-immediate-reload.opfs.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-resume-two-tab-oracle.opfs.spec.ts": "packages/browser-db-sqlite-persistence/e2e/electric-resume-two-tab.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/electric-resume-two-tab-oracle.opfs.ts": "packages/browser-db-sqlite-persistence/e2e/electric-resume-two-tab.opfs.ts", + "packages/browser-db-sqlite-persistence/e2e/open-timeout-oracle.opfs.spec.ts": "packages/browser-db-sqlite-persistence/e2e/open-timeout.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/remote-subset-two-tab-oracle.opfs.spec.ts": "packages/browser-db-sqlite-persistence/e2e/remote-subset-two-tab.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/e2e/remote-subset-two-tab-oracle.opfs.ts": "packages/browser-db-sqlite-persistence/e2e/remote-subset-two-tab.opfs.ts", + "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness-oracle.opfs.ts": "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness.opfs.ts", + "packages/capacitor-db-sqlite-persistence/e2e/capacitor-persisted-collection-conformance-suite-oracle.ts": "packages/capacitor-db-sqlite-persistence/e2e/capacitor-persisted-collection-conformance-suite.ts", + "packages/capacitor-db-sqlite-persistence/e2e/shared/register-persisted-collection-conformance-suite-oracle.ts": "packages/capacitor-db-sqlite-persistence/e2e/shared/register-persisted-collection-conformance-suite.ts", + "packages/db-collection-e2e/src/fixtures/persisted-conformance-manifest-oracle.ts": "packages/db-collection-e2e/src/fixtures/persisted-conformance-manifest.ts", + "packages/db-collection-e2e/src/suites/collation-oracle.suite.ts": "packages/db-collection-e2e/src/suites/collation.suite.ts", + "packages/db-collection-e2e/src/suites/deduplication-oracle.suite.ts": "packages/db-collection-e2e/src/suites/deduplication.suite.ts", + "packages/db-collection-e2e/src/suites/mutations-oracle.suite.ts": "packages/db-collection-e2e/src/suites/mutations.suite.ts", + "packages/db-collection-e2e/src/suites/progressive-oracle.suite.ts": "packages/db-collection-e2e/src/suites/progressive.suite.ts", + "packages/db-collection-e2e/src/utils/assertions-oracle.ts": "packages/db-collection-e2e/src/utils/assertions.ts", + "packages/db-ivm/tests/hash-session-oracle.ts": "packages/db-ivm/tests/hash-session.ts", + "packages/db-ivm/tests/hash-session-replay-oracle.test.ts": "packages/db-ivm/tests/hash-session-replay.test.ts", + "packages/db-ivm/tests/hash-work-oracle.test.ts": "packages/db-ivm/tests/hash-work.test.ts", + "packages/db-ivm/tests/operators/topKWithIndex-oracle.test.ts": "packages/db-ivm/tests/operators/topKWithIndex.test.ts", + "packages/db-sqlite-persistence-core/tests/contracts/driver-admission-laws-oracle.ts": "packages/db-sqlite-persistence-core/tests/contracts/driver-admission-laws.ts", + "packages/db-sqlite-persistence-core/tests/contracts/persisted-collection-conformance-contract-oracle.ts": "packages/db-sqlite-persistence-core/tests/contracts/persisted-collection-conformance-contract.ts", + "packages/db-sqlite-persistence-core/tests/contracts/runtime-bridge-e2e-contract-oracle.ts": "packages/db-sqlite-persistence-core/tests/contracts/runtime-bridge-e2e-contract.ts", + "packages/db-sqlite-persistence-core/tests/contracts/runtime-persistence-contract-oracle.ts": "packages/db-sqlite-persistence-core/tests/contracts/runtime-persistence-contract.ts", + "packages/db-sqlite-persistence-core/tests/contracts/sqlite-core-adapter-contract-oracle.ts": "packages/db-sqlite-persistence-core/tests/contracts/sqlite-core-adapter-contract.ts", + "packages/db-sqlite-persistence-core/tests/contracts/sqlite-driver-contract-oracle.ts": "packages/db-sqlite-persistence-core/tests/contracts/sqlite-driver-contract.ts", + "packages/db-sqlite-persistence-core/tests/persisted-real-adapter-lifecycle-oracle.test.ts": "packages/db-sqlite-persistence-core/tests/persisted-real-adapter-lifecycle.test.ts", + "packages/db-sqlite-persistence-core/tests/runtime-restart-checker-oracle.test.ts": "packages/db-sqlite-persistence-core/tests/runtime-restart-checker.test.ts", + "packages/db-sqlite-persistence-core/tests/sqlite-driver-admission-laws-oracle.test.ts": "packages/db-sqlite-persistence-core/tests/sqlite-driver-admission-laws.test.ts", + "packages/db/tests/adapter-schema-transform-conformance-oracle.test-d.ts": "packages/db/tests/adapter-schema-transform-conformance.test-d.ts", + "packages/db/tests/collection-gc-clock-oracle.test.ts": "packages/db/tests/collection-gc-clock.test.ts", + "packages/db/tests/collection-idle-cleanup-oracle.test.ts": "packages/db/tests/collection-idle-cleanup.test.ts", + "packages/db/tests/conformance-disabled-laws-oracle.test.ts": "packages/db/tests/conformance-disabled-laws.test.ts", + "packages/db/tests/conformance-infinite-calibration-oracle.test.ts": "packages/db/tests/conformance-infinite-calibration.test.ts", + "packages/db/tests/conformance-infinite-demand-oracle.test.ts": "packages/db/tests/conformance-infinite-demand.test.ts", + "packages/db/tests/conformance-page-laws-oracle.test.ts": "packages/db/tests/conformance-page-laws.test.ts", + "packages/db/tests/conformance-registration-oracle.test.ts": "packages/db/tests/conformance-registration.test.ts", + "packages/db/tests/conformance-result-laws-oracle.test.ts": "packages/db/tests/conformance-result-laws.test.ts", + "packages/db/tests/conformance-scenario-lifetime-oracle.test.ts": "packages/db/tests/conformance-scenario-lifetime.test.ts", + "packages/db/tests/conformance-scenario-sources-oracle.test.ts": "packages/db/tests/conformance-scenario-sources.test.ts", + "packages/db/tests/conformance-scope-setup-oracle.test.ts": "packages/db/tests/conformance-scope-setup.test.ts", + "packages/db/tests/conformance/contract-oracle.ts": "packages/db/tests/conformance/contract.ts", + "packages/db/tests/conformance/disabled-laws-oracle.ts": "packages/db/tests/conformance/disabled-laws.ts", + "packages/db/tests/conformance/infinite-contract-oracle.ts": "packages/db/tests/conformance/infinite-contract.ts", + "packages/db/tests/conformance/infinite-on-demand-oracle.ts": "packages/db/tests/conformance/infinite-on-demand.ts", + "packages/db/tests/conformance/result-laws-oracle.ts": "packages/db/tests/conformance/result-laws.ts", + "packages/db/tests/conformance/suite-oracle.ts": "packages/db/tests/conformance/suite.ts", + "packages/db/tests/db-client-oracle.test-d.ts": "packages/db/tests/db-client.test-d.ts", + "packages/db/tests/db-client-oracle.test.ts": "packages/db/tests/db-client.test.ts", + "packages/db/tests/live-query-observer-oracle.test.ts": "packages/db/tests/live-query-observer.test.ts", + "packages/db/tests/observer-cleanup-restart-oracle.test.ts": "packages/db/tests/observer-cleanup-restart.test.ts", + "packages/db/tests/query/aggregate-value-contracts-oracle.test-d.ts": "packages/db/tests/query/aggregate-value-contracts.test-d.ts", + "packages/db/tests/query/builder/ref-proxy-oracle.test.ts": "packages/db/tests/query/builder/ref-proxy.test.ts", + "packages/db/tests/query/compiler/lazy-targets-oracle.test.ts": "packages/db/tests/query/compiler/lazy-targets.test.ts", + "packages/db/tests/query/includes-functional-input-boundary-oracle.test.ts": "packages/db/tests/query/includes-functional-input-boundary.test.ts", + "packages/db/tests/query/ordered-default-work-oracle.test.ts": "packages/db/tests/query/ordered-default-work.test.ts", + "packages/db/tests/query/ordered-demand-retirement-oracle.test.ts": "packages/db/tests/query/ordered-demand-retirement.test.ts", + "packages/db/tests/query/public-container-copy-oracle.test.ts": "packages/db/tests/query/public-container-copy.test.ts", + "packages/db/tests/query/query-api-type-algebra-oracle.test-d.ts": "packages/db/tests/query/query-api-type-algebra.test-d.ts", + "packages/db/tests/query/query-api-type-algebra-oracle.test.ts": "packages/db/tests/query/query-api-type-algebra.test.ts", + "packages/db/tests/query/replay-failure-boundary-oracle.test.ts": "packages/db/tests/query/replay-failure-boundary.test.ts", + "packages/db/tests/query/scheduler-oracle.test.ts": "packages/db/tests/query/scheduler.test.ts", + "packages/db/tests/query/validate-aliases-oracle.test.ts": "packages/db/tests/query/validate-aliases.test.ts", + "packages/db/tests/query/where-prefilter-property-visibility-oracle.test.ts": "packages/db/tests/query/where-prefilter-property-visibility.test.ts", + "packages/db/tests/replay-publication-storage-oracle.test.ts": "packages/db/tests/replay-publication-storage.test.ts", + "packages/db/tests/single-row-ref-proxy-oracle.test-d.ts": "packages/db/tests/single-row-ref-proxy.test-d.ts", + "packages/db/tests/sync-reused-row-oracle.test.ts": "packages/db/tests/sync-reused-row.test.ts", + "packages/db/tests/trace-runner-oracle.ts": "packages/db/tests/trace-runner.ts", + "packages/db/tests/transactions-oracle.test.ts": "packages/db/tests/transactions.test.ts", + "packages/db/tests/virtual-props-cache-oracle.test.ts": "packages/db/tests/virtual-props-cache.test.ts", + "packages/electric-db-collection/e2e/subset-sql-acceptance-oracle.e2e.test.ts": "packages/electric-db-collection/e2e/subset-sql-acceptance.e2e.test.ts", + "packages/electric-db-collection/tests/electric-resume-snapshot-races-oracle.test.ts": "packages/electric-db-collection/tests/electric-resume-snapshot-races.test.ts", + "packages/electric-db-collection/tests/electric-sdk-framing-oracle.test.ts": "packages/electric-db-collection/tests/electric-sdk-framing.test.ts", + "packages/electric-db-collection/tests/schema-transform-conformance-oracle.test-d.ts": "packages/electric-db-collection/tests/schema-transform-conformance.test-d.ts", + "packages/electron-db-sqlite-persistence/tests/electron-ipc-oracle.test.ts": "packages/electron-db-sqlite-persistence/tests/electron-ipc.test.ts", + "packages/expo-db-sqlite-persistence/e2e/mobile-persisted-collection-conformance-suite-oracle.ts": "packages/expo-db-sqlite-persistence/e2e/mobile-persisted-collection-conformance-suite.ts", + "packages/node-db-sqlite-persistence/tests/cached-upstream-history-oracle.test.ts": "packages/node-db-sqlite-persistence/tests/cached-upstream-history.test.ts", + "packages/node-db-sqlite-persistence/tests/node-driver-oracle.test.ts": "packages/node-db-sqlite-persistence/tests/node-driver.test.ts", + "packages/node-db-sqlite-persistence/tests/node-persistence-oracle.test.ts": "packages/node-db-sqlite-persistence/tests/node-persistence.test.ts", + "packages/node-db-sqlite-persistence/tests/node-sqlite-core-adapter-contract-oracle.test.ts": "packages/node-db-sqlite-persistence/tests/node-sqlite-core-adapter-contract.test.ts", + "packages/offline-transactions/tests/filtered-replay-work-oracle.test.ts": "packages/offline-transactions/tests/filtered-replay-work.test.ts", + "packages/offline-transactions/tests/indexeddb-write-settlement-oracle.test.ts": "packages/offline-transactions/tests/indexeddb-write-settlement.test.ts", + "packages/offline-transactions/tests/storage-delete-settlement-oracle.test.ts": "packages/offline-transactions/tests/storage-delete-settlement.test.ts", + "packages/powersync-db-collection/tests/schema-transform-conformance-oracle.test-d.ts": "packages/powersync-db-collection/tests/schema-transform-conformance.test-d.ts", + "packages/query-db-collection/tests/cursor-pagination-oracle.no-peek.test.ts": "packages/query-db-collection/tests/cursor-pagination.no-peek.test.ts", + "packages/query-db-collection/tests/cursor-pagination/no-peek-oracle.ts": "packages/query-db-collection/tests/cursor-pagination/no-peek.ts", + "packages/query-db-collection/tests/query-oracle.test-d.ts": "packages/query-db-collection/tests/query.test-d.ts", + "packages/react-db/tests/conformance-oracle.test.tsx": "packages/react-db/tests/conformance.test.tsx", + "packages/react-db/tests/infinite-query-conformance-oracle.test.tsx": "packages/react-db/tests/infinite-query-conformance.test.tsx", + "packages/react-native-db-sqlite-persistence/e2e/mobile-persisted-collection-conformance-suite-oracle.ts": "packages/react-native-db-sqlite-persistence/e2e/mobile-persisted-collection-conformance-suite.ts", + "packages/react-native-db-sqlite-persistence/tests/react-native-persistence-oracle.test.ts": "packages/react-native-db-sqlite-persistence/tests/react-native-persistence.test.ts", + "packages/rxdb-db-collection/tests/schema-transform-conformance-oracle.test-d.ts": "packages/rxdb-db-collection/tests/schema-transform-conformance.test-d.ts", + "packages/solid-db/tests/conformance-oracle.test.tsx": "packages/solid-db/tests/conformance.test.tsx", + "packages/svelte-db/tests/conformance-oracle.svelte.test.ts": "packages/svelte-db/tests/conformance.svelte.test.ts", + "packages/svelte-db/tests/infinite-query-conformance-oracle.svelte.test.ts": "packages/svelte-db/tests/infinite-query-conformance.svelte.test.ts", + "packages/tauri-db-sqlite-persistence/e2e/shared/register-persisted-collection-conformance-suite-oracle.ts": "packages/tauri-db-sqlite-persistence/e2e/shared/register-persisted-collection-conformance-suite.ts", + "packages/vue-db/tests/conformance-oracle.test.ts": "packages/vue-db/tests/conformance.test.ts", + "packages/vue-db/tests/infinite-query-conformance-oracle.test.ts": "packages/vue-db/tests/infinite-query-conformance.test.ts" + }, + "currentTerminologyFindingPaths": { + "01_collection-1": "packages/db/tests/collection-subscription-lifecycle-publication-oracle.property.test.ts", + "01_collection-2": "packages/db/tests/collection-subscription-lifecycle-grammar-oracle.ts", + "01_collection-3": "packages/db/tests/collection-subscription-lifecycle-oracle.test.ts", + "02_optimistic_values-1": "packages/db/tests/proxy-native-methods-oracle.property.test.ts", + "02_optimistic_values-2": "packages/db/tests/optimistic-history-oracle.ts", + "03_includes-1": "packages/db/tests/query/includes-oracle-helpers.ts", + "03_includes-2": "packages/db/tests/query/includes-collection-oracle.property.test.ts", + "03_includes-3": "packages/db/tests/query/includes-temporal-oracle.test.ts", + "04_acquisition-1": "packages/db/tests/query/load-subset-oracle.property.test.ts", + "04_acquisition-3": "packages/db/tests/query/ordered-lifecycle-oracle.property.test.ts", + "04_acquisition-4": "packages/db/tests/query/ordered-work-oracle.property.test.ts", + "04_acquisition-2": "packages/db/tests/query/pagination-oracle.property.test.ts", + "04_acquisition-5": "packages/db/tests/query/load-subset-replay-refinement-oracle.test.ts", + "05_query-2": "docs/contributing/glossary.md", + "05_query-1": "packages/db/tests/live-query-observer-history-oracle.property.test.ts", + "05_query-3": "packages/db/tests/query/scheduler.test.ts", + "06_ivm-1": "packages/db-ivm/tests/test-utils.ts", + "06_ivm-2": "packages/db-ivm/tests/index-refinement-oracle.property.test.ts", + "06_ivm-3": "packages/db/tests/cursor-oracle.property.test.ts", + "06_ivm-4": "packages/db/tests/utils-oracle.property.test.ts", + "07_query_adapter-4": "packages/query-db-collection/tests/ownership-lifecycle.oracle.test.ts", + "07_query_adapter-2": "packages/query-db-collection/tests/cursor-pagination.cache-oracle.test.ts", + "07_query_adapter-3": "packages/query-db-collection/tests/ownership-lifecycle.oracle.test.ts", + "07_query_adapter-5": "packages/query-db-collection/tests/load-subset-lifecycle-oracle.test.ts", + "08_providers-1": "packages/electric-db-collection/tests/electric-descriptor-isolation-oracle.test.ts", + "08_providers-2": "packages/powersync-db-collection/tests/correctness-oracle.test.ts", + "08_providers-3": "packages/electric-db-collection/tests/electric-oracle.property.test.ts", + "09_sqlite_core-2": "packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-oracle.test.ts", + "09_sqlite_core-1": "packages/db-sqlite-persistence-core/tests/persisted-oracle.test.ts", + "09_sqlite_core-3": "packages/db-sqlite-persistence-core/tests/persisted-readiness-oracle.test.ts", + "10_browser_sqlite-1": "packages/browser-db-sqlite-persistence/tests/browser-coordinator-oracle.test.ts", + "10_browser_sqlite-2": "packages/browser-db-sqlite-persistence/tests/browser-coordinator-oracle.test.ts", + "10_browser_sqlite-3": "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.ts", + "11_offline-1": "packages/offline-transactions/tests/transaction-settlement-oracle.property.test.ts", + "11_offline-2": "packages/offline-transactions/tests/KeyScheduler-oracle.property.test.ts", + "11_offline-3": "docs/contributing/glossary.md", + "11_offline-4": "packages/offline-transactions/tests/indexeddb-write-settlement.test.ts", + "12_frameworks-1": "packages/db/tests/conformance/infinite-contract.ts", + "12_frameworks-2": "packages/db/tests/conformance/infinite-suite-oracle.ts" + }, + "files": [ + { + "path": "packages/angular-db/tests/conformance.test.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/angular-db/tests/conformance-oracle.test.ts", + "evidenceLines": [ + 62, + 144, + 183, + 224, + 283 + ], + "mechanism": "Angular source/mount/current/cleanup adapter passes a LiveQueryDriver to runSuite in packages/db/tests/conformance/suite-oracle.ts. Additional checks are fixed publication examples or driver/scope calibration; this file does not compute independent product expectations.", + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.spec.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle-oracle.opfs.spec.ts", + "evidenceLines": [ + 91, + 108, + 122, + 132, + 158, + 183, + 188, + 216 + ], + "mechanism": "One hardcoded PostgreSQL update history: initialRow and updatedRow are supplied literals, and expectExactRow merely wraps those literals into public/durable expected observations. The remaining tests check diagnostic helpers. There is no independent history reducer or generalized reference rule here.", + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle-oracle.opfs.ts", + "evidenceLines": [ + 122, + 188, + 207, + 221, + 285, + 290, + 318 + ], + "mechanism": "Holds production sync begin/commit and hydration return, records applied-receipt reach and public/durable rows, and exposes a browser probe. It does not compute an independently expected result.", + "ownerPaths": [ + "packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.spec.ts" + ], + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/e2e/electric-immediate-reload.opfs.spec.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/browser-db-sqlite-persistence/e2e/electric-immediate-reload-oracle.opfs.spec.ts", + "evidenceLines": [ + 88, + 101, + 151, + 158, + 217, + 229, + 239, + 252, + 263 + ], + "mechanism": "Single insert/hard-close/reopen regression with a literal row and manually enumerated phase/public/durable expectations. expectedPublicObservation only projects the supplied expected record; the PostgreSQL SELECT verifies the same literal, rather than supplying a differential reference computation. Additional cases test polling/diagnostic helpers.", + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/e2e/electric-immediate-reload.opfs.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/browser-db-sqlite-persistence/e2e/electric-immediate-reload-oracle.opfs.ts", + "evidenceLines": [ + 103, + 178, + 184, + 195, + 201, + 205 + ], + "mechanism": "Creates the Electric/persisted Collection, parks its durable adapter write, records real public/durable rows, and exposes insert/recovery controls. Expected-result judgments live in the spec.", + "ownerPaths": [ + "packages/browser-db-sqlite-persistence/e2e/electric-immediate-reload.opfs.spec.ts" + ], + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/e2e/electric-resume-two-tab.opfs.spec.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/browser-db-sqlite-persistence/e2e/electric-resume-two-tab-oracle.opfs.spec.ts", + "evidenceLines": [ + 72, + 80, + 137, + 156, + 251, + 261, + 312 + ], + "mechanism": "Two named legacy-loss examples run the same fixed seed/add-row/handoff/reopen trace. expectedRows only sorts the explicitly supplied fixture rows; rowsAfter is a case-table expectation. No independent transition model or reusable query-result computation is exercised.", + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/e2e/electric-resume-two-tab.opfs.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/browser-db-sqlite-persistence/e2e/electric-resume-two-tab-oracle.opfs.ts", + "evidenceLines": [ + 126, + 175, + 302, + 311, + 320, + 346 + ], + "mechanism": "Creates real host Collections, edits durable storage to establish legacy-loss input, and transports actual Collection/resume observations. Poisoning checks confirm fixture setup, not an independent expected-result law.", + "ownerPaths": [ + "packages/browser-db-sqlite-persistence/e2e/electric-resume-two-tab.opfs.spec.ts" + ], + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/e2e/open-timeout.opfs.spec.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/browser-db-sqlite-persistence/e2e/open-timeout-oracle.opfs.spec.ts", + "evidenceLines": [ + 36, + 41, + 101, + 115, + 121, + 125, + 139 + ], + "mechanism": "One real-Web-Lock receiving witness with a fixed 15-second deadline and hardcoded TimeoutError, removed pending lock, and SELECT 1 expectations. Important host regression, but no independent generalized deadline/state oracle is invoked.", + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/e2e/remote-subset-two-tab.opfs.spec.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/browser-db-sqlite-persistence/e2e/remote-subset-two-tab-oracle.opfs.spec.ts", + "evidenceLines": [ + 24, + 28, + 40, + 43, + 59, + 69, + 77, + 85 + ], + "mechanism": "One fixed item ID and two-tab load, followed by one invalid-wire value. Expected row, route flags, counts, and error path are literal example assertions, without an independent reference computation.", + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/e2e/remote-subset-two-tab.opfs.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/browser-db-sqlite-persistence/e2e/remote-subset-two-tab-oracle.opfs.ts", + "evidenceLines": [ + 81, + 138, + 141, + 186, + 203, + 210, + 215 + ], + "mechanism": "Supplies a controlled QueryClient-backed provider, records local request fields and wire posts, starts a real filtered live query, and exposes its actual rows. Parsing the request in the provider supplies test data, not expected-result judgment.", + "ownerPaths": [ + "packages/browser-db-sqlite-persistence/e2e/remote-subset-two-tab.opfs.spec.ts" + ], + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness-oracle.opfs.spec.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness-oracle.opfs.spec.ts", + "evidenceLines": [ + 81, + 84, + 115, + 128 + ], + "mechanism": "The fixed native storm executes the independently defined K=1 fairness rule through its page companion and rejects any returned violation. This is a narrow receiving oracle, not merely the fixed row assertions: the shared checker derives permitted persist IDs/counts from the scenario and compares every hydrate checkpoint. Fixed native scenarios do not make that generalized independent rule a hardcoded trace. Borderline ownership is split across the page and spec, but the spec owns pass/fail at the semantic checkpoint.", + "ownerPaths": [ + "packages/browser-db-sqlite-persistence/tests/shared-driver-fairness-oracle.ts", + "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness.opfs.ts" + ], + "confidence": "medium" + }, + { + "path": "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness.opfs.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness-oracle.opfs.ts", + "evidenceLines": [ + 77, + 112, + 120, + 125, + 140 + ], + "mechanism": "Chooses two fixed host scenarios, runs the shared production driver with real OPFS, invokes the imported fairness checker, and transports its violation result. It defines neither the independent fairness rule nor test acceptance; the receiving spec rejects that result. Dedicated oracle support remains a fixture.", + "ownerPaths": [ + "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness-oracle.opfs.spec.ts", + "packages/browser-db-sqlite-persistence/tests/shared-driver-fairness-oracle.ts" + ], + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/tests/browser-coordinator-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/browser-db-sqlite-persistence/tests/browser-coordinator-oracle.test.ts", + "evidenceLines": [ + 6419, + 6423, + 6472, + 6506, + 6513, + 6788, + 6843, + 6851 + ], + "mechanism": "Although mostly example tests, it also contains genuine generalized independent routing and retention laws. Generated collection counts/registration permutations/target IDs drive real coordinator RPC; expected call counts are computed solely from target identity (index === targetIndex ? 1 : 0). A separate generated release-order ledger decrements independent remaining count and compares both retained maps after each action.", + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/tests/opfs-page-lifecycle-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/browser-db-sqlite-persistence/tests/opfs-page-lifecycle-oracle.test.ts", + "evidenceLines": [ + 371, + 478, + 486, + 547, + 585, + 588, + 605, + 1145, + 1163 + ], + "mechanism": "Computes the expected raw settlement ledger from delivery stage, request count, release direction, and completed prefix. For mixed histories, the independent index predicate determines fulfilled versus rejected outcomes before comparison with actual production opener/query settlements. Existing pre-PR oracle name remains untouched.", + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/tests/opfs-worker-diagnostics-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/browser-db-sqlite-persistence/tests/opfs-worker-diagnostics-oracle.test.ts", + "evidenceLines": [ + 61, + 66, + 211, + 216, + 279 + ], + "mechanism": "referenceMessage independently concatenates primary/cause fields from scalar input; generated error classes/messages invoke the production worker init handler and compare the complete response to that computation. Existing pre-PR name is untouched.", + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/tests/per-collection-coordinator-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/browser-db-sqlite-persistence/tests/per-collection-coordinator-oracle.test.ts", + "evidenceLines": [ + 1664, + 1668, + 1670, + 1709, + 2125, + 2247, + 2778, + 2790, + 3391 + ], + "mechanism": "Contains explicit independent reusable models: remoteLeaseHistoryViolations computes expected loads/unloads/remaining acquisitions from the history, and PerCollectionRouteOracle maps owner plus Collection identity to expected adapter. Generated production histories compare their captured traces against those models. Existing pre-PR name is untouched.", + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/tests/shared-driver-fairness-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/browser-db-sqlite-persistence/tests/shared-driver-fairness-oracle.test.ts", + "evidenceLines": [ + 235, + 256, + 260, + 270, + 653, + 702 + ], + "mechanism": "For generated logical admission histories, independently derives expected hydrate rows and persist FIFO order and applies findSharedDriverFairnessViolation to actual shared-driver observations. Fixed/random campaigns execute this comparison; the wrong-scheduler control checks sensitivity. Existing pre-PR name is untouched.", + "confidence": "high" + }, + { + "path": "packages/browser-db-sqlite-persistence/tests/shared-driver-fairness-oracle.ts", + "role": "oracle-definition", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/browser-db-sqlite-persistence/tests/shared-driver-fairness-oracle.ts", + "evidenceLines": [ + 438, + 449, + 454, + 463, + 471, + 475, + 486 + ], + "mechanism": "Defines createFairnessReference: the expected bound is min(persistCount, 1 + hydrateIndex * K), with FIFO permitted persist IDs. findSharedDriverFairnessViolation compares real checkpoint identities/counts/remaining work to that rule. Also contains production-driver mechanics, but its independent reusable checker establishes definition ownership. Existing pre-PR name is untouched.", + "ownerPaths": [ + "packages/browser-db-sqlite-persistence/tests/shared-driver-fairness-oracle.test.ts", + "packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness-oracle.opfs.spec.ts" + ], + "confidence": "high" + }, + { + "path": "packages/capacitor-db-sqlite-persistence/e2e/capacitor-persisted-collection-conformance-suite.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/capacitor-db-sqlite-persistence/e2e/capacitor-persisted-collection-conformance-suite-oracle.ts", + "evidenceLines": [ + 13, + 17, + 25, + 29 + ], + "mechanism": "Creates a temporary SQLite database and platform harness, then registers the shared suite. No expected-result computation or product assertion is defined.", + "ownerPaths": [ + "packages/db-sqlite-persistence-core/tests/contracts/persisted-collection-conformance-contract.ts" + ], + "confidence": "high" + }, + { + "path": "packages/capacitor-db-sqlite-persistence/e2e/shared/register-persisted-collection-conformance-suite.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/capacitor-db-sqlite-persistence/e2e/shared/register-persisted-collection-conformance-suite-oracle.ts", + "evidenceLines": [ + 18, + 24, + 30, + 36, + 44 + ], + "mechanism": "Only lifecycle hooks, harness lookup, and invocation of the shared conformance registration function. It imports judgment; it does not own it.", + "ownerPaths": [ + "packages/db-sqlite-persistence-core/tests/contracts/persisted-collection-conformance-contract.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db-collection-e2e/src/fixtures/persisted-conformance-manifest.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/db-collection-e2e/src/fixtures/persisted-conformance-manifest-oracle.ts", + "evidenceLines": [ + 13, + 129 + ], + "mechanism": "Literal persisted-conformance test-name manifest and name-formatting function support registration/native result collection. They neither run production nor judge a modeled result.", + "confidence": "high" + }, + { + "path": "packages/db-collection-e2e/src/suites/collation.suite.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db-collection-e2e/src/suites/collation-oracle.suite.ts", + "evidenceLines": [ + 160, + 161, + 173, + 188, + 218, + 252 + ], + "mechanism": "A fixed lexical witness inserts the five authored names A10, A2, Z, a, ä in a fixed permutation and compares real rows to that literal sequence. The local expectOrderedRows closure is exact equality against this example, not an independently computed collation rule; negative controls do not change its role.", + "confidence": "high" + }, + { + "path": "packages/db-collection-e2e/src/suites/deduplication.suite.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db-collection-e2e/src/suites/deduplication-oracle.suite.ts", + "evidenceLines": [ + 278, + 307, + 313, + 324, + 338, + 342 + ], + "mechanism": "Fixed concurrent-query examples assert sizes, nonemptiness, differing offsets, and equal result counts among identical queries. The 20-query burst compares every count to the first production count; it provides no independently computed deduplication/load model. This weak same-input peer comparison is borderline, so conservatively restore the example-suite name.", + "confidence": "medium" + }, + { + "path": "packages/db-collection-e2e/src/suites/joins-oracle.suite.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-collection-e2e/src/suites/joins-oracle.suite.ts", + "evidenceLines": [ + 29, + 35, + 36, + 42, + 45, + 48, + 87, + 108, + 125 + ], + "mechanism": "Independent userPostPairs and withComments loops compute left-join pairs/triples from captured fixture rows, including unmatched children. Real query projections are compared against those reference rows through createJoinOracle, with independent fixture ordering for ordered cases.", + "confidence": "high" + }, + { + "path": "packages/db-collection-e2e/src/suites/live-updates-oracle.suite.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-collection-e2e/src/suites/live-updates-oracle.suite.ts", + "evidenceLines": [ + 144, + 159, + 161, + 163, + 216 + ], + "mechanism": "Captures every real subscribeChanges batch alongside callback-visible complete rows and executes expectNotificationHistory on that production history. The imported checker independently reconstructs row state from each insert/update/delete and checks every callback and final row set.", + "confidence": "high" + }, + { + "path": "packages/db-collection-e2e/src/suites/moves-oracle.suite.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-collection-e2e/src/suites/moves-oracle.suite.ts", + "evidenceLines": [ + 192, + 193, + 221, + 226, + 231, + 236, + 239, + 244, + 249, + 254, + 319 + ], + "mechanism": "Maintains independent activeUsers/posts maps from authored commands. check computes expected visible posts by filtering modeled posts through modeled user activity, compares complete production entries, and also applies notification-history reconstruction to real callback observations.", + "confidence": "high" + }, + { + "path": "packages/db-collection-e2e/src/suites/mutations.suite.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db-collection-e2e/src/suites/mutations-oracle.suite.ts", + "evidenceLines": [ + 188, + 192, + 194, + 200, + 376, + 383, + 389, + 394 + ], + "mechanism": "Authored insertion/deletion/update histories compare observed peers plus a particular inserted row, and a fixed eleven-row ordered witness checks literal slices before/after one age change. Generic equality/capture helpers do not independently evaluate a query or maintain a generalized mutation model. The insert-then-delete frame check has a metamorphic flavor; conservatively restore the example-suite name.", + "confidence": "medium" + }, + { + "path": "packages/db-collection-e2e/src/suites/pagination-oracle.suite.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-collection-e2e/src/suites/pagination-oracle.suite.ts", + "evidenceLines": [ + 47, + 52, + 55, + 62, + 64, + 69, + 72, + 78, + 85, + 86 + ], + "mechanism": "createWindowOracle clones independent fixture rows, sorts with a test-side comparator, and computes ranked.slice(offset, offset + limit). It checks real query rows for exact cardinality, unique identities, unchanged values, and legal rank ties across window scenarios.", + "confidence": "high" + }, + { + "path": "packages/db-collection-e2e/src/suites/predicates-oracle.suite.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-collection-e2e/src/suites/predicates-oracle.suite.ts", + "evidenceLines": [ + 76, + 78, + 79, + 90, + 103, + 104, + 179, + 200, + 218 + ], + "mechanism": "Computes expected rows by native fixture filtering (and independent ordering for orderedAliceRows), then captures real query values and compares their complete selected rows. The reference predicate evaluation is separate from the production query builder.", + "confidence": "high" + }, + { + "path": "packages/db-collection-e2e/src/suites/progressive.suite.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db-collection-e2e/src/suites/progressive-oracle.suite.ts", + "evidenceLines": [ + 350, + 355, + 360, + 368, + 372, + 391, + 396, + 399, + 403 + ], + "mechanism": "Fixed progressive-load smoke/regression cases check readiness, limits, literal predicates, and peer-query membership. The snapshot deduplication case runs three identical age=30 queries and compares them to the first result; there is no independent progressive/publication state model. Treat the limited peer comparison conservatively as an example.", + "confidence": "medium" + }, + { + "path": "packages/db-collection-e2e/src/utils/assertions.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/db-collection-e2e/src/utils/assertions-oracle.ts", + "evidenceLines": [ + 8, + 13, + 15, + 78, + 89, + 108, + 140, + 162 + ], + "mechanism": "Generic assertion utilities compare caller-supplied IDs/counts, apply a caller-supplied predicate, or check adjacent ordering. They do not derive complete product expectations or own a domain reference computation; the retained pagination/predicate suites own their reference fixture computations.", + "ownerPaths": [ + "packages/db-collection-e2e/src/suites/pagination-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/predicates-oracle.suite.ts" + ], + "confidence": "medium" + }, + { + "path": "packages/db-collection-e2e/src/utils/notification-laws-oracle.ts", + "role": "oracle-definition", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-collection-e2e/src/utils/notification-laws-oracle.ts", + "evidenceLines": [ + 16, + 22, + 24, + 32, + 36, + 42, + 46 + ], + "mechanism": "expectNotificationHistory independently reconstructs a Map from notification events, checks event admission/previous values, and requires each callback-visible row set and final rows to equal that reconstructed state. Named suites execute it against real production callbacks.", + "ownerPaths": [ + "packages/db-collection-e2e/src/suites/live-updates-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/moves-oracle.suite.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/d2-work-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db-ivm/tests/d2-work-oracle.test.ts", + "evidenceLines": [ + 47, + 53, + 61, + 62, + 66, + 73, + 74 + ], + "mechanism": "A bounded per-branch input ledger computes the expected invocation vector from the selected active branch and next branch, then compares every real D2 operator call count after each graph.run(). This is a small generalized work rule across branch positions; the separate reversed-registration case is a fixed example.", + "confidence": "medium" + }, + { + "path": "packages/db-ivm/tests/hash-failure-retry-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-ivm/tests/hash-failure-retry-oracle.property.test.ts", + "evidenceLines": [ + 38, + 76, + 90, + 101, + 105, + 108, + 135 + ], + "mechanism": "expectRetryHistory derives getter-read counts from the generated rejecting position, failed-attempt count, and untouched suffix. It checks the thrown error and all read counts after each real hash attempt, compares the successful result with a separately built structural copy, and checks subsequent cache reuse.", + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/hash-graph-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-ivm/tests/hash-graph-oracle.property.test.ts", + "evidenceLines": [ + 50, + 69, + 87, + 98, + 108, + 112, + 181 + ], + "mechanism": "An independent reachable-indegree/Kahn model predicts cycle rejection. For acyclic generated graphs, the checker unfolds shared nodes into fresh trees and requires real hash agreement; for reachable cycles it requires repeated rejection.", + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/hash-identity-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db-ivm/tests/hash-identity-oracle.property.test.ts", + "evidenceLines": [ + 135, + 182, + 233, + 752, + 758, + 765, + 775, + 834 + ], + "mechanism": "A spec-level canonical identity encoding derives expected equality independently of the production hasher. Generated specs are realized into runtime values and checked in both comparison directions and through hash compatibility, including a second module with forced collisions and separately constructed cyclic pairs.", + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/hash-mixed-graph-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-ivm/tests/hash-mixed-graph-oracle.property.test.ts", + "evidenceLines": [ + 100, + 118, + 135, + 151, + 159, + 165, + 174 + ], + "mechanism": "The checker computes reachable acyclicity with an indegree model over a separate graph specification. Realizations mix object, array, Map, Set, and symbol edge carriers; cyclic results must reject and acyclic shared graphs must hash like their independent unfoldings.", + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/hash-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-ivm/tests/hash-oracle.property.test.ts", + "evidenceLines": [ + 95, + 113, + 148, + 239, + 248, + 253, + 303, + 319 + ], + "mechanism": "Generated metamorphic laws compare hash results for independently constructed clones and reordered object properties. The concrete judgment includes insertion-order independence, equal byte/date contents, and declared type-marker distinctions; it is not only deterministic-output examples.", + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/hash-session.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/db-ivm/tests/hash-session-oracle.ts", + "evidenceLines": [ + 24, + 38, + 42, + 47, + 58, + 61, + 78 + ], + "mechanism": "captureHashSession reloads the production module while recording/replaying Math.random initialization draws and attaching environment metadata. HashReplayError preserves failure context. Tape validation judges capture/replay mechanics, not hash semantics; there is no independent product-result model here.", + "ownerPaths": [ + "packages/db-ivm/tests/hash-oracle.property.test.ts", + "packages/db-ivm/tests/hash-identity-oracle.property.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/hash-session-replay.test.ts", + "role": "harness-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db-ivm/tests/hash-session-replay-oracle.test.ts", + "evidenceLines": [ + 14, + 40, + 51, + 63, + 66, + 78, + 87, + 97 + ], + "mechanism": "The main comparisons verify that captureHashSession reproduces the same module initialization and encounter order, including generated permutations, and rejects incomplete/excessive tapes. expectSessionLaws supplies fixed hash sanity examples across a few tapes; it does not make this replay-harness calibration an independent product owner.", + "ownerPaths": [ + "packages/db-ivm/tests/hash-oracle.property.test.ts", + "packages/db-ivm/tests/hash-identity-oracle.property.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/hash-work.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db-ivm/tests/hash-work-oracle.test.ts", + "evidenceLines": [ + 5, + 30, + 83, + 100, + 105, + 128, + 137, + 143, + 148, + 164 + ], + "mechanism": "The allocation counter observes production work, but the tests judge fixed constructions with literal expectations: a depth-200 shared DAG must read 400 getters, one repeated Map pair must copy entries twice, and a table supplies hand-written maximum sizes for seven shapes. The two-attempt retry examples and single opaque-handle mutation example do not provide a reusable expected-work model. Conservatively restore the original name.", + "confidence": "medium" + }, + { + "path": "packages/db-ivm/tests/incrementalization-law-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-ivm/tests/incrementalization-law-oracle.property.test.ts", + "evidenceLines": [ + 176, + 184, + 264, + 289, + 336, + 341, + 348, + 354, + 378 + ], + "mechanism": "Plain Map/loop/full-sort evaluators compute whole relations for consolidate, reduce, joins, grouped aggregates, and top-K. Generated input-world histories are sent through real D2 operators and judged by the companion incrementalization checker at each logical batch, including compatible split delivery.", + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/incrementalization-law-oracle.ts", + "role": "oracle-definition", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-ivm/tests/incrementalization-law-oracle.ts", + "evidenceLines": [ + 109, + 136, + 168, + 309, + 326, + 338, + 347, + 355, + 371, + 435, + 457, + 465 + ], + "mechanism": "Owns the reusable weighted-relation model, signed integration and difference, legal partition grammar, and unary/binary refinement checks. The checks compare real emitted deltas and cumulative output with independently supplied full-recomputation results and compare atomic versus split delivery. This owns judgment as well as driver mechanics.", + "ownerPaths": [ + "packages/db-ivm/tests/incrementalization-law-oracle.property.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/index-refinement-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db-ivm/tests/index-refinement-oracle.property.test.ts", + "evidenceLines": [ + 58, + 71, + 179, + 191, + 195, + 198, + 201, + 246 + ], + "mechanism": "expectedIndex independently folds each history prefix into nested native Maps using a declared type-and-value identity and signed multiplicities. After every real Index.addValue, the checker compares complete observed multiplicities and has() with that prefix model.", + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/multiset-consolidate-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db-ivm/tests/multiset-consolidate-oracle.property.test.ts", + "evidenceLines": [ + 106, + 154, + 163, + 408, + 412, + 414, + 428, + 437, + 544 + ], + "mechanism": "expectedConsolidation independently classifies the supported identity domain, groups records by direct primitive/reference or canonical structural equality, sums multiplicities, and retains the first record. Generated real MultiSet.consolidate output is checked for each exact group, weight, retained reference, omissions, duplicates, and unchanged inputs.", + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/operators/topKWithFractionalIndex-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-ivm/tests/operators/topKWithFractionalIndex-oracle.test.ts", + "evidenceLines": [ + 86, + 95, + 125, + 138, + 148, + 168, + 196, + 239, + 243, + 279, + 311 + ], + "mechanism": "Despite many fixed examples later in the file, the generated sections maintain independent source Maps, recompute full ordered windows with sort/slice, and compare them with the cumulative signed TopKRelation after every real graph turn. The grammar includes replacements, transient cancellation, outer joins, and multiple production top-K variants.", + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/operators/topKWithIndex.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db-ivm/tests/operators/topKWithIndex-oracle.test.ts", + "evidenceLines": [ + 49, + 96, + 146, + 167, + 191, + 224, + 291, + 359, + 409, + 425, + 438 + ], + "mechanism": "The file supplies hand-written inputs and expected output arrays for initial windows and individual row changes. Its one TopKMessageTracker/TopKRelation use checks a fixed remove-b example against the literal rows a,c,d; the local helpers only sort observations. It contains no independent window recomputation or generalized history law of its own. Importing the shared checker is the borderline point; conservatively restore this filename.", + "confidence": "medium" + }, + { + "path": "packages/db-ivm/tests/operators/topk-batch-contract-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-ivm/tests/operators/topk-batch-contract-oracle.test.ts", + "evidenceLines": [ + 16, + 22, + 26, + 129, + 161, + 177, + 182, + 202, + 203, + 213, + 228, + 230 + ], + "mechanism": "Parameterized value-pair constructors define equivalence relations independently of hashing, then generated payloads and delivery order cross those relations with collision and grouping modes. The cancellation rule judges real topKBatch output, and a real ordered D2 graph must retain exactly the equivalent old row or distinct replacement with unit weight.", + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/operators/topk-relation-oracle.test.ts", + "role": "harness-test", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db-ivm/tests/operators/topk-relation-oracle.test.ts", + "evidenceLines": [ + 3, + 19, + 20, + 41, + 44, + 77, + 84, + 98 + ], + "mechanism": "Only constructs TopKRelation checker instances and feeds them valid or deliberately corrupted observations to calibrate duplicate weight, retraction, index, payload, capture, and replay behavior. No real top-K production operator is exercised. The existing pre-PR oracle filename is outside the rename correction.", + "ownerPaths": [ + "packages/db-ivm/tests/operators/topKWithFractionalIndex-oracle.test.ts", + "packages/db-ivm/tests/operators/topk-support-window-oracle.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/operators/topk-relation-oracle.ts", + "role": "oracle-definition", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db-ivm/tests/operators/topk-relation-oracle.ts", + "evidenceLines": [ + 27, + 33, + 38, + 49, + 51, + 59, + 64, + 67, + 75 + ], + "mechanism": "TopKRelation owns independent cumulative signed integration keyed by full modeled row/index identity. Its checker rejects nonunit residue, compares complete rows, derives numeric indexes from offset and position, or checks strict fractional-index order. This is reusable semantic judgment used by generated production owners; TopKMessageTracker additionally supplies capture.", + "ownerPaths": [ + "packages/db-ivm/tests/operators/topKWithFractionalIndex-oracle.test.ts", + "packages/db-ivm/tests/operators/topk-support-window-oracle.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/operators/topk-support-window-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db-ivm/tests/operators/topk-support-window-oracle.test.ts", + "evidenceLines": [ + 37, + 124, + 128, + 154, + 169, + 196, + 229, + 236, + 247, + 252, + 258 + ], + "mechanism": "An independent native Map counts typed-key support. At each generated input or window-move checkpoint, a fixed independent key order is filtered by positive support and sliced by offset/limit, then compared with the accumulated real fractional-index output and reported window size. Ordinary top-K also checks preserved multiplicity against its running input count.", + "confidence": "high" + }, + { + "path": "packages/db-ivm/tests/temporal-group-key-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db-ivm/tests/temporal-group-key-oracle.test.ts", + "evidenceLines": [ + 27, + 70, + 78, + 86, + 101, + 103, + 109, + 113, + 122, + 127 + ], + "mechanism": "expectedGroupCounts independently counts fixture-declared identity classes, and observedGroupCounts executes real D2 groupBy and records group cardinalities, unit weights, and distinct output keys. The bounded Temporal-kind cross product is judged by that class-counting rule rather than output arrays calculated separately per kind. Its oracle is narrow and based on fixed equivalence-class assignments.", + "confidence": "medium" + }, + { + "path": "packages/db-sqlite-persistence-core/tests/contracts/driver-admission-laws.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/db-sqlite-persistence-core/tests/contracts/driver-admission-laws-oracle.ts", + "evidenceLines": [ + 4, + 8 + ], + "mechanism": "expectAdmissionHistory only maps rows to value and compares them to a caller-supplied expected string array. This is a generic equality wrapper, not an independent admission state model or reference rule.", + "confidence": "high" + }, + { + "path": "packages/db-sqlite-persistence-core/tests/contracts/persisted-collection-conformance-contract.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/db-sqlite-persistence-core/tests/contracts/persisted-collection-conformance-contract-oracle.ts", + "evidenceLines": [ + 34, + 39, + 47, + 49, + 52, + 55, + 58, + 61, + 64, + 67 + ], + "mechanism": "Only registers imported predicate/pagination/join/deduplication/collation/mutation/live-update suites according to capability flags. It computes no expected result and performs no independent comparison.", + "ownerPaths": [ + "packages/db-collection-e2e/src/suites/predicates-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/pagination-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/joins-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/deduplication.suite.ts", + "packages/db-collection-e2e/src/suites/collation.suite.ts", + "packages/db-collection-e2e/src/suites/mutations.suite.ts", + "packages/db-collection-e2e/src/suites/live-updates-oracle.suite.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db-sqlite-persistence-core/tests/contracts/runtime-bridge-e2e-contract.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db-sqlite-persistence-core/tests/contracts/runtime-bridge-e2e-contract-oracle.ts", + "evidenceLines": [ + 31, + 34, + 39, + 48, + 50, + 51, + 52, + 81, + 92, + 118, + 124 + ], + "mechanism": "assertRuntimeRestartHistory encapsulates one fixed two-row write/restart/write example with literal rows and literal expected snapshots. The other exported suite cases are one fixed round-trip and fixed missing-collection error assertions. Sharing this scenario across hosts does not add an independent reference model or generalized checker.", + "confidence": "high" + }, + { + "path": "packages/db-sqlite-persistence-core/tests/contracts/runtime-persistence-contract.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db-sqlite-persistence-core/tests/contracts/runtime-persistence-contract-oracle.ts", + "evidenceLines": [ + 44, + 49, + 57, + 81, + 95, + 112, + 121, + 128, + 136 + ], + "mechanism": "Three hardcoded shared examples: write one fixed todo and query it, persist one fixed Collection insert and inspect its key/title through a second adapter, and assert coordinator identity. Factory injection supplies host coverage but no independently computed domain-wide result.", + "confidence": "high" + }, + { + "path": "packages/db-sqlite-persistence-core/tests/contracts/sqlite-core-adapter-contract.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/db-sqlite-persistence-core/tests/contracts/sqlite-core-adapter-contract-oracle.ts", + "evidenceLines": [ + 1, + 2, + 3, + 4 + ], + "mechanism": "Four-line re-export only; it neither owns nor executes independent judgment. The model and registered property are in sqlite-core-adapter-oracle.test.ts.", + "ownerPaths": [ + "packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-oracle.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db-sqlite-persistence-core/tests/contracts/sqlite-driver-contract.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db-sqlite-persistence-core/tests/contracts/sqlite-driver-contract-oracle.ts", + "evidenceLines": [ + 65, + 70, + 91, + 181, + 200, + 262, + 264, + 268, + 273, + 307, + 311, + 320, + 353 + ], + "mechanism": "Reusable host suite is a set of fixed SQL examples with literal expected rows/orders: [1,2,3] for one held transaction, [3] after one rollback, [1,3] after one nested savepoint rollback. expectAdmissionHistory receives those literal arrays; it does not derive admission from an independent schedule model.", + "confidence": "high" + }, + { + "path": "packages/db-sqlite-persistence-core/tests/persisted-options-type-oracle.test-d.ts", + "role": "example-test", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db-sqlite-persistence-core/tests/persisted-options-type-oracle.test-d.ts", + "evidenceLines": [ + 48, + 58, + 60, + 63, + 79, + 84, + 91, + 103, + 115, + 136 + ], + "mechanism": "Ordinary positive and negative TypeScript examples for one concrete RowInput/RowOutput schema, string keys, and own-key sync overloads. No generalized independent type relation or type-level algebra. Existing pre-PR oracle filename must remain unchanged despite this classification.", + "confidence": "high" + }, + { + "path": "packages/db-sqlite-persistence-core/tests/persisted-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-sqlite-persistence-core/tests/persisted-oracle.test.ts", + "evidenceLines": [ + 668, + 679, + 687, + 697, + 698, + 703, + 8880, + 8881, + 8902, + 9009, + 9195 + ], + "mechanism": "Mixed large file contains a genuine independent append-only durability reference: foldDurabilityLedger interprets begin/write/abort/commit events into committedRows and commitOrder without production queues. Real persisted-wrapper histories are checked against that fold at durable receipt and reopen observations; this specific mechanism, not the many fixed regressions, warrants the name.", + "confidence": "high" + }, + { + "path": "packages/db-sqlite-persistence-core/tests/persisted-readiness-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db-sqlite-persistence-core/tests/persisted-readiness-oracle.test.ts", + "evidenceLines": [ + 22, + 23, + 26, + 29, + 210, + 216, + 259, + 265, + 267, + 279, + 283 + ], + "mechanism": "expectedPersistedSnapshot independently computes opt-in availability, error precedence, and all-source readiness from source outcomes. A finite cross-product drives real Collections/live-query observer and compares persistedStatus, isPersistedReady, and exact error to that computation. Existing pre-PR name remains unchanged.", + "confidence": "high" + }, + { + "path": "packages/db-sqlite-persistence-core/tests/persisted-real-adapter-lifecycle.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db-sqlite-persistence-core/tests/persisted-real-adapter-lifecycle-oracle.test.ts", + "evidenceLines": [ + 165, + 188, + 213, + 218, + 220, + 234, + 256, + 259, + 267, + 270, + 280, + 282, + 285 + ], + "mechanism": "observeRestartOrder runs one fixed two-start cleanup/restart schedule and records counts. The generated variant only selects scheduled versus unscheduled and an incidental schemaVersion; assertions choose the fixed 1/2/4 counts for those same two schedules. No independent lifecycle model or scalable/generalized schedule judgment is present. Borderline because it uses fc.asyncProperty, but restore the original filename conservatively.", + "confidence": "medium" + }, + { + "path": "packages/db-sqlite-persistence-core/tests/runtime-restart-checker.test.ts", + "role": "harness-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db-sqlite-persistence-core/tests/runtime-restart-checker-oracle.test.ts", + "evidenceLines": [ + 9, + 12, + 15, + 28, + 31, + 47, + 48, + 51, + 54, + 56 + ], + "mechanism": "Runs assertRuntimeRestartHistory against an in-memory fake and deliberately changes score/id/extra-row/drop-next-write to ensure the checker throws. It tests checker sensitivity, not production persistence.", + "confidence": "high" + }, + { + "path": "packages/db-sqlite-persistence-core/tests/shared-logical-scheduling-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-sqlite-persistence-core/tests/shared-logical-scheduling-oracle.test.ts", + "evidenceLines": [ + 302, + 304, + 306, + 307, + 311, + 316, + 318, + 325, + 328, + 332, + 334, + 335 + ], + "mechanism": "Contains a generalized partial admission/cardinality law: generated hydrateQueries and peerQueries control real adapter work; while the hydrate is held, admission count must not advance, and after release metadata query count must equal independently computed hydrateQueries + peerQueries. It judges variable-size production histories without consulting the scheduler; fixed cases elsewhere are not the basis for retention.", + "confidence": "high" + }, + { + "path": "packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-oracle.test.ts", + "evidenceLines": [ + 251, + 258, + 261, + 265, + 335, + 349, + 378, + 584, + 1824, + 1852, + 1856, + 1882, + 1884, + 1895 + ], + "mechanism": "Contains generated reset/resume lineage oracle: expectedResetResumeMetadata derives exact retained metadata keys and resume kind from the declared destructive/non-destructive transition and arbitrary metadata set. observeResetResumeHistory drives real SQLite adapter transitions, then expectResetResumeLaw compares observed metadata with the independent result. The property generates rows, metadata, versions, and reopen counts.", + "confidence": "high" + }, + { + "path": "packages/db-sqlite-persistence-core/tests/sqlite-driver-admission-laws.test.ts", + "role": "harness-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db-sqlite-persistence-core/tests/sqlite-driver-admission-laws-oracle.test.ts", + "evidenceLines": [ + 4, + 5, + 11, + 12, + 18, + 27, + 29, + 30, + 34 + ], + "mechanism": "Feeds fixed good and deliberately interleaved/missing/extra arrays to expectAdmissionHistory and asserts acceptance or throw. No production driver is used; this is checker calibration.", + "confidence": "high" + }, + { + "path": "packages/db-sqlite-persistence-core/tests/sqlite-resume-snapshot-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db-sqlite-persistence-core/tests/sqlite-resume-snapshot-oracle.test.ts", + "evidenceLines": [ + 257, + 272, + 286, + 351, + 365, + 379, + 383, + 386, + 391, + 398, + 437, + 442, + 445, + 450 + ], + "mechanism": "Mixed file contains startup reference recomputation across generated baseline sizes and managed/no-write/raw-loss transitions. Expected public rows are independently built from original baseline plus managed insert, or empty for raw loss, then compared with real Collection and durable snapshot observations. It runs the same computation in fixed and random campaigns.", + "confidence": "high" + }, + { + "path": "packages/db/tests/SortedMap-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/SortedMap-oracle.test.ts", + "evidenceLines": [ + 53, + 59, + 64, + 78, + 90, + 109, + 111, + 125, + 133 + ], + "mechanism": "Generated set/delete/clear histories update both production SortedMap and a native Map. expectMap derives expected ordering by a fresh full sort and compares every public iterator, size, membership, and value observation, including deferred-order checkpoints and three ordering modes.", + "confidence": "high" + }, + { + "path": "packages/db/tests/adapter-schema-transform-conformance.test-d.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/adapter-schema-transform-conformance-oracle.test-d.ts", + "evidenceLines": [ + 9, + 23, + 42, + 74, + 78, + 96, + 104, + 114, + 130 + ], + "mechanism": "Two concrete schema-transform fixtures assert RowInput/RowOutput and individual callback/parameter types with expectTypeOf and @ts-expect-error. The ItemOf extractor is ordinary type plumbing; there is no generalized independent type algebra that computes expected adapter types. Restore the PR-added oracle name.", + "confidence": "high" + }, + { + "path": "packages/db/tests/btree-map-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/btree-map-oracle.test.ts", + "evidenceLines": [ + 118, + 143, + 171, + 177, + 208, + 216, + 229, + 234, + 257, + 273 + ], + "mechanism": "A native Map step model independently computes operation returns and preserves both payload references and original values. Generated BTree histories are compared after each action for point reads, size/extrema, sorted full/range scans, bounds, and neighboring pairs using filtering over independently sorted model keys.", + "confidence": "high" + }, + { + "path": "packages/db/tests/change-event-history-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/change-event-history-oracle.test.ts", + "evidenceLines": [ + 139, + 149, + 187, + 443, + 453, + 461 + ], + "mechanism": "An independent keyed Map reducer applyModelOp/expectedRowsAfter computes each legal operation prefix; expectedEventTrace derives causal insert/update/delete payloads. runHistory compares actual Collection rows, callback replicas, and index observations against those computations.", + "confidence": "high" + }, + { + "path": "packages/db/tests/cleanup-queue-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/cleanup-queue-oracle.property.test.ts", + "evidenceLines": [ + 61, + 77, + 88, + 109, + 128, + 143, + 153, + 247 + ], + "mechanism": "stepModel independently reduces schedule/cancel/elapsed-time actions into appointments, due deliveries and errors. runHistory drives the production CleanupQueue and compares delivery/error traces after each step; generated action histories execute that rule.", + "confidence": "high" + }, + { + "path": "packages/db/tests/collection-cleanup-restart-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/collection-cleanup-restart-oracle.test.ts", + "evidenceLines": [ + 88, + 92, + 100, + 108, + 334, + 347, + 356 + ], + "mechanism": "expectedCleanupBoundary is an independent three-cut function of prior Collection status and cleanup boundary. Real cleanup/restart tests compare restart admission, public status, dependent termination, and settlement observations with its calculated boundary state; the file also contains ordinary regressions.", + "confidence": "high" + }, + { + "path": "packages/db/tests/collection-gc-clock.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/collection-gc-clock-oracle.test.ts", + "evidenceLines": [ + 11, + 24, + 31, + 35, + 38 + ], + "mechanism": "One fixed fake-timer history sets gcTime to 1, steps the wall clock backward, advances elapsed time by 10, and asserts subscriber count 1 then 0. It contains no appointment reference computation or reusable independent judgment.", + "confidence": "high" + }, + { + "path": "packages/db/tests/collection-idle-cleanup.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/collection-idle-cleanup-oracle.test.ts", + "evidenceLines": [ + 26, + 47, + 57, + 80, + 84, + 88, + 90 + ], + "mechanism": "One fixed idle-scheduler regression executes a no-time callback, returns/removes a subscriber, executes the rescheduled callback, and checks literal ready status. The pending callback Map is a controllable scheduler fixture, not an expected lifecycle model.", + "confidence": "high" + }, + { + "path": "packages/db/tests/collection-metadata-publication-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/collection-metadata-publication-oracle.property.test.ts", + "evidenceLines": [ + 285, + 338, + 340, + 374, + 389, + 398, + 407, + 412 + ], + "mechanism": "applyRound maintains independent row and metadata Maps, applying committed metadata writes to a separately cloned expected world. It derives expected change messages and callback-time metadata/row cuts and compares those with the real Collection across generated rounds.", + "confidence": "high" + }, + { + "path": "packages/db/tests/collection-mutation-startup-oracle.test.ts", + "role": "example-test", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/collection-mutation-startup-oracle.test.ts", + "evidenceLines": [ + 63, + 72, + 90, + 145, + 231, + 375, + 406, + 440, + 475 + ], + "mechanism": "The rejectionCases table supplies concrete mutations and per-example error assertions; subsequent startup cases assert fixed starts, handler calls, rows, and errors. The stated five admission cells are descriptive categories, not a reusable executable admission model. Existing pre-PR oracle filename is outside rename correction.", + "confidence": "high" + }, + { + "path": "packages/db/tests/collection-state-retention-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/collection-state-retention-oracle.property.test.ts", + "evidenceLines": [ + 135, + 153, + 164, + 168, + 184, + 204, + 215, + 2718 + ], + "mechanism": "applyAction updates an independent retained-row Map from the input history, and expectRetainedState compares exposed authoritative base, public rows, and stale row-origin keys after production sync/lifecycle actions. Other sections execute the shared optimistic-history model.", + "confidence": "high" + }, + { + "path": "packages/db/tests/collection-subscription-lifecycle-grammar-oracle.ts", + "role": "oracle-definition", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/collection-subscription-lifecycle-grammar-oracle.ts", + "evidenceLines": [ + 183, + 352, + 375, + 412, + 832 + ], + "mechanism": "Owns the independent LifecycleModel, reduceLifecycle command reducer, expected observations/trace, and deferral grammar. The history and publication owners import this model and compare real Collection observations with its transitions.", + "ownerPaths": [ + "packages/db/tests/collection-subscription-lifecycle-history-oracle.property.test.ts", + "packages/db/tests/collection-subscription-lifecycle-publication-oracle.property.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db/tests/collection-subscription-lifecycle-history-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/collection-subscription-lifecycle-history-oracle.property.test.ts", + "evidenceLines": [ + 163, + 349, + 356, + 401, + 409, + 446, + 467 + ], + "mechanism": "runHistory executes real subscription/lifecycle commands and separately reduces the shared LifecycleModel. assertState compares loads, unloads, caller outcomes, errors, Collection/subscription statuses, signals, and full event trace with model-derived values at every command.", + "confidence": "high" + }, + { + "path": "packages/db/tests/collection-subscription-lifecycle-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/collection-subscription-lifecycle-oracle.test.ts", + "evidenceLines": [ + 484, + 650, + 685, + 769, + 774, + 778, + 784, + 801, + 809 + ], + "mechanism": "The mixed file contains runAsyncRestartScenario: its independent settlement ledger derives current-generation completeness, success, retained versus replacement row version, failed attempts, publication trace, and status transitions from scenario outcomes. It compares these computed values after each controlled production settlement; this qualifies independently of its many fixed boundary examples.", + "confidence": "high" + }, + { + "path": "packages/db/tests/collection-subscription-lifecycle-publication-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/collection-subscription-lifecycle-publication-oracle.property.test.ts", + "evidenceLines": [ + 261, + 291, + 301, + 335, + 932, + 943, + 954 + ], + "mechanism": "Owns an independent publication model with source, visible, and private replacement Maps. publicationDiff/publishIfChanged/finishReplacement/projectPublication compute expected rows and message batches from lifecycle and source commands; the production driver compares public observations after each command.", + "confidence": "high" + }, + { + "path": "packages/db/tests/collection-subscription-reentrancy-oracle.test.ts", + "role": "example-test", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/collection-subscription-reentrancy-oracle.test.ts", + "evidenceLines": [ + 28, + 97, + 118, + 120, + 123, + 125, + 141, + 273 + ], + "mechanism": "The callback-phase × release/unsubscribe matrix runs one fixed snapshot pattern and checks literal false/no publication/one acquisition outcomes, with small phase-dependent hook/read counts. Remaining cases are pinned regressions. No independent ownership/history reducer or generalized expected-result computation is executed here. Existing pre-PR oracle filename remains unchanged.", + "confidence": "medium" + }, + { + "path": "packages/db/tests/collection-subscription-replay-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/collection-subscription-replay-oracle.property.test.ts", + "evidenceLines": [ + 310, + 383, + 745, + 757, + 762, + 768, + 790, + 798, + 803, + 814, + 815 + ], + "mechanism": "runReplayScenario tracks independent source and published-row Maps plus pending replay state. It derives retained versus replacement publications from controlled settlement/release/source histories and compares source state, visible rows, message diffs, status, and publication counts against real subscription behavior.", + "confidence": "high" + }, + { + "path": "packages/db/tests/collection-sync-reentrancy-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/collection-sync-reentrancy-oracle.test.ts", + "evidenceLines": [ + 121, + 137, + 146, + 149, + 189, + 198, + 206, + 1508, + 1514 + ], + "mechanism": "runListenerScenario builds an independent ordered list of committed keys from generated commit/abort actions. It compares actual application order and batches against that list, checks aborted receipt counts/outcomes and no nested delivery, and executes exhaustive and generated histories.", + "confidence": "high" + }, + { + "path": "packages/db/tests/collection-truncate-ownership-oracle.property.test.ts", + "role": "example-test", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/collection-truncate-ownership-oracle.property.test.ts", + "evidenceLines": [ + 46, + 82, + 86, + 121, + 128, + 140, + 154, + 156, + 247 + ], + "mechanism": "The generator varies a key, two payload values, and rollback/rejection in one fixed two-owner/truncate schedule. expectObservation merely substitutes the accepted input row into a literal ready/key-set expectation; it does not reduce owner histories or compare a broader independent relation. Conservative classification as a parameterized regression; existing pre-PR name remains unchanged.", + "confidence": "medium" + }, + { + "path": "packages/db/tests/comparison-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/comparison-oracle.property.test.ts", + "evidenceLines": [ + 237, + 295, + 313, + 473, + 475, + 482, + 491, + 501 + ], + "mechanism": "Generalized comparator laws independently constrain production ascComparator over generated values: reflexivity, antisymmetry, transitivity, and deterministic valid numeric signs. Additional value-specific comparisons use direct primitive/byte relations. Replay-calibration sections do not replace these executed product laws.", + "confidence": "high" + }, + { + "path": "packages/db/tests/conformance-disabled-laws.test.ts", + "role": "harness-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/conformance-disabled-laws-oracle.test.ts", + "evidenceLines": [ + 9, + 22, + 29, + 68, + 72, + 74, + 79 + ], + "mechanism": "Builds synthetic disabled-result objects, mutates their fields, and verifies expectDisabledResult accepts/rejects them. It calibrates a shared assertion helper without observing production hook behavior.", + "confidence": "high" + }, + { + "path": "packages/db/tests/conformance-infinite-calibration.test.ts", + "role": "harness-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/conformance-infinite-calibration-oracle.test.ts", + "evidenceLines": [ + 6, + 8, + 9, + 41, + 84, + 91, + 100 + ], + "mechanism": "Intercepts Vitest registration, injects deliberately faulty/coalesced fake drivers into the shared suite, and checks whether its concurrent-fetch scenario passes/rejects and cleans up. The object under test is the conformance runner.", + "confidence": "high" + }, + { + "path": "packages/db/tests/conformance-infinite-demand.test.ts", + "role": "harness-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/conformance-infinite-demand-oracle.test.ts", + "evidenceLines": [ + 27, + 50, + 52, + 54, + 59, + 69, + 108, + 124, + 174, + 179 + ], + "mechanism": "Checks the test-only makeInfiniteOnDemandSource provider against literal supported/invalid requests and verifies request capture. Its additional production-query integration uses fixed expected row windows; no independent generalized product oracle is defined here.", + "confidence": "high" + }, + { + "path": "packages/db/tests/conformance-page-laws.test.ts", + "role": "harness-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/conformance-page-laws-oracle.test.ts", + "evidenceLines": [ + 7, + 15, + 20, + 23, + 27, + 37, + 42, + 43, + 48 + ], + "mechanism": "Feeds synthetic page partitions and corrupted page arrays into expectPageRows. The randomized property generates checker inputs, rather than observing production pagination.", + "confidence": "high" + }, + { + "path": "packages/db/tests/conformance-registration.test.ts", + "role": "harness-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/conformance-registration-oracle.test.ts", + "evidenceLines": [ + 2, + 4, + 7, + 11, + 18, + 21 + ], + "mechanism": "Tests duplicate scenario registration and failure-waiver rejection in the test registry using literal names. No production product observation.", + "confidence": "high" + }, + { + "path": "packages/db/tests/conformance-result-laws.test.ts", + "role": "harness-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/conformance-result-laws-oracle.test.ts", + "evidenceLines": [ + 15, + 32, + 55, + 69, + 120, + 132, + 145, + 151, + 181 + ], + "mechanism": "Calibrates result-surface/equality helpers with synthetic rows, generated duplicate groups, wrong order, and wrong keyed values. Generated samples remain inputs to the checker under test, not product observations.", + "confidence": "high" + }, + { + "path": "packages/db/tests/conformance-scenario-lifetime.test.ts", + "role": "harness-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/conformance-scenario-lifetime-oracle.test.ts", + "evidenceLines": [ + 5, + 49, + 88, + 139, + 154, + 178, + 217, + 228 + ], + "mechanism": "Exercises the ScenarioLifetime test resource manager with successful/failed cleanups, aggregate errors, and late acquisitions. These are harness lifecycle checks rather than product laws.", + "confidence": "high" + }, + { + "path": "packages/db/tests/conformance-scenario-sources.test.ts", + "role": "harness-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/conformance-scenario-sources-oracle.test.ts", + "evidenceLines": [ + 3, + 4, + 9, + 10, + 31, + 33, + 53, + 58, + 87, + 102 + ], + "mechanism": "Checks ScenarioSources/ScenarioLifetime ownership, source cleanup, duplicate handles, and error aggregation. Although one case allocates a real Collection, the judged contract is test-harness disposal.", + "confidence": "high" + }, + { + "path": "packages/db/tests/conformance-scope-setup.test.ts", + "role": "harness-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/conformance-scope-setup-oracle.test.ts", + "evidenceLines": [ + 4, + 5, + 45, + 49, + 64 + ], + "mechanism": "Checks the test scope-setup wrapper preserves successful values and combines setup/disposal failures. No production query/reference comparison.", + "confidence": "high" + }, + { + "path": "packages/db/tests/conformance/contract.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/conformance/contract-oracle.ts", + "evidenceLines": [ + 28, + 40, + 65, + 79, + 102, + 135 + ], + "mechanism": "Type/interface declarations for source handles, operation access, result surfaces, and LiveQueryDriver. They describe adapter plumbing and contain no executable independent judgment.", + "confidence": "high" + }, + { + "path": "packages/db/tests/conformance/disabled-laws.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/conformance/disabled-laws-oracle.ts", + "evidenceLines": [ + 5, + 9, + 13, + 17, + 18, + 20 + ], + "mechanism": "Reusable fixed assertion template requires disabled status/flags and either absent values or empty reactive containers. It does not compute a modeled result or a generalized relation beyond those two literal shapes; conservatively restore the helper name.", + "confidence": "medium" + }, + { + "path": "packages/db/tests/conformance/infinite-contract.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/conformance/infinite-contract-oracle.ts", + "evidenceLines": [ + 27, + 32, + 43, + 59, + 73 + ], + "mechanism": "Interfaces describe infinite-query config, result, handles, and driver operations; the file contains no executable window reference computation.", + "ownerPaths": [ + "packages/db/tests/conformance/infinite-suite-oracle.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db/tests/conformance/infinite-on-demand.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/conformance/infinite-on-demand-oracle.ts", + "evidenceLines": [ + 139, + 144, + 182, + 185, + 187, + 193, + 203, + 207, + 210 + ], + "mechanism": "Controlled test provider copies request inputs, filters/sorts a finite backend, and writes resulting rows into production sync. Its evaluator generates provider input responses; it never judges expected versus observed production output. The shared infinite suite owns that judgment.", + "ownerPaths": [ + "packages/db/tests/conformance/infinite-suite-oracle.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db/tests/conformance/infinite-suite-oracle.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/conformance/infinite-suite-oracle.ts", + "evidenceLines": [ + 38, + 45, + 46, + 49, + 54, + 55, + 56, + 57, + 657, + 658, + 674, + 704, + 705, + 712, + 713, + 718, + 722 + ], + "mechanism": "expectedOverlappingWindow independently derives visible rows, page slices/params, continuation, fetching, error, and status from modeled source extent and settlement flags. The overlapping preload/fetch scenario enumerates source sizes and settlement orders, applies source changes, and compares the real exported controller snapshot to this model.", + "confidence": "high" + }, + { + "path": "packages/db/tests/conformance/page-laws-oracle.ts", + "role": "oracle-definition", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/conformance/page-laws-oracle.ts", + "evidenceLines": [ + 5, + 13, + 15, + 18, + 21 + ], + "mechanism": "expectPageRows independently computes complete page count and page slices from expected rows/pageSize, and enforces reconstruction of data by flattening pages. The shared infinite suite applies this generalized page-partition law to real hook observations.", + "ownerPaths": [ + "packages/db/tests/conformance/infinite-suite-oracle.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db/tests/conformance/result-laws.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/conformance/result-laws-oracle.ts", + "evidenceLines": [ + 4, + 19, + 45, + 68, + 79, + 82, + 88 + ], + "mechanism": "Generic selected-row normalization and ordered/unordered/keyed equality helpers compare actual data with caller-supplied expected data. They do not derive domain expected results; the infinite suite and page checker own their independent window/partition computations.", + "ownerPaths": [ + "packages/db/tests/conformance/infinite-suite-oracle.ts" + ], + "confidence": "medium" + }, + { + "path": "packages/db/tests/conformance/suite.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/conformance/suite-oracle.ts", + "evidenceLines": [ + 66, + 247, + 251, + 260, + 267, + 280, + 284, + 289, + 293, + 297, + 298 + ], + "mechanism": "Registers reusable fixed conformance examples over SEED and hand-authored mutations. basic-select expects a literal John Smith row; equality-filter transitions expect literal ID arrays and final rows. Reuse across framework drivers and generic equality helpers does not provide an independent query evaluator or state model.", + "confidence": "high" + }, + { + "path": "packages/db/tests/cursor-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/cursor-oracle.property.test.ts", + "evidenceLines": [ + 70, + 78, + 103, + 115, + 117, + 124, + 146, + 171, + 212, + 256 + ], + "mechanism": "Independent scalar and tuple comparison functions define continuation and ordering. The checker evaluates the expression returned by real buildCursor with a reference evaluator and compares its denotation to the direct boundary rule; public Collection ordered snapshots after preload are compared with independently derived tuple order.", + "confidence": "high" + }, + { + "path": "packages/db/tests/d2-source-reconciliation-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/d2-source-reconciliation-oracle.property.test.ts", + "evidenceLines": [ + 218, + 230, + 246, + 290, + 303, + 346, + 349, + 373, + 378 + ], + "mechanism": "Source operations update an independent source-row Map. Signed production reconciliation outputs are integrated into a separate weighted relation and compared with one unit contribution per expected source row; the production reconciler is the system under test, not the source of expected values.", + "confidence": "high" + }, + { + "path": "packages/db/tests/db-client-hydration-authority-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/db-client-hydration-authority-oracle.test.ts", + "evidenceLines": [ + 77, + 160, + 211, + 217 + ], + "mechanism": "referenceRows independently folds initial rows and declarative adapter/hydration history; runHistory compares synced data, public rows, and a subscription mirror against that recomputation.", + "confidence": "high" + }, + { + "path": "packages/db/tests/db-client.test-d.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/db-client-oracle.test-d.ts", + "evidenceLines": [ + 15, + 47, + 72, + 90, + 111 + ], + "mechanism": "Concrete DbClient dependency, descriptor, hydration payload, preload, and schema type assertions. Expected types are explicitly written for the examples; there is no independent generalized type relation.", + "confidence": "high" + }, + { + "path": "packages/db/tests/db-client.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/db-client-oracle.test.ts", + "evidenceLines": [ + 28, + 168, + 463, + 987, + 1066, + 1173 + ], + "mechanism": "Fixed client isolation, hydration, serialization, and cleanup regressions, including parameterized insert/delete authority cases. No reusable independent state/reference computation judges these observations; the separate hydration-authority oracle owns that model.", + "confidence": "high" + }, + { + "path": "packages/db/tests/effect-disposal-oracle.test.ts", + "role": "example-test", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/effect-disposal-oracle.test.ts", + "evidenceLines": [ + 23, + 34, + 84, + 87, + 105, + 108, + 114, + 124, + 126, + 130 + ], + "mechanism": "A fixed matrix crosses two reentry sites, handler pending/synchronous, and three outcomes for the same three-caller disposal schedule. Assertions check literal one-release/no-early-settlement outcomes and equality of the three returned results. There is a useful common-result relation, but no separate reusable disposal/history checker; conservatively retain example classification. Existing pre-PR name remains unchanged.", + "confidence": "medium" + }, + { + "path": "packages/db/tests/flat-change-tracking-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/flat-change-tracking-oracle.property.test.ts", + "evidenceLines": [ + 165, + 169, + 175, + 601, + 617, + 630, + 660, + 714 + ], + "mechanism": "expectedChanges executes operations on independent plain copies and derives changed/deleted fields. runHistory compares both production tracking paths with that result, including a separate modeled error outcome, across generated histories.", + "confidence": "high" + }, + { + "path": "packages/db/tests/index-suggestion-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/index-suggestion-oracle.test.ts", + "evidenceLines": [ + 34, + 40, + 44, + 71, + 84, + 97, + 103 + ], + "mechanism": "expectedSuggestions computes the policy from advice-enabled, Collection size, indexing mode and indexed field. A finite scenario domain drives real query/index suggestion creation, and the result is compared to the computed expected count. This is a small independent decision rule, not merely per-scenario expected literals. Existing pre-PR name stays untouched.", + "confidence": "high" + }, + { + "path": "packages/db/tests/index-update-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/index-update-oracle.property.test.ts", + "evidenceLines": [ + 102, + 117, + 121, + 133, + 139, + 202, + 207, + 211, + 224, + 235, + 250, + 253 + ], + "mechanism": "A native Map owns the expected key/value rows through generated put, delete, and rebuild histories. Fresh grouping, sorting, and direct range predicates derive expected lookups and complete memberships for both real index types; the same independent model also checks a separately rebuilt index.", + "confidence": "high" + }, + { + "path": "packages/db/tests/live-query-observer-history-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/live-query-observer-history-oracle.property.test.ts", + "evidenceLines": [ + 232, + 251, + 328, + 335, + 413, + 563, + 580 + ], + "mechanism": "Independent listener-eligibility and delivery state machine: subscribeModel, publishModel, and disposeModel evolve expected state; runHistory drives the real observer and compares exact delivery history, source state, and snapshots after commands.", + "confidence": "high" + }, + { + "path": "packages/db/tests/live-query-observer.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/live-query-observer-oracle.test.ts", + "evidenceLines": [ + 23, + 393, + 657, + 734, + 793, + 823, + 849, + 1244 + ], + "mechanism": "Focused observer regressions assert concrete snapshot, publication, listener, and lifecycle outcomes. Setup helpers construct sources; no independent history model is executed in this file. The independent eligibility model is in the separate observer-history file.", + "confidence": "high" + }, + { + "path": "packages/db/tests/local-only-direct-write-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/local-only-direct-write-oracle.test.ts", + "evidenceLines": [ + 163, + 174, + 191, + 198, + 199, + 209, + 263, + 264, + 266 + ], + "mechanism": "Mixed file, but observe runs the same write history through two distinct paths: direct local-only writes and the explicitly confirmed optimistic path. The test compares their computed rows, batches, errors and transaction states. The differential mechanism at 263–266 qualifies independently of surrounding hardcoded guard regressions.", + "confidence": "high" + }, + { + "path": "packages/db/tests/mutation-handler-type-oracle.test-d.ts", + "role": "example-test", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/mutation-handler-type-oracle.test-d.ts", + "evidenceLines": [ + 26, + 44, + 54, + 67, + 80, + 142, + 152, + 155, + 169, + 224 + ], + "mechanism": "Concrete default/explicit/schema-inferred, branded and numeric key fixtures assert callback types and rejected assignments. IsAny is a helper for an ordinary type assertion, not an independent type model/algebra. Classify as examples under the corrected rule, while leaving the existing pre-PR oracle filename untouched.", + "confidence": "high" + }, + { + "path": "packages/db/tests/notification-laws-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/notification-laws-oracle.test.ts", + "evidenceLines": [ + 5, + 17, + 26, + 42, + 75, + 82, + 85, + 90 + ], + "mechanism": "Generated source histories drive a real Collection and live-query Collection. The shared independent expectNotificationHistory checker reconstructs membership and previous values from callback messages and checks callback snapshots against input-derived expected worlds; post-unsubscribe silence is also checked.", + "confidence": "high" + }, + { + "path": "packages/db/tests/observer-cleanup-restart.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/observer-cleanup-restart-oracle.test.ts", + "evidenceLines": [ + 50, + 51 + ], + "mechanism": "A fixed cleanup/restart scenario is repeated across observer mode and resumption variants, then asserts literal empty data and Map results. No independent state machine or differential result computation.", + "confidence": "high" + }, + { + "path": "packages/db/tests/optimistic-composition-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/optimistic-composition-oracle.test.ts", + "evidenceLines": [ + 12, + 54, + 253, + 256, + 261, + 262, + 350, + 359, + 369, + 372 + ], + "mechanism": "Although much of this file is fixed regression coverage, its permutation tests execute an independent snapshot ledger: expected snapshots are assembled from input patches, active owners select the newest surviving snapshot, and a reducer excludes rolled-back owners. Real source rows, event replicas, and downstream rows are compared with the computed snapshot.", + "confidence": "high" + }, + { + "path": "packages/db/tests/optimistic-history-oracle.ts", + "role": "oracle-definition", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/optimistic-history-oracle.ts", + "evidenceLines": [ + 96, + 124, + 172, + 217, + 242, + 350, + 409, + 460, + 722, + 799, + 829 + ], + "mechanism": "Defines the reusable independent HistoryModel over base rows, ordered intents and source batches, plus generic event/outcome comparisons. runOptimisticHistory drives a real Collection and compares reads, event replicas and downstream rows to model state after each action. This module has no test registration; its importing test owners execute it.", + "ownerPaths": [ + "packages/db/tests/collection-state-retention-oracle.property.test.ts", + "packages/db/tests/optimistic-history-outcomes-oracle.test.ts", + "packages/db/tests/optimistic-history-publication-oracle.test.ts", + "packages/db/tests/optimistic-settlement-boundaries-oracle.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db/tests/optimistic-history-outcomes-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/optimistic-history-outcomes-oracle.test.ts", + "evidenceLines": [ + 40, + 43, + 57, + 64, + 83, + 93, + 104, + 114 + ], + "mechanism": "The product-test section builds failed-write/peer-survival histories from generated scenarios and executes runOptimisticHistory, which computes expected rows, callbacks and promise outcomes independently. The file also contains harness calibration tests, but is not solely a harness test.", + "ownerPaths": [ + "packages/db/tests/optimistic-history-oracle.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db/tests/optimistic-history-publication-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/optimistic-history-publication-oracle.test.ts", + "evidenceLines": [ + 21, + 24, + 38, + 47, + 53, + 66, + 69, + 82, + 84 + ], + "mechanism": "Pinned source/optimistic histories execute the shared independent HistoryModel/refinement check via runOptimisticHistory; this file supplies action sequences rather than hardcoded expected rows or batches. It also runs deliberate captured-observation corruptions through the same checker. Retained because the production outcome is judged by the reusable model, not by the example names.", + "ownerPaths": [ + "packages/db/tests/optimistic-history-oracle.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db/tests/optimistic-settlement-boundaries-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/optimistic-settlement-boundaries-oracle.test.ts", + "evidenceLines": [ + 26, + 31, + 34, + 40, + 43, + 141, + 144, + 148, + 149 + ], + "mechanism": "Boundary case corpus invokes runOptimisticHistory for every initial-state/action program. Although the corpus is fixed and looks like a regression table, it supplies no expected-result literals: the independent shared model computes and compares every public cut. This qualifies as execution of a reusable oracle under the supplied rule, not only hardcoded regression assertions.", + "ownerPaths": [ + "packages/db/tests/optimistic-history-oracle.ts" + ], + "confidence": "medium" + }, + { + "path": "packages/db/tests/optimistic-transaction-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/optimistic-transaction-oracle.property.test.ts", + "evidenceLines": [ + 102, + 114, + 184, + 196, + 212, + 280, + 802, + 803, + 808, + 916, + 925, + 940, + 1162 + ], + "mechanism": "runSameKey independently reduces operation sequences into net mutation payloads and outcomes, while runTransaction computes proposed public rows in plain Maps and checks source/read/replica/downstream observations. Generated payloads and operation-order matrices execute those computations. Ordinary replacement examples elsewhere do not determine the classification.", + "confidence": "high" + }, + { + "path": "packages/db/tests/oracle-replay.test.ts", + "role": "harness-test", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/oracle-replay.test.ts", + "evidenceLines": [ + 38, + 80, + 185, + 254, + 289, + 311, + 345, + 363, + 427 + ], + "mechanism": "Exercises guarded replay subprocess selection, execution counts, property/reporting failures, cleanup diagnostics, and manifest mapping. These assertions judge oracle execution/reporting infrastructure rather than a production data or lifecycle law. Its existing filename is outside rename correction.", + "confidence": "high" + }, + { + "path": "packages/db/tests/paced-mutations-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/paced-mutations-oracle.test.ts", + "evidenceLines": [ + 77, + 98, + 117, + 141, + 174, + 291, + 420, + 436, + 451, + 1063, + 1064 + ], + "mechanism": "queueStarts/debounceStarts/throttleStarts/nonLeadingThrottleStarts simulate starts from action histories with an independent virtual clock and ordered call IDs. Scenario expectations call these models; runProduction observations of real paced mutations are compared to the computed starts and transaction grouping.", + "confidence": "high" + }, + { + "path": "packages/db/tests/proxy-detachment-contract-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/proxy-detachment-contract-oracle.test.ts", + "evidenceLines": [ + 370, + 379, + 393, + 413, + 414, + 416, + 419, + 423, + 425, + 427 + ], + "mechanism": "Mixed contract/example file contains actual native differential judgment: reorder executes on an independent native Map/Set row and on the draft/Collection production paths, then compares detached and stored iteration contents to the native result across container and operation alternatives. This mechanism, not the surrounding contract prose or fixed expected assertions, warrants the name.", + "confidence": "high" + }, + { + "path": "packages/db/tests/proxy-iteration-contract-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/proxy-iteration-contract-oracle.test.ts", + "evidenceLines": [ + 117, + 135, + 151, + 156, + 158, + 161, + 449, + 452, + 477, + 478, + 481 + ], + "mechanism": "Native differential iteration rule executes the same iterator/edit program on a native array and a production draft, computing expected visits/final contents. A separate Map/Set run computes native membership-change observations and compares the production draft and extracted changes across iteration protocols.", + "confidence": "high" + }, + { + "path": "packages/db/tests/proxy-native-methods-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/proxy-native-methods-oracle.property.test.ts", + "evidenceLines": [ + 209, + 214, + 215, + 217, + 221, + 225, + 257, + 258, + 263, + 365, + 408 + ], + "mechanism": "expectArrayCall and expectTypedCall execute the same built-in method on separate native and draft values; native outcomes, identity and post-write values supply the independent expected result. Arbitraries vary rows, method and arguments and feed that differential checker.", + "confidence": "high" + }, + { + "path": "packages/db/tests/proxy-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/proxy-oracle.test.ts", + "evidenceLines": [ + 48, + 99, + 108, + 111, + 112, + 114, + 123, + 136, + 138, + 243, + 265, + 270, + 272 + ], + "mechanism": "Mostly unit examples, but it actually contains a reusable native array callback oracle: observeArrayCallbacks executes each history step on independent native/proxy rows, derives the expected change set from the native row, and assertArrayCallbacks compares every recorded cut. Generated two-step callbacks invoke this mechanism, so the mixed file qualifies.", + "confidence": "high" + }, + { + "path": "packages/db/tests/proxy-revert-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/proxy-revert-oracle.property.test.ts", + "evidenceLines": [ + 137, + 519, + 569, + 696, + 708, + 709, + 712, + 718, + 725, + 730, + 764, + 774 + ], + "mechanism": "Independent plain-data Spec state reducer step plus canonical equality computes expected changes after generated histories. expectHistory drives createChangeProxy and checks changed keys/values, final draft and untouched baseline against that model.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/aggregate-value-contracts.test-d.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/query/aggregate-value-contracts-oracle.test-d.ts", + "evidenceLines": [ + 54, + 91, + 98, + 144, + 179, + 198, + 242 + ], + "mechanism": "AggregateRow fixtures and concrete expectTypeOf assertions specify numeric/orderable result types and rejected inputs. Generic forwarders exercise production overloads before concrete assertions; they do not implement a generalized independent aggregate type algebra.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/builder/ref-proxy.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/query/builder/ref-proxy-oracle.test.ts", + "evidenceLines": [ + 12, + 21, + 64, + 111, + 157, + 199, + 261 + ], + "mechanism": "Unit examples for proxy paths, descriptors, identity, type guards, and literal wrapping. Expected paths/descriptors/values are literal examples, with no independent reusable semantic model.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/cold-join-reconciliation-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/cold-join-reconciliation-oracle.test.ts", + "evidenceLines": [ + 69, + 225, + 236, + 242, + 243 + ], + "mechanism": "Maintains independent source rows and recomputes the cold join with plain nested filtering/mapping. The checker compares both live output and subscription replica to those rows, and requires a real cold acquisition.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/compiler/evaluators-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/query/compiler/evaluators-oracle.test.ts", + "evidenceLines": [ + 87, + 127, + 154, + 164, + 564, + 572 + ], + "mechanism": "Mixed unit file contains an independent dynamic-programming LIKE/ILIKE interpreter (referenceLike), generated string/pattern cases, and findLikeMismatch comparisons against compiled production expressions.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/compiler/lazy-targets.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/query/compiler/lazy-targets-oracle.test.ts", + "evidenceLines": [ + 38, + 41, + 51, + 55, + 75 + ], + "mechanism": "Three lexical-source targeting examples: matching fallback alias, mismatched fallback alias, and dotted versus nested paths. Each checks a hardcoded target/path result; no independent resolver or generated law checker.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/derived-delete-reconciliation-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/query/derived-delete-reconciliation-oracle.test.ts", + "evidenceLines": [ + 23, + 30, + 66, + 74, + 89, + 117, + 124 + ], + "mechanism": "runFlushHistory tracks an independent expected row Map through generated insert/update histories, drives real derived reconciliation beneath deletes, and compares published rows and a lookup-work bound after removing the overlay.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/identity-output-shape-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/identity-output-shape-oracle.test.ts", + "evidenceLines": [ + 74, + 255, + 261, + 271, + 278, + 368 + ], + "mechanism": "Computes expected complete output bags using plain row mapping/nested-loop joins for each query shape and alias assignment; compares both executions to independent output and checks explicit-shape equivalence. Also owns an explicit equality-partition checker.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/includes-collection-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/includes-collection-oracle.property.test.ts", + "evidenceLines": [ + 304, + 310, + 566, + 577, + 585, + 599, + 826 + ], + "mechanism": "recompute() independently filters and orders source-Map children per parent. collectionProjection compares real live-query rows, callback publications and diff-derived parent events against that recomputation across generated CollectionAction histories; this is more than the neighboring fixed facade examples.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/includes-context-transport-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/includes-context-transport-oracle.test.ts", + "evidenceLines": [ + 1253, + 1257, + 1262, + 1281, + 1307, + 1309, + 1318 + ], + "mechanism": "Recursive-source cells keep modelRows and compute expected filter/projection/aggregate/having/ordered-window results in JavaScript, then compare all public materialization forms against expected(parent.id) after real source updates. The finite grammar executes an independent result rule, alongside fixed path examples.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/includes-cross-formulation-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/includes-cross-formulation-oracle.property.test.ts", + "evidenceLines": [ + 408, + 422, + 439, + 706, + 733, + 759, + 771 + ], + "mechanism": "Independent source-Map recomputeNestedModel/recomputeWindowedModel supply expected rows. expectFormulationsEquivalent compares real nested query, regrouped flat join, fresh per-parent query and TLP partitions at each generated action checkpoint.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/includes-functional-input-boundary.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/query/includes-functional-input-boundary-oracle.test.ts", + "evidenceLines": [ + 11, + 18, + 55, + 95, + 105, + 112, + 115, + 142, + 262, + 268, + 394 + ], + "mechanism": "The form/failureAt matrix applies one fixed parent/children/peer scenario and checks literal ID lists [10,100], [20,200], [20,200,201]. Other tests assert literal count/sum outcomes, exact rejection text and fixed handle identity. The production fn.select computations are the SUT, not independent reference computations. No reusable reference model or differential/metamorphic comparison computes outcomes across the matrix. Restore original name despite the earlier classification.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/includes-functional-projection-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/includes-functional-projection-oracle.test.ts", + "evidenceLines": [ + 1253, + 1264, + 1374, + 1379, + 1382, + 1397, + 1420, + 1457, + 1463 + ], + "mechanism": "Mixed file with an actual reference-model lane: renamedCells retains a separate truth Map and recomputes expected primary/sibling child arrays from current group and source rows. check() compares public results and independently summed totals across materialization/projection/consumer combinations and child/sibling/route updates.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/includes-optimistic-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/includes-optimistic-oracle.property.test.ts", + "evidenceLines": [ + 350, + 357, + 368, + 371, + 572, + 578, + 625, + 656 + ], + "mechanism": "visibleLevels() independently overlays pending whole-row snapshots on cloned synced Maps; recompute() recursively filters/sorts resulting relationship trees. The projection compares real Collection results with this model through optimistic, sync, confirmation and rollback histories with generated route roles.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/includes-oracle-helpers.ts", + "role": "driver-or-fixture", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/includes-oracle-helpers.ts", + "evidenceLines": [ + 41, + 46, + 53, + 54, + 55, + 62, + 65, + 71 + ], + "mechanism": "createControlledCollection creates the real source Collection, clones supplied rows, forwards begin/write/commit and exposes mutation-gate controls. It contains no expected-result computation or judgment. Existing pre-PR oracle spelling is outside this correction.", + "ownerPaths": [ + "packages/db/tests/query/includes-oracle.property.test.ts", + "packages/db/tests/query/includes-collection-oracle.property.test.ts", + "packages/db/tests/query/includes-context-transport-oracle.test.ts", + "packages/db/tests/query/includes-functional-projection-oracle.test.ts", + "packages/db/tests/query/includes-publication-oracle.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db/tests/query/includes-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/includes-oracle.property.test.ts", + "evidenceLines": [ + 471, + 480, + 490, + 496, + 3444, + 3449, + 3450, + 3456, + 5973 + ], + "mechanism": "recompute() rebuilds nested trees independently from root/level Maps using correlation equality and total row order. structuralProjection compares real incremental results at each runTrace checkpoint for generated histories. Additional scalar and alpha-renaming mechanisms also execute independent recomputations.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/includes-publication-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/includes-publication-oracle.test.ts", + "evidenceLines": [ + 269, + 274, + 278, + 285, + 297, + 306, + 321, + 769, + 857 + ], + "mechanism": "recomputeRows() independently joins source Maps into two child arrays. publicationProjection compares both real live-query layers, callback-time rows and complete change payloads with model rows and prior delivered membership across generated source/optimistic actions. It judges transient cuts as well as final reads.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/includes-query-shape-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/includes-query-shape-oracle.test.ts", + "evidenceLines": [ + 170, + 176, + 177, + 179, + 307, + 314, + 318, + 481, + 523 + ], + "mechanism": "multiplicityProjection computes public parent membership from independent source Maps via positive child support, while correlationProjection recomputes joined-alias matching from orders/parts/productions. Real live-query observations are checked after source writes and generated input values.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/includes-scope-identity-oracle.ts", + "role": "oracle-definition", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/includes-scope-identity-oracle.ts", + "evidenceLines": [ + 165, + 202, + 337, + 339, + 357, + 378, + 402, + 429, + 816 + ], + "mechanism": "Owns scopedScenarioArbitrary/history grammar, classifyScopedNaming legality and recomputeScopedRows independent source-role relational model (including joins, multiplicity, predicates, DISTINCT and limits). The includes-oracle.property.test.ts alpha-renaming owner imports and executes this judgment against canonical/generated query spellings.", + "ownerPaths": [ + "packages/db/tests/query/includes-oracle.property.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db/tests/query/includes-space-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/includes-space-oracle.test.ts", + "evidenceLines": [ + 38, + 134, + 136, + 140, + 146, + 149, + 155, + 168, + 180, + 182, + 193 + ], + "mechanism": "The rootCount lane observes distinct constructed/retained production facade entries and compares all three counts to the independent topology formula rootCount + 2*rootCount + 10*rootCount supplied by the fixture, for 0/1/20 roots. The leaf-count lane checks topology-count invariance while actual leaf volume changes. This is a bounded cardinality law, although this mixed file also has fixed examples and fixture-cleanup tests. Formula evidence: includes-space-oracle-fixture.ts:123.", + "confidence": "medium" + }, + { + "path": "packages/db/tests/query/includes-temporal-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/includes-temporal-oracle.test.ts", + "evidenceLines": [ + 1365, + 1370, + 1371, + 1375, + 2579, + 2722, + 2801, + 2810, + 2813, + 2814, + 2818, + 2836 + ], + "mechanism": "Contains many pinned examples, but scheduled acquisition observations are judged by an independent rule selecting current rows only when the current scheduled acquisition fulfilled. More directly, the generated partialBodies lane independently accumulates an expected child prefix and compares every production publication cut and readiness state while the acquisition is held.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/includes-work-counter-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/includes-work-counter-oracle.test.ts", + "evidenceLines": [ + 422, + 427, + 435, + 436, + 439, + 442, + 457, + 460, + 475, + 577, + 584, + 591 + ], + "mechanism": "Metamorphic work law: observe a minimal production baseline and a separately scaled fixture, then require identical public results and source delivery/read counts as unrelated link/target/all-source cardinality varies. The generated 1..24 filler domain uses this same cross-execution relation; literal baseline calibration alone is not the mechanism.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/index-path-collision-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/index-path-collision-oracle.test.ts", + "evidenceLines": [ + 123, + 128, + 133, + 138, + 147, + 157, + 160, + 215 + ], + "mechanism": "Each predicate has a separately expressed JavaScript accepts rule. Expected keys are recomputed by array filtering and compared against both scan and reached-index production paths; ordering also uses direct JavaScript sorting.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/ir-stable-identity-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/query/ir-stable-identity-oracle.test.ts", + "evidenceLines": [ + 186, + 202, + 213, + 235, + 1534, + 1538 + ], + "mechanism": "Mixed regression file owns interpretOutputProgram, an independent denotation for generated concat/coalesce/caseWhen contexts. assertOutputProgram compares compiled output to that denotation and enforces equal-identity output preservation, with fixed and random campaigns.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/join-result-key-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/join-result-key-oracle.property.test.ts", + "evidenceLines": [ + 96, + 206, + 230, + 234 + ], + "mechanism": "expectedPairs independently recomputes join membership by nested loops over model rows after history mutations; runHistory compares production publications against those expected pair descriptions.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/load-subset-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/load-subset-oracle.property.test.ts", + "evidenceLines": [ + 114, + 199, + 203, + 213, + 219, + 224, + 232, + 242, + 249, + 268, + 274, + 1521, + 1541 + ], + "mechanism": "assertCompletedExactDemandTrace keeps an independent Set of serialized demand descriptors and predicts whether each call starts work; assertConcurrentExactDemandTrace keeps a separate descriptor-to-promise ledger and checks sharing, distinct starts, settlement, and reset against real DeduplicatedLoadSubset calls. Both checkers run over generated traces as well as fixed distinguishing pairs.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/load-subset-replay-refinement-oracle.test.ts", + "role": "example-test", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/load-subset-replay-refinement-oracle.test.ts", + "evidenceLines": [ + 145, + 146, + 221, + 223, + 335, + 361, + 402, + 565, + 584, + 676, + 709, + 723, + 774, + 792, + 820, + 850 + ], + "mechanism": "The shared createHarness supplies production calls, deferred results, and observations. Expected rows and batches are specified as literal old/new snapshots at individual checkpoints; the restart matrix only selects between its fixed initial and replacement rows. No reusable replay-participant state model or independent generalized result computation is executed. The opening model prose does not change that role. Its oracle filename predates this PR and should remain unchanged.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/load-subset-source-readiness-refinement-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/load-subset-source-readiness-refinement-oracle.test.ts", + "evidenceLines": [ + 36, + 43, + 78, + 230, + 240, + 262, + 278, + 284, + 290, + 294, + 312 + ], + "mechanism": "expectedRows independently filters applied child rows by the current parent group. The four old-outcome/settlement-order histories drive real Collections and correlated queries, compare the model at progressive-write and parent-change cuts, and recompute rows and readiness after each old/fresh settlement. The general group-filter computation supplies judgment independently of the controlled adapter.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/load-subset-transaction-refinement-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/load-subset-transaction-refinement-oracle.test.ts", + "evidenceLines": [ + 42, + 46, + 47, + 61, + 70, + 94, + 96, + 121, + 148, + 151, + 159, + 160, + 161 + ], + "mechanism": "expectedOutcome implements the independent publication-started rule: an abort before publication rejects and yields no visible row/events, whereas an abort after publication starts fulfills and preserves the row. The bounded three-phase driver executes real Collection commit and optimistic-transaction blocking, then compares load outcome, visibility, event batches, and callback reads with that computation.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/optimizer-semantics-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/optimizer-semantics-oracle.test.ts", + "evidenceLines": [ + 192, + 203, + 384, + 935, + 1017 + ], + "mechanism": "Contains independent array-based sums and joins plus differential materialized-query formulations. Actual optimized query rows are compared with separately computed expected results, beyond the file's fixed regressions.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/ordered-default-work.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/query/ordered-default-work-oracle.test.ts", + "evidenceLines": [ + 13, + 17, + 25, + 60, + 73, + 181, + 197, + 206, + 218, + 230, + 252, + 254, + 267, + 294, + 305 + ], + "mechanism": "The finite-source filtering/sorting is provider fixture behavior, not an independent expected public-result calculation. Product assertions use fixed rows and fixed request counts for named scenarios. expectRepairSchedule is a reusable assertion helper, but it supplies a hardcoded five-cut expected retry table and a fixed cap rather than computing a general schedule law. Its self-calibration checks only two substituted second delays. Conservatively restore the original filename; this schedule helper is the closest borderline mechanism.", + "confidence": "medium" + }, + { + "path": "packages/db/tests/query/ordered-demand-retirement.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/query/ordered-demand-retirement-oracle.test.ts", + "evidenceLines": [ + 12, + 15, + 31, + 36, + 49, + 88, + 90, + 96, + 106, + 113, + 114, + 121, + 124 + ], + "mechanism": "A single fixed four-row history is repeated with or without one peer. The reference-expression evaluator supplies the fake provider responses; expected public rows remain the literal [2,3]. The owner-scaled work counts describe this pinned mutation/truncate/cleanup sequence and do not constitute a reusable independent model or generalized checker. Restore the original filename.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/ordered-lifecycle-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/ordered-lifecycle-oracle.property.test.ts", + "evidenceLines": [ + 183, + 198, + 218, + 590, + 595, + 598, + 604, + 766, + 776, + 1138, + 1164, + 1189, + 1192, + 1202 + ], + "mechanism": "observeHistory computes referenceWindow by independently sorting the authoritative finite rows and slicing by the requested width. It derives legal publication traces and checks observed rows, waiters, ownership, and restart cuts. assertHistory runs this judgment across the finite acquisition/delivery/window/outcome/sync-run/barrier domain and generated numeric variants.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/ordered-source-loader-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/query/ordered-source-loader-oracle.test.ts", + "evidenceLines": [ + 505, + 519, + 537, + 572, + 594, + 611 + ], + "mechanism": "Mixed unit file contains a bounded independent work-plan rule: expectedStagedWindowTrace derives the request sequence from boundary presence and remaining demand. The full two-by-two semantic domain is driven through OrderedSourceLoader and observed requests are compared to the computed plan. Other route regressions alone would not qualify.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/ordered-source-loader-state-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/query/ordered-source-loader-state-oracle.test.ts", + "evidenceLines": [ + 635, + 636, + 638, + 639, + 658, + 684, + 694, + 704, + 713, + 717, + 723, + 726, + 730, + 734, + 738 + ], + "mechanism": "This mixed regression file contains a bounded independent release-sequence law at lines 635-744. Across older request kind, both settlement orders, and both outcomes for each request, it computes successfulFinite from the full-source-success and finite-success rule, computes failedIndices from outcome plus completion order, and compares their composed acquisition identities with the real OrderedSourceLoader release trace. The expectation uses test-controlled outcomes and observed handle identity, not production transition/classification helpers or a hardcoded expected release array. That narrow finite-domain computation qualifies; the numerous other pinned regressions do not independently justify the name.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/ordered-work-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/ordered-work-oracle.property.test.ts", + "evidenceLines": [ + 149, + 174, + 251, + 257, + 260, + 305, + 309, + 674, + 679, + 682, + 692, + 4293, + 4295, + 4303 + ], + "mechanism": "observeConsumer derives matchingTruth by independently sorting finite authoritative rows and filtering marker membership. expectRawWindow judges exact membership and permitted order, while assertConsumerParity compares equivalent Collection and Effect executions for rows, errors, liveness, and semantic request traces. The same differential checker runs over generated scenarios.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/pagination-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/pagination-oracle.property.test.ts", + "evidenceLines": [ + 626, + 631, + 646, + 648, + 678, + 682, + 686, + 788, + 797, + 829, + 832, + 835, + 841, + 5506, + 5515, + 5531 + ], + "mechanism": "referenceWindowRows recomputes the result by an independent rank/NaN/key ordering and offset-limit slice. expectedPageChanges independently derives insert/update/delete changes from before/after maps. Real live-query preload and setWindow observations are compared with these computations across generated window and state histories, including the structural matrix.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/pooled-live-query-gc-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/query/pooled-live-query-gc-oracle.test.ts", + "evidenceLines": [ + 46, + 58, + 66, + 82, + 85, + 86, + 90 + ], + "mechanism": "Differential lifetime oracle runs the same gcTime/subscription cases through pooled and compiled live queries, independently observes release times under fake timers, and compares them with the documented one-tick cleanup allowance.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/pooled-live-query-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/pooled-live-query-oracle.property.test.ts", + "evidenceLines": [ + 170, + 179, + 196, + 583, + 633, + 672, + 685, + 697 + ], + "mechanism": "Independent modelEq/expectedKeys/expectedRows determine membership, while separately executed compiled Collections supply differential ordering/status/value observations. runHistory compares pooled public snapshots and folded granular changes after generated commands.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/public-container-copy.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/query/public-container-copy-oracle.test.ts", + "evidenceLines": [ + 11, + 52, + 66, + 83, + 90, + 114, + 150, + 177 + ], + "mechanism": "Query checks receive literal key arrays for a fixed parent/children history. Identity-transform and descriptor tests cover a hand-built container topology with selected leaves, using direct regression assertions rather than a reusable independently computed transform over a grammar. The identity relation is a borderline law claim; conservatively restore the original name.", + "confidence": "medium" + }, + { + "path": "packages/db/tests/query/query-api-type-algebra.test-d.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/query/query-api-type-algebra-oracle.test-d.ts", + "evidenceLines": [ + 31, + 35, + 46, + 82, + 206, + 311, + 334, + 440 + ], + "mechanism": "Primarily explicit nullable/output schema type expectations and ordinary generic assignability regressions. Selected uses production WithResult, DeepNullable is a negative control, and the generic source composition is checked using concrete expected field types. Generic preservation could be described as a law, but no independent generalized expected query type algebra is executed; conservatively restore.", + "confidence": "medium" + }, + { + "path": "packages/db/tests/query/query-api-type-algebra.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/query/query-api-type-algebra-oracle.test.ts", + "evidenceLines": [ + 6, + 33, + 37, + 88, + 93, + 126 + ], + "mechanism": "Three concrete runtime examples assert unmatched projection undefined, one matched/one unmatched union result, and one retained null value. There is no independent type or runtime reference computation.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/replay-failure-boundary.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/query/replay-failure-boundary-oracle.test.ts", + "evidenceLines": [ + 13, + 16, + 43, + 104, + 131, + 148, + 166, + 178, + 195 + ], + "mechanism": "The failure-mode/consumer matrix repeats one fixed replay, peer, retained-child, and recovery history with literal versions 1/2/3/4. evaluateReferenceExpression selects fixture rows in the adapter; it is not used to independently judge the publication/recovery result.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/scheduler.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/query/scheduler-oracle.test.ts", + "evidenceLines": [ + 73, + 117, + 133, + 671, + 1038, + 1146, + 1238, + 1422 + ], + "mechanism": "Scheduler setup and batch-recording helpers drive fixed reentry, failure, join, restart, and scheduling regressions. expectedObservation constructs a single literal Ada insertion; the shared-source/consumer matrix checks one hardcoded next-left/next-right publication. No independent scheduler state machine or reusable derived expected schedule.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/subquery-user-value-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/subquery-user-value-oracle.test.ts", + "evidenceLines": [ + 60, + 144, + 155, + 201, + 501, + 580, + 741, + 785 + ], + "mechanism": "expectedDistinctRows independently filters plain source rows and deduplicates with Set. Incremental source model Maps drive complete recomputation and comparison to public query outputs; other lanes independently count/filter and recompute singleton projections.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/validate-aliases.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/query/validate-aliases-oracle.test.ts", + "evidenceLines": [ + 59, + 108, + 165, + 276, + 296, + 368, + 400 + ], + "mechanism": "Concrete query shapes assert throw/pass outcomes for parent/grandparent alias reuse, union branches, and sibling scope reuse. There is no independent lexical-scope model computing validity across a query grammar.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/virtual-row-fields-oracle.test-d.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/virtual-row-fields-oracle.test-d.ts", + "evidenceLines": [ + 64, + 89, + 223, + 267, + 283, + 304, + 313 + ], + "mechanism": "PublishedValueFor independently maps semantic publication categories to values with or without virtual fields; the type suite compares actual whole-row/projected/opaque query outputs to that generalized relation.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/virtual-row-fields-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/virtual-row-fields-oracle.test.ts", + "evidenceLines": [ + 73, + 77, + 388, + 409, + 422 + ], + "mechanism": "expectsVirtualFields independently decides virtual-field eligibility from publication subject (root/whole-row versus projected/nested/opaque). Real query observations are classified and checked field by field against this rule across the category domain.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/where-predicate-publication-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/query/where-predicate-publication-oracle.property.test.ts", + "evidenceLines": [ + 192, + 203, + 229, + 634, + 691, + 825, + 831 + ], + "mechanism": "Independent Kleene evaluator expectedTruth and expectedVisible touched-row visibility model compute expected membership from declarative predicates and model history. runHistory compares the production publication paths with those recomputed observations.", + "confidence": "high" + }, + { + "path": "packages/db/tests/query/where-prefilter-property-visibility.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/query/where-prefilter-property-visibility-oracle.test.ts", + "evidenceLines": [ + 19, + 45, + 68, + 91, + 131, + 168 + ], + "mechanism": "Fixed inherited, non-enumerable, enumerable, and getter fixtures assert literal snapshot/subscriber key arrays and getter behavior. No independent visibility evaluator computes expected results across a model domain.", + "confidence": "high" + }, + { + "path": "packages/db/tests/reference-expression-oracle.ts", + "role": "oracle-definition", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/reference-expression-oracle.ts", + "evidenceLines": [ + 1, + 3, + 15, + 19, + 22, + 29, + 32, + 43, + 46, + 58 + ], + "mechanism": "Defines a standalone interpreter for the supported BasicExpression subset, with its own scalar comparison, property traversal, boolean operators, null handling, comparisons, and IN semantics; it imports only the IR type. The cursor oracle directly uses this interpreter in expectCursorDenotation to judge production-generated cursor predicates against independent tuple comparison (cursor-oracle.property.test.ts:103-119). This is semantic reference computation, although other consumers also use it in provider fixtures.", + "ownerPaths": [ + "packages/db/tests/cursor-oracle.property.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db/tests/replay-publication-storage.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/replay-publication-storage-oracle.test.ts", + "evidenceLines": [ + 44, + 83, + 101, + 145, + 213, + 238, + 263, + 275, + 278, + 285, + 301, + 360, + 408 + ], + "mechanism": "Contains fixed replay/restart publication histories with literal expected batches and rows. expectDelegatedStorageAbsent is a small assertion wrapper invoked for one real retention snapshot (plus synthetic calibration); the reference expression evaluator only supplies fixture input rows. This does not establish a generalized storage/model oracle, so restore the original filename.", + "confidence": "high" + }, + { + "path": "packages/db/tests/single-row-ref-proxy.test-d.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/single-row-ref-proxy-oracle.test-d.ts", + "evidenceLines": [ + 59, + 61, + 82, + 112, + 200, + 222, + 234, + 252 + ], + "mechanism": "Ordinary expectTypeOf, assignment-compatibility, and ts-expect-error examples cover optional objects, unions, built-ins, and generic callback use. There is no independent generalized type relation or algebra calculating expected projections.", + "confidence": "high" + }, + { + "path": "packages/db/tests/sync-reused-row.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/sync-reused-row-oracle.test.ts", + "evidenceLines": [ + 47, + 53, + 59, + 69, + 73, + 89, + 100, + 106 + ], + "mechanism": "Five concrete reused-row regression cases assert development errors, previousValue acceptance, unchanged rewrites, fresh-object updates, and the production environment exception. There is no independent row/history model or reusable law checker.", + "confidence": "high" + }, + { + "path": "packages/db/tests/trace-runner.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/trace-runner-oracle.ts", + "evidenceLines": [ + 19, + 30, + 36, + 77, + 88, + 89, + 91, + 106, + 109, + 121 + ], + "mechanism": "Generic execution/checkpoint orchestration: receives observe/recompute/assertEqual callbacks from callers and invokes them after startup/steps; preserves errors and runs cleanup. It supplies no product-specific expected result, model, grammar or independent judgment. This is runner infrastructure, not a harness-test (it contains no tests). Restore trace-runner.ts.", + "ownerPaths": [ + "packages/db/tests/query/includes-oracle.property.test.ts", + "packages/db/tests/query/includes-publication-oracle.test.ts", + "packages/db/tests/query/includes-query-shape-oracle.test.ts", + "packages/db/tests/query/includes-temporal-oracle.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/db/tests/transactions.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/transactions-oracle.test.ts", + "evidenceLines": [ + 169, + 178, + 191, + 319, + 343, + 348, + 359, + 412, + 421, + 425, + 428, + 437, + 765, + 810, + 821, + 890 + ], + "mechanism": "Ordinary transaction API/regression suite: tests set up concrete transactions and hardcode their expected states, errors, rows and callback batches. The parameterized late-rejection test only substitutes several rejection payloads into one fixed history, with literal expected results. No independent transaction state reducer, differential implementation or reusable generalized judgment was found. Restore transactions.test.ts.", + "confidence": "high" + }, + { + "path": "packages/db/tests/utils-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/db/tests/utils-oracle.property.test.ts", + "evidenceLines": [ + 250, + 260, + 275, + 284, + 286, + 493, + 518, + 534, + 947, + 956, + 958 + ], + "mechanism": "Generated change-event equality laws construct equivalent copies, sharing/unfolding variants, and deliberate single-payload changes independently of deepEquals. The same bidirectional checker judges cyclic mixed-container rings, every changed reachable ring payload, and Map/Set insertion-order invariance against the real comparator.", + "confidence": "high" + }, + { + "path": "packages/db/tests/virtual-props-cache.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/db/tests/virtual-props-cache-oracle.test.ts", + "evidenceLines": [ + 18, + 23, + 35, + 39, + 45, + 57, + 61, + 65, + 79, + 87, + 88 + ], + "mechanism": "Three narrow cache regressions compare callback/read object identity for one row updated with [1,2], then assert cache size zero after explicit deletion/rollback. These are valuable direct invariant assertions, but no independent reusable model/comparison program or transformed-history oracle is present. Conservatively restore the original filename instead of treating every identity assertion as an oracle owner.", + "confidence": "medium" + }, + { + "path": "packages/db/tests/virtual-row-legacy-guard-oracle.test-d.ts", + "role": "example-test", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/db/tests/virtual-row-legacy-guard-oracle.test-d.ts", + "evidenceLines": [ + 5, + 6, + 13, + 15, + 19, + 20, + 21 + ], + "mechanism": "Two concrete expectTypeOf assertions pin optional versus required $hasPendingWrites on one legacy-guard fixture and one WithVirtualProps instantiation. No generalized independent type relation/algebra. Existing pre-PR oracle filename is out of scope for renaming.", + "confidence": "high" + }, + { + "path": "packages/electric-db-collection/e2e/sql-predicate-semantics-oracle.e2e.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/electric-db-collection/e2e/sql-predicate-semantics-oracle.e2e.test.ts", + "evidenceLines": [ + 230, + 292, + 315, + 319 + ], + "mechanism": "The independent recursive three-valued evaluate(Predicate, row) function computes expected selected IDs. The test executes the compiled predicate against real PostgreSQL and compares the returned IDs with that reference computation.", + "confidence": "high" + }, + { + "path": "packages/electric-db-collection/e2e/subset-sql-acceptance.e2e.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/electric-db-collection/e2e/subset-sql-acceptance-oracle.e2e.test.ts", + "evidenceLines": [ + 22, + 47, + 65, + 83, + 110 + ], + "mechanism": "selectedIds only observes provider results. A fixed table fixture is checked against literal expected ID arrays for individual SQL examples; the file has no independent evaluator or generalized law checker.", + "confidence": "high" + }, + { + "path": "packages/electric-db-collection/tests/ORACLE_MUTATIONS.md", + "role": "documentation", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/electric-db-collection/tests/ORACLE_MUTATIONS.md", + "evidenceLines": [ + 1, + 3, + 13, + 115 + ], + "mechanism": "A prose mutation ledger describing source changes, replay commands, and named tests. It does not execute independent expected-result judgment. Its preexisting filename remains unchanged.", + "confidence": "high" + }, + { + "path": "packages/electric-db-collection/tests/electric-descriptor-isolation-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/electric-db-collection/tests/electric-descriptor-isolation-oracle.test.ts", + "evidenceLines": [ + 230, + 242, + 269, + 280, + 285, + 473 + ], + "mechanism": "runTagHistory owns an independent Map of complete rows and tag sets. Generated edits and removals update this model, and the check function compares both production public rows and durable rows with expectedRows computed from the Map.", + "confidence": "high" + }, + { + "path": "packages/electric-db-collection/tests/electric-oracle-lifecycle.test.ts", + "role": "harness-test", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/electric-db-collection/tests/electric-oracle-lifecycle.test.ts", + "evidenceLines": [ + 2, + 11, + 18, + 35, + 105, + 113 + ], + "mechanism": "Tests timeout and resource-cleanup helpers using fake primary/secondary errors and fake timers. These assertions concern the oracle lifecycle harness rather than a product law. Its preexisting filename remains unchanged.", + "ownerPaths": [ + "packages/electric-db-collection/tests/electric-oracle-lifecycle.ts" + ], + "confidence": "high" + }, + { + "path": "packages/electric-db-collection/tests/electric-oracle-lifecycle.ts", + "role": "driver-or-fixture", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/electric-db-collection/tests/electric-oracle-lifecycle.ts", + "evidenceLines": [ + 10, + 37, + 50, + 61, + 73 + ], + "mechanism": "Provides atCheckpoint timeout handling, setup wrappers, and resource cleanup preserving primary failures. It supplies execution lifecycle support and computes no independent expected product result. Its preexisting filename remains unchanged.", + "ownerPaths": [ + "packages/electric-db-collection/tests/electric-oracle.property.test.ts", + "packages/electric-db-collection/tests/electric-sdk-delivery-oracle.property.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/electric-db-collection/tests/electric-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/electric-db-collection/tests/electric-oracle.property.test.ts", + "evidenceLines": [ + 1241, + 1274, + 1291, + 3831, + 3850, + 3851, + 3852, + 3892 + ], + "mechanism": "applyReferenceBatch and expectedSnapshots independently model pending and committed rows; recomputeCommittedRows independently reconstructs committed results. Generated delivery histories compare full public snapshots from real Electric, persisted, and Query drivers with referenceSnapshots.", + "confidence": "high" + }, + { + "path": "packages/electric-db-collection/tests/electric-recovery-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/electric-db-collection/tests/electric-recovery-oracle.test.ts", + "evidenceLines": [ + 106, + 1067, + 1073, + 1095, + 1132, + 1143, + 1147, + 1204 + ], + "mechanism": "assertPublicationHistory updates an independent complete-row Map from authored commands and compares production public and durable rows with it after transitions. expectWholeRecoveryTrace independently judges complete allowed recovery traces across generated histories.", + "confidence": "high" + }, + { + "path": "packages/electric-db-collection/tests/electric-resume-snapshot-races.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/electric-db-collection/tests/electric-resume-snapshot-races-oracle.test.ts", + "evidenceLines": [ + 124, + 164, + 384, + 445, + 507, + 976 + ], + "mechanism": "Borderline parameterized lifecycle fixture: runRace seeds fixed rows and branches on scenario flags to choose literal expected rows, statuses, metadata, and a fixed legacy observation. replacesUncertifiedBaseline is a scenario predicate, not a separately computed baseline-tuple/state model. No reusable independent reference computation was identified; conservatively restore the original name.", + "confidence": "medium" + }, + { + "path": "packages/electric-db-collection/tests/electric-sdk-delivery-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/electric-db-collection/tests/electric-sdk-delivery-oracle.property.test.ts", + "evidenceLines": [ + 374, + 375, + 687, + 712, + 723, + 790 + ], + "mechanism": "Generated snapshot histories update an independent union Map and compare production public rows with it. Separate generated tag histories use an independent bitmask DNF visibility model, compute visible rows from that model, and compare production observations after transitions.", + "confidence": "high" + }, + { + "path": "packages/electric-db-collection/tests/electric-sdk-framing.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/electric-db-collection/tests/electric-sdk-framing-oracle.test.ts", + "evidenceLines": [ + 7, + 28, + 67, + 72 + ], + "mechanism": "Two boolean-parameterized cases feed fixed HTTP responses to the real SDK and assert three literal callback payloads. This is a useful provider framing example, but it does not own a generalized independent reference checker.", + "confidence": "high" + }, + { + "path": "packages/electric-db-collection/tests/pg-serializer-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/electric-db-collection/tests/pg-serializer-oracle.property.test.ts", + "evidenceLines": [ + 131, + 183, + 187, + 320, + 323 + ], + "mechanism": "An independent finite PostgreSQL array decoder parses the actual serializer output. A generic round-trip checker compares the decoded result with normalized input over generated serializer cases.", + "confidence": "high" + }, + { + "path": "packages/electric-db-collection/tests/schema-transform-conformance.test-d.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/electric-db-collection/tests/schema-transform-conformance-oracle.test-d.ts", + "evidenceLines": [ + 63, + 81, + 87, + 95, + 105 + ], + "mechanism": "Concrete Zod schema examples assert ordinary inferred-type equalities with expectTypeOf and reject particular sample inputs with ts-expect-error. No generalized independent type relation or reference algebra is present.", + "confidence": "high" + }, + { + "path": "packages/electron-db-sqlite-persistence/tests/electron-ipc.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/electron-db-sqlite-persistence/tests/electron-ipc-oracle.test.ts", + "evidenceLines": [ + 367, + 458, + 853, + 2236, + 2237, + 2294, + 2571 + ], + "mechanism": "Large collection of fixed IPC/reopen/ownership regressions. Expected transactions, rows, error types, and callback counts are manually specified. The small parameter tables supply their own expected values (for example expectedUnloads 1/2); no independent generated-history ledger, state reducer, differential computation, or reusable generalized product checker was found. Do not retain the rename merely because these mirror Browser laws.", + "confidence": "high" + }, + { + "path": "packages/expo-db-sqlite-persistence/e2e/mobile-persisted-collection-conformance-suite.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/expo-db-sqlite-persistence/e2e/mobile-persisted-collection-conformance-suite-oracle.ts", + "evidenceLines": [ + 36, + 49, + 138, + 153, + 211, + 225, + 299 + ], + "mechanism": "Creates/seeds eager and on-demand Collections, supplies mutation and cleanup callbacks, and invokes the shared conformance suite. Seed generation and Collection operations are host inputs/driver mechanics, not expected-result logic.", + "ownerPaths": [ + "packages/db-sqlite-persistence-core/tests/contracts/persisted-collection-conformance-contract.ts" + ], + "confidence": "high" + }, + { + "path": "packages/node-db-sqlite-persistence/tests/cached-upstream-history.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/node-db-sqlite-persistence/tests/cached-upstream-history-oracle.test.ts", + "evidenceLines": [ + 14, + 21, + 22, + 26, + 46, + 77, + 78, + 88, + 90, + 93, + 97, + 104, + 105, + 117, + 129, + 136 + ], + "mechanism": "Two fixed histories parameterized only by throw versus reject; cached/next/fresh rows and every expected snapshot are literal, with one branch for whether a failed acquisition was accepted. The later case supplies a real SQLite harness to the same fixed two-row restart helper. No independent ownership state model or generated/differential judgment.", + "confidence": "high" + }, + { + "path": "packages/node-db-sqlite-persistence/tests/expression-index-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/node-db-sqlite-persistence/tests/expression-index-oracle.test.ts", + "evidenceLines": [ + 253, + 258, + 259, + 934, + 951, + 952, + 989, + 998, + 1004, + 1087, + 1092, + 1104, + 1112, + 1125, + 1133 + ], + "mechanism": "Independent path walker and strict scalar filter compute expected keys from seeded/scanned rows; actual indexed adapter rows and captured raw SQL rows must match. Generated scenario matrix additionally checks independently specified keys and named-index plans against real better-sqlite3 execution. Existing pre-PR oracle name remains unchanged.", + "confidence": "high" + }, + { + "path": "packages/node-db-sqlite-persistence/tests/node-driver.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/node-db-sqlite-persistence/tests/node-driver-oracle.test.ts", + "evidenceLines": [ + 10, + 27, + 61, + 73, + 104, + 115, + 119, + 123, + 148 + ], + "mechanism": "Registers the fixed shared driver examples and adds two fixed shared-handle transaction/savepoint schedules. Their expected output is literal [1,2,3] and [1,3]; no independent admission reference or generalized schedule checker exists in this file.", + "confidence": "high" + }, + { + "path": "packages/node-db-sqlite-persistence/tests/node-persistence.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/node-db-sqlite-persistence/tests/node-persistence-oracle.test.ts", + "evidenceLines": [ + 16, + 41, + 55, + 63, + 85, + 115, + 131, + 180, + 187, + 202, + 226, + 233, + 246, + 267, + 274, + 326, + 333, + 393, + 413 + ], + "mechanism": "Provides host registration for the shared fixed examples, followed by hardcoded options/round-trip/pruning/schema-policy regressions. Row-cap cases always write seq 1,2,3 and assert literal [2,3], while age and disabled-pruning cases assert other literal sequences; there is no reference pruning computation.", + "confidence": "high" + }, + { + "path": "packages/node-db-sqlite-persistence/tests/node-sqlite-core-adapter-contract.test.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/node-db-sqlite-persistence/tests/node-sqlite-core-adapter-contract-oracle.test.ts", + "evidenceLines": [ + 9, + 12, + 13, + 18, + 21, + 31, + 33 + ], + "mechanism": "Constructs a temporary better-sqlite3 driver and SQLiteCorePersistenceAdapter, supplies cleanup, and registers runSQLiteCoreAdapterContractSuite. All independent expected-result computation belongs to the imported core adapter owner.", + "ownerPaths": [ + "packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-oracle.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/offline-transactions/tests/KeyScheduler-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/offline-transactions/tests/KeyScheduler-oracle.property.test.ts", + "evidenceLines": [ + 314, + 324, + 353, + 388, + 395, + 420, + 448, + 470, + 485, + 494, + 506, + 511, + 520, + 522 + ], + "mechanism": "The independent pending ledger plus fake time computes FIFO order, eligible head, active count, and payload snapshot in ordered/expectedNext/expectedSnapshot. runHistory applies each legal generated command separately to that ledger and the real KeyScheduler, then compares observations after every command. This is an executable state-model oracle, not merely a group of scheduler examples.", + "confidence": "high" + }, + { + "path": "packages/offline-transactions/tests/connectivity-replay-oracle.test.ts", + "role": "example-test", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/offline-transactions/tests/connectivity-replay-oracle.test.ts", + "evidenceLines": [ + 32, + 37, + 38, + 39, + 42, + 81, + 98, + 103, + 107, + 109, + 126, + 128, + 132 + ], + "mechanism": "Two parameterized examples execute the same single-write hidden-to-visible history, differing only in the notification trigger. expectedAt is a lookup of two literal expected observation records (0 calls/1 row/pending versus 1 call/0 rows/fulfilled), not a state transition model or generalized computation over histories. Conservatively classify this bounded regression as an example test. Its oracle filename predates this PR and must remain unchanged.", + "confidence": "medium" + }, + { + "path": "packages/offline-transactions/tests/fifo-retry-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/offline-transactions/tests/fifo-retry-oracle.property.test.ts", + "evidenceLines": [ + 63, + 68, + 70, + 71, + 75, + 84, + 85, + 86, + 87, + 99, + 138, + 142, + 146, + 151, + 161, + 167, + 172, + 177 + ], + "mechanism": "expectedStateAt independently computes the full expected provider call sequence and outbox cardinality from elapsed time, generated retry delay, and the input transaction IDs. One shared comparison receives real TransactionExecutor/OutboxManager observations at before, delay-minus-one, and deadline cuts across generated count/delay inputs; this is a reusable threshold/FIFO reference computation.", + "confidence": "high" + }, + { + "path": "packages/offline-transactions/tests/filtered-replay-work.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/offline-transactions/tests/filtered-replay-work-oracle.test.ts", + "evidenceLines": [ + 8, + 9, + 11, + 32, + 40, + 50, + 51, + 72, + 92, + 97, + 98, + 99, + 101, + 102 + ], + "mechanism": "This is one instrumented regression with a fixed n=100 outbox and one even-index beforeRetry filter. It asserts a fixed-scenario work budget (n*4) and the known even-ID sequence. Arithmetic constructs this example's expected array, but there is no reusable reference/checker over variable inputs, history grammar, differential relation, or finite domain enumeration. The computed budget and expected IDs make this borderline; conservatively restore the original name instead of promoting one performance example to an oracle owner.", + "confidence": "medium" + }, + { + "path": "packages/offline-transactions/tests/indexeddb-write-settlement.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/offline-transactions/tests/indexeddb-write-settlement-oracle.test.ts", + "evidenceLines": [ + 4, + 5, + 9, + 43, + 50, + 54, + 66, + 71, + 72, + 84, + 92, + 95, + 99, + 108, + 109, + 113, + 121, + 122, + 126, + 135, + 149 + ], + "mechanism": "controlledWrite is a production-driver fixture that fires chosen IndexedDB callbacks and records the adapter promise outcome. The it.each cases repeat fixed event sequences for set/delete/clear and assert literal pending/fulfilled/rejected outcomes or an exact supplied error. No independent reference state machine or generalized law checker computes an expected outcome from an event history.", + "confidence": "high" + }, + { + "path": "packages/offline-transactions/tests/leadership-replay-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/offline-transactions/tests/leadership-replay-oracle.property.test.ts", + "evidenceLines": [ + 93, + 103, + 107, + 111, + 118, + 1760, + 1763, + 1764, + 1766, + 1767, + 1790, + 1794, + 1799, + 1811, + 1813, + 1819, + 1824 + ], + "mechanism": "Mixed file contains a concrete independent replay oracle: foldReplayLedger folds stored, captured-read, and durably-removed events into unfinished IDs without using production revision fences. A generated stale-read history drives real OutboxManager storage reads/removals and compares delivered IDs with that independent fold. This specific reusable mechanism qualifies the file even though many other cases are fixed examples.", + "confidence": "high" + }, + { + "path": "packages/offline-transactions/tests/oracle-lifecycle.test.ts", + "role": "harness-test", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/offline-transactions/tests/oracle-lifecycle.test.ts", + "evidenceLines": [ + 2, + 13, + 19, + 29, + 30, + 39, + 45, + 48, + 51, + 70, + 81, + 96, + 107, + 111 + ], + "mechanism": "Calls cleanupOfflineOracle and atOracleCheckpoint directly with held/rejecting cleanup actions, asserting warning/error preservation, timeout reporting, and later cleanup calls. It tests the oracle's test harness rather than offline product behavior. Filename already contained oracle before the PR and must remain unchanged.", + "ownerPaths": [ + "packages/offline-transactions/tests/oracle-lifecycle.ts" + ], + "confidence": "high" + }, + { + "path": "packages/offline-transactions/tests/storage-delete-settlement.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/offline-transactions/tests/storage-delete-settlement-oracle.test.ts", + "evidenceLines": [ + 12, + 13, + 17, + 24, + 25, + 26, + 29, + 40, + 49, + 54, + 67, + 69, + 73, + 75, + 76 + ], + "mechanism": "Two hardcoded regression histories: one localStorage key retained after a thrown removeItem error, and one known outbox transaction retained after a held read overlaps failed removal. Assertions compare exact supplied values/objects/errors. No independent reusable computation, model, or generalized checker is present; being a receiving companion for a larger oracle does not make this file an owner.", + "confidence": "high" + }, + { + "path": "packages/offline-transactions/tests/transaction-serializer-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/offline-transactions/tests/transaction-serializer-oracle.property.test.ts", + "evidenceLines": [ + 67, + 84, + 97, + 105, + 110, + 114, + 134, + 147, + 155, + 242, + 261, + 297, + 299, + 302, + 308, + 319, + 333, + 1392, + 1393, + 1400 + ], + "mechanism": "Independent semantic Pair values recursively construct matching runtime and expected-wire trees from generated leaves, arrays, escaped objects, and edits. checkRoundtrip computes expectedWire from those inputs and compares real TransactionSerializer encode/decode output against it, including independently authored decode inputs. mutationMeaningProperty executes that reference across generated edits/time values. Fixed wire examples elsewhere do not replace this clear reusable reference computation.", + "confidence": "high" + }, + { + "path": "packages/offline-transactions/tests/transaction-settlement-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/offline-transactions/tests/transaction-settlement-oracle.property.test.ts", + "evidenceLines": [ + 133, + 136, + 137, + 139, + 140, + 141, + 169, + 196, + 197, + 209, + 212, + 223, + 239, + 242, + 243, + 245, + 256, + 258, + 292, + 293, + 306, + 308, + 309 + ], + "mechanism": "For generated key-sharing, row width, and per-transaction success/failure sequences, assertState computes expected caller statuses from the completed prefix and each supplied outcome, folds independent successful server rows, overlays unfinished local rows, and computes remaining outbox IDs. Actual provider calls, public Collection rows, promise outcomes, and outbox contents are compared after each controlled provider release. This is an independent prefix/row reference computation; the mixed fixed examples do not negate ownership.", + "confidence": "high" + }, + { + "path": "packages/powersync-db-collection/tests/correctness-oracle.test.ts", + "role": "example-test", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/powersync-db-collection/tests/correctness-oracle.test.ts", + "evidenceLines": [ + 98, + 105, + 256, + 644, + 784, + 870 + ], + "mechanism": "Fixed native SQLite and Collection scenarios assert literal patch tuples, key arrays, and comparator order. observeUpdate packages actual observations and observeViewKeys projects actual keys; neither computes independent expected results. The existing correctness-oracle filename predates the PR and must remain unchanged.", + "confidence": "high" + }, + { + "path": "packages/powersync-db-collection/tests/schema-transform-conformance.test-d.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/powersync-db-collection/tests/schema-transform-conformance-oracle.test-d.ts", + "evidenceLines": [ + 159, + 164, + 212, + 218, + 246, + 262 + ], + "mechanism": "Two concrete schema paths assert ordinary expectTypeOf equalities and specific rejected inputs/deserializers. Extracting production types is not an independent generalized type relation or algebra.", + "confidence": "high" + }, + { + "path": "packages/query-db-collection/tests/cursor-pagination-oracle.integration.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/query-db-collection/tests/cursor-pagination-oracle.integration.test.ts", + "evidenceLines": [ + 188, + 246, + 248, + 257, + 271, + 272, + 360, + 370, + 391, + 393, + 394, + 403, + 408, + 409 + ], + "mechanism": "Executes an independent row-array mutation model against Query Collection manual writes, then compares production live-query/window-controller snapshots and callback publications with expectedWindow (full filter/sort/slice and exhaustion). The matrix computes answers from source rows, page width, direction and scope instead of enumerating expected output literals.", + "confidence": "high" + }, + { + "path": "packages/query-db-collection/tests/cursor-pagination-oracle.no-peek.integration.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/query-db-collection/tests/cursor-pagination-oracle.no-peek.integration.test.ts", + "evidenceLines": [ + 86, + 94, + 96, + 98, + 101, + 126, + 129, + 132, + 140, + 141, + 144, + 198 + ], + "mechanism": "The four-size matrix drives real Collection setWindow/preload and createLiveQueryWindowController. It computes full-source expectedWindow for the candidate graph result and differentially compares the production controller data/continuation with that independent candidate result; a filtered graph is also checked against full-source recomputation. The claim is limited to this experimental controlled bridge, but actual production observations are judged.", + "confidence": "high" + }, + { + "path": "packages/query-db-collection/tests/cursor-pagination.no-peek.test.ts", + "role": "harness-test", + "namingDecision": "restore original name", + "evidencePath": "packages/query-db-collection/tests/cursor-pagination-oracle.no-peek.test.ts", + "evidenceLines": [ + 5, + 6, + 7, + 18, + 20, + 70, + 88, + 90, + 92, + 98, + 100, + 111, + 113 + ], + "mechanism": "Model/prototype validation, the closest supplied harness-test role: generated histories compare createNoPeekDemandModel with expectedWindow, but the subject is exclusively the test-only candidate plus synthetic createFactTransport. No production pager, Query Collection, live-query graph or window controller is exercised. Its generated input does not make it an executable product oracle owner; restore the original filename. Ambiguity: this is a prototype-model test rather than a literal runner/configuration test.", + "ownerPaths": [ + "packages/query-db-collection/tests/cursor-pagination-oracle.no-peek.integration.test.ts" + ], + "confidence": "medium" + }, + { + "path": "packages/query-db-collection/tests/cursor-pagination.boundary-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/query-db-collection/tests/cursor-pagination.boundary-oracle.test.ts", + "evidenceLines": [ + 88, + 102, + 114, + 115, + 120, + 140, + 147, + 155, + 178, + 183, + 212, + 214, + 215, + 216 + ], + "mechanism": "Generated page widths exercise real pager/Query Collection cancellation and replacement. The judgment derives complete replacement rows from the independent source array and replacement action, requires success exactly for replacement, and checks that an aborted reader leaves the shared transport and cached source slice usable. This is a partial generalized boundary law, alongside fixed regression tests; its oracle name predates this PR.", + "confidence": "medium" + }, + { + "path": "packages/query-db-collection/tests/cursor-pagination.cache-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/query-db-collection/tests/cursor-pagination.cache-oracle.test.ts", + "evidenceLines": [ + 59, + 67, + 380, + 395, + 412, + 413, + 416, + 435, + 456, + 457, + 461, + 462, + 465, + 469, + 471 + ], + "mechanism": "A small independent cache-history state tracks permitted source snapshot, freshness deadline and presence through generated read/grow/age/invalidate/change/remove actions. Each production pager read is judged using expectedRows; starts and repeated-read work are checked against independently tracked freshness. The existing oracle filename is unchanged by this PR.", + "confidence": "high" + }, + { + "path": "packages/query-db-collection/tests/cursor-pagination.oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/query-db-collection/tests/cursor-pagination.oracle.test.ts", + "evidenceLines": [ + 108, + 114, + 115, + 134, + 143, + 236, + 244, + 245, + 247, + 249, + 259, + 267, + 272 + ], + "mechanism": "checkRead computes expectedRows independently of opaque tokens and compares the real production pager result (the pager companion wraps the exported production createCursorPager). Generated source/window histories, reversed read histories and backend page repartition reuse this judgment, with explicit wrong-order/duplicate/capped-result controls. Existing oracle name, not a PR rename.", + "confidence": "high" + }, + { + "path": "packages/query-db-collection/tests/cursor-pagination.publication-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/query-db-collection/tests/cursor-pagination.publication-oracle.test.ts", + "evidenceLines": [ + 78, + 87, + 96, + 104, + 105, + 106, + 169, + 184, + 212, + 216, + 222, + 233, + 375, + 381 + ], + "mechanism": "checkCachedSlice computes full-source expectedRows and checks both returned values and exact row-access work against the slice cardinality across generated count/offset/limit inputs. The refresh property independently recomputes the replacement snapshot and judges real QueryObserver publication, including a stale-result negative control. Existing oracle name remains unchanged.", + "confidence": "high" + }, + { + "path": "packages/query-db-collection/tests/cursor-pagination/model-oracle.ts", + "role": "oracle-definition", + "namingDecision": "retain PR rename", + "evidencePath": "packages/query-db-collection/tests/cursor-pagination/model-oracle.ts", + "evidenceLines": [ + 13, + 19, + 20, + 21, + 22, + 26, + 29, + 34, + 35 + ], + "mechanism": "Owns expectedRows: filter the independent complete source, sort by declared rank/id order, slice by offset/limit, clone. expectedWindow derives visible prefix and hasNextPage from that full computation. These functions are the expected-result side of the production pager, cache, publication and integration owners.", + "ownerPaths": [ + "packages/query-db-collection/tests/cursor-pagination.oracle.test.ts", + "packages/query-db-collection/tests/cursor-pagination.cache-oracle.test.ts", + "packages/query-db-collection/tests/cursor-pagination.publication-oracle.test.ts", + "packages/query-db-collection/tests/cursor-pagination-oracle.integration.test.ts", + "packages/query-db-collection/tests/cursor-pagination-oracle.no-peek.integration.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/query-db-collection/tests/cursor-pagination/no-peek.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/query-db-collection/tests/cursor-pagination/no-peek-oracle.ts", + "evidenceLines": [ + 3, + 15, + 33, + 36, + 50, + 63, + 79, + 89, + 99, + 110, + 111 + ], + "mechanism": "Implements the proposed test-only no-peek candidate: retain/retire demand, perform acquisitions, validate response facts, retain snapshots and dispatch listeners. It is the algorithm under experimental evaluation, with independent truth supplied by model-oracle.ts; it does not own that full-source judgment. The integration test does also compare this candidate with the production controller, so the alternative-reference interpretation is borderline. Conservatively restore no-peek.ts instead of treating every tested candidate as an oracle definition.", + "ownerPaths": [ + "packages/query-db-collection/tests/cursor-pagination-oracle.no-peek.integration.test.ts", + "packages/query-db-collection/tests/cursor-pagination.no-peek.test.ts" + ], + "confidence": "medium" + }, + { + "path": "packages/query-db-collection/tests/includes-work-counter-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/query-db-collection/tests/includes-work-counter-oracle.test.ts", + "evidenceLines": [ + 138, + 177, + 178, + 179, + 244, + 247, + 269, + 286, + 440, + 444, + 448, + 470, + 478, + 490, + 493, + 501, + 504, + 532, + 560 + ], + "mechanism": "expectedTreeCounts derives cardinalities from root count and branching factors; expectedTreeEntries independently reconstructs the source foreign-key world and checks observed nested values/parentage. An additional metamorphic comparison adds disconnected branches and requires identical tree rows, source delivery and demand work. The finite size matrix uses computed judgments against real Query Collection/includes results, not hand-listed answers.", + "confidence": "high" + }, + { + "path": "packages/query-db-collection/tests/load-subset-lifecycle-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/query-db-collection/tests/load-subset-lifecycle-oracle.test.ts", + "evidenceLines": [ + 386, + 403, + 419, + 420, + 422, + 432, + 443, + 446, + 449, + 763, + 777, + 784, + 793, + 897, + 918, + 947, + 949, + 951, + 969, + 979, + 1438, + 1441, + 1448, + 1450 + ], + "mechanism": "Mixed lifecycle examples plus a narrow metamorphic demand-identity owner: constructs operand-swapped AND/OR/equality and equal-Date requests, exercises real Query Collection loads, and checks transport reuse plus distinct-result/owner separation through a common independent trace judgment. The qualifying mechanism is semantic-equivalence transformation and identity checking, not the numerous fixed failure/refetch examples. This is a conservative borderline owner classification; no PR rename exists to retain or reverse.", + "confidence": "medium" + }, + { + "path": "packages/query-db-collection/tests/ownership-lifecycle.oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/query-db-collection/tests/ownership-lifecycle.oracle.test.ts", + "evidenceLines": [ + 90, + 114, + 137, + 151, + 160, + 190, + 218, + 226, + 231, + 400, + 428, + 4903, + 4919, + 4938, + 4949, + 4953, + 5011, + 5020, + 5028, + 5034 + ], + "mechanism": "Owns reusable independent result-settlement and explicit-refetch obligation state models. Model actions compute waiting/deferred/applied/rejected/cancelled outcomes; expectPublicRefetchObservation judges real refetch promise observations against those computed states across overlapping barrier histories. Concrete production creation, calls and model-check checkpoints establish ownership even though the large file also contains ordinary examples and calibration tests.", + "confidence": "high" + }, + { + "path": "packages/query-db-collection/tests/query.test-d.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/query-db-collection/tests/query-oracle.test-d.ts", + "evidenceLines": [ + 39, + 58, + 63, + 73, + 76, + 127, + 189, + 228, + 492, + 507, + 513, + 514, + 535, + 549, + 559, + 573, + 579, + 874, + 887 + ], + "mechanism": "Concrete API type-inference and rejection examples use expectTypeOf and @ts-expect-error for named row/schema/config types. The documented schema-output case tests one string-to-Date transform with paired concrete configs; it supplies no generalized independent type relation, mapped algebra or reusable type-level reference computation. Restore query.test-d.ts.", + "confidence": "high" + }, + { + "path": "packages/query-db-collection/tests/ssr-dehydration-oracle.test.ts", + "role": "example-test", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/query-db-collection/tests/ssr-dehydration-oracle.test.ts", + "evidenceLines": [ + 43, + 45, + 59, + 95, + 97, + 100, + 106, + 113, + 155, + 156, + 167, + 210, + 241 + ], + "mechanism": "Four fixed SSR regression shapes all use the same literal row. expectDehydratedRow/expectHydratedRow assert that literal row and selected metadata at stream/hydration checkpoints; the serialization helper is a driver, not an independent expected-result model. There is no generalized row/cache round-trip relation evaluated from arbitrary input state. The existing pre-PR oracle filename must remain unchanged despite this narrower role classification.", + "confidence": "high" + }, + { + "path": "packages/react-db/tests/conformance.test.tsx", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/react-db/tests/conformance-oracle.test.tsx", + "evidenceLines": [ + 49, + 125, + 170, + 203, + 220 + ], + "mechanism": "React source/mount/current/cleanup adapter passes a LiveQueryDriver to runSuite in packages/db/tests/conformance/suite-oracle.ts. Additional checks are fixed publication examples or driver/scope calibration; this file does not compute independent product expectations.", + "confidence": "high" + }, + { + "path": "packages/react-db/tests/infinite-query-conformance.test.tsx", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/react-db/tests/infinite-query-conformance-oracle.test.tsx", + "evidenceLines": [ + 33, + 63, + 100, + 193, + 210 + ], + "mechanism": "React hook adapter supplies sources, mount/current observations, scheduling, and disposal to runInfiniteQuerySuite. The independent window expectation is owned by the imported shared suite; local extra checks are fixed examples or scope calibration.", + "ownerPaths": [ + "packages/db/tests/conformance/infinite-suite-oracle.ts" + ], + "confidence": "high" + }, + { + "path": "packages/react-native-db-sqlite-persistence/e2e/mobile-persisted-collection-conformance-suite.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/react-native-db-sqlite-persistence/e2e/mobile-persisted-collection-conformance-suite-oracle.ts", + "evidenceLines": [ + 138, + 144, + 150, + 154, + 161, + 180, + 205, + 212, + 300 + ], + "mechanism": "Creates a hosted database, persistence-backed eager/on-demand collections, seeds fixtures, exposes mutations and teardown, then delegates registration to runPersistedCollectionConformanceSuite. Independent judgment is in the imported E2E suites.", + "ownerPaths": [ + "packages/db-collection-e2e/src/suites/joins-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/live-updates-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/moves-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/pagination-oracle.suite.ts", + "packages/db-collection-e2e/src/suites/predicates-oracle.suite.ts" + ], + "confidence": "high" + }, + { + "path": "packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "retain PR rename", + "evidencePath": "packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver-oracle.test.ts", + "evidenceLines": [ + 804, + 806, + 811, + 829, + 831, + 836, + 866, + 871, + 901, + 906, + 915, + 917, + 972, + 975, + 980, + 986 + ], + "mechanism": "Generated alias properties independently construct expected row objects from alias/value grammar. They check equivalent documented result carriers through the production driver, and execute generated SQL aliases through a hosted SQLite-backed OpSQLiteDriver.query against the independently constructed exact rows.", + "confidence": "high" + }, + { + "path": "packages/react-native-db-sqlite-persistence/tests/react-native-persistence.test.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/react-native-db-sqlite-persistence/tests/react-native-persistence-oracle.test.ts", + "evidenceLines": [ + 145, + 157, + 176, + 178, + 269, + 270, + 291, + 292, + 330, + 351, + 363, + 371, + 372 + ], + "mechanism": "Fixed restart and lifecycle examples check authored single/two-row values and metadata; the burst writes 50 known rows and checks count. No independent reusable persistence state machine or reference calculation is executed. A before/after registry comparison is a fixed reopen regression witness.", + "confidence": "high" + }, + { + "path": "packages/rxdb-db-collection/tests/schema-transform-conformance.test-d.ts", + "role": "example-test", + "namingDecision": "restore original name", + "evidencePath": "packages/rxdb-db-collection/tests/schema-transform-conformance-oracle.test-d.ts", + "evidenceLines": [ + 70, + 77, + 83, + 89, + 101, + 110 + ], + "mechanism": "Concrete schema examples check output/mutation inference equalities, rejected sample inputs, and an input-shaped RxCollection case. They contain no generalized independent type relation or algebra.", + "confidence": "high" + }, + { + "path": "packages/solid-db/tests/conformance.test.tsx", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/solid-db/tests/conformance-oracle.test.tsx", + "evidenceLines": [ + 52, + 136, + 176, + 220, + 284 + ], + "mechanism": "Solid source/mount/current/cleanup adapter passes a LiveQueryDriver to runSuite in packages/db/tests/conformance/suite-oracle.ts. Additional checks are fixed publication examples or driver/scope calibration; this file does not compute independent product expectations.", + "confidence": "high" + }, + { + "path": "packages/svelte-db/tests/conformance.svelte.test.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/svelte-db/tests/conformance-oracle.svelte.test.ts", + "evidenceLines": [ + 50, + 133, + 159, + 211, + 228 + ], + "mechanism": "Svelte source/mount/current/cleanup adapter passes a LiveQueryDriver to runSuite in packages/db/tests/conformance/suite-oracle.ts. Additional checks are fixed publication examples or driver/scope calibration; this file does not compute independent product expectations.", + "confidence": "high" + }, + { + "path": "packages/svelte-db/tests/infinite-query-conformance.svelte.test.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/svelte-db/tests/infinite-query-conformance-oracle.svelte.test.ts", + "evidenceLines": [ + 40, + 81, + 104, + 207, + 224 + ], + "mechanism": "Svelte hook adapter supplies sources, mount/current observations, scheduling, and disposal to runInfiniteQuerySuite. The independent window expectation is owned by the imported shared suite; local extra checks are fixed examples or scope calibration.", + "ownerPaths": [ + "packages/db/tests/conformance/infinite-suite-oracle.ts" + ], + "confidence": "high" + }, + { + "path": "packages/tauri-db-sqlite-persistence/e2e/shared/register-persisted-collection-conformance-suite.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/tauri-db-sqlite-persistence/e2e/shared/register-persisted-collection-conformance-suite-oracle.ts", + "evidenceLines": [ + 18, + 24, + 30, + 36, + 44 + ], + "mechanism": "Registers before/after lifecycle hooks, retrieves config, and forwards it to the shared suite. No independent product judgment.", + "ownerPaths": [ + "packages/db-sqlite-persistence-core/tests/contracts/persisted-collection-conformance-contract.ts" + ], + "confidence": "high" + }, + { + "path": "packages/trailbase-db-collection/tests/ORACLE.md", + "role": "documentation", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/trailbase-db-collection/tests/ORACLE.md", + "evidenceLines": [ + 1, + 3, + 11, + 51, + 72 + ], + "mechanism": "Prose describing the TrailBase lifecycle oracle contract, campaign commands, and mutation evidence. The actual independent row model and production comparisons live in lifecycle-oracle.property.test.ts. Its preexisting filename remains unchanged.", + "ownerPaths": [ + "packages/trailbase-db-collection/tests/lifecycle-oracle.property.test.ts" + ], + "confidence": "high" + }, + { + "path": "packages/trailbase-db-collection/tests/lifecycle-oracle.property.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/trailbase-db-collection/tests/lifecycle-oracle.property.test.ts", + "evidenceLines": [ + 164, + 176, + 181, + 298, + 319, + 325, + 600 + ], + "mechanism": "An independent expected Map models row state. The history interpreter updates the Map for authored insert, update, and delete commands and compares public production rows with the model while driving the real adapter and native stream across generated histories.", + "confidence": "high" + }, + { + "path": "packages/vue-db/tests/conformance.test.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/vue-db/tests/conformance-oracle.test.ts", + "evidenceLines": [ + 51, + 133, + 175, + 218, + 277 + ], + "mechanism": "Vue source/mount/current/cleanup adapter passes a LiveQueryDriver to runSuite in packages/db/tests/conformance/suite-oracle.ts. Additional checks are fixed publication examples or driver/scope calibration; this file does not compute independent product expectations.", + "confidence": "high" + }, + { + "path": "packages/vue-db/tests/infinite-query-conformance.test.ts", + "role": "driver-or-fixture", + "namingDecision": "restore original name", + "evidencePath": "packages/vue-db/tests/infinite-query-conformance-oracle.test.ts", + "evidenceLines": [ + 41, + 94, + 118, + 210, + 227 + ], + "mechanism": "Vue hook adapter supplies sources, mount/current observations, scheduling, and disposal to runInfiniteQuerySuite. The independent window expectation is owned by the imported shared suite; local extra checks are fixed examples or scope calibration.", + "ownerPaths": [ + "packages/db/tests/conformance/infinite-suite-oracle.ts" + ], + "confidence": "high" + }, + { + "path": "packages/vue-db/tests/useLiveQuery-publication-oracle.test.ts", + "role": "oracle-owner", + "namingDecision": "pre-existing name unchanged", + "evidencePath": "packages/vue-db/tests/useLiveQuery-publication-oracle.test.ts", + "evidenceLines": [ + 79, + 90, + 94, + 113, + 115, + 119, + 126, + 130, + 132, + 133, + 134, + 136, + 137, + 138 + ], + "mechanism": "Captures source state before/after a real transaction, records synchronous Vue watcher publications with source-at-callback state, and requires every publication to be a complete before/after snapshot with one final coherent publication. This checks an independent cross-surface publication relation. Filename already existed before this PR and remains unchanged.", + "confidence": "high" + } + ] +} diff --git a/docs/contributing/oracle-reviews/2026-10-03-oracle-naming-scope.md b/docs/contributing/oracle-reviews/2026-10-03-oracle-naming-scope.md new file mode 100644 index 0000000000..edabb5e583 --- /dev/null +++ b/docs/contributing/oracle-reviews/2026-10-03-oracle-naming-scope.md @@ -0,0 +1,86 @@ +# Oracle naming scope correction — 2026-10-03 + +Reviewed implementation: [fe40ab59191d046bda12cc9563cdc4a82b5fd97c](https://github.com/TanStack/db/commit/fe40ab59191d046bda12cc9563cdc4a82b5fd97c). +Classification evidence refers to `134b7e8bacce5999ab7e06da96d5dbe9989820f5`, before the reverse moves. +The [classification ledger](2026-10-03-oracle-naming-scope.json) names each evidence path and its line numbers, final path, role, and naming decision. + +## Corrected scope + +The earlier claim of 251 executable oracle owners and dedicated companions was too broad. +The audit category included ordinary examples, type assertions, harness tests, fixtures, and documentation. +Converting that category directly into a rename list was incorrect. +This record supersedes the naming inventory in [the original review](2026-10-02-glossary-alignment.md). +Its 39 terminology resolutions remain intact. + +This correction restores 101 original filenames and their imports, commands, replay references, and current documentation links. +The PR retains 63 moves: 57 files that execute an independent oracle and six model, grammar, or checker definitions. +Each retained move has a named mechanism and source evidence in the ledger. +Existing filenames that already contained `oracle` before this PR remain unchanged. + +| Role in the original 251-file review scope | Files | +| --- | ---: | +| Executes an independent model, comparison, or generalized checker | 121 | +| Defines an independent model, checker, or its history grammar | 10 | +| Ordinary example, regression, or concrete type-assertion tests | 67 | +| Drivers, fixtures, registration, or supporting declarations | 34 | +| Harness, checker-calibration, or prototype tests | 17 | +| Documentation | 2 | + +These are file roles within the previous inventory, not a count of distinct oracles across the repository. +Several files execute the same model, and a mixed test file can contain multiple oracle mechanisms. +The classification is conservative for borderline cases. It does not declare all pre-existing oracle names correct. + +## Naming evidence + +A retained owner executes an independent expected-result computation, state model, differential comparison, metamorphic relation, or reusable law checker. +A definition owns that model, checker, or its history grammar and names its receiving owner. +Random generation is not required. Fixed histories can execute an independent model, as the optimistic settlement histories do. +Ordinary fixed assertions and parameterization alone are insufficient. +Coverage-map entries and opening comments do not substitute for executable evidence. + +Examples of restored names include `transactions.test.ts`, `query.test-d.ts`, the framework `conformance.test` entrypoints, and `trace-runner.ts`. +They contain fixed assertions, registration/driver mechanics, or generic execution plumbing. +Examples of retained names include `SortedMap-oracle.test.ts`, which compares against native Map plus full sorting, +and `proxy-oracle.test.ts`, which contains a native-value differential callback model alongside ordinary examples. +The test-only no-peek candidate returns to `no-peek.ts`; the independent filter/sort/slice reference remains `model-oracle.ts`. + +The contributor guidance now states this distinction and requires separate counts for owners, definitions, and support. +It does not add a CI linter or introduce new product contracts. + +## Preservation checks + +An independent content comparison accounted for all 2,164 tracked files before final whitespace formatting. +It found 2,048 unchanged blobs, 114 files with mapped path-reference substitutions, and the two naming-policy documents. +The correction preserves glossary definitions, identifier/prose fixes, assertions, model rules, and campaign inputs. +Final formatting changes only whitespace around shortened paths. + +Static checks found all 101 restored paths and all 251 classified files present and indexed. +They checked 672 relative imports, 68 explicit command paths, five browser script entries, and 42 replay targets. +Replay title selectors remained valid. No stale restored-name references or escaped filename patterns remained in current files. +Historical review records and immutable revision links retain their original paths. + +## Validation after the correction + +| Runtime check | Passed | Files | +| --- | ---: | ---: | +| DB | 7,962 | 210 | +| IVM | 704 | 44 | +| Offline | 242 | 18 | +| SQLite core | 375 | 9 | +| Node SQLite | 109 | 5 | +| Browser SQLite | 242 | 9 | +| Electron SQLite | 97 | 3 | +| Electric | 629 | 13 | +| Query DB affected no-peek suites | 18 | 2 | +| React, Vue, Solid, Svelte, Angular receiving suites | 290 | 9 | +| Total | 10,668 | 322 | + +SQLite core also reports one todo. Scoped ESLint passed for 166 changed TypeScript files. +Formatting and `git diff --check` passed. +These runs used the same installed dependencies described in the original record, with coverage and integrated typechecking disabled. +The direct command was `node /vitest.mjs run --coverage.enabled=false --typecheck.enabled=false --maxWorkers=1 --reporter=dot`. +DB used two workers. Framework and Query DB checks selected only the affected receiving files. + +The earlier locked-dependency, integrated-typecheck, and intermittent Query DB baseline limits remain. +This correction did not rerun the full Query DB package, package builds, or external-provider/native-host E2E campaigns. +No new typecheck or real-host claim follows from the runtime passes. diff --git a/docs/contributing/oracle-tests.md b/docs/contributing/oracle-tests.md index 5bf327d59d..7ccffc6cf3 100644 --- a/docs/contributing/oracle-tests.md +++ b/docs/contributing/oracle-tests.md @@ -310,9 +310,31 @@ Two small examples show the form: - [`load-subset-transaction-refinement-oracle.test.ts`](https://github.com/TanStack/db/blob/main/packages/db/tests/query/load-subset-transaction-refinement-oracle.test.ts) explains when an abort can still cancel an on-demand load. -- [`fifo-retry.property.test.ts`](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/fifo-retry.property.test.ts) +- [`fifo-retry-oracle.property.test.ts`](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/fifo-retry-oracle.property.test.ts) explains why a ready transaction waits behind a delayed FIFO head. +### Name oracle files consistently + +Use `oracle` in filenames that own an independent expected-result computation, +state model, differential or metamorphic comparison, or reusable law checker. +A separate module that defines that model, checker, or its history grammar also +qualifies. Identify the mechanism in the code before applying the name. A mixed +test file can qualify through a specific oracle inside it; its other tests do +not thereby become separate oracles. + +An ordinary example or regression does not need this suffix merely because it +asserts a contract. The same applies to concrete type assertions, fixtures, +registration wrappers, and generic runner utilities. A driver that only invokes +production or records observations remains support. Coverage-map inclusion, +parameterization, and contract prose alone do not establish oracle ownership. + +Count owners, model/checker definitions, drivers, and other support separately. +Several files may execute one shared oracle, and one file may contain several +oracle mechanisms. A filename is a discovery aid, not evidence of guide +conformance. Preserve runner suffixes such as `.property.test.ts`, `.test-d.ts`, +and `.spec.ts`. Update imports, test commands, replay selectors, and current +coverage links whenever an oracle file moves. + ### Keep five responsibilities distinguishable ORC-003 requires these responsibilities to remain distinguishable even when @@ -628,7 +650,7 @@ observation recorder, refinement check, and run budget. Only their seed source may differ. This keeps a random failure eligible for promotion into a pinned example or fixed campaign. -[`fifo-retry.property.test.ts`](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/fifo-retry.property.test.ts) +[`fifo-retry-oracle.property.test.ts`](https://github.com/TanStack/db/blob/main/packages/offline-transactions/tests/fifo-retry-oracle.property.test.ts) shows this shape. Its fixed run preserves one scheduler campaign. Its second campaign uses a random seed by default and accepts `OFFLINE_ORACLE_SEED` with `OFFLINE_ORACLE_PATH` for replay. diff --git a/packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.spec.ts b/packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.spec.ts index 5bd4bc0174..896079ebe7 100644 --- a/packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.spec.ts +++ b/packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.spec.ts @@ -187,7 +187,11 @@ test(`a live Electric row commits after OPFS hydration closes and survives hando ) await expectExactRow(leader, updatedRow) expect((await reach(leader)).rowCommitApplied).toBe(true) - await expectReach(leader, { subsetDemandSettled: true }, 30_000) + await expectReach( + leader, + { subsetLoadAndReleaseChainSettled: true }, + 30_000, + ) expect((await observe(leader)).phase).toBe(`ready`) expect((await observe(leader)).isLeader).toBe(true) diff --git a/packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.ts b/packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.ts index 0a873b5624..9ce1f3a525 100644 --- a/packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.ts +++ b/packages/browser-db-sqlite-persistence/e2e/electric-hydration-straddle.opfs.ts @@ -24,7 +24,8 @@ export type HydrationStraddleReach = { rowCommitParked: boolean hydrationScopeExited: boolean rowCommitApplied: boolean - subsetDemandSettled: boolean + // Fixture-only cut after the load, success-path unload, and error handling. + subsetLoadAndReleaseChainSettled: boolean } export type HydrationStraddleObservation = { @@ -101,7 +102,7 @@ const reach: HydrationStraddleReach = { rowCommitParked: false, hydrationScopeExited: false, rowCommitApplied: false, - subsetDemandSettled: false, + subsetLoadAndReleaseChainSettled: false, } const events: Array = [] let phase: HydrationStraddleObservation[`phase`] = `starting` @@ -321,7 +322,7 @@ try { phase = `failed` }) .finally(() => { - reach.subsetDemandSettled = true + reach.subsetLoadAndReleaseChainSettled = true }) } } catch (error) { diff --git a/packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness.opfs.spec.ts b/packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness-oracle.opfs.spec.ts similarity index 100% rename from packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness.opfs.spec.ts rename to packages/browser-db-sqlite-persistence/e2e/shared-driver-fairness-oracle.opfs.spec.ts diff --git a/packages/browser-db-sqlite-persistence/playwright.opfs.config.ts b/packages/browser-db-sqlite-persistence/playwright.opfs.config.ts index 3f2d651797..43cf5a9c80 100644 --- a/packages/browser-db-sqlite-persistence/playwright.opfs.config.ts +++ b/packages/browser-db-sqlite-persistence/playwright.opfs.config.ts @@ -7,7 +7,7 @@ const browserChannel = export default defineConfig({ testDir: `./e2e`, testMatch: [ - `shared-driver-fairness.opfs.spec.ts`, + `shared-driver-fairness-oracle.opfs.spec.ts`, `remote-subset-two-tab.opfs.spec.ts`, `open-timeout.opfs.spec.ts`, ], diff --git a/packages/browser-db-sqlite-persistence/tests/browser-coordinator.test.ts b/packages/browser-db-sqlite-persistence/tests/browser-coordinator-oracle.test.ts similarity index 99% rename from packages/browser-db-sqlite-persistence/tests/browser-coordinator.test.ts rename to packages/browser-db-sqlite-persistence/tests/browser-coordinator-oracle.test.ts index 3f81916f22..a62146fc77 100644 --- a/packages/browser-db-sqlite-persistence/tests/browser-coordinator.test.ts +++ b/packages/browser-db-sqlite-persistence/tests/browser-coordinator-oracle.test.ts @@ -31,7 +31,10 @@ import type { BrowserCollectionCoordinatorOptions } from '../src/browser-coordin * without losing metadata. A mutating RPC may replay only through the same * known leader and term, and one envelope id cannot identify two mutation * request types. Remote subset request data must be clone-safe, and each - * accepted physical acquisition creates one exact acquisition lease. A + * accepted physical acquisition creates one exact acquisition lease. Retained + * coordinator demand survives remote-owner replacement; each replacement + * acquisition has its own lease and release obligation. The Collection-level + * mapping is documented in `per-collection-coordinator-oracle.test.ts`. A * passive heartbeat can update a route, but only a local participant may join * that collection's leadership. A mutation requested before the first leader * is known waits for a route up to the RPC deadline. The sole participant @@ -653,7 +656,7 @@ describe(`BrowserCollectionCoordinator`, () => { let write: | Promise | undefined - let publications = 0 + let committedMessagePosts = 0 try { await vi.waitFor(() => @@ -664,7 +667,7 @@ describe(`BrowserCollectionCoordinator`, () => { (data as { payload?: { type?: string } }).payload?.type === `tx:committed` ) { - publications++ + committedMessagePosts++ } } write = @@ -700,7 +703,7 @@ describe(`BrowserCollectionCoordinator`, () => { }) expect(formerAdapter.appliedTxs).toEqual([]) expect(newAdapter.appliedTxs).toEqual([]) - expect(publications).toBe(0) + expect(committedMessagePosts).toBe(0) } finally { releaseQueued.resolve() await write?.catch(() => undefined) @@ -1611,13 +1614,13 @@ describe(`BrowserCollectionCoordinator`, () => { vi.useFakeTimers() try { - let publications = 0 + let committedMessagePosts = 0 observeBroadcastMessage = (data) => { if ( (data as { payload?: { type?: string } }).payload?.type === `tx:committed` ) { - publications++ + committedMessagePosts++ } } dropNextBroadcastMessage = (data) => @@ -1665,7 +1668,7 @@ describe(`BrowserCollectionCoordinator`, () => { }) expect(retiredLeaderAdapter.appliedTxs).toHaveLength(1) expect(requesterAdapter.appliedTxs).toEqual([]) - expect(publications).toBe(1) + expect(committedMessagePosts).toBe(1) } finally { observeBroadcastMessage = undefined retiredLeader.dispose() @@ -3131,13 +3134,13 @@ describe(`BrowserCollectionCoordinator`, () => { vi.useFakeTimers() try { - let publications = 0 + let committedMessagePosts = 0 observeBroadcastMessage = (data) => { if ( (data as { payload?: { type?: string } }).payload?.type === `tx:committed` ) { - publications++ + committedMessagePosts++ } } let droppedResponse: unknown @@ -3197,7 +3200,7 @@ describe(`BrowserCollectionCoordinator`, () => { }) expect(retiredLeaderAdapter.appliedTxs).toHaveLength(1) expect(requesterAdapter.appliedTxs).toEqual([]) - expect(publications).toBe(1) + expect(committedMessagePosts).toBe(1) } finally { observeBroadcastMessage = undefined retiredLeader.dispose() @@ -4991,7 +4994,7 @@ describe(`BrowserCollectionCoordinator`, () => { } }) - it(`replays a held Browser lease after an A to B to A leader cycle`, async () => { + it(`establishes replacement Browser acquisitions for retained demand after an A to B to A leader cycle`, async () => { const leader = createCoordinator() const follower = createCoordinator() let releaseFirstLoad = (): void => {} @@ -5358,7 +5361,7 @@ describe(`BrowserCollectionCoordinator`, () => { } }) - it(`rebinds a live Browser acquisition when its owner is replaced`, async () => { + it(`establishes a replacement Browser acquisition for retained demand when its owner changes`, async () => { const coordinator = createCoordinator() coordinator.subscribe(`todos`, () => {}) await flush(50) @@ -5413,7 +5416,7 @@ describe(`BrowserCollectionCoordinator`, () => { } }) - it(`rebinds a live remote Browser follower lease when the same leader replaces its owner`, async () => { + it(`establishes a replacement remote Browser acquisition for retained follower demand when the same leader changes owners`, async () => { const leader = createCoordinator() const follower = createCoordinator() leader.subscribe(`todos`, () => {}) @@ -5566,7 +5569,7 @@ describe(`BrowserCollectionCoordinator`, () => { } }) - it(`reacquires the same Browser lease after leadership retirement`, async () => { + it(`establishes a replacement Browser acquisition for retained demand after leadership retirement`, async () => { const coordinator = createCoordinator() coordinator.subscribe(`todos`, () => {}) await flush(50) @@ -5721,7 +5724,7 @@ describe(`BrowserCollectionCoordinator`, () => { }, ) - it(`starts independent Browser lease replays without sibling head-of-line blocking`, async () => { + it(`starts replacement Browser acquisitions without sibling head-of-line blocking`, async () => { const coordinator = createCoordinator() coordinator.subscribe(`todos`, () => {}) await flush(50) diff --git a/packages/browser-db-sqlite-persistence/tests/per-collection-coordinator-oracle.test.ts b/packages/browser-db-sqlite-persistence/tests/per-collection-coordinator-oracle.test.ts index 9258bfdd16..210ae69e5d 100644 --- a/packages/browser-db-sqlite-persistence/tests/per-collection-coordinator-oracle.test.ts +++ b/packages/browser-db-sqlite-persistence/tests/per-collection-coordinator-oracle.test.ts @@ -113,8 +113,8 @@ Coverage owner and test cards This suite owns the RFC #1659 Workstream 2 cut across BrowserCollectionCoordinator, browser persistence resolution, and the -persisted sync wrapper. browser-coordinator.test.ts is still the focused RPC -unit owner, and db-sqlite-persistence-core/tests/persisted.test.ts is still the +persisted sync wrapper. browser-coordinator-oracle.test.ts is still the focused RPC +unit owner, and db-sqlite-persistence-core/tests/persisted-oracle.test.ts is still the single-runtime owner. Putting this history in either file would replace the other production boundary with a stub and lose the collection x tab x adapter identity question. The real SQLite witness below extends the existing browser @@ -157,6 +157,11 @@ Acquisition law and source: objects, prefix and duplicate release, owner replacement, and leadership transfer. `RemoteLeaseOwnerLedger` is a model-only call ledger whose active entries represent physical acquisitions and their acquisition leases. + In the composed history, the outer Collection acquisition calls the + persisted sync adapter, which retains coordinator demand across leadership + changes. Each accepted remote-owner load establishes a separate owner-level + physical acquisition and acquisition lease. Retiring that owner releases + its lease while the outer Collection acquisition remains active. - Production/checkpoint: real coordinator ensure/release calls. Compare owner load/unload counts, exact request-data identity, active acquisitions, and cleanup after each release and takeover cut. @@ -1873,7 +1878,7 @@ describe(`remote subset ownership lease oracle`, () => { } }) - it(`keeps one public acquisition live across leader takeover and releases both owners exactly`, async () => { + it(`retains the outer Collection acquisition across leader takeover and releases both owner acquisition leases exactly`, async () => { type Todo = { id: string; title: string } const firstOwner = new RemoteLeaseOwnerLedger() const secondOwner = new RemoteLeaseOwnerLedger() @@ -1954,7 +1959,8 @@ describe(`remote subset ownership lease oracle`, () => { `remote subset takeover leader`, ) // Deliver the new leader heartbeat and every acquisition replay it - // causes. The public acquisition remains live throughout this cut. + // causes. The outer Collection acquisition retains coordinator demand + // while the retired remote-owner acquisition is replaced. await pumpNetwork() await nextTurn() await pumpNetwork() diff --git a/packages/browser-db-sqlite-persistence/tests/shared-driver-fairness-oracle.test.ts b/packages/browser-db-sqlite-persistence/tests/shared-driver-fairness-oracle.test.ts index 431bd3bf17..d2085dc6d2 100644 --- a/packages/browser-db-sqlite-persistence/tests/shared-driver-fairness-oracle.test.ts +++ b/packages/browser-db-sqlite-persistence/tests/shared-driver-fairness-oracle.test.ts @@ -14,7 +14,7 @@ * tail-order variation loses hydrate-before-later-persist histories. * The shared fixture holds the first `BEGIN IMMEDIATE` while cold `preload()` * calls queue. This file supplies BetterSQLite; the receiving witness in - * `../e2e/shared-driver-fairness.opfs.spec.ts` uses the same fixture with a + * `../e2e/shared-driver-fairness-oracle.opfs.spec.ts` uses the same fixture with a * Chromium OPFSCoopSyncVFS worker after release. It checks rows and K=1 cuts. * Generated failures record the original and reduced histories with their * violated laws and checkpoints; the report says whether shrinking retained diff --git a/packages/db-collection-e2e/README.md b/packages/db-collection-e2e/README.md index b027b14c7d..ffb74ddc1e 100644 --- a/packages/db-collection-e2e/README.md +++ b/packages/db-collection-e2e/README.md @@ -267,7 +267,7 @@ The e2e tests will run alongside your regular tests. All test suites are implemented in `src/suites/*.suite.ts` files and exported as factory functions. -### Predicates Suite (`predicates.suite.ts`) +### Predicates Suite (`predicates-oracle.suite.ts`) Tests basic where clause functionality with ~20 test scenarios: @@ -293,7 +293,7 @@ it('should filter with eq() on number field', async () => { - Complex boolean logic with `and()`, `or()`, `not()` - Predicate pushdown verification -### Pagination Suite (`pagination.suite.ts`) +### Pagination Suite (`pagination-oracle.suite.ts`) Tests ordering and pagination with ~15 test scenarios: @@ -319,7 +319,7 @@ it('should sort ascending by single field', async () => { - Edge cases (limit=0, offset beyond dataset) - Performance verification (only requested page loaded) -### Joins Suite (`joins.suite.ts`) +### Joins Suite (`joins-oracle.suite.ts`) Tests multi-collection joins with ~12 test scenarios: diff --git a/packages/db-collection-e2e/src/index.ts b/packages/db-collection-e2e/src/index.ts index bccff24e2f..ec748f27c3 100644 --- a/packages/db-collection-e2e/src/index.ts +++ b/packages/db-collection-e2e/src/index.ts @@ -18,12 +18,12 @@ export { } from './utils/helpers' // Export test suite creators -export { createPredicatesTestSuite } from './suites/predicates.suite' -export { createPaginationTestSuite } from './suites/pagination.suite' -export { createJoinsTestSuite } from './suites/joins.suite' +export { createPredicatesTestSuite } from './suites/predicates-oracle.suite' +export { createPaginationTestSuite } from './suites/pagination-oracle.suite' +export { createJoinsTestSuite } from './suites/joins-oracle.suite' export { createDeduplicationTestSuite } from './suites/deduplication.suite' export { createCollationTestSuite } from './suites/collation.suite' export { createMutationsTestSuite } from './suites/mutations.suite' -export { createLiveUpdatesTestSuite } from './suites/live-updates.suite' +export { createLiveUpdatesTestSuite } from './suites/live-updates-oracle.suite' export { createProgressiveTestSuite } from './suites/progressive.suite' -export { createMovesTestSuite } from './suites/moves.suite' +export { createMovesTestSuite } from './suites/moves-oracle.suite' diff --git a/packages/db-collection-e2e/src/suites/joins.suite.ts b/packages/db-collection-e2e/src/suites/joins-oracle.suite.ts similarity index 100% rename from packages/db-collection-e2e/src/suites/joins.suite.ts rename to packages/db-collection-e2e/src/suites/joins-oracle.suite.ts diff --git a/packages/db-collection-e2e/src/suites/live-updates.suite.ts b/packages/db-collection-e2e/src/suites/live-updates-oracle.suite.ts similarity index 99% rename from packages/db-collection-e2e/src/suites/live-updates.suite.ts rename to packages/db-collection-e2e/src/suites/live-updates-oracle.suite.ts index 04a5751353..111ae93c64 100644 --- a/packages/db-collection-e2e/src/suites/live-updates.suite.ts +++ b/packages/db-collection-e2e/src/suites/live-updates-oracle.suite.ts @@ -5,7 +5,7 @@ import { waitForQueryData } from '../utils/helpers' import { expectNotificationHistory, expectNotificationsStopped, -} from '../utils/notification-laws' +} from '../utils/notification-laws-oracle' import { assertUserRows, captureUserRows, diff --git a/packages/db-collection-e2e/src/suites/moves.suite.ts b/packages/db-collection-e2e/src/suites/moves-oracle.suite.ts similarity index 99% rename from packages/db-collection-e2e/src/suites/moves.suite.ts rename to packages/db-collection-e2e/src/suites/moves-oracle.suite.ts index 16fffec27f..e6301f2d35 100644 --- a/packages/db-collection-e2e/src/suites/moves.suite.ts +++ b/packages/db-collection-e2e/src/suites/moves-oracle.suite.ts @@ -10,7 +10,7 @@ import { beforeAll, describe, expect, it, vi } from 'vitest' import { createCollection } from '@tanstack/db' import { electricCollectionOptions } from '@tanstack/electric-db-collection' import { waitFor } from '../utils/helpers' -import { expectNotificationHistory } from '../utils/notification-laws' +import { expectNotificationHistory } from '../utils/notification-laws-oracle' import type { E2ETestConfig, Post, User } from '../types' import type { Client } from 'pg' import type { Collection } from '@tanstack/db' diff --git a/packages/db-collection-e2e/src/suites/pagination.suite.ts b/packages/db-collection-e2e/src/suites/pagination-oracle.suite.ts similarity index 100% rename from packages/db-collection-e2e/src/suites/pagination.suite.ts rename to packages/db-collection-e2e/src/suites/pagination-oracle.suite.ts diff --git a/packages/db-collection-e2e/src/suites/predicates.suite.ts b/packages/db-collection-e2e/src/suites/predicates-oracle.suite.ts similarity index 100% rename from packages/db-collection-e2e/src/suites/predicates.suite.ts rename to packages/db-collection-e2e/src/suites/predicates-oracle.suite.ts diff --git a/packages/db-collection-e2e/src/utils/notification-laws.ts b/packages/db-collection-e2e/src/utils/notification-laws-oracle.ts similarity index 100% rename from packages/db-collection-e2e/src/utils/notification-laws.ts rename to packages/db-collection-e2e/src/utils/notification-laws-oracle.ts diff --git a/packages/db-ivm/package.json b/packages/db-ivm/package.json index a72c57a4c8..543e4d41ef 100644 --- a/packages/db-ivm/package.json +++ b/packages/db-ivm/package.json @@ -23,7 +23,7 @@ "dev": "vite build --watch", "lint": "eslint . --fix", "test": "vitest --run", - "test:incrementalization": "vitest --run tests/incrementalization-law.property.test.ts", + "test:incrementalization": "vitest --run tests/incrementalization-law-oracle.property.test.ts", "typecheck": "tsc --noEmit", "bench:hash": "vitest bench --run tests/hash.bench.ts --coverage.enabled=false" }, diff --git a/packages/db-ivm/tests/hash-failure-retry.property.test.ts b/packages/db-ivm/tests/hash-failure-retry-oracle.property.test.ts similarity index 98% rename from packages/db-ivm/tests/hash-failure-retry.property.test.ts rename to packages/db-ivm/tests/hash-failure-retry-oracle.property.test.ts index 17282fdae1..183e785fd6 100644 --- a/packages/db-ivm/tests/hash-failure-retry.property.test.ts +++ b/packages/db-ivm/tests/hash-failure-retry-oracle.property.test.ts @@ -13,7 +13,7 @@ import { hash } from '../src/hashing/hash' * publication from cycle, depth, and work-limit rejection. * * This is the established structural-hash retry contract, also exercised for - * cycle rejection by hash-graph.property.test.ts. The claim here is limited to + * cycle rejection by hash-graph-oracle.property.test.ts. The claim here is limited to * serial calls on one previously uncached array of plain objects with one * rejecting getter. It does not cover pre-cached descendants, shared objects, * reentrant getters, other containers, or other rejection causes. diff --git a/packages/db-ivm/tests/hash-graph.property.test.ts b/packages/db-ivm/tests/hash-graph-oracle.property.test.ts similarity index 100% rename from packages/db-ivm/tests/hash-graph.property.test.ts rename to packages/db-ivm/tests/hash-graph-oracle.property.test.ts diff --git a/packages/db-ivm/tests/hash-identity-oracle.property.test.ts b/packages/db-ivm/tests/hash-identity-oracle.property.test.ts index b9a096b3ca..107a2a3b9d 100644 --- a/packages/db-ivm/tests/hash-identity-oracle.property.test.ts +++ b/packages/db-ivm/tests/hash-identity-oracle.property.test.ts @@ -11,11 +11,11 @@ import { import { captureHashSession } from './hash-session' /** - * # Which values do structural hashing and structural equality identify? + * # Which values share D2 value identity? * * `hash` fingerprints a value, and `equalHashValues` compares two values * without a digest (`topKBatch` uses it to cancel a retraction against its - * replacement). Both use one value identity: + * replacement). Both use D2 value identity: * * 1. **Primitives** compare by value. `-0` equals `0`, `NaN` equals `NaN`, * and a bigint differs from the number with the same text. Symbols compare diff --git a/packages/db-ivm/tests/hash-mixed-graph.property.test.ts b/packages/db-ivm/tests/hash-mixed-graph-oracle.property.test.ts similarity index 99% rename from packages/db-ivm/tests/hash-mixed-graph.property.test.ts rename to packages/db-ivm/tests/hash-mixed-graph-oracle.property.test.ts index d3a358df38..0efcba72da 100644 --- a/packages/db-ivm/tests/hash-mixed-graph.property.test.ts +++ b/packages/db-ivm/tests/hash-mixed-graph-oracle.property.test.ts @@ -4,7 +4,7 @@ import { hash } from '../src/hashing/hash' /** * Mixed-carrier graphs extend the established structural-hash graph law across - * every recursive container (see hash-graph.property.test.ts and the structural + * every recursive container (see hash-graph-oracle.property.test.ts and the structural * values row in docs/contributing/oracle-coverage.md). * * Law: a reachable structural cycle rejects each hash attempt; unfolding diff --git a/packages/db-ivm/tests/hash.property.test.ts b/packages/db-ivm/tests/hash-oracle.property.test.ts similarity index 99% rename from packages/db-ivm/tests/hash.property.test.ts rename to packages/db-ivm/tests/hash-oracle.property.test.ts index 37383f5884..e002070a20 100644 --- a/packages/db-ivm/tests/hash.property.test.ts +++ b/packages/db-ivm/tests/hash-oracle.property.test.ts @@ -132,7 +132,7 @@ const typeMarkerValues = fc.uniqueArray(fc.integer(), { // stable campaign and a fresh campaign. Select a single test name with Vitest // when replaying, for example: // TANSTACK_DB_IVM_HASH_SEED=123 TANSTACK_DB_IVM_HASH_PATH=0:1 \ -// pnpm exec vitest --run tests/hash.property.test.ts -t 'cloned arrays have same hash' +// pnpm exec vitest --run tests/hash-oracle.property.test.ts -t 'cloned arrays have same hash' const valueReplaySeedText = process.env.TANSTACK_DB_IVM_HASH_SEED const valueReplayPath = process.env.TANSTACK_DB_IVM_HASH_PATH const valueReplaySeed = @@ -236,7 +236,7 @@ describe(`hash property-based tests`, () => { ) }) - describe(`structural equality`, () => { + describe(`D2 value identity`, () => { hashProp([arbitrarySimpleObject])( `cloned objects have same hash`, (obj) => { diff --git a/packages/db-ivm/tests/incrementalization-law.property.test.ts b/packages/db-ivm/tests/incrementalization-law-oracle.property.test.ts similarity index 99% rename from packages/db-ivm/tests/incrementalization-law.property.test.ts rename to packages/db-ivm/tests/incrementalization-law-oracle.property.test.ts index 7edafff6ac..0c75c9aef2 100644 --- a/packages/db-ivm/tests/incrementalization-law.property.test.ts +++ b/packages/db-ivm/tests/incrementalization-law-oracle.property.test.ts @@ -24,8 +24,8 @@ import { weightedDifference, weightedStateArbitrary, weightedTransitions, -} from './incrementalization-law.js' -import type { Weighted } from './incrementalization-law.js' +} from './incrementalization-law-oracle.js' +import type { Weighted } from './incrementalization-law-oracle.js' /** * # Does incremental execution equal full recomputation? diff --git a/packages/db-ivm/tests/incrementalization-law.ts b/packages/db-ivm/tests/incrementalization-law-oracle.ts similarity index 100% rename from packages/db-ivm/tests/incrementalization-law.ts rename to packages/db-ivm/tests/incrementalization-law-oracle.ts diff --git a/packages/db-ivm/tests/index-refinement-oracle.property.test.ts b/packages/db-ivm/tests/index-refinement-oracle.property.test.ts index c5c300ee9c..952e5987ce 100644 --- a/packages/db-ivm/tests/index-refinement-oracle.property.test.ts +++ b/packages/db-ivm/tests/index-refinement-oracle.property.test.ts @@ -176,7 +176,7 @@ const pinnedHistories: ReadonlyArray<{ // Production driver and refinement check // --------------------------------------------------------------------------- -function published( +function observedMultiplicities( index: Index, key: string, ): Map { @@ -195,7 +195,7 @@ function expectRefinement(additions: ReadonlyArray): void { const model = expectedIndex(additions.slice(0, step + 1)) for (const key of [`k1`, `k2`]) { const checkpoint = `after addition ${step} for ${key}` - expect(published(index, key), checkpoint).toEqual( + expect(observedMultiplicities(index, key), checkpoint).toEqual( model.get(key) ?? new Map(), ) expect(index.has(key), `${checkpoint} has`).toBe(model.has(key)) diff --git a/packages/db-ivm/tests/operators/count.test.ts b/packages/db-ivm/tests/operators/count.test.ts index 941c3a0db1..a858955ecf 100644 --- a/packages/db-ivm/tests/operators/count.test.ts +++ b/packages/db-ivm/tests/operators/count.test.ts @@ -46,7 +46,11 @@ function testCount() { const result = tracker.getResult() // Assert only keys that have values are affected - assertOnlyKeysAffected(`basic count operation`, result.messages, [1, 2, 3]) + assertOnlyKeysAffected( + `basic count operation`, + result.weightedDeltas, + [1, 2, 3], + ) // Assert the final materialized results are correct assertKeyedResults( @@ -57,7 +61,7 @@ function testCount() { [2, 3], // 3 values for key 2 [3, 1], // 1 value for key 3 (1 + (-1) + 1 = 1) ], - 6, // Expected message count + 6, // Expected weighted delta count ) }) @@ -88,7 +92,7 @@ function testCount() { // Assert only key 1 is affected assertOnlyKeysAffected( `count with all negative multiplicities`, - result.messages, + result.weightedDeltas, [1], ) @@ -99,7 +103,7 @@ function testCount() { [ [1, -3], // -1 + (-2) = -3 ], - 2, // Expected message count + 2, // Expected weighted delta count ) }) @@ -136,10 +140,11 @@ function testCount() { const result = tracker.getResult() // Assert only keys 'one' and 'two' are affected - assertOnlyKeysAffected(`count with multiple batches`, result.messages, [ - `one`, - `two`, - ]) + assertOnlyKeysAffected( + `count with multiple batches`, + result.weightedDeltas, + [`one`, `two`], + ) // Assert the final materialized results are correct assertKeyedResults( @@ -149,11 +154,11 @@ function testCount() { [`one`, 3], // 2 + 1 = 3 [`two`, 1], // 1 ], - 5, // Expected message count + 5, // Expected weighted delta count ) }) - test(`count incremental updates - only affected keys produce messages`, () => { + test(`count incremental updates - only affected keys produce weighted deltas`, () => { const graph = new D2() const input = graph.newInput<[string, string]>() const tracker = new KeyedMessageTracker() @@ -195,7 +200,7 @@ function testCount() { const result = tracker.getResult() // Assert only keys 'a' and 'c' are affected (NOT 'b') - assertOnlyKeysAffected(`count incremental updates`, result.messages, [ + assertOnlyKeysAffected(`count incremental updates`, result.weightedDeltas, [ `a`, `c`, ]) @@ -208,7 +213,7 @@ function testCount() { [`a`, 3], // Count increased from 2 to 3 [`c`, 0], // Count decreased from 1 to 0 ], - 4, // Expected message count: remove old 'a', add new 'a', remove old 'c', add new 'c' + 4, // Expected weighted delta count: remove old 'a', add new 'a', remove old 'c', add new 'c' ) }) } diff --git a/packages/db-ivm/tests/operators/groupBy.test.ts b/packages/db-ivm/tests/operators/groupBy.test.ts index 6f700b2ad5..63067bc1b4 100644 --- a/packages/db-ivm/tests/operators/groupBy.test.ts +++ b/packages/db-ivm/tests/operators/groupBy.test.ts @@ -625,7 +625,7 @@ describe(`Operators`, () => { }) // These are readable replay witnesses. The generated groupBy law lives in - // incrementalization-law.property.test.ts. + // incrementalization-law-oracle.property.test.ts. test(`min and max reduce keep 0, 0n, and empty string as extremes`, () => { const minNum = min() const maxNum = max() diff --git a/packages/db-ivm/tests/operators/groupedOrderByWithFractionalIndex.test.ts b/packages/db-ivm/tests/operators/groupedOrderByWithFractionalIndex.test.ts index d88617b887..520a382142 100644 --- a/packages/db-ivm/tests/operators/groupedOrderByWithFractionalIndex.test.ts +++ b/packages/db-ivm/tests/operators/groupedOrderByWithFractionalIndex.test.ts @@ -163,7 +163,7 @@ describe(`Operators`, () => { ) expect(initialValues).toEqual([1, 3]) - const initialMessageCount = initialResult.messageCount + const initialDeltaCount = initialResult.deltaCount // Insert a better value (0) which should evict value 3 input.sendData( @@ -174,8 +174,8 @@ describe(`Operators`, () => { graph.run() const updateResult = tracker.getResult(compareFractionalIndex) - // Should have 2 new messages: add 0, remove 3 - expect(updateResult.messageCount - initialMessageCount).toBe(2) + // Should have 2 new weighted deltas: add 0, remove 3 + expect(updateResult.deltaCount - initialDeltaCount).toBe(2) // Check final state (cumulative) const sortedFinalResults = sortByKeyAndIndex(updateResult.sortedResults) @@ -217,7 +217,7 @@ describe(`Operators`, () => { ) graph.run() - const initialMessageCount = tracker.getResult().messageCount + const initialDeltaCount = tracker.getResult().deltaCount // Remove the element with value 1 (which is in topK) input.sendData( @@ -228,8 +228,8 @@ describe(`Operators`, () => { graph.run() const updateResult = tracker.getResult(compareFractionalIndex) - // Should have 2 new messages: remove 1, add 5 - expect(updateResult.messageCount - initialMessageCount).toBe(2) + // Should have 2 new weighted deltas: remove 1, add 5 + expect(updateResult.deltaCount - initialDeltaCount).toBe(2) // Final state should have values 3 and 5 const sortedFinalResults = sortByKeyAndIndex(updateResult.sortedResults) @@ -315,27 +315,27 @@ describe(`Operators`, () => { const updateResult = tracker.getResult() - // Should have exactly 2 messages: one removal and one addition - expect(updateResult.messages.length).toBe(2) + // Should have exactly 2 weighted deltas: one removal and one addition + expect(updateResult.weightedDeltas.length).toBe(2) - // Find the removal message (multiplicity -1) and addition message (multiplicity 1) - const removalMessage = updateResult.messages.find( + // Find the removal delta (multiplicity -1) and addition delta (multiplicity 1) + const removalDelta = updateResult.weightedDeltas.find( ([_item, mult]) => mult === -1, ) - const additionMessage = updateResult.messages.find( + const additionDelta = updateResult.weightedDeltas.find( ([_item, mult]) => mult === 1, ) - expect(removalMessage).toBeDefined() - expect(additionMessage).toBeDefined() + expect(removalDelta).toBeDefined() + expect(additionDelta).toBeDefined() // Check that removal is for value 20 (g1-b) - const [_removalKey, [removalValue, _removalIdx]] = removalMessage![0] + const [_removalKey, [removalValue, _removalIdx]] = removalDelta![0] expect(removalValue.value).toBe(20) expect(removalValue.id).toBe(`g1-b`) // Check that addition is for value 5 (g1-c) - const [_additionKey, [additionValue, additionIdx]] = additionMessage![0] + const [_additionKey, [additionValue, additionIdx]] = additionDelta![0] expect(additionValue.value).toBe(5) expect(additionValue.id).toBe(`g1-c`) diff --git a/packages/db-ivm/tests/operators/groupedTopKWithFractionalIndex.test.ts b/packages/db-ivm/tests/operators/groupedTopKWithFractionalIndex.test.ts index c5890d22cb..1717f3ab25 100644 --- a/packages/db-ivm/tests/operators/groupedTopKWithFractionalIndex.test.ts +++ b/packages/db-ivm/tests/operators/groupedTopKWithFractionalIndex.test.ts @@ -104,7 +104,7 @@ describe(`Operators`, () => { .sort((a, b) => a - b) expect(initialValues).toEqual([1, 3]) - const initialMessageCount = initialResult.messageCount + const initialDeltaCount = initialResult.deltaCount // Insert a better value (0) which should evict value 3 input.sendData( @@ -115,8 +115,8 @@ describe(`Operators`, () => { graph.run() const updateResult = tracker.getResult(compareFractionalIndex) - // Should have 2 new messages: add 0, remove 3 - expect(updateResult.messageCount - initialMessageCount).toBe(2) + // Should have 2 new weighted deltas: add 0, remove 3 + expect(updateResult.deltaCount - initialDeltaCount).toBe(2) // Check final state (cumulative) const finalValues = updateResult.sortedResults @@ -155,7 +155,7 @@ describe(`Operators`, () => { ) graph.run() - const initialMessageCount = tracker.getResult().messageCount + const initialDeltaCount = tracker.getResult().deltaCount // Remove the element with value 1 (which is in topK) input.sendData( @@ -166,8 +166,8 @@ describe(`Operators`, () => { graph.run() const updateResult = tracker.getResult(compareFractionalIndex) - // Should have 2 new messages: remove 1, add 5 - expect(updateResult.messageCount - initialMessageCount).toBe(2) + // Should have 2 new weighted deltas: remove 1, add 5 + expect(updateResult.deltaCount - initialDeltaCount).toBe(2) // Final state should have values 3 and 5 const finalValues = updateResult.sortedResults @@ -219,27 +219,27 @@ describe(`Operators`, () => { const updateResult = tracker.getResult() - // Should have exactly 2 messages: one removal and one addition - expect(updateResult.messages.length).toBe(2) + // Should have exactly 2 weighted deltas: one removal and one addition + expect(updateResult.weightedDeltas.length).toBe(2) - // Find the removal message (multiplicity -1) and addition message (multiplicity 1) - const removalMessage = updateResult.messages.find( + // Find the removal delta (multiplicity -1) and addition delta (multiplicity 1) + const removalDelta = updateResult.weightedDeltas.find( ([_item, mult]) => mult === -1, ) - const additionMessage = updateResult.messages.find( + const additionDelta = updateResult.weightedDeltas.find( ([_item, mult]) => mult === 1, ) - expect(removalMessage).toBeDefined() - expect(additionMessage).toBeDefined() + expect(removalDelta).toBeDefined() + expect(additionDelta).toBeDefined() // Check that removal is for value 20 (g1-b) - const [_removalKey, [removalValue, _removalIdx]] = removalMessage![0] + const [_removalKey, [removalValue, _removalIdx]] = removalDelta![0] expect(removalValue.value).toBe(20) expect(removalValue.id).toBe(`g1-b`) // Check that addition is for value 5 (g1-c) - const [_additionKey, [additionValue, _additionIdx]] = additionMessage![0] + const [_additionKey, [additionValue, _additionIdx]] = additionDelta![0] expect(additionValue.value).toBe(5) expect(additionValue.id).toBe(`g1-c`) }) diff --git a/packages/db-ivm/tests/operators/join-types.test.ts b/packages/db-ivm/tests/operators/join-types.test.ts index f0943893e7..20989f38cf 100644 --- a/packages/db-ivm/tests/operators/join-types.test.ts +++ b/packages/db-ivm/tests/operators/join-types.test.ts @@ -130,12 +130,12 @@ describe(`Operators`, () => { // Assert only expected keys are affected assertOnlyKeysAffected( `${joinType} join with multiple batches`, - result.messages, + result.weightedDeltas, expectedKeys, ) // Verify that we actually got some results - expect(result.messages.length).toBeGreaterThan(0) + expect(result.weightedDeltas.length).toBeGreaterThan(0) }) }) }) @@ -210,7 +210,7 @@ function testJoin(joinType: JoinType) { `${joinType} join - initial join with missing rows`, result, expectedResults[joinType], - 6, // Max expected messages (generous upper bound) + 6, // Max expected weighted deltas (generous upper bound) ) }) @@ -288,7 +288,7 @@ function testJoin(joinType: JoinType) { `${joinType} join - insert left (initial)`, initialResult, initialExpectedResults[joinType], - 4, // Max expected messages for initial join + 4, // Max expected weighted deltas for initial join ) // Clear results after initial join @@ -341,13 +341,13 @@ function testJoin(joinType: JoinType) { `${joinType} join - insert left`, result, expectedResults[joinType], - 4, // Max expected messages for incremental update + 4, // Max expected weighted deltas for incremental update ) - // Verify only affected keys produced messages + // Verify only affected keys produced weighted deltas assertOnlyKeysAffected( `${joinType} join - insert left`, - result.messages, + result.weightedDeltas, [2], // Only key 2 should be affected ) }) diff --git a/packages/db-ivm/tests/operators/join.test.ts b/packages/db-ivm/tests/operators/join.test.ts index 0d00578f00..624bbfa438 100644 --- a/packages/db-ivm/tests/operators/join.test.ts +++ b/packages/db-ivm/tests/operators/join.test.ts @@ -51,7 +51,11 @@ function testJoin() { const result = tracker.getResult() // Assert only keys that can actually join (1, 2) are affected, not key 3 - assertOnlyKeysAffected(`basic join operation`, result.messages, [1, 2]) + assertOnlyKeysAffected( + `basic join operation`, + result.weightedDeltas, + [1, 2], + ) // Assert the final materialized results are correct assertKeyedResults( @@ -61,7 +65,7 @@ function testJoin() { [1, [`a`, `x`]], [2, [`b`, `y`]], ], - 4, // Expected message count + 4, // Expected weighted delta count ) }) @@ -103,7 +107,7 @@ function testJoin() { // Assert only expected keys (1, 2) are affected in the join output assertOnlyKeysAffected( `join with late arriving data`, - result.messages, + result.weightedDeltas, [1, 2], ) @@ -115,7 +119,7 @@ function testJoin() { [1, [`a`, `x`]], [2, [`b`, `y`]], ], - 4, // Expected message count + 4, // Expected weighted delta count ) }) @@ -154,16 +158,16 @@ function testJoin() { // Assert only keys that participate in join (1, 2) are affected assertOnlyKeysAffected( `join with negative multiplicities`, - result.messages, + result.weightedDeltas, [1, 2], ) // Verify that key 2 produces a message but with negative multiplicity - const key2Messages = result.messages.filter( + const key2Deltas = result.weightedDeltas.filter( ([[key, _value], _mult]) => key === 2, ) - expect(key2Messages.length).toBeGreaterThan(0) // Key 2 should produce messages - expect(key2Messages[0]![1]).toBeLessThan(0) // But with negative multiplicity + expect(key2Deltas.length).toBeGreaterThan(0) // Key 2 should produce weighted deltas + expect(key2Deltas[0]![1]).toBeLessThan(0) // But with negative multiplicity // Assert the final materialized results (only positive multiplicities remain) assertKeyedResults( @@ -172,7 +176,7 @@ function testJoin() { [ [1, [`a`, `x`]], // Only key 1 should remain in final results ], - 4, // Expected message count + 4, // Expected weighted delta count ) }) @@ -228,7 +232,7 @@ function testJoin() { const expectedKeys = [`key1`, `key2`, `key3`, `key4`, `key5`] assertOnlyKeysAffected( `join multiple batches`, - result.messages, + result.weightedDeltas, expectedKeys, ) @@ -243,7 +247,7 @@ function testJoin() { [`key4`, [`batch2_b`, `x4`]], [`key5`, [`batch3_a`, `x5`]], ], - 10, // Expected message count + 10, // Expected weighted delta count ) }) @@ -319,12 +323,12 @@ function testJoin() { const expectedKeys = [`item1`, `item2`, `item3`] assertOnlyKeysAffected( `join step-by-step`, - stepResult.messages, + stepResult.weightedDeltas, expectedKeys, ) assertOnlyKeysAffected( `join batch processing`, - batchResult.messages, + batchResult.weightedDeltas, expectedKeys, ) diff --git a/packages/db-ivm/tests/operators/orderByWithFractionalIndex.test.ts b/packages/db-ivm/tests/operators/orderByWithFractionalIndex.test.ts index e341b84d5e..1a0b7faa10 100644 --- a/packages/db-ivm/tests/operators/orderByWithFractionalIndex.test.ts +++ b/packages/db-ivm/tests/operators/orderByWithFractionalIndex.test.ts @@ -380,7 +380,7 @@ describe(`Operators`, () => { const initialResult = tracker.getResult(compareFractionalIndex) // Should have the top 3 items by value expect(initialResult.sortedResults.length).toBe(3) - expect(initialResult.messageCount).toBeLessThanOrEqual(4) // Should be efficient + expect(initialResult.deltaCount).toBeLessThanOrEqual(4) // Should be efficient expect( initialResult.sortedResults.map( @@ -404,10 +404,10 @@ describe(`Operators`, () => { const updateResult = tracker.getResult(compareFractionalIndex) - // The incremental messages should tell us that key1 is no longer in the top K + // The incremental weighted deltas should tell us that key1 is no longer in the top K // and that key4 entered the top K - expect(updateResult.messages.length).toBe(2) - const sortedKeysAndMultiplicities = updateResult.messages + expect(updateResult.weightedDeltas.length).toBe(2) + const sortedKeysAndMultiplicities = updateResult.weightedDeltas .map(([[key, _v], multiplicity]) => [key, multiplicity]) .sort((a, b) => (a[0]! < b[0]! ? -1 : a[0]! > b[0]! ? 1 : 0)) expect(sortedKeysAndMultiplicities).toEqual([ @@ -462,7 +462,7 @@ describe(`Operators`, () => { [`key3`, { id: 3, value: `b` }], [`key2`, { id: 2, value: `c` }], ]) - expect(initialResult.messageCount).toBeLessThanOrEqual(4) // Should be efficient + expect(initialResult.deltaCount).toBeLessThanOrEqual(4) // Should be efficient tracker.reset() @@ -477,13 +477,13 @@ describe(`Operators`, () => { const updateResult = tracker.getResult(compareFractionalIndex) // Should have efficient incremental update - expect(updateResult.messageCount).toBeLessThanOrEqual(6) // Should be incremental (modify operation) - expect(updateResult.messageCount).toBeGreaterThan(0) // Should have changes + expect(updateResult.deltaCount).toBeLessThanOrEqual(6) // Should be incremental (modify operation) + expect(updateResult.deltaCount).toBeGreaterThan(0) // Should have changes - // The incremental messages should tell us that key2 is no longer in the top K + // The incremental weighted deltas should tell us that key2 is no longer in the top K // and that key4 entered the top K - expect(updateResult.messages.length).toBe(2) - const sortedKeysAndMultiplicities = updateResult.messages + expect(updateResult.weightedDeltas.length).toBe(2) + const sortedKeysAndMultiplicities = updateResult.weightedDeltas .map(([[key, _v], multiplicity]) => [key, multiplicity]) .sort((a, b) => (a[0]! < b[0]! ? -1 : a[0]! > b[0]! ? 1 : 0)) expect(sortedKeysAndMultiplicities).toEqual([ @@ -544,7 +544,7 @@ describe(`Operators`, () => { // Initial result should have first 3 elements (a, b, c) const initialResult = tracker.getResult(compareFractionalIndex) expect(initialResult.sortedResults.length).toBe(3) - expect(initialResult.messageCount).toBeLessThanOrEqual(6) + expect(initialResult.deltaCount).toBeLessThanOrEqual(6) // Verify initial order const initialSortedValues = initialResult.sortedResults.map( @@ -618,7 +618,7 @@ describe(`Operators`, () => { // Initial result should have elements d, e, f const initialResult = tracker.getResult(compareFractionalIndex) expect(initialResult.sortedResults.length).toBe(3) - expect(initialResult.messageCount).toBeLessThanOrEqual(6) + expect(initialResult.deltaCount).toBeLessThanOrEqual(6) // Verify initial order const initialSortedValues = initialResult.sortedResults.map( diff --git a/packages/db-ivm/tests/operators/reduce.test.ts b/packages/db-ivm/tests/operators/reduce.test.ts index 31998920ef..2fe504bd3f 100644 --- a/packages/db-ivm/tests/operators/reduce.test.ts +++ b/packages/db-ivm/tests/operators/reduce.test.ts @@ -45,7 +45,7 @@ describe(`Operators`, () => { const result = tracker.getResult() // Assert only keys 'a' and 'b' are affected - assertOnlyKeysAffected(`basic reduce operation`, result.messages, [ + assertOnlyKeysAffected(`basic reduce operation`, result.weightedDeltas, [ `a`, `b`, ]) @@ -58,7 +58,7 @@ describe(`Operators`, () => { [`a`, 7], // 1*2 + 2*1 + 3*1 = 7 [`b`, 9], // 4*1 + 5*1 = 9 ], - 4, // Expected message count + 4, // Expected weighted delta count ) }) @@ -96,7 +96,7 @@ describe(`Operators`, () => { // Assert only keys 'a' and 'b' are affected assertOnlyKeysAffected( `reduce with negative multiplicities`, - result.messages, + result.weightedDeltas, [`a`, `b`], ) @@ -108,7 +108,7 @@ describe(`Operators`, () => { [`a`, 3], // 1*(-1) + 2*2 = 3 [`b`, -6], // 3*(-2) = -6 ], - 4, // Expected message count + 4, // Expected weighted delta count ) }) @@ -142,10 +142,11 @@ describe(`Operators`, () => { graph.run() const firstResult = tracker.getResult() - assertOnlyKeysAffected(`reduce first update`, firstResult.messages, [ - `a`, - `b`, - ]) + assertOnlyKeysAffected( + `reduce first update`, + firstResult.weightedDeltas, + [`a`, `b`], + ) assertKeyedResults( `reduce first update`, firstResult, @@ -153,7 +154,7 @@ describe(`Operators`, () => { [`a`, 1], [`b`, 2], ], - 4, // Expected message count + 4, // Expected weighted delta count ) tracker.reset() @@ -168,10 +169,11 @@ describe(`Operators`, () => { graph.run() const secondResult = tracker.getResult() - assertOnlyKeysAffected(`reduce second update`, secondResult.messages, [ - `a`, - `b`, - ]) + assertOnlyKeysAffected( + `reduce second update`, + secondResult.weightedDeltas, + [`a`, `b`], + ) assertKeyedResults( `reduce second update`, secondResult, @@ -179,7 +181,7 @@ describe(`Operators`, () => { [`a`, 4], // 1+3 [`b`, 6], // 2+4 ], - 6, // Expected message count (old removed, new added for both keys) + 6, // Expected weighted delta count (old removed, new added for both keys) ) tracker.reset() @@ -190,14 +192,18 @@ describe(`Operators`, () => { const thirdResult = tracker.getResult() // Only key 'a' should be affected, not 'b' - assertOnlyKeysAffected(`reduce third update`, thirdResult.messages, [`a`]) + assertOnlyKeysAffected( + `reduce third update`, + thirdResult.weightedDeltas, + [`a`], + ) assertKeyedResults( `reduce third update`, thirdResult, [ [`a`, 3], // 4-1=3 ], - 3, // Expected message count (old removed, new added for key a) + 3, // Expected weighted delta count (old removed, new added for key a) ) }) @@ -245,7 +251,7 @@ describe(`Operators`, () => { // Assert only keys 'a' and 'b' are affected assertOnlyKeysAffected( `updates that cancel out completely`, - result.messages, + result.weightedDeltas, [`a`, `b`], ) @@ -257,7 +263,7 @@ describe(`Operators`, () => { [`a`, 0], // 5+3-5-3 = 0 [`b`, 10], // 10 (unchanged) ], - 6, // Expected message count + 6, // Expected weighted delta count ) }) @@ -308,7 +314,7 @@ describe(`Operators`, () => { // Assert only keys 'a', 'b', and 'c' are affected assertOnlyKeysAffected( `mixed positive and negative updates`, - result.messages, + result.weightedDeltas, [`a`, `b`, `c`], ) @@ -321,7 +327,7 @@ describe(`Operators`, () => { [`b`, 15], // 20-20+15 = 15 [`c`, 100], // 100 ], - 8, // Expected message count + 8, // Expected weighted delta count ) }) @@ -382,7 +388,7 @@ describe(`Operators`, () => { // Assert only keys 'a' and 'b' are affected assertOnlyKeysAffected( `complex aggregation with multiple updates`, - result.messages, + result.weightedDeltas, [`a`, `b`], ) @@ -394,7 +400,7 @@ describe(`Operators`, () => { [`a`, { avg: 25, total: 50 }], // Final: (20*1+30*1)/(1+1) = 50/2 = 25 [`b`, { avg: 50, total: 150 }], // Final: 50*3 = 150 ], - 6, // Expected message count + 6, // Expected weighted delta count ) }) @@ -442,7 +448,7 @@ describe(`Operators`, () => { // Assert only keys 'a' and 'b' are affected assertOnlyKeysAffected( `updates with zero-multiplicity results`, - result.messages, + result.weightedDeltas, [`a`, `b`], ) @@ -454,11 +460,11 @@ describe(`Operators`, () => { [`a`, 7], // Final: 5-3-2+7 = 7 [`b`, 10], // Final: 10 (unchanged) ], - 5, // Expected message count + 5, // Expected weighted delta count ) }) - test(`reduce incremental updates - only affected keys produce messages`, () => { + test(`reduce incremental updates - only affected keys produce weighted deltas`, () => { const graph = new D2() const input = graph.newInput<[string, number]>() const tracker = new KeyedMessageTracker() @@ -506,10 +512,11 @@ describe(`Operators`, () => { const result = tracker.getResult() // Assert only keys 'x' and 'z' are affected (NOT 'y') - assertOnlyKeysAffected(`reduce incremental updates`, result.messages, [ - `x`, - `z`, - ]) + assertOnlyKeysAffected( + `reduce incremental updates`, + result.weightedDeltas, + [`x`, `z`], + ) // Assert the final materialized results are correct assertKeyedResults( @@ -519,11 +526,11 @@ describe(`Operators`, () => { [`x`, 60], // Sum increased from 30 to 60 [`z`, 0], // Sum decreased from 100 to 0 ], - 4, // Expected message count: remove old 'x', add new 'x', remove old 'z', add new 'z' + 4, // Expected weighted delta count: remove old 'x', add new 'x', remove old 'z', add new 'z' ) }) - test(`reduce with object identity - may produce messages for identical content`, () => { + test(`reduce with object identity - may produce weighted deltas for identical content`, () => { const graph = new D2() const input = graph.newInput<[string, { id: number; value: number }]>() const tracker = new KeyedMessageTracker() @@ -571,21 +578,21 @@ describe(`Operators`, () => { const result = tracker.getResult() - // With object identity: 'a' produces messages even though content is identical + // With object identity: 'a' produces weighted deltas even though content is identical // This demonstrates the object identity issue, but keysTodo should still limit processing - const aMessages = result.messages.filter( + const aDeltas = result.weightedDeltas.filter( ([[key, _value], _mult]) => key === `a`, ) - expect(aMessages.length).toBe(2) // Object identity causes 2 messages (remove + add) + expect(aDeltas.length).toBe(2) // Object identity causes 2 weighted deltas (remove + add) - // But the messages cancel out due to identical content + // But the weighted deltas cancel out due to identical content assertKeyedResults( `reduce with object identity`, result, [ [`b`, { result: 0 }], // Changed from 100 to 0 ], - 4, // With object identity: 4 messages total (2 for 'a', 2 for 'b') + 4, // With object identity: 4 weighted deltas total (2 for 'a', 2 for 'b') ) }) }) diff --git a/packages/db-ivm/tests/operators/topKWithFractionalIndex.test.ts b/packages/db-ivm/tests/operators/topKWithFractionalIndex-oracle.test.ts similarity index 93% rename from packages/db-ivm/tests/operators/topKWithFractionalIndex.test.ts rename to packages/db-ivm/tests/operators/topKWithFractionalIndex-oracle.test.ts index 934e8cf44c..f1e088007b 100644 --- a/packages/db-ivm/tests/operators/topKWithFractionalIndex.test.ts +++ b/packages/db-ivm/tests/operators/topKWithFractionalIndex-oracle.test.ts @@ -445,13 +445,13 @@ describe(`Operators`, () => { // Initial result should have all elements with fractional indices const initialResult = tracker.getResult() expect(initialResult.sortedResults.length).toBe(5) // Should have all 5 elements - expect(initialResult.messageCount).toBeLessThanOrEqual(6) // Should be efficient + expect(initialResult.deltaCount).toBeLessThanOrEqual(6) // Should be efficient - // Check that indices are in lexicographic order by examining raw messages - const initialMessages = initialResult.messages + // Check that indices are in lexicographic order by examining raw weighted deltas + const initialDeltas = initialResult.weightedDeltas expect( checkLexicographicOrder( - initialMessages.map(([item, mult]) => [item, mult]), + initialDeltas.map(([item, mult]) => [item, mult]), ), ).toBe(true) @@ -483,23 +483,23 @@ describe(`Operators`, () => { [4, 4, `d`], [5, 5, `e`], ]) - expect(updateResult.messageCount).toBeLessThanOrEqual(4) // Should be incremental - expect(updateResult.messageCount).toBeGreaterThan(0) // Should have some changes + expect(updateResult.deltaCount).toBeLessThanOrEqual(4) // Should be incremental + expect(updateResult.deltaCount).toBeGreaterThan(0) // Should have some changes - // Check that only the affected key (null) produces messages + // Check that only the affected key (null) produces weighted deltas assertOnlyKeysAffected( `topKFractional update`, - updateResult.messages, + updateResult.weightedDeltas, [3], ) - // Check that the update messages maintain lexicographic order on their own - if (updateResult.messages.length > 0) { - const updateMessages = updateResult.messages.map(([item, mult]) => [ + // Check that the update weighted deltas maintain lexicographic order on their own + if (updateResult.weightedDeltas.length > 0) { + const updateDeltas = updateResult.weightedDeltas.map(([item, mult]) => [ item, mult, ]) - expect(checkLexicographicOrder(updateMessages)).toBe(true) + expect(checkLexicographicOrder(updateDeltas)).toBe(true) } }) @@ -534,7 +534,7 @@ describe(`Operators`, () => { expect(initialResult.sortedResults.length).toBe(5) // Should have all 5 elements expect( checkLexicographicOrder( - initialResult.messages.map(([item, mult]) => [item, mult]), + initialResult.weightedDeltas.map(([item, mult]) => [item, mult]), ), ).toBe(true) @@ -562,23 +562,23 @@ describe(`Operators`, () => { [4, 4, `d`], [5, 5, `e`], ]) - expect(updateResult.messageCount).toBeLessThanOrEqual(2) // Should be incremental (1 addition) - expect(updateResult.messageCount).toBeGreaterThan(0) // Should have changes + expect(updateResult.deltaCount).toBeLessThanOrEqual(2) // Should be incremental (1 addition) + expect(updateResult.deltaCount).toBeGreaterThan(0) // Should have changes - // Check that only the affected key (null) produces messages + // Check that only the affected key (null) produces weighted deltas assertOnlyKeysAffected( `topKFractional duplicate keys`, - updateResult.messages, + updateResult.weightedDeltas, [6], ) - // Check that the update messages maintain lexicographic order on their own - if (updateResult.messages.length > 0) { - const updateMessages = updateResult.messages.map(([item, mult]) => [ + // Check that the update weighted deltas maintain lexicographic order on their own + if (updateResult.weightedDeltas.length > 0) { + const updateDeltas = updateResult.weightedDeltas.map(([item, mult]) => [ item, mult, ]) - expect(checkLexicographicOrder(updateMessages)).toBe(true) + expect(checkLexicographicOrder(updateDeltas)).toBe(true) } // The total state should have more elements after adding a duplicate @@ -656,7 +656,7 @@ describe(`Operators`, () => { // Initial result should be b, c, d (offset 1, limit 3) const initialResult = tracker.getResult() expect(initialResult.sortedResults.length).toBe(3) // Should have 3 elements - expect(initialResult.messageCount).toBeLessThanOrEqual(6) // Should be efficient + expect(initialResult.deltaCount).toBeLessThanOrEqual(6) // Should be efficient // Check that we have the correct elements (b, c, d) when sorted by fractional index const sortedByIndex = initialResult.sortedResults.sort((a, b) => { @@ -689,16 +689,20 @@ describe(`Operators`, () => { const updateResult = tracker.getResult() // Should have efficient incremental update - expect(updateResult.messageCount).toBeLessThanOrEqual(4) // Should be incremental - expect(updateResult.messageCount).toBeGreaterThan(0) // Should have changes + expect(updateResult.deltaCount).toBeLessThanOrEqual(4) // Should be incremental + expect(updateResult.deltaCount).toBeGreaterThan(0) // Should have changes // Check that final results still maintain correct limit/offset behavior expect(updateResult.sortedResults.length).toBeLessThanOrEqual(3) // Should respect limit - // Check that only the affected key produces messages + // Check that only the affected key produces weighted deltas // 4 is affected because it is pushed out of the topK // by 6 which enters the topK - assertOnlyKeysAffected(`topK limit+offset`, updateResult.messages, [4, 6]) + assertOnlyKeysAffected( + `topK limit+offset`, + updateResult.weightedDeltas, + [4, 6], + ) tracker.relation.expectRows([ [2, 2, `b`], [3, 3, `c`], @@ -734,7 +738,7 @@ describe(`Operators`, () => { const initialResult = tracker.getResult() expect(initialResult.sortedResults.length).toBe(5) // Should have all 5 elements - expect(initialResult.messageCount).toBeLessThanOrEqual(6) // Should be efficient + expect(initialResult.deltaCount).toBeLessThanOrEqual(6) // Should be efficient // Check that results are in correct order initially const initialSortedByIndex = initialResult.sortedResults.sort((a, b) => { @@ -770,13 +774,13 @@ describe(`Operators`, () => { const updateResult = tracker.getResult() // Should have efficient incremental update - expect(updateResult.messageCount).toBeLessThanOrEqual(6) // Should be incremental (4 changes max) - expect(updateResult.messageCount).toBeGreaterThan(0) // Should have changes + expect(updateResult.deltaCount).toBeLessThanOrEqual(6) // Should be incremental (4 changes max) + expect(updateResult.deltaCount).toBeGreaterThan(0) // Should have changes - // Check that only the affected key produces messages + // Check that only the affected key produces weighted deltas assertOnlyKeysAffected( `topK move positions`, - updateResult.messages, + updateResult.weightedDeltas, [2, 4], ) @@ -819,7 +823,7 @@ describe(`Operators`, () => { const initialResult = tracker.getResult() expect(initialResult.sortedResults.length).toBe(5) // Should have all 5 elements - expect(initialResult.messageCount).toBeLessThanOrEqual(6) // Should be efficient + expect(initialResult.deltaCount).toBeLessThanOrEqual(6) // Should be efficient tracker.reset() @@ -854,8 +858,8 @@ describe(`Operators`, () => { [9, 9, `i`], ]) // Should have efficient incremental update - expect(update1Result.messageCount).toBeLessThanOrEqual(6) // Should be incremental - expect(update1Result.messageCount).toBeGreaterThan(0) // Should have changes + expect(update1Result.deltaCount).toBeLessThanOrEqual(6) // Should be incremental + expect(update1Result.deltaCount).toBeGreaterThan(0) // Should have changes tracker.reset() @@ -883,13 +887,13 @@ describe(`Operators`, () => { [3, 3, `j`], ]) // Should have efficient incremental update for value changes - expect(update2Result.messageCount).toBeLessThanOrEqual(6) // Should be incremental - expect(update2Result.messageCount).toBeGreaterThan(0) // Should have changes + expect(update2Result.deltaCount).toBeLessThanOrEqual(6) // Should be incremental + expect(update2Result.deltaCount).toBeGreaterThan(0) // Should have changes - // Check that only the affected key produces messages + // Check that only the affected key produces weighted deltas assertOnlyKeysAffected( `topK lexicographic update2`, - update2Result.messages, + update2Result.weightedDeltas, [3, 7], ) }) @@ -922,7 +926,7 @@ describe(`Operators`, () => { const initialResult = tracker.getResult() expect(initialResult.sortedResults.length).toBe(5) // Should have all 5 elements - expect(initialResult.messageCount).toBeLessThanOrEqual(6) // Should be efficient + expect(initialResult.deltaCount).toBeLessThanOrEqual(6) // Should be efficient // Check that results are in correct initial order const initialSortedByIndex = initialResult.sortedResults.sort((a, b) => { @@ -963,8 +967,8 @@ describe(`Operators`, () => { [5, 5, `e`], ]) // Should have efficient incremental update - expect(cycle1Result.messageCount).toBeLessThanOrEqual(4) // Should be incremental - expect(cycle1Result.messageCount).toBeGreaterThan(0) // Should have changes + expect(cycle1Result.deltaCount).toBeLessThanOrEqual(4) // Should be incremental + expect(cycle1Result.deltaCount).toBeGreaterThan(0) // Should have changes tracker.reset() @@ -986,11 +990,15 @@ describe(`Operators`, () => { [5, 5, `e`], ]) // Should have efficient incremental update for the repositioning - expect(cycle2Result.messageCount).toBeLessThanOrEqual(4) // Should be incremental - expect(cycle2Result.messageCount).toBeGreaterThan(0) // Should have changes + expect(cycle2Result.deltaCount).toBeLessThanOrEqual(4) // Should be incremental + expect(cycle2Result.deltaCount).toBeGreaterThan(0) // Should have changes - // Check that only the affected key produces messages - assertOnlyKeysAffected(`topK cycling update2`, cycle2Result.messages, [1]) + // Check that only the affected key produces weighted deltas + assertOnlyKeysAffected( + `topK cycling update2`, + cycle2Result.weightedDeltas, + [1], + ) // The key point is that the fractional indexing system can handle // multiple repositioning operations efficiently @@ -1263,7 +1271,7 @@ describe(`Operators`, () => { // Initial result should have first 3 elements (a, b, c) const initialResult = tracker.getResult(compareFractionalIndex) expect(initialResult.sortedResults.length).toBe(3) - expect(initialResult.messageCount).toBeLessThanOrEqual(6) + expect(initialResult.deltaCount).toBeLessThanOrEqual(6) // Verify initial order const initialSortedValues = initialResult.sortedResults.map( @@ -1274,7 +1282,7 @@ describe(`Operators`, () => { // Verify windowFn was set expect(windowFn).toBeDefined() - const numberOfMessages = tracker.getResult().messageCount + const priorDeltaCount = tracker.getResult().deltaCount // Move the window to show elements d, e, f (offset: 3, limit: 3) windowFn!({ offset: 3, limit: 3 }) @@ -1288,9 +1296,9 @@ describe(`Operators`, () => { ) expect(moveSortedValues).toEqual([`d`, `e`, `f`]) - // Check that only the affected keys produce messages - const affectedKeys = moveResult.messages.map(([key, _]) => key[0]) - expect(affectedKeys.length).toBe(numberOfMessages + 6) + // Check that only the affected keys produce weighted deltas + const affectedKeys = moveResult.weightedDeltas.map(([key, _]) => key[0]) + expect(affectedKeys.length).toBe(priorDeltaCount + 6) expect(affectedKeys).toEqual(expect.arrayContaining([1, 2, 3, 4, 5, 6])) }) @@ -1336,7 +1344,7 @@ describe(`Operators`, () => { // Initial result should have first 3 elements (a, b, c) const initialResult = tracker.getResult(compareFractionalIndex) expect(initialResult.sortedResults.length).toBe(3) - expect(initialResult.messageCount).toBeLessThanOrEqual(6) + expect(initialResult.deltaCount).toBeLessThanOrEqual(6) // Verify initial order const initialSortedValues = initialResult.sortedResults.map( @@ -1347,7 +1355,7 @@ describe(`Operators`, () => { // Verify windowFn was set expect(windowFn).toBeDefined() - const numberOfMessages = tracker.getResult().messageCount + const priorDeltaCount = tracker.getResult().deltaCount // Move the window to show elements d, e, f (offset: 3, limit: 3) windowFn!({ offset: 0, limit: 3 }) @@ -1361,9 +1369,9 @@ describe(`Operators`, () => { ) expect(moveSortedValues).toEqual([`a`, `b`, `c`]) - // Check that only the affected keys produce messages - const affectedKeys = moveResult.messages.map(([key, _]) => key[0]) - expect(affectedKeys.length).toBe(numberOfMessages + 6) + // Check that only the affected keys produce weighted deltas + const affectedKeys = moveResult.weightedDeltas.map(([key, _]) => key[0]) + expect(affectedKeys.length).toBe(priorDeltaCount + 6) expect(affectedKeys).toEqual(expect.arrayContaining([1, 2, 3, 4, 5, 6])) }) @@ -1676,7 +1684,7 @@ describe(`Operators`, () => { expect(moveSortedValues).toEqual([`a`, `b`, `c`]) // Check that we have changes (elements d, e, f should be removed) - expect(moveResult.messageCount).toBeGreaterThan(0) + expect(moveResult.deltaCount).toBeGreaterThan(0) }) it(`should handle moving window from infinite limit to finite limit while moving offset forward`, () => { @@ -1735,7 +1743,7 @@ describe(`Operators`, () => { expect(moveSortedValues).toEqual([`c`, `d`, `e`]) // Check that we have changes - expect(moveResult.messageCount).toBeGreaterThan(0) + expect(moveResult.deltaCount).toBeGreaterThan(0) }) it(`should handle moving window from infinite limit to finite limit while moving offset backward`, () => { @@ -1799,7 +1807,7 @@ describe(`Operators`, () => { expect(moveSortedValues).toEqual([`b`, `c`]) // Check that we have changes (elements d, e, f should be removed, b, c should be added) - expect(moveResult.messageCount).toBeGreaterThan(0) + expect(moveResult.deltaCount).toBeGreaterThan(0) }) it(`should handle moving window from infinite limit to infinite limit with same offset (no-op)`, () => { @@ -1863,7 +1871,7 @@ describe(`Operators`, () => { expect(moveSortedValues).toEqual([`c`, `d`, `e`, `f`]) // Check that we have no more changes (this should be a no-op) - expect(moveResult.messageCount).toBe(initialResult.messageCount) + expect(moveResult.deltaCount).toBe(initialResult.deltaCount) }) it(`should handle moving window from infinite limit to infinite limit while moving offset forward`, () => { @@ -1927,7 +1935,7 @@ describe(`Operators`, () => { expect(moveSortedValues).toEqual([`c`, `d`, `e`, `f`]) // Check that we have changes (elements a, b should be removed) - expect(moveResult.messageCount).toBeGreaterThan(0) + expect(moveResult.deltaCount).toBeGreaterThan(0) }) it(`should handle moving window from infinite limit to infinite limit while moving offset backward`, () => { @@ -1991,7 +1999,7 @@ describe(`Operators`, () => { expect(moveSortedValues).toEqual([`b`, `c`, `d`, `e`, `f`]) // Check that we have changes (elements b, c should be added) - expect(moveResult.messageCount).toBeGreaterThan(0) + expect(moveResult.deltaCount).toBeGreaterThan(0) }) it(`should handle moving window from finite limit to infinite limit with same offset`, () => { @@ -2056,7 +2064,7 @@ describe(`Operators`, () => { expect(moveSortedValues).toEqual([`c`, `d`, `e`, `f`]) // Check that we have changes (elements e, f should be added) - expect(moveResult.messageCount).toBeGreaterThan(0) + expect(moveResult.deltaCount).toBeGreaterThan(0) }) it(`should handle moving window from finite limit to infinite limit while moving offset forward`, () => { @@ -2121,7 +2129,7 @@ describe(`Operators`, () => { expect(moveSortedValues).toEqual([`d`, `e`, `f`]) // Check that we have changes (elements b, c should be removed, d, e, f should be added) - expect(moveResult.messageCount).toBeGreaterThan(0) + expect(moveResult.deltaCount).toBeGreaterThan(0) }) it(`should handle moving window from finite limit to infinite limit while moving offset backward`, () => { @@ -2186,7 +2194,7 @@ describe(`Operators`, () => { expect(moveSortedValues).toEqual([`b`, `c`, `d`, `e`, `f`]) // Check that we have changes (elements b, c, f should be added, d, e should remain) - expect(moveResult.messageCount).toBeGreaterThan(0) + expect(moveResult.deltaCount).toBeGreaterThan(0) }) }) }) diff --git a/packages/db-ivm/tests/operators/topKWithIndex.test.ts b/packages/db-ivm/tests/operators/topKWithIndex.test.ts index edbf06c6e2..266b79d398 100644 --- a/packages/db-ivm/tests/operators/topKWithIndex.test.ts +++ b/packages/db-ivm/tests/operators/topKWithIndex.test.ts @@ -196,7 +196,7 @@ describe(`Operators`, () => { [null, [{ id: 2, value: `b` }, 1]], [null, [{ id: 3, value: `c` }, 2]], ], - 4, // Max expected messages for initial data + 4, // Max expected weighted deltas for initial data ) tracker.reset() @@ -206,19 +206,21 @@ describe(`Operators`, () => { graph.run() // After removing 'b', we should get incremental changes - // The important thing is that we get a reasonable number of messages + // The important thing is that we get a reasonable number of weighted deltas // and that only the affected key (null) produces output const updateResult = tracker.getResult() // This is an output-transfer cap, not a measurement of internal recomputation. - expect(updateResult.messageCount).toBeLessThanOrEqual(8) - expect(updateResult.messageCount).toBeGreaterThan(0) // Should have some changes + expect(updateResult.deltaCount).toBeLessThanOrEqual(8) + expect(updateResult.deltaCount).toBeGreaterThan(0) // Should have some changes // The materialized result should have some entries (items with positive multiplicity) expect(updateResult.sortedResults.length).toBeGreaterThan(0) - // Check that the messages only affect the null key (verify incremental processing) - assertOnlyKeysAffected(`topK remove row`, updateResult.messages, [null]) + // Check that the weighted deltas only affect the null key (verify incremental processing) + assertOnlyKeysAffected(`topK remove row`, updateResult.weightedDeltas, [ + null, + ]) tracker.relation.expectRows( [ [null, 1, `a`], diff --git a/packages/db-ivm/tests/operators/topk-batch-contract.test.ts b/packages/db-ivm/tests/operators/topk-batch-contract-oracle.test.ts similarity index 100% rename from packages/db-ivm/tests/operators/topk-batch-contract.test.ts rename to packages/db-ivm/tests/operators/topk-batch-contract-oracle.test.ts diff --git a/packages/db-ivm/tests/operators/topk-relation-oracle.ts b/packages/db-ivm/tests/operators/topk-relation-oracle.ts index 09e0bee8a0..3360158e92 100644 --- a/packages/db-ivm/tests/operators/topk-relation-oracle.ts +++ b/packages/db-ivm/tests/operators/topk-relation-oracle.ts @@ -70,8 +70,8 @@ export class TopKRelation< } } -// MessageTracker measures transfer work and can reset. The semantic relation -// must persist across that reset so later checks still include earlier changes. +// MessageTracker counts transferred weighted deltas and can reset. The semantic +// relation must persist across that reset so later checks include earlier changes. export class TopKMessageTracker< K extends string | number | null, I extends number | string, diff --git a/packages/db-ivm/tests/test-utils.ts b/packages/db-ivm/tests/test-utils.ts index c59a27c5ac..d2d55dcbc2 100644 --- a/packages/db-ivm/tests/test-utils.ts +++ b/packages/db-ivm/tests/test-utils.ts @@ -6,13 +6,13 @@ const LOG_RESULTS = process.env.LOG_RESULTS === `true` || process.env.LOG_RESULTS === `1` /** - * Materialize a result set from diff messages - * Takes an array of messages and consolidates them into a final result set + * Materialize a result set from weighted deltas + * Takes an array of weighted deltas and consolidates them into a final result set */ export function materializeResults( - messages: Array<[T, number]>, + weightedDeltas: Array<[T, number]>, ): Map { - const multiSet = new MultiSet(messages) + const multiSet = new MultiSet(weightedDeltas) const consolidated = multiSet.consolidate() const result = new Map() @@ -28,16 +28,16 @@ export function materializeResults( } /** - * Materialize a keyed result set from diff messages - * Takes an array of keyed messages and consolidates them per key + * Materialize a keyed result set from weighted deltas + * Takes an array of keyed weighted deltas and consolidates them per key */ export function materializeKeyedResults( - messages: Array<[[K, V], number]>, + weightedDeltas: Array<[[K, V], number]>, ): Map { const result = new Map>() - // Group messages by key first - for (const [[key, value], multiplicity] of messages) { + // Group weighted deltas by key first + for (const [[key, value], multiplicity] of weightedDeltas) { if (!result.has(key)) { result.set(key, new Map()) } @@ -104,55 +104,58 @@ export function createExpectedResults(items: Array): Map { } /** - * Test helper that tracks messages and materializes results + * Test observation of flattened weighted deltas and their materialized result. + * Each [row, weight] entry contributes one to deltaCount, regardless of weight. + * Both trackers receive D2 MultiSet messages and flatten their entries. + * They omit message boundaries: an empty message contributes no delta. */ export interface TestResult { - messages: Array<[T, number]> - messageCount: number + weightedDeltas: Array<[T, number]> + deltaCount: number materializedResults: Map sortedResults: Array } export interface KeyedTestResult { - messages: Array<[[K, V], number]> - messageCount: number + weightedDeltas: Array<[[K, V], number]> + deltaCount: number materializedResults: Map sortedResults: Array<[K, V]> } export class MessageTracker { - private messages: Array<[T, number]> = [] + private weightedDeltas: Array<[T, number]> = [] addMessage(message: MultiSet) { - this.messages.push(...message.getInner()) + this.weightedDeltas.push(...message.getInner()) } getResult(compare?: (a: T, b: T) => number): TestResult { - const materializedResults = materializeResults(this.messages) + const materializedResults = materializeResults(this.weightedDeltas) const sortedResults = mapToSortedArray(materializedResults, compare) return { - messages: this.messages, - messageCount: this.messages.length, + weightedDeltas: this.weightedDeltas, + deltaCount: this.weightedDeltas.length, materializedResults, sortedResults, } } reset() { - this.messages = [] + this.weightedDeltas = [] } } export class KeyedMessageTracker { - private messages: Array<[[K, V], number]> = [] + private weightedDeltas: Array<[[K, V], number]> = [] addMessage(message: MultiSet<[K, V]>) { - this.messages.push(...message.getInner()) + this.weightedDeltas.push(...message.getInner()) } getResult(): KeyedTestResult { - const materializedResults = materializeKeyedResults(this.messages) + const materializedResults = materializeKeyedResults(this.weightedDeltas) const sortedResults = Array.from(materializedResults.entries()).sort( (a, b) => { // Sort by key for consistent ordering @@ -161,65 +164,65 @@ export class KeyedMessageTracker { ) return { - messages: this.messages, - messageCount: this.messages.length, + weightedDeltas: this.weightedDeltas, + deltaCount: this.weightedDeltas.length, materializedResults, sortedResults, } } reset() { - this.messages = [] + this.weightedDeltas = [] } } /** - * Assert that results match expected, with message count logging + * Assert that results match expected, with weighted delta count logging */ export function assertResults( testName: string, actual: TestResult, expected: Array, - maxExpectedMessages?: number, + maxExpectedDeltas?: number, ) { const expectedMap = createExpectedResults(expected) const expectedSorted = mapToSortedArray(expectedMap) if (LOG_RESULTS) { console.log( - `${testName}: ${actual.messageCount} messages, ${actual.sortedResults.length} final results`, + `${testName}: ${actual.deltaCount} weighted deltas, ${actual.sortedResults.length} final results`, ) - console.log(` Messages:`, actual.messages) + console.log(` Weighted deltas:`, actual.weightedDeltas) console.log(` Final results:`, actual.sortedResults) } // Check that materialized results match expected expect(actual.sortedResults).toEqual(expectedSorted) - // Check message count constraints if provided - if (maxExpectedMessages !== undefined) { - expect(actual.messageCount).toBeLessThanOrEqual(maxExpectedMessages) + // Check weighted delta count constraints if provided + if (maxExpectedDeltas !== undefined) { + expect(actual.deltaCount).toBeLessThanOrEqual(maxExpectedDeltas) } // Log for debugging - use more reasonable threshold - // For empty results, allow up to 2 messages (typical for removal operations) + // For empty results, allow up to 2 weighted deltas (typical for removal operations) // For non-empty results, allow up to 3x the expected count const reasonableThreshold = expected.length === 0 ? 2 : expected.length * 3 - if (actual.messageCount > reasonableThreshold) { + if (actual.deltaCount > reasonableThreshold) { console.warn( - `⚠️ ${testName}: High message count (${actual.messageCount} messages for ${expected.length} expected results)`, + `⚠️ ${testName}: High weighted delta count (${actual.deltaCount} weighted deltas for ${expected.length} expected results)`, ) } } /** - * Assert that keyed results match expected, with message count logging + * Assert that keyed results match expected, with weighted delta count logging */ export function assertKeyedResults( testName: string, actual: KeyedTestResult, expected: Array<[K, V]>, - maxExpectedMessages?: number, + maxExpectedDeltas?: number, ) { const expectedSorted = expected.sort((a, b) => { return JSON.stringify(a[0]).localeCompare(JSON.stringify(b[0])) @@ -227,33 +230,33 @@ export function assertKeyedResults( if (LOG_RESULTS) { console.log( - `${testName}: ${actual.messageCount} messages, ${actual.sortedResults.length} final results per key`, + `${testName}: ${actual.deltaCount} weighted deltas, ${actual.sortedResults.length} final results per key`, ) - console.log(` Messages:`, actual.messages) + console.log(` Weighted deltas:`, actual.weightedDeltas) console.log(` Final results:`, actual.sortedResults) } // Check that materialized results match expected expect(actual.sortedResults).toEqual(expectedSorted) - // Check message count constraints if provided - if (maxExpectedMessages !== undefined) { - expect(actual.messageCount).toBeLessThanOrEqual(maxExpectedMessages) + // Check weighted delta count constraints if provided + if (maxExpectedDeltas !== undefined) { + expect(actual.deltaCount).toBeLessThanOrEqual(maxExpectedDeltas) } // Log for debugging - use more reasonable threshold - // Account for scenarios where messages cancel out due to object identity + // Account for scenarios where weighted deltas cancel out due to object identity // Allow up to 4x the expected count to accommodate remove/add pairs const reasonableThreshold = Math.max(expected.length * 4, 2) - if (actual.messageCount > reasonableThreshold) { + if (actual.deltaCount > reasonableThreshold) { console.warn( - `⚠️ ${testName}: High message count (${actual.messageCount} messages for ${expected.length} expected key-value pairs)`, + `⚠️ ${testName}: High weighted delta count (${actual.deltaCount} weighted deltas for ${expected.length} expected key-value pairs)`, ) } // Log key insights const affectedKeys = new Set( - actual.messages.map(([[key, _value], _mult]) => key), + actual.weightedDeltas.map(([[key, _value], _mult]) => key), ) if (LOG_RESULTS) { console.log( @@ -263,33 +266,33 @@ export function assertKeyedResults( } /** - * Extract unique keys from messages to verify incremental behavior + * Extract unique keys from weighted deltas to verify incremental behavior */ -export function extractMessageKeys( - messages: Array<[[K, V], number]>, +export function extractDeltaKeys( + weightedDeltas: Array<[[K, V], number]>, ): Set { const keys = new Set() - for (const [[key, _value], _multiplicity] of messages) { + for (const [[key, _value], _multiplicity] of weightedDeltas) { keys.add(key) } return keys } /** - * Assert that only specific keys appear in messages (for incremental processing verification) + * Assert that only specific keys appear in weighted deltas (for incremental processing verification) */ export function assertOnlyKeysAffected( testName: string, - messages: Array<[[K, V], number]>, + weightedDeltas: Array<[[K, V], number]>, expectedKeys: Array, ) { - const actualKeys = extractMessageKeys(messages) + const actualKeys = extractDeltaKeys(weightedDeltas) const expectedKeySet = new Set(expectedKeys) // Check that all actual keys are expected Array.from(actualKeys).forEach((key) => { if (!expectedKeySet.has(key)) { - throw new Error(`${testName}: Unexpected key ${key} in messages`) + throw new Error(`${testName}: Unexpected key ${key} in weighted deltas`) } }) diff --git a/packages/db-sqlite-persistence-core/tests/contracts/persisted-collection-conformance-contract.ts b/packages/db-sqlite-persistence-core/tests/contracts/persisted-collection-conformance-contract.ts index 699e7b232c..31f019acee 100644 --- a/packages/db-sqlite-persistence-core/tests/contracts/persisted-collection-conformance-contract.ts +++ b/packages/db-sqlite-persistence-core/tests/contracts/persisted-collection-conformance-contract.ts @@ -1,11 +1,11 @@ import { describe } from 'vitest' import { createCollationTestSuite } from '../../../db-collection-e2e/src/suites/collation.suite' import { createDeduplicationTestSuite } from '../../../db-collection-e2e/src/suites/deduplication.suite' -import { createJoinsTestSuite } from '../../../db-collection-e2e/src/suites/joins.suite' -import { createLiveUpdatesTestSuite } from '../../../db-collection-e2e/src/suites/live-updates.suite' +import { createJoinsTestSuite } from '../../../db-collection-e2e/src/suites/joins-oracle.suite' +import { createLiveUpdatesTestSuite } from '../../../db-collection-e2e/src/suites/live-updates-oracle.suite' import { createMutationsTestSuite } from '../../../db-collection-e2e/src/suites/mutations.suite' -import { createPaginationTestSuite } from '../../../db-collection-e2e/src/suites/pagination.suite' -import { createPredicatesTestSuite } from '../../../db-collection-e2e/src/suites/predicates.suite' +import { createPaginationTestSuite } from '../../../db-collection-e2e/src/suites/pagination-oracle.suite' +import { createPredicatesTestSuite } from '../../../db-collection-e2e/src/suites/predicates-oracle.suite' import type { E2ETestConfig } from '../../../db-collection-e2e/src/types' /** diff --git a/packages/db-sqlite-persistence-core/tests/contracts/sqlite-core-adapter-contract.ts b/packages/db-sqlite-persistence-core/tests/contracts/sqlite-core-adapter-contract.ts index 1aae487154..6fd445f37f 100644 --- a/packages/db-sqlite-persistence-core/tests/contracts/sqlite-core-adapter-contract.ts +++ b/packages/db-sqlite-persistence-core/tests/contracts/sqlite-core-adapter-contract.ts @@ -1,4 +1,4 @@ export { runSQLiteCoreAdapterContractSuite, type SQLiteCoreAdapterHarnessFactory, -} from '../sqlite-core-adapter.test' +} from '../sqlite-core-adapter-oracle.test' diff --git a/packages/db-sqlite-persistence-core/tests/persisted.test.ts b/packages/db-sqlite-persistence-core/tests/persisted-oracle.test.ts similarity index 99% rename from packages/db-sqlite-persistence-core/tests/persisted.test.ts rename to packages/db-sqlite-persistence-core/tests/persisted-oracle.test.ts index 2d3dfc3d64..e1c7391e17 100644 --- a/packages/db-sqlite-persistence-core/tests/persisted.test.ts +++ b/packages/db-sqlite-persistence-core/tests/persisted-oracle.test.ts @@ -61,7 +61,7 @@ import type { * Startup hydrates rows and metadata, buffers concurrent source work, then * publishes one coherent public snapshot. Complete committed transactions * route through the configured collection owner. Publication precedes - * durability, but a rejected durability boundary must reject its applied + * durability, but a rejected durability boundary must reject its wrapped sync * receipt and fail-stop that sync run without admitting a suffix. * * `foldDurabilityLedger` is the independent model for append-only source diff --git a/packages/db-sqlite-persistence-core/tests/persisted-readiness-oracle.test.ts b/packages/db-sqlite-persistence-core/tests/persisted-readiness-oracle.test.ts index 08beef068a..7fffabef11 100644 --- a/packages/db-sqlite-persistence-core/tests/persisted-readiness-oracle.test.ts +++ b/packages/db-sqlite-persistence-core/tests/persisted-readiness-oracle.test.ts @@ -90,7 +90,7 @@ function source( }, } : {}), - // Upstream never declares network readiness. Local restore is a + // Upstream never declares Collection readiness. Local restore is a // separately observable boundary even while this stays loading. sync: { sync: () => ({}) }, }), @@ -145,8 +145,9 @@ async function checkWithCleanup( * its restore in the current sync run. A source that opts out makes the * query unavailable for this signal. A failed restore reports that exact * failure. Neither an empty persisted database nor a pending network source - * changes the rule. Initial rendering prefers network readiness until the - * longest opted-in source deadline, then permits only completed restoration. + * changes the rule. Initial rendering prefers upstream-signaled Collection + * readiness until the longest opted-in source deadline, then permits only + * completed restoration. * Network failure permits earlier fallback without stopping sync. A failed * client query stream is a network failure; a derived-query failure is not. * If the stream failure precedes restore, the fallback must include the @@ -622,19 +623,19 @@ describe(`persisted-readiness oracle`, () => { ]) }) - it(`offers an initial-render fallback without changing preload's network boundary`, async () => { + it(`offers an initial-render fallback without changing preload's Collection readiness boundary`, async () => { const fixture = recordingAdapter([{ id: `one`, value: `local` }]) const persisted = source(`local-suspense`, fixture.adapter, true) const query = createLiveQueryCollection({ query: (q) => q.from({ row: persisted }), }) const observer = createLiveQueryObserver(query) - let networkPreloadSettled = false + let collectionPreloadSettled = false await checkWithCleanup(async () => { - const networkPreload = observer.preload() - void networkPreload.then( - () => (networkPreloadSettled = true), - () => (networkPreloadSettled = true), + const collectionPreload = observer.preload() + void collectionPreload.then( + () => (collectionPreloadSettled = true), + () => (collectionPreloadSettled = true), ) const initialRenderWait = observer.preloadForInitialRender() fixture.load.resolve() @@ -644,7 +645,7 @@ describe(`persisted-readiness oracle`, () => { persistedStatus: `ready`, data: [{ id: `one`, value: `local` }], }) - expect(networkPreloadSettled).toBe(false) + expect(collectionPreloadSettled).toBe(false) }, [ () => observer.dispose(), () => query.cleanup(), @@ -654,7 +655,7 @@ describe(`persisted-readiness oracle`, () => { it(`keeps the initial render gated until the network-first deadline`, async () => { const fixture = recordingAdapter([{ id: `one`, value: `persisted` }]) - let markNetworkReady!: () => void + let markCollectionReady!: () => void const persisted = createCollection( persistedCollectionOptions({ id: `network-first-deadline`, @@ -666,7 +667,7 @@ describe(`persisted-readiness oracle`, () => { }, sync: { sync: ({ markReady }) => { - markNetworkReady = markReady + markCollectionReady = markReady return {} }, }, @@ -702,14 +703,14 @@ describe(`persisted-readiness oracle`, () => { } finally { vi.useRealTimers() } - markNetworkReady() + markCollectionReady() await vi.waitFor(() => expect(persisted.status).toBe(`ready`)) }, [unsubscribe, () => observer.dispose(), () => persisted.cleanup()]) }) - it(`uses network readiness before the fallback deadline`, async () => { + it(`uses Collection readiness before the fallback deadline`, async () => { const fixture = recordingAdapter([{ id: `one`, value: `persisted` }]) - let markNetworkReady!: () => void + let markCollectionReady!: () => void const persisted = createCollection( persistedCollectionOptions({ id: `network-first-success`, @@ -721,7 +722,7 @@ describe(`persisted-readiness oracle`, () => { }, sync: { sync: ({ markReady }) => { - markNetworkReady = markReady + markCollectionReady = markReady return {} }, }, @@ -742,7 +743,7 @@ describe(`persisted-readiness oracle`, () => { await Promise.resolve() expect(settled).toBe(false) - markNetworkReady() + markCollectionReady() await initialRender expect(settled).toBe(true) expect(persisted.status).toBe(`ready`) diff --git a/packages/db-sqlite-persistence-core/tests/persisted-real-adapter-lifecycle.test.ts b/packages/db-sqlite-persistence-core/tests/persisted-real-adapter-lifecycle.test.ts index 8b39be10f5..4ca1f8403e 100644 --- a/packages/db-sqlite-persistence-core/tests/persisted-real-adapter-lifecycle.test.ts +++ b/packages/db-sqlite-persistence-core/tests/persisted-real-adapter-lifecycle.test.ts @@ -20,7 +20,7 @@ import { createSQLiteCorePersistenceAdapter, persistedCollectionOptions, } from '../src' -import { SqliteCliDriver } from './sqlite-core-adapter.test' +import { SqliteCliDriver } from './sqlite-core-adapter-oracle.test' import type { PersistenceAdapter, SQLiteDriver } from '../src' type Deferred = { diff --git a/packages/db-sqlite-persistence-core/tests/shared-logical-scheduling.test.ts b/packages/db-sqlite-persistence-core/tests/shared-logical-scheduling-oracle.test.ts similarity index 100% rename from packages/db-sqlite-persistence-core/tests/shared-logical-scheduling.test.ts rename to packages/db-sqlite-persistence-core/tests/shared-logical-scheduling-oracle.test.ts diff --git a/packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-cli-runtime.test.ts b/packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-cli-runtime.test.ts index e14291a269..57d4edad0a 100644 --- a/packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-cli-runtime.test.ts +++ b/packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-cli-runtime.test.ts @@ -1,3 +1,3 @@ -import { runSQLiteCoreAdapterContractSuite } from './sqlite-core-adapter.test' +import { runSQLiteCoreAdapterContractSuite } from './sqlite-core-adapter-oracle.test' runSQLiteCoreAdapterContractSuite(`SQLiteCorePersistenceAdapter (sqlite3 CLI)`) diff --git a/packages/db-sqlite-persistence-core/tests/sqlite-core-adapter.test.ts b/packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-oracle.test.ts similarity index 98% rename from packages/db-sqlite-persistence-core/tests/sqlite-core-adapter.test.ts rename to packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-oracle.test.ts index 4da7909c9a..055e005af2 100644 --- a/packages/db-sqlite-persistence-core/tests/sqlite-core-adapter.test.ts +++ b/packages/db-sqlite-persistence-core/tests/sqlite-core-adapter-oracle.test.ts @@ -232,7 +232,7 @@ type ResetResumeHistory = { } type ResetResumeObservation = { - checkpoint: `after-persistence-transition-restart` + checkpoint: `after-persistence-transition-reopen` resetEpoch: number schemaVersion: number durableRows: ReadonlyArray @@ -454,15 +454,15 @@ async function observeResetResumeHistory( const nextSchemaVersion = usesSchemaReset ? history.fromSchemaVersion + 1 : history.fromSchemaVersion - let restarted = new SQLiteCorePersistenceAdapter({ + let reopened = new SQLiteCorePersistenceAdapter({ driver: harness.driver, schemaVersion: nextSchemaVersion, schemaMismatchPolicy: `sync-present-reset`, }) - await restarted.loadSubset(collectionId, {}) + await reopened.loadSubset(collectionId, {}) if (history.transition === `partial-restore`) { - await restarted.applyCommittedTx(collectionId, { + await reopened.applyCommittedTx(collectionId, { txId: `partial-restore`, term: 2, seq: 1, @@ -482,15 +482,15 @@ async function observeResetResumeHistory( } for (let index = 0; index < history.reopensAfterTransition; index++) { - restarted = new SQLiteCorePersistenceAdapter({ + reopened = new SQLiteCorePersistenceAdapter({ driver: harness.driver, schemaVersion: nextSchemaVersion, schemaMismatchPolicy: `sync-present-reset`, }) - await restarted.loadSubset(collectionId, {}) + await reopened.loadSubset(collectionId, {}) } - const metadata = await restarted.loadCollectionMetadata(collectionId) + const metadata = await reopened.loadCollectionMetadata(collectionId) const resetEpochRows = await harness.driver.query<{ reset_epoch: number }>( `SELECT reset_epoch FROM collection_reset_epoch WHERE collection_id = ?`, [collectionId], @@ -518,10 +518,10 @@ async function observeResetResumeHistory( [collectionId], ) observation = { - checkpoint: `after-persistence-transition-restart`, + checkpoint: `after-persistence-transition-reopen`, resetEpoch: resetEpochRows[0]?.reset_epoch ?? -1, schemaVersion: registryRows[0]?.schema_version ?? -1, - durableRows: (await restarted.loadSubset(collectionId, {})).sort((a, b) => + durableRows: (await reopened.loadSubset(collectionId, {})).sort((a, b) => String(a.key).localeCompare(String(b.key)), ), tombstones: tombstones.map(({ key, row_version }) => ({ @@ -1784,15 +1784,15 @@ export function runSQLiteCoreAdapterContractSuite( * * Law and source: a destructive schema reset creates a new persisted * baseline and clears every collection-metadata record in that reset - * transaction. Same-schema restarts preserve metadata, including for a - * genuinely empty baseline. The production reset policy above and the + * transaction. Same-schema adapter reopens preserve metadata, including + * for a genuinely empty baseline. The production reset policy above and the * independently reproduced history in * https://github.com/TanStack/db/issues/1589 establish this narrow law. * * Domain and legal histories: zero-to-four committed rows; absent, reset, - * or non-initial resume metadata; same-schema restart, vN -> vN+1 + * or non-initial resume metadata; same-schema adapter reopen, vN -> vN+1 * sync-present-reset, a partial restore after reset, or out-of-band row - * loss; restarts on either side; unrelated metadata. + * loss; adapter reopens on either side; unrelated metadata. * * Reference: a two-generation lineage relation. Same-schema reopen and raw * external loss keep the core generation/metadata record; schema reset @@ -1803,7 +1803,7 @@ export function runSQLiteCoreAdapterContractSuite( * Production path and checkpoint: SQLiteCorePersistenceAdapter commits a * real SQLite baseline, then a new adapter instance reaches * ensureCollectionReady/handleSchemaMismatch. At the - * after-persistence-transition-restart checkpoint we inspect registry + * after-persistence-transition-reopen checkpoint we inspect registry * version, reset epoch/generation, complete durable rows, tombstones, * applied transactions, and collection metadata. * @@ -1821,7 +1821,7 @@ export function runSQLiteCoreAdapterContractSuite( * is removed after evidence capture. The failure reports first and reduced * histories plus a verified fast-check seed/path replay. */ - it(`resets collection metadata with its persisted baseline across generated restart histories`, async () => { + it(`resets collection metadata with its persisted baseline across generated adapter reopen histories`, async () => { const historyArbitrary = fc .constantFrom< ResetResumeHistory[`transition`] @@ -1996,7 +1996,7 @@ export function runSQLiteCoreAdapterContractSuite( unrelatedMetadataKeys: [`provider`], } const observation: ResetResumeObservation = { - checkpoint: `after-persistence-transition-restart`, + checkpoint: `after-persistence-transition-reopen`, resetEpoch: 0, schemaVersion: 1, durableRows: [], diff --git a/packages/db-sqlite-persistence-core/tests/sqlite-resume-snapshot.test.ts b/packages/db-sqlite-persistence-core/tests/sqlite-resume-snapshot-oracle.test.ts similarity index 99% rename from packages/db-sqlite-persistence-core/tests/sqlite-resume-snapshot.test.ts rename to packages/db-sqlite-persistence-core/tests/sqlite-resume-snapshot-oracle.test.ts index 40939e9398..62f041dc3c 100644 --- a/packages/db-sqlite-persistence-core/tests/sqlite-resume-snapshot.test.ts +++ b/packages/db-sqlite-persistence-core/tests/sqlite-resume-snapshot-oracle.test.ts @@ -218,7 +218,7 @@ async function observeCachedSchemaState( * key loss makes that evidence incompatible until a full replacement establishes * a new baseline; concurrent schema migration may advance but never downgrade or * repeat the observed generation. These laws refine the shared persistence and - * schema-mismatch contracts exercised by sqlite-core-adapter.test.ts. + * schema-mismatch contracts exercised by sqlite-core-adapter-oracle.test.ts. * * `CachedSchemaState` is the independent projection: complete rows and metadata, * transaction position, schema/reset lineage, and expected keys. The history diff --git a/packages/db-sqlite-persistence-core/vite.config.ts b/packages/db-sqlite-persistence-core/vite.config.ts index 52bf45a0f0..803780c28f 100644 --- a/packages/db-sqlite-persistence-core/vite.config.ts +++ b/packages/db-sqlite-persistence-core/vite.config.ts @@ -6,7 +6,7 @@ const config = defineConfig({ test: { name: packageJson.name, include: [`tests/**/*.test.ts`], - exclude: [`tests/sqlite-core-adapter.test.ts`], + exclude: [`tests/sqlite-core-adapter-oracle.test.ts`], environment: `jsdom`, coverage: { enabled: true, provider: `istanbul`, include: [`src/**/*`] }, typecheck: { diff --git a/packages/db/package.json b/packages/db/package.json index 4aa87b5b11..981f5fa3fe 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -23,7 +23,7 @@ "test": "vitest --run", "test:dist": "vitest run --config vitest.dist.config.ts", "test:facade-retention": "node --expose-gc --import tsx tests/facade-retention.probe.ts", - "test:oracles": "vitest --run --coverage.enabled=false tests/cleanup-queue.property.test.ts tests/comparison.property.test.ts tests/cursor.property.test.ts tests/index-update.property.test.ts tests/utils.property.test.ts tests/change-event-history-oracle.test.ts tests/index-suggestion-oracle.test.ts tests/btree-map-oracle.test.ts tests/paced-mutations-oracle.test.ts tests/db-client-hydration-authority-oracle.test.ts tests/collection-mutation-startup-oracle.test.ts tests/collection-cleanup-restart-oracle.test.ts tests/effect-disposal-oracle.test.ts tests/optimistic-transaction-oracle.property.test.ts tests/optimistic-settlement-boundaries.test.ts tests/optimistic-history-publication.test.ts tests/optimistic-history-outcomes.test.ts tests/collection-metadata-publication-oracle.property.test.ts tests/collection-state-retention-oracle.property.test.ts tests/collection-truncate-ownership-oracle.property.test.ts tests/collection-subscription-lifecycle-history.property.test.ts tests/collection-subscription-lifecycle-oracle.test.ts tests/collection-subscription-reentrancy-oracle.test.ts tests/collection-subscription-lifecycle-publication.property.test.ts tests/collection-subscription-replay-oracle.property.test.ts tests/d2-source-reconciliation-oracle.property.test.ts tests/live-query-observer-history.property.test.ts tests/query/cold-join-reconciliation-oracle.test.ts tests/query/identity-output-shape-oracle.test.ts tests/query/optimizer-semantics-oracle.test.ts tests/query/index-path-collision-oracle.test.ts tests/query/includes-collection-oracle.property.test.ts tests/query/includes-functional-projection-oracle.test.ts tests/query/includes-functional-input-boundary.test.ts tests/query/includes-context-transport-oracle.test.ts tests/query/includes-cross-formulation-oracle.property.test.ts tests/query/includes-optimistic-oracle.property.test.ts tests/query/includes-oracle.property.test.ts tests/query/includes-publication-oracle.test.ts tests/query/includes-query-shape-oracle.test.ts tests/query/subquery-user-value-oracle.test.ts tests/query/includes-temporal-oracle.test.ts tests/query/includes-work-counter-oracle.test.ts tests/query/load-subset-oracle.property.test.ts tests/query/load-subset-replay-refinement-oracle.test.ts tests/query/load-subset-source-readiness-refinement-oracle.test.ts tests/query/load-subset-transaction-refinement-oracle.test.ts tests/query/ordered-source-loader-state.test.ts tests/query/ordered-demand-retirement.test.ts tests/query/ordered-default-work.test.ts tests/query/ordered-lifecycle-oracle.property.test.ts tests/query/ordered-work-oracle.property.test.ts tests/query/pagination-oracle.property.test.ts tests/query/includes-space-oracle.test.ts tests/query/virtual-row-fields-oracle.test.ts tests/query/where-predicate-publication-oracle.property.test.ts tests/query/join-result-key-oracle.property.test.ts tests/query/pooled-live-query-oracle.property.test.ts tests/flat-change-tracking-oracle.property.test.ts", + "test:oracles": "vitest --run --coverage.enabled=false tests/cleanup-queue-oracle.property.test.ts tests/comparison-oracle.property.test.ts tests/cursor-oracle.property.test.ts tests/index-update-oracle.property.test.ts tests/utils-oracle.property.test.ts tests/change-event-history-oracle.test.ts tests/index-suggestion-oracle.test.ts tests/btree-map-oracle.test.ts tests/paced-mutations-oracle.test.ts tests/db-client-hydration-authority-oracle.test.ts tests/collection-mutation-startup-oracle.test.ts tests/collection-cleanup-restart-oracle.test.ts tests/effect-disposal-oracle.test.ts tests/optimistic-transaction-oracle.property.test.ts tests/optimistic-settlement-boundaries-oracle.test.ts tests/optimistic-history-publication-oracle.test.ts tests/optimistic-history-outcomes-oracle.test.ts tests/collection-metadata-publication-oracle.property.test.ts tests/collection-state-retention-oracle.property.test.ts tests/collection-truncate-ownership-oracle.property.test.ts tests/collection-subscription-lifecycle-history-oracle.property.test.ts tests/collection-subscription-lifecycle-oracle.test.ts tests/collection-subscription-reentrancy-oracle.test.ts tests/collection-subscription-lifecycle-publication-oracle.property.test.ts tests/collection-subscription-replay-oracle.property.test.ts tests/d2-source-reconciliation-oracle.property.test.ts tests/live-query-observer-history-oracle.property.test.ts tests/query/cold-join-reconciliation-oracle.test.ts tests/query/identity-output-shape-oracle.test.ts tests/query/optimizer-semantics-oracle.test.ts tests/query/index-path-collision-oracle.test.ts tests/query/includes-collection-oracle.property.test.ts tests/query/includes-functional-projection-oracle.test.ts tests/query/includes-functional-input-boundary.test.ts tests/query/includes-context-transport-oracle.test.ts tests/query/includes-cross-formulation-oracle.property.test.ts tests/query/includes-optimistic-oracle.property.test.ts tests/query/includes-oracle.property.test.ts tests/query/includes-publication-oracle.test.ts tests/query/includes-query-shape-oracle.test.ts tests/query/subquery-user-value-oracle.test.ts tests/query/includes-temporal-oracle.test.ts tests/query/includes-work-counter-oracle.test.ts tests/query/load-subset-oracle.property.test.ts tests/query/load-subset-replay-refinement-oracle.test.ts tests/query/load-subset-source-readiness-refinement-oracle.test.ts tests/query/load-subset-transaction-refinement-oracle.test.ts tests/query/ordered-source-loader-state-oracle.test.ts tests/query/ordered-demand-retirement.test.ts tests/query/ordered-default-work.test.ts tests/query/ordered-lifecycle-oracle.property.test.ts tests/query/ordered-work-oracle.property.test.ts tests/query/pagination-oracle.property.test.ts tests/query/includes-space-oracle.test.ts tests/query/virtual-row-fields-oracle.test.ts tests/query/where-predicate-publication-oracle.property.test.ts tests/query/join-result-key-oracle.property.test.ts tests/query/pooled-live-query-oracle.property.test.ts tests/flat-change-tracking-oracle.property.test.ts", "bench:nested-includes": "vitest bench tests/query/includes-performance.bench.ts --run" }, "type": "module", diff --git a/packages/db/src/proxy.ts b/packages/db/src/proxy.ts index b10ff85dcf..d0f822887f 100644 --- a/packages/db/src/proxy.ts +++ b/packages/db/src/proxy.ts @@ -270,7 +270,7 @@ function deepClone( } // Arbitrary instances may carry private/native state we cannot reconstruct. - // Keep them by reference at publication, rather than silently flattening them. + // Keep them by reference when detaching a change set. if (detach) { const prototype = Object.getPrototypeOf(obj) if (prototype !== Object.prototype && prototype !== null) return obj diff --git a/packages/db/tests/SortedMap.test.ts b/packages/db/tests/SortedMap-oracle.test.ts similarity index 100% rename from packages/db/tests/SortedMap.test.ts rename to packages/db/tests/SortedMap-oracle.test.ts diff --git a/packages/db/tests/btree-map-oracle.test.ts b/packages/db/tests/btree-map-oracle.test.ts index 73869f190a..a3cd6b9e25 100644 --- a/packages/db/tests/btree-map-oracle.test.ts +++ b/packages/db/tests/btree-map-oracle.test.ts @@ -32,7 +32,7 @@ import { BTree } from '../src/utils/btree.js' // The tree trusts its comparator to return a valid order; BTreeIndex rejects // invalid custom-comparator results before they reach the tree, so that law -// lives in index-update.property.test.ts. +// lives in index-update-oracle.property.test.ts. // Splitting already determines the new child's position from the insertion // index. A redundant comparison after mutation must not misplace it. Each diff --git a/packages/db/tests/cleanup-queue.property.test.ts b/packages/db/tests/cleanup-queue-oracle.property.test.ts similarity index 100% rename from packages/db/tests/cleanup-queue.property.test.ts rename to packages/db/tests/cleanup-queue-oracle.property.test.ts diff --git a/packages/db/tests/collection-subscription-lifecycle-grammar.ts b/packages/db/tests/collection-subscription-lifecycle-grammar-oracle.ts similarity index 98% rename from packages/db/tests/collection-subscription-lifecycle-grammar.ts rename to packages/db/tests/collection-subscription-lifecycle-grammar-oracle.ts index 6427daf096..bca68caa39 100644 --- a/packages/db/tests/collection-subscription-lifecycle-grammar.ts +++ b/packages/db/tests/collection-subscription-lifecycle-grammar-oracle.ts @@ -14,9 +14,11 @@ import { fc } from '@fast-check/vitest' * command combines demand retirement with release of that owner's acquisition * lease. `abort` only requests cancellation; it does not retire the owner. * `settle` changes an acquisition attempt. `truncate` starts a private - * replacement. `restart`, `cleanup`, and `unsubscribe` change the enclosing - * sync run. The reducer is a pure reference machine: it never calls an - * adapter and never reads production state. + * replacement. `cleanup` ends the current sync run; `restart` starts a new + * sync run. `unsubscribe` ends this subscription, retires its logical subset + * owners, and releases their acquisition leases. It does not end the + * Collection's sync run. The reducer is a pure reference machine: it never + * calls an adapter and never reads production state. * * The model is intentionally one graph rather than one model per assertion. * Ownership decides which attempts are live; attempts decide readiness and diff --git a/packages/db/tests/collection-subscription-lifecycle-history.property.test.ts b/packages/db/tests/collection-subscription-lifecycle-history-oracle.property.test.ts similarity index 99% rename from packages/db/tests/collection-subscription-lifecycle-history.property.test.ts rename to packages/db/tests/collection-subscription-lifecycle-history-oracle.property.test.ts index 260d89a350..c70d985b84 100644 --- a/packages/db/tests/collection-subscription-lifecycle-history.property.test.ts +++ b/packages/db/tests/collection-subscription-lifecycle-history-oracle.property.test.ts @@ -16,7 +16,7 @@ import { settle, syncLifecycleHistory, syncLifecycleHistoryArbitrary, -} from './collection-subscription-lifecycle-grammar.js' +} from './collection-subscription-lifecycle-grammar-oracle.js' import { flushPromises } from './utils.js' import { oraclePropertyOptions, @@ -32,7 +32,7 @@ import type { LifecycleResultEvent, LifecycleTraceEvent, LifecycleUnloadEvent, -} from './collection-subscription-lifecycle-grammar.js' +} from './collection-subscription-lifecycle-grammar-oracle.js' const { multiplier, ...replay } = readOracleRunConfig() const it = replay.replayPath === undefined ? vitestIt : vitestIt.skip diff --git a/packages/db/tests/collection-subscription-lifecycle-oracle.test.ts b/packages/db/tests/collection-subscription-lifecycle-oracle.test.ts index 09f6025af3..0b10dc6449 100644 --- a/packages/db/tests/collection-subscription-lifecycle-oracle.test.ts +++ b/packages/db/tests/collection-subscription-lifecycle-oracle.test.ts @@ -16,7 +16,7 @@ import type { LoadSubsetOptions, SyncConfig } from '../src/types.js' /** * This is the boundary matrix for subscription acquisition and retirement. * - * The model is a product of a small physical-acquisition state, logical owners, + * The model is a product of a small acquisition lifecycle state, logical owners, * sync run, and callback entry point. The explicit cell table names every * legal phase/entry pair and gives a reason for every excluded pair. Scenario * drivers then add sync return/throw/resolve/reject, abort, release, peer loss, @@ -182,36 +182,50 @@ function acquisitionCase( ) } -const physicalAcquisitionStates = [ +/** + * Model-only lifecycle projection spanning attempts and accepted acquisitions: + * `none` has no accepted work; `starting` is a tentative acquisition attempt; + * `active` has an accepted physical acquisition and its acquisition lease; + * `obsolete` has retired acquisition ownership; `failed-release` has attempted + * acquisition release and must not retry it. + */ +const acquisitionLifecycleStates = [ `none`, `starting`, `active`, `obsolete`, `failed-release`, ] as const -const physicalInteractionCauses = [ +const acquisitionInteractionCauses = [ `release`, `abort`, `truncate`, `cleanup`, `unsubscribe`, ] as const -type PhysicalAcquisitionState = (typeof physicalAcquisitionStates)[number] -type PhysicalInteractionCause = (typeof physicalInteractionCauses)[number] -type PhysicalInteractionCell = - `${PhysicalAcquisitionState}:${PhysicalInteractionCause}` -type PhysicalInteraction = +type AcquisitionLifecycleState = (typeof acquisitionLifecycleStates)[number] +type AcquisitionInteractionCause = (typeof acquisitionInteractionCauses)[number] +type AcquisitionInteractionCell = + `${AcquisitionLifecycleState}:${AcquisitionInteractionCause}` +// `retire` projects the end of ownership, not necessarily acquisition release. +// During `starting`, a synchronous throw fails the attempt before acceptance. +// Cleanup invalidation cancels a returned tentative acquisition before activation +// without retaining its lease. An accepted acquisition instead releases its lease. +// Logical demand can survive this boundary, as it does during truncate replay. +// An `active` interaction ends accepted ownership through acquisition release +// or enclosing sync-run cleanup. +type AcquisitionInteraction = | `no-acquisition` | `abort-only` | `retire` | `no-repeat-on-truncate` | `no-repeat-on-cleanup` | `no-repeat-on-unsubscribe` -type PhysicalInteractionCellDefinition = - | { kind: `covered`; interaction: PhysicalInteraction } +type AcquisitionInteractionCellDefinition = + | { kind: `covered`; interaction: AcquisitionInteraction } | { kind: `excluded`; reason: string } -const physicalInteractionCellDefinitions = { +const acquisitionInteractionCellDefinitions = { 'none:release': { kind: `covered`, interaction: `no-acquisition`, @@ -285,29 +299,32 @@ const physicalInteractionCellDefinitions = { kind: `covered`, interaction: `no-repeat-on-unsubscribe`, }, -} satisfies Record - -const requiredPhysicalInteractions = new Map< - PhysicalInteractionCell, - PhysicalInteraction +} satisfies Record< + AcquisitionInteractionCell, + AcquisitionInteractionCellDefinition +> + +const requiredAcquisitionInteractions = new Map< + AcquisitionInteractionCell, + AcquisitionInteraction >( - Object.entries(physicalInteractionCellDefinitions).flatMap( + Object.entries(acquisitionInteractionCellDefinitions).flatMap( ([cell, definition]) => definition.kind === `covered` - ? [[cell as PhysicalInteractionCell, definition.interaction]] + ? [[cell as AcquisitionInteractionCell, definition.interaction]] : [], ), ) -const observedPhysicalInteractions = new Map< - PhysicalInteractionCell, - PhysicalInteraction +const observedAcquisitionInteractions = new Map< + AcquisitionInteractionCell, + AcquisitionInteraction >() -function observePhysicalInteraction( - cell: PhysicalInteractionCell, - interaction: PhysicalInteraction, +function observeAcquisitionInteraction( + cell: AcquisitionInteractionCell, + interaction: AcquisitionInteraction, ): void { - observedPhysicalInteractions.set(cell, interaction) + observedAcquisitionInteractions.set(cell, interaction) } const requiredSyncRunBoundaries = new Set([ @@ -1011,13 +1028,15 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { ).toEqual(allCells) }) - it(`accounts for every physical acquisition state and interaction cause`, () => { - const allCells = new Set( - physicalAcquisitionStates.flatMap((state) => - physicalInteractionCauses.map((cause) => `${state}:${cause}` as const), + it(`accounts for every acquisition lifecycle state and interaction cause`, () => { + const allCells = new Set( + acquisitionLifecycleStates.flatMap((state) => + acquisitionInteractionCauses.map( + (cause) => `${state}:${cause}` as const, + ), ), ) - expect(new Set(Object.keys(physicalInteractionCellDefinitions))).toEqual( + expect(new Set(Object.keys(acquisitionInteractionCellDefinitions))).toEqual( allCells, ) }) @@ -1026,7 +1045,9 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { // A direct property replay may select only that test by name. if (replay.replayPath !== undefined) return expect(observedAcquisitionCells).toEqual(legalAcquisitionCells) - expect(observedPhysicalInteractions).toEqual(requiredPhysicalInteractions) + expect(observedAcquisitionInteractions).toEqual( + requiredAcquisitionInteractions, + ) expect(observedSyncRunBoundaries).toEqual(requiredSyncRunBoundaries) expect(observedFailureDeliverySuffixes).toEqual( requiredFailureDeliverySuffixes, @@ -1155,7 +1176,7 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { ? `starting:cleanup` : undefined if (interaction) { - observePhysicalInteraction( + observeAcquisitionInteraction( interaction, reentry === `abort-self` ? `abort-only` : `retire`, ) @@ -1510,9 +1531,9 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { } catch (error) { thrown = error } - observePhysicalInteraction(`active:release`, `retire`) + observeAcquisitionInteraction(`active:release`, `retire`) if (reentry === `unsubscribe`) { - observePhysicalInteraction(`active:unsubscribe`, `retire`) + observeAcquisitionInteraction(`active:unsubscribe`, `retire`) } expect(thrown).toBe(outcome === `throw` ? releaseFailure : undefined) @@ -1545,7 +1566,7 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { ).toHaveLength(Number(reentry === `reacquire-self`)) expect(unloads.filter((options) => options === peerLoad)).toHaveLength(1) if (outcome === `throw` && reentry === `unsubscribe`) { - observePhysicalInteraction( + observeAcquisitionInteraction( `failed-release:unsubscribe`, `no-repeat-on-unsubscribe`, ) @@ -2178,7 +2199,7 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { subscription.requestSnapshot() reach(`eager:request`) subscription.unsubscribe() - observePhysicalInteraction(`none:unsubscribe`, `no-acquisition`) + observeAcquisitionInteraction(`none:unsubscribe`, `no-acquisition`) expect(loads).toBe(0) expect(unloads).toBe(0) @@ -2215,7 +2236,7 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { subscription.requestSnapshot({ where }) subscription.releaseSnapshot(where) - observePhysicalInteraction(`none:release`, `no-acquisition`) + observeAcquisitionInteraction(`none:release`, `no-acquisition`) expect(loads).toBe(0) expect(unloads).toBe(0) @@ -2260,7 +2281,7 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { truncate() commit() await flushPromises() - observePhysicalInteraction(`none:truncate`, `no-acquisition`) + observeAcquisitionInteraction(`none:truncate`, `no-acquisition`) expect.soft(loads).toEqual([]) expect.soft(unloads).toEqual([]) @@ -2305,7 +2326,7 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { await flushPromises() reach(`on-demand:request`) subscription.unsubscribe() - observePhysicalInteraction(`none:unsubscribe`, `no-acquisition`) + observeAcquisitionInteraction(`none:unsubscribe`, `no-acquisition`) expect(loads).toBe(0) expect(unloads).toBe(0) @@ -2349,7 +2370,7 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { }) await flushPromises() subscription.releaseSnapshot(where) - observePhysicalInteraction(`none:release`, `no-acquisition`) + observeAcquisitionInteraction(`none:release`, `no-acquisition`) expect(loads).toBe(0) expect(unloads).toBe(0) @@ -2447,7 +2468,7 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { subscription.requestSnapshot({ where, signal: controller.signal }) controller.abort() await flushPromises() - observePhysicalInteraction(`none:abort`, `no-acquisition`) + observeAcquisitionInteraction(`none:abort`, `no-acquisition`) expect(loads).toEqual([]) expect(unloads).toEqual([]) @@ -2485,7 +2506,7 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { const acquisition = loads[0]! controller.abort() await flushPromises() - observePhysicalInteraction(`active:abort`, `abort-only`) + observeAcquisitionInteraction(`active:abort`, `abort-only`) expect(loads).toEqual([acquisition]) expect(acquisition.signal?.aborted).toBe(true) @@ -2638,7 +2659,7 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { else collection._resumeSyncStart() await flushPromises() if (action === `cleanup`) { - observePhysicalInteraction(`none:cleanup`, `no-acquisition`) + observeAcquisitionInteraction(`none:cleanup`, `no-acquisition`) } expect(loads).toBe(action === `resume` ? 1 : 0) @@ -3496,7 +3517,10 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { await collection.cleanup() expect(unloads).toBe(1) expect(sourceCleanups).toBe(1) - observePhysicalInteraction(`failed-release:cleanup`, `no-repeat-on-cleanup`) + observeAcquisitionInteraction( + `failed-release:cleanup`, + `no-repeat-on-cleanup`, + ) subscription.unsubscribe() }) @@ -3687,7 +3711,7 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { subscription.unsubscribe() expect(unloads).toBe(1) - observePhysicalInteraction( + observeAcquisitionInteraction( `failed-release:truncate`, `no-repeat-on-truncate`, ) @@ -3811,7 +3835,7 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { await collection.cleanup() expect(sourceCleanups).toEqual([0]) - observePhysicalInteraction(`active:cleanup`, `retire`) + observeAcquisitionInteraction(`active:cleanup`, `retire`) collection.startSyncImmediate() observeSyncRunBoundary(`restart-installed`) await flushPromises() @@ -4241,7 +4265,7 @@ describe(`CollectionSubscription demand lifecycle oracle`, () => { begin() truncate() commit() - observePhysicalInteraction(`active:truncate`, `retire`) + observeAcquisitionInteraction(`active:truncate`, `retire`) expect(loads).toHaveLength(1) expect(subscription.status).toBe(`loadingSubset`) diff --git a/packages/db/tests/collection-subscription-lifecycle-publication.property.test.ts b/packages/db/tests/collection-subscription-lifecycle-publication-oracle.property.test.ts similarity index 99% rename from packages/db/tests/collection-subscription-lifecycle-publication.property.test.ts rename to packages/db/tests/collection-subscription-lifecycle-publication-oracle.property.test.ts index ad94f0057f..a715c4d1d8 100644 --- a/packages/db/tests/collection-subscription-lifecycle-publication.property.test.ts +++ b/packages/db/tests/collection-subscription-lifecycle-publication-oracle.property.test.ts @@ -10,7 +10,7 @@ import { greenLifecycleHistories, greenLifecycleHistoryArbitrary, reduceLifecycle, -} from './collection-subscription-lifecycle-grammar.js' +} from './collection-subscription-lifecycle-grammar-oracle.js' import { oracleRandomParameters, readOracleRunConfig } from './oracle-config.js' import { flushPromises } from './utils.js' import type { SyncConfig } from '../src/types.js' @@ -21,15 +21,17 @@ import type { LifecycleCommand, LifecycleEffect, LifecycleModel, -} from './collection-subscription-lifecycle-grammar.js' +} from './collection-subscription-lifecycle-grammar-oracle.js' /** * # Which lifecycle work may become public rows? * * The lifecycle grammar decides which acquisition attempt is current. This * file adds the row-publication node. A truncate opens a private replacement; - * source writes accumulate there until every gating attempt succeeds. Failure - * retires that replacement. Independent live source work remains public. + * source writes accumulate there until every gating attempt succeeds. Replay + * failure keeps the replacement and later source changes private while the + * last public snapshot remains visible. Retiring the final logical subset + * owner can retire that replacement barrier without publishing its rows. * The `Collection.subscribeChanges` API contract in `../src/collection/index.ts` * is the authority for callback batches and their per-key causal order. The * public Collection lifecycle and shared lifecycle grammar specify cleanup, diff --git a/packages/db/tests/collection-subscription-reentrancy-oracle.test.ts b/packages/db/tests/collection-subscription-reentrancy-oracle.test.ts index b5a834ba6d..1b01c39e1f 100644 --- a/packages/db/tests/collection-subscription-reentrancy-oracle.test.ts +++ b/packages/db/tests/collection-subscription-reentrancy-oracle.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it, vi } from 'vitest' import { createCollection } from '../src/collection/index.js' import { createDeferred } from '../src/deferred.js' import { Func, PropRef, Value } from '../src/query/ir.js' -import { reentrantSnapshotHistories } from './collection-subscription-lifecycle-grammar.js' +import { reentrantSnapshotHistories } from './collection-subscription-lifecycle-grammar-oracle.js' import type { LoadSubsetOptions, SyncConfig } from '../src/types.js' /** diff --git a/packages/db/tests/collection-sync-reentrancy.test.ts b/packages/db/tests/collection-sync-reentrancy-oracle.test.ts similarity index 100% rename from packages/db/tests/collection-sync-reentrancy.test.ts rename to packages/db/tests/collection-sync-reentrancy-oracle.test.ts diff --git a/packages/db/tests/comparison.property.test.ts b/packages/db/tests/comparison-oracle.property.test.ts similarity index 99% rename from packages/db/tests/comparison.property.test.ts rename to packages/db/tests/comparison-oracle.property.test.ts index 9dc48268da..55ad28c4d2 100644 --- a/packages/db/tests/comparison.property.test.ts +++ b/packages/db/tests/comparison-oracle.property.test.ts @@ -60,7 +60,7 @@ const nullsLastOpts: CompareOptions = { // new values. Set all three variables to replay one property directly, for // example COMPARISON_ORACLE_PROPERTY=1 COMPARISON_ORACLE_SEED=123 // COMPARISON_ORACLE_PATH='0:0' pnpm --filter @tanstack/db exec vitest run -// --configLoader runner tests/comparison.property.test.ts. +// --configLoader runner tests/comparison-oracle.property.test.ts. const fixedSeed = 20260911 const campaignRuns = 100 const requestedProperty = process.env.COMPARISON_ORACLE_PROPERTY @@ -76,9 +76,9 @@ function failureCheckpoint(error: unknown): string { // into a throwing comparator. Unlike a matcher message, it is unchanged // when fast-check shrinks the input values. const site = error.stack?.match( - /comparison\.property\.test\.ts:(\d+):(\d+)/, + /comparison-oracle\.property\.test\.ts:(\d+):(\d+)/, ) - if (site) return `comparison.property.test.ts:${site[1]}:${site[2]}` + if (site) return `comparison-oracle.property.test.ts:${site[1]}:${site[2]}` return `${error.name}: ${error.message.split(`\n`)[0]}` } return `non-Error throw: ${String(error)}` diff --git a/packages/db/tests/conformance-infinite-calibration.test.ts b/packages/db/tests/conformance-infinite-calibration.test.ts index 9dd9117289..754a5c36bd 100644 --- a/packages/db/tests/conformance-infinite-calibration.test.ts +++ b/packages/db/tests/conformance-infinite-calibration.test.ts @@ -1,5 +1,5 @@ import { vi } from 'vitest' -import { runInfiniteQuerySuite } from './conformance/infinite-suite' +import { runInfiniteQuerySuite } from './conformance/infinite-suite-oracle' import type { InfiniteQueryDriver } from './conformance/infinite-contract' import type * as Vitest from 'vitest' diff --git a/packages/db/tests/conformance-page-laws.test.ts b/packages/db/tests/conformance-page-laws.test.ts index 27904bfc0d..f373941fef 100644 --- a/packages/db/tests/conformance-page-laws.test.ts +++ b/packages/db/tests/conformance-page-laws.test.ts @@ -1,6 +1,6 @@ import { expect, it } from 'vitest' import fc from 'fast-check' -import { expectPageRows } from './conformance/page-laws' +import { expectPageRows } from './conformance/page-laws-oracle' const rows = [1, 2, 3].map((id) => ({ id: `${id}`, name: `row${id}` })) diff --git a/packages/db/tests/conformance/infinite-contract.ts b/packages/db/tests/conformance/infinite-contract.ts index c304c31870..eb3c86d685 100644 --- a/packages/db/tests/conformance/infinite-contract.ts +++ b/packages/db/tests/conformance/infinite-contract.ts @@ -2,11 +2,13 @@ * Cross-adapter contract for `useLiveInfiniteQuery`. * * The model is an ordered source plus a visible prefix split into pages. A - * fetch may extend that prefix; changing the query, collection, or page shape - * creates a new demand generation. The public observation includes flattened - * rows, page boundaries and params, continuation, in-flight state, errors, and - * the backing collection. Those facts must agree; final rows alone cannot show - * a stale page ledger or a duplicate request. + * fetch may extend that prefix. Changing the query or input Collection identity + * replaces the live-query binding. Changing page shape updates the requested + * window and page labels while retaining committed page depth. The model tracks + * these input changes directly. The public observation includes flattened rows, + * page boundaries and params, continuation, in-flight state, errors, and the + * backing Collection. Those facts must agree; final rows alone cannot show a + * stale page ledger or a duplicate request. * * Drivers preserve native framework scheduling and package-realm details. * Controllable handles allow setter-to-fetch calls without an explicit driver diff --git a/packages/db/tests/conformance/infinite-on-demand.ts b/packages/db/tests/conformance/infinite-on-demand.ts index 8050b1e107..b8715081cb 100644 --- a/packages/db/tests/conformance/infinite-on-demand.ts +++ b/packages/db/tests/conformance/infinite-on-demand.ts @@ -1,4 +1,4 @@ -import { evaluateReferenceExpression } from '../reference-expression.js' +import { evaluateReferenceExpression } from '../reference-expression-oracle.js' import type { Collection, LoadSubsetOptions } from '../../src/index.js' import type { BasicExpression } from '../../src/query/ir.js' diff --git a/packages/db/tests/conformance/infinite-suite.ts b/packages/db/tests/conformance/infinite-suite-oracle.ts similarity index 99% rename from packages/db/tests/conformance/infinite-suite.ts rename to packages/db/tests/conformance/infinite-suite-oracle.ts index 773ee5e147..c65691fb0c 100644 --- a/packages/db/tests/conformance/infinite-suite.ts +++ b/packages/db/tests/conformance/infinite-suite-oracle.ts @@ -14,7 +14,7 @@ * history instead of test-runner housekeeping. */ import { describe, expect, it, vi } from 'vitest' -import { expectPageRows } from './page-laws' +import { expectPageRows } from './page-laws-oracle' import { ScenarioLifetime } from './scenario-lifetime' import { ScenarioSources } from './scenario-sources' import { scenarioRegistry } from './registration' @@ -30,8 +30,8 @@ interface InfiniteRow { } /** - * A settled page extends the committed prefix. A failed request leaves that - * prefix alone and keeps its error visible until explicit recovery. + * A fulfilled page fetch advances the committed prefix. A failed request leaves + * that prefix alone and keeps its error visible until explicit recovery. * Source length, not the controller's failed-window cache, decides whether the * committed prefix has a continuation, including after later source writes. */ @@ -486,7 +486,7 @@ export function runInfiniteQuerySuite(rawDriver: InfiniteQueryDriver): void { scenario( `fetch-settlement`, - `settles the driver operation with the window request`, + `fulfills the driver operation only after the window request fulfills`, async () => { const source = driver.makeSource(rows(8)) const handle = driver.mount( @@ -515,17 +515,17 @@ export function runInfiniteQuerySuite(rawDriver: InfiniteQueryDriver): void { } try { - let settled = false + let fetchFulfilled = false const fetch = trackPromise(handle.fetchNextPage()).then(() => { - settled = true + fetchFulfilled = true }) void fetch.catch(() => undefined) await waitFor(() => resolveWindow !== undefined) await Promise.resolve() - expect(settled).toBe(false) + expect(fetchFulfilled).toBe(false) resolveWindow?.() await fetch - expect(settled).toBe(true) + expect(fetchFulfilled).toBe(true) } finally { utils.setWindow = originalSetWindow } diff --git a/packages/db/tests/conformance/page-laws.ts b/packages/db/tests/conformance/page-laws-oracle.ts similarity index 100% rename from packages/db/tests/conformance/page-laws.ts rename to packages/db/tests/conformance/page-laws-oracle.ts diff --git a/packages/db/tests/cursor.property.test.ts b/packages/db/tests/cursor-oracle.property.test.ts similarity index 96% rename from packages/db/tests/cursor.property.test.ts rename to packages/db/tests/cursor-oracle.property.test.ts index 9255abbc9d..410107caaa 100644 --- a/packages/db/tests/cursor.property.test.ts +++ b/packages/db/tests/cursor-oracle.property.test.ts @@ -9,7 +9,7 @@ import { readOracleRunConfig, } from './oracle-config.js' import { withHistoryCleanup } from './optimistic-history-oracle.js' -import { evaluateReferenceExpression } from './reference-expression.js' +import { evaluateReferenceExpression } from './reference-expression-oracle.js' import type { OrderBy } from '../src/query/ir.js' /** @@ -22,10 +22,11 @@ import type { OrderBy } from '../src/query/ir.js' * direction and null placement. Production builds an expression; the driver * evaluates that expression against candidate rows and requires the same * Boolean answer. Unsupported composite cursor construction must reject rather - * than silently approximate it. A retained local-snapshot path still checks + * than silently approximate it. A read of the public snapshot still checks * multi-term nullable ordering without claiming composite cursor support. * The grammar covers finite integers, null, undefined, one to four order - * terms, and two public Collection rows at the settled local-snapshot cut. + * terms, and two public Collection rows read after collection.preload() fulfills. + * The comparison cut is the return from collection.currentStateAsChanges(). * It does not establish provider ordering, other value types, or a whole * paginated query's acquisition and publication behavior. */ @@ -118,8 +119,8 @@ function expectCursorDenotation( ) } -// Keep the nullable mixed-direction ordering law at the retained production -// snapshot boundary even though direct composite cursor construction is removed. +// Keep nullable mixed-direction ordering in the public snapshot read after +// preload fulfills, even though direct composite cursor construction is removed. async function expectLocalTupleOrder( terms: ReadonlyArray, boundary: ReadonlyArray, @@ -312,7 +313,7 @@ describe(`buildCursor properties`, () => { expectCursorDenotation([term, term], [0, 0], [1, 1]) }) - it(`orders a leading tie by a nullable trailing term at the local snapshot`, async () => { + it(`orders a leading tie by a nullable trailing term in the public snapshot after preload fulfills`, async () => { const terms: Array = [ { direction: `asc`, nulls: `last` }, { direction: `desc`, nulls: `first` }, diff --git a/packages/db/tests/cursor.test.ts b/packages/db/tests/cursor.test.ts index aff7105b27..ba0141b133 100644 --- a/packages/db/tests/cursor.test.ts +++ b/packages/db/tests/cursor.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from 'vitest' import { PropRef } from '../src/query/ir.js' import { buildCursor, canExpressCursorOrder } from '../src/utils/cursor.js' -import { evaluateReferenceExpression } from './reference-expression.js' +import { evaluateReferenceExpression } from './reference-expression-oracle.js' import type { OrderBy } from '../src/query/ir.js' function orderBy( diff --git a/packages/db/tests/index-update.property.test.ts b/packages/db/tests/index-update-oracle.property.test.ts similarity index 100% rename from packages/db/tests/index-update.property.test.ts rename to packages/db/tests/index-update-oracle.property.test.ts diff --git a/packages/db/tests/live-query-observer-history.property.test.ts b/packages/db/tests/live-query-observer-history-oracle.property.test.ts similarity index 97% rename from packages/db/tests/live-query-observer-history.property.test.ts rename to packages/db/tests/live-query-observer-history-oracle.property.test.ts index 9a5371eff2..09d2290ca1 100644 --- a/packages/db/tests/live-query-observer-history.property.test.ts +++ b/packages/db/tests/live-query-observer-history-oracle.property.test.ts @@ -56,13 +56,13 @@ type Reach = { commands: Record reactions: Record } -type DeliveryFault = +type DeliveryMutant = | `dropPeerAfterThrow` | `duplicateBootstrap` | `reentrantOutOfOrder` | `earlyPeerDelivery` type RunOptions = { - fault?: DeliveryFault + mutant?: DeliveryMutant reach?: Reach } @@ -79,7 +79,7 @@ type RunOptions = { * granular and wholesale observers. The driver compares exact listener order, * multiplicity, raw batches, reconstructed rows, bootstrap flags, and the first * surfaced error after every command. Fixed histories prove every command and - * reaction is reachable; injected faults calibrate the observations. + * reaction is reachable; observation mutants calibrate the comparisons. * * Hydration, status scheduling, resource ownership, and multi-row layout have * separate focused owners. This model stays one-row on purpose: listener @@ -345,12 +345,12 @@ function deliveryVersion(delivery: Delivery): number | undefined { return delivery.rows.find(({ key }) => key === `row`)?.version } -function injectDeliveryFault( +function applyDeliveryMutant( actual: ReadonlyArray, - fault: DeliveryFault | undefined, + mutant: DeliveryMutant | undefined, ): Array { const corrupted = [...actual] - if (fault === `dropPeerAfterThrow`) { + if (mutant === `dropPeerAfterThrow`) { const index = corrupted.findIndex( (delivery) => delivery.listener === 1 && @@ -358,10 +358,10 @@ function injectDeliveryFault( deliveryVersion(delivery) === 1, ) if (index >= 0) corrupted.splice(index, 1) - } else if (fault === `duplicateBootstrap`) { + } else if (mutant === `duplicateBootstrap`) { const index = corrupted.findIndex((delivery) => delivery.bootstrap) if (index >= 0) corrupted.splice(index, 0, corrupted[index]!) - } else if (fault === `reentrantOutOfOrder`) { + } else if (mutant === `reentrantOutOfOrder`) { const outer = corrupted.findIndex( (delivery) => delivery.listener === 1 && deliveryVersion(delivery) === 1, ) @@ -373,7 +373,7 @@ function injectDeliveryFault( corrupted[outer] = corrupted[nested]! corrupted[nested] = outerDelivery } - } else if (fault === `earlyPeerDelivery`) { + } else if (mutant === `earlyPeerDelivery`) { const outer = corrupted.findIndex( (delivery) => delivery.listener === 0 && deliveryVersion(delivery) === 1, ) @@ -563,7 +563,7 @@ async function runHistory( assertHistory( history, checkpoint, - injectDeliveryFault(actual, options.fault), + applyDeliveryMutant(actual, options.mutant), model.deliveries, ) expect(visibleRows(source.state)).toEqual( @@ -704,7 +704,7 @@ describe(`LiveQueryObserver generated histories`, () => { await runHistory(mode, history, { reach }) expect(reach.reactions.addPeer).toBe(1) await expect( - runHistory(mode, history, { fault: `earlyPeerDelivery` }), + runHistory(mode, history, { mutant: `earlyPeerDelivery` }), ).rejects.toMatchObject({ name: `AssertionError` }) }, ) @@ -772,7 +772,7 @@ describe(`LiveQueryObserver generated histories`, () => { await runHistory(mode, history) const reach = emptyReach() await expect( - runHistory(mode, history, { fault: `dropPeerAfterThrow`, reach }), + runHistory(mode, history, { mutant: `dropPeerAfterThrow`, reach }), ).rejects.toMatchObject({ name: `AssertionError` }) expect(reach.reactions.throw).toBe(1) }, @@ -792,7 +792,7 @@ describe(`LiveQueryObserver generated histories`, () => { ] await runHistory(`granular`, history) await expect( - runHistory(`granular`, history, { fault: `duplicateBootstrap` }), + runHistory(`granular`, history, { mutant: `duplicateBootstrap` }), ).rejects.toMatchObject({ name: `AssertionError` }) }) @@ -803,7 +803,7 @@ describe(`LiveQueryObserver generated histories`, () => { await runHistory(mode, history) const reach = emptyReach() await expect( - runHistory(mode, history, { fault: `reentrantOutOfOrder`, reach }), + runHistory(mode, history, { mutant: `reentrantOutOfOrder`, reach }), ).rejects.toMatchObject({ name: `AssertionError` }) expect(reach.reactions.nested).toBe(1) }, diff --git a/packages/db/tests/live-query-window-controller.test.ts b/packages/db/tests/live-query-window-controller.test.ts index 0ae0f6c6fd..cfa1a4a02c 100644 --- a/packages/db/tests/live-query-window-controller.test.ts +++ b/packages/db/tests/live-query-window-controller.test.ts @@ -9,7 +9,7 @@ import { normalizeLiveQueryWindowPageSize, } from '../src/live-query-window-controller.js' import { mockSyncCollectionOptions } from './utils.js' -import { evaluateReferenceExpression } from './reference-expression.js' +import { evaluateReferenceExpression } from './reference-expression-oracle.js' import type { Collection } from '../src/collection/index.js' interface Row { diff --git a/packages/db/tests/local-only-direct-write.test.ts b/packages/db/tests/local-only-direct-write-oracle.test.ts similarity index 100% rename from packages/db/tests/local-only-direct-write.test.ts rename to packages/db/tests/local-only-direct-write-oracle.test.ts diff --git a/packages/db/tests/notification-laws.test.ts b/packages/db/tests/notification-laws-oracle.test.ts similarity index 98% rename from packages/db/tests/notification-laws.test.ts rename to packages/db/tests/notification-laws-oracle.test.ts index f6dc95aec0..f92282e3ed 100644 --- a/packages/db/tests/notification-laws.test.ts +++ b/packages/db/tests/notification-laws-oracle.test.ts @@ -4,9 +4,9 @@ import { createCollection, createLiveQueryCollection } from '../src' import { expectNotificationHistory, expectNotificationsStopped, -} from '../../db-collection-e2e/src/utils/notification-laws' +} from '../../db-collection-e2e/src/utils/notification-laws-oracle' import { ScenarioLifetime } from './conformance/scenario-lifetime' -import type { Notification } from '../../db-collection-e2e/src/utils/notification-laws' +import type { Notification } from '../../db-collection-e2e/src/utils/notification-laws-oracle' type Row = { id: string; count: number } diff --git a/packages/db/tests/optimistic-composition.test.ts b/packages/db/tests/optimistic-composition-oracle.test.ts similarity index 100% rename from packages/db/tests/optimistic-composition.test.ts rename to packages/db/tests/optimistic-composition-oracle.test.ts diff --git a/packages/db/tests/optimistic-history-oracle.ts b/packages/db/tests/optimistic-history-oracle.ts index a63035683f..552f7b155b 100644 --- a/packages/db/tests/optimistic-history-oracle.ts +++ b/packages/db/tests/optimistic-history-oracle.ts @@ -34,9 +34,9 @@ import type { CollectionConfig, SyncConfig } from '../src/types.js' * state, and complete publication cuts. A second subscriber starts without * initial state, so no sent-key filter can hide an invalid message. Each of * its batches must be valid for its replica: an insert names an absent key, - * and an update or delete names a present one. Fault injection proves those - * observations can reject wrong keys, partial batches, stale previous values, - * and transient fields. + * and an update or delete names a present one. Wrong-answer mutants prove + * these observations reject wrong keys, partial batches, stale previous + * values, and transient fields. */ export type HistoryRow = { id: number; a: number; b: number; c: number } @@ -460,7 +460,7 @@ export async function withHistoryCleanup( export async function runOptimisticHistory( initial: Array, steps: ReadonlyArray, - fault?: + mutant?: | `wrong-key` | `transient-field` | `partial-batch` @@ -636,12 +636,12 @@ export async function runOptimisticHistory( source: sorted([...collection.values()].map(observed)), }) } - // Faults act on a copy of a real callback, never on production state. + // Observation mutants alter a copy of a real callback. if (initialPublication) { record(captured) return } - if (!injected && fault === `wrong-key` && captured.length) { + if (!injected && mutant === `wrong-key` && captured.length) { injected = true record( captured.map((change) => ({ @@ -651,7 +651,7 @@ export async function runOptimisticHistory( ) } else if ( !injected && - fault === `transient-field` && + mutant === `transient-field` && captured.length ) { injected = true @@ -664,7 +664,7 @@ export async function runOptimisticHistory( record(captured) } else if ( !injected && - fault === `partial-batch` && + mutant === `partial-batch` && captured.length > 1 ) { injected = true @@ -672,7 +672,7 @@ export async function runOptimisticHistory( record(captured) } else if ( !injected && - (fault === `previous-value` || fault === `update-as-insert`) && + (mutant === `previous-value` || mutant === `update-as-insert`) && captured.some((change) => change.type === `update`) ) { injected = true @@ -680,7 +680,7 @@ export async function runOptimisticHistory( captured.map((change) => change.type !== `update` ? change - : fault === `previous-value` + : mutant === `previous-value` ? { ...change, previousValue: { ...change.previousValue!, c: 999999 }, @@ -730,7 +730,7 @@ export async function runOptimisticHistory( rawPublications = [] if ( !injected && - fault === `backwards-cuts` && + mutant === `backwards-cuts` && settling && initialFrame && publications.length > 0 && @@ -799,7 +799,7 @@ export async function runOptimisticHistory( const expected = sorted(model.visible().values()) const actual = sorted([...collection.values()].map(observed)) if ( - fault === `retained-default` && + mutant === `retained-default` && settling && !injected && actual.length @@ -946,8 +946,8 @@ export async function runOptimisticHistory( ) } } - if (fault) - expect(injected, `fault reached an actual publication`).toBe(true) + if (mutant) + expect(injected, `observation mutant reached its checkpoint`).toBe(true) return counts }, () => [ diff --git a/packages/db/tests/optimistic-history-outcomes.test.ts b/packages/db/tests/optimistic-history-outcomes-oracle.test.ts similarity index 100% rename from packages/db/tests/optimistic-history-outcomes.test.ts rename to packages/db/tests/optimistic-history-outcomes-oracle.test.ts diff --git a/packages/db/tests/optimistic-history-publication.test.ts b/packages/db/tests/optimistic-history-publication-oracle.test.ts similarity index 100% rename from packages/db/tests/optimistic-history-publication.test.ts rename to packages/db/tests/optimistic-history-publication-oracle.test.ts diff --git a/packages/db/tests/optimistic-settlement-boundaries.test.ts b/packages/db/tests/optimistic-settlement-boundaries-oracle.test.ts similarity index 98% rename from packages/db/tests/optimistic-settlement-boundaries.test.ts rename to packages/db/tests/optimistic-settlement-boundaries-oracle.test.ts index 409c58930b..e1355f3389 100644 --- a/packages/db/tests/optimistic-settlement-boundaries.test.ts +++ b/packages/db/tests/optimistic-settlement-boundaries-oracle.test.ts @@ -22,7 +22,7 @@ const sync = ( // Every regression is a program for the same model, driver and checkpoint // assertions used by generated histories. Membership work has its own generated -// law in query/derived-delete-reconciliation.test.ts. +// law in query/derived-delete-reconciliation-oracle.test.ts. const cases: Array<{ name: string initial: Array diff --git a/packages/db/tests/oracle-replay-manifest.ts b/packages/db/tests/oracle-replay-manifest.ts index 09384a35f5..c1184689ee 100644 --- a/packages/db/tests/oracle-replay-manifest.ts +++ b/packages/db/tests/oracle-replay-manifest.ts @@ -8,11 +8,19 @@ import { registeredOracleProperties } from './oracle-config.js' * promoted to assertion evidence merely because a process exited cleanly. */ const ownerGroups: ReadonlyArray = [ - [`db/tests/cleanup-queue.property.test.ts`, `cleanup-queue`, `history`], - [`db/tests/SortedMap.test.ts`, `sorted-map`, `key ascending descending`], + [ + `db/tests/cleanup-queue-oracle.property.test.ts`, + `cleanup-queue`, + `history`, + ], + [ + `db/tests/SortedMap-oracle.test.ts`, + `sorted-map`, + `key ascending descending`, + ], [`db/tests/oracle-replay.fixture.test.ts`, `oracle-replay`, `calibration`], [ - `db-sqlite-persistence-core/tests/persisted.test.ts`, + `db-sqlite-persistence-core/tests/persisted-oracle.test.ts`, `sqlite-persistence`, `source-fifo-order abort-graph owner-isolation open-transaction-boundary`, ], @@ -22,17 +30,17 @@ const ownerGroups: ReadonlyArray = [ `mixed-transaction same-key`, ], [ - `db/tests/index-update.property.test.ts`, + `db/tests/index-update-oracle.property.test.ts`, `index-update`, `reference-model exact-identity custom-comparator`, ], [ - `db/tests/cursor.property.test.ts`, + `db/tests/cursor-oracle.property.test.ts`, `cursor`, `scalar-continuation exact-width exact-local-order partial-width partial-local-order repeat-construction`, ], [ - `db/tests/optimistic-history-outcomes.test.ts`, + `db/tests/optimistic-history-outcomes-oracle.test.ts`, `collection-state`, `optimistic-outcomes`, ], @@ -47,7 +55,7 @@ const ownerGroups: ReadonlyArray = [ `lifecycle`, ], [ - `electric-db-collection/tests/electric-descriptor-isolation.test.ts`, + `electric-db-collection/tests/electric-descriptor-isolation-oracle.test.ts`, `electric`, `persisted-tag-history bound-descriptor-history`, ], @@ -62,12 +70,12 @@ const ownerGroups: ReadonlyArray = [ `publication-stream-convergence`, ], [ - `electric-db-collection/tests/electric-sdk-delivery.property.test.ts`, + `electric-db-collection/tests/electric-sdk-delivery-oracle.property.test.ts`, `electric`, `sdk-snapshot-delivery sdk-dnf-membership`, ], [ - `db/tests/collection-sync-reentrancy.test.ts`, + `db/tests/collection-sync-reentrancy-oracle.test.ts`, `collection-sync`, `reentrant-drain`, ], @@ -87,12 +95,12 @@ const ownerGroups: ReadonlyArray = [ `metadata-only metadata-cancellation`, ], [ - `db/tests/collection-subscription-lifecycle-publication.property.test.ts`, + `db/tests/collection-subscription-lifecycle-publication-oracle.property.test.ts`, `subscription-lifecycle`, `publication-history`, ], [ - `db/tests/collection-subscription-lifecycle-history.property.test.ts`, + `db/tests/collection-subscription-lifecycle-history-oracle.property.test.ts`, `subscription-lifecycle`, `history-statistics async-history sync-history`, ], @@ -117,17 +125,17 @@ const ownerGroups: ReadonlyArray = [ `reconciliation`, ], [ - `db/tests/live-query-observer-history.property.test.ts`, + `db/tests/live-query-observer-history-oracle.property.test.ts`, `live-query-observer`, `granular-history wholesale-history`, ], [ - `db-sqlite-persistence-core/tests/sqlite-resume-snapshot.test.ts`, + `db-sqlite-persistence-core/tests/sqlite-resume-snapshot-oracle.test.ts`, `sqlite-resume`, `startup-generation`, ], [ - `db/tests/query/derived-delete-reconciliation.test.ts`, + `db/tests/query/derived-delete-reconciliation-oracle.test.ts`, `derived-publication`, `membership-work`, ], @@ -192,7 +200,7 @@ const ownerGroups: ReadonlyArray = [ `multi-order nullable-cursor pending-mutation pending-history ordered-window window-transition async-cursor`, ], [ - `db-sqlite-persistence-core/tests/persisted.test.ts`, + `db-sqlite-persistence-core/tests/persisted-oracle.test.ts`, `persistence`, `retained-demand`, ], diff --git a/packages/db/tests/oracle-replay.test.ts b/packages/db/tests/oracle-replay.test.ts index 39abfbc0a4..de172a716b 100644 --- a/packages/db/tests/oracle-replay.test.ts +++ b/packages/db/tests/oracle-replay.test.ts @@ -95,11 +95,19 @@ describe(`guarded oracle replay`, () => { }, 40_000) it.each([ - [`index-update.reference-model`, `tests/index-update.property.test.ts`, 2], - [`index-update.exact-identity`, `tests/index-update.property.test.ts`, 2], + [ + `index-update.reference-model`, + `tests/index-update-oracle.property.test.ts`, + 2, + ], + [ + `index-update.exact-identity`, + `tests/index-update-oracle.property.test.ts`, + 2, + ], [ `index-update.custom-comparator`, - `tests/index-update.property.test.ts`, + `tests/index-update-oracle.property.test.ts`, 2, ], [ @@ -128,17 +136,17 @@ describe(`guarded oracle replay`, () => { it.each([ [ `sorted-map.key`, - `tests/SortedMap.test.ts`, + `tests/SortedMap-oracle.test.ts`, `SortedMap key history.*seed undefined`, ], [ `sorted-map.ascending`, - `tests/SortedMap.test.ts`, + `tests/SortedMap-oracle.test.ts`, `SortedMap ascending history.*seed undefined`, ], [ `sorted-map.descending`, - `tests/SortedMap.test.ts`, + `tests/SortedMap-oracle.test.ts`, `SortedMap descending history.*seed undefined`, ], [ diff --git a/packages/db/tests/proxy-detachment-contract.test.ts b/packages/db/tests/proxy-detachment-contract-oracle.test.ts similarity index 99% rename from packages/db/tests/proxy-detachment-contract.test.ts rename to packages/db/tests/proxy-detachment-contract-oracle.test.ts index cece3ee639..52030d1923 100644 --- a/packages/db/tests/proxy-detachment-contract.test.ts +++ b/packages/db/tests/proxy-detachment-contract-oracle.test.ts @@ -746,7 +746,7 @@ describe(`Mutation result detachment`, () => { expect(row.child.name).toBe(`before`) }) - it(`publishes a changed sibling alias even when it has a nested row back-reference`, () => { + it(`includes a changed sibling alias in detached changes even when it has a nested row back-reference`, () => { type Child = { name: string; back?: Row } type Row = { child: Child; alias: Child } const child: Child = { name: `before` } diff --git a/packages/db/tests/proxy-iteration-contract.test.ts b/packages/db/tests/proxy-iteration-contract-oracle.test.ts similarity index 97% rename from packages/db/tests/proxy-iteration-contract.test.ts rename to packages/db/tests/proxy-iteration-contract-oracle.test.ts index a8cf2f1cfc..dd2eb31995 100644 --- a/packages/db/tests/proxy-iteration-contract.test.ts +++ b/packages/db/tests/proxy-iteration-contract-oracle.test.ts @@ -12,7 +12,8 @@ import { * Iterators and `forEach` see membership changes made before an entry is * consumed. They visit each entry once, use the draft collection as the * callback receiver, and report no change for reads alone. New caller-owned - * members remain shared during the callback, then detach at publication. + * members remain shared during the callback, then detach in the returned + * change set. * Existing members reuse one draft identity across values, entries, iterator, * and `forEach` paths. * @@ -77,7 +78,7 @@ describe.each([`Map`, `Set`] as const)(`%s draft iteration`, (kind) => { type Item = { x: number } -function expectPublishedMembers( +function expectMembers( actual: Map | Set, expected: Map | Set, ): void { @@ -93,11 +94,11 @@ it.each([`Map`, `Set`] as const)( const expected = kind === `Map` ? new Map([[`item`, { x: 2 }]]) : new Set([{ x: 2 }]) const empty = kind === `Map` ? new Map() : new Set() - expect(() => expectPublishedMembers(empty, expected)).toThrow() - expectPublishedMembers(expected, expected) + expect(() => expectMembers(empty, expected)).toThrow() + expectMembers(expected, expected) if (kind === `Map`) { expect(() => - expectPublishedMembers(new Map([[`wrong`, { x: 2 }]]), expected), + expectMembers(new Map([[`wrong`, { x: 2 }]]), expected), ).toThrow() } }, @@ -149,7 +150,7 @@ describe(`Array draft iteration`, () => { describe.each(iterations)(`%s`, (_name, iterate) => { it.each(edits)( - `visits and publishes what a native array does after %s`, + `matches native visits and detached changes after %s`, (_edit, edit) => { const native = make() const expectedVisits = run(native.items, iterate, edit) @@ -295,7 +296,7 @@ describe(`Whole-draft identity boundary`, () => { [false, true].map((throughAlias) => ({ kind, throughAlias })), ), )( - `publishes both aliases for $kind, throughAlias=$throughAlias`, + `includes both aliases in detached changes for $kind, throughAlias=$throughAlias`, ({ kind, throughAlias }) => { const item = { x: 1 } const alias = @@ -366,7 +367,7 @@ describe.each([`Map`, `Set`] as const)(`%s nested iteration laws`, (kind) => { } }) expect(item.x).toBe(1) - expectPublishedMembers( + expectMembers( changes.values as typeof values, kind === `Map` ? new Map([ @@ -500,7 +501,7 @@ describe.each([`Map`, `Set`] as const)(`%s nested iteration laws`, (kind) => { }) expect(item.x).toBe(2) item.x = 3 - expectPublishedMembers( + expectMembers( changes.values as typeof values, kind === `Map` ? new Map([ @@ -618,13 +619,13 @@ it.each( value.x = 2 }) }) - expectPublishedMembers( + expectMembers( tx.mutations[0]!.changes.values as ReturnType, expected, ) - expectPublishedMembers(collection.get(1)!.values, expected) + expectMembers(collection.get(1)!.values, expected) await tx.isPersisted.promise - expectPublishedMembers(collection.get(1)!.values, expected) + expectMembers(collection.get(1)!.values, expected) } finally { await collection.cleanup() } diff --git a/packages/db/tests/proxy-native-methods.property.test.ts b/packages/db/tests/proxy-native-methods-oracle.property.test.ts similarity index 93% rename from packages/db/tests/proxy-native-methods.property.test.ts rename to packages/db/tests/proxy-native-methods-oracle.property.test.ts index 40c4e3a6e3..07bd328fe0 100644 --- a/packages/db/tests/proxy-native-methods.property.test.ts +++ b/packages/db/tests/proxy-native-methods-oracle.property.test.ts @@ -8,8 +8,8 @@ import { withChangeTracking } from '../src/proxy' * Contract: a draft behaves like the native value it represents. Every * built-in method called on a draft array or typed array gives the native * result, returns the draft where the native method returns the array itself, - * hands out drafts of the row's objects, and publishes what the native row - * now holds. + * hands out drafts of the row's objects, and reports changes that reconstruct + * the native row's final value. * * Model: the same call on a native row of equal data. The expected result * never reads a draft or production code. @@ -23,17 +23,18 @@ import { withChangeTracking } from '../src/proxy' * * Driver: `withChangeTracking` runs the same call on a draft of an equal row. * - * Check, at the end of the callback: the call's result or the class of the - * error it threw, whether it returned + * Check, after the callback returns and its changes are detached: the call's + * result or the class of the error it threw, whether it returned * the array itself, the row index of each original object in the result, and - * the published row after the optional write. + * the detached field value after the optional write. * * Authority: the draft contract in `src/proxy.ts` and the native-differential - * laws in `tests/proxy.test.ts`. + * laws in `tests/proxy-oracle.test.ts`. * * Limits: - * - A mutator that changes nothing may publish an equal value. Mutators mark - * a change without a revert check (see the revert oracle's limits). + * - A mutator that changes nothing may report an equal value in its change + * set. Mutators mark a change without a revert check (see the revert oracle's + * limits). * - An object the callback inserts reads back as a draft, not as itself, so * identity is checked only for objects of the original row. * - Callback arguments are fixed per method. The callbacks read only. @@ -201,7 +202,7 @@ function observeArray(row: ArrayRow, method: string, k: number) { return { snapshot, returnsSelf, identity } } -// Holes count: a draft must publish a hole where the native row has one. +// Holes count: a detached array must preserve the native array's holes. const encodeArray = (items: Array) => JSON.stringify({ items, present: items.map((_, i) => i in items) }) @@ -220,11 +221,11 @@ function expectArrayCall( expect(actual, `result, ${context}`).toEqual(expected) const changed = encodeArray(native.items) !== encodeArray(realizeArray(spec).items) - const published = (changes as Partial).items - if (changed || published !== undefined) + const detachedItems = (changes as Partial).items + if (changed || detachedItems !== undefined) expect( - published && encodeArray(published), - `published row, ${context}`, + detachedItems && encodeArray(detachedItems), + `detached items, ${context}`, ).toBe(encodeArray(native.items)) if (!changed && !MUTATORS.has(method)) expect(changes, `no change, ${context}`).toEqual({}) @@ -383,11 +384,11 @@ function expectTypedCall( expect(actual, `result, ${context}`).toEqual(expected) // -0 differs from 0 here: a typed array stores the sign. const changed = native.t.some((v, i) => !Object.is(v, values[i])) - const published = (changes as Partial).t - if (changed || published !== undefined) + const detachedArray = (changes as Partial).t + if (changed || detachedArray !== undefined) expect( - published && encodeTyped(published), - `published row, ${context}`, + detachedArray && encodeTyped(detachedArray), + `detached typed array, ${context}`, ).toEqual(encodeTyped(native.t)) if (!changed && !TYPED_MUTATORS.has(method)) expect(changes, `no change, ${context}`).toEqual({}) diff --git a/packages/db/tests/proxy.test.ts b/packages/db/tests/proxy-oracle.test.ts similarity index 100% rename from packages/db/tests/proxy.test.ts rename to packages/db/tests/proxy-oracle.test.ts diff --git a/packages/db/tests/proxy-revert-oracle.property.test.ts b/packages/db/tests/proxy-revert-oracle.property.test.ts index 87d209f5ce..0b4fb94cb3 100644 --- a/packages/db/tests/proxy-revert-oracle.property.test.ts +++ b/packages/db/tests/proxy-revert-oracle.property.test.ts @@ -30,8 +30,8 @@ import { createChangeProxy } from '../src/proxy' * instances as plain objects. A class instance without enumerable keys * (here, one with only a private field) equals only itself. * - * Laws checked at one checkpoint: after the last write of a history, before - * the draft publishes. The driver writes through `createChangeProxy`'s draft + * Laws checked at one checkpoint: after the last write of a history. + * The driver writes through `createChangeProxy`'s draft * (its `set`, `deleteProperty`, and `get` traps, and the array iterator), and * the check reads `getChanges()` and the draft. * @@ -41,7 +41,7 @@ import { createChangeProxy } from '../src/proxy' * * Authority: rules 1 to 6 and the laws come from the `createChangeProxy` and * `getChanges` implementation comments in `src/proxy.ts` and the revert - * examples in `tests/proxy.test.ts`, as of `18abceee`. Rules 7 to 9 are design + * examples in `tests/proxy-oracle.test.ts`, as of `18abceee`. Rules 7 to 9 are design * decisions recorded in * `docs/contributing/oracle-reviews/code-weight-draft-proxy.md`. * @@ -49,7 +49,7 @@ import { createChangeProxy } from '../src/proxy' * - Writes are assignments, deletes, nested property writes, and nested writes * through `for...of` on an array. Map, Set, and array mutator methods * (`set`, `add`, `push`) mark a value changed without a revert check; the - * native-operation tests in `proxy.test.ts` own them. + * native-operation tests in `proxy-oracle.test.ts` own them. * - Top-level symbol keys are not written. `getChanges()` does not report * them; the coverage map lists symbol writes as unsupported. Symbol keys * inside nested objects are written. diff --git a/packages/db/tests/query/cold-join-reconciliation-oracle.test.ts b/packages/db/tests/query/cold-join-reconciliation-oracle.test.ts index e4e07cf7f6..efc652cc3f 100644 --- a/packages/db/tests/query/cold-join-reconciliation-oracle.test.ts +++ b/packages/db/tests/query/cold-join-reconciliation-oracle.test.ts @@ -31,8 +31,8 @@ import type { * reference joins matching keys from scratch after each command. The production * driver starts with a cold child Collection and observes the actual acquisition, * raw batches, reconstructed replica, and live rows across scan and indexed - * paths. Faults prove a hidden acquisition, dropped delete, or wrong result is - * detected independently. + * paths. Observation mutants prove that a hidden acquisition, dropped delete, + * or wrong result is detected independently. * * The Identity and Initial demand sections of live/ARCHITECTURE.md authorize * the equality and acquisition laws. The test-only replica folds public change @@ -46,7 +46,7 @@ type Parent = { id: number; name: string } type Child = { id: number; parentId: number; amount: number } type Joined = { id: number; parentId: number; name: string; amount: number } type Step = { type: `delete`; id: number } | { type: `put`; row: Child } -type Fault = `hide-acquisition` | `drop-delete` | `wrong-result` +type ObservationMutant = `hide-acquisition` | `drop-delete` | `wrong-result` const parents: ReadonlyArray = [ { id: 1, name: `Ada` }, @@ -66,7 +66,10 @@ const plain = ({ id, parentId, name, amount }: Joined): Joined => ({ const ordered = (rows: Iterable) => [...rows].map(plain).sort((a, b) => a.id - b.id) -async function runColdJoin(steps: ReadonlyArray, fault?: Fault) { +async function runColdJoin( + steps: ReadonlyArray, + mutant?: ObservationMutant, +) { const model = new Map(initial.map((row) => [row.id, { ...row }])) const backend = new Map(initial.map((row) => [row.id, { ...row }])) const installed = new Set() @@ -165,7 +168,7 @@ async function runColdJoin(steps: ReadonlyArray, fault?: Fault) { batches.push(captured) for (const change of captured) { if (change.type === `delete`) { - if (fault !== `drop-delete`) replica.delete(change.key) + if (mutant !== `drop-delete`) replica.delete(change.key) } else replica.set(change.key, change.value) } }, @@ -212,11 +215,11 @@ async function runColdJoin(steps: ReadonlyArray, fault?: Fault) { projection: { observe: () => { const rows = ordered(live.values()) - if (fault === `wrong-result` && rows.length) rows[0]!.amount++ + if (mutant === `wrong-result` && rows.length) rows[0]!.amount++ return { rows, replica: ordered(replica.values()), - calls: fault === `hide-acquisition` ? [] : calls, + calls: mutant === `hide-acquisition` ? [] : calls, } }, recompute: () => @@ -872,9 +875,9 @@ it.each(coldJoinSeeds)(`checks cold join histories, seed=%s`, async (seed) => { }) it.each([`hide-acquisition`, `drop-delete`, `wrong-result`] as const)( `rejects %s through the real cold join trace checker`, - async (fault) => { + async (mutant) => { await runColdJoin(history) - await expect(runColdJoin(history, fault)).rejects.toMatchObject({ + await expect(runColdJoin(history, mutant)).rejects.toMatchObject({ name: `TraceAssertionError`, cause: { name: `AssertionError` }, }) diff --git a/packages/db/tests/query/compiler/evaluators.test.ts b/packages/db/tests/query/compiler/evaluators-oracle.test.ts similarity index 100% rename from packages/db/tests/query/compiler/evaluators.test.ts rename to packages/db/tests/query/compiler/evaluators-oracle.test.ts diff --git a/packages/db/tests/query/derived-delete-reconciliation.test.ts b/packages/db/tests/query/derived-delete-reconciliation-oracle.test.ts similarity index 100% rename from packages/db/tests/query/derived-delete-reconciliation.test.ts rename to packages/db/tests/query/derived-delete-reconciliation-oracle.test.ts diff --git a/packages/db/tests/query/identity-output-shape-oracle.test.ts b/packages/db/tests/query/identity-output-shape-oracle.test.ts index cf4efdd966..621b36a9bc 100644 --- a/packages/db/tests/query/identity-output-shape-oracle.test.ts +++ b/packages/db/tests/query/identity-output-shape-oracle.test.ts @@ -37,7 +37,7 @@ import type { QueryIR } from '../../src/query/ir.js' * only when complete output bags—including lexical keys and multiplicity—match; * output-sensitive aliases remain part of identity. * - * Fault drivers remove peers, collapse identity, corrupt aliases or weights, + * Result mutants remove peers, collapse identity, corrupt aliases or weights, * and require the checker to fail. This calibrates the implication that matters: * equal QueryIdentity implies equal compiled results, not merely equal hashes. * @@ -57,7 +57,7 @@ type Form = | 'implicit-join' | 'implicit-union' | 'empty-group' -type Fault = +type ResultMutant = | 'alias' | 'missing-peer' | 'constant-identity' @@ -93,7 +93,7 @@ async function runShapes( form: Form, aliases: [string, string, string, string], label: string, - fault?: Fault, + mutant?: ResultMutant, ) { const users = createCollection({ getKey: (row) => row.id, @@ -192,7 +192,7 @@ async function runShapes( entry = { row, count: 0 } bag.push(entry) } - entry.count += fault === 'fractional-weight' ? weight * 1.25 : weight + entry.count += mutant === 'fractional-weight' ? weight * 1.25 : weight } }), ) @@ -240,7 +240,7 @@ async function runShapes( getQueryIdentity(left.query), getQueryIdentity(right.query), ] - if (fault === 'constant-identity') identities[1] = identities[0]! + if (mutant === 'constant-identity') identities[1] = identities[0]! expect( identities[0] === identities[1], 'output-sensitive identity law', @@ -269,9 +269,9 @@ async function runShapes( ) } const check = (outputs: Array>, rows: Array) => { - if (fault === 'alias') outputs[1]![0] = { wrongAlias: outputs[1]![0] } - if (fault === 'missing-peer') outputs[1]!.pop() - if (fault === 'shared-wrong-output') { + if (mutant === 'alias') outputs[1]![0] = { wrongAlias: outputs[1]![0] } + if (mutant === 'missing-peer') outputs[1]!.pop() + if (mutant === 'shared-wrong-output') { outputs[0] = [{ wrong: true }] outputs[1] = [{ wrong: true }] } @@ -329,15 +329,15 @@ describe('query identity agrees with compiled lexical output shape', () => { 'fractional-weight', ] as const)( 'rejects captured %s against independent results', - async (fault) => { - const form = fault === 'missing-peer' ? 'explicit-join' : 'implicit-join' + async (mutant) => { + const form = mutant === 'missing-peer' ? 'explicit-join' : 'implicit-join' await runShapes(form, ['user', 'post', 'account', 'article'], 'author') await expect( runShapes( form, ['user', 'post', 'account', 'article'], 'author', - fault, + mutant, ), ).rejects.toMatchObject({ name: 'AssertionError' }) }, diff --git a/packages/db/tests/query/includes-collection-oracle.property.test.ts b/packages/db/tests/query/includes-collection-oracle.property.test.ts index c6157778f8..9c135d176c 100644 --- a/packages/db/tests/query/includes-collection-oracle.property.test.ts +++ b/packages/db/tests/query/includes-collection-oracle.property.test.ts @@ -41,9 +41,9 @@ import type { SyncConfig } from '../../src/types.js' * A bare child query materializes as a public Collection facade. That facade * has lifecycle and identity rules that inline arrays do not have: * - * 1. Parents on the same active route share one facade. + * 1. Parents routed to the same active bucket share one facade. * 2. Child changes update the facade without forcing a parent value change. - * 3. Moving a parent route gives it the destination route's facade. + * 3. Moving a parent route gives it the destination bucket's facade. * 4. A held facade becomes empty and ready when its last route retires. * 5. A later active interval gets a new facade instead of retargeting the old * facade. @@ -56,7 +56,7 @@ import type { SyncConfig } from '../../src/types.js' * snapshots. * * The history grammar varies parent and child writes, route movement, shared - * routes, dormant buckets, ordering, parent-dependent filters, and joins. It + * buckets, dormant buckets, ordering, parent-dependent filters, and joins. It * also varies optimistic confirmation and rollback. A bounded exhaustive lane covers every * two-step history in the smallest relationship domain. Random histories add * longer combinations and shrink failures. @@ -66,7 +66,7 @@ import type { SyncConfig } from '../../src/types.js' * does not model acquisition ownership or publication scheduling. Callback * snapshots and change messages are separate public observations. * - * Grammar controls: the fixed route-retirement, dormant-bucket, shared-route, + * Grammar controls: the fixed route-retirement, dormant-bucket, shared-bucket, * and child-order witnesses reconstruct the key relationship histories. The * generated action lane needs both parent and child writes: removing either * loses route transitions or child-only facade changes. Its IDs (parents 0–3, diff --git a/packages/db/tests/query/includes-optimistic-oracle.property.test.ts b/packages/db/tests/query/includes-optimistic-oracle.property.test.ts index ac816febde..3b4ec10ce9 100644 --- a/packages/db/tests/query/includes-optimistic-oracle.property.test.ts +++ b/packages/db/tests/query/includes-optimistic-oracle.property.test.ts @@ -23,7 +23,8 @@ import type { LoadSubsetOptions, SyncConfig } from '../../src/types.js' /** * # How should optimistic relationship writes affect a nested result? * - * An optimistic write changes the public relationship tree before sync settles. + * An optimistic write changes the public relationship tree before its + * optimistic transaction's persistence promise settles. * The visible tree follows these laws: * * 1. A reparent moves the row to its optimistic parent route immediately. @@ -32,8 +33,8 @@ import type { LoadSubsetOptions, SyncConfig } from '../../src/types.js' * 4. Confirmation keeps the overlay until settlement, then reveals the * authoritative row without an intermediate stale route. * 5. Pending changes at different levels compose, regardless of settlement - * order. The controlled sync cannot settle two changes at one level alone, - * so the grammar rejects that unsupported harness state. + * order. The shared mutation-handler gate cannot settle two mutation + * promises at one level independently. The grammar rejects that harness state. * * The semantic model is small: three Maps hold synced child levels and pending * rows overlay them by ID. Full recomputation filters each level by its current diff --git a/packages/db/tests/query/includes-oracle-helpers.ts b/packages/db/tests/query/includes-oracle-helpers.ts index 8547a665d7..d2fd9a642b 100644 --- a/packages/db/tests/query/includes-oracle-helpers.ts +++ b/packages/db/tests/query/includes-oracle-helpers.ts @@ -4,7 +4,14 @@ import type { Collection } from '../../src/collection/index.js' /** * A controlled include source exposes only the environment operations the - * oracle grammar needs: atomic source batches and explicit startup settlement. + * oracle grammar needs: atomic source batches and explicit optimistic + * mutation-handler fulfillment or rejection. Startup synchronously publishes + * the initial rows and marks the Collection ready. + * + * The inherited `resolveSync` and `rejectSync` names fulfill or reject the + * shared mutation-handler gate. They do not settle startup, end the sync run, + * acknowledge source rows, or settle a sync transaction's applied receipt. + * * Each write snapshots the row before it enters production, so later test code * cannot mutate both the stimulus and an expected value through one reference. * Query shape, route state, and expected nested results remain in the owning diff --git a/packages/db/tests/query/includes-temporal-oracle.test.ts b/packages/db/tests/query/includes-temporal-oracle.test.ts index 011ec0f73f..8c154a1c3d 100644 --- a/packages/db/tests/query/includes-temporal-oracle.test.ts +++ b/packages/db/tests/query/includes-temporal-oracle.test.ts @@ -30,24 +30,27 @@ import type { TraceDriver, TraceProjection } from '../trace-runner.js' import type { Scheduler } from 'fast-check' /** - * # Which child demand controls readiness and publication? + * # Which child acquisitions control initial-query readiness and publication? * * Parent routes can appear, disappear, and return. Their correlated child * demand changes with them. A settled Promise does not identify current work. * The model follows logical demand incarnations and applies these laws: * - * 1. Every reachable child demand must settle before initial readiness. - * 2. Demand that is no longer reachable cannot block readiness. - * 3. An obsolete demand cannot publish rows or settle a later incarnation. - * 4. A successful load settles only after its source writes are public. + * 1. Successful current acquisitions must cover every reachable child demand + * before initial-query readiness, with their establishing sync writes applied. + * 2. Demand that is no longer reachable cannot block initial-query readiness. + * 3. An obsolete acquisition cannot publish request-scoped rows, satisfy + * current demand, or complete the current preload. + * 4. A subset-load promise fulfills only after its establishing sync writes apply. * 5. Failure belongs to the demand that failed. Retired failure cannot poison * a later demand or keep unrelated graph work private. * 6. Growth loads only uncovered keys. Churn replaces fragmented coverage only * after the complete current union applies; failure preserves prior coverage. * * No one state machine mirrors the production controller. The file uses small - * models for readiness, cancellation, scheduled completion, and progressive - * delivery. Each model records only the public facts needed for its law. + * models for initial-query readiness, cancellation, acquisition promise + * settlement, and progressive delivery. Each model records only the public + * facts needed for its law. * "Demand incarnation" is a model label for one interval of active logical * demand on a route. Reactivation starts another interval; the label does not * imply one physical acquisition or one provider transport. The fast/late @@ -57,9 +60,11 @@ import type { Scheduler } from 'fast-check' * * The production drivers use real Collections, compiled includes, applied * receipts, release callbacks, replay barriers, and source writes. They observe - * readiness, preload settlement, visible rows, request keys, release signals, - * and errors at each named boundary. The live-query architecture remains the - * contract source. + * live-query Collection readiness, preload settlement, visible rows, request + * keys, release signals, and errors at each named boundary. Observation fields + * named `ready` record `live.isReady()`; `preloadSettled` records whether the + * preload promise fulfilled or rejected. The live-query architecture remains + * the contract source. * * The fragmented-demand lanes observe requested key unions and adapter abort * signals before settlement and after success, rejection, retry, or @@ -897,7 +902,7 @@ it.each( }, ) -// Model A: initial readiness depends only on currently reachable demand. +// Model A: initial-query readiness depends only on currently reachable demand. type ReadinessObservation = { ready: boolean preloadSettled: boolean @@ -999,8 +1004,8 @@ async function expectReadinessMatches( }) } -// Model B: retiring the only route removes its child load from readiness, even -// when the physical acquisition cannot settle yet. +// Model B: retiring the only route removes its child acquisition from +// initial-query readiness, even when that acquisition's promise is pending. type DemandCancellationObservation = { ready: boolean rowCount: number @@ -1158,7 +1163,7 @@ async function expectObsoleteDemandDoesNotBlockReadiness(): Promise { }) } -async function expectObsoleteDemandCannotPublishAfterReactivation(): Promise { +async function expectObsoleteAcquisitionCannotPublishAfterReactivation(): Promise { const { collection: posts, remove, add } = createRemovablePost() const requests: Array<{ deferred: Deferred @@ -1246,11 +1251,11 @@ async function expectObsoleteDemandCannotPublishAfterReactivation(): Promise { - // The scheduler changes only completion order. Request generations decide - // whether a completion can publish. + // The scheduler changes only acquisition promise settlement order. An aborted + // acquisition cannot publish request-scoped rows for the reactivated demand. const { collection: posts, remove, add } = createRemovablePost() const requests: Array<{ outcome: Promise @@ -1355,8 +1360,8 @@ type ScheduledDemandObservation = { rows: Array<{ id: number; comments: Array<{ id: number; body: string }> }> } -// The public row is determined by whether the current demand completed. An -// obsolete completion alone cannot add its child row. +// The public row depends on whether the current acquisition's promise fulfilled. +// An obsolete acquisition's settlement alone cannot add its child row. function expectScheduledDemandObservation( observation: ScheduledDemandObservation, index: number, @@ -1751,7 +1756,7 @@ function expectContradictoryReplacementStartCrashes(): void { expect(releaseSnapshot).not.toHaveBeenCalled() } -async function expectObsoleteDemandCannotSettleReactivatedDemand(): Promise { +async function expectObsoleteAcquisitionCannotCompleteCurrentPreload(): Promise { const post = { id: 1, authorId: `selected`, title: `one` } const posts = createMutablePosts([post], { markReadyInitially: false }) const { collection: comments, requests } = createPendingComments() @@ -2286,8 +2291,9 @@ type FastPathEvent = { keys: Array } -// Model C: progressive rows can publish before demand settles. The load still -// starts inside the initial fast-path window and readiness waits for settlement. +// Model C: progressive rows can publish while the acquisition promise is pending. +// The load starts inside the initial fast-path phase; initial-query readiness +// waits for fulfillment. type ProgressiveObservation = { events: Array ready: boolean @@ -2550,13 +2556,13 @@ describe(`includes temporal oracle`, () => { }) it( - `obsolete child demand does not block readiness`, + `retired child demand does not block initial-query readiness`, expectObsoleteDemandDoesNotBlockReadiness, ) it( - `obsolete child demand cannot publish after the route is reactivated`, - expectObsoleteDemandCannotPublishAfterReactivation, + `an obsolete child acquisition cannot publish after the route is reactivated`, + expectObsoleteAcquisitionCannotPublishAfterReactivation, ) // Grammar: one route is retired and reactivated, leaving one obsolete and @@ -2571,17 +2577,15 @@ describe(`includes temporal oracle`, () => { 1_658_301, )) { campaign.test.prop([demandScheduler], campaign.options)( - `obsolete and current demand completions are generation-safe with ${campaign.label}`, - expectScheduledDemandCompletionsStayGenerationSafe, + `acquisition settlements preserve current demand with ${campaign.label}`, + expectScheduledAcquisitionsRespectCurrentDemand, ) } it.each([{ order: [1, 2] }, { order: [2, 1] }])( `observes every completion in fixed scheduler order $order`, ({ order }) => - expectScheduledDemandCompletionsStayGenerationSafe( - fc.schedulerFor(order), - ), + expectScheduledAcquisitionsRespectCurrentDemand(fc.schedulerFor(order)), ) it(`rejects an obsolete child row at the first scheduled checkpoint`, () => { @@ -2598,7 +2602,7 @@ describe(`includes temporal oracle`, () => { }) it( - `retained pending demand blocks readiness after demand expands`, + `retained demand with a pending acquisition blocks initial-query readiness after demand expands`, expectRetainedDemandBlocksReadiness, ) @@ -2622,8 +2626,8 @@ describe(`includes temporal oracle`, () => { ) it( - `obsolete demand cannot settle a reactivated demand incarnation`, - expectObsoleteDemandCannotSettleReactivatedDemand, + `an obsolete acquisition cannot complete preload for reactivated demand`, + expectObsoleteAcquisitionCannotCompleteCurrentPreload, ) it(`rejected demand enters error`, expectRejectedDemandEntersError) @@ -2699,8 +2703,8 @@ describe(`includes temporal oracle`, () => { it(`a nested progressive subset loads inside the fast-path window`, () => expectProgressiveTraceMatches(`nested`)) - // Grammar: one parent receives 2..4 distinct-key children before its held - // demand settles; a sibling stays empty. Every prefix, including zero, is a + // Grammar: one parent receives 2..4 distinct-key children while its acquisition + // promise is pending; a sibling stays empty. Every prefix, including zero, is a // public checkpoint in both inline forms. The two-child minimum reconstructs // the first partial prefix and its continuation. Removing the hold loses the // before-settlement law; removing the empty sibling loses its empty-value @@ -2716,7 +2720,7 @@ describe(`includes temporal oracle`, () => { 1_658_303, )) { campaign.test.prop([partialBodies], campaign.options)( - `publishes each partial child prefix before demand settles with ${campaign.label}`, + `publishes each partial child prefix before the acquisition promise fulfills with ${campaign.label}`, async (bodies) => { for (const form of [`array`, `materialized`] as const) { const parents = createMutablePosts([ diff --git a/packages/db/tests/query/ir-stable-identity.test.ts b/packages/db/tests/query/ir-stable-identity-oracle.test.ts similarity index 100% rename from packages/db/tests/query/ir-stable-identity.test.ts rename to packages/db/tests/query/ir-stable-identity-oracle.test.ts diff --git a/packages/db/tests/query/live-query-collection.test.ts b/packages/db/tests/query/live-query-collection.test.ts index 8728489631..320332b1a2 100644 --- a/packages/db/tests/query/live-query-collection.test.ts +++ b/packages/db/tests/query/live-query-collection.test.ts @@ -21,7 +21,7 @@ import { BTreeIndex } from '../../src/indexes/btree-index' import { createFilterFunctionFromExpression } from '../../src/collection/change-events' import { Func, PropRef, Value } from '../../src/query/ir.js' import { withHistoryCleanup } from '../optimistic-history-oracle.js' -import { evaluateReferenceExpression } from '../reference-expression.js' +import { evaluateReferenceExpression } from '../reference-expression-oracle.js' import type { BasicExpression } from '../../src/query/ir.js' import type { ChangeMessage, diff --git a/packages/db/tests/query/load-subset-oracle.property.test.ts b/packages/db/tests/query/load-subset-oracle.property.test.ts index b1c9732055..d1ce0a40c3 100644 --- a/packages/db/tests/query/load-subset-oracle.property.test.ts +++ b/packages/db/tests/query/load-subset-oracle.property.test.ts @@ -8,7 +8,7 @@ import { Func, PropRef, Value } from '../../src/query/ir.js' import { DeduplicatedLoadSubset } from '../../src/query/subset-dedupe.js' import { createTransaction } from '../../src/transactions.js' import { expectAssertionFailure } from '../expected-failure.js' -import { evaluateReferenceExpression } from '../reference-expression.js' +import { evaluateReferenceExpression } from '../reference-expression-oracle.js' import { oracleRandomParameters, readOracleRunConfig, @@ -30,8 +30,10 @@ import type { * `refetch` starts fresh work for the same request data. Requests with separate * abort signals cannot share in-flight work. * - * A separate application law says acquisition settlement is not enough. Loaded - * rows must cross the Collection publication boundary before readiness settles. + * A separate application law says provider completion is not enough. Successful + * loadSubset results wait for their establishing applied receipts. Loaded rows + * must cross the source Collection publication boundary before initial-query + * readiness. * Abort before that boundary rejects and suppresses the rows. Abort after * publication is too late and the applied rows remain visible. * @@ -77,13 +79,15 @@ type ConcurrentExactScenario = { const rankRef = new PropRef([`rank`]) const scoreRef = new PropRef([`score`]) -function requirePendingAppliedReceipt( - receipt: LoadSubsetRequestResult, +// A load result may include delivery before it awaits the establishing applied +// receipt. Only commit() returns that receipt. +function requirePendingLoadSubsetResult( + loadResult: LoadSubsetRequestResult, ): Promise { - if (receipt === true) { + if (loadResult === true) { throw new Error(`Expected an asynchronous subset load`) } - return receipt + return loadResult } const exactDemandArbitrary: fc.Arbitrary = fc @@ -469,17 +473,17 @@ async function expectPersistingLoadIsApplied( if (persisting) expect(transaction.state).toBe(`persisting`) const ready = live.toArrayWhenReady() if (persisting) { - let settled = false + let fulfilled = false void ready.then( () => { - settled = true + fulfilled = true }, () => undefined, ) await Promise.resolve() await Promise.resolve() - expect(settled).toBe(false) + expect(fulfilled).toBe(false) expect(source.get(`r1`)).toBeUndefined() expect(source.get(`r2`)).toBeUndefined() @@ -563,43 +567,43 @@ async function expectAppliedReceiptTiming( transaction.mutate(() => source.insert({ id: `local`, projectId: `p2` })) } if (gate === `parked`) expect(transaction.state).toBe(`persisting`) - const receipt = source._sync.loadSubset({}) + const loadResult = source._sync.loadSubset({}) if (gate === `free` && delivery === `synchronous`) { - expect(receipt).toBe(true) + expect(loadResult).toBe(true) expect(source.get(`remote`)).toEqual( expect.objectContaining({ id: `remote`, projectId: `p1` }), ) return } - const pending = requirePendingAppliedReceipt(receipt) - let settled = false - let visibleWhenSettled = false + const pending = requirePendingLoadSubsetResult(loadResult) + let fulfilled = false + let visibleWhenFulfilled = false void pending .then( () => { - settled = true - visibleWhenSettled = source.get(`remote`)?.id === `remote` + fulfilled = true + visibleWhenFulfilled = source.get(`remote`)?.id === `remote` }, () => undefined, ) .catch(() => undefined) - expect(settled).toBe(false) + expect(fulfilled).toBe(false) expect(source.get(`remote`)).toBeUndefined() await Promise.resolve() await Promise.resolve() if (gate === `parked`) { - expect(settled).toBe(false) + expect(fulfilled).toBe(false) expect(source.get(`remote`)).toBeUndefined() persistence.resolve() await transaction.isPersisted.promise } await pending - expect(settled).toBe(true) - expect(visibleWhenSettled).toBe(true) + expect(fulfilled).toBe(true) + expect(visibleWhenFulfilled).toBe(true) expect(source.get(`remote`)).toEqual( expect.objectContaining({ id: `remote`, projectId: `p1` }), ) @@ -608,7 +612,7 @@ async function expectAppliedReceiptTiming( throw error } finally { await runOracleCleanup( - `subset receipt follows applied publication`, + `subset load fulfillment follows application`, primaryFailure, [ { @@ -672,17 +676,17 @@ async function expectAppliedLoadDoesNotFlushEarlierParkedSync() { cleanupLive = () => live.cleanup() expect(transaction.state).toBe(`persisting`) const ready = live.toArrayWhenReady() - let settled = false + let fulfilled = false void ready.then( () => { - settled = true + fulfilled = true }, () => undefined, ) await Promise.resolve() await Promise.resolve() - expect(settled).toBe(false) + expect(fulfilled).toBe(false) expect(source.get(`unrelated`)).toBeUndefined() persistence.resolve() @@ -856,21 +860,21 @@ async function expectConcurrentStreamCommitStaysParked( }) settlement = transaction.isPersisted.promise transaction.mutate(() => source.insert({ id: `other`, projectId: `p2` })) - const load = requirePendingAppliedReceipt(source._sync.loadSubset({})) + const load = requirePendingLoadSubsetResult(source._sync.loadSubset({})) void load.catch(() => undefined) publishUnrelated() publishSubset() - let settled = false + let fulfilled = false void load.then( () => { - settled = true + fulfilled = true }, () => undefined, ) await Promise.resolve() await Promise.resolve() - expect(settled).toBe(false) + expect(fulfilled).toBe(false) expect(source.get(`unrelated`)).toBeUndefined() expect(source.get(`r1`)).toBeUndefined() if (cancelBeforePersistence) { @@ -958,15 +962,15 @@ async function expectLaterImmediateCommitSettlesAppliedSubset() { }) settlement = transaction.isPersisted.promise transaction.mutate(() => source.insert({ id: `local`, projectId: `p3` })) - const load = requirePendingAppliedReceipt(source._sync.loadSubset({})) + const load = requirePendingLoadSubsetResult(source._sync.loadSubset({})) const later = publishLater() - let loadSettled = false - let subsetVisibleWhenSettled = false + let loadFulfilled = false + let subsetVisibleWhenFulfilled = false void load .then( () => { - loadSettled = true - subsetVisibleWhenSettled = source.get(`subset`)?.id === `subset` + loadFulfilled = true + subsetVisibleWhenFulfilled = source.get(`subset`)?.id === `subset` }, () => undefined, ) @@ -974,8 +978,8 @@ async function expectLaterImmediateCommitSettlesAppliedSubset() { await later await load - expect(loadSettled).toBe(true) - expect(subsetVisibleWhenSettled).toBe(true) + expect(loadFulfilled).toBe(true) + expect(subsetVisibleWhenFulfilled).toBe(true) expect(source.get(`subset`)).toEqual( expect.objectContaining({ id: `subset` }), ) @@ -1011,7 +1015,7 @@ async function expectLaterImmediateCommitSettlesAppliedSubset() { } } -async function expectAbortedReceiptDoesNotSettleDemand( +async function expectAbortedLoadDoesNotEstablishCoverage( abortPhase: `before-commit` | `while-parked`, ) { let transportCalls = 0 @@ -1065,7 +1069,7 @@ async function expectAbortedReceiptDoesNotSettleDemand( }) settlement = transaction.isPersisted.promise transaction.mutate(() => source.insert({ id: `local`, projectId: `p2` })) - const first = requirePendingAppliedReceipt( + const first = requirePendingLoadSubsetResult( source._sync.loadSubset({ signal: controller.signal }), ) if (abortPhase === `while-parked`) { @@ -1145,7 +1149,7 @@ async function expectAbortDuringPublicationDoesNotCancelReceipt() { } }) unsubscribe = () => subscription.unsubscribe() - const load = requirePendingAppliedReceipt( + const load = requirePendingLoadSubsetResult( source._sync.loadSubset({ signal: controller.signal }), ) persistence.resolve() @@ -1299,7 +1303,7 @@ async function expectCleanupRejectsDemandOnce() { }) settlement = transaction.isPersisted.promise transaction.mutate(() => source.insert({ id: `local`, projectId: `p2` })) - const load = requirePendingAppliedReceipt(source._sync.loadSubset({})) + const load = requirePendingLoadSubsetResult(source._sync.loadSubset({})) void load.catch(() => undefined) void receipt.then( () => { @@ -1611,17 +1615,17 @@ describe(`loadSubset application and cancellation`, () => { it(`releases a pending mutation and source despite a cleanup fault`, async () => { const primary = new TraceAssertionError( 4, - new Error(`subset receipt settled before publication`), + new Error(`subset load fulfilled before application`), ) const persistence = createDeferred() const stillPending = createDeferred() const cleanupFault = new Error(`subscription release failed`) const released: Array = [] - let receiptSettled = false - let receiptSettledAtCleanup = false + let cleanupWaitFulfilled = false + let cleanupWaitFulfilledAtCleanup = false void stillPending.promise.then( () => { - receiptSettled = true + cleanupWaitFulfilled = true }, () => undefined, ) @@ -1629,7 +1633,7 @@ describe(`loadSubset application and cancellation`, () => { let failure: unknown try { await runOracleCleanup( - `subset receipt follows applied publication`, + `subset load fulfillment follows application`, { error: primary }, [ { @@ -1657,7 +1661,7 @@ describe(`loadSubset application and cancellation`, () => { } catch (error) { failure = error } finally { - receiptSettledAtCleanup = receiptSettled + cleanupWaitFulfilledAtCleanup = cleanupWaitFulfilled stillPending.resolve() } @@ -1667,7 +1671,7 @@ describe(`loadSubset application and cancellation`, () => { `subscription`, `source collection`, ]) - expect(receiptSettledAtCleanup).toBe(false) + expect(cleanupWaitFulfilledAtCleanup).toBe(false) expect(failure).toBeInstanceOf(AggregateError) const aggregate = failure as AggregateError expect(aggregate.cause).toBe(primary) @@ -1767,7 +1771,7 @@ describe(`loadSubset application and cancellation`, () => { await expectAppliedLoadDoesNotFlushEarlierParkedSync() }) - it(`settles a demand only after its rows apply`, async () => { + it(`fulfills a subset load only after its rows apply`, async () => { await expectCompletionWaitsForAppliedRows() }) @@ -1779,13 +1783,13 @@ describe(`loadSubset application and cancellation`, () => { await expectConcurrentStreamCommitStaysParked(true) }) - it(`settles a subset receipt after a later immediate commit applies it`, async () => { + it(`fulfills a subset load after a later immediate commit applies its rows`, async () => { await expectLaterImmediateCommitSettlesAppliedSubset() }) it.each([`before-commit`, `while-parked`] as const)( - `does not settle a demand when its parked receipt is aborted %s`, - expectAbortedReceiptDoesNotSettleDemand, + `establishes no subset coverage when the load is aborted %s`, + expectAbortedLoadDoesNotEstablishCoverage, ) it(`ignores an abort raised after application starts publishing`, async () => { diff --git a/packages/db/tests/query/load-subset-replay-refinement-oracle.test.ts b/packages/db/tests/query/load-subset-replay-refinement-oracle.test.ts index 6f1c06c8af..0e7ce1dcd9 100644 --- a/packages/db/tests/query/load-subset-replay-refinement-oracle.test.ts +++ b/packages/db/tests/query/load-subset-replay-refinement-oracle.test.ts @@ -7,7 +7,7 @@ import { toArray, } from '../../src/query/index.js' import { BasicIndex } from '../../src/indexes/basic-index.js' -import { evaluateReferenceExpression } from '../reference-expression.js' +import { evaluateReferenceExpression } from '../reference-expression-oracle.js' import { flushPromises } from '../utils.js' import type { ChangeMessageOrDeleteKeyMessage, @@ -593,7 +593,7 @@ describe(`loadSubset replay refinement`, () => { } }) - it(`publishes a replay replacement before its source reports ready`, async () => { + it(`publishes a truncate-replay replacement before its source subscription reports ready`, async () => { const replay = createDeferred() let loadCount = 0 let begin!: () => void diff --git a/packages/db/tests/query/ordered-default-work.test.ts b/packages/db/tests/query/ordered-default-work.test.ts index 01bb4320b4..b58996a846 100644 --- a/packages/db/tests/query/ordered-default-work.test.ts +++ b/packages/db/tests/query/ordered-default-work.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it, vi } from 'vitest' import { createCollection } from '../../src/collection/index.js' import { BTreeIndex } from '../../src/indexes/btree-index.js' import { createLiveQueryCollection } from '../../src/query/index.js' -import { evaluateReferenceExpression } from '../reference-expression.js' +import { evaluateReferenceExpression } from '../reference-expression-oracle.js' import { flushPromises } from '../utils.js' import type { LoadSubsetOptions, SyncConfig } from '../../src/types.js' diff --git a/packages/db/tests/query/ordered-demand-retirement.test.ts b/packages/db/tests/query/ordered-demand-retirement.test.ts index 3a93708f49..25ef8a9cbc 100644 --- a/packages/db/tests/query/ordered-demand-retirement.test.ts +++ b/packages/db/tests/query/ordered-demand-retirement.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest' import { createCollection } from '../../src/collection/index.js' import { BTreeIndex } from '../../src/indexes/btree-index.js' import { createLiveQueryCollection } from '../../src/query/index.js' -import { evaluateReferenceExpression } from '../reference-expression.js' +import { evaluateReferenceExpression } from '../reference-expression-oracle.js' import { flushPromises } from '../utils.js' import type { LoadSubsetOptions, SyncConfig } from '../../src/types.js' diff --git a/packages/db/tests/query/ordered-lifecycle-oracle.property.test.ts b/packages/db/tests/query/ordered-lifecycle-oracle.property.test.ts index 4725559fe9..beb4ca885d 100644 --- a/packages/db/tests/query/ordered-lifecycle-oracle.property.test.ts +++ b/packages/db/tests/query/ordered-lifecycle-oracle.property.test.ts @@ -5,7 +5,7 @@ import { createCollection } from '../../src/collection/index.js' import { createDeferred } from '../../src/deferred.js' import { BTreeIndex } from '../../src/indexes/btree-index.js' import { createLiveQueryCollection, eq } from '../../src/query/index.js' -import { evaluateReferenceExpression } from '../reference-expression.js' +import { evaluateReferenceExpression } from '../reference-expression-oracle.js' import { flushPromises } from '../utils.js' import { oracleRandomParameters, @@ -27,7 +27,7 @@ import type { LoadSubsetOptions, SyncConfig } from '../../src/types.js' * render-time contracts. * * Ordered acquisition has six independent control dimensions: acquisition - * path, delivery time, window change, acquisition outcome, sync run, and + * path, delivery time, window change, provider-response outcome, sync run, and * initial-versus-replay barrier. Their 192-cell product is small enough to * enumerate. A constrained initial-success grammar separately crosses * synchronous versus Promise settlement with indexed versus prefix loading. @@ -56,7 +56,7 @@ import type { LoadSubsetOptions, SyncConfig } from '../../src/types.js' * request. `boundary` and `full-source` retain the production names. * * Grammar controls: the 192-cell product reconstructs each path with an - * applied-before-settlement and a deferred-write witness, a retained and a + * applied-before-response and a deferred-write witness, a retained and a * restarted sync run, and an initial and a truncate-replay barrier. Removing * path loses a distinct provider request; removing delivery loses the held * applied-receipt cut; removing window loses the pending move; removing outcome @@ -86,9 +86,12 @@ type Row = { type OrderTerm = { direction: `asc` | `desc`; nulls: `first` | `last` } type AcquisitionPath = `page` | `prefix` | `boundary` | `full-source` type InitialSettlementShape = `synchronous` | `promise` +// The controlled providerResponse gate models a provider response, not the +// loadSubset result. Both delivery schedules await establishing applied receipts +// before acquisition fulfillment; only their order around this response differs. type Scenario = { acquisitionPath: AcquisitionPath - delivery: `before-settlement` | `after-success` + delivery: `before-provider-response` | `after-provider-response` window: `keep` | `widen` outcome: `resolve` | `reject` | `abort-error` syncRun: `retain` | `restart` @@ -223,7 +226,7 @@ async function observeHistory( a.id - b.id, ) .slice(0, limit) - const gate = createDeferred() + const providerResponse = createDeferred() const failure = scenario.outcome === `abort-error` ? Object.assign(new Error(`target canceled`), { name: `AbortError` }) @@ -245,7 +248,7 @@ async function observeHistory( let targetOutcome: string | undefined let target: (typeof requests)[number] | undefined let targetWrites = 0 - let appliedBeforeSettlement = false + let appliedBeforeResponse = false let replayStarted = false let repaired = false let allowTarget = scenario.barrier === `initial` @@ -331,10 +334,10 @@ async function observeHistory( if (receipt !== true) await receipt } return (async () => { - if (gated && scenario.delivery === `before-settlement`) + if (gated && scenario.delivery === `before-provider-response`) await apply() if (gated) - await gate.promise.then( + await providerResponse.promise.then( () => { targetOutcome = `resolve` }, @@ -344,7 +347,8 @@ async function observeHistory( throw error }, ) - if (!gated || scenario.delivery === `after-success`) await apply() + if (!gated || scenario.delivery === `after-provider-response`) + await apply() })() }, unloadSubset: (options) => { @@ -486,9 +490,11 @@ async function observeHistory( expect(read()).toEqual(baseline) check(`pending-window`, live.utils.getWindow(), { offset: 0, limit: 1 }) expect(publications).toEqual([]) - expect(target!.applied).toBe(scenario.delivery === `before-settlement`) - appliedBeforeSettlement = target!.applied - if (scenario.delivery === `before-settlement`) { + expect(target!.applied).toBe( + scenario.delivery === `before-provider-response`, + ) + appliedBeforeResponse = target!.applied + if (scenario.delivery === `before-provider-response`) { // A replay peer may have installed the same rows already. The provider // still completed this read; its whole selected subset must be present. expect(target!.ids.every((id) => source.has(id))).toBe(true) @@ -539,15 +545,15 @@ async function observeHistory( const prior = read() const priorStatus = live.status const priorError = live.utils.lastSubsetError - const callbacksBeforeSettlement = publications.length - if (scenario.outcome === `resolve`) gate.resolve() - else gate.reject(failure) + const callbacksBeforeResponse = publications.length + if (scenario.outcome === `resolve`) providerResponse.resolve() + else providerResponse.reject(failure) for (let turn = 0; turn < 8; turn++) await flushPromises() expect(targetOutcome).toBe(scenario.outcome) - // Deferred application happens only after a live attempt succeeds. Failure - // and old-sync-run success must not apply its rows through this provider. + // Deferred application follows provider-response fulfillment in the current + // sync run. A failed or obsolete response must not apply rows. expect(target!.applied).toBe( - scenario.delivery === `before-settlement` || + scenario.delivery === `before-provider-response` || (scenario.outcome === `resolve` && scenario.syncRun === `retain`), ) if (scenario.syncRun === `restart`) { @@ -557,7 +563,7 @@ async function observeHistory( check( `obsolete-publication`, publications.length, - callbacksBeforeSettlement, + callbacksBeforeResponse, ) const first = referenceWindow(1)[0]! const firstIndex = truth.findIndex((row) => row.id === first.id) @@ -572,7 +578,7 @@ async function observeHistory( check( `restart-callback`, publications.length, - callbacksBeforeSettlement + 1, + callbacksBeforeResponse + 1, ) } else if (scenario.outcome === `resolve`) { check(`success-preload`, preload.state, { settled: true }) @@ -700,7 +706,7 @@ async function observeHistory( await finishOracleCleanup( primaryFailure, [ - () => gate.resolve(), + () => providerResponse.resolve(), () => subscription.unsubscribe(), () => live.cleanup(), () => source.cleanup(), @@ -745,7 +751,9 @@ async function observeHistory( ).length, coordinates: [ acquisitionPath, - appliedBeforeSettlement ? `before-settlement` : `after-success`, + appliedBeforeResponse + ? `before-provider-response` + : `after-provider-response`, move ? `widen` : `keep`, targetOutcome, syncRunGeneration === 2 ? `restart` : `retain`, @@ -1128,21 +1136,22 @@ describe(`synchronous initial settlement refinement`, () => { describe(`ordered lifecycle product`, () => { const observed = new Set() const cells: Array = acquisitionPaths.flatMap((acquisitionPath) => - ([`before-settlement`, `after-success`] as const).flatMap((delivery) => - ([`keep`, `widen`] as const).flatMap((window) => - ([`resolve`, `reject`, `abort-error`] as const).flatMap((outcome) => - ([`retain`, `restart`] as const).flatMap((syncRun) => - ([`initial`, `replay`] as const).map((barrier) => ({ - acquisitionPath, - delivery, - window, - outcome, - syncRun, - barrier, - })), + ([`before-provider-response`, `after-provider-response`] as const).flatMap( + (delivery) => + ([`keep`, `widen`] as const).flatMap((window) => + ([`resolve`, `reject`, `abort-error`] as const).flatMap((outcome) => + ([`retain`, `restart`] as const).flatMap((syncRun) => + ([`initial`, `replay`] as const).map((barrier) => ({ + acquisitionPath, + delivery, + window, + outcome, + syncRun, + barrier, + })), + ), ), ), - ), ), ) it(`keeps all 192 declared histories distinct`, () => { @@ -1162,8 +1171,8 @@ describe(`ordered lifecycle product`, () => { const arbitrary = fc.record({ acquisitionPath: fc.constantFrom(...acquisitionPaths), delivery: fc.constantFrom( - `before-settlement` as const, - `after-success` as const, + `before-provider-response` as const, + `after-provider-response` as const, ), window: fc.constantFrom(`keep` as const, `widen` as const), outcome: fc.constantFrom( @@ -1423,7 +1432,7 @@ describe(`nullable multi-term lifecycle product`, () => { acquisitionPath === `boundary` && primaryNulls === `first` ? `full-source` : acquisitionPath, - delivery: `before-settlement`, + delivery: `before-provider-response`, window: `widen`, outcome: mode === `repair` ? `reject` : `resolve`, syncRun: mode === `restart` ? `restart` : `retain`, diff --git a/packages/db/tests/query/ordered-source-loader.test.ts b/packages/db/tests/query/ordered-source-loader-oracle.test.ts similarity index 100% rename from packages/db/tests/query/ordered-source-loader.test.ts rename to packages/db/tests/query/ordered-source-loader-oracle.test.ts diff --git a/packages/db/tests/query/ordered-source-loader-state.test.ts b/packages/db/tests/query/ordered-source-loader-state-oracle.test.ts similarity index 99% rename from packages/db/tests/query/ordered-source-loader-state.test.ts rename to packages/db/tests/query/ordered-source-loader-state-oracle.test.ts index 12c1e66952..2cc5563250 100644 --- a/packages/db/tests/query/ordered-source-loader-state.test.ts +++ b/packages/db/tests/query/ordered-source-loader-state-oracle.test.ts @@ -4,7 +4,7 @@ import { BTreeIndex } from '../../src/indexes/btree-index.js' import { createLiveQueryCollection } from '../../src/query/index.js' import { OrderedSourceLoader } from '../../src/query/live/ordered-source-loader.js' import { PropRef } from '../../src/query/ir.js' -import { evaluateReferenceExpression } from '../reference-expression.js' +import { evaluateReferenceExpression } from '../reference-expression-oracle.js' import { flushPromises } from '../utils.js' import type { CollectionSubscription, diff --git a/packages/db/tests/query/ordered-work-oracle.property.test.ts b/packages/db/tests/query/ordered-work-oracle.property.test.ts index fb79d80f62..62829a2af3 100644 --- a/packages/db/tests/query/ordered-work-oracle.property.test.ts +++ b/packages/db/tests/query/ordered-work-oracle.property.test.ts @@ -16,7 +16,7 @@ import { oracleRandomParameters, readOracleRunConfig, } from '../oracle-config.js' -import { evaluateReferenceExpression } from '../reference-expression.js' +import { evaluateReferenceExpression } from '../reference-expression-oracle.js' import { flushPromises } from '../utils.js' import { withHistoryCleanup } from '../optimistic-history-oracle.js' import type { InitialQueryBuilder } from '../../src/query/builder/index.js' @@ -50,7 +50,8 @@ import type { LoadSubsetOptions, SyncConfig } from '../../src/types.js' * remote relation-hint evaluation, or arbitrary source scheduling. * * The value model is a plain sorted array. The work recorder captures normalized - * page and boundary requests, graph schedules, publications, and errors. + * request shapes with and without order hints, graph schedules, publications, + * and errors. * Live Collections and Effects receive the same scenario and must agree with * each other and the model. Exhaustive small domains cover ties, eligibility, * direction, and middle-row count; generated runs vary the same grammar. @@ -85,8 +86,12 @@ type Scenario = { type JoinFilter = `two-alias` | `joined-only` | `some` | `none` | `to-one` +// These recorder categories describe only the presence of adapter orderBy. +// With-order combines indexed pages and unindexed prefixes. Without-order +// combines tie-boundary requests and filtered or unfiltered full-source loads; +// it does not describe the local query order. type RequestObservation = { - kind: `page` | `boundary` + kind: `with-order` | `without-order` key: string | undefined fingerprint: string hasCursor: boolean @@ -345,9 +350,9 @@ async function observeConsumer( operations.markReady() return { loadSubset: async (options) => { - const isPage = options.orderBy !== undefined + const hasOrderHint = options.orderBy !== undefined requests.push({ - kind: isPage ? `page` : `boundary`, + kind: hasOrderHint ? `with-order` : `without-order`, key: getLoadSubsetDemandKey(options), fingerprint: requestFingerprint(options), hasCursor: options.cursor !== undefined, @@ -366,7 +371,7 @@ async function observeConsumer( ) : truth - if (!isPage) { + if (!hasOrderHint) { await apply(matching.filter((row) => !delivered.has(row.id))) return } @@ -520,7 +525,9 @@ async function observeConsumer( } if (loadingMode === `indexed`) expect( - requests.filter(({ kind: requestKind }) => requestKind === `page`), + requests.filter( + ({ kind: requestKind }) => requestKind === `with-order`, + ), ).toHaveLength(1) else if (loadingMode === `custom`) expect(requests).toHaveLength(1) else @@ -632,7 +639,7 @@ async function observeConsumer( expect( requests.every( (request) => - request.kind === `boundary` || request.limit !== undefined, + request.kind === `without-order` || request.limit !== undefined, ), ).toBe(true) @@ -3446,7 +3453,7 @@ describe(`ordered source work oracle`, () => { for (const scenario of exhaustiveScenarios) { const observed = await observeConsumer(`collection`, scenario, `none`) expect(observed.requests.length).toBeGreaterThan(0) - expect(observed.requests[0]?.kind).toBe(`page`) + expect(observed.requests[0]?.kind).toBe(`with-order`) expect(observed.requests[0]?.limit).toBeGreaterThan(0) } }) @@ -3466,7 +3473,7 @@ describe(`ordered source work oracle`, () => { // A direct LEFT-joined filter retains finite root acquisition. for (const observation of [collection, effect]) { expect(observation.requests.length).toBeGreaterThan(0) - expect(observation.requests[0]?.kind).toBe(`page`) + expect(observation.requests[0]?.kind).toBe(`with-order`) expect(observation.requests[0]?.limit).toBeGreaterThan(0) } } @@ -3500,13 +3507,14 @@ describe(`ordered source work oracle`, () => { expect(observed.rows.map(({ id }) => id)).toEqual([3]) expect(observed.errors).toEqual([]) if (loadingMode === `custom`) { + // The full-source acquisition uses the without-order request shape. expect(observed.requests).toHaveLength(1) - expect(observed.requests[0]?.kind).toBe(`boundary`) + expect(observed.requests[0]?.kind).toBe(`without-order`) expect(observed.requests[0]?.limit).toBeUndefined() expect(observed.requests[0]?.hasCursor).toBe(false) expect(observed.requests[0]?.offset).toBeUndefined() } else { - expect(observed.requests[0]?.kind).toBe(`page`) + expect(observed.requests[0]?.kind).toBe(`with-order`) expect(observed.requests.some(({ limit }) => limit === undefined)).toBe( true, ) @@ -3537,7 +3545,7 @@ describe(`ordered source work oracle`, () => { true, ) expect(observed.errors).toEqual([]) - expect(observed.requests[0]?.kind).toBe(`page`) + expect(observed.requests[0]?.kind).toBe(`with-order`) }, ) @@ -3579,7 +3587,7 @@ describe(`ordered source work oracle`, () => { expect(observed.requests.length).toBeLessThan(10) expect( observed.requests.every( - ({ kind, key }) => kind === `page` || key !== undefined, + ({ kind, key }) => kind === `with-order` || key !== undefined, ), ).toBe(true) }, @@ -3621,10 +3629,12 @@ describe(`ordered source work oracle`, () => { JSON.stringify(observation.requests), ).toBeLessThanOrEqual(2 * sourceSize) expect( - observation.requests.filter(({ kind }) => kind === `page`).length, + observation.requests.filter(({ kind }) => kind === `with-order`) + .length, ).toBeLessThanOrEqual(sourceSize) expect( - observation.requests.filter(({ kind }) => kind === `boundary`).length, + observation.requests.filter(({ kind }) => kind === `without-order`) + .length, ).toBeLessThanOrEqual(sourceSize) expect( new Set(observation.requests.map(({ key }) => key)).size, diff --git a/packages/db/tests/query/pagination-oracle.property.test.ts b/packages/db/tests/query/pagination-oracle.property.test.ts index 52c09622bb..d7f51c3a6b 100644 --- a/packages/db/tests/query/pagination-oracle.property.test.ts +++ b/packages/db/tests/query/pagination-oracle.property.test.ts @@ -11,7 +11,7 @@ import { oracleRandomParameters, readOracleRunConfig, } from '../oracle-config.js' -import { evaluateReferenceExpression } from '../reference-expression.js' +import { evaluateReferenceExpression } from '../reference-expression-oracle.js' import { TraceAssertionError } from '../trace-runner.js' import { flushPromises, mockSyncCollectionOptions } from '../utils.js' import { withHistoryCleanup } from '../optimistic-history-oracle.js' @@ -158,10 +158,12 @@ type PaginationStructure = Pick< `explicitPublicKeyOrder` | `includeFilter` | `reverseInsertion` > +// responseStarted is driver bookkeeping: provider response processing has started (delivery or rejection), although the +// acquisition promise may remain pending until its writes apply. type PendingCursorLoad = { options: LoadSubsetOptions deferred: ReturnType> - settled?: boolean + responseStarted?: boolean } type PendingMutation = @@ -999,7 +1001,7 @@ async function runNullableCursorScenario( write({ type: `insert`, value: { ...row } }) } commit() - request.settled = true + request.responseStarted = true request.deferred.resolve() await flushPromises() } @@ -1987,8 +1989,8 @@ async function runPendingMutationScenario( throw new Error(`Pending mutation exceeded finite provider work bound`) } const request = pending[index]! - if (request.settled) continue - request.settled = true + if (request.responseStarted) continue + request.responseStarted = true const orderedRows = [...rows.values()].sort( (left, right) => (left.rank - right.rank) * (scenario.direction === `asc` ? 1 : -1) || @@ -2082,7 +2084,7 @@ async function runPendingMutationScenario( ) expect(pending).toHaveLength(1) if (timing === `before-response`) applyMutation() - pending[0]!.settled = true + pending[0]!.responseStarted = true pending[0]!.deferred.reject(cursorError) capture(`provider-reject-call`) if (timing === `after-response`) applyMutation() @@ -2345,7 +2347,7 @@ async function runRejectedCursorRetryAfterMutation(): Promise { ) const settle = async (request: PendingCursorLoad): Promise => { - request.settled = true + request.responseStarted = true begin() const orderedRows = referenceWindowRows([...rows.values()], `asc`, { offset: 0, @@ -2381,17 +2383,17 @@ async function runRejectedCursorRetryAfterMutation(): Promise { write({ type: `update`, value: { id: 1, rank: 3 } }) commit() - pending[0]!.settled = true + pending[0]!.responseStarted = true pending[0]!.deferred.reject(cursorError) await flushPromises() for (let index = 1; index < pending.length; index++) { - if (!pending[index]!.settled) await settle(pending[index]!) + if (!pending[index]!.responseStarted) await settle(pending[index]!) } expect(await observedFailure).toBe(cursorError) const retry = live.utils.setWindow({ offset: 0, limit: 3 }) for (let index = 1; index < pending.length; index++) { - if (!pending[index]!.settled) await settle(pending[index]!) + if (!pending[index]!.responseStarted) await settle(pending[index]!) } if (retry instanceof Promise) await retry @@ -2533,7 +2535,7 @@ async function runPendingHistoryScenario( } const settle = async (request: PendingCursorLoad): Promise => { - request.settled = true + request.responseStarted = true const orderedRows = referenceWindowRows( [...rows.values()], scenario.direction, @@ -4382,7 +4384,7 @@ describe(`pagination recomputation oracle`, () => { }) it.each([`return-only`, `write-after-cleanup`])( - `does not settle a window move after its sync run is cleaned up: %s`, + `rejects a window move when its sync run is cleaned up: %s`, async (delivery) => { const authoritativeRows: Array = [ { id: 1, rank: 0 }, diff --git a/packages/db/tests/query/pooled-live-query-gc.test.ts b/packages/db/tests/query/pooled-live-query-gc-oracle.test.ts similarity index 100% rename from packages/db/tests/query/pooled-live-query-gc.test.ts rename to packages/db/tests/query/pooled-live-query-gc-oracle.test.ts diff --git a/packages/db/tests/query/replay-failure-boundary.test.ts b/packages/db/tests/query/replay-failure-boundary.test.ts index afbebf8bb8..54926265ca 100644 --- a/packages/db/tests/query/replay-failure-boundary.test.ts +++ b/packages/db/tests/query/replay-failure-boundary.test.ts @@ -4,7 +4,7 @@ import { createDeferred } from '../../src/deferred' import { BasicIndex } from '../../src/indexes/basic-index' import { createLiveQueryCollection, eq } from '../../src/query' import { PropRef } from '../../src/query/ir' -import { evaluateReferenceExpression } from '../reference-expression' +import { evaluateReferenceExpression } from '../reference-expression-oracle' import { flushPromises } from '../utils' import type { SyncConfig } from '../../src/types' diff --git a/packages/db/tests/query/scheduler.test.ts b/packages/db/tests/query/scheduler.test.ts index f05f6c17eb..6c1881eca5 100644 --- a/packages/db/tests/query/scheduler.test.ts +++ b/packages/db/tests/query/scheduler.test.ts @@ -504,7 +504,7 @@ describe(`live query scheduler`, () => { } }) - it(`settles a dependent live query when an earlier source listener throws`, async () => { + it(`publishes dependent live-query rows before reporting an earlier source listener failure`, async () => { let begin!: () => void let write!: (message: { type: `insert`; value: User }) => void let commit!: () => void @@ -1049,7 +1049,7 @@ describe(`live query scheduler`, () => { ), ), )( - `publishes settled dependencies once: $consumer shared=$sharedSource derivedRight=$derivedRight reverse=$reverseWrites`, + `publishes both updated dependencies together: $consumer shared=$sharedSource derivedRight=$derivedRight reverse=$reverseWrites`, async ({ consumer, sharedSource, derivedRight, reverseWrites }) => { type Row = { id: number; left: string; right: string } const makeSource = (id: string) => @@ -1156,7 +1156,7 @@ describe(`live query scheduler`, () => { }, ) - it(`runs join live queries once after their parent queries settle`, async () => { + it(`runs the joined graph once after both parent graphs publish in the same scheduler context`, async () => { const collectionA = createCollection<{ id: number; value: string }>({ id: `diamond-A`, getKey: (row) => row.id, diff --git a/packages/db/tests/reference-expression.ts b/packages/db/tests/reference-expression-oracle.ts similarity index 100% rename from packages/db/tests/reference-expression.ts rename to packages/db/tests/reference-expression-oracle.ts diff --git a/packages/db/tests/replay-publication-storage.test.ts b/packages/db/tests/replay-publication-storage.test.ts index a62622c25f..ca7392f365 100644 --- a/packages/db/tests/replay-publication-storage.test.ts +++ b/packages/db/tests/replay-publication-storage.test.ts @@ -4,7 +4,7 @@ import { createDeferred } from '../src/deferred' import { BasicIndex } from '../src/indexes/basic-index' import { createLiveQueryCollection, eq } from '../src/query' import { PropRef } from '../src/query/ir' -import { evaluateReferenceExpression } from './reference-expression' +import { evaluateReferenceExpression } from './reference-expression-oracle' import { withHistoryCleanup } from './optimistic-history-oracle' import { flushPromises } from './utils' import type { Deferred } from '../src/deferred' diff --git a/packages/db/tests/utils.property.test.ts b/packages/db/tests/utils-oracle.property.test.ts similarity index 99% rename from packages/db/tests/utils.property.test.ts rename to packages/db/tests/utils-oracle.property.test.ts index 4884e8ff7c..86fe559589 100644 --- a/packages/db/tests/utils.property.test.ts +++ b/packages/db/tests/utils-oracle.property.test.ts @@ -5,7 +5,7 @@ import { deepEquals } from '../src/utils' /** * The `deepEquals` API contract in `../src/utils.ts`, reinforced by the - * established examples in `utils.test.ts`, promises structural equality for + * established examples in `utils.test.ts`, promises change-event equality for * its supported value classes. This oracle checks bounded equality and * inequality laws for those classes, not general graph isomorphism. * @@ -22,7 +22,7 @@ import { deepEquals } from '../src/utils' // Every generated law below uses the same property in a fixed and a fresh // campaign. Set UTILS_ORACLE_PROPERTY to the numbered test label and provide // UTILS_ORACLE_SEED and UTILS_ORACLE_PATH to replay its fast-check shrink -// directly, for example with `vitest run tests/utils.property.test.ts`. +// directly, for example with `vitest run tests/utils-oracle.property.test.ts`. const fixedSeed = 20260911 const campaignRuns = 100 const requestedProperty = process.env.UTILS_ORACLE_PROPERTY @@ -778,7 +778,7 @@ describe(`deepEquals property-based tests`, () => { }) }) - describe(`structural equality`, () => { + describe(`change-event equality`, () => { it(`treats copied NaN values and invalid Dates as equal`, () => { expect(deepEquals({ rank: NaN }, { rank: NaN })).toBe(true) expect(deepEquals(new Date(NaN), new Date(NaN))).toBe(true) diff --git a/packages/db/tests/utils.ts b/packages/db/tests/utils.ts index a3e7c0b5ac..fec9745811 100644 --- a/packages/db/tests/utils.ts +++ b/packages/db/tests/utils.ts @@ -302,6 +302,14 @@ type MockSyncCollectionConfig> = { defaultIndexType?: IndexConstructor } +/** + * Both mock sync helpers retain legacy mutation-gate names: `resolveSync` + * fulfills the shared promise awaited by the optimistic mutation handlers, + * and `rejectSync` rejects it. `awaitSync` and the `syncPending*` locals own + * that gate. They do not end a sync run, acknowledge source rows, or settle a + * sync transaction's applied receipt. Source writes and Collection readiness + * use the separate sync callbacks. + */ type MockSyncCollectionUtils = { begin: () => void write: Parameters[`sync`]>[0][`write`] @@ -414,6 +422,7 @@ type MockSyncCollectionConfigNoInitialState = { defaultIndexType?: IndexConstructor } +/** Uses the same legacy mutation-gate mapping as MockSyncCollectionUtils. */ export function mockSyncCollectionOptionsNoInitialState< T extends object = Record, >(config: MockSyncCollectionConfigNoInitialState) { diff --git a/packages/db/vitest.dist.config.ts b/packages/db/vitest.dist.config.ts index b9c0b8e427..9aa26e144a 100644 --- a/packages/db/vitest.dist.config.ts +++ b/packages/db/vitest.dist.config.ts @@ -66,7 +66,7 @@ export default defineConfig({ // do not read private members directly, which would test the rename map // instead of behavior. About 9 seconds in total. include: [ - `query/ordered-source-loader-state.test.ts`, + `query/ordered-source-loader-state-oracle.test.ts`, `live-query-observer.test.ts`, `query/includes-publication-oracle.test.ts`, `query/bucket-facade-adapter.test.ts`, diff --git a/packages/electric-db-collection/e2e/sql-predicate-semantics.e2e.test.ts b/packages/electric-db-collection/e2e/sql-predicate-semantics-oracle.e2e.test.ts similarity index 100% rename from packages/electric-db-collection/e2e/sql-predicate-semantics.e2e.test.ts rename to packages/electric-db-collection/e2e/sql-predicate-semantics-oracle.e2e.test.ts diff --git a/packages/electric-db-collection/package.json b/packages/electric-db-collection/package.json index 52667e5afa..0e59ea8d59 100644 --- a/packages/electric-db-collection/package.json +++ b/packages/electric-db-collection/package.json @@ -21,7 +21,7 @@ "dev": "vite build --watch", "lint": "eslint . --fix", "test": "vitest run", - "test:oracles": "vitest run tests/pg-serializer.property.test.ts tests/electric-oracle.property.test.ts tests/electric-recovery-oracle.test.ts tests/electric-descriptor-isolation.test.ts tests/electric-sdk-framing.test.ts tests/electric-sdk-delivery.property.test.ts tests/electric-oracle-lifecycle.test.ts", + "test:oracles": "vitest run tests/pg-serializer-oracle.property.test.ts tests/electric-oracle.property.test.ts tests/electric-recovery-oracle.test.ts tests/electric-descriptor-isolation-oracle.test.ts tests/electric-sdk-framing.test.ts tests/electric-sdk-delivery-oracle.property.test.ts tests/electric-oracle-lifecycle.test.ts", "test:e2e": "vitest run --config vitest.e2e.config.ts" }, "type": "module", diff --git a/packages/electric-db-collection/tests/ORACLE_MUTATIONS.md b/packages/electric-db-collection/tests/ORACLE_MUTATIONS.md index 4572673868..b26531de3f 100644 --- a/packages/electric-db-collection/tests/ORACLE_MUTATIONS.md +++ b/packages/electric-db-collection/tests/ORACLE_MUTATIONS.md @@ -23,7 +23,7 @@ reset/cleanup. In `src/electric.ts`, remove the active-lifecycle term from either `processMessages` lifecycle guard. -Killed by: `settles every startup, hydration, snapshot availability, commit, and cleanup permutation` and `keeps stream cleanup and stale callbacks scoped to their lifecycle`. +Killed by: `settles every startup, hydration, snapshot availability, persistence-apply release, and cleanup permutation` and `keeps stream cleanup and stale callbacks scoped to their lifecycle`. ## 3. Acknowledgement liveness @@ -114,10 +114,10 @@ checks retained rows, error state, and reset metadata together. ## 11. Tag ownership across collection reuse and restart -Share one tag tracker between collections, or recreate it on every sync -session instead of retaining it for a compatible same-collection resume. +Share one tag tracker between collections, or recreate it on every sync run +instead of retaining it for a compatible same-collection resume. -Killed by `electric-descriptor-isolation.test.ts`: equal-key peer streams +Killed by `electric-descriptor-isolation-oracle.test.ts`: equal-key peer streams cannot remove each other's rows, and compatible persisted restart must still apply move-outs to retained tagged rows. The fresh-restart control proves old tags do not leak into a new snapshot. @@ -200,10 +200,10 @@ untagged resume fixtures explicitly declare that they do not need tag state; the legacy cells retain coverage for missing metadata. A subset-end during cold recovery must not publish the incomplete replacement. -The callback-reentry histories retire a session either before a stale callback +The callback-reentry histories retire a sync run either before a stale callback or inside an `awaitMatch` predicate at a generated row position. Only the -replacement stream may acknowledge new-session waiters. Generated message tails -must not cross that boundary. The law also registers a replacement waiter inside +replacement stream may acknowledge waiters from the new sync run. Generated +message tails must not cross that boundary. The law also registers a replacement waiter inside the restart callback: the old match iteration must not visit it. Epoch guards after user callbacks fence both the waiter loop and the remaining message batch. diff --git a/packages/electric-db-collection/tests/electric-descriptor-isolation.test.ts b/packages/electric-db-collection/tests/electric-descriptor-isolation-oracle.test.ts similarity index 99% rename from packages/electric-db-collection/tests/electric-descriptor-isolation.test.ts rename to packages/electric-db-collection/tests/electric-descriptor-isolation-oracle.test.ts index eb6cd6b54b..187efde64a 100644 --- a/packages/electric-db-collection/tests/electric-descriptor-isolation.test.ts +++ b/packages/electric-db-collection/tests/electric-descriptor-isolation-oracle.test.ts @@ -864,7 +864,7 @@ describe.each([`original`, `once-spread`] as const)( }, ) - it(`discards tag state when the same collection starts a fresh session`, async () => { + it(`discards tag state when the same Collection starts a new sync run`, async () => { const collection = createCollection(descriptor(form)) try { streams[0]!.send([insert(1, `old`), upToDate]) diff --git a/packages/electric-db-collection/tests/electric-oracle.property.test.ts b/packages/electric-db-collection/tests/electric-oracle.property.test.ts index 1194b7669f..a0b2650e82 100644 --- a/packages/electric-db-collection/tests/electric-oracle.property.test.ts +++ b/packages/electric-db-collection/tests/electric-oracle.property.test.ts @@ -191,7 +191,7 @@ function isSdkResetFramedPartition( batches: Array>>, ): boolean { // Model the installed SDK's HTTP 409 reset path: it publishes a synthetic - // singleton reset, not the response body. See electric-sdk-framing.test.ts. + // singleton reset, not the response body. See electric-sdk-framing-oracle.test.ts. // Arbitrary data/reset coalescing is outside this verified protocol domain; // this is not a claim that the SDK validates every other server response. return batches.every( @@ -1740,9 +1740,11 @@ type HistoryToken = { name: string } +// Provider controls can initiate a sync commit; delivering them does not by +// itself establish applied settlement, publication, or persistence durability. type DesignToken = | HistoryToken - | { operation: `reset` | `commit` | `subset` | `neutral` } + | { operation: `reset` | `deliver-up-to-date` | `subset` | `neutral` } type ProcessSlot = `a` | `b` @@ -2150,20 +2152,19 @@ const designTokenArb: fc.Arbitrary = fc.oneof( name: fc.string({ maxLength: 8 }), }), fc.record({ - operation: fc.constantFrom<`reset` | `commit` | `subset` | `neutral`>( - `reset`, - `commit`, - `subset`, - `neutral`, - ), + operation: fc.constantFrom< + `reset` | `deliver-up-to-date` | `subset` | `neutral` + >(`reset`, `deliver-up-to-date`, `subset`, `neutral`), }), ) +// Releasing persistence application opens the adapter's held applyCommittedTx +// call. It is separate from provider delivery and the sync applied receipt. type SchedulerEvent = | `startup-promise` | `hydration` | `snapshot-available` - | `commit` + | `release-persistence-apply` | `cleanup` function permutations(values: ReadonlyArray): Array> { @@ -2218,7 +2219,7 @@ function buildValidHistory(tokens: Array): { function designMessage(token: DesignToken): Message { if (token.operation === `reset`) return mustRefetch - if (token.operation === `commit`) return upToDate + if (token.operation === `deliver-up-to-date`) return upToDate if (token.operation === `subset`) return subsetEnd if (token.operation === `neutral`) { return { @@ -2250,7 +2251,7 @@ function buildDifferentialHistory( continue } if ( - token.operation === `commit` || + token.operation === `deliver-up-to-date` || token.operation === `subset` || token.operation === `neutral` ) { @@ -2620,7 +2621,7 @@ async function runSchedulerPermutation( }> { const startup = createDeferred() const hydration = createDeferred() - const commit = createDeferred() + const persistenceApplyGate = createDeferred() const persistedMetadata = new Map(resumeState()) const persistedRows = new Map([ [1, { id: 1, name: `persisted`, stable: `stable-1` }], @@ -2637,7 +2638,7 @@ async function runSchedulerPermutation( } const applyCommittedTx = adapter.applyCommittedTx.bind(adapter) adapter.applyCommittedTx = async (...args) => { - await commit.promise + await persistenceApplyGate.promise return applyCommittedTx(...args) } @@ -2732,7 +2733,7 @@ async function runSchedulerPermutation( if (event === `startup-promise`) startup.resolve() if (event === `hydration`) hydration.resolve() if (event === `snapshot-available`) snapshotRequested = true - if (event === `commit`) commit.resolve() + if (event === `release-persistence-apply`) persistenceApplyGate.resolve() if (event === `cleanup`) { await collection.cleanup() cleanupCompleted = true @@ -2745,7 +2746,7 @@ async function runSchedulerPermutation( startup.resolve() hydration.resolve() - commit.resolve() + persistenceApplyGate.resolve() snapshotRequested = true await drainScheduler() deliverSnapshotIfPossible() @@ -3474,12 +3475,12 @@ describeUnlessQueuedPresenceReplay(`Electric adapter laws`, () => { } }) - it(`settles every startup, hydration, snapshot availability, commit, and cleanup permutation`, async () => { + it(`settles every startup, hydration, snapshot availability, persistence-apply release, and cleanup permutation`, async () => { const events: Array = [ `startup-promise`, `hydration`, `snapshot-available`, - `commit`, + `release-persistence-apply`, `cleanup`, ] let permutationIndex = 0 @@ -3871,7 +3872,7 @@ describeUnlessQueuedPresenceReplay(`Electric adapter laws`, () => { [ [ { operation: `insert`, id: 2, name: `` }, - { operation: `commit` }, + { operation: `deliver-up-to-date` }, { operation: `delete`, id: 2, name: `` }, ], 2032071466, @@ -5551,8 +5552,15 @@ describeUnlessQueuedPresenceReplay(`Electric adapter laws`, () => { fc.array( fc.record({ operation: fc.constantFrom< - HistoryToken[`operation`] | `reset` | `acquire` | `commit` - >(`insert`, `update`, `delete`, `reset`, `acquire`, `commit`), + HistoryToken[`operation`] | `reset` | `acquire` | `deliver-subset-end` + >( + `insert`, + `update`, + `delete`, + `reset`, + `acquire`, + `deliver-subset-end`, + ), id: fc.integer({ min: 1, max: 3 }), name: fc.string({ maxLength: 8 }), }), @@ -5576,7 +5584,7 @@ describeUnlessQueuedPresenceReplay(`Electric adapter laws`, () => { if (command.operation === `acquire`) { // This enters the acquisition API with a fresh disjoint predicate, // but the mock does not deliver response rows. Actual installed-SDK - // delivery and overlap are in electric-sdk-delivery.property.test.ts. + // delivery and overlap are in electric-sdk-delivery-oracle.property.test.ts. await trace.collection._sync.loadSubset({ where: new IR.Func(`eq`, [ new IR.PropRef([`id`]), @@ -5587,7 +5595,7 @@ describeUnlessQueuedPresenceReplay(`Electric adapter laws`, () => { const message = command.operation === `reset` ? mustRefetch - : command.operation === `commit` + : command.operation === `deliver-subset-end` ? subsetEnd : change( command.operation === `insert` && @@ -5616,9 +5624,15 @@ describeUnlessQueuedPresenceReplay(`Electric adapter laws`, () => { undefined, [ [ - ([`insert`, `commit`, `reset`, `acquire`, `update`] as const).map( - (operation) => ({ operation, id: 1, name: `` }), - ), + ( + [ + `insert`, + `deliver-subset-end`, + `reset`, + `acquire`, + `update`, + ] as const + ).map((operation) => ({ operation, id: 1, name: `` })), ], ], ) diff --git a/packages/electric-db-collection/tests/electric-sdk-delivery.property.test.ts b/packages/electric-db-collection/tests/electric-sdk-delivery-oracle.property.test.ts similarity index 99% rename from packages/electric-db-collection/tests/electric-sdk-delivery.property.test.ts rename to packages/electric-db-collection/tests/electric-sdk-delivery-oracle.property.test.ts index 63faa9e3ea..2f95b4d2ce 100644 --- a/packages/electric-db-collection/tests/electric-sdk-delivery.property.test.ts +++ b/packages/electric-db-collection/tests/electric-sdk-delivery-oracle.property.test.ts @@ -19,7 +19,7 @@ import type { Message } from '@electric-sql/client' * * The Collection subset contract and the Electric adapter's tagged-row * contract are owned by electric-oracle.property.test.ts. The installed SDK's - * reset framing is checked by electric-sdk-framing.test.ts. This driver + * reset framing is checked by electric-sdk-framing-oracle.test.ts. This driver * moves the boundary outward: a finite HTTP provider sends authored Electric * responses, and the installed ShapeStream owns framing, pause, snapshot, * abort, and silent-move delivery. The adapter must publish the union of @@ -45,7 +45,7 @@ import type { Message } from '@electric-sql/client' // TANSTACK_DB_ORACLE_PATH, and TANSTACK_DB_ORACLE_PROPERTY. For example: // TANSTACK_DB_ORACLE_SEED=20260917 TANSTACK_DB_ORACLE_PATH=0 \ // TANSTACK_DB_ORACLE_PROPERTY=electric.sdk-snapshot-delivery \ -// pnpm --dir packages/electric-db-collection exec vitest run tests/electric-sdk-delivery.property.test.ts -t 'replay' +// pnpm --dir packages/electric-db-collection exec vitest run tests/electric-sdk-delivery-oracle.property.test.ts -t 'replay' const { replayPath, replayProperty } = readOracleRunConfig() const fixedCase = replayPath === undefined ? it : it.skip const replayFault = process.env.TANSTACK_DB_ELECTRIC_SDK_DELIVERY_FAULT @@ -89,7 +89,7 @@ function violationCheckpoint(error: unknown): string { )?.[1] const assertion = /^(.+?): expected(?: |$)/.exec(message)?.[1] const sourceLine = error.stack?.match( - /electric-sdk-delivery\.property\.test\.ts:(\d+):/, + /electric-sdk-delivery-oracle\.property\.test\.ts:(\d+):/, )?.[1] return `${error.name}:${checkpoint ?? assertion ?? sourceLine ?? message}` } diff --git a/packages/electric-db-collection/tests/pg-serializer.property.test.ts b/packages/electric-db-collection/tests/pg-serializer-oracle.property.test.ts similarity index 99% rename from packages/electric-db-collection/tests/pg-serializer.property.test.ts rename to packages/electric-db-collection/tests/pg-serializer-oracle.property.test.ts index bd20841048..322e254768 100644 --- a/packages/electric-db-collection/tests/pg-serializer.property.test.ts +++ b/packages/electric-db-collection/tests/pg-serializer-oracle.property.test.ts @@ -5,7 +5,7 @@ import { serialize } from '../src/pg-serializer' // Replay one named law directly with PG_SERIALIZER_ORACLE_PROPERTY=, // PG_SERIALIZER_ORACLE_SEED=, and // PG_SERIALIZER_ORACLE_PATH=. -// Example: pnpm exec vitest run tests/pg-serializer.property.test.ts -t 'mixed finite arrays retain ordered typed contents' +// Example: pnpm exec vitest run tests/pg-serializer-oracle.property.test.ts -t 'mixed finite arrays retain ordered typed contents' const replayProperty = process.env.PG_SERIALIZER_ORACLE_PROPERTY const replaySeedText = process.env.PG_SERIALIZER_ORACLE_SEED const replayPath = process.env.PG_SERIALIZER_ORACLE_PATH diff --git a/packages/electron-db-sqlite-persistence/tests/electron-ipc.test.ts b/packages/electron-db-sqlite-persistence/tests/electron-ipc.test.ts index e46c314b71..2dbc5b065e 100644 --- a/packages/electron-db-sqlite-persistence/tests/electron-ipc.test.ts +++ b/packages/electron-db-sqlite-persistence/tests/electron-ipc.test.ts @@ -49,7 +49,11 @@ import type { * and collection metadata. Mutating RPC replay is limited to the same known * leader and term, and one envelope id cannot identify two mutation request * types. Remote subset request data stays inside the clone-safe wire domain, - * and each accepted physical acquisition has one acquisition lease. + * and each accepted physical acquisition has one acquisition lease. Retained + * coordinator demand survives remote-owner replacement; each replacement + * acquisition has its own lease and release obligation. The Collection-level + * mapping is documented in the Browser + * `per-collection-coordinator-oracle.test.ts` companion. * * Expected transactions, adapter call logs, SQLite rows, metadata, owner * callbacks, and coordinator snapshots form the reference observations. @@ -2775,7 +2779,7 @@ describe(`electron sqlite persistence bridge`, () => { } }) - it(`replays a held Electron lease after an A to B to A leader cycle`, async () => { + it(`establishes replacement Electron acquisitions for retained demand after an A to B to A leader cycle`, async () => { const dbName = `electron-subset-a-b-a` const leader = new ElectronCollectionCoordinator({ dbName, @@ -2915,7 +2919,7 @@ describe(`electron sqlite persistence bridge`, () => { } }) - it(`rebinds a live Electron acquisition when its owner is replaced`, async () => { + it(`establishes a replacement Electron acquisition for retained demand when its owner changes`, async () => { const coordinator = new ElectronCollectionCoordinator({ dbName: `electron-subset-owner-replacement`, }) @@ -2971,7 +2975,7 @@ describe(`electron sqlite persistence bridge`, () => { } }) - it(`rebinds a live remote Electron follower lease when the same leader replaces its owner`, async () => { + it(`establishes a replacement remote Electron acquisition for retained follower demand when the same leader changes owners`, async () => { const dbName = `electron-remote-owner-replacement` const leader = new ElectronCollectionCoordinator({ dbName, @@ -3132,7 +3136,7 @@ describe(`electron sqlite persistence bridge`, () => { } }) - it(`reacquires the same Electron lease after leadership retirement`, async () => { + it(`establishes a replacement Electron acquisition for retained demand after leadership retirement`, async () => { const coordinator = new ElectronCollectionCoordinator({ dbName: `electron-subset-leadership-return`, }) @@ -3297,7 +3301,7 @@ describe(`electron sqlite persistence bridge`, () => { }, ) - it(`starts independent Electron lease replays without sibling head-of-line blocking`, async () => { + it(`starts replacement Electron acquisitions without sibling head-of-line blocking`, async () => { const coordinator = new ElectronCollectionCoordinator({ dbName: `electron-subset-parallel-replay`, }) diff --git a/packages/offline-transactions/tests/KeyScheduler.property.test.ts b/packages/offline-transactions/tests/KeyScheduler-oracle.property.test.ts similarity index 99% rename from packages/offline-transactions/tests/KeyScheduler.property.test.ts rename to packages/offline-transactions/tests/KeyScheduler-oracle.property.test.ts index ce2d54e40f..5fd1e581af 100644 --- a/packages/offline-transactions/tests/KeyScheduler.property.test.ts +++ b/packages/offline-transactions/tests/KeyScheduler-oracle.property.test.ts @@ -100,7 +100,7 @@ const { * eligible ID and payload, ordered pending records, counts, and active state. * * Reach and controls: one fixed history reaches every transition. Two fixed - * histories cross retry-deadline order. Five injected observation faults prove + * histories cross retry-deadline order. Five observation mutants prove * the comparison rejects bypass, double issue, stale payload, stale clear, and * failed selective retirement. The generated property runs at fixed seed 1815 * and at a random seed with the same budget. Set TANSTACK_DB_OFFLINE_ORACLE_SEED @@ -380,14 +380,14 @@ function assertSnapshot( expect(actual, JSON.stringify({ history, commandIndex })).toEqual(expected) } -type FaultInjection = { +type ObservationMutant = { commandIndex: number apply: (snapshot: Snapshot) => Snapshot } function runHistory( history: Array, - fault?: FaultInjection, + observationMutant?: ObservationMutant, ): Set { vi.useFakeTimers() vi.setSystemTime(BASE_TIME) @@ -505,7 +505,9 @@ function runHistory( coverage.add(nextCommand.type) const observed = snapshot(scheduler, scheduler.getNext()) const actual = - fault?.commandIndex === commandIndex ? fault.apply(observed) : observed + observationMutant?.commandIndex === commandIndex + ? observationMutant.apply(observed) + : observed assertSnapshot(history, commandIndex, actual, expectedSnapshot(model)) }) diff --git a/packages/offline-transactions/tests/connectivity-replay-oracle.test.ts b/packages/offline-transactions/tests/connectivity-replay-oracle.test.ts index 95e253c30f..6fb3a49164 100644 --- a/packages/offline-transactions/tests/connectivity-replay-oracle.test.ts +++ b/packages/offline-transactions/tests/connectivity-replay-oracle.test.ts @@ -16,6 +16,8 @@ import { atOracleCheckpoint, cleanupOfflineOracle } from './oracle-lifecycle' * calls and keeps the row; the visible/false cut permits one call and then no * row after provider success. The model describes public observations, not the * detector's predicate or the executor's queue. + * Outbox replay here means resuming unfinished durable transaction work in the + * same executor. It is neither Collection truncate replay nor oracle replay. * * Grammar: one elected executor, one write, false online hint, hidden admission, * then visible notification through either the browser event or explicit diff --git a/packages/offline-transactions/tests/fifo-retry.property.test.ts b/packages/offline-transactions/tests/fifo-retry-oracle.property.test.ts similarity index 99% rename from packages/offline-transactions/tests/fifo-retry.property.test.ts rename to packages/offline-transactions/tests/fifo-retry-oracle.property.test.ts index 28d896c46f..982f2b8173 100644 --- a/packages/offline-transactions/tests/fifo-retry.property.test.ts +++ b/packages/offline-transactions/tests/fifo-retry-oracle.property.test.ts @@ -20,7 +20,7 @@ import type { OfflineTransaction } from '../src/types' * * The package README's FIFO sequential-processing and automatic-retry * contracts supply the order and eventual-retry laws. The established - * `KeyScheduler.property.test.ts` supplies the `nextAttemptAt` eligibility + * `KeyScheduler-oracle.property.test.ts` supplies the `nextAttemptAt` eligibility * boundary. * Advancing fake timers to that boundary is a bounded executor liveness check, * not a user-facing wall-clock latency guarantee. Timer count and polling diff --git a/packages/offline-transactions/tests/indexeddb-write-settlement.test.ts b/packages/offline-transactions/tests/indexeddb-write-settlement.test.ts index 6cbb84c2dd..6bf679ce7c 100644 --- a/packages/offline-transactions/tests/indexeddb-write-settlement.test.ts +++ b/packages/offline-transactions/tests/indexeddb-write-settlement.test.ts @@ -48,12 +48,12 @@ function controlledWrite(issueError?: Error) { ? adapter.delete(`key`) : adapter.clear() const outcome: { - state: `pending` | `resolved` | `rejected` + state: `pending` | `fulfilled` | `rejected` error?: unknown } = { state: `pending` } const observed = promise.then( () => { - outcome.state = `resolved` + outcome.state = `fulfilled` }, (error: unknown) => { outcome.state = `rejected` @@ -92,7 +92,7 @@ it.each(writes)( expect(outcome.state).toBe(`pending`) storage.commit() await observed - expect(outcome.state).toBe(`resolved`) + expect(outcome.state).toBe(`fulfilled`) }, ) diff --git a/packages/offline-transactions/tests/leadership-replay.property.test.ts b/packages/offline-transactions/tests/leadership-replay-oracle.property.test.ts similarity index 99% rename from packages/offline-transactions/tests/leadership-replay.property.test.ts rename to packages/offline-transactions/tests/leadership-replay-oracle.property.test.ts index 5c8146f2cc..4f715a3a56 100644 --- a/packages/offline-transactions/tests/leadership-replay.property.test.ts +++ b/packages/offline-transactions/tests/leadership-replay-oracle.property.test.ts @@ -34,6 +34,10 @@ import type { TestItem } from './harness' * `foldReplayLedger` models stored and durably removed IDs without copying * production revision counters, so stale captured reads cannot restore removed * work in the model. + * Outbox replay means resuming unfinished durable transaction work. An offline + * executor restart constructs a fresh executor over the retained outbox; neither + * is a Collection sync restart or truncate replay. Seed/path replay below is + * oracle replay of a recorded failure. * * History grammar: leadership may be acquired, lost, regained, or disposed at * construction, outbox read, retry hook, provider, acknowledgement, or retry @@ -121,7 +125,7 @@ function foldReplayLedger(events: ReadonlyArray): { // For example, from the repository root: // OFFLINE_ORACLE_SEED=20260923 OFFLINE_ORACLE_PATH=0:0 \ // pnpm --dir packages/offline-transactions exec vitest run \ -// tests/leadership-replay.property.test.ts -t 'filters every durably removed transaction' +// tests/leadership-replay-oracle.property.test.ts -t 'filters every durably removed transaction' // // Grammar controls: each fixed lane enumerates the named causal boundary, and // the seedless lane samples adjacent values with the same property/checkpoint. @@ -190,10 +194,10 @@ function oracleOptions( it(`removes an earlier deletion-pending row before replaying an equal-time peer`, async () => { // The README promises creation-order FIFO and deletion before success. This - // fixed restart history uses storage insertion order to distinguish creation - // when both persisted timestamps are equal. The independent expected trace - // is removal of the earlier completed-provider row, then provider execution - // and removal of its later peer. It covers this controlled storage boundary, + // fixed offline executor restart history uses storage insertion order to + // distinguish creation when both persisted timestamps are equal. The + // independent expected trace first removes the earlier completed-provider row, + // then executes and removes its later peer. It covers this storage boundary, // not ordering across independent storage writers or a native browser host. const earlier: OfflineTransaction = { ...storedTransaction(`earlier`), diff --git a/packages/offline-transactions/tests/transaction-serializer.property.test.ts b/packages/offline-transactions/tests/transaction-serializer-oracle.property.test.ts similarity index 98% rename from packages/offline-transactions/tests/transaction-serializer.property.test.ts rename to packages/offline-transactions/tests/transaction-serializer-oracle.property.test.ts index f57022d0d8..08e12dc5ed 100644 --- a/packages/offline-transactions/tests/transaction-serializer.property.test.ts +++ b/packages/offline-transactions/tests/transaction-serializer-oracle.property.test.ts @@ -15,7 +15,7 @@ import type { PendingMutation } from '@tanstack/db' /** * # Does an offline transaction survive durable serialization exactly? * - * Contract and source: SerializedOfflineTransaction and the established restart + * Contract and source: SerializedOfflineTransaction and the offline persistence * contract preserve mutation meaning across process boundaries. Encoding v3 * supports JSON trees, Date, and the eight restorable Temporal scalar types. * Marker-shaped user objects remain data. Unversioned and v2 records retain @@ -36,6 +36,10 @@ import type { PendingMutation } from '@tanstack/db' * it through the same registry keys. Each checkpoint compares the wire tree, * decoded transaction fields, registry binding, order, errors, and retained * storage after a failed read. + * The application-restart model recreates the serializer and Collections over + * retained wire records. It simulates process recreation without starting another + * process or restarting an existing Collection's sync run. Seed/path replay is + * oracle replay of a recorded failure. * * Reach and controls: pinned histories force every edit kind and hostile marker. * Fixed and random lanes support seed/path replay. Encoder and decoder faults @@ -183,7 +187,8 @@ async function checkRoundtrip( }, }), ) - // A restart has different object and collection IDs, but the same registry keys. + // Application restart uses fresh Collection objects and IDs, but the same + // registry keys. const readers = [0, 1].map((slot) => createCollection({ id: `reader:${slot}`, @@ -1349,9 +1354,9 @@ const pinned: Array = [ // Grammar controls: the pinned history is a legal ten-edit reconstruction of // every edit kind, both registry slots, Date/string twins, marker escapes, and // an own __proto__ key. Dropping one of those axes loses a distinct wire or -// restart observation. Generated trees add empty and nested arrays/objects, -// with depth two and at most three children or keys; current records admit -// zero edits, while compatibility records start at one. Cycles and malformed +// application-restart observation. Generated trees add empty and nested arrays +// and objects with depth two and at most three children or keys. Current records +// admit zero edits, while compatibility records start at one. Cycles and malformed // markers are outside this valid-tree grammar and have rejection witnesses // above. The generated edit bound includes the complete pinned history. A // never-escape rule fails its marker-shaped user object; an always-escape rule @@ -1410,7 +1415,7 @@ it(`replays a shrunk mutation-wire failure at the same checkpoint`, async () => // a command to run the recorded seed/path without repeating the capture. // Captured replay: OFFLINE_ORACLE_SEED=20260914 // OFFLINE_ORACLE_PATH=0:1:0:0:0:1:1:1:1:1 pnpm exec vitest run - // tests/transaction-serializer.property.test.ts --configLoader runner + // tests/transaction-serializer-oracle.property.test.ts --configLoader runner // -t 'replays a shrunk mutation-wire failure' const property = mutationMeaningProperty(`omit-changes`) const captured = await fc.check(property, { diff --git a/packages/offline-transactions/tests/transaction-settlement.property.test.ts b/packages/offline-transactions/tests/transaction-settlement-oracle.property.test.ts similarity index 98% rename from packages/offline-transactions/tests/transaction-settlement.property.test.ts rename to packages/offline-transactions/tests/transaction-settlement-oracle.property.test.ts index e824b832ca..45cf7654c9 100644 --- a/packages/offline-transactions/tests/transaction-settlement.property.test.ts +++ b/packages/offline-transactions/tests/transaction-settlement-oracle.property.test.ts @@ -18,12 +18,16 @@ import type { OfflineTransaction, TransactionSignaler } from '../src/types' * The README's FIFO, durable-outbox, and NonRetriableError contracts, together * with waitForTransactionCompletion's per-ID API, authorize this law: * transactions enter a global FIFO, but commit and wait promises belong to one - * transaction ID. Success applies its server rows and, after outbox removal, - * fulfills both promises. + * transaction ID. Fulfillment of mutationFn and acknowledged outbox deletion + * fulfill both caller promises. This alone does not establish server application + * or public Collection publication. * Permanent failure rejects those promises with the same error and rolls back * only its local overlay. A peer's provider, retry-record, or durable-admission * failure cannot settle or erase independently admitted work. * + * In this fixture, a successful mutationFn updates the modeled server rows and + * submits their Collection sync writes before returning. Row assertions depend + * on that controlled premise; the executor does not supply it for every provider. * The model is a prefix of completed transaction outcomes and an independently * folded map of provider-applied rows. Its pending local rows represent the * optimistic overlay, not durable outbox entries. Generated histories use 2–5 @@ -57,14 +61,18 @@ import type { OfflineTransaction, TransactionSignaler } from '../src/types' * run pairs fixed and seedless campaigns. * A permanent provider failure uses a separate rejection-pending marker. The * original caller rejects with that failure; a storage failure also throws - * from the executor batch and stops further work. Restart removes a marked row - * without another provider call or optimistic restore. Direct executor checks - * pin the storage error, FIFO peer hold, and refusal of further attempts. An - * unmarked row after a failed marker write can still replay after a crash. + * from the executor batch and stops further work. An offline executor restart + * removes a marked row without another provider call or optimistic restore. + * Direct executor checks pin the storage error, FIFO peer hold, and refusal of + * further attempts. An unmarked row after a failed marker write can still replay + * after a crash. * Public manual removal may acknowledge deletion while a provider call is * held. Once that call fulfills, both success conditions have occurred, so * the caller and local persistence promise must settle without another row. - * To replay one shrink directly, set OFFLINE_ORACLE_SEED and + * Here, an offline executor restart constructs a fresh executor over the retained + * outbox. Outbox replay resumes unfinished durable work, including terminal-phase + * deletion; neither operation is a Collection sync restart or truncate replay. + * To replay one oracle shrink directly, set OFFLINE_ORACLE_SEED and * OFFLINE_ORACLE_PATH, then select this file and the failing test name. */ diff --git a/packages/powersync-db-collection/tests/correctness-oracle.test.ts b/packages/powersync-db-collection/tests/correctness-oracle.test.ts index 0b6c797bd4..a974b7b781 100644 --- a/packages/powersync-db-collection/tests/correctness-oracle.test.ts +++ b/packages/powersync-db-collection/tests/correctness-oracle.test.ts @@ -305,13 +305,13 @@ describePowerSync(`PowerSync correctness oracle`, () => { changes: {}, } const transactor = new PowerSyncTransactor({ database: db }) - let settled = false + let persistenceFulfilled = false const persistence = transactor .applyTransaction({ mutations: [effective, trailingNoop], } as never) .then(() => { - settled = true + persistenceFulfilled = true }) await vi.waitFor(async () => { @@ -322,11 +322,11 @@ describePowerSync(`PowerSync correctness oracle`, () => { ).toEqual({ done: 1 }) }) for (let turn = 0; turn < 10; turn++) await Promise.resolve() - expect(settled).toBe(false) + expect(persistenceFulfilled).toBe(false) await heldChanges.flush() await persistence - expect(settled).toBe(true) + expect(persistenceFulfilled).toBe(true) } catch (error) { failure = { error } throw error @@ -473,11 +473,11 @@ describePowerSync(`PowerSync correctness oracle`, () => { metadata, } const transactor = new PowerSyncTransactor({ database: db }) - let settled = false + let persistenceFulfilled = false const persistence = transactor .applyTransaction({ mutations: [metadataOnly] } as never) .then(() => { - settled = true + persistenceFulfilled = true }) await vi.waitFor(async () => { @@ -485,11 +485,11 @@ describePowerSync(`PowerSync correctness oracle`, () => { expect(batch?.crud.at(-1)?.metadata).toBe(JSON.stringify(metadata)) }) for (let turn = 0; turn < 10; turn++) await Promise.resolve() - expect(settled).toBe(false) + expect(persistenceFulfilled).toBe(false) await heldChanges.flush() await persistence - expect(settled).toBe(true) + expect(persistenceFulfilled).toBe(true) } catch (error) { failure = { error } throw error diff --git a/packages/query-db-collection/package.json b/packages/query-db-collection/package.json index b66ed4299c..f99e2654d4 100644 --- a/packages/query-db-collection/package.json +++ b/packages/query-db-collection/package.json @@ -21,7 +21,7 @@ "dev": "vite build --watch", "lint": "eslint . --fix", "test": "vitest run", - "test:oracles": "vitest run --coverage.enabled=false tests/includes-work-counter-oracle.test.ts tests/load-subset-lifecycle-oracle.test.ts tests/ownership-lifecycle.oracle.test.ts tests/ssr-dehydration-oracle.test.ts tests/cursor-pagination.oracle.test.ts tests/cursor-pagination.cache-oracle.test.ts tests/cursor-pagination.publication-oracle.test.ts tests/cursor-pagination.boundary-oracle.test.ts tests/cursor-pagination.integration.test.ts", + "test:oracles": "vitest run --coverage.enabled=false tests/includes-work-counter-oracle.test.ts tests/load-subset-lifecycle-oracle.test.ts tests/ownership-lifecycle.oracle.test.ts tests/ssr-dehydration-oracle.test.ts tests/cursor-pagination.oracle.test.ts tests/cursor-pagination.cache-oracle.test.ts tests/cursor-pagination.publication-oracle.test.ts tests/cursor-pagination.boundary-oracle.test.ts tests/cursor-pagination-oracle.integration.test.ts", "test:e2e": "vitest run --config vitest.e2e.config.ts" }, "type": "module", diff --git a/packages/query-db-collection/tests/cursor-pagination.integration.test.ts b/packages/query-db-collection/tests/cursor-pagination-oracle.integration.test.ts similarity index 98% rename from packages/query-db-collection/tests/cursor-pagination.integration.test.ts rename to packages/query-db-collection/tests/cursor-pagination-oracle.integration.test.ts index 5f68bb3d30..5327a08ac1 100644 --- a/packages/query-db-collection/tests/cursor-pagination.integration.test.ts +++ b/packages/query-db-collection/tests/cursor-pagination-oracle.integration.test.ts @@ -11,8 +11,8 @@ import { createDeferred } from '../../db/src/deferred.js' import { createLiveQueryWindowController } from '../../db/src/live-query-window-controller.js' import { createCursorPager, queryCollectionOptions } from '../src/index.js' import { createBackend } from './cursor-pagination/backend.js' -import { expectedWindow } from './cursor-pagination/model.js' -import type { Row, Scope } from './cursor-pagination/model.js' +import { expectedWindow } from './cursor-pagination/model-oracle.js' +import type { Row, Scope } from './cursor-pagination/model-oracle.js' /** * # Does opaque pagination refine a real live-query window? @@ -442,17 +442,17 @@ describe(`cursor adapter through production pagination`, () => { publications.push(shallow.getSnapshot().data.map((row) => row.id)), ) const stopDeep = deep.subscribe(() => {}) - let settled = 0 + let fulfilledPreloads = 0 const pending = Promise.allSettled( [shallow.preload(), deep.preload()].map((promise) => promise.then(() => { - settled++ + fulfilledPreloads++ }), ), ) try { await vi.waitFor(() => expect(fixture.received()).toBe(1)) - expect(settled).toBe(0) + expect(fulfilledPreloads).toBe(0) expect(shallow.getSnapshot().data).toEqual([]) expect(publications.every((batch) => batch.length === 0)).toBe(true) fixture.gate.resolve() diff --git a/packages/query-db-collection/tests/cursor-pagination.no-peek.integration.test.ts b/packages/query-db-collection/tests/cursor-pagination-oracle.no-peek.integration.test.ts similarity index 98% rename from packages/query-db-collection/tests/cursor-pagination.no-peek.integration.test.ts rename to packages/query-db-collection/tests/cursor-pagination-oracle.no-peek.integration.test.ts index ed16a26b38..bb0f5f8db0 100644 --- a/packages/query-db-collection/tests/cursor-pagination.no-peek.integration.test.ts +++ b/packages/query-db-collection/tests/cursor-pagination-oracle.no-peek.integration.test.ts @@ -6,10 +6,10 @@ import { import { describe, expect, it } from 'vitest' import { createDeferred } from '../../db/src/deferred.js' import { createLiveQueryWindowController } from '../../db/src/live-query-window-controller.js' -import { expectedWindow } from './cursor-pagination/model.js' +import { expectedWindow } from './cursor-pagination/model-oracle.js' import { createNoPeekDemandModel } from './cursor-pagination/no-peek.js' import { createFactTransport } from './cursor-pagination/no-peek-transport.js' -import type { Row } from './cursor-pagination/model.js' +import type { Row } from './cursor-pagination/model-oracle.js' import type { PrefixPublication } from './cursor-pagination/no-peek.js' const scope = { group: undefined, descending: false } diff --git a/packages/query-db-collection/tests/cursor-pagination.boundary-oracle.test.ts b/packages/query-db-collection/tests/cursor-pagination.boundary-oracle.test.ts index 0902ee9423..e968e36d58 100644 --- a/packages/query-db-collection/tests/cursor-pagination.boundary-oracle.test.ts +++ b/packages/query-db-collection/tests/cursor-pagination.boundary-oracle.test.ts @@ -18,7 +18,7 @@ import { createCursorPager, queryCollectionOptions } from '../src/index.js' * cancellation rejects a nested QueryCollection preload. A silent replacement * may fulfill it only with replacement rows. Reader abort rejects that reader * with its reason and leaves Query's shared transport active. Query's configured - * retry policy applies to both initial and growth acquisitions. + * retry policy applies to both initial and growth Query fetches. * * Each generated size from one to four creates two pages, so the held second * page is always reachable; size zero cannot enter that history. The independent @@ -80,7 +80,7 @@ const makeClient = () => const rowsFor = (size: number) => Array.from({ length: size * 2 }, (_, id) => ({ id })) -describe(`cursor acquisition boundaries`, () => { +describe(`cursor Query fetch boundaries`, () => { it.each([false, true])( `nested row query settles when pages cancel; replacement=%s`, async (replace) => { @@ -228,7 +228,7 @@ describe(`cursor acquisition boundaries`, () => { ) }) - it(`a fresh hit does not inherit another acquisition's same-turn cancellation`, async () => { + it(`a fresh hit does not inherit another Query fetch's same-turn cancellation`, async () => { const client = makeClient(), entered = createDeferred(), release = createDeferred() @@ -268,7 +268,7 @@ describe(`cursor acquisition boundaries`, () => { }) it.each([undefined, false, 1] as const)( - `browser retry policy is the same across acquisition phases: %s`, + `browser retry policy is the same across Query fetch phases: %s`, async (retry) => { for (const phase of [`initial`, `growth`] as const) { const client = new QueryClient({ diff --git a/packages/query-db-collection/tests/cursor-pagination.cache-oracle.test.ts b/packages/query-db-collection/tests/cursor-pagination.cache-oracle.test.ts index efc4f9cfdd..b8d8a30665 100644 --- a/packages/query-db-collection/tests/cursor-pagination.cache-oracle.test.ts +++ b/packages/query-db-collection/tests/cursor-pagination.cache-oracle.test.ts @@ -8,9 +8,9 @@ import { } from '../../db/tests/oracle-config.js' import { createCursorPager } from '../src/index.js' import { createBackend } from './cursor-pagination/backend.js' -import { expectedRows } from './cursor-pagination/model.js' +import { expectedRows } from './cursor-pagination/model-oracle.js' import type { CursorPager } from '../src/index.js' -import type { Row } from './cursor-pagination/model.js' +import type { Row } from './cursor-pagination/model-oracle.js' /** * # When may cached cursor pages answer a later read? @@ -28,7 +28,7 @@ import type { Row } from './cursor-pagination/model.js' * The cache contract comes from cursor-pagination/README.md and QueryClient's * public cache operations. The controlled backend holds each sequence stable; * this oracle does not establish snapshot behavior for changing HTTP endpoints. - * Window values, cache publication, browser acquisition, and QueryCollection + * Window values, cache publication, browser Query fetches, and QueryCollection * integration have separate owners in oracle-coverage.md. */ @@ -140,7 +140,7 @@ describe(`cursor cache lifecycle`, () => { ) it.each([`initial`, `growth`, `refresh`] as const)( - `cancellation stops a held %s acquisition and permits later recovery`, + `cancellation stops a held %s Query fetch and permits later recovery`, async (phase) => { await assertCacheProperty( fc.asyncProperty( @@ -203,7 +203,7 @@ describe(`cursor cache lifecycle`, () => { const signal = await started.promise if (phase === `growth`) { // A reader whose whole window is cached need not wait for a - // peer's deeper acquisition, even though they share a key. + // peer's deeper Query fetch, even though they share a key. await checkWindow(createCursorPager(options), rows, size) } const query = client @@ -228,7 +228,7 @@ describe(`cursor cache lifecycle`, () => { }), ) // Observe the real fetch join instead of guessing how many - // microtasks the peer takes to reach the acquisition boundary. + // microtasks the peer takes to reach the Query fetch boundary. await joined.promise joinWitness.mockRestore() await client.cancelQueries({ queryKey: key, exact: true }) @@ -460,7 +460,7 @@ describe(`cursor cache lifecycle`, () => { const window = { offset: 0, limit: width } await checkWindow(pager, expectedSource, width) expect(starts - beforeStarts).toBe(refresh ? 1 : 0) - // Query dates the cache from its latest successful acquisition, + // Cache freshness starts at the latest successful Query fetch, // including fetchNextPage, rather than aging each page separately. if (calls !== beforeCalls) deadline = now + 100 cached = true @@ -572,7 +572,7 @@ describe(`cursor cache lifecycle`, () => { }, ) - it(`shares acquisitions across readers without letting one abort cancel its peer`, async () => { + it(`shares Query fetches across readers without letting one abort cancel its peer`, async () => { const client = new QueryClient({ defaultOptions: { queries: { retry: false, gcTime: Infinity, staleTime: Infinity }, diff --git a/packages/query-db-collection/tests/cursor-pagination.no-peek.test.ts b/packages/query-db-collection/tests/cursor-pagination.no-peek.test.ts index 21f07fe1b9..457b32373a 100644 --- a/packages/query-db-collection/tests/cursor-pagination.no-peek.test.ts +++ b/packages/query-db-collection/tests/cursor-pagination.no-peek.test.ts @@ -2,10 +2,10 @@ import { describe, expect, it } from 'vitest' import fc from 'fast-check' import { createDeferred } from '../../db/src/deferred.js' import { oraclePropertyOptions } from '../../db/tests/oracle-config.js' -import { expectedWindow } from './cursor-pagination/model.js' +import { expectedWindow } from './cursor-pagination/model-oracle.js' import { createNoPeekDemandModel } from './cursor-pagination/no-peek.js' import { createFactTransport } from './cursor-pagination/no-peek-transport.js' -import type { Row, Scope } from './cursor-pagination/model.js' +import type { Row, Scope } from './cursor-pagination/model-oracle.js' const scope: Scope = { group: undefined, descending: false } const rowsOf = (count: number): Array => diff --git a/packages/query-db-collection/tests/cursor-pagination.oracle.test.ts b/packages/query-db-collection/tests/cursor-pagination.oracle.test.ts index 5d29c9664a..08a749fe7f 100644 --- a/packages/query-db-collection/tests/cursor-pagination.oracle.test.ts +++ b/packages/query-db-collection/tests/cursor-pagination.oracle.test.ts @@ -6,9 +6,9 @@ import { readOracleRunConfig, } from '../../db/tests/oracle-config.js' import { createBackend } from './cursor-pagination/backend.js' -import { expectedRows } from './cursor-pagination/model.js' +import { expectedRows } from './cursor-pagination/model-oracle.js' import { createCursorPager } from './cursor-pagination/pager.js' -import type { Row, Scope, Window } from './cursor-pagination/model.js' +import type { Row, Scope, Window } from './cursor-pagination/model-oracle.js' /** * # Can opaque pages reconstruct any requested ordered slice? @@ -321,8 +321,8 @@ describe(`opaque cursor adapter`, () => { expectedRows(fixtureRows, allAscending, { offset: 0, limit: 6 }), ) expect(outcomes).toEqual([`first-error`, `peer-success`]) - // Cancelling a reader does not cancel Query's shared acquisition. A - // successful page remains reusable; failed/reset acquisitions restart. + // Cancelling a reader leaves the shared Query fetch active. A successful + // page remains reusable; failed or reset Query fetches start again. if (action === `abort`) { expect(backend.calls[1]).toEqual(expect.any(String)) expect(backend.calls).toHaveLength(3) @@ -433,7 +433,7 @@ describe(`opaque cursor adapter`, () => { value: expectedRows(rows, scope, all), }) expect(backend.calls).toHaveLength( - // Query marks failed acquisitions stale and rebuilds their prefix. + // Query marks failed fetches stale and rebuilds their prefix. Math.ceil(rows.length / size) + (fault === `reject` ? faultPage + 1 : 0), ) diff --git a/packages/query-db-collection/tests/cursor-pagination.publication-oracle.test.ts b/packages/query-db-collection/tests/cursor-pagination.publication-oracle.test.ts index adfab09f45..38287a0481 100644 --- a/packages/query-db-collection/tests/cursor-pagination.publication-oracle.test.ts +++ b/packages/query-db-collection/tests/cursor-pagination.publication-oracle.test.ts @@ -8,8 +8,8 @@ import { } from '../../db/tests/oracle-config.js' import { createCursorPager } from '../src/index.js' import { createBackend } from './cursor-pagination/backend.js' -import { expectedRows } from './cursor-pagination/model.js' -import type { Row } from './cursor-pagination/model.js' +import { expectedRows } from './cursor-pagination/model-oracle.js' +import type { Row } from './cursor-pagination/model-oracle.js' /** * # Which cursor sequence may become the next public result? @@ -195,7 +195,7 @@ describe(`cursor cache publication`, () => { return result }) // Follow the guide's force-refresh recipe through a real active - // outer query. Observe its acquisition before releasing old data. + // outer query. Observe its Query fetch before releasing old data. if (cancel) await client.cancelQueries({ queryKey: [`posts`] }) refreshEntered = createDeferred() const refresh = client.invalidateQueries({ queryKey: [`posts`] }) @@ -343,7 +343,7 @@ describe(`cursor cache publication`, () => { } expect( published, - `invalid acquisition must not publish success`, + `invalid Query fetch must not publish success`, ).toEqual([]) expect(client.getQueryData(key)).toBe(previous) } finally { diff --git a/packages/query-db-collection/tests/cursor-pagination/NO-PEEK-RESULTS.md b/packages/query-db-collection/tests/cursor-pagination/NO-PEEK-RESULTS.md index 48de6d7141..12400618b1 100644 --- a/packages/query-db-collection/tests/cursor-pagination/NO-PEEK-RESULTS.md +++ b/packages/query-db-collection/tests/cursor-pagination/NO-PEEK-RESULTS.md @@ -115,9 +115,9 @@ From `packages/query-db-collection`: TANSTACK_DB_ORACLE_RUNS_MULTIPLIER=100 TANSTACK_DB_ORACLE_SEED=863 \ ../../node_modules/.bin/vitest run \ tests/cursor-pagination.no-peek.test.ts \ - tests/cursor-pagination.no-peek.integration.test.ts \ + tests/cursor-pagination-oracle.no-peek.integration.test.ts \ tests/cursor-pagination.oracle.test.ts \ - tests/cursor-pagination.integration.test.ts \ + tests/cursor-pagination-oracle.integration.test.ts \ --typecheck.enabled=false --maxWorkers=1 ``` diff --git a/packages/query-db-collection/tests/cursor-pagination/README.md b/packages/query-db-collection/tests/cursor-pagination/README.md index 2d81ed2592..25040a9209 100644 --- a/packages/query-db-collection/tests/cursor-pagination/README.md +++ b/packages/query-db-collection/tests/cursor-pagination/README.md @@ -19,9 +19,9 @@ cursor experiment or the existing production controller. - Zero limit performs no transport work. Short and empty nonterminal pages do not establish exhaustion. A repeated cursor fails clearly rather than loops. - Reads of one pager serialize. Reader cancellation rejects that reader but - does not cancel Query's shared acquisition or discard its valid page. Use + does not cancel the shared Query fetch or discard its valid page. Use QueryClient cancellation to stop transport; reset rejects old reads. Failed - acquisitions leave the previous cached result available and can cause Query + Query fetches leave the previous cached result available and can cause Query to rebuild the prefix when retried. These are Query's semantics, replacing the prototype's rule that an aborted reader must discard its response. - Query owns cache expiry, garbage collection and invalidation. Use a distinct @@ -33,11 +33,11 @@ cursor experiment or the existing production controller. invalidation alone can join an old in-flight append. Collection refetch alone may reuse fresh pages. Reset removes pages, but does not refresh collection rows. - The internal page format and full prefix are fixed: inherited `select` and - `maxPages` settings cannot change them. Explicit acquisition cancellation rejects its - waiting reads with AbortError without starting new work; a silent cancelling + `maxPages` settings cannot change them. Explicit Query fetch cancellation + rejects its waiting reads with AbortError without starting new work; a silent cancelling refetch moves waiters to the replacement. Aborted readers release their own queue position without cancelling transport. Cached reads - need not wait for a deeper peer acquisition. + need not wait for a deeper peer Query fetch. - Rows are immutable request/cache values. Reading may return a fresh array; cross-read object identity is not promised. @@ -47,8 +47,8 @@ An adapter must define its real endpoint's cursor validity/invalidation rules. ## Oracle and responsibility boundary -`model.ts` filters/sorts the complete independent dataset and slices it. It has -no cursor or acquisition state. Generated histories vary windows, ties, backend +`model-oracle.ts` filters/sorts the complete independent dataset and slices it. It has +no cursor or Query fetch state. Generated histories vary windows, ties, backend page size, source scope, failure/retry and reset. Fixed products retain empty, zero, unlimited, peer and backend/UI boundary witnesses. Fault controls must fail value/protocol assertions, not merely fail setup or time out. @@ -75,7 +75,7 @@ observe production publications, not manufacture them in the fixture. - Use Query's infinite-query page cache, not a parallel TTL/registry. Loading more fetches the missing suffix while pages are fresh. Expiry or invalidation rebuilds the loaded sequence from the beginning. Query measures freshness - from the latest successful acquisition, including page growth. This differs + from the latest successful Query fetch, including page growth. This differs from the earlier suggestion to date a session from its oldest page. - The fresh-pager-per-queryFn prototype was rejected: it would repeat fetching on ordinary page growth. Creating a helper per call is now safe **only @@ -86,7 +86,7 @@ observe production publications, not manufacture them in the fixture. - Keep N+1. No metadata setter, no-peek optimization, metadata-only notification, eligibility planner, new D2 graph, total-count API, previous-page API, cursor persistence promise, backend snapshot guarantee or offset/cursor jump hybrid. -- Query-native key sharing reuses acquisitions. We do not add cross-owner +- Query-native key sharing reuses fetches. We do not add cross-owner cancellation leases or replace Query's own concurrent-fetch semantics. - The hook and core are unchanged. The maintainer chose to close #863 with this partial implementation. Cached opaque-cursor loading ships; metadata/no-peek @@ -123,12 +123,12 @@ failed eight cells before production changed (seed 863, minimized size/depth `[1, 1]`): global/key `maxPages`, `select`, their combination, and cancellation with an existing prefix during growth/refresh. Initial cancellation stayed green. -The fixes pin the internal page format and preserve acquisition rejection even +The fixes pin the internal page format and preserve Query fetch rejection even when Query's fetch API returns reverted cache data. Generated cancellation histories hold actual response delivery at varied page depths, observe a real peer fetch join, assert both waiters reject without replacement transport, fence late completion, and retry. A fresh cached shallow read still completes while a -deeper acquisition is held. The reference remains full filter/sort/slice; no +deeper Query fetch is held. The reference remains full filter/sort/slice; no Query state machine was added to it. The reviewer independently rechecked the three fixes after implementation. @@ -140,7 +140,7 @@ The new five-cell suite retains an invalidation-only mutant and covers shared readers, retries, malformed final tokens, recovery and bounded slice work. See LOSS-AUDIT.md for the distinct generator and observation gaps. -Verification for the acquisition-boundary review fixes on base head `3f43deeb6`: +Verification for the Query fetch boundary review fixes on base head `3f43deeb6`: - Full Query DB package: **370 tests in 14 files**, default random-seed lane, exit 0, 7.82 seconds. @@ -168,9 +168,9 @@ TANSTACK_DB_ORACLE_RUNS_MULTIPLIER=100 TANSTACK_DB_ORACLE_SEED=863 \ tests/cursor-pagination.cache-oracle.test.ts \ tests/cursor-pagination.publication-oracle.test.ts \ tests/cursor-pagination.boundary-oracle.test.ts \ - tests/cursor-pagination.integration.test.ts \ + tests/cursor-pagination-oracle.integration.test.ts \ tests/cursor-pagination.no-peek.test.ts \ - tests/cursor-pagination.no-peek.integration.test.ts \ + tests/cursor-pagination-oracle.no-peek.integration.test.ts \ --typecheck.enabled=false --maxWorkers=1 --testTimeout=60000 ``` @@ -226,7 +226,7 @@ From `packages/query-db-collection`, using the installed local binaries: TANSTACK_DB_ORACLE_RUNS_MULTIPLIER=100 TANSTACK_DB_ORACLE_SEED=863 \ ../../node_modules/.bin/vitest run \ tests/cursor-pagination.oracle.test.ts \ - tests/cursor-pagination.integration.test.ts \ + tests/cursor-pagination-oracle.integration.test.ts \ --typecheck.enabled=false --maxWorkers=1 ``` diff --git a/packages/query-db-collection/tests/cursor-pagination/backend.ts b/packages/query-db-collection/tests/cursor-pagination/backend.ts index 18c41b3d5d..f80b5832df 100644 --- a/packages/query-db-collection/tests/cursor-pagination/backend.ts +++ b/packages/query-db-collection/tests/cursor-pagination/backend.ts @@ -1,4 +1,4 @@ -import type { Row, Scope } from './model.js' +import type { Row, Scope } from './model-oracle.js' export type Page = { rows: Array; nextCursor: string | null } export type FetchPage = ( diff --git a/packages/query-db-collection/tests/cursor-pagination/model.ts b/packages/query-db-collection/tests/cursor-pagination/model-oracle.ts similarity index 100% rename from packages/query-db-collection/tests/cursor-pagination/model.ts rename to packages/query-db-collection/tests/cursor-pagination/model-oracle.ts diff --git a/packages/query-db-collection/tests/cursor-pagination/no-peek-transport.ts b/packages/query-db-collection/tests/cursor-pagination/no-peek-transport.ts index 9639c82168..7f97877cac 100644 --- a/packages/query-db-collection/tests/cursor-pagination/no-peek-transport.ts +++ b/packages/query-db-collection/tests/cursor-pagination/no-peek-transport.ts @@ -1,6 +1,6 @@ import { createBackend } from './backend.js' import { createCursorPager } from './pager.js' -import type { Row, Scope } from './model.js' +import type { Row, Scope } from './model-oracle.js' import type { PrefixPublication } from './no-peek.js' /** Endpoint fixture derives continuation from opaque pages and retained tails, diff --git a/packages/query-db-collection/tests/cursor-pagination/no-peek.ts b/packages/query-db-collection/tests/cursor-pagination/no-peek.ts index 80ba2d21ab..1f3b573c25 100644 --- a/packages/query-db-collection/tests/cursor-pagination/no-peek.ts +++ b/packages/query-db-collection/tests/cursor-pagination/no-peek.ts @@ -1,4 +1,4 @@ -import type { Row } from './model.js' +import type { Row } from './model-oracle.js' /** Proposed test-only boundary: this packet describes a complete public prefix, * not a transport response or merely applied source rows. */ diff --git a/packages/query-db-collection/tests/includes-work-counter-oracle.test.ts b/packages/query-db-collection/tests/includes-work-counter-oracle.test.ts index 60b8942b99..a36d8b9925 100644 --- a/packages/query-db-collection/tests/includes-work-counter-oracle.test.ts +++ b/packages/query-db-collection/tests/includes-work-counter-oracle.test.ts @@ -6,7 +6,7 @@ import { eq, } from '@tanstack/db' import { describe, expect, it } from 'vitest' -import { evaluateReferenceExpression } from '../../db/tests/reference-expression' +import { evaluateReferenceExpression } from '../../db/tests/reference-expression-oracle' import { queryCollectionOptions } from '../src/query' import type { Collection } from '@tanstack/db' diff --git a/packages/query-db-collection/tests/load-subset-lifecycle-oracle.test.ts b/packages/query-db-collection/tests/load-subset-lifecycle-oracle.test.ts index 93c590bf63..618610b52a 100644 --- a/packages/query-db-collection/tests/load-subset-lifecycle-oracle.test.ts +++ b/packages/query-db-collection/tests/load-subset-lifecycle-oracle.test.ts @@ -600,9 +600,9 @@ async function expectDeferredRefetchWaitsForApplication( const result = collection._sync.loadSubset({ refetch: true }) expect(result).not.toBe(true) refetch = result as Promise - let settled = false + let fulfilled = false void refetch.then(() => { - settled = true + fulfilled = true }) const callsBeforeBarrier = demand === `existing` ? 2 : 1 @@ -611,7 +611,7 @@ async function expectDeferredRefetchWaitsForApplication( ) await new Promise((resolve) => setTimeout(resolve, 0)) - expect(settled).toBe(false) + expect(fulfilled).toBe(false) expect(collection.has(`fresh`)).toBe(false) collection.deferDataRefresh = null @@ -668,9 +668,9 @@ async function expectRefetchWaitsForPostWriteAuthority(): Promise { refetchDemand = collection._sync.loadSubset({ refetch: true, }) as Promise - let refetchSettled = false + let refetchFulfilled = false void refetchDemand.then(() => { - refetchSettled = true + refetchFulfilled = true }) initialResult.resolve([{ id: `stale` }]) @@ -678,7 +678,7 @@ async function expectRefetchWaitsForPostWriteAuthority(): Promise { await new Promise((resolve) => setTimeout(resolve, 0)) expect(queryFn).toHaveBeenCalledTimes(2) - expect(refetchSettled).toBe(false) + expect(refetchFulfilled).toBe(false) expect(collection.has(`stale`)).toBe(false) authoritativeResult.resolve([{ id: `authoritative` }]) diff --git a/packages/query-db-collection/tests/ownership-lifecycle.oracle.test.ts b/packages/query-db-collection/tests/ownership-lifecycle.oracle.test.ts index f45ff8af6a..7a653e0c1a 100644 --- a/packages/query-db-collection/tests/ownership-lifecycle.oracle.test.ts +++ b/packages/query-db-collection/tests/ownership-lifecycle.oracle.test.ts @@ -43,8 +43,9 @@ import type { QueryCollectionUtils } from '../src/query.js' * Mutation refetches add a second authority path but do not bypass those rules. * * The reference view is an ownership graph: query scope and demand nodes point - * to row keys; sync generations order competing results; publication - * and persistence are separate commit boundaries. Tests use real QueryClient + * to row keys. Sync-run lifetime fences, post-write-refetch generations, and + * defer-result barriers govern competing results. Publication and persistence + * are separate commit boundaries. Tests use real QueryClient * observers, cache events, collection metadata, persisted scans, and live * queries. They compare source rows, derived rows, cache rows, metadata writes, * exact request lifetimes, and bounded refetch work at each boundary. @@ -100,6 +101,16 @@ type ResultSettlementModelState = ReadonlyMap< ResultSettlementOperationState > +/** + * `query-succeeded` and `refresh-succeeded` compress the result lifecycle. + * With an applicable result and no `deferOn`, each action combines Query fetch + * fulfillment, completed Collection application and its applied settlement, + * and the terminal public-refetch checkpoint. + * A `deferOn` action instead records the skipped result and its replacement wait; + * a nondeferred `invalid-shape` result records application rejection. The model + * omits intermediate application states, which the separate obligation models + * below retain. + */ type ResultSettlementModelAction = | { type: `start-refetch`; operation: string } | { diff --git a/packages/query-db-collection/tests/query.test.ts b/packages/query-db-collection/tests/query.test.ts index fb4f05c5ff..1e4e02e099 100644 --- a/packages/query-db-collection/tests/query.test.ts +++ b/packages/query-db-collection/tests/query.test.ts @@ -24,7 +24,7 @@ import { mockSyncCollectionOptions, stripVirtualProps, } from '../../db/tests/utils' -import { evaluateReferenceExpression } from '../../db/tests/reference-expression' +import { evaluateReferenceExpression } from '../../db/tests/reference-expression-oracle' import { persistedCollectionOptions } from '../../db-sqlite-persistence-core/src' import { queryCollectionOptions } from '../src/query' import { SyncNotInitializedError } from '../src/errors' diff --git a/packages/query-db-collection/tests/server-pagination-fixture.ts b/packages/query-db-collection/tests/server-pagination-fixture.ts index 28fd9745ee..6782d27498 100644 --- a/packages/query-db-collection/tests/server-pagination-fixture.ts +++ b/packages/query-db-collection/tests/server-pagination-fixture.ts @@ -1,7 +1,7 @@ import { QueryClient } from '@tanstack/query-core' import { BTreeIndex, createCollection } from '@tanstack/db' import { queryCollectionOptions } from '../src/index' -import { evaluateReferenceExpression } from '../../db/tests/reference-expression' +import { evaluateReferenceExpression } from '../../db/tests/reference-expression-oracle' import { Func, PropRef, Value } from '../../db/src/query/ir' import type { LoadSubsetOptions } from '@tanstack/db' import type { BasicExpression } from '../../db/src/query/ir' diff --git a/packages/react-db/tests/infinite-query-conformance.test.tsx b/packages/react-db/tests/infinite-query-conformance.test.tsx index 77139a58a3..51a5913186 100644 --- a/packages/react-db/tests/infinite-query-conformance.test.tsx +++ b/packages/react-db/tests/infinite-query-conformance.test.tsx @@ -17,7 +17,7 @@ import { gt, } from '@tanstack/db' import { mockSyncCollectionOptions } from '../../db/tests/utils' -import { runInfiniteQuerySuite } from '../../db/tests/conformance/infinite-suite' +import { runInfiniteQuerySuite } from '../../db/tests/conformance/infinite-suite-oracle' import { makeInfiniteOnDemandSource } from '../../db/tests/conformance/infinite-on-demand' import { useLiveInfiniteQuery } from '../src/useLiveInfiniteQuery' import type { RenderHookResult } from '@testing-library/react' diff --git a/packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver.test.ts b/packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver-oracle.test.ts similarity index 100% rename from packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver.test.ts rename to packages/react-native-db-sqlite-persistence/tests/op-sqlite-driver-oracle.test.ts diff --git a/packages/svelte-db/tests/infinite-query-conformance.svelte.test.ts b/packages/svelte-db/tests/infinite-query-conformance.svelte.test.ts index 3cb98e7943..1271dfa797 100644 --- a/packages/svelte-db/tests/infinite-query-conformance.svelte.test.ts +++ b/packages/svelte-db/tests/infinite-query-conformance.svelte.test.ts @@ -16,7 +16,7 @@ import { import { flushSync } from 'svelte' import { describe, expect, it } from 'vitest' import { mockSyncCollectionOptions } from '../../db/tests/utils' -import { runInfiniteQuerySuite } from '../../db/tests/conformance/infinite-suite' +import { runInfiniteQuerySuite } from '../../db/tests/conformance/infinite-suite-oracle' import { makeInfiniteOnDemandSource } from '../../db/tests/conformance/infinite-on-demand' import { withScopeSetup } from '../../db/tests/conformance/scope-setup' import { useLiveInfiniteQuery } from '../src/useLiveInfiniteQuery.svelte.js' diff --git a/packages/vue-db/tests/infinite-query-conformance.test.ts b/packages/vue-db/tests/infinite-query-conformance.test.ts index 7450e370d2..a163fec60a 100644 --- a/packages/vue-db/tests/infinite-query-conformance.test.ts +++ b/packages/vue-db/tests/infinite-query-conformance.test.ts @@ -22,7 +22,7 @@ import { } from 'vue' import { describe, expect, it } from 'vitest' import { mockSyncCollectionOptions } from '../../db/tests/utils' -import { runInfiniteQuerySuite } from '../../db/tests/conformance/infinite-suite' +import { runInfiniteQuerySuite } from '../../db/tests/conformance/infinite-suite-oracle' import { makeInfiniteOnDemandSource } from '../../db/tests/conformance/infinite-on-demand' import { withScopeSetup } from '../../db/tests/conformance/scope-setup' import { useLiveInfiniteQuery } from '../src/useLiveInfiniteQuery'