fix: dedup received CMBs to stop mesh replay storm - #32
Merged
Conversation
Surfaces the identity/addressing gap: a node's `name` is both the agent ID
(1:1 with a Claude Code session) and the only addressing handle, with no
role dimension — so a role served by many sessions (the README's own
"one planning, one coding" case) can't be expressed or targeted. Evidence:
defaultNodeName() per-session IDs + the plugin's hardcoded, non-addressable
cognitiveProfile "Engineering node".
Proposes ID:role = N:1 with role as an identity/addressing-layer attribute
(MMP §3/§4.4), explicitly NOT an 8th CAT7 field; role advertised in
discovery/handshake; `sym_send {to_role}` fan-out; orthogonal to groups
(isolation boundary) vs roles (addressable function). Backward compatible
(role optional). Open questions routed to CTO.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a receive-path seen-set (content-hash key -> last-seen ts, TTL 1h, cap 10000) in FrameHandler. _handleMemoryShare previously only guarded against lineage-parent echoes; a CMB re-sent by a peer (anchor-CMB replay on every Bonjour reconnect, or the same CMB gossiped by multiple peers) was reprocessed each time -- re-run through SVAF, remixed under a fresh key, re-emitted as cmb-accepted. With several flapping/zombie node instances replaying accumulated memory, this produced a sustained replay storm flooding every session. _cmbKey is a content hash over CMB fields (sym-core, MMP 8.2), so an identical re-send carries an identical key; suppressing a key already seen within the TTL window converges instead of cycling (MMP 4.2 O2 rejoin-without-replay). New remixes get new keys and are unaffected; a first-seen anchor CMB still bootstraps a fresh peer. Verified: same CMB x3 across 2 peers -> processed once; distinct keys still process; dedup cache respects the size cap. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Sustained mesh replay storm: old CMBs (CTO-concur, scope-doc, scan, lane-reconciliation) re-broadcast endlessly with fresh IDs across many nodes, flooding every session's context.
Root cause
FrameHandler._handleMemoryShareonly guarded against lineage-parent echoes. A CMB received from a peer — the anchor-CMB replay every node sends on each Bonjour reconnect (node.js ~1401), or the same CMB gossiped by multiple peers — was reprocessed each time: re-run through SVAF, remixed under a fresh key, re-emitted ascmb-accepted. With ~6-7 flapping/zombie instances each replaying accumulated memory, this cycled instead of converging. (Amplifier = the duplicate instances; this PR fixes the dedup gap.)Fix
Receive-path seen-set keyed on the CMB content-hash key (
_cmbKey, sym-core MMP §8.2): suppress a key already processed within a TTL window (1h, cache cap 10000). Converges per MMP §4.2 O2 (rejoin-without-replay). New remixes get new keys → unaffected; a first-seen anchor CMB still bootstraps a fresh peer.Verification
Same CMB ×3 across 2 peers → processed once; distinct keys still process; cache respects size cap. Existing failures in ask/llm-reason/empty-mesh tests are pre-existing + environment-dependent (no LLM provider / semantic-model variance), unrelated to frame routing.
Deploy (not done in this PR — gated)
Operational Track A (kill duplicate/zombie node instances) routed to founder — independent of this code fix.
🤖 Generated with Claude Code