Skip to content

feat(comms): agent roster read path — GetRoster + set_status (SEA-1721) - #163

Merged
mattwilkinsonn merged 2 commits into
mainfrom
compass-comms-1721-t2-roster
Aug 5, 2026
Merged

feat(comms): agent roster read path — GetRoster + set_status (SEA-1721)#163
mattwilkinsonn merged 2 commits into
mainfrom
compass-comms-1721-t2-roster

Conversation

@seal-agent

Copy link
Copy Markdown
Contributor

What

Manager-comms substrate T2 (SEA-1721): the agent roster read path. Replaces the T1 GetRoster CodeUnimplemented stub with a real body, and wires the two agent-initiated relay arms (roster, set_status). Design record section T2 (design.md:426-452) + T3 (set_status ordering, :473-486).

Independent — base is main. T2 touches only internal/comms (roster), internal/presence, internal/runnerhub (relay arms), server/sinks.go — no migration, no overlap with T4's channel-policy legs. It does not stack on #161.

Changes

  • comms.roster joins all three roster sources for the vantage agent's scope — durable tree (treeForScope: NEIGHBORHOOD/SUBTREE/OWNER), live presence enum (absent → OFFLINE), durable activity string (agent_activity, absent → empty) — clipped to the CALLER's account-visible set (D9, via ListAccounts) so a tree agent the caller may not see never leaks. GetRoster delegates; vantage defaults to the caller.
  • SetStatusAsAccount truncates activity server-side to 140 runes (never mid-codepoint), write-throughs Store.SetActivity (commits), returns the truncated value.
  • presence: Publisher.PresenceFor (project last-published enum for a set), Publisher.PublishActivity (always publishes AgentPresenceChanged, absent presence → OFFLINE).
  • runnerhub: Hub.PresenceFor/PublishActivity delegate to a nil-safe presenceSource; executeCall gains the roster arm and the set_status arm (ordered write-then-publish — durable SetActivity commits first, best-effort PublishActivity fires the live event with the truncated string, never gated on, never errors the call). Fail-closed default untouched.
  • server: hubPresenceSource adapter bridges the hub's presence into comms (mirrors the AskAnswerWaker bridge).

Tests (red-first, each proven red-sensitive by mutation)

  • roster pgtest: neighborhood/subtree/owner scoping; D9 clip drops a non-visible agent; OFFLINE default + presence join; activity round-trips through the durable store and survives a simulated restart (fresh handler + empty presence, same store); set_status truncates over-cap and the truncated value lands in the table.
  • presence: PresenceFor OFFLINE default; nil-source all-OFFLINE; PublishActivity forwards; nil-source publish is safe.
  • relay: roster arm forwards under a bound account + wraps result; set_status arm write-then-publishes the server-truncated value; set_status succeeds with no presence source (best-effort publish).

Verification

go build ./..., go vet, CI-exact golangci-lint run --config .golangci.yml ./... all clean (0 issues); internal/comms (21.5s), internal/runnerhub (17.6s), internal/presence pgtest suites green under -race. Mutation checks: D9-clip bypass, OFFLINE-default flip, truncation bypass, durable-activity-read stub, and publish-raw-instead-of-truncated each fail exactly the intended test(s).

Realization notes (for the human gate)

  • SetChannelPolicy / UpdatePinnedBoard stubs left CodeUnimplemented — those are T4's and T6's legs; T2 is independent off main and does not touch them.
  • Doc-honesty fix folded in (coordinator lane, not a design change): executeCall's fail-closed default error message said "has no post/list variant set"; now that roster + set_status are handled it names the recognized set (post/list/roster/set_status). T6 adds pin.

Refs SEA-1721

Manager-comms substrate T2. Replaces the T1 GetRoster CodeUnimplemented stub
with a real body and wires the two agent-initiated relay arms (roster, set_status).

- comms: (*Comms).roster joins all three roster sources for the vantage agent's
  scope — the durable tree (treeForScope: NEIGHBORHOOD/SUBTREE/OWNER), the live
  presence enum (in-memory source, absent -> OFFLINE), and the durable activity
  string (agent_activity table, absent -> empty) — clipped to the CALLER's
  account-visible set (D9, via ListAccounts) so a tree agent the caller may not
  see never leaks. GetRoster delegates to it; vantage defaults to the caller.
- comms: SetStatusAsAccount truncates activity server-side to 140 runes (never
  cutting a codepoint), write-throughs Store.SetActivity (commits), and returns
  the truncated value so the publish carries exactly what landed.
- presence: Publisher.PresenceFor projects the last-published enum for a set
  (absent omitted); Publisher.PublishActivity always publishes
  AgentPresenceChanged{current presence, activity} (absent presence -> OFFLINE).
- runnerhub: Hub.PresenceFor / PublishActivity delegate to a nil-safe
  presenceSource (mirrors the sink setter); executeCall gains the roster arm
  and the set_status arm (ordered write-then-publish: durable SetActivity commits
  first, best-effort PublishActivity fires the live event with the truncated
  string, never gated on and never erroring the call). The fail-closed default
  is untouched; its message now names the recognized variant set.
- server: wireHubServiceCycles + startPresencePublisher bridge the hub's
  presence source into comms (hubPresenceSource adapter, mirroring the
  AskAnswerWaker bridge).

Red-first: neighborhood/subtree/owner scoping; D9 clip drops a non-visible
agent; OFFLINE default + presence join; activity round-trips through the durable
store and survives a simulated restart (fresh handler, empty presence, same
store); set_status truncates over-cap and the truncated value lands in the table;
relay roster arm forwards + wraps; set_status arm write-then-publishes the
server-truncated value and succeeds with no presence source. Each proven
red-sensitive by mutating the implementation.

Refs SEA-1721

Co-authored-by: Matt Wilkinson <matt@sealedsecurity.com>
@linear-code

linear-code Bot commented Aug 5, 2026

Copy link
Copy Markdown

SEA-1721

…ath (SEA-1721)

Review-fix for the T2 roster PR (mandatory skill://review, 1 medium + 1 low
test-adequacy gaps; source unchanged, guards/order already correct).

- RosterAsAccount and SetStatusAsAccount both fail closed on an empty account
  (errNoActor -> CodeInvalidArgument), refusing to attribute an unresolved
  caller to the bootstrap-admin fallback — but neither guard had a test that
  fails on its removal. Add two pgtest cases mirroring the sibling security test
  (agent_caller_pgtest_test.go): TestRosterAsAccountEmptyAccountFailsClosed
  (asserts the error AND a nil response — no tree read, no ListAccounts("")
  enumeration; SUBTREE scope isolates the guard, since OWNER scope errors
  independently) and TestSetStatusAsAccountEmptyAccountFailsClosedNoWrite
  (asserts the error AND that agent_activity holds no row for the empty id).
- The set_status relay arm returns before PublishActivity when the durable
  write fails, so a subscriber never sees a status the store rejected — but the
  fakeCommsCaller.setStatusErr field was unused. Add
  TestRelayCommsCallSetStatusArmWriteErrorDoesNotPublish: the failure renders
  in-band (CommsCallError, transport survives) and src.published stays empty.

Each proven red-first by mutating the guard/order and watching the test fail.

Co-authored-by: Matt Wilkinson <matt@sealedsecurity.com>
@mattwilkinsonn
mattwilkinsonn merged commit ff377fb into main Aug 5, 2026
1 check passed
@mattwilkinsonn
mattwilkinsonn deleted the compass-comms-1721-t2-roster branch August 5, 2026 19:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants