caveman bug. test fail since #505 (commit 8c40e32 fix(state): gate Pin/Unpin/Set/UpdateProfile on membership).
Repro
$ cargo test -p willow-state non_admin_set_profile_is_accepted
thread panicked at crates/state/src/tests/materialize.rs:67:5:
assertion `left == right` failed
left: None
right: Some("Alice")
Root cause
Test emits two events via do_emit (crates/state/src/tests/materialize.rs:25):
- admin's
GrantPermission { peer_id: alice, permission: SendMessages }
- alice's
SetProfile { display_name: "Alice" }
do_emit always passes deps: vec![]. Cross-author causal linkage absent. Per-author seq chains both authors separately but doesn't link admin's grant to alice's set-profile.
Pre-#505: SetProfile had no membership gate → order-of-application irrelevant → test passed.
Post-#505: SetProfile rejected if author not yet in state.members. topological_sort tiebreaker happens to apply alice's SetProfile BEFORE admin's GrantPermission → membership check fails → silent reject → state.profiles.get(alice) returns None.
Two valid fixes
A. Test-side: thread the grant event's hash into SetProfile's deps so causal ordering is forced. Minimal, isolated. But same shape exists in 4+ other tests (grep do_emit.*SetProfile).
B. Production-side: have apply_event buffer events whose author membership isn't yet established, retry on later GrantPermission. Mirrors PendingBuffer's prev-chain handling. Bigger refactor but resolves the same shape for real-world out-of-order delivery.
Skill: ambiguous-fix-path; design call needed. Coordinator-flagged + filed during run that exposed it (auto-fix batch claude/friendly-maxwell-M5xB6).
Sites
Run notes
Surfaced by 2 implementer agents in this session (#550 + #520) running cargo test -p willow-state. Reproduced from coordinator HEAD before filing — not a sandbox flake.
caveman bug. test fail since #505 (commit
8c40e32 fix(state): gate Pin/Unpin/Set/UpdateProfile on membership).Repro
Root cause
Test emits two events via
do_emit(crates/state/src/tests/materialize.rs:25):GrantPermission { peer_id: alice, permission: SendMessages }SetProfile { display_name: "Alice" }do_emitalways passesdeps: vec![]. Cross-author causal linkage absent. Per-author seq chains both authors separately but doesn't link admin's grant to alice's set-profile.Pre-#505:
SetProfilehad no membership gate → order-of-application irrelevant → test passed.Post-#505:
SetProfilerejected if author not yet instate.members.topological_sorttiebreaker happens to apply alice'sSetProfileBEFORE admin'sGrantPermission→ membership check fails → silent reject →state.profiles.get(alice)returnsNone.Two valid fixes
A. Test-side: thread the grant event's hash into
SetProfile'sdepsso causal ordering is forced. Minimal, isolated. But same shape exists in 4+ other tests (grepdo_emit.*SetProfile).B. Production-side: have
apply_eventbuffer events whose author membership isn't yet established, retry on laterGrantPermission. MirrorsPendingBuffer's prev-chain handling. Bigger refactor but resolves the same shape for real-world out-of-order delivery.Skill: ambiguous-fix-path; design call needed. Coordinator-flagged + filed during run that exposed it (auto-fix batch claude/friendly-maxwell-M5xB6).
Sites
crates/state/src/tests/materialize.rs:43— failing testcrates/state/src/tests/materialize.rs:25—do_emithelper (alwaysdeps: vec![])crates/state/src/materialize.rs:548-555—SetProfilemembership gate (introduced auto-fix batch claude/friendly-maxwell-EjeTz (2026-05-01) #505)8c40e32— originRun notes
Surfaced by 2 implementer agents in this session (#550 + #520) running
cargo test -p willow-state. Reproduced from coordinator HEAD before filing — not a sandbox flake.