Context
Operator escalation (twice in 24h): agents receiving wake digests acknowledge them and idle, burning turns with no lane progress ("~40 wake messages, all ignored, ONE PR from 4 active agents… wasting VAST amounts of tokens without any results"). The cheapest, highest-leverage lever is the wake digest content itself: it currently states WHAT happened but never directs an idle agent to DO anything. Operator prescription, verbatim: "this could have been as simple as changing wake message content to 'pick up a new active lane, in case you don't have one.'" — and explicitly: "there is no 'operator gated'. there is no holding state."
Problem
ai/daemons/wake/daemon.mjs flushSubscription() builds the digest (~line 656):
[WAKE][priority:X] N events for <id>: <breakdown>
Subscription: <subId>
No standing directive. An agent with idle capacity reads the digest as "an interruption to acknowledge" rather than "a prompt to execute a lane." Other recent wake work (delivery routing, GitHub-notification ingestion, unread-count accuracy) changes delivery/counting — none changes the content to direct execution, and notification-ingestion actually increases wake volume without making each wake actionable.
Fix
Append a concise standing directive to every digest via a named module constant (WAKE_LANE_DIRECTIVE). Wording directs: if not already executing a lane → survey the backlog and drive one impl→test→PR this turn; acknowledge pure-FYI broadcasts in one line; a wake is never "handled" by acknowledgement alone when idle capacity + open lanes exist; do not idle or hold.
Acceptance Criteria
Contract Ledger
| Target Surface |
Contract detail |
| wake digest text (agent-consumed) |
Digest gains a trailing directive line; the [WAKE][priority:X] N events… header, breakdown bullets, and Subscription: <subId> line are unchanged. Anything parsing the header/subscription is unaffected (strictly append). |
Authored by Ada (@neo-opus-ada, Claude Opus 4.8)
Context
Operator escalation (twice in 24h): agents receiving wake digests acknowledge them and idle, burning turns with no lane progress ("~40 wake messages, all ignored, ONE PR from 4 active agents… wasting VAST amounts of tokens without any results"). The cheapest, highest-leverage lever is the wake digest content itself: it currently states WHAT happened but never directs an idle agent to DO anything. Operator prescription, verbatim: "this could have been as simple as changing wake message content to 'pick up a new active lane, in case you don't have one.'" — and explicitly: "there is no 'operator gated'. there is no holding state."
Problem
ai/daemons/wake/daemon.mjsflushSubscription()builds the digest (~line 656):No standing directive. An agent with idle capacity reads the digest as "an interruption to acknowledge" rather than "a prompt to execute a lane." Other recent wake work (delivery routing, GitHub-notification ingestion, unread-count accuracy) changes delivery/counting — none changes the content to direct execution, and notification-ingestion actually increases wake volume without making each wake actionable.
Fix
Append a concise standing directive to every digest via a named module constant (
WAKE_LANE_DIRECTIVE). Wording directs: if not already executing a lane → survey the backlog and drive one impl→test→PR this turn; acknowledge pure-FYI broadcasts in one line; a wake is never "handled" by acknowledgement alone when idle capacity + open lanes exist; do not idle or hold.Acceptance Criteria
flushSubscription()ends with the standing lane directive.Subscription:lines are unchanged (append-only — no parser break).Contract Ledger
[WAKE][priority:X] N events…header, breakdown bullets, andSubscription: <subId>line are unchanged. Anything parsing the header/subscription is unaffected (strictly append).Authored by Ada (@neo-opus-ada, Claude Opus 4.8)