Skip to content

[Dream Cycle 2026-10-09] swarm: MessageBus broadcast-retry re-queues under the 'broadcast' sentinel instead of the real subscriber, silently dropping failed deliveries + ruvector-integration, ruview-integration scan #3928

Closed

Description

@ruvnet

1. Tonight's Rotation

DATE=2026-10-09
DEEP=swarm
SCAN=ruview-integration,ruvector-integration
SLOT=4
COMMIT=58e0ae7e14e68aab45a4127d6f42f567bbcfb328
BRANCH=dream/2026-10-09-swarm

No bonus deep-dive triggers tonight (20261009 % 25 = 9, % 75 = 59).

2. Ledger Check

Last 14 rows inspected in docs/dream-cycle/LEDGER.md (through 2026-09-30). GitHub-verified fates for the trailing 7 nights before tonight (via pull_request_read/list_pull_requests/search_pull_requests, gh CLI present but its GH_TOKEN is invalid this session — FALLBACK applies to local gh use only, GitHub MCP tools work fine):

Night Surface PR State
10-01 security #3599 MERGED 2026-10-07
10-02 intelligence #3622 open/draft
10-03 memory #3650 open/draft
10-04 swarm — no-run gap (confirmed via git ls-remote --heads origin "dream/*"; slot sequence skipped straight to 10-05=performance)
10-05 performance #3754 closed, NOT merged (2026-10-07)
10-06 security #3835 open/draft
10-07 intelligence #3879 open/draft
10-08 memory #3909 open/draft

Also spot-checked older still-open items: #3339 (09-16 security, round 2) MERGED 2026-10-07; #3539 (09-29 swarm) MERGED 2026-10-07; #3476 (09-27 intelligence) still open/draft but updated today (not stale, <14d... actually 12d, still under the 14d STALE threshold). No new STALE items found (open >14d AND no follow-up) among the trailing 7.

Swarm-surface historical merge rate stays strong: #3086 (08-24), #3123 (08-29), #3243 (09-09), #3357 (09-19), #3539 (09-29) — 5/5 merged.

pi.ruv.io collective-memory check (STEP 2.1, read-only): unreachable from this environment (curl → HTTP status 000, connection failure) — noted as a supplementary-signal gap, not blocking.

3. Deep Dive Findings

5-role parallel research fan-out (deep researcher, competitor analyst, ruview scan, architecture reviewer, plus this session's own direct verification). Full report: docs/dream-cycle/dream-gist-2026-10-09.md (this branch).

Selected finding: MessageBus.broadcast() (v3/@claude-flow/swarm/src/message-bus.ts) sets message.to = 'broadcast' as a sentinel; enqueue() fans the message out to each real subscriber's own agentId-keyed queue. When a subscriber's delivery callback throws, handleDeliveryError()'s retry re-queue used this.addToQueue(message.to, message, entry.attempts) — i.e. the literal string 'broadcast', a queue key with no subscription. processQueues() skips any unsubscribed queue (if (!subscription) continue), so a failing broadcast subscriber's retries — and eventual message.failed — were silently dropped forever, and the orphaned queue entry leaked until shutdown(). This was explicitly flagged in-code as a "KNOWN LIMITATION (pre-existing, not fixed here)" comment by the immediately-preceding #3562/#3563 MessageBus rewrite, which fixed the direct-message path's busy-poll but left this broadcast-path gap disclosed and open.

Candidate scoring (STEP 3.2, 5 candidates, weighted formula): this finding scored highest (4.90) against three other swarm-internal candidates (TopologyManager role re-index gap, TaskOrchestrator priority-map missing-key bug, AgentPool heartbeat dead-code) and the ruview-integration scan (which scored 1.60 — architecturally real but not testable-tonight material). Full scoring table in the gist.

4. Hypothesis

Given a swarm using MessageBus.broadcast() where at least one subscriber's delivery callback throws, when handleDeliveryError()'s retry re-queue is changed to use the real subscriber's agentId (threaded through from deliverMessage()) instead of the literal string 'broadcast', then the failing subscriber should receive bounded retries up to config.retryAttempts and emit message.failed once exhausted — matching the already-correct direct-message path — subject to: zero change to happy-path (no-error) behavior, zero regression across the existing 274-test swarm suite, deterministic $0 Vitest evaluation.

Frozen before evaluation; not modified after seeing results.

5. Evaluation Receipt

evaluated: accepted. Real evaluator: Vitest 4.1.8, deterministic, $0, zero LLM calls, against a freshly pnpm install-ed v3/ workspace (not pre-built at session start — native deps like hnswlib-node compiled during setup).

  • New test file message-bus.broadcast-retry.test.ts (2 tests): stash-isolated baseline (fix reverted via git stash push -- src/message-bus.ts, test file untracked/unaffected) — both fail exactly as predicted (badInvocations 1 vs. expected 3; getQueueDepth() 1 vs. expected 0, i.e. the leaked orphaned queue). Candidate (stash popped): both pass.
  • Full @claude-flow/swarm suite: baseline 274/274 (17 files) → candidate 276/276 (18 files, +2 new), zero regressions.
  • tsc --noEmit: clean, 0 errors, both ways.
  • Healthy co-subscriber in the same broadcast delivers exactly once throughout, unaffected by the sibling's failure — explicit regression guard built into the new test.
  • Independently re-reproduced end-to-end by the adversarial critic (own stash/pop cycle, own full-suite + tsc run), byte-identical results.

6. Darwin Results

Skipped — binary correctness/wiring fix (which queue key to re-queue a retry under), no continuous or categorical parameter for Darwin's real interface (npx ruvector harness darwin <config> --execute, confirmed available v0.9.2) to search over. Same skip class as nearly every accepted fix in this ledger since 2026-08-18 (#3110/.../#3909).

7. Flywheel Evidence

No .claude-flow/flywheel/ state exists in this repo; npx ruvector harness flywheel --help confirms the real interface (verify/gate) targets signed, LLM-scored replay bundles, not a deterministic code fix like this one — same conclusion every prior night in this ledger has reached for this class of candidate. Evidence retained as: the 2 discriminating tests, this issue, the gist, the stash-isolated comparison (reproduced independently twice), and the full adversarial critique transcript (§9).

Classification: the broadcast-sentinel-vs-real-agentId root cause is an OBSERVATION (directly read from source); the stash-isolated before/after counts are a MEASUREMENT; "this closes the gap #3562/#3563 explicitly disclosed" is an INFERENCE connecting the two; ACCEPT is the DECISION.

8. Reward Hack Check

No standalone reward-hack CLI reachable this session (npx ruvector harness --help and npx metaharness --help expose Darwin/Flywheel/routing but no dedicated reward-hack verb despite @metaharness/weight-eft showing as an available direct dependency in harness doctor). Manual checklist, independently re-verified by the adversarial critic:

  • Test/threshold/gold-data weakened? No — diff is purely additive (2 call-site args, 1 new param, 1 re-queue-key line, 1 comment rewrite; one new test file).
  • Cherry-picked tasks / hidden preprocessing / seed manipulation? No — deterministic, no RNG involved, full suite disclosed both ways.
  • Error suppression hiding a real failure? No — the opposite: the fix makes a previously-suppressed failure (message.failed) surface correctly.
  • Cost hiding? N/A, $0 throughout.

9. Security Review

Not security-sensitive — pure in-process queue-key bookkeeping on an already-internal agentId, no new I/O/network/credential/filesystem surface. Independent adversarial critique (separate subagent, no authoring context, own repro): CONFIRMED, no blocking issues. It verified: the bug claim by reading the full file; baseline-fails/candidate-passes via its own stash/pop cycle; full suite 276/276 + clean tsc; that direct-message behavior is unchanged (subscription.agentId for a direct message already equals what message.to held); that subscription.agentId is always === the processQueues() loop's agentId key (no code path decouples them, including across subscribe/unsubscribe/resubscribe); no infinite-retry/double-delivery/leak risk; and that the new test's timing matches the already-merged sibling test exactly (no new flake exposure).

10. Scan Findings: ruview-integration

No real integration exists beyond a well-tested but unwired policy/schema module: v3/@claude-flow/security/src/policy/product-plane.ts defines a RuView product-plane profile (RuViewSemanticObservationV1, validateRuViewSemanticObservation(), privacy-ceiling P2/P3 enforcement) with substantive unit tests, but zero consumers anywhere in the codebase — no CLI command, MCP tool, or caller constructs/validates a real RuView observation. ADR-325 and ADR-326 (the covering design docs) are both still Proposed. This is new-feature work (building a consumer), not a scoped bugfix — not testable-tonight material, consistent with prior nights on this surface.

11. Scan Findings: ruvector-integration

v3/@claude-flow/cli/src/ruvector/graph-analyzer.ts's loadRuVector() checks for ruvector.hooks_graph_mincut/ruvector.hooks_graph_cluster and @ruvector/wasm's GraphAnalyzer class — neither exists in any version of either real package. Independently confirmed by two separate reviews: this session downloaded and inspected ruvector 0.2.27 through 0.3.3 directly (real exports: minCut, spectralClustering, louvainCommunities, buildGraph) and @ruvector/wasm (only VectorDB/SIMD utilities, no GraphAnalyzer); a separately-spawned architecture-reviewer agent independently verified against the locally-installed ruvector v0.2.41. git log --follow shows the file was introduced whole, not regressed from a once-working state — this has been 100% dead code since introduction. analyzeMinCutBoundaries()/analyzeModuleCommunities() always run the slower, approximate JS fallbacks instead of the real package's exact Stoer-Wagner minCut(). The existing test's own assertion (result === null || typeof result === 'object') is trivially true either way, so it doesn't catch this. Scored 4.20 in tonight's candidate table — a strong secondary finding, carried forward as a recommended candidate for a future ruvector-integration night rather than bundled into tonight's patch (keeping tonight's diff to one conceptual change).

12. Competitors Reviewed

LangGraph, Microsoft Agent Framework (AutoGen successor), CrewAI, OpenAI Agents SDK, Temporal (swarm topology/coordination); Qdrant, Weaviate, Milvus, LanceDB, LangChain.js faiss-node/hnswlib-node (native-fallback failure-mode research for the ruvector-integration scan). Full comparison table in the gist.

13. Gist

gh gist create unavailable this session (gh auth status → "Failed to log in... The token in GH_TOKEN is invalid" — same environment gap flagged by the 2026-09-30/10-08 nights). Full SOTA report committed instead at docs/dream-cycle/dream-gist-2026-10-09.md on this branch, and reproduced in full below the witness block for convenience. GIST=LOCAL.

14. Witness

Session commit:   58e0ae7e14e68aab45a4127d6f42f567bbcfb328
Candidate commit: (this branch's tip — see PR for the exact SHA)
Gist SHA-256 (pre-witness, mutable fields stripped to PENDING): 3b02818262f559907245450201b00bb7742dc781270d60f3deea159fa568e1fc
Witness stamp: 1b7e818e917acd3925b622ec26d78632ab8c872dab78da3ecf97fb0da27d461c

Verifier: fetch docs/dream-cycle/dream-gist-2026-10-09.md from this branch, strip its Witness block's filled-in values back to PENDING, SHA-256 the file, concatenate with the session commit above, SHA-256 again — must equal the witness stamp.

15. Recommendation

evaluated: accepted. Human review required before merge — see PR. Do not self-merge, do not autonomously promote Flywheel state. Two follow-up candidates disclosed for future nights: (1) wire the real ruvector package's graph exports into graph-analyzer.ts (ruvector-integration), (2) AgentPool.updateAgentHeartbeat() remains dead code post-#3242/3243 (swarm).


🤖 Generated with RuFlo

https://claude.ai/code/session_016qkoWKmaupqNEJwqiedzsX

Activity

  1. added a commit that references this issue on Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions