Hold inbound messages older than 1 hour; deliver a count plus a held_messages fetch tool
ORDER (Elazar, direct CLI 2026-09-23, relayed by bin-venus-cc): inbound messages older than 1 hour must be HELD by the hub instead of delivered. On connect/register an agent receives only a notice - "you have N messages older than 1 hour" - plus a new MCP tool (working name held_messages(n)) it may call to fetch the next n held messages, newest first. Messages under 1 hour old deliver exactly as today. Spec details (tool name, whether a fetch RELEASES the messages or only reads them, ARO fan-out handling) are the implementer's call. Audit gate as usual. TRIGGER CASE: db-mars-ca answered a kpi-coach report from 2026-09-10, 13 days stale. The cost is not the delivery, it is an agent spending a full turn acting on dead context. DESIGN CONSTRAINT, measured 2026-09-23 before this was parked - do not design around a cursor trick. All delivery funnels through unreadRowsFor() at hub/hub.mjs:3813, and the read position is a SINGLE monotonic integer: cursors.read_id, MAX-merge upsert at hub/hub.mjs:3828 (stmtAdvanceCursor), with the shim acking the highest id it saw. So if the hub withholds old messages while delivering new ones, the shim acks the newest id, the MAX-merge advances read_id past the withheld ids, and those messages are unreachable forever - /unread can never return them again. Held messages therefore need their own state (a holds table keyed on agent + message_id, with a released/read marker), written at the delivery-filter point, and held_messages must read from that table rather than from the id stream. OPEN SPEC QUESTIONS to settle before coding: (1) does a held_messages fetch release the rows (they then also flow through /unread) or is it read-only, leaving them held forever until read again; (2) does an ARO fan-out row age the same way as a DM, given a room message may be stale-but-still-relevant; (3) does the N-held notice ride the existing /unread poll response - aros_pm already does, see hub/hub.mjs:8915 - or arrive as its own synthetic message from llmmsg-srv-hub; (4) what the age cutoff is configurable as, and its fail direction when the env value is a typo (see the Number() coercion hazard: NaN must not switch the gate open). STATUS: not started. Filed after the fact - the order arrived 2026-09-23, a fleet-wide park order stopped work the same evening, and the lane was handed to coder-llmmsgsrv-ca and back. No code exists yet and nothing has been committed against this ref.