Skip to content

feat(comms): org-management agent tools — comms adapters, hub dispatch, spawn role/persona (RIG-2673) - #630

Merged
mattwilkinsonn merged 2 commits into
mainfrom
compass-server/rig-2724-org-mgmt-handlers
Aug 30, 2026
Merged

feat(comms): org-management agent tools — comms adapters, hub dispatch, spawn role/persona (RIG-2673)#630
mattwilkinsonn merged 2 commits into
mainfrom
compass-server/rig-2724-org-mgmt-handlers

Conversation

@rigel-mintaka

@rigel-mintaka rigel-mintaka commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

This PR is part of a stack containing 3 PRs:

  1. main
  2. feat(proto): org-management comms + spawn arms for agent gateway (RIG-2673) #628
  3. "feat(comms): org-management agent tools — comms adapters, hub dispatch, spawn role/persona (RIG-2673)" (this PR)
  4. feat(proto): OpenDM RPC + gateway arm; GROUP_DM retirement; DM/convert fields (RIG-2962) #738

Wires the compass-server half of the org-management agent tools (RIG-2673 T2–T4) on top of the T1 proto arms (#628): the three comms adapters, their hub dispatch, and the spawn role/persona thread-through. Every operation flows through the existing agent→Runner→Server relay under the server-resolved account, so the authz, idempotency, and event fan-out are identical to a human caller's.

T2 — comms adapters (go/internal/comms/agent_caller.go)

CreateChannelAsAccount, UpdateChannelMembersAsAccount, CreateChannelGroupAsAccount — each mirrors UpdatePinnedBoardAsAccount: guard empty account → errNoActor, then WithActor + the shared handler path, returning resp.Msg. No home-channel defaulting (create-channel names no channel; update-members carries channel_id explicitly; create-group names only an optional parent). Founding membership rides CreateChannel's expandOwnerMembership, so a Manager can immediately post to the channel it just made.

T3 — hub dispatch (go/internal/runnerhub/hub.go, relay_comms.go)

Extended the CommsCaller interface with the three methods and added three executeCall cases on the Pin pattern, each wrapping the matching CommsCallResult oneof. The default-case error string's variant list now includes the three new arms. A tool error renders in-band as CommsCallError, never a stream teardown.

T4 — spawn role/persona thread-through (go/server/lifecycle.go)

Dropped the Persona: "" / Role: "" hardcodes in the store.CreateAgent literal for req.GetPersona() / req.GetRole(). Under the D9 owner-acts model the caller's owner is the authority, so a Manager-creating spawn legitimately carries role+persona set-at-creation; the values are stored via CreateAgent (the source of record) and threaded to the Runner from the created store account — an empty-field spawn is byte-identical to today's field-less spawn.

Tests (red-green)

  • T2 pgtests (org_mgmt_pgtest_test.go): founder-membership + ChannelChanged fan-out, member-add, group-create; each with empty-account → errNoActor and an invisible/non-member target → CodeNotFound (the D9 collapse a human gets).
  • T3 relay tests (relay_org_mgmt_test.go): each arm forwards under the bound account with call_id round-trip; a create-channel tool error is in-band, not a transport teardown.
  • T4 spawn pgtests (spawn_role_persona_pgtest_test.go): role and persona each stored + on the Provision wire; empty-field spawn stores + wires empty (wire-level regression); idempotent re-spawn keeps stored values.

Verified: go build ./..., gofmt, compass-go:lint (0 issues), and the affected internal/comms / internal/runnerhub / server suites all green (pgtests via the throwaway-container path).

Refs RIG-2724, RIG-2673.

Co-authored-by: Matt Wilkinson matt@rigel.build

@linear-code

linear-code Bot commented Aug 25, 2026

Copy link
Copy Markdown

RIG-2724

RIG-2673

@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown

Compass engineering docs preview: https://compass-server-rig-2724-org-au33.compass-eng-docs.pages.dev

Deployed from compass-server/rig-2724-org-mgmt-handlers at aab6347.

@rigel-mintaka
rigel-mintaka force-pushed the compass-server/rig-2724-org-mgmt-proto branch from 60728dd to 836c472 Compare August 25, 2026 23:05
@rigel-mintaka
rigel-mintaka force-pushed the compass-server/rig-2724-org-mgmt-handlers branch 2 times, most recently from 9584e0b to 10fb626 Compare August 25, 2026 23:40
@rigel-mintaka
rigel-mintaka marked this pull request as draft August 26, 2026 03:15
rigel-mintaka added a commit that referenced this pull request Aug 28, 2026
…solver, comms edge (RIG-2880)

The handle-addressing cutover: every request-input account field carries a `@handle`, resolved to an account id at the service edge, per `docs/designs/product/compass-handle-addressing-cutover/design.md` (Plan T0-T3, plus the compass-agent T6 tool rewire folded in to keep the tree green).

**T0 — resolution index** (`0001_init.sql`). Adds `account_handles(account_id, handle, owner_user_id NULL)` with two partial-unique indexes: user/system handles globally unique (`owner_user_id IS NULL`), agent handles unique per owner. `accounts.handle` stays as a display column, no longer the resolution key. No backfill (pre-dogfood); store write paths insert the handle row in the same tx as the account.

**T1 — proto flip** (`comms.proto`, `agent_gateway.proto`, `compass.proto`). Every request-input account field renamed to its `@handle` form (`member_handles`, `add/remove/subscribe/unsubscribe_handles`, `agent_handle`, `new_parent_handle`, `parent_handle`, `owner_handle`, `vantage_handle`, `account_handle`), field numbers kept in place (rename-in-place, DL-186). Response, stored, and event account fields stay id-typed (the stable join keys clients hold). All four gen lanes regenerated; gen-fence clean.

**T2 — resolver** (`accounts.go`). `AccountsByHandles` is an owner-qualified batch resolve over `account_handles`: atomic (any miss fails the whole call, naming every unresolved handle in submitted spelling — OQ-2), visibility-scoped (an invisible handle misses exactly like an unknown one — OQ-6), system-excluded. `AgentByHandle` re-keyed to `(owner, handle)`; `UserByHandle` global-tier helper; `QualifiedHandle`/`ParseQualifiedHandle` split on the first `/`.

**T3 — comms edge** (`resolve.go` new, `mapping.go`, `roster.go`). Handles resolve before the store calls, with oracle-safe NOT_FOUND remaps on the authority/visibility legs (DL-269): CreateAgent foreign parent, ReparentAgent `ErrPermissionDenied` merge, OpenAgentWorkspace re-key to the submitted handle, roster vantage visibility-close. A delivery mention `@handle` resolves in the posting author's owner namespace. `memberUpdatesFromWire` merges post-resolution so two spellings of one handle cannot yield two conflicting `MemberUpdate`s.

**T6 (folded) — compass-agent despawn tool** (`lifecycle.ts`). `agents_despawn_peer` takes `agent_handle` (non-blank) and builds `DespawnPeerRequest{agentHandle}`; the description drops "by its agent account id". The roster tool is unchanged (it never set the vantage). Folded into this PR so the whole tree — Go, proto, and the bun lane the proto regen touches — stays green in one atomic change rather than landing a red intermediate.

Admin/ops (T8) and lifecycle despawn (T4) server handlers are mechanically renamed to the handle-typed fields but still consume the value as an id (documented id-passthrough skew); their real resolution lands in the follow-up T4/T8 commits on this stack.

**Verification.** `go vet ./...` and `-tags "pgtest podman unix microvm"` clean, `go build ./...` clean, all test binaries compile, `compass-proto:drift`/`gen-fence` pass, store/comms/delivery pgtests pass against live Postgres, `go test -race` clean; `compass-agent` typecheck + 610 bun tests green; `compass-ui`/`compass-client` typecheck green.

Adds DL-269 (request-input account fields are handle-typed), DL-270 (response/stored/event fields stay id-typed), DL-271 (owner-namespaced `account_handles` resolution) on merge.

Unblocks the remaining cutover lanes: T5 rebase of #628/#630, T8 admin/ops resolution, T9 additive `Message.author_handle`, and the compass-ui T7 sweep.

Spec-impact: none. Refs RIG-2880

Co-authored-by: Matt Wilkinson <matt@rigel.build>
rigel-mintaka added a commit that referenced this pull request Aug 28, 2026
…solver, comms edge (RIG-2880)

The handle-addressing cutover: every request-input account field carries a `@handle`, resolved to an account id at the service edge, per `docs/designs/product/compass-handle-addressing-cutover/design.md` (Plan T0-T3, plus the compass-agent T6 tool rewire folded in to keep the tree green).

**T0 — resolution index** (`0001_init.sql`). Adds `account_handles(account_id, handle, owner_user_id NULL)` with two partial-unique indexes: user/system handles globally unique (`owner_user_id IS NULL`), agent handles unique per owner. `accounts.handle` stays as a display column, no longer the resolution key. No backfill (pre-dogfood); store write paths insert the handle row in the same tx as the account.

**T1 — proto flip** (`comms.proto`, `agent_gateway.proto`, `compass.proto`). Every request-input account field renamed to its `@handle` form (`member_handles`, `add/remove/subscribe/unsubscribe_handles`, `agent_handle`, `new_parent_handle`, `parent_handle`, `owner_handle`, `vantage_handle`, `account_handle`), field numbers kept in place (rename-in-place, DL-186). Response, stored, and event account fields stay id-typed (the stable join keys clients hold). All four gen lanes regenerated; gen-fence clean.

**T2 — resolver** (`accounts.go`). `AccountsByHandles` is an owner-qualified batch resolve over `account_handles`: atomic (any miss fails the whole call, naming every unresolved handle in submitted spelling — OQ-2), visibility-scoped (an invisible handle misses exactly like an unknown one — OQ-6), system-excluded. `AgentByHandle` re-keyed to `(owner, handle)`; `UserByHandle` global-tier helper; `QualifiedHandle`/`ParseQualifiedHandle` split on the first `/`.

**T3 — comms edge** (`resolve.go` new, `mapping.go`, `roster.go`). Handles resolve before the store calls, with oracle-safe NOT_FOUND remaps on the authority/visibility legs (DL-269): CreateAgent foreign parent, ReparentAgent `ErrPermissionDenied` merge, OpenAgentWorkspace re-key to the submitted handle, roster vantage visibility-close. A delivery mention `@handle` resolves in the posting author's owner namespace. `memberUpdatesFromWire` merges post-resolution so two spellings of one handle cannot yield two conflicting `MemberUpdate`s.

**T6 (folded) — compass-agent despawn tool** (`lifecycle.ts`). `agents_despawn_peer` takes `agent_handle` (non-blank) and builds `DespawnPeerRequest{agentHandle}`; the description drops "by its agent account id". The roster tool is unchanged (it never set the vantage). Folded into this PR so the whole tree — Go, proto, and the bun lane the proto regen touches — stays green in one atomic change rather than landing a red intermediate.

Admin/ops (T8) and lifecycle despawn (T4) server handlers are mechanically renamed to the handle-typed fields but still consume the value as an id (documented id-passthrough skew); their real resolution lands in the follow-up T4/T8 commits on this stack.

**Verification.** `go vet ./...` and `-tags "pgtest podman unix microvm"` clean, `go build ./...` clean, all test binaries compile, `compass-proto:drift`/`gen-fence` pass, store/comms/delivery pgtests pass against live Postgres, `go test -race` clean; `compass-agent` typecheck + 610 bun tests green; `compass-ui`/`compass-client` typecheck green.

Adds DL-269 (request-input account fields are handle-typed), DL-270 (response/stored/event fields stay id-typed), DL-271 (owner-namespaced `account_handles` resolution) on merge.

Unblocks the remaining cutover lanes: T5 rebase of #628/#630, T8 admin/ops resolution, T9 additive `Message.author_handle`, and the compass-ui T7 sweep.

Spec-impact: none. Refs RIG-2880

Co-authored-by: Matt Wilkinson <matt@rigel.build>
rigel-mintaka added a commit that referenced this pull request Aug 28, 2026
…solver, comms edge (RIG-2880)

The handle-addressing cutover: every request-input account field carries a `@handle`, resolved to an account id at the service edge, per `docs/designs/product/compass-handle-addressing-cutover/design.md` (Plan T0-T3, plus the compass-agent T6 tool rewire folded in to keep the tree green).

**T0 — resolution index** (`0001_init.sql`). Adds `account_handles(account_id, handle, owner_user_id NULL)` with two partial-unique indexes: user/system handles globally unique (`owner_user_id IS NULL`), agent handles unique per owner. `accounts.handle` stays as a display column, no longer the resolution key. No backfill (pre-dogfood); store write paths insert the handle row in the same tx as the account.

**T1 — proto flip** (`comms.proto`, `agent_gateway.proto`, `compass.proto`). Every request-input account field renamed to its `@handle` form (`member_handles`, `add/remove/subscribe/unsubscribe_handles`, `agent_handle`, `new_parent_handle`, `parent_handle`, `owner_handle`, `vantage_handle`, `account_handle`), field numbers kept in place (rename-in-place, DL-186). Response, stored, and event account fields stay id-typed (the stable join keys clients hold). All four gen lanes regenerated; gen-fence clean.

**T2 — resolver** (`accounts.go`). `AccountsByHandles` is an owner-qualified batch resolve over `account_handles`: atomic (any miss fails the whole call, naming every unresolved handle in submitted spelling — OQ-2), visibility-scoped (an invisible handle misses exactly like an unknown one — OQ-6), system-excluded. `AgentByHandle` re-keyed to `(owner, handle)`; `UserByHandle` global-tier helper; `QualifiedHandle`/`ParseQualifiedHandle` split on the first `/`.

**T3 — comms edge** (`resolve.go` new, `mapping.go`, `roster.go`). Handles resolve before the store calls, with oracle-safe NOT_FOUND remaps on the authority/visibility legs (DL-269): CreateAgent foreign parent, ReparentAgent `ErrPermissionDenied` merge, OpenAgentWorkspace re-key to the submitted handle, roster vantage visibility-close. A delivery mention `@handle` resolves in the posting author's owner namespace. `memberUpdatesFromWire` merges post-resolution so two spellings of one handle cannot yield two conflicting `MemberUpdate`s.

**T6 (folded) — compass-agent despawn tool** (`lifecycle.ts`). `agents_despawn_peer` takes `agent_handle` (non-blank) and builds `DespawnPeerRequest{agentHandle}`; the description drops "by its agent account id". The roster tool is unchanged (it never set the vantage). Folded into this PR so the whole tree — Go, proto, and the bun lane the proto regen touches — stays green in one atomic change rather than landing a red intermediate.

Admin/ops (T8) and lifecycle despawn (T4) server handlers are mechanically renamed to the handle-typed fields but still consume the value as an id (documented id-passthrough skew); their real resolution lands in the follow-up T4/T8 commits on this stack.

**Verification.** `go vet ./...` and `-tags "pgtest podman unix microvm"` clean, `go build ./...` clean, all test binaries compile, `compass-proto:drift`/`gen-fence` pass, store/comms/delivery pgtests pass against live Postgres, `go test -race` clean; `compass-agent` typecheck + 610 bun tests green; `compass-ui`/`compass-client` typecheck green.

Adds DL-269 (request-input account fields are handle-typed), DL-270 (response/stored/event fields stay id-typed), DL-271 (owner-namespaced `account_handles` resolution) on merge.

Unblocks the remaining cutover lanes: T5 rebase of #628/#630, T8 admin/ops resolution, T9 additive `Message.author_handle`, and the compass-ui T7 sweep.

Spec-impact: none. Refs RIG-2880

Co-authored-by: Matt Wilkinson <matt@rigel.build>
mattwilkinsonn added a commit that referenced this pull request Aug 29, 2026
…solver, comms edge (RIG-2880) (#698)

* feat(compass): handle-address request inputs — schema, proto flip, resolver, comms edge (RIG-2880)

The handle-addressing cutover: every request-input account field carries a `@handle`, resolved to an account id at the service edge, per `docs/designs/product/compass-handle-addressing-cutover/design.md` (Plan T0-T3, plus the compass-agent T6 tool rewire folded in to keep the tree green).

**T0 — resolution index** (`0001_init.sql`). Adds `account_handles(account_id, handle, owner_user_id NULL)` with two partial-unique indexes: user/system handles globally unique (`owner_user_id IS NULL`), agent handles unique per owner. `accounts.handle` stays as a display column, no longer the resolution key. No backfill (pre-dogfood); store write paths insert the handle row in the same tx as the account.

**T1 — proto flip** (`comms.proto`, `agent_gateway.proto`, `compass.proto`). Every request-input account field renamed to its `@handle` form (`member_handles`, `add/remove/subscribe/unsubscribe_handles`, `agent_handle`, `new_parent_handle`, `parent_handle`, `owner_handle`, `vantage_handle`, `account_handle`), field numbers kept in place (rename-in-place, DL-186). Response, stored, and event account fields stay id-typed (the stable join keys clients hold). All four gen lanes regenerated; gen-fence clean.

**T2 — resolver** (`accounts.go`). `AccountsByHandles` is an owner-qualified batch resolve over `account_handles`: atomic (any miss fails the whole call, naming every unresolved handle in submitted spelling — OQ-2), visibility-scoped (an invisible handle misses exactly like an unknown one — OQ-6), system-excluded. `AgentByHandle` re-keyed to `(owner, handle)`; `UserByHandle` global-tier helper; `QualifiedHandle`/`ParseQualifiedHandle` split on the first `/`.

**T3 — comms edge** (`resolve.go` new, `mapping.go`, `roster.go`). Handles resolve before the store calls, with oracle-safe NOT_FOUND remaps on the authority/visibility legs (DL-269): CreateAgent foreign parent, ReparentAgent `ErrPermissionDenied` merge, OpenAgentWorkspace re-key to the submitted handle, roster vantage visibility-close. A delivery mention `@handle` resolves in the posting author's owner namespace. `memberUpdatesFromWire` merges post-resolution so two spellings of one handle cannot yield two conflicting `MemberUpdate`s.

**T6 (folded) — compass-agent despawn tool** (`lifecycle.ts`). `agents_despawn_peer` takes `agent_handle` (non-blank) and builds `DespawnPeerRequest{agentHandle}`; the description drops "by its agent account id". The roster tool is unchanged (it never set the vantage). Folded into this PR so the whole tree — Go, proto, and the bun lane the proto regen touches — stays green in one atomic change rather than landing a red intermediate.

Admin/ops (T8) and lifecycle despawn (T4) server handlers are mechanically renamed to the handle-typed fields but still consume the value as an id (documented id-passthrough skew); their real resolution lands in the follow-up T4/T8 commits on this stack.

**Verification.** `go vet ./...` and `-tags "pgtest podman unix microvm"` clean, `go build ./...` clean, all test binaries compile, `compass-proto:drift`/`gen-fence` pass, store/comms/delivery pgtests pass against live Postgres, `go test -race` clean; `compass-agent` typecheck + 610 bun tests green; `compass-ui`/`compass-client` typecheck green.

Adds DL-269 (request-input account fields are handle-typed), DL-270 (response/stored/event fields stay id-typed), DL-271 (owner-namespaced `account_handles` resolution) on merge.

Unblocks the remaining cutover lanes: T5 rebase of #628/#630, T8 admin/ops resolution, T9 additive `Message.author_handle`, and the compass-ui T7 sweep.

Spec-impact: none. Refs RIG-2880

Co-authored-by: Matt Wilkinson <matt@rigel.build>

* fix(compass): close ReparentAgent oracle leak, complete OQ-2 miss naming, add DL rows (RIG-2880)

Review-fix commit on the handle-addressing foundation. Addresses the review of the parent commit (three code findings plus the mandated ledger rows); the low-2 finding (globally-visible user directory) is a pre-existing decision surfaced to Matt, not changed here.

HIGH — ReparentAgent oracle leak (DL-269 violation). A foreign new_parent_handle (one that exists under another owner) fell through the edge to the store, which re-keyed the error to name the AGENT handle, while an unknown parent named the submitted parent handle. The divergence let a caller distinguish "this parent exists under another owner" from "no such handle" — an enumeration probe against another owner's tree. Fixed by mirroring CreateAgent's same-owner edge pre-check in ReparentAgent (go/internal/comms/comms.go): after resolving the new parent, resolve the caller's owner and the parent's owner, and if they differ return the indistinguishable NOT_FOUND naming the submitted new_parent_handle. The store's clause-0 permission-denied catch stays correct for agent-authority; the store clause-1 foreign-parent path is now unreachable via the edge.

MEDIUM — reparent cross-owner tests asserted code only, not message. TestReparentAgentCrossOwnerParentNotFound now captures both the foreign-parent and unknown-parent errors and asserts each names its own submitted parent handle, that the foreign error does NOT name the agent handle, and that the two are byte-identical modulo the caller's own submitted spelling — the oracle invariant, not just the code.

LOW-1 — memberUpdatesFromWire OQ-2 completeness. The four member lists (add/subscribe/unsubscribe/remove) resolved sequentially, so a miss in a later list was masked by an earlier list's miss — the error named only the first failing list. Rewritten to one combined resolveHandles call over all four lists, slicing results back per-list by offset; every unresolved handle across every list is now named in one pass. New TestUpdateChannelMembersNamesMissesAcrossAllLists defends this.

Ledger — adds the three rows the frozen record's §Ledger impact mandates (DL-269 request-input handle-typing + oracle invariant, DL-270 response/stored/event stay id-typed, DL-271 owner-namespaced account_handles resolution), placed in the Storage section. The design PR merged without adding them; per house convention the impl PR fills its allocated numbers.

Verification: go build + go vet (all tags) clean; gofmt + compass-go:lint (0 issues) clean; comms pgtest suite green against live Postgres (reparent oracle fix, one-pass member resolution, and both new tests); design-ledger-gate green (244 rows, anchor resolves).

Co-authored-by: Matt Wilkinson <matt@rigel.build>

* docs(store): note ReparentAgent clause-1 is edge-shadowed on the RPC path (RIG-2880)

Review-fix on #698 (low, non-gating). The re-review noted that comms.ReparentAgent's new edge pre-check makes the store's validateNewParent same-owner ErrPermissionDenied unreachable via the RPC path — a future reader at the store clause might mistake it for dead code. Adds a one-line note that it is edge-shadowed on the RPC path and remains as store-layer defense-in-depth (the store is independently callable and tested).

Co-authored-by: Matt Wilkinson <matt@rigel.build>

* fix(compass): spawn allows cross-owner same-name agents, guards against shadowing a human (RIG-2880)

The per-owner `account_handles` namespace (DL-271) changes the spawn-collision
domain from global to per-owner, which the two `go/server` lifecycle spawn tests
did not yet reflect — they asserted the pre-cutover global-unique behavior and
reddened the `pgtest` CI suite. Matt ruled the intended `SpawnPeer` contract
(2026-08-27): allow cross-owner same-name agents, but keep a defense-in-depth
guard so an agent can never shadow a human or the system sender.

- **Shadow guard** (`lifecycle.go`): `SpawnAsAccount` resolves the bare handle in
  the global user/system index (`UserByHandle`) before `CreateAgent`; a hit is
  the same in-band `already_exists`/`errHandleTaken` a duplicate agent handle
  gets, never revealing the account kind. Storage permits an agent handle to
  overlap a user/system handle (the two partial-unique indexes never contend),
  but resolution resolves the global tier first (OQ-7), so this closes the one
  way a peer could be created onto a human's handle.

- **`resumeOrReject` simplification** (`lifecycle.go`): with the guard excluding
  user/system handles and the per-owner namespace isolating foreign owners, a
  `CreateAgent` `ErrConflict` can only mean a same-owner agent already holds the
  handle. The two former reject branches (non-agent handle, foreign owner) are
  now unreachable and removed; an `AgentByHandle(callerOwner, handle)` miss there
  is an invariant violation (`CodeInternal`), not a routine collapse.

- **Tests** (`lifecycle_pgtest_test.go`): `...DifferentOwnerIsAlreadyExists` is
  rewritten as `...CreatesDistinctPeer` — owner B spawning owner A's handle now
  creates a distinct owner-B peer, A untouched, each owner's handle resolving to
  its own agent. `...CollidesWithUserAccountIsAlreadyExists` keeps its
  `already_exists` assertion, now backed by the guard, with an added
  system-handle sibling pinning the indistinguishable code shape.

- **Fake runner** (`service_placement_pgtest_test.go`): an opt-in FIFO
  container-name override (mirroring the existing `startIDs`), so the cross-owner
  test's two genuinely-distinct spawns get distinct container names instead of
  colliding on the fixture's constant `fakeContainer` (production derives the
  name from the globally-unique account id, so real spawns never collide).

Verification: `go build ./...`, `go vet -tags "pgtest podman unix microvm"`, and
the `go/server`, `go/internal/store`, `go/internal/comms` pgtest suites all green
against live Postgres. Self-driven `review` agent: 0 high / 0 medium / 2 low
(both no-change informational).

Refs RIG-2880

Co-authored-by: Matt Wilkinson <matt@rigel.build>

---------

Co-authored-by: Matt Wilkinson <matt@rigel.build>
@rigel-mintaka
rigel-mintaka force-pushed the compass-server/rig-2724-org-mgmt-proto branch from 836c472 to 8374738 Compare August 29, 2026 20:36
@rigel-mintaka
rigel-mintaka force-pushed the compass-server/rig-2724-org-mgmt-handlers branch from 10fb626 to 38468e2 Compare August 29, 2026 20:36
@rigel-mintaka
rigel-mintaka marked this pull request as ready for review August 29, 2026 20:36
rigel-mintaka and others added 2 commits August 30, 2026 10:56
…-2673)

Add the three org-management comms-call arms (create_channel=7,
update_members=8, create_channel_group=9 on CommsCallRequest.call; the
matching results =8/=9/=10 on CommsCallResult.result) and the Manager-
creation role=5/persona=6 fields on SpawnPeerRequest, reusing the existing
comms.proto payload messages verbatim. Regenerated the internal Go
(go/internal/gen) and agent TS (packages/compass-agent/src/gen) lanes.

T1 of the frozen org-management-tools record (RIG-2673, #589); the single
additive proto+regen commit both compass-server and compass-agent consume.

Co-authored-by: Matt Wilkinson <matt@rigel.build>

jj-hooks: autofixes for compass-server/rig-2724-org-mgmt-proto

regen-resolve
…h, spawn role/persona (RIG-2673)

Wires the compass-server half of the org-management agent tools (RIG-2673 T2–T4) on top of the T1 proto arms (#628): the three comms adapters, their hub dispatch, and the spawn role/persona thread-through. Every operation flows through the existing agent→Runner→Server relay under the server-resolved account, so the authz, idempotency, and event fan-out are identical to a human caller's.

### T2 — comms adapters (`go/internal/comms/agent_caller.go`)

`CreateChannelAsAccount`, `UpdateChannelMembersAsAccount`, `CreateChannelGroupAsAccount` — each mirrors `UpdatePinnedBoardAsAccount`: guard empty account → `errNoActor`, then `WithActor` + the shared handler path, returning `resp.Msg`. No home-channel defaulting (create-channel names no channel; update-members carries `channel_id` explicitly; create-group names only an optional parent). Founding membership rides `CreateChannel`'s `expandOwnerMembership`, so a Manager can immediately post to the channel it just made.

### T3 — hub dispatch (`go/internal/runnerhub/hub.go`, `relay_comms.go`)

Extended the `CommsCaller` interface with the three methods and added three `executeCall` cases on the `Pin` pattern, each wrapping the matching `CommsCallResult` oneof. The default-case error string's variant list now includes the three new arms. A tool error renders in-band as `CommsCallError`, never a stream teardown.

### T4 — spawn role/persona thread-through (`go/server/lifecycle.go`)

Dropped the `Persona: ""` / `Role: ""` hardcodes in the `store.CreateAgent` literal for `req.GetPersona()` / `req.GetRole()`. Under the D9 owner-acts model the caller's owner is the authority, so a Manager-creating spawn legitimately carries role+persona set-at-creation; the values are stored via `CreateAgent` (the source of record) and threaded to the Runner from the created store account — an empty-field spawn is byte-identical to today's field-less spawn.

### Tests (red-green)

- T2 pgtests (`org_mgmt_pgtest_test.go`): founder-membership + `ChannelChanged` fan-out, member-add, group-create; each with empty-account → `errNoActor` and an invisible/non-member target → `CodeNotFound` (the D9 collapse a human gets).
- T3 relay tests (`relay_org_mgmt_test.go`): each arm forwards under the bound account with `call_id` round-trip; a create-channel tool error is in-band, not a transport teardown.
- T4 spawn pgtests (`spawn_role_persona_pgtest_test.go`): role and persona each stored + on the Provision wire; empty-field spawn stores + wires empty (wire-level regression); idempotent re-spawn keeps stored values.

Verified: `go build ./...`, `gofmt`, `compass-go:lint` (0 issues), and the affected `internal/comms` / `internal/runnerhub` / `server` suites all green (pgtests via the throwaway-container path).

Refs RIG-2724, RIG-2673.

Co-authored-by: Matt Wilkinson <matt@rigel.build>
@rigel-mintaka
rigel-mintaka force-pushed the compass-server/rig-2724-org-mgmt-handlers branch from 38468e2 to aab6347 Compare August 30, 2026 15:00
@rigel-mintaka
rigel-mintaka force-pushed the compass-server/rig-2724-org-mgmt-proto branch from 8374738 to c5f84cd Compare August 30, 2026 15:00
Base automatically changed from compass-server/rig-2724-org-mgmt-proto to main August 30, 2026 17:23
@mattwilkinsonn
mattwilkinsonn merged commit bca111c into main Aug 30, 2026
17 of 28 checks passed
@mattwilkinsonn
mattwilkinsonn deleted the compass-server/rig-2724-org-mgmt-handlers branch August 30, 2026 17:24
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