Files
buzz/docs/formal/nip-rs-unread/exhaustive.py
T
cls 9dfa06ffee
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
feat: import Chinese-localized Buzz source snapshot
Signed-off-by: cls_宁波本机 <908705107@qq.com>
2026-08-13 18:34:25 +08:00

1487 lines
63 KiB
Python

"""Bounded transition-system explorer for NIP-RS manual-unread candidates.
BFS over canonical global states. At each depth, enabled transitions are
local actions and message deliveries, interleaved — not phased.
Universe: 2 upgraded devices + 1 legacy device, 2 contexts.
Transitions: mark_unread, mark_read (with frontier advance),
advance_frontier, compact, reinstall, deliver (including
duplicate/replay). Legacy rewrite semantics are exercised through the
deliver path (legacy_sanitize_and_publish), not as a separate
transition — a legacy device never mutates its own state outside
delivery, so a dedicated no-op transition added nothing (see NOTE.md).
Invariants:
I1 merge_reg_b associative/commutative/idempotent
I2 convergence: all delivery orders -> identical override verdict
I3 no frontier regression
I4 concurrent set/clear winner stable (order-independent, ancestor-independent)
I5 compaction: no loss of live set, no resurrection of dead clear,
survives merge with stale pre-compaction state
I5c directed deep-history: compact -> new local actions (counter reuse)
-> delayed stale delivery does not resurrect a dead override or
lose a genuinely-live one. Scope: the compacting device's own
pre-compaction ancestor (or an exact copy of it) replayed back to
that same device.
I5d cross-device compaction transparency (requalified, NOT
zero-divergence): a tombstone's counter ceiling can one-shot
suppress an unrelated device's concurrent fresh set with no
resurrection, and the suppression is always recoverable by one
more local action. Proven suppress-only direction via a bounded
witness cube plus a structural monotonicity argument.
I6 replay harmless
I7 legacy rewrite: B sibling keys survive / A overrides erased (witness)
I8 bounded key growth per context
I9 DeviceA post-receive counter absorption
"""
from itertools import permutations
from copy import deepcopy
from model import (
RegB, merge_reg_b, override_set_b, compact_b,
RegA, merge_reg_a,
DeviceB, DeviceA,
SET, CLEAR,
legacy_prune, legacy_trim, legacy_sanitize_blob,
escape_context_key, unescape_context_key, ESCAPE_PREFIX,
)
CONTEXTS = ("c0", "c1")
FRONTIER_VALS = (10, 20)
# ---------------------------------------------------------------------------
# I1: algebraic properties
# ---------------------------------------------------------------------------
def test_merge_algebra_b():
vals = [0, 1, 2, 3]
regs = [RegB(s, c, b) for s in vals for c in vals for b in vals]
violations = []
for a in regs:
if merge_reg_b(a, a) != a:
violations.append(("idempotent", a))
for a in regs:
for b in regs:
if merge_reg_b(a, b) != merge_reg_b(b, a):
violations.append(("commutative", a, b))
for a in regs:
for b in regs:
for c in regs:
if merge_reg_b(merge_reg_b(a, b), c) != merge_reg_b(a, merge_reg_b(b, c)):
violations.append(("associative", a, b, c))
return violations
def test_merge_algebra_a():
vals = [0, 1, 2]
tiebreaks = ["a", "b"]
ops = [SET, CLEAR]
baselines = [0, 10]
regs = [RegA(ct, t, o, bl)
for ct in vals for t in tiebreaks for o in ops for bl in baselines]
violations = []
for tie_op in [CLEAR, SET]:
for a in regs:
if merge_reg_a(a, a, tie_op) != a:
violations.append(("idempotent", tie_op, a))
for a in regs:
for b in regs:
if merge_reg_a(a, b, tie_op) != merge_reg_a(b, a, tie_op):
violations.append(("commutative", tie_op, a, b))
for a in regs:
for b in regs:
for c in regs:
ab_c = merge_reg_a(merge_reg_a(a, b, tie_op), c, tie_op)
a_bc = merge_reg_a(a, merge_reg_a(b, c, tie_op), tie_op)
if ab_c != a_bc:
violations.append(("associative", tie_op, a, b, c))
return violations
# ---------------------------------------------------------------------------
# BFS state explorer — Candidate B
# ---------------------------------------------------------------------------
def next_frontier(device, ctx):
cur = device.effective_frontier(ctx)
for fv in FRONTIER_VALS:
if fv > cur:
return fv
return None
def enabled_transitions(devices, tie_policy):
"""Generate (kind, args) tuples for all enabled transitions."""
trans = []
for di, d in enumerate(devices):
for ctx in CONTEXTS:
if not d.is_legacy:
trans.append(("mark_unread", di, ctx))
fv = next_frontier(d, ctx)
if fv is not None:
trans.append(("mark_read", di, ctx, fv))
if ctx in d.overrides:
trans.append(("compact", di, ctx))
fv = next_frontier(d, ctx)
if fv is not None:
trans.append(("advance", di, ctx, fv))
if not d.is_legacy:
trans.append(("reinstall", di))
for si in range(len(devices)):
for di in range(len(devices)):
if si != di:
trans.append(("deliver", si, di))
return trans
def apply_transition(devices, t, tie_policy):
kind = t[0]
if kind == "mark_unread":
devices[t[1]].do_mark_unread(t[2])
elif kind == "mark_read":
devices[t[1]].do_mark_read(t[2], t[3])
elif kind == "advance":
devices[t[1]].do_advance_frontier(t[2], t[3])
elif kind == "compact":
devices[t[1]].do_compact(t[2], tie_policy)
elif kind == "reinstall":
devices[t[1]].do_reinstall()
elif kind == "deliver":
src = devices[t[1]]
dst = devices[t[2]]
if src.is_legacy:
blob = src.legacy_sanitize_and_publish(tie_policy)
else:
blob = src.publish_blob(tie_policy)
dst.receive_merge(blob)
def state_sig(devices, tie_policy):
return tuple(d.state_key(CONTEXTS, tie_policy) for d in devices)
def check_convergence(devices, tie_policy, trace, violations):
"""Publish all blobs, deliver in every order, check upgraded devices
converge on override_is_set for each context.
Tests with latest_ts=5 (below all frontiers) so the override is the
sole unread source — no masking by natural unread.
"""
blobs = []
for d in devices:
if d.is_legacy:
blobs.append(d.legacy_sanitize_and_publish(tie_policy))
else:
blobs.append(d.publish_blob(tie_policy))
verdicts_per_order = []
for perm in permutations(range(len(blobs))):
receivers = deepcopy(devices)
for idx in perm:
for r in receivers:
r.receive_merge(blobs[idx])
per_device = []
for r in receivers:
if not r.is_legacy:
per_device.append(
tuple(r.override_is_set(ctx, tie_policy) for ctx in CONTEXTS)
)
verdicts_per_order.append(tuple(per_device))
if len(set(verdicts_per_order)) > 1:
violations.append(("I2-convergence", trace, set(verdicts_per_order)))
def check_compaction_safety(devices, tie_policy, trace, violations):
"""For each upgraded device with overrides:
1. Check override_is_set directly (not via verdict/latest_ts).
2. Compact and verify override_is_set unchanged.
3. Merge compacted state with stale pre-compaction state in both orders.
Verify no resurrection and no loss.
"""
for di, d in enumerate(devices):
if d.is_legacy:
continue
for ctx in CONTEXTS:
reg = d.overrides.get(ctx)
if reg is None:
continue
front = d.effective_frontier(ctx)
ov_before = d._override_set(reg, front, tie_policy)
compacted = d._compact(reg, front, tie_policy)
ov_after = d._override_set(compacted, front, tie_policy) if compacted else False
if ov_before and not ov_after:
violations.append((
"I5-compaction-lost-set", trace, di, ctx,
reg, compacted, front, tie_policy
))
if not ov_before and ov_after:
violations.append((
"I5-compaction-resurrection", trace, di, ctx,
reg, compacted, front, tie_policy
))
if compacted is not None:
for merged in [merge_reg_b(compacted, reg), merge_reg_b(reg, compacted)]:
ov_merged = d._override_set(merged, front, tie_policy)
if not ov_before and ov_merged:
violations.append((
"I5-compaction-merge-resurrection", trace, di, ctx,
reg, compacted, merged
))
def explore_b(max_depth=4, tie_policy=CLEAR, device_cls=DeviceB):
"""BFS over all reachable global states up to max_depth.
Returns (states_explored, violations).
Accepts device_cls for mutation testing via subclassing.
"""
def make_devices():
return [
device_cls("d0", is_legacy=False),
device_cls("d1", is_legacy=False),
device_cls("d2", is_legacy=True),
]
violations = []
seen = set()
states_explored = 0
queue = [(make_devices(), [])]
while queue:
devices, trace = queue.pop(0)
sig = state_sig(devices, tie_policy)
if sig in seen:
continue
seen.add(sig)
states_explored += 1
for di, d in enumerate(devices):
for ctx in CONTEXTS:
prev_front = d.effective_frontier(ctx)
if prev_front < 0:
violations.append(("I3-frontier-negative", trace, di, ctx))
if len(trace) >= max_depth:
check_convergence(devices, tie_policy, trace, violations)
check_compaction_safety(devices, tie_policy, trace, violations)
continue
for t in enabled_transitions(devices, tie_policy):
new_devs = deepcopy(devices)
fronts_before = {
(di, ctx): d.effective_frontier(ctx)
for di, d in enumerate(new_devs) for ctx in CONTEXTS
}
apply_transition(new_devs, t, tie_policy)
# Reinstall intentionally wipes local state; frontier regression
# is only invalid during merge/delivery/compaction/advance.
if t[0] != "reinstall":
for (di, ctx), fb in fronts_before.items():
fa = new_devs[di].effective_frontier(ctx)
if fa < fb:
violations.append(("I3-frontier-regression", trace + [t], di, ctx, fb, fa))
queue.append((new_devs, trace + [t]))
return states_explored, violations
# ---------------------------------------------------------------------------
# I4: concurrent set/clear winner stable
# ---------------------------------------------------------------------------
def test_concurrent_stability(device_cls=DeviceB):
"""Two devices concurrently set and clear from every possible ancestor state.
The winner must be the same regardless of delivery order AND ancestor state."""
violations = []
for tie_policy in [CLEAR, SET]:
for pre_s, pre_c in [(0, 0), (1, 0), (0, 1), (2, 1), (1, 2), (1, 1)]:
for front in [0, 10]:
for ctx in CONTEXTS:
ancestor = RegB(s=pre_s, c=pre_c, b=front)
d0 = device_cls("d0")
d0.frontier[ctx] = front
d0.overrides[ctx] = deepcopy(ancestor)
d1 = device_cls("d1")
d1.frontier[ctx] = front
d1.overrides[ctx] = deepcopy(ancestor)
d0.do_mark_unread(ctx)
d1.do_mark_read(ctx, front + 10)
blob0 = d0.publish_blob(tie_policy)
blob1 = d1.publish_blob(tie_policy)
verdicts = set()
for first, second in [(blob0, blob1), (blob1, blob0)]:
r = device_cls("recv")
r.frontier[ctx] = front
r.overrides[ctx] = deepcopy(ancestor)
r.receive_merge(first)
r.receive_merge(second)
verdicts.add(r.override_is_set(ctx, tie_policy))
if len(verdicts) > 1:
violations.append((
"I4-unstable", tie_policy, ctx,
pre_s, pre_c, front
))
return violations
# ---------------------------------------------------------------------------
# I5: direct compaction register-level check (all register values x policies)
# ---------------------------------------------------------------------------
def test_compaction_register_exhaustive():
"""Exhaustive check over bounded register cube and frontier values.
Tests override_is_set directly — no latest_ts masking."""
violations = []
vals = [0, 1, 2, 3]
frontiers = [0, 10, 20]
for tie_policy in [CLEAR, SET]:
for s in vals:
for c in vals:
for b in frontiers:
for fv in frontiers:
reg = RegB(s=s, c=c, b=b)
ov_before = override_set_b(reg, fv, tie_policy)
compacted = compact_b(reg, fv, tie_policy)
ov_after = (override_set_b(compacted, fv, tie_policy)
if compacted else False)
if ov_before and not ov_after:
violations.append((
"loss", tie_policy, reg, fv, compacted
))
if not ov_before and ov_after:
violations.append((
"resurrection", tie_policy, reg, fv, compacted
))
if compacted is not None:
merged_fwd = merge_reg_b(compacted, reg)
merged_rev = merge_reg_b(reg, compacted)
for label, merged in [("fwd", merged_fwd), ("rev", merged_rev)]:
ov_merged = override_set_b(merged, fv, tie_policy)
if not ov_before and ov_merged:
violations.append((
f"merge-resurrection-{label}",
tie_policy, reg, fv, compacted, merged
))
return violations
# ---------------------------------------------------------------------------
# I5c: directed deep-history — compact -> new actions (counter reuse) ->
# delayed stale delivery (including split across two slots)
# ---------------------------------------------------------------------------
def _apply_action_seq(dev, ctx, seq, ts):
for a in seq:
if a == "set":
dev.do_mark_unread(ctx)
else:
dev.do_mark_read(ctx, ts)
def _ancestor_ctx_dict(ctx, reg):
return {f"ov_s:{ctx}": reg.s, f"ov_c:{ctx}": reg.c, f"ov_b:{ctx}": reg.b}
_DEEP_HISTORY_ACTION_SEQS = [
(), ("set",), ("clear",), ("set", "clear"), ("clear", "set"),
("set", "set"), ("clear", "clear"),
]
# One delivery shape: single unsplit blob. The prior "split_fwd"/"split_rev"
# shapes are no longer distinct — with the atomic-grouping rule a single-
# context blob's compliant split puts the whole group in one slot and the
# other empty, making split_fwd and split_rev semantically identical to
# single. Keeping only one shape avoids 2/3 duplicate executions (2,016 →
# 672 meaningful points) while losing zero register-level coverage.
_DEEP_HISTORY_DELIVERY_SHAPES = ("single",)
def test_deep_history_compaction(device_cls=DeviceB):
"""Directed check over the exact shape a depth-4 BFS structurally
cannot reach (~9 transitions): compact -> new local set/clear actions
(counter reuse against the tombstone floor) -> delayed delivery of
the pre-compaction stale ancestor, including split across 2 slots.
Oracle: compaction is a storage optimization and must never change
the semantic outcome. A reference device that never compacts, given
the identical ancestor / frontier advance / action sequence / late
ancestor delivery, must reach the same override_is_set verdict as
the compacting device. This directly targets Thufir's counterexample
(RegB(3,0,10) -> None under delete-on-dominance -> counter reuse ->
RegB(3,2,20) resurrection) and requires the tombstone floor from
compact_b to hold under it.
Returns (cube_size, violations).
"""
violations = []
cube_size = 0
ctx = "c0"
stale_vals = (0, 1, 2, 3)
baselines = (0, 10)
post_frontiers = (10, 20)
for s0 in stale_vals:
for c0 in stale_vals:
for b0 in baselines:
for f1 in post_frontiers:
if f1 <= b0:
continue # not a dominance/compaction scenario
ancestor = RegB(s=s0, c=c0, b=b0)
ancestor_blob = _ancestor_ctx_dict(ctx, ancestor)
for seq in _DEEP_HISTORY_ACTION_SEQS:
for tie_policy in (CLEAR, SET):
for shape in _DEEP_HISTORY_DELIVERY_SHAPES:
cube_size += 1
dev = device_cls("d0")
dev.frontier[ctx] = b0
dev.overrides[ctx] = ancestor
dev.do_advance_frontier(ctx, f1)
dev.do_compact(ctx, tie_policy)
_apply_action_seq(dev, ctx, seq, f1)
if shape == "single":
dev.receive_merge({"contexts": dict(ancestor_blob)})
ov_after = dev.override_is_set(ctx, tie_policy)
ref = device_cls("ref")
ref.frontier[ctx] = b0
ref.overrides[ctx] = ancestor
ref.do_advance_frontier(ctx, f1)
_apply_action_seq(ref, ctx, seq, f1)
ref.receive_merge({"contexts": dict(ancestor_blob)})
ov_ref = ref.override_is_set(ctx, tie_policy)
if ov_after != ov_ref:
violations.append((
"I5c-deep-history-divergence", tie_policy, shape,
ancestor, f1, seq,
f"compacted_path={ov_after}", f"reference={ov_ref}",
))
return cube_size, violations
def test_tombstone_stale_merge_direct():
"""Tombstone floor merged directly with its own pre-compaction stale
ancestor (no intervening local actions) must not resurrect and must
not exceed the ancestor's own verdict."""
violations = []
vals = (0, 1, 2, 3)
frontiers = (0, 10, 20)
for tie_policy in (CLEAR, SET):
for s in vals:
for c in vals:
for b in frontiers:
for fv in frontiers:
if fv <= b:
continue
reg = RegB(s=s, c=c, b=b)
compacted = compact_b(reg, fv, tie_policy)
if compacted is None:
continue # virgin register: nothing to tombstone
ov_before = override_set_b(reg, fv, tie_policy)
for merged in (merge_reg_b(compacted, reg), merge_reg_b(reg, compacted)):
ov_merged = override_set_b(merged, fv, tie_policy)
if not ov_before and ov_merged:
violations.append((
"tombstone-stale-merge-resurrection",
tie_policy, reg, fv, compacted, merged,
))
return violations
# ---------------------------------------------------------------------------
# I5d: cross-device compaction transparency (requalified — suppress-only,
# NOT zero-divergence) + re-mark recovery
# ---------------------------------------------------------------------------
def test_tombstone_merge_monotonic():
"""Structural lemma: merging in ANY tombstone RegB(0, k, 0) is a
monotonically non-increasing function of the ceiling k in
override_set_b's boolean output, for a fixed receiving register and
frontier. A tombstone only ever adds to C (its S and B are both 0,
so max() with any receiving register leaves that register's own S
and B untouched) — raising C can only weaken S's relative standing,
never strengthen it. This is what makes resurrection structurally
impossible and suppression the only possible direction, independent
of any bounded cube.
"""
violations = []
vals = (0, 1, 2, 3)
baselines = (0, 10, 20)
ceilings = (0, 1, 2, 3, 4, 5)
for tie_policy in (CLEAR, SET):
for s in vals:
for c in vals:
for b in baselines:
for fv in baselines:
x_reg = RegB(s=s, c=c, b=b)
prev = None
for k in ceilings:
merged = merge_reg_b(x_reg, RegB(s=0, c=k, b=0))
cur = override_set_b(merged, fv, tie_policy)
if prev is not None and cur and not prev:
violations.append((
"I5d-non-monotonic-ceiling", tie_policy,
x_reg, fv, k, merged,
))
prev = cur
return violations
def test_cross_device_compaction_suppression(device_cls=DeviceB):
"""Compaction is NOT semantically transparent cross-device (I5c only
covers the same-device replay shape). A tombstone re-encodes
baseline-dominated death — frontier-relative, doesn't transfer
across devices — as a clear-counter ceiling — globally comparable —
so it can one-shot suppress an unrelated device's concurrent fresh
set whose own counters don't exceed that ceiling.
Witness (Paul's report, illustrative — the cube below tests nearby
parameter values `f_x` in `(5, 15, 25, 35)`, not the literal
`f_x=30` used in the original report; the shape is the same):
Y: mark_unread -> RegB(1,0,0); frontier->10 (dead) -> compact ->
tombstone RegB(0,1,0)
X: offline, fresh mark_unread at frontier 30 -> RegB(1,0,30), LIVE
X merges Y's tombstone -> RegB(1,1,30) -> suppressed (clear-wins)
Control (Y publishes the uncompacted RegB(1,0,0) instead): X stays
RegB(1,0,30), LIVE — the divergence is caused by compaction, not
by the merge itself.
Proves over a bounded cube, both tie policies: every divergence
between "X merges Y's tombstone" and "X merges Y's uncompacted
ancestor" is a suppression (never a resurrection — that would
contradict test_tombstone_merge_monotonic), and every suppression
recovers with one more local mark-unread, stable under tombstone
replay.
Returns (cube_size, suppress_count, violations).
"""
violations = []
cube_size = 0
suppress_count = 0
dead_vals = (0, 1, 2, 3)
dead_baselines = (0, 10)
dead_post_frontiers = (10, 20)
fresh_frontiers = (5, 15, 25, 35)
for tie_policy in (CLEAR, SET):
for s_y in dead_vals:
for c_y in dead_vals:
for b_y in dead_baselines:
for f_y in dead_post_frontiers:
if f_y <= b_y:
continue
ancestor = RegB(s=s_y, c=c_y, b=b_y)
tomb = compact_b(ancestor, f_y, tie_policy)
if tomb is None or tomb == ancestor:
continue # virgin, or was live (not compacted)
for f_x in fresh_frontiers:
cube_size += 1
x_reg = RegB(s=1, c=0, b=f_x)
x_before = override_set_b(x_reg, f_x, tie_policy)
if not x_before:
violations.append((
"I5d-setup-not-live", tie_policy, x_reg, f_x,
))
continue
ov_tomb = override_set_b(
merge_reg_b(x_reg, tomb), f_x, tie_policy
)
ov_ancestor = override_set_b(
merge_reg_b(x_reg, ancestor), f_x, tie_policy
)
if ov_tomb == ov_ancestor:
continue
if ov_tomb and not ov_ancestor:
violations.append((
"I5d-resurrection-vs-ancestor", tie_policy,
ancestor, tomb, x_reg, f_x,
))
continue
suppress_count += 1
dev = device_cls("x")
dev.frontier["c0"] = f_x
dev.overrides["c0"] = merge_reg_b(x_reg, tomb)
dev.do_mark_unread("c0")
if not dev.override_is_set("c0", tie_policy):
violations.append((
"I5d-recovery-failed", tie_policy,
ancestor, tomb, x_reg, f_x, dev.overrides["c0"],
))
continue
dev.receive_merge({"contexts": {
"ov_s:c0": tomb.s, "ov_c:c0": tomb.c, "ov_b:c0": tomb.b,
}})
if not dev.override_is_set("c0", tie_policy):
violations.append((
"I5d-recovery-not-replay-stable", tie_policy,
ancestor, tomb, x_reg, f_x, dev.overrides["c0"],
))
return cube_size, suppress_count, violations
# ---------------------------------------------------------------------------
# New invariant: published-state merge closure (Paul's fix-scope item 2,
# generalizing Thufir's pass-1/2 CRITICAL — dead+dead merge resurrection)
# ---------------------------------------------------------------------------
def _dead_register_points(tie_policy):
"""Bounded cube of (label, reg, frontier) points independently
verified DEAD (inactive) under `tie_policy` by the real
`override_set_b` predicate — the death cause (baseline dominance,
clear-count dominance, or clear-wins tie) is whatever the predicate
actually computes for that point, not asserted by construction.
"""
vals = (0, 1, 2, 3)
baselines = (0, 10, 50)
frontiers = (0, 20, 60, 100)
points = []
for s in vals:
for c in vals:
if s == 0 and c == 0:
continue # virgin: not a "dead override" case
for b in baselines:
for fv in frontiers:
reg = RegB(s=s, c=c, b=b)
if override_set_b(reg, fv, tie_policy):
continue # live: out of scope for this invariant
points.append((f"s={s}c={c}b={b}fv={fv}", reg, fv))
return points
def test_published_merge_closure(device_cls=DeviceB):
"""Over reachable *published* states: joining any two individually-
inactive published states must remain inactive.
This targets Thufir's pass-1/2 CRITICAL directly: a dead register's
death cause is frontier-relative (baseline dominance) or
device-local-history-relative (clear-count dominance), but the
componentwise-max join recombines each register's `S`/`C`/`B`
independent of the history that produced them, so two individually-
dead registers could — before canonical publication — recombine
into a live join. Canonicalizing every override to `RegB(0,
max(S,C), 0)` before serialization (this round's CRITICAL fix)
folds every dead cause into a single globally-comparable `C`
ceiling with `S=0`, which per `test_tombstone_merge_monotonic` can
only ever raise a receiver's `C` — never resurrect.
Checked two ways:
- Directed case: Thufir's exact witness pair — `RegB(3,2,0)`
inactive via baseline dominance at frontier 50, `RegB(1,2,100)`
inactive via clear dominance at frontier 100 — whose raw
componentwise join is `RegB(3,2,100)`, live (`S=3>C=2`,
`frontier(100) not> B(100)`). Both tie policies.
- General search: every pairwise join of a bounded cube of
independently-dead `(reg, frontier)` points (see
`_dead_register_points`), delivered to a fresh receiver in both
direct orders and via a one-hop relay that itself republishes
(re-canonicalizes) what it received before forwarding — covering
delayed/multi-hop delivery, not just direct pairwise merge.
Returns (cube_size, violations).
"""
violations = []
cube_size = 0
def _check_pair(tie_policy, label_a, blob_a, label_b, blob_b, tag):
nonlocal cube_size
cube_size += 1
for first, second in [(blob_a, blob_b), (blob_b, blob_a)]:
recv = device_cls("recv")
recv.receive_merge(first)
recv.receive_merge(second)
if recv.override_is_set("c0", tie_policy):
violations.append((
tag, tie_policy, label_a, label_b, recv.overrides.get("c0"),
))
# Multi-hop: a relay receives blob_a alone, republishes
# (re-canonicalizes) before forwarding, then the receiver gets
# the relayed form plus blob_b directly, in both orders.
relay = device_cls("relay")
relay.receive_merge(blob_a)
relayed = relay.publish_blob(tie_policy)
for first, second in [(relayed, blob_b), (blob_b, relayed)]:
recv = device_cls("recv_hop")
recv.receive_merge(first)
recv.receive_merge(second)
if recv.override_is_set("c0", tie_policy):
violations.append((
tag + "-multihop", tie_policy, label_a, label_b,
recv.overrides.get("c0"),
))
# --- Directed case: Thufir's exact witness pair. ---
for tie_policy in (CLEAR, SET):
reg_a, front_a = RegB(s=3, c=2, b=0), 50
reg_b, front_b = RegB(s=1, c=2, b=100), 100
assert not override_set_b(reg_a, front_a, tie_policy)
assert not override_set_b(reg_b, front_b, tie_policy)
dev_a = device_cls("a")
dev_a.frontier["c0"] = front_a
dev_a.overrides["c0"] = reg_a
dev_b = device_cls("b")
dev_b.frontier["c0"] = front_b
dev_b.overrides["c0"] = reg_b
_check_pair(
tie_policy, f"thufir-witness-A={reg_a}@{front_a}",
dev_a.publish_blob(tie_policy),
f"thufir-witness-B={reg_b}@{front_b}",
dev_b.publish_blob(tie_policy),
"merge-closure-thufir-witness",
)
# --- General search over a bounded cube of dead published states. ---
for tie_policy in (CLEAR, SET):
points = _dead_register_points(tie_policy)
for label_a, reg_a, front_a in points:
dev_a = device_cls("a")
dev_a.frontier["c0"] = front_a
dev_a.overrides["c0"] = reg_a
blob_a = dev_a.publish_blob(tie_policy)
for label_b, reg_b, front_b in points:
dev_b = device_cls("b")
dev_b.frontier["c0"] = front_b
dev_b.overrides["c0"] = reg_b
blob_b = dev_b.publish_blob(tie_policy)
_check_pair(
tie_policy, label_a, blob_a, label_b, blob_b,
"merge-closure-cube",
)
return cube_size, violations
# ---------------------------------------------------------------------------
# I6: replay harmless
# ---------------------------------------------------------------------------
def test_replay_harmless(device_cls=DeviceB):
violations = []
for tie_policy in [CLEAR, SET]:
for ctx in CONTEXTS:
d = device_cls("d0")
d.frontier[ctx] = 10
d.do_mark_unread(ctx)
blob = d.publish_blob(tie_policy)
state_before = (
dict(d.frontier),
{k: v for k, v in d.overrides.items()},
)
d.receive_merge(blob)
d.receive_merge(blob)
d.receive_merge(blob)
state_after = (
dict(d.frontier),
{k: v for k, v in d.overrides.items()},
)
if state_before != state_after:
violations.append(("I6-replay", tie_policy, ctx))
return violations
# ---------------------------------------------------------------------------
# I7: legacy rewrite
# ---------------------------------------------------------------------------
def test_legacy_rewrite_b():
"""B's sibling keys survive legacy sanitization (round-trip)."""
violations = []
for ctx in CONTEXTS:
d = DeviceB("d0")
d.frontier[ctx] = 10
d.do_mark_unread(ctx)
blob = d.publish_blob()
sanitized = legacy_sanitize_blob(blob)
recv_orig = DeviceB("recv1")
recv_orig.receive_merge(blob)
recv_san = DeviceB("recv2")
recv_san.receive_merge(sanitized)
for c in CONTEXTS:
if recv_orig.overrides.get(c) != recv_san.overrides.get(c):
violations.append(("I7-B-sanitize-mutated", c,
recv_orig.overrides.get(c),
recv_san.overrides.get(c)))
return violations
def test_legacy_erasure_a():
"""A's top-level overrides field is erased by legacy rewrite. Expected witness."""
d = DeviceA("d0")
d.frontier["c0"] = 10
d.do_mark_unread("c0")
blob = d.publish_blob()
assert "overrides" in blob
legacy_blob = {"v": 1, "client_id": "legacy", "contexts": dict(blob["contexts"])}
return "overrides" not in legacy_blob
# ---------------------------------------------------------------------------
# I8: bounded key growth
# ---------------------------------------------------------------------------
def test_bounded_growth():
"""I8: bounded key growth, canonical wire shape. A live override
(last action = mark_unread, still within baseline) publishes
exactly 3 keys/ctx; a dead override (mark_read past baseline, or
C > S under clear-wins) canonicalizes to exactly 1 key/ctx
(`ov_c:` tombstone) at publish time — never 0 (virgin-only) or 3
(dead-but-uncompacted, which the pre-fix serializer allowed).
"""
violations = []
for ctx in CONTEXTS:
# Live: 100 set/clear round-trips, ending on a fresh mark_unread
# so S > C (live under both tie policies) at publish time.
d = DeviceB("d0")
d.frontier[ctx] = 10
for _ in range(100):
d.do_mark_unread(ctx)
d.do_mark_read(ctx, d.effective_frontier(ctx) + 1)
d.do_mark_unread(ctx)
blob = d.publish_blob(CLEAR)
ov_keys = [k for k in blob["contexts"] if k.startswith("ov_")]
if ov_keys != [f"ov_s:{ctx}", f"ov_c:{ctx}", f"ov_b:{ctx}"]:
violations.append(("I8-growth-live", ctx, ov_keys))
# Dead: advance the frontier past baseline B — override_set_b's
# baseline-dominance clause forces S dead regardless of S vs C.
d.do_advance_frontier(ctx, d.effective_frontier(ctx) + 100)
tomb_blob = d.publish_blob(CLEAR)
tomb_keys = [k for k in tomb_blob["contexts"] if k.startswith("ov_")]
if tomb_keys != [f"ov_c:{ctx}"]:
violations.append(("I8-growth-tombstone", ctx, tomb_keys))
return violations
def test_wire_shape_exact():
"""Exact wire-shape regression (Paul's fix-scope item 4): a live
override serializes to exactly 3 `ov_*` keys, a dead override to
exactly 1 (`ov_c:` only, zero-valued `ov_s`/`ov_b` omitted), and a
virgin override to exactly 0. Checked directly against
`publish_blob`'s output, independent of `do_compact`.
"""
violations = []
for tie_policy in (CLEAR, SET):
# Live.
d_live = DeviceB("d0")
d_live.frontier["c0"] = 10
d_live.do_mark_unread("c0")
live_blob = d_live.publish_blob(tie_policy)
live_keys = sorted(k for k in live_blob["contexts"] if k.startswith("ov_"))
if live_keys != ["ov_b:c0", "ov_c:c0", "ov_s:c0"]:
violations.append(("wire-shape-live", tie_policy, live_keys))
# Dead (clear-wins only: S==C>0 is dead under CLEAR, live under
# SET — use baseline dominance instead so it's dead under both).
d_dead = DeviceB("d0")
d_dead.frontier["c0"] = 10
d_dead.do_mark_unread("c0")
d_dead.do_advance_frontier("c0", 100)
dead_blob = d_dead.publish_blob(tie_policy)
dead_keys = sorted(k for k in dead_blob["contexts"] if k.startswith("ov_"))
if dead_keys != ["ov_c:c0"]:
violations.append(("wire-shape-tombstone", tie_policy, dead_keys))
if dead_blob["contexts"]["ov_c:c0"] != 1:
violations.append((
"wire-shape-tombstone-ceiling", tie_policy,
dead_blob["contexts"]["ov_c:c0"],
))
# Virgin: no override ever set for this context.
d_virgin = DeviceB("d0")
d_virgin.frontier["c0"] = 10
d_virgin.overrides["c0"] = RegB(s=0, c=0, b=0)
virgin_blob = d_virgin.publish_blob(tie_policy)
virgin_keys = [k for k in virgin_blob["contexts"] if k.startswith("ov_")]
if virgin_keys:
violations.append(("wire-shape-virgin", tie_policy, virgin_keys))
return violations
# ---------------------------------------------------------------------------
# I9: DeviceA counter absorption
# ---------------------------------------------------------------------------
def test_a_counter_absorption():
"""After receiving a blob with counter=10, a local action must use counter>10."""
d0 = DeviceA("d0")
d0.frontier["c0"] = 10
d0.counter = 10
d0.do_mark_unread("c0")
blob0 = d0.publish_blob()
d1 = DeviceA("d1")
d1.frontier["c0"] = 10
d1.receive_merge(blob0)
assert d1.counter >= 10, f"counter not absorbed: {d1.counter}"
d1.do_mark_read("c0", 20)
reg = d1.overrides.get("c0")
assert reg is not None and reg.counter > 10, \
f"post-receive clear at counter {reg.counter} would lose to set at 10"
return True
# ---------------------------------------------------------------------------
# Identity-free (B): reinstall convergence
# ---------------------------------------------------------------------------
def test_b_identity_free(device_cls=DeviceB):
violations = []
for tie_policy in [CLEAR, SET]:
for ctx in CONTEXTS:
d = device_cls("d0")
d.frontier[ctx] = 10
d.do_mark_unread(ctx)
blob1 = d.publish_blob(tie_policy)
d_re = device_cls("d0_reinstalled")
d_re.receive_merge(blob1)
d_re.do_mark_read(ctx, 20)
blob2 = d_re.publish_blob(tie_policy)
verdicts = set()
for first, second in [(blob1, blob2), (blob2, blob1)]:
recv = device_cls("recv")
recv.receive_merge(first)
recv.receive_merge(second)
verdicts.add(recv.override_is_set(ctx, tie_policy))
if len(verdicts) > 1:
violations.append(("identity-free", tie_policy, ctx))
return violations
# ---------------------------------------------------------------------------
# Legacy prune/trim interaction
# ---------------------------------------------------------------------------
def test_legacy_prune_interaction():
"""ov_ keys survive prune; msg:ov_ nested keys would be pruned (state loss)."""
base = {"c0": 50, "msg:m1": 30, "thread:t1": 40}
ov = {"ov_s:c0": 1, "ov_c:c0": 0, "ov_b:c0": 10}
all_keys = {**base, **ov}
pruned = legacy_prune(all_keys, horizon=35)
ov_survived = all(k in pruned for k in ov)
msg_pruned = "msg:m1" not in pruned
nested = {"msg:ov_s:c0": 1, "msg:ov_c:c0": 0, "msg:ov_b:c0": 10}
pruned_nested = legacy_prune({**base, **nested}, horizon=35)
nested_lost = any(k not in pruned_nested for k in nested)
return ov_survived, msg_pruned, nested_lost
def test_legacy_trim_interaction():
"""Excess override keys block legacy publish when budget exceeded."""
contexts = {"c0": 50}
for i in range(1000):
contexts[f"ov_s:c{i}"] = 1
contexts[f"ov_c:c{i}"] = 0
contexts[f"ov_b:c{i}"] = 10
_, fits = legacy_trim(contexts, "client1", max_bytes=32768)
return not fits
# ---------------------------------------------------------------------------
# Multi-slot union
# ---------------------------------------------------------------------------
def test_multi_slot_union(device_cls=DeviceB):
"""Split a published blob across 2 slots using the atomic-grouping rule,
deliver each slot separately, verify convergence with delivering the full blob.
Production: mergeReadStateEvents merges per-slot blobs with per-context
max(). Override sibling keys are individual context entries, so they
follow the same merge path. The atomic-grouping rule requires that all
`ov_*` sibling keys for a context travel with that context's frontier
key in the same slot — `split_blob_into_slots` enforces this.
"""
violations = []
for tie_policy in [CLEAR, SET]:
dev = device_cls("d0")
dev.frontier["c0"] = 10
dev.frontier["c1"] = 20
dev.do_mark_unread("c0")
dev.do_mark_read("c1", 30)
full_blob = dev.publish_blob(tie_policy)
slots = dev.split_blob_into_slots(tie_policy, n_slots=2)
slot0, slot1 = slots[0], slots[1]
recv_full = device_cls("recv_full")
recv_full.receive_merge(full_blob)
for first, second in [(slot0, slot1), (slot1, slot0)]:
recv_split = device_cls("recv_split")
recv_split.receive_merge(first)
recv_split.receive_merge(second)
for ctx in CONTEXTS:
ov_full = recv_full.override_is_set(ctx, tie_policy)
ov_split = recv_split.override_is_set(ctx, tie_policy)
f_full = recv_full.effective_frontier(ctx)
f_split = recv_split.effective_frontier(ctx)
if ov_full != ov_split:
violations.append(("multi-slot-override", tie_policy, ctx))
if f_full != f_split:
violations.append(("multi-slot-frontier", tie_policy, ctx))
return violations
# ---------------------------------------------------------------------------
# Interleaved-delivery grouping: Thufir's CRITICAL transport counterexample
#
# Without the atomic-grouping rule a compliant publisher would still split
# ov_s:/ov_c:/ov_b: across slots as independent entries. M8's per-entry
# split places frontier+ov_s: in slot 0 and ov_b:+ov_c: in slot 1. An
# observer holding only slot 0 reconstructs RegB(1,0,0), judges it
# baseline-dead (B=0 ≤ frontier=10), and canonically publishes tombstone
# RegB(0,1,0). After all slots and that transient tombstone are eventually
# merged the result is RegB(1,1,10) — dead under clear-wins —
# permanently suppressing a live override.
#
# The atomic-grouping rule closes this: every ov_* entry for a context
# travels with the context's frontier entry, so a receiver always sees
# either the complete register or nothing. This test exercises both:
# - The PASS path: grouped slots → no false tombstone possible.
# - The FAIL path (M8): per-entry split → Thufir's exact witness reproduced.
# ---------------------------------------------------------------------------
def test_interleaved_delivery_grouping(device_cls=DeviceB):
"""Exercise receive-one-slot → canonical re-publish → receive-rest →
re-publish permutations, both slot orders, including delayed delivery
of both transient re-publications to a third observer.
Protocol sequence (exact, per Paul's brief):
1. partial_obs receives first_slot → publishes transient_1.
2. partial_obs receives second_slot → publishes transient_2.
3. Third-party finals receive BOTH source slots AND both transient
publications in relevant interleaving orders.
Oracle: after eventual delivery of ALL blobs (both source slots +
both transients), every observer's override matches source liveness.
With the atomic-grouping rule (default DeviceB):
- The compliant split puts the full register in one slot, the other
is empty. partial_obs after step 1 holds either the complete
register (live → transient_1 is live) or nothing (transient_1 is
empty/virgin). Either way, step 2 delivers the remaining (possibly
empty) slot. Final merge of all blobs = source liveness. PASS.
With per-entry splitting (M8):
- slot 0 carries frontier + ov_s: (partial → RegB(1,0,0), dead).
transient_1 is tombstone RegB(0,1,0). After step 2 partial_obs
holds full register but transient_1 tombstone is already in
circulation. Finals that receive transient_1 get
RegB(1,1,10) — dead under clear-wins. FAIL (Thufir's witness).
"""
violations = []
# Source: live override RegB(1,0,10) at frontier=10 — Thufir's witness.
src_s, src_c, src_b, src_front = 1, 0, 10, 10
for tie_policy in (CLEAR, SET):
src = device_cls("src")
src.frontier["c0"] = src_front
src.overrides["c0"] = RegB(s=src_s, c=src_c, b=src_b)
# Confirm source is actually live.
assert src.override_is_set("c0", tie_policy), (
f"test precondition: source must be live under {tie_policy}"
)
# Produce the source's two slots via the (possibly mutated) split.
slots = src.split_blob_into_slots(tie_policy, n_slots=2)
slot0, slot1 = slots[0], slots[1]
src_live = src.override_is_set("c0", tie_policy)
for first_slot, second_slot in [(slot0, slot1), (slot1, slot0)]:
# Step 1: partial_obs receives first slot, canonically re-publishes.
partial_obs = device_cls("partial_obs")
partial_obs.receive_merge(first_slot)
transient_1 = partial_obs.publish_blob(tie_policy)
# Step 2: partial_obs receives second slot, publishes again.
partial_obs.receive_merge(second_slot)
transient_2 = partial_obs.publish_blob(tie_policy)
# Step 3: third-party finals receive BOTH source slots AND both
# transient publications, in several representative interleaving
# orders. All must agree with source liveness.
# Representative orders: transient_1 before both slots (most
# dangerous under M8), transient_1 after both slots, and
# interleaved. We check 3 explicit orders rather than all 4!
# permutations (24) for speed; M8's canonical false-clear path
# (transient_1 first, then second_slot only) is order 1.
check_orders = [
# Most dangerous: transient_1 arrives first, before any source
[transient_1, slot0, slot1, transient_2],
# Normal: both source slots first, then both transients
[slot0, slot1, transient_1, transient_2],
# Interleaved: first source, transient_1, second source, transient_2
[first_slot, transient_1, second_slot, transient_2],
]
for order in check_orders:
final = device_cls("final")
for blob in order:
final.receive_merge(blob)
final_live = final.override_is_set("c0", tie_policy)
if final_live != src_live:
t1_reg = partial_obs.overrides.get("c0")
violations.append((
"interleaved-delivery-false-clear",
tie_policy,
f"slot_order=(first={list(first_slot['contexts'].keys())[:2]}...)",
f"delivery_order={[list(b['contexts'].keys())[:2] for b in order]}",
f"transient_1_reg={t1_reg}",
f"final_reg={final.overrides.get('c0')}",
f"expected_live={src_live} got_live={final_live}",
))
return violations
# ---------------------------------------------------------------------------
# Escaped-context slot-grouping regression
#
# Thufir's CRITICAL (round 2): a raw context ID that starts with a
# reserved prefix (e.g. "ov_s:evil") escapes to "esc:ov_s:evil" as its
# frontier wire key. Before the fix, split_blob_into_slots grouped the
# frontier by its wire key ("esc:ov_s:evil") but the ov_* siblings by
# the raw suffix ("ov_s:evil") — two identities for one logical context.
# The frontier and its siblings landed in different slots.
#
# Across publication cycles the replaceable slot d-tag coordinates
# update slot-by-slot. A relay can therefore serve: new frontier slot
# (just published, carries esc:ov_s:evil=10) + stale override slot
# (old coordinate, carries ov_s/ov_c/ov_b at b=0 from the old pub).
# The reconstructed register is RegB(s=1, c=0, b=0) at frontier=10 —
# baseline-dead. Canonical re-publication emits tombstone RegB(0,1,0).
# Eventually both current slots + the transient merge to RegB(1,1,10) —
# dead under clear-wins — permanently suppressing a live override.
#
# The fix: derive the frontier's group identity via unescape_context_key
# so it joins the same group as its ov_* siblings. This test exercises
# both directions: M9 (reverts to escaped-key grouping) must reproduce
# the witness, and the correct model must pass.
# ---------------------------------------------------------------------------
def test_escaped_context_slot_grouping(device_cls=DeviceB):
"""Regression for escaped-context identity mismatch in split_blob_into_slots.
Scenario:
1. Source has a live override on raw context "ov_s:evil" (escapes to
"esc:ov_s:evil" as frontier wire key) — Thufir's exact escaped witness.
2. Source publishes twice: first at frontier=0/b=0, then after advancing
frontier to 10 and re-marking unread (b=10). Each publication produces
2 slots. Simulates a relay retaining a stale old-cycle slot under its
old replaceable coordinate while only the new-cycle slot for the OTHER
half has been updated — the old/new slot-coordinate mixture.
3. An observer receives: new-cycle frontier-bearing slot (frontier=10,
esc:ov_s:evil=10) + stale old-cycle override slot (ov_s/ov_c/ov_b from
first pub where b=0).
4. Observer canonically re-publishes (mandatory, per NIP-RS spec).
5. A third-party final observer receives both current-cycle source slots
plus the transient re-publication.
6. Oracle: final observer must see the override as live.
With the unescape-before-group fix: frontier + ov_* siblings always land
in the same slot → no partial register → no false tombstone. PASS.
With M9 (escaped-key grouping): frontier in one slot, siblings in another
→ partial reconstruction → false tombstone → final merge dead. FAIL.
"""
violations = []
raw_ctx = "ov_s:evil"
for tie_policy in (CLEAR, SET):
# --- Publication cycle 1: initial state, frontier=0 ---
src_old = device_cls("src")
src_old.frontier[raw_ctx] = 0
src_old.do_mark_unread(raw_ctx) # RegB(s=1, c=0, b=0)
old_slots = src_old.split_blob_into_slots(tie_policy, n_slots=2)
# old_slots[0] is the "stale old-coordinate slot" a relay may retain.
# --- Publication cycle 2: frontier advances, re-mark-unread ---
src_new = device_cls("src")
src_new.frontier[raw_ctx] = 10
src_new.do_mark_unread(raw_ctx) # RegB(s=1, c=0, b=10) — live at frontier=10
assert src_new.override_is_set(raw_ctx, tie_policy), (
f"test precondition: source must be live under {tie_policy}"
)
new_slots = src_new.split_blob_into_slots(tie_policy, n_slots=2)
# --- Full delivery: both new slots → both current-cycle slot arrive ---
recv_full = device_cls("recv_full")
recv_full.receive_merge(new_slots[0])
recv_full.receive_merge(new_slots[1])
if not recv_full.override_is_set(raw_ctx, tie_policy):
violations.append((
"escaped-ctx-full-delivery-dead", tie_policy,
f"full={recv_full.overrides.get(raw_ctx)}",
))
# --- Mixture: new frontier-bearing slot + stale old override slot ---
# Identify which new slot carries the frontier and which carries ov_*,
# then pair the frontier slot with the old-cycle override slot.
wire_frontier = escape_context_key(raw_ctx)
new_frontier_slot_idx = 0 if wire_frontier in new_slots[0]["contexts"] else 1
new_frontier_slot = new_slots[new_frontier_slot_idx]
old_override_slot = old_slots[1 - new_frontier_slot_idx] # opposite slot
# Check whether the frontier and ov_* siblings are co-located in new_slots.
ov_s_key = f"ov_s:{raw_ctx}"
frontier_and_ov_same_slot = (
wire_frontier in new_slots[new_frontier_slot_idx]["contexts"] and
ov_s_key in new_slots[new_frontier_slot_idx]["contexts"]
)
if frontier_and_ov_same_slot:
# Correct grouping: old override slot has nothing relevant, mixture
# is safe by construction — the stale slot is just an empty dict.
# Verify anyway for defense-in-depth.
obs = device_cls("obs")
obs.receive_merge(new_frontier_slot)
obs.receive_merge(old_override_slot)
transient = obs.publish_blob(tie_policy)
final = device_cls("final")
final.receive_merge(new_slots[0])
final.receive_merge(new_slots[1])
final.receive_merge(transient)
if not final.override_is_set(raw_ctx, tie_policy):
violations.append((
"escaped-ctx-grouped-mixture-dead", tie_policy,
f"transient={obs.overrides.get(raw_ctx)}",
f"final={final.overrides.get(raw_ctx)}",
))
else:
# Mismatched grouping (M9 path): frontier and siblings split.
# The mixture produces a partial register → false tombstone.
obs = device_cls("obs")
obs.receive_merge(new_frontier_slot) # gets frontier=10, no ov_*
obs.receive_merge(old_override_slot) # gets ov_s/ov_c/ov_b at b=0
transient = obs.publish_blob(tie_policy)
# Final observer gets everything: both new slots + transient.
for order in [(new_slots[0], new_slots[1]), (new_slots[1], new_slots[0])]:
final = device_cls("final")
final.receive_merge(order[0])
final.receive_merge(order[1])
final.receive_merge(transient)
if not final.override_is_set(raw_ctx, tie_policy):
violations.append((
"escaped-ctx-mixture-false-clear", tie_policy,
f"obs_reg={obs.overrides.get(raw_ctx)}",
f"transient_reg={transient['contexts']}",
f"final_reg={final.overrides.get(raw_ctx)}",
))
return violations
# ---------------------------------------------------------------------------
# Reserved key namespace: adversarial prefix collision
# ---------------------------------------------------------------------------
def test_reserved_namespace_collision():
"""A genuine user context whose raw ID begins with the reserved `ov_`
stem (e.g. a pre-existing legacy context literally named `ov_s:evil`)
must round-trip as frontier state, not be misparsed as a control key
for a different context, and must not collide with a real override's
sibling keys in the same flattened contexts map.
Exercises: escape on publish, unescape on receive, and a live
override on a DIFFERENT context in the same blob to prove no
control-key collision occurs.
"""
violations = []
adversarial_raw = "ov_s:evil" # would misparse as ov_s: control for ctx "evil"
real_ctx = "c0"
# Escaping must be a no-op for every context ID Buzz actually
# generates, and must trigger for the adversarial one.
for benign in ("b68cd7cb-6f8d-4641-b743-a7349eb4114b",
"msg:" + "a" * 64, "thread:" + "b" * 64):
if escape_context_key(benign) != benign:
violations.append(("namespace-benign-escaped", benign))
if escape_context_key(adversarial_raw) == adversarial_raw:
violations.append(("namespace-adversarial-not-escaped", adversarial_raw))
if not escape_context_key(adversarial_raw).startswith(ESCAPE_PREFIX):
violations.append(("namespace-adversarial-missing-marker", adversarial_raw))
dev = DeviceB("d0")
dev.frontier[adversarial_raw] = 42
dev.frontier[real_ctx] = 5
dev.do_mark_unread(real_ctx)
blob = dev.publish_blob()
wire_key = escape_context_key(adversarial_raw)
if wire_key not in blob["contexts"]:
violations.append(("namespace-wire-key-missing", wire_key, blob["contexts"]))
if blob["contexts"].get(wire_key) != 42:
violations.append(("namespace-value-corrupted", wire_key, blob["contexts"].get(wire_key)))
recv = DeviceB("recv")
recv.receive_merge(blob)
if recv.effective_frontier(adversarial_raw) != 42:
violations.append((
"namespace-roundtrip-failed", adversarial_raw,
recv.effective_frontier(adversarial_raw),
))
if adversarial_raw in recv.overrides:
violations.append(("namespace-misparsed-as-override", adversarial_raw))
if recv.overrides.get(real_ctx) is None or recv.overrides[real_ctx].s == 0:
violations.append(("namespace-real-override-corrupted", real_ctx, recv.overrides.get(real_ctx)))
return violations
# ---------------------------------------------------------------------------
# Run all
# ---------------------------------------------------------------------------
def run_all():
print("=" * 60)
print("NIP-RS manual-unread exhaustive model")
print("=" * 60)
total_violations = 0
def report(name, violations):
nonlocal total_violations
n = len(violations) if isinstance(violations, list) else 0
total_violations += n
status = "PASS" if n == 0 else f"FAIL ({n})"
print(f" {name}: {status}")
if n > 0:
for v in violations[:3]:
print(f" {v}")
print("\n--- I1: merge algebra (B) ---")
report("assoc/commut/idempot", test_merge_algebra_b())
print("\n--- I1: merge algebra (A) ---")
report("assoc/commut/idempot", test_merge_algebra_a())
print("\n--- I2+I3+I5: BFS explorer (B, clear-wins) ---")
n, v = explore_b(max_depth=4, tie_policy=CLEAR)
print(f" states explored: {n}")
report("convergence+frontier+compaction", v)
print("\n--- I2+I3+I5: BFS explorer (B, set-wins) ---")
n, v = explore_b(max_depth=4, tie_policy=SET)
print(f" states explored: {n}")
report("convergence+frontier+compaction", v)
print("\n--- I4: concurrent set/clear stability ---")
report("stable winner", test_concurrent_stability())
print("\n--- I5: compaction register-level exhaustive ---")
report("all register values x policies", test_compaction_register_exhaustive())
print("\n--- I5c: directed deep-history (compact -> reuse -> stale delivery) ---")
cube_size, deep_v = test_deep_history_compaction()
print(f" parameter cube size: {cube_size}")
report("no divergence from never-compact reference", deep_v)
print("\n--- I5c: tombstone + stale-ancestor merge (direct) ---")
report("no resurrection", test_tombstone_stale_merge_direct())
print("\n--- I5d: tombstone-merge monotonicity (structural lemma) ---")
report("ceiling never strengthens S", test_tombstone_merge_monotonic())
print("\n--- I5d: cross-device compaction transparency (suppress-only) ---")
cd_cube, cd_suppress, cd_v = test_cross_device_compaction_suppression()
print(f" parameter cube size: {cd_cube} suppressions observed: {cd_suppress}")
report("suppress-only + recoverable", cd_v)
print("\n--- Published-state merge closure (canonical publication guarantee) ---")
mc_cube, mc_v = test_published_merge_closure()
print(f" pairs checked: {mc_cube}")
report("no dead+dead resurrection", mc_v)
print("\n--- I6: replay harmless ---")
report("replay", test_replay_harmless())
print("\n--- I7: legacy rewrite (B) ---")
report("sibling keys survive", test_legacy_rewrite_b())
print("\n--- I7: legacy erasure (A) — expected witness ---")
erased = test_legacy_erasure_a()
print(f" overrides erased by legacy: {'CONFIRMED' if erased else 'NOT FOUND'}")
if not erased:
total_violations += 1
print("\n--- I8: bounded growth ---")
report("canonical wire shape (3 live / 1 tombstone)", test_bounded_growth())
print("\n--- I8: exact wire-shape regression ---")
report("live=3 keys, tombstone=1 key, virgin=0 keys", test_wire_shape_exact())
print("\n--- I9: DeviceA counter absorption ---")
absorbed = test_a_counter_absorption()
print(f" post-receive counter > received: {'CONFIRMED' if absorbed else 'FAIL'}")
if not absorbed:
total_violations += 1
print("\n--- Identity-free (B) ---")
report("reinstall convergence", test_b_identity_free())
print("\n--- Legacy prune interaction ---")
ov_ok, msg_ok, nested_lost = test_legacy_prune_interaction()
print(f" ov_ keys survive: {'PASS' if ov_ok else 'FAIL'}")
print(f" msg: pruned at horizon: {'PASS' if msg_ok else 'FAIL'}")
print(f" nested msg:ov_ lost: {'CONFIRMED (hazard)' if nested_lost else 'NOT FOUND'}")
if not ov_ok:
total_violations += 1
print("\n--- Legacy trim interaction ---")
blocked = test_legacy_trim_interaction()
print(f" excess overrides block publish: {'CONFIRMED (hazard)' if blocked else 'NOT FOUND'}")
print("\n--- Multi-slot union ---")
report("split+merge convergence", test_multi_slot_union())
print("\n--- Interleaved delivery + atomic grouping rule ---")
report("no false clear under slot interleaving", test_interleaved_delivery_grouping())
print("\n--- Escaped-context slot-grouping regression ---")
report("escaped ctx: frontier + ov_* siblings same slot", test_escaped_context_slot_grouping())
print("\n--- Reserved key namespace: adversarial prefix collision ---")
report("escape/unescape + no misparse", test_reserved_namespace_collision())
print("\n" + "=" * 60)
if total_violations == 0:
print("ALL INVARIANTS HOLD — 0 violations")
else:
print(f"VIOLATIONS: {total_violations}")
print("=" * 60)
return total_violations
if __name__ == "__main__":
import sys
sys.exit(0 if run_all() == 0 else 1)