Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/designs/DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ check enforces the mechanical half. Full rationale:
| 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) |
| DL-264 | The DL-053 agent-notification transport is WEBHOOK-ONLY: a per-deployment GitHub App (one App-level webhook URL + secret, install-to-subscribe, `X-Hub-Signature-256` fail-closed) posting to `POST /webhooks/github` on the network TLS door, and Linear `Issue`/`Comment` data-change events on the RIG-2717 `POST /webhooks` handler (implementation in flight — Global Constraints) — no standing poll loop exists on this lane. Reliability is a bounded reconciliation catch-up: one conditional-GET sweep at startup plus a 30 min backstop that diffs snapshots via `DetectChanges` and re-notifies from the durable `delivered_revision` gap (synthesizing one payload-free UPDATE when the missed set is no longer derivable) — a gap-healer at tens-of-minutes cadence, never a primary transport. Supersedes DL-053's transport premise; its two-cursor split and delivery semantics survive. | Active (Matt, 2026-08-26) | [forge agent-notification §transport pivot](product/compass-forge-agent-notification/design.md#the-transport-pivot-dl-053s-poll-premise-and-why-the-app-dissolves-it) |
| DL-265 | Forge notifications ride the generic `DispatchControl` relay (`SessionsResponse.deliver_control` envelope wrapping `AgentControl.forge_notification`), NOT the bare `SessionsResponse.forge_notification = 7` variant — that variant predates the generic relay (`compass-notification-delivery/design.md:199-202`) and is superseded: it stays reserved on the wire with a doc comment, and no Runner dispatch arm is built for it. Zero new Runner code on the relay path. Agent-side delivery idempotency is control-rail SEQ-based (`acks.isApplied`, `packages/compass-agent/src/transport/control-source.ts:363-367`); no content-tuple key exists on this lane, and duplicate content is within the at-least-once contract. | Active (Matt, 2026-08-26) | [forge agent-notification §pipeline](product/compass-forge-agent-notification/design.md#the-pipeline-end-to-end) |
| DL-266 | The forge delivery cursor (`delivered_revision`) advances on the agent's in-band forge delivery ack — `ForgeNotificationAck{subscription_id, revision}`, an additive AgentFrame variant emitted at turn-end flush — NEVER on dispatch success (Matt's W3 ruling, option beta), aligning this lane with the dispatch arm's own model ("The cursor is never advanced on send — it advances only later on the recipient's delivery_ack", `go/internal/runnerhub/dispatch_control.go:31-33`). Every pre-ack loss (synchronous refusal, async RunnerError via `router.complete`, agent death before flush) leaves the cursor unadvanced and is healed by the reconcile sweep within one backstop interval. The correlation is new work: today's `delivery_ack` carries only a comms `message_id` (`agent.proto:232-239`). This reopens the frozen delivery record's advance-signal clause (`compass-notification-delivery/design.md:894-897`) and rides the freeze-gate ratification, bundled with the fresh-subscription catch-up baseline moving from DL-053's "at Subscribe time" to first-observed-event/sweep (bounded by ≤1 backstop interval) — also decided in W3's ruling. | Active (Matt, 2026-08-26) | [forge agent-notification §W3](product/compass-forge-agent-notification/design.md#resolved-decisions-matt-2026-08-26) |
| DL-267 | Forge subscriptions gain CONTAINER-SCOPE granularity via an explicit `ForgeSubscriptionScope` enum on `SubscribeForgeRequest` — Matt's W2 ruling, option (b); the `number = 0` sentinel is REJECTED (proto3 absent-vs-0 blindness would convert a forgotten `number` from an LLM tool caller into a silent whole-repo subscription). Containers are PROVIDER-NATIVE: GitHub's container is the REPO (the existing `repo` slot); Linear's is a PROJECT, carried in a slot of its own and never overloaded onto the team key in `repo` — Linear project scope is thereby IN scope (promoted from deferral). The project identifier lives in a dedicated column (OQ-1, ruled (i): additive `scope` + `project` columns, UNIQUE widened). A container subscription delivers exactly `FORGE_NOTIFICATION_KIND_OPENED` with the new artifact's number/url — never a fan-in of every event on every artifact. Two additive `ForgeNotificationKind` values land with it: `REVIEW = 5` (submitted PR review; free on webhooks where the poll design priced no review endpoint) and `OPENED = 6`. | Active (Matt, 2026-08-26) | [forge agent-notification §subscription model](product/compass-forge-agent-notification/design.md#the-subscription-model-folded-per-matts-rulings-3--w2) |

> Note (2026-07-31, SEA-1570 R5): DL-065's retired internal `ResumeContext
> resume = 12` envelope field is NOT silently reintroduced — the collapsed
Expand Down
Loading
Loading