Conversation
Layer retirement is a durable broadcast deletion, but a window's view composed whatever layers remained over whatever committed value it held, so the instant a fence deleted a committed layer's rows every window — the writer included, whose fence can settle on a resume served from a stale cached basis — re-rendered the pre-commit position until its own committed value caught up seconds later. A handle now carries a retired committed-unobserved layer in its composed view, keyed to the basis at which the layer was acknowledged and the activation that retired it, and releases it when either moves; newer layers still win by sequence, rejections are never carried, and an outcome whose commit already landed retires at once. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Reef preview: https://ramose-reef-api-pr-635-rj232vtfnjcyca6s.tvanhens.workers.dev Deployed from 75c04f2 as stage |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0ee006fc30
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The acknowledgement basis was recorded when a layer was first observed committed-unobserved, so a handle that observed it late — a fresh tab, or the replica notice beating the receipt notice — anchored to a basis that already contained the authoritative result and carried the stale layer over a server-decided value. The anchor is now the basis at which the handle first observed the layer queued; a layer never observed queued gets no anchor and retires at its fence immediately. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 791826a881
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A mutation's receipt had no linkage to the replication state containing its outcome, so layer retirement guessed from observation order — and the guesses failed both ways: carried layers masked server-decided values, and anchored layers snapped back under coalesced notices or unrelated traffic. The transactor now assigns each principal's committed invocations a dense settlement sequence, atomic with the receipt; the acknowledgement and frames carry it, the manifest persists the covered watermark, and a handle composes a retired layer exactly until its own committed state covers the layer's settlement. Only the principal's own commits move the watermark, so hidden activity stays unobservable. Protocol and replica storage versions rotate. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n coverage A handle decided carries from the layer rows it happened to observe, so a refresh that coalesced the acknowledgement and the fence saw an unsettled row and snapped back; receipts outlive the fence, so the overlay state now joins every receiver receipt's settlement and the carry decision takes the durable value over the observed one. A carried layer was also dropped when the next activation began, uncovered — the last vestige of the observation-order heuristic; coverage is now the only release, which confirms that durable deletion timing is irrelevant and the activation fence needs no change. A committed acknowledgement without a settlement classifies as malformed and retries, and an unparseable settlement lookup fails upstream instead of degrading to a value that can never be covered. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f09b517f52
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…-layers # Conflicts: # test/local/conformance-catalog.ts # test/local/replication.ts
A completed receipt written before settlements existed made replay throw instead of returning its recorded outcome; it now decodes as an unsettled receipt the transactor must settle before deciding — a fresh sequence assigned idempotently at first touch, recorded at the receipt's original basis so coverage stays truthful. An acknowledgement that advanced the settlement without changing the visible revision was persisted durably but republished with only the ordinal, leaving the handle's watermark stale and a fenced layer carried indefinitely; the acknowledgement now returns both positions and the session publishes each monotonically. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3514d5fe17
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Coverage asked for the highest settlement at a basis, which assumed sequences were assigned in commit order; a backfilled receipt could then vouch for a later commit a stale frame did not contain. Coverage now returns the largest settlement whose entire prefix is committed at the basis — exact when order aligns, strictly conservative when it does not, so assignment order can no longer matter. A layer acknowledged before settlements existed decodes as settlement-pending: incomparable, therefore unreleasable, and the reconciler re-enqueues its invocation so the server's idempotent replay returns the backfilled sequence and the layer rejoins normal coverage-based retirement. Layers carrying client references stay conservatively pending until reload, and carried layers now lift recovered settlements from the durable records. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4e8d776205
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The carry set was per-handle memory, so a tab opened after the fence had nothing to compose and rendered the pre-commit value; a fenced layer whose settlement is uncovered now becomes a durable retired row, composed by every handle while its settlement exceeds the watermark and deleted only at a fence that observes coverage atomically. The in-memory carry machinery is deleted; composition is a pure function of durable rows and the watermark. Install paths merged only the ordinal, letting a delayed frame regress the settlement watermark a concurrent acknowledgement had advanced; every manifest and head write now folds the maximum stored settlement, and only committed-unobserved rows ever retire, so a rejected legacy queued layer drops its value immediately. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1a7dac15fa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ruction The fence read one arbitrary partition head, so an advanced read view could license deleting a layer a stale partition's handle still composed; coverage is now the minimum settlement across every matching head, with a malformed head pinning it at zero. A settlement-pending layer can only decode from a record written before settlements existed, and every such commit predates the storage rotation whose clean slate forces re-snapshotting — so any current head covers it by construction, client references included, and the fence deletes it outright. The recovery machinery that existed to make legacy rows comparable is deleted; the server-side receipt backfill remains for replayed idempotency. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-layers # Conflicts: # packages/ramose/test/internal/replication/protocol.test.ts # test/browser/client-graph.browser.test.ts # test/browser/frames/optimistic-fence-change.ndjson # test/browser/frames/optimistic-fence-resume.ndjson # test/browser/frames/optimistic-fence.client.json # test/browser/frames/optimistic-fence.ndjson # test/browser/propagation-tab.ts # test/browser/propagation.browser.test.ts # test/local/graph-paths.ts # test/local/replication.ts
|
Merge of master (#640, graphs-of-graphs removal) resolved. All 15 settlement acceptance tests survived: the propagation suite's deletion was collateral (its tab harness never used the deleted example stack), so both files are restored adapted to the graphless src; the five dropped tests were each intrinsically graph-of-graphs (receiver routes, child resolution) with no settlement assertions. Recorded frames regenerated on the resolved tree (no graphLineage, protocol 4, truthful settled values; provenance retained). Semantic audit clean: partition keys never carried lineage, the fence's min-across-heads ranges over exactly the intended set (the readView collapse removes a distinction only where it genuinely no longer exists), the IDB version chain lands coherently (MANIFEST_V6 = 15 over master's renamed slot), and settlement resolution keys on the same database name as the ordinal store. All five lanes green post-merge. 🤖 Generated with Claude Code |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 164b420147
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A change or snapshot re-delivering the committed revision discarded the higher settlement it carried — in the state machine's dedup before storage ever saw it, and again in the storage early return that read without writing; both now fold the maximum, and the storage path persists it under the full install discipline before announcing. A settlement-only acknowledgement advanced the durable head silently, and a follower's durable re-read refused any restore at the published revision, so other tabs kept composing a retired layer against a stale watermark; the advance now announces after commit and a strictly higher durable watermark is adopted at the same revision, one-directionally so a lagging read can never regress one. Every path that can advance durable settlement state now merges the maximum and announces. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c2c089b4d6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A settlement-only advance announced to other tabs could not reach the one recipient it targeted: a live session refused durable adoption entirely, and its stream deliberately sends nothing for an unchanged revision, so its watermark never advanced and it composed the retired layer indefinitely. A live session now performs a watermark-only adoption — a head read, guarded by generation, published-value identity, matching revision, and a strictly higher settlement — that republishes the same value with the advanced watermark and the maximum ordinal, never touching content or retention, so the open stream's authority over revisions is preserved while announced settlements reach every recipient. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fixes #634.
What
The two-window snap-back that survived #632: retiring an optimistic layer is a durable, broadcast deletion, but layer visibility was never gated on the retiring window's own committed state. The moment
fenceActivationdeleted a committed layer's rows, every window — the writer included, whose fence can settle on aResumeReadyserved from a stale 5s-TTL-cached basis in another isolate — recomposed committed-without-layer and rendered the pre-commit position until its committed value caught up 0–5s later. Deterministic repro: two iframes, one IndexedDB, real rendering — both tabs regress in ~250ms on master.The fix keeps all state in
ClientDatabaseHandle: a retiredcommitted-unobservedlayer is carried in the composed view, keyed to the basis (the #632 per-partition ordinal) at which it was acknowledged and the activation that retired it, and released when either moves. Newer queued layers still win by sequence;pendingsemantics are unchanged (durable rows only); rejections are never carried (deleted whilequeued); the update-required quarantine clears carries; identity resets forget them.OptimisticReconciler.viewgains an optional layers parameter — no other reconciler change.Known bound, stated deliberately: a commit producing no visible change for its own principal never advances the ordinal, so its carried layer persists until the next activation instead of vanishing at the fence. Lifting that needs the wire to carry the commit's visibility ordinal — a protocol change deferred until it matters.
Tests
test/browser/propagation.browser.test.ts(real client, two iframes over one IndexedDB, fence driven through the product's durable API):Negative controls: each of the three design elements reverted independently fails exactly its test. Propagation file run 5× consecutively clean.
bun run typecheckclean ·test:unit1788 pass ·test:browser233 pass ·test:local135 pass ·buildclean.🤖 Generated with Claude Code