diff --git a/.moon/workspace.yml b/.moon/workspace.yml index 443d19b3..a61ba547 100644 --- a/.moon/workspace.yml +++ b/.moon/workspace.yml @@ -54,7 +54,7 @@ projects: # rather than the schema. stamp-gate: 'tools/stamp-gate' # The design-ledger gate: validates the Compass design-decision ledger - # (docs/designs/product/DECISIONS.md), the per-record `Status:` headers, and + # (docs/designs/DECISIONS.md), the per-record `Status:` headers, and # dangling supersession/Record pointers (SEA-1187). Migrated from the sealed # repo with the corpus it governs (SEA-1794). design-ledger-gate: 'tools/design-ledger-gate' diff --git a/docs/designs/product/DECISIONS.md b/docs/designs/DECISIONS.md similarity index 80% rename from docs/designs/product/DECISIONS.md rename to docs/designs/DECISIONS.md index 260f7bb6..c7835331 100644 --- a/docs/designs/product/DECISIONS.md +++ b/docs/designs/DECISIONS.md @@ -17,7 +17,7 @@ and flipped, never frozen. The rules that keep it honest (append-only rows, immutable `Decision` cells, the same-PR flip that a design PR owes its ledger delta) live in the design record and `AGENTS.md`; the `design-ledger-gate` CI check enforces the mechanical half. Full rationale: -[the design-ledger record](compass-design-ledger/design.md). +[the design-ledger record](product/compass-design-ledger/design.md). ## Conventions @@ -38,64 +38,64 @@ check enforces the mechanical half. Full rationale: | ID | Decision | Status | Record | | --- | --- | --- | --- | -| DL-001 | Compass is an agent development environment: named workstream agents supervised by a Dispatcher, gated by a Warden | Superseded by DL-239 (Matt, 2026-08-21) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-002 | OMP is the default/reference agent, carried as an external OSS fork; Compass builds on it, does not rebuild it | Active (Matt, 2026-07-01) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-003 | seal is scoped to hosting the Warden, not the whole runtime | Retired (Matt, 2026-08-21) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-004 | Adopt Cotal as the coordination substrate behind a thin Compass-owned seam | Superseded by DL-005 (Matt, 2026-07-04) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-005 | The NATS/JetStream substrate is kept, but Cotal moves from adopted dependency to reference implementation; comms is first-party behind a Compass seam | Superseded by DL-021 (Matt, 2026-07-04) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-006 | Upstream contribution to OMP is a distribution channel, not a governance dependency | Active (Matt, 2026-07-01) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-095 | The agent tree is Compass's organizing primitive — Compass is a tool to build and manage agent trees: `AgentAccount` carries `parent_agent_id` (field 4; empty = root, set at creation — the spawning agent, or user choice — and editable thereafter via a `ReparentAgent` mutation, so users iterate hierarchy without teardown), the workspaces sidebar and board views derive from and filter by the tree, REPLACING the user-defined folder organization (replace, not coexist); channels (SEA-1622) and roles (SEA-1623) compose onto the tree later | Active (Matt, 2026-08-01) | [agent trees §Approach](compass-agent-trees/design.md#approach) | -| DL-239 | Compass is an agent development environment: named workstream agents supervised by a Dispatcher (the corrected ADE core definition — the Warden security-auditor concept of DL-001 is scrapped, so the gate-by-a-Warden clause is dropped; the ADE, named-workstream-agents, and Dispatcher legs stand) | Active (Matt, 2026-08-21) | [architecture lineage](compass-architecture-lineage/design.md) | +| DL-001 | Compass is an agent development environment: named workstream agents supervised by a Dispatcher, gated by a Warden | Superseded by DL-239 (Matt, 2026-08-21) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-002 | OMP is the default/reference agent, carried as an external OSS fork; Compass builds on it, does not rebuild it | Active (Matt, 2026-07-01) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-003 | seal is scoped to hosting the Warden, not the whole runtime | Retired (Matt, 2026-08-21) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-004 | Adopt Cotal as the coordination substrate behind a thin Compass-owned seam | Superseded by DL-005 (Matt, 2026-07-04) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-005 | The NATS/JetStream substrate is kept, but Cotal moves from adopted dependency to reference implementation; comms is first-party behind a Compass seam | Superseded by DL-021 (Matt, 2026-07-04) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-006 | Upstream contribution to OMP is a distribution channel, not a governance dependency | Active (Matt, 2026-07-01) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-095 | The agent tree is Compass's organizing primitive — Compass is a tool to build and manage agent trees: `AgentAccount` carries `parent_agent_id` (field 4; empty = root, set at creation — the spawning agent, or user choice — and editable thereafter via a `ReparentAgent` mutation, so users iterate hierarchy without teardown), the workspaces sidebar and board views derive from and filter by the tree, REPLACING the user-defined folder organization (replace, not coexist); channels (SEA-1622) and roles (SEA-1623) compose onto the tree later | Active (Matt, 2026-08-01) | [agent trees §Approach](product/compass-agent-trees/design.md#approach) | +| DL-239 | Compass is an agent development environment: named workstream agents supervised by a Dispatcher (the corrected ADE core definition — the Warden security-auditor concept of DL-001 is scrapped, so the gate-by-a-Warden clause is dropped; the ADE, named-workstream-agents, and Dispatcher legs stand) | Active (Matt, 2026-08-21) | [architecture lineage](product/compass-architecture-lineage/design.md) | ## Topology & tiers | ID | Decision | Status | Record | | --- | --- | --- | --- | -| DL-007 | Architecture is three tiers: Client → Server → Runner, with the communication layer as the spine | Active (Matt, 2026-07-04) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-008 | Evolve `compass.v1` from a local daemon contract into the Client↔Server contract (multi-user) | Active (Matt, 2026-07-04) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-009 | The Server tier realizes the reserved hosted-mode transport seam | Active (Matt, 2026-07-04) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-010 | Multi-agent orchestration (Supervisor + Bridge) is in the MVP; single-agent is the first build increment | Active (Matt, 2026-07-04) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-011 | The Server tier is built by promoting `compass-daemon` in place, not a new server crate | Active (Matt, 2026-07-08) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-012 | The authenticated network door is rustls-via-tonic TLS + bearer-token accounts (in-memory token store for T2) | Active (Matt, 2026-07-08) | [architecture lineage](compass-architecture-lineage/design.md) | +| DL-007 | Architecture is three tiers: Client → Server → Runner, with the communication layer as the spine | Active (Matt, 2026-07-04) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-008 | Evolve `compass.v1` from a local daemon contract into the Client↔Server contract (multi-user) | Active (Matt, 2026-07-04) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-009 | The Server tier realizes the reserved hosted-mode transport seam | Active (Matt, 2026-07-04) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-010 | Multi-agent orchestration (Supervisor + Bridge) is in the MVP; single-agent is the first build increment | Active (Matt, 2026-07-04) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-011 | The Server tier is built by promoting `compass-daemon` in place, not a new server crate | Active (Matt, 2026-07-08) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-012 | The authenticated network door is rustls-via-tonic TLS + bearer-token accounts (in-memory token store for T2) | Active (Matt, 2026-07-08) | [architecture lineage](product/compass-architecture-lineage/design.md) | ## Transport | ID | Decision | Status | Record | | --- | --- | --- | --- | -| DL-013 | Transport is gRPC everywhere (Client↔Server and Runner↔Server), authenticated by per-Runner provisioned tokens | Active (Matt, 2026-07-06) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-014 | NATS/JetStream is not a Client/Runner-facing transport; it is comms-internal only | Active (Matt, 2026-07-06) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-015 | The in-container agent talks to the Runner alone (Runner-sole topology), off stdio, over a `RunnerCallTransport` seam | Active (Matt, 2026-07-21) | [agent↔Runner transport §Decisions](compass-agent-runner-transport/design.md#decisions-frozen-by-matt--not-reopened-below) | -| DL-016 | The concrete agent↔Runner transport is a per-container Unix socket, 1:1 with a session; network transport is a future additive | Superseded by DL-017 (Matt, 2026-07-21) | [agent↔Runner transport §The concrete impl](compass-agent-runner-transport/design.md#the-concrete-impl-unix-socket-per-container) | -| DL-017 | Consolidate agent↔Runner onto socket streams: telemetry via `Publish` client-stream, control via `Control` server-stream on `AgentGateway`; retire the protocol stdio pipe | Active (Matt, 2026-07-22) | [transport consolidation §What is superseded](compass-agent-transport-consolidation/design.md#what-is-superseded-exactly) | -| DL-018 | The frozen `RunnerService` transport recommendation #2 is socket-only, superseding the earlier off-stdio carrier clause | Active (Matt, 2026-07-22) | [agent comms tools §The frozen transport](compass-agent-comms-tools/design.md#the-frozen-transport-this-rides-was-the-keystone-fork-now-decided) | +| DL-013 | Transport is gRPC everywhere (Client↔Server and Runner↔Server), authenticated by per-Runner provisioned tokens | Active (Matt, 2026-07-06) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-014 | NATS/JetStream is not a Client/Runner-facing transport; it is comms-internal only | Active (Matt, 2026-07-06) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-015 | The in-container agent talks to the Runner alone (Runner-sole topology), off stdio, over a `RunnerCallTransport` seam | Active (Matt, 2026-07-21) | [agent↔Runner transport §Decisions](product/compass-agent-runner-transport/design.md#decisions-frozen-by-matt--not-reopened-below) | +| DL-016 | The concrete agent↔Runner transport is a per-container Unix socket, 1:1 with a session; network transport is a future additive | Superseded by DL-017 (Matt, 2026-07-21) | [agent↔Runner transport §The concrete impl](product/compass-agent-runner-transport/design.md#the-concrete-impl-unix-socket-per-container) | +| DL-017 | Consolidate agent↔Runner onto socket streams: telemetry via `Publish` client-stream, control via `Control` server-stream on `AgentGateway`; retire the protocol stdio pipe | Active (Matt, 2026-07-22) | [transport consolidation §What is superseded](product/compass-agent-transport-consolidation/design.md#what-is-superseded-exactly) | +| DL-018 | The frozen `RunnerService` transport recommendation #2 is socket-only, superseding the earlier off-stdio carrier clause | Active (Matt, 2026-07-22) | [agent comms tools §The frozen transport](product/compass-agent-comms-tools/design.md#the-frozen-transport-this-rides-was-the-keystone-fork-now-decided) | ## Storage | ID | Decision | Status | Record | | --- | --- | --- | --- | -| DL-019 | Postgres is the store of record; transcript bodies live in object storage behind a blob seam; JetStream is comms-only | Active (Matt, 2026-07-04) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-020 | Postgres is the substrate and is not swappable; the in-memory event bus is a cache/fan-out ring, not a second store | Active (Matt, 2026-07-06) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-021 | The comms substrate is Postgres write-through fan-out, not a swappable NATS-backed seam | Active (Matt, 2026-07-06) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-022 | Config distribution is a Runner-mediated pull into a read-only mount; agent binary + base image ride versioned OCI pulls | Active (Matt, 2026-07-04) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-052 | Only the Server holds forge write credentials, as a `server_only` declared secret filtered out of container injection — a NEW scoping mechanism this record introduces, since none exists in the tree. The agent keeps a push-scoped git credential. The boundary that creates is half enforced (the filter, which Compass controls and tests) and half operator hygiene (the agent token's scope, which Compass neither mints nor inspects); closing the second half would require Compass to hold secret values, which today it deliberately never does | Active (Matt, 2026-07-27) | [ownership layer §Decision 4](compass-server-ownership-layer/design.md#decision-4--the-servers-forge-credential-is-a-declared-secret-resolved-not-stored) | -| DL-053 | Forge subscriptions are Server-side Postgres rows with a per-artifact FETCH cursor (advanced on any 200) split from a per-subscriber DELIVERY cursor (advanced only on that subscriber's own successful notify), change-detected by conditional polling in v1 (webhooks are an additive accelerator), delivered by account on the existing `Sessions` → `AgentGateway.Control` push path | Active (Matt, 2026-07-27) | [ownership layer §Decision 5](compass-server-ownership-layer/design.md#decision-5--subscriptions-server-stored-poll-based-in-v1-delivered-on-the-existing-push-path) | -| DL-055 | Compass stores a row per artifact it authored (coordinate + agent + owner + session, written with the stamp), so agent ownership queries and the Bridge boards are local index scans over Server-recorded truth rather than forge-wide searches of untrusted header text; it is an ownership index, never a mirror of forge content | Active (Matt, 2026-07-27) | [ownership layer §OQ-8](compass-server-ownership-layer/design.md#oq-8-ruled-2026-07-27-matt--recommendation-reversed--does-a-compass-authored-artifact-need-a-compass-side-record) | -| DL-063 | Agent session transcripts persist to S3 for v1 via an ENDPOINT-AGNOSTIC backend (`COMPASS_S3_ENDPOINT`, generic `Bun.S3Client`, no S3-server-specific calls), reached under default-deny egress via an allowlisted endpoint — the S3 client path is exercised from v1, never a swap-later local-fs abstraction. Solo/self-host backend is a local-filesystem Garage (≥ v2.3.0) per Runner host, granting a full-bucket credential (cross-agent read/tamper accepted only within the single-trust-domain MVP); real/multi-user deployments MUST NOT use the Garage full-bucket credential — they use Cloudflare R2 with prefix-scoped tokens, which is a CONFIG change not a new build (endpoint-agnostic). Docs advisory + hardening follow-up ("R2 + prefix-scoped tokens for real deployments") stated; no bucket-per-agent, no Runner signing proxy | Superseded by DL-084 (Matt, 2026-07-31) | [session persistence §Appendix](compass-agent-session-persistence/design.md#appendix--superseded-by-the-reversal-2026-07-31-the-agent-direct-s3-model) | -| DL-064 | The agent persists its transcript DIRECTLY from inside the container as the session runs: a Compass-owned S3 `SessionStorageBackend` wrapped in the SDK's `IndexedSessionStorage`, injected at the cli.ts composition root via `createAgentSession({ sessionManager })`; no runner-ships-the-log-after-teardown step exists. The persist model is a SEGMENTED PER-EPOCH LOG — a stable `session_id` keys the prefix `sessions//` and each container lifetime appends only to its own `.jsonl` segment (continuous per-append full-object PUT of that one segment + terminal drain); reconstruction is an S3 LIST of the prefix reconstructed in ascending epoch order with title-slot CHECKPOINT SUPERSESSION — a segment whose first line parses as a title slot is a full-body-rewrite snapshot that supersedes prior epochs (readFull resets its accumulator to it), so SDK-internal compaction rewrites do not double-count (readFull=LIST+reconstruct vs append=single-current-segment asymmetry). Fresh opens `<0>.jsonl` via `SessionManager.open`; resume opens the PRIOR latest existing epoch key (context is seeded by the backend readFull=LIST+reconstruct on that existing, indexed key) then repoints the write target to a fresh `.jsonl` via the public `captureState`/`restoreState` seams (`session-manager.ts:919/939`, `onDisk:true, needsRewrite:false`), so appends land only in the new segment and prior segments stay immutable — NO SDK patch | Superseded by DL-085 (Matt, 2026-07-31) | [session persistence §Appendix](compass-agent-session-persistence/design.md#appendix--superseded-by-the-reversal-2026-07-31-the-agent-direct-s3-model) | -| DL-065 | A Postgres pointer row (`agent_session_transcripts`: stable logical session_id PK → bucket + key PREFIX + a nullable `endpoint` provenance column, FK-rooted in the post-0004 `agent_sessions`) indexes each stored log; resume reuses `StartAgentSession` with an additive authz-gated `resume_session_id` on the PUBLIC request, and the resolved pointer rides a NEW top-level `ResumeContext resume = 12` on the INTERNAL `SessionsResponse` (outside the command oneof, tag 2 untouched — additive, non-forgeable) so a client-set pointer can never reach the Runner (the public request is relayed verbatim). The new container reconstructs one logical log from the prefix and the built replay barrier gates live input (`ReplayComplete` alone lifts it — no TranscriptReplay frames on the resume path) | Superseded by DL-084 (Matt, 2026-07-31) | [session persistence §Appendix](compass-agent-session-persistence/design.md#appendix--superseded-by-the-reversal-2026-07-31-the-agent-direct-s3-model) | -| DL-066 | The `TranscriptReplay` payload shape (`agent_message_json` + index/total) is a PROPOSAL handed to SEA-1310, which compass owns; this record does not freeze it and does not depend on it. The handoff MUST carry a replay-path admission/size bound, because defining the payload turns the replay path into an admission path the retention cap exempts today (control.go:546-560) | Superseded by DL-086 (Matt, 2026-07-31) | [session persistence §Appendix](compass-agent-session-persistence/design.md#appendix--superseded-by-the-reversal-2026-07-31-the-agent-direct-s3-model) | -| DL-082 | Writer fencing for session-log persistence is force-teardown of the old container (PRIMARY fence) plus a per-container-lifetime epoch token in the object key (`sessions//.jsonl`, BELT): force-teardown removes the zombie writer in the normal case, and the epoch guarantees a zombie from a crashed lifetime a Runner could not confirm torn down can only clobber its OWN dead epoch segment, never erase another lifetime's segment | Superseded by DL-085 (Matt, 2026-07-31) | [session persistence §Appendix](compass-agent-session-persistence/design.md#appendix--superseded-by-the-reversal-2026-07-31-the-agent-direct-s3-model) | -| DL-083 | Session-transcript credential/storage posture: a full-bucket S3 credential is acceptable for solo/self-host v1 (Garage, single trust domain) despite the stated cross-agent read/tamper threat; real/multi-user deployments use Cloudflare R2 with prefix-scoped tokens so each agent is confined to its own `sessions//` prefix. The S3 backend is endpoint-agnostic via `COMPASS_S3_ENDPOINT` (generic `Bun.S3Client`), so the hardening is config not a new build; the threat is stated and a hardening follow-up is filed | Superseded by DL-084 (Matt, 2026-07-31) | [session persistence §Appendix](compass-agent-session-persistence/design.md#appendix--superseded-by-the-reversal-2026-07-31-the-agent-direct-s3-model) | -| DL-084 | The Server owns durable session-transcript storage: a Postgres transcript-entry store (`agent_session_transcript_entries`: (session_id, entry_seq) PK, UNIQUE idempotency_key, checkpoint flag, FK `agent_sessions`) persisted on receipt of durable `TranscriptEntry` frames at the `CommitConversationFrame` at-most-once commit seam, with CHECKPOINT SUPERSESSION server-side (the read view is latest checkpoint + later deltas — the old read-side reconstruction rule relocated to the one owner that reads). Storage backend choice and credential posture are Server-internal; the agent and Runner hold zero storage detail, zero S3 credentials | Superseded by DL-093 (Matt, 2026-07-31) | [session persistence §Whole bodies in Postgres — rejected](compass-agent-session-persistence/design.md#whole-transcript-bodies-as-permanent-postgres-rows--rejected-the-dl-084-model) | -| DL-085 | The agent persists nothing: an injected emit-backend on the SDK `createAgentSession({ sessionManager })` seam turns every committed session entry into a durable `TranscriptEntry` AgentFrame variant (entry_json verbatim, checkpoint discriminator for SDK full-body rewrites, agent-stamped entry_seq) on the delivered-or-erred, idempotency-keyed PostConversationFrame lane — awaited per-path for per-session send order; the local SessionManager is ephemeral and dies with the container. Writer fencing is force-teardown (primary) + the durable lane's idempotency keys and entry_seq (belt); the S3 epoch-token fence is retired with the object model | Superseded by DL-089 (Matt, 2026-07-31) | [session persistence §Appendix (collapse)](compass-agent-session-persistence/design.md#appendix--superseded-by-the-collapse-2026-07-31-the-control-lane-replay-resume-model) | -| DL-086 | Resume is replay-driven: `StartAgentSession{resume_session_id}` (authz-gated, no storage locator on any message) makes the Server push its persisted transcript down the existing `SessionsResponse.deliver_control`/`DispatchControl` relay as `TranscriptReplay` ops consumed by `appendMessage`, gated by the Runner replay barrier until `ReplayComplete`/`ReplayCompleteAck`; the `TranscriptReplay` + `TranscriptEntry` payload shapes are co-ratified with SEA-1310 and BLOCK resume (inverting DL-066's independence), and the replay-path admission bound is in-scope, enforced at the retention-cap site on the SEA-1569 RESOURCE_EXHAUSTED refuse-and-redeliver model | Superseded by DL-087 (Matt, 2026-07-31) | [session persistence §Appendix (collapse)](compass-agent-session-persistence/design.md#appendix--superseded-by-the-collapse-2026-07-31-the-control-lane-replay-resume-model) | -| DL-087 | Resume is file-materialized + SDK-native: on `StartAgentSession{resume_session_id}` (authz-gated, no storage locator on any message) the Server reconstructs the post-supersession session-JSONL body from its transcript store (latest checkpoint body verbatim + later delta lines) and hands it to the Runner on a TOP-LEVEL internal `SessionsResponse` sibling field (outside the `command` oneof, NOT inside the verbatim public `start` request); the Runner writes it into the new container's session dir at PROVISION time via the provision-exec family, before the agent is exec'd; the agent loads it through the SDK's own `setSessionFile`/`loadEntriesFromFile` seam. No control-lane replay, no `TranscriptReplay` payload, no replay barrier or admission bound, and no SEA-1310 dependency — the co-ratification is retracted (peer-contract relief). Inline-image blobs are out of MVP scope (SEA-1582). | Active (Matt, 2026-07-31) | [session persistence §Appendix (collapse)](compass-agent-session-persistence/design.md#t5-compass-server--the-resume-body-reconstructor) | -| DL-088 | The durable session log and the live client trace are two projections of ONE canonical artifact — the SDK session-entry log: the agent emits committed entries, the Server persists them AND projects the block-level trace from the same store. MVP runs two agent→server streams (durable settled-entry log + ephemeral, non-persisted live per-token trace — token streaming is mandatory); collapsing them into one token stream carrying log metadata is the post-MVP follow-up SEA-1580 | Active (Matt, 2026-07-31) | [session persistence §One canonical artifact](compass-agent-session-persistence/design.md#one-canonical-artifact-the-session-log-unified-with-the-trace-r1) | -| DL-089 | The agent persists nothing DURABLE: the injected backend is a TEE — it reads and writes the container-local EPHEMERAL session file normally (so the SDK's own loader, compaction, and rewrites work) and tees each committed write upstream as a durable `TranscriptEntry` frame (append→delta, writeFull→checkpoint, awaited per-path for per-session send order; agent-stamped per-lifetime entry_seq, server-rebased to session scope). Zero S3 credentials, zero storage detail; the local file dies with the container. A definitively-erred emit buffers under a bounded cap with escalating warn→error retry and FAILS THE SESSION at cap exhaustion (resumable from the last committed prefix; cap value is tuning, not freeze-scope) | Active (Matt, 2026-07-31) | [session persistence §The SDK seam](compass-agent-session-persistence/design.md#the-sdk-seam-grounded-revised-for-the-tee) | -| DL-093 | The Server's durable session-transcript store is TWO-TIER: a Postgres hot-tail (`agent_session_transcript_entries`) holding `[latest checkpoint..now]` = the resume set, per-frame durable at the `CommitConversationFrame` seam and pruned at flush; superseded entries flush to an S3-compatible object-store cold archive (verbatim JSONL segments, PUT-before-prune, indexed by an `agent_session_archive_segments` manifest) at compaction (primary), a high size-cap safety valve, and session-end. Resume reads PG-only (S3 fallback only when the safety valve fired); the archive feeds the post-MVP opt-in analytics layer. Agent+Runner hold zero storage detail; the object-store client/credential is Server-internal (endpoint-agnostic: Garage/R2/MinIO). Realigns with DL-019 | Active (Matt, 2026-07-31) | [session persistence §T4](compass-agent-session-persistence/design.md#t4-compass-server--the-two-tier-durable-transcript-store-pg-hot-tail--object-store-cold-archive) | -| DL-161 | The board-ingestion forge poll is a ctx-cancellable driver in `internal/ingest` (immediate first pass then `time.Ticker`, sequential per-repo, log-and-continue on per-repo error, `nil` on ctx cancel) that instantiates the DL-053 FETCH-cursor model at repo-LIST granularity: a new `forge_list_cursors` table (per `(provider, host, repo, page)` ETag + hasNext) whose page cursor advances ONLY after every issue on that page durably sinks, so the board holds no per-subscriber DELIVERY cursor (its notify is the synchronous in-pass projection sink). One hand-rolled `net/http` GitHub read client (OQ-6 frozen: no new dep), a fail-fast `x-ratelimit-*` budget gate (never in-client sleep), and a DL-052 `server_only` token resolved behind a short TTL. Builds the FETCH half of DL-053; PR-C (DL-129 tracker-status) and the agent-notification slice both ride it | Active (Matt, 2026-08-08) | [forge-poll driver §Approach](compass-forge-poll-driver/design.md#approach) | -| DL-162 | The board's poll targets are durable TABLE rows, not config: a new `forge_repo_subscriptions` table keyed `(forge_provider, forge_host, repo)` with an `enabled` soft-disable flag, enumerated `WHERE enabled` at the top of every pass so add/remove is a live row op needing no restart or deploy. The `--forge-repos` CLI flag becomes a declarative boot SEED reconciled into the table `ON CONFLICT DO NOTHING` (bootstrap-only insert: the table is authoritative after first insert, a soft-disabled row stays disabled across restarts, the seed never deletes/disables/re-enables an existing row); a `--forge-poll` bool runs the driver with an empty seed. The dynamic add/remove mutation RPC/admin surface is a named non-goal of this slice | Active (Matt, 2026-08-08) | [forge-poll driver §OQ-C](compass-forge-poll-driver/design.md#oq-c--resolved-matt-2026-08-08-the-boards-subscription-set-is-a-table) | -| DL-163 | Migration `0015_forge_subscriptions.sql` lands FOUR tables unconditionally — `forge_repo_subscriptions` (DL-162), `forge_list_cursors` (DL-161), and the two DL-053-spec'd tables `agent_forge_subscriptions` (DL-053's `forge_subscriptions`, RENAMED to disambiguate the per-artifact agent-owned subscription from the board's per-repo target) and `forge_artifact_cursors` (both writer-less this slice, shape frozen + pgtest-covered before their writers) — every key coordinate-aligned to the 0013 issue convention (SMALLINT provider + `forge_host`) and every provider CHECK admitting the full declared proto enum `IN (1, 2, 3, 4)` (the CHECK's job is "never UNSPECIFIED(0)", not gating rollout; rollout is gated by which `forge.Provider` has a real client — GitHub only this slice). The `issues` CHECK `IN (1, 2, 3)` widening for Linear ingestion is a separate future-slice prerequisite (OQ-E) | Active (Matt, 2026-08-08) | [forge-poll driver §OQ-D](compass-forge-poll-driver/design.md#oq-d--resolved-matt-2026-08-08-all-four-tables-land-now-checks-admit-the-full-enum) | +| DL-019 | Postgres is the store of record; transcript bodies live in object storage behind a blob seam; JetStream is comms-only | Active (Matt, 2026-07-04) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-020 | Postgres is the substrate and is not swappable; the in-memory event bus is a cache/fan-out ring, not a second store | Active (Matt, 2026-07-06) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-021 | The comms substrate is Postgres write-through fan-out, not a swappable NATS-backed seam | Active (Matt, 2026-07-06) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-022 | Config distribution is a Runner-mediated pull into a read-only mount; agent binary + base image ride versioned OCI pulls | Active (Matt, 2026-07-04) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-052 | Only the Server holds forge write credentials, as a `server_only` declared secret filtered out of container injection — a NEW scoping mechanism this record introduces, since none exists in the tree. The agent keeps a push-scoped git credential. The boundary that creates is half enforced (the filter, which Compass controls and tests) and half operator hygiene (the agent token's scope, which Compass neither mints nor inspects); closing the second half would require Compass to hold secret values, which today it deliberately never does | Active (Matt, 2026-07-27) | [ownership layer §Decision 4](product/compass-server-ownership-layer/design.md#decision-4--the-servers-forge-credential-is-a-declared-secret-resolved-not-stored) | +| DL-053 | Forge subscriptions are Server-side Postgres rows with a per-artifact FETCH cursor (advanced on any 200) split from a per-subscriber DELIVERY cursor (advanced only on that subscriber's own successful notify), change-detected by conditional polling in v1 (webhooks are an additive accelerator), delivered by account on the existing `Sessions` → `AgentGateway.Control` push path | Active (Matt, 2026-07-27) | [ownership layer §Decision 5](product/compass-server-ownership-layer/design.md#decision-5--subscriptions-server-stored-poll-based-in-v1-delivered-on-the-existing-push-path) | +| DL-055 | Compass stores a row per artifact it authored (coordinate + agent + owner + session, written with the stamp), so agent ownership queries and the Bridge boards are local index scans over Server-recorded truth rather than forge-wide searches of untrusted header text; it is an ownership index, never a mirror of forge content | Active (Matt, 2026-07-27) | [ownership layer §OQ-8](product/compass-server-ownership-layer/design.md#oq-8-ruled-2026-07-27-matt--recommendation-reversed--does-a-compass-authored-artifact-need-a-compass-side-record) | +| DL-063 | Agent session transcripts persist to S3 for v1 via an ENDPOINT-AGNOSTIC backend (`COMPASS_S3_ENDPOINT`, generic `Bun.S3Client`, no S3-server-specific calls), reached under default-deny egress via an allowlisted endpoint — the S3 client path is exercised from v1, never a swap-later local-fs abstraction. Solo/self-host backend is a local-filesystem Garage (≥ v2.3.0) per Runner host, granting a full-bucket credential (cross-agent read/tamper accepted only within the single-trust-domain MVP); real/multi-user deployments MUST NOT use the Garage full-bucket credential — they use Cloudflare R2 with prefix-scoped tokens, which is a CONFIG change not a new build (endpoint-agnostic). Docs advisory + hardening follow-up ("R2 + prefix-scoped tokens for real deployments") stated; no bucket-per-agent, no Runner signing proxy | Superseded by DL-084 (Matt, 2026-07-31) | [session persistence §Appendix](product/compass-agent-session-persistence/design.md#appendix--superseded-by-the-reversal-2026-07-31-the-agent-direct-s3-model) | +| DL-064 | The agent persists its transcript DIRECTLY from inside the container as the session runs: a Compass-owned S3 `SessionStorageBackend` wrapped in the SDK's `IndexedSessionStorage`, injected at the cli.ts composition root via `createAgentSession({ sessionManager })`; no runner-ships-the-log-after-teardown step exists. The persist model is a SEGMENTED PER-EPOCH LOG — a stable `session_id` keys the prefix `sessions//` and each container lifetime appends only to its own `.jsonl` segment (continuous per-append full-object PUT of that one segment + terminal drain); reconstruction is an S3 LIST of the prefix reconstructed in ascending epoch order with title-slot CHECKPOINT SUPERSESSION — a segment whose first line parses as a title slot is a full-body-rewrite snapshot that supersedes prior epochs (readFull resets its accumulator to it), so SDK-internal compaction rewrites do not double-count (readFull=LIST+reconstruct vs append=single-current-segment asymmetry). Fresh opens `<0>.jsonl` via `SessionManager.open`; resume opens the PRIOR latest existing epoch key (context is seeded by the backend readFull=LIST+reconstruct on that existing, indexed key) then repoints the write target to a fresh `.jsonl` via the public `captureState`/`restoreState` seams (`session-manager.ts:919/939`, `onDisk:true, needsRewrite:false`), so appends land only in the new segment and prior segments stay immutable — NO SDK patch | Superseded by DL-085 (Matt, 2026-07-31) | [session persistence §Appendix](product/compass-agent-session-persistence/design.md#appendix--superseded-by-the-reversal-2026-07-31-the-agent-direct-s3-model) | +| DL-065 | A Postgres pointer row (`agent_session_transcripts`: stable logical session_id PK → bucket + key PREFIX + a nullable `endpoint` provenance column, FK-rooted in the post-0004 `agent_sessions`) indexes each stored log; resume reuses `StartAgentSession` with an additive authz-gated `resume_session_id` on the PUBLIC request, and the resolved pointer rides a NEW top-level `ResumeContext resume = 12` on the INTERNAL `SessionsResponse` (outside the command oneof, tag 2 untouched — additive, non-forgeable) so a client-set pointer can never reach the Runner (the public request is relayed verbatim). The new container reconstructs one logical log from the prefix and the built replay barrier gates live input (`ReplayComplete` alone lifts it — no TranscriptReplay frames on the resume path) | Superseded by DL-084 (Matt, 2026-07-31) | [session persistence §Appendix](product/compass-agent-session-persistence/design.md#appendix--superseded-by-the-reversal-2026-07-31-the-agent-direct-s3-model) | +| DL-066 | The `TranscriptReplay` payload shape (`agent_message_json` + index/total) is a PROPOSAL handed to SEA-1310, which compass owns; this record does not freeze it and does not depend on it. The handoff MUST carry a replay-path admission/size bound, because defining the payload turns the replay path into an admission path the retention cap exempts today (control.go:546-560) | Superseded by DL-086 (Matt, 2026-07-31) | [session persistence §Appendix](product/compass-agent-session-persistence/design.md#appendix--superseded-by-the-reversal-2026-07-31-the-agent-direct-s3-model) | +| DL-082 | Writer fencing for session-log persistence is force-teardown of the old container (PRIMARY fence) plus a per-container-lifetime epoch token in the object key (`sessions//.jsonl`, BELT): force-teardown removes the zombie writer in the normal case, and the epoch guarantees a zombie from a crashed lifetime a Runner could not confirm torn down can only clobber its OWN dead epoch segment, never erase another lifetime's segment | Superseded by DL-085 (Matt, 2026-07-31) | [session persistence §Appendix](product/compass-agent-session-persistence/design.md#appendix--superseded-by-the-reversal-2026-07-31-the-agent-direct-s3-model) | +| DL-083 | Session-transcript credential/storage posture: a full-bucket S3 credential is acceptable for solo/self-host v1 (Garage, single trust domain) despite the stated cross-agent read/tamper threat; real/multi-user deployments use Cloudflare R2 with prefix-scoped tokens so each agent is confined to its own `sessions//` prefix. The S3 backend is endpoint-agnostic via `COMPASS_S3_ENDPOINT` (generic `Bun.S3Client`), so the hardening is config not a new build; the threat is stated and a hardening follow-up is filed | Superseded by DL-084 (Matt, 2026-07-31) | [session persistence §Appendix](product/compass-agent-session-persistence/design.md#appendix--superseded-by-the-reversal-2026-07-31-the-agent-direct-s3-model) | +| DL-084 | The Server owns durable session-transcript storage: a Postgres transcript-entry store (`agent_session_transcript_entries`: (session_id, entry_seq) PK, UNIQUE idempotency_key, checkpoint flag, FK `agent_sessions`) persisted on receipt of durable `TranscriptEntry` frames at the `CommitConversationFrame` at-most-once commit seam, with CHECKPOINT SUPERSESSION server-side (the read view is latest checkpoint + later deltas — the old read-side reconstruction rule relocated to the one owner that reads). Storage backend choice and credential posture are Server-internal; the agent and Runner hold zero storage detail, zero S3 credentials | Superseded by DL-093 (Matt, 2026-07-31) | [session persistence §Whole bodies in Postgres — rejected](product/compass-agent-session-persistence/design.md#whole-transcript-bodies-as-permanent-postgres-rows--rejected-the-dl-084-model) | +| DL-085 | The agent persists nothing: an injected emit-backend on the SDK `createAgentSession({ sessionManager })` seam turns every committed session entry into a durable `TranscriptEntry` AgentFrame variant (entry_json verbatim, checkpoint discriminator for SDK full-body rewrites, agent-stamped entry_seq) on the delivered-or-erred, idempotency-keyed PostConversationFrame lane — awaited per-path for per-session send order; the local SessionManager is ephemeral and dies with the container. Writer fencing is force-teardown (primary) + the durable lane's idempotency keys and entry_seq (belt); the S3 epoch-token fence is retired with the object model | Superseded by DL-089 (Matt, 2026-07-31) | [session persistence §Appendix (collapse)](product/compass-agent-session-persistence/design.md#appendix--superseded-by-the-collapse-2026-07-31-the-control-lane-replay-resume-model) | +| DL-086 | Resume is replay-driven: `StartAgentSession{resume_session_id}` (authz-gated, no storage locator on any message) makes the Server push its persisted transcript down the existing `SessionsResponse.deliver_control`/`DispatchControl` relay as `TranscriptReplay` ops consumed by `appendMessage`, gated by the Runner replay barrier until `ReplayComplete`/`ReplayCompleteAck`; the `TranscriptReplay` + `TranscriptEntry` payload shapes are co-ratified with SEA-1310 and BLOCK resume (inverting DL-066's independence), and the replay-path admission bound is in-scope, enforced at the retention-cap site on the SEA-1569 RESOURCE_EXHAUSTED refuse-and-redeliver model | Superseded by DL-087 (Matt, 2026-07-31) | [session persistence §Appendix (collapse)](product/compass-agent-session-persistence/design.md#appendix--superseded-by-the-collapse-2026-07-31-the-control-lane-replay-resume-model) | +| DL-087 | Resume is file-materialized + SDK-native: on `StartAgentSession{resume_session_id}` (authz-gated, no storage locator on any message) the Server reconstructs the post-supersession session-JSONL body from its transcript store (latest checkpoint body verbatim + later delta lines) and hands it to the Runner on a TOP-LEVEL internal `SessionsResponse` sibling field (outside the `command` oneof, NOT inside the verbatim public `start` request); the Runner writes it into the new container's session dir at PROVISION time via the provision-exec family, before the agent is exec'd; the agent loads it through the SDK's own `setSessionFile`/`loadEntriesFromFile` seam. No control-lane replay, no `TranscriptReplay` payload, no replay barrier or admission bound, and no SEA-1310 dependency — the co-ratification is retracted (peer-contract relief). Inline-image blobs are out of MVP scope (SEA-1582). | Active (Matt, 2026-07-31) | [session persistence §Appendix (collapse)](product/compass-agent-session-persistence/design.md#t5-compass-server--the-resume-body-reconstructor) | +| DL-088 | The durable session log and the live client trace are two projections of ONE canonical artifact — the SDK session-entry log: the agent emits committed entries, the Server persists them AND projects the block-level trace from the same store. MVP runs two agent→server streams (durable settled-entry log + ephemeral, non-persisted live per-token trace — token streaming is mandatory); collapsing them into one token stream carrying log metadata is the post-MVP follow-up SEA-1580 | Active (Matt, 2026-07-31) | [session persistence §One canonical artifact](product/compass-agent-session-persistence/design.md#one-canonical-artifact-the-session-log-unified-with-the-trace-r1) | +| DL-089 | The agent persists nothing DURABLE: the injected backend is a TEE — it reads and writes the container-local EPHEMERAL session file normally (so the SDK's own loader, compaction, and rewrites work) and tees each committed write upstream as a durable `TranscriptEntry` frame (append→delta, writeFull→checkpoint, awaited per-path for per-session send order; agent-stamped per-lifetime entry_seq, server-rebased to session scope). Zero S3 credentials, zero storage detail; the local file dies with the container. A definitively-erred emit buffers under a bounded cap with escalating warn→error retry and FAILS THE SESSION at cap exhaustion (resumable from the last committed prefix; cap value is tuning, not freeze-scope) | Active (Matt, 2026-07-31) | [session persistence §The SDK seam](product/compass-agent-session-persistence/design.md#the-sdk-seam-grounded-revised-for-the-tee) | +| DL-093 | The Server's durable session-transcript store is TWO-TIER: a Postgres hot-tail (`agent_session_transcript_entries`) holding `[latest checkpoint..now]` = the resume set, per-frame durable at the `CommitConversationFrame` seam and pruned at flush; superseded entries flush to an S3-compatible object-store cold archive (verbatim JSONL segments, PUT-before-prune, indexed by an `agent_session_archive_segments` manifest) at compaction (primary), a high size-cap safety valve, and session-end. Resume reads PG-only (S3 fallback only when the safety valve fired); the archive feeds the post-MVP opt-in analytics layer. Agent+Runner hold zero storage detail; the object-store client/credential is Server-internal (endpoint-agnostic: Garage/R2/MinIO). Realigns with DL-019 | Active (Matt, 2026-07-31) | [session persistence §T4](product/compass-agent-session-persistence/design.md#t4-compass-server--the-two-tier-durable-transcript-store-pg-hot-tail--object-store-cold-archive) | +| DL-161 | The board-ingestion forge poll is a ctx-cancellable driver in `internal/ingest` (immediate first pass then `time.Ticker`, sequential per-repo, log-and-continue on per-repo error, `nil` on ctx cancel) that instantiates the DL-053 FETCH-cursor model at repo-LIST granularity: a new `forge_list_cursors` table (per `(provider, host, repo, page)` ETag + hasNext) whose page cursor advances ONLY after every issue on that page durably sinks, so the board holds no per-subscriber DELIVERY cursor (its notify is the synchronous in-pass projection sink). One hand-rolled `net/http` GitHub read client (OQ-6 frozen: no new dep), a fail-fast `x-ratelimit-*` budget gate (never in-client sleep), and a DL-052 `server_only` token resolved behind a short TTL. Builds the FETCH half of DL-053; PR-C (DL-129 tracker-status) and the agent-notification slice both ride it | Active (Matt, 2026-08-08) | [forge-poll driver §Approach](product/compass-forge-poll-driver/design.md#approach) | +| DL-162 | The board's poll targets are durable TABLE rows, not config: a new `forge_repo_subscriptions` table keyed `(forge_provider, forge_host, repo)` with an `enabled` soft-disable flag, enumerated `WHERE enabled` at the top of every pass so add/remove is a live row op needing no restart or deploy. The `--forge-repos` CLI flag becomes a declarative boot SEED reconciled into the table `ON CONFLICT DO NOTHING` (bootstrap-only insert: the table is authoritative after first insert, a soft-disabled row stays disabled across restarts, the seed never deletes/disables/re-enables an existing row); a `--forge-poll` bool runs the driver with an empty seed. The dynamic add/remove mutation RPC/admin surface is a named non-goal of this slice | Active (Matt, 2026-08-08) | [forge-poll driver §OQ-C](product/compass-forge-poll-driver/design.md#oq-c--resolved-matt-2026-08-08-the-boards-subscription-set-is-a-table) | +| DL-163 | Migration `0015_forge_subscriptions.sql` lands FOUR tables unconditionally — `forge_repo_subscriptions` (DL-162), `forge_list_cursors` (DL-161), and the two DL-053-spec'd tables `agent_forge_subscriptions` (DL-053's `forge_subscriptions`, RENAMED to disambiguate the per-artifact agent-owned subscription from the board's per-repo target) and `forge_artifact_cursors` (both writer-less this slice, shape frozen + pgtest-covered before their writers) — every key coordinate-aligned to the 0013 issue convention (SMALLINT provider + `forge_host`) and every provider CHECK admitting the full declared proto enum `IN (1, 2, 3, 4)` (the CHECK's job is "never UNSPECIFIED(0)", not gating rollout; rollout is gated by which `forge.Provider` has a real client — GitHub only this slice). The `issues` CHECK `IN (1, 2, 3)` widening for Linear ingestion is a separate future-slice prerequisite (OQ-E) | Active (Matt, 2026-08-08) | [forge-poll driver §OQ-D](product/compass-forge-poll-driver/design.md#oq-d--resolved-matt-2026-08-08-all-four-tables-land-now-checks-admit-the-full-enum) | > Note (2026-07-31, SEA-1570 R5): DL-065's retired internal `ResumeContext > resume = 12` envelope field is NOT silently reintroduced — the collapsed @@ -107,216 +107,216 @@ check enforces the mechanical half. Full rationale: | ID | Decision | Status | Record | | --- | --- | --- | --- | -| DL-023 | The in-container agent is a first-party program on the OMP SDK, emitting `compass.v1` natively | Active (Matt, 2026-07-06) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-024 | Each agent runs in a per-agent container on the Runner for blast-radius isolation, not credential avoidance | Active (Matt, 2026-07-06) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-025 | Container base image is self-contained; the agent manages its own devenv | Active (Matt, 2026-07-15) | [agent container runtime §Decision 1](compass-agent-container-runtime.md#decision-1--self-contained-base-image-the-agent-manages-its-own-devenv) | -| DL-026 | Secrets are a Server-side SecretSpec + keyring store with inject-all, no repo manifest | Active (Matt, 2026-07-15) | [agent container runtime §Decision 2](compass-agent-container-runtime.md#decision-2--secrets-store-secretspec--keyring-server-side-no-repo-manifest-inject-all) | -| DL-027 | No in-container supervisor for the MVP | Active (Matt, 2026-07-15) | [agent container runtime §Decision 4](compass-agent-container-runtime.md#decision-4--no-in-container-supervisor-for-mvp) | -| DL-047 | The agent is integrated via ACP/BYOA over stdio, with OMP as the external default over ACP and other agents as BYOA citizens | Superseded by DL-023 (Matt, 2026-07-06) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-078 | Agent config (skills/extensions/MCP configs) is declared into a Server-side FLEET-WIDE bundle store (one bundle all agents get) via new operator-scoped CompassService RPCs, never pushed as provision-request fields; the recommended MVP authoring workflow is a version-controlled config repo published via a CI `compass config put` step; persona/role-keyed bundles and native GitOps pull (Server reconciles a config repo) are the named post-MVP seams | Active (Matt, 2026-07-30) | [config delivery §Decision CD-1](compass-agent-config-delivery/design.md#decision-cd-1--declaration-surface-a-server-side-fleet-wide-bundle-store) | -| DL-079 | Config carriage is Runner-fetch — a server-STREAMING `FetchAgentConfig` RPC + a `ConfigVersion` signal on the Sessions response stream (signal-then-pull over the frozen dial-out inversion; no inbound Server→Runner route) | Active (Matt, 2026-07-30) | [config delivery §Decision CD-2](compass-agent-config-delivery/design.md#decision-cd-2--carriage-streaming-runner-fetch-over-the-frozen-inversion) | -| DL-080 | Config injection is a Runner-local read-only bind mount of the parent config dir at `/run/compass/agent-config` (agent reads through `current/`); env-vars ride SEA-1327's secret surface exclusively; MVP forbids credentials in MCP configs (SEA-1576 tracks the post-MVP credentialed path) | Active (Matt, 2026-07-30) | [config delivery §Decision CD-3](compass-agent-config-delivery/design.md#decision-cd-3--injection-per-config-type) | -| DL-081 | The MVP config-update path is re-materialize + in-place agent Reload (the exec-driven model), reserving throwaway-container restart for image changes; live structured injection (ConfigControl/SEA-1310) is the named future seam | Active (Matt, 2026-07-30) | [config delivery §Decision CD-4](compass-agent-config-delivery/design.md#decision-cd-4--update-path-in-place-agent-reload-live-pull-as-the-named-seam) | -| DL-123 | Fleet OMP `settings`/`config.yml` are delivered whole-file (yml-only, no key-merge) as a bundle member, injected at `createAgentSession` as a `Settings.loadIsolated` `settingsManager` overlay with overlay-over-project precedence — extending the CD-1 bundle store with a settings category | Active (Matt, 2026-08-03) | [config passthrough §CP-1](compass-agent-config-passthrough/design.md#decision-cp-1--settings-delivery-whole-file-passthrough-via-the-configfilessettingsmanager-injection-seam) | -| DL-124 | The fleet `AGENTS.md` is a top-level bundle member injected at `createAgentSession` as a composed `contextFiles` global (fleet-first, the entrypoint re-runs project discovery), never workspace-placement — extending the CD family with an agent-context category | Active (Matt, 2026-08-03) | [config passthrough §CP-2](compass-agent-config-passthrough/design.md#decision-cp-2--agentsmd-delivery-bundle-member-injected-as-a-composed-contextfiles-global-not-workspace-placement) | -| DL-125 | The complete OMP config-dir surface is enumerated with a per-category deliver/defer table; the MVP delivers every category the wave populates (the rest are named defer seams), fixing the config-passthrough scope boundary | Active (Matt, 2026-08-03) | [config passthrough §CP-3](compass-agent-config-passthrough/design.md#decision-cp-3--the-complete-omp-config-dir-surface-deliverdefer-table) | -| DL-126 | Agent-dir-anchored categories (`rules/`, `agents/`, `models.yml`) are delivered per SDK seam — `rules/` as a composed `rules: Rule[]` object injection, `agents/` and `models.yml` via user-level symlinks; the CD-3 server-door credential denylist extends to `models.yml` BOTH credential surfaces — `providers..apiKey` AND `providers..headers.*` literal secrets (env-indirection references pass; non-env-indirection literals are rejected with a client warning), because header values materialize outbound value-first | Active (Matt, 2026-08-03) | [config passthrough §CP-4](compass-agent-config-passthrough/design.md#decision-cp-4--agent-dir-anchored-categories-rules-as-an-injected-object-agents-and-modelsyml-via-user-level-symlinks) | +| DL-023 | The in-container agent is a first-party program on the OMP SDK, emitting `compass.v1` natively | Active (Matt, 2026-07-06) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-024 | Each agent runs in a per-agent container on the Runner for blast-radius isolation, not credential avoidance | Active (Matt, 2026-07-06) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-025 | Container base image is self-contained; the agent manages its own devenv | Active (Matt, 2026-07-15) | [agent container runtime §Decision 1](product/compass-agent-container-runtime.md#decision-1--self-contained-base-image-the-agent-manages-its-own-devenv) | +| DL-026 | Secrets are a Server-side SecretSpec + keyring store with inject-all, no repo manifest | Active (Matt, 2026-07-15) | [agent container runtime §Decision 2](product/compass-agent-container-runtime.md#decision-2--secrets-store-secretspec--keyring-server-side-no-repo-manifest-inject-all) | +| DL-027 | No in-container supervisor for the MVP | Active (Matt, 2026-07-15) | [agent container runtime §Decision 4](product/compass-agent-container-runtime.md#decision-4--no-in-container-supervisor-for-mvp) | +| DL-047 | The agent is integrated via ACP/BYOA over stdio, with OMP as the external default over ACP and other agents as BYOA citizens | Superseded by DL-023 (Matt, 2026-07-06) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-078 | Agent config (skills/extensions/MCP configs) is declared into a Server-side FLEET-WIDE bundle store (one bundle all agents get) via new operator-scoped CompassService RPCs, never pushed as provision-request fields; the recommended MVP authoring workflow is a version-controlled config repo published via a CI `compass config put` step; persona/role-keyed bundles and native GitOps pull (Server reconciles a config repo) are the named post-MVP seams | Active (Matt, 2026-07-30) | [config delivery §Decision CD-1](product/compass-agent-config-delivery/design.md#decision-cd-1--declaration-surface-a-server-side-fleet-wide-bundle-store) | +| DL-079 | Config carriage is Runner-fetch — a server-STREAMING `FetchAgentConfig` RPC + a `ConfigVersion` signal on the Sessions response stream (signal-then-pull over the frozen dial-out inversion; no inbound Server→Runner route) | Active (Matt, 2026-07-30) | [config delivery §Decision CD-2](product/compass-agent-config-delivery/design.md#decision-cd-2--carriage-streaming-runner-fetch-over-the-frozen-inversion) | +| DL-080 | Config injection is a Runner-local read-only bind mount of the parent config dir at `/run/compass/agent-config` (agent reads through `current/`); env-vars ride SEA-1327's secret surface exclusively; MVP forbids credentials in MCP configs (SEA-1576 tracks the post-MVP credentialed path) | Active (Matt, 2026-07-30) | [config delivery §Decision CD-3](product/compass-agent-config-delivery/design.md#decision-cd-3--injection-per-config-type) | +| DL-081 | The MVP config-update path is re-materialize + in-place agent Reload (the exec-driven model), reserving throwaway-container restart for image changes; live structured injection (ConfigControl/SEA-1310) is the named future seam | Active (Matt, 2026-07-30) | [config delivery §Decision CD-4](product/compass-agent-config-delivery/design.md#decision-cd-4--update-path-in-place-agent-reload-live-pull-as-the-named-seam) | +| DL-123 | Fleet OMP `settings`/`config.yml` are delivered whole-file (yml-only, no key-merge) as a bundle member, injected at `createAgentSession` as a `Settings.loadIsolated` `settingsManager` overlay with overlay-over-project precedence — extending the CD-1 bundle store with a settings category | Active (Matt, 2026-08-03) | [config passthrough §CP-1](product/compass-agent-config-passthrough/design.md#decision-cp-1--settings-delivery-whole-file-passthrough-via-the-configfilessettingsmanager-injection-seam) | +| DL-124 | The fleet `AGENTS.md` is a top-level bundle member injected at `createAgentSession` as a composed `contextFiles` global (fleet-first, the entrypoint re-runs project discovery), never workspace-placement — extending the CD family with an agent-context category | Active (Matt, 2026-08-03) | [config passthrough §CP-2](product/compass-agent-config-passthrough/design.md#decision-cp-2--agentsmd-delivery-bundle-member-injected-as-a-composed-contextfiles-global-not-workspace-placement) | +| DL-125 | The complete OMP config-dir surface is enumerated with a per-category deliver/defer table; the MVP delivers every category the wave populates (the rest are named defer seams), fixing the config-passthrough scope boundary | Active (Matt, 2026-08-03) | [config passthrough §CP-3](product/compass-agent-config-passthrough/design.md#decision-cp-3--the-complete-omp-config-dir-surface-deliverdefer-table) | +| DL-126 | Agent-dir-anchored categories (`rules/`, `agents/`, `models.yml`) are delivered per SDK seam — `rules/` as a composed `rules: Rule[]` object injection, `agents/` and `models.yml` via user-level symlinks; the CD-3 server-door credential denylist extends to `models.yml` BOTH credential surfaces — `providers..apiKey` AND `providers..headers.*` literal secrets (env-indirection references pass; non-env-indirection literals are rejected with a client warning), because header values materialize outbound value-first | Active (Matt, 2026-08-03) | [config passthrough §CP-4](product/compass-agent-config-passthrough/design.md#decision-cp-4--agent-dir-anchored-categories-rules-as-an-injected-object-agents-and-modelsyml-via-user-level-symlinks) | ## Comms & tools | ID | Decision | Status | Record | | --- | --- | --- | --- | -| DL-028 | The MVP agent comms toolset is two native tools (`comms_post_message`, `comms_list_messages`); no ask-answering capability | Active (Matt, 2026-07-22) | [agent comms tools §Tool set](compass-agent-comms-tools/design.md#tool-set-and-shape--native-two-tools-for-mvp) | -| DL-211 | The agent-side ask round-trip rides the comms transport: raise = a dedicated native `comms_post_ask` tool posting `PostMessage(MessageBlock{ask})` onto the agent's home channel into a named topic/thread (like `comms_post_message`), non-blocking; consume = `AskAnswerControl` over the control lane, correlated by server-minted `ask_id`. The session stays observe+stop only (no promptable session; no reply path). The session-id keying of the answer wake is a wart — an owed answer is keyed on the agent HANDLE, delivered to whatever session is next live for it (a runner/hub delivery-lane fix, entangled RIG-1310); when the asking agent is not live the human decides recovery (relaunch it, or route the answer to a new agent) — deliberately no agent-side boot poll | Active (Matt, 2026-08-18) | [ask comms round-trip §Approach](compass-ask-comms-roundtrip/design.md#approach) | -| DL-212 | The agent comms native toolset is `comms_post_message`, `comms_list_messages`, `comms_roster`, `comms_set_status`, and (DL-211) `comms_post_ask` — five tools; refreshes DL-028's "two native tools" count (already four in code before `comms_post_ask`). DL-028's load-bearing clause — the agent may RAISE an ask but has NO ask-ANSWERING capability, structurally (the request oneof cannot express RespondToAsk) — carries forward unchanged | Active (Matt, 2026-08-18) | [ask comms round-trip §Decisions](compass-ask-comms-roundtrip/design.md#decisions-ratified-by-matt--this-record-is-post-fork) | -| DL-029 | Agent comms identity/authz is session-resolved server-side, defaulting to the home channel | Active (Matt, 2026-07-22) | [agent comms tools §Identity / authz](compass-agent-comms-tools/design.md#identity--authz--session-resolved-server-side-home-channel-default) | -| DL-048 | The Server is the ownership layer: agents reach Issues/Chat/PRs only through the Server, which stamps a machine-parseable author/owner header — replacing per-agent forge accounts (Forgejo/Plane deprioritised) | Active (Matt, 2026-07-27) | [ownership layer §Approach](compass-server-ownership-layer/design.md#approach) | -| DL-049 | Forge tools ride the existing `AgentGateway` socket as a sibling `ForgeCall*` family relayed by `RelayForgeCall`, not a `CommsCallRequest` extension and not a second channel | Active (Matt, 2026-07-27) | [ownership layer §Decision 1](compass-server-ownership-layer/design.md#decision-1--a-sibling-forgecallrequest-on-the-same-agentgateway-socket) | -| DL-050 | The `compass:owner` header is a top-placed HTML comment + rendered line, stamped at one chokepoint (`forge.StampOwner`), idempotent, unforgeable ON WRITE; a header PARSED from forge text is untrusted display metadata that may not reach any authz/routing/ownership decision | Active (Matt, 2026-07-27) | [ownership layer §Decision 2](compass-server-ownership-layer/design.md#decision-2--the-authorowner-header-a-fenced-html-comment-plus-a-visible-line) | -| DL-051 | The forge adapter is `go/internal/forge` behind a swappable `Provider` interface (GitHub first, Linear issues-only), wired as a `runnerhub` sink | Active (Matt, 2026-07-27) | [ownership layer §Decision 3](compass-server-ownership-layer/design.md#decision-3--the-forge-adapter-lives-in-a-new-gointernalforge-package) | -| DL-054 | Notifications v1 is chat pings plus asks on the existing comms surfaces; no notifications page, centre, badge, or read state | Active (Matt, 2026-07-27) | [ownership layer §Decision 6](compass-server-ownership-layer/design.md#decision-6--notifications-v1-pings-in-chat-plus-asks-nothing-else) | -| DL-071 | Channel→agent delivery is a Server-side comms-bus consumer dispatching `deliver`/`steer` ops through the RunnerHub over a generic `SessionsResponse.DispatchControl` relay variant onto the built control lane; agent-authored (streaming) messages are held and delivered at the author's turn-settle edge (WORKING → READY/IDLE), human-authored at post (OQ-7, Matt 2026-07-29) | Active (Matt, 2026-07-29) | [notification delivery §D1](compass-notification-delivery/design.md#d1--the-fan-out-consumer-a-server-side-bus-consumer-dispatching-over-the-existing-sessions-relay) | -| DL-072 | The durable delivery cursor is Server-owned: a contiguous low-water cursor plus a bounded above-cursor set per `(agent_account_id, channel_id)` on `messages.seq` (mirroring `ControlAck`'s `acked_seq` + `applied_above`), reconstructed from per-message acks, swept gap-aware on session start/reconnect; the per-(agent, channel) keying is ratified (Matt, 2026-07-29), amending RT-3's "per-session" wording | Active (Matt, 2026-07-29) | [notification delivery §D2](compass-notification-delivery/design.md#d2--the-durable-delivery-cursor-server-owned-keyed-agent_account-channel-advanced-on-ack) | -| DL-073 | `DeliverControl` (and channel-borne `SteerControl`) carry the full first-party `compass.v1.Message` and nothing else (no `channel_seq`); the agent acks per message via `AgentFrame.delivery_ack { message_id }` — the frozen ack shape | Active (Matt, 2026-07-29) | [notification delivery §D3](compass-notification-delivery/design.md#d3--delivercontrol-payload-the-first-party-compassv1message-the-ack-is-the-message-id) | -| DL-074 | MVP presence is 4-state, Cotal-aligned (WORKING/IDLE/WAITING/OFFLINE): WORKING/IDLE/OFFLINE derived from the agent-session lifecycle, WAITING a server-side unanswered-ask overlay (an authored `Ask` with `Ask.answered=false` in a visible channel; WAITING > IDLE), no heartbeat, published as an additive `SubscribeCommsResponse` variant visible to actors sharing at least one visible channel with the agent, in-memory only with re-enroll reconciliation | Active (Matt, 2026-07-29) | [notification delivery §D4](compass-notification-delivery/design.md#d4--presence-derived-from-the-session-lifecycle-no-heartbeat) | -| DL-075 | Agent-facing spawn/despawn is owned by the spawning agent's owner (the human): all wave agents share `AgentAccount.OwnerUserID`, and despawn authority is same-owner-scoped for the MVP (finer caller-scoped authz deferred to SEA-1573) | Active (Matt, 2026-07-29) | [spawn/despawn §Identity and authz](compass-agent-spawn-despawn/design.md#identity-and-authz--owner-inherited-from-the-caller-resolved-at-the-rpc-edge) | -| DL-076 | Spawn/despawn rides a sibling `LifecycleCall*` family on the existing `AgentGateway` socket relayed by `RelayLifecycleCall` (mirroring DL-049), orchestrated server-side via a `LifecycleCaller` seam while the runnerhub resolves caller identity only; there is no public agent-callable spawn RPC (the egress-sealed agent holds no server token) | Active (Matt, 2026-07-29) | [spawn/despawn §Seam (a)](compass-agent-spawn-despawn/design.md#seam-a--spawn-a-lifecyclecall-family-on-the-agent-gateway-orchestrated-server-side) | -| DL-077 | Despawn stops the live session and calls a NEW public `RemoveAgentWorkspace` RPC (`compass.proto`, deliberately outside the SEA-1267 gen-fence); the agent account persists (teardown is compute-only). The MVP accepts the Runner's serial-dispatch head-of-line blocking, guarded by a bounded relay deadline as the sole guard with no spawn rate cap (limits → SEA-1574, concurrent dispatch → SEA-1575) | Active (Matt, 2026-07-29) | [spawn/despawn §Seam (b)](compass-agent-spawn-despawn/design.md#seam-b--despawn--the-new-removeagentworkspace-rpc) | -| DL-090 | Repo/auto-clone is removed from every agent-start contract: neither SpawnPeerRequest nor ProvisionAgentWorkspaceRequest carries repo/ref; agents self-clone after launch with the container's scoped git credential (post-MVP: a clone tool so agents hold no creds). Resolves OQ-4 (Workspace.Source optional->removed). | Active (Matt, 2026-07-29) | [spawn/despawn §Spawn carries no repo](compass-agent-spawn-despawn/design.md#seam-a--spawn-a-lifecyclecall-family-on-the-agent-gateway-orchestrated-server-side) | -| DL-092 | #995's forge-shaped proto domain family (`Issue`/`IssueComment`/`PullRequest`/`ForgeAuthor`/`ForgeChecksSummary`/`ForgeCheck` in `agent_gateway.proto`) is not built: per DL-069 the forge Provider layer's value types stay internal Go data at the ingestion boundary, the `ForgeCall*` carrier family survives with its result arms retyped to the canonical `compass.v1` types, and `AgentAttribution` supersedes `ForgeAuthor` (closing #995 OQ-1's field-set gate) | Active (Matt, 2026-07-31) | [ownership amendment §What this amendment asserts](compass-server-ownership-layer-amendment/design.md#what-this-amendment-asserts) | -| DL-135 | Agent roster is a pull: a public `CommsService.GetRoster` (account-visibility-scoped via `accountVisibleFromWhere`, tree-derived scopes NEIGHBORHOOD/SUBTREE/OWNER — OWNER ratified fleet-wide under the shared-owner model, activity strings fleet-visible) plus a native `compass_roster` tool on the `CommsCallRequest` relay family, reading the DL-074 in-memory presence enum joined with the agent tree; the activity string is DURABLE (its own `agent_activity` store table), recovered from Postgres on Server restart — agent-set via `compass_set_status` (write-through to the table + additive `AgentPresenceChanged.activity`), re-published by the agent-side harness on session (re)attach for freshness — a deliberate divergence from DL-074's in-memory posture for the STRING; the presence enum stays in-memory. Presence EVENTS keep the shared-channel visibility rule while the roster uses account visibility (divergence stated: an owner sharing no channel with its agent gets snapshot-only presence). SEA-1721 | Active (Matt, 2026-07-31) | [manager comms substrate](compass-manager-comms-substrate/design.md#a1--sea-1721-roster-query--a-getroster-rpc--compass_roster-tool-over-the-d4-presence-snapshot) | -| DL-136 | Channel post authority and forced subscription are channel-level policy fields (`post_policy` OPEN/OWNER_ONLY + `owner_account_id` + `mandatory_subscription`), never a `ChannelKind` or a visibility overload; `mandatory_subscription` is enforced read-side as a third disjunct in D1's subscriber resolution; an owner/operator `SetChannelPolicy` (create-or-update) is the only post-creation mutation path, its txn seeding delivery cursors for every member a mandatory flip newly targets. A Manager's coordination channel is auto-provisioned on first report gained via a reconciler hooked at the two store-level writers of `agent_accounts.parent_agent_id` (`store.CreateAgent`, `store.ReparentAgent`) — covering spawn, public `CreateAgent`, reparent, and any future writer by construction; resume on name-collision is ownership-checked (never adopts a user-created channel); membership reconciles with tree edges; dormant channels are never deleted (accepted MVP accretion). The coordination channel is OWNER_ONLY + mandatory-subscribe — a one-way manager→reports directive surface; report→manager and lateral coordination flows through DMs/group DMs, and agents at every level heavily prefer direct DMs/small targeted group DMs to keep coordination-token-cost low (standing directive, Matt). Precursor primitive to SEA-1622, not part of it. SEA-1722 | Active (Matt, 2026-07-31) | [manager comms substrate](compass-manager-comms-substrate/design.md#a2--sea-1722-coordination-channel--a-channel-level-post_policy--mandatory_subscription-auto-provisioned-from-tree-edges) | -| DL-137 | The pinned board is a server-side per-channel capped ordered POINTER set over existing topic-scoped messages: pinning references an existing `message_id` (validated to a topic of the channel, join through `topics`) and creates no `Message`, so DL-099's single-write-path stands; edit = a normal topic-mandatory post + compare-and-swap repoint (redelivery is ordinary DL-071/072/073 delivery of a new message id, dedup-safe); board txns serialize on `channels … FOR UPDATE` (cap + repoint races); startup delivery is a session-start pin sweep beside the D2 cursor sweep dispatching current pins regardless of cursor position; edits land at turn-settle (never steer); explicitly distinct from DL-096's client-local sidebar pins, and compatible with DL-054 (no centre/badge/read state). SEA-1723 | Active (Matt, 2026-07-31) | [manager comms substrate](compass-manager-comms-substrate/design.md#a3--sea-1723-pinned-board--a-pure-pointer-set-over-existing-topic-scoped-messages-edit--topic-mandatory-post--repoint-so-redelivery-is-delivery) | -| DL-182 | The forge notification/carrier types that `AgentControl.forge_notification` reaches (`ForgeNotification`/`ForgeNotificationKind`, `ForgeArtifactKind`, `CommentRef`) live in a new internal-only leaf `proto/compass/v1/forge.proto` (imports only `compass.proto`), NOT in `agent_gateway.proto` as #995 T1 / this record's original §A1 add-list 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 by `agent.proto`/`agent_gateway.proto`/`runner.proto` acyclically. Wire contract, field numbers, and generated names unchanged — placement only | Active (Matt, 2026-08-05) | [ownership amendment §A1](compass-server-ownership-layer-amendment/design.md#a1--proto-amend-the-t1-add-list-to-the-reconciled-surface) | -| DL-200 | The forge write path is served by a single-method `ForgeCaller` seam (`ExecuteForgeCallAsAccount(ctx, caller, sessionID, call)`) behind `Hub.RelayForgeCall` with the RelayBoardCall guard order (nil-caller CodeUnavailable before resolution; unbound session CodeNotFound; tool errors in-band); the hub keeps only the resolution edge, the oneof dispatch + stamping + provider selection live in the server-side `forgeService` — the first production `forge.StampOwner` caller (DL-050) | Active (Matt, 2026-08-17) | [forge write path §1](compass-forge-write-path/design.md#1-the-forgecaller-seam--relayforgecall-server-leg-the-dl-050-chokepoint) | -| DL-201 | The review surface is a `submit_review` arm on the existing `ForgeCallRequest` oneof (verdict + summary body + optional inline path/line/side comments, one POST, never a PENDING review) acked by a `ReviewRef` reference in forge.proto mirroring `CommentRef`; the canonical read-side `compass.v1.Review` is untouched (DL-069/DL-092 hold). The arm executes under a DISTINCT reviewer GitHub identity — a second `server_only` declared secret — so APPROVE/REQUEST_CHANGES/COMMENT are all usable on Compass-authored PRs (GitHub 422s an author's self-review verdicts); the motivating consumer is the `skill://review` loop posting its per-PR review to the PR as that reviewer. Amends DL-052 (the reviewer credential joins the author credential; the Server-holds-write-creds core stands) | Active (Matt, 2026-08-17) | [forge write path §3](compass-forge-write-path/design.md#3-github-provider-writes--the-review-surface) | -| DL-202 | Multi-provider addressing is an optional `ForgeRef forge` field on the `ForgeCallRequest` envelope (unset = the configured default GitHub forge — the additive follow-up the standing agent_gateway.proto comment names); there is no capability-negotiation RPC: an op the addressed provider cannot serve returns the in-band `ForgeCallError{code:"unimplemented"}` built on `forge.ErrUnsupported`, and the agent tool prompt documents the static per-provider capability matrix | Active (Matt, 2026-08-17) | [forge write path §4](compass-forge-write-path/design.md#4-provider-addressing-same-oneof-envelope-forgeref-typed-degradation) | -| DL-203 | The Linear provider (`go/internal/forge/linear.go`, stdlib GraphQL, team key as `repo`) serves the issues half read+write — the read half served live via the OQ-A untracked-artifact fallback (no Linear ingestion exists) — and returns `ErrUnsupported` for the whole PR/review family — the canonical PullRequest surface is never fabricated on a Linear coordinate; its write credential is its own `server_only` declared secret (DL-052). Amends DL-051 (Linear moves from a deferred issues-only follow-on to in-scope issues read+write; the swappable-`Provider` framing and the PR/review-family-unsupported core stand) | Active (Matt, 2026-08-17) | [forge write path §5](compass-forge-write-path/design.md#5-linear-provider-read--write-issues-half) | -| DL-204 | Linear attribution is dual-channel with deliberate granularity: every write passes through `StampOwner` unchanged (the one chokepoint; the header carries the fine-grained PER-AGENT owner truth) AND sets Linear's native `createAsUser` to the ONE general shared Compass app identity (coarse native display, never per-agent; the token is OAuth actor=app, degrading to stamp-only via a named boot-time capability probe on a non-actor token); both values are Server-chosen so DL-050 unforgeability holds on both channels | Active (Matt, 2026-08-17) | [forge write path §5](compass-forge-write-path/design.md#5-linear-provider-read--write-issues-half) | -| DL-205 | The DL-055 ownership index materializes as `forge_authored_artifacts` (PK = forge coordinate; agent/owner/session columns; ON DELETE RESTRICT FKs), written by `forgeService` strictly after forge write success — no row for a rejected write, no orphan row on a stamp failure | Active (Matt, 2026-08-17) | [forge write path §6](compass-forge-write-path/design.md#6-the-dl-055-ownership-index-first-writer) | -| DL-206 | Forge creates are idempotent under a caller-minted `ForgeCallRequest.client_request_id` whole-chain key (the SpawnPeerRequest.client_request_id precedent, agent_gateway.proto:172), deduped by a memo — a `client_request_id` column + UNIQUE `(agent_account_id, client_request_id)` index on `forge_authored_artifacts`, written in the SAME ordered step as the DL-055 row — so a retried create returns the original artifact, a retry after a failed create re-attempts, and the accepted residual window is exactly the forge-success→pre-commit crash gap | Active (Matt, 2026-08-17) | [forge write path §6](compass-forge-write-path/design.md#6-the-dl-055-ownership-index-first-writer) | -| DL-210 | Forge integration testing adds two live-contract tiers above the DL-174 hermetic pyramid: (1) a hermetic golden-fixture replay leg (committed `go/internal/forge/testdata/` fixtures replayed through the stub RoundTripper, an untagged Go test riding moon affected-detection on every forge-affected PR + the main/nightly sweep, no `ci.yml` project enumeration) and (2) a `//go:build livegithub` live-credentials oracle (same scenarios against a throwaway `RigelBuild/compass-forge-testbed` + a Linear test team under test-only bot PATs ≠ the `server_only` production secrets), REQUIRED on forge-affected PRs + nightly, covering GitHub and Linear co-equally (the GitHub-only F1 reviewer≠author 422→APPROVE headline; Linear's PR/review family is `ErrUnsupported`, not a scenario). This is a NEW secret-bearing per-PR CI step — a standalone decision, NOT an amendment: D2's full-stack deterministic tier (`compass-dogfood-e2e/design.md:815-830`) stays secret-free and unchanged; a forward pointer next to D2 records the carve-out. Fork-PR secret safety: the same-repo-head-guarded step goes vacuously green on fork heads (GitHub withholds secrets there); accepted, with the push-to-main run + a maintainer same-repo re-push convention as the catch (0 forks today) | Active (Matt, 2026-08-18) | [forge integration testing §Approach](compass-forge-integration-testing/design.md#approach) | -| DL-226 | A message owed to an OFFLINE channel agent member is never silently stranded: the server wakes the member by RESUMING its most recent session (a system-authorized internal sibling of the public resume path, via a new `LatestSessionForAccount` read; fresh start only for a never-started agent; per-agent singleflight + not-live pre-check as cost control — agent-triggered starts are a core product capability, and `StartAgentSession`'s adminOnly PUBLIC door is untouched). Durability split: a mentioned member outside the sweep set (unsubscribed, non-home, non-mandatory) gets a durable owed-mention row `(agent_account_id, message_id)` written at the settle edge before the wake and swept subscription-independently on session start AS A STEER (D5 mention→steer preserved; steer-only precedence intact), cleared on the frozen message_id ack; a subscribed/home/mandatory member gets no owed row — the D2 cursor sweep is its durable backstop and the wake (both the mention arm and the plain-deliver arm) is pure latency. Broadcast mentions (`@everyone`/`@agents`) wake too; N-start amplification accepted. The residual pre-settle window is accepted for MVP (RIG-2490). Amends D5/OQ-3's offline clause by citation | Active (Matt, 2026-08-21); residual pre-settle window closed by DL-240 (RIG-2490, 2026-08-23) | [mention offline redelivery §Decisions](compass-mention-offline-redelivery.md#decisions-ruled-by-matt-2026-08-21) | -| DL-240 | The RIG-1641 OQ-5 residual pre-settle mention-loss window (a mention to an offline out-of-sweep-set member, lost when a crash or bus overrun drops `MessagePosted` before the settle-edge `routeMentions` pass) is closed by a per-message delivery marker, NOT a high-water cursor: a nullable `messages.mentions_routed_at BIGINT` (unix ms) set by the consumer after the settle-edge pass, with a recovery scan at consumer start + the `Lagged()` overrun re-subscribe reading `WHERE mentions_routed_at IS NULL` (skipping message_ids in `c.held`), replaying the ONE shared `routeMentions` body, then marking. The killed cursor could advance past a LOWER in-flight seq (`messages.seq` is `BIGSERIAL` assigned at INSERT but the bus event publishes post-commit, `comms.go:361-375`) whose crash-dropped event then stranded the mention forever — a new silent loss the marker cannot express. Seed-forward on first deploy (no historical backfill; compass pre-live). Extends DL-226's no-loss invariant from the settle edge back to the message-post commit; DL-226's wake+owed-mention mechanism is unchanged | Active (Matt, 2026-08-23) | [mention offline pre-settle closure §Resolved decisions](compass-mention-offline-redelivery-pre-settle-closure.md#resolved-decisions) | +| DL-028 | The MVP agent comms toolset is two native tools (`comms_post_message`, `comms_list_messages`); no ask-answering capability | Active (Matt, 2026-07-22) | [agent comms tools §Tool set](product/compass-agent-comms-tools/design.md#tool-set-and-shape--native-two-tools-for-mvp) | +| DL-211 | The agent-side ask round-trip rides the comms transport: raise = a dedicated native `comms_post_ask` tool posting `PostMessage(MessageBlock{ask})` onto the agent's home channel into a named topic/thread (like `comms_post_message`), non-blocking; consume = `AskAnswerControl` over the control lane, correlated by server-minted `ask_id`. The session stays observe+stop only (no promptable session; no reply path). The session-id keying of the answer wake is a wart — an owed answer is keyed on the agent HANDLE, delivered to whatever session is next live for it (a runner/hub delivery-lane fix, entangled RIG-1310); when the asking agent is not live the human decides recovery (relaunch it, or route the answer to a new agent) — deliberately no agent-side boot poll | Active (Matt, 2026-08-18) | [ask comms round-trip §Approach](product/compass-ask-comms-roundtrip/design.md#approach) | +| DL-212 | The agent comms native toolset is `comms_post_message`, `comms_list_messages`, `comms_roster`, `comms_set_status`, and (DL-211) `comms_post_ask` — five tools; refreshes DL-028's "two native tools" count (already four in code before `comms_post_ask`). DL-028's load-bearing clause — the agent may RAISE an ask but has NO ask-ANSWERING capability, structurally (the request oneof cannot express RespondToAsk) — carries forward unchanged | Active (Matt, 2026-08-18) | [ask comms round-trip §Decisions](product/compass-ask-comms-roundtrip/design.md#decisions-ratified-by-matt--this-record-is-post-fork) | +| DL-029 | Agent comms identity/authz is session-resolved server-side, defaulting to the home channel | Active (Matt, 2026-07-22) | [agent comms tools §Identity / authz](product/compass-agent-comms-tools/design.md#identity--authz--session-resolved-server-side-home-channel-default) | +| DL-048 | The Server is the ownership layer: agents reach Issues/Chat/PRs only through the Server, which stamps a machine-parseable author/owner header — replacing per-agent forge accounts (Forgejo/Plane deprioritised) | Active (Matt, 2026-07-27) | [ownership layer §Approach](product/compass-server-ownership-layer/design.md#approach) | +| DL-049 | Forge tools ride the existing `AgentGateway` socket as a sibling `ForgeCall*` family relayed by `RelayForgeCall`, not a `CommsCallRequest` extension and not a second channel | Active (Matt, 2026-07-27) | [ownership layer §Decision 1](product/compass-server-ownership-layer/design.md#decision-1--a-sibling-forgecallrequest-on-the-same-agentgateway-socket) | +| DL-050 | The `compass:owner` header is a top-placed HTML comment + rendered line, stamped at one chokepoint (`forge.StampOwner`), idempotent, unforgeable ON WRITE; a header PARSED from forge text is untrusted display metadata that may not reach any authz/routing/ownership decision | Active (Matt, 2026-07-27) | [ownership layer §Decision 2](product/compass-server-ownership-layer/design.md#decision-2--the-authorowner-header-a-fenced-html-comment-plus-a-visible-line) | +| DL-051 | The forge adapter is `go/internal/forge` behind a swappable `Provider` interface (GitHub first, Linear issues-only), wired as a `runnerhub` sink | Active (Matt, 2026-07-27) | [ownership layer §Decision 3](product/compass-server-ownership-layer/design.md#decision-3--the-forge-adapter-lives-in-a-new-gointernalforge-package) | +| DL-054 | Notifications v1 is chat pings plus asks on the existing comms surfaces; no notifications page, centre, badge, or read state | Active (Matt, 2026-07-27) | [ownership layer §Decision 6](product/compass-server-ownership-layer/design.md#decision-6--notifications-v1-pings-in-chat-plus-asks-nothing-else) | +| DL-071 | Channel→agent delivery is a Server-side comms-bus consumer dispatching `deliver`/`steer` ops through the RunnerHub over a generic `SessionsResponse.DispatchControl` relay variant onto the built control lane; agent-authored (streaming) messages are held and delivered at the author's turn-settle edge (WORKING → READY/IDLE), human-authored at post (OQ-7, Matt 2026-07-29) | Active (Matt, 2026-07-29) | [notification delivery §D1](product/compass-notification-delivery/design.md#d1--the-fan-out-consumer-a-server-side-bus-consumer-dispatching-over-the-existing-sessions-relay) | +| DL-072 | The durable delivery cursor is Server-owned: a contiguous low-water cursor plus a bounded above-cursor set per `(agent_account_id, channel_id)` on `messages.seq` (mirroring `ControlAck`'s `acked_seq` + `applied_above`), reconstructed from per-message acks, swept gap-aware on session start/reconnect; the per-(agent, channel) keying is ratified (Matt, 2026-07-29), amending RT-3's "per-session" wording | Active (Matt, 2026-07-29) | [notification delivery §D2](product/compass-notification-delivery/design.md#d2--the-durable-delivery-cursor-server-owned-keyed-agent_account-channel-advanced-on-ack) | +| DL-073 | `DeliverControl` (and channel-borne `SteerControl`) carry the full first-party `compass.v1.Message` and nothing else (no `channel_seq`); the agent acks per message via `AgentFrame.delivery_ack { message_id }` — the frozen ack shape | Active (Matt, 2026-07-29) | [notification delivery §D3](product/compass-notification-delivery/design.md#d3--delivercontrol-payload-the-first-party-compassv1message-the-ack-is-the-message-id) | +| DL-074 | MVP presence is 4-state, Cotal-aligned (WORKING/IDLE/WAITING/OFFLINE): WORKING/IDLE/OFFLINE derived from the agent-session lifecycle, WAITING a server-side unanswered-ask overlay (an authored `Ask` with `Ask.answered=false` in a visible channel; WAITING > IDLE), no heartbeat, published as an additive `SubscribeCommsResponse` variant visible to actors sharing at least one visible channel with the agent, in-memory only with re-enroll reconciliation | Active (Matt, 2026-07-29) | [notification delivery §D4](product/compass-notification-delivery/design.md#d4--presence-derived-from-the-session-lifecycle-no-heartbeat) | +| DL-075 | Agent-facing spawn/despawn is owned by the spawning agent's owner (the human): all wave agents share `AgentAccount.OwnerUserID`, and despawn authority is same-owner-scoped for the MVP (finer caller-scoped authz deferred to SEA-1573) | Active (Matt, 2026-07-29) | [spawn/despawn §Identity and authz](product/compass-agent-spawn-despawn/design.md#identity-and-authz--owner-inherited-from-the-caller-resolved-at-the-rpc-edge) | +| DL-076 | Spawn/despawn rides a sibling `LifecycleCall*` family on the existing `AgentGateway` socket relayed by `RelayLifecycleCall` (mirroring DL-049), orchestrated server-side via a `LifecycleCaller` seam while the runnerhub resolves caller identity only; there is no public agent-callable spawn RPC (the egress-sealed agent holds no server token) | Active (Matt, 2026-07-29) | [spawn/despawn §Seam (a)](product/compass-agent-spawn-despawn/design.md#seam-a--spawn-a-lifecyclecall-family-on-the-agent-gateway-orchestrated-server-side) | +| DL-077 | Despawn stops the live session and calls a NEW public `RemoveAgentWorkspace` RPC (`compass.proto`, deliberately outside the SEA-1267 gen-fence); the agent account persists (teardown is compute-only). The MVP accepts the Runner's serial-dispatch head-of-line blocking, guarded by a bounded relay deadline as the sole guard with no spawn rate cap (limits → SEA-1574, concurrent dispatch → SEA-1575) | Active (Matt, 2026-07-29) | [spawn/despawn §Seam (b)](product/compass-agent-spawn-despawn/design.md#seam-b--despawn--the-new-removeagentworkspace-rpc) | +| DL-090 | Repo/auto-clone is removed from every agent-start contract: neither SpawnPeerRequest nor ProvisionAgentWorkspaceRequest carries repo/ref; agents self-clone after launch with the container's scoped git credential (post-MVP: a clone tool so agents hold no creds). Resolves OQ-4 (Workspace.Source optional->removed). | Active (Matt, 2026-07-29) | [spawn/despawn §Spawn carries no repo](product/compass-agent-spawn-despawn/design.md#seam-a--spawn-a-lifecyclecall-family-on-the-agent-gateway-orchestrated-server-side) | +| DL-092 | #995's forge-shaped proto domain family (`Issue`/`IssueComment`/`PullRequest`/`ForgeAuthor`/`ForgeChecksSummary`/`ForgeCheck` in `agent_gateway.proto`) is not built: per DL-069 the forge Provider layer's value types stay internal Go data at the ingestion boundary, the `ForgeCall*` carrier family survives with its result arms retyped to the canonical `compass.v1` types, and `AgentAttribution` supersedes `ForgeAuthor` (closing #995 OQ-1's field-set gate) | Active (Matt, 2026-07-31) | [ownership amendment §What this amendment asserts](product/compass-server-ownership-layer-amendment/design.md#what-this-amendment-asserts) | +| DL-135 | Agent roster is a pull: a public `CommsService.GetRoster` (account-visibility-scoped via `accountVisibleFromWhere`, tree-derived scopes NEIGHBORHOOD/SUBTREE/OWNER — OWNER ratified fleet-wide under the shared-owner model, activity strings fleet-visible) plus a native `compass_roster` tool on the `CommsCallRequest` relay family, reading the DL-074 in-memory presence enum joined with the agent tree; the activity string is DURABLE (its own `agent_activity` store table), recovered from Postgres on Server restart — agent-set via `compass_set_status` (write-through to the table + additive `AgentPresenceChanged.activity`), re-published by the agent-side harness on session (re)attach for freshness — a deliberate divergence from DL-074's in-memory posture for the STRING; the presence enum stays in-memory. Presence EVENTS keep the shared-channel visibility rule while the roster uses account visibility (divergence stated: an owner sharing no channel with its agent gets snapshot-only presence). SEA-1721 | Active (Matt, 2026-07-31) | [manager comms substrate](product/compass-manager-comms-substrate/design.md#a1--sea-1721-roster-query--a-getroster-rpc--compass_roster-tool-over-the-d4-presence-snapshot) | +| DL-136 | Channel post authority and forced subscription are channel-level policy fields (`post_policy` OPEN/OWNER_ONLY + `owner_account_id` + `mandatory_subscription`), never a `ChannelKind` or a visibility overload; `mandatory_subscription` is enforced read-side as a third disjunct in D1's subscriber resolution; an owner/operator `SetChannelPolicy` (create-or-update) is the only post-creation mutation path, its txn seeding delivery cursors for every member a mandatory flip newly targets. A Manager's coordination channel is auto-provisioned on first report gained via a reconciler hooked at the two store-level writers of `agent_accounts.parent_agent_id` (`store.CreateAgent`, `store.ReparentAgent`) — covering spawn, public `CreateAgent`, reparent, and any future writer by construction; resume on name-collision is ownership-checked (never adopts a user-created channel); membership reconciles with tree edges; dormant channels are never deleted (accepted MVP accretion). The coordination channel is OWNER_ONLY + mandatory-subscribe — a one-way manager→reports directive surface; report→manager and lateral coordination flows through DMs/group DMs, and agents at every level heavily prefer direct DMs/small targeted group DMs to keep coordination-token-cost low (standing directive, Matt). Precursor primitive to SEA-1622, not part of it. SEA-1722 | Active (Matt, 2026-07-31) | [manager comms substrate](product/compass-manager-comms-substrate/design.md#a2--sea-1722-coordination-channel--a-channel-level-post_policy--mandatory_subscription-auto-provisioned-from-tree-edges) | +| DL-137 | The pinned board is a server-side per-channel capped ordered POINTER set over existing topic-scoped messages: pinning references an existing `message_id` (validated to a topic of the channel, join through `topics`) and creates no `Message`, so DL-099's single-write-path stands; edit = a normal topic-mandatory post + compare-and-swap repoint (redelivery is ordinary DL-071/072/073 delivery of a new message id, dedup-safe); board txns serialize on `channels … FOR UPDATE` (cap + repoint races); startup delivery is a session-start pin sweep beside the D2 cursor sweep dispatching current pins regardless of cursor position; edits land at turn-settle (never steer); explicitly distinct from DL-096's client-local sidebar pins, and compatible with DL-054 (no centre/badge/read state). SEA-1723 | Active (Matt, 2026-07-31) | [manager comms substrate](product/compass-manager-comms-substrate/design.md#a3--sea-1723-pinned-board--a-pure-pointer-set-over-existing-topic-scoped-messages-edit--topic-mandatory-post--repoint-so-redelivery-is-delivery) | +| DL-182 | The forge notification/carrier types that `AgentControl.forge_notification` reaches (`ForgeNotification`/`ForgeNotificationKind`, `ForgeArtifactKind`, `CommentRef`) live in a new internal-only leaf `proto/compass/v1/forge.proto` (imports only `compass.proto`), NOT in `agent_gateway.proto` as #995 T1 / this record's original §A1 add-list 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 by `agent.proto`/`agent_gateway.proto`/`runner.proto` acyclically. Wire contract, field numbers, and generated names unchanged — placement only | Active (Matt, 2026-08-05) | [ownership amendment §A1](product/compass-server-ownership-layer-amendment/design.md#a1--proto-amend-the-t1-add-list-to-the-reconciled-surface) | +| DL-200 | The forge write path is served by a single-method `ForgeCaller` seam (`ExecuteForgeCallAsAccount(ctx, caller, sessionID, call)`) behind `Hub.RelayForgeCall` with the RelayBoardCall guard order (nil-caller CodeUnavailable before resolution; unbound session CodeNotFound; tool errors in-band); the hub keeps only the resolution edge, the oneof dispatch + stamping + provider selection live in the server-side `forgeService` — the first production `forge.StampOwner` caller (DL-050) | Active (Matt, 2026-08-17) | [forge write path §1](product/compass-forge-write-path/design.md#1-the-forgecaller-seam--relayforgecall-server-leg-the-dl-050-chokepoint) | +| DL-201 | The review surface is a `submit_review` arm on the existing `ForgeCallRequest` oneof (verdict + summary body + optional inline path/line/side comments, one POST, never a PENDING review) acked by a `ReviewRef` reference in forge.proto mirroring `CommentRef`; the canonical read-side `compass.v1.Review` is untouched (DL-069/DL-092 hold). The arm executes under a DISTINCT reviewer GitHub identity — a second `server_only` declared secret — so APPROVE/REQUEST_CHANGES/COMMENT are all usable on Compass-authored PRs (GitHub 422s an author's self-review verdicts); the motivating consumer is the `skill://review` loop posting its per-PR review to the PR as that reviewer. Amends DL-052 (the reviewer credential joins the author credential; the Server-holds-write-creds core stands) | Active (Matt, 2026-08-17) | [forge write path §3](product/compass-forge-write-path/design.md#3-github-provider-writes--the-review-surface) | +| DL-202 | Multi-provider addressing is an optional `ForgeRef forge` field on the `ForgeCallRequest` envelope (unset = the configured default GitHub forge — the additive follow-up the standing agent_gateway.proto comment names); there is no capability-negotiation RPC: an op the addressed provider cannot serve returns the in-band `ForgeCallError{code:"unimplemented"}` built on `forge.ErrUnsupported`, and the agent tool prompt documents the static per-provider capability matrix | Active (Matt, 2026-08-17) | [forge write path §4](product/compass-forge-write-path/design.md#4-provider-addressing-same-oneof-envelope-forgeref-typed-degradation) | +| DL-203 | The Linear provider (`go/internal/forge/linear.go`, stdlib GraphQL, team key as `repo`) serves the issues half read+write — the read half served live via the OQ-A untracked-artifact fallback (no Linear ingestion exists) — and returns `ErrUnsupported` for the whole PR/review family — the canonical PullRequest surface is never fabricated on a Linear coordinate; its write credential is its own `server_only` declared secret (DL-052). Amends DL-051 (Linear moves from a deferred issues-only follow-on to in-scope issues read+write; the swappable-`Provider` framing and the PR/review-family-unsupported core stand) | Active (Matt, 2026-08-17) | [forge write path §5](product/compass-forge-write-path/design.md#5-linear-provider-read--write-issues-half) | +| DL-204 | Linear attribution is dual-channel with deliberate granularity: every write passes through `StampOwner` unchanged (the one chokepoint; the header carries the fine-grained PER-AGENT owner truth) AND sets Linear's native `createAsUser` to the ONE general shared Compass app identity (coarse native display, never per-agent; the token is OAuth actor=app, degrading to stamp-only via a named boot-time capability probe on a non-actor token); both values are Server-chosen so DL-050 unforgeability holds on both channels | Active (Matt, 2026-08-17) | [forge write path §5](product/compass-forge-write-path/design.md#5-linear-provider-read--write-issues-half) | +| DL-205 | The DL-055 ownership index materializes as `forge_authored_artifacts` (PK = forge coordinate; agent/owner/session columns; ON DELETE RESTRICT FKs), written by `forgeService` strictly after forge write success — no row for a rejected write, no orphan row on a stamp failure | Active (Matt, 2026-08-17) | [forge write path §6](product/compass-forge-write-path/design.md#6-the-dl-055-ownership-index-first-writer) | +| DL-206 | Forge creates are idempotent under a caller-minted `ForgeCallRequest.client_request_id` whole-chain key (the SpawnPeerRequest.client_request_id precedent, agent_gateway.proto:172), deduped by a memo — a `client_request_id` column + UNIQUE `(agent_account_id, client_request_id)` index on `forge_authored_artifacts`, written in the SAME ordered step as the DL-055 row — so a retried create returns the original artifact, a retry after a failed create re-attempts, and the accepted residual window is exactly the forge-success→pre-commit crash gap | Active (Matt, 2026-08-17) | [forge write path §6](product/compass-forge-write-path/design.md#6-the-dl-055-ownership-index-first-writer) | +| DL-210 | Forge integration testing adds two live-contract tiers above the DL-174 hermetic pyramid: (1) a hermetic golden-fixture replay leg (committed `go/internal/forge/testdata/` fixtures replayed through the stub RoundTripper, an untagged Go test riding moon affected-detection on every forge-affected PR + the main/nightly sweep, no `ci.yml` project enumeration) and (2) a `//go:build livegithub` live-credentials oracle (same scenarios against a throwaway `RigelBuild/compass-forge-testbed` + a Linear test team under test-only bot PATs ≠ the `server_only` production secrets), REQUIRED on forge-affected PRs + nightly, covering GitHub and Linear co-equally (the GitHub-only F1 reviewer≠author 422→APPROVE headline; Linear's PR/review family is `ErrUnsupported`, not a scenario). This is a NEW secret-bearing per-PR CI step — a standalone decision, NOT an amendment: D2's full-stack deterministic tier (`compass-dogfood-e2e/design.md:815-830`) stays secret-free and unchanged; a forward pointer next to D2 records the carve-out. Fork-PR secret safety: the same-repo-head-guarded step goes vacuously green on fork heads (GitHub withholds secrets there); accepted, with the push-to-main run + a maintainer same-repo re-push convention as the catch (0 forks today) | Active (Matt, 2026-08-18) | [forge integration testing §Approach](product/compass-forge-integration-testing/design.md#approach) | +| DL-226 | A message owed to an OFFLINE channel agent member is never silently stranded: the server wakes the member by RESUMING its most recent session (a system-authorized internal sibling of the public resume path, via a new `LatestSessionForAccount` read; fresh start only for a never-started agent; per-agent singleflight + not-live pre-check as cost control — agent-triggered starts are a core product capability, and `StartAgentSession`'s adminOnly PUBLIC door is untouched). Durability split: a mentioned member outside the sweep set (unsubscribed, non-home, non-mandatory) gets a durable owed-mention row `(agent_account_id, message_id)` written at the settle edge before the wake and swept subscription-independently on session start AS A STEER (D5 mention→steer preserved; steer-only precedence intact), cleared on the frozen message_id ack; a subscribed/home/mandatory member gets no owed row — the D2 cursor sweep is its durable backstop and the wake (both the mention arm and the plain-deliver arm) is pure latency. Broadcast mentions (`@everyone`/`@agents`) wake too; N-start amplification accepted. The residual pre-settle window is accepted for MVP (RIG-2490). Amends D5/OQ-3's offline clause by citation | Active (Matt, 2026-08-21); residual pre-settle window closed by DL-240 (RIG-2490, 2026-08-23) | [mention offline redelivery §Decisions](product/compass-mention-offline-redelivery.md#decisions-ruled-by-matt-2026-08-21) | +| DL-240 | The RIG-1641 OQ-5 residual pre-settle mention-loss window (a mention to an offline out-of-sweep-set member, lost when a crash or bus overrun drops `MessagePosted` before the settle-edge `routeMentions` pass) is closed by a per-message delivery marker, NOT a high-water cursor: a nullable `messages.mentions_routed_at BIGINT` (unix ms) set by the consumer after the settle-edge pass, with a recovery scan at consumer start + the `Lagged()` overrun re-subscribe reading `WHERE mentions_routed_at IS NULL` (skipping message_ids in `c.held`), replaying the ONE shared `routeMentions` body, then marking. The killed cursor could advance past a LOWER in-flight seq (`messages.seq` is `BIGSERIAL` assigned at INSERT but the bus event publishes post-commit, `comms.go:361-375`) whose crash-dropped event then stranded the mention forever — a new silent loss the marker cannot express. Seed-forward on first deploy (no historical backfill; compass pre-live). Extends DL-226's no-loss invariant from the settle edge back to the message-post commit; DL-226's wake+owed-mention mechanism is unchanged | Active (Matt, 2026-08-23) | [mention offline pre-settle closure §Resolved decisions](product/compass-mention-offline-redelivery-pre-settle-closure.md#resolved-decisions) | ## Agent roles & prompts | ID | Decision | Status | Record | | --- | --- | --- | --- | -| DL-138 | A Compass role's system prompt REPLACES OMP's block 0 via the fork's `customSystemPrompt` path (`custom-system-prompt.md`), which keeps auto-injected skills/rules/always-apply lists and the project/env footer by construction — append is rejected (it pays for both prose sets every turn; the skills-loss fear was the fixed #3014 pre-fix behavior) | Active (Matt, 2026-08-04) | [manager prompt §MP-1](compass-manager-prompt/design.md#decision-mp-1--replace-block-0-per-role-through-omps-custom-prompt-template-dl-129) | -| DL-130 | Compass OWNS both role prompts: the Manager block-0 is authored fresh (~350 words, coordinator-shaped, OMP as style reference only) and the implementer block-0 is a copy-and-adapt of OMP's full block 0 — an owned file diverging where Compass differs, never an inherited prompt | Active (Matt, 2026-08-04) | [manager prompt §MP-2](compass-manager-prompt/design.md#decision-mp-2--we-own-both-role-prompts-dl-130) | -| DL-131 | "Manager" is an agent ROLE label in prompts/docs/UI/marketing; proto/Go/UI data types stay `Agent`/`AgentAccount` (no rename); the role mechanism itself (role field, per-role bundles, per-role model/thinking) is SEA-1724 (Beta), forward-referenced only | Active (Matt, 2026-08-04) | [manager prompt §MP-3](compass-manager-prompt/design.md#decision-mp-3--manager-is-a-role-label-not-a-data-type-rename-dl-131) | -| DL-132 | Role prompts version v0→target: the frozen text is the target contract, v0 ships naming only primitives that exist at the shipped commit, and every unshipped affordance is an explicit `[TODO ]` line flipped on in the same PR that lands its primitive — updates ride the existing bundle re-materialize + Reload path (DL-081), never new delivery | Active (Matt, 2026-08-04) | [manager prompt §MP-4](compass-manager-prompt/design.md#decision-mp-4--v0target-prompt-versioning-dl-132) | -| DL-133 | The Manager content layer split is frozen: irreducible operating model (identity, tree position, async comms, work loop, human merge gate, compaction) in block 0; invariants as always-apply rules (never-block/own-your-issue/red-green-testing adapted, never-merge/design-first/compact-often new); procedure in on-demand skills (comms-playbook, management-trees, compass-setup, supervisor-channel, manager-coordination-channel, jj-stacking/review/design adapted) — with the name-Managers-by-FUNCTION-never-tool tenet | Active (Matt, 2026-08-04) | [manager prompt §The layer split](compass-manager-prompt/design.md#the-layer-split-dl-133) | -| DL-134 | Dogfood implementers are IN-PROCESS SUBAGENTS the Manager briefs via the live `task` mechanism (the Manager authors each subagent's brief — task + context — at spawn time and names a standing subagent def whose body supplies block-0; there is no per-spawn `systemPrompt` param); the implementer block-0 is therefore an ACTIVE Dogfood deliverable, shipping as a fleet-delivered subagent def under `config/agents/` (body = `AgentDefinition.systemPrompt`), consumed by `task` + `discoverAgents` at `cf048ca` with no `cli.ts` wiring; `agents_spawn_peer`/`agents_despawn_peer` are reserved for standing peer/child Managers; per-implementer containers are rejected for Dogfood (container-per-subagent too heavy) and gate on the SEA-1717 brain/hands split (Beta, distinct from SEA-1724's role mechanism), which alone defers the containerized non-subagent implementer path (not the prompt) | Active (Matt, 2026-08-04) | [manager prompt §MP-5](compass-manager-prompt/design.md#decision-mp-5--dogfood-implementers-are-in-process-subagents-dl-134) | -| DL-139 | The `task`-subagent prompt seam is ADDITIVE, not a replace: a subagent def body is spliced INTO the full default OMP block-0 (`executor.ts:2808-2810`, `[...defaultPrompt.slice(0,-1), subagentPrompt, defaultPrompt.at(-1)]`), which co-renders around it (identity, Tool Policy, Delivery Contract, Internal URLs, Delegation), and the def body renders VERBATIM with no injector (`task/types.ts:362`, `systemPrompt: string`). So the Dogfood implementer `config/agents/implementer.md` is a THIN ROLE DELTA — identity + only the Compass divergences the default gets wrong (async comms/no `ask`, one-slice-then-yield, jj-stacking push, operator-not-user) — dropping everything the default supplies and carrying no `[runtime-injected]` placeholders and no `lsp`/todo mandates (`task.enableLsp` defaults false, `settings-schema.ts:4528`; the wrapper COMPLETION already sets no-todo); the full copy-and-adapt of OMP's block-0 is kept as the FUTURE SEA-1717 standalone-container artifact (a REPLACE path absent at `cf048ca`), not the Dogfood deliverable. Corrects DL-134's "block-0" framing (the def is the delta, not the full block) | Active (Matt, 2026-08-05) | [manager prompt §Implementer block-0](compass-manager-prompt/design.md#implementer-block-0-dogfood-thin-role-delta--the-future-full-container) | +| DL-138 | A Compass role's system prompt REPLACES OMP's block 0 via the fork's `customSystemPrompt` path (`custom-system-prompt.md`), which keeps auto-injected skills/rules/always-apply lists and the project/env footer by construction — append is rejected (it pays for both prose sets every turn; the skills-loss fear was the fixed #3014 pre-fix behavior) | Active (Matt, 2026-08-04) | [manager prompt §MP-1](product/compass-manager-prompt/design.md#decision-mp-1--replace-block-0-per-role-through-omps-custom-prompt-template-dl-129) | +| DL-130 | Compass OWNS both role prompts: the Manager block-0 is authored fresh (~350 words, coordinator-shaped, OMP as style reference only) and the implementer block-0 is a copy-and-adapt of OMP's full block 0 — an owned file diverging where Compass differs, never an inherited prompt | Active (Matt, 2026-08-04) | [manager prompt §MP-2](product/compass-manager-prompt/design.md#decision-mp-2--we-own-both-role-prompts-dl-130) | +| DL-131 | "Manager" is an agent ROLE label in prompts/docs/UI/marketing; proto/Go/UI data types stay `Agent`/`AgentAccount` (no rename); the role mechanism itself (role field, per-role bundles, per-role model/thinking) is SEA-1724 (Beta), forward-referenced only | Active (Matt, 2026-08-04) | [manager prompt §MP-3](product/compass-manager-prompt/design.md#decision-mp-3--manager-is-a-role-label-not-a-data-type-rename-dl-131) | +| DL-132 | Role prompts version v0→target: the frozen text is the target contract, v0 ships naming only primitives that exist at the shipped commit, and every unshipped affordance is an explicit `[TODO ]` line flipped on in the same PR that lands its primitive — updates ride the existing bundle re-materialize + Reload path (DL-081), never new delivery | Active (Matt, 2026-08-04) | [manager prompt §MP-4](product/compass-manager-prompt/design.md#decision-mp-4--v0target-prompt-versioning-dl-132) | +| DL-133 | The Manager content layer split is frozen: irreducible operating model (identity, tree position, async comms, work loop, human merge gate, compaction) in block 0; invariants as always-apply rules (never-block/own-your-issue/red-green-testing adapted, never-merge/design-first/compact-often new); procedure in on-demand skills (comms-playbook, management-trees, compass-setup, supervisor-channel, manager-coordination-channel, jj-stacking/review/design adapted) — with the name-Managers-by-FUNCTION-never-tool tenet | Active (Matt, 2026-08-04) | [manager prompt §The layer split](product/compass-manager-prompt/design.md#the-layer-split-dl-133) | +| DL-134 | Dogfood implementers are IN-PROCESS SUBAGENTS the Manager briefs via the live `task` mechanism (the Manager authors each subagent's brief — task + context — at spawn time and names a standing subagent def whose body supplies block-0; there is no per-spawn `systemPrompt` param); the implementer block-0 is therefore an ACTIVE Dogfood deliverable, shipping as a fleet-delivered subagent def under `config/agents/` (body = `AgentDefinition.systemPrompt`), consumed by `task` + `discoverAgents` at `cf048ca` with no `cli.ts` wiring; `agents_spawn_peer`/`agents_despawn_peer` are reserved for standing peer/child Managers; per-implementer containers are rejected for Dogfood (container-per-subagent too heavy) and gate on the SEA-1717 brain/hands split (Beta, distinct from SEA-1724's role mechanism), which alone defers the containerized non-subagent implementer path (not the prompt) | Active (Matt, 2026-08-04) | [manager prompt §MP-5](product/compass-manager-prompt/design.md#decision-mp-5--dogfood-implementers-are-in-process-subagents-dl-134) | +| DL-139 | The `task`-subagent prompt seam is ADDITIVE, not a replace: a subagent def body is spliced INTO the full default OMP block-0 (`executor.ts:2808-2810`, `[...defaultPrompt.slice(0,-1), subagentPrompt, defaultPrompt.at(-1)]`), which co-renders around it (identity, Tool Policy, Delivery Contract, Internal URLs, Delegation), and the def body renders VERBATIM with no injector (`task/types.ts:362`, `systemPrompt: string`). So the Dogfood implementer `config/agents/implementer.md` is a THIN ROLE DELTA — identity + only the Compass divergences the default gets wrong (async comms/no `ask`, one-slice-then-yield, jj-stacking push, operator-not-user) — dropping everything the default supplies and carrying no `[runtime-injected]` placeholders and no `lsp`/todo mandates (`task.enableLsp` defaults false, `settings-schema.ts:4528`; the wrapper COMPLETION already sets no-todo); the full copy-and-adapt of OMP's block-0 is kept as the FUTURE SEA-1717 standalone-container artifact (a REPLACE path absent at `cf048ca`), not the Dogfood deliverable. Corrects DL-134's "block-0" framing (the def is the delta, not the full block) | Active (Matt, 2026-08-05) | [manager prompt §Implementer block-0](product/compass-manager-prompt/design.md#implementer-block-0-dogfood-thin-role-delta--the-future-full-container) | ## UI shell | ID | Decision | Status | Record | | --- | --- | --- | --- | -| DL-030 | UI: the communication layer is the primary surface (comms-primary shell) | Superseded by DL-031 (Matt, 2026-07-06) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-031 | UI shell is board-primary: channel chat lives inside the board-primary workspace, not as the top-level surface | Active (Matt, 2026-07-12) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-032 | Compass state is canonical; the tracker is a projection of it | Superseded by DL-129 (Matt, 2026-08-04) | [ADE shell §D2](compass-ade-shell/design.md#d2--compass-state-is-canonical-the-tracker-is-a-projection) | -| DL-033 | The workstream lifecycle is Backlog→Todo→Queued→Blocked⇄In Progress→In Review→Done | Active (Matt, 2026-07-10) | [ADE shell §D1](compass-ade-shell/design.md#d1--workstream-state-model) | -| DL-034 | The right sidebar mirrors Orca; fleet + workstream conversations live there | Active (Matt, 2026-07-10) | [ADE shell §D5](compass-ade-shell/design.md#d5--right-sidebar-mirrors-orca) | -| DL-035 | The bottom dock is a tabbed Dispatcher + Warden surface | Superseded by DL-036 (Matt, 2026-07-11) | [ADE shell §D7](compass-ade-shell/design.md#d7--bottom-dock-is-tabbed-dispatcher--warden) | -| DL-036 | The bottom dock is folded into the right sidebar: one activity bar, one signal, the dock removed | Active (Matt, 2026-07-11) | [dock-in-sidebar §D1](compass-dock-in-sidebar/design.md#d1--one-activity-bar-one-signal-the-dock-state-is-removed) | -| DL-037 | Standalone channel asks are answerable wherever they are asked (first-responder-wins), not read-only-deferred | Active (Matt, 2026-07-20) | [ask-in-channel §The designed change](compass-ask-in-channel/design.md#the-designed-change) | -| DL-067 | The `workstream` concept is removed from the Compass UI entirely; the board unit becomes the canonical Compass `Issue` (and `PullRequest`) — the forge artifact's fields plus the Compass machinery (lifecycle state, priority, assignee, tracker projection), server-computed | Active (Matt, 2026-07-30) | [issue model §Approach](compass-issue-model/design.md#approach) | -| DL-068 | Agent attribution on issues and PRs is consumed from the canonical type's server-parsed `agent`/owner fields (parsed at ingestion per #995's stamping) and rendered as an untrusted claim, hedged unless the server's forge-login cross-check verifies it (DL-050, #995 OQ-1); the UI never stamps a header and never derives `assignee` (Compass truth) from `agent` (a parsed claim) | Superseded by DL-094 (Matt, 2026-08-01) | [issue model §Attribution](compass-issue-model/design.md#attribution-consumed-never-stamped) | -| DL-069 | Compass owns a single canonical `compass.v1` `Issue`/`PullRequest` type pair (forge fields + agent author/owner attribution + Compass machinery); the server translates raw forge data into these types at ingestion, the raw forge shape is never a proto/wire type, and the UI consumes only the generated canonical type from `@compass/client` | Active (Matt, 2026-07-31) | [issue model §The Compass Issue and PullRequest types](compass-issue-model/design.md#the-compass-issue-and-pullrequest-types) | -| DL-070 | The DL-033 issue lifecycle (its seven working states unchanged, extended by a terminal `ARCHIVED` state per DL-091) is server-authoritative: a server-side board projection — composing the existing `go/internal/board` recorded-state pattern and DL-055's board-as-local-index-scan — computes and streams the canonical type, moving DL-032's canonical Compass state server-side | Active (Matt, 2026-07-30) | [issue model §The server projection](compass-issue-model/design.md#the-server-projection) | -| DL-091 | Archiving a Compass issue is a lifecycle transition to a terminal `ARCHIVED` state via `UpdateIssueState`, not a separate `archived_at` marker field or a separate `ArchiveIssue` RPC; an archived issue drops off the active board and is listed in the Done view's Archived section, and every board item carries a forge identity (`ForgeRef` provider+host) so multi-forge artifacts never collide on `repo` alone | Superseded by DL-129 (Matt, 2026-08-04) | [issue model §The write path](compass-issue-model/design.md#the-write-path) | -| DL-094 | Compass agent attribution is a plain display fact, not a trust claim: `AgentAttribution` slims to `{agent_handle}` (field numbers 2–3 and names `owner_handle`/`verified` reserved), populated directly from the parsed owner header at ingestion with no forge-login cross-check and no population gating; the board and the forge-tool path both render the bare `@handle` with no hedge; owner is an account property (`AgentAccount.owner_user_id`), resolved server-side, never restated per artifact. Reverses DL-068's hedge-unless-verified board render and the verified/cross-check of DL-050 and #995 OQ-1 as applied to attribution display; routes around #1018/#1037 (unedited; no wire build shipped) | Superseded by DL-186 (Matt, 2026-08-07) | [attribution simplification §Approach](compass-attribution-simplification/design.md#approach) | -| DL-096 | Sidebar pinning is a user-configurable presentation layer over the agent set (the layer DL-095 names and defers): any agent can be pinned as a right-sidebar fleet tab, the hardcoded always-on Supervisor/Warden tabs and their `FleetTab` union literals are removed (no built-in privileged agent), the pin set is a per-user client-local UI preference (`localStorage`-backed; never DL-078's fleet-wide bundle; server per-user prefs a post-MVP seam), the default pin set is EMPTY, and the shell boots onto the first pin that resolves to a visible agent, else Status, instead of a special-cased Supervisor conversation | Active (Matt, 2026-08-01) | [sidebar pins §Approach](compass-sidebar-pins/design.md#approach) | -| DL-097 | The Bridge board splits into peer Issues/PRs tabs inside the board view (a Bridge-local tab signal, not a new `View` or a third `BoardMode`): the Issues tab is today's board ordered by Record C's `treeOrder`; the PRs tab is a flat one-row-per-OPEN-PR list (the `primaryPr` compression deliberately does not apply) grouped by assignee in `treeOrder` with the tab badge = the open-PR row count; issues ↔ PRs cross-link through the existing issue-keyed selection (`selectIssue`, no new PR-selection state); and the card's per-check pip strip collapses to a CI badge (the `ChecksSummary.state` roll-up) + a review badge (latest-per-author verdict, `changes_requested` > `approved` > `commented`) as pure `board-render.ts` helpers — a VIEW remodel consuming the frozen #1018 model, no proto/server/model change | Active (Matt, 2026-08-01) / PRs-tab flat-list clause superseded by DL-196 (Matt, 2026-08-16) | [board view §Approach](compass-board-view/design.md#approach) | -| DL-129 | The issue-state write model is agent-primary: the Compass UI is read-only for lifecycle state; agents set state via a sibling `BoardCall*` family on the `AgentGateway` socket relayed by `RelayBoardCall` (DL-049/DL-076 convention), and users set state in the external tracker, whose native status is ingested into the DL-070 server projection through the reverse `TrackerStatusMapping` (DL-053 poll; echo-suppressed in tracker-status space, tracker-sourced transitions never mirror back, stale polls dropped by a recency guard). All issues flow from the tracker (no Compass-native/unlinked issues in the MVP); `ARCHIVED` is not agent-only (a Done issue auto-transitions to `ARCHIVED` after 24h, a user reopen un-archives via ingestion); MVP write-authz is single-trust-domain (hierarchical scope is a filed follow-up over DL-095's tree). `UpdateIssueState` on `CompassService` is never built (no wire build shipped). Supersedes DL-091 (the `UpdateIssueState`-on-`CompassService` mechanism; archive-as-transition survives here) and DL-032 (the tracker is now also a state write source); DL-070/DL-033/DL-067 unchanged | Active (Matt, 2026-08-04) | [agent-primary lifecycle §Approach](compass-agent-primary-lifecycle/design.md#approach) | -| DL-113 | An unresolvable pinned agent does not vanish: the pin keeps its activity-bar item, its pane renders an "agent unreachable" state, and removal is a manual unpin only — a visibility fluctuation to unresolvable never auto-switches the active tab to `status` (the unpin-active→status fallback is retained, and the pane arm closes the Switch's no-default-arm gap) — amending DL-096's unresolvable-pin handling (the frozen record's §T2 filter and §T3 fluctuation-coercion clauses are superseded; DL-096's pinning-layer core stands) | Active (Matt, 2026-08-02) | [unreachable-pin amendment §Approach](compass-sidebar-pins-unreachable-amendment/design.md#approach) | -| DL-127 | The Compass UI shell adopts `@solidjs/router` in `HashRouter` mode (Matt's library ruling) emitting the frozen `#/channel//topic/` route shape for a client-only SPA in the Wails v3 webview (DL-110); and the URL becomes the source of truth for view + routed selection — the store derives `View` and routed memos from the matched route (route drives store, not store drives route), with `MemoryRouter` for deterministic tests | Active (Matt, 2026-08-03) | [shell routing §A2](compass-shell-routing/design.md#a2--source-of-truth-url-drives-the-store-decision) | -| DL-128 | The Compass UI adopts `@tanstack/solid-query` + `@connectrpc/connect-query-core` for server-state: one app-lifetime `QueryClient` created beside the store singleton in `index.tsx` and provided via the SolidJS `QueryClientProvider` (Solid adapter, never React); server-state reads move off the store onto query hooks over the generated Connect clients, the store keeping only client/UI state | Active (Matt, 2026-08-03) | [query layer §Approach](compass-ui-query-layer/design.md#approach) | -| DL-186 | Pre-dogfood proto wire-compat is stripped: all `reserved` markers removed across compass/v1, live fields densely renumbered (no holes), and the `buf breaking` CI gate removed (re-armed at GA / first pinned client). Reclaims AgentAttribution field numbers 2,3 (DL-094's forever-reservation) — DL-094's attribution-as-display-fact semantics are UNCHANGED (owner resolved on AgentAccount.owner_user_id, not per-artifact); only its wire-number reservation is dropped, safe because zero clients are deployed and nothing on disk is proto-encoded. | Active (Matt, 2026-08-07) | [attribution simplification §Approach](compass-attribution-simplification/design.md#approach) | -| DL-193 | The Compass UI's live agent roster is a reactive JOIN, not a `GetRoster`-as-roster replace: durable identity + tree come from the already-live `SubscribeComms` accounts (the single identity source — `RosterEntry` lacks `homeChannelId`/`kind` the UI requires), while ephemeral presence + activity come from a new `CommsState.presence` map seeded by one `GetRoster(scope: OWNER)` per snapshot boundary and tailed by the `AgentPresenceChanged` event the stream driver currently drops; `STUB_AGENTS` is demoted from live render source to the offline-store seed behind the store's reactive `agents` accessor (the `STUB_ISSUES` seam pattern), never rendered on a live connection | Active (Matt, 2026-08-16) | [live roster §Resolved decisions](compass-live-roster/design.md#resolved-decisions) | -| DL-194 | The presence→dot projection is the total 4-state mapping `WORKING→working, IDLE→idle, WAITING→waiting, OFFLINE→stopped` plus a defensive `UNSPECIFIED→undefined` (unreachable on the `GetRoster` path, which defaults every agent absent from its in-memory presence source to `OFFLINE`; the client `joinAgents` mirrors this at its own seam, mapping a presence-map miss — a snapshot-boundary race or a post-snapshot `accountChanged` arrival — to `stopped` rather than the components' `?? "idle"` fallback, so the absent→stopped invariant holds end-to-end); the 4-state enum cannot distinguish a deliberately-stopped agent from a never-started one, so a freshly-seeded-but-unstarted agent renders the "stopped" dot — accepted as a known day-one cost, with the terminated/never-started split owed to the deferred `AgentSessionStatus` lane, which is also the only source for the remaining four `AgentState` values (`done/paused/error/disconnected`) | Active (Matt, 2026-08-16) | [live roster §Resolved decisions](compass-live-roster/design.md#resolved-decisions) | -| DL-195 | `Agent.role`/`model`/`cwd` are optional view-model fields with no server source: a live agent renders without them (the role pip is render-gated on a present, non-worker role — never derived from tree position, since "has children" is not "supervisor"), and `terminals` is `[]` for live agents until a terminal stream exists | Active (Matt, 2026-08-16) | [live roster §Resolved decisions](compass-live-roster/design.md#resolved-decisions) | -| DL-196 | The Bridge PRs tab is board-ified: the flat one-row-per-open-PR assignee-grouped list (DL-097's PRs-tab clause) becomes the same swimlane grid the Issues tab uses, on PR-lifecycle columns (in progress → in review → ready to merge → merged); unresolved review threads gate a PR to "In review" (an approved + CI-green PR with open threads is not "Ready to merge"), and the "Merged" column shows a 1-day window computed server-side / in the store lane (the UI renders whatever merged rows the store hands it, implements no retention); supersedes only DL-097's flat-list clause — DL-097's Issues/PRs tab split, issue↔PR cross-link selection, and CI/review badge roll-up seams stay Active | Active (Matt, 2026-08-16) | [bridge re-clothe §Decisions](compass-bridge-reclothe/design.md#decisions-matt-ruled-2026-08-16-via-ask) | -| DL-197 | Bridge board cards adopt the DS `.cx-card` primitive with a board-scoped dense layout override; the priority left-stripe is retired in favor of the `.cx-card` selection left-rule (selection owns the left edge), and the quiet-key/bright-title hierarchy propagates to the shared Done-view card sub-parts (one convention, not two) | Active (Matt, 2026-08-16) | [bridge re-clothe §Approach](compass-bridge-reclothe/design.md#approach) | -| DL-198 | The advancing-card affordance ships as a dormant CSS hook (`.cx-card[data-advancing]` chase-light on existing motion tokens with a load-bearing reduced-motion `display:none` guard), wired to no live data until a store transition-timestamp source lands; the motion-spec addition routes to the D9/foundation motion lane, the data field to the store lane | Active (Matt, 2026-08-16) | [bridge re-clothe §Decisions](compass-bridge-reclothe/design.md#decisions-matt-ruled-2026-08-16-via-ask) | -| DL-199 | The Compass review/CI badge form is Option B — a pixel-art 1-bit glyph plus a fixed 2-character axis code (`CI` / `RV`) in the DS mono face, both in the status color, degrading to glyph-only (Option A) on cramped surfaces via `data-compact`; badge colors route onto the dedicated `--cx-ci-*` / `--cx-review-*` tier (off the raw `--cx-ok/error/warn` bypass) and the `commented` verdict maps to `--cx-review-pending` | Active (Matt, 2026-08-16) | [badge clarity §Decision](compass-badge-clarity/design.md#decision-matt-from-the-t1-render) | -| DL-207 | The apps/ui Solid v2 migration builds NOW on a migration branch against `solid-js 2.0.0-rc.0` (branch-only peer overrides), not deferred to GA: the two blocker deps gate the branch *merge* independently of RC-vs-GA, so the real fork was build-now vs build-lazily — build now for early de-risking signal, branch upkeep the accepted cost. v1-safe effect/batching prep (S1-S3) lands on main ahead of the branch. The RIG-2186 accounts-login greenfield is a new surface with no blocker deps and starts directly on Solid v2 (cross-issue, owned by RIG-2186 planning) | Active (Matt, 2026-08-18) | [solid v2 migration §Resolved decisions](compass-ui-solid-v2/design.md#resolved-decisions) | -| DL-208 | Both Solid-2 blocker deps are FORKED into the RigelBuild org and consumed as externalized pinned artifacts, never vendored into the compass tree (matching the org-wide fork-externalization ruling): `@tanstack/solid-virtual` is forked with Solid-2 support + an upstream PR to TanStack/virtual (a 136-line thin wrapper over the framework-agnostic `@tanstack/virtual-core`, likely to land), consumed via a `package.json` git ref (`github:RigelBuild/virtual`) until upstream merges then dropped; `solid-markdown` (effectively abandoned upstream) is forked-and-owned, published as `@rigelbuild/solid-markdown` with the `solid-js` 2.x peer bump + Solid-2 codemods (imports + effect lifecycle, no algorithmic rewrite, no in-repo AST renderer). Overrides this record's earlier adapter-over-core virtualizer recommendation | Active (Matt, 2026-08-18) / solid-markdown clause superseded by DL-218 (Matt, 2026-08-19) | [solid v2 migration §Resolved decisions](compass-ui-solid-v2/design.md#resolved-decisions) | -| DL-209 | The Wails packaged-shell seam under Solid 2 is low-risk-but-verified (no automation): the seam is Solid-free plain TS (`daemon-transport.ts` string-name `Call`/`Events`; `MarkdownText.tsx:1` `Browser.openExternal`), so effect-flush timing is the lesser risk; the packaged shell is the first place the babel-preset-solid 2 / vite-plugin-solid 3 / `@solidjs/web` production-build compilation and v2's render-root-owned delegated events run outside dev/happy-dom, so S7's manual packaged-shell smoke (RPC round-trip + openExternal) stays the mandatory gate — no automation justified for a one-shot migration | Active (Matt, 2026-08-18) | [solid v2 migration §Resolved decisions](compass-ui-solid-v2/design.md#resolved-decisions) | -| DL-218 | The owned `RigelBuild/solid-markdown` fork adopts upstream `andi23rosca/solid-markdown` #44 (the react-markdown-10 API rewrite — a third-party draft, upstream effectively inactive on it) + #45 (the bundle-deps jsdom-compat fix), re-ported to Solid 2 via a fork-local `src/jsx-runtime.ts` `jsx`/`jsxs`/`Fragment` triple over `createComponent`/`merge` + `@solidjs/web` `Dynamic` (solid-jsx dropped as Solid-1-bound), published as a clean `@rigelbuild/solid-markdown@3.0.0` (no `-rigel.N` suffix — the fork is ours and sets its own versions); this retires the fork's in-repo AST renderer in favor of the maintained `hast-util-to-jsx-runtime`. The apps/ui consumer injects @mention chips via a consumer-side rehype plugin over the existing `mentionRuns` splitter (the removed `text` component override), derives inline-vs-block code structurally via a `pre`/`code` override split (the removed `inline` prop), keeps `renderingStrategy="reconcile"` (un-deprecated in the owned fork), and adds a synchronous consumer-side `(lang, code)` highlight cache that `CodeBlock` reads at initial render (seeding highlighted HTML and bypassing the debounce + async `createResource` on a hit) to suppress the code-highlight flash caused by #44's per-tick component teardown (accepting marginal within-stream selection loss; the fine-grained-walker re-port is the escalation if it bites). Supersedes DL-208's `solid-markdown` clause ONLY (no-algorithmic-rewrite/no-in-repo-AST-renderer) — DL-208's `@tanstack/solid-virtual` clause and its org-wide fork-externalization stance stay Active | Active (Matt, 2026-08-19) | [markdown react10 §Approach](compass-ui-markdown-react10/design.md#approach) | +| DL-030 | UI: the communication layer is the primary surface (comms-primary shell) | Superseded by DL-031 (Matt, 2026-07-06) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-031 | UI shell is board-primary: channel chat lives inside the board-primary workspace, not as the top-level surface | Active (Matt, 2026-07-12) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-032 | Compass state is canonical; the tracker is a projection of it | Superseded by DL-129 (Matt, 2026-08-04) | [ADE shell §D2](product/compass-ade-shell/design.md#d2--compass-state-is-canonical-the-tracker-is-a-projection) | +| DL-033 | The workstream lifecycle is Backlog→Todo→Queued→Blocked⇄In Progress→In Review→Done | Active (Matt, 2026-07-10) | [ADE shell §D1](product/compass-ade-shell/design.md#d1--workstream-state-model) | +| DL-034 | The right sidebar mirrors Orca; fleet + workstream conversations live there | Active (Matt, 2026-07-10) | [ADE shell §D5](product/compass-ade-shell/design.md#d5--right-sidebar-mirrors-orca) | +| DL-035 | The bottom dock is a tabbed Dispatcher + Warden surface | Superseded by DL-036 (Matt, 2026-07-11) | [ADE shell §D7](product/compass-ade-shell/design.md#d7--bottom-dock-is-tabbed-dispatcher--warden) | +| DL-036 | The bottom dock is folded into the right sidebar: one activity bar, one signal, the dock removed | Active (Matt, 2026-07-11) | [dock-in-sidebar §D1](product/compass-dock-in-sidebar/design.md#d1--one-activity-bar-one-signal-the-dock-state-is-removed) | +| DL-037 | Standalone channel asks are answerable wherever they are asked (first-responder-wins), not read-only-deferred | Active (Matt, 2026-07-20) | [ask-in-channel §The designed change](product/compass-ask-in-channel/design.md#the-designed-change) | +| DL-067 | The `workstream` concept is removed from the Compass UI entirely; the board unit becomes the canonical Compass `Issue` (and `PullRequest`) — the forge artifact's fields plus the Compass machinery (lifecycle state, priority, assignee, tracker projection), server-computed | Active (Matt, 2026-07-30) | [issue model §Approach](product/compass-issue-model/design.md#approach) | +| DL-068 | Agent attribution on issues and PRs is consumed from the canonical type's server-parsed `agent`/owner fields (parsed at ingestion per #995's stamping) and rendered as an untrusted claim, hedged unless the server's forge-login cross-check verifies it (DL-050, #995 OQ-1); the UI never stamps a header and never derives `assignee` (Compass truth) from `agent` (a parsed claim) | Superseded by DL-094 (Matt, 2026-08-01) | [issue model §Attribution](product/compass-issue-model/design.md#attribution-consumed-never-stamped) | +| DL-069 | Compass owns a single canonical `compass.v1` `Issue`/`PullRequest` type pair (forge fields + agent author/owner attribution + Compass machinery); the server translates raw forge data into these types at ingestion, the raw forge shape is never a proto/wire type, and the UI consumes only the generated canonical type from `@compass/client` | Active (Matt, 2026-07-31) | [issue model §The Compass Issue and PullRequest types](product/compass-issue-model/design.md#the-compass-issue-and-pullrequest-types) | +| DL-070 | The DL-033 issue lifecycle (its seven working states unchanged, extended by a terminal `ARCHIVED` state per DL-091) is server-authoritative: a server-side board projection — composing the existing `go/internal/board` recorded-state pattern and DL-055's board-as-local-index-scan — computes and streams the canonical type, moving DL-032's canonical Compass state server-side | Active (Matt, 2026-07-30) | [issue model §The server projection](product/compass-issue-model/design.md#the-server-projection) | +| DL-091 | Archiving a Compass issue is a lifecycle transition to a terminal `ARCHIVED` state via `UpdateIssueState`, not a separate `archived_at` marker field or a separate `ArchiveIssue` RPC; an archived issue drops off the active board and is listed in the Done view's Archived section, and every board item carries a forge identity (`ForgeRef` provider+host) so multi-forge artifacts never collide on `repo` alone | Superseded by DL-129 (Matt, 2026-08-04) | [issue model §The write path](product/compass-issue-model/design.md#the-write-path) | +| DL-094 | Compass agent attribution is a plain display fact, not a trust claim: `AgentAttribution` slims to `{agent_handle}` (field numbers 2–3 and names `owner_handle`/`verified` reserved), populated directly from the parsed owner header at ingestion with no forge-login cross-check and no population gating; the board and the forge-tool path both render the bare `@handle` with no hedge; owner is an account property (`AgentAccount.owner_user_id`), resolved server-side, never restated per artifact. Reverses DL-068's hedge-unless-verified board render and the verified/cross-check of DL-050 and #995 OQ-1 as applied to attribution display; routes around #1018/#1037 (unedited; no wire build shipped) | Superseded by DL-186 (Matt, 2026-08-07) | [attribution simplification §Approach](product/compass-attribution-simplification/design.md#approach) | +| DL-096 | Sidebar pinning is a user-configurable presentation layer over the agent set (the layer DL-095 names and defers): any agent can be pinned as a right-sidebar fleet tab, the hardcoded always-on Supervisor/Warden tabs and their `FleetTab` union literals are removed (no built-in privileged agent), the pin set is a per-user client-local UI preference (`localStorage`-backed; never DL-078's fleet-wide bundle; server per-user prefs a post-MVP seam), the default pin set is EMPTY, and the shell boots onto the first pin that resolves to a visible agent, else Status, instead of a special-cased Supervisor conversation | Active (Matt, 2026-08-01) | [sidebar pins §Approach](product/compass-sidebar-pins/design.md#approach) | +| DL-097 | The Bridge board splits into peer Issues/PRs tabs inside the board view (a Bridge-local tab signal, not a new `View` or a third `BoardMode`): the Issues tab is today's board ordered by Record C's `treeOrder`; the PRs tab is a flat one-row-per-OPEN-PR list (the `primaryPr` compression deliberately does not apply) grouped by assignee in `treeOrder` with the tab badge = the open-PR row count; issues ↔ PRs cross-link through the existing issue-keyed selection (`selectIssue`, no new PR-selection state); and the card's per-check pip strip collapses to a CI badge (the `ChecksSummary.state` roll-up) + a review badge (latest-per-author verdict, `changes_requested` > `approved` > `commented`) as pure `board-render.ts` helpers — a VIEW remodel consuming the frozen #1018 model, no proto/server/model change | Active (Matt, 2026-08-01) / PRs-tab flat-list clause superseded by DL-196 (Matt, 2026-08-16) | [board view §Approach](product/compass-board-view/design.md#approach) | +| DL-129 | The issue-state write model is agent-primary: the Compass UI is read-only for lifecycle state; agents set state via a sibling `BoardCall*` family on the `AgentGateway` socket relayed by `RelayBoardCall` (DL-049/DL-076 convention), and users set state in the external tracker, whose native status is ingested into the DL-070 server projection through the reverse `TrackerStatusMapping` (DL-053 poll; echo-suppressed in tracker-status space, tracker-sourced transitions never mirror back, stale polls dropped by a recency guard). All issues flow from the tracker (no Compass-native/unlinked issues in the MVP); `ARCHIVED` is not agent-only (a Done issue auto-transitions to `ARCHIVED` after 24h, a user reopen un-archives via ingestion); MVP write-authz is single-trust-domain (hierarchical scope is a filed follow-up over DL-095's tree). `UpdateIssueState` on `CompassService` is never built (no wire build shipped). Supersedes DL-091 (the `UpdateIssueState`-on-`CompassService` mechanism; archive-as-transition survives here) and DL-032 (the tracker is now also a state write source); DL-070/DL-033/DL-067 unchanged | Active (Matt, 2026-08-04) | [agent-primary lifecycle §Approach](product/compass-agent-primary-lifecycle/design.md#approach) | +| DL-113 | An unresolvable pinned agent does not vanish: the pin keeps its activity-bar item, its pane renders an "agent unreachable" state, and removal is a manual unpin only — a visibility fluctuation to unresolvable never auto-switches the active tab to `status` (the unpin-active→status fallback is retained, and the pane arm closes the Switch's no-default-arm gap) — amending DL-096's unresolvable-pin handling (the frozen record's §T2 filter and §T3 fluctuation-coercion clauses are superseded; DL-096's pinning-layer core stands) | Active (Matt, 2026-08-02) | [unreachable-pin amendment §Approach](product/compass-sidebar-pins-unreachable-amendment/design.md#approach) | +| DL-127 | The Compass UI shell adopts `@solidjs/router` in `HashRouter` mode (Matt's library ruling) emitting the frozen `#/channel//topic/` route shape for a client-only SPA in the Wails v3 webview (DL-110); and the URL becomes the source of truth for view + routed selection — the store derives `View` and routed memos from the matched route (route drives store, not store drives route), with `MemoryRouter` for deterministic tests | Active (Matt, 2026-08-03) | [shell routing §A2](product/compass-shell-routing/design.md#a2--source-of-truth-url-drives-the-store-decision) | +| DL-128 | The Compass UI adopts `@tanstack/solid-query` + `@connectrpc/connect-query-core` for server-state: one app-lifetime `QueryClient` created beside the store singleton in `index.tsx` and provided via the SolidJS `QueryClientProvider` (Solid adapter, never React); server-state reads move off the store onto query hooks over the generated Connect clients, the store keeping only client/UI state | Active (Matt, 2026-08-03) | [query layer §Approach](product/compass-ui-query-layer/design.md#approach) | +| DL-186 | Pre-dogfood proto wire-compat is stripped: all `reserved` markers removed across compass/v1, live fields densely renumbered (no holes), and the `buf breaking` CI gate removed (re-armed at GA / first pinned client). Reclaims AgentAttribution field numbers 2,3 (DL-094's forever-reservation) — DL-094's attribution-as-display-fact semantics are UNCHANGED (owner resolved on AgentAccount.owner_user_id, not per-artifact); only its wire-number reservation is dropped, safe because zero clients are deployed and nothing on disk is proto-encoded. | Active (Matt, 2026-08-07) | [attribution simplification §Approach](product/compass-attribution-simplification/design.md#approach) | +| DL-193 | The Compass UI's live agent roster is a reactive JOIN, not a `GetRoster`-as-roster replace: durable identity + tree come from the already-live `SubscribeComms` accounts (the single identity source — `RosterEntry` lacks `homeChannelId`/`kind` the UI requires), while ephemeral presence + activity come from a new `CommsState.presence` map seeded by one `GetRoster(scope: OWNER)` per snapshot boundary and tailed by the `AgentPresenceChanged` event the stream driver currently drops; `STUB_AGENTS` is demoted from live render source to the offline-store seed behind the store's reactive `agents` accessor (the `STUB_ISSUES` seam pattern), never rendered on a live connection | Active (Matt, 2026-08-16) | [live roster §Resolved decisions](product/compass-live-roster/design.md#resolved-decisions) | +| DL-194 | The presence→dot projection is the total 4-state mapping `WORKING→working, IDLE→idle, WAITING→waiting, OFFLINE→stopped` plus a defensive `UNSPECIFIED→undefined` (unreachable on the `GetRoster` path, which defaults every agent absent from its in-memory presence source to `OFFLINE`; the client `joinAgents` mirrors this at its own seam, mapping a presence-map miss — a snapshot-boundary race or a post-snapshot `accountChanged` arrival — to `stopped` rather than the components' `?? "idle"` fallback, so the absent→stopped invariant holds end-to-end); the 4-state enum cannot distinguish a deliberately-stopped agent from a never-started one, so a freshly-seeded-but-unstarted agent renders the "stopped" dot — accepted as a known day-one cost, with the terminated/never-started split owed to the deferred `AgentSessionStatus` lane, which is also the only source for the remaining four `AgentState` values (`done/paused/error/disconnected`) | Active (Matt, 2026-08-16) | [live roster §Resolved decisions](product/compass-live-roster/design.md#resolved-decisions) | +| DL-195 | `Agent.role`/`model`/`cwd` are optional view-model fields with no server source: a live agent renders without them (the role pip is render-gated on a present, non-worker role — never derived from tree position, since "has children" is not "supervisor"), and `terminals` is `[]` for live agents until a terminal stream exists | Active (Matt, 2026-08-16) | [live roster §Resolved decisions](product/compass-live-roster/design.md#resolved-decisions) | +| DL-196 | The Bridge PRs tab is board-ified: the flat one-row-per-open-PR assignee-grouped list (DL-097's PRs-tab clause) becomes the same swimlane grid the Issues tab uses, on PR-lifecycle columns (in progress → in review → ready to merge → merged); unresolved review threads gate a PR to "In review" (an approved + CI-green PR with open threads is not "Ready to merge"), and the "Merged" column shows a 1-day window computed server-side / in the store lane (the UI renders whatever merged rows the store hands it, implements no retention); supersedes only DL-097's flat-list clause — DL-097's Issues/PRs tab split, issue↔PR cross-link selection, and CI/review badge roll-up seams stay Active | Active (Matt, 2026-08-16) | [bridge re-clothe §Decisions](product/compass-bridge-reclothe/design.md#decisions-matt-ruled-2026-08-16-via-ask) | +| DL-197 | Bridge board cards adopt the DS `.cx-card` primitive with a board-scoped dense layout override; the priority left-stripe is retired in favor of the `.cx-card` selection left-rule (selection owns the left edge), and the quiet-key/bright-title hierarchy propagates to the shared Done-view card sub-parts (one convention, not two) | Active (Matt, 2026-08-16) | [bridge re-clothe §Approach](product/compass-bridge-reclothe/design.md#approach) | +| DL-198 | The advancing-card affordance ships as a dormant CSS hook (`.cx-card[data-advancing]` chase-light on existing motion tokens with a load-bearing reduced-motion `display:none` guard), wired to no live data until a store transition-timestamp source lands; the motion-spec addition routes to the D9/foundation motion lane, the data field to the store lane | Active (Matt, 2026-08-16) | [bridge re-clothe §Decisions](product/compass-bridge-reclothe/design.md#decisions-matt-ruled-2026-08-16-via-ask) | +| DL-199 | The Compass review/CI badge form is Option B — a pixel-art 1-bit glyph plus a fixed 2-character axis code (`CI` / `RV`) in the DS mono face, both in the status color, degrading to glyph-only (Option A) on cramped surfaces via `data-compact`; badge colors route onto the dedicated `--cx-ci-*` / `--cx-review-*` tier (off the raw `--cx-ok/error/warn` bypass) and the `commented` verdict maps to `--cx-review-pending` | Active (Matt, 2026-08-16) | [badge clarity §Decision](product/compass-badge-clarity/design.md#decision-matt-from-the-t1-render) | +| DL-207 | The apps/ui Solid v2 migration builds NOW on a migration branch against `solid-js 2.0.0-rc.0` (branch-only peer overrides), not deferred to GA: the two blocker deps gate the branch *merge* independently of RC-vs-GA, so the real fork was build-now vs build-lazily — build now for early de-risking signal, branch upkeep the accepted cost. v1-safe effect/batching prep (S1-S3) lands on main ahead of the branch. The RIG-2186 accounts-login greenfield is a new surface with no blocker deps and starts directly on Solid v2 (cross-issue, owned by RIG-2186 planning) | Active (Matt, 2026-08-18) | [solid v2 migration §Resolved decisions](product/compass-ui-solid-v2/design.md#resolved-decisions) | +| DL-208 | Both Solid-2 blocker deps are FORKED into the RigelBuild org and consumed as externalized pinned artifacts, never vendored into the compass tree (matching the org-wide fork-externalization ruling): `@tanstack/solid-virtual` is forked with Solid-2 support + an upstream PR to TanStack/virtual (a 136-line thin wrapper over the framework-agnostic `@tanstack/virtual-core`, likely to land), consumed via a `package.json` git ref (`github:RigelBuild/virtual`) until upstream merges then dropped; `solid-markdown` (effectively abandoned upstream) is forked-and-owned, published as `@rigelbuild/solid-markdown` with the `solid-js` 2.x peer bump + Solid-2 codemods (imports + effect lifecycle, no algorithmic rewrite, no in-repo AST renderer). Overrides this record's earlier adapter-over-core virtualizer recommendation | Active (Matt, 2026-08-18) / solid-markdown clause superseded by DL-218 (Matt, 2026-08-19) | [solid v2 migration §Resolved decisions](product/compass-ui-solid-v2/design.md#resolved-decisions) | +| DL-209 | The Wails packaged-shell seam under Solid 2 is low-risk-but-verified (no automation): the seam is Solid-free plain TS (`daemon-transport.ts` string-name `Call`/`Events`; `MarkdownText.tsx:1` `Browser.openExternal`), so effect-flush timing is the lesser risk; the packaged shell is the first place the babel-preset-solid 2 / vite-plugin-solid 3 / `@solidjs/web` production-build compilation and v2's render-root-owned delegated events run outside dev/happy-dom, so S7's manual packaged-shell smoke (RPC round-trip + openExternal) stays the mandatory gate — no automation justified for a one-shot migration | Active (Matt, 2026-08-18) | [solid v2 migration §Resolved decisions](product/compass-ui-solid-v2/design.md#resolved-decisions) | +| DL-218 | The owned `RigelBuild/solid-markdown` fork adopts upstream `andi23rosca/solid-markdown` #44 (the react-markdown-10 API rewrite — a third-party draft, upstream effectively inactive on it) + #45 (the bundle-deps jsdom-compat fix), re-ported to Solid 2 via a fork-local `src/jsx-runtime.ts` `jsx`/`jsxs`/`Fragment` triple over `createComponent`/`merge` + `@solidjs/web` `Dynamic` (solid-jsx dropped as Solid-1-bound), published as a clean `@rigelbuild/solid-markdown@3.0.0` (no `-rigel.N` suffix — the fork is ours and sets its own versions); this retires the fork's in-repo AST renderer in favor of the maintained `hast-util-to-jsx-runtime`. The apps/ui consumer injects @mention chips via a consumer-side rehype plugin over the existing `mentionRuns` splitter (the removed `text` component override), derives inline-vs-block code structurally via a `pre`/`code` override split (the removed `inline` prop), keeps `renderingStrategy="reconcile"` (un-deprecated in the owned fork), and adds a synchronous consumer-side `(lang, code)` highlight cache that `CodeBlock` reads at initial render (seeding highlighted HTML and bypassing the debounce + async `createResource` on a hit) to suppress the code-highlight flash caused by #44's per-tick component teardown (accepting marginal within-stream selection loss; the fine-grained-walker re-port is the escalation if it bites). Supersedes DL-208's `solid-markdown` clause ONLY (no-algorithmic-rewrite/no-in-repo-AST-renderer) — DL-208's `@tanstack/solid-virtual` clause and its org-wide fork-externalization stance stay Active | Active (Matt, 2026-08-19) | [markdown react10 §Approach](product/compass-ui-markdown-react10/design.md#approach) | ## Threading & rendering | ID | Decision | Status | Record | | --- | --- | --- | --- | -| DL-038 | The session trace is a dedicated OMP-native opaque session stream, rendered by OMP's own renderer | Superseded by DL-039 (Matt, 2026-07-20) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-039 | Compass builds a first-party typed session renderer; session events cross a typed gRPC stream, not opaque bytes and explicitly not ACP | Active (Matt, 2026-07-20) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-040 | Threaded replies use a Slack-style side-thread panel keyed by a deterministic root id | Superseded by DL-098 (Matt, 2026-08-02) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-041 | The message surface is a virtualized thread list with streaming markdown (solid-markdown + Shiki), mention-first composition | Superseded by DL-098 (Matt, 2026-08-02) | [message surface rendering §Approach](compass-message-surface-rendering/design.md#approach) | -| DL-098 | Compass adopts Zulip's threading model: a channel is a collection of named topics and every message belongs to exactly one topic (`messages.topic_id NOT NULL`) and stores only that topic id — never a channel id; the channel is reached through `topics.channel_id` (so moving a topic between channels is a single-row update). `parent_message_id` and the message's channel container are removed outright (pre-dogfood: no reserved tombstone, field numbers reused). Topics are first-class (proto `Topic` + `topics` table), named, id-stable, in exactly one channel; posting is topic-mandatory via `topic_name` get-or-create (one call); there is no default, general, or catch-all topic anywhere — channels carry zero messages directly. Rename-to-existing merges topics; the delivery cursor stays per-(agent,channel) with topic as deliver-op metadata, its channel resolved through the topic join (clarifies DL-072). The pre-dogfood SQL migrations collapse to a single baseline (no data conversion). UI is Zulip two-level drill-in: a channel shows its topic index (no composer), a topic shows its messages + composer (no nested threading), the left sidebar lists a channel's recent topics. Reverses DL-040 (Slack side-thread panel) and DL-041 (virtualized thread list, re-pointed at the topic list) | Active (Matt, 2026-08-02) | [Zulip threading model §Decisions](compass-zulip-threading-model/design.md#decisions-ratified) | -| DL-099 | An agent's streamed turn does not write to comms at all: the SEA-1364 T3 conversation write-through (streamed-turn → home-channel comms auto-post) is removed. A comms `Message` is created only by an explicit `comms_post_message(topic)` call (agents) or the human client's PostMessage — the comms tool is the only agent comms-write path, and it carries a mandatory topic. The streamed turn survives in full on the session/trace surface (`SessionFrame.typed_event`). Structural enforcement of on-topic posting: an agent cannot flood a channel by talking, only by deliberately posting | Active (Matt, 2026-08-02) | [Zulip threading model §D7](compass-zulip-threading-model/design.md#d7--one-comms-write-path-the-streaming-write-through-is-removed-supersedes-sea-1364-t3) | +| DL-038 | The session trace is a dedicated OMP-native opaque session stream, rendered by OMP's own renderer | Superseded by DL-039 (Matt, 2026-07-20) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-039 | Compass builds a first-party typed session renderer; session events cross a typed gRPC stream, not opaque bytes and explicitly not ACP | Active (Matt, 2026-07-20) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-040 | Threaded replies use a Slack-style side-thread panel keyed by a deterministic root id | Superseded by DL-098 (Matt, 2026-08-02) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-041 | The message surface is a virtualized thread list with streaming markdown (solid-markdown + Shiki), mention-first composition | Superseded by DL-098 (Matt, 2026-08-02) | [message surface rendering §Approach](product/compass-message-surface-rendering/design.md#approach) | +| DL-098 | Compass adopts Zulip's threading model: a channel is a collection of named topics and every message belongs to exactly one topic (`messages.topic_id NOT NULL`) and stores only that topic id — never a channel id; the channel is reached through `topics.channel_id` (so moving a topic between channels is a single-row update). `parent_message_id` and the message's channel container are removed outright (pre-dogfood: no reserved tombstone, field numbers reused). Topics are first-class (proto `Topic` + `topics` table), named, id-stable, in exactly one channel; posting is topic-mandatory via `topic_name` get-or-create (one call); there is no default, general, or catch-all topic anywhere — channels carry zero messages directly. Rename-to-existing merges topics; the delivery cursor stays per-(agent,channel) with topic as deliver-op metadata, its channel resolved through the topic join (clarifies DL-072). The pre-dogfood SQL migrations collapse to a single baseline (no data conversion). UI is Zulip two-level drill-in: a channel shows its topic index (no composer), a topic shows its messages + composer (no nested threading), the left sidebar lists a channel's recent topics. Reverses DL-040 (Slack side-thread panel) and DL-041 (virtualized thread list, re-pointed at the topic list) | Active (Matt, 2026-08-02) | [Zulip threading model §Decisions](product/compass-zulip-threading-model/design.md#decisions-ratified) | +| DL-099 | An agent's streamed turn does not write to comms at all: the SEA-1364 T3 conversation write-through (streamed-turn → home-channel comms auto-post) is removed. A comms `Message` is created only by an explicit `comms_post_message(topic)` call (agents) or the human client's PostMessage — the comms tool is the only agent comms-write path, and it carries a mandatory topic. The streamed turn survives in full on the session/trace surface (`SessionFrame.typed_event`). Structural enforcement of on-topic posting: an agent cannot flood a channel by talking, only by deliberately posting | Active (Matt, 2026-08-02) | [Zulip threading model §D7](product/compass-zulip-threading-model/design.md#d7--one-comms-write-path-the-streaming-write-through-is-removed-supersedes-sea-1364-t3) | ## Ask contract | ID | Decision | Status | Record | | --- | --- | --- | --- | -| DL-042 | The UI pivots around the communication layer; the frozen single-question `compass.v1.Ask` is D5's contract child | Superseded by DL-043 (Matt, 2026-07-04) | [architecture lineage](compass-architecture-lineage/design.md) | -| DL-043 | Reshape `compass.v1.Ask` to `repeated AskQuestion` (Option A, buf-breaking), carrying all native axes + free-text | Active (Matt, 2026-07-15) | [ask typed derivation §Approach](compass-ask-typed-derivation.md#approach--option-a-reshape-ask--repeated-askquestion-buf-breaking) | -| DL-213 | Outbound realization of an ask moves off the dead AgentFrame conversation-frame path onto the live comms `PostMessage` lane: the `mapping.ts #deriveAsk` → AgentFrame derivation the ask-typed-derivation record specified is superseded by citation (the outbound `AgentFrame` oneof has no conversation/Ask variant — fields 1-2 REMOVED per F9, `agent.proto:46-85` — and `mapping.ts` has no ask arm). DL-043's `Ask = repeated AskQuestion` SHAPE stays Active and live — it is exactly the shape both lanes of DL-211 ride (`comms.proto:361-427`); only the derivation MECHANISM is dead | Active (Matt, 2026-08-18) | [ask comms round-trip §AgentFrame reconciliation](compass-ask-comms-roundtrip/design.md#the-agentframe-reconciliation-dl-043) | +| DL-042 | The UI pivots around the communication layer; the frozen single-question `compass.v1.Ask` is D5's contract child | Superseded by DL-043 (Matt, 2026-07-04) | [architecture lineage](product/compass-architecture-lineage/design.md) | +| DL-043 | Reshape `compass.v1.Ask` to `repeated AskQuestion` (Option A, buf-breaking), carrying all native axes + free-text | Active (Matt, 2026-07-15) | [ask typed derivation §Approach](product/compass-ask-typed-derivation.md#approach--option-a-reshape-ask--repeated-askquestion-buf-breaking) | +| DL-213 | Outbound realization of an ask moves off the dead AgentFrame conversation-frame path onto the live comms `PostMessage` lane: the `mapping.ts #deriveAsk` → AgentFrame derivation the ask-typed-derivation record specified is superseded by citation (the outbound `AgentFrame` oneof has no conversation/Ask variant — fields 1-2 REMOVED per F9, `agent.proto:46-85` — and `mapping.ts` has no ask arm). DL-043's `Ask = repeated AskQuestion` SHAPE stays Active and live — it is exactly the shape both lanes of DL-211 ride (`comms.proto:361-427`); only the derivation MECHANISM is dead | Active (Matt, 2026-08-18) | [ask comms round-trip §AgentFrame reconciliation](product/compass-ask-comms-roundtrip/design.md#the-agentframe-reconciliation-dl-043) | ## Desktop shell | ID | Decision | Status | Record | | --- | --- | --- | --- | -| DL-044 | The Tauri desktop shell is a thin webview→daemon shell over a swappable transport seam; the daemon spawns detached and outlives the shell | Superseded by DL-106 (Matt, 2026-08-02) | [Tauri shell §Approach](compass-tauri-shell.md#approach) | -| DL-106 | The Compass native app is one binary in two modes (embedded / native-client); the mode difference is confined to the connection provider and the stack supervisor, and nothing above the transport boundary assumes local | Superseded by DL-235 (Matt, 2026-08-23) | [native app §A1](compass-native-app/design.md#a1--one-binary-two-modes-mode--which-connection-the-resolver-produces) | -| DL-107 | One framework-neutral shell IPC contract (`compass_rpc` + `head\|body\|end\|error` frames) carries gRPC-Web over a custom `fetch` for both modes — embedded pumps to the UDS, native-client to the TLS network door with shell-side private-CA trust and a shell-injected bearer | Active (Matt, 2026-08-02) | [native app §A2](compass-native-app/design.md#a2--the-transport-seam-one-frame-contract-two-bridges) | -| DL-108 | Embedded lifecycle is a Go stack supervisor (`go/internal/stack` + `compass-stack up\|down\|status`) of spawned children (never in-process), linger-by-default, productizing the dogfood chain with a supervised private Postgres, expiry-aware cert rotation, and lockfiled attach | Active (Matt, 2026-08-02) | [native app §A3](compass-native-app/design.md#a3--embedded-lifecycle-a-go-stack-supervisor-spawned-by-the-shell) | -| DL-109 | Native-app mode selection is `$XDG_CONFIG_HOME/compass/app.toml` (absent → embedded default); the native-client bearer is entered in a connect screen and stored keychain-first (0600-file fallback), never in config-file or argv | Active (Matt, 2026-08-02) | [native app §A4](compass-native-app/design.md#a4--mode-selection-and-native-client-configuration) | -| DL-110 | The Compass native shell is Wails v3 (Go), its module under `go/` (`go/cmd/compass-app`) importing `go/internal/stack` and the bridge pump directly; re-decides DL-044's framework on the Go stack (Wails, not Tauri) | Active (Matt, 2026-08-02) | [native app §OQ1](compass-native-app/design.md#oq1--shell-framework-tauri-rust-vs-wails-go-vs-other--blocks-t3) | -| DL-111 | A new `compass.v1` `WhoAmI` RPC returns the caller's account id from its own credential (embedded: socket ambient-admin; native-client: bearer subject), retiring the parked `caller_account_id` seam and the connect-screen caller-id field | Active (Matt, 2026-08-02) | [native app §OQ7](compass-native-app/design.md#oq7--embedded-caller-identity-mechanism--blocks-t4-cross-lane-compass-server) | -| DL-112 | The `compass-agent` image is published to GHCR and `podman pull`ed by `compass-stack` at first run (not bundled in the app), making a GHCR publish lane for `compass-agent` a native-app packaging dependency | Active (Matt, 2026-08-02) | [native app §OQ6](compass-native-app/design.md#oq6--agent-image-distribution-for-embedded-mode--blocks-t4-reshapes-t6) | -| DL-183 | Cross-process embedded-stack teardown: `up` persists each supervised child's process-group ID plus a start-time identity token to an atomic `stack.pgids` record beside the lockfile; a fresh `down` refuses while an `up` holds the lock, then reads the record, verifies each group's identity before signaling, SIGTERMs each exact persisted pgid in reverse start order with bounded SIGKILL escalation, and confirms teardown per component (server/postgres socket quiescence, runner group-ESRCH) — scoped to the three supervised stack children (postgres, compass-server, compass-runner); live agent containers escape the process group via conmon double-fork and are OUT of scope (SEA-1884). Refines DL-108 (which stays Active) and realizes the frozen record's `down`-SIGTERMs-the-tree claim for the supervised children | Active (Matt, 2026-08-05) | [cross-process teardown §Approach](compass-stack-cross-process-teardown/design.md#approach--option-a-persist-child-pgids-at-up-down-signals-the-persisted-groups) | -| DL-214 | The T6 Linux app artifact is a versioned tarball of a nix-closure-backed bundle directory (store-rpathed binaries via the devenv.lock-pinned GTK closure + cc-wrapper, `.desktop` inside), not AppImage/`nix bundle`/`wails3 package`; no-nix-store end-user distribution is the A5 installer follow-up's concern, which wraps this same bundle dir | Active (Matt, 2026-08-19) | [packaging §A1](compass-native-packaging/design.md#a1--bundle-format-a-versioned-tarball-of-a-nix-closure-backed-bundle-dir-fork-1-resolved) | -| DL-215 | Bundle binary carriage is the sidecar `bin/` layout the shell already resolves (stack sibling + `dist` beside the executable), completed by the app prepending its executable dir to the spawned `compass-stack`'s PATH so the stack's LookPath children resolve in-bundle — never Go `embed` of ELF sidecars, never Wails asset bundling | Superseded by DL-238 (Matt, 2026-08-23) | [packaging §A2](compass-native-packaging/design.md#a2--binary-embedding-sidecar-bin-layout--path-threading-fork-2-resolved) | -| DL-216 | The bundle build is a moon-registered project (`compass-app-bundle`) riding affected-detection per-PR and the unconditional main/nightly full sweep — the `compass-agent-image` heavy-build precedent — with a built-in completeness sanity gate (binaries present, uniform `--version` stamp, dist present); never a per-PR unconditional build, never a ci.yml-enumerated job | Active (Matt, 2026-08-19) | [packaging §A4](compass-native-packaging/design.md#a4--ci-cadence-affected-gated-per-pr-unconditional-on-main--nightly-fork-3-resolved) | -| DL-217 | Postgres tooling (`postgres`/`initdb`/`createdb`) ships in the bundle `bin/` from the devenv.lock-pinned bare `postgresql` attr, leaving rootless podman as the sole host prerequisite of the packaged embedded mode | Superseded by DL-238 (Matt, 2026-08-23) | [packaging §OQ1](compass-native-packaging/design.md#oq1-load-bearing-for-matt--postgres-tooling-bundled-or-host-prerequisite) | -| DL-235 | The Compass native app is CLIENT-ONLY: `compass-app` retires embedded mode entirely (supervisor invocation, host preflight, UDS bridge target, embedded config arm) and connects exclusively over the authenticated TLS door to a headless Compass stack — normally on a dedicated KVM-capable machine, or the same box via `compass-stack up` + `https://localhost`; driven by the microVM Runner's KVM floor retiring local agent execution. Supersedes DL-106 (dual-mode charter) | Active (Matt, 2026-08-23) | [client-only §A1](compass-native-client-only/design.md#a1--thesis-compass-app-is-a-native-client-only-binary) | -| DL-236 | `compass-stack` survives the app's retirement of embedded mode as the standalone headless single-user bring-up CLI (`up`/`down`/`status`, DL-183 teardown intact); the app never spawns, supervises, or tears down a stack. Refines DL-108 (which stays Active — the supervisor design lives; only the app's shell-spawn invocation retires) | Active (Matt, 2026-08-23) | [client-only §A1](compass-native-client-only/design.md#a1--thesis-compass-app-is-a-native-client-only-binary) | -| DL-237 | app.toml is client-only: absent or `mode="client"` → client (`server_url` required); `mode="embedded"` is a legible retirement error, never a compatibility arm; the `--mode`/`$COMPASS_APP_MODE` override retires with the second mode. Supersedes the embedded-default mode-selection half of DL-109 (whose keychain-first bearer clause stays Active) | Active (Matt, 2026-08-23) | [client-only §A3](compass-native-client-only/design.md#a3--appconfig-the-clean-cut-client-is-the-only-mode) | -| DL-238 | The app bundle is the THIN CLIENT: `compass-app` + `dist` + `.desktop` + LICENSE, no sidecar binaries, no postgres tooling; headless-stack distribution (`compass-stack`+`compass-postgres` onto the dedicated machine) is a releases-lane follow-up, and RIG-2477 re-scopes to client-app release artifacts with macOS as the first new target. Supersedes DL-215 (sidecar `bin/` + PATH threading) and DL-217 (bundled postgres tooling) | Active (Matt, 2026-08-23) | [client-only §A4](compass-native-client-only/design.md#a4--cutover-plan-sequenced-clean-no-shims) | +| DL-044 | The Tauri desktop shell is a thin webview→daemon shell over a swappable transport seam; the daemon spawns detached and outlives the shell | Superseded by DL-106 (Matt, 2026-08-02) | [Tauri shell §Approach](product/compass-tauri-shell.md#approach) | +| DL-106 | The Compass native app is one binary in two modes (embedded / native-client); the mode difference is confined to the connection provider and the stack supervisor, and nothing above the transport boundary assumes local | Superseded by DL-235 (Matt, 2026-08-23) | [native app §A1](product/compass-native-app/design.md#a1--one-binary-two-modes-mode--which-connection-the-resolver-produces) | +| DL-107 | One framework-neutral shell IPC contract (`compass_rpc` + `head\|body\|end\|error` frames) carries gRPC-Web over a custom `fetch` for both modes — embedded pumps to the UDS, native-client to the TLS network door with shell-side private-CA trust and a shell-injected bearer | Active (Matt, 2026-08-02) | [native app §A2](product/compass-native-app/design.md#a2--the-transport-seam-one-frame-contract-two-bridges) | +| DL-108 | Embedded lifecycle is a Go stack supervisor (`go/internal/stack` + `compass-stack up\|down\|status`) of spawned children (never in-process), linger-by-default, productizing the dogfood chain with a supervised private Postgres, expiry-aware cert rotation, and lockfiled attach | Active (Matt, 2026-08-02) | [native app §A3](product/compass-native-app/design.md#a3--embedded-lifecycle-a-go-stack-supervisor-spawned-by-the-shell) | +| DL-109 | Native-app mode selection is `$XDG_CONFIG_HOME/compass/app.toml` (absent → embedded default); the native-client bearer is entered in a connect screen and stored keychain-first (0600-file fallback), never in config-file or argv | Active (Matt, 2026-08-02) | [native app §A4](product/compass-native-app/design.md#a4--mode-selection-and-native-client-configuration) | +| DL-110 | The Compass native shell is Wails v3 (Go), its module under `go/` (`go/cmd/compass-app`) importing `go/internal/stack` and the bridge pump directly; re-decides DL-044's framework on the Go stack (Wails, not Tauri) | Active (Matt, 2026-08-02) | [native app §OQ1](product/compass-native-app/design.md#oq1--shell-framework-tauri-rust-vs-wails-go-vs-other--blocks-t3) | +| DL-111 | A new `compass.v1` `WhoAmI` RPC returns the caller's account id from its own credential (embedded: socket ambient-admin; native-client: bearer subject), retiring the parked `caller_account_id` seam and the connect-screen caller-id field | Active (Matt, 2026-08-02) | [native app §OQ7](product/compass-native-app/design.md#oq7--embedded-caller-identity-mechanism--blocks-t4-cross-lane-compass-server) | +| DL-112 | The `compass-agent` image is published to GHCR and `podman pull`ed by `compass-stack` at first run (not bundled in the app), making a GHCR publish lane for `compass-agent` a native-app packaging dependency | Active (Matt, 2026-08-02) | [native app §OQ6](product/compass-native-app/design.md#oq6--agent-image-distribution-for-embedded-mode--blocks-t4-reshapes-t6) | +| DL-183 | Cross-process embedded-stack teardown: `up` persists each supervised child's process-group ID plus a start-time identity token to an atomic `stack.pgids` record beside the lockfile; a fresh `down` refuses while an `up` holds the lock, then reads the record, verifies each group's identity before signaling, SIGTERMs each exact persisted pgid in reverse start order with bounded SIGKILL escalation, and confirms teardown per component (server/postgres socket quiescence, runner group-ESRCH) — scoped to the three supervised stack children (postgres, compass-server, compass-runner); live agent containers escape the process group via conmon double-fork and are OUT of scope (SEA-1884). Refines DL-108 (which stays Active) and realizes the frozen record's `down`-SIGTERMs-the-tree claim for the supervised children | Active (Matt, 2026-08-05) | [cross-process teardown §Approach](product/compass-stack-cross-process-teardown/design.md#approach--option-a-persist-child-pgids-at-up-down-signals-the-persisted-groups) | +| DL-214 | The T6 Linux app artifact is a versioned tarball of a nix-closure-backed bundle directory (store-rpathed binaries via the devenv.lock-pinned GTK closure + cc-wrapper, `.desktop` inside), not AppImage/`nix bundle`/`wails3 package`; no-nix-store end-user distribution is the A5 installer follow-up's concern, which wraps this same bundle dir | Active (Matt, 2026-08-19) | [packaging §A1](product/compass-native-packaging/design.md#a1--bundle-format-a-versioned-tarball-of-a-nix-closure-backed-bundle-dir-fork-1-resolved) | +| DL-215 | Bundle binary carriage is the sidecar `bin/` layout the shell already resolves (stack sibling + `dist` beside the executable), completed by the app prepending its executable dir to the spawned `compass-stack`'s PATH so the stack's LookPath children resolve in-bundle — never Go `embed` of ELF sidecars, never Wails asset bundling | Superseded by DL-238 (Matt, 2026-08-23) | [packaging §A2](product/compass-native-packaging/design.md#a2--binary-embedding-sidecar-bin-layout--path-threading-fork-2-resolved) | +| DL-216 | The bundle build is a moon-registered project (`compass-app-bundle`) riding affected-detection per-PR and the unconditional main/nightly full sweep — the `compass-agent-image` heavy-build precedent — with a built-in completeness sanity gate (binaries present, uniform `--version` stamp, dist present); never a per-PR unconditional build, never a ci.yml-enumerated job | Active (Matt, 2026-08-19) | [packaging §A4](product/compass-native-packaging/design.md#a4--ci-cadence-affected-gated-per-pr-unconditional-on-main--nightly-fork-3-resolved) | +| DL-217 | Postgres tooling (`postgres`/`initdb`/`createdb`) ships in the bundle `bin/` from the devenv.lock-pinned bare `postgresql` attr, leaving rootless podman as the sole host prerequisite of the packaged embedded mode | Superseded by DL-238 (Matt, 2026-08-23) | [packaging §OQ1](product/compass-native-packaging/design.md#oq1-load-bearing-for-matt--postgres-tooling-bundled-or-host-prerequisite) | +| DL-235 | The Compass native app is CLIENT-ONLY: `compass-app` retires embedded mode entirely (supervisor invocation, host preflight, UDS bridge target, embedded config arm) and connects exclusively over the authenticated TLS door to a headless Compass stack — normally on a dedicated KVM-capable machine, or the same box via `compass-stack up` + `https://localhost`; driven by the microVM Runner's KVM floor retiring local agent execution. Supersedes DL-106 (dual-mode charter) | Active (Matt, 2026-08-23) | [client-only §A1](product/compass-native-client-only/design.md#a1--thesis-compass-app-is-a-native-client-only-binary) | +| DL-236 | `compass-stack` survives the app's retirement of embedded mode as the standalone headless single-user bring-up CLI (`up`/`down`/`status`, DL-183 teardown intact); the app never spawns, supervises, or tears down a stack. Refines DL-108 (which stays Active — the supervisor design lives; only the app's shell-spawn invocation retires) | Active (Matt, 2026-08-23) | [client-only §A1](product/compass-native-client-only/design.md#a1--thesis-compass-app-is-a-native-client-only-binary) | +| DL-237 | app.toml is client-only: absent or `mode="client"` → client (`server_url` required); `mode="embedded"` is a legible retirement error, never a compatibility arm; the `--mode`/`$COMPASS_APP_MODE` override retires with the second mode. Supersedes the embedded-default mode-selection half of DL-109 (whose keychain-first bearer clause stays Active) | Active (Matt, 2026-08-23) | [client-only §A3](product/compass-native-client-only/design.md#a3--appconfig-the-clean-cut-client-is-the-only-mode) | +| DL-238 | The app bundle is the THIN CLIENT: `compass-app` + `dist` + `.desktop` + LICENSE, no sidecar binaries, no postgres tooling; headless-stack distribution (`compass-stack`+`compass-postgres` onto the dedicated machine) is a releases-lane follow-up, and RIG-2477 re-scopes to client-app release artifacts with macOS as the first new target. Supersedes DL-215 (sidecar `bin/` + PATH threading) and DL-217 (bundled postgres tooling) | Active (Matt, 2026-08-23) | [client-only §A4](product/compass-native-client-only/design.md#a4--cutover-plan-sequenced-clean-no-shims) | ## Agent batteries | ID | Decision | Status | Record | | --- | --- | --- | --- | -| DL-140 | The default Compass batteries bundle is LANGUAGE-NEUTRAL: no `go-*` rules or `golang-*` skills ship by default — for Dogfood the user adds language skills via the normal user-skill path; language packs (per-repo language → skill-pack selection) are the SEA-1739 Beta feature, an additive seam on the same bundle delivery surface | Active (Matt, 2026-08-05) | [batteries §BI-3](compass-batteries-included/design.md#decision-bi-3--language-neutral-default-packs-are-beta-dl-140) | -| DL-141 | `delegated-implementation` ships as NO separate Compass skill: its when-to-delegate litmus, review-every-diff discipline, and brief contract fold into the `management-trees` skill's delegation-mechanics section (SEA-1732 T5), with the OMP tier naming (`implement`/`implement-hard`, Opus thinking levels) stripped in favor of the `task` mechanism + standing subagent defs (DL-134) | Active (Matt, 2026-08-05) | [batteries §BI-2](compass-batteries-included/design.md#decision-bi-2--three-sourcing-modes-one-per-manifest-row) | -| DL-142 | The wave `version-control` rule's three footguns (auto-amend; submit-is-the-only-push-path; review-fixes-are-additive-never-amend+force-push) fold into ONE Compass always-apply rule that keeps the jj model + additive-fixes + never-`git push` and keeps `jj-vine submit` as the push path (Compass KEEPS jj-vine as its stacked-PR tool — submit, PR-tree-in-description, `gh stack` forge integration — retargeted to the Compass repo; the `jj-hp` push-guard is Compass's own push-authorization concern, resolved in SEA-1732 T8); the adapted skill is named `jj` (Compass names skills on their own merits, not by mirroring the wave) — renaming SEA-1732 T8's `jj-stacking` (that frozen record's `jj-stacking` text is superseded by this citation per the immutable-cell convention, §conventions); and there is no separate `stacking` skill (stacking lives in the one adapted `jj` skill, SEA-1732 T8) | Active (Matt, 2026-08-05) | [batteries §BI-2](compass-batteries-included/design.md#decision-bi-2--three-sourcing-modes-one-per-manifest-row) | -| DL-143 | Eight wave artifacts are EXCLUDED from the Compass batteries as wave-specific infrastructure that would confuse a Compass agent — `multi-agent-wave`, `spawn-agent`, `wave-status-sync`, `session-recovery`, `nix-hosts`, `github-pr-review` (folds into the adapted `review`), `woodpecker-ci` (Compass CI = GitHub Actions), `zellij-session-safety` (Compass agents are session-isolated); exclusion is curation, not deferral — a future need routes through a new decision row | Active (Matt, 2026-08-05) | [batteries §BI-4](compass-batteries-included/design.md#decision-bi-4--the-exclusion-set-dl-143) | -| DL-144 | Every forwarded always-apply rule in the Compass batteries self-scopes by ROLE in its authored body: the `task` executor forwards parent session rules into every subagent (`executor.ts:2793`) but NOT the session `customTools` (`executor.ts:2829`, MCP-proxy tools only), so a Manager always-apply rule rides every implementer-subagent turn without the Manager affordances it assumes — `hold-your-lane`, `decision-authority`, and `own-your-issue` are actively wrong there. Each such rule's body branches explicitly (hands-subagent behavior AND Manager behavior); role-invariant rules need no branch. This is body-level self-scoping, NOT per-role delivery (the SEA-1724 seam). Resolves batteries OQ-1 | Active (Matt, 2026-08-05) | [batteries §BC-7](compass-batteries-included/design.md#global-constraints) | -| DL-145 | The B1 `version-control` always-apply-rule fold (DL-142) is hard-ordered AFTER SEA-1732 T8: it ships with or after T8, never before, and carries no `[TODO T8]` placeholder — an always-apply rule injected full-text every turn (BC-6) cannot ship the `never git push` invariant with only a placeholder where the one correct submit verb goes; T8 names the Compass submit path first, B1 writes it in (same BC-3 posture B5 takes with SEA-1734) | Active (Matt, 2026-08-05) | [batteries §Tasks B1](compass-batteries-included/design.md#tasks) | -| DL-146 | The Compass batteries ship `process-safety` at RULEBOOK tier (not always-apply as the wave file is): per-container session isolation (one container per standing agent, DL-143) removes the cross-agent/host clobber blast radius that justified `alwaysApply: true` on the shared wave box; the intra-container sibling-process residual (a Manager and its in-process `task` subagents share one container) is covered by rulebook forwarding (BC-7) + on-demand pull before a destructive kill, not always-on injection. Resolves batteries OQ-3 | Active (Matt, 2026-08-05) | [batteries §Implementer domain rules](compass-batteries-included/design.md#implementer--domain-rules-configrulesmd-rulebook-tier) | -| DL-147 | The default Compass batteries are STACK-neutral, not merely language-neutral: no default battery names a language- or CI-engine-specific command as normative (illustrative tables permitted, marked). devenv/direnv is a deliberate product baseline (kept, B3); GitHub-Actions-specific `ci-failure-triage` hooks come OUT of the default skill and become SEA-1739 pack territory (same seam shape as a language pack), the default skill shipping the CI-engine-neutral 4-step triage discipline. Refines DL-140, and reverses DL-143's `woodpecker-ci`-row parenthetical rationale (`Compass CI = GitHub Actions`) — that parenthetical stays verbatim in DL-143 per the immutable-cell convention (§conventions), its normative posture superseded here; sharpens BC-4 to a checkable gate | Active (Matt, 2026-08-05) | [batteries §BI-3](compass-batteries-included/design.md#decision-bi-3--language-neutral-default-packs-are-beta-dl-140) | +| DL-140 | The default Compass batteries bundle is LANGUAGE-NEUTRAL: no `go-*` rules or `golang-*` skills ship by default — for Dogfood the user adds language skills via the normal user-skill path; language packs (per-repo language → skill-pack selection) are the SEA-1739 Beta feature, an additive seam on the same bundle delivery surface | Active (Matt, 2026-08-05) | [batteries §BI-3](product/compass-batteries-included/design.md#decision-bi-3--language-neutral-default-packs-are-beta-dl-140) | +| DL-141 | `delegated-implementation` ships as NO separate Compass skill: its when-to-delegate litmus, review-every-diff discipline, and brief contract fold into the `management-trees` skill's delegation-mechanics section (SEA-1732 T5), with the OMP tier naming (`implement`/`implement-hard`, Opus thinking levels) stripped in favor of the `task` mechanism + standing subagent defs (DL-134) | Active (Matt, 2026-08-05) | [batteries §BI-2](product/compass-batteries-included/design.md#decision-bi-2--three-sourcing-modes-one-per-manifest-row) | +| DL-142 | The wave `version-control` rule's three footguns (auto-amend; submit-is-the-only-push-path; review-fixes-are-additive-never-amend+force-push) fold into ONE Compass always-apply rule that keeps the jj model + additive-fixes + never-`git push` and keeps `jj-vine submit` as the push path (Compass KEEPS jj-vine as its stacked-PR tool — submit, PR-tree-in-description, `gh stack` forge integration — retargeted to the Compass repo; the `jj-hp` push-guard is Compass's own push-authorization concern, resolved in SEA-1732 T8); the adapted skill is named `jj` (Compass names skills on their own merits, not by mirroring the wave) — renaming SEA-1732 T8's `jj-stacking` (that frozen record's `jj-stacking` text is superseded by this citation per the immutable-cell convention, §conventions); and there is no separate `stacking` skill (stacking lives in the one adapted `jj` skill, SEA-1732 T8) | Active (Matt, 2026-08-05) | [batteries §BI-2](product/compass-batteries-included/design.md#decision-bi-2--three-sourcing-modes-one-per-manifest-row) | +| DL-143 | Eight wave artifacts are EXCLUDED from the Compass batteries as wave-specific infrastructure that would confuse a Compass agent — `multi-agent-wave`, `spawn-agent`, `wave-status-sync`, `session-recovery`, `nix-hosts`, `github-pr-review` (folds into the adapted `review`), `woodpecker-ci` (Compass CI = GitHub Actions), `zellij-session-safety` (Compass agents are session-isolated); exclusion is curation, not deferral — a future need routes through a new decision row | Active (Matt, 2026-08-05) | [batteries §BI-4](product/compass-batteries-included/design.md#decision-bi-4--the-exclusion-set-dl-143) | +| DL-144 | Every forwarded always-apply rule in the Compass batteries self-scopes by ROLE in its authored body: the `task` executor forwards parent session rules into every subagent (`executor.ts:2793`) but NOT the session `customTools` (`executor.ts:2829`, MCP-proxy tools only), so a Manager always-apply rule rides every implementer-subagent turn without the Manager affordances it assumes — `hold-your-lane`, `decision-authority`, and `own-your-issue` are actively wrong there. Each such rule's body branches explicitly (hands-subagent behavior AND Manager behavior); role-invariant rules need no branch. This is body-level self-scoping, NOT per-role delivery (the SEA-1724 seam). Resolves batteries OQ-1 | Active (Matt, 2026-08-05) | [batteries §BC-7](product/compass-batteries-included/design.md#global-constraints) | +| DL-145 | The B1 `version-control` always-apply-rule fold (DL-142) is hard-ordered AFTER SEA-1732 T8: it ships with or after T8, never before, and carries no `[TODO T8]` placeholder — an always-apply rule injected full-text every turn (BC-6) cannot ship the `never git push` invariant with only a placeholder where the one correct submit verb goes; T8 names the Compass submit path first, B1 writes it in (same BC-3 posture B5 takes with SEA-1734) | Active (Matt, 2026-08-05) | [batteries §Tasks B1](product/compass-batteries-included/design.md#tasks) | +| DL-146 | The Compass batteries ship `process-safety` at RULEBOOK tier (not always-apply as the wave file is): per-container session isolation (one container per standing agent, DL-143) removes the cross-agent/host clobber blast radius that justified `alwaysApply: true` on the shared wave box; the intra-container sibling-process residual (a Manager and its in-process `task` subagents share one container) is covered by rulebook forwarding (BC-7) + on-demand pull before a destructive kill, not always-on injection. Resolves batteries OQ-3 | Active (Matt, 2026-08-05) | [batteries §Implementer domain rules](product/compass-batteries-included/design.md#implementer--domain-rules-configrulesmd-rulebook-tier) | +| DL-147 | The default Compass batteries are STACK-neutral, not merely language-neutral: no default battery names a language- or CI-engine-specific command as normative (illustrative tables permitted, marked). devenv/direnv is a deliberate product baseline (kept, B3); GitHub-Actions-specific `ci-failure-triage` hooks come OUT of the default skill and become SEA-1739 pack territory (same seam shape as a language pack), the default skill shipping the CI-engine-neutral 4-step triage discipline. Refines DL-140, and reverses DL-143's `woodpecker-ci`-row parenthetical rationale (`Compass CI = GitHub Actions`) — that parenthetical stays verbatim in DL-143 per the immutable-cell convention (§conventions), its normative posture superseded here; sharpens BC-4 to a checkable gate | Active (Matt, 2026-08-05) | [batteries §BI-3](product/compass-batteries-included/design.md#decision-bi-3--language-neutral-default-packs-are-beta-dl-140) | ## UX foundation (design system) | ID | Decision | Status | Record | | --- | --- | --- | --- | -| DL-148 | Compass visual language is the frozen Rigel chase-light/dot-matrix spine worn at ADE density: surface-color elevation, blue-rationed interaction contrast (purple mark-only), 4px-grid density, mono-as-identity per the three-face type system, keyboard-answerable everything (D1) | Active (Matt, 2026-08-05) | [ux foundation §D1](compass-ux-foundation/design.md#d1--visual-language-the-frozen-rigel-spine-worn-at-ade-density) | -| DL-149 | Three-tier token model: `--rigel-*` primitives mirrored verbatim from the frozen brand token set (no invented names, no violet) → `--cx-*` semantic tier → scale tokens; one downward consumption rule (component CSS names only `--cx-*`, so the brand motion primitives are aliased into `--cx-motion-slow`/`--cx-ease-*`/`--cx-pulse-*`/`--cx-stream-char-ms`/`--cx-cursor-blink`); `[data-theme]` indirection keeping the light pair open; agent-state colors per brand (working `#addb67` green, done cyan, waiting/disconnected amber, idle/paused/stopped mute); issue lanes remapped off the dead violet (D2) | Active (Matt, 2026-08-05) | [ux foundation §D2](compass-ux-foundation/design.md#d2--token-model-three-tiers-one-consumption-rule) | -| DL-150 | First-party component system of ~20 primitives specified as class + `data-*` visual contracts with six mandatory states; the state dot consumes the frozen brand eight-glyph vocabulary (working `»`, idle 3×3 block, waiting `?`, done tick, paused bars, stopped hollow square, error `!`, disconnected broken square) as 9×9 crispEdges SVG; Kobalte scoped to a11y-hard behavior only (D3) | Active (Matt, 2026-08-05) | [ux foundation §D3](compass-ux-foundation/design.md#d3--component-system-a-small-first-party-set-with-class--data--visual-contracts) | -| DL-151 | Focus model: the single upstream-frozen `--cx-focus-ring` (2px solid `--rigel-blue`) on `:focus-visible`, four interactive shell focus zones (left/main/right/topbar; the usage bar is a display-only landmark until it gains a control) with roving tabindex, pane-focus rule, escape ladder (D4) | Active (Matt, 2026-08-05) | [ux foundation §D4](compass-ux-foundation/design.md#d4--focus-model-one-ring-spatial-focus-zones-roving-tabindex) | -| DL-152 | Command palette (Cmd/Ctrl-K, registry-backed, actions + destinations) and global keymap (direct chords) as first-class surfaces; every primary action registers a command; carried intact across the brand freeze (D5) | Active (Matt, 2026-08-05) | [ux foundation §D5](compass-ux-foundation/design.md#d5--command-palette--global-keymap-the-keyboard-is-a-first-class-surface) | -| DL-153 | The frozen IA renders through the component system surface-by-surface (agent tree, pinned right sidebar, Issues/PRs board, channel→topic comms, agent workspace = home channel + session trace) in BOTH render hosts (Wails desktop app + browser); four primary surfaces (Bridge board, Manager tree, channels+threads, session trace) carry an explicit excellence bar with concrete starting points (the Rigel-site mockups, Zulip's threading UX, the brand streaming treatment) (D6) | Active (Matt, 2026-08-05) | [ux foundation §D6](compass-ux-foundation/design.md#d6--rendering-the-frozen-ia-surface-by-surface-composition) | -| DL-154 | Delivery layout: in-tree `apps/ui/src/design/` (tokens.css/base.css/components/) + `keyboard/` contracts; stylelint guard bans raw hex, `--rigel-*`, and literal durations outside tokens.css, with one narrow allowlist — the mark component's CSS may name `--rigel-purple` directly (purple is never aliased into `--cx-*`); no token package, no W3C token source (D7) | Active (Matt, 2026-08-05) | [ux foundation §D7](compass-ux-foundation/design.md#d7--delivery-in-tree-token--component-layout-under-appsuisrc) | -| DL-155 | Brand seam: primitives mirrored with provenance from the frozen spec; the mark per the brand surface table is the one purple per surface with the 16px floor honored; Compass-owned `--cx-ed-*` editor-theme mapping from the Night Owl syntax ramp; mutual co-review (D8) | Active (Matt, 2026-08-05) | [ux foundation §D8](compass-ux-foundation/design.md#d8--brand-seam--the-mark--editor-theme-mapping) | -| DL-156 | Motion: the product UI consumes the frozen brand motion system in pure CSS/SVG (no client animation runtime) — brand duration/easing/pulse/streaming tokens, the green working pulse with the one-pulse-per-region budget, chase-light spinner/bar loaders, the boot-sequence, reduced-motion as substitution not removal; literal durations are review failures (D9) | Active (Matt, 2026-08-05) | [ux foundation §D9](compass-ux-foundation/design.md#d9--motion-consume-the-frozen-brand-motion-system-pure-csssvg) | -| DL-157 | Adoption path: design-first, five-step incremental migration (tokens → shell → keyboard spine → surface flips → legacy retirement); in-flight lanes SEA-1645/SEA-1633 re-skin post-merge (D10) | Superseded by DL-184 (Matt, 2026-08-07) | [ux foundation §D10](compass-ux-foundation/design.md#d10--adoption-path-design-first-migration-incremental) | -| DL-158 | The agent workspace simplifies to the agent's home channel + its session trace (two fixed panes, no arbitrary split tree); no terminal pane and no file-viewer pane in dogfood (isolated containers; an operator dev-server-view affordance is deferred to backlog, PR review lives on the user's forge); the terminal `PaneKind` arm + `newTerminalPane` retire at the workspace flip (D6/D10) | Active (Matt, 2026-08-05) | [ux foundation §D6](compass-ux-foundation/design.md#d6--rendering-the-frozen-ia-surface-by-surface-composition) | -| DL-159 | One UI codebase renders in two hosts — the Wails v3 desktop app (primary) and the browser (the managed/hosted product at `compass.rigel.build`) — over the same transport-agnostic UI above the `connection.ts` provider seam; the layout is fluid within its window/viewport (a dense supervision surface that reflows, not a fixed-pixel canvas and not a mobile redesign) (D6/§Global Constraints 2) | Active (Matt, 2026-08-05) | [ux foundation §D6](compass-ux-foundation/design.md#d6--rendering-the-frozen-ia-surface-by-surface-composition) | -| DL-160 | The desktop app is first-class multi-window: every top-level surface (Bridge, a channel, an agent workspace, Backlog/Done, Settings) is an independently mountable window-scoped view (own DL-127 route, own focus zones + command scope, no sibling region required); compass-native spawns/manages OS windows, this record owns the decomposition; in-window tabs (Linear-style) and split views are deferred to the Beta milestone (SEA-1808), admitted by the same decomposition without rework (D6.1) | Active (Matt, 2026-08-05) | [ux foundation §D6](compass-ux-foundation/design.md#d6--rendering-the-frozen-ia-surface-by-surface-composition) | -| DL-184 | Token adoption is a FULL CUTOVER, not the DL-157 incremental strangler: a pre-dogfood codebase has no live users to protect, so the legacy `:root` tier is deleted and every consumer flips to `--cx-*` in one atomically-merged migration (canvas → Night Owl, base.css un-shadowed, state dots recolored, D7 stylelint guard wired directly at error), proven by a Playwright visual-smoke harness Matt reviews | Active (Matt, 2026-08-07) | [DS token cutover](compass-ds-token-cutover/design.md) | -| DL-174 | Compass test coverage is a differential-oracle pyramid: every seam carries a hermetic in-memory reference in the default gate plus a `pgtest` suite proving the real Postgres backend obeys the same contract; Postgres is the one live dependency the strategy gates on (D1) | Active (Matt, 2026-08-07) | [test strategy §Decisions](compass-test-strategy/design.md#decisions) | -| DL-175 | The real-Postgres `pgtest` suites run INLINE as a step in the one existing `CI` job — no separate CI job, lane, or moon task; one required check, hermetic moon `test` stays dependency-free via the build tag (D-A1, overruling the internal monorepo ancestor's separate `test-pg` lane; Matt: "trimmed but no extra CI job, it goes in the same existing job") | Active (Matt, 2026-08-07) | [test strategy §A1](compass-test-strategy/design.md#a1--one-ci-job-pgtest-inline-no-separate-lane-amends-the-ancestor-records-d2dl-049) | -| DL-176 | CI Postgres is the shipped GitHub Actions SERVICE CONTAINER — digest-pinned `postgres:16-alpine`, health-gated, URL-form TCP DSN, digest kept equal to `pgtest.go`'s image pin — not the internal monorepo ancestor's per-step embedded `postgresql_18` postmaster, which solved a Woodpecker constraint compass does not have (D-A2) | Active (Matt, 2026-08-07) | [test strategy §A2](compass-test-strategy/design.md#a2--postgres-provisioning-in-ci-the-shipped-service-container-amends-the-ancestor-records-d4) | -| DL-177 | Require-live teeth live in the harness: `COMPASS_REQUIRE_LIVE=1` (set by the CI pgtest step) turns `RequireDSN`'s no-DSN skip path into `t.Fatal` at the one policy seam every suite passes through — layered with, not replacing, the workflow-level skipped-suite assert step (D2/S1) | Active (Matt, 2026-08-07) | [test strategy §Decisions](compass-test-strategy/design.md#decisions) | -| DL-178 | Whole-flow scope is one thin composing test: `runner.Dial` over TLS with a real minted Runner-kind token through the production `RunnerService` door built by `buildNetworkServer` — the one seam no suite on `main` composes; a full smoke rebuild is rejected as re-describing shipped work (D3/S2) | Active (Matt, 2026-08-07) | [test strategy §Decisions](compass-test-strategy/design.md#decisions) | -| DL-179 | The `podman`-tagged surface (runtime lifecycle suites and the `go/e2e/` dogfood legs) stays skip-if-absent and out of this record's gate; its CI promotion is owned by the dogfood-e2e/infra lane (D4) | Active (Matt, 2026-08-07) | [test strategy §Decisions](compass-test-strategy/design.md#decisions) | -| DL-180 | No browser e2e in the test pyramid: the whole-flow level is a Go/`pgtest` composing test; the UI transport is contract-tested at the frame level and the generated client factory over the bun contract lane once it lands (D5) | Active (Matt, 2026-08-07) | [test strategy §Decisions](compass-test-strategy/design.md#decisions) | -| DL-181 | The bun TS-client↔Go-server contract lane is filed as a follow-up feature against the compass-dogfood-e2e harness scope (it consumes that harness's bring-up and served door rather than duplicating them); it is not built from this record (D6/S3) | Active (Matt, 2026-08-07) | [test strategy §Decisions](compass-test-strategy/design.md#decisions) | -| DL-219 | The keyboard spine lands minimal-first (Fork A-minimal): a `CommandRegistry` implementation + a `DEFAULT_KEYMAP` dispatcher + a `createRovingGroup` one-tab-stop primitive, with the Bridge board as first consumer; zone cycling, the escape ladder, pane focus, and the palette stay contracts-only until their consuming lanes flip. The spine's movement API is command-id routing through a `RovingGroupHandle`, a second surface beside the frozen 1-D `FocusZoneController.moveWithinGroup(RovingDirection)` — a later zone-controller lane delegates `moveWithinGroup` into the handle or amends `zones.ts` additively. Refines DL-151/152 (the D4/D5 focus + keymap contracts) with their first runtime. | Active (Matt, 2026-08-21) | [bridge keyboard-nav §Resolved decisions](compass-bridge-keyboard-nav/design.md#resolved-decisions) | -| DL-220 | The Bridge 2-D cursor model — stops are cards + gutter heads (gutter = column −1, swimlane only, non-null agents), never cells; empty (`dim`) cells skipped; Up/Down column-flattened through card stacks, Left/Right row-wise with an `indexInCell` clamp (a named non-reversible asymmetry), Home/End = column first/last, edges clamp (no wrap); focus is distinct from selection (cursor moves focus, Enter selects); no ARIA `grid` role on the sparse board — stops stay `