From 685f7a90655c0f70a0d43b61a2eea861072d5015 Mon Sep 17 00:00:00 2001 From: mintaka Date: Mon, 31 Aug 2026 19:41:33 -0400 Subject: [PATCH] =?UTF-8?q?refactor(design-docs):=20dissolve=20product/=20?= =?UTF-8?q?into=20ui/=20=E2=80=94=20visible-surface=20records=20(RIG-2577?= =?UTF-8?q?=20T8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the product's visible-surface records (shell, board, sidebar, keyboard, rendering, design system) out of the dissolving product/ bucket into the ruled top-level ui/ bucket (RIG-2577 §Approach 2). 26 records: the frozen roster's 24 ui-block records (minus the native family, deferred — see below) plus the 2 post-freeze drift records Matt ratified into ui/ on 2026-08-31 (compass-coaching-tooltips, compass-leader-chords). DEFERRED to T10 (per RIG-2577 §T8/T10 + Matt's 2026-08-31 ratification): the native-app family stays under the transitional product/ root while it settles — compass-native-app, compass-native-client-mode, compass-native-client-only, compass-native-packaging, compass-tauri-shell.md, compass-multi-window, compass-stack-cross-process-teardown, and compass-gtk4-migration. After this PR, product/ holds exactly these 8 records. ui/ is already a governed root; records stay governed across the move, no Status normalization needed. Same-PR link integrity (RIG-2577 Global Constraints): - DECISIONS.md Record cells re-pointed product// -> ui// (284 rows unchanged; pure relocation, no decision changed). Deferred-native cells stay product/-qualified (they didn't move) — still governed. - Cross-bucket body links: server/compass-zulip-threading-model's 2 outbound links to now-ui records (threading-ui, slack-thread-rendering) re-pointed to ../../ui/. - External citation sweep: gate test fixtures (design-ledger-gate, sea-ref-gate), BadgeGlyph.test.tsx comment, and inter-record prose re-pointed to ui/. Verified: design-ledger-gate OK (284 rows, 120 headers); eng-docs gather 73/73; gate-suite tests 81/81 + 22/22; BadgeGlyph 17/17 (--conditions browser); deferred native records intact + still governed; no dangling product/ refs to moved records. Ledger-impact: records relocated within governance, no decision changed Co-authored-by: Matt Wilkinson --- apps/ui/src/components/BadgeGlyph.test.tsx | 2 +- docs/designs/DECISIONS.md | 112 +++++++++--------- .../meta/compass-design-ledger/design.md | 2 +- .../compass-zulip-threading-model/design.md | 4 +- .../compass-ade-shell/design.md | 0 .../compass-badge-clarity/design.md | 0 .../compass-board-view/design.md | 0 .../compass-bridge-keyboard-nav/design.md | 0 .../compass-bridge-reclothe/design.md | 0 .../compass-coaching-tooltips/design.md | 0 .../compass-command-palette/design.md | 0 .../compass-dev-boot-gate/design.md | 0 .../compass-dock-in-sidebar/design.md | 2 +- .../compass-ds-token-cutover/design.md | 0 .../design.md | 2 +- .../compass-keyboard-spine-app-root/design.md | 2 +- .../compass-leader-chords/design.md | 0 .../compass-live-roster/design.md | 0 .../design.md | 0 .../compass-session-trace-diff.md | 0 .../compass-shell-routing/design.md | 0 .../design.md | 4 +- .../compass-sidebar-pins/design.md | 2 +- .../compass-slack-thread-rendering.md | 0 .../compass-threading-ui/design.md | 0 .../compass-ui-fixture-boot/design.md | 0 .../compass-ui-markdown-react10/design.md | 0 .../compass-ui-query-layer/design.md | 0 .../compass-ui-solid-v2/design.md | 0 .../compass-ux-foundation/design.md | 0 tools/design-ledger-gate/index.test.ts | 10 +- tools/sea-ref-gate/index.test.ts | 10 +- 32 files changed, 76 insertions(+), 76 deletions(-) rename docs/designs/{product => ui}/compass-ade-shell/design.md (100%) rename docs/designs/{product => ui}/compass-badge-clarity/design.md (100%) rename docs/designs/{product => ui}/compass-board-view/design.md (100%) rename docs/designs/{product => ui}/compass-bridge-keyboard-nav/design.md (100%) rename docs/designs/{product => ui}/compass-bridge-reclothe/design.md (100%) rename docs/designs/{product => ui}/compass-coaching-tooltips/design.md (100%) rename docs/designs/{product => ui}/compass-command-palette/design.md (100%) rename docs/designs/{product => ui}/compass-dev-boot-gate/design.md (100%) rename docs/designs/{product => ui}/compass-dock-in-sidebar/design.md (99%) rename docs/designs/{product => ui}/compass-ds-token-cutover/design.md (100%) rename docs/designs/{product => ui}/compass-keyboard-shortcuts-overlay/design.md (99%) rename docs/designs/{product => ui}/compass-keyboard-spine-app-root/design.md (99%) rename docs/designs/{product => ui}/compass-leader-chords/design.md (100%) rename docs/designs/{product => ui}/compass-live-roster/design.md (100%) rename docs/designs/{product => ui}/compass-message-surface-rendering/design.md (100%) rename docs/designs/{product => ui}/compass-session-trace-diff.md (100%) rename docs/designs/{product => ui}/compass-shell-routing/design.md (100%) rename docs/designs/{product => ui}/compass-sidebar-pins-unreachable-amendment/design.md (99%) rename docs/designs/{product => ui}/compass-sidebar-pins/design.md (99%) rename docs/designs/{product => ui}/compass-slack-thread-rendering.md (100%) rename docs/designs/{product => ui}/compass-threading-ui/design.md (100%) rename docs/designs/{product => ui}/compass-ui-fixture-boot/design.md (100%) rename docs/designs/{product => ui}/compass-ui-markdown-react10/design.md (100%) rename docs/designs/{product => ui}/compass-ui-query-layer/design.md (100%) rename docs/designs/{product => ui}/compass-ui-solid-v2/design.md (100%) rename docs/designs/{product => ui}/compass-ux-foundation/design.md (100%) diff --git a/apps/ui/src/components/BadgeGlyph.test.tsx b/apps/ui/src/components/BadgeGlyph.test.tsx index fcca1a6ce..04f7a4b92 100644 --- a/apps/ui/src/components/BadgeGlyph.test.tsx +++ b/apps/ui/src/components/BadgeGlyph.test.tsx @@ -11,7 +11,7 @@ import { BadgeGlyph } from "./BadgeGlyph"; // a CSS-selector change could silently break. // The six frozen glyph grids, transcribed verbatim from the ASCII art in -// docs/designs/product/compass-badge-clarity/design.md §"The six glyph grids" +// docs/designs/ui/compass-badge-clarity/design.md §"The six glyph grids" // (`#` = lit, `.` = off; 9×9). This is an INDEPENDENT copy of the contract — // the component transcribes the same grids into [x,y] coordinate arrays, so // comparing the rendered rects against these grids catches a wrong grid even diff --git a/docs/designs/DECISIONS.md b/docs/designs/DECISIONS.md index c1d7e8a8d..40e8b1393 100644 --- a/docs/designs/DECISIONS.md +++ b/docs/designs/DECISIONS.md @@ -215,11 +215,11 @@ check enforces the mechanical half. Full rationale: | --- | --- | --- | --- | | DL-030 | UI: the communication layer is the primary surface (comms-primary shell) | Superseded by DL-031 (Matt, 2026-07-06) | [architecture lineage](meta/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](meta/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-032 | Compass state is canonical; the tracker is a projection of it | Superseded by DL-129 (Matt, 2026-08-04) | [ADE shell §D2](ui/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](ui/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](ui/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](ui/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](ui/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](agent/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](server/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](server/compass-issue-model/design.md#attribution-consumed-never-stamped) | @@ -227,24 +227,24 @@ check enforces the mechanical half. Full rationale: | 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](server/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](server/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](server/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-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](ui/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](ui/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](agent/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-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](ui/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](ui/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](ui/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](server/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) | +| 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](ui/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](ui/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](ui/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](ui/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](ui/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](ui/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](ui/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](ui/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](ui/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](ui/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](ui/compass-ui-markdown-react10/design.md#approach) | ## Threading & rendering @@ -253,7 +253,7 @@ check enforces the mechanical half. Full rationale: | 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](meta/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](meta/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](meta/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-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](ui/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](server/compass-zulip-threading-model/design.md#decisions-ratified) | | DL-099 | An agent's streamed turn does not write to comms at all: the RIG-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](server/compass-zulip-threading-model/design.md#d7--one-comms-write-path-the-streaming-write-through-is-removed-supersedes-rig-1364-t3) | @@ -312,20 +312,20 @@ check enforces the mechanical half. Full rationale: | 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](product/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](product/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](product/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](product/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](product/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](product/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](product/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](product/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](product/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 RIG-1645/RIG-1633 re-skin post-merge (D10) | Superseded by DL-184 (Matt, 2026-08-07) | [ux foundation §D10](product/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](product/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](product/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 (RIG-1808), admitted by the same decomposition without rework (D6.1) | Active (Matt, 2026-08-05) | [ux foundation §D6](product/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](product/compass-ds-token-cutover/design.md) | +| 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](ui/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](ui/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](ui/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](ui/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](ui/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](ui/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](ui/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](ui/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](ui/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 RIG-1645/RIG-1633 re-skin post-merge (D10) | Superseded by DL-184 (Matt, 2026-08-07) | [ux foundation §D10](ui/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](ui/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](ui/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 (RIG-1808), admitted by the same decomposition without rework (D6.1) | Active (Matt, 2026-08-05) | [ux foundation §D6](ui/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](ui/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](meta/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](meta/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](meta/compass-test-strategy/design.md#a2--postgres-provisioning-in-ci-the-shipped-service-container-amends-the-ancestor-records-d4) | @@ -334,29 +334,29 @@ check enforces the mechanical half. Full rationale: | 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](meta/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](meta/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](meta/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](product/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 `