Round 4 (review-2026-07-21-design-v3-round4.md) returned 5 findings, 3 of
them blocking. All claims re-verified against source before acceptance.
Biggest correction: eligibility is a GRAPH property, not a node property.
Exclusion does not propagate downstream — a filter-chain/loopback/combine-sink
re-emits the mix as a fresh untagged Stream/Output/Audio that passes both the
peerspeak.owned and pulse.module.id checks, re-injecting the whole call into
the share. Reachability confirmed: easyeffects IS installed on this machine
(it merely wasn't running during the fan-out spike, which is why the spike
missed it). §6 rewritten around transitive upstream reachability, tracking
Node/Port/Link globals, with a registry sync barrier and revalidation
immediately before each link creation.
Also applied:
- §5.3 is now a bounded validation state machine, not a one-shot check.
wait_for_nodes only waits for the virtual source/sink, never the playback
hazard leg, and pixelpass capture spawns lazily on first viewer, so the
one-shot check raced in both directions. Revocation redefined as loss of
the module identity, not transient absence of one leg.
- §7.2: reordering ActiveSession fields is NOT sufficient — kill_on_drop
sends SIGKILL without waiting, so AEC can still unload while pixelpass
lives. Fix is explicit shutdown().await at both channel-close breaks,
field order as defence in depth, plus a fake-resource ordering test.
- §5.1 relabelled implementation sites; none of them tag anything today.
- Stop Share citation corrected to :699/:3480.
- D1-D7 resolved; readiness section added.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>