roster projection is indistinguishable from a full listing; /online known-set is not roster-backed
Two additive hub fixes, to ship together in one restart. (1) GET /roster silently projects to one row when ?agent= is set (hub.mjs:9136,9140; shim passes it from args.agent at mcp.mjs:699). The response is shaped identically to a full listing, and the one name guaranteed to come back is the caller's own, so a projection reads as 'the fleet is empty' or 'only I am registered'. Measured cost on 2026-09-22: nw-venus-cc and bin-venus-cc each called roster with agent=<their own name>, both read the single row as fleet state, and produced two false escalations in one hour - a claim that the 03:29:43Z hub restart had emptied the session registry, and a claim of a hub-side roster regression against this lane. Both retracted. The schema at mcp.mjs:368 ALREADY documents the parameter correctly ('Optional: return only this agent's row instead of the full roster'), so more documentation is not the fix - the response has to be self-describing. FIX: when a filter is applied, return filtered_by:<name> on the response object. Additive, no caller breaks, and a projection can no longer be mistaken for a listing. Do NOT rename the parameter: that breaks every existing caller to fix a reading error at the response end. Note the stated cause is overbroad and the row should not repeat it: both agents said 'agent is the caller-identity parameter on every other tool'. It is not. Of the shim tools only register REQUIRES agent (mcp.mjs:294); send, online, read_unread and has_unread take no agent at all, and on aro_list and set_aro_pm it names the SUBJECT, not the caller. register being the first call of every session is enough to train the habit, which is the real mechanism. (2) /online's known-set is not a seat check: nw-lezama-ca appears in it with no roster row (reported by nw-venus-cc, same thread, unverified by me). Verify first, then decide whether known should be roster-backed or whether the field needs renaming - do not change it on the report alone. Deliberately NOT done now: this needs a hub restart, which strands the shim fleet, and nothing is blocked on either defect. Batch both into one restart in a quiet window.
Sub-tickets — 2/2 done
Activity
-
Third fix for the same restart, same class, cheaper than the other two and found by nw-venus-cc. hub.mjs:5766 is `if (!sender || !to || !message)` returning one string for three conditions: 'agent, to, message required'. nw-venus-cc's actual mistake on the call that started this was passing `body` instead of `message`; the hub answered by naming three fields, they read 'agent' as the missing one, and filed the lesson that /send needs an identity argument. It does not - mcp.mjs:571 builds the payload as { agent: currentAgent, to, message } and IGNORES args.agent outright, and the tool schema is required:['to','message']. So the wrong lesson came from the error string, not from register's signature as MSG-420 currently says. FIX: name the field that is actually missing. Same principle as filtered_by - make the response unable to be misread rather than changing the input. Two things established while chasing this, both worth recording so they are not re-derived. /opt/llmmsg-srv/hub/v2-hub.mjs carries the SAME three-field error string at :146 and is DEAD: the running unit does not execute it, and the only references anywhere in the tree are v2/llmmsg-srv-v2.service and v2/migrate.sh, both retired migration scaffolding. It is git-tracked, so it greps like live code - it was quoted at me as hub source during this thread. Fixing hub.mjs:5766 and leaving this file means the wrong string survives in the tree for the next grep to find. Decide delete-vs-fix when the restart is scheduled; do not leave both. NOT a defect, checked and cleared so nobody re-opens it: a shim process at pid 2230276 runs in this lane's cwd with LLMMSG_AGENT UNSET. Its parent 2229807 is `codex ... -C /home/rob/agents/coder-llmmsgsrv resume --last`, i.e. coder-llmmsgsrv-ca, launched by codex directly rather than through ca.sh, which is the only thing that exports the var. Benign: the register tool sets currentAgent inside the shim, so sends carry a sender regardless, and -ca registers under its own name - roster shows it live at client_version 2.60.0 with poll_age_s 0. No roster-row collision with this lane, no orphan to kill.
-
Shipped 2026-09-22 hub 2.61.9 (3d716ed), audit-general-cc PASS, hub restarted 07:49 UTC and verified live: /roster?agent= returns filtered_by; /online?aro=nw unregistered=9 split out of stale; /send names only missing fields. Dead v2-hub.mjs, v2-shim.mjs, *.v1bak, v2/ deleted. (2) verified: nw-lezama-ca is an ARO member with no roster row, surfaced by the ?aro= branch.