A review request at default priority never wakes an idle reviewer
Context
Live incident 2026-08-21, operator-observed: PR #17491's review request to @neo-gpt (MESSAGE:a1845f64, 18:30:29Z, direct 1:1, not suppressed) sat unread while the reviewer stayed idle — the operator asked "did not get a wake. what went wrong?". The reviewer had gone idle at 17:57:40Z, before the send; a wake was the only path back, and none fired. A manual resend at priority: high (MESSAGE:578c6332, 19:06:43Z) was the workaround.
Evidence chain, verified not inferred: the sender's own wake subscription (recipe-bootstrapped 2026-08-02, same shape across seats) declares trigger: SENT_TO_ME with filters: {priority: "high"} — and the inverse case proves the filter live: the reviewer's earlier priority: high 1:1 (17:57Z) woke the sender mid-turn, while the sender's priority: normal request in the other direction woke nobody.
The Problem
The platform already encodes "actionable direct lifecycle messages must be able to wake": the mailbox acceptance guard rejects wakeSuppressed: true on exactly that class. But wake delivery has a second, independent drop point — the subscription priority filter — and nothing routes the same classification through it. A review request sent at the default priority is actionable-lifecycle by the server's own definition, passes acceptance un-suppressed, emits SENT_TO_ME, and then dies at a filter that only asks "is it high?". The suppression-rejection intent is defeated one layer downstream, silently: the sender sees a successful send, the recipient sees nothing, and review latency (the fleet's named bottleneck) absorbs the loss until a human notices.
The Architectural Reality
ai/services/memory-core/MailboxService.mjs:374 — getWakeSuppressionRisk({wakeSuppressed, to, subject, priority, taggedConcepts, task, senderPrincipalClass}): the acceptance-side classifier that names the protected class ("known-actionable DIRECT messages — actionable lifecycle subjects, high-priority", per its own docblock at :349) and rejects suppression on it. It runs ONLY when a sender sets wakeSuppressed: true.
ai/services/memory-core/MailboxService.mjs:2404 — priority = priority ?? (operatorSteering ? 'high' : 'normal'): agent sends default to normal; only operator steering elevates. The docblock (:2400) frames priority as "turn-start drain-ordering metadata" — but the wake substrate ALSO consumes it as a delivery gate, an unstated second consumer.
ai/services/memory-core/MailboxService.mjs:2411 — the suppression default: direct messages default un-suppressed, so the class arrives at the wake substrate correctly; the loss is purely the filter mismatch.
- Wake subscriptions (
manage_wake_subscription, WAKE_SUB rows): per-seat filters.priority is the recipe's shipped shape; a subscription filtering on high is legitimate throttle hygiene — the defect is that the SENDER side has no mechanism to mark lifecycle sends as filter-passing, and no substrate line tells authors to.
- The routing substrate is silent:
grep -rn "priority" .agents/skills/pull-request/references/*.md → zero matches. The review-request format (ci-green-review-routing.md, review-response-protocol.md §14) specifies role lines and wake-required classes but never the priority a waking send must carry.
The Fix
Elevate at acceptance, where the classification already lives: in addMessage, when the message matches the SAME actionable-direct-lifecycle classification getWakeSuppressionRisk protects (direct recipient + lifecycle subject/task shape) and the sender did not explicitly set a priority, default priority to 'high' instead of 'normal' — one code path, the classifier consulted once at one seam, and the class of silent drops disappears for every current and future seat without touching subscription semantics. An explicit priority: 'normal'/'low' from the sender stays a sender election (mirror of the wakeSuppressed: false election rule).
Companion one-liner in ci-green-review-routing.md: waking review-lifecycle sends carry priority: high — stated for the window until the mechanical default lands, and as reader documentation for why their sends wake.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
add_message priority default (MCP tool + MailboxService.addMessage) |
MailboxService.mjs:2404 default expression |
Unset priority on actionable-direct-lifecycle messages defaults high (classification per the :374 guard's subject/task shape); explicit sender priority always wins |
Non-lifecycle and broadcast sends keep the normal default unchanged |
This ticket + the ci-green-review-routing.md line |
Unit spec on the default expression: lifecycle-direct unset → high; explicit normal preserved; broadcast unset → normal |
Wake subscription filters.priority |
WAKE_SUB rows (per-seat) |
Unchanged — filters keep their semantics; the class now passes them by carrying the priority they ask for |
n/a |
n/a |
The incident pair above (high wakes, normal does not) stays the manual reproduction |
Decision Record impact
none — no ADR governs mailbox priority semantics; the change is aligned-with the acceptance guard's own stated intent (MailboxService.mjs:349-360).
Acceptance Criteria
Out of Scope
#16526 (the wake daemon's host-path read — a sibling delivery-layer defect, claimed by @neo-opus-grace; this ticket's fix is necessary but not sufficient while that one stands) · subscription-filter semantics redesign (filters consulting classifications directly) · per-seat subscription repair or audit tooling · retroactive re-delivery of dropped wakes.
Related
#16526 (sibling delivery-layer defect) · PR #17491 (the incident's review lane) · #15987 (the claim-class quiet-by-default precedent this mirrors on the opposite class).
Live latest-open sweep: latest 20 open checked 2026-08-21T19:09Z, no equivalent; A2A herd-window sweep (last ~90 min, all read-states) clean — nearest neighbor is #16526, a different layer.
Origin Session ID: 8947f450-e0c3-424b-8aa1-1e52ea33c03f
Retrieval Hint: query_raw_memories("review request wake priority filter subscription normal high idle reviewer")
A review request at default priority never wakes an idle reviewer
Context
Live incident 2026-08-21, operator-observed: PR
#17491's review request to @neo-gpt (MESSAGE:a1845f64, 18:30:29Z, direct 1:1, not suppressed) sat unread while the reviewer stayed idle — the operator asked "did not get a wake. what went wrong?". The reviewer had gone idle at 17:57:40Z, before the send; a wake was the only path back, and none fired. A manual resend atpriority: high(MESSAGE:578c6332, 19:06:43Z) was the workaround.Evidence chain, verified not inferred: the sender's own wake subscription (recipe-bootstrapped 2026-08-02, same shape across seats) declares
trigger: SENT_TO_MEwithfilters: {priority: "high"}— and the inverse case proves the filter live: the reviewer's earlierpriority: high1:1 (17:57Z) woke the sender mid-turn, while the sender'spriority: normalrequest in the other direction woke nobody.The Problem
The platform already encodes "actionable direct lifecycle messages must be able to wake": the mailbox acceptance guard rejects
wakeSuppressed: trueon exactly that class. But wake delivery has a second, independent drop point — the subscription priority filter — and nothing routes the same classification through it. A review request sent at the default priority is actionable-lifecycle by the server's own definition, passes acceptance un-suppressed, emitsSENT_TO_ME, and then dies at a filter that only asks "is it high?". The suppression-rejection intent is defeated one layer downstream, silently: the sender sees a successful send, the recipient sees nothing, and review latency (the fleet's named bottleneck) absorbs the loss until a human notices.The Architectural Reality
ai/services/memory-core/MailboxService.mjs:374—getWakeSuppressionRisk({wakeSuppressed, to, subject, priority, taggedConcepts, task, senderPrincipalClass}): the acceptance-side classifier that names the protected class ("known-actionable DIRECT messages — actionable lifecycle subjects, high-priority", per its own docblock at :349) and rejects suppression on it. It runs ONLY when a sender setswakeSuppressed: true.ai/services/memory-core/MailboxService.mjs:2404—priority = priority ?? (operatorSteering ? 'high' : 'normal'): agent sends default tonormal; only operator steering elevates. The docblock (:2400) frames priority as "turn-start drain-ordering metadata" — but the wake substrate ALSO consumes it as a delivery gate, an unstated second consumer.ai/services/memory-core/MailboxService.mjs:2411— the suppression default: direct messages default un-suppressed, so the class arrives at the wake substrate correctly; the loss is purely the filter mismatch.manage_wake_subscription,WAKE_SUBrows): per-seatfilters.priorityis the recipe's shipped shape; a subscription filtering onhighis legitimate throttle hygiene — the defect is that the SENDER side has no mechanism to mark lifecycle sends as filter-passing, and no substrate line tells authors to.grep -rn "priority" .agents/skills/pull-request/references/*.md→ zero matches. The review-request format (ci-green-review-routing.md,review-response-protocol.md §14) specifies role lines and wake-required classes but never the priority a waking send must carry.The Fix
Elevate at acceptance, where the classification already lives: in
addMessage, when the message matches the SAME actionable-direct-lifecycle classificationgetWakeSuppressionRiskprotects (direct recipient + lifecycle subject/task shape) and the sender did not explicitly set a priority, defaultpriorityto'high'instead of'normal'— one code path, the classifier consulted once at one seam, and the class of silent drops disappears for every current and future seat without touching subscription semantics. An explicitpriority: 'normal'/'low'from the sender stays a sender election (mirror of thewakeSuppressed: falseelection rule).Companion one-liner in
ci-green-review-routing.md: waking review-lifecycle sends carrypriority: high— stated for the window until the mechanical default lands, and as reader documentation for why their sends wake.Contract Ledger Matrix
add_messagepriority default (MCP tool +MailboxService.addMessage)MailboxService.mjs:2404default expressionhigh(classification per the:374guard's subject/task shape); explicit sender priority always winsnormaldefault unchangedci-green-review-routing.mdlinehigh; explicitnormalpreserved; broadcast unset →normalfilters.priorityWAKE_SUBrows (per-seat)Decision Record impact
none — no ADR governs mailbox priority semantics; the change is aligned-with the acceptance guard's own stated intent (
MailboxService.mjs:349-360).Acceptance Criteria
:374classification) is stored and emitted atpriority: 'high'; an explicit sender priority is never overridden.AGENT:*) and non-lifecycle direct sends keep the currentnormaldefault (spec-pinned).ci-green-review-routing.mdcarries the one-line priority statement for waking review-lifecycle sends.Out of Scope
#16526(the wake daemon's host-path read — a sibling delivery-layer defect, claimed by @neo-opus-grace; this ticket's fix is necessary but not sufficient while that one stands) · subscription-filter semantics redesign (filters consulting classifications directly) · per-seat subscription repair or audit tooling · retroactive re-delivery of dropped wakes.Related
#16526(sibling delivery-layer defect) · PR#17491(the incident's review lane) ·#15987(the claim-class quiet-by-default precedent this mirrors on the opposite class).Live latest-open sweep: latest 20 open checked 2026-08-21T19:09Z, no equivalent; A2A herd-window sweep (last ~90 min, all read-states) clean — nearest neighbor is
#16526, a different layer.Origin Session ID: 8947f450-e0c3-424b-8aa1-1e52ea33c03f
Retrieval Hint:
query_raw_memories("review request wake priority filter subscription normal high idle reviewer")