feat(triage): 3-state delivery + admin observer + admin cache #2

Merged
hzhang merged 1 commits from feat/triage-3state-delivery into main 2026-05-22 21:59:19 +00:00
Contributor

Triage channels now compute a 3-state delivery decision per recipient (wake / observer / skip) instead of the binary wakeup flag. New triage matrix:

  1. author → skip
  2. on-duty (wake_mapping) → wake
  3. mention (NEW: was skip before) → wake
  4. Center-scoped admin → observer (wakeup=false)
  5. anyone else → skip (no socket emit at all)

Adds AdminCacheService (1d TTL, lazy fetch from Center) + cli node dist/cli/admin-refresh.js for force-refresh. emitMessageCreated now skips 'skip' decisions entirely so non-eligible members receive nothing.

Sim-verified 4 cases: on-duty wake / admin observer wake=false / mention wake=true / random member skip 0 events

Pairs with Fabric.Backend.Center PR and Fabric.OpenclawPlugin PR.

🤖 Generated with Claude Code

Triage channels now compute a 3-state delivery decision per recipient (wake / observer / skip) instead of the binary wakeup flag. New triage matrix: 1. author → skip 2. on-duty (wake_mapping) → wake 3. mention (NEW: was skip before) → wake 4. Center-scoped admin → observer (wakeup=false) 5. anyone else → skip (no socket emit at all) Adds `AdminCacheService` (1d TTL, lazy fetch from Center) + cli `node dist/cli/admin-refresh.js` for force-refresh. `emitMessageCreated` now skips 'skip' decisions entirely so non-eligible members receive nothing. Sim-verified 4 cases: on-duty wake ✅ / admin observer wake=false ✅ / mention wake=true ✅ / random member skip 0 events ✅ Pairs with Fabric.Backend.Center PR and Fabric.OpenclawPlugin PR. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
hzhang added 1 commit 2026-05-22 21:59:15 +00:00
Triage channels now compute a 3-state delivery decision per recipient
(wake / observer / skip) instead of the binary wakeup flag, and route
according to:

  1. author never gets back their own message            → skip
  2. wake_mapping member (on-duty)                       → wake
  3. mention (NEW: was 'skip' for triage before)         → wake
  4. Center-scoped admin (at most 1)                     → observer
  5. anyone else                                         → skip
                                                         (was 'deliver wake=false')

Skipping means the websocket emit is omitted entirely — the recipient's
openclaw plugin never sees the message and the agent's session stays
free of background noise. Observer means delivered with wakeup=false
(silent UI / no model dispatch on the plugin side).

## What this PR ships

### realtime/realtime.gateway.ts
- new `computeDelivery()` returns DeliveryDecision = 'wake'|'observer'|'skip'
- old `computeWakeup()` kept as a deprecated wrapper for callers that
  still want the boolean answer (treats observer + skip as false)
- `emitMessageCreated` accepts `adminUserId?: string|null` and now
  short-circuits on 'skip' (no socket emit at all)
- general kept its current behavior; custom kept its current behavior
  (members not in wake_mapping become observer instead of `wake=false`)
  — the user-visible bit is just that the response field is the same
  `wakeup: boolean`; the explicit 'skip' is new for triage

### common/center-auth.ts
- `fetchAdminEmail()` calls GET `${center}/auth/admin-email` with the
  existing x-api-key (same auth as introspect/resolve-names). Returns
  `{email, userId}` or `null` on either "no admin" or any error

### common/admin-cache.service.ts (NEW)
- `AdminCacheService` — in-memory cache, 1-day TTL, lazy refresh.
  `get(force=true)` bypasses TTL for cli-triggered refresh
- exposed by MessagingModule

### messaging/messaging.controller.ts
- non-rotating branch threads `adminUserId` into emitMessageCreated

### cli/admin-refresh.ts (NEW)
- `node dist/cli/admin-refresh.js` — force-refresh cache and print
  before/after JSON. Use after a Center `user set-admin` so triage
  delivery picks up the new admin without waiting for 24h TTL

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hzhang merged commit 0111fdf699 into main 2026-05-22 21:59:19 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: nav/Fabric.Backend.Guild#2