Skip to content

feat(warp-core): plural settlement + theta_braid retained boundary shells (design 0026, E1)#539

Merged
flyingrobots merged 15 commits into
mainfrom
lane/0026-braid-shell-family
Jun 13, 2026
Merged

feat(warp-core): plural settlement + theta_braid retained boundary shells (design 0026, E1)#539
flyingrobots merged 15 commits into
mainfrom
lane/0026-braid-shell-family

Conversation

@flyingrobots

@flyingrobots flyingrobots commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Hill

Make lawful plurality a retainable, replayable outcome: settlement gains the Plural arm of the outcome algebra, and every braid-scope settlement act retains a θ_braid shell — an in-graph holographic boundary that replays without member strand histories (AIΩN Paper VII Prop 3.5, §4.2). The hostile replay test extracts the shells and drops the runtime, strand registry, and provenance entries entirely; replay reproduces the outcome arm, member verdicts, policy id, and witness from the shells alone.

Design packet: docs/design/0026-braid-shell-family-and-plural-settlement/design.md (reviewed twice by James: packet ENHANCE→APPROVE; θ_braid core APPROVE + ENHANCE-before-PR — all enhancements landed).

Doctrine issues: #537 (shell family, requirements 1–2), #538 (tier posture, E0-lite). Connective doctrine for #470/#476/#483 — this PR establishes the shell family they must reuse.

What landed (15 commits incl. a main-sync merge, RED-first throughout)

E0-lite posture core (revelation.rs): RevelationPosture { Scratch < AuthorOnly < Shared }, AuthorOnly default, widen-only witnessed promotion, least-revealed-member invariant.

Plural settlement (settlement.rs): SettlementDecision::PluralAlternative lowering to the existing AdmissionOutcomeKind::Plural; SettlementPolicy separates plural-settlement law from collapse law (Default = Refused = legacy behavior, regression-pinned byte-identically); the plural branch fires only where each claim applied lawfully on its own under explicit policy; the base never silently takes the strand's value; later entries block with ConflictReason::PluralUpstream; retention via ProvenanceEventKind::PluralArtifact; canonical slot ordering so permutation cannot move plural_id.

θ_braid shells (braid_shell.rs): four-arm BraidShellOutcome (collapse is Derived + collapsed_from lineage, never a fifth arm); members carry compact digest sets + verdict snapshots, never histories; domain-separated digests (echo.shell.braid.v1 / member / witness); version digest-bound and validated; canonical member and alternative-set ordering; posture floor at assembly and validation; replay_braid_shell through BraidShellRecords — a trait whose only method returns shells, so strand access is a type error.

Settlement emission: every non-empty settlement retains exactly one shell as its final fallible step (no-leak law tested); Plural outcomes carry the plural artifact ids (boundary→residue); plural_shell_index gives residue→boundary; empty settlement emits no shell by law; BraidShellQuery scan-backed query by basis/member/outcome/posture.

Collapse transition: collapse_braid_shell — named witnessed CollapsePolicy → new Derived shell with all-or-none lineage fields; missing policy → retained Obstruction shell (obstruction is also law); plural parent stays byte-identical; WitnessDigest refuses zero/empty digests.

One boundary family in code: RetainedBoundaryRecord/RetainedBoundaryKind implemented by both BoundaryTransitionRecord (θ_tick) and BraidShell (θ_braid).

ABI

Additive only: PluralAlternativeDraft, SettlementDecision::PluralAlternative, RevelationPosture, ConflictReason::PluralUpstream, SettlementResult.appended_plurals + braid_shell_digest (serde-default). No wire-format breakage; Rust exhaustive matches updated in-repo.

Verification

  • 518/518 warp-core tests (posture, shell-law, settlement — the five θ_braid gate tests, the first- and second-review tests incl. the late no-leak proof and BTR digest sensitivity, and the Code Lawyer remediation tests incl. checkpoint shell-map rollback and type-enforced witness)
  • workspace clean under -D warnings; clippy clean; fmt clean
  • every commit passed verify-local pre-commit; pushes passed the full-suite pre-push gate

Honesty notes

  • E1 structures are N-capable; behavior is pinned for two-participant settlement. N-strand weave is E3.
  • ProvenanceEventKind::PluralArtifact { plural_id } stays thin by design — the shell is the body; the index links the directions. Named debts (PluralUpstream→Obstruction migration, full E0 strand posture) recorded in the packet.

Summary by CodeRabbit

  • New Features
    • Plural settlement alternatives: Settlements can now retain lawful plural outcomes when policy permits.
    • Settlement replay and validation: Past settlements can be revalidated and replayed deterministically.
    • Policy-driven settlement: New explicit policy controls for settlement decision-making.
    • Enhanced settlement querying: Query and track settlement artifacts by outcome and member involvement.

E1 of the strand/braid campaign (echo#537 requirements 1-2, #538 rider):
SettlementDecision::Plural + in-graph theta_braid shells in the
BoundaryTransitionRecord family, replay-from-shell as the acceptance
test. Source facts verified @465cf61e. Awaiting packet + test-plan
review before RED.
…ready exists

admission.rs#150-152@465cf61e mints the Plural discriminant at admission
scope; the slice extends the algebra to settlement scope with no new ABI
discriminant.
ENHANCE->APPROVE verdict applied in full:
- outcome algebra is Derived/Plural/Conflict/Obstruction only; collapse
  is a witnessed transition emitting a new Derived shell with
  collapsed_from lineage, never a fifth arm
- plural-settlement policy and collapse policy explicitly separated
  with the four-rule block
- BraidShell made replay-sufficient: canonical member entries carry
  support-pin/basis/frontier/footprint/claim digests + compact verdict
  snapshots; no entry vectors, no histories
- Obstruction included in shell emission scope; shells append-only
- canonical member ordering + domain-separated digests
  (echo.shell.braid.v1 etc.) + permutation/tamper/query tests
- E0-lite posture core (RevelationPosture, author-only default,
  least-revealed-member invariant) pinned as first commit of E1
- N-strand honesty rule; serialization variant-tag requirement; ABI
  wording corrected to wire-format-only claim
- enhanced 12-item acceptance criteria + 11-item test plan adopted
Three-Tier Thinking Room substrate (Paper VII 6.3, echo#538) required
before any theta_braid shell lands, per design packet 0026 resolved
question 1:

- RevelationPosture { Scratch < AuthorOnly < Shared } with AuthorOnly
  default — nothing ships with implicit shared visibility; stable
  canonical wire tags for digest domains
- promote_posture: posture only widens, explicitly and witnessed;
  narrowing and same-posture requests are typed PostureObstructions,
  never silent no-ops
- least-revealed-member invariant via shell_posture_obstruction: a
  composite shell cannot reveal more than its least-revealed member
- 10 unit tests; clippy-clean (remaining repo clippy errors are
  pre-existing in coordinator.rs, untouched here)

Part of lane/0026-braid-shell-family (E1). theta_braid and
SettlementDecision::Plural build on these nouns next.
…fact (0026)

Type surface + failing tests for SettlementDecision::Plural per the
approved 0026 test plan (items 1, 5, 7 + regression pin):

- SettlementDecision::PluralAlternative(PluralAlternativeDraft) lowering
  to the existing AdmissionOutcomeKind::Plural; draft carries source ref,
  contended slots, policy id, and RevelationPosture (default AuthorOnly)
- SettlementPolicy { policy_id, plural } separates plural-settlement law
  from any future collapse policy; Default = Refused (today's behavior)
- plan_with_policy / settle_with_policy entries; plan()/settle()
  delegate with the default policy — legacy paths regression-pinned by
  default_policy_plan_matches_legacy_plan_exactly
- ProvenanceEventKind::PluralArtifact retained-residue event kind;
  append_plural_artifact mirrors conflict retention (no-op patch — the
  base never silently takes the strand's value)
- ConflictReason::PluralUpstream (code 6): later suffix entries cannot
  import past retained plurality
- ABI: PluralAlternativeDraft + PluralAlternative variant +
  RevelationPosture + ConflictReason::PluralUpstream +
  SettlementResult.appended_plurals (serde default — wire-additive)

RED: settlement_plans_plural_alternative_under_explicit_plural_policy
and settlement_retains_plural_artifact_without_collapsing_base_state
fail (plan still emits conflict under plural policy); 7 legacy tests
green. GREEN flips the overlap-not-clean branch next.
…print overlap (0026)

Flips the overlap-not-clean branch: when each claim applied lawfully on
its own and an explicit plural-settlement policy permits coexistence,
the strand's claim is retained as SettlementDecision::PluralAlternative
instead of conflict residue. The base worldline never silently takes
the strand's value; later suffix entries are blocked with
ConflictReason::PluralUpstream rather than importing past retained
plurality.

plural_id is domain-separated (echo:settlement-plural-artifact:v1) over
target worldline, source coordinate, contended-slots digest, and policy
id — deterministic across runs and input orderings of the same facts.

All 9 settlement tests green (2 RED tests now pass; 7 legacy pinned);
workspace clean under -D warnings.
…rine notes

Checkpoint review corrections (0026):
- settlement_overlap_slots_digest sorts slots by canonical byte key
  before hashing; plural_draft canonicalizes the retained slot vec.
  New test: slot permutation cannot move plural_id or overlap digest.
- Packet records the E1a hierarchy invariant (PluralAlternative is
  per-entry residue; theta_braid is the plural settlement boundary;
  BraidShell is the replayable outcome) plus named debts: thin
  PluralArtifact event kind, PluralUpstream->Obstruction migration,
  posture witness quality bar.
…gate (0026)

The braid shell module lands fully implemented as pure record law —
shells are data discipline, not behavior — with 6 tests green:

- BraidShell/BraidShellMember/BraidShellOutcome over the four-arm
  algebra; collapse is Derived-with-collapsed_from lineage, never a
  fifth arm; members carry compact digest sets + verdict snapshots,
  never histories
- domain-separated digests (echo.shell.braid.v1, echo.braid.member.v1,
  echo.braid.witness.v1); canonical member ordering (permutation cannot
  move the shell digest); witness + shell digests recomputed on
  validate(), so tampering with policy/posture/verdict/outcome fails
- posture floor enforced at assembly and validation (shell cannot
  reveal more than its least-revealed member)
- replay_braid_shell reproduces outcome arm + member verdicts through
  BraidShellRecords — a trait whose only method returns shells, so
  strand-history access is a type error; collapse lineage requires a
  retained Plural parent
- ProvenanceService retains shells append-only (validated, idempotent,
  divergent-content refused) with query iterator and take_braid_shells
  for hostile replay proofs

RED (3 settlement gate tests fail — emission not wired):
- plural settlement retains exactly one shell with full body
- shell replays after runtime, registry, and provenance are dropped
- derived and conflict settlements also retain shells

SettlementResult.braid_shell: Option<Hash> (always None until GREEN);
ABI braid_shell_digest serde-default additive.
…ells (0026)

Every non-empty settlement act now retains exactly one theta_braid
shell as its final fallible step (a failed settle restores entries
before any shell describing them could land):

- one member per settled strand (N-capable structures; E3 owns weave):
  verdict = plural > conflict > derived precedence over the per-entry
  decisions; verdict digest binds the full ordered decision sequence;
  claim digest binds ordered source commit hashes; basis / frontier /
  footprint / support-pin digests domain-separated
- outcome arm follows the algebra: Plural carries the retained plural
  artifact ids (linking the boundary to its per-entry residue),
  Conflict carries ordered reason codes, Derived carries the appended
  import refs
- the sacred test passes: after settling under plural policy, the
  shells are extracted and the runtime, strand registry, and provenance
  entries are dropped — replay_braid_shell reproduces the outcome arm,
  member verdicts, and policy id from the shells alone

497/497 warp-core tests green; workspace clean under -D warnings.
…_braid review (0026)

Must-fixes:
- shell version is digest-bound (hash_shell_body hashes the stored
  version) AND explicitly validated (UnsupportedVersion); tamper test
- one retained boundary family made explicit in code:
  RetainedBoundaryRecord trait + RetainedBoundaryKind implemented for
  both BoundaryTransitionRecord (tick, echo.shell.tick.v1 digest) and
  BraidShell — theta_tick and theta_braid are visible siblings
- no-leak law encoded as test: failed settlement retains no shell
- residue->shell direction: plural_shell_index on ProvenanceService;
  braid_shell_for_plural resolves a plural artifact id to its boundary
  without scanning (no archaeology)
- empty-settlement law named and tested: no claims means no braid
  outcome; an empty settlement emits no shell by law

Should-fixes:
- plural alternative_ids are a canonical set: sorted at assembly,
  NonCanonicalAlternativeOrder on validation; permutation test
- support pins sorted before digesting (tuition paid once)
- claim_digest binds the full source coordinate (worldline, tick,
  commit), not commit hash alone
- first-class query API: BraidShellQuery + query_braid_shells
  (scan-backed), tested by member/outcome/posture

Collapse transition (append-only or bust):
- WitnessDigest newtype refuses zero and empty-input digests — a
  witness is never a 32-byte shrug
- collapse_braid_shell: named CollapsePolicy -> new Derived shell with
  collapse_policy + collapse_witness + collapsed_from, plural parent
  byte-identical; missing policy -> retained Obstruction shell
  (CollapseResult::Obstructed), because obstruction is also law
- Derived lineage fields are all-or-none (IncoherentCollapseFields);
  collapse-derived shells may summarize the plural members they
  collapsed; settlement-derived shells may not

508/508 warp-core tests; workspace clean under -D warnings.
…trait, canonical sets, residue links, collapse)
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces plural settlement outcomes with retained, replayable braid shells and revelation posture tracking. Plural alternatives are now a first-class settlement decision encoded in θ_braid shells, which canonicalize member ordering, compute deterministic digests, enforce posture floor constraints, and support append-only collapse lineage. The system integrates with provenance service for plural artifact resolution and with settlement planning/execution under explicit policies.

Changes

Plural Settlement and Braid Shell System

Layer / File(s) Summary
ABI Data Model: Plural Settlement Types
crates/echo-wasm-abi/src/kernel_port.rs
RevelationPosture enum, PluralAlternativeDraft struct with plural ID/source/channel metadata, SettlementDecision::PluralAlternative variant, and SettlementResult extensions for appended_plurals and braid_shell_digest (with serde defaults).
Revelation Posture Semantics
crates/warp-core/src/revelation.rs
RevelationPosture tiers (Scratch/AuthorOnly/Shared) with canonical wire tags, PosturePromotion auditable records, PostureObstruction error variants for narrowing/no-op/composite violations, and enforcement functions: least_revealed computes minimum posture from members; shell_posture_obstruction enforces floor constraint; promote_posture witnesses explicit promotions only when strictly widening.
Braid Shell Data Model and Validation
crates/warp-core/src/braid_shell.rs (lines 1–728)
BraidShellMember/BraidShellOutcome with member digest and outcome-kind hashing, MemberVerdict tagging, BraidCoordinate and WitnessDigest types, and BraidShell record with canonical member/plural-alternative ordering, outcome/member coherence validation (including collapse lineage all-or-none rules), and posture floor constraint checking via assemble and validate.
Braid Shell Digest and Boundary Integration
crates/warp-core/src/braid_shell.rs (lines 638–928)
Deterministic shell-body hashing binding version, worldline, basis, ordered member digests, policy id, outcome, posture, and witness; RetainedBoundaryKind/RetainedBoundaryRecord abstraction for braid shells; and tick-boundary retained record digest with event-kind discriminators and full payload hashing.
Braid Shell Replay, Collapse, and Query
crates/warp-core/src/braid_shell.rs (lines 713–1051)
BraidShellRecords trait and lookup by digest; replay_braid_shell loads/validates shells without accessing strand histories and verifies collapse/obstruction lineage parent existence; collapse_braid_shell produces Derived shells (witnessed policy + collapsed_from) or Obstruction shells (deterministic reason + witness domain) without mutating the plural parent; BraidShellQuery and matches filter by coordinate/basis/member/outcome/posture.
Settlement Policy and Plural-Aware Planning
crates/warp-core/src/settlement.rs (lines 34–121, 206–231, 677–816)
PluralSettlementPolicy and SettlementPolicy with stable policy_id and allow_plural_over_footprint_overlap constructor; ConflictReason::PluralUpstream variant; plan_with_policy entry point; planning branch that emits PluralAlternative decisions (instead of conflicts) when policy permits plural outcomes over footprint overlap.
Settlement Execution and Braid Shell Construction
crates/warp-core/src/settlement.rs (lines 857–1468)
settle_with_policy entry point with appended_plurals tracking; append_plural_artifact appending ProvenanceEventKind::PluralArtifact events; build_braid_shell binding plural/conflict/derived member verdicts, computing plural artifact ID from overlapping-slot canonicalized digest + policy, and retaining exactly one braid shell per non-empty settlement with claims.
Settlement Result Types and Error Handling
crates/warp-core/src/settlement.rs (lines 354–384, 604–606)
SettlementResult extended with appended_plurals and optional braid_shell digest; ABI conversion includes braid_shell_digest; SettlementError::BraidShell variant; and overlap-slot digest canonicalization ensuring order-independent plural ID and overlap digest generation.
Provenance Service Braid Shell Storage and Lookup
crates/warp-core/src/provenance_store.rs
ProvenanceEventKind::PluralArtifact { plural_id } variant; ProvenanceService internal storage (braid_shells map, plural_shell_index); BraidShellRecords trait implementation; append_braid_shell with idempotency and plural-id rebinding prevention; lookup by plural artifact id, query iteration, digest access, and take_braid_shells atomic extraction.
Coordinator and Crate-Level Integration
crates/warp-core/src/coordinator.rs, crates/warp-core/src/lib.rs
hash_provenance_event_kind recognizes PluralArtifact variant; lib.rs declares braid_shell and revelation modules and re-exports braid-shell types/functions, revelation posture/helpers, and settlement policy items.
Witnessed Suffix ABI Conversion
crates/warp-core/src/witnessed_suffix.rs
conflict_reason_to_abi maps ConflictReason::PluralUpstream to ABI abi::ConflictReason::PluralUpstream.
Settlement Test Suite Expansion
crates/warp-core/src/settlement.rs (lines 1779–2723)
New tests validating plural planning under explicit policy, braid-shell retention/replay for plural/derived/conflict settlements, empty/no-suffix settlement law (no shell emission), rollback on braid-shell failure, braid-shell resolution and queryability by member outcome/posture, and slot-order invariance of plural IDs and overlap digests.
Design Specification 0026
docs/design/0026-braid-shell-family-and-plural-settlement/design.md
Full specification defining retained θ_braid shell family, SettlementDecision::Plural arm aligned to AdmissionOutcomeKind::Plural, BraidShell structure and canonicalization rules, replay-from-shell semantics without strand histories, posture promotion/least-revealed defaults, append-only collapse lineage, acceptance criteria, enhanced test plan, design notes, and resolved review questions.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Poem

A braid is woven, witnessed true,
Shells collapsing what once were few,
Plural paths now found and stored,
Replayed from digest, posture assured,
Determinism in the weave. 🧵✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main feature: plural settlement and theta_braid retained boundary shells, with design reference (0026) and phase marker (E1).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch lane/0026-braid-shell-family

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Blockers:
1. BoundaryTransitionRecord::boundary_digest is now a full canonical
   content digest: payload coordinates, every entry's coordinate, event
   kind, head key, parents, and hash triplet, plus the auth tag — a
   record digest, not a vibes checksum
2. WitnessDigest side door closed: check_outcome_law applies the
   newtype bar to collapse_witness and obstruction witnesses in both
   assemble() and validate(); empty-witness shells refuse to exist
3. plural_shell_index is append-only: a plural artifact id may never
   migrate to a different shell (PluralArtifactAlreadyBound); bindings
   are checked before anything inserts, so refusal leaves no partial
   state
4. take_braid_shells clears the residue index — no stale archaeology
5. BraidCoordinate(hash(basis, canonical member digests, policy_id))
   stored on every shell, recomputed at validation
   (CoordinateMismatch), queryable via BraidShellQuery.coordinate —
   EchoCoordinate::Braid stops being decorative

Should-fixes:
- Obstruction outcomes carry obstructed_from: Option<Hash>; no-policy
  collapse names its plural parent; replay verifies obstruction lineage
  the same way it verifies collapse lineage
- duplicate alternative_ids refused (a sorted list with duplicates is
  not a set, it is a list wearing a fake mustache)
- duplicate member strands refused (N-capable invariant landed now)
- late no-leak proof: pre-binding the deterministic plural id forces
  shell retention to fail AFTER entries append; test proves entries and
  frontier roll back, no shell leaks, index unchanged

516/516 warp-core tests; workspace clean under -D warnings.
@flyingrobots

Copy link
Copy Markdown
Owner Author

All five blockers and all four should-fixes landed in 81501d1 (516/516 warp-core tests, workspace clean under -D warnings):

Blockers

  1. BTR digest is now a full canonical content digest — payload coordinates, every entry's coordinate + event kind + head key + parents + hash triplet, plus auth_tag. The doc comment now says it out loud: "a record digest, not a vibes checksum." (Note: each entry's commit_hash transitively binds its patch digest/state root/parents via compute_commit_hash_v2, but the coordinates and event facts are bound explicitly per your enumeration.)
  2. Side door closedcheck_outcome_law applies WitnessDigest::new to collapse_witness and obstruction witnesses in both assemble() and validate(). Tests: derived_shell_rejects_empty_collapse_witness, obstruction_shell_rejects_empty_witness. The bouncer now guards every door.
  3. plural_shell_index is append-onlyPluralArtifactAlreadyBound { plural_id, existing_shell, attempted_shell }; all bindings checked before anything inserts, so refusal leaves no partial state. Idempotent re-append still fine.
  4. take_braid_shells clears the index — no stale archaeology.
  5. BraidCoordinate existshash(basis, canonical_member_digest_list, policy_id) under echo.braid.coordinate.v1, stored on every shell, recomputed at validation (CoordinateMismatch, tamper-tested), queryable via BraidShellQuery.coordinate. EchoCoordinate::Braid is no longer decorative.

Should-fixes
6. Obstruction outcomes carry obstructed_from: Option<Hash>; no-policy collapse names its plural parent, and replay verifies obstruction lineage exactly like collapse lineage (parent retained + plural).
7. Duplicate alternative_ids refused (DuplicateAlternativeId) at assembly and validation — no fake mustaches.
8. Duplicate member strands refused (DuplicateMemberStrand) — the N-capable invariant landed now rather than deferred.
9. Late no-leak prooflate_shell_retention_failure_rolls_back_entries_and_leaks_nothing: the test pre-binds the settlement's deterministic plural id to a dummy shell, so the real settlement's shell append fails after entries append. Asserts: entries restored, frontier restored, no shell leaked, index unchanged. Belt, suspenders, and the pants demonstrably exist.

One emergent interaction worth noting: tampering a member's verdict_digest now fails at CoordinateMismatch before reaching the witness/digest checks (member digests feed the coordinate) — strictly earlier refusal; the tamper test accepts any of the three.

Ready for re-review.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/warp-core/src/witnessed_suffix.rs (1)

1084-1113: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Align overlap-slot digesting with canonical ordering across modules.

conflict_reason_to_abi now includes PluralUpstream, but this module’s settlement_overlap_slots_digest is still order-sensitive. crates/warp-core/src/settlement.rs canonicalizes slot bytes before hashing; this one does not. The same overlap set can emit different overlapping_slots_digest values depending on path, which breaks deterministic cross-surface contracts.

Suggested fix (make witnessed-suffix digest canonical like settlement)
 fn settlement_overlap_slots_digest(slots: &[SlotId]) -> Hash {
+    let mut encoded: Vec<Vec<u8>> = slots.iter().map(canonical_slot_bytes).collect();
+    encoded.sort_unstable();
     let mut hasher = Hasher::new();
     hasher.update(b"echo:settlement-overlap-slots:v1\0");
-    hasher.update(&len_to_u64(slots.len()).to_le_bytes());
-    for slot in slots {
-        hash_settlement_slot(&mut hasher, slot);
+    hasher.update(&len_to_u64(encoded.len()).to_le_bytes());
+    for slot_bytes in &encoded {
+        hasher.update(slot_bytes);
     }
     hasher.finalize().into()
 }
 
-fn hash_settlement_slot(hasher: &mut Hasher, slot: &SlotId) {
+fn canonical_slot_bytes(slot: &SlotId) -> Vec<u8> {
+    let mut bytes = Vec::new();
     match slot {
         SlotId::Node(node) => {
-            hasher.update(&[1]);
-            hasher.update(node.warp_id.as_bytes());
-            hasher.update(node.local_id.as_bytes());
+            bytes.push(1);
+            bytes.extend_from_slice(node.warp_id.as_bytes());
+            bytes.extend_from_slice(node.local_id.as_bytes());
         }
         SlotId::Edge(edge) => {
-            hasher.update(&[2]);
-            hasher.update(edge.warp_id.as_bytes());
-            hasher.update(edge.local_id.as_bytes());
+            bytes.push(2);
+            bytes.extend_from_slice(edge.warp_id.as_bytes());
+            bytes.extend_from_slice(edge.local_id.as_bytes());
         }
         SlotId::Attachment(attachment) => {
-            hasher.update(&[3]);
+            bytes.push(3);
             match attachment.owner {
                 AttachmentOwner::Node(node) => {
-                    hasher.update(&[1]);
-                    hasher.update(node.warp_id.as_bytes());
-                    hasher.update(node.local_id.as_bytes());
+                    bytes.push(1);
+                    bytes.extend_from_slice(node.warp_id.as_bytes());
+                    bytes.extend_from_slice(node.local_id.as_bytes());
                 }
                 AttachmentOwner::Edge(edge) => {
-                    hasher.update(&[2]);
-                    hasher.update(edge.warp_id.as_bytes());
-                    hasher.update(edge.local_id.as_bytes());
+                    bytes.push(2);
+                    bytes.extend_from_slice(edge.warp_id.as_bytes());
+                    bytes.extend_from_slice(edge.local_id.as_bytes());
                 }
             }
             match attachment.plane {
-                AttachmentPlane::Alpha => hasher.update(&[1]),
-                AttachmentPlane::Beta => hasher.update(&[2]),
-            };
+                AttachmentPlane::Alpha => bytes.push(1),
+                AttachmentPlane::Beta => bytes.push(2),
+            }
         }
         SlotId::Port((warp_id, port_key)) => {
-            hasher.update(&[4]);
-            hasher.update(warp_id.as_bytes());
-            hasher.update(&port_key.to_le_bytes());
+            bytes.push(4);
+            bytes.extend_from_slice(warp_id.as_bytes());
+            bytes.extend_from_slice(&port_key.to_le_bytes());
         }
     }
+    bytes
 }

As per coding guidelines: crates/warp-core/** is the deterministic kernel, so canonical ordering must hold across all deterministic paths.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/warp-core/src/witnessed_suffix.rs` around lines 1084 - 1113, The
overlap-slot digest in settlement_overlap_slots_digest is order-sensitive but
must be canonicalized like in settlement.rs; change it to first convert each
SlotId into its canonical hashed-bytes (using the same hash_settlement_slot
transformation/format), collect those byte sequences into a Vec, sort them
lexicographically, then feed the sorted byte sequences (with the same
"echo:settlement-overlap-slots:v1\0" prefix and len_to_u64 count) into the
Hasher before finalizing so the digest matches settlement.rs for the same set
regardless of input order.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/warp-core/src/braid_shell.rs`:
- Around line 154-170: Derived::result_refs are included in shell identity
without canonicalization, causing equivalent shells with refs in different
orders to produce different digests; update hash_into (the match arm for
Self::Derived) to canonicalize/sort result_refs before hashing (e.g., sort by a
stable key derived from each ProvenanceRef) so hash_provenance_ref is called on
a deterministic order, and ensure the same canonicalization is applied where
refs are forwarded (e.g., collapse_braid_shell's selected_result_refs) and where
validate checks equality so comparison uses the canonical form; use existing
helpers hash_provenance_ref and hash_optional_digest and pick a stable
comparator (e.g., digest or tuple of fields) to order ProvenanceRef instances.
- Around line 121-125: BraidShellOutcome::Plural must be rejected when
alternative_ids is empty: add a check in the shell validation/assembly path (the
functions named assemble and validate that process BraidShellOutcome) to return
an error if a Plural variant has alternative_ids.is_empty(), and update any code
paths that assume a valid plural (e.g., braid_shell_for_plural and
ProvenanceService::append_braid_shell) to rely on that validation so no plural
shell without alternative_ids is persisted or causes missing plural_shell_index
entries; ensure the error path prevents storing/plumbing plural shells with
empty alternative_ids.

In `@crates/warp-core/src/provenance_store.rs`:
- Around line 1751-1788: append_braid_shell currently only runs shell.validate()
but must also reject shells whose collapsed_from or obstructed_from point to
missing or non-Plural parents before persisting; update append_braid_shell to,
prior to inserting into self.braid_shells, check any shell.collapsed_from and
shell.obstructed_from (and any plural parent ids in the outcome) against
self.braid_shells and ensure the referenced parent exists and its outcome is
crate::braid_shell::BraidShellOutcome::Plural (or otherwise acceptable),
returning an appropriate crate::braid_shell::BraidShellError if the parent is
absent or has the wrong outcome so we never persist shells that cannot replay in
replay_braid_shell.

In `@docs/design/0026-braid-shell-family-and-plural-settlement/design.md`:
- Around line 145-155: Update the "Planned shape" pseudocode for
BraidShellOutcome::Derived to match the implemented variant in
crates/warp-core/src/braid_shell.rs: change result_ref to result_refs:
Vec<ProvenanceRef>, rename PolicyRef to Hash (collapse_policy: Option<Hash>),
add collapse_witness: Option<Hash>, and ensure collapsed_from uses Hash; make
the types and field names (result_refs, collapse_policy, collapse_witness,
collapsed_from) consistent with the code so the design section reflects the
actual BraidShellOutcome::Derived structure.
- Around line 161-171: Clarify and codify whether RevelationPosture exists at
shell-level, member-level, or both: update the design text and the planned shape
so BraidShell either (A) has no posture field and its visibility is derived as
shell.posture = min(member.posture for member in BraidShell.members) (the
"least-revealed-member" invariant), or (B) has an explicit posture field that
must be kept consistent with member postures via rules (e.g., shell.posture is
initialized to min(member.postures) and any shell-level promotion to Shared
requires a witnessed shell-level transform that optionally also promotes
member.postures); reference the types BraidShell, BraidShellMember,
RevelationPosture, the "least-revealed-member" invariant, and digest/replay
semantics so the doc states exactly which posture(s) are canonical for digesting
and when witnessed promotions apply.
- Around line 182-186: Update the design doc to state that canonical member
ordering is strictly ascending by BraidShellMember::member_digest (not the
4-tuple), matching the implementation in BraidShell::assemble which calls
members.sort_by_key(BraidShellMember::member_digest) and the validate() check
that errors on any prior > current; remove or replace the “sort key:
basis_digest, strand_ref, support_pin_digest, claim_digest” text unless you
explicitly redefine that 4-tuple to include every field hashed by member_digest
(e.g., frontier_digest, footprint_digest, verdict tag/digest, posture) so it
exactly matches BraidShellMember::member_digest().

---

Outside diff comments:
In `@crates/warp-core/src/witnessed_suffix.rs`:
- Around line 1084-1113: The overlap-slot digest in
settlement_overlap_slots_digest is order-sensitive but must be canonicalized
like in settlement.rs; change it to first convert each SlotId into its canonical
hashed-bytes (using the same hash_settlement_slot transformation/format),
collect those byte sequences into a Vec, sort them lexicographically, then feed
the sorted byte sequences (with the same "echo:settlement-overlap-slots:v1\0"
prefix and len_to_u64 count) into the Hasher before finalizing so the digest
matches settlement.rs for the same set regardless of input order.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 82033a4f-f02a-4b46-9bb6-a66c23b2631e

📥 Commits

Reviewing files that changed from the base of the PR and between 465cf61 and 81501d1.

📒 Files selected for processing (9)
  • crates/echo-wasm-abi/src/kernel_port.rs
  • crates/warp-core/src/braid_shell.rs
  • crates/warp-core/src/coordinator.rs
  • crates/warp-core/src/lib.rs
  • crates/warp-core/src/provenance_store.rs
  • crates/warp-core/src/revelation.rs
  • crates/warp-core/src/settlement.rs
  • crates/warp-core/src/witnessed_suffix.rs
  • docs/design/0026-braid-shell-family-and-plural-settlement/design.md

Comment on lines +121 to +125
/// Multiple lawful alternatives remain retained.
Plural {
/// Stable plural artifact ids of the retained alternatives.
alternative_ids: Vec<Hash>,
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Refuse Plural shells that carry no alternative_ids.

Right now BraidShellOutcome::Plural { alternative_ids: vec![] } passes assemble/validate as long as one member verdict is Plural. That leaves you with a retained plural shell that has no residue→shell mapping material to index, and ProvenanceService::append_braid_shell will store it without inserting any plural_shell_index entries.

Based on docs/design/0026-braid-shell-family-and-plural-settlement/design.md, plural shells are supposed to list plural artifact ids so braid_shell_for_plural can resolve residue → shell.

Also applies to: 404-417, 488-501

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/warp-core/src/braid_shell.rs` around lines 121 - 125,
BraidShellOutcome::Plural must be rejected when alternative_ids is empty: add a
check in the shell validation/assembly path (the functions named assemble and
validate that process BraidShellOutcome) to return an error if a Plural variant
has alternative_ids.is_empty(), and update any code paths that assume a valid
plural (e.g., braid_shell_for_plural and ProvenanceService::append_braid_shell)
to rely on that validation so no plural shell without alternative_ids is
persisted or causes missing plural_shell_index entries; ensure the error path
prevents storing/plumbing plural shells with empty alternative_ids.

Comment thread crates/warp-core/src/braid_shell.rs
Comment on lines +1751 to +1788
pub fn append_braid_shell(
&mut self,
shell: crate::braid_shell::BraidShell,
) -> Result<Hash, crate::braid_shell::BraidShellError> {
shell.validate()?;
let digest = shell.digest;
if let Some(existing) = self.braid_shells.get(&digest) {
if *existing != shell {
return Err(
crate::braid_shell::BraidShellError::DuplicateDigestDivergentContent { digest },
);
}
return Ok(digest);
}
// Index bindings are append-only retained truth: a plural artifact
// id may never migrate to a different shell. Check every binding
// before inserting anything so a refused append leaves no partial
// state behind.
if let crate::braid_shell::BraidShellOutcome::Plural { alternative_ids } = &shell.outcome {
for plural_id in alternative_ids {
if let Some(existing) = self.plural_shell_index.get(plural_id) {
if *existing != digest {
return Err(
crate::braid_shell::BraidShellError::PluralArtifactAlreadyBound {
plural_id: *plural_id,
existing_shell: *existing,
attempted_shell: digest,
},
);
}
}
}
for plural_id in alternative_ids {
self.plural_shell_index.insert(*plural_id, digest);
}
}
self.braid_shells.insert(digest, shell);
Ok(digest)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reject invalid collapse lineage before persisting the shell.

append_braid_shell only calls shell.validate(), which is intra-record. A shell with collapsed_from or obstructed_from pointing at a missing or non-Plural parent is accepted here and only fails later when replay_braid_shell checks lineage. That leaves durable store state containing shells that can never replay. Validate the referenced parent against self.braid_shells before insertion.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/warp-core/src/provenance_store.rs` around lines 1751 - 1788,
append_braid_shell currently only runs shell.validate() but must also reject
shells whose collapsed_from or obstructed_from point to missing or non-Plural
parents before persisting; update append_braid_shell to, prior to inserting into
self.braid_shells, check any shell.collapsed_from and shell.obstructed_from (and
any plural parent ids in the outcome) against self.braid_shells and ensure the
referenced parent exists and its outcome is
crate::braid_shell::BraidShellOutcome::Plural (or otherwise acceptable),
returning an appropriate crate::braid_shell::BraidShellError if the parent is
absent or has the wrong outcome so we never persist shells that cannot replay in
replay_braid_shell.

Comment thread docs/design/0026-braid-shell-family-and-plural-settlement/design.md
Comment on lines +161 to +171
**E0-lite posture core (first commit of E1):**

```rust
enum RevelationPosture { Scratch, AuthorOnly, Shared }
```

Default `AuthorOnly`. Promotion to `Shared` is an explicit witnessed act.
Invariant: **a braid shell cannot reveal more than its least-revealed
member** unless a witnessed redaction/promotion transform exists. Posture
is load-bearing, not cosmetic: it affects query, replay digests, promotion,
and visibility.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clarify posture field presence in BraidShell struct.

Lines 161–171 describe RevelationPosture (E0-lite posture core) with default AuthorOnly, promotion as explicit witnessed act, and least-revealed-member invariant. However, the "Planned shape" pseudocode for BraidShell (line 128) includes posture: RevelationPosture, but the description at lines 163–171 does not explicitly state whether the posture is:

  • A shell-level field (single per shell, reflecting the shell's visibility boundary)
  • A member-level field (per BraidShellMember, line 142)
  • Both

The E0-lite description is correct in principle, but the interaction between shell-level posture (if present) and member-level posture (line 142) under the "least-revealed-member" invariant needs clarification. Does the shell's posture always equal the minimum of member postures, or is it separately witnessed/promoted?

This affects replay visibility and digesting (lines 185–186 claim digest domains include posture), so the scope must be explicit in the design.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design/0026-braid-shell-family-and-plural-settlement/design.md` around
lines 161 - 171, Clarify and codify whether RevelationPosture exists at
shell-level, member-level, or both: update the design text and the planned shape
so BraidShell either (A) has no posture field and its visibility is derived as
shell.posture = min(member.posture for member in BraidShell.members) (the
"least-revealed-member" invariant), or (B) has an explicit posture field that
must be kept consistent with member postures via rules (e.g., shell.posture is
initialized to min(member.postures) and any shell-level promotion to Shared
requires a witnessed shell-level transform that optionally also promotes
member.postures); reference the types BraidShell, BraidShellMember,
RevelationPosture, the "least-revealed-member" invariant, and digest/replay
semantics so the doc states exactly which posture(s) are canonical for digesting
and when witnessed promotions apply.

Comment on lines +182 to +186
**Determinism:** members are canonically ordered (sort key:
`basis_digest, strand_ref, support_pin_digest, claim_digest` — or a single
canonical `member_digest`). Digest domains are explicit and separated:
`echo.shell.tick.v1`, `echo.shell.braid.v1`, `echo.shell.import.v1`,
`echo.braid.member.v1`, `echo.braid.witness.v1`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Show the referenced doc snippet with line numbers
echo "=== docs/design/0026-braid-shell-family-and-plural-settlement/design.md (182-200) ==="
sed -n '170,210p' docs/design/0026-braid-shell-family-and-plural-settlement/design.md | nl -ba

# 2) Find where these digest/sort key fields are implemented/used in code
echo
echo "=== rg: basis_digest / strand_ref / support_pin_digest / claim_digest / member_digest ==="
rg -n --hidden --no-ignore-vcs -S "basis_digest|strand_ref|support_pin_digest|claim_digest|member_digest" .

# 3) Narrow to likely ordering/sorting code patterns
echo
echo "=== rg: sort / ordering / canonically / canonical / deterministic / member_digest ==="
rg -n --hidden --no-ignore-vcs -S "(sort|sorted|ordering|ordered|canonically|canonical|deterministic|determinism).*(basis_digest|strand_ref|support_pin_digest|claim_digest|member_digest)" . || true

# 4) Specifically look for braid/member ordering structures if they exist
echo
echo "=== rg: braid.*member.*(sort|order|ordered|digest) ==="
rg -n --hidden --no-ignore-vcs -S "braid.*member.*(sort|order|ordered|digest)" . || true

Repository: flyingrobots/echo

Length of output: 208


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== docs design snippet (requested range) ==="
sed -n '170,210p' docs/design/0026-braid-shell-family-and-plural-settlement/design.md

echo
echo "=== rg: digest field names (find ordering/sort usage) ==="
rg -n --hidden --no-ignore-vcs -S "basis_digest|strand_ref|support_pin_digest|claim_digest|member_digest" .

echo
echo "=== rg: ordering/canonical determinism hints ==="
rg -n --hidden --no-ignore-vcs -S "(sort|sorted|ordering|ordered|canonically|canonical|deterministic|determinism)" docs src . || true

echo
echo "=== rg: braid/member ordering code ==="
rg -n --hidden --no-ignore-vcs -S "braid.*member.*(sort|order|ordered|digest)" . || true

Repository: flyingrobots/echo

Length of output: 50439


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== crates/warp-core/src/braid_shell.rs: member_digest + member ordering ==="
sed -n '1,160p' crates/warp-core/src/braid_shell.rs
echo
sed -n '280,520p' crates/warp-core/src/braid_shell.rs

echo
echo "=== Narrow search for sort calls in braid_shell.rs ==="
rg -n "sort_by_key|sort_by\(|canonical_member_digest_list|member_digest\(\)" crates/warp-core/src/braid_shell.rs

Repository: flyingrobots/echo

Length of output: 15475


Fix design doc: canonical member order is ascending BraidShellMember::member_digest (not the 4-tuple).

BraidShell::assemble canonicalizes member ordering with members.sort_by_key(BraidShellMember::member_digest); validate() errors on any decrease (prior > current), so the order is strictly ascending by member_digest.

The design text “sort key: basis_digest, strand_ref, support_pin_digest, claim_digest — or a single canonical member_digest” is under-specified/misleading: the implementation sorts only by member_digest(), which hashes additional fields beyond those four (e.g., frontier_digest, footprint_digest, verdict tag, verdict_digest, posture). Update docs/design/0026-braid-shell-family-and-plural-settlement/design.md (lines 182-186) to declare the exact ordering strategy (ascending member_digest) and remove the 4-tuple alternative unless you redefine it to exactly match member_digest()’s contents.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design/0026-braid-shell-family-and-plural-settlement/design.md` around
lines 182 - 186, Update the design doc to state that canonical member ordering
is strictly ascending by BraidShellMember::member_digest (not the 4-tuple),
matching the implementation in BraidShell::assemble which calls
members.sort_by_key(BraidShellMember::member_digest) and the validate() check
that errors on any prior > current; remove or replace the “sort key:
basis_digest, strand_ref, support_pin_digest, claim_digest” text unless you
explicitly redefine that 4-tuple to include every field hashed by member_digest
(e.g., frontier_digest, footprint_digest, verdict tag/digest, posture) so it
exactly matches BraidShellMember::member_digest().

Source: Coding guidelines

…ites

The remaining #539 merge blocker: ProvenanceEntry's retained patch body
(header fields explicitly, since patch_digest does not bind the header,
plus the canonical patch_digest which binds ops and slots),
materialization outputs (channel + frame bytes), and atom-write
provenance (atom, rule, tick, old/new values) are now bound by the
boundary digest. No retained field named like content is excluded.

Sensitivity test proves it: stripping the patch, appending an output
frame, or appending an atom write each move the digest.

517/517 warp-core tests; workspace clean under -D warnings.
@flyingrobots

Copy link
Copy Markdown
Owner Author

Final blocker resolved in 00233fc: BoundaryTransitionRecord::boundary_digest now binds the retained patch body (header fields explicitly — patch_digest does not bind the header — plus the canonical patch_digest, which binds ops and slots), materialization outputs (channel + frame bytes), and atom-write provenance including old_value/new_value (which the original grep window hid from me; they are exactly the kind of fields named like content that must not be excluded). Sensitivity test: stripping the patch, appending an output frame, or appending an atom write each move the digest.

PR body updated: 13 commits, 517/517. Nobody is selling the dragon's tail separately.

@flyingrobots

Copy link
Copy Markdown
Owner Author

@codex please review

@flyingrobots

Copy link
Copy Markdown
Owner Author

🐰 Code Lawyer self-review — lane/0026-braid-shell-family @ 00233fc vs origin/main

Pre-flight: worktree clean, refs fetched. CI green, 517/517, -D warnings clean, production code unwrap-free, ABI additions wire-additive (#[serde(default)]), markdown passes markdownlint-cli2. No CRITICAL issues. Architecture sound. Findings are hardening, not reversal.

# Severity File:Loc Type Issue
M1 🟠 Major provenance_store.rs:1214 (ProvenanceCheckpoint) + settlement.rs settle_with_policy Latent correctness No-leak guarantee is sequencing-dependent, not enforced. checkpoint_for/restore snapshot only per-worldline entry/checkpoint lengths; braid_shells + plural_shell_index are not covered. Safe today only because append_braid_shell is the last fallible step. Any future fallible step after it leaks a shell describing rolled-back history — the exact class this system exists to murder.
D1 🟡 Medium revelation.rs promote_posture Witness law hole Accepts raw Hash witness; [0;32]/empty shrug passes. Braid shells enforce the bar via check_outcome_law+WitnessDigest; posture promotion does not. Exported pub API (no prod caller yet).
D2 🟡 Medium coordinator.rs:2438 vs braid_shell.rs hash_event_kind DRY / divergence Two independent ProvenanceEventKind hash encoders (byte-string tags vs numeric tags). Compiler-guarded against omission only; schemes can silently diverge in meaning.
D3 🟡 Medium braid_shell.rs validate/assemble Efficiency (scales w/ N) member_digest() (blake3) recomputed ~4× per member per validate() (order loop + coordinate + witness + shell digest); assemble uses sort_by_key not sort_by_cached_key. Trivial at E1 (1 member), O(4N) at E3.
L1 🔵 Low braid_shell.rs assemble/validate # Errors Doc accuracy Documented error set omits DuplicateMemberStrand, DuplicateAlternativeId, EmptyWitness, CoordinateMismatch, UnsupportedVersion, IncoherentCollapseFields.
L2 🔵 Low braid_shell.rs replay_braid_shell Error clarity Obstruction-lineage failure returns InvalidCollapseLineage { collapsed_from } — field name is collapse-specific, reused for the obstructed_from case.
L3 🔵 Low provenance_store.rs take_braid_shells API surface pub production method existing only for hostile-replay proofs; consider #[doc(hidden)] or test-gating.
L4 🔵 Low braid_shell.rs collapse_braid_shell Footgun selected_result_refs silently dropped on the no-policy (obstruction) path.
L5 🔵 Low braid_shell.rs compute_witness_digest Semantics witness_digest = hash(WITNESS_DOMAIN ‖ body) then folded into shell digest — a self-witness, not independent attestation. Fine as E1 scaffolding; should be doc'd as such.
L6 🔵 Low provenance_store.rs BraidShellRecords::shell DRY Duplicates inherent braid_shell() body.
L7 🔵 Low lib.rs exports + settlement.rs SettlementPolicy::default Housekeeping braid_shell exports sit under // --- Truth delivery ---; default() re-hashes a constant per call.

Tally: 0 critical · 1 major · 3 medium · 7 low. Recommend addressing M1 (or documenting the invariant at the call site with a guard) before relying on the no-leak property under future change; the rest are improve-on-touch.

@codex — please confirm M1 (checkpoint/restore vs shell-store coverage) and sanity-check D1/D2. Do you concur, or is M1 acceptable as a documented sequencing invariant for E1?

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 00233fc72a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1726 to +1729
/// Retained braid shells by canonical shell digest (θ_braid family).
braid_shells: BTreeMap<Hash, crate::braid_shell::BraidShell>,
/// Residue → boundary index: plural artifact id to braid shell digest.
plural_shell_index: BTreeMap<Hash, Hash>,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include braid shells in rollback checkpoints

These new retained-shell maps sit outside ProvenanceCheckpoint: checkpoint_for only records per-worldline entry/checkpoint lengths, and ProvenanceService::restore only delegates to the store restore. In any transaction that captures a checkpoint, appends a braid shell, then hits a later fallible step and restores (the settlement path is safe only because append_braid_shell is currently last), the new shell and plural index entry remain visible even though the provenance entries they describe were rolled back.

Useful? React with 👍 / 👎.

Comment thread crates/warp-core/src/revelation.rs Outdated
if to == from {
return Err(PostureObstruction::AlreadyAtPosture { posture: from });
}
Ok(PosturePromotion { from, to, witness })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject placeholder witnesses for posture promotion

When callers promote posture with a placeholder digest such as [0; 32] or blake3_empty(), this returns a successful PosturePromotion even though the module promises every widening is witnessed. Because this is an exported API for moving artifacts toward Shared, a caller can accidentally persist an unauthenticated promotion; the braid-shell path already has WitnessDigest to reject these shrug values, but posture promotion bypasses that quality bar.

Useful? React with 👍 / 👎.

// collapsed; a settlement-derived shell must carry none.
collapsed_from.is_some() || (!any_plural && !any_conflict)
}
BraidShellOutcome::Plural { .. } => any_plural,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require plural shells to name an alternative

For a public caller assembling or validating a retained shell directly, BraidShellOutcome::Plural { alternative_ids: vec![] } is accepted as long as some member verdict is Plural. That leaves a shell that replays as a plural outcome but names no retained plural artifact for plural_shell_index/braid_shell_for_plural to bind, so the boundary can no longer be reached from any residue id despite claiming retained plurality.

Useful? React with 👍 / 👎.

Comment on lines +879 to +882
let mut witness_hasher = Hasher::new();
witness_hasher.update(COLLAPSE_OBSTRUCTION_WITNESS_DOMAIN);
witness_hasher.update(&plural_shell_digest);
let mut policy_hasher = Hasher::new();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bind refused collapse attempts to the selected result

When a caller attempts to collapse a plural shell without a policy, this obstruction witness only hashes the parent shell digest, so two different selected_result_refs attempts against the same plural parent produce the same obstruction shell. That loses the actual attempted collapse target in the retained evidence and makes distinct refused acts indistinguishable/idempotent.

Useful? React with 👍 / 👎.

…026)

Eleven findings (0 critical / 1 major / 3 medium / 7 low), all resolved:

M1 (major) — no-leak becomes a mechanism: ProvenanceCheckpoint snapshots
the braid-shell + plural-index key sets and restore() prunes anything
retained after the checkpoint, so a rolled-back settlement cannot leak a
shell describing vanished history. RED test
restore_rolls_back_braid_shells_and_plural_index_added_after_checkpoint.

D1 — witnessed-promotion law enforced by the type system: WitnessDigest
moved to revelation; promote_posture takes WitnessDigest (a shrug cannot
construct, so it cannot reach the function). One shrug-rejection impl,
shared by posture promotion and the shell family.

D2 — one event-kind digest scheme: BoundaryTransitionRecord reuses
coordinator::hash_provenance_event_kind (now pub(crate)); braid_shell's
parallel encoder deleted.

D3 — member digests computed once per assemble/validate (sort_by_cached_key
+ a single digest vec feeding coordinate/witness/shell digests).

L1 accurate # Errors docs; L2 obstruction lineage uses
InvalidLineageParent { parent }; L3 take_braid_shells is #[doc(hidden)];
L4 collapse no-policy ref-drop documented; L5 witness_digest self-witness
scaffolding documented; L6 trait shell() delegates to braid_shell();
L7 export grouping clarified.

518/518 warp-core tests; workspace clean under -D warnings; changed files
clippy-clean incl --tests.
@flyingrobots

Copy link
Copy Markdown
Owner Author

✅ Code Lawyer findings resolved — 566d08e1

All eleven self-review findings addressed (0 critical / 1 major / 3 medium / 7 low). 518/518 warp-core tests, workspace clean under -D warnings, changed files clippy-clean including --tests.

# Sev Resolution
M1 🟠 ProvenanceCheckpoint now snapshots the braid-shell + plural-index key sets; restore() prunes anything retained after the checkpoint. No-leak is a mechanism, not a sequencing convention — proven by restore_rolls_back_braid_shells_and_plural_index_added_after_checkpoint.
D1 🟡 WitnessDigest moved to revelation; promote_posture takes WitnessDigest, so a shrug witness cannot construct, cannot reach it. One shrug-rejection impl shared with the shell family.
D2 🟡 BoundaryTransitionRecord reuses coordinator::hash_provenance_event_kind (now pub(crate)); the parallel numeric encoder is deleted. One canonical event-kind scheme.
D3 🟡 Member digests computed once per assemble/validate (sort_by_cached_key + a single digest vec feeding coordinate/witness/shell).
L1 🔵 # Errors docs on assemble/validate now enumerate the full error set.
L2 🔵 Obstruction lineage uses InvalidLineageParent { parent } (no more collapse-specific field name on the obstruction path).
L3 🔵 take_braid_shells is #[doc(hidden)].
L4 🔵 No-policy collapse's selected_result_refs drop is documented.
L5 🔵 witness_digest documented as E1 self-witness scaffolding (integrity, not independent attestation).
L6 🔵 BraidShellRecords::shell delegates to braid_shell().
L7 🔵 Export grouping comment clarified.

Design packet updated with a "Record-law remediations" section. @codex — re-confirm M1 (checkpoint now covers the shell maps) and D1 (type-enforced witness) at your convenience.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 566d08e147

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@flyingrobots flyingrobots merged commit 3c4a3d0 into main Jun 13, 2026
36 checks passed
@flyingrobots flyingrobots deleted the lane/0026-braid-shell-family branch June 13, 2026 04:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant