Skip to content

fix(owl): write a retract row when a functional value is superseded - #787

Merged
scbrown merged 1 commit into
mainfrom
malcolm/xdvg1-feed-f1
Oct 24, 2026
Merged

scbrown merged 1 commit into
mainfrom
malcolm/xdvg1-feed-f1

Conversation

@scbrown

@scbrown scbrown commented Oct 24, 2026 •

Copy link
Copy Markdown
Collaborator

What

When a functional property is superseded (a new value replaces the old one), the store now writes the same immutable retract row that an explicit retract writes. Before, the old value was closed in place and no record reached the change feed, so a replica that replayed the feed kept both values live.

Base

The PR is now rebased onto main b8ebe7e3, so it is no longer stacked. #780 landed as a squash. Its patch is byte-identical to the reviewed f43688dd (git diff af452206 f43688dd equals git diff 8d62e332 b8ebe7e3). This PR is now the single commit 1ca33336 on top of it.

Landing order for the rest of the series: this PR, then #788 (oversized-transaction frames), then #789 (store_id/log_epoch on every page), then #785 (freeze epoch). Each is rebased when its predecessor lands.

Evidence (at 1ca33336)

  • Replay test. f1_functional_supersede_replays_as_one_current_value replays every change page into an empty store and compares a canonical live-fact digest. It failed before this change, because the replica held an extra stale value. It passes after.
  • Sabotage. Removing the retract row turns the test red; restoring the file brings back identical bytes.
  • Local checks. cargo test --features shacl,owl: 3191 passed, 0 failed. clippy -D warnings -A missing-docs is clean for full and for shacl,owl. fmt is clean.

Rollback

Revert the commit. Supersede then stops emitting the retract record. There is no schema change.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BzgSY2LpdGhBhb7D1nHbiF

A functional-property supersede closed the prior value with an UPDATE and
wrote no op=0 row, unlike an explicit retract. The change feed derives its
records from rows, so it showed the new value and never the end of the old
one, and a replica built from the feed kept both (local-sync-mode.md F1).

The supersede now writes the same immutable op=0 row an explicit retract
writes, at the superseding transaction. The resident read model reads op=1
rows and their retracted_tx stamp, so it is unaffected.

The replay test asserts the replica holds exactly one current value;
removing the new row turns it red.

Refs aegis-xdvg.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0185RxTpLsPCQFB9ni72Nzac
@scbrown
scbrown force-pushed the malcolm/xdvg1-feed-f1 branch from 7595271 to 1ca3333 Compare October 24, 2026 06:40
@scbrown
scbrown marked this pull request as ready for review October 24, 2026 06:40
@scbrown

scbrown commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator Author

SOURCE APPROVE exact 1ca3333, base b8ebe7e. Independent full two-file review of gate.rs and changes_replay_tests.rs, plus transaction staging/savepoint, source claims, fact schema and change-feed ordering context. The new immutable retract row carries the exact closed blob, graph, transaction and closing timestamp; closure count gates insertion, and the enclosing savepoint rolls both changes back on refusal. Reviewed ambiguity, repeated values and graph isolation.

Independent SQLite controls executed the proposal's extracted exact close/insert SQL against its facts schema: old close-only behavior reproduced a stale replica value; new SQL removed it. Multi-source claims produce one retract, named/ROOT scope stays isolated, a no-op emits nothing, rollback restores both changes, and conflict retry is idempotent. Guard command exit0 and HOME157+5 clean. Complete pinned-head hosted CI independently verified by native preparation/review. No second local Cargo build: coordinated finite build slot is with another reviewer; these controls do not claim a local Rust suite run.

Native T2 risk140c98e9; accepted independent Tim content binding766397514a7f1ae12b6d3e3cd5f8be129e943a39f918d88a8cd7fe03652b97f9. Source approval only; merge/current gates, exact-main watch and runtime acceptance remain separate.

@scbrown
scbrown merged commit 472faae into main Oct 24, 2026
24 checks passed
@scbrown
scbrown deleted the malcolm/xdvg1-feed-f1 branch October 24, 2026 09:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant