docs(product): Linear Agent Session responder design (RIG-2717) - #625
Merged
Conversation
|
Compass engineering docs preview: https://compass-server-rig-2717-resp.compass-eng-docs.pages.dev Deployed from Changed pages: |
rigel-mintaka
force-pushed
the
compass-server/rig-2717-responder-design
branch
from
August 25, 2026 21:21
a33cd21 to
acb8dac
Compare
…-2717) Capture Compass's comms model as a first-class `concepts/` doc: **threads for conversation, the session log for work**. ## Why The premise is load-bearing and already frozen across the ledger (DL-098 Zulip threading, DL-099 streamed-turn-writes-nothing-to-comms, DL-088 log-and-trace are two projections of one artifact, DL-158 workspace = home channel + session trace) — but it lived only in those scattered design records, never stated as one discoverable idea in the `concepts/` layer whose charter is exactly "the load-bearing ideas the code and prompts assume you already hold." The gap bites when bridging an external agent-session protocol in: the reflex is to adopt that system's flat single-session-per-task-with-everything-in-one-log shape, which is precisely the model Compass's threads/log split exists to reject. This doc states the premise plainly so an integration maps onto the Compass model rather than replacing it. ## What - New `docs/concepts/comms-model.md`: the two surfaces (session log = work; channels/threads = communication), why the split is structural not a prompting convention, stable agents with home channels, typed comms blocks (`ask` and planned kinds), and the explicit contrast an external-session bridge must respect. - `docs/concepts/README.md`: new "The comms model" section, placed before "The tools" (which references it). Spec-impact: none. Ledger-impact: none. Refs RIG-2717. Co-authored-by: Matt Wilkinson <matt@rigel.build>
rigel-mintaka
force-pushed
the
compass-server/rig-2717-comms-model-concept
branch
from
August 25, 2026 21:56
1a5ece4 to
88e08df
Compare
rigel-mintaka
force-pushed
the
compass-server/rig-2717-responder-design
branch
2 times, most recently
from
August 25, 2026 22:05
6cfcd60 to
b0dd959
Compare
Production **design record** for making the installed `Compass` Linear app (RIG-2682) a live Linear Agent App: receive Agent Session webhooks, route a delegated issue to the right stable Compass Manager, carry the conversation as a topic in that Manager's home channel, and link the Linear session back out to Compass. Stacked on #624 (the comms-model concept doc), which this record's premise cites. All ten open questions were ruled by Matt on 2026-08-25 (RIG-2729); this record folds every ruling in and freezes with no live open questions. ## The premise this record is built on Matt's steer, captured in #624 and load-bearing here: **Compass's comms model is deliberate, and Linear's Agent Session model is what it rejects.** Compass has stable agents (Managers + peers) each with a home channel; communication rides Zulip-style threads (channel → named topics) and the agent's *work* stays out of the threads in a side-panel session log. Linear's Agent Session is the opposite — one ephemeral flat activity log per issue, no stable agent, no threads. So the Linear session is a doorway, not a home. ## The decision — Option B (dumb link), Matt ruled RIG-2729 A hard constraint forces the mapping-depth choice: **Linear's Agent Activity vocabulary is a fixed, server-validated set of five types** (`thought`/`action`/`elicitation`/`response`/`error`) with no extension point, so Compass's typed comms blocks (a structured `ask` with discrete options) cannot round-trip through a Linear session. - **Option A — full relay (bidirectional).** Mirror the Compass conversation into the Linear session. Richest, but shows a degraded conversation. **Off-table** until Linear makes the activity format configurable. - **Option B — dumb link (chosen).** On `created`, emit one `thought` + an `externalUrls` "Open in Compass" deep link to the resolved Manager's home channel; all real interaction happens in Compass. Deletes the entire return relay. - **Option C — hybrid (ratified follow-up).** Dumb link + a coarse one-way status back, no message-level mirroring. ## What the bridge does 1. **Receive** — a plain `POST /webhooks` `http.Handler` on the network TLS door, fail-closed HMAC-SHA256 signature check (bad/missing → 400; stale-but-valid timestamp → 200-with-drop, never a retry-burning 400), ack 200 before any async work. 2. **Route** (Matt ruled routing is in scope, OQ-3) — resolve the delegated issue to a stable Manager keyed on Compass's **recorded** forge ownership index (`forge_authored_artifacts`, DL-055/DL-205), **never** a header parsed from forge text (DL-050/DL-094 forbid that reaching a routing decision). An unstamped issue routes to the supervisor via a dedicated routing channel, which decides the lane and stamps it. 3. **Map** (Matt ruled not 1-1, OQ-4) — the prompt lands in an issue-named comms topic in the Manager's home channel (sessions on one issue coalesce), delivered as `@linear`-authored messages on the durable deliver rail, deduped by `PostAsAccount`'s `client_request_id` on the `Linear-Delivery` UUID. The deep link targets the **home channel**, not the topic. 4. **Link back** — the two `created` emits (the ack `thought` + the session external URL) are the whole return path. No relay, no settle observation, no session-lifecycle machine. The public base URL (webhook host + deep-link base) is **per-deployment** (Matt ruled OQ-2): managed = `compass.rigel.build`, self-host = its own URL, dev/tailnet deploys need their own ingress. ## Resolved decisions (all ten OQs, Matt 2026-08-25) OQ-1 Option B (C follow-up, A off-table) · OQ-2 network door + per-deployment public URL · OQ-3 routing in scope, keyed on the recorded ownership index · OQ-4 not 1-1, link to the home channel · OQ-5 secret names as designed · OQ-6/8/9/10 dissolve under B (no relay → no streaming cadence, no Linear elicitation, no settle-edge observability, no session-lifecycle machine) · OQ-7 production, not a spike. ## Ledger-impact Adds DL-254 (webhook receiver on the network door + per-deployment URL), DL-255 (routing keyed on the recorded ownership index, never a parsed header), and DL-256 (Option-B dumb-link return path + not-1-1 topic mapping) to `docs/designs/DECISIONS.md` at freeze. Highest row on current main is DL-253; the driver re-verifies the next-free id at freeze. Spec-impact: none. Refs RIG-2717. Co-authored-by: Matt Wilkinson <matt@rigel.build>
rigel-mintaka
force-pushed
the
compass-server/rig-2717-comms-model-concept
branch
from
August 25, 2026 22:13
689cdd8 to
3ae8486
Compare
rigel-mintaka
force-pushed
the
compass-server/rig-2717-responder-design
branch
from
August 25, 2026 22:13
b0dd959 to
af39c93
Compare
Base automatically changed from
compass-server/rig-2717-comms-model-concept
to
main
August 26, 2026 02:45
mattwilkinsonn
approved these changes
Aug 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR is part of a stack containing 2 PRs:
mainProduction design record for making the installed
CompassLinear app (RIG-2682) a live Linear Agent App: receive Agent Session webhooks, route a delegated issue to the right stable Compass Manager, carry the conversation as a topic in that Manager's home channel, and link the Linear session back out to Compass.Stacked on #624 (the comms-model concept doc), which this record's premise cites.
All ten open questions were ruled by Matt on 2026-08-25 (RIG-2729); this record folds every ruling in and freezes with no live open questions.
The premise this record is built on
Matt's steer, captured in #624 and load-bearing here: Compass's comms model is deliberate, and Linear's Agent Session model is what it rejects. Compass has stable agents (Managers + peers) each with a home channel; communication rides Zulip-style threads (channel → named topics) and the agent's work stays out of the threads in a side-panel session log. Linear's Agent Session is the opposite — one ephemeral flat activity log per issue, no stable agent, no threads. So the Linear session is a doorway, not a home.
The decision — Option B (dumb link), Matt ruled RIG-2729
A hard constraint forces the mapping-depth choice: Linear's Agent Activity vocabulary is a fixed, server-validated set of five types (
thought/action/elicitation/response/error) with no extension point, so Compass's typed comms blocks (a structuredaskwith discrete options) cannot round-trip through a Linear session.created, emit onethought+ anexternalUrls"Open in Compass" deep link to the resolved Manager's home channel; all real interaction happens in Compass. Deletes the entire return relay.What the bridge does
POST /webhookshttp.Handleron the network TLS door, fail-closed HMAC-SHA256 signature check (bad/missing → 400; stale-but-valid timestamp → 200-with-drop, never a retry-burning 400), ack 200 before any async work.forge_authored_artifacts, DL-055/DL-205), never a header parsed from forge text (DL-050/DL-094 forbid that reaching a routing decision). An unstamped issue routes to the supervisor via a dedicated routing channel, which decides the lane and stamps it.@linear-authored messages on the durable deliver rail, deduped byPostAsAccount'sclient_request_idon theLinear-DeliveryUUID. The deep link targets the home channel, not the topic.createdemits (the ackthought+ the session external URL) are the whole return path. No relay, no settle observation, no session-lifecycle machine.The public base URL (webhook host + deep-link base) is per-deployment (Matt ruled OQ-2): managed =
compass.rigel.build, self-host = its own URL, dev/tailnet deploys need their own ingress.Resolved decisions (all ten OQs, Matt 2026-08-25)
OQ-1 Option B (C follow-up, A off-table) · OQ-2 network door + per-deployment public URL · OQ-3 routing in scope, keyed on the recorded ownership index · OQ-4 not 1-1, link to the home channel · OQ-5 secret names as designed · OQ-6/8/9/10 dissolve under B (no relay → no streaming cadence, no Linear elicitation, no settle-edge observability, no session-lifecycle machine) · OQ-7 production, not a spike.
Ledger-impact
Adds DL-254 (webhook receiver on the network door + per-deployment URL), DL-255 (routing keyed on the recorded ownership index, never a parsed header), and DL-256 (Option-B dumb-link return path + not-1-1 topic mapping) to
docs/designs/DECISIONS.mdat freeze. Highest row on current main is DL-253; the driver re-verifies the next-free id at freeze.Spec-impact: none.
Refs RIG-2717.
Co-authored-by: Matt Wilkinson matt@rigel.build