LearnNewsExamplesServices
Frontmatter
id16800
titleWake poll-digest verb on manage_wake_subscription (S7 slice 1)
stateClosed
labels
enhancementai
assigneesneo-kimi-iris
createdAtAug 9, 2026, 4:57 PM
updatedAtAug 9, 2026, 5:50 PM
githubUrlhttps://github.com/neomjs/neo/issues/16800
authorneo-kimi-iris
commentsCount0
parentIssue16741
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 9, 2026, 5:50 PM

Wake poll-digest verb on manage_wake_subscription (S7 slice 1)

Closed Backlog/active-chunk-14 enhancementai
neo-kimi-iris
neo-kimi-iris commented on Aug 9, 2026, 4:57 PM

Context

First implementation slice of #16741 (D#16720's S7 — wake delivery over the ingress). The parent's design thread carries design v1 (fork + contract ledger), v1.1 (the ingress-liveness falsifier folded: honest-degraded as AC), the F1 closure (all four digest event classes are GraphLog-persisted), and the recon-grounded implementation plan. This ticket exists because the slice is one-PR-deliverable while the parent's AC2 (the remote-only journey's working wake story) is journey-level, landing with the C1/C2 client consumption — and a draft PR cannot collect review, so the slice carries its own close-target.

Live latest-open sweep: checked latest 20 open issues at 2026-08-09T15:05Z — no equivalent beyond the parent. A2A in-flight sweep: mailbox drained 15:07Z, no overlapping claims.

The Problem

Pull-bridge-class seats and no-checkout cockpit machines have no wake-delivery channel that crosses the authenticated ingress: push terminates on host-side listeners a remote client cannot be. The verb-shaped delivery half: a client-held-watermark poll that derives the caller's wake digest at read time, over the same authenticated MCP surface the client already holds.

The Architectural Reality

  • ai/services/memory-core/WakeSubscriptionService.mjsresync({subscriptionId, sinceLogId}) already replays GraphLog deltas above a client-tracked watermark; the shared match() evaluator (heartbeatPulseEvaluator.mjs) already reconciles CURRENT read state per delivery shape (a wake for an already-read message never matches); ai/daemons/wake/wakeDigestBuilder.mjs's buildWakeDigest is pure over {messages, tasks, permissions, heartbeats} and already imported into the service tree (precedent: buildReceiverManifest import).
  • The fleet MCP convention is action dispatch on manage_wake_subscription (resync's sibling), registered at toolService.mjs + Server.mjs + openapi.yaml (parity-linted).
  • Caller binding via RequestContextService.getAgentIdentityNodeId() + per-subscription ownership check (resync's guard).

The Fix

  1. WakeSubscriptionService.pollDigest({subscriptionId, sinceLogId}) — ownership guard verbatim; the resync delta walk extracted verbatim into _collectSubscriptionEvents (both consume it — cannot drift); survivors bucketed into the daemon's own buildWakeDigest. Empty answer = closed {pending: 0, reason, watermark} — distinguishable from transport failure, never a verdict. Watermark echoed, never server-persisted.
  2. manage() gains the poll-digest case; openapi.yaml action enum + descriptions updated.
  3. Five falsifier tests in WakeSubscriptionService.spec.mjs: derivation above watermark; closed empty-with-reason; client-held watermark semantics both directions (advancing empties the next poll; replay at the old watermark still sees the events); ownership rejection; manage routing.

Contract Ledger

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
WakeSubscriptionService.pollDigest (new method) this ticket + parent design thread derive-at-read digest over the caller's subscription events closed empty-with-reason state method docblock spec: 5 falsifier tests
manage() action switch + JSDoc this ticket poll-digest case; error string lists it spec: routing test
openapi.yaml /wake-subscriptions/manage this ticket action enum + subscriptionId/sinceLogId descriptions operation description parity lint
resync public contract pre-existing unchanged (walk extracted verbatim) 110 pre-existing spec tests green

Acceptance Criteria

  • poll-digest returns a digest derived from events above the client watermark, with digestPriority and the echoed watermark.
  • Empty answer is a closed state carrying its reason; a transport failure is never representable as an empty answer.
  • Watermark is client-held: advancing past events empties the next poll; replay at the original watermark still sees them.
  • A subscription owned by a different identity rejects (permission-denied), same guard as resync.
  • Full wake suite green (service spec + wakeDigestBuilder.spec).

Out of Scope

  • The parent's AC2 (remote-only journey wake story) — C1/C2 consumption slice.
  • The ingress-pull route-class metadata (the verb does not need it; the journey slice decides).
  • Fleet-surface alias placement (the design's F4 — MC surface now, S1 alias later).
  • Any AiConfig touch (none — the gate is considered, not triggered).

Related

#16741 · PR #16796 · #16710 (SDK vocabulary) · ADR 0038 §2.5.1 row 6 names the target ("S7 moves it onto the authenticated ingress").

Origin Session ID: 6df9925c-e527-496d-9fbf-0a277c175d59

Retrieval Hint: "wake poll-digest derive-at-read ingress pull-bridge client watermark"

tobiu closed this issue on Aug 9, 2026, 5:50 PM