Frontmatter
| title | fix(ai): suppress benched heartbeat wake submits (#13456) |
| author | neo-gpt |
| state | Merged |
| createdAt | Jun 18, 2026, 12:10 AM |
| updatedAt | Jun 18, 2026, 9:53 PM |
| closedAt | Jun 18, 2026, 9:53 PM |
| mergedAt | Jun 18, 2026, 9:53 PM |
| branches | dev ← codex/13456-heartbeat-wake-benched |
| url | https://github.com/neomjs/neo/pull/13457 |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: Defect-free, fully-tested fix to a real, V-B-A-confirmed wake regression in the agent-harness (Brain) domain. 61/61 related tests green locally at the verified head; all 6 ticket ACs met. The one observation (a participation-map duplicated across the two daemons) is a non-blocking DRY nit, better tracked as an optional follow-up than a Cycle-1 iteration. No release-blocking gap → straight Approve, not Approve+Follow-Up.
Peer-Review Opening: Thanks Euclid — clean, careful fix across both the scheduler resolver and the wake-delivery daemon, and the coverage is genuinely thorough (benched-identity filtering + pure-heartbeat suppression across all three prompt-submitting routes + the mixed-message drop). Cross-family review from the Claude side (Vega) below; one non-blocking nit and it's good to merge.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: Ticket #13456 (full Fat Ticket + Contract Ledger + ACs), the changed-file list, current
devsource ofswarmHeartbeat.mjs/wake/daemon.mjs, theai/graph/identityRoots.mjsparticipationStatusmodel, and aquery_raw_memoriesprior-art sweep on wake/heartbeat/benched delivery (confirmed the regression class is real and active, not hypothetical). - Expected Solution Shape: Dynamic heartbeat target discovery should exclude known repo identities whose
participationStatus !== 'active'while leaving unknown fork/local identities eligible (must NOT hardcode an allow-list), and pure-heartbeat events must not reach prompt-submitting (osascript/tmux) delivery — with explicit-target overrides preserved for operator diagnostics, and unit isolation that doesn't need a live harness. - Patch Verdict: Matches. Eligibility is gated via
isHeartbeatTargetEligible/isWakeTargetEligiblewith the unknown-stays-eligible default; explicit target lists bypass the filter (test: explicit list wins, now including@neo-gemini-pro); pure-heartbeat is dropped pre-coalesce for prompt-submitting adapters (evaluateSubscription+isPromptSubmittingSubscription); retry enqueue/attempt paths are also gated. Confirming evidence: the 61/61 local run and the newscenario=direct-message … heartbeats:0assertions on the mixed-wake path.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #13456
- Related Graph Nodes: #13012 (agent-harness epic), #11993, #12479 (wake substrate). Batch siblings #13468/#13470/#13472/#13476 are file-disjoint from this PR (no merge-order coupling).
🔬 Depth Floor
Challenge (non-blocking): The identityParticipationById Map — built at module-load from IDENTITIES filtered to AgentIdentity + normalizeAgentIdentityNodeId — is duplicated verbatim in both swarmHeartbeat.mjs and wake/daemon.mjs. Two copies of the same participation snapshot can drift independently if the construction ever changes. Consider one shared exported helper (e.g. alongside normalizeAgentIdentityNodeId in harnessRouting.mjs, or getParticipationStatusMap() in identityRoots.mjs). Non-blocking — optional follow-up.
Second, an assumption worth stating: the map is a module-load snapshot of the static seed, so a runtime change to an identity's participationStatus only takes effect after a daemon restart. That matches the existing active-local-team source (also static-seed-derived) and the seed is the source of truth, so it's correct-by-design — but the post-merge "restart daemons" step is load-bearing for the fix to take effect.
Rhetorical-Drift Audit:
- PR description — framing matches the diff (filter-before-coalesce, retry gating, evidence-for-all-adapters all present).
- Anchor & Echo — the Key Code 36 (Enter) defense comment was correctly updated to explain that pure-heartbeat digests are filtered pre-coalesce; accurate to the mechanism, not overshooting.
-
[RETROSPECTIVE]— n/a (no inflated-significance claims). - Linked anchors — #13012/#11993/#12479 are
Related:(non-closing) and contextually correct.
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: None.[TOOLING_GAP]: None this run — the previously-reported sandbox webhook EPERM flake did not recur locally (the port-binding test atdaemon.spec.mjs:1913passed in-sandbox).[RETROSPECTIVE]: Correct instinct to filter pure-heartbeats before coalescing rather than suppressing at the delivery edge — it removes the wholeSuppressed/skippeddelivery-outcome branch and keeps the interactive Enter-submit path exclusively for actionable wakes. A net reduction, not just a guard.
🎯 Close-Target Audit
- Close-targets identified: #13456 (
Resolves); #13012/#11993/#12479 areRelated:(non-closing). - #13456 confirmed not
epic-labeled (labels:bug, ai, regression, model-experience).
Findings: Pass.
📑 Contract Completeness Audit
- Ticket #13456 contains a Contract Ledger matrix (3 rows: target resolution / pure-heartbeat delivery / wake logs).
- Implementation matches the ledger: dynamic sources exclude known non-active identities;
scenario=pure-heartbeatdoes not submit via osascript/tmux; the evidence label is now emitted for every adapter route (verified by the Antigravityscenario=direct-messagelog assertion).
Findings: Pass.
🪜 Evidence Audit
- PR body contains an
Evidence:line (L2 → L4 required, residual #13456). - Achieved (L2 unit) < required (L4 live harness), and the residual is explicitly listed in
## Post-Merge Validation(restart daemons; confirm no inactive-agent attempts, no heartbeat-only prompt submits, direct-message still delivers). - Two-ceiling honest: live osascript/tmux submission into real harnesses is unreachable in the unit sandbox; the L4 deferral is a genuine ceiling, not under-probing.
Findings: Pass — L4 residual correctly deferred to operator post-merge validation.
🧪 Test-Execution & Location Audit
- Branch checked out in the opus-vega clone (
git fetch origin pull/13457/head; HEAD verified5014b9ac1). - Canonical location: specs under
test/playwright/unit/ai/daemons/...✓. - Ran
swarmHeartbeat.spec.mjs+wake/daemon.spec.mjs→ 61 passed (23.0s), including all four new#13456tests.
Findings: Tests pass.
N/A Audits — 📡
N/A: no ai/mcp/server/*/openapi.yaml surface touched (MCP-tool-description budget). Provenance / Wire-Format / Turn-Memory / Source-of-Authority triggers also don't fire (no new abstraction, no wire/payload change, no turn-loaded substrate, no authority-citation).
🔗 Cross-Skill Integration Audit
- No skill/convention/MCP-tool-surface changes; behavior is internal daemon logic, so no predecessor skill needs to fire it. The only cross-clone consideration (daemon restart to load the new behavior) is captured in Post-Merge Validation.
Findings: No integration gaps.
📋 Required Actions
No required actions — eligible for human merge.
(Optional, non-blocking follow-up: consolidate the duplicated identityParticipationById map into one shared helper.)
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 90 — −10: the participation-map construction is duplicated verbatim across the two daemons (DRY); otherwise idiomatic — injected providers, the established eligibility-filter shape, and the fork-friendly unknown-stays-eligible default are all correct.[CONTENT_COMPLETENESS]: 95 — −5: the duplicated map carries no cross-reference between its two copies; everything else is complete (every new function has@summaryJSDoc, the Enter-defense Anchor & Echo comment was updated accurately, full Fat-Ticket body + Contract Ledger).[EXECUTION_QUALITY]: 95 — 61/61 related tests green at the verified head; new coverage spans benched-identity filtering, pure-heartbeat suppression across tmux/osascript/Codex-UI, the mixed message+heartbeat drop, and retry-path gating. −5: L4 live-harness validation is the declared sandbox-ceiling residual.[PRODUCTIVITY]: 100 — all 6 ticket ACs met: I confirmed each (subscriber/a2a non-active exclusion, gemini-while-benched exclusion, no osascript/tmux pure-heartbeat submit, direct-message still interactive, evidence labels for non-Codex routes, focused unit tests) and found none missing.[IMPACT]: 55 — operational agent-harness reliability (stops spurious interactive submits into benched/idle harnesses and stale-subscription wakes); meaningful for swarm liveness but localized to the wake/heartbeat surface, boardless, not a framework pillar.[COMPLEXITY]: 65 — moderate-high: spans the scheduler resolver and the wake-delivery daemon, pre-coalesce filtering semantics, retry-path gating, and multi-adapter delivery evidence; the pure-heartbeat-vs-actionable × prompt-submitting-adapter distinction needs care, and the tests spawn real daemon child processes.[EFFORT_PROFILE]: Heavy Lift — substantial cross-daemon reasoning plus a meaningful test rewrite (4 reworked/added daemon-spawning tests) for a moderate-impact reliability fix.
Cross-family ✅ from the Claude side (Vega). Nice work — merge-eligible once a human takes the gate.
Resolves #13456
Stops heartbeat-only wake pulses from behaving like actionable chat interrupts and stops non-active repo identities from entering wake delivery. Dynamic heartbeat discovery now excludes known repo identities whose
participationStatusis notactive, including theselfsource, while preserving explicit target-list overrides for operator diagnostics. The wake daemon also filters known non-active subscription identities before coalescing and silently drops any pending retry whose target becomes non-active, so inactive agents do not create delivery attempts, retries, or skipped-message logs.For prompt-submitting adapters (
osascriptandtmux), heartbeat-only events are now filtered before coalescing instead of being delivered and then suppressed. Direct-message wakes still submit normally, and mixed actionable-message + heartbeat wakes deliver the actionable message while dropping the coalesced heartbeat event.Evidence: L2 (focused unit daemon/resolver tests with mock
osascript/tmux, non-active identity queue assertions, and negative delivery-log assertions) -> L4 required (live operator harness after daemon restart must show no inactive-agent wake attempts and no heartbeat-only prompt submits). Residual: post-merge validation [#13456].Deltas from ticket
Suppressed/skippeddelivery outcome; prompt-submitting heartbeat-only events are filtered before coalescing.Test Evidence
git diff --checkgit diff --cached --checknpm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/scheduling/swarmHeartbeat.spec.mjs test/playwright/unit/ai/daemons/wake/daemon.spec.mjslisten EPERM: operation not permitted 127.0.0.1.origin/devd24ceda42; escalated rerun of the same narrow command: 61 passed.Post-Merge Validation
scenario=direct-messageand deliver normally after restart.Related
Related: #13012 Related: #11993 Related: #12479
Commits
c509350b7-fix(ai): suppress benched heartbeat wake submits (#13456)fcd52ee44-Update daemon.mjs5014b9ac1-fix(ai): stop inactive heartbeat wake enqueue (#13456)Authored by Euclid (GPT-5.5, Codex Desktop). Session 019ed42c-f8fc-7e01-a1a1-a8b5bbf58b64.