feat(2c-G): the admitted terminal close — one commit path that derives every close fact from the composition (PR 2 of 3: G4) - #864
Merged
Conversation
…s every close fact from the composition (G4) PR 2 of amendment 2c-G's three, cut from main after PR 1 (#863). - The close is admitted. admitted_dlv_close runs on PR 1's admit_reserve_mutation with facts None, and the builder derives the two 0x0024 same-transition credits. Its write set drains exactly the owner's ADMITTED reserve leaves at the parent generation, so the proceeds exist in R_econ. Before, they existed on the head only. - The one close commit derives, and no longer trusts its caller. commit_canonical_close(vault_id, composed, close_commitment, op) reads the parent, generation, reserves, parent binding and storage set off the composition through the pure close_plan, and holds the signed operation to them. It refuses: - a close whose parent a realized market successor consumed (it may not erase it); - later generations realized, or a generation beyond the frontier (no skip); - altered amounts; - a parent another candidate holds unrealized (an uncertified predecessor). Below the route gate, a close of the owner's stale baseline would otherwise have passed both core and an admission, because R_econ is exactly as stale as the head. finish_prepared_close keeps its resume-specific identity checks. - Core: advance refuses a DlvClose with no attached admission. fence_allows runs first, so a fenced head still gets the fence's own refusal. The dependents move to advance_admitted, including the table-driven malformed-close test. - Close before catch-up still refuses. Authority, QuorumBind, accepted-successor and close-auth are unchanged. - Lean DSMAdmittedClose is the 21st module, and ci.yml now expects 21. Docs: a Req 6.30 implementation note, and the producers in registry §5.34. Not here: G3, the fresh baseline anchor (PR 3).
cryptskii
added a commit
that referenced
this pull request
Sep 11, 2026
…ght-up V_k, history falls back to the immutable birth anchor (PR 3 of 3: G3) (#865) * feat(2c-G): the fresh owner baseline — strangers compose from the caught-up V_k, history falls back to the immutable birth anchor (G3) PR 3 of amendment 2c-G's three, cut from main after PR 2 (#864). It implements the owner's G3 ruling, the three implementation rulings, and the G3 blocker ruling, all recorded verbatim in §0. - After every catch-up, finished or stopped, the last FULLY materialized generation V_k becomes the owner's baseline. - plan_owner_baseline takes the walk's own certified V_k (never rebuilt, never supplied) and checks the ruling's validity conditions: vault, generation, parent link, reserves equal to the admitted leaves, the authenticated storage set, and canonical encoding. - The presentation comes from the birth baseline's owner-anchor machinery and is verified the way a stranger verifies it. - One transaction freezes the anchor, freezes a reserve proof built at the owner's admitted head, and switches the record's baseline and proof locator. The switch is local bookkeeping. - The advertisement moves, anchor and proof together, only once both are quorum-durable. The move is a read-modify-write that bumps updated_state_number. Until then the old baseline stays valid. - Blocker ruling. Moving the anchor made earlier settles unverifiable: lineage re-validation composed history from the CURRENT anchor. - The advertisement now also names the vault's immutable birth anchor, in field 20, transport only. It is recorded once at dlv.create and never moved. - A history walk composes from the current anchor when it is at or before the needed generation (from_generation, now on the core composed_vault_history seam). Otherwise it composes from birth, which must be this vault's birth state. - dsm_app_pb.ts was regenerated with the vendored protoc. - dlv.reconcile: replaying a settlement applied before the owner's baseline is satisfied by its consume-once claim. - Lean DSMFreshBaseline is the 22nd module; ci.yml now expects 22. The Req 6.31 note is updated. * test(2c-G): state what the same-generation short-circuit is — mutating it stays green because re-anchoring is byte-idempotent The move-and-compose test claimed that dropping the <= short-circuit in try_refresh_owner_baseline would turn its no-writes assertion red. It does not. Re-anchoring an already-anchored generation is byte-idempotent, because the presentation signature is deterministic, a freeze of an identical (key, digest) is a no-op, and the advertisement republish reports unchanged. The short-circuit saves work; it is not a gate. The doc comment now says so.
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.
PR 2 of 3 for amendment 2c-G, per the owner's delivery ruling of 2026-09-11. This PR implements G4: the admitted terminal close. It is cut from main after PR 1 (#863) merged, and PR 3 (G3, the re-anchor) follows once this one merges.
What this does
The close now runs on PR 1's economic-admission foundation rather than beside it.
The close is admitted.
admitted_dlv_closegoes through the sameadmit_reserve_mutationbody that funded create and owner apply use. Its facts are fixed atCreditSourceFacts::None: the builder derives the two0x0024same-transition-move credits itself.R_econ.R_econreserve leaf was never withdrawn, so close proceeds could fund no admitted operation.The one close commit derives every fact from the composition.
commit_canonical_closeis shared bydlv.closeand by the resume pass. It now takes only(vault_id, composed, close_commitment, op). A new pure function,close_plan:No caller supplies a reserve, generation, parent or storage set any more.
finish_prepared_closekeeps its resume-specific checks: the kind, the terminal commitment, and this device's fence identity. Its parent-binding derivation moves intoclose_plan.Core chokepoint.
advancenow refuses aDlvClosethat has no attached Prepared admission, as it already does for funded create and owner apply.advance_refuses_an_economic_write_while_an_admission_is_pendingis unchanged.advance_admitted:DlvCloseadvance outsidedevice_state.rs.Close before catch-up still refuses, as the survey recommended.
storage.syncordlv.reconcile. That catch-up consumes the certified frontier and is not approval of it.Boundaries kept (G4 ruling)
Not in this PR
AnchorPresentationV3after catch-up, is PR 3.Formal
lean4/DSMAdmittedClose.leanis the 21st module, andci.ymlnow expects 21. It is sorry-free and uses only thepropextandQuot.soundaxioms. It proves:Three mutation controls each make the kernel prove a named sample's negation, and the unmutated control refuses it:
Tests
These are targeted
--releaseruns, filtered by the module path of each edited module. CI is the board.dsmtypes::device_state::tests::: 68/0. This includes the newa_close_is_refused_without_its_own_attached_admissionand the dependents moved toadvance_admitted.every_malformed_close_is_refused_with_zero_mutationdrives its cases through one raw.advance(case.op …). My pattern-matching dependent sweep could not see that call; the module run caught it. The fix gives each case its own admission, so every case is refused by the check it names.dsm_sdklib:handlers::dlv_routes::: 57/0. This covers every existing close, resume and catch-up test, plus the two new ones:close_plan_takes_every_fact_of_a_close_from_the_composition. It checks the exact plan, then six named refusals: stale baseline, skipped generation, older parent with later generations realized, altered reserves, another vault, and uncertified predecessor.a_close_below_the_gate_drains_exactly_the_caught_up_frontier_or_nothing. It drives the one commit below the gate:close_plan;sdk::economic_admission_flow::: 1/0handlers::storage_routes::: 20/0 (1 ignored)a_contested_parent_refuses_the_close_and_moves_nothingstill covers the uncertified predecessor at the route: a rival bound at quorum and never realized.Mutation controls
Each mutation is applied to a byte copy of the source file. A named test is run against it, and the file is then restored and checked byte for byte.
DlvClosearm of the core fencea_close_is_refused_without_its_own_attached_admissionclose_planfold from a MARKET-consumed parentclose_plan_takes_every_fact_of_a_close_from_the_composition: "the stale baseline must not plan"close_plan's field-equality checka_close_below_the_gate_drains_exactly_the_caught_up_frontier_or_nothing: the proceeds-funded create is refused, because the proceeds never reachedR_econThe first two versions of G2 and G3 were invalid: they failed to compile rather than running.
dsm_sdkis#![deny(warnings)]:if trueguard that drops the only use ofBundleShapeleaves an import unused, which is an error.My first runner keyed compile detection on
error[and missed these errors, which carry no code. It now treats anycould not compileas an invalid control. The third definitions keep the import used and put a guarded arm ahead of the untouched ones. Both compile and go red.Gates:
make lint: exit 0. The one eslint warning is in frontend code this PR does not touch.ci/production_safety_checks.sh: exit 0. This covers clippy with production lints, plus TLA+.Docs
sofispecs.instructions.md: an implementation note under Req 6.30.ccb-object-registry.md§5.34: the0x0024producers, and the close now being admission-fenced.