fix(persistence): enforce membership weight and share budgets - #615
Draft
seonghobae wants to merge 34 commits into
Draft
seonghobae wants to merge 34 commits into
seonghobae wants to merge 34 commits into
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This was referenced Sep 19, 2026
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.
Scope
Dependent persistence repair for the Membership owner contract. This PR remains intentionally stacked on #287 (
feat/analysis-run-persistence) so it inherits the active persistence writer's0008_analysis_run_persistencemigration.0009closes the row-local(0, 1]mismatch; unreleased successor0010owns exact represented-binary64 same-role composition, temporal uncertainty, duplicate-edge, upgrade-validation, and concurrent-writer parity. Historical0006/0009are not rewritten.Current base authority: #287 exact
9fd492a3b3873d03460c1393308d3c8d1ca73f83.Current exact head:
10b07fcdf47f867e3c7b78ba1b8e8a2a668cc4b3.Base→head is ordinary-forward; Draft remains required.
Row-local parity (#614)
Membership owner #605 defines affiliation shares in
(0,1], while the predecessor persistence boundary rejected only non-finite/<=0values.MembershipAssignmentRecordand PostgreSQL0006therefore admitted finite values above one.0009_membership_weight_unit_intervalinstallsCHECK (membership_weight > 0 AND membership_weight <= 1) NOT VALIDfirst, then validates it separately so new writes fail closed immediately without doing the historical-row scan under the initial stronger DDL lock.Lineage: RED
f8b161d571f0d48be7697ab8668ecd4f7da17025/ catalog REDa3d74094bda7d15b20d25a98709e45f7ab354259→ Rust repaire1a2414518543afe76affab15e416f54653876a3→ forward/rollback00097eacf14e57cc2f16a817f7ccb4d4a2ee7aa682dc/b431eb2a9f7747d983a8ef0e444ba38af27b3c3a→ embedded ordering964fa844c74a5a864024338c4fc08cc27423c334→ operational REDc017cf9b3456def4dfc2f961db1047d6b80136c5→NOT VALID/VALIDATErepairb570f69742a256cbe8c38b944a6cd70bb6a8eab3.Exact same-role composition (#616/#612)
0010canonicalizes persistedNUMERICshares through PostgreSQLdouble precision, extracts the IEEE-754 binary64 payload, and compares exact scaled integer numerators. Decimal-onlySUM, ordinary floating accumulation, tolerance, clamp, and normalization are not used. The guard row serializes one(tenant, observed unit, role)lane so concurrent first writers cannot both observe an empty lane.Original lineage: RED
6668a161a312f546c58b5a5823e27b19bb3f29e6→ first exact-binary64/guard repair56c9a89c2adc98b673966bbb815b780fc65c2410→ rollbackdb3607885378f02a8ba472f7199fb75e21ad4d7d→ live contract4cf24a02c0e24fff3a0fe883345dd92bee3edabd→ embedded catalog7e48075bde8c95bc6cc62ec8615fcb8145330460→ canonical live path49f1575528548005ba8967df10f3606eb46dacc9.Temporal uncertainty (#617/#618)
0006admits non-emptytstzrangeuncertainty windows with unbounded sides and explicit endpoint inclusivity. Scalarlower()/upper()comparison was unsound: unbounded sides became SQLNULL, and equal timestamps lost open/closed semantics.#617 RED
4ad3a3cef1ef77972d71cb93b7b7627405c901b1and #618 REDbed68e3aceb49170a5a984622940159f22c26456led to range-native possible-activity envelopes; #618 repairebd816eb9d8153d54905273aefe05ae7846fc767preserves unbounded/open/closed semantics without timestamp nudging.def43f135a75d6d20ed51ee918b902ede0ddf8cfwas compile/API-only doctoring.Pointwise temporal composition (#620)
Pairwise overlap with the candidate is not enough to aggregate weights. Two existing spells can each overlap a spanning candidate at different event times without ever co-occurring. Old
0010could therefore reject a valid history such as early0.6, late0.6, spanning0.4even though every pointwise total is<= 1.0.6eaa5dc2caf601b65112996a436f37e455a2916eadds the disjoint-existing/spanning-candidate positive case and a genuine triple-overlap negative control;aa43c6520f71744504c703bd853a97a53571341freplaces pairwise candidate-overlapSUMwith an event-state sweep over exact boundary points, right-open states, and the lower-unbounded state while retaining exact binary64 numerators;75d6f65de7c4dd3bcc8f67d3d747a69a7a033e95.Pre-existing state validation (#619)
A future-write trigger alone cannot make predecessor data reconstructable.
0006/0009can contain positiveNUMERICvalues that underflow to binary64 zero, ordinary same-role overruns, the #612 boundary overrun, or duplicate temporal edges.44e310839bcc24bcefc503db4777b899614120deadds a live predecessor→successor upgrade contract.0010validates historical rows with the same binary64, pointwise temporal, and duplicate-edge semantics used by admission. Invalid state fails the migration rather than being normalized.Duplicate temporal-edge parity (#621)
Membership owner #605 rejects overlapping
(member, group, role)duplicate edges even when their weights sum to unity or less. Persistence previously enforced only the aggregate share budget.5923151335d440b33df3aab17961451e51c53124proves overlapping same-target/same-role duplicates must fail while strict leave/re-entry, different targets, and different roles remain valid;98abb27c7c5a29f4ec4ea7502375987cdea84035adds same-target/same-role range-native duplicate detection to both live admission and legacy validation and includes target-only UPDATEs in the trigger surface;81b400b5bb8a869b9622509f90b35f26b85af7e6and fixture doctoringf2de8acfe9e52ade01b5183c51407f388400b88epreserve non-empty uncertainty windows;1c2328259cfb8f507b9b7809ebe565dde809a412verifies changing only the target cannot bypass duplicate-edge admission and that rejection is atomic.Retry-safe cutover (#622)
Historical validation originally ran before the trigger. Because the repository applies migration statements sequentially rather than as one giant transaction, a predecessor writer could commit invalid state between the scan and trigger installation. Holding a long explicit table lock across the scientific scan would be the wrong operational trade-off.
84e5859a34a7864f06d74794bac2f6180ac05e97installs retry-safe guard/RLS/function/trigger admission before the historical scan;f471211abbce2503d51c503533d5d197f6c0b09eproves a failed historical validation leaves future writes protected and explicit data-owner remediation can be followed by an idempotent retry;54bf6128333b6698c2926ed20b9945aa917ecf43detects a remaining retry window fromDROP TRIGGER; CREATE TRIGGER;10b07fcdf47f867e3c7b78ba1b8e8a2a668cc4b3uses PostgreSQL 18CREATE OR REPLACE TRIGGER, so retry replaces the active gate without a committed drop/create interval.Current gate
This is not GREEN. Fresh exact-head Rust Foundation run
35463797907on10b07fcd...is queued; predecessor receipts do not transfer. Hosted PostgreSQL 18 must prove exact-binary64 arithmetic, pointwise temporal composition, bounded/unbounded and open/closed uncertainty, duplicate-edge refusal including target-only UPDATE, predecessor upgrade validation, retry-safe/no-gap cutover, embedded rollback, and concurrent first-writer behavior.#287 itself is still not GREEN. The active foundation prerequisite remains #538
f335624...; do not duplicate its dispatch/dependency-policy repairs here. #538 must land normally, then #287 and this branch must be reconciled ordinary-forward and reacquire exact-head checks.Acceptance
No self-approval, force push, destructive rebase, blind rerun, historical released-migration rewrite, decimal-only aggregate, timestamp epsilon, tolerance, clamp, normalization, source copy, or cross-service SQL is authorized.
Refs #604, #605, #610, #612, #613, #614, #616, #617, #618, #619, #620, #621, #622.