Skip to content

feat(proto): forge-carrier family reconciled to canonical compass.v1 (SEA-1731) - #149

Open
seal-agent wants to merge 2 commits into
mainfrom
compass-repo-1731-forge-carrier
Open

feat(proto): forge-carrier family reconciled to canonical compass.v1 (SEA-1731)#149
seal-agent wants to merge 2 commits into
mainfrom
compass-repo-1731-forge-carrier

Conversation

@seal-agent

@seal-agent seal-agent commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

This PR is part of a stack containing 3 PRs:

  1. main
  2. "feat(proto): forge-carrier family reconciled to canonical compass.v1 (SEA-1731)" (this PR)
  3. feat(proto): BoardCall* agent write family + RelayBoardCall relay (SEA-1830) #201
  4. feat(server): agent issue-state write path (RelayBoardCall + transition executor) #206

What

A1 of the compass-server-ownership-layer amendment (docs/designs/product/compass-server-ownership-layer-amendment/design.md §A1): the internal-only forge-call carrier family, reconciled to the canonical compass.v1 types that landed in #145.

  • ForgeCall* carrier on AgentGateway (Forge RPC), relayed Runner→Server by RelayForgeCall (DL-049 sibling of CommsCall*/LifecycleCall*). Result arms retype to the canonical compass.v1.Issue/PullRequest/ChecksSummary (DL-069/DL-092); comment arms take a new CommentRef.
  • Per DL-092, the #995 forge-shaped domain messages (Issue/IssueComment/PullRequest/ForgeAuthor/ForgeChecksSummary/ForgeCheck) are not built — the forge Provider value types stay internal Go at the ingestion boundary; no raw forge shape is a wire type.
  • Read ops survive on the gateway, answered from the projection/store (DL-069 amendment OQ-A). The op requests are scalar-only, so the wire is identical under either forge read model (store-first read-through or stateless relay) — A1 is independent of that open question.

The one deviation from the frozen A1 directive: a circular import

The frozen record (#995 T1, carried into amendment §A1) places ForgeNotification in agent_gateway.proto and adds AgentControl.forge_notification in agent.proto. That is a circular importagent_gateway.proto already imports agent.proto (for AgentFrame/AgentControl), so a back-reference from agent.proto to a type defined in agent_gateway.proto is a cycle. Reproduced with buf:

compass/v1/agent.proto:26:1: detected cyclic import while importing "compass/v1/agent_gateway.proto"

Root cause: every other AgentControl payload type (PromptControl, DeliverControl, …) is defined in agent.proto; forge is the first agent_gateway.proto call family that also needs an AgentControl notification variant.

Fix (Matt-ruled, 2026-08-05): a new internal-only leaf forge.proto that imports only compass.proto and holds the four AgentControl-reachable types — ForgeNotification, ForgeNotificationKind, ForgeArtifactKind, CommentRef. agent.proto, agent_gateway.proto, and runner.proto all import the leaf without a cycle. Wire contract, field numbers, and generated Go/TS names are identical to the frozen shapes — only the source file changes.

One small vocabulary tightening the amendment explicitly permitted (§item 13): ForgeNotification carries ForgeRef forge rather than a bare string provider, so the notification path speaks one forge-identity vocabulary.

Gen wiring

forge.proto is internal-only, wired into all three lanes: public buf.gen.yaml exclude (kept off go/gen + compass-client), buf.gen.internal-go.yaml inputs + M-maps (→ compassv1internal), buf.gen.agent-ts.yaml inputs. The SEA-1267 gen-fence is extended with the forge carrier symbols; the canonical compass.v1 result types stay unfenced (they are public and must generate into the public trees — no forge pattern prefixes them).

Verification

moon run compass-proto:ci green: lint, breaking (additive → clean), drift (all 4 gen trees match checked-in), gen-fence (gen-fence ok: no internal symbols in public gen). Change set = 17 files: 4 proto edits + new forge.proto + 3 gen configs + regenerated internal gen only. Zero public-tree (go/gen, compass-client) changes.

Downstream

Gates compass-server's #995 Service layer (A2/A3 consume A1's regenerated types). A2's read path (store-join / store-first read-through) is the server's lane and does not change this proto.

Refs SEA-1731

@linear-code

linear-code Bot commented Aug 5, 2026

Copy link
Copy Markdown

SEA-1731

seal-agent added a commit that referenced this pull request Aug 5, 2026
Review of #149 flagged the CommentRef doc-comment mashing DL-092 (a DECISIONS.md
id) and §Resolved decisions OQ-B (an amendment section) into one parenthetical
with no separator, reading as if DL-092 lives in that section. Cite OQ-B for the
ruled reference shape and DL-069/DL-092 for the no-domain-type rule, separately.
Comment-only; regenerated so the gen trees carry the corrected comment.

Refs SEA-1731
Ledger-impact: none

Co-Authored-By: seal <noreply@sealedsecurity.com>
seal-agent added a commit that referenced this pull request Aug 5, 2026
… ListBoardIssues (SEA-1728)

Part 4 (board projection delivery) needs the connect-time re-snapshot seam
Matt ruled as Option B (comms-pattern snapshot delivery, not snapshot-as-
events). Two additive surfaces on the public compass.v1 contract:

- SubscribeEventsResponse.snapshot_seq (field 4): the store-space snapshot
  boundary a since_seq=0 subscriber gets on its leading frame, mirroring
  SubscribeCommsResponse.snapshot_seq. Client unions the catch-up read with
  the full live tail and dedups by issue id (never seq-filters the tail).
- ListBoardIssues RPC (+ Request/Response): the durable board re-snapshot
  read a UI calls at since_seq=0, the read counterpart to the snapshot-as-
  events burst. Single-shot for the bounded MVP board; returns every issue in
  all lifecycle states (incl. ARCHIVED, which the Done view needs). Named
  ListBoardIssues, not ListIssues, to avoid a compass.v1 duplicate-symbol
  collision with the forge-scoped ListIssues{Request,Response} that #149
  (forge carrier) adds to agent_gateway.proto in the same package.

Classifier green-keep: ListBoardIssues classified authenticatedOpen (same
access class as the SubscribeEvents tail it re-snapshots), with both
admin-gate spot-check tables extended. The server handler lands in the
compass-server part-4b PR (free CodeUnimplemented default meanwhile).

Refs SEA-1728.
seal-agent added a commit that referenced this pull request Aug 5, 2026
Review of #149 flagged the CommentRef doc-comment mashing DL-092 (a DECISIONS.md
id) and §Resolved decisions OQ-B (an amendment section) into one parenthetical
with no separator, reading as if DL-092 lives in that section. Cite OQ-B for the
ruled reference shape and DL-069/DL-092 for the no-domain-type rule, separately.
Comment-only; regenerated so the gen trees carry the corrected comment.

Refs SEA-1731
Ledger-impact: none

Co-Authored-By: seal <noreply@sealedsecurity.com>
@seal-agent
seal-agent force-pushed the compass-repo-1731-forge-carrier branch from ffb2a48 to 108dbbb Compare August 5, 2026 19:22
seal-agent added a commit that referenced this pull request Aug 5, 2026
… ListBoardIssues (SEA-1728)

Part 4 (board projection delivery) needs the connect-time re-snapshot seam
Matt ruled as Option B (comms-pattern snapshot delivery, not snapshot-as-
events). Two additive surfaces on the public compass.v1 contract:

- SubscribeEventsResponse.snapshot_seq (field 4): the store-space snapshot
  boundary a since_seq=0 subscriber gets on its leading frame, mirroring
  SubscribeCommsResponse.snapshot_seq. Client unions the catch-up read with
  the full live tail and dedups by issue id (never seq-filters the tail).
- ListBoardIssues RPC (+ Request/Response): the durable board re-snapshot
  read a UI calls at since_seq=0, the read counterpart to the snapshot-as-
  events burst. Single-shot for the bounded MVP board; returns every issue in
  all lifecycle states (incl. ARCHIVED, which the Done view needs). Named
  ListBoardIssues, not ListIssues, to avoid a compass.v1 duplicate-symbol
  collision with the forge-scoped ListIssues{Request,Response} that #149
  (forge carrier) adds to agent_gateway.proto in the same package.

Classifier green-keep: ListBoardIssues classified authenticatedOpen (same
access class as the SubscribeEvents tail it re-snapshots), with both
admin-gate spot-check tables extended. The server handler lands in the
compass-server part-4b PR (free CodeUnimplemented default meanwhile).

Refs SEA-1728.
seal-agent added a commit that referenced this pull request Aug 5, 2026
… ListBoardIssues (SEA-1728)

Part 4 (board projection delivery) needs the connect-time re-snapshot seam
Matt ruled as Option B (comms-pattern snapshot delivery, not snapshot-as-
events). Two additive surfaces on the public compass.v1 contract:

- SubscribeEventsResponse.snapshot_seq (field 4): the store-space snapshot
  boundary a since_seq=0 subscriber gets on its leading frame, mirroring
  SubscribeCommsResponse.snapshot_seq. Client unions the catch-up read with
  the full live tail and dedups by issue id (never seq-filters the tail).
- ListBoardIssues RPC (+ Request/Response): the durable board re-snapshot
  read a UI calls at since_seq=0, the read counterpart to the snapshot-as-
  events burst. Single-shot for the bounded MVP board; returns every issue in
  all lifecycle states (incl. ARCHIVED, which the Done view needs). Named
  ListBoardIssues, not ListIssues, to avoid a compass.v1 duplicate-symbol
  collision with the forge-scoped ListIssues{Request,Response} that #149
  (forge carrier) adds to agent_gateway.proto in the same package.

Classifier green-keep: ListBoardIssues classified authenticatedOpen (same
access class as the SubscribeEvents tail it re-snapshots), with both
admin-gate spot-check tables extended. The server handler lands in the
compass-server part-4b PR (free CodeUnimplemented default meanwhile).

Refs SEA-1728.
mattwilkinsonn pushed a commit that referenced this pull request Aug 6, 2026
… ListBoardIssues (SEA-1728) (#172)

Part 4 (board projection delivery) needs the connect-time re-snapshot seam
Matt ruled as Option B (comms-pattern snapshot delivery, not snapshot-as-
events). Two additive surfaces on the public compass.v1 contract:

- SubscribeEventsResponse.snapshot_seq (field 4): the store-space snapshot
  boundary a since_seq=0 subscriber gets on its leading frame, mirroring
  SubscribeCommsResponse.snapshot_seq. Client unions the catch-up read with
  the full live tail and dedups by issue id (never seq-filters the tail).
- ListBoardIssues RPC (+ Request/Response): the durable board re-snapshot
  read a UI calls at since_seq=0, the read counterpart to the snapshot-as-
  events burst. Single-shot for the bounded MVP board; returns every issue in
  all lifecycle states (incl. ARCHIVED, which the Done view needs). Named
  ListBoardIssues, not ListIssues, to avoid a compass.v1 duplicate-symbol
  collision with the forge-scoped ListIssues{Request,Response} that #149
  (forge carrier) adds to agent_gateway.proto in the same package.

Classifier green-keep: ListBoardIssues classified authenticatedOpen (same
access class as the SubscribeEvents tail it re-snapshots), with both
admin-gate spot-check tables extended. The server handler lands in the
compass-server part-4b PR (free CodeUnimplemented default meanwhile).

Refs SEA-1728.
seal-agent added a commit that referenced this pull request Aug 6, 2026
Review of #149 flagged the CommentRef doc-comment mashing DL-092 (a DECISIONS.md
id) and §Resolved decisions OQ-B (an amendment section) into one parenthetical
with no separator, reading as if DL-092 lives in that section. Cite OQ-B for the
ruled reference shape and DL-069/DL-092 for the no-domain-type rule, separately.
Comment-only; regenerated so the gen trees carry the corrected comment.

Refs SEA-1731
Ledger-impact: none

Co-Authored-By: seal <noreply@sealedsecurity.com>
@seal-agent
seal-agent force-pushed the compass-repo-1731-forge-carrier branch from 108dbbb to e012e12 Compare August 6, 2026 18:53
seal-agent added a commit that referenced this pull request Aug 7, 2026
…(SEA-1731)

Corrects the frozen `compass-server-ownership-layer-amendment` record so its §A1 add-list matches the shipped A1 proto (PR #149): the forge notification/carrier types (`ForgeNotification`/`ForgeNotificationKind`, `ForgeArtifactKind`, `CommentRef`) live in a new internal-only leaf `proto/compass/v1/forge.proto` that imports only `compass.proto`, **not** in `agent_gateway.proto` as #995 T1 and this record's original text directed — that placement is a circular import (`agent_gateway.proto` already imports `agent.proto`, so `agent.proto` referencing an `agent_gateway.proto` type is a cycle `buf` rejects). The `ForgeCall*` carrier + op requests stay in `agent_gateway.proto`; the leaf is imported acyclically by `agent.proto`/`agent_gateway.proto`/`runner.proto`. Wire contract, field numbers, and generated names are unchanged — placement only.

Rewrites the "one structural consequence" section to "two structural consequences" (the cross-file import **plus** the new leaf), updates the T1 add-list and the row-13 disposition, and adds the ledger row for the placement decision.

This correction was originally authored as a sealed PR (#1095) against the design corpus while it lived in `sealedsecurity/sealed`. #179 (SEA-1794) migrated the corpus + decision ledger + ledger gate into this repo, so the correction is re-homed here and #1095 is closed. The decision takes **DL-148** — allocated above the current ledger max after the migration (DL-130 in this repo is an unrelated role-prompts decision).

Refs SEA-1731

Co-authored-by: Matt Wilkinson <matt@sealedsecurity.com>
@seal-agent seal-agent closed this Aug 7, 2026
@seal-agent seal-agent reopened this Aug 7, 2026
seal-agent and others added 2 commits August 6, 2026 23:57
…(SEA-1731)

A1 of the compass-server-ownership-layer amendment: the internal-only forge
call carrier (ForgeCall* on AgentGateway relayed by RelayForgeCall) with its
result arms retyped to the canonical compass.v1 Issue/PullRequest/ChecksSummary
(DL-069/DL-092) and comment arms to a new CommentRef. Per DL-092 the #995
forge-shaped domain messages (Issue/IssueComment/PullRequest/ForgeAuthor/
ForgeChecksSummary/ForgeCheck) are NOT built; forge Provider value types stay
internal Go at the ingestion boundary.

New leaf forge.proto holds the AgentControl-reachable types (ForgeNotification,
ForgeNotificationKind, ForgeArtifactKind, CommentRef), importing only
compass.proto. This breaks the circular import the frozen A1 placement would
have created: it put ForgeNotification in agent_gateway.proto while agent.proto
needs AgentControl.forge_notification, but agent_gateway.proto already imports
agent.proto (buf: "detected cyclic import"). The leaf is imported by
agent.proto, agent_gateway.proto, and runner.proto without a cycle (Matt-ruled).

Wires forge.proto into all three gen lanes (public exclude, internal-go M-maps,
agent-ts inputs) and extends the SEA-1267 gen-fence with the forge carrier
symbols; the canonical compass.v1 result types stay unfenced (public).

proto:ci green: lint, breaking (additive), drift (4 trees), gen-fence.

Refs SEA-1731
Ledger-impact: none

Co-Authored-By: seal <noreply@sealedsecurity.com>
Review of #149 flagged the CommentRef doc-comment mashing DL-092 (a DECISIONS.md
id) and §Resolved decisions OQ-B (an amendment section) into one parenthetical
with no separator, reading as if DL-092 lives in that section. Cite OQ-B for the
ruled reference shape and DL-069/DL-092 for the no-domain-type rule, separately.
Comment-only; regenerated so the gen trees carry the corrected comment.

Refs SEA-1731
Ledger-impact: none

Co-Authored-By: seal <noreply@sealedsecurity.com>
@seal-agent
seal-agent force-pushed the compass-repo-1731-forge-carrier branch from e012e12 to 0c15c67 Compare August 7, 2026 03:58
seal-agent added a commit that referenced this pull request Aug 7, 2026
…A-1830)

T2 of the frozen `compass-agent-primary-lifecycle` amendment — the agent-facing issue-state-write proto. Adds a new sibling call family on the existing internal `AgentGateway` socket (DL-049/DL-076 shape), relayed Runner→Server, mirroring the `CommsCall*`/`ForgeCall*`/`LifecycleCall*` precedents exactly.

### `agent_gateway.proto`

- `rpc Board(BoardCallRequest) returns (BoardCallResult)` — the agent write, beside `Comms`/`Lifecycle`/`Forge`.
- `BoardCallRequest{ call_id, oneof call { SetIssueStateRequest set_issue_state } }` — the same envelope rides the relay leg verbatim.
- `SetIssueStateRequest{ issue_id, compass.v1.IssueState state }` / `SetIssueStateResponse{ compass.v1.Issue issue }` — carries the frozen `UpdateIssueState` semantics re-homed: any-to-any target, `ISSUE_STATE_UNSPECIFIED` → in-band `invalid_argument`, target == current → idempotent no-op returning current truth, `ISSUE_STATE_ARCHIVED` a legal target (DL-091 survives).
- `BoardCallResult{ call_id, oneof result { SetIssueStateResponse set_issue_state, BoardCallError error } }` — in-band tool error, never a transport teardown.
- `BoardCallError{ code, message }`.

### `runner.proto`

- `rpc RelayBoardCall(RelayBoardCallRequest) returns (RelayBoardCallResponse)` — Runner→Server relay, beside `RelayForgeCall`. Runner is a pure forwarder, asserts no account; the Server resolves `session_id` → account and runs the transition under that caller (single-trust-domain MVP, amendment §Resolved decisions 2), fail-closed `CodeNotFound` for an unknown/stopped session.
- `RelayBoardCallRequest{ session_id, BoardCallRequest call }` / `RelayBoardCallResponse{ BoardCallResult result }`.

### gen-fence

Extends the `proto/moon.yml` SEA-1267 fence with `BoardCall|RelayBoardCall|SetIssueState` (unanchored prefixes) — the new internal envelopes generate only into the internal lanes; the public `compass.v1` `Issue`/`IssueState` the result arms reference are not prefixed and stay in the public trees.

Additive, buf-breaking-safe. Whole-tree 3-lane regen (internal Go + agent TS; public trees unchanged). Explicitly NOT here: no `UpdateIssueState` RPC (dropped by DL-129), no classifier row (`Board`/`RelayBoardCall` are AgentGateway/RunnerService RPCs, not `CompassService`, so `classify_exhaustive_test` is untouched). Gates SEA-1728 Part 5 (T3, compass-server handler stacks on this bookmark).

Stacked on #149 (SEA-1731 forge-carrier): both edit `agent_gateway.proto` + run whole-tree regen, so stacking avoids a guaranteed generated-file conflict at merge.

Spec-impact: none. Refs SEA-1830, SEA-974.

Co-authored-by: Matt Wilkinson <matt@sealedsecurity.com>
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.

1 participant