Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

### Fixed

- `WorldlineState::state_root` documentation now states its reachable-state boundary. Detached create-if-absent writes remain bound by patch and commit identities. Hash bytes are unchanged.

- `ReadView::at` validates the aperture and derives the selected current frontier
basis with one state hash. `ReadView::new` still checks an independently
selected expected basis. Both retain the same aperture and trust boundaries.
Expand Down
59 changes: 58 additions & 1 deletion crates/warp-core/src/worldline_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,11 @@ impl WorldlineState {
&self.warp_state
}

/// Returns the canonical full-state root hash for this worldline.
/// Returns the canonical hash of WARP state reachable from this worldline's root.
///
/// Detached nodes and their attachments are outside this hash boundary.
/// Equal state roots therefore do not prove equal stores. A committed
/// detached write remains bound by the tick patch digest and commit identity.
#[must_use]
pub fn state_root(&self) -> Hash {
crate::snapshot::compute_state_root_for_warp_state(&self.warp_state, &self.root)
Expand Down Expand Up @@ -483,6 +487,59 @@ mod tests {
assert_eq!(ws.root().local_id, make_node_id("root"));
}

#[test]
fn detached_creates_preserve_state_root_but_change_patch_and_commit_identity() {
use crate::attachment::{AtomPayload, AttachmentValue};
use crate::snapshot::compute_commit_hash_v2;
use crate::tick_patch::{TickCommitStatus, WarpOp};

let mut state = WorldlineState::empty();
let root = state.state_root();
let mut patch_digests = Vec::new();
let mut commit_ids = Vec::new();
for label in ["detached-a", "detached-b"] {
let node = NodeKey {
warp_id: state.root().warp_id,
local_id: make_node_id(label),
};
let slot = AttachmentKey::node_alpha(node);
let patch = WarpTickPatchV1::new(
0,
[1; 32],
TickCommitStatus::Committed,
vec![crate::SlotId::Node(node), crate::SlotId::Attachment(slot)],
vec![crate::SlotId::Node(node), crate::SlotId::Attachment(slot)],
vec![
WarpOp::UpsertNode {
node,
record: NodeRecord {
ty: make_type_id("cell"),
},
},
WarpOp::SetAttachment {
key: slot,
value: Some(AttachmentValue::Atom(AtomPayload::new(
make_type_id("value"),
bytes::Bytes::from_static(b"retained"),
))),
},
],
);
let result = patch.apply_to_state(&mut state.warp_state);
assert!(result.is_ok(), "detached create must apply: {result:?}");
assert_eq!(state.state_root(), root);
assert!(state.store(&node.warp_id).is_some_and(|store| {
store.node(&node.local_id).is_some()
&& store.node_attachment(&node.local_id).is_some()
}));
patch_digests.push(patch.digest());
// Hold root, parents, and policy fixed to isolate the patch binding.
commit_ids.push(compute_commit_hash_v2(&root, &[], &patch.digest(), 0));
}
assert_ne!(patch_digests[0], patch_digests[1]);
assert_ne!(commit_ids[0], commit_ids[1]);
}

#[test]
fn worldline_frontier_starts_at_tick_zero() {
let frontier = WorldlineFrontier::new(wl(1), WorldlineState::empty());
Expand Down
2 changes: 2 additions & 0 deletions docs/architecture/application-contract-hosting.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ state, frontier, or Receipt publication. The transitional direct
prepare/commit seam can still return noncommitted evidence to trusted host
tests, but it is not the application lifecycle.

The create-if-absent profile creates a node and its alpha attachment. It does not create a skeleton edge from the lane root. A detached cell therefore remains outside the reachable-state root hash. Equal roots do not prove equal stores or the absence of a detached write. The retained tick patch and commit identity bind that write; duplicate checks also compare the typed target-value digest. This preserves the [Merkle commit law](../spec/merkle-commit.md).

The external-provider schema additionally admits one exact zero-choice
`compiler-produced-bounded-pure/v1` target configuration. It contains no
application operation, target-specific budget override, or mutation authority.
Expand Down
2 changes: 2 additions & 0 deletions docs/topics/WAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ buffer says it is dirty, because a file was written to disk, or because a UI
event happened. It is durable because Echo recorded the accepted submission and
later recorded any decided receipt under host-owned WAL authority.

State roots cover reachable WARP state. A detached create-if-absent cell can leave the root unchanged. The retained patch and commit bind that write. Root equality alone is not a complete recovery or no-mutation witness.

## Recovery Postures

The useful postures are:
Expand Down
Loading