git-ents.gitmain
⌘K
foforge
commit 8105cb4
spec: require multi-ref entities to write as one atomic proposal

Phase 9’s review entity occupies two refs (its own tree and a retention pin) that must both exist for the review to exist at all, but receive.adoc never said how such a pairing gets written. The gap let phase 9’s review new write the two refs as two independent, sequential proposals: if the second write fails, a review is left with no retention pin, silently losing model.review-pin’s reachability guarantee — exactly the failure mode the existing atomic multi-ref CAS (arch.refstore-read-cas-split) exists to prevent, had the spec required its use.

feat: add receive.multi-ref-atomicity, requiring every ref of a multi-ref entity to travel in one Proposal / one receive() call, distinguished from the inbox/canonical relationship’s deliberate two-time write Assisted-by: Claude:claude-sonnet-5

Joseph D. Carpinelli · 1 month ago

Reviews

No reviews of this commit yet — record a verdict below.

Start a review

verdict

docs/spec/receive.adoc @@ -46,6 +46,26 @@ through uninterpreted until one is. -- +[role="requirement", id="receive.multi-ref-atomicity"] +.An Entity Declared Across Multiple Refs Writes Them as One Proposal +-- +Some entities are declared to require more than one ref at once as part +of their canonical shape — a review and its retention pin are the +motivating case: two refs that MUST both exist for the review to exist +at all. +Creating or updating such an entity MUST carry every one of its refs' +transitions in a single `Proposal` (<<receive.proposal-shape>>) through +one call to `receive`, never as two or more independent proposals. +The ref-store's atomic multi-ref compare-and-swap +(<<arch.refstore-read-cas-split>>) then admits or refuses the whole +batch together, so such an entity is never observable with only some of +its refs written. +This is distinct from the inbox/canonical relationship +(<<meta-ref.inbox>>), where a contributor's ref and the canonical ref +are deliberately written at different times by different actors, not as +one unit. +-- + [role="requirement", id="receive.shared-path"] .One Receive, Every Frontend --