# Content temporarily unavailable
# Issue #2310: equal rows in restarted publication

Reviewed source: [issue #2310](https://github.com/TanStack/db/issues/2310),
including its complete body and no comments, retrieved 2026-10-30.
Original investigation base: `c351fc04d7f70dc59bf92ecbed310f899b9511cd`.
At that checkpoint, the repair was an uncommitted diff on `codex/issue-2310-publication`.
Production and oracle repairs were made. No product-law change is needed.

This document is a chronology. Later sections supersede earlier branch and
measurement claims. PR [#2313](https://github.com/TanStack/db/pull/2313) published
the repair. The [external review evaluation](2026-10-30-pr-2313-review.md)
supersedes the original 72-state reach claim and records the current evidence.

## Law, experiment, and inference

A direct subscription survives Collection cleanup. Cleanup discards source rows
without sending subscriber deletes. After restart, successful reacquisition
publishes the new source replacement: an equal row actually restored by that
source remains present, an omitted row leaves, and a changed row updates.
An equal restored row needs no redundant callback. Failed replacement keeps
the prior subscriber snapshot; an obsolete acquisition cannot authorize it.

Authority: the public `Collection.subscribeChanges` change-message contract,
the existing publication owner's opening contract and independent row model,
and the shared lifecycle grammar's cleanup, restart, cancellation and settlement
rules. The coverage map assigns these observations to the Collection lifecycle
publication owner. This is enforcement of existing replacement membership, not
a new policy for source completeness or retention time.

| Law | Existing instrument | Decisive experiment | Inference and repair |
| --- | --- | --- | --- |
| Successful replacement includes every restored row, even one equal to the retained subscriber row | The shared lifecycle model selects current attempts; the independent publication model uses Maps to compute source and subscriber membership. The driver compares exact callback batches, source rows and callback-applied rows after each command. | Exact issue seed/path fails at command 5. Current attempt 1 in sync run 1 writes `{id:'b', value:1}`; attempt 0 belongs to the ended run. Source rows contain b, but the subscriber receives delete b. | Production drops the equal delta before adding it to private replacement rows. Retain that delta while a direct private replacement exists; its final diff suppresses a redundant public update. |
| Ordinary source writes obey the same replacement law | Same owner, model and comparison; no new expected-result computation | Before production edits, the new source-delivery lane restores equal independent row c while demand a holds publication. Settlement deletes c unexpectedly, alongside the legitimate deletion of omitted d. | A patch restricted to acquisition keys would miss the class. The predicate covers both real source delivery paths. |
| Omitted rows leave, failed replacement stays private, obsolete settlements are inert, and nonbuffered equal writes stay silent | Same model and observation cuts | Generated neighbors cross missing/equal/changed rows, six demand lifetimes, current resolve/reject and obsolete outcomes. A mutant retaining omitted rows fails; canceled and absent current attempts are measured as no-ops. | Preserve the existing final diff, stale-row cleanup and cancellation semantics. No model or comparison was relaxed. |

The repair-location judgment is production. Neither the driver nor the model
needs a changed expectation. The actual source write supplies membership before
the disputed publication cut, so there is no missing-provider-information
hypothesis at this controlled boundary.

## Original reach and grammar (superseded)

The original general grammar already generated the counterexample; the defect
was not a false-green model. Its finite random budget did not reliably exercise
cleanup/restart with an equal restored row. The added constructive crossing
makes that distinction durable and measures reach.

`subscription-lifecycle.restart-publication` runs both delivery paths:
acquisition writes and ordinary independent source writes. Each generated input
runs every combination of:

- six demand histories: pending, settled, two live demands, aborted, released,
  and no owner;
- three prior-row relations: absent, equal, changed;
- current resolve and reject commands, with a successful truncate replay after
  rejection.

The demand key (a/b), independent value (0–5), and obsolete resolve/reject outcome
vary. The fixture's acquisition rows use attempt IDs, so the grammar derives
which initial value will equal the restarted write. Omitted independent d
prevents a keep-all-rows implementation from passing.

There are 72 declared history states. Each is reached **12 times per campaign**,
separately for acquisition and ordinary-source paths, in the normal fixed-seed
and random runs: 1,728 histories total. The reach counter and an exact-count
assertion enforce these counts. For aborted, released and absent owners, the
current-settlement command is explicitly checked as unexecuted; its label is
not evidence of a successful or failed acquisition. Both actual current
outcomes are structurally required for the live-owner histories.

Reconstruction: the exact nine-command issue history is retained as input to
`runPublicationHistory`, without separate expected values. The general grammar
and original seed/path remain unchanged. Ablation: removing equality loses the
reported defect; removing ordinary source delivery admits an acquisition-only
repair; removing omission admits stale-row retention. Range: both demand keys,
all six independent values, old pending/settled/canceled demand, zero/one/two
live owners, and late obsolete outcomes. Exclusion: source operations always
commit valid complete transactions; the fixture fences writes with their
acquisition signal. An aborted attempt cannot legally supply replacement rows.

## RED, GREEN, and calibration

All RED results below preceded production edits. The original model and shared
comparison remained unchanged throughout.

```sh
TANSTACK_DB_ORACLE_SEED=-1439698414 \
TANSTACK_DB_ORACLE_PATH=1:22 \
TANSTACK_DB_ORACLE_PROPERTY=subscription-lifecycle.publication-history \
pnpm --filter @tanstack/db exec vitest run \
  tests/collection-subscription-lifecycle-publication-oracle.property.test.ts \
  -t 'matches row publications for a random or replayed seed' \
  --maxWorkers=2 --coverage.enabled=false
```

Original RED: one assertion fails at `assertPublications`, command 5:
observed delete b(value 1), expected no batch. Repaired GREEN: one test passes.

The extended owner's fixed seed 2310 and random campaigns also failed before
production edits on both acquisition and ordinary-source paths. The
ordinary-source mismatch at command 7 incorrectly deleted restored c. The
legitimate deletion of omitted d and insertion of demand a remained visible,
so this is a publication assertion failure, not setup or missing execution.

The new property's direct replay is also GREEN:

```sh
TANSTACK_DB_ORACLE_SEED=2310 TANSTACK_DB_ORACLE_PATH=0:0:0 \
TANSTACK_DB_ORACLE_PROPERTY=subscription-lifecycle.restart-publication \
pnpm --filter @tanstack/db exec vitest run \
  tests/collection-subscription-lifecycle-publication-oracle.property.test.ts \
  -t 'matches restarted row publication' \
  --maxWorkers=2 --coverage.enabled=false
```

This selects only the replayed campaign and runs both delivery paths: two tests
pass. Normal campaigns use the same grammar, driver, model, comparisons and
12-input budget; one uses seed 2310 and one chooses a random seed.

| Temporary production mutant | Result at the intended comparison |
| --- | --- |
| Original equal-delta suppression, removing the private-replacement predicate | Original regression and all four generated tests fail at publication assertions. |
| Preserve equal deltas only for acquisition keys a/b | The original b regression passes, but both source-delivery campaigns fail: restored c is wrongly deleted. This rejects a one-trace repair. |
| Put omitted stale rows back into the final replacement | All four campaigns fail publication assertions because omitted d survives. |

Each mutant was restored before the next experiment. None survives, times out,
or fails during setup. Mutant passes are not reported as repaired-branch GREEN.

The eight-suite surrounding run passed **646 tests**, covering lifecycle
publication, lifecycle histories, lifecycle oracle, replay oracle, ordinary
lifecycle/publication examples, reentrancy, and cleanup/restart. The final
publication owner alone passed **143 tests** after stronger reach assertions.
`pnpm --filter @tanstack/db exec tsc --noEmit` passed. Final lint, formatting,
code-weight measurements and any later verification are appended below.

## Limits and oracle-guide audit

The closure claim is direct Collection subscriptions × the bounded histories
above × the public Collection sync boundary × per-command exact callbacks,
source rows and callback-applied subscriber rows. The changed predicate applies
only when a direct private-rows map exists. Delegated graph publication keeps
its prior path. These experiments do not establish compiled includes behavior,
a framework's scheduling, or an external provider's completeness or cancellation.
The controlled rows have string keys and numeric values; virtual fields,
arbitrary object equality, optimistic writes and reentrant adapter callbacks
remain with their existing owners. No known reachable violation of this bounded
law remains; generated passing histories are not a universal proof.

| Requirement | Outcome |
| --- | --- |
| ORC-001 | Existing API/publication contract and limits stated above; no new product law. |
| ORC-002 | Existing independent Map model unchanged; production supplies only observations. |
| ORC-003 | Opening law and adjacent grammar prose explain membership, source delivery, histories, observations and checkpoints. |
| ORC-004 | Reconstruction, ablation, range and exclusion recorded above. |
| ORC-005 | Real Collection API and sync writes; exact callback/source/subscriber comparisons at every command. Actual restart and current/no-op settlement execution are checked. No missing source fact identified. |
| ORC-006 | Three hostile production mutants fail at the intended publication assertions. |
| ORC-007 | Fixed/random campaigns have equal budgets and mechanics; original and new seed/path replay commands were executed. No `fc.commands` replay path applies. |
| ORC-008 | No reference-model state added, removed or merged. |
| ORC-009 | Existing glossary terms retained. Demand-history labels describe grammar premises; canceled/absent current attempts are not classified as settlements. |
| ORC-010 | Existing driver preserves primary mismatch and secondary cleanup failures with `AggregateError`; its cleanup is unchanged. |
| ORC-011 | No new shared semantic-fault hypothesis requiring a second formulation. Counterexample comes from independent source/subscriber disagreement, not merely production/model agreement. |
| ORC-012 | This record identifies the reviewed HEAD and final code/test diff; applicable requirements are accounted for. |
| ORC-013 | Equal/changed/absent and omitted-row neighbors distinguish suppression from membership; narrow-fix and retain-omitted mutants are rejected. |
| ORC-014 | No real-provider or native-host claim is made. This is a controlled Collection boundary. |
| ORC-015 | Every declared history state reaches the driver and comparisons 12 times per normal campaign; each receiving path has separate reach. |
| ORC-016 | Regression and all generated histories replay the shared model/driver/comparison; no separate expected answer was added. |

## Lossless finding ledger

Source-order IDs preserve the issue's separate claims and requirements. No
comments, footnotes or capped findings were present. The linked issue supplies the source. This versioned record preserves the
decisive traces, commands, results, and limits without requiring local scratch.

| ID | Original claim or action | Evidence / verdict | Action | Durable value and destination |
| --- | --- | --- | --- | --- |
| R1 | Cleanup/restart publication deletes retained b; reproduced on main c351fc04d and PR #2307 1d619bb; cause explicitly undiagnosed | Confirmed production defect on the reported main commit with exact seed/path. PR head replay is reported evidence from the issue, not independently rerun here. | fixed-now | Exact shared replay plus generated membership crossing in the primary publication owner. |
| R2 | Identify the selected attempt and establish authority before changing implementation or model | Attempt 1, new sync run 1; source b is installed before settlement publication. Existing replacement law authorizes no delete. | fixed-now | Law, root cause and repair-location judgment above. |
| R3 | Preserve the nine-command history; cross rows, demand lifetimes and current/obsolete outcomes; require RED/GREEN/mutant | Both receiving paths fail unchanged production; all 72 constructed states are measured; original and narrow/broad mutants are rejected. | fixed-now | Primary oracle and coverage-map addition. No expectations, exclusions or existing budgets changed. |
| R4 | Keep separate from Solid PR #2307; #2121 retired-truncate, #1921 deferral handles, #2294 ordered replay and #2302 ordered retirement/provenance are distinct; maintainer requested a separate issue | Approved scope in #2310. The final production diff touches only Collection subscription reconciliation, not Solid, an ordered loader or the model. Historical related-PR claims were context, not independently audited. | accepted-design | This scope record. No GitHub issue or PR was changed. |

Sibling S1: ordinary source delivery of an equal independent retained row also
vanishes. This is confirmed and fixed under the same law, with its own generated
receiving path and pre-edit RED. It is separate from the four raw items.

Loss audit: **4 raw items = 3 fixed-now + 1 accepted-design**. No confirmed-open,
deferred, stale, refuted, design-decision or duplicate items remain. S1 is also
fixed. Item accounting and bounded implementation/oracle enforcement are
complete. PR readiness is **not assessed**: no PR was requested, created or
pushed with the repair, and whole-repository CI was not evaluated.

## Final verification and code weight

Code/test diff SHA-256, computed from `git diff --` for `subscription.ts`, the
publication owner and `oracle-config.ts`:
`2544ec5a5e5e2727a22be470ae53d3ca4ef4e6d31900cc326501cea60b877e27`.
This identifies the uncommitted repair in addition to its base HEAD.

`pnpm size:compare --files` completed successfully against the same merge-base.
The final Collection subscription module grows **24 minified bytes**. The db
package grows **5 gzip bytes** and shrinks **4 Brotli bytes**. The typical app
grows **7 gzip bytes / 76 Brotli bytes**; all other package bundles are unchanged.
The production change reuses the existing private-row map and final diff;
it introduces no state, recovery path or helper. Refactoring the predicate from
an explicit undefined comparison to its equivalent Map truthiness reduced
module growth from 33 to 24 minified bytes, db gzip growth from 7 to 5 bytes,
and typical-app gzip growth from 9 to 7 bytes. Retaining the final diff and
stale-row removal is necessary: the omitted-row mutant demonstrates why removing
that work is incorrect. The remaining predicate growth pays for distinguishing
replacement membership from public delta equality. Tests and evidence documentation
grow separately and do not ship in the package.

Formatting and `git diff --check` pass. The original 60-input broad fixed/random
campaign budgets are unchanged; the new 12-input structural campaigns add
coverage rather than replacing those budgets.

Worktree setup: `.worktrees/codex-issue-2310-publication`, branch
`codex/issue-2310-publication`, based on freshly fetched `origin/main` at the
recorded HEAD. Initial publication to
`origin/codex/issue-2310-publication` succeeded. `pnpm install` succeeded without
local overrides. At that original checkpoint, the repair and evidence were uncommitted and no PR existed.

Exact surrounding verification command:

```sh
pnpm --filter @tanstack/db exec vitest run \
  tests/collection-subscription-lifecycle-publication-oracle.property.test.ts \
  tests/collection-subscription-lifecycle-history-oracle.property.test.ts \
  tests/collection-subscription-lifecycle-oracle.test.ts \
  tests/collection-subscription-replay-oracle.property.test.ts \
  tests/collection-subscription-lifecycle.test.ts \
  tests/collection-subscription-lifecycle-publication.test.ts \
  tests/collection-subscription-reentrancy-oracle.test.ts \
  tests/collection-cleanup-restart-oracle.test.ts \
  --maxWorkers=2 --coverage.enabled=false
```

Final TypeScript checking and focused ESLint both pass with no diagnostics.
`pnpm lint:changed` also passes with no reports; no oracle run budget was lowered
or removed. The final eight-suite run remains GREEN at 646 tests.

## Prep-pr follow-up on current main

The preceding `c351fc04d` entries describe the original investigation. During
prep-pr, `origin/main` advanced to
`bfd1da1a7e752d66fd667adfd3cdf54f60732b22` with the separate Effect membership
repair (#2301). This branch fast-forwarded with its uncommitted changes
preserved. The code/test diff SHA-256 remains
`2544ec5a5e5e2727a22be470ae53d3ca4ef4e6d31900cc326501cea60b877e27`.
No source or oracle repair was added during quality review.

At that prep-pr checkpoint, the same eight-suite verification command above passes
**646 tests** and `pnpm --filter @tanstack/db exec tsc --noEmit` is clean.
An independent reviewer additionally ran the shared issue replay and four new
campaigns (**5 passed**) and the original exact seed/path replay (**1 passed**).
Both the independent correctness review and a separate simplification review
recommend no code changes. They agree that equal restored membership belongs
in the private replacement and the final diff owns redundant-update suppression.
The simplifier considered delivery-parameter and typed-owner-metadata alternatives
but declined them because the existing bounded grammar remains clear and small.

The preceding paragraphs record the review conclusions and validation. There are no behavioral findings or law decisions to
resolve. Two declined style alternatives were evaluated, and the duplicated
request for current-head evidence is closed by this append. The review did not
change any law, exclusion, comparison, generator or run budget. This supplements
the earlier oracle-rubric audit; its finite direct-subscription limits remain.

The required size comparison also succeeds against `bfd1da1a7`: subscription
**+24 minified bytes**, db **+5 gzip / +39 Brotli bytes**, typical app
**+7 gzip / +76 Brotli bytes**. Other package bundles are unchanged. These are
the current-base measurements; the earlier measurements remain attributed to
the original base.

Local quality review is complete. PR readiness remains unproven until the
changeset, committed/pushed head and PR checks have been prepared and verified.


## CI replay registration follow-up

PR #2313 first ran at `ebdd2140d6a25efdc6c747070f1385d4b367449d`.
The replay shard found a missing manifest owner for the newly registered
`subscription-lifecycle.restart-publication` property. The property's direct
Vitest replay was valid, but the guarded replay portfolio could not discover
its owner. This was a test-registration omission, not a changed product law
or a mismatch in the independent publication model.

The existing `named oracle replay manifest` tests reproduce RED locally:
one failure names that property as `no-named-owner`. Adding its suffix beside
`publication-history` in `oracle-replay-manifest.ts` gives GREEN: all six
manifest tests pass. The same check rejects the omitted mapping, so it also
calibrates the registration repair. No production, model, history, comparison,
exclusion or run budget changed.

```sh
pnpm --filter @tanstack/db exec vitest run tests/oracle-replay.test.ts \
  -t 'named oracle replay manifest' --maxWorkers=2 --coverage.enabled=false

TANSTACK_DB_ORACLE_SEED=2310 TANSTACK_DB_ORACLE_PATH=0:0:0 \
TANSTACK_DB_ORACLE_PROPERTY=subscription-lifecycle.restart-publication \
pnpm --filter @tanstack/db exec node --import tsx tests/oracle-replay.ts \
  tests/collection-subscription-lifecycle-publication-oracle.property.test.ts \
  -t 'matches restarted row publication' --maxWorkers=2 --coverage.enabled=false
```

The guarded replay now passes both delivery paths and reports two successful
witnesses with the requested property, seed and path. This supplements the
earlier direct replay and closes the missing portfolio-discovery boundary.

## Production-weight refactor

The maintainer requested broader refactoring after PR #2313 reached
`e453634da7339e79d892a2bf198f0e5556828b12`. This follow-up preserves behavior:

- Update `publishedRows` and `sentKeys` in one pass before calling the consumer.
  Delete the two single-use tracking methods and the callback alias.
- Keep the three source listener removal callbacks in one ordered array.
  Registration and removal retain their order. Unsubscription detaches the
  array before invoking callbacks through `runAllCallbacks`, which still attempts
  every callback and rethrows the first exact failure value.
- Initialize that array at registration, removing an unused initial allocation.
  Cleanup-start registration can call synchronously, but the initial subscription
  has no demands, rows or replay, and that path does not read the listener array
  or expose the subscription to a consumer.

The equal-row production predicate remains intact. No contract, model, grammar,
comparison, exclusion, replay registration or run budget changed. The existing
owners exercise the unchanged contract, so this internal refactor needs no new
oracle law or examples. The final production file's SHA-256 is
`f2ee13496359611fa5fe22066df96d80dec88a77fa18693af2fcfeff4ce29bc4`.

### Measured shipped bytes

`pnpm size:compare --files` compares the complete PR with merge-base
`bfd1da1a7e752d66fd667adfd3cdf54f60732b22`, after fetching `origin/main`.
Negative values mean fewer shipped bytes. Test and documentation additions
remain outside these production bundles.

| Build | Gzip delta | Brotli delta |
| --- | ---: | ---: |
| Full DB package | -28 | -43 |
| Typical app | -32 | -8 |
| App with Effect | -33 | +4 |
| App with groupBy | -38 | +22 |
| App with includes | -33 | +92 |
| App with join | -33 | +76 |
| App with local storage | -32 | -110 |
| App with optimistic action | -33 | +54 |
| App with paced mutations | -33 | +26 |

The subscription module shrinks **73 minified bytes** against the base. Other
package bundles remain unchanged. Every measured app shrinks under gzip.
Brotli results vary across feature scenarios, so the claim is negative weight
for the typical app and full DB bundle, not for every compressed app.

The original PR grew 24 minified bytes, 5 DB gzip bytes and 7 typical-app gzip
bytes. Fusing the loops while retaining a single helper reduced the module but
still grew both gzip bundles by 2 bytes. A generic Map-fold helper also left
the DB gzip bundle 2 bytes larger and hid simple bookkeeping behind an
abstraction. Inlining the loop reduced DB gzip by 5 bytes but grew DB Brotli
by 88 bytes. The ordered listener array removes parallel optional fields and
wrapper callbacks, paying for the fix with simpler existing machinery. A
redundant callback alias and initial array allocation were then removed for
clarity and fewer allocations, without tuning names, comments or formatting.

### Review and verification

Independent correctness review found no defect or optional suggestion. It
checked tracking before reentry, repeated keys, callback throws, listener handle
ownership, synchronous cleanup registration, idempotence, cleanup order and
exact first-error propagation. Its selected final-wrapper checks passed 20 tests.
The simplification reviewer proposed one P3 item: remove the unused initial
listener array. That proposal was accepted under the maintainer's refactoring
request and verified with TypeScript and the surrounding suites.

Lossless evaluation: **one raw suggestion = one fixed-now item**. No
confirmed-open, deferred, refuted, stale, design-decision or duplicate item
remains. The source-order suggestion and its rationale appear above.

The exact eight-suite command recorded earlier passes **646 tests** on the
final refactor, with no type errors. `pnpm --filter @tanstack/db exec tsc --noEmit`,
ESLint, Prettier, `pnpm lint:changed`, and `git diff --check` pass. The latter
reports no lowered or removed oracle budget.

The final-head sensitivity check temporarily restored the original equality
suppression while retaining the refactor. All four restart campaigns failed
at the shared publication comparison. Restoring the exact production file
made all four campaigns pass (139 unrelated owner tests deselected):

```sh
pnpm --filter @tanstack/db exec vitest run \
  tests/collection-subscription-lifecycle-publication-oracle.property.test.ts \
  -t 'matches restarted row publication' \
  --maxWorkers=2 --coverage.enabled=false
```

This is renewed sensitivity evidence after an internal refactor. The earlier
oracle-first RED, two distinguishing mutants and direct-subscription limits
still govern the original repair. No temporary mutant remains. Local review
and implementation work are complete; final pushed-head CI is checked separately.

## Private-member build-cache follow-up

CI at `1aadaaedc1a2159fc4000a36867bd023896b409a` rejected five obsolete
private-member cache entries before the minified consumer test ran. Local
`pnpm run check:mangle` reproduced the same RED. Running
`node scripts/mangle-private-members.mjs --write` removes those five entries
and adds `sourceListenerCleanups`. Every surviving assignment stays unchanged.
The generated cache now passes its safety check with 437 names.

`pnpm --filter @tanstack/db run build:minified` and
`pnpm run test:minified-db` then pass: 113 error names, index metadata,
query rows and live updates. This repairs build metadata, with no source,
contract, oracle or budget change. The source hash and 646-test result above
remain current. The earlier failed local consumer-test invocation rejected
stale dist output after temporary mutant restoration, before testing behavior.
The explicit fresh build resolves that setup condition.

The corrected cache changes shipped bytes. These `pnpm size:compare --files`
results **supersede the provisional weight table above** at the same base:

| Build | Gzip delta | Brotli delta |
| --- | ---: | ---: |
| Full DB package | -44 | +5 |
| Typical app | -45 | +20 |
| App with Effect | -45 | +37 |
| App with groupBy | -49 | -30 |
| App with includes | -45 | +64 |
| App with join | -45 | +37 |
| App with local storage | -44 | -14 |
| App with optimistic action | -46 | -65 |
| App with paced mutations | -46 | +47 |

The subscription module shrinks **133 minified bytes**. Other package bundles
remain unchanged. The production source diff is 28 additions and 54 deletions
against the base. Tests and documentation grow separately. The final claim is
negative minified production weight and negative gzip across every measured
app. Brotli remains mixed, including +20 bytes for the typical app and +5 bytes
for DB. No names or formatting were tuned to change compression results.


## External review correction

The external review evaluated published head `ef6316a91`. Its
[versioned evaluation](2026-10-30-pr-2313-review.md) records all ten findings.
The original 72 labels were constructed history categories, not 72 measured
production states. Fixture-dependent equality made that claim too strong.
The updated owner measures actual retained and delivered values, executed
settlement and owner lifetime, and replacement acquisition counts. It uses
51 distinct structural cases plus four three-relation receiving paths.
The production repair and the final shipped-byte measurements above remain
unchanged.
