Skip to main content
pending_advisories is the unified cross-turn carryover surface. One table, one read point at the start of each runtime turn (gateway/src/index.ts::injectPendingNudges), multiple sources via a closed source enum spanning runtime + sideband + manual contexts. This page documents the row shape every consumer can rely on (gateway, observer, dashboard, CLI, webhook subscribers) and the expansion contract for adding new sources.

Row shape

TTL. Default 24 hours. Configurable platform-wide by Mnemom platform admins; not configurable per-org or per-agent. Status transitions. Always forward: pending → consumed (gateway injected on a turn) or pending → expired (TTL elapsed without injection). No revivals.

Source taxonomy

Closed, hierarchical, append-only enum. Adding a new value requires the expansion recipe (schema amendment + migration + producer + consumer-tolerance).
Surface-separation invariant. As of 2026-05-07, sideband.* sources are no longer accepted into pending_advisories. Cron-driven, fleet-shaped observations (the four legacy sideband.drift / sideband.coherence / sideband.fault_line / sideband.fleet rows) now write to the operator-actionable governance_signals table, never to pending_advisories. A NOT VALID CHECK constraint on pending_advisories.source rejects new sideband.* writes; pre-cutover historical rows remain queryable for compliance attestation but were marked status='expired' by migration 193.

Current ratified values (post-cutover)

sideband.drift / sideband.coherence / sideband.fault_line / sideband.fleet previously appeared here. They moved to governance_signals with the 2026-05-07 cutover; the four legacy sideband.*.fired and drift.detected webhook event names continue to fire for D+30 backwards-compat through 2026-06-07.

source_ref shapes

JSONB envelope keyed off source. Conventions:
  • Every runtime.* row carries {checkpoint_id: string, mode_at_fire: "off"|"observe"|"nudge"|"enforce"}
  • Every manual.* row carries {actor_user_id: string, attached_at: string, note?: string}
For sideband.* source_ref shapes, see the governance_signals table; those observations write to the operator-actionable surface, not to this table.

runtime.*source_ref

checkpoint_id references the integrity_checkpoints row created on the same turn. mode_at_fire is the agent’s effective mode at intervention time (post-cascade, pre-fire).

manual.adminsource_ref

nudge_content format

Every advisory’s text follows a stable wrapper:
The bracket wrapper enables the gateway’s user-visible-explanation guarantee to detect that an injection happened. Producers MUST keep the wrapper; if the wrapper is missing on a delivered turn, the gateway suffix-injects its own marker [Mnemom: <intervention summary>].

concerns_summary format

Short structured headline (≤80 chars) used for telemetry, dashboard display, and CLI list output. Convention: <axis>: <short outcome>.

Read endpoints

Filters (all optional, on the agent + team listing endpoints):
  • ?since=<ISO-8601> — only advisories created after this timestamp
  • ?limit=<n> — page size (default 50/100, max 200/500)
Service-key paths used by the observer cron (not customer-facing — gated behind X-Service-Key, exposed under an internal namespace that does not appear in the customer OpenAPI):

Expansion contract

Adding a new source

To add a new value to source, a single PR train MUST land all of:
  1. Schema amendment to the source taxonomy adding the value with its producer, consumer responsibilities, and source_ref shape.
  2. Migration (ALTER TABLE pending_advisories DROP CONSTRAINT … ADD CONSTRAINT … CHECK (source IN (…))) appending the new value. Migration MUST use the post-DDL pg_proc.prosrc ASSERT pattern from mnemom-api/database/migrations/158_*.sql.
  3. Producer code that writes rows with the new source — fire-and-forget, never throws on insert failure.
  4. Consumer-tolerance disciplinegateway/src/index.ts::injectPendingNudges MUST already render any unknown source as a generic advisory (the current code does this; it doesn’t filter on source). Future consumers (dashboard filter chips, CLI --source, webhook event types) MUST tolerate the value via either pre-registration or graceful unknown-source fallback.
  5. source_ref JSONB shape documented per source on this page.
  6. For sideband.* only — extend PostureBody.sideband with the corresponding axis configuration (enabled, cadence_seconds, severity_floor or fire_on.*, severity_on_fire). The Posture is the policy surface; new sideband sources without posture-body fields are forbidden.

Removing a source

Forbidden. Removing a source breaks compliance attestation (historical advisories with that source value become un-renderable) and breaks deserialization for any consumer holding archived rows. Deprecation is the only valid path: stop producing the source, document the deprecation, but leave the CHECK constraint accepting the value forever.

Webhook events

Each source’s webhook event name follows <source>.fired — with one documented carve-out: sideband.drift keeps its legacy drift.detected name. Subscribers receive the standard webhook envelope:
See Subscribing to Safe House webhooks for the full subscription + signature-verification flow.

See also