Repository navigation
fix(sync): a row-uid fill never captures a stray K op (T13311) - #1979
Merged
Merged
Conversation
With row uids on by default (T13305), every minted insert under sync.capture also captured a K: the per-connection fill sets uid, then birth_fp, in two UPDATEs, and _sync_cap_<t>_k read the second one (birth_fp NULL -> value, uid already set) as a re-key. The K trigger now counts a birth_fp change only when the old value was set; _f alone patches the filled identity into the I, in both trigger orders. capture, sealer, repair, rewriters-capture and recursive-triggers-audit tests run with row uids on (their CLEO_ROW_UID_FILL=0 pins removed). Tests that need NULL-identity rows write as an older build through the new asOlderBuild helper. Journal spec v11.4 records the decision. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VjjTKbQXyCFdkLBSeuyKLt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
T13311. With row uids on by default (#1964, T13305), every insert of a minted row under
sync.capturealso captured a K (re-key) op:[K,I,U,D]instead of[I,U,D].Root cause. The per-connection TEMP fill (
installRowUidTriggers) setsuidand thenbirth_fpin two UPDATEs. By the second,OLD.uidis set, and_sync_cap_<t>_k'sOLD.birth_fp IS NOT NEW.birth_fpread thebirth_fpNULL -> value fill as a re-key.Decision (journal spec v11.4, §2.3, recorded via
cleo docs update). No stray K at all, rather than a K the sealer must recognise and drop. The K trigger counts abirth_fpchange only when the old value was set:OLD.uid IS NOT NULL AND (OLD.uid IS NOT NEW.uid OR (OLD.birth_fp IS NOT NULL AND OLD.birth_fp IS NOT NEW.birth_fp))._falone patches the filled identity into the I, in both trigger orders. This keeps the S2 rule "identity-fill updates capture nothing". A value -> value or value -> NULLbirth_fpchange is still a K. Existing stores get the new trigger text at the next open (installCaptureTriggersreplaces any trigger that differs).Changes
packages/core/src/store/sync/capture.ts: K trigger condition.capture.test.ts,sealer.test.ts,repair.test.ts(the AC), plusrewriters-capture.test.tsandrecursive-triggers-audit.test.ts: theCLEO_ROW_UID_FILL=0pins are removed. (trigger-suspend.test.tskeeps its single-test pin. That pin is a deliberate rollback-under-kill-switch case.)__tests__/older-build.tsasOlderBuild(): tests that need NULL-identity rows (sealer step 0, the repair "without uid" reason, the stand-in fill order test, the raw bracket rebuild) drop the connection's TEMP fill triggers and reinstall them afterwards, as an older build would.birth_fpwith no K, in both orders. Abirth_fpvalue -> value change is still a K.Verification
[K,I,U,D]and[K,I].birth_fpre-key term fails the new test's K assertion.pnpm run typecheck(tsc -b),pnpm run buildand biome on the diff set pass.Notes
ALTER TABLE ... RENAMErebuild oftasks_taskson a connection that holds the TEMP fill triggers fails, because the AC fill trigger referencesmain.tasks_tasks. Production migrations run before the TEMP triggers are installed (prepareRowIdentityruns after migrations; migration connections passtriggers: false), so only the raw-bracket test hit it.🤖 Generated with Claude Code
https://claude.ai/code/session_01VjjTKbQXyCFdkLBSeuyKLt