LearnNewsExamplesServices
Frontmatter
id13137
titleWake lifecycle-directive: heartbeat-only placement (not A2A message wakes) + text compression
stateClosed
labels
enhancementaimodel-experience
assigneesneo-opus-vega
createdAtJun 13, 2026, 11:24 PM
updatedAtJun 14, 2026, 12:41 AM
githubUrlhttps://github.com/neomjs/neo/issues/13137
authorneo-opus-vega
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 14, 2026, 12:41 AM

Wake lifecycle-directive: heartbeat-only placement (not A2A message wakes) + text compression

Closed v13.1.0/archive-v13-1-0-chunk-2 enhancementaimodel-experience
neo-opus-vega
neo-opus-vega commented on Jun 13, 2026, 11:24 PM

Context

Follow-up to #13118 / #13119 (lifecycle-first wake directive), from @tobiu's review of PR #13119 on 2026-06-13. Two coupled cost issues with the standing WAKE_LANE_DIRECTIVE:

  1. (primary) placement — it is appended to EVERY wake digest, including A2A-message-triggered wakes, when it is an idle-watchdog nudge that only belongs on heartbeat wakes.
  2. (secondary) length — the directive text is token-heavy (~1,100 chars / ~280 tokens) for per-wake content.

Release classification: boardless — Agent OS / MX cost hardening, not a v13 release blocker.

The Problem

ai/daemons/wake/daemon.mjs buildWakeDigest appends the directive UNCONDITIONALLY (line ~1158):

return `[WAKE][priority:${digestPriority}] ${N} events for ${identity}: ${breakdown}\n\nSubscription: ${subId}\n\n${WAKE_LANE_DIRECTIVE}`;

A digest's events are {messages, tasks, permissions, heartbeats}. So a wake triggered by an A2A broadcast (lane-claim) or direct message carries the full lifecycle directive — even though that wake already has specific actionable content. The directive is an IDLE-agent nudge ("you're idle, here's what to do next"); on a message wake it is pure noise + token waste. And message wakes are far more frequent than the 20-min heartbeat, so frequency × length makes placement the dominant directive token cost — worse than the length alone.

The Architectural Reality

  • daemon.mjs buildWakeDigest is the append site (line ~1158); the directive is the idle-watchdog semantic, which maps to the heartbeat event type (heartbeat_pulse{type:'heartbeat'}), NOT messages / tasks / permissions.
  • The daemon already distinguishes wake types (coalescing handles type === 'heartbeat' vs message events distinctly), so the gate is cheap.
  • wakeLaneDirective.mjs owns the directive text; wakeLaneDirective.spec pins its behavioral anchors (lifecycle-first ordering, routing tiers, idle terminals) — these are the clarity floor for any compression.

The Fix

  • AC1 (placement, primary): buildWakeDigest appends WAKE_LANE_DIRECTIVE ONLY to pure-heartbeat digests — i.e. when messages, tasks, and permissions are all empty and a heartbeat is present. A digest carrying any actionable A2A content (broadcast / direct message / task / permission), including a mixed heartbeat+message digest, omits the directive.
  • AC2 (test): a daemon test asserts the directive IS present on a heartbeat-only digest and ABSENT on a message-triggered digest (and on a mixed heartbeat+message digest).
  • AC3 (compression, secondary): compress the directive text to net-reduce per-wake tokens while preserving the behavioral anchors (lifecycle-first ordering, the routing tiers, the idle terminals); co-update wakeLaneDirective.spec's phrase assertions to the new load-bearing anchors. Risk to avoid: over-compression that reverts to the backlog-first / idle failure mode #13118 fixed — the directive is long because the explicit ordering changed behavior; the spec anchors are the floor.
  • AC4 (evidence): PR body shows the token/char before→after AND notes the placement change removes the directive from the majority of wakes (message wakes), with the heartbeat-only retained surface named.

Out of Scope

  • No delivery-trigger PR-state watcher (still deferred per #13118).
  • No change to the directive's behavioral MEANING beyond compression.
  • No new scheduler / scoreboard / lease.

Dependency

Touches daemon.mjs buildWakeDigest (the same surface PR #13119 modifies) → implement AFTER #13119 merges, off dev, to avoid a conflict.

Duplicate / freshness evidence

  • Live open-issue sweep 2026-06-13: gh issue list --search "wake directive token" and "WAKE_LANE_DIRECTIVE" → both empty; no equivalent ticket.
  • #13118 "Out of Scope" lists the delivery-trigger watcher but NOT directive placement / compression — this is a distinct, un-tracked follow-up.

Related

Related: #13118, #13119, #13114

Origin Session ID: 4cc428e3-cf36-4324-8646-1b96cb23fa4a