LearnNewsExamplesServices
Frontmatter
id14486
titleDisable wake + swarm-heartbeat emission via AiConfig toggles
stateClosed
labels
enhancementaiarchitecturemodel-experience
assigneesneo-opus-grace
createdAtJul 2, 2026, 5:07 PM
updatedAtJul 2, 2026, 9:09 PM
githubUrlhttps://github.com/neomjs/neo/issues/14486
authorneo-opus-grace
commentsCount1
parentIssue13652
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 2, 2026, 9:09 PM

Disable wake + swarm-heartbeat emission via AiConfig toggles

Closed v13.1.0/archive-v13-1-0-chunk-8 enhancementaiarchitecturemodel-experience
neo-opus-grace
neo-opus-grace commented on Jul 2, 2026, 5:07 PM

Context

Operator-directed prio-0 (@tobiu, 2026-07-02): after the lane-state Stop hook (NEO_LANE_STATE_ENFORCE=1, .claude/hooks/laneStateStopHook.mjs) landed, the swarm is flooded with duplicate wake messages + heartbeats. With 6 peers online the flood compounds N×. Live symptom this session: the mailbox unread count inflated to 450+; #14426 (mailbox integrity) is the sibling incident.

Root: the Stop hook forces turn continuation (no-hold-state), so an agent no longer needs to be woken to keep working — the hook already covers continuation. The wake-subscription + swarm-heartbeat mechanisms therefore became redundant flood-sources: each forced continuation re-processes and re-emits, and with 6 peers every wake fans out. What was liveness plumbing pre-hook is duplicate noise post-hook.

The Problem

There is no enable/disable toggle for wake emission or swarm heartbeats in the AiConfig SSOT (V-B-A'd config.template.mjs): wakeDaemon (:219) declares only data-paths (watermarks/cursors); mailbox (:679) declares only defaultReplyPolicy. The flood cannot be turned off without code changes — the operator needs a config switch.

The Architectural Reality

Emission SSOTs (V-B-A'd 2026-07-02):

  • Wake: ai/daemons/orchestrator/services/WakeDecisionService.mjs (the active AND idle AND ready wake-decision gate) · ai/services/memory-core/WakeSubscriptionService.mjs · ai/daemons/wake/daemon.mjs · ai/services/memory-core/MailboxService.mjs (A2A→wake).
  • Heartbeat: ai/daemons/orchestrator/services/SwarmHeartbeatService.mjs · ai/daemons/orchestrator/scheduling/swarmHeartbeat.mjs · ai/services/memory-core/heartbeatPulseEvaluator.mjs.
  • Config home: aiConfig (ADR-0019 SSOT). New wake.enabled leaf (or mailbox.wakeEnabled) + a swarmHeartbeat.enabled leaf.
  • ⚠️ Carve-out (config.template.mjs:367-368): genuine liveness-marker heartbeats (resumeHarness.mjs health-check, boot-heartbeat) "carry thin-but-real content and must keep passing." The disable targets the swarm work-pulse (the flood source), NOT process-liveness health-checks.

The Fix

Add ADR-0019-compliant AiConfig leaves + gate the emission sites:

  1. aiConfig.wake.enabledleaf(true, 'NEO_WAKE_ENABLED', 'boolean'). When false, WakeDecisionService / WakeSubscriptionService / the wake daemon emit no wake interrupts — globally what per-message wakeSuppressed:true already does. A2A messages still persist + deliver on the next list_messages; only the interrupt is suppressed.
  2. aiConfig.swarmHeartbeat.enabledleaf(true, 'NEO_SWARM_HEARTBEAT_ENABLED', 'boolean'). When false, SwarmHeartbeatService / swarmHeartbeat.mjs emit no work-pulse heartbeats. Process-liveness health-checks (carve-out) are NOT gated by this.
  3. Read the resolved leaf at each emission site (ADR-0019 §5.1 — read-at-use-site, no re-derivation/threading/mutation).
  4. Immediate relief once shipped: the flooding swarm sets NEO_WAKE_ENABLED=false + NEO_SWARM_HEARTBEAT_ENABLED=false (env override) and restarts — no code redeploy.

Contract Ledger Matrix

Field Value
Target Surface aiConfig.wake.enabled, aiConfig.swarmHeartbeat.enabled
Source of Authority ai/mcp/server/memory-core/config.template.mjs (AiConfig SSOT, ADR-0019)
Proposed Behavior boolean toggles; false → no wake-interrupt / no swarm work-pulse
Fallback NEO_WAKE_ENABLED / NEO_SWARM_HEARTBEAT_ENABLED env overrides; default true (backward-compat)
Docs JSDoc on each leaf + the emission-site gates
Evidence with both false: no wake events + no work-pulses; A2A messages still persist + deliver on next poll

Decision Record impact

aligned-with ADR-0019 (AiConfig reactive Provider SSOT — new declarative leaves + read-at-site gates). No ADR challenge.

Acceptance Criteria

  • aiConfig.wake.enabled leaf added (SSOT + env override); false suppresses wake emission/delivery interrupts across WakeDecisionService / WakeSubscriptionService / the wake daemon.
  • aiConfig.swarmHeartbeat.enabled leaf added; false suppresses SwarmHeartbeatService / swarmHeartbeat.mjs work-pulses.
  • Process-liveness health-check heartbeats (resumeHarness / boot-heartbeat carve-out, config.template.mjs:367-368) are NOT disabled by the swarm-heartbeat toggle.
  • A2A messages (add_message) still PERSIST and DELIVER on next list_messages when wake is disabled — only the wake interrupt is suppressed (mailbox not broken).
  • Each gate reads the resolved AiConfig leaf at the emission site (ADR-0019 — no re-derivation/threading/mutation).
  • Verified: with both leaves false, a message send + a heartbeat interval produce no wake interrupt / no work-pulse (test or documented observation).

Out of Scope

  • The Stop-hook itself (#14438 / #14439 / #14441 — the no-hold enforcement; this removes the redundant wake/heartbeat flood the hook made moot, it does not touch the hook).
  • Cross-harness wake delivery tiers (#14167 / #14168 — wake-enabling, the opposite concern).
  • Mailbox integrity forensics (#14426 — sibling flood symptom, different root).

Related

  • Parent epic: #13652 ("reduce AGENTS.md / wakes / heartbeats / skill cadence — hook-gated" — this is a direct leaf).
  • #14426 (mailbox integrity — the flood's sibling symptom).
  • #14438 / #14439 / #14441 (the Stop-hook + the L3-vs-economics Discussion that made wakes/heartbeats redundant).
  • #14167 / #14168 / #11829 (wake-driver substrate — the pre-hook rationale this supersedes for stop-hook deployments).
  • ADR-0019 (AiConfig SSOT).

Origin Session ID: 1d7923bf-11bd-4c02-925b-5286b10d244d

Handoff Retrieval Hints: query_raw_memories("disable wake heartbeat AiConfig flood stop-hook redundant"); emission SSOTs WakeDecisionService / SwarmHeartbeatService.

Live latest-open sweep: checked open issues 2026-07-02T~15:00Z (wake/heartbeat in:title + flood search); no equivalent — #13652 is the parent epic, #14167/#14168 are wake-ENABLING (opposite). A2A in-flight claim sweep (last 25): no overlapping claim.

Authored by Grace (@neo-opus-grace, Claude Opus 4.8). Operator-directed prio-0 (@tobiu).

tobiu referenced in commit 7d909ac - "fix(orchestrator): default wake delivery + swarm-heartbeat OFF (#14486) (#14498) on Jul 2, 2026, 9:09 PM
tobiu closed this issue on Jul 2, 2026, 9:09 PM