LearnNewsExamplesServices
Frontmatter
id12612
titleEnrich daemon idle-out wake digests with cycle-state content
stateClosed
labels
enhancementno auto closeaiarchitecturemodel-experience
assigneesneo-opus-vega
createdAtJun 6, 2026, 3:31 AM
updatedAtJun 20, 2026, 11:44 AM
githubUrlhttps://github.com/neomjs/neo/issues/12612
authorneo-gpt
commentsCount3
parentIssue11829
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 20, 2026, 11:44 AM

Enrich daemon idle-out wake digests with cycle-state content

Closed v13.1.0/archive-v13-1-0-chunk-1 enhancementno auto closeaiarchitecturemodel-experience
neo-gpt
neo-gpt commented on Jun 6, 2026, 3:31 AM

Context

D#12630 graduated the idle-holding fix under Epic #11829. This issue is Sub B of that graduation.

The previous body described A2A add_message / MESSAGE.wakeMetadata consumer work. That shape is stale. The corrected source of authority is daemon GraphLog-pulse content: idleOutNudge.mjs -> WakeSubscriptionService.emitHeartbeatPulse() -> the bridge-daemon wake digest. Daemon pulses are not MESSAGE nodes, so they cannot use the A2A wakeMetadata schema.

Verified Source Anchors

  • D#12630 final [GRADUATED_TO_TICKET] maps Sub B to #12612 and names the corrected daemon-vs-A2A split.
  • ai/scripts/lifecycle/idleOutNudge.mjs emits idle-out heartbeat pulses through WakeSubscriptionService.emitHeartbeatPulse().
  • WakeSubscriptionService.emitHeartbeatPulse() records GraphLog pulse events rather than mailbox messages.
  • ai/daemons/bridge/daemon.mjs renders delivered wake digests; current heartbeat lines are opaque count summaries such as N heartbeat pulses plus the latest GraphLog id.
  • PR #12608 A2A wakeMetadata was held/closed as superseded for this lane; #11909 remains open for the daemon wake-content layer.

The Problem

The daemon wake digest can tell a receiver that heartbeat or idle-out pulses happened, but it does not expose enough lifecycle state for the agent to choose the next cycle step without prose inference.

That opacity is part of the idle-holding failure mode: an agent sees a wake, treats async wait states as synchronous blockers, and signs off instead of advancing the lifecycle queue or claiming a non-colliding lane.

The Fix

Enrich the daemon GraphLog pulse path and bridge-daemon digest with compact cycle content:

  1. Carry machine-readable cycle-state / lane-ownership / next-action fields for idle-out and heartbeat pulse wakes at the GraphLog payload boundary, bridge summary boundary, or a clearly documented equivalent daemon boundary.
  2. Render those fields in the bridge-daemon wake digest so the receiving harness can branch on the cycle step without regex-parsing subject/body prose.
  3. Preserve replay and delivery semantics for GraphLog-only pulses. Do not convert daemon pulses into MESSAGE nodes unless a separate contract explicitly requires it.
  4. Add focused tests for the daemon pulse payload/digest path and legacy heartbeat fallback.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback / Edge Case Evidence
idleOutNudge.mjs -> WakeSubscriptionService.emitHeartbeatPulse() D#12630 Sub B + #11909 daemon scope Idle-out pulses carry enough structured cycle state for the receiver to select the next step If a pulse has no cycle context, legacy GraphLog-only delivery still works Focused wake-subscription / lifecycle tests
ai/daemons/bridge/daemon.mjs wake digest D#12630 Sub B + #11829 wake-driver substrate Heartbeat / idle-out digest lines include cycle-state, lane ownership, and next-action content when present Existing opaque count digest remains valid for legacy pulses Bridge-daemon digest tests
A2A add_message.wakeMetadata Corrected daemon-vs-A2A split in D#12630 Out of scope for this issue; it is a different mechanism A2A awareness/noise control is handled separately through the existing wakeSuppressed path No A2A schema assertions in this PR

Acceptance Criteria

  • Daemon idle-out / heartbeat pulses expose structured cycle content at the selected daemon boundary.
  • Bridge-daemon digest rendering includes that cycle content for pulse wakes and remains backward-compatible for legacy pulse events.
  • The PR explicitly documents why this issue does not use add_message, MESSAGE.wakeMetadata, or mailbox sender population.
  • Focused unit coverage proves pulse enrichment, digest rendering, and legacy fallback behavior.
  • #11909 stays open until the daemon wake-content behavior is delivered or separately dispositioned.

Out of Scope

  • A2A MESSAGE.wakeMetadata schema/storage/read surfaces.
  • Relaxing wakeSuppressed for FYI peer-message noise control.
  • Reworking the whole wake-subscription trigger system.
  • Replacing bridge-daemon delivery adapters.

Related

Parent epic: #11829

Graduation source: D#12630

Daemon backing ticket: #11909

Superseded A2A path: PR #12608

Retrieval Hint: daemon GraphLog heartbeat pulse bridge digest idle-out cycle-state next-action

tobiu referenced in commit 269f735 - "refactor(agentos): delete holding vocabulary + encode the cycle as operating model (#12632) (#12658) on Jun 7, 2026, 1:17 AM