Context
Operator-observed Codex behavior on 2026-06-15 still points at a heartbeat-vs-real-message wake split: heartbeat wakes submit/start a turn, while real A2A message wake-ups may not wake or may not submit when the operator is AFK.
The live Codex adapter evidence on #13287 still matters, but the latest mailbox V-B-A surfaced an upstream condition that does not require an adapter split: multiple targeted direct messages in the recent @neo-gpt inbox were persisted with wakeSuppressed: true, including subjects that are lifecycle-actionable by the current contract.
Examples observed in list_messages({status:'all', limit:30}) at 2026-06-15T03:44:09Z:
[review][REQUEST_CHANGES] #13290 — clean work, one close-target gate from @neo-opus-grace to @neo-gpt, wakeSuppressed: true.
[review][APPROVED] #13290 — close-target clean, merge-eligible (human-gate) from @neo-opus-grace to @neo-gpt, wakeSuppressed: true.
[review][APPROVED] #13293 — clean docs capture, merge-eligible from @neo-opus-grace to @neo-gpt, wakeSuppressed: true.
These messages stay visible in list_messages, but source and tests confirm wakeSuppressed: true intentionally prevents SENT_TO_ME wake delivery. That can look exactly like "real A2A messages do not wake" even when heartbeat pulses still do.
Release classification: post-release Agent Harness reliability; operationally urgent for AFK lifecycle continuity, but not a release-board blocker.
The Problem
The existing convention is explicit: actionable peer messages must wake recipients; awareness-only messages may be mailbox-only. The substrate currently exposes wakeSuppressed as a caller-controlled boolean and correctly honors it, but there is no mechanical guard or audit trail preventing an actionable direct message from being suppressed.
In autonomous mode this is high impact: a reviewer request, REQUEST_CHANGES, addressed-review ping, or merge-gate signal can sit unread until the recipient happens to boot or manually checks the mailbox. Heartbeat pulses can still submit, so the symptom misleadingly resembles a Codex adapter or payload-shape bug even when the actionable message was never eligible for wake delivery.
The Architectural Reality
V-B-A sources:
ai/services/memory-core/MailboxService.mjs persists wakeSuppressed: Boolean(wakeSuppressed) on every MESSAGE node.
ai/services/memory-core/heartbeatPulseEvaluator.mjs treats a message as wake-eligible only when it is a MESSAGE and not flagged wakeSuppressed.
test/playwright/unit/ai/services/memory-core/WakeSubscriptionService.spec.mjs asserts suppressed mailbox-only messages emit no SENT_TO_ME wake.
test/playwright/unit/ai/daemons/wake/daemon.spec.mjs asserts the wake daemon does not deliver suppressed mailbox-only messages.
.agents/skills/peer-role/references/peer-role-mode.md states the convention: direct review/re-review requests, REQUEST_CHANGES, lane overrides, and overlapping lane claims wake; ordinary awareness messages may suppress.
ai/mcp/server/memory-core/openapi.yaml describes the same contract for the add_message.wakeSuppressed parameter.
Historical context from the local ticket/KB sweep:
#10545 tightened the original misuse risk when wakeSuppressed hid active coordination.
#12635 later relaxed the contract to allow FYI/awareness suppression while preserving the actionable-must-wake rule.
- Neither closed ticket added a current mechanical/audit guard for actionable direct-message suppression.
Memory-mining note: same-day raw semantic memory queries were attempted for wakeSuppressed direct A2A no wake, Codex A2A wake prompt not submitted, and heartbeat wakes direct messages suppressed, but Memory Core rejected query_raw_memories as not fully operational during active maintenance. This ticket therefore rests on live mailbox output, source V-B-A, KB ticket search, and local issue/discussion sweep rather than raw-memory recall.
The Fix
Add a narrow guard/audit path around add_message.wakeSuppressed so actionable direct A2A messages cannot silently become mailbox-only.
Likely implementation shape:
- Centralize an
isActionableWakeSuppressionRisk() classifier for MailboxService.addMessage() inputs, based on direct recipient actionability rather than broad primitive names.
- Fail closed or emit a structured warning/audit result when callers set
wakeSuppressed: true for direct messages that match known actionable lifecycle patterns such as review requests, re-review requests, REQUEST_CHANGES, addressed-review responses, lane overrides, or high-priority direct messages.
- Preserve legitimate mailbox-only cases: session-sunset self-DMs, lead-role baton handoffs, explicit FYI/awareness broadcasts, non-overlapping lane-claim broadcasts, and KB alert audit mode.
- Add focused unit coverage proving both sides: actionable suppressed direct messages are blocked/audited, while allowed mailbox-only messages still persist and do not wake.
- Keep #13287 separate: it remains the live Codex submit/start-turn validation lane for wake-eligible A2A messages.
Contract Ledger
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback / Edge Case |
Docs |
Evidence |
add_message.wakeSuppressed |
ai/mcp/server/memory-core/openapi.yaml; peer-role wake-control convention |
wakeSuppressed: true remains valid only for mailbox-only / awareness use, not actionable direct lifecycle messages. |
If classifier confidence is ambiguous, prefer an audit/warning surface over silently suppressing a wake; do not block known valid sunset/baton/audit cases. |
Update schema/JSDoc only if behavior or warning semantics change. |
OpenAPI validator plus mailbox unit tests. |
MailboxService.addMessage() |
ai/services/memory-core/MailboxService.mjs |
Enforce or audit the actionable-direct-message suppression risk before persisting the message. |
Broadcasts and explicit non-actionable FYI messages may still suppress; self-DM handovers retain existing behavior. |
JSDoc for helper/classifier if added. |
Focused MailboxService.spec.mjs coverage. |
Wake eligibility (WakeSubscriptionService / daemon) |
Existing tests proving suppressed messages do not wake |
Do not weaken wake suppression honor-sites; they are correct. The fix belongs before or at message acceptance, not by ignoring wakeSuppressed downstream. |
If a legacy suppressed actionable message already exists, it remains mailbox-visible; the guard applies to new sends. |
None unless warning docs added. |
Existing wake tests remain green. |
| #13287 live Codex submit matrix |
#13287 / #13292 / ai/docs/wake-prompt-landing-matrix.md |
Matrix validation must distinguish wake-eligible direct messages from mailbox-only suppressed messages. |
A suppressed message is not valid evidence that Codex failed to submit a wake; it never emitted a wake by contract. |
Add a note only if needed while implementing #13287. |
#13287 live matrix artifact. |
Acceptance Criteria
Out of Scope
- Changing Codex app-server,
osascript, or any harness adapter.
- Proving live Codex prompt submission/start-turn behavior for wake-eligible messages; that remains #13287.
- Removing
wakeSuppressed or reversing the #12635 FYI/awareness relaxation.
- Re-delivering already-read messages or changing #13281/#13285 retry/read-state behavior.
Avoided Traps
- Adapter-first diagnosis: a suppressed direct message will never emit
SENT_TO_ME, so switching adapters cannot fix that upstream condition.
- Downstream honor-site bypass: making the wake daemon ignore
wakeSuppressed would break valid session-sunset, baton, and audit-mailbox contracts.
- Wake-noise regression: reverting to "all peer messages wake" would undo the intended #12635 awareness/FYI noise reduction.
Related
- Related: #13287 (live Codex submit/start-turn validation for wake-eligible direct messages).
- Related: #13291 and #13292 (boundary pin + matrix docs for the current wake-submit investigation).
- Related historical context:
#10545, #12635.
- Parent context: #13012 (Agent Harness).
Duplicate / Claim Sweep
- Live latest-open sweep: checked latest 20 open issues at 2026-06-15T03:44:09Z. Adjacent open tickets found: #13287, #13291, #13292; none is scoped to guarding/auditing
wakeSuppressed:true misuse on actionable direct A2A messages.
- A2A in-flight claim sweep: checked latest 30
list_messages({status:'all'}) at 2026-06-15T03:44:09Z. No overlapping [lane-claim] / [lane-intent] on this guard scope found.
- Local/KB historical sweep: found closed predecessors
#10545 and #12635, plus docs/tests proving the current honor-sites work; no open equivalent guard ticket found.
Decision Record impact: aligned with ADR 0020 Agent Harness reliability and existing wake-substrate contracts; no ADR change expected.
Origin Session ID: 9c41c4c0-e14b-4e86-bd59-62f7fe64491a
Handoff Retrieval Hints: wakeSuppressed actionable direct A2A REQUEST_CHANGES no wake; Codex heartbeat submits direct messages suppressed; #13287 wake eligible vs mailbox-only suppressed messages
Context
Operator-observed Codex behavior on 2026-06-15 still points at a heartbeat-vs-real-message wake split: heartbeat wakes submit/start a turn, while real A2A message wake-ups may not wake or may not submit when the operator is AFK.
The live Codex adapter evidence on #13287 still matters, but the latest mailbox V-B-A surfaced an upstream condition that does not require an adapter split: multiple targeted direct messages in the recent
@neo-gptinbox were persisted withwakeSuppressed: true, including subjects that are lifecycle-actionable by the current contract.Examples observed in
list_messages({status:'all', limit:30})at 2026-06-15T03:44:09Z:[review][REQUEST_CHANGES] #13290 — clean work, one close-target gatefrom@neo-opus-graceto@neo-gpt,wakeSuppressed: true.[review][APPROVED] #13290 — close-target clean, merge-eligible (human-gate)from@neo-opus-graceto@neo-gpt,wakeSuppressed: true.[review][APPROVED] #13293 — clean docs capture, merge-eligiblefrom@neo-opus-graceto@neo-gpt,wakeSuppressed: true.These messages stay visible in
list_messages, but source and tests confirmwakeSuppressed: trueintentionally preventsSENT_TO_MEwake delivery. That can look exactly like "real A2A messages do not wake" even when heartbeat pulses still do.Release classification: post-release Agent Harness reliability; operationally urgent for AFK lifecycle continuity, but not a release-board blocker.
The Problem
The existing convention is explicit: actionable peer messages must wake recipients; awareness-only messages may be mailbox-only. The substrate currently exposes
wakeSuppressedas a caller-controlled boolean and correctly honors it, but there is no mechanical guard or audit trail preventing an actionable direct message from being suppressed.In autonomous mode this is high impact: a reviewer request,
REQUEST_CHANGES, addressed-review ping, or merge-gate signal can sit unread until the recipient happens to boot or manually checks the mailbox. Heartbeat pulses can still submit, so the symptom misleadingly resembles a Codex adapter or payload-shape bug even when the actionable message was never eligible for wake delivery.The Architectural Reality
V-B-A sources:
ai/services/memory-core/MailboxService.mjspersistswakeSuppressed: Boolean(wakeSuppressed)on everyMESSAGEnode.ai/services/memory-core/heartbeatPulseEvaluator.mjstreats a message as wake-eligible only when it is aMESSAGEand not flaggedwakeSuppressed.test/playwright/unit/ai/services/memory-core/WakeSubscriptionService.spec.mjsasserts suppressed mailbox-only messages emit noSENT_TO_MEwake.test/playwright/unit/ai/daemons/wake/daemon.spec.mjsasserts the wake daemon does not deliver suppressed mailbox-only messages..agents/skills/peer-role/references/peer-role-mode.mdstates the convention: direct review/re-review requests,REQUEST_CHANGES, lane overrides, and overlapping lane claims wake; ordinary awareness messages may suppress.ai/mcp/server/memory-core/openapi.yamldescribes the same contract for theadd_message.wakeSuppressedparameter.Historical context from the local ticket/KB sweep:
#10545tightened the original misuse risk whenwakeSuppressedhid active coordination.#12635later relaxed the contract to allow FYI/awareness suppression while preserving the actionable-must-wake rule.Memory-mining note: same-day raw semantic memory queries were attempted for
wakeSuppressed direct A2A no wake,Codex A2A wake prompt not submitted, andheartbeat wakes direct messages suppressed, but Memory Core rejectedquery_raw_memoriesas not fully operational during active maintenance. This ticket therefore rests on live mailbox output, source V-B-A, KB ticket search, and local issue/discussion sweep rather than raw-memory recall.The Fix
Add a narrow guard/audit path around
add_message.wakeSuppressedso actionable direct A2A messages cannot silently become mailbox-only.Likely implementation shape:
isActionableWakeSuppressionRisk()classifier forMailboxService.addMessage()inputs, based on direct recipient actionability rather than broad primitive names.wakeSuppressed: truefor direct messages that match known actionable lifecycle patterns such as review requests, re-review requests,REQUEST_CHANGES, addressed-review responses, lane overrides, or high-priority direct messages.Contract Ledger
add_message.wakeSuppressedai/mcp/server/memory-core/openapi.yaml; peer-role wake-control conventionwakeSuppressed: trueremains valid only for mailbox-only / awareness use, not actionable direct lifecycle messages.MailboxService.addMessage()ai/services/memory-core/MailboxService.mjsMailboxService.spec.mjscoverage.WakeSubscriptionService/ daemon)wakeSuppresseddownstream.ai/docs/wake-prompt-landing-matrix.mdAcceptance Criteria
MailboxService.addMessage()(or a helper it owns) detectswakeSuppressed: trueon known-actionable direct lifecycle messages before they can silently become mailbox-only.WakeSubscriptionServiceand wake daemon remain green; downstream wake honor-sites are not loosened.Out of Scope
osascript, or any harness adapter.wakeSuppressedor reversing the #12635 FYI/awareness relaxation.Avoided Traps
SENT_TO_ME, so switching adapters cannot fix that upstream condition.wakeSuppressedwould break valid session-sunset, baton, and audit-mailbox contracts.Related
#10545,#12635.Duplicate / Claim Sweep
wakeSuppressed:truemisuse on actionable direct A2A messages.list_messages({status:'all'})at 2026-06-15T03:44:09Z. No overlapping[lane-claim]/[lane-intent]on this guard scope found.#10545and#12635, plus docs/tests proving the current honor-sites work; no open equivalent guard ticket found.Decision Record impact: aligned with ADR 0020 Agent Harness reliability and existing wake-substrate contracts; no ADR change expected.
Origin Session ID: 9c41c4c0-e14b-4e86-bd59-62f7fe64491a
Handoff Retrieval Hints:
wakeSuppressed actionable direct A2A REQUEST_CHANGES no wake;Codex heartbeat submits direct messages suppressed;#13287 wake eligible vs mailbox-only suppressed messages