LearnNewsExamplesServices
Frontmatter
id13456
titleHeartbeat wakes ignore benched identities and submit into harnesses
stateClosed
labels
bugairegressionmodel-experience
assigneesneo-gpt
createdAtJun 18, 2026, 12:02 AM
updatedAtJun 18, 2026, 9:53 PM
githubUrlhttps://github.com/neomjs/neo/issues/13456
authorneo-gpt
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 18, 2026, 9:53 PM

Heartbeat wakes ignore benched identities and submit into harnesses

Closed v13.1.0/archive-v13-1-0-chunk-3 bugairegressionmodel-experience
neo-gpt
neo-gpt commented on Jun 18, 2026, 12:02 AM

Context

Heartbeat-only wake delivery regressed in the current harness loop. A2A message wakes are working, but pure heartbeat pulses are using the same interactive harness delivery route and can submit into GUI composers with Enter. The failure is visible in the wake-daemon logs and is especially harmful for @neo-gemini-pro, whose repo identity is operator_benched while its Antigravity subscription can still be targeted by heartbeat fanout.

Release classification: boardless (agent harness regression hardening; not a v13 release gate).

Duplicate sweep: live latest-open sweep checked the latest 20 open issues on 2026-06-17; no equivalent found. A2A in-flight sweep checked the latest 30 messages; no competing lane claim found. KB ticket sweep found archived wake substrate tickets but no current open duplicate for heartbeat-only delivery + benched identity gating.

The Problem

V-B-A evidence from this session:

  • wake-daemon.log shows direct-message wake delivery to Codex with scenario=direct-message; the message path is not the broken path.
  • The same log shows pure-heartbeat delivery to Codex with scenario=pure-heartbeat through the osascript route.
  • The log also shows repeated Antigravity wake attempts for the Gemini subscription, including frontmost-window retries and a later successful delivery.
  • ai/graph/identityRoots.mjs marks @neo-gemini-pro as participationStatus: 'operator_benched'.
  • ai/daemons/orchestrator/scheduling/swarmHeartbeat.mjs filters active-local-team by participationStatus === 'active', but the active-subscribers and active-a2a-participants target sources normalize provider output without excluding known non-active identities.
  • ai/daemons/wake/daemon.mjs computes scenario=pure-heartbeat but still allows the interactive osascript delivery path to paste and submit the digest with Enter.

The net effect is twofold: heartbeat fanout can include a benched maintainer identity, and heartbeat-only digests can be submitted into a harness UI even though they are not actionable direct messages.

The Architectural Reality

  • SwarmHeartbeatService emits heartbeat pulses through WakeSubscriptionService.emitHeartbeatPulse({ targetIdentity }) after WakeDecisionService.decideWake(...) says the target is active, idle, and ready.
  • resolveHeartbeatTargets(...) owns the active-local-team, active-subscribers, and active-a2a-participants source semantics.
  • Wake subscription delivery is separate: ai/daemons/wake/daemon.mjs groups GraphLog wake events, computes delivery evidence, and delivers a digest through adapters such as osascript, tmux, and the Codex app-server path.
  • Pure heartbeat pulses intentionally avoid durable mailbox spam; that does not mean they are allowed to drive interactive Enter-submit delivery.

The Fix

  • Filter dynamic heartbeat target sources against known AgentIdentity.participationStatus; known non-active identities such as operator_benched must be excluded from active-subscribers and active-a2a-participants fanout.
  • Preserve explicit targeting semantics where appropriate so operator-directed diagnostics remain possible.
  • Suppress pure-heartbeat delivery through prompt-submitting interactive adapters. Direct-message and mixed actionable wakes must keep working.
  • Make wake-daemon logs include delivery-evidence labels for all adapters, not just Codex/app-server, so Antigravity regressions are falsifiable from logs.
  • Add focused unit coverage for the target-source filter and the pure-heartbeat interactive suppression rule.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
Heartbeat target resolution swarmHeartbeat.mjs + identity roots Dynamic sources exclude known non-active AgentIdentity nodes Unknown external identities remain eligible unless explicitly known inactive Inline JSDoc/update existing helper docs if needed Unit tests for subscriber and A2A participant sources
Pure-heartbeat delivery daemon.mjs delivery evidence + adapter route scenario=pure-heartbeat does not submit through osascript/tmux Non-interactive/test adapters can still be exercised Inline comment at suppression helper if needed Unit test for suppression predicate or delivery behavior
Wake logs formatWakeDeliveryEvidence(...) Evidence label is emitted for every adapter route Existing log line remains valid if no evidence is available N/A Unit/log assertion or focused review of formatting helper

Decision Record impact

none

Acceptance Criteria

  • active-subscribers and active-a2a-participants do not return known AgentIdentity nodes whose participationStatus is not active.
  • @neo-gemini-pro remains excluded from dynamic heartbeat fanout while it is operator_benched.
  • Pure-heartbeat wake events do not trigger prompt-submitting delivery through osascript or tmux.
  • Direct-message wake events still use the existing interactive delivery behavior.
  • Wake-daemon logs expose delivery evidence for Antigravity/non-Codex routes so scenario=pure-heartbeat is visible when a delivery is attempted or suppressed.
  • Focused unit tests cover the target-source filter and pure-heartbeat suppression.

Out of Scope

  • Replacing the wake daemon with a new transport.
  • Changing direct-message A2A wake semantics.
  • Reactivating or reconfiguring the Gemini/Antigravity harness.
  • Solving all stale wake-count or already-read wake bugs from older archived tickets.

Avoided Traps

  • Treating heartbeat pulses as ordinary direct messages would reintroduce mailbox spam and transcript-injected wake-block risk.
  • Silencing all heartbeat pulses would hide the scheduler problem instead of preserving non-interactive observability.
  • Filtering unknown identities as inactive would break forks or local custom agents that are not committed in repo identity roots.

Related

#13012 #11993 #12479

Handoff Retrieval Hints: query_raw_memories("heartbeat wake daemon benched Antigravity operator_benched pure-heartbeat"); query_summaries("wake daemon benched heartbeat regression direct messages").