LearnNewsExamplesServices
Frontmatter
id17267
title`who_is_online` counts open re-review loops from the A2A trail
stateClosed
labels
bugaiagent-os
assigneesneo-kimi-iris
createdAtAug 17, 2026, 12:29 AM
updatedAtAug 17, 2026, 1:19 AM
githubUrlhttps://github.com/neomjs/neo/issues/17267
authorneo-kimi-iris
commentsCount0
parentIssue17225
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 17, 2026, 1:19 AM

who_is_online counts open re-review loops from the A2A trail

Closed Backlog/active-chunk-17 bugaiagent-os
neo-kimi-iris
neo-kimi-iris commented on Aug 17, 2026, 12:29 AM

Context

Leaf of #17225 — slice PR2 per the posted slice plan (issuecomment-5304989519). PR1 (leaf #17248, merged PR #17249) landed the honest-surface unit: plane declaration, unobservable axes as unknown, imported presence vocabulary. This leaf adds the one observation the parent's diagnosis showed nothing models: re-review load.

The premise reproduced live at 2026-08-16T22:06Z while routing a review: the tool read Ada idle (stale add_memory 20:51Z) minutes after she posted a review round, and my own row read idle mid-turn. The presence inversion is PR1's declaration; the LOAD inversion is this leaf — a reviewer holding N open CHANGES_REQUESTED loops reads as queue-depth 0 on every GitHub-derived signal, because reviewRequests empties the moment the review posts.

The Problem

Parent AC4: "Load is added and counts re-review obligations — a peer holding N CHANGES_REQUESTED reads as N, not 0. Pinned against the live tree with a positive control: a peer whose load is genuinely zero must read zero."

Vega's sharpening on the parent: the re-review obligation after an author response is invisible everywhere — no reviewRequests, no notification, no query surfaces it (#17218 was finished, green, and silent until hand-diffed).

The Architectural Reality

The swarm's review protocol makes lifecycle A2A pings mandatory (AGENTS.md §critical_gates 6), so the plane-resident mailbox holds the canonical trail: MESSAGE nodes carry from / to / subject / sentAt on their properties (MailboxService.mjs:2361-2379), queryable through the same SQLite json_extract pattern the roster read already uses (WakeSubscriptionService._listAgentIdentityNodes). The derivation itself is pure over already-read rows — new helper ai/services/memory-core/helpers/reviewLoadProjection.mjs, sibling precedent mailboxReadStateClassifier.mjs (same folder, same no-I/O contract).

The classifier's robustness rule is the first-bracket-tag anchor: prose that NAMES a disposition without being one — a stale-approval warning quoting APPROVED, an author response quoting the CHANGES_REQUESTED it answers — must neither open nor retire a loop. And PR refs come from the SUBJECT only: review pings list the tickets they resolve in relatedTickets, so counting every ref would open phantom loops on issues nobody reviewed.

The Fix

  1. ai/services/memory-core/helpers/reviewLoadProjection.mjs (new, pure): deriveReviewLoad(messages) → per-reviewer {open, returned, loops[]} (oldest-first); 30-day trail horizon as a module constant, declared in the envelope reason.
  2. WakeSubscriptionService.whoIsOnline: axes.load envelope on both shapes (container plane, wired/observed, signal a2a-review-lifecycle); terse gains the sparse reviewLoad map (identity → open count; absent IS the counted zero); verbose rows gain per-row reviewLoad.
  3. ai/mcp/server/memory-core/openapi.yaml: description + schema for the new fields (the declared-schema pin test reads them).

Contract Ledger

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
who_is_online axes surface — WakeSubscriptionService._composedAxesEnvelope (ai/services/memory-core/WakeSubscriptionService.mjs) this ticket (parent AC4) adds the load capability envelope: container-plane, wired/observed, signal a2a-review-lifecycle, blind class named in reason trail store absent or read failure → the envelope degrades (degraded/none + reason): absence of observation, never a counted zero method JSDoc + openapi description AC4 spec pins
Terse payload reviewLoad parent AC4 positive control sparse map identity → open loop count absent entry = counted zero; the whole key is OMITTED when the trail is unreadable openapi schema terse pin test
Verbose per-row reviewLoad parent AC4 {open, returned, loops[]}, loops oldest-first (stalest obligation at the head) {open: 0, returned: 0, loops: []}; null when the trail is unreadable openapi schema verbose pin tests
Derivation — ai/services/memory-core/helpers/reviewLoadProjection.mjs (new) parent AC4 + the mailbox write contract (MailboxService.mjs:2361) first-tag-anchored disposition classifier over MESSAGE rows; subject-only PR refs; 30d horizon non-conforming subjects invisible — declared in the envelope reason module docstring robustness pin + 3 mutation controls

Decision Record impact

aligned-with the FM capability-envelope grammar as declared by PR #17249's superset. No ADR amended; no AiConfig touch (the horizon is a module constant, not a config leaf — ADR-0019 not engaged).

Acceptance Criteria

  • A reviewer holding N open CHANGES_REQUESTED loops reads N (verbose per-row open + loops; terse sparse map), red-proved by fixture.
  • Positive control: a peer whose load is genuinely zero reads 0 — the counted zero, never an unknown.
  • First-tag anchoring: stale-approval warnings quoting APPROVED and author responses quoting CHANGES_REQUESTED neither open nor retire loops — pinned with the author rostered, so the assertion cannot be vacuous.
  • A returned ball (re-review request addressed to the reviewer) reads as returned, distinct from a fresh open.
  • Loops older than the 30-day trail horizon age out; the horizon is declared in the envelope reason.
  • Live-tree pin (PMV): after plane redeploy, verbose reviewLoad for a seat with a known open loop matches hand-counted GitHub state.

Out of Scope

  • The fleet-publish slice (parent AC6-8, forked to @neo-fable-clio Tier-2.5): the host-originated axes stay unobserved until then.
  • Live GitHub review state at read time (see Avoided Traps).
  • Human/external reviewer coverage — the trail is the swarm protocol's; the envelope declares the blind class.

Avoided Traps

  • Live GitHub reads at call time. who_is_online is a fast routing glance; per-call GraphQL is seconds and credential-bound, and reviewRequests-based queue depth is the exact signal the parent ticket falsified. The plane-resident trail is instant and canonical.
  • relatedTickets as the PR source. Review pings list the tickets they resolve; counting every ref would open loops on ISSUES nobody reviewed. The subject's PR #N is the protocol surface.
  • A config leaf for the horizon. Module constant with the declaration in the envelope reason; no AiConfig surface.

Related

Parent #17225 · sibling leaf #17248 (PR1, merged PR #17249) · the fleet-publish fork rides the parent's AC6-8.

Live latest-open sweep: latest 20 open issues checked live via gh at 2026-08-16T22:10Z, no equivalent (the only who_is_online items are this chain's own). A2A claim sweep (last hour, all read-states): no competing claim on the load-axis scope; the umbrella claim is mine from the parent intake.

Origin Session ID: ade8fd5d-4732-49ad-9763-b1c8b6772826

Retrieval Hint: query_raw_memories("who_is_online load axis review lifecycle trail A2A CHANGES_REQUESTED derivation")

tobiu referenced in commit 12233c7 - "feat(memory-core): who_is_online counts open re-review loops from the A2A trail (#17267) (#17270) on Aug 17, 2026, 1:19 AM
tobiu closed this issue on Aug 17, 2026, 1:19 AM