docs(as-built): modular reorg — 19-doc forensically source-grounded tree (context-architecture-v1 slice-08)

Reorganize the monolithic as-built docs into a navigable modular tree,
forensically source-grounded at a named commit. Docs-only; zero product
source or daemon changes. Founder-ratified (slice-08 founder-walk).

- architecture.md / ui.md → `status: superseded` redirect stubs
- new architecture/ (13 modules) + ui/ (4 modules)
- new README.md (nav index) + frontmatter-schema.md (the
  last-verified-against-source contract)
- codemap.md rewritten as the navigation index
- cli-reference.md kept whole + updated

Each module carries inline source-grounding annotations
(`> Source: file:line @<sha>`) so drift is detectable, not silent — the
drift-detection loop is the deliverable, not a one-time doc.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
mvschwarzandClaude Opus 4.7 committed 2026-05-17 20:15:54 -07:00
1 parent 7eaf524cc4
commit 16b85d9c41
23 files changed
+4275 -1773

No files matched your search

+100
View File
@@ -0,0 +1,100 @@
---
kind: as-built
title: As-Built Docs — Map of Territory + Module Index
status: active
topics: [knowledge-and-context, observability]
domains: [engineering-advisor, operating-advisor, product-advisor]
applies-when: |
Starting any technical task that needs the shipped OpenRig system as it
actually is. Read this first to learn what the as-built tree contains and
which module to open; then go to codemap.md for use-case navigation or
straight to the named module.
siblings: [codemap.md, cli-reference.md, frontmatter-schema.md]
prerequisite-reads: []
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# OpenRig As-Built Docs
OpenRig is a local control plane for multi-agent coding topologies — a
multi-agent harness that manages your Claude Code and Codex sessions as a
single system, with a daemon (`@openrig/daemon`), a CLI (`@openrig/cli`), a UI
(`@openrig/ui`), and an MCP server all sitting on one SQLite-backed core. This
tree is the **source-verified** description of that system as it actually
ships — every load-bearing claim is grounded to `packages/*/src` at a named
commit, not to memory, chat, or older docs.
> Verified against source at HEAD `7eaf524c` (`git describe` →
> `v0.3.1-6-g7eaf524c`). Package version is **0.3.1** across all three
> packages; HEAD carries 6 commits of unreleased 0.3.2 work, no `v0.3.2` tag.
## How this tree is organized
The as-built corpus was modularized (slice 08, `context-architecture-v1`) from
two monolithic files into a folder of thematic modules, each independently
loadable, each frontmatter-tagged for retrieval, each ≤300 lines (author-mode
modules with no prior prose may run to ≤400 — see the slice-08 ACK).
```
docs/as-built/
├── README.md ← you are here: map-of-territory + index
├── codemap.md ← navigation index (use-case lookup, source-root pointers)
├── frontmatter-schema.md← the frontmatter convention these docs follow
├── cli-reference.md ← full rig CLI surface (kept whole)
├── architecture/ ← 13 backend/runtime modules
└── ui/ ← 4 operator-surface modules
```
`docs/DESIGN.md` (the canonical visual / brand / design-system spec) **stays
at the repo `docs/` root** by design — it is referenced by many existing
`docs/DESIGN.md` paths and carries no source drift. This tree points at it
(see `ui/library-specs-and-design-system.md`); it is not copied here.
## Module index
### `architecture/` — backend, daemon, runtime
| Module | What it covers |
|---|---|
| [daemon-core.md](architecture/daemon-core.md) | How the daemon boots, `createDaemon` wiring, the SQLite schema/40-migration set, the route-mount surface. |
| [adapters-and-runtimes.md](architecture/adapters-and-runtimes.md) | The five-method RuntimeAdapter contract, the Claude/Codex/Terminal adapters (launch/resume/fork in tmux), and the resume-honesty layer (honest resumed-vs-fresh assessment). |
| [coordination-primitive.md](architecture/coordination-primitive.md) | PL-004 Phase A stream/queue/inbox/outbox; the hot-potato closure contract; where queue closure is enforced. |
| [workflow-runtime.md](architecture/workflow-runtime.md) | PL-004 Phase D Workflow Runtime — spec cache, instance state, step trails, transactional-scribe projection, watchdog policies. |
| [mission-control.md](architecture/mission-control.md) | PL-005 queue-observability surface — seven views, seven write verbs, action audit, bearer-token middleware. |
| [agent-spec-and-startup.md](architecture/agent-spec-and-startup.md) | AgentSpec/RigSpec types, profile resolution, additive startup layering, StartupOrchestrator, whoami/materialize/bind/adopt identity. |
| [lifecycle-snapshot-restore.md](architecture/lifecycle-snapshot-restore.md) | Snapshot capture, honest restore (resume vs rebuild vs fresh), restore-honesty enforcement, restore-check / restore-packet probes. |
| [transport-and-transcripts.md](architecture/transport-and-transcripts.md) | rig send/capture/broadcast over tmux, pipe-pane transcript capture + search, durable SQLite chat, `rig ask`, MCP-name vs tmux-key distinction. |
| [workspace-primitive.md](architecture/workspace-primitive.md) | The PL-007 typed workspace declaration (root/repos/defaultRepo/knowledgeRoot), migrations 038/039, per-item repo-scope gating, file-backed missions/slices indexing. |
| [content-surfaces.md](architecture/content-surfaces.md) | The operator-allowlisted file browser, atomic conflict-checked writes + JSONL edit audit, PROGRESS.md tree indexer, the one-screen Steering composer. |
| [plugin-agent-image-context-pack.md](architecture/plugin-agent-image-context-pack.md) | The filesystem-canonical content layer — plugin discovery, agent images, context packs, the Claude auto-compaction policy enforcer. |
| [packaging-bootstrap-bundles.md](architecture/packaging-bootstrap-bundles.md) | Bundle assembly (schema-v2 pod bundles + legacy v1), bundle create/inspect/install + `/api/up`, the staged BootstrapOrchestrator, legacy install seams. |
| [architecture-rules-and-event-system.md](architecture/architecture-rules-and-event-system.md) | The cross-cutting invariants — the 25 architecture rules, the RigEvent union + SSE delivery, intentional compatibility limits. |
### `ui/` — operator surfaces
| Module | What it covers |
|---|---|
| [shell-and-routing.md](ui/shell-and-routing.md) | The UI shell (rail / Explorer / center workspace / drawer / preview stack), the actual route tree the shipped UI mounts, the shared detail drawer + event consumption. |
| [topology.md](ui/topology.md) | The topology surface — host hybrid graph, table/terminal views, activity-ring / hot-potato visual language, terminal-preview popovers, navigation/overlay contracts. |
| [project-and-for-you.md](ui/project-and-for-you.md) | The operator destination surfaces — the For-You attention feed (5-card classifier + verb actions), the Project workspace/mission/slice scope pages, the Dashboard landing on the vellum brand system. |
| [library-specs-and-design-system.md](ui/library-specs-and-design-system.md) | The Library (`/specs`) UI — specs/skills/plugins/agent-images surfaces, the spec-review + spec-library + live-identity flows, the design-system pointer. |
### Root docs
| Doc | What it covers |
|---|---|
| [codemap.md](codemap.md) | Navigation index — module map, structural relationship diagram, fast-lookup-by-use-case, source-root pointer table. Start here when you know *what* you need but not *which module*. |
| [cli-reference.md](cli-reference.md) | The full `rig` CLI surface — command groups, subcommands, flags, JSON output, cross-host, coordination primitives. Kept as one doc (slice-08 Q4). |
| [frontmatter-schema.md](frontmatter-schema.md) | Which frontmatter convention governs every doc in this tree, plus the one as-built-unique field (`last-verified-against-source`). |
| `../DESIGN.md` | The canonical visual / brand / design-system spec (lives at `docs/` root by design; pointer only — not duplicated here). |
## Source-grounding contract
Every module declares `last-verified-against-source: <commit-sha>` — the
commit its claims were checked against. Load-bearing corrections are recorded
inline with an auditable annotation (`> Drift-fix Dx — said X; corrected to Y;
slice-00 §z; re-confirmed <file:line> @HEAD`). OPEN items (counts that are
definitional or runtime-only) are carried verbatim, never smoothed. The
schema is defined in [frontmatter-schema.md](frontmatter-schema.md) and the
governing convention is `openrig-work/conventions/frontmatter-for-context/`.
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,228 @@
---
kind: as-built
title: Adapters and Runtimes — Claude/Codex/Terminal, tmux/cmux, Resume Honesty
status: active
topics: [agent-runtime, runtime-control]
domains: [engineering-advisor, operating-advisor]
applies-when: |
Need the runtime-adapter contract — how OpenRig launches and resumes a
Claude Code, Codex, or terminal harness inside tmux, what the five adapter
methods do, or how the daemon honestly assesses whether a harness actually
resumed vs fresh-launched (the resume-honesty layer).
siblings: [daemon-core.md, agent-spec-and-startup.md, lifecycle-snapshot-restore.md]
prerequisite-reads: [../README.md, daemon-core.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# Adapters and Runtimes
How OpenRig drives the agent harnesses. The daemon never talks to Claude Code,
Codex, or a shell directly — it talks to a `RuntimeAdapter`. Three adapters
implement one five-method contract; a separate resume-honesty layer answers the
question "did this harness *actually* resume, or did it silently fresh-launch?"
truthfully rather than optimistically.
> Verified against source at HEAD `7eaf524c` (`git describe` →
> `v0.3.1-6-g7eaf524c`). All source in this module is **present at `v0.3.0`**
> (`git cat-file -e v0.3.0:<path>` for all 7 files → present) — the adapter
> layer is core reboot-era machinery, **not** a 0.3.x feature; do not
> back-attribute (§10.8 version-attribution proof technique).
> Drift-fix (scope) — `architecture.md` §5 "Runtime adapters" carries **no
> slice-00 numeric drift** (proposed-structure §4.2: "adapter contract is
> current"). The corrections below are *precision* refinements where the source
> is more specific than the prose, not stale-count fixes. Each is annotated
> inline and re-confirmed at HEAD.
## 1. The five-method RuntimeAdapter contract
`RuntimeAdapter` is `packages/daemon/src/domain/runtime-adapter.ts:127`
(`interface RuntimeAdapter`). Every adapter declares a `readonly runtime`
string and implements exactly five methods (`runtime-adapter.ts:128–153`):
| Method | Signature (`runtime-adapter.ts`) | Responsibility |
|---|---|---|
| `listInstalled` | `(binding)` `:131` | List currently installed/projected resources for a node. |
| `project` | `(plan, binding)` `:134` | Project resources from a `ProjectionPlan` to the runtime's target locations. |
| `deliverStartup` | `(files, binding)` `:137` | Deliver resolved startup files to the runtime. |
| `launchHarness` | `(binding, opts)` `:147` | Launch the harness inside the bound tmux session; return a resume token. |
| `checkReady` | `(binding)` `:153` | Probe whether the harness is responsive and ready. |
Startup *action* execution (`slash_command` / `send_text`) is explicitly **not**
part of this contract — the contract docstring (`runtime-adapter.ts:121–125`)
states actions belong to the `StartupOrchestrator` *after* `checkReady()`. The
orchestrator delivery split is in `agent-spec-and-startup.md`.
### `launchHarness` opts and the fork seam
`launchHarness` opts is `{ name: string; resumeToken?: string; forkSource?:
ForkSource }` (`runtime-adapter.ts:147–150`).
> Drift-fix (precision) — `architecture.md` §4 said `launchHarness(binding,
> opts: { name, resumeToken? })`. Source adds a third, mutually-exclusive
> `forkSource` field. Per the contract docstring (`runtime-adapter.ts:142–146`)
> `resumeToken` and `forkSource` are mutually exclusive — if both are provided
> the adapter **must refuse** with a clear error, not guess; `forkSource`
> triggers a fork and the captured token is the NEW post-fork token, never the
> parent. `ForkSource` is `runtime-adapter.ts:116` (`kind: "native_id" |
> "artifact_path" | "name" | "last"`; v1 MVP accepts `native_id` only — other
> shapes rejected at schema validation, docstring `:106–119`).
### `HarnessLaunchResult` is a discriminated union with an honest failure arm
> Drift-fix (precision) — `architecture.md` §4 said `HarnessLaunchResult` is
> `{ ok, resumeToken?, resumeType?, error? }` (a single optional-field shape).
> Source is a **discriminated union** (`runtime-adapter.ts:81–86`):
> `| { ok: true; resumeToken?; resumeType? }`
> `| { ok: false; error: string; recovery?: HarnessLaunchRecovery; evidence? }`.
> The failure arm carries a typed `recovery` hint
> (`HarnessLaunchRecovery = "retry_fresh" | "attention_required"`,
> `:79`) and optional `evidence` (last-N pane lines, flowed through to
> `RestoreNodeResult.attentionEvidence` for `attention_required` outcomes,
> `:83–86`). This is the honest-failure shape, not a smoothed optional `error`.
## 2. The three adapters
All three live under `packages/daemon/src/adapters/` and implement
`RuntimeAdapter` (Architecture Rule 1: zero Hono in `adapters/`).
### ClaudeCodeAdapter (`claude-code-adapter.ts:41`)
- `readonly runtime = "claude-code"` (`:42`).
- **Projects** to `.claude/` targets: `guidance_merge` → `<cwd>/CLAUDE.md`
(`:127`); `skill_install` → `<cwd>/.claude/skills/<name>/` (`:71,133`);
subagents → `.claude/agents`, plugins → `.claude/plugins/<id>`,
runtime resources → `.claude/extensions/<id>`, settings fragments merged
into `.claude/settings.local.json` (`:388–400`).
- **Launches** (`:213–215`): fresh = `claude <permissionMode> --session-id
<generatedId> --name <name>`; resume = `claude <permissionMode> --resume
<token> --name <name>`; fork = `claude <permissionMode> --resume <parentId>
--fork-session --name <seat>` (`:188`).
> Drift-fix (precision) — `architecture.md` §5 said only "launches via
> `claude --name <name>`, resumes via `claude --resume <token>`". Source
> shows fresh launch uses an explicit `--session-id` (so a deterministic
> resume token exists immediately) and the fork branch exists. Re-confirmed
> `claude-code-adapter.ts:188,213–215` @HEAD.
- **Readiness** (`checkReady`, `:239`): verifies tmux session alive, captures
40 pane lines + pane command, delegates to `assessNativeResumeProbe` (§3);
ready only when probe `status === "resumed"`. The resume-launch verification
loop `verifyResumeLaunch` retries up to **16 attempts** (`:273`), failing
loudly with `recovery: "retry_fresh"` on `no_conversation_found`
(`:284–289`) — no silent fresh fallback.
### CodexRuntimeAdapter (`codex-runtime-adapter.ts:37`)
- `readonly runtime = "codex"` (`:38`).
- **Projects** to `.agents/` targets: `guidance_merge` → `<cwd>/AGENTS.md`
(`:139,330`); `skill_install` → `<cwd>/.agents/skills/<name>/` (`:89,145`);
skills resolve under `.agents/skills/<id>` (`:377`).
- **Launches/resumes** (`:205,225–226`): fresh launch then capture a fresh
thread id; resume = `codex<profileArg> resume<queueStateDirArg> <token>`;
fork = `codex<profileArg> fork<queueStateDirArg> <parentId>` (`:205`). On
success returns `{ ok: true, resumeToken: threadId, resumeType: "codex_id" }`
(`:222,245,250`).
> Drift-fix (precision) — `architecture.md` §5 said "launches via `codex`,
> resumes via `codex resume <threadId>`". Source confirms the `codex resume
> <token>` shape (`:226`) and adds the fork branch + the
> `resumeType: "codex_id"` tag. Re-confirmed @HEAD.
- Refuses `resumeToken` + `forkSource` together with a clear error
(`:180–181`) — honors the mutual-exclusivity contract.
### TerminalAdapter (`terminal-adapter.ts:19`)
- `readonly runtime = "terminal"` (`:20`).
- **All operations are no-ops** — "the shell IS the harness"
(`terminal-adapter.ts:15`): no-op `project`/`deliverStartup`/`launchHarness`
(`:34`), and `checkReady` returns ready immediately as soon as the tmux
session exists (`:47`). Used for infrastructure nodes — servers, log tails,
build watchers. (A terminal node cannot fork; the runtime-adapter docstring
notes fork-unsupported adapters refuse with a runtime-mismatch error,
`runtime-adapter.ts:113–115`.)
These three are constructed by `createDaemon` step 4 (`startup.ts`; see
`daemon-core.md` §4 "Startup sequence").
## 3. Resume honesty
The daemon does not assume a harness resumed just because the launch command
ran. Three domain files (`packages/daemon/src/domain/`, all present @v0.3.0)
make resume assessment honest:
### `native-resume-probe.ts`
`assessNativeResumeProbe(input)` (`native-resume-probe.ts:43`) reads pane
command + pane content and returns one of four honest statuses
(`NativeResumeProbeStatus`, `:6`):
- `resumed` — runtime-specific indicators confirm a resumed session.
- `failed` — terminal failure (e.g. Claude printed "No conversation found" →
code `no_conversation_found`, `:51–57`).
- `inconclusive` — we don't know yet (e.g. Claude trust gate, code
`trust_gate`, `:65–70`).
- `attention_required` — alive and recoverable but **needs operator action**
(e.g. Claude resume-selection prompt, code `claude_resume_selection_prompt`,
`:58–64`). This is the proxy for "an operator must choose the conversation";
it is *distinct* from `inconclusive` and `failed` (docstring `:3–5`).
`buildNativeResumeCommand` (`:27`) builds the resume command per runtime:
claude → `claude --resume <token> [--name <name>]` (`:35`); codex → `codex
resume <token>` (`:38`); other runtimes → `null` (`:40`).
This is Architecture Rule 15 in code: a failed resume is FAILED loudly; there
is no automatic fresh fallback (the adapter's `verifyResumeLaunch` returns
`ok:false` with a `retry_fresh` recovery hint, never a silent relaunch).
### `resume-metadata-refresher.ts`
`ResumeMetadataRefresher` (`resume-metadata-refresher.ts:37`). Post-launch
resume-token capture: `refresh(sessions)` (`:62`) skips sessions that already
have a `resumeToken` (`:65`), and for `claude-code` sessions with a token runs
a `probeClaudeResume` returning `"resumable" | "not_resumable" |
"inconclusive"` (`:31,74–75`) — a real launch of the resume command in a
throwaway probe tmux session (`:106–111`), not a metadata guess.
### `codex-thread-id.ts`
Codex thread-id extraction (`codex-thread-id.ts`). Reads the Codex thread id
from the Codex *logs* SQLite databases under `~/.codex/`:
`readCodexThreadIdFromCandidateHomes(...)` (`:22`) →
`readCodexThreadIdFromLogs(...)` (`:49`) → `resolveCodexLogDbPaths(homeDir)`
(`:79`) which globs `<homeDir>/.codex/logs_<N>.sqlite` (`:84–89`,
regex `^logs_(\d+)\.sqlite$`) and falls back to `logs_1.sqlite` (`:97`).
Uses `better-sqlite3` (`:5`). Resolves the home dir by the harness PID
(`defaultResolveHomeDirByPid`, `:9`).
> Precision note — `architecture.md` §5 "Resume honesty" says codex thread IDs
> come from "the Codex SQLite database". Source is more specific: the
> per-version Codex *logs* DBs `~/.codex/logs_N.sqlite`. Stated precisely here;
> re-confirmed `codex-thread-id.ts:79–97` @HEAD.
## 4. Relevant Architecture Rules (source-verified at HEAD)
From `architecture.md` §7 (re-confirmed against the source cited inline):
- **Rule 5** — Runtime is member-authoritative in the pod-aware model.
- **Rule 13** — Readiness checking is a retry loop with exponential backoff and
a configurable timeout, using adapter-specific probes (Claude TUI indicator,
Codex ready message, terminal immediate). Re-confirmed: `checkReady`
delegates to `assessNativeResumeProbe`; the retry loop is
`claude-code-adapter.ts:273` (16 attempts).
- **Rule 14** — Resume states are locked: `resumed` / `rebuilt` / `fresh`;
`rebuilt` = new process assembled from artifacts. (The probe layer adds
`inconclusive` / `attention_required` as honest *transient* states, not
outcomes — see §3.)
- **Rule 15** — Restore honesty: failed resume is FAILED loudly; no automatic
fresh fallback; fresh launch is an explicit follow-up only. Enforced in code
by §2/§3 (`verifyResumeLaunch` returns `ok:false`, never relaunches).
## See also
- `daemon-core.md` — where `createDaemon` constructs the three adapters.
- `agent-spec-and-startup.md` — the `StartupOrchestrator` that calls these
adapters and owns startup-action execution after `checkReady()`.
- `lifecycle-snapshot-restore.md` — how persisted resume tokens flow into
snapshot/restore (resume vs rebuild vs fresh).
- Source roots: `packages/daemon/src/domain/runtime-adapter.ts`,
`packages/daemon/src/adapters/{claude-code-adapter,codex-runtime-adapter,terminal-adapter}.ts`,
`packages/daemon/src/domain/{native-resume-probe,resume-metadata-refresher,codex-thread-id}.ts`.
@@ -0,0 +1,232 @@
---
kind: as-built
title: Agent/Rig Spec, Resolution, Startup, Identity
status: active
topics: [specification-and-bundles, agent-runtime]
domains: [engineering-advisor, operating-advisor]
applies-when: |
Need to know the canonical AgentSpec/RigSpec/pod-aware reboot types, how
profile resolution and additive startup layering work, the StartupOrchestrator
pre-launch-vs-interactive delivery split, or how whoami/materialize/bind/adopt
resolve and preserve identity.
siblings: [daemon-core.md, adapters-and-runtimes.md, lifecycle-snapshot-restore.md, packaging-bootstrap-bundles.md]
prerequisite-reads: [../README.md, daemon-core.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# Agent/Rig Spec, Resolution, Startup, Identity
How the daemon turns authored YAML specs into a resolved, projected, launched,
and identity-addressable topology. The spec-and-startup contract: parse →
resolve → project → deliver → launch → wait → persist replay context.
> Verified against source at HEAD `7eaf524c` (`git describe` →
> `v0.3.1-6-g7eaf524c`). Package version is **0.3.1** across all three
> packages (slice-00 §1.1). Source feed located by `architecture.md` headings
> (§4 Canonical Reboot Types, §5 Domain Services, §6 Execution Flows, §7
> Architecture Rules) per slice-08 §10.1 — line numbers are advisory only.
## 1. Canonical spec and topology types
(`architecture.md` §4 "Spec and topology")
- **AgentSpec** — parsed from `agent.yaml`. Owns imports, defaults, startup,
resources, and profiles. Canonical parse/normalize/validate is
`domain/agent-manifest.ts`.
- **RigSpec** — canonical pod-aware rig topology. Uses `version: "0.2"` and
`pods[]`; owns cross-pod `edges[]`, rig-level startup overlays, and
`cultureFile`.
> Drift-fix D-spec-version — `architecture.md` §4 says RigSpec
> "Uses `version: "0.2"`". This is the **spec-schema version, NOT the
> package version** — a different versioning axis from the 0.3.1 package
> version. The value is NOT a code constant: `rigspec-schema.ts:52`
> validates `version` only as a "required non-empty string"
> (`if (!obj["version"] || typeof obj["version"] !== "string")`); `:163`
> carries it through as `raw["version"] as string`. `"0.2"` is the
> canonical authored value, correctly described as a schema axis. Do NOT
> "correct" it toward 0.3.1 (slice-08 §4.6 binding). Re-confirmed
> `rigspec-schema.ts:52,163` @HEAD.
- **RigServicesSpec** — optional `services` block on a pod-aware RigSpec.
Shipped kind is Compose-backed env management with `composeFile`,
`projectName?`, `profiles?`, `downPolicy?`, `waitFor?`, `surfaces?`,
`checkpoints?`.
- **RigSpecPod** — pod-local bounded context with `members[]`, pod-local
`edges[]`, pod startup, optional continuity policy.
- **RigSpecPodMember** — member-level runtime/startup surface: `agentRef`,
`profile`, `runtime`, `model?`, `cwd`, `restorePolicy?`, member startup
overlays.
- **Pod** — persisted DB entity for a pod.
- **ContinuityState** — persisted live continuity row keyed by
`podId + nodeId`.
## 2. Execution and projection types
(`architecture.md` §4 "Execution and restore" — restore/snapshot members are
detailed in `lifecycle-snapshot-restore.md`; the spec/projection members live
here)
- **ResolvedNodeConfig** — output of profile resolution. Carries effective
runtime/model/cwd, narrowed restore policy, selected resources, layered
startup block, resolved spec identity.
- **ProjectionPlan** — runtime projection plan for a node: runtime, cwd,
projection entries, startup block, diagnostics, conflict/no-op
classifications.
- **RuntimeAdapter** — the five-method contract (adapter detail in
`adapters-and-runtimes.md`): `listInstalled(binding)`
(`runtime-adapter.ts:131`), `project(plan, binding)` (`:134`),
`deliverStartup(files, binding)` (`:137`), `launchHarness(binding, opts)`
(`:147`), `checkReady(binding)` (`:153`). Re-confirmed @HEAD — the contract
is current.
- **HarnessLaunchResult** — `{ ok, resumeToken?, resumeType?, error? }`
returned by `launchHarness`.
- **StartupOrchestrator** — drives the full startup sequence (§4 below).
## 3. Parsing, validation, resolution pipeline
(`architecture.md` §5 "Parsing and validation" + "Resolution pipeline"; all
under `packages/daemon/src/domain/`, zero Hono imports per Architecture Rule 1)
**Parse / validate:**
- `agent-manifest.ts` — canonical AgentSpec parse/normalize/validate.
- `rigspec-schema.ts` — dual-format RigSpec validation.
- `rigspec-codec.ts` — dual-format YAML codec.
- `startup-validation.ts` — shared startup-block validation.
- `path-safety.ts` — shared relative-path safety checks.
- `spec-validation-service.ts` — pure raw-YAML validation helpers.
- `spec-review-service.ts` — daemon-owned structured review model for
RigSpec/AgentSpec YAML, incl. topology preview, provenance state, managed-app
services metadata (`waitFor`, `surfaces`, `composePreview`).
**Resolve:**
- `agent-resolver.ts` — resolves `agent_ref`, imports, collision metadata.
- `agent-preflight.ts` — single-agent resolution/preflight.
- `profile-resolver.ts` — applies defaults, profile uses, resource selection,
startup layering, restore-policy narrowing.
- `startup-resolver.ts` — additive startup layering.
- `projection-planner.ts` — runtime resource projection planning.
All eleven files re-confirmed present in `packages/daemon/src/domain/` @HEAD.
## 4. Startup orchestration (the spec-startup contract)
(`architecture.md` §4 "StartupOrchestrator" + §5 "Startup, runtime, and
instantiation" + §7 Architecture Rule 6)
`StartupOrchestrator` (`domain/startup-orchestrator.ts`) drives:
mark pending → project resources → deliver pre-launch files → launch harness
→ wait for ready → deliver interactive files → execute actions → persist
context → mark ready.
**Pre-launch vs interactive delivery split** — the load-bearing seam,
re-confirmed at source:
- Pre-launch (filesystem, before harness boot): `guidance_merge`,
`skill_install` (`startup-orchestrator.ts:78,167` — "Deliver pre-launch
files (guidance_merge, skill_install → filesystem)").
- Post-launch (TUI, after harness is ready): `send_text`
(`startup-orchestrator.ts:82,160,263` — partition by concrete hint at
`:141`, deliver after readiness at `:263`).
The orchestrator persists replay context including the resume token for future
restores (consumed by `lifecycle-snapshot-restore.md`).
**Architecture Rule 6 — startup layering is additive and ordered** (carried
verbatim, `architecture.md` §7): (1) agent base, (2) profile, (3) rig culture
file, (4) rig startup, (5) pod startup, (6) member startup, (7) operator debug
append. This is the spec-startup contract's invariant; the full 25-rule list
lives in `architecture-rules-and-event-system.md`.
**Startup action constraints** (`architecture.md` §7 "Current startup action
constraints"): no shell startup actions; action types are `slash_command` and
`send_text` only; non-idempotent actions must not apply on restore; retrying
failed startup is handled as restore.
**Remote import constraints** (§7): the reboot supports `local:...` and
`path:/abs/...`. Remote `agent_ref` sources remain unsupported and fail in
preflight.
## 5. Instantiation, preflight, export
(`architecture.md` §5 "Startup, runtime, and instantiation" + §6 "RigSpec
import / validate / preflight / export")
- `runtime-adapter.ts` — adapter contract + bridge types.
- `rigspec-preflight.ts` — dual-stack legacy preflight plus rebooted
`rigPreflight(...)`.
- `rigspec-instantiator.ts` — dual-stack `RigInstantiator` plus
`PodRigInstantiator`.
- `rigspec-exporter.ts` — dual-format live rig export to YAML/JSON.
- `pod-repository.ts` — pod CRUD plus live continuity-state CRUD.
`routes/rigspec.ts` is the dual-format seam: validate
(pod-aware → `RigSpecSchema.validate`; legacy → `LegacyRigSpecSchema.validate`),
preflight (`rigPreflight({ rigSpecYaml, rigRoot, fsOps })` vs
`RigSpecPreflight.check(spec)`), import
(`podInstantiator.instantiate(yaml, rigRoot)` vs
`RigInstantiator.instantiate(spec)`), export (pod-aware exports canonical
`version: "0.2"` RigSpec; legacy exports flat-node v1).
## 6. Identity: whoami, materialize, bind, adopt
(`architecture.md` §6 "Whoami and adopted-session parity flow" +
"Materialize / bind / adopt flow")
**Whoami resolution** — the daemon owns the truth surface through
`/api/whoami` (`routes/whoami.ts`); tmux metadata is an adopted-session
anchor, not sovereign truth. `whoami-service.ts:8` declares
`resolvedBy: "node_id" | "session_name"`. The route requires `nodeId` or
`sessionName` (`routes/whoami.ts:10-15`). Resolution order:
explicit `--node-id` → explicit `--session` → env vars → tmux metadata →
raw tmux session-name fallback.
- Managed sessions prefer projected `OPENRIG_NODE_ID` /
`OPENRIG_SESSION_NAME`.
- Adopted sessions use tmux-owned metadata written at claim/bind time.
> Drift-nuance D5 (the careful axis — see also `transport-and-transcripts.md`):
> the tmux metadata keys `@rigged_node_id` / `@rigged_session_name` /
> `@rigged_rig_id` / `@rigged_rig_name` / `@rigged_logical_id` in
> `architecture.md` §6 are **CORRECT as-is** and were verified literally at
> source — `claim-service.ts:77-81` writes exactly these `@rigged_*` keys;
> `claim-service.ts` and `rig-lifecycle-service.ts` read them. This is a
> SEPARATE axis from MCP tool names (which are `rig_*`, slice-00 §1.4). Do
> NOT blanket-replace `rigged` → `rig` (banked
> `feedback_release_prep_three_layer_depersonalization`: the rename was
> scoped, not global). The tmux metadata keys were NOT renamed.
> Re-confirmed `claim-service.ts:77-81` @HEAD.
**Materialize / bind / adopt** (`architecture.md` §6): `POST
/api/rigs/import/materialize` creates a pod-aware topology without launching
sessions; `POST /api/discovery/:id/bind` attaches a discovered live session to
an existing logical node; `POST /api/discovery/:id/adopt` is the composite
route (bind to existing node, or create a new member in a target pod and bind
immediately). CLI mirrors via `rig bind` / `rig adopt`. Authored pod namespace
is preserved through adoption so logical ids stay
`${podNamespace}.${memberName}` (Architecture Rule 24: adopted-session parity
is tmux-metadata parity, not fake env-var parity).
## OPEN / carried items
- **D-spec-version (resolved-as-correct):** RigSpec `version: "0.2"` is the
spec-schema axis, validated only as a non-empty string in source. Documented,
not "corrected".
- **D5 (careful, resolved-as-correct for this module):** tmux `@rigged_*`
metadata keys are literally still `@rigged_*` at HEAD — architecture.md §6 is
accurate. The MCP-tool-name `rigged_*` drift lands in
`transport-and-transcripts.md`.
## See also
- `daemon-core.md` — createDaemon wiring; the migration/route surface.
- `adapters-and-runtimes.md` — the five-method RuntimeAdapter contract detail.
- `lifecycle-snapshot-restore.md` — snapshot/restore consumes persisted replay
context.
- `architecture-rules-and-event-system.md` — the full 25 architecture rules.
- Source roots: `packages/daemon/src/domain/{agent-manifest,rigspec-schema,
profile-resolver,startup-orchestrator,whoami-service,claim-service}.ts`,
`packages/daemon/src/routes/{rigspec,whoami}.ts`.
@@ -0,0 +1,216 @@
---
kind: as-built
title: Architecture Invariants, Event System, Compatibility Notes
status: active
topics: [runtime-control, observability, doctrine]
domains: [engineering-advisor, operating-advisor, review]
applies-when: |
Need the cross-cutting architecture invariants the codebase enforces (the
25 architecture rules + startup/import constraints), the shape of the
RigEvent union and its SSE delivery surfaces, or the intentional
compatibility limits that still describe the shipped system.
siblings: [daemon-core.md, coordination-primitive.md]
prerequisite-reads: [../README.md, daemon-core.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# Architecture Invariants, Event System, Compatibility Notes
This module collects the cross-cutting invariants that do not belong to any
single subsystem: the architecture rules the codebase holds itself to, the
event-system shape, and the intentional compatibility limits.
> Verified against source at HEAD `7eaf524c` (`git describe` →
> `v0.3.1-6-g7eaf524c`); package version **0.3.1** across all three packages
> (slice-00 §1.1). HEAD carries 6 commits of unreleased 0.3.2 work; no
> `v0.3.2` tag exists.
## 1. Architecture rules
These are the invariants the codebase is built to preserve (`architecture.md`
§7). Rule 6 (startup layering) and rule 7 (restore-policy narrowing) are the
spec/startup contract — see `agent-spec-and-startup.md` for their flow detail;
they are restated here as system-level invariants.
1. Zero Hono in `domain/` and `adapters/`.
2. Routes depend on the domain; the domain never depends on routes.
3. Shared DB-handle invariants are enforced at construction time.
4. The reboot is engine-first: domain services land before public-surface
rewiring.
5. Runtime is member-authoritative in the pod-aware model.
6. Startup layering is additive and ordered: agent base → profile → rig
culture file → rig startup → pod startup → member startup → operator debug
append.
7. Restore-policy narrowing is one-way only: `resume_if_possible` →
`relaunch_fresh` → `checkpoint_only`.
8. Base/import collisions warn; ambiguous import/import unqualified refs fail
loudly.
9. Bundle assembly and startup-file resolution use containment checks rooted
in the owning artifact.
10. Restore replay uses classification-free projection intent, not stale
startup-time `no_op` / conflict classifications.
11. Startup status is explicit session state: `pending`, `ready`, `failed`.
12. Session recency depends on monotonic ULIDs: `session-registry.ts` uses
`monotonicFactory()`; restore selects the newest session by max ULID.
13. Readiness checking is a retry loop with exponential backoff and
configurable timeout, using adapter-specific probes (Claude TUI
indicator, Codex ready message, terminal immediate).
14. Resume states are locked: `resumed` / `rebuilt` / `fresh`. `rebuilt` =
new process assembled from artifacts.
15. Restore honesty: failed resume is FAILED loudly. No automatic fresh
fallback. Fresh launch is explicit follow-up only.
16. Post-command handoff required on `up`, `down`, `restore`,
`snapshot create`: what happened + current state + next action.
17. Session naming: `{pod}-{member}@{rig}` — human-authored,
system-validated. No generation, no slugification.
18. Communication: tmux is transport, not truth. `send/capture/broadcast`
wrap tmux reliably with honest errors.
19. Transcripts: raw capture via pipe-pane, ANSI strip on read. `rg`
preferred, `grep -E` fallback.
20. Config precedence: CLI flag > env var > config file
(`~/.openrig/config.json`, with legacy fallback from
`~/.rigged/config.json`) > default.
21. Semi-deterministic calibration: build what agents use constantly. Agent
handles edge cases from error messages.
22. `rig ask` is context engineering: gathers evidence, does NOT call an
external LLM. The agent IS the LLM.
23. Spec library truth is YAML on disk; daemon owns the structured
review/index/cache layer.
24. Adopted-session parity is tmux-metadata parity, not fake env-var parity.
25. Human-readable IDs are UI-only presentation helpers. CLI/API/MCP/backend
keep full canonical ids.
### Startup action constraints
- No shell startup actions.
- Action types are `slash_command` and `send_text` only.
- Non-idempotent actions must not apply on restore.
- Retrying failed startup is handled as restore.
### Remote import constraints
The reboot supports `local:...` and `path:/abs/...` agent refs. Remote
`agent_ref` sources remain unsupported and fail in preflight
(`architecture.md` §7 "Remote import constraints"; restated in compat note 1).
## 2. Event system
The daemon's event surface is the single `RigEvent` discriminated union.
> Drift-fix D8 / OPEN-4 (carried verbatim, slice-00): `architecture.md` §8
> says "PL-004 Phase A adds 9 coordination events" and (in §3) "Existing 32
> PL-004 events" / "Existing 20 PL-004 events" — internally inconsistent
> contested PL-004 sub-counts. **Do NOT carry the 9 / 32 / 20 figures.** The
> `architecture.md` §8 "Currently emitted in production code" / "Present in
> the union but not yet emitted" lists also predate 0.3.x and are stale. The
> union shape below is re-derived from source at HEAD, not migrated.
`RigEvent` is declared at `packages/daemon/src/domain/types.ts:94`
(`export type RigEvent =`) and runs through `types.ts:218`. It has **73
union members** (slice-00 §1.8, re-confirmed at HEAD:
`grep -cE '^\s*\| \{ type:'` over L94–218 = 73). Every one of the 73
declared `type:` literals is also constructed somewhere in
`packages/daemon/src/{domain,routes}` (re-verified at HEAD: the set of
`type: "<x>"` literals in domain+routes exactly equals the 73 union members
— zero union-only-but-never-referenced types).
### Per-prefix event families (grep-verified at HEAD)
Each count below is a fresh, primary-source-grep-verified, explicitly-labeled
per-prefix family count over the union body
(`types.ts:94–218`) — NOT the contested PL-004 sub-count (OPEN-4 ruling:
labeled grep-verified family counts are ground truth; the `9`/`32`/`20`
figures are forbidden).
| Prefix | Members | Sample / role |
|---|---|---|
| `node.*` | 7 | `node.added` (`types.ts:97`) … `node.startup_failed` (`:139`) — lifecycle/startup |
| `workflow.*` | 6 | PL-004 Phase D workflow runtime (detail in `workflow-runtime.md`) |
| `watchdog.*` | 5 | `watchdog.evaluation_fired` (`:187`) … `watchdog.job_stopped` (`:191`) — PL-004 Phase C |
| `rig.*` | 5 | `rig.created` / `rig.deleted` / `rig.imported` / `rig.stopped` / `rig.expanded` (`:151`) |
| `queue.*` | 5 | PL-004 Phase A queue lifecycle (`:156`–`:159`, `:169`; detail in `coordination-primitive.md`) |
| `package.*` | 5 | legacy package/install engine events |
| `mission_control.*` | 5 | PL-005 audit/notification (`:212`–`:218`; detail in `mission-control.md`) |
| `bootstrap.*` | 5 | legacy bootstrap-run events |
| `session.*` | 4 | session discovery / status / detach / vanish |
| `classifier.*` | 4 | PL-004 Phase B classifier-lease lifecycle |
| `restore.*` | 3 | restore start/complete/reconcile (detail in `lifecycle-snapshot-restore.md`) |
| `qitem.*` | 2 | `qitem.fallback_routed` (`:160`), `qitem.closure_overdue` (`:161`) |
| `pod.*` | 2 | `pod.created` (`:135`), `pod.deleted` (`:136`) |
| `inbox.*` | 2 | `inbox.absorbed` (`:162`), `inbox.denied` (`:163`) |
| `continuity.*` | 2 | `continuity.sync` (`:140`), `continuity.degraded` (`:141`) |
| singletons | 11 | one member each: `workflow_spec.*`, `view.*`, `stream.*` (`:155`), `snapshot.*`, `seat.*`, `project.*`, `kernel.*`, `chat.*` (`:149`), `bundle.*`, `binding.*`, `agent.*` |
Family counts sum to 73 (15 multi-member families totalling 62 + 11
singletons), re-confirmed at HEAD.
### Emission and delivery
Events are constructed and emitted via `eventBus.emit({ type: ... })` across
domain services (`stream-store.ts`, `workflow-runtime.ts`,
`restore-orchestrator.ts`, `node-launcher.ts`, etc.) and route handlers. The
event log is append-only and SQLite-backed.
Three SSE delivery surfaces (re-confirmed at HEAD):
- `GET /api/events` — global stream of all events (`server.ts:457`
`app.route("/api/events", eventsRoute)`).
- `GET /api/stream/watch` — new stream items (`routes/stream.ts:117`).
- `GET /api/queue/watch` — queue/inbox coordination events
(`routes/queue.ts:357`).
- The chat SSE stream `GET /api/rigs/:rigId/chat/watch` delivers
`chat.message` for one rig (rig-scoped; see compat note 6).
> OPEN-4 (carried verbatim, slice-00): the precise PL-004-only vs PL-005-only
> sub-partition is NOT asserted here. `architecture.md`'s `32`/`20`/`9`
> figures are internally inconsistent and not reconcilable without
> classifying all 73 members by introducing slice — flagged, not smoothed.
> The grep-verified per-prefix family counts above are the substituted ground
> truth.
## 3. Remaining compatibility notes
Intentional limits that still describe the shipped system (`architecture.md`
§11), verified as still-current at HEAD:
1. Remote `agent_ref` imports remain unsupported (see §1 remote import
constraints).
2. Startup actions remain intentionally constrained (`slash_command`,
`send_text`).
3. Legacy compatibility seams still ship for pre-reboot data and v1
artifacts.
4. `rig ask` gathers context only — does not call an external LLM (rule 22).
5. Transcript search prefers `rg`, falls back to `grep -E`; quality/perf
varies by backend.
6. Chat is rig-scoped only — no cross-rig channels or DMs.
7. `--verify` on `rig send` checks pane content for message visibility but
can produce false positives from pre-existing matching content. Known
limitation.
8. Terminal node readiness is shell-ready only — no service health probes.
9. `rig env down --volumes` exists in the CLI surface, but the explicit
daemon-side override is not fully plumbed through yet.
10. Managed-app service surfaces are descriptive only — OpenRig does not
auto-inject service URLs/tokens into agent prompts beyond authored
startup/context files.
11. Specialist delegation is conventional, not automatic — addressed by
session name or normal communication surfaces.
## 4. Cross-references
`architecture.md` §12 names itself the architecture-level source of truth and
points at `codemap.md` for file-by-file structure. Under the modular
as-built, that role is distributed: this module owns the invariants + event
shape; the source-of-truth pointer is the rewritten `../codemap.md`
navigation index.
## See also
- `daemon-core.md` — wiring, DB, migrations, startup; footprint drift-fixes.
- `coordination-primitive.md` — PL-004 Phase A queue/stream/inbox/outbox
events.
- `workflow-runtime.md` — PL-004 Phase D `workflow.*` events.
- `mission-control.md` — PL-005 `mission_control.*` events.
- Source roots: `packages/daemon/src/domain/types.ts` (RigEvent union),
`packages/daemon/src/routes/{stream,queue}.ts` (SSE watch),
`packages/daemon/src/server.ts` (`/api/events`).
@@ -0,0 +1,308 @@
---
kind: as-built
title: Content Surfaces — Files Browser, Atomic Write, Progress Tree, Steering Composer
status: active
topics: [observability, specification-and-bundles]
domains: [engineering-advisor, operating-advisor]
applies-when: |
Need to know how the operator-allowlisted file browser enforces path
safety, how atomic conflict-checked writes + the JSONL edit audit work,
how the workspace PROGRESS.md tree is indexed, or how the one-screen
Steering surface (priority stack + roadmap rail + lane rails + health
gates) is composed. Author-mode module — no prior architecture.md prose;
every load-bearing claim is sourced to file:line at HEAD.
siblings: [workspace-primitive.md, daemon-core.md, ../ui/project-and-for-you.md]
prerequisite-reads: [../README.md, workspace-primitive.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# Content Surfaces — Files Browser, Atomic Write, Progress Tree, Steering Composer
The **content surfaces** are the operator-allowlisted, filesystem-canonical
read/write layer that the Project / Steering UI sits on: a fail-closed file
browser, an atomic conflict-checked write service with a JSONL edit audit,
the recursive PROGRESS.md tree indexer, and the one-screen Steering composer
(+ its compact health-summary gates). None adds SQLite state.
> **AUTHOR-FROM-SOURCE module.** No prior `architecture.md` prose exists for
> this. Every load-bearing claim carries `> Source: <file:line> @HEAD`;
> ambiguity is declared as an OPEN item, never smoothed. Paths are relative
> to `packages/daemon/src/` unless prefixed `packages/` or `docs/`.
>
> Verified at HEAD `7eaf524c` (`git describe` → `v0.3.1-6-g7eaf524c`).
> Package version **0.3.1**; HEAD carries 6 unreleased release-0.3.2
> commits; no `v0.3.2` tag (daemon-core.md; slice-00 §1.1).
>
> **SPLIT NOTE (§10.6).** This is the content-surfaces half of the
> `workspace-and-content-primitives` SPLIT (sibling `workspace-primitive.md`
> carries the workspace primitive + migrations 038/039 +
> missions/projects/slices). See `workspace-primitive.md` § header SPLIT
> NOTE for the §10.6 rationale and the transparent-noted-deviation
> disclosure.
## 0. Release attribution (forensic proof — read first)
Per §10.8, re-verified at HEAD via `git cat-file -e <tag>:<path>`:
| Subsystem | Release | Forensic proof @HEAD |
|---|---|---|
| `domain/files/{path-safety,file-write-service}.ts` | **≤0.3.0** | `v0.3.0:<path>` → present |
| `domain/progress/progress-indexer.ts` | **≤0.3.0** | `v0.3.0:<path>` → present |
| `domain/steering/{steering-composer,health-summary}.ts` | **≤0.3.0** | `v0.3.0:<path>` → present |
| `routes/{files,progress,steering,health-summary}.ts` | **≤0.3.0** | `v0.3.0:<path>` → present |
> Source: §10.8 proof re-run at HEAD `7eaf524c` — every listed path
> resolves at `v0.3.0` (no failures). All content surfaces are
> **≤0.3.0** features (UI Enhancement Pack v0 + Operator Surface
> Reconciliation v0; slice-00 0.3.0-GT §1.7 "Files / Markdown /
> Progress / Proofs" confirms the cluster shipped 0.3.0). Do **not**
> back-attribute any of these to 0.3.1 — the gap is missing
> architecture.md prose, not a new feature.
## 1. Path safety — the fail-closed allowlist (UI Enhancement Pack v0)
The file browser is gated by a daemon-enforced, **fail-closed** allowlist.
Roots are decoded from `OPENRIG_FILES_ALLOWLIST` (env), comma-separated
`<name>:<absolute-path>` pairs (legacy fallback `RIGGED_FILES_ALLOWLIST`
via `||` so an empty string falls through). Invalid pairs (no colon, empty
name, non-absolute path) are **silently skipped**; duplicate names →
last-wins. Empty/unset → no roots → routes return an empty list with a
structured "configure OPENRIG_FILES_ALLOWLIST" hint. The safe default after
a fresh install is **nothing allowlisted**.
> Source: `domain/files/path-safety.ts:50-51` (env vars),
> `:60-93` (`decodeAllowlist` / `readAllowlistFromEnv`; silent-skip
> L67-71, last-wins L78, `||` fallback comment L89-91) @HEAD.
`resolveAllowedPath(allowlist, rootName, relativePath)` is the load-bearing
guard. Algorithm: (1) reject unknown root (`root_unknown`); (2) reject
expressed-intent `..` segments **before** filesystem resolution
(`path_escape`) — segment-split so `foo..bar` is not a false positive;
(3) reject an absolute `relativePath` (`path_invalid`); (4) resolve
symlinks via `fs.realpathSync` and reject when the realpath does not start
with `<canonicalRoot><sep>` (`path_escape`) — a `path.sep` boundary so
`/foo/bar` does not match `/foo/bar-other`; (5) `path === ""` resolves to
the root itself (so callers can list the root). Symlinks **inside** the
tree resolve normally; symlinks pointing **outside** are escape attempts.
A non-existent candidate falls back to the unresolved path so the
subsequent stat surfaces the absence with a specific code.
`resolveAllowedFile` / `resolveAllowedDirectory` add a stat assertion
(`not_a_file` / `not_a_directory`).
> Source: `domain/files/path-safety.ts:95-171` (`resolveAllowedPath`;
> `..`-before-fs L124-140, absolute-reject L141-147, sep-boundary
> L158-169, empty-path base case in the doc-comment L108-110),
> `:173-225` (file/dir convenience asserts) @HEAD.
## 2. Atomic write + JSONL audit (UI Enhancement Pack v0 item 4)
`FileWriteService.writeAtomic(req)` is the operator-actionable write surface
for `STEERING.md` / `PROGRESS.md` / spec YAML / any allowlisted file.
Sequence: (1) resolve target under allowlist (reuses §1 path-safety);
(2) re-stat + re-hash the target — if `mtime !== expectedMtime` OR
`contentHash !== expectedContentHash`, throw `WriteConflictError` carrying
the **current** mtime + hash for the UI to surface (optimistic-concurrency,
not a lock); (3) write to a temp file in the **same directory** (PID +
random suffix so concurrent writes don't collide); (4) `fsync` the temp fd
for durability before the rename; (5) atomic `renameSync` over the target
(single inode swap on POSIX — readers see old or new, never partial);
(6) recompute mtime + hash + byte delta; (7) append one JSONL audit row.
> Source: `domain/files/file-write-service.ts:9-25` (documented
> atomic-write semantics), `:111-212` (`writeAtomic`; conflict-detect
> L129-135, same-dir temp L137-141, fsync L146, atomic rename L161)
> @HEAD.
The audit file is `~/.openrig/file-edit-audit.jsonl` by default
(`HOME`/`USERPROFILE` → `/tmp` fallback). **Append-only; never rotates at
v0.** A failed audit append throws `FileWriteError("audit_write_failed")`
but does **NOT** undo the landed write — the user's edit succeeded; an
audit-system flake must not silently revert canon. (The route still
surfaces it as a 500 so the failure is honest, not swallowed.)
> Source: `domain/files/file-write-service.ts:87-91` (default path +
> fallback), `:24-25` (never-rotates-at-v0), `:182-204` (audit append;
> "does NOT undo the write" comment L183-184) @HEAD.
## 3. Files routes — browse + read + asset + write
`filesRoutes()` (mounted `server.ts:507` as `/api/files`). All routes are
**literal** (no `/:param` catchall) so order doesn't matter for shadowing
(Phase A R1 SSE lesson):
- `GET /roots` — allowlist root list (or `{roots:[], hint}` when none).
- `GET /list?root&path` — directory entries (dirs first, then files,
name-sorted; dotfiles always included — allowlisting a root expresses
inspection intent).
- `GET /read?root&path` — file content + `mtime` + `contentHash` (SHA-256)
+ `size`. **Content is capped at `FILE_READ_TRUNCATION_BYTES` (1 MB)** but
the hash is computed over the **FULL** file so atomic-write conflict
detection stays honest even on a truncated read; response carries
`truncated` / `truncatedAtBytes` / `totalBytes`.
- `GET /asset?root&path` — raw bytes for embedded images/video/pdf (inferred
`Content-Type`, 5-min cache).
- `POST /write` — atomic write (§2); 503 when no write service
(`OPENRIG_FILES_ALLOWLIST` empty); 409 `write_conflict` on stale
mtime/hash with the current values for the UI's refresh prompt.
503 `files_routes_unavailable` when the allowlist dep is unwired.
Path-safety errors map to HTTP per code (`root_unknown`/`path_*` → 400,
`stat_failed` → 404).
> Source: `routes/files.ts:51-242` (handlers; route-order comment
> L17-19, truncation L139-154, write 503/409 L187-191/L225-231,
> path-safety→HTTP `:61-69`); `FILE_READ_TRUNCATION_BYTES = 1_048_576`
> `:49`; mounted `server.ts:507`; CLI: no `rig files` verb — files are
> a UI-only surface @HEAD.
> **§10.7 route-reality (source-verified at `packages/ui/src/routes.tsx`):**
> `/files` is a **REAL route** (`FilesWorkspace`) the Phase-8.1 survey
> MISSED. There is **NO `/markdown` route** — markdown rendering is a
> *component* inside file / drawer surfaces, not a navigable destination.
>
> Source: `packages/ui/src/routes.tsx:192-195` (`path: "/files"` +
> `FilesWorkspace`); grep-confirmed no `path: "/markdown"` declaration
> anywhere in routes.tsx @HEAD.
## 4. Progress tree indexer (UI Enhancement Pack v0 item 1B)
`ProgressIndexer` walks operator-allowlisted scan roots
(`OPENRIG_PROGRESS_SCAN_ROOTS`, same `<name>:<abs-path>` shape as the file
allowlist; legacy `RIGGED_PROGRESS_SCAN_ROOTS`), finds **`PROGRESS.md` AND
`STEERING.md`** files (STEERING.md is anchored as the constraint-frame node
per OSR v0 Item 2; the row-machinery is filename-agnostic), and parses each
into a checkbox-hierarchy tree. Recursion is depth-bounded (default 6 —
enough for mission/lane/slice nesting without descending into
`node_modules`/`.git`/`.worktrees`/`dist`/`build`/`.turbo`/`.next` or
dotfiles). Checkbox status: `[x]` → `done`, `[~]` → `blocked`, `[ ]` →
`active`; headings (`##`–`####`) become hierarchy rows; depth from
2-space indent or heading level. Per-file `counts` + a scan-wide
`aggregate`. **In-memory walk per request; no caching at v0** (bounded by
the operator's allowlist scope).
> Source: `domain/progress/progress-indexer.ts:79-84` (STEERING anchor +
> env vars), `:81` (SKIP_DIRS), `:71` (`DEFAULT_MAX_DEPTH = 6`),
> `:218-235` (checkbox status mapping), `:204-215` (heading rows),
> `:21-23` (no-caching-at-v0) @HEAD.
`progressRoutes()` (mounted `server.ts:508` as `/api/progress`):
`GET /tree` — the indexed hierarchy; 503 `progress_indexer_unavailable`
when unwired; 503 `progress_scan_roots_not_configured` + setup hint when
no roots.
> Source: `routes/progress.ts:18-40` (handler; 503s L29-35); mounted
> `server.ts:508` @HEAD.
> **§10.7 route-reality:** `/progress` is a **`<Navigate to="/project" />`
> redirect-stub** — the progress system lives at the daemon
> `/api/progress` route, but the UI URL folds into Project tabs (Phase 3).
>
> Source: `packages/ui/src/routes.tsx:464-468` ("folds into Project tabs
> (Phase 3) — redirect to /project") @HEAD.
## 5. Steering composer (Operator Surface Reconciliation v0 item 1)
`SteeringComposer.compose()` is the **one-screen composed steering surface**.
It is deliberately narrow: it composes only the **filesystem-derived**
pieces; the UI fetches PL-005 queue views (in-motion / loop-state) and
health gates via their own existing endpoints so the composer stays
testable. Three sources, all resolved from a single workspace root
(`OPENRIG_STEERING_WORKSPACE`; per-piece overrides
`OPENRIG_STEERING_PATH` / `OPENRIG_ROADMAP_PATH` /
`OPENRIG_DELIVERY_READY_DIR` trump the root-derived defaults; legacy
`RIGGED_STEERING_WORKSPACE`):
- **priorityStack** — verbatim `STEERING.md` content + mtime + byteCount.
- **roadmapRail** — `roadmap/PROGRESS.md` checkbox rows; detects `PL-XXX`
rail-item codes; marks the **first unchecked** item as `isNextUnchecked`.
- **laneRails** — `delivery-ready/mode-{N}/PROGRESS.md` per-lane: reuses
`ProgressIndexer` (maxDepth 3) for identical checkbox semantics to the
Progress view; "next pull" = first non-done, non-blocked row (Priority
Rail Rule — shelf/queue recency does NOT override); top-N (default 3)
prefers active+blocked, falls back to done only to fill N.
Missing sources are reported in `unavailableSources` (each names the env
var that would resolve it) rather than failing the whole payload.
`isReady()` is true when **at least one** source resolves.
> Source: `domain/steering/steering-composer.ts:1-25` (narrow-by-design
> rationale + 3-source list), `:103-119` (env vars +
> `steeringOptsFromEnv`), `:155-169` (`isReady` / `compose`), `:198-250`
> (roadmap rail; next-unchecked L231-235), `:282-316` (lane next-pull
> L288-289, top-N L293-296), `RAIL_CODE_REGEX` `:346` @HEAD.
`steeringRoutes()` (mounted `server.ts:510` as `/api/steering`):
`GET /` — the composed payload; 503 `steering_composer_unavailable` when
unwired; 503 `steering_workspace_not_configured` + a hint pointing at
`rig config init-workspace` / `workspace.steering_path` /
`OPENRIG_STEERING_PATH` when no source resolves.
> Source: `routes/steering.ts:18-34` (handler; 503s L23-29); mounted
> `server.ts:510` @HEAD.
> **§10.7 route-reality:** `/steering` is a **`<Navigate to="/project" />`
> redirect-stub** — the composer lives at daemon `/api/steering`; the UI
> URL folds into the Project workspace overview tab (Phase 3).
>
> Source: `packages/ui/src/routes.tsx:470-474` ("folds into Project
> workspace overview tab (Phase 3) — redirect to /project") @HEAD.
## 6. Health-summary aggregator (OSR v0 item 1F)
`computeNodeHealthSummary` / `computeContextHealthSummary` are the compact
health gates on the steering surface — **daemon-side aggregation, not a CLI
shell-out** (no per-request subprocess). Node summary: cross-rig roll-up of
`sessionStatus` + `lifecycleState` via `getNodeInventory` per rig, with an
`attentionRequired` tally. Context summary: reads `context_usage` directly
(ContextUsageStore exposes per-node accessors only; listing all rows is a
steering-surface concern) and buckets by urgency
(`usedPercentage` ≥80 critical / ≥60 warning / else low / null unknown) +
freshness (`sampledAt` age vs 300 s → fresh/stale/none). A missing
`context_usage` table (test harness without the migration) yields an empty
summary, not an error.
> Source: `domain/steering/health-summary.ts:44-46` (thresholds:
> `FRESHNESS_THRESHOLD_S=300`, `URGENCY_CRITICAL_PCT=80`,
> `URGENCY_WARNING_PCT=60`), `:48-66` (node roll-up), `:75-117`
> (context roll-up; table-absent → empty L81-84) @HEAD.
`healthSummaryRoutes()` (mounted `server.ts:511` as `/api/health-summary`):
`GET /nodes`, `GET /context`; 503 `health_summary_unavailable` when the
rigRepo dep is unwired.
> Source: `routes/health-summary.ts:23-44` (handlers; 503 L33,L40);
> mounted `server.ts:511` @HEAD.
## 7. Cross-cutting properties
- **Filesystem-canonical, no new SQLite:** all four surfaces read/write the
filesystem + the JSONL audit; health-summary reads existing
`context_usage` only. No content-surface migration
(`progress-indexer.ts:21-23`; `health-summary.ts:81-84`) @HEAD.
- **Fail-closed, honest errors:** path-safety rejects every escape attempt
before fs resolution; write conflicts surface the current mtime/hash for
an explicit refresh; missing config returns 503 + a setup hint naming the
exact env var — never a silent empty success
(`path-safety.ts:124-169`; `file-write-service.ts:129-135`;
`routes/steering.ts:25-29`) @HEAD.
- **Atomic-or-nothing writes:** same-directory temp + fsync + atomic rename;
a rename failure leaves the target untouched (never a partial write)
(`file-write-service.ts:160-172`) @HEAD.
- **Composer narrowness is deliberate:** the steering composer owns only
filesystem-derived pieces; queue/health come from their own endpoints —
keeps it testable (`steering-composer.ts:6-16`) @HEAD.
## OPEN items (carried, not smoothed)
- **OPEN-A** — the JSONL edit audit at `~/.openrig/file-edit-audit.jsonl`
**never rotates at v0** by explicit design
(`file-write-service.ts:24-25`); unbounded growth is a known accepted v0
state (PRD § Item 4 defers rotation), stated here rather than smoothed.
- **OPEN-B** — `OPENRIG_FILES_ALLOWLIST` vs `OPENRIG_PROGRESS_SCAN_ROOTS`
vs `OPENRIG_STEERING_WORKSPACE` are three independent operator-config
surfaces with the same encoding but separate resolution; there is no
single "workspace allowlist" that unifies them at v0. Source-real;
noted, not reconciled.
- No slice-00 numeric-drift OPEN (1–5) applies — this module carries no
migration-count / route-group / PL-004-event-count claim.
@@ -0,0 +1,157 @@
---
kind: as-built
title: Coordination Primitive — Stream/Queue/Inbox/Outbox (PL-004 Phase A)
status: active
topics: [coordination, observability]
domains: [engineering-advisor, operating-advisor, orchestrator]
applies-when: |
Need to know how the daemon-backed coordination primitive works — the
stream/queue/inbox/outbox tables, the hot-potato closure contract, the
transactional handoff guarantee, or where queue closure is enforced.
siblings: [workflow-runtime.md, mission-control.md, daemon-core.md]
prerequisite-reads: [../README.md, daemon-core.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# Coordination Primitive — Stream/Queue/Inbox/Outbox (PL-004 Phase A)
The PL-004 Phase A coordination primitive is the SQLite-canonical
durable-work layer the daemon exposes through `/api/stream` and `/api/queue`.
It replaces the POC filesystem `rigx queue` / `rigx stream` path for
daemon-backed work; the POC filesystem path remains untouched and the daemon
`rig queue` / `rig stream` write only to SQLite (`architecture.md` §5 L651).
> Verified against source at HEAD `7eaf524c`.
## 1. The five host-scoped tables
Five host-scoped tables back the primitive (`architecture.md` §3 L416–438;
migrations re-confirmed at HEAD `packages/daemon/src/db/migrations/`):
- **`stream_items`** (`023_stream_items.ts`) — L1 append-only intake/audit
root. Columns: `stream_item_id` (ULID PK), `ts_emitted`,
`stream_sort_key`, `source_session`, `body`, `format` (default `text`),
`hint_type`, `hint_urgency`, `hint_destination`, `hint_tags` (JSON),
`interrupt`, `archived_at`. Items immutable after emit (only `archived_at`
may be set).
- **`queue_items`** (`024_queue_items.ts`) — L3 owned-work queue. `qitem_id`
is TEXT PK preserving the POC `qitem-YYYYMMDDHHMMSS-<hex>` shape. State
enum (8 values): `pending | in-progress | done | blocked | failed |
denied | canceled | handed-off`. Carries `closure_reason`,
`closure_target`, `closure_required_at`, `chain_of_record` (JSON),
`blocked_on`, `handed_off_to`/`handed_off_from`, nudge/heartbeat fields.
- **`queue_transitions`** (`025_queue_transitions.ts`) — L3 append-only
transition log; authoritative audit trail for state evolution. No
UPDATE/DELETE from domain code.
- **`inbox_entries`** (`026_inbox_entries.ts`) — mailbox-style asynchronous
deposit; idempotent on `inbox_id`. State: `pending | absorbed | denied`.
- **`outbox_entries`** (`027_outbox_entries.ts`) — sender-side audit;
symmetric to inbox; idempotent on `outbox_id`. Delivery state:
`pending | delivered | failed`.
> Drift-fix D3 — `architecture.md` §3 L243 frames the schema as "27
> migrations (22 existing plus 5 added by PL-004 Phase A)". The 5 PL-004
> Phase A coordination tables (`023`–`027`) are still correct as a *range*,
> but the headline migration count is **40**, not 27 (slice-00 §1.3,
> re-confirmed at HEAD: `startup.ts:206` 40-element `migrate()` array; full
> drift-fix authority and the correction live in `daemon-core.md`).
## 2. The six host-scoped services
Six host-scoped domain services implement the layer (`architecture.md` §5
L649–658; files re-confirmed in `packages/daemon/src/domain/` at HEAD).
Routes import these; services are Hono-free:
- **`stream-store.ts`** — L1 stream: idempotent emit (on `stream_item_id`),
chronological list with cursor pagination, soft archive.
- **`queue-repository.ts`** — L3 queue: create, claim/unclaim, update
(general state mutator with hot-potato strict-rejection on `done`),
transactional handoff (close source as `handed-off` plus create new owned
qitem in a single transaction), pod-fallback rerouting, overdue lookup,
nudge/heartbeat tracking. Cross-rig validation hook exposed as
`validateRig` constructor option.
- **`queue-transition-log.ts`** — append-only state-transition log; used by
`queue-repository.ts`, exposed read-only on
`queue_repository.transitionLog`.
- **`hot-potato-enforcer.ts`** — pure validator for the load-bearing API
contract (see §3).
- **`inbox-handler.ts`** — mailbox handler: authenticated drop (idempotent
on `inbox_id`), absorb (promotes a pending entry to a `queue_item`,
idempotent), deny (records reason). Auth check is a pluggable constructor
hook.
- **`outbox-handler.ts`** — sender-side outbox: idempotent record, mark
delivered/failed, list. Emits no event-bus events (pure audit).
## 3. The hot-potato closure contract (where queue closure is enforced)
`hot-potato-enforcer.ts` is the pure validator for the load-bearing API
contract. Re-confirmed at HEAD (`hot-potato-enforcer.ts:10–24`):
`state=done` requires `closure_reason ∈ {handed_off_to, blocked_on, denied,
canceled, no-follow-on, escalation}`. The reasons
`handed_off_to | blocked_on | escalation` additionally require
`closure_target`:
- `handed_off_to` — work continues with a different seat (`closure_target` =
new owner).
- `blocked_on` — work is parked pending another qitem (`closure_target` =
blocker `qitem_id`).
- `denied` — receiver rejected the work (`closure_target` = reason text).
- `canceled` — sender or receiver withdrew (`closure_target` = note).
- `no-follow-on` — terminal completion, nothing else needed.
- `escalation` — kicked up to a higher tier (`closure_target` = escalation
target).
Tier→SLA mapping for `closure_required_at` also lives in
`hot-potato-enforcer.ts`. This validator is invoked by
`QueueRepository.update()` (and `updateWithinTransaction()`), so closure is
enforced at the daemon transaction boundary — the workflow runtime
*projects* on closure but does not gate it (see `workflow-runtime.md`).
## 4. Coordination events
> Drift-fix D8 / OPEN-4 (carried verbatim, slice-00): `architecture.md`
> §3 L394 says "Existing 32 PL-004 events untouched" and L410 says "Existing
> 20 PL-004 events are unchanged" — these two body claims are internally
> inconsistent with each other and predate 0.3.x. **Do NOT carry either
> number.** The current `RigEvent` union (`packages/daemon/src/domain/types.ts:94`)
> has **73 union members** total (slice-00 §1.8, re-confirmed at HEAD:
> `grep -cE '^\s*\| \{ type: ' = 73`). A precise PL-004-only vs PL-005-only
> sub-partition is not reconcilable from static inspection without
> classifying all 73 members by introducing slice; slice-00 OPEN-4 flags
> this and it is carried, not smoothed.
Coordination events emitted by these services (re-confirmed in
`domain/types.ts` at HEAD): `stream.emitted` (StreamStore.emit,
`types.ts:155`); `queue.created` / `queue.handed_off` / `queue.claimed` /
`queue.unclaimed` / `qitem.fallback_routed` / `qitem.closure_overdue`
(QueueRepository); `inbox.absorbed` (`types.ts:162`) / `inbox.denied`
(InboxHandler). `architecture.md` §8 L987–990 listed these as "9
coordination events"; the count of the broader `stream|queue|inbox|qitem`
event family at HEAD is 10 (`stream` 1 + `queue` 5 + `inbox` 2 + `qitem` 2)
— stated as a re-derived family count, not as a contested PL-004 sub-count
(OPEN-4).
Two SSE surfaces stream coordination events: `/api/stream/watch`
(aliased `/api/stream/sse`, `routes/stream.ts:117–118`) for new stream
items, and `/api/queue/watch` for queue/inbox events. The event log remains
append-only and SQLite-backed.
## 5. Route surface
- `/api/stream` (`server.ts:489`) — `POST /emit` (`routes/stream.ts:24`),
`GET /list` (`:56`), `GET /watch` + `/sse` SSE (`:117`),
`GET /:streamItemId` (`:121`), `POST /:streamItemId/archive` (`:130`).
- `/api/queue` (`server.ts:490`) — `POST /create` (`routes/queue.ts:99`),
`POST /:qitemId/claim` (`:144`), `POST /:qitemId/unclaim` (`:157`),
`POST /:qitemId/update` (`:170`), plus handoff/list/watch surfaces.
## See also
- `daemon-core.md` — daemon wiring, the 40-migration set, route surface.
- `workflow-runtime.md` — PL-004 Phase D runtime that projects on closure.
- `mission-control.md` — PL-005 queue observability over `queue_items`.
- Source roots: `packages/daemon/src/domain/{stream-store,queue-repository,
queue-transition-log,hot-potato-enforcer,inbox-handler,outbox-handler}.ts`,
`packages/daemon/src/routes/{stream,queue}.ts`.
+260
View File
@@ -0,0 +1,260 @@
---
kind: as-built
title: Daemon Core — Wiring, DB, Migrations, Startup
status: active
topics: [runtime-control, observability]
domains: [engineering-advisor, operating-advisor]
applies-when: |
Need to know how the daemon boots, how createDaemon wires the dependency
graph, the SQLite schema/migration set, or the route-mount surface.
siblings: [coordination-primitive.md, agent-spec-and-startup.md, lifecycle-snapshot-restore.md]
prerequisite-reads: [../README.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# Daemon Core — Wiring, DB, Migrations, Startup
OpenRig is a local control plane for multi-agent coding topologies. The daemon
(`@openrig/daemon`) is the framework-free SQLite-backed core that the CLI
(`@openrig/cli`), UI (`@openrig/ui`), and MCP server all sit on top of.
> Verified against source at HEAD `7eaf524c` (`git describe` →
> `v0.3.1-6-g7eaf524c`). Current package version is **0.3.1** across all three
> packages (`package.json` root `"version": "0.3.1"`; slice-00 §1.1). HEAD
> carries 6 commits of unreleased release-0.3.2 work; no `v0.3.2` tag exists.
## 1. System overview
The system has six architectural layers (`architecture.md` §1 L23–30):
1. **AgentSpec / pod-aware core** — spec parsing, resolution, precedence,
startup orchestration, snapshot/restore, bundles.
2. **Operator and topology layer** — harness auto-launch, node inventory,
session naming, infrastructure nodes, explorer UI, existing-rig power-on,
auto-snapshot, post-command handoff.
3. **Communication and history layer** — transcript capture (pipe-pane),
communication primitives (send/capture/broadcast), config/preflight,
`rig ask` context packs, durable rig chat.
4. **Authoring and identity layer** — spec review + spec library, `whoami`,
adopted-session tmux-metadata parity, bind/materialize/adopt workflows.
5. **Rig environment layer** — rig-scoped services records, Compose-backed
service orchestration, readiness gates, env snapshot/restore integration.
6. **Agent-managed software layer** — managed-app classification, app-focused
browse/review/runtime UI, and the canonical `secrets-manager` example.
Legacy flat-node/package flows remain for backward compatibility.
### Verified source footprint at HEAD `7eaf524c`
> Drift-fix D1/D6 — `architecture.md` L6,11 said `OpenRig v0.2.0` /
> "Current v0.2.0 release verification" and L7 said `376` source files. Both
> are a frozen pre-v0.2.0-era header (slice-00 §1.9 — last edited `72982bb2`,
> 2026-03-30). Corrected to the values below.
| Metric | Value @ HEAD | Source (independently re-confirmed) |
|---|---|---|
| Package version | **0.3.1** (HEAD +6 unreleased 0.3.2 commits) | slice-00 §1.1; `package.json:version` |
| Total source footprint | **601** files | slice-00 §1.6; `find packages/*/src` non-test = 279+87+235 |
| Daemon footprint | **279** total / **173** domain / **49** route mounts (46 route files) / **11** adapters / **40** migrations | slice-00 §1.5/§1.6; `find packages/daemon/src` non-test |
| CLI footprint | **87** files | slice-00 §1.6; `find packages/cli/src` non-test |
| UI footprint | **235** files | slice-00 §1.6; `find packages/ui/src` `.ts`+`.tsx` non-test |
> Footprint counts use the `find packages/*/src -type f \( -name '*.ts' -o
> -name '*.tsx' \) ! -name '*.test.*'` predicate (tests live in separate
> `packages/*/test/` dirs). Counts are reproducible with that predicate; a
> different counting convention shifts absolute numbers (slice-00 OPEN-5).
### The stack
> Drift-fix D2 — `architecture.md` L37,125 said `CLI (53 command groups)`.
> Corrected to **58** at HEAD (slice-00 §1.2: 53 at v0.2.0 tag, 56 at v0.3.0,
> 57 at v0.3.1, **58 at HEAD** — the 58th is `scopeCommand()` added post-0.3.1
> by `0b77cba4`, re-confirmed `index.ts:20,187`).
>
> Drift-fix D4 — `architecture.md` L40 said `31 route groups` and L76 said
> "`createApp()` now mounts 22 route groups". Corrected to **49 `app.route()`
> mounts + 4 dedicated handlers** (slice-00 §1.5; re-confirmed `server.ts`
> 49×`app.route(` L450–513, plus `app.get("/healthz")` :446,
> `handleExportYaml` :461, `handleExportJson` :462, `app.get("*")` :519).
> Carry slice-00 **OPEN-2**: "route-group count is definitional" — there is
> no single canonical "route group" definition in source; reported as mount
> count + dedicated handlers.
>
> Drift-fix D3 — `architecture.md` L54 said `SQLite state (36 migrations)`.
> Corrected to **40** (slice-00 §1.3; re-confirmed below).
```text
CLI (58 command groups) / UI (explorer + workspace + drawer) / MCP (17 tools)
|
v
Hono daemon routes (49 app.route() mounts + 4 dedicated health/export/static handlers)
|
+-- dual-format route adapters (legacy v1 + rebooted v0.2)
+-- env routes (status / logs / down)
+-- transport routes (send/capture/broadcast)
+-- transcript routes (tail/grep)
+-- ask routes (context evidence packs)
+-- chat routes (durable rig messaging + SSE)
+-- spec review/library routes (managed-app enrichment + compose preview)
+-- whoami identity + context-usage route
+-- coordination routes (stream / queue / workflow / mission-control)
|
v
Framework-free domain services (173 daemon domain files)
|
+-- SQLite state (40 migrations)
+-- tmux / cmux / resume adapters
+-- runtime adapters (Claude Code / Codex / Terminal)
+-- RigEnv substrate (compose adapter, readiness, orchestrator)
+-- transport / transcript / chat / ask layers
+-- whoami identity service
```
The core product loop: `down (auto-snapshot) → up <rig-name> (auto-restore) →
handoff → inspect/attach → work → repeat`.
> MCP tool count is **17** (`rig_*`) — slice-00 §1.4 confirms the count is
> correct and the names are `rig_*` (NOT `rigged_*`; the `rigged_*` text in
> `architecture.md` §2 is stale — the rename predates v0.2.0). Per-occurrence
> verification of any `rigged_*` reference lands in `transport-and-transcripts.md`
> (D5); the tmux `@rigged_*` metadata keys are a separate axis, not blanket-replaced.
## 2. Database schema
> Drift-fix D3 — `architecture.md` L243 said "27 migrations (22 existing plus
> 5 added by PL-004 Phase A)" and L1002 repeated "27 migrations"; the §1 stack
> diagram L54 said "36 migrations". All corrected to **40** migrations
> (`001`–`040`). Triangulated (slice-00 §1.3, re-confirmed at HEAD): (1)
> filesystem `packages/daemon/src/db/migrations/[0-9][0-9][0-9]_*.ts` → 40
> files, `001_core_schema.ts` … `040_workflow_specs_diagnostic.ts`; (2)
> `startup.ts:206` `migrate(db, [...])` passes a 40-element schema array
> (`coreSchema` … `workflowSpecsDiagnosticSchema`); (3) `migrate.ts:13`
> applies them sorted by name, tracked in `schema_migrations`.
### Core state tables (`001_core_schema.ts`)
`rigs` (topology container, `001_core_schema.ts:7`), `nodes` (logical node
identity, `:17`), `edges` (logical topology relationships, `:30`), plus
`bindings` (physical tmux/cmux surface attachment), `sessions` (live execution
state), `events` (append-only event log), `snapshots` (serialized rig state),
`checkpoints` (per-node recovery state). `architecture.md` §3 L247–289.
### Reboot-era schema
- `014_agentspec_reboot.ts` — reboot schema shape; adds `pods`,
`continuity_state`, and reboot columns on `nodes`/`sessions`/`checkpoints`
(`pod_id`, `agent_ref`, `resolved_spec_*`, `startup_status`,
`continuity_source`). `architecture.md` §3 L253–289.
- `015_startup_context.ts` — persisted startup replay context for restore.
- `016_chat_messages.ts` — durable rig-scoped chat (SQLite-backed; transcripts
remain filesystem-backed via pipe-pane).
- `017_pod_namespace.ts` — first-class authored pod namespace for export/adoption.
- `018_context_usage.ts` — per-node context-usage snapshots.
- `019_external_cli_attachment.ts` — binding-row extension for external CLI attach.
- `020_rig_services.ts` — rig-scoped environment record for service-backed rigs.
- `021_seat_handover_observability.ts`, `022_node_codex_config_profile.ts`.
### Coordination / PL-004 / PL-005 / workspace migrations
- `023_stream_items.ts` … `027_outbox_entries.ts` — PL-004 Phase A
coordination tables (detail in `coordination-primitive.md`).
- `028_project_classifications.ts`, `029_classifier_leases.ts`,
`030_views_custom.ts` — PL-004 Phase B classifier + view tables. (Note:
`architecture.md` L361 said "028 through 030"; the middle migration is
literally `029_classifier_leases.ts` — re-confirmed at HEAD.)
- `031_watchdog_jobs.ts`, `032_watchdog_history.ts` — PL-004 Phase C watchdog.
- `033_workflow_specs.ts`, `034_workflow_instances.ts`,
`035_workflow_step_trails.ts` — PL-004 Phase D Workflow Runtime tables
(detail in `workflow-runtime.md`). `036_watchdog_policy_enum_extension.ts`
is a documenting no-op.
- `037_mission_control_actions.ts` — PL-005 Phase A audit table
(`037_mission_control_actions.ts:54` `CREATE TABLE … mission_control_actions`;
detail in `mission-control.md`).
- `038_workspace_primitive.ts`, `039_queue_target_repo.ts` — PL-007 typed
workspace primitive (`bab24bf7`).
- `040_workflow_specs_diagnostic.ts` — slice-11 (`f68f453a`); an
`ALTER TABLE ADD COLUMN` adding parser/validator diagnostic columns to
`workflow_specs` (no new table). **Net-new since `architecture.md` was last
edited** — slice-00 §1.3 provenance; carried into `workflow-runtime.md`.
Legacy package/bootstrap/discovery tables (`packages`, `package_installs`,
`install_journal`, `bootstrap_runs`, `bootstrap_actions`,
`runtime_verifications`, `discovered_sessions`) remain active.
## 3. Route-mount surface
`createApp(deps)` (`packages/daemon/src/server.ts:295`) mounts **49**
`app.route()` route-group mounts (`server.ts` L450–513) plus 4 dedicated
non-route handlers: `GET /healthz` (`:446`), `GET /api/rigs/:rigId/spec`
(`handleExportYaml`, `:461`), `GET /api/rigs/:rigId/spec.json`
(`handleExportJson`, `:462`), and the static/deep-link `app.get("*")`
catch-all (`:519`).
> OPEN-2 (carried verbatim, slice-00): the route-group "count" is definitional
> — "49" is the count of `app.route()` mounts in `server.ts`. The older
> "31 route groups" / "createApp now mounts 22 route groups" framing
> (`architecture.md` L40,76) used a different, smaller accounting. Independent
> corroboration: `packages/daemon/src/routes/` has 46 non-test route `.ts`
> files (some groups composed from shared modules; the 49 mounts are the
> authoritative count of mounted groups — slice-00 §1.5).
Mount families include reboot-era rig/session/spec routes plus the coordination
routes (`/api/stream` `server.ts:489`, `/api/queue` `:490`,
`/api/workflow` `:495`, `missionControlRoutes(...)` `:498`),
`/api/health-summary` (`:511`), `/api/rigs/:rigId/env` (`:512`), and
`/api/restore-check` (`:513`).
## 4. Startup sequence (`createDaemon`)
`createDaemon(opts?)` is `packages/daemon/src/startup.ts:203` (async,
returns `DaemonResult`). It returns `{ app, db, deps, contextMonitor }`
(`startup.ts:1204`). The sequence (`architecture.md` §9 L1000–1028,
corrected against source):
1. Open SQLite and run **all 40 migrations** (`startup.ts:206`
`migrate(db, [coreSchema … workflowSpecsDiagnosticSchema])` — a 40-element
array; `architecture.md` L1002 said "27 migrations (22 existing plus the 5
PL-004 Phase A coordination tables)" — corrected to 40, drift-fix D3).
2. Construct core repositories and legacy services.
3. Construct package/bootstrap/discovery services.
4. Construct rebooted startup/runtime services: `StartupOrchestrator`,
`ClaudeCodeAdapter`, `CodexRuntimeAdapter`, `TerminalAdapter`,
`PodRigInstantiator`, `PodBundleSourceResolver`.
5. Construct rig environment services: `ComposeServicesAdapter`,
`ServiceOrchestrator`.
6. Construct operator/transport/history services: `TranscriptStore`,
`SessionTransport`, `ChatRepository`, `AskService` (with `HistoryQuery`),
`ResumeMetadataRefresher`, `ContextUsageStore`, `ContextMonitor`,
`NodeInventory`.
7. Construct authoring/identity/managed-app services: `SpecReviewService`,
`SpecLibraryService`, `WhoamiService`.
8. Construct `BootstrapOrchestrator` with both legacy and rebooted seams.
9. Construct PL-004 Phase A coordination services from a shared
`QueueRepository` instance (so `InboxHandler.absorb()` and `/api/queue`
write to the same repo): `StreamStore`, `QueueRepository`, `InboxHandler`,
`OutboxHandler`.
10. Build `AppDeps`, enforce shared-DB invariants, and call
`createApp(deps)` (`startup.ts:1202`) to mount the full route tree.
The daemon entrypoint `packages/daemon/src/index.ts:36` calls
`createDaemon({ dbPath, bearerToken })`.
## 5. Test and verification state
> Drift-fix D7 / OPEN-3 (carried verbatim, slice-00): `architecture.md` L12,13
> and §10 L1036–1046 assert daemon `2561/2561` / CLI `794/794` / total
> `2422/2422` test pass counts and per-package file counts (`127`/`37`/`37`).
> **These are runtime claims and are NOT re-run here** — a read-only static
> trace counted `*.test.ts` files only: daemon **255**, cli **234**
> (slice-00 §1.7; ui test-file count not separately gathered). Pass tallies
> are marked `unverified-runtime-claim`; do not assert them as current. To
> assert pass counts, run `pnpm/npm test` and re-verify.
## See also
- `coordination-primitive.md` — PL-004 Phase A stream/queue/inbox/outbox.
- `agent-spec-and-startup.md` — spec parsing/resolution/startup contract.
- `lifecycle-snapshot-restore.md` — snapshot/restore/continuity.
- Source roots: `packages/daemon/src/{startup.ts,server.ts,index.ts}`,
`packages/daemon/src/db/migrations/`, `packages/cli/src/index.ts`.
@@ -0,0 +1,214 @@
---
kind: as-built
title: Lifecycle — Snapshot, Restore, Continuity
status: active
topics: [continuity, runtime-control]
domains: [engineering-advisor, operating-advisor]
applies-when: |
Need to know how OpenRig captures a snapshot, restores a rig (resume vs
rebuild vs fresh), enforces restore honesty, consults live continuity state,
or how the daemon-side restore-check / restore-packet readiness probes work.
siblings: [daemon-core.md, agent-spec-and-startup.md, transport-and-transcripts.md]
prerequisite-reads: [../README.md, agent-spec-and-startup.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# Lifecycle — Snapshot, Restore, Continuity
The durable-state half of the core product loop:
`down (auto-snapshot) → up <rig-name> (auto-restore) → handoff`. Snapshot
captures serialized rig state; restore replays it honestly (no silent
fresh-fallback); restore-check is a separate read-only readiness probe.
> Verified against source at HEAD `7eaf524c` (`git describe` →
> `v0.3.1-6-g7eaf524c`). Package version **0.3.1** (slice-00 §1.1). Source
> located by `architecture.md` headings (§4 Execution and restore, §5
> Snapshot/restore/continuity, §6 Snapshot/restore + Auto-snapshot, §7 rules)
> per slice-08 §10.1 — line numbers advisory only. This module is a pure
> split EXCEPT §6 (restore-check/restore-packet) which is the D15
> author-from-source piece — flagged explicitly there.
## 1. Snapshot / restore / continuity types
(`architecture.md` §4 "Execution and restore" — spec/projection members live
in `agent-spec-and-startup.md`; the snapshot/restore members live here)
- **NodeRestoreOutcome** — `"resumed" | "rebuilt" | "fresh" | "failed" |
"n-a"` — the locked restore vocabulary. Re-confirmed at source:
`restore-orchestrator.ts:725-726` sets `baseStatus = "resumed"` on a
resumed harness; `:763` sets `"rebuilt"` when a checkpoint is replayed; the
outcome union appears at `:944` (`{ kind: "resumed" }` … ).
- **SnapshotData** — current serialized snapshot payload. Reboot extensions
are optional for older-snapshot compatibility: `pods?`,
`continuityStates?`, `nodeStartupContext?`.
- **NodeStartupSnapshot** — persisted restore replay input:
classification-free projection entries, resolved startup files, startup
actions, runtime.
- **PersistedProjectionEntry** — the classification-free restore replay seam:
persists only entry identity + source metadata, NOT stale `classification`,
`conflicts`, or `noOps` (Architecture Rule 10).
## 2. Snapshot, restore, continuity domain services
(`architecture.md` §5 "Snapshot, restore, and continuity")
- `checkpoint-store.ts` — checkpoint persistence with pod/continuity context.
- `snapshot-capture.ts` — captures pods, continuity state, startup replay
context, and latest env receipt. Re-confirmed: `snapshot-capture.ts:66-77`
pulls `pods`, `continuity_state`, and `node_startup_context` rows per rig.
- `snapshot-repository.ts` — snapshot CRUD.
- `restore-orchestrator.ts` — resume, checkpoint delivery, startup replay,
live continuity consultation, topology ordering, and RigEnv boot gating
before agent restore.
## 3. Restore flow and restore honesty
(`architecture.md` §6 "Snapshot / restore" + §7 rules 7/14/15/16)
Restore behavior, each point re-confirmed at `restore-orchestrator.ts`:
- Reads the newest session by **monotonic ULID**, not timestamp alone
(`:700` — "Find the NEWEST session for this node. ULIDs are monotonic, so
latest = max id").
- Consults live `continuity_state`; preserves state when a node is already
`restoring` (`:611-615` — `SELECT status FROM continuity_state …`; if
`status === "restoring"` the node is skipped with a warning).
- Replays restore-safe startup using persisted startup context;
prefilters missing optional artifacts into warnings; **hard-fails a node if
a required startup file is missing** (`:799` — status `"failed"`, error
"Missing required startup files: …").
- Writes a **transcript boundary marker before re-launch** (`:652` — "Write
transcript boundary marker BEFORE launch (before pipe-pane attaches)").
- Refuses to restore over live sessions (`:168` — `rig_not_stopped`: "Rig …
has live sessions. Stop the rig with 'rig down' before restoring").
- Uses `nativeResumeProbe` to honestly assess whether the harness actually
resumed (`:857` continuity-outcome reconciliation).
**Restore-honesty rules (carried verbatim, `architecture.md` §7):**
- Rule 7 — restore-policy narrowing is one-way only:
`resume_if_possible` → `relaunch_fresh` → `checkpoint_only`.
- Rule 14 — resume states are locked: `resumed` / `rebuilt` / `fresh`.
`rebuilt` = new process assembled from artifacts.
- Rule 15 — failed resume is FAILED loudly. No automatic fresh fallback.
Fresh launch is explicit follow-up only.
- Rule 16 — post-command handoff required on `up`, `down`, `restore`,
`snapshot create`: what happened + current state + next action.
(The full 25-rule list lives in `architecture-rules-and-event-system.md`.)
## 4. Auto-snapshot and existing-rig power-on
(`architecture.md` §6 "Auto-snapshot and existing-rig power-on")
- `rig down <rigId>` auto-captures an `auto-pre-down` snapshot before
teardown.
- `rig up <rig-name>` (no file extension) searches for an existing rig by
name and restores from the latest `auto-pre-down` snapshot.
- If no snapshot: error with guidance ("No saved snapshot for rig 'X'. Boot
from a spec or bundle path.").
- Post-command handoff: `down` output includes snapshot ID + restore command;
`up` output includes node statuses + attach command.
## 5. Daemon-side restore-check / restore-packet — AUTHORED FROM SOURCE (D15)
> **D15 author bit (flagged per slice-08 §4.7 binding):** `restore-check` and
> `restore-packet` have NO `architecture.md` narrative. This section is the
> one author-from-source piece in this otherwise pure-split module — authored
> at the slice-00 forensic bar from `routes/restore-check.ts` +
> `domain/restore-check-service.ts` + `commands/restore-packet.ts`, file:line
> cited, version-attribution forensically checked.
>
> **Version attribution (forensic):** restore-check is NOT a 0.3.1 feature.
> `routes/restore-check.ts` first-created `277e279c` ("feat: native rig
> restore-check command", 2026-04-23, pre-0.3.0); present at both `v0.3.0`
> and `v0.3.1` git trees (`git ls-tree` confirmed). `restore-packet`
> first-created `23f2921e` ("Restore-Packet vertical M2a", 2026-05-01),
> likewise present at v0.3.0 and v0.3.1. The gap is missing
> architecture.md *prose*, not a version-attribution drift.
### 5.1 `rig restore-check` — readiness probe
`GET /api/restore-check?rig=<name>&noQueue=<bool>&noHooks=<bool>`
(`routes/restore-check.ts:131`). The route assembles a framework-free
`RestoreCheckDeps` (`:138-168`) over existing daemon projections —
`listRigs` from `rigRepo`, `getNodeInventory` (joining `node_id` by
`logical_id`, `:21-26,143-149`), `getStartupContext` (reads
`node_startup_context`, parses `projection_entries_json` /
`resolved_files_json` / `startup_actions_json`, `:44-128`), `hasSnapshot`
/ `getLatestSnapshot` from `snapshotRepo`, and `probeDaemonHealth`
(self-evident: "We're inside the daemon — if this route is responding,
daemon is healthy", `:160-163`). It then runs
`new RestoreCheckService(deps).check(...)` (`:170-171`).
`RestoreCheckService.check()` (`restore-check-service.ts:244`) layers:
1. **Host checks** — `checkDaemonReachable` (probe-throw → `verdict:
unknown`, NOT `not_restorable`, `:252-259`), `checkStateDirWritable`
(`:261`), `checkHostInfraDeclaration` (`:262`, impl `:406`).
2. **Rig enumeration** — `listRigs()` throw → `buildUnknown` (`:267-274`);
`--rig` filter; unknown rig → red `rig.<name>.exists` (`:276-284`).
3. **Per-rig checks** — `checkSnapshot` (`:290`, impl `:675`),
`checkSpecPresent` (`:295`).
4. **Per-seat checks** — `checkSeatReadiness` (`:311`), `checkStartupContext`
(`:315`, impl `:763`; `unknownChecks` → `buildUnknown`),
`checkTranscript` (`:325`), `checkResumePath` (`:329`), and unless opted
out: `checkQueueFile` (`:334`, gated by `--no-queue`, impl `:870`) and
`checkHooks` (`:339`, gated by `--no-hooks`, impl `:896`).
5. **Verdict** — `buildResult` aggregates: any red → `not_restorable`; any
yellow → `restorable_with_caveats`; else `restorable`; probe-uninspectable
→ `unknown` (`:1074-1085`, `:1362-1379`). Plus a `RecoveryPlan`
(`buildRecovery`, `:1186`) and a `RepairStep[]` packet
(`buildRepairPacket`, `:1392`; `null` when fully restorable).
The result shape is `RestoreCheckResult` (`restore-check-service.ts:120-130`):
`verdict`, `readiness`, `continuity`, `rigs[]`, `hostInfra`, `recovery`,
`counts {red,yellow,green}`, `checks[]`, `repairPacket`.
**Honest-error design (slice-00 bar):** a daemon-probe *exception* produces
`verdict: unknown` (uninspectable state), distinct from a daemon
definitely-down state which is `red` / `not_restorable`
(`restore-check-service.ts:249-259`). The route's catch-all returns the same
`unknown`-shaped body with HTTP 500 + a `probe.error` red check
(`routes/restore-check.ts:174-222`). `CheckEntry.remediationSafe` defaults to
`false` (conservative — unclassified remediations are NOT
auto-execution-safe, `restore-check-service.ts:18-24`).
CLI surface (`cli-reference.md` `### rig restore-check`):
`rig restore-check [--rig <name>] [--no-queue] [--no-hooks] [--json]`. Exit
codes: `0` restorable (or with caveats), `1` not restorable (red), `2`
unknown / probe error.
### 5.2 `rig restore-packet` — cross-runtime restore packet
CLI-side, no daemon route. `commands/restore-packet.ts` (528 lines)
implements three subcommands (`cli-reference.md` `### rig restore-packet`):
`write [options]` (generate a packet directory from a source session or JSONL
file, with `omitted-records` accounting), `read <packet-dir> [--json]`
(render contents; non-mutating), `validate <packet-dir> [--json]` (validate
against the v0 schema; non-mutating). Packet shape is the cross-runtime v0
standard — Claude Code and Codex transcripts both supported via runtime
parsers + redaction.
## OPEN / carried items
- **D15 (author-from-source, completed):** restore-check / restore-packet
authored from source above; flagged as the single author bit in this
module. Version attribution forensically resolved (both pre-0.3.0; the gap
was missing prose, not drift).
- No slice-00 numeric drift applies to this module's split content (the
footprint/migration/route counts land in `daemon-core.md`).
## See also
- `agent-spec-and-startup.md` — StartupOrchestrator persists the replay
context that restore consumes.
- `daemon-core.md` — `/api/restore-check` is one of the 49 route mounts
(`server.ts:513`).
- `transport-and-transcripts.md` — transcript boundary markers written on
restore.
- Source roots: `packages/daemon/src/domain/{restore-orchestrator,
snapshot-capture,snapshot-repository,checkpoint-store,
restore-check-service}.ts`, `packages/daemon/src/routes/restore-check.ts`,
`packages/cli/src/commands/restore-packet.ts`.
@@ -0,0 +1,165 @@
---
kind: as-built
title: Mission Control — Queue Observability + 7-Verb Contract (PL-005)
status: active
topics: [coordination, observability]
domains: [engineering-advisor, operating-advisor, orchestrator, human-operator]
applies-when: |
Need to know how the daemon-backed Mission Control surface works — the
seven views, the seven write verbs, the action audit table, the
bearer-token middleware, or how queue observability maps to PL-004 sources.
siblings: [coordination-primitive.md, workflow-runtime.md, ../ui/project-and-for-you.md]
prerequisite-reads: [../README.md, coordination-primitive.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# Mission Control — Queue Observability + 7-Verb Contract (PL-005)
Mission Control (PL-005) is the daemon-backed queue-observability surface: an
integrated product UI inside the existing shell (a top-level `/mission-control`
route, NOT a new managed app) over the PL-004 Phase A coordination primitive.
Per the PRD acceptance criteria: seven views, seven verbs, first-class human
seats, recent-ships=10, and a daemon-backed action audit table; no
old-dashboard migration/cutover (`architecture.md` §3 L368, L390).
> Verified against source at HEAD `7eaf524c`. Mission Control is PL-005 (an
> early-0.3.0 graft); plugins and Claude auto-compaction are 0.3.1 features
> and are NOT back-attributed here (slice-00 0.3.0-ground-truth seams a/row-7).
## 1. The seven views
`MISSION_CONTROL_VIEWS` is the canonical view list (re-confirmed at HEAD
`packages/daemon/src/domain/mission-control/mission-control-read-layer.ts:32–42`):
`my-queue`, `human-gate`, `fleet`, `active-work`, `recent-ships`,
`recently-active`, `recent-observations`.
All seven return rows in the load-bearing 9-field phone-friendly content
model (rig/mission name, current phase,
active|idle|attention|blocked|degraded, next-action,
pending-human-decision, read-cost, last-update timestamp,
confidence/freshness, evidence link). The model is non-negotiable across all
7 views; UI may render compact, JSON preserves all 9 (`architecture.md` §3
L370).
`MissionControlReadLayer` maps each view to its source-of-truth path
(`mission-control-read-layer.ts:4–14`, re-confirmed at HEAD):
- `my-queue` / `human-gate` / `active-work` / `recent-ships` query PL-004
Phase A `queue_items` via `QueueRepository`.
- `fleet` consumes the per-rig CLI capability cache + queue summary.
- `recently-active` delegates to PL-004 Phase B
`ViewProjector.show("recently-active")`.
- `recent-observations` reads PL-004 Phase A `stream_items` via
`StreamStore`.
Filesystem fallbacks (`~/.openrig/stream/<date>.jsonl`, raw queue file grep)
are graceful-degradation aids, NOT the primary path (`architecture.md` §3
L378).
> Scope note (slice-00 0.3.0-ground-truth OPEN-3, carried): the exact
> For-You verb subset is an unresolved velocity slice-01 ruling. This module
> describes the **system-level** 7-verb vocabulary (proven, slice-00
> §1.6/seam-c). It does NOT enumerate a For-You-surface subset — that
> surface is described in `../ui/project-and-for-you.md` when authored.
## 2. The seven verbs (the write contract)
The seven verbs execute through the load-bearing
`MissionControlWriteContract` (re-confirmed at HEAD
`packages/daemon/src/domain/mission-control/mission-control-write-contract.ts:27–36`):
| Verb | Effect |
|---|---|
| `approve` | `state="done"`, `closure_reason="no-follow-on"` |
| `deny` | `state="done"`, `closure_reason="denied"` |
| `route` | `state="done"`, `closure_reason="handed_off_to"`, `closure_target`+`handed_off_to`=route target; creates new qitem at the route target (1-hop) |
| `annotate` | no queue mutation; audit record only |
| `hold` | `state="blocked"`, `closure_reason="blocked_on"` |
| `drop` | `state="done"`, `closure_reason="canceled"` |
| `handoff` | the 4-step shape (see below) |
Each verb is one atomic daemon transaction: queue mutation via
`QueueRepository.updateWithinTransaction()` (which preserves Phase A
hot-potato closure validation — see `coordination-primitive.md` §3) + an
audit row in `mission_control_actions` + a persisted
`mission_control.action_executed` event, all in one `db.transaction`. The
4-step `handoff` shape (source-update + destination-create + opt-in
best-effort notify + audit-record append) is verified atomic; notify failure
does NOT roll back durable mutations (PRD invariant). Failure-injection rolls
back source closure + audit row + new qitem together (`architecture.md` §3
L380; `mission-control-write-contract.ts:5,15`).
## 3. The action audit table
`mission_control_actions` (`037_mission_control_actions.ts:54` `CREATE TABLE
IF NOT EXISTS mission_control_actions`) is append-only at the API surface:
it records every operator action through Mission Control with before/after
qitem snapshots for forensic reconstruction. Columns include `action_verb`
(TEXT, app-layer enum enforcement, `:56`) and `acted_at` (TEXT NOT NULL ISO
timestamp); indexes `(acted_at DESC, action_verb)`,
`(qitem_id, acted_at DESC)`, `(actor_session, acted_at DESC)`
(`037_mission_control_actions.ts:28–44`). Phase B added NO migrations — this
Phase A table is the only data source (`architecture.md` §3 L364, L392).
## 4. PL-005 Phase B — bearer middleware, notifications, audit browse
Phase B extends the daemon Mission Control surface:
- **Bearer-token middleware** —
`packages/daemon/src/middleware/auth-bearer-token.ts` (re-confirmed at
HEAD: header `auth-bearer-token.ts:1–9` "PL-005 Phase B"). Constant-time
bearer comparison via Node `crypto.timingSafeEqual`; the daemon refuses to
start with a non-loopback bind interface AND an empty bearer config
(startup-side check). Bearer enforced on the write verbs:
`app.post("/action", requireAuth)` (`routes/mission-control.ts:294`) and
`app.post("/notifications/test", requireAuth)` (`:295`). v0 is bearer-on-write;
no OAuth/SSO/per-user model.
- **Notification dispatcher** — two adapters
(`notification-adapter-ntfy.ts` default + `notification-adapter-webhook.ts`
alternate; selected via `OPENRIG_NOTIFICATIONS_MECHANISM` env) plus
`notification-dispatcher.ts` (re-confirmed in
`domain/mission-control/`). ntfy.sh recommended for the operator's phone
via tailnet.
- **Read-only audit-history browse** — `audit-browse.ts` over
`mission_control_actions`, exposed at `GET /api/mission-control/audit`
(`routes/mission-control.ts:346`) with filters and `(limit, before_id)`
pagination cursored on SQLite `rowid` (`architecture.md` §3 L392).
## 5. Mission Control events
> Drift-fix D8 / OPEN-4 (carried verbatim, slice-00): `architecture.md` §3
> L394 says "Existing 32 PL-004 events untouched" — internally inconsistent
> with §3 L410's "20" and predates 0.3.x. **Do NOT carry either number.**
> The current `RigEvent` union (`packages/daemon/src/domain/types.ts:94`)
> has **73 members** total (slice-00 §1.8, re-confirmed at HEAD); the
> additive `mission_control.*` events are described below WITHOUT asserting
> a contested PL-004 sub-count.
Re-confirmed `domain/types.ts:212–218`: Phase A added
`mission_control.action_executed`, `mission_control.cli_drift_detected`,
`mission_control.view_refreshed`; Phase B added
`mission_control.notification_sent`, `mission_control.notification_failed`
(5 `mission_control.*` members at HEAD).
## 6. Route surface
`missionControlRoutes({ bearerToken })` is mounted at `server.ts:498`. Key
routes (`routes/mission-control.ts`): `GET /views` (`:245`),
`GET /cli-capabilities` (`:250`), `POST /action` (`:298`, auth-gated),
`GET /audit` (`:346`), `POST /notifications/test` (auth-gated), plus an SSE
surface. The integrated UI is the `/mission-control` top-level route in
`packages/ui/src/routes.tsx` mounting `MissionControlSurface`
(`architecture.md` §3 L390); UI detail lands in
`../ui/project-and-for-you.md`.
## See also
- `coordination-primitive.md` — the PL-004 Phase A `queue_items`/`stream_items`
sources Mission Control reads, and the hot-potato closure contract verbs honor.
- `workflow-runtime.md` — PL-004 Phase D transactional-scribe runtime.
- `../ui/project-and-for-you.md` — the UI surface counterpart (authored phase).
- Source roots: `packages/daemon/src/domain/mission-control/`,
`packages/daemon/src/middleware/auth-bearer-token.ts`,
`packages/daemon/src/routes/mission-control.ts`,
`packages/daemon/src/db/migrations/037_mission_control_actions.ts`.
@@ -0,0 +1,143 @@
---
kind: as-built
title: Packaging, Bootstrap, Bundles, Legacy Install Engine
status: active
topics: [specification-and-bundles, release-and-versioning]
domains: [engineering-advisor, operating-advisor]
applies-when: |
Need to know how rig/pod bundles are assembled (schema-version-2 vs legacy
v1), how bundle create/inspect/install and /api/up route across source kinds,
the staged BootstrapOrchestrator plan/apply flow, or which legacy install-
engine seams still ship for pre-reboot data.
siblings: [agent-spec-and-startup.md, plugin-agent-image-context-pack.md]
prerequisite-reads: [../README.md, agent-spec-and-startup.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# Packaging, Bootstrap, Bundles, Legacy Install Engine
How OpenRig packages a topology into a shareable bundle and reconstitutes it
on another host. Fully dual-format: schema-version-2 pod bundles plus legacy
v1 artifacts, routed deterministically by the bootstrap orchestrator.
> Verified against source at HEAD `7eaf524c` (`git describe` →
> `v0.3.1-6-g7eaf524c`). Package version **0.3.1** (slice-00 §1.1). Source
> located by `architecture.md` headings (§5 Bundles/bootstrap/legacy
> compatibility, §6 Bundle create/inspect/install + /api/up, §11 Compat
> note 3) per slice-08 §10.1 — line numbers advisory only.
## 1. Bundle, bootstrap, legacy domain services
(`architecture.md` §5 "Bundles, bootstrap, and legacy compatibility")
- `pod-bundle-assembler.ts` — schema-version-2 bundle assembler.
Re-confirmed: emits `schemaVersion: 2` (`pod-bundle-assembler.ts:167`).
- `bundle-types.ts` — v1 and v2 manifest types plus parse/validate/serialize.
Re-confirmed: v2 `PodBundleManifest` type carries `schemaVersion: 2`
(`:23`); `validatePodBundleManifest` rejects unless `schema_version === 2`
(`:38`); `serializePodBundleManifest` writes `schema_version: 2` (`:62`);
`parsePodBundleManifest` (`:87`); legacy path
`validateLegacyBundleManifest` (`:143`) — both formats live in one file.
- `bundle-source-resolver.ts` — `LegacyBundleSourceResolver`
(`bundle-source-resolver.ts:25`) plus `PodBundleSourceResolver` (`:132`).
- `bootstrap-orchestrator.ts` — staged bootstrap flow with direct pod-aware
rig and v2 bundle delegation. `BootstrapMode = "plan" | "apply"`
(`bootstrap-orchestrator.ts:26`).
- `up-command-router.ts` — spec/bundle source classification for `/api/up`.
`SourceKind = "rig_spec" | "rig_bundle" | "rig_name"`
(`up-command-router.ts:6`).
All re-confirmed present in `packages/daemon/src/domain/` @HEAD.
## 2. Bundle create / inspect / install
(`architecture.md` §6 "Bundle create / inspect / install")
`routes/bundles.ts` is fully dual-format:
- **create** — detects a pod-aware RigSpec and uses `PodBundleAssembler`
(accepts an optional `rigRoot`); legacy create still uses
`LegacyBundleAssembler`.
- **inspect** — safely extracts the archive, detects `schema_version`; v2
returns `schemaVersion: 2`, `agents[]`, and integrity data; v1 returns the
legacy manifest shape.
- **install** — uses the full bootstrap plan/apply; bootstrap peeks the
manifest and routes deterministically to `pod_bundle` or `rig_bundle`.
Re-confirmed at source: `bootstrap-orchestrator.ts:134-143` — when
`sourceKind === "rig_bundle"` it unpacks to a temp peek dir, reads
`bundle.yaml`, and calls `parsePodBundleManifest(...)` to detect the
schema version before routing.
## 3. `/api/up` source routing
(`architecture.md` §6 "`/api/up`")
`UpCommandRouter` + `BootstrapOrchestrator` own:
- direct pod-aware rig specs,
- legacy rig specs,
- v1 bundle installs,
- v2 pod-bundle installs.
Plan mode and apply mode both work across those source kinds.
> Definitional note (carried, not a numeric drift) — `architecture.md` §6
> describes bootstrap routing to `pod_bundle` / `rig_bundle`. The
> `UpCommandRouter` *classification* enum is `SourceKind = "rig_spec" |
> "rig_bundle" | "rig_name"` (`up-command-router.ts:6`); the
> `pod_bundle`-vs-`rig_bundle` distinction is resolved one layer deeper in
> `bootstrap-orchestrator.ts` by peeking the manifest schema version
> (`:134-143`). Both statements are accurate at different layers; documented
> here so the layering is explicit rather than appearing contradictory.
## 4. Legacy install engine (still ships)
(`architecture.md` §5 "Legacy systems that still ship" + §11 compat note 3)
These pre-reboot seams remain active for backward compatibility:
- package install engine: `package-install-service.ts`,
`package-manifest.ts`, `package-repository.ts`, `install-engine.ts`,
`conflict-detector.ts`, `role-resolver.ts` (all re-confirmed present
@HEAD).
- bootstrap and requirement-probe support.
- discovery and claim services.
- tmux/cmux adapters and resume adapters.
> Drift-check D-pkg — `architecture.md` §5/§6 carries no slice-00 numeric
> drift in this content; the v2 bundle-assembler + dual-format flows were
> verified accurate at HEAD (§1–§3 above). The footprint/migration counts
> that ARE stale land in `daemon-core.md`, not here.
Compat note 3 (carried verbatim, `architecture.md` §11): "Legacy
compatibility seams still ship for pre-reboot data and v1 artifacts." (The
full §11 list lives in `architecture-rules-and-event-system.md`.)
> Provenance note (carried, not asserted): `bootstrap-orchestrator.ts:3-5`
> still imports `LegacyRigSpec` / `LegacyRigSpecCodec` / `LegacyRigSpecSchema`
> with in-source `TODO: AS-T08b — migrate to pod-aware RigSpec` markers, and
> `:16` `TODO: AS-T12 — migrate to pod-aware bundle source resolver`. The
> legacy seam is intentional, in-progress migration scaffolding — recorded
> as-is, not smoothed.
## OPEN / carried items
- **D-pkg (resolved-as-current):** no slice-00 numeric drift in this
module's split content; v2 assembler + dual-format flows verified accurate
at HEAD. Bundle-routing layering documented explicitly to pre-empt an
apparent §6-vs-source contradiction.
- Legacy-migration TODOs carried from source verbatim (AS-T08b / AS-T12).
## See also
- `agent-spec-and-startup.md` — `RigInstantiator` / `PodRigInstantiator` and
the dual-format spec seam that bundles wrap.
- `plugin-agent-image-context-pack.md` — the 0.3.0/0.3.1 reusable
starter-state / content-provenance cluster (authored separately in 8.4b).
- `daemon-core.md` — `/api/up` + `/api/bundles` are among the 49 route
mounts; `BootstrapOrchestrator` is constructed in the createDaemon
sequence.
- Source roots: `packages/daemon/src/domain/{pod-bundle-assembler,
bundle-types,bundle-source-resolver,bootstrap-orchestrator,
up-command-router}.ts`, `packages/daemon/src/routes/{bundles,up}.ts`.
@@ -0,0 +1,346 @@
---
kind: as-built
title: Content Layer — Plugins, Agent Images, Context Packs, Compaction Policy
status: active
topics: [extension-and-user-workspace, continuity, skill-management]
domains: [engineering-advisor, operating-advisor]
applies-when: |
Need to know how OpenRig discovers plugins, captures/forks agent images,
assembles/sends context packs, or how the Claude auto-compaction enforcer
decides to send /compact. Author-mode module — no prior architecture.md
prose; every claim is sourced to file:line at HEAD.
siblings: [packaging-bootstrap-bundles.md, agent-spec-and-startup.md]
prerequisite-reads: [../README.md, agent-spec-and-startup.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# Content Layer — Plugins, Agent Images, Context Packs, Compaction Policy
Four filesystem-canonical content primitives the daemon discovers and
serves: **plugins**, **agent images**, **context packs**, and the **Claude
auto-compaction policy enforcer**. None adds SQLite state — all are
filesystem-canonical with in-memory daemon caches.
> **AUTHOR-FROM-SOURCE module.** No prior `architecture.md` prose exists
> for this. Every load-bearing claim carries `> Source: <file:line>
> @HEAD`; ambiguity is declared as an OPEN item, never smoothed. Paths are
> relative to `packages/daemon/src/` unless prefixed `docs/`.
>
> Verified at HEAD `7eaf524c` (`git describe` → `v0.3.1-6-g7eaf524c`).
> Package version **0.3.1**; HEAD carries 6 unreleased release-0.3.2
> commits; no `v0.3.2` tag (daemon-core.md; slice-00 §1.1).
## 0. Release attribution (forensic seam — read first)
Re-verified at HEAD via `git cat-file -e <tag>:<path>`:
| Subsystem | Release | Forensic proof @HEAD |
|---|---|---|
| Context packs | **0.3.0** | `v0.3.0:domain/context-packs/context-pack-library-service.ts` → present (slice-00 0.3.0-GT §1.9) |
| Agent images | **0.3.0** | `v0.3.0:domain/agent-images/agent-image-library-service.ts` → present (slice-00 0.3.0-GT §1.9) |
| Plugins | **0.3.1, NOT 0.3.0** | `v0.3.0:domain/plugin-discovery-service.ts` → **ABSENT**; `v0.3.1:` → present (slice-00 0.3.0-GT seam (a); map row 5) |
| Claude auto-compaction | **0.3.1 headline, no 0.3.0 antecedent** | `v0.3.0:domain/claude-compaction-enforcer.ts` → **ABSENT**; `v0.3.1:` → present (slice-00 0.3.0-GT map row 7) |
> Source: re-run at HEAD `7eaf524c` —
> `git cat-file -e v0.3.0:packages/daemon/src/domain/plugin-discovery-service.ts`
> and `...claude-compaction-enforcer.ts` both fail ("exists on disk, but
> not in 'v0.3.0'"); the two 0.3.0 library services resolve at `v0.3.0`.
> Code present on disk at HEAD does NOT make plugins/compaction a 0.3.0
> feature — ancestry is truth; the same-calendar-day commit date is the
> forensic trap slice-00 0.3.0-GT seam (a) warns about.
**Do not back-attribute plugins or compaction to 0.3.0.** The CLI
reference already encodes this ("## Plugin Inspection (v0.3.1)").
> Source: `docs/as-built/cli-reference.md:943` @HEAD.
## 1. Context packs (PL-014) — 0.3.0
A **context pack** is a directory of `manifest.yaml` + included markdown /
yaml / txt files: operator-authored, library-discoverable, reviewable,
sendable. No SQLite tables; in-memory cache at daemon scope.
> Source: `domain/context-packs/context-pack-types.ts:1-11` @HEAD.
`ContextPackLibraryService.scan()` walks roots, parses each
`manifest.yaml`, replaces the in-memory index; collisions are
**last-wins** in discovery order (workspace > user_file > builtin).
Startup wires three roots: builtin (`../context-packs`, first), user-file
(`~/.openrig/context-packs`), and workspace-local
`<workspaceRoot>/.openrig/context-packs` when present + distinct. Stable
id `context-pack:<name>:<version>`.
> Source: `domain/context-packs/context-pack-library-service.ts:59-94`
> (scan; last-wins L79-81), `:31-33` (id); `startup.ts:481-502` (3-root
> IIFE; builtin `unshift` L497, workspace L491-493) @HEAD.
The parser is pure (no fs; caller passes raw YAML). It rejects malformed
YAML, missing `name`/`version`, non-array `files`, per-file path traversal
(`..`/leading `/`), and unsupported suffixes (`.md .markdown .yaml .yml
.txt`); `version` coerced to string. Per-file token estimate is
`ceil(bytes/4)`.
> Source: `domain/context-packs/manifest-parser.ts:11` (suffixes),
> `:13-121` (rejects; traversal `:83-89`); token estimate
> `context-pack-library-service.ts:46-48` @HEAD.
`assembleBundle` concatenates files into one paste-ready string framed
`# OpenRig Context Pack: <name> v<version>` + optional purpose + `## File:
<path> (role: <role>)` headers. Missing files are **skipped and surfaced
in `missingFiles`** (operator repair), not a hard fail; a present-but-
unreadable file throws `file_read_failed`.
> Source: `domain/context-packs/bundle-assembler.ts:38-39` (prefixes),
> `:73-100` (missing skip L74-76; read-fail throw L81-87) @HEAD.
`contextPacksRoutes()` (mounted `server.ts:482`): `GET /library`,
`POST /library/sync`, `GET /library/:id`, `GET /library/:id/preview`
(assembled, no send), `POST /library/:id/send`
(`{ destinationSession, dryRun }`; dry-run returns text without
`SessionTransport`; real send → 502 on transport failure). `id==="sync"`
→ 404 so it cannot shadow the sync route; 503 when unprovisioned. CLI:
`rig context-pack list|show|preview|sync|add|send` (`send --dry-run`).
> Source: `routes/context-packs.ts:25-138` (table; sync-guard L51; 503
> L31; dry-run L121-123; 502 L126-133); `server.ts:482`;
> `docs/as-built/cli-reference.md:914-929` @HEAD.
## 2. Agent images (PL-016) — 0.3.0
An **agent image** is a snapshot bundle of a productive seat's resumable
state: runtime-specific resume token (Claude `resume_token` / Codex
`thread_id`), source-seat lineage, optional cwd-deltas + notes. Consumable
by AgentSpec `session_source: mode: agent_image`. Filesystem-canonical at
`~/.openrig/agent-images/<name>/` + workspace-local; **no SQLite tables**.
> Source: `domain/agent-images/agent-image-types.ts:1-13` @HEAD.
`AgentImageLibraryService` mirrors `ContextPackLibraryService` (scan / list
/ get / last-wins) with three source-stated differences: `sourceResumeToken`
passes through to consumers (instantiator consumes; operator surfaces
redact); `stats.json` is a separate mutable file updated atomically on
fork-count increment; a `.pinned` sentinel pins from prune. Id
`agent-image:<name>:<version>`.
> Source: `domain/agent-images/agent-image-library-service.ts:5-14`
> (3-difference comment), `:38-41` (id) @HEAD.
`discoverResumeToken(db, sourceSession)` queries `sessions` then `nodes`
and returns a typed failure (`session_not_found`/`runtime_unsupported`)
rather than fabricating a token; only `claude-code`/`codex` have a native
fork primitive. Claude prefers `context_usage.session_id` over persisted
`sessions.resume_token`; Codex uses `resume_token`, falling back to a
binding's `external_session_name` for `external_cli` seats; returns
`nativeId: null` honestly when none.
> Source: `domain/agent-images/resume-token-discovery.ts:37-85` (honest
> null L84; Claude pref L64-69; external_cli L78-83); honesty comment
> `:9-10` @HEAD.
`SnapshotCapturer.capture()` routes through `discoverResumeToken`, throws
`AgentImageError` on failure or missing native id (no fabricated token, no
auto-fallback to fresh), writes manifest + empty `stats.json` via
`install()`, re-scans. Captured `nodeCwd` → manifest `source_cwd` so the
Use-as-starter snippet emits `cwd:` (fork starts in the parent's directory
where Claude's project-dir-scoped jsonl lives); the daemon does NOT
override cwd at fork dispatch.
> Source: `domain/agent-images/snapshot-capturer.ts:60-104` (throw
> L65-79; source_cwd L88-93; install+scan L101-102);
> `routes/agent-images.ts:256-265` (no-cwd-override contract) @HEAD.
**Evidence guard (CATASTROPHIC-bounce; fails closed).**
`evaluateProtection()` protects an image from deletion if ANY: pinned;
referenced by an active `agent.yaml`; referenced by a rig spec; or a
lineage descendant of a protected image (transitive, fixed-point
iteration). Spec-root scanning parses YAML structure (not string-grep)
and is deliberately conservative — false positives (over-protection)
acceptable; false negatives = catastrophic data loss. `--force` /
`?force=true` overrides.
> Source: `domain/agent-images/evidence-guard.ts:1-16` (bounce +
> fail-closed), `:53-115` (direct + transitive; fixed point L92-112),
> `:117-122` (conservative) @HEAD.
**Resume-token redaction at route boundary (LOAD-BEARING).**
`/api/agent-images` redacts `sourceResumeToken` → `"(redacted)"` on every
operator-facing path; tokens are **never returned over the wire**; only
the in-process rigspec-instantiator consumes the real token.
> Source: `routes/agent-images.ts:15-17` + `:44-46` (`redactResumeToken`),
> applied `:60`,`:67`,`:94`,`:161`; slice-00 0.3.0-GT §1.9 flags this
> LOAD-BEARING @HEAD.
`agentImagesRoutes()` (mounted `server.ts:483-485`): `GET /library`,
`POST /library/sync`, `GET /library/:id`, `GET /library/:id/preview`,
`POST /library/:id/pin`, `POST /library/:id/unpin`,
`DELETE /library/:id` (evidence-guarded unless `force=true`),
`POST /snapshot`, `POST /prune` (**dry-run by default**,
`dryRun !== false`); guard `specRoots` injected via
`deps.agentImageSpecRoots`. CLI: `rig agent-image
list|show|preview|create|delete|pin|unpin|prune|sync`.
> Source: `routes/agent-images.ts:54-250` (table; prune default L112;
> delete-guard L224-239); `server.ts:483-485`;
> `docs/as-built/cli-reference.md:895-912` @HEAD.
## 3. Plugins (plugin-primitive Phase 3a) — **0.3.1, NOT 0.3.0**
> **Forensic trap (slice-00 0.3.0-GT seam (a)):** the plugin-discovery
> file's first-creating commit is dated the same day as the 0.3.0 release
> commit but is NOT an ancestor of `v0.3.0`. Plugins are **0.3.1**.
> Re-confirmed at HEAD by the §0 tag-presence test.
`PluginDiscoveryService` is a read-only filesystem aggregator — no SQLite,
no mutation routes (SC-29 EXCEPTION #8, declared verbatim in the source
header). It scans four source kinds, unioned with provenance labels:
vendored (`~/.openrig/plugins/<id>/`), Claude cache
(`~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/`), Codex cache
(same under `~/.codex`), and rig-cwd (`<cwd>/.claude/plugins/*` +
`<cwd>/.codex/plugins/*`). Detection = presence of
`.claude-plugin/plugin.json` and/or `.codex-plugin/plugin.json` (declares
`runtimes`). Slice 28 added `skillCount` (readdir of `<plugin>/skills/`)
to the list response so the index page avoids an N+1 detail fetch
(SC-29 EXCEPTION #11, verbatim).
> Source: `domain/plugin-discovery-service.ts:1-29` (SC-29 #8 + scan
> desc), `:39` (4-kind `PluginSourceKind`), `listPlugins` `:205-276`
> (4 scan blocks), `scanCwdBundledPlugins` `:283-307`, `detectPlugin`
> `:393-453` (marker rule L399-404; `skillCount` L433-451 + #11
> L75-80) @HEAD.
`getPlugin(id)` returns detail (manifests + skills + hooks + MCP servers);
`rig-cwd:` ids are self-resolvable (parses the cwd out of the id prefix
and re-scans so `/api/plugins/:id` does not 404 on an id `?cwd=`
returned). `findUsedBy(id)` walks `agent.yaml` files parsing YAML
structure (not string-grep — comments don't false-positive) to collect
`resources.plugins[].id` + referencing profiles.
> Source: `domain/plugin-discovery-service.ts:309-369` (getPlugin;
> rig-cwd self-resolve L310-321), `extractCwdFromRigCwdId` `:466-479`,
> `findUsedBy` `:371-389`, `readResourcesPlugins` `:599-615`,
> `readProfilesUsingPlugin` `:617-633` (structure-not-grep `:20-23`)
> @HEAD.
`PluginVendorService.ensureLatest()` runs `ensureVendored` (hash-skip
idempotent copy from `packages/daemon/assets/plugins/<name>/` to
`~/.openrig/plugins/<name>/`) then `attemptAutoFetch`
(`github.com/mvschwarz/openrig-plugins`, 5s timeout,
**404/network/timeout tolerated silently** — vendored is ALWAYS the
fallback; upstream repo intentionally empty at v0 so 404 is normal-state;
NO tarball extraction at v0). Wired at startup for `openrig-core`.
> Source: `domain/plugin-vendor-service.ts:1-24`, `ensureVendored`
> `:80-103` (hash-skip L97-99), `attemptAutoFetch` `:111-131`
> (404-tolerant L116-117; no-extract L123-125), `ensureLatest`
> `:138-141`; `startup.ts:434-472` @HEAD.
`pluginsRoutes()` (mounted `server.ts:478`, read-only): `GET /` (filters
`?runtime=`, `?source=`, `?cwd=`), `GET /:id/used-by`,
`GET /:id/files/list?path=`, `GET /:id/files/read?path=` (slice 28
docs-browser), `GET /:id`. Literal sub-paths are mounted **before** the
bare `/:id` catchall (route-order discipline). The files endpoints reuse
the path-safety machinery with the discovered plugin's absolute path as a
synthetic single-root allowlist (operator need not declare plugin paths
in `OPENRIG_FILES_ALLOWLIST`; plugin folders read-only at v0 so the
content hash is informational). CLI: `rig plugin
list|show|used-by|validate`; no `install` verb at v0 (deferred to 0.3.2).
> Source: `routes/plugins.ts:29-39` + `:107-231` (table; before-catchall
> L128-130/L141-142; `pluginRootAllowlist` :74-92; read-only-hash
> L182-184); `server.ts:478`;
> `docs/as-built/cli-reference.md:943-963` @HEAD.
> **OPEN-A** — `parseSourceFilter` (`routes/plugins.ts:69-72`) accepts
> only `vendored|claude-cache|codex-cache`; it does NOT accept `rig-cwd`
> though `PluginSourceKind` (`domain/plugin-discovery-service.ts:39`) and
> `ListPluginsOpts.sourceFilter` include it. `?source=rig-cwd` is
> silently dropped at the route while `?cwd=` still surfaces rig-cwd
> entries unfiltered. Stated as-is; intent (rig-cwd reachable only via
> `?cwd=`) vs filter-gap is not resolvable from source alone.
## 4. Claude auto-compaction enforcer (slice 27) — **0.3.1 headline**
> **No 0.3.0 antecedent (slice-00 0.3.0-GT map row 7).** The enforcer
> file is absent at `v0.3.0`, present at `v0.3.1` (§0).
`ClaudeCompactionEnforcer.maybeAutoCompact()` decides per seat whether
`ContextMonitor` should send `/compact`, driven by operator
`policies.claude_compaction.*` settings. Decoupled from `ContextMonitor`
scheduling; `ContextMonitor` is constructed with the enforcer at startup.
> Source: `domain/claude-compaction-enforcer.ts:7-12`, `maybeAutoCompact`
> `:205-331`; `startup.ts:1191-1199` (enforcer →
> `new ContextMonitor(db, contextUsageStore, claudeAdapter,
> compactionEnforcer)`) @HEAD.
**Defensive contract** (source classifies compaction lifecycle as
load-bearing per the banked permission-layer foot-gun rule):
- **Opt-in, default-off:** `enabled=false` → never triggers.
- **Runtime filter:** triggers only when `runtime === "claude-code"`.
- **Invalid-policy = disabled:** a hand-edited non-integer / out-of-
`[1,100]` `thresholdPercent` is treated as disabled (safer-failure).
- **Re-arm via threshold crossing:** session must drop below threshold
before another auto-compact fires; window state NOT persisted (restart
resets — safer-failure direction).
- **Send-failure graceful-degrade:** returns `{ triggered: false,
reason: "send_failed" }`, never throws; dedup timestamp set only on
successful send so a transient failure retries next tick.
> Source: `domain/claude-compaction-enforcer.ts:14-44` (risk-class +
> contract), runtime `:206-208`, invalid-policy `:224-232`,
> dedup/threshold `:285-300`, send-fail `:312-314`/`:323-325` @HEAD.
**Active handshake state machine** (Claude hooks can supply context but
do not create a new assistant turn): (1) **pre-compact prep** — first
eligible above-threshold tick sends a normal user-channel prep prompt;
state → `prep_prompt_sent`. (2) **/compact** — next eligible tick sends
`/compact <instruction> + trust-channel bridge note`; sets dedup
timestamp + `triggeredAboveThreshold`; queues post stage
`turn_boundary`. (3) **post-compact, below threshold** — staged sends
`turn_boundary` (ack-only) → `restore_prompt` (points at the pending
marker `<openrigHome>/compaction/restore-pending/<key>.json`, transcript
/ session-id fallbacks) → `compliance_prompt` (read-depth audit); final
stage sets post-restore cooldown + clears the above-threshold latch.
> Source: `domain/claude-compaction-enforcer.ts:71-77` (compact+bridge),
> `:79-98` (prep), `:108-145` (restore + marker path), `:147-163`
> (compliance), `:165-171` (turn boundary), state machine `:233-330`
> (below-threshold L233-283; above-threshold L302-330) @HEAD.
Policy fields via `SettingsStore.resolveClaudeCompactionPolicy()`:
`enabled`, `thresholdPercent`, `preCompactInstruction`,
`compactInstruction`, `messageInline`, `messageFilePath`,
`postRestoreAuditInstruction` — each backed by a
`policies.claude_compaction.*` key + `OPENRIG_POLICIES_CLAUDE_COMPACTION_*`
env override. Defaults: dedup `60_000` ms; post-compact restore cooldown
`10 * 60_000` ms.
> Source: `domain/user-settings/settings-store.ts:553-565` (resolver),
> keys `:97-103`, env `:145-151`;
> `domain/claude-compaction-enforcer.ts:45-46` (default windows) @HEAD.
## 5. Cross-cutting properties
- **Filesystem-canonical, no new SQLite** across all four; daemon caches
in-memory; compaction window state intentionally not persisted
(context-pack-types.ts:8-11; agent-image-types.ts:12-13;
routes/plugins.ts:6; claude-compaction-enforcer.ts:26-29) @HEAD.
- **Honest failure, no fabrication** — discovery returns null; capturer
throws; enforcer degrades + never throws; evidence guard fails closed
(resume-token-discovery.ts:9-10; snapshot-capturer.ts:11-12;
claude-compaction-enforcer.ts:30-33; evidence-guard.ts:16) @HEAD.
- **503-when-unprovisioned** is the uniform route pattern when the
backing service is absent from context (routes/context-packs.ts:31;
routes/agent-images.ts:59; routes/plugins.ts:113) @HEAD.
## OPEN items (carried, not smoothed)
- **OPEN-A** — plugin `?source=` filter omits `rig-cwd` (§3); intent vs
filter-gap unresolvable from source.
- No slice-00 numeric-drift OPEN (1–5) applies — this module carries no
migration / route-group / PL-004-event counts. Slice-00 0.3.0-GT
OPEN-3 (For-You verb subset) is out of scope (UI surface, not
content-layer).
@@ -0,0 +1,186 @@
---
kind: as-built
title: Transport, Transcripts, Chat, Ask
status: active
topics: [coordination, observability]
domains: [engineering-advisor, operating-advisor]
applies-when: |
Need to know how rig send/capture/broadcast works, how pipe-pane transcript
capture and rg/grep search behave, how durable rig chat (SQLite + SSE) is
modeled, what rig ask gathers, or the exact MCP-tool-name vs tmux-metadata-key
naming distinction.
siblings: [daemon-core.md, lifecycle-snapshot-restore.md]
prerequisite-reads: [../README.md, daemon-core.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# Transport, Transcripts, Chat, Ask
The communication-and-history layer: tmux is transport, not truth. Send/
capture/broadcast wrap tmux with honest errors; transcripts are raw pipe-pane
captures; chat is daemon-backed SQLite; `rig ask` gathers evidence but never
calls an LLM.
> Verified against source at HEAD `7eaf524c` (`git describe` →
> `v0.3.1-6-g7eaf524c`). Package version **0.3.1** (slice-00 §1.1). Source
> located by `architecture.md` headings (§5 Transport and communication, §6
> Communication/Transcript/Chat flows, §11 Compat notes) per slice-08 §10.1
> — line numbers advisory only.
## 1. The naming axes (D5 — read this first)
This module carries the D5 drift, which has **two independent axes** that
must NOT be conflated or blanket-replaced (banked
`feedback_release_prep_three_layer_depersonalization`: the rename was scoped,
not global). Per-occurrence source verification:
**Axis 1 — MCP tool names: `rig_*` (architecture.md is STALE → corrected).**
slice-00 §1.4 confirms all 17 MCP tools are `rig_*`. The `rigged_*`
references in `architecture.md` are stale text from a rename that predates
v0.2.0:
> Drift-fix D5 (MCP-tool-name axis) — `architecture.md` §5 `node-inventory.ts`
> description says MCP `rigged_rig_nodes`; §6 chat flow says MCP
> `rigged_chatroom_send` + `rigged_chatroom_watch`. Corrected to **`rig_*`**.
> Re-confirmed at source: `mcp-server.ts:288` registers `"rig_rig_nodes"`,
> `:305` `"rig_send"`, `:339` `"rig_capture"`, `:364` `"rig_chatroom_send"`,
> `"rig_chatroom_watch"` (tool #17). Zero `rigged_chatroom_send` /
> `rigged_send` / `rigged_rig_nodes` in non-test product source (grep clean
> @HEAD). slice-00 §1.4; the rename landed in `b183c50c` pre-v0.2.0.
**Axis 2 — tmux metadata keys: `@rigged_*` (architecture.md is CORRECT → do
NOT change).** The tmux metadata keys written at claim/bind time are a
SEPARATE thing from MCP tool names and were NOT renamed:
> Drift-nuance D5 (tmux-metadata-key axis) — `architecture.md` §6 "Whoami
> and adopted-session parity flow" lists `@rigged_node_id`,
> `@rigged_session_name`, `@rigged_rig_id`, `@rigged_rig_name`,
> `@rigged_logical_id`. These are **CORRECT as-is** — verified literally at
> source: `claim-service.ts:77-81` writes exactly these five `@rigged_*`
> keys. Do NOT blanket-sed `rigged` → `rig`; this is a per-occurrence
> verify, not a global substitution. (The metadata-key axis is detailed in
> `agent-spec-and-startup.md` §6.) Re-confirmed `claim-service.ts:77-81`
> @HEAD.
## 2. Transport and communication domain services
(`architecture.md` §5 "Transport and communication")
- `session-transport.ts` — communication primitives: send/capture/broadcast
with session resolution (canonical + legacy names), mid-work detection,
honest error reporting, pod/rig/global targeting.
- `transcript-store.ts` — pipe-pane transcript management: ANSI stripping on
read, boundary markers, readTail, grep. Filesystem-backed, NOT SQLite.
- `history-query.ts` — transcript + chat search. Prefers `rg` when
available, falls back to `grep -E`, surfaces which backend was used.
Re-confirmed: `history-query.ts:7` `backend: "rg" | "grep" | "none"`;
`:103` execs `rg -i --no-filename -e <pattern>`; `:108` returns
`backend: "rg"`.
- `ask-service.ts` — context-engineering evidence pack: gathers rig summary
plus transcript excerpts, chat excerpts, insufficiency state, guidance.
Does NOT call an external LLM.
- `chat-repository.ts` — durable rig-scoped chat: CRUD for `chat_messages`
table, SSE-compatible event emission.
Routes: `routes/{transport,transcripts,ask,chat,whoami}.ts` — all confirmed
present @HEAD.
## 3. Communication flow
(`architecture.md` §6 "Communication flow")
`rig send <session> "message"` → CLI → `POST /api/transport/send` →
`SessionTransport`:
1. Resolve session name (canonical or legacy; by session/rig/pod/global).
2. Check mid-work state (unless `--force`) — re-confirmed
`session-transport.ts:136-141` (`findPatternEvidence(recentLines,
MID_WORK_PATTERNS)`); legacy mid-work check at `:666`.
3. Two-step tmux send: `send-keys -l` → ~200ms delay → `C-m`
(`session-transport.ts:717` submits `C-m`).
4. Optional `--verify`: capture post-send pane, check message visibility
(`session-transport.ts:305` `verify?`; `:694` `if (opts?.verify)`).
5. Honest result with reason on failure.
Architecture Rule 18 (carried, `architecture.md` §7): tmux is transport, not
truth — `send/capture/broadcast` wrap tmux reliably with honest errors.
## 4. Transcript flow
(`architecture.md` §6 "Transcript flow")
1. `NodeLauncher` starts `pipe-pane` immediately after tmux session creation
(before harness boot).
2. Raw terminal output streams to
`~/.openrig/transcripts/{rig-name}/{session-name}.log`.
3. `TranscriptStore` owns path convention, ANSI stripping on read, boundary
markers, `readTail`, `grep`.
4. `rig transcript <session> --tail N / --grep "pattern"` provides
agent-facing access.
5. On restore: a boundary marker is written before re-launch; pipe-pane
reconnects to the same file (append). (Restore-side detail in
`lifecycle-snapshot-restore.md` §3.)
6. `rig ask` gathers rig summary plus transcript excerpts, chat excerpts,
insufficiency state, and guidance.
Architecture Rule 19 (carried): transcripts are raw capture via pipe-pane,
ANSI strip on read; `rg` preferred, `grep -E` fallback. Rule 22: `rig ask`
is context engineering — gathers evidence, does NOT call an external LLM;
the agent IS the LLM.
## 5. Chat flow
(`architecture.md` §6 "Chat flow")
1. `rig chatroom send <rig> "message"` → `POST
/api/rigs/:rigId/chat/send` → `ChatRepository.addMessage()`.
2. SSE: `GET /api/rigs/:rigId/chat/watch` delivers real-time messages.
3. History: `GET /api/rigs/:rigId/chat/history` returns full channel
history; `POST /api/rigs/:rigId/chat/topic` persists topic markers.
4. UI: chat-room tab in the rig drawer.
5. MCP: **`rig_chatroom_send` + `rig_chatroom_watch`** (D5 axis-1 correction
— `architecture.md` §6 said `rigged_*`; source `mcp-server.ts:364` +
tool #17).
6. Source of truth: daemon-backed SQLite (`chat_messages` table), NOT tmux
scrollback.
**ChatMessage** type (`architecture.md` §4): durable rig-scoped message —
`id`, `rigId`, `sender`, `kind`, `body`, `topic`, `createdAt`.
## 6. Compatibility notes (carried verbatim, `architecture.md` §11)
The intentional limits in this layer:
- Note 4 — `rig ask` gathers context only; does not call an external LLM.
The agent reasons about the gathered evidence.
- Note 5 — transcript search prefers `rg` but falls back to `grep -E`;
search quality/performance varies by backend.
- Note 6 — chat is rig-scoped only: no cross-rig channels or DMs.
- Note 7 — `--verify` on `rig send` checks pane content for message
visibility but can produce false positives from pre-existing matching
content. Known limitation.
(The full §11 compatibility-notes list lives in
`architecture-rules-and-event-system.md`.)
## OPEN / carried items
- **D5 (the careful one — resolved per-occurrence, NOT blanket-replaced):**
Axis 1 (MCP tool names) corrected `rigged_*` → `rig_*` (3 sites: §5
node-inventory, §6 chat flow ×2). Axis 2 (tmux `@rigged_*` metadata keys)
verified literally correct at `claim-service.ts:77-81` and left unchanged.
No slice-00 numeric drift applies to this module's split content.
## See also
- `daemon-core.md` — transport/transcript/chat/ask are among the 49 route
mounts; MCP tool count (17, `rig_*`) is anchored there.
- `agent-spec-and-startup.md` §6 — the tmux `@rigged_*` metadata-key axis
detail (whoami/adopt).
- `lifecycle-snapshot-restore.md` §3 — restore-side transcript boundary
markers.
- Source roots: `packages/daemon/src/domain/{session-transport,
transcript-store,history-query,ask-service,chat-repository}.ts`,
`packages/daemon/src/routes/{transport,transcripts,ask,chat}.ts`,
`packages/cli/src/mcp-server.ts`.
@@ -0,0 +1,152 @@
---
kind: as-built
title: Workflow Runtime + Watchdog Policies (PL-004 Phase C/D)
status: active
topics: [coordination, runtime-control]
domains: [engineering-advisor, operating-advisor]
applies-when: |
Need to know how the daemon-native Workflow Runtime works — workflow specs
cache, instance state, step trails, the transactional-scribe projection
contract, or the watchdog policy set including workflow-keepalive.
siblings: [coordination-primitive.md, mission-control.md]
prerequisite-reads: [../README.md, coordination-primitive.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# Workflow Runtime + Watchdog Policies (PL-004 Phase C/D)
The daemon-native Workflow Runtime (PL-004 Phase D) turns an intended
sequence of work into durable SQLite state: declarative workflow specs, live
instance state, append-only step trails, and the load-bearing
transactional-scribe contract. The PRD §L4 operating model is
owner-as-author semantically plus workflow-as-transactional-scribe
mechanically (`architecture.md` §3 L398).
> Verified against source at HEAD `7eaf524c`.
## 1. The three Phase D tables (+ the diagnostic addition)
Re-confirmed at HEAD in `packages/daemon/src/db/migrations/`:
- **`workflow_specs`** (`033_workflow_specs.ts:33` `CREATE TABLE … workflow_specs`)
— a read-through cache of human-authored markdown/YAML spec files. Sources
are workspace-surface; the daemon caches by `(name, version)` with a
content `source_hash` so valid operator edits to the spec file win at next
read (workspace-surface reconciliation). Spec authoring stays
markdown-authoritative; the cache exists for fast lookup and runtime
resolution (`architecture.md` §3 L400).
- **`workflow_instances`** (`034_workflow_instances.ts:45` `CREATE TABLE …
workflow_instances`) — live state per running workflow: `status`
(`active|waiting|completed|failed`), `current_frontier_json` (active qitem
ids), `hop_count` (loop-guard counter), `last_continuation_decision_json`.
Instances survive daemon restart from SQLite — no filesystem
reconciliation (`architecture.md` §3 L402).
- **`workflow_step_trails`** (`035_workflow_step_trails.ts:32` `CREATE TABLE …
workflow_step_trails`) — append-only history of meaningful step
transitions. Every closure produces one trail row pairing the prior qitem
with the next qitem (null on terminal). `WorkflowStepTrailLog.record()` is
the only writer (`architecture.md` §3 L404).
- **`040_workflow_specs_diagnostic.ts`** — slice-11 (`f68f453a`,
slice-00 §1.3 provenance). An `ALTER TABLE ADD COLUMN` adding
parser/validator diagnostic columns to `workflow_specs` (**no new table,
no constraint changes beyond a DEFAULT**; the cache carries the
parse/validation diagnostic for the UI to render — `040_..._diagnostic.ts:5–25`).
**This migration is net-new since `architecture.md` was last edited** and
is not described in any prior as-built doc (slice-00 §1.3 — `f68f453a`
postdates the §3 body) — authored here from source per the slice-08
drift-to-fix register.
`036_watchdog_policy_enum_extension.ts` is a documenting no-op that records
the Phase D watchdog enum extension (Phase C uses application-layer
enforcement via the `PHASE_D_POLICIES` array, so no DDL is needed —
`architecture.md` §3 L363).
## 2. The transactional-scribe contract
The load-bearing Phase D guarantee is implemented in
`WorkflowProjector.project()` (`packages/daemon/src/domain/workflow-projector.ts`).
Re-confirmed at HEAD: the projector header (`workflow-projector.ts:1–20`)
declares "transactional-scribe contract" and `project()` runs a single
`db.transaction` (`workflow-projector.ts:184` `const txn = this.db.transaction(...)`).
Inside that one transaction:
1. Close the current packet (state mutation on `queue_items`).
2. Create the next-step packet (`QueueRepository.createWithinTransaction()`,
`workflow-projector.ts:230`).
3. Record the trail entry.
4. Update the instance frontier + status.
5. Persist workflow events.
Either everything commits or everything rolls back; lost handoffs are
impossible by design. Post-commit, subscribers are notified and the next
owner is nudged (`architecture.md` §3 L406).
`WorkflowRuntime` (`packages/daemon/src/domain/workflow-runtime.ts:61`
`export class WorkflowRuntime`) is the orchestration class above the
projector.
**Phase D scope boundary** (`architecture.md` §3 L412): excludes multi-hop
chaining, gate-return-sweep, and the closure-enforcement path. The daemon's
transactional state remains the closure authority via Phase A's hot-potato
strict-rejection (see `coordination-primitive.md` §3); the workflow runtime
**projects on closure, it does not gate closure**.
## 3. The workflow-keepalive watchdog policy
`workflow-keepalive` is the Phase C-deferred watchdog policy, a TypeScript
port of the POC `lib/policies/workflow-keepalive.mjs` adapted to read SQLite
(`packages/daemon/src/domain/policies/workflow-keepalive.ts:1–5`).
Re-confirmed at HEAD (`workflow-keepalive.ts:5–16`):
- **LOAD-BEARING:** it MUST read `workflow_instances` directly via SQLite —
never the markdown source.
- Eligibility: `status === "active" || status === "waiting"`. Else
`action=terminal, reason="workflow_not_active"`.
- Frontier empty + no fallback target: skip with `reason="empty_frontier"`.
- Resolves frontier qitem owners by querying `queue_items`; combines with
explicit observer/created-by targets; sends to the first resolved target.
The watchdog supervision tree itself (PL-004 Phase C, `031_watchdog_jobs.ts` /
`032_watchdog_history.ts`) records only meaningful evaluations; quiet skip
reasons (`not_due`, `no_actionable_artifacts`, `active_wake_not_due`) are
NOT recorded and do NOT emit `watchdog.*` events — POC parity so agents are
not woken about scheduler polls (`architecture.md` §3 L362). The Phase D
policy enum extends Phase C's three values with `workflow-keepalive`.
## 4. Workflow events
> Drift-fix D8 / OPEN-4 (carried verbatim, slice-00): `architecture.md` §3
> L410 says "Existing 20 PL-004 events are unchanged" — internally
> inconsistent with L394's "32 PL-004 events untouched". **Do NOT carry
> either number.** The current `RigEvent` union
> (`packages/daemon/src/domain/types.ts:94`) has **73 members** total
> (slice-00 §1.8, re-confirmed at HEAD). The additive Phase D `workflow.*`
> events are described below WITHOUT asserting a contested PL-004 sub-count.
Phase D extends `RigEvent` with the additive `workflow.*` events
(re-confirmed `domain/types.ts:196–201`): `workflow.instantiated`,
`workflow.step_closed`, `workflow.next_qitem_projected`,
`workflow.completed`, `workflow.failed`, `workflow.routing_table_changed`
(6 members; a separate `workflow_spec` event also exists in the union).
## 5. Route surface
`/api/workflow` (`server.ts:495`) — `POST /validate`
(`routes/workflow.ts:82`), `POST /instantiate` (`:93`,
`getRuntime(c).instantiate(...)`), `POST /project` (`:118`,
`getRuntime(c).project(...)` — the transactional-scribe entry),
`GET /:instance_id/trace` (instance + trail), `POST /:instance_id/continue`
(idempotent inspect). Surface enumerated `routes/workflow.ts:21–28`.
Cross-ref: the `rig workflow` CLI surface — see `../cli-reference.md`.
## See also
- `coordination-primitive.md` — PL-004 Phase A; the closure authority the
runtime projects against.
- `mission-control.md` — PL-005 queue observability + 7-verb contract.
- Source roots: `packages/daemon/src/domain/{workflow-projector,
workflow-runtime,workflow-instance-store,workflow-spec-cache,
workflow-step-trail-log,workflow-validator}.ts`,
`packages/daemon/src/domain/policies/workflow-keepalive.ts`,
`packages/daemon/src/routes/workflow.ts`.
@@ -0,0 +1,416 @@
---
kind: as-built
title: Workspace Primitive — RigSpec.workspace, Migrations 038/039, Missions/Projects/Slices
status: active
topics: [specification-and-bundles, observability]
domains: [engineering-advisor, operating-advisor]
applies-when: |
Need to know how a rig declares a typed workspace (workspaceRoot / repos /
defaultRepo / knowledgeRoot), how that block is persisted and resolved into
whoami / node-inventory, how per-item target_repo scope is validated, or how
the file-backed missions/slices tree is indexed and projected into the
Project UI. Author-mode module — no prior architecture.md prose; every
load-bearing claim is sourced to file:line at HEAD.
siblings: [content-surfaces.md, daemon-core.md, ../ui/project-and-for-you.md]
prerequisite-reads: [../README.md, daemon-core.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# Workspace Primitive — RigSpec.workspace, Migrations 038/039, Missions/Projects/Slices
The **workspace primitive (PL-007)** is the typed declaration that lets a rig
name *where its work lives* — a workspace root, a set of named repos with
kinds, an optional default repo, and an optional knowledge root — and have
that surface through `whoami` / node-inventory and gate per-item repo scope.
Alongside it, a **file-backed missions/slices tree** is indexed read-only and
projected into the Project UI's mission / slice surfaces.
> **AUTHOR-FROM-SOURCE module.** No prior `architecture.md` prose exists for
> this. Every load-bearing claim carries `> Source: <file:line> @HEAD`;
> ambiguity is declared as an OPEN item, never smoothed. Paths are relative to
> `packages/daemon/src/` unless prefixed `packages/` or `docs/`.
>
> Verified at HEAD `7eaf524c` (`git describe` → `v0.3.1-6-g7eaf524c`).
> Package version **0.3.1**; HEAD carries 6 unreleased release-0.3.2 commits;
> no `v0.3.2` tag (daemon-core.md; slice-00 §1.1).
>
> **SPLIT NOTE (§10.6).** The honest source-grounded scope of
> `workspace-and-content-primitives` (proposed-structure.md §4.9 / D13)
> exceeds ~400 lines across two distinct subsystem clusters with distinct
> source roots. Per the §10.6 SPLIT DIRECTIVE it is split by subsystem
> cluster into this module (workspace primitive + migrations 038/039 +
> missions/projects/slices) and the sibling `content-surfaces.md`
> (files/markdown/progress/steering). This is a transparent noted deviation
> from ratified Q7 "18", a faithful application of the founder's own
> ratified Q3 principle ("distinct primitive / distinct source root →
> split"); surfaced at the slice-08 review gate, not a mid-execution
> interrupt.
## 0. Release attribution (forensic proof — read first)
Per §10.8, re-verified at HEAD via `git cat-file -e <tag>:<path>`:
| Subsystem | Release | Forensic proof @HEAD |
|---|---|---|
| `domain/workspace/{workspace-resolver,frontmatter-validator,default-workspace-scaffold}.ts` | **≤0.3.0** | `v0.3.0:<path>` → present |
| migrations `038_workspace_primitive.ts`, `039_queue_target_repo.ts` | **≤0.3.0** | `v0.3.0:<path>` → present |
| `domain/slices/{slice-indexer,slice-detail-projector}.ts` | **≤0.3.0** | `v0.3.0:<path>` → present |
| `routes/{workspace,slices,projects}.ts` | **≤0.3.0** | `v0.3.0:<path>` → present |
| `domain/workspace/getting-started-narrative.ts` | **0.3.1** | `v0.3.0:` → **ABSENT**; `v0.3.1:` → present |
| `routes/missions.ts` | **0.3.1** | `v0.3.0:` → **ABSENT**; `v0.3.1:` → present |
> Source: §10.8 proof re-run at HEAD `7eaf524c` —
> `git cat-file -e v0.3.0:packages/daemon/src/domain/workspace/getting-started-narrative.ts`
> and `...routes/missions.ts` both fail ("exists on disk, but not in
> 'v0.3.0'"); all other listed paths resolve at `v0.3.0`. The workspace
> primitive itself is a **0.3.0** feature (slice-00 0.3.0-GT §1.4, PL-007,
> migrations 038/039) — do not back-attribute it to 0.3.1. The
> `missions` route + the getting-started narrative scaffold are the
> **0.3.1** additions layered on top (slice 12 mission scope; slice 21
> onboarding-conveyor).
slice-00 0.3.0-GT §1.4 independently confirms the primitive shipped 0.3.0:
workspace-primitive merge `2ce54abc` (PL-007) with migrations
`038_workspace_primitive` + `039_queue_target_repo`, "fresh databases apply
migrations through `039_queue_target_repo`".
## 1. The typed workspace declaration (PL-007) — 0.3.0
`RigSpec.workspace` is an **optional** typed block. Rigs without it stay valid;
`whoami` / node-inventory return a null workspace block in that case.
> Source: `domain/types.ts:762-770` (`WorkspaceSpec`), `:751-758`
> (`WorkspaceRepoSpec`), `:780` (`RigSpec.workspace?`) @HEAD.
| Field | Shape | Notes |
|---|---|---|
| `workspaceRoot` | string | Verbatim from spec |
| `repos[]` | `{ name, path, kind }[]` | `path` resolved to absolute at parse time; authors may declare relative to `workspaceRoot` in YAML |
| `defaultRepo?` | string | active repo when no env override / cwd match |
| `knowledgeRoot?` | string | treated as `kind=knowledge` when surfaced |
`WorkspaceKind` is a closed 5-member union: `user`, `project`, `knowledge`,
`lab`, `delivery`.
> Source: `domain/types.ts:748-749` (`WORKSPACE_KINDS` /
> `WorkspaceKind`) @HEAD.
### 1.1 Persistence — migration 038 + RigRepository
Migration **038** adds `workspace_json TEXT` to the `rigs` table. It holds the
typed `RigSpec.workspace` block as JSON when a rig declares one; NULL for rigs
without a workspace block.
> Source: `db/migrations/038_workspace_primitive.ts:16-21`
> (`ALTER TABLE rigs ADD COLUMN workspace_json TEXT`); doc-comment
> `:3-14` @HEAD.
`RigRepository.setRigWorkspace(rigId, workspace)` persists it (UPDATE
`workspace_json` + `updated_at`); `getRigWorkspace(rigId)` reads it back,
JSON-parsing to `WorkspaceSpec` and returning `null` on parse failure. Both
are **defensive no-ops** when the column is absent (`hasRigColumn` probe) —
older test fixtures that bypass the canonical migration list don't have the
column; the setter's contract is "best-effort persistence".
> Source: `domain/rig-repository.ts:98-105` (setter, column probe
> L99), `:106-117` (getter; parse-fail → null L114-116) @HEAD.
The instantiator persists the block at rig-create time **only when declared**:
> Source: `domain/rigspec-instantiator.ts:653-655` (`if
> (rigSpec.workspace) … setRigWorkspace(rigId, rigSpec.workspace)`) @HEAD.
### 1.2 Runtime resolution — workspace-resolver
`resolveWorkspaceContext({ spec, cwd, envOverride })` (consumed by
`whoami-service`) returns the `WhoamiWorkspaceBlock` or `null` when no spec.
`activeRepo` resolution: an `envOverride` (non-empty, trimmed) wins
**verbatim** — even an unknown repo name is honored, because operators set
`OPENRIG_TARGET_REPO` consciously (PL-007 PRD § Item 3); otherwise
`defaultRepo` is used **only if it names a declared repo**. `knowledgeKind`
is `"knowledge"` when `knowledgeRoot` is declared, else `null`.
> Source: `domain/workspace/workspace-resolver.ts:26-52` (resolver;
> env-override-verbatim L34-43, including the "honored verbatim"
> comment L35-36) @HEAD.
`whoami-service` reads the persisted spec and resolves with the query's
`targetRepoOverride`, falling back to `process.env["OPENRIG_TARGET_REPO"]`:
> Source: `domain/whoami-service.ts:319-324` (`getRigWorkspace` +
> `resolveWorkspaceContext`, env fallback L323); `whoami` returns
> `workspace` in its payload `:335` @HEAD.
`resolveNodeWorkspace({ spec, cwd })` (consumed by `node-inventory`) derives a
per-node `NodeWorkspaceInfo` by walking the node's `cwd` up the directory
tree for the **longest-prefix repo path** that contains it; falls back to
`knowledge` when cwd is under `knowledgeRoot`, then to the rig's
`defaultRepo` when cwd doesn't resolve. Containment uses a `path.relative`
boundary check (not a string `startsWith`) so `/foo/bar` does not match
`/foo/bar-other`.
> Source: `domain/workspace/workspace-resolver.ts:57-95`
> (longest-prefix L67-73; knowledge fallback L77-79; default-repo
> fallback L82-88), `isInside` `:97-103`;
> `domain/node-inventory.ts:397` (`workspace: resolveNodeWorkspace(...)`),
> `:434-437` (`NodeWorkspaceInfo`) @HEAD.
### 1.3 Per-item repo scope — migration 039 + queue validation
Migration **039** adds `target_repo TEXT` to `queue_items` plus
`idx_queue_items_target_repo`. It carries the per-item typed repo scope when
an operator passes `--target-repo <name>`; NULL when the qitem is
unambiguous against the rig's `default_repo` or no workspace is declared.
Mission Control views surface the field for cross-rig handoff clarity.
> Source: `db/migrations/039_queue_target_repo.ts:16-22`
> (`ALTER TABLE queue_items ADD COLUMN target_repo TEXT` +
> `CREATE INDEX … idx_queue_items_target_repo`); doc-comment
> `:3-14` @HEAD.
The queue route validates `target_repo` at the route layer against the
**source rig's** `RigSpec.workspace.repos[]`: it parses the rig name out of
`source_session` (`<member>@<rig>`), looks up the rig, reads
`getRigWorkspace`, and rejects an unknown repo with `unknown_target_repo` +
the known-repo list. It **fails open** (`{ ok: true }`) when there is no
rigRepo, no parseable rig, the rig is unknown, or no workspace is declared —
validation only bites when a workspace actively declares repos.
> Source: `routes/queue.ts:49-57` (fail-open guards), `:55`
> (`getRigWorkspace`), `:58-66` (`unknown_target_repo` +
> `knownRepos`) @HEAD.
## 2. Workspace HTTP route — frontmatter validator (0.3.0)
`workspaceRoutes()` (mounted `server.ts:491` as `/api/workspace`) exposes a
**single read-only endpoint** at v0:
`POST /api/workspace/validate` — body `{ root, workspaceKind?, recursive?,
requireFrontmatter?, maxFiles? }`; returns a `FrontmatterValidationReport`.
`root` is required (400 `root_required`); an out-of-vocabulary
`workspaceKind` is rejected 400 `invalid_workspace_kind`; validator throws
→ 500 `validate_failed`. **No filesystem mutation.**
> Source: `routes/workspace.ts:23-65` (handler; root-required L35-37;
> kind-enum L39-47; 500 L59-62); mounted `server.ts:491` @HEAD.
`validateWorkspaceFrontmatter()` walks a root, parses each `.md` file's
YAML frontmatter (delimited `---` on the first line), and emits a structured
gap report — **advisory only, never modifies files**. Gap kinds:
`missing-required-field`, `unrecognized-status-value`, `parse-error`,
`missing-frontmatter`. Per-kind required fields: `user`/`project` →
`["doc"]`; `knowledge`/`lab`/`delivery` → `["doc","status","created","owner"]`.
Valid `status` enum: `active|draft|archived|superseded`. Default behavior
skips files without `---` silently (informal notes) unless
`requireFrontmatter`; recurses by default; skips `node_modules` / `.git` /
`.worktrees` / `dist` / `build`; hard cap `maxFiles` default 10000.
> Source: `domain/workspace/frontmatter-validator.ts:53` (status enum),
> `:56-62` (per-kind required), `:23-27` (gap kinds), `:90-122` (walk;
> skip-dirs L105-111), `:160-172` (missing-frontmatter behavior),
> `:201-226` (required + status check) @HEAD.
CLI surface: `rig workspace validate [root]` — v0 is intentionally narrow
(`validate` only); future versions add typed-kind authoring on the same
walker.
> Source: `docs/as-built/cli-reference.md:931-941` @HEAD.
## 3. Default workspace scaffold (0.3.0 spine; 0.3.1 narrative layer)
`workspaceScaffoldDirs()` / `workspaceScaffoldFiles()` produce the
mission-aware default workspace (`~/.openrig/workspace/` or `--root`). The
same scaffold is used **idempotently by daemon startup** so a fresh install
has a browsable Project workspace before the operator discovers
`rig config init-workspace`. Canonical subdirs: `missions/`, `artifacts/`,
`evidence/`, `progress/`, `field-notes/`, `specs/`, `dogfood-evidence/`,
plus per-mission `missions/<id>/slices/<slice-id>` folders. Drops
`README.md` + `STEERING.md` (placeholder) + per-mission `README.md` /
`PROGRESS.md` + per-slice `README.md` / `PROGRESS.md` /
`IMPLEMENTATION-PRD.md`.
> Source: `domain/workspace/default-workspace-scaffold.ts:44-59`
> (`workspaceScaffoldDirs`), `:247-283` (`workspaceScaffoldFiles`),
> `WORKSPACE_README` `:82-94`, `STEERING_PLACEHOLDER` `:96-120`;
> CLI `packages/cli/src/commands/config-init-workspace.ts:1-16`
> (idempotent; `--dry-run`/`--force`; never deletes operator
> content L12-16); cli-reference workspace note "See `rig config
> init-workspace`" `:939` @HEAD.
**0.3.1 narrative layer (slice 21 onboarding-conveyor).** The
`getting-started` mission's two slices ship rich teaching content from
`GETTING_STARTED_NARRATIVE` (the click-through-to-learn surface) including a
`timeline.md` the slice Story tab renders via slice-06's
`useSliceTimelineMarkdown` hook; other slices keep the boilerplate.
> Source: `domain/workspace/default-workspace-scaffold.ts:1-4`
> (slice-21 header), `:153-190` (narrative branch in `sliceReadme`),
> `:192-200` (`sliceTimeline`), `:270-279` (timeline emit); §0 proof:
> `getting-started-narrative.ts` [email protected] ⇒ **0.3.1** @HEAD.
## 4. File-backed missions / slices tree
### 4.1 SliceIndexer (Slice Story View v0) — 0.3.0
`SliceIndexer` reads slice folders from a configured filesystem root. The
**default workspace contract** is
`workspace/missions/<mission>/slices/<slice>`; explicitly configured flat
roots (`workspace/slices/<slice>`) remain supported for compatibility.
A nested `slices/` child folder makes the parent a mission
(`missionId = <mission-folder>`); a bare folder is a flat slice
(`missionId = null`). NO new SQLite migration, NO new event type: read-only
projection over existing tables (`queue_items`, `queue_transitions`,
`mission_control_actions`) + dogfood-evidence directories. Time-bounded
listing + detail caches (`invalidate()` drops both). `isReady()` is true
when any configured slice root exists on disk.
> Source: `domain/slices/slice-indexer.ts:1-14` (contract + no-new-state),
> `:174-176` (`isReady`), `:179-182` (`invalidate`), `:212-256`
> (`readSliceLocations`; nested-vs-flat L233-253), `:62-89`
> (`SliceListEntry` shape: `missionId` / `slicePath` / `qitemIds` /
> `proofPacket`) @HEAD.
### 4.2 SliceDetailProjector (Slice Story View v0 + v1) — 0.3.0
Given a `SliceRecord`, the projector assembles the full per-slice payload
across six tabs (Story, Acceptance, Decisions, Docs, Tests/Verification,
Topology). Read-only; composes already-shipped tables +
`workflow_specs`/`workflow_instances`/`workflow_step_trails` + slice docs on
disk + dogfood-evidence. **v1 removed the v0 hardcoded legacy phase enum**
(`discovery`/`product-lab`/`delivery`/…): `StoryEvent.phase` is now an
open-ended string-or-null — the spec-defined `step.id` when bound to a
`workflow_instance`, else `null` (UI groups under "Untagged"). When no
workflow runtime is constructed the projector silently degrades to v0
behavior (`workflowBinding=null`, `specGraph=null`).
> Source: `domain/slices/slice-detail-projector.ts:1-21` (six-tab
> contract + v1 enrichment), `:18-21` (v0 phase enum REMOVED at v1);
> startup degrade-path `startup.ts:1063-1076` (projector built with
> `workflowRuntime?.specCache`; comment L1064-1071) @HEAD.
### 4.3 Slices routes — 0.3.0
`slicesRoutes()` (mounted `server.ts:501` as `/api/slices`):
`GET /` (filter `all|active|done|blocked`, default `all`; `?refresh=1`
invalidates; optional `?boundToWorkflow=<name>:<version>` lens narrows to
slices bound to a workflow instance), `POST /refresh` (drops both indexer
caches — no daemon restart), `GET /:name/proof-asset/*` (path-traversal
guarded; immutable 1-day cache), `GET /:name/doc/*` (markdown for the Docs
tab; traversal guarded), `GET /:name` (full per-tab payload). 503
`slices_indexer_unavailable` when unwired; 503 `slices_root_not_configured`
+ setup hint when not ready. **Route-order discipline:** literal `/` /
`/refresh` / `/:name/proof-asset/*` / `/:name/doc/*` are registered BEFORE
the dynamic `/:name` so they are not shadowed.
> Source: `routes/slices.ts:31-177` (handlers; route-order L34-35,
> L101-102, L109-113, L166-167; 503s L38-44; `boundToWorkflow`
> L60-86); mounted `server.ts:501` @HEAD.
### 4.4 Missions route — **0.3.1** (slice 12 + slice 13 + slice 18)
`missionsRoutes()` (mounted `server.ts:505` as `/api/missions`) is the
mission scope data layer. `GET /:missionId` returns
`{ missionId, missionPath, slices, workflow_spec, topology, status }` —
slices filtered from the SliceIndexer by `missionId`; `missionPath` derived
by going up two levels from any slice's `slicePath`; `workflow_spec` parsed
lazily from `<missionPath>/README.md` frontmatter (same `parseWorkflowSpecRef`
helper the slice-indexer uses); `topology.specGraph` projected via
`projectSpecGraph(spec, null)` when the spec is cached, `{ specGraph: null }`
when declared-but-not-cached, `null` when nothing declared; `status` read
from README frontmatter. `POST /:missionId/complete` writes
`status: complete` to the mission README frontmatter (idempotent; preserves
unrelated fields) — the daemon is the audit-trail surface, the UI keeps an
optimistic localStorage mirror. 404 `mission_not_found` when no slices match.
> Source: `routes/missions.ts:39-118` (handlers), `:124-142`
> (`writeMissionStatusComplete`), `:148-150` (`computeMissionPath`
> up-two-levels), `:171-177` (`readMissionWorkflowSpec`), `:205-215`
> (`computeMissionTopology`); mounted `server.ts:505`; §0 proof:
> `routes/missions.ts` [email protected] ⇒ **0.3.1** @HEAD.
### 4.5 Projects route — Coordination L2 classifier (PL-004 Phase B) — 0.3.0
`projectsRoutes()` (mounted `server.ts:492` as `/api/projects`) backs the
`rig project` CLI verb — this is the **PL-004 Phase B project *classifier***
(lease lifecycle + idempotent classify + operator-verb reclaim + SSE), NOT
the Project *workspace UI* (that is the slices/missions surface above; the
naming overlap is a documented seam). Endpoints: `POST /lease/acquire`
(optional `evaluateDeadnessFirst` clears stale/dead leases first),
`POST /lease/heartbeat`, `POST /reclaim-classifier`, `POST /project`
(idempotent on `stream_item_id`), `GET /lease`, `GET /list`,
`GET /sse` + `GET /watch` (SSE), `GET /:projectId`. **Route-order
discipline:** literal `/lease`, `/list`, `/sse`, `/watch` are registered
BEFORE the bare `/:projectId` catchall (Phase A R1 SSE lesson).
> Source: `routes/projects.ts:18-194` (handlers; route-order note
> L15-17, L140-141, L158-159, L185); error-code → HTTP mapping
> `:31-52`; mounted `server.ts:492` @HEAD.
## 5. UI route-reality (§10.7 — source-verified at routes.tsx@HEAD)
`packages/ui/src/routes.tsx` is **542 lines** and uses TanStack Router
(`createRoute({ path, component })` objects), NOT JSX `<Route>`. The
Phase-8.1 survey's grep-derived missions/projects expectations are
corrected here against routes.tsx reality:
| Survey expectation | routes.tsx@HEAD reality | routes.tsx:NN |
|---|---|---|
| `/project` (workspace) | **REAL route** — `WorkspaceScopePage` | `:128-131` |
| `/project/mission/$missionId` | **REAL route** — `MissionScopePage` | `:134-137` |
| `/project/slice/$sliceId` | **REAL route** — `SliceScopePage` | `:140-143` |
| `/files` | **REAL route** — `FilesWorkspace` (see content-surfaces.md) | `:192-195` |
| `/mission-control` | **`<Navigate to="/for-you" />`** redirect-stub (DELETED per SC-18; the Mission Control *system* lives at daemon/PL-005, not a UI destination) | `:440-444` |
| `/slices` | **`<Navigate to="/project" />`** redirect-stub (DELETED per project-tree.md) | `:447-451` |
| `/slices/$name` | **`<Navigate to="/project/slice/$sliceId" />`** redirect-stub | `:453-460` |
| `/progress` | **`<Navigate to="/project" />`** redirect-stub (folds into Project tabs, Phase 3) | `:464-468` |
| `/steering` | **`<Navigate to="/project" />`** redirect-stub (folds into Project workspace overview tab, Phase 3) | `:470-474` |
| `/missions` (top-level) | **NO route** — missions are reached only via `/project/mission/$missionId` | (absent) |
| `/markdown` | **NO route** — markdown is a component in file/drawer surfaces, not a destination (see content-surfaces.md §4) | (absent) |
> Source: `packages/ui/src/routes.tsx:90-195` (real routes),
> `:435-474` (redirect-stub block; each `<Navigate>` + DELETED/folds
> comment), `:476-490` (route tree) @HEAD. Grep-confirmed absent:
> no `path: "/missions"` / `path: "/markdown"` declaration anywhere
> in routes.tsx @HEAD.
Net §10.7 ruling: the daemon `/api/missions` + `/api/slices` +
`/api/projects` routes are real and load-bearing; the **operator-facing UI**
consumes them through `/project*` destinations only. `/mission-control`,
`/slices`, `/progress`, `/steering` are redirect-stubs (the systems exist at
the daemon layer, the URLs were collapsed into `/project` / `/for-you`).
## 6. Cross-cutting properties
- **Optional + valid-without:** rigs without a `workspace` block stay valid;
whoami / node-inventory / queue-target-repo all return null / fail-open
(`workspace-resolver.ts:32`; `rig-repository.ts:99,107`;
`routes/queue.ts:55`) @HEAD.
- **Defensive column probes:** every `workspace_json` / `target_repo` access
guards on column presence so partial test fixtures don't crash
(`rig-repository.ts:99,107`; migrations 038/039 ship separately so a
fixture can apply only the half it needs — `038.ts:11-14`) @HEAD.
- **Read-only projection, no new state for the tree:** SliceIndexer /
SliceDetailProjector add NO migration / event type; only the workspace
declaration (038) + per-item scope (039) touch SQLite
(`slice-indexer.ts:12-14`) @HEAD.
- **Advisory, never mutates:** the frontmatter validator and the
init-workspace scaffold never delete operator content
(`frontmatter-validator.ts:12-13`; `config-init-workspace.ts:12-16`) @HEAD.
## OPEN items (carried, not smoothed)
- **OPEN-A** — `resolveWorkspaceContext` honors an `envOverride`
**verbatim even when it names no declared repo** (`workspace-resolver.ts:34-43`,
by explicit PL-007 PRD § Item 3 design), whereas the queue route
**rejects** an unknown `target_repo` against the same `repos[]`
(`routes/queue.ts:58-66`). These two surfaces apply opposite policies to
an unknown repo name (whoami trusts the operator; queue validates). Stated
as-is — the asymmetry is source-real and intentional per the cited
comments, but the divergence is not reconciled in source.
- **OPEN-B** — the `/api/projects` *classifier* (PL-004 Phase B) and the
`/project*` *workspace UI* (slices/missions) share the word "project" but
are unrelated subsystems. Documented as a naming seam; no source defect.
- No slice-00 numeric-drift OPEN (1–5) applies — this module carries no
migration-count / route-group / PL-004-event-count claim (those land in
daemon-core / coordination-primitive / architecture-rules).
+52 -2
View File
@@ -1,3 +1,18 @@
---
kind: as-built
title: OpenRig CLI Reference — Full rig Command Surface
status: active
topics: [runtime-control, agent-runtime]
domains: [operating-advisor, engineering-advisor, orchestrator]
applies-when: |
Need the exact rig CLI surface — command groups, subcommands, flags,
JSON output, cross-host, coordination primitives.
siblings: [README.md, architecture/daemon-core.md]
prerequisite-reads: [README.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# OpenRig CLI Reference
Verified against the shipped CLI on 2026-05-15 (v0.3.1) using:
@@ -11,7 +26,7 @@ This document reflects the current `rig` surface as shipped. Where live help tex
## Overview
- Binary: `rig`
- Top-level command groups: `57`
- Top-level command groups: `58`
- Output mode: human-readable by default; many commands also support `--json`
- Daemon-backed commands fail when the daemon is stopped or unhealthy; `daemon`, `config`, `preflight`, and `doctor` also have local responsibilities
- Managed apps are launched through the normal spec/library surfaces; the canonical shipped example is `rig up secrets-manager`
@@ -78,6 +93,7 @@ This document reflects the current `rig` surface as shipped. Where live help tex
| `context-pack` | Browse, preview, send, and install operator-authored context packs |
| `workspace` | Workspace primitive — typed-kind tooling (frontmatter validation) |
| `plugin` | Inspect plugins (read-only) — list, show, used-by, validate |
| `scope` | Scope tree primitive — missions, slices, sub-slices |
## Core Daemon and System Commands
@@ -868,7 +884,7 @@ Notes:
Mission Control is an integrated product UI inside the existing shell, NOT a new `rig` command. Per PL-005 PRD line 301: "no new commands at v0; the `rig ps --nodes --json` surface is consumed read-only."
Mission Control is reached via the product UI at the `/mission-control` route. The HTTP API surface (`/api/mission-control/*`) is documented in `docs/as-built/architecture.md` § Mission Control / Queue Observability. The 7 verbs (`approve`, `deny`, `route`, `annotate`, `hold`, `drop`, `handoff`) execute via `POST /api/mission-control/action`; the 7 views are read via `GET /api/mission-control/views/:view-name`.
Mission Control is reached via the product UI at the `/mission-control` route. The HTTP API surface (`/api/mission-control/*`) is documented in `docs/as-built/architecture/mission-control.md`. The 7 verbs (`approve`, `deny`, `route`, `annotate`, `hold`, `drop`, `handoff`) execute via `POST /api/mission-control/action`; the 7 views are read via `GET /api/mission-control/views/:view-name`.
Mission Control consumes `rig ps --nodes --json` for fleet roll-up where the canonical CLI source is preferred. Cross-CLI-version drift is handled per the 4 sub-clauses of PRD § Runtime/Source Drift Acceptance: missing fields surface as honest "field unavailable on this rig's daemon version" placeholders; once-per-session-per-rig logging avoids spam; the fleet view shows a top-level "rigs running stale CLI" indicator.
@@ -946,6 +962,40 @@ Notes:
- `openrig-core` ships bundled with the daemon (11 skills). Additional plugins (`gstack` — 45 skills; `obra-superpowers` — 14 skills) ship as substrate references for plugin authors to copy-install per the `OPENRIG-INSTALL.md` workflow inside each plugin's source tree.
- A first-class `rig plugin install <substrate-path>` verb is deferred to 0.3.2.
## Scope Tree Primitive (release-0.3.2)
One top-level command added post-0.3.1 (`scopeCommand`,
`packages/cli/src/index.ts:20,187`; defined in
`packages/cli/src/commands/scope.ts`; added by `0b77cba4`, release-0.3.2
slice 12). Operates the scope tree (missions, slices, sub-slices) per
`conventions/scope-and-versioning`. This is the 58th command group at HEAD
(`v0.3.1` shipped 57; see overview).
### `rig scope`
Usage: `rig scope <subcommand>` — scope tree primitive: missions, slices, sub-slices.
Top-level option:
- `--workspace <path>` — override workspace root (otherwise inferred from cwd or `$OPENRIG_WORK_ROOT`).
Two subcommand groups: `slice` and `mission`.
`rig scope slice <subcommand>` — slice-tier commands:
- `ls [--mission <name>] [--state <state>] [--json]` — list slices in a mission (or across all missions). `--state` filter: `active | closed | shipped | all` (default `active`).
- `show <slice-path> [--mission <name>] [--json]` — inspect a single slice (frontmatter + README + children). `slice-path` is absolute, relative-to-substrate, or `NN-slug`; `--mission` hints the mission when path is just `NN-slug`.
- `create <mission> <slug> [--template <kind>] [--title <text>] [--json]` — create a new slice in a mission. `--template` default `placeholder`.
- `ship <slice-path> <release-mission> [--mission <name>] [--json]` — ship a slice to a release mission (preserves git history).
- `close <slice-path> [--note <text>] [--mission <name>] [--json]` — close a slice (move to `<mission>/closed/`, update status). `--note` is an optional closure note.
- `move <slice-path> <dest-mission> [--mission <name>] [--json]` — move a slice between missions (re-numbers in destination).
`rig scope mission <subcommand>` — mission-tier commands:
- `ls [--json]` — list missions (top-level folders with `README.md`).
- `show <mission> [--json]` — inspect a single mission.
- `create <name> [--template <kind>] [--id <dot-id>] [--title <text>] [--json]` — create a new mission (mints a stable dot-ID into frontmatter). `--template` auto-selects when name matches `release-X.Y.Z`; `--id` overrides name-pattern inference.
Notes:
- Surface source-verified against `packages/cli/src/commands/scope.ts` @HEAD `7eaf524c`; not in `v0.3.1`.
## Commands Not Present
These are not current top-level `rig` commands:
+168 -399
View File
@@ -1,425 +1,194 @@
# OpenRig Source Codemap
---
kind: as-built
title: OpenRig Codemap — Navigation Index / Map of Territory
status: active
topics: [knowledge-and-context, observability]
domains: [engineering-advisor, operating-advisor]
applies-when: |
You know what you need to learn about the shipped OpenRig system but not
which as-built module holds it. Use the module map, the use-case lookup,
or the source-root table to route to the right doc — or jump straight to
the source root the codemap points at.
siblings: [README.md, cli-reference.md]
prerequisite-reads: [README.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
Source-driven map of every file under `packages/daemon/src`, `packages/cli/src`, and `packages/ui/src` at current `HEAD`.
# OpenRig Codemap — Navigation Index
Current footprint:
- daemon: 211 source files (126 domain, 31 routes, 11 adapters, 36 migrations, 7 other)
- CLI: 78 source files
- UI: 87 source files
- total: 376 source files
This is a **map of territory**, not a content dump. It tells you which
as-built module answers a question and which `packages/*/src` root that
module is grounded in. The deep content lives in the modules; the code lives
in the source roots; this file points at both.
How to use this doc:
- `Exports` lists the public symbols defined by the file.
- `Related` lists the file's primary local outgoing dependencies so you can follow the code path quickly.
- The package/area groupings are structural, not ownership metadata.
> The old codemap was a 425-line file-by-file `Exports:`/`Related:` flat dump
> that drifted fastest (its own header carried a stale v0.2.0 footprint and an
> internally-contradictory command-group count) and never fit a context
> window. That anti-pattern is retired (slice-08 Q5, founder-ratified). The
> genuinely-useful part — the source-root index — is preserved below as the
> source-root pointer table; the per-file transcription is not.
Fast lookup:
- Daemon app wiring and mounted HTTP surface: `packages/daemon/src/startup.ts`, `packages/daemon/src/server.ts`, `packages/daemon/src/routes/*`
- AgentSpec / pod-aware engine: `packages/daemon/src/domain/agent-*`, `profile-resolver.ts`, `projection-planner.ts`, `startup-*`, `rigspec-*`, `pod-repository.ts`
- Rig environment / managed-app substrate: `packages/daemon/src/adapters/compose-services-adapter.ts`, `packages/daemon/src/domain/service-orchestrator.ts`, `packages/daemon/src/domain/services-readiness.ts`, `packages/daemon/src/routes/env.ts`
- Snapshot / restore / continuity: `packages/daemon/src/domain/snapshot-*`, `checkpoint-store.ts`, `restore-orchestrator.ts`
- Transport / communication: `packages/daemon/src/domain/session-transport.ts`, `packages/daemon/src/routes/transport.ts`
- Transcripts / persistence: `packages/daemon/src/domain/transcript-store.ts`, `packages/daemon/src/domain/history-query.ts`, `packages/daemon/src/routes/transcripts.ts`
- Ask / context packs: `packages/daemon/src/domain/ask-service.ts`, `packages/daemon/src/routes/ask.ts`
- Chat: `packages/daemon/src/domain/chat-repository.ts`, `packages/daemon/src/routes/chat.ts`
- Spec review / library / identity: `packages/daemon/src/domain/spec-review-service.ts`, `packages/daemon/src/domain/spec-library-service.ts`, `packages/daemon/src/domain/whoami-service.ts`, `packages/daemon/src/routes/spec-review.ts`, `packages/daemon/src/routes/spec-library.ts`, `packages/daemon/src/routes/whoami.ts`
- Node inventory: `packages/daemon/src/domain/node-inventory.ts`
- Context usage: `packages/daemon/src/domain/context-usage-store.ts`, `packages/daemon/src/domain/context-monitor.ts`
- Resume honesty: `packages/daemon/src/domain/native-resume-probe.ts`, `resume-metadata-refresher.ts`, `codex-thread-id.ts`
- Package / bootstrap / bundle flows: `packages/daemon/src/domain/package-*`, `install-*`, `bootstrap-*`, `bundle-*`
- CLI command surface: `packages/cli/src/index.ts`, `packages/cli/src/commands/*` (53 groups)
- CLI infrastructure: `packages/cli/src/config-store.ts`, `packages/cli/src/system-preflight.ts`
- UI workspace and navigation: `packages/ui/src/components/Explorer.tsx`, `packages/ui/src/components/WorkspaceHome.tsx`, `packages/ui/src/components/AppShell.tsx`
- UI shared drawer: `packages/ui/src/components/SharedDetailDrawer.tsx`, `RigDetailPanel.tsx`, `NodeDetailPanel.tsx`, `DiscoveryPanel.tsx`, `SpecsPanel.tsx`, `RigChatPanel.tsx`, `SystemPanel.tsx`
- UI spec/library surfaces: `packages/ui/src/components/RigSpecDisplay.tsx`, `packages/ui/src/components/AgentSpecDisplay.tsx`, `packages/ui/src/components/LibraryReview.tsx`, `packages/ui/src/components/SpecsWorkspace.tsx`
- UI managed-app runtime surfaces: `packages/ui/src/components/RigEnvPanel.tsx`, `packages/ui/src/hooks/useRigEnv.ts`, `packages/ui/src/lib/build-setup-prompt.ts`
- UI live identity surfaces: `packages/ui/src/components/LiveIdentityDisplay.tsx`, `packages/ui/src/components/LiveNodeDetails.tsx`
- UI data layer: `packages/ui/src/hooks/*`
## (a) Product frame
## Daemon
OpenRig is a local control plane for multi-agent coding topologies — a
multi-agent harness that manages your Claude Code and Codex sessions as a
single system. The daemon (`@openrig/daemon`) is the framework-free
SQLite-backed core; the CLI (`@openrig/cli`), UI (`@openrig/ui`), and MCP
server all sit on top of it.
### Entrypoints And Wiring
- `packages/daemon/src/index.ts`: CLI entrypoint for starting the daemon HTTP server. Exports: startServer. Related: `packages/daemon/src/startup.js`.
- `packages/daemon/src/seed.ts`: Development/test seed entrypoint for populating sample daemon state. Exports: none. Related: `packages/daemon/src/db/connection.js`, `packages/daemon/src/db/migrate.js`, `packages/daemon/src/db/migrations/001_core_schema.js`, `packages/daemon/src/db/migrations/002_bindings_sessions.js`, +3 more.
- `packages/daemon/src/server.ts`: Defines `AppDeps`, enforces shared-DB invariants, and mounts the full public Hono route tree including dual-format rigspec import/export/materialize, bundles, transport/transcripts/ask/chat, env status/logs/down, specs review/library, and `whoami`. Exports: AppDeps, createApp. Related: `packages/daemon/src/adapters/cmux.js`, `packages/daemon/src/adapters/tmux.js`, `packages/daemon/src/domain/bootstrap-orchestrator.js`, `packages/daemon/src/domain/bootstrap-repository.js`, +36 more.
- `packages/daemon/src/startup.ts`: Constructs the daemon dependency graph, runs all 36 migrations, wires legacy, reboot, North Star, Post-North-Star, Phase 5 RigEnv, context-usage, Final Stretch 3 managed-app services, and PL-004 coordination services together, and returns `{ app, db, deps }`. Exports: createDaemon. Related: `packages/daemon/src/adapters/claude-resume.js`, `packages/daemon/src/adapters/cmux-transport.js`, `packages/daemon/src/adapters/cmux.js`, `packages/daemon/src/adapters/codex-resume.js`, +58 more.
> Source-verified at HEAD `7eaf524c` (`v0.3.1-6-g7eaf524c`); package version
> **0.3.1**, 6 unreleased 0.3.2 commits on HEAD, no `v0.3.2` tag. Frame
> sentence triangulated against `architecture/daemon-core.md` §1 +
> `openrig-internal/product/positioning.md` ("a multi-agent harness, a local
> control plane that manages your Claude Code and Codex sessions as a single
> system").
### Adapters
- `packages/daemon/src/adapters/claude-code-adapter.ts`: Adapter implementation for claude code integration. Exports: ClaudeAdapterFsOps, ClaudeCodeAdapter. Related: `packages/daemon/src/adapters/tmux.js`, `packages/daemon/src/domain/projection-planner.js`, `packages/daemon/src/domain/runtime-adapter.js`.
- `packages/daemon/src/adapters/claude-resume.ts`: Resume adapter for claude sessions. Exports: ClaudeResumeAdapter, ResumeResult. Related: `packages/daemon/src/adapters/shell-quote.js`, `packages/daemon/src/adapters/tmux.js`.
- `packages/daemon/src/adapters/cmux-transport.ts`: Adapter/util module for cmux transport integration. Exports: createCmuxCliTransport. Related: `packages/daemon/src/adapters/cmux.js`, `packages/daemon/src/adapters/tmux.js`.
- `packages/daemon/src/adapters/cmux.ts`: Adapter/util module for cmux integration. Exports: CmuxAdapter, CmuxResult, CmuxStatus, CmuxSurface, CmuxTransport, CmuxTransportFactory, CmuxWorkspace. Related: none.
- `packages/daemon/src/adapters/compose-services-adapter.ts`: Compose-backed rig-environment adapter for `up`, `ps`, `logs`, and teardown. Exports: ComposePsService, ComposeServicesAdapter, ComposeServicesUpParams, ComposeServicesUpResult, ComposeServicesLogsParams, ComposeServicesLogsResult, ComposeServicesDownParams, ComposeServicesDownResult. Related: `packages/daemon/src/adapters/tmux-exec.js`.
- `packages/daemon/src/adapters/codex-resume.ts`: Resume adapter for codex sessions. Exports: CodexResumeAdapter, ResumeResult. Related: `packages/daemon/src/adapters/claude-resume.js`, `packages/daemon/src/adapters/shell-quote.js`, `packages/daemon/src/adapters/tmux.js`.
- `packages/daemon/src/adapters/codex-runtime-adapter.ts`: Adapter implementation for codex runtime integration. Exports: CodexAdapterFsOps, CodexRuntimeAdapter. Related: `packages/daemon/src/adapters/tmux.js`, `packages/daemon/src/domain/projection-planner.js`, `packages/daemon/src/domain/runtime-adapter.js`.
- `packages/daemon/src/adapters/terminal-adapter.ts`: Infrastructure runtime adapter for terminal/shell nodes. No-op project/deliver/launch, immediate readiness. Exports: TerminalAdapter. Related: `packages/daemon/src/domain/runtime-adapter.js`.
- `packages/daemon/src/adapters/shell-quote.ts`: Adapter/util module for shell quote integration. Exports: shellQuote. Related: none.
- `packages/daemon/src/adapters/tmux-exec.ts`: Adapter/util module for tmux exec integration. Exports: execCommand. Related: `packages/daemon/src/adapters/tmux.js`.
- `packages/daemon/src/adapters/tmux.ts`: Adapter/util module for tmux integration. Exports: ExecFn, TmuxAdapter, TmuxPane, TmuxResult, TmuxSession, TmuxWindow. Related: none.
## (b) Module map
### DB Core
- `packages/daemon/src/db/connection.ts`: Creates the SQLite connection with daemon-wide pragmas. Exports: createDb. Related: none.
- `packages/daemon/src/db/migrate.ts`: Migration runner and `Migration` type shared by all schema files. Exports: Migration, migrate. Related: none.
One row per module. "Reach for this when…" mirrors each module's actual
`applies-when` frontmatter.
### DB Migrations
- `packages/daemon/src/db/migrations/001_core_schema.ts`: Database migration for core schema. Exports: coreSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/002_bindings_sessions.ts`: Database migration for bindings sessions. Exports: bindingsSessionsSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/003_events.ts`: Database migration for events. Exports: eventsSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/004_snapshots.ts`: Database migration for snapshots. Exports: snapshotsSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/005_checkpoints.ts`: Database migration for checkpoints. Exports: checkpointsSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/006_resume_metadata.ts`: Database migration for resume metadata. Exports: resumeMetadataSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/007_node_spec_fields.ts`: Database migration for node spec fields. Exports: nodeSpecFieldsSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/008_packages.ts`: Database migration for packages. Exports: packagesSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/009_install_journal.ts`: Database migration for install journal. Exports: installJournalSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/010_journal_seq.ts`: Database migration for journal seq. Exports: journalSeqSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/011_bootstrap.ts`: Database migration for bootstrap. Exports: bootstrapSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/012_discovery.ts`: Database migration for discovery. Exports: discoverySchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/013_discovery_fk_fix.ts`: Database migration for discovery fk fix. Exports: discoveryFkFix. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/014_agentspec_reboot.ts`: Database migration for agentspec reboot. Exports: agentspecRebootSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/015_startup_context.ts`: Database migration for startup context. Exports: startupContextSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/016_chat_messages.ts`: Database migration for durable rig-scoped chat messages. Exports: chatMessagesSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/017_pod_namespace.ts`: Database migration that persists authored pod namespace separately from pod DB id for export, adoption, and identity parity. Exports: podNamespaceSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/018_context_usage.ts`: Database migration for per-node context-usage persistence. Exports: contextUsageSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/019_external_cli_attachment.ts`: Database migration extending bindings for external CLI attachment metadata. Exports: externalCliAttachmentSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/020_rig_services.ts`: Database migration for rig-scoped services records and persisted env receipts. Exports: rigServicesSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/021_seat_handover_observability.ts`: Database migration for seat-handover observability fields. Exports: seatHandoverObservabilitySchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/022_node_codex_config_profile.ts`: Database migration adding Codex config-profile field on nodes. Exports: nodeCodexConfigProfileSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/023_stream_items.ts`: PL-004 Phase A — L1 stream items table (append-only intake/audit root). Exports: streamItemsSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/024_queue_items.ts`: PL-004 Phase A — L3 queue items table (owned-work queue with closure obligation). Exports: queueItemsSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/025_queue_transitions.ts`: PL-004 Phase A — append-only queue state transition log. Exports: queueTransitionsSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/026_inbox_entries.ts`: PL-004 Phase A — mailbox-style inbox for asynchronous deposit. Exports: inboxEntriesSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/027_outbox_entries.ts`: PL-004 Phase A — sender-side outbox audit. Exports: outboxEntriesSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/028_project_classifications.ts`: PL-004 Phase B — L2 project classifications table (idempotent on stream_item_id; FK to stream_items). Exports: projectClassificationsSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/029_classifier_leases.ts`: PL-004 Phase B — single-writer classifier lease table (partial UNIQUE INDEX on state='active'). Exports: classifierLeasesSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/030_views_custom.ts`: PL-004 Phase B — custom view registry. Exports: viewsCustomSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/031_watchdog_jobs.ts`: PL-004 Phase C — watchdog jobs (canonical scheduler state; policy enum + intervals + lifecycle). Exports: watchdogJobsSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/032_watchdog_history.ts`: PL-004 Phase C — append-only watchdog evaluation history (sent/skipped/terminal; not_due polls not recorded). Exports: watchdogHistorySchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/033_workflow_specs.ts`: PL-004 Phase D — workflow specs (cached read-through from markdown/YAML; UNIQUE on name+version; source_hash invalidation). Exports: workflowSpecsSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/034_workflow_instances.ts`: PL-004 Phase D — workflow instances (live state; status enum; current_frontier_json; hop_count). Exports: workflowInstancesSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/035_workflow_step_trails.ts`: PL-004 Phase D — append-only workflow step trail history (FK to workflow_instances and queue_items). Exports: workflowStepTrailsSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/036_watchdog_policy_enum_extension.ts`: PL-004 Phase D — documenting no-op migration; Phase C uses application-layer enforcement so the enum extension to include workflow-keepalive is implemented in PHASE_D_POLICIES (watchdog-jobs-repository.ts), not in DDL. Exports: watchdogPolicyEnumExtensionSchema. Related: `packages/daemon/src/db/migrate.js`.
- `packages/daemon/src/db/migrations/037_mission_control_actions.ts`: PL-005 Phase A — Mission Control action audit table (append-only; 7-verb enum at app layer; before/after qitem snapshots; FK to queue_items). Exports: missionControlActionsSchema. Related: `packages/daemon/src/db/migrate.js`.
### architecture/
### Domain: Mission Control / Queue Observability (PL-005 Phase A)
- `packages/daemon/src/domain/mission-control/mission-control-action-log.ts`: Append-only writer for mission_control_actions. API surface lacks update/delete/remove (contract enforcement). Validates verb-specific required fields (annotate→annotation, hold/drop→reason). Exports: MissionControlActionLog, MissionControlActionLogError, MissionControlVerb, MISSION_CONTROL_VERBS. Related: `packages/daemon/src/db/migrations/037_mission_control_actions.js`.
- `packages/daemon/src/domain/mission-control/mission-control-write-contract.ts`: LOAD-BEARING. Atomic 7-verb action coordinator. Each verb is one db.transaction: queue mutation via Phase D's QueueRepository.updateWithinTransaction (preserves Phase A hot-potato closure validation; emits queue.updated) + audit row + persisted mission_control.action_executed event. The 4-step handoff shape (source-update + destination-create + opt-in best-effort notify + audit append) is verified atomic; notify failure does NOT roll back durable state. Exports: MissionControlWriteContract, MissionControlWriteContractError, MissionControlActionInput, MissionControlActionResult. Related: `packages/daemon/src/domain/queue-repository.js`, `packages/daemon/src/domain/mission-control/mission-control-action-log.js`.
- `packages/daemon/src/domain/mission-control/mission-control-read-layer.ts`: Maps 7 Mission Control views to source-of-truth paths. my-queue/human-gate/active-work/recent-ships query queue_items via QueueRepository; fleet uses fleetCliCapability roll-up; recently-active delegates to PL-004 Phase B ViewProjector.show("recently-active"); recent-observations reads stream_items via StreamStore. All rows return the 9-field phone-friendly content model (PRD non-negotiable). Exports: MissionControlReadLayer, MissionControlViewName, CompactStatusRow, MISSION_CONTROL_VIEWS. Related: `packages/daemon/src/domain/queue-repository.js`, `packages/daemon/src/domain/view-projector.js`, `packages/daemon/src/domain/stream-store.js`, `packages/daemon/src/domain/mission-control/mission-control-fleet-cli-capability.js`.
- `packages/daemon/src/domain/mission-control/mission-control-fleet-cli-capability.ts`: Per-rig CLI capability cache + fleet roll-up. Implements 4 sub-clauses of PRD § Runtime/Source Drift Acceptance: per-field availability check, per-rig honesty, once-per-session-per-rig logging, "rigs running stale CLI" indicator. Synthesizes per-rig activity state (active|idle|attention|blocked|degraded) from queue_items aggregation. Exports: MissionControlFleetCliCapability, FleetRollupRow, FleetRollup, MISSION_CONTROL_DESIRED_FIELDS. Related: `packages/daemon/src/domain/rig-repository.js`, `packages/daemon/src/db/migrations/024_queue_items.js`.
- `packages/daemon/src/routes/mission-control.ts`: Hono route module for `/api/mission-control` (`GET /views` literal list; `GET /views/:view-name` view fetch; `POST /action` 7-verb atomic execute; `GET /sse` + `GET /watch` SSE; `GET /cli-capabilities` fleet drift cache). SSE/literal paths mounted before /views/:view-name catchall per PL-004 Phase A R1 route-order discipline. Exports: missionControlRoutes. Related: `packages/daemon/src/domain/mission-control/*`, `packages/daemon/src/domain/event-bus.js`.
| Module | One-sentence summary | Reach for this when… |
|---|---|---|
| `daemon-core.md` | The framework-free SQLite-backed core the CLI/UI/MCP all sit on. | You need to know how the daemon boots, how `createDaemon` wires the dependency graph, the SQLite schema/migration set, or the route-mount surface. |
| `adapters-and-runtimes.md` | The five-method runtime-adapter contract + the resume-honesty layer. | You need the runtime-adapter contract, how OpenRig launches/resumes a Claude Code, Codex, or terminal harness inside tmux, or how the daemon honestly assesses whether a harness actually resumed vs fresh-launched. |
| `coordination-primitive.md` | PL-004 Phase A: the SQLite-canonical durable-work layer (`/api/stream`, `/api/queue`). | You need the stream/queue/inbox/outbox tables, the hot-potato closure contract, the transactional handoff guarantee, or where queue closure is enforced. |
| `workflow-runtime.md` | PL-004 Phase D: turns an intended sequence of work into durable SQLite state. | You need workflow specs cache, instance state, step trails, the transactional-scribe projection contract, or the watchdog policy set including workflow-keepalive. |
| `mission-control.md` | PL-005: the daemon-backed queue-observability surface inside the existing shell. | You need the seven views, the seven write verbs, the action audit table, the bearer-token middleware, or how queue observability maps to PL-004 sources. |
| `agent-spec-and-startup.md` | How authored YAML specs become a resolved, launched, identity-addressable topology. | You need the AgentSpec/RigSpec/pod-aware reboot types, profile resolution + additive startup layering, the StartupOrchestrator delivery split, or how whoami/materialize/bind/adopt resolve identity. |
| `lifecycle-snapshot-restore.md` | The durable-state half of `down → up → handoff`. | You need how OpenRig captures a snapshot, restores a rig (resume vs rebuild vs fresh), enforces restore honesty, consults live continuity, or how restore-check / restore-packet readiness probes work. |
| `transport-and-transcripts.md` | The communication-and-history layer; tmux is transport, not truth. | You need how rig send/capture/broadcast works, pipe-pane transcript capture + search, durable SQLite chat, what `rig ask` gathers, or the MCP-tool-name vs tmux-metadata-key distinction. |
| `workspace-primitive.md` | PL-007: the typed declaration of where a rig's work lives. | You need how a rig declares a typed workspace (root/repos/defaultRepo/knowledgeRoot), how it persists/resolves into whoami / node-inventory, how per-item `target_repo` scope is validated, or how the file-backed missions/slices tree is indexed and projected into Project. |
| `content-surfaces.md` | The operator-allowlisted, filesystem-canonical read/write layer Project/Steering sits on. | You need how the file browser enforces path safety, how atomic conflict-checked writes + the JSONL edit audit work, how the PROGRESS.md tree is indexed, or how the one-screen Steering surface is composed. |
| `plugin-agent-image-context-pack.md` | Four filesystem-canonical content primitives the daemon discovers and serves. | You need how OpenRig discovers plugins, captures/forks agent images, assembles/sends context packs, or how the Claude auto-compaction enforcer decides to send `/compact`. |
| `packaging-bootstrap-bundles.md` | How a topology is packaged into a shareable bundle and reconstituted elsewhere. | You need how rig/pod bundles are assembled (schema-v2 vs legacy v1), how bundle create/inspect/install + `/api/up` route across source kinds, the staged BootstrapOrchestrator flow, or which legacy install-engine seams still ship. |
| `architecture-rules-and-event-system.md` | The cross-cutting invariants that belong to no single subsystem. | You need the 25 architecture rules + startup/import constraints, the shape of the RigEvent union and its SSE delivery, or the intentional compatibility limits that still describe the shipped system. |
### Product UI: Mission Control / Queue Observability (PL-005 Phase A)
- `packages/ui/src/components/mission-control/MissionControlSurface.tsx`: Top-level Mission Control surface inside the existing product UI shell. Tab navigation across the 7 view names. Mounted at the `/mission-control` route. Exports: MissionControlSurface.
- `packages/ui/src/components/mission-control/views/{MyQueueView,HumanGateView,FleetView,ActiveWorkView,RecentShipsView,RecentlyActiveView,RecentObservationsView}.tsx`: 7 view components. Most wrap a shared GenericListView; FleetView combines CliDriftIndicator + per-row MissingFieldPlaceholder; MyQueueView combines HumanSeatCard + GenericListView with verb actions enabled.
- `packages/ui/src/components/mission-control/components/CompactStatusRow.tsx`: 9-field phone-friendly content-model atom (PRD non-negotiable). Renders compact / expanded density modes; UI may collapse but JSON preserves all 9 fields.
- `packages/ui/src/components/mission-control/components/VerbActions.tsx`: Shared 7-verb action sub-component. Renders verb buttons + per-verb required-field input (destination for route/handoff, annotation for annotate, reason for hold/drop). Submits to `POST /api/mission-control/action`. Invalidates Mission Control view queries on success.
- `packages/ui/src/components/mission-control/components/HumanSeatCard.tsx`: First-class human-seat rendering. Shows session identity, pending load, blocked count, verb capabilities. NOT invisible config-layer convention.
- `packages/ui/src/components/mission-control/components/CliDriftIndicator.tsx`: Cross-CLI-version drift indicator (PRD sub-clause 4). Shows fleet-level "rigs running stale CLI" badge + per-row "field unavailable on this rig's daemon version" placeholders via the MissingFieldPlaceholder export.
- `packages/ui/src/components/mission-control/hooks/{useMissionControlView,useMissionControlAction,useMissionControlCliCapabilities}.ts`: TanStack Query hooks fetching from `/api/mission-control/{views/:name,action,cli-capabilities}`.
### ui/
### Domain: Coordination Watchdog (PL-004 Phase C; extended in Phase D)
- `packages/daemon/src/domain/watchdog-jobs-repository.ts`: Persistence for watchdog_jobs. Phase D extension: enforces four-policy enum (periodic-reminder, artifact-pool-ready, edge-artifact-required, workflow-keepalive) at register-time. Phase C's policy_deferred_to_phase_d rejection has been replaced with positive registration-accept. Exports: WatchdogJobsRepository, WatchdogJobsError, WatchdogJob, PHASE_D_POLICIES, PHASE_C_POLICIES (alias). Related: `packages/daemon/src/db/migrations/031_watchdog_jobs.js`.
- `packages/daemon/src/domain/watchdog-history-log.ts`: Append-only writer for watchdog_history. Records meaningful evaluations only (sent/skipped/terminal). API surface intentionally lacks update/delete. Exports: WatchdogHistoryLog, WatchdogHistoryEntry, WatchdogOutcome. Related: `packages/daemon/src/db/migrations/032_watchdog_history.js`.
- `packages/daemon/src/domain/watchdog-policy-engine.ts`: Resolves policy by name, parses spec_yaml context, dispatches policy.evaluate(), records meaningful outcomes via history-log, emits watchdog.* events, calls injected delivery callback for action=send. Exports: WatchdogPolicyEngine, DeliveryFn, DeliveryRequest, DeliveryOutcome. Related: `packages/daemon/src/domain/watchdog-jobs-repository.js`, `packages/daemon/src/domain/watchdog-history-log.js`, `packages/daemon/src/domain/event-bus.js`.
- `packages/daemon/src/domain/watchdog-scheduler.ts`: Tick-driven daemon-native scheduler that joins the supervision tree. Filters listActive() through isDue(), evaluates due jobs sequentially, supports start/stop with graceful in-flight await. Exports: WatchdogScheduler, isDue. Related: `packages/daemon/src/domain/watchdog-policy-engine.js`, `packages/daemon/src/domain/watchdog-jobs-repository.js`.
- `packages/daemon/src/domain/policies/types.ts`: Policy contract (Policy, PolicyJob, PolicyEvaluation). Exports: Policy, PolicyJob, PolicyEvaluation. Related: none.
- `packages/daemon/src/domain/policies/periodic-reminder.ts`: Policy that returns send {target, message} unconditionally; throws policy_spec_invalid if context.target.session or context.message missing. Translated from POC `lib/policies/periodic-reminder.mjs`. Exports: periodicReminderPolicy. Related: `packages/daemon/src/domain/policies/types.js`.
- `packages/daemon/src/domain/policies/artifact-pool-ready.ts`: Policy that scans context.pools and skips with no_actionable_artifacts when empty; otherwise sends a formatted message capped at max_items. Translated from POC `lib/policies/artifact-pool-ready.mjs`. Exports: artifactPoolReadyPolicy. Related: `packages/daemon/src/domain/policies/artifact-pool-helpers.js`, `packages/daemon/src/domain/policies/types.js`.
- `packages/daemon/src/domain/policies/edge-artifact-required.ts`: Policy that scans source_pools and target_pools, computes source-key per artifact, and sends an edge-repair message for sources lacking matching downstream artifacts. Skips with no_missing_edge_artifacts when all sources matched. Translated from POC `lib/policies/edge-artifact-required.mjs`. Exports: edgeArtifactRequiredPolicy. Related: `packages/daemon/src/domain/policies/artifact-pool-helpers.js`, `packages/daemon/src/domain/policies/types.js`.
- `packages/daemon/src/domain/policies/artifact-pool-helpers.ts`: Shared filesystem scanner + formatter for artifact-pool-ready and edge-artifact-required. Translated from POC `lib/policies/artifact-pool.js`. Exports: scanArtifactPools, formatArtifactList, sourceKeyFor, ArtifactPoolSpec, ScannedArtifact. Related: none.
- `packages/daemon/src/routes/watchdog.ts`: Hono route module for `/api/watchdog` (`POST /register`, `GET /list`, `GET /sse`, `GET /watch`, `GET /:job_id`, `GET /:job_id/status`, `POST /:job_id/stop`). SSE/literal paths mounted before /:job_id catchall per Phase A R1 route-order discipline. Exports: watchdogRoutes. Related: `packages/daemon/src/domain/watchdog-jobs-repository.js`, `packages/daemon/src/domain/watchdog-history-log.js`, `packages/daemon/src/domain/event-bus.js`.
- `packages/daemon/src/domain/policies/workflow-keepalive.ts`: PL-004 Phase D — workflow-keepalive policy (carry-forward from Phase C deferral). Reads workflow_instances directly via SQLite (audit row 18 LOAD-BEARING); requires status active|waiting; resolves frontier qitem owners via queue_items. Translated from POC `lib/policies/workflow-keepalive.mjs`; source-of-truth switched from markdown to SQLite. Exports: makeWorkflowKeepalivePolicy. Related: `packages/daemon/src/domain/policies/types.js`, `packages/daemon/src/db/migrations/034_workflow_instances.js`.
| Module | One-sentence summary | Reach for this when… |
|---|---|---|
| `shell-and-routing.md` | The shell-first, route-first, primitive-driven operator surface. | You need how the UI shell (rail / Explorer / center workspace / drawer / preview stack) is assembled, the actual route tree the shipped UI mounts, or how the shared detail drawer and event consumption work. |
| `topology.md` | The operator's live picture of host → rig → pod → seat. | You need how the topology surface is built — the host hybrid graph, the table/terminal views, the activity-ring / hot-potato visual language, terminal-preview popovers, and the navigation/overlay contracts. |
| `project-and-for-you.md` | The three operator-facing destination surfaces (For You / Project / Dashboard). | You need how the For-You attention feed (5-card classifier + verb actions), the Project workspace/mission/slice scope pages, and the Dashboard landing on the vellum brand system are built. |
| `library-specs-and-design-system.md` | The Library (`/specs`) destination + the design-system pointer. | You need how the Library UI is assembled — the spec/skills/plugins surfaces, the spec-review + spec-library + live-identity flows that feed it — or where the canonical visual/design-system spec lives. |
### Domain: Workflow Runtime (PL-004 Phase D)
- `packages/daemon/src/domain/workflow-types.ts`: Shared types (WorkflowSpec, WorkflowInstance, WorkflowStepTrailEntry, WorkflowExitKind). Reverse-engineered from POC `workflow-runtime-v0/lib/workflow-runtime.rb` + fixture YAMLs. Exports: WorkflowSpec, WorkflowStepSpec, WorkflowRoleSpec, WorkflowInvariants, WorkflowClosureMessages, WorkflowLoopGuards, WorkflowInstance, WorkflowInstanceStatus, WorkflowStepTrailEntry, WorkflowExitKind, WorkflowSpecRow. Related: none.
- `packages/daemon/src/domain/workflow-spec-cache.ts`: Read-through cache from markdown/YAML spec files into workflow_specs table. Workspace-surface reconciliation: source_hash invalidates the cache on next read; valid operator edits to spec files win. Uses the `yaml` package for parsing. Exports: WorkflowSpecCache, WorkflowSpecError, parseWorkflowSpec. Related: `packages/daemon/src/db/migrations/033_workflow_specs.js`.
- `packages/daemon/src/domain/workflow-validator.ts`: Validates a workflow spec against role resolution, step uniqueness, allowed-exits consistency, and (optional via injected callback) seat liveness. Returns structured ValidationResult with severity-tagged issues. Exports: WorkflowValidator, ValidationIssue, ValidationResult, SeatLivenessCheckFn. Related: `packages/daemon/src/domain/workflow-types.js`.
- `packages/daemon/src/domain/workflow-instance-store.ts`: CRUD on workflow_instances + frontier tracking. Survives daemon restart (queries SQLite directly). Exports: WorkflowInstanceStore, WorkflowInstanceError, CreateWorkflowInstanceInput. Related: `packages/daemon/src/db/migrations/034_workflow_instances.js`.
- `packages/daemon/src/domain/workflow-step-trail-log.ts`: Append-only writer/reader for workflow_step_trails. API surface lacks update/delete (contract enforcement). Mirrors Phase A's queue-transition-log + Phase C's watchdog-history-log shape. Exports: WorkflowStepTrailLog, WorkflowStepTrailRecordInput. Related: `packages/daemon/src/db/migrations/035_workflow_step_trails.js`.
- `packages/daemon/src/domain/workflow-projector.ts`: LOAD-BEARING. Implements the transactional-scribe contract: closing a workflow_instances frontier qitem AND creating the next-step queue_items row AND appending the workflow_step_trails entry AND updating instance frontier+status all happen in the SAME daemon transaction (db.transaction). If any side throws, all roll back. Lost handoffs are impossible by design. Post-commit, fans out persisted events + nudges next owner. Uses Phase A QueueRepository.createWithinTransaction() (Phase D extension point). Exports: WorkflowProjector, WorkflowProjectorError, ProjectStepInput, ProjectStepResult. Related: `packages/daemon/src/domain/queue-repository.js`, `packages/daemon/src/domain/workflow-instance-store.js`, `packages/daemon/src/domain/workflow-step-trail-log.js`.
- `packages/daemon/src/domain/workflow-runtime.ts`: Facade over spec-cache + validator + instance-store + projector + step-trail-log. Operations: validate, instantiate (creates instance + entry qitem in same transaction), project (delegates to projector), continue (idempotent inspector). Exports: WorkflowRuntime, WorkflowRuntimeDeps, InstantiateInput, InstantiateResult, WorkflowInstanceError, WorkflowProjectorError, WorkflowSpecError. Related: `packages/daemon/src/domain/workflow-projector.js`, `packages/daemon/src/domain/workflow-spec-cache.js`.
- `packages/daemon/src/routes/workflow.ts`: Hono route module for `/api/workflow` (`POST /validate`, `POST /instantiate`, `POST /project`, `GET /list`, `GET /sse`, `GET /watch`, `GET /:instance_id`, `GET /:instance_id/trace`, `POST /:instance_id/continue`). SSE/literal paths mounted before /:instance_id catchall per Phase A R1 route-order discipline. Exports: workflowRoutes. Related: `packages/daemon/src/domain/workflow-runtime.js`, `packages/daemon/src/domain/event-bus.js`.
### root
### Domain: Core Runtime
- `packages/daemon/src/domain/errors.ts`: Domain-specific error types, currently including `RigNotFoundError`. Exports: RigNotFoundError. Related: none.
- `packages/daemon/src/domain/event-bus.ts`: Persistent event log plus in-process pub/sub for routes, SSE, and domain emitters. Exports: EventBus. Related: `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/graph-projection.ts`: Pure projection from persisted rig/session state to React Flow graph nodes and edges. Exports: ReactFlowGraph, RigGraphInput, projectRigToGraph. Related: `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/context-monitor.ts`: Daemon-owned context-usage recorder that samples live runtime state and updates persistent usage summaries. Exports: ContextMonitor. Related: `packages/daemon/src/domain/context-usage-store.js`.
- `packages/daemon/src/domain/context-usage-store.ts`: SQLite-backed store for per-node context usage snapshots used by whoami/node inventory surfaces. Exports: ContextUsageStore, ContextUsageSnapshot, ContextUsageStoreOpts. Related: none.
- `packages/daemon/src/domain/node-launcher.ts`: Atomic node launch service that creates tmux, session rows, bindings, and launch events together. Exports: LaunchResult, NodeLauncher. Related: `packages/daemon/src/adapters/tmux.js`, `packages/daemon/src/domain/event-bus.js`, `packages/daemon/src/domain/rig-repository.js`, `packages/daemon/src/domain/session-name.js`, +2 more.
- `packages/daemon/src/domain/ps-projection.ts`: Builds the `/api/ps` summary view over rigs, nodes, sessions, and latest snapshots. Exports: PsEntry, PsProjectionService. Related: none.
- `packages/daemon/src/domain/reconciler.ts`: Marks missing tmux sessions as detached and keeps persisted session state aligned with reality. Exports: ReconcileResult, Reconciler. Related: `packages/daemon/src/adapters/tmux.js`, `packages/daemon/src/domain/event-bus.js`, `packages/daemon/src/domain/session-registry.js`.
- `packages/daemon/src/domain/rig-repository.ts`: SQLite-backed repository for rig, node, edge, and rig-services state. Also projects `hasServices` into rig summaries for runtime/UI gating. Exports: RigRepository. Related: `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/rig-teardown.ts`: Graceful rig shutdown/delete orchestrator used by `/api/down`. Exports: RigTeardownOrchestrator, TeardownResult. Related: `packages/daemon/src/adapters/tmux.js`, `packages/daemon/src/domain/errors.js`, `packages/daemon/src/domain/event-bus.js`, `packages/daemon/src/domain/rig-repository.js`, +2 more.
- `packages/daemon/src/domain/service-orchestrator.ts`: Rig-scoped services orchestrator for env boot, readiness gating, receipt capture, and teardown. Exports: ServiceBootResult, ServiceOrchestrator, ServiceTeardownResult. Related: `packages/daemon/src/adapters/compose-services-adapter.js`, `packages/daemon/src/domain/rig-repository.js`, `packages/daemon/src/domain/services-readiness.js`.
- `packages/daemon/src/domain/session-name.ts`: Tmux session-name derivation and validation helpers. Exports: deriveSessionName, validateSessionName. Related: none.
- `packages/daemon/src/domain/session-registry.ts`: Session and binding lifecycle repository, including claimed-session registration and startup-status updates. Exports: SessionRegistry. Related: `packages/daemon/src/domain/session-name.js`, `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/services-readiness.ts`: Shared readiness evaluator for RigEnv wait targets (`url`, `tcp`, `service + condition`). Exports: WaitTargetFailure, WaitTargetSuccess, evaluateWaitTargets. Related: none.
- `packages/daemon/src/domain/types.ts`: Canonical daemon type layer for entities, events, legacy rig specs, rebooted RigSpec/AgentSpec topology, RigEnv/service contracts, startup, snapshots, and restore. Exports: AgentResources, AgentSpec, Binding, Checkpoint, ContinuityPolicySpec, ContinuityState, Edge, EnvCheckpoint, EnvReceipt, GuidanceResource, HookResource, ImportSpec, InstantiateOutcome, InstantiateResult, LegacyRigSpec, LegacyRigSpecEdge, LegacyRigSpecNode, LifecycleDefaults, Node, NodeStartupSnapshot, NodeWithBinding, PersistedEvent, PersistedProjectionEntry, Pod, PreflightResult, ProfileSpec, RestoreNodeResult, RestoreOutcome, RestoreResult, Rig, RigEvent, RigServicesRecord, RigServicesSpec, RigSpec, RigSpecCrossPodEdge, RigSpecPod, RigSpecPodEdge, RigSpecPodMember, RigWithRelations, RuntimeResource, Session, SkillResource, Snapshot, SnapshotData, StartupAction, StartupBlock, StartupFile, SubagentResource, ValidationResult. Related: none.
- `packages/daemon/src/domain/up-command-router.ts`: Source router that classifies a path as a rig spec or rig bundle before bootstrap. Exports: RouteResult, SourceKind, UpCommandRouter. Related: `packages/daemon/src/domain/rigspec-codec.js`, `packages/daemon/src/domain/rigspec-schema.js`.
| Doc | One-sentence summary | Reach for this when… |
|---|---|---|
| `cli-reference.md` | The full `rig` CLI surface, kept as one doc. | You need the exact rig CLI surface — command groups, subcommands, flags, JSON output, cross-host, coordination primitives. |
| `frontmatter-schema.md` | The frontmatter convention these docs follow + the as-built-unique field. | You are authoring or updating a doc under `docs/as-built/`. |
| `../DESIGN.md` | The canonical visual / brand / design-system spec (repo `docs/` root). | You need the visual system, brand identity, or design-system tokens. (Stays at root by design; pointer only.) |
### Domain: Specs, Resolution, Startup
- `packages/daemon/src/domain/agent-manifest.ts`: Canonical `agent.yaml` parser, validator, and normalizer for AgentSpec files. Exports: normalizeAgentSpec, parseAgentSpec, validateAgentSpec. Related: `packages/daemon/src/domain/path-safety.js`, `packages/daemon/src/domain/startup-validation.js`, `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/agent-preflight.ts`: Lightweight preflight for a single `agent_ref`, used before full rig instantiation. Exports: agentPreflight. Related: `packages/daemon/src/domain/agent-resolver.js`, `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/agent-resolver.ts`: Resolves `agent_ref` roots, imported AgentSpecs, and cross-spec resource-collision metadata. Exports: AgentResolverFsOps, ResolveResult, ResolvedAgentSpec, ResourceCollision, resolveAgentRef, resolveImports. Related: `packages/daemon/src/domain/agent-manifest.js`, `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/pod-repository.ts`: SQLite-backed repository for pods and live continuity-state rows. Exports: PodRepository. Related: `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/profile-resolver.ts`: Applies AgentSpec defaults, profile uses, startup layering, and restore-policy narrowing to produce a `ResolvedNodeConfig`. Exports: QualifiedResource, ResolutionContext, ResolutionResult, ResolvedNodeConfig, ResolvedResources, resolveNodeConfig. Related: `packages/daemon/src/domain/agent-resolver.js`, `packages/daemon/src/domain/startup-resolver.js`, `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/projection-planner.ts`: Converts resolved node config plus collision data into runtime projection entries, diagnostics, conflicts, and no-ops. Exports: PlanResult, ProjectionClassification, ProjectionEntry, ProjectionFsOps, ProjectionInput, ProjectionPlan, planProjection. Related: `packages/daemon/src/domain/agent-resolver.js`, `packages/daemon/src/domain/conflict-detector.js`, `packages/daemon/src/domain/profile-resolver.js`, `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/rigspec-codec.ts`: YAML codec layer for both legacy flat-node RigSpec and rebooted pod-aware RigSpec shapes. Exports: LegacyRigSpecCodec, RigSpecCodec. Related: `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/rigspec-exporter.ts`: Exports live rigs back into RigSpec YAML/JSON. Dual-format: detects pod-aware rigs (podId non-null) and exports canonical v0.2 RigSpec with pods/members/edges; legacy rigs export as flat-node v1. Exports: RigSpecExporter. Related: `packages/daemon/src/domain/errors.js`, `packages/daemon/src/domain/pod-repository.js`, `packages/daemon/src/domain/rig-repository.js`, `packages/daemon/src/domain/session-registry.js`, `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/rigspec-instantiator.ts`: Dual-stack instantiation layer containing both legacy `RigInstantiator` and rebooted `PodRigInstantiator`. Exports: PodRigInstantiator, RigInstantiator. Related: `packages/daemon/src/domain/agent-resolver.js`, `packages/daemon/src/domain/event-bus.js`, `packages/daemon/src/domain/node-launcher.js`, `packages/daemon/src/domain/pod-repository.js`, +10 more.
- `packages/daemon/src/domain/rigspec-preflight.ts`: Dual-stack preflight layer: legacy `RigSpecPreflight` plus rebooted pure `rigPreflight`. Exports: RigPreflightInput, RigSpecPreflight, rigPreflight. Related: `packages/daemon/src/adapters/tmux.js`, `packages/daemon/src/domain/agent-resolver.js`, `packages/daemon/src/domain/profile-resolver.js`, `packages/daemon/src/domain/rig-repository.js`, +4 more.
- `packages/daemon/src/domain/rigspec-schema.ts`: Validation and normalization for both legacy and rebooted RigSpec schemas. Exports: LegacyRigSpecSchema, RigSpecSchema. Related: `packages/daemon/src/domain/path-safety.js`, `packages/daemon/src/domain/startup-validation.js`, `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/runtime-adapter.ts`: Runtime-adapter contract plus bridge types used by startup orchestration and runtime-specific adapters. Exports: InstalledResource, NodeBinding, ProjectionResult, ReadinessResult, ResolvedStartupFile, RuntimeAdapter, StartupDeliveryResult. Related: `packages/daemon/src/domain/projection-planner.js`, `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/spec-validation-service.ts`: Pure validation helpers for raw AgentSpec and RigSpec YAML strings. Exports: validateAgentSpecFromYaml, validateRigSpecFromYaml. Related: `packages/daemon/src/domain/agent-manifest.js`, `packages/daemon/src/domain/rigspec-codec.js`, `packages/daemon/src/domain/rigspec-schema.js`.
- `packages/daemon/src/domain/spec-review-service.ts`: Structured review-model builder for RigSpec and AgentSpec YAML. Produces topology preview data, normalized summaries, provenance/source-state, and managed-app services metadata used by preview, library, and live display surfaces. Exports: AgentSpecReview, LegacyRigSpecReview, PodAwareRigSpecReview, RigSpecReview, RigSpecServicesReview, SourceState, SpecGraphData, SpecReviewError, SpecReviewService. Related: `packages/daemon/src/domain/agent-manifest.js`, `packages/daemon/src/domain/rigspec-codec.js`, `packages/daemon/src/domain/rigspec-schema.js`.
- `packages/daemon/src/domain/spec-library-service.ts`: Filesystem-backed spec library index over builtin and user roots. Classifies YAML through `SpecReviewService`, assigns stable ids, marks service-backed rigs with `hasServices`, and serves metadata/YAML lookup. Exports: SpecLibraryEntry, SpecLibraryOpts, SpecLibraryService. Related: `packages/daemon/src/domain/spec-review-service.js`.
- `packages/daemon/src/domain/whoami-service.ts`: Daemon-side runtime identity projector used by `/api/whoami`. Resolves by node or session, expands peers/edges/transcript helpers, and surfaces ambiguity honestly. Exports: WhoamiResult, WhoamiAmbiguousError, WhoamiService. Related: `packages/daemon/src/domain/rig-repository.js`, `packages/daemon/src/domain/session-registry.js`, `packages/daemon/src/domain/transcript-store.js`.
- `packages/daemon/src/domain/startup-orchestrator.ts`: Startup execution engine for projection, startup-file delivery, action execution, readiness, and persisted replay context. Exports: StartupInput, StartupOrchestrator, StartupResult. Related: `packages/daemon/src/adapters/tmux.js`, `packages/daemon/src/domain/event-bus.js`, `packages/daemon/src/domain/projection-planner.js`, `packages/daemon/src/domain/runtime-adapter.js`, +2 more.
- `packages/daemon/src/domain/startup-resolver.ts`: Pure additive startup-layer merge function across agent, profile, rig, pod, member, and operator layers. Exports: StartupLayerInputs, resolveStartup. Related: `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/startup-validation.ts`: Shared validation and normalization for startup files and startup actions. Exports: normalizeStartupBlock, validateStartupAction, validateStartupBlock, validateStartupFile. Related: `packages/daemon/src/domain/path-safety.js`, `packages/daemon/src/domain/types.js`.
## (c) Structural relationship diagram
### Domain: Snapshots And Restore
- `packages/daemon/src/domain/checkpoint-store.ts`: Checkpoint persistence, lookup, and rig-wide checkpoint aggregation. Exports: CheckpointStore. Related: `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/restore-orchestrator.ts`: Restore pipeline for relaunch, resume, checkpoint delivery, startup replay, topology ordering, and RigEnv boot gating before agent restore. Exports: RestoreOrchestrator. Related: `packages/daemon/src/adapters/claude-resume.js`, `packages/daemon/src/adapters/codex-resume.js`, `packages/daemon/src/adapters/tmux.js`, `packages/daemon/src/domain/checkpoint-store.js`, +7 more.
- `packages/daemon/src/domain/snapshot-capture.ts`: Captures a consistent snapshot of rig topology, sessions, checkpoints, pods, continuity state, startup context, and the latest rig-env receipt. Exports: SnapshotCapture. Related: `packages/daemon/src/domain/checkpoint-store.js`, `packages/daemon/src/domain/errors.js`, `packages/daemon/src/domain/event-bus.js`, `packages/daemon/src/domain/rig-repository.js`, +3 more.
- `packages/daemon/src/domain/snapshot-repository.ts`: SQLite-backed repository for snapshot CRUD and listing. Exports: SnapshotRepository. Related: `packages/daemon/src/domain/types.js`.
Built from each module's `siblings` / `prerequisite-reads` frontmatter.
`daemon-core.md` is the spine (prerequisite for almost every architecture
module); `shell-and-routing.md` is the UI spine.
### Domain: Packages And Install Engine
- `packages/daemon/src/domain/conflict-detector.ts`: Content-aware conflict classification shared by package installs and rebooted projection planning. Exports: GuidanceConflictMeta, RefinedInstallPlan, classifyResourceProjection, detectConflicts. Related: `packages/daemon/src/domain/install-planner.js`, `packages/daemon/src/domain/package-resolver.js`, `packages/daemon/src/domain/projection-planner.js`.
- `packages/daemon/src/domain/install-engine.ts`: Journaled apply/rollback engine for package installs. Exports: EngineFsOps, InstallEngine, InstallResult, RollbackResult. Related: `packages/daemon/src/domain/conflict-detector.js`, `packages/daemon/src/domain/install-planner.js`, `packages/daemon/src/domain/install-policy.js`, `packages/daemon/src/domain/install-repository.js`.
- `packages/daemon/src/domain/install-planner.ts`: Computes classified package install entries and target paths. Exports: ActionClassification, ConflictInfo, InstallPlan, InstallPlanEntry, InstallPlanner, PlanOptions. Related: `packages/daemon/src/domain/package-resolver.js`, `packages/daemon/src/domain/role-resolver.js`.
- `packages/daemon/src/domain/install-policy.ts`: Approval-policy gate for package install plans. Exports: PolicyRejection, PolicyResult, applyPolicy. Related: `packages/daemon/src/domain/conflict-detector.js`, `packages/daemon/src/domain/install-planner.js`.
- `packages/daemon/src/domain/install-repository.ts`: SQLite-backed repository for package install records and journal entries. Exports: Install, InstallRepository, InstallSummary, JournalEntry. Related: none.
- `packages/daemon/src/domain/install-verifier.ts`: Post-apply verification for install records and filesystem targets. Exports: Check, EntryVerification, InstallVerifier, VerificationResult, VerifierFsOps. Related: `packages/daemon/src/domain/install-repository.js`, `packages/daemon/src/domain/package-repository.js`.
- `packages/daemon/src/domain/package-install-service.ts`: Top-level package validate/plan/install/rollback service used by routes and bootstrap. Exports: PackageInstallOutcome, PackageInstallService. Related: `packages/daemon/src/domain/conflict-detector.js`, `packages/daemon/src/domain/install-engine.js`, `packages/daemon/src/domain/install-planner.js`, `packages/daemon/src/domain/install-policy.js`, +4 more.
- `packages/daemon/src/domain/package-manifest.ts`: Parser and validator for `package.yaml` manifests. Exports: AgentExport, GuidanceExport, HookExport, InstallPolicy, McpExport, PackageExports, PackageManifest, PackageRequirements, RoleDefinition, SkillExport, ValidationResult, VerificationCheck, VerificationConfig, normalizeManifest, parseManifest, serializeManifest, validateManifest. Related: none.
- `packages/daemon/src/domain/package-repository.ts`: SQLite-backed repository for package metadata and install summaries. Exports: Package, PackageRepository, PackageSummary. Related: none.
- `packages/daemon/src/domain/package-resolve-helper.ts`: Shared helper that wraps package resolution for routes and orchestrators. Exports: ResolveResult, resolvePackage. Related: `packages/daemon/src/domain/package-manifest.js`, `packages/daemon/src/domain/package-resolver.js`.
- `packages/daemon/src/domain/package-resolver.ts`: Resolves local package sources and computes manifest hashes. Exports: FsOps, PackageResolver, ResolvedPackage. Related: `packages/daemon/src/domain/package-manifest.js`.
- `packages/daemon/src/domain/path-safety.ts`: Shared safe-path validator used by manifests and startup config. Exports: validateSafePath. Related: none.
- `packages/daemon/src/domain/role-resolver.ts`: Filters package exports according to selected roles/runtime scope. Exports: DeferredExport, ResolvedExports, resolveExports. Related: `packages/daemon/src/domain/package-manifest.js`.
```
README.md (entry — prerequisite for all)
│
┌───────────────┴───────────────┐
▼ ▼
architecture/ ui/
│ │
daemon-core.md ◀── (prerequisite spine for the column below)
│ │ │ │
│ │ │ └──▶ adapters-and-runtimes.md
│ │ │ (five-method contract + resume honesty;
│ │ │ consumed by agent-spec startup orchestration)
│ │ └────────────────────────────┐
│ └──────────────┐ │
▼ ▼ ▼
coordination- agent-spec-and- transport-and-
primitive.md startup.md transcripts.md
│ │ │ │
▼ ▼ │ ▼
workflow- mission- │ lifecycle-snapshot-restore.md
runtime.md control.md │ ▲ (consumes persisted replay context)
│ │ │
└────┬─────┘ ├──▶ packaging-bootstrap-bundles.md
▼ │ ▲
architecture-rules- │ │ (0.3.x reusable starter-state cluster)
and-event-system.md │ ▼
(consumes all └──▶ plugin-agent-image-context-pack.md
PL-004/005 events)
### Domain: Bootstrap, Discovery, Bundles
- `packages/daemon/src/domain/bootstrap-orchestrator.ts`: Staged bootstrap workflow that composes runtime verification, requirement probes, external installs, package installs, legacy rig instantiation, direct pod-aware rig handling, and schema-version-2 pod-bundle delegation. Exports: BootstrapMode, BootstrapOptions, BootstrapOrchestrator, BootstrapResult, BootstrapStageResult. Related: `packages/daemon/src/domain/bootstrap-repository.js`, `packages/daemon/src/domain/bootstrap-types.js`, `packages/daemon/src/domain/bundle-source-resolver.js`, `packages/daemon/src/domain/external-install-executor.js`, +10 more.
- `packages/daemon/src/domain/bootstrap-repository.ts`: SQLite-backed repository for bootstrap runs and action journals. Exports: BootstrapRepository. Related: `packages/daemon/src/domain/bootstrap-types.js`.
- `packages/daemon/src/domain/bootstrap-types.ts`: Shared type definitions for bootstrap data. Exports: ActionKind, ActionStatus, BootstrapAction, BootstrapRun, BootstrapStatus, RuntimeStatus, RuntimeVerification. Related: none.
- `packages/daemon/src/domain/bundle-archive.ts`: Archive pack/unpack and digest verification for `.rigbundle` files. Exports: pack, unpack, verifyArchiveDigest. Related: `packages/daemon/src/domain/bundle-integrity.js`, `packages/daemon/src/domain/bundle-types.js`.
- `packages/daemon/src/domain/bundle-assembler.ts`: Legacy rig-bundle assembler for package-based bundles. Exports: AssembleOptions, AssemblerFsOps, LegacyBundleAssembler, PackageInput. Related: `packages/daemon/src/domain/bundle-types.js`, `packages/daemon/src/domain/rigspec-codec.js`, `packages/daemon/src/domain/rigspec-schema.js`.
- `packages/daemon/src/domain/bundle-integrity.ts`: Per-file integrity manifest generation and verification for bundles. Exports: IntegrityFsOps, VerifyResult, computeIntegrity, verifyIntegrity, writeIntegrity. Related: `packages/daemon/src/domain/bundle-types.js`.
- `packages/daemon/src/domain/bundle-source-resolver.ts`: Dual-stack bundle resolver containing legacy package-bundle and rebooted pod-bundle extraction flows. Exports: BundleResolvedSource, LegacyBundleSourceResolver, PodBundleResolvedSource, PodBundleSourceResolver. Related: `packages/daemon/src/domain/bundle-archive.js`, `packages/daemon/src/domain/bundle-types.js`, `packages/daemon/src/domain/package-resolve-helper.js`, `packages/daemon/src/domain/package-resolver.js`.
- `packages/daemon/src/domain/bundle-types.ts`: Bundle manifest types plus parse/validate/serialize helpers for schema v1 and schema v2 bundles. Exports: BundleIntegrity, LegacyBundleManifest, LegacyBundlePackageEntry, PodBundleAgentEntry, PodBundleAgentImportEntry, PodBundleManifest, isRelativeSafePath, normalizeLegacyBundleManifest, parseLegacyBundleManifest, parsePodBundleManifest, serializeLegacyBundleManifest, serializePodBundleManifest, validateLegacyBundleManifest, validatePodBundleManifest. Related: none.
- `packages/daemon/src/domain/claim-service.ts`: Claims discovered sessions into managed rig/node state. Exports: ClaimResult, ClaimService. Related: `packages/daemon/src/domain/discovery-repository.js`, `packages/daemon/src/domain/event-bus.js`, `packages/daemon/src/domain/rig-repository.js`, `packages/daemon/src/domain/session-registry.js`.
- `packages/daemon/src/domain/discovery-coordinator.ts`: Coordinates tmux scans, fingerprinting, enrichment, persistence, and event emission for discovery. Exports: DiscoveryCoordinator. Related: `packages/daemon/src/domain/discovery-repository.js`, `packages/daemon/src/domain/discovery-types.js`, `packages/daemon/src/domain/event-bus.js`, `packages/daemon/src/domain/session-enricher.js`, +3 more.
- `packages/daemon/src/domain/discovery-repository.ts`: SQLite-backed repository for discovered session records. Exports: DiscoveryRepository, UpsertData. Related: `packages/daemon/src/domain/discovery-types.js`.
- `packages/daemon/src/domain/discovery-types.ts`: Shared type definitions for discovery data. Exports: Confidence, DiscoveredSession, DiscoveryStatus, RuntimeHint, SessionOrigin. Related: none.
- `packages/daemon/src/domain/external-install-executor.ts`: Runs approved external install actions and journals execution results. Exports: ExecutionResult, ExecutionSummary, ExternalInstallExecutor, TaggedAction. Related: `packages/daemon/src/adapters/tmux.js`, `packages/daemon/src/domain/external-install-planner.js`.
- `packages/daemon/src/domain/external-install-planner.ts`: Turns requirement-probe results into auto-approvable or manual external install actions. Exports: ApprovalClassification, ExternalInstallAction, ExternalInstallPlan, ExternalInstallPlanner. Related: `packages/daemon/src/adapters/shell-quote.js`, `packages/daemon/src/domain/requirements-probe.js`.
- `packages/daemon/src/domain/pod-bundle-assembler.ts`: Rebooted bundle assembler that vendors AgentSpecs, imports, rig startup files, and rewritten `agent_ref`s. Exports: PodAssembleOptions, PodAssembleResult, PodAssemblerFsOps, PodBundleAssembler. Related: `packages/daemon/src/domain/agent-resolver.js`, `packages/daemon/src/domain/bundle-types.js`, `packages/daemon/src/domain/rigspec-codec.js`, `packages/daemon/src/domain/rigspec-schema.js`, +1 more.
- `packages/daemon/src/domain/requirements-probe.ts`: Requirement-probe registry and probe result types used during bootstrap. Exports: ProbeResult, ProbeStatus, RequirementSpec, RequirementsProbeRegistry. Related: `packages/daemon/src/adapters/shell-quote.js`, `packages/daemon/src/adapters/tmux.js`.
- `packages/daemon/src/domain/runtime-verifier.ts`: Verifies runtime/tool availability and persists verification results. Exports: RuntimeVerifier. Related: `packages/daemon/src/adapters/tmux.js`, `packages/daemon/src/domain/bootstrap-types.js`.
- `packages/daemon/src/domain/session-enricher.ts`: Adds repository/config hints to discovered sessions based on filesystem inspection. Exports: EnrichmentResult, SessionEnricher. Related: none.
- `packages/daemon/src/domain/session-fingerprinter.ts`: Infers runtime/session identity from tmux, cmux, process, and pane evidence. Exports: FingerprintEvidence, FingerprintResult, SessionFingerprinter. Related: `packages/daemon/src/adapters/cmux.js`, `packages/daemon/src/adapters/tmux.js`, `packages/daemon/src/domain/discovery-types.js`, `packages/daemon/src/domain/tmux-discovery-scanner.js`.
- `packages/daemon/src/domain/tmux-discovery-scanner.ts`: Low-level tmux scanner that enumerates panes/sessions for discovery. Exports: ScanResult, ScannedPane, TmuxDiscoveryScanner. Related: `packages/daemon/src/adapters/tmux.js`.
workspace-primitive.md ──▶ content-surfaces.md
(PL-007 declaration) (filesystem read/write layer on top)
│ │
└──────────┬───────────────┘
▼ (UI counterpart)
ui/project-and-for-you.md
### Domain: North Star Operator Layer
- `packages/daemon/src/domain/node-inventory.ts`: Universal node-level projection consumed by CLI, UI, and MCP. Core fields (session name, status, startup status, restore outcome, attach command) plus extended fields (model, agent ref, startup files, installed resources). Exports: NodeInventoryService. Related: `packages/daemon/src/domain/types.js`, `packages/daemon/src/domain/runtime-adapter.js`.
- `packages/daemon/src/domain/demo-rig-selector.ts`: Helper for existing-rig power-on — finds the right rig by name from ps summary entries. Exports: selectCurrentRigSummary. Related: none.
- `packages/daemon/src/domain/draft-rig-generator.ts`: Synthesizes a candidate RigSpec YAML from discovered sessions — groups by CWD, suggests pods, sanitizes IDs. Exports: generateDraftRig. Related: `packages/daemon/src/domain/discovery-types.js`, `packages/daemon/src/domain/rigspec-codec.js`, `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/domain/native-resume-probe.ts`: Honest assessment of whether a harness actually resumed vs fresh-launched — probes pane command and content for runtime-specific indicators. Exports: NativeResumeProbeResult, assessNativeResumeProbe, buildNativeResumeCommand, isProbeShellReady. Related: `packages/daemon/src/adapters/shell-quote.js`.
- `packages/daemon/src/domain/resume-metadata-refresher.ts`: Post-launch resume token capture — reads Claude conversation IDs from state files and Codex thread IDs from SQLite. Exports: ResumeMetadataRefresher. Related: `packages/daemon/src/domain/codex-thread-id.js`, `packages/daemon/src/domain/native-resume-probe.js`, `packages/daemon/src/domain/session-registry.js`, `packages/daemon/src/adapters/tmux.js`.
- `packages/daemon/src/domain/codex-thread-id.ts`: Codex-specific thread ID extraction from the Codex SQLite state database. Exports: defaultResolveHomeDirByPid, readCodexThreadIdFromCandidateHomes, ResolveHomeDirByPid. Related: none.
shell-and-routing.md ──▶ topology.md
│ └──▶ project-and-for-you.md ◀──▶ architecture/mission-control.md
└──────────────▶ library-specs-and-design-system.md ──▶ ../DESIGN.md (pointer)
```
### Domain: Post-North-Star Transport and History
- `packages/daemon/src/domain/session-transport.ts`: Communication primitives — send/capture/broadcast with session resolution (canonical + legacy names), mid-work detection via pane content heuristics, honest error reporting, pod/rig/global targeting. Exports: SessionTransport, TargetSpec, SendResult, CaptureResult, BroadcastResult, SendOpts. Related: `packages/daemon/src/domain/rig-repository.js`, `packages/daemon/src/domain/session-registry.js`, `packages/daemon/src/adapters/tmux.js`.
- `packages/daemon/src/domain/transcript-store.ts`: Pipe-pane transcript management — ANSI stripping on read (preserves raw on disk), boundary markers for session lifecycle events, readTail, grep. Filesystem-backed, not SQLite. Exports: TranscriptStore, TranscriptStoreOpts. Related: none (filesystem-only).
- `packages/daemon/src/domain/history-query.ts`: Unified transcript + chat search — prefers `rg` when available, falls back to `grep -E`, surfaces which backend was used. Exports: HistoryQuery, SearchResult, ChatSearchResult, ExecDep. Related: `packages/daemon/src/domain/transcript-store.js`.
- `packages/daemon/src/domain/ask-service.ts`: Context engineering evidence pack — gathers topology snapshot, transcript excerpts, chat history excerpts, restore metadata. Returns structured context for the agent to reason about. Does NOT call an external LLM. Exports: AskService, AskDeps. Related: `packages/daemon/src/domain/ps-projection.js`, `packages/daemon/src/domain/rig-repository.js`, `packages/daemon/src/domain/history-query.js`.
- `packages/daemon/src/domain/chat-repository.ts`: Durable rig-scoped chat messages — CRUD for chat_messages table, monotonic ULID IDs, rig-scoped queries. Exports: ChatRepository, ChatMessage. Related: none (SQLite-only).
Reading-order rule: open a module's `prerequisite-reads` first
(`README.md`, then `daemon-core.md` for most architecture modules;
`README.md` then `shell-and-routing.md` for most ui modules).
### Domain: Coordination Primitive (PL-004 Phase A)
- `packages/daemon/src/domain/stream-store.ts`: L1 coordination stream — append-only intake/audit root. Idempotent emit on stream_item_id, chronological list with cursor pagination, soft archive. Exports: StreamStore, StreamItem, StreamEmitInput, StreamListOptions. Related: `packages/daemon/src/domain/event-bus.js`.
- `packages/daemon/src/domain/queue-repository.ts`: L3 coordination queue — create, claim/unclaim, update with hot-potato strict-rejection, transactional handoff (close source + create new in one transaction), pod-fallback rerouting, overdue lookup. POC qitem_id format preserved. Exports: QueueRepository, QueueRepositoryError, QueueItem, QueueState, QueuePriority, QueueCreateInput, QueueUpdateInput, QueueHandoffInput. Related: `packages/daemon/src/domain/event-bus.js`, `packages/daemon/src/domain/queue-transition-log.js`, `packages/daemon/src/domain/hot-potato-enforcer.js`.
- `packages/daemon/src/domain/queue-transition-log.ts`: Append-only state transition log for queue_items. No UPDATE / DELETE from domain code. Exports: QueueTransitionLog, QueueTransition, QueueTransitionInput. Related: `packages/daemon/src/domain/hot-potato-enforcer.js`.
- `packages/daemon/src/domain/hot-potato-enforcer.ts`: Pure validator for the load-bearing hot-potato API contract — state=done requires closure_reason from the 6-value enum. Tier→SLA mapping for closure_required_at. Exports: CLOSURE_REASONS, ClosureReason, validateClosure, isClosureReason, computeClosureRequiredAt. Related: none.
- `packages/daemon/src/domain/inbox-handler.ts`: Mailbox handler — authenticated drop (idempotent on inbox_id), absorb (promote pending entry to a queue_item), deny (record reason). Authentication is a pluggable constructor hook. Exports: InboxHandler, InboxHandlerError, InboxEntry, InboxState, InboxDropInput. Related: `packages/daemon/src/domain/event-bus.js`, `packages/daemon/src/domain/queue-repository.js`.
- `packages/daemon/src/domain/outbox-handler.ts`: Sender-side outbox — symmetric to inbox; idempotent record, mark delivered/failed, list. No event-bus events emitted. Exports: OutboxHandler, OutboxHandlerError, OutboxEntry, OutboxDeliveryState, OutboxRecordInput. Related: none (SQLite-only).
## (d) Fast lookup by use-case
### Routes
- `packages/daemon/src/routes/adapters.ts`: Hono route module for adapters API endpoints. Exports: adaptersRoutes. Related: `packages/daemon/src/adapters/cmux.js`, `packages/daemon/src/adapters/tmux.js`.
- `packages/daemon/src/routes/agents.ts`: Hono route module for AgentSpec validation. POST `/api/agents/validate` using `validateAgentSpecFromYaml`. Exports: agentsRoutes. Related: `packages/daemon/src/domain/spec-validation-service.js`.
- `packages/daemon/src/routes/bootstrap.ts`: Hono route module for bootstrap API endpoints. Exports: bootstrapRoutes. Related: `packages/daemon/src/domain/bootstrap-orchestrator.js`, `packages/daemon/src/domain/bootstrap-repository.js`, `packages/daemon/src/domain/event-bus.js`.
- `packages/daemon/src/routes/bundles.ts`: Hono route module for dual-format bundle create/inspect/install. Supports legacy v1 package bundles and schema-version-2 pod bundles, including v2 inspect responses with `agents[]` and integrity data. Exports: bundleRoutes. Related: `packages/daemon/src/domain/bootstrap-orchestrator.js`, `packages/daemon/src/domain/bootstrap-repository.js`, `packages/daemon/src/domain/bundle-archive.js`, `packages/daemon/src/domain/bundle-assembler.js`, +7 more.
- `packages/daemon/src/routes/discovery.ts`: Hono route module for discovery scan/list/detail plus Final Stretch flows: `draft-rig`, `bind`, and composite `adopt`. Exports: discoveryRoutes. Related: `packages/daemon/src/domain/claim-service.js`, `packages/daemon/src/domain/discovery-coordinator.js`, `packages/daemon/src/domain/discovery-repository.js`, `packages/daemon/src/domain/draft-rig-generator.js`.
- `packages/daemon/src/routes/down.ts`: Hono route module for down API endpoints. Exports: downRoutes. Related: `packages/daemon/src/domain/errors.js`, `packages/daemon/src/domain/rig-teardown.js`.
- `packages/daemon/src/routes/env.ts`: Hono route module for rig-environment status, logs, and teardown. Refreshes env receipts best-effort and returns additive managed-app/runtime metadata (`hasServices`, `surfaces`, `receipt`). Exports: envRoutes. Related: `packages/daemon/src/adapters/compose-services-adapter.js`, `packages/daemon/src/domain/rig-repository.js`, `packages/daemon/src/domain/service-orchestrator.js`.
- `packages/daemon/src/routes/events.ts`: Hono route module for events API endpoints. Exports: eventsRoute. Related: `packages/daemon/src/domain/event-bus.js`, `packages/daemon/src/domain/types.js`.
- `packages/daemon/src/routes/packages.ts`: Hono route module for the legacy package-install surface (`/validate`, `/plan`, `/install`, history, rollback). AgentSpec validation no longer lives here. Exports: packagesRoutes. Related: `packages/daemon/src/domain/conflict-detector.js`, `packages/daemon/src/domain/event-bus.js`, `packages/daemon/src/domain/install-engine.js`, `packages/daemon/src/domain/install-planner.js`, +6 more.
- `packages/daemon/src/routes/ps.ts`: Hono route module for ps API endpoints. Exports: psRoutes. Related: `packages/daemon/src/domain/ps-projection.js`.
- `packages/daemon/src/routes/rigs.ts`: Hono route module for rig CRUD, graph projection, summary, delete, and existing-rig power-on by rig id. Exports: rigsRoutes. Related: `packages/daemon/src/domain/event-bus.js`, `packages/daemon/src/domain/graph-projection.js`, `packages/daemon/src/domain/node-inventory.js`, `packages/daemon/src/domain/rig-repository.js`, `packages/daemon/src/domain/session-registry.js`.
- `packages/daemon/src/routes/rigspec.ts`: Hono route module for dual-format RigSpec import, validate, preflight, materialize, and export. Pod-aware import/preflight/materialize require `X-Rig-Root`; export emits v0.2 pod-aware YAML/JSON when the live rig has pods. Exports: handleExportJson, handleExportYaml, rigspecImportRoutes. Related: `packages/daemon/src/domain/errors.js`, `packages/daemon/src/domain/rigspec-codec.js`, `packages/daemon/src/domain/rigspec-exporter.js`, `packages/daemon/src/domain/rigspec-instantiator.js`, +2 more.
- `packages/daemon/src/routes/sessions.ts`: Hono route module for rig sessions and node inventory/detail/launch/focus. `GET /api/rigs/:rigId/nodes/:logicalId` is the backend contract for the live node drawer and full-details workspace. Exports: nodesRoutes, sessionsRoutes. Related: `packages/daemon/src/adapters/cmux.js`, `packages/daemon/src/domain/node-inventory.js`, `packages/daemon/src/domain/node-launcher.js`, `packages/daemon/src/domain/rig-repository.js`, `packages/daemon/src/domain/session-registry.js`.
- `packages/daemon/src/routes/snapshots.ts`: Hono route module for snapshots API endpoints. Exports: restoreRoutes, snapshotsRoutes. Related: `packages/daemon/src/domain/errors.js`, `packages/daemon/src/domain/restore-orchestrator.js`, `packages/daemon/src/domain/snapshot-capture.js`, `packages/daemon/src/domain/snapshot-repository.js`.
- `packages/daemon/src/routes/transport.ts`: Hono route module for communication primitives (`POST /send`, `/capture`, `/broadcast`). Resolves session targets, delegates to SessionTransport. Exports: transportRoutes. Related: `packages/daemon/src/domain/session-transport.js`.
- `packages/daemon/src/routes/transcripts.ts`: Hono route module for transcript access (`GET /:session/tail`, `/:session/grep`). Resolves session to rig/node, delegates to TranscriptStore. Exports: transcriptRoutes. Related: `packages/daemon/src/domain/transcript-store.js`, `packages/daemon/src/domain/rig-repository.js`.
- `packages/daemon/src/routes/ask.ts`: Hono route module for context evidence packs (`POST /`). Delegates to AskService. Exports: askRoutes. Related: `packages/daemon/src/domain/ask-service.js`.
- `packages/daemon/src/routes/chat.ts`: Hono route module for durable rig chat (`GET /watch` SSE stream, `POST /send`, `GET /history`, `POST /topic`). Delegates to ChatRepository, streams via SSE. Exports: chatRoutes. Related: `packages/daemon/src/domain/chat-repository.js`, `packages/daemon/src/domain/event-bus.js`.
- `packages/daemon/src/routes/stream.ts`: Hono route module for the PL-004 Phase A coordination L1 stream (`POST /emit`, `GET /list`, `GET /:id`, `POST /:id/archive`, `GET /watch` SSE). Host-scoped (no rigId). Exports: streamRoutes. Related: `packages/daemon/src/domain/stream-store.js`, `packages/daemon/src/domain/event-bus.js`.
- `packages/daemon/src/routes/queue.ts`: Hono route module for the PL-004 Phase A coordination L3 queue plus inbox/outbox (`POST /create`, `POST /:id/{claim,unclaim,update,handoff,fallback}`, `GET /list`, `GET /overdue`, `GET /:id`, `GET /:id/transitions`, inbox/outbox subroutes, `GET /watch` SSE). Surfaces hot-potato strict-rejection structured errors with validReasons enum. Exports: queueRoutes. Related: `packages/daemon/src/domain/queue-repository.js`, `packages/daemon/src/domain/inbox-handler.js`, `packages/daemon/src/domain/outbox-handler.js`, `packages/daemon/src/domain/event-bus.js`.
- `packages/daemon/src/routes/spec-review.ts`: Hono route module for structured review over raw RigSpec / AgentSpec YAML. Accepts `sourceState` and returns review models or validation errors. Exports: specReviewRoutes. Related: `packages/daemon/src/domain/spec-review-service.js`.
- `packages/daemon/src/routes/spec-library.ts`: Hono route module for the filesystem-backed spec library (`list`, `get`, `review`, `sync`). Enriches service-backed reviews with best-effort compose preview data for managed-app UI surfaces. Exports: specLibraryRoutes. Related: `packages/daemon/src/domain/spec-library-service.js`, `packages/daemon/src/domain/spec-review-service.js`.
- `packages/daemon/src/routes/whoami.ts`: Hono route module for daemon-backed runtime identity lookup by `nodeId` or `sessionName`. Exports: whoamiRoutes. Related: `packages/daemon/src/domain/whoami-service.js`.
- `packages/daemon/src/routes/up.ts`: Hono route module for `/api/up`, routing direct rig specs, bundles, and rig-name restore into the staged bootstrap flow. Exports: upRoutes. Related: `packages/daemon/src/domain/bootstrap-orchestrator.js`, `packages/daemon/src/domain/bootstrap-repository.js`, `packages/daemon/src/domain/event-bus.js`, `packages/daemon/src/domain/up-command-router.js`.
| I need to know… | → see |
|---|---|
| How the daemon boots / `createDaemon` wiring / migration set / route mounts | `architecture/daemon-core.md` |
| The runtime-adapter contract / how a harness is launched or resumed in tmux | `architecture/adapters-and-runtimes.md` |
| Where Claude resume honesty lives / resumed-vs-fresh assessment | `architecture/adapters-and-runtimes.md` |
| Where queue closure is enforced / hot-potato contract / durable handoff | `architecture/coordination-primitive.md` |
| How workflow specs project on closure / transactional-scribe / watchdog policies | `architecture/workflow-runtime.md` |
| The Mission Control views/verbs / queue-observability / action audit | `architecture/mission-control.md` |
| AgentSpec/RigSpec types, profile resolution, startup layering, whoami/bind/adopt | `architecture/agent-spec-and-startup.md` |
| Snapshot/restore, restore honesty, restore-check / restore-packet probes | `architecture/lifecycle-snapshot-restore.md` |
| rig send/capture/broadcast, transcripts, durable chat, `rig ask`, MCP-name vs tmux-key | `architecture/transport-and-transcripts.md` |
| The workspace primitive (root/repos), `target_repo` scope gating, missions/slices indexing | `architecture/workspace-primitive.md` |
| The file browser path safety, atomic writes + edit audit, PROGRESS tree, Steering composer | `architecture/content-surfaces.md` |
| Plugin discovery / agent images / context packs / Claude auto-compaction enforcer | `architecture/plugin-agent-image-context-pack.md` |
| Bundle assembly, bundle install / `/api/up`, BootstrapOrchestrator, legacy install seams | `architecture/packaging-bootstrap-bundles.md` |
| The 25 architecture rules / RigEvent union / SSE delivery / compatibility limits | `architecture/architecture-rules-and-event-system.md` |
| The UI shell, the real route tree, the shared detail drawer | `ui/shell-and-routing.md` |
| The topology graph/table/terminal views, activity-ring / hot-potato visuals | `ui/topology.md` |
| The For-You attention feed, Project scope pages, the Dashboard landing | `ui/project-and-for-you.md` |
| The vellum brand system on the destination surfaces (0.3.1 brand identity) | `ui/project-and-for-you.md` (vellum brand = **0.3.1** per slice-00 0.3.0-GT seam (b); slice-00 §2 row 1 = vellum-primitives → brand-identity, row 2 = destination-model → polished-destinations) |
| The Library `/specs` UI + spec-review/spec-library/live-identity flows | `ui/library-specs-and-design-system.md` |
| The full `rig` CLI surface | `cli-reference.md` |
| The visual / brand / design-system spec | `../DESIGN.md` (repo `docs/` root) |
| Which frontmatter these docs use + the as-built-unique field | `frontmatter-schema.md` |
## CLI
## (e) Source-root pointer table
### Entrypoints And Infrastructure
- `packages/cli/src/client.ts`: Shared HTTP client for talking to the daemon API, including raw JSON posts and text-body posts with optional extra headers such as `X-Rig-Root`. Exports: DaemonClient, DaemonConnectionError, DaemonResponse. Related: none.
- `packages/cli/src/daemon-lifecycle.ts`: Starts, stops, inspects, and tails the local daemon process. Spawns the daemon with `process.execPath` and bypasses local `daemon.json` gating when `OPENRIG_URL` is set by probing remote `/healthz` directly. Exports: DaemonState, DaemonStatus, LOG_FILE, LifecycleDeps, OPENRIG_DIR, STATE_FILE, StartOptions, getDaemonPath, getDaemonStatus, readLogs, startDaemon, stopDaemon, tailLogs. Related: none.
- `packages/cli/src/index.ts`: Commander entrypoint that assembles the full `rig` CLI program (40 mounted command groups, including env status/logs/down, `destroy`, and Final Stretch 1 `specs`, `whoami`, `bind`, and `adopt`). Exports: ProgramDeps, createProgram. Related: `packages/cli/src/commands/bootstrap.js`, `packages/cli/src/commands/bundle.js`, `packages/cli/src/commands/claim.js`, `packages/cli/src/commands/daemon.js`, +19 more.
- `packages/cli/src/mcp-server.ts`: Implements the CLI-hosted MCP server over stdio, wrapping 17 daemon-backed tools including node inventory, send/capture, bundle/spec validation, and chatroom. Exports: createMcpServer. Related: `packages/cli/src/client.js`.
Module → primary `packages/*/src/...` roots. This replaces the old per-file
`Exports:`/`Related:` dump: it points at the code, it does not transcribe it.
Source-grounding for each claim lives inside the module with file:line cites.
### Commands
- `packages/cli/src/commands/agent.ts`: Commander command module for `agent`. Subcommands: `validate` (POST `/api/agents/validate`). Supports `--json`. Exports: AgentDeps, agentCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/bootstrap.ts`: Commander command module for `bootstrap`. Supports library-name resolution before falling back to raw source refs. Exports: bootstrapCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/commands/specs.js`, `packages/cli/src/commands/status.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/bind.ts`: Commander command module for `bind` — bind a discovered session to an existing logical node. Exports: bindCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/commands/status.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/bundle.ts`: Commander command module for `bundle`. Supports dual-format bundle create/inspect/install, `--json`, and pod-aware `--rig-root` on create. Exports: bundleCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/commands/status.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/claim.ts`: Commander command module for `claim`. Exports: claimCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/commands/status.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/daemon.ts`: Commander command module for `daemon`. Exports: daemonCommand, realDeps. Related: `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/discover.ts`: Commander command module for `discover`. Exports: discoverCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/commands/status.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/down.ts`: Commander command module for `down`. Exports: downCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/commands/status.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/env.ts`: Commander command module for `env` — rig environment status/logs/down for service-backed rigs and managed apps. Exports: envCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/daemon-lifecycle.js`, `packages/cli/src/commands/status.js`.
- `packages/cli/src/commands/export.ts`: Commander command module for `export`. Exports: ExportDeps, exportCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/commands/status.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/import.ts`: Commander command module for `import`. Locally parses YAML to detect pod-aware rigs, sends `X-Rig-Root` for pod-aware preflight/instantiate flows, and supports `--rig-root`. Exports: ImportDeps, importCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/commands/status.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/mcp.ts`: Commander command module for `mcp`. Exports: mcpCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/commands/status.js`, `packages/cli/src/daemon-lifecycle.js`, +1 more.
- `packages/cli/src/commands/package.ts`: Commander command module for the legacy package-management surface. Exports: packageCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/commands/status.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/ps.ts`: Commander command module for `ps`. Exports: psCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/commands/status.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/requirements.ts`: Commander command module for `requirements`. Exports: requirementsCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/commands/status.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/restore.ts`: Commander command module for `restore`. Exports: restoreCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/commands/status.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/rig.ts`: Commander command module for `rig`. Subcommands: `validate` (POST `/api/rigs/import/validate`), `preflight` (POST `/api/rigs/import/preflight` with `X-Rig-Root` header). Both support `--json`. Exports: RigDeps, rigCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/snapshot.ts`: Commander command module for `snapshot`. Exports: snapshotCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/commands/status.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/status.ts`: Commander command module for `status`. Exports: StatusDeps, statusCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/specs.ts`: Commander command module for the agent-facing spec library workflow. Subcommands: `ls`, `show`, `preview`, `add`, `sync`, plus shared name resolution used by `up` and `bootstrap`. `add` accepts single YAML files and full spec directories containing `rig.yaml` or `agent.yaml`. Help/examples and not-found guidance explicitly call out managed apps. Exports: resolveLibrarySpec, specsCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/ui.ts`: Commander command module for `ui`. Exports: UiDeps, uiCommand. Related: `packages/cli/src/commands/daemon.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/up.ts`: Commander command module for `up`. Supports spec paths, bundle paths, rig-name restore, and library-name resolution; fails loudly on rig-name vs library-name ambiguity. Help/examples now treat managed apps like `secrets-manager` as first-class launch targets. Auto-preflight, auto-daemon-start, post-command handoff with attach commands. Exports: upCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/daemon.js`, `packages/cli/src/commands/specs.js`, `packages/cli/src/daemon-lifecycle.js`, `packages/cli/src/system-preflight.js`.
- `packages/cli/src/commands/whoami.ts`: Commander command module for `whoami`. Resolves identity from explicit args, env vars, tmux metadata, and session-name fallback, then delegates to daemon `/api/whoami`. Exports: resolveIdentitySource, whoamiCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/adopt.ts`: Commander command module for `adopt` — materialize topology from a pod-aware RigSpec, then bind discovered live sessions according to `--bind` mappings. Exports: AdoptDeps, adoptCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/commands/import.js`, `packages/cli/src/daemon-lifecycle.js`.
| Module | Primary source roots |
|---|---|
| `architecture/daemon-core.md` | `packages/daemon/src/{startup.ts,server.ts,index.ts}`, `packages/daemon/src/db/migrations/`, `packages/cli/src/index.ts` |
| `architecture/adapters-and-runtimes.md` | `packages/daemon/src/domain/runtime-adapter.ts`, `packages/daemon/src/adapters/{claude-code-adapter,codex-runtime-adapter,terminal-adapter}.ts`, `packages/daemon/src/domain/{native-resume-probe,resume-metadata-refresher,codex-thread-id}.ts` |
| `architecture/coordination-primitive.md` | `packages/daemon/src/domain/{stream-store,queue-repository,queue-transition-log,hot-potato-enforcer,inbox-handler,outbox-handler}.ts`, `packages/daemon/src/routes/{stream,queue}.ts` |
| `architecture/workflow-runtime.md` | `packages/daemon/src/domain/{workflow-projector,workflow-runtime,workflow-instance-store,workflow-spec-cache,workflow-step-trail-log,workflow-validator}.ts`, `packages/daemon/src/domain/policies/workflow-keepalive.ts`, `packages/daemon/src/routes/workflow.ts` |
| `architecture/mission-control.md` | `packages/daemon/src/domain/mission-control/`, `packages/daemon/src/middleware/auth-bearer-token.ts`, `packages/daemon/src/routes/mission-control.ts`, `packages/daemon/src/db/migrations/037_mission_control_actions.ts` |
| `architecture/agent-spec-and-startup.md` | `packages/daemon/src/domain/{agent-manifest,rigspec-schema,profile-resolver,startup-orchestrator,whoami-service,claim-service}.ts`, `packages/daemon/src/routes/{rigspec,whoami}.ts` |
| `architecture/lifecycle-snapshot-restore.md` | `packages/daemon/src/domain/{restore-orchestrator,snapshot-capture,snapshot-repository,checkpoint-store}.ts`, `packages/daemon/src/routes/restore-check.ts`, `packages/cli/src/commands/restore-packet.ts` |
| `architecture/transport-and-transcripts.md` | `packages/daemon/src/domain/{session-transport,transcript-store,history-query,ask-service,chat-repository}.ts`, `packages/daemon/src/routes/{transport,transcripts,ask,chat}.ts`, `packages/cli/src/mcp-server.ts` |
| `architecture/workspace-primitive.md` | `packages/daemon/src/domain/workspace/`, `packages/cli/src/commands/config-init-workspace.ts`, `packages/daemon/src/db/migrations/{038,039}*`, `packages/ui/src/routes.tsx` |
| `architecture/content-surfaces.md` | `packages/daemon/src/domain/{files,progress,steering}*`, `packages/daemon/src/routes/{files,progress,steering}.ts`, `packages/ui/src/routes.tsx` |
| `architecture/plugin-agent-image-context-pack.md` | `packages/daemon/src/domain/plugin-discovery-service.ts`, `packages/daemon/src/domain/{agent-images,context-packs}/`, `packages/daemon/src/domain/claude-compaction-enforcer.ts` |
| `architecture/packaging-bootstrap-bundles.md` | `packages/daemon/src/domain/{pod-bundle-assembler,bootstrap-orchestrator,bundle-*,package-*,install-*}.ts`, `packages/daemon/src/routes/{bundles,up}.ts` |
| `architecture/architecture-rules-and-event-system.md` | `packages/daemon/src/domain/types.ts` (RigEvent union), `packages/daemon/src/routes/{stream,queue}.ts` (SSE watch), `packages/daemon/src/server.ts` (`/api/events`) |
| `ui/shell-and-routing.md` | `packages/ui/src/routes.tsx`, `packages/ui/src/components/AppShell.tsx` |
| `ui/topology.md` | `packages/ui/src/components/topology/`, `packages/ui/src/lib/{graph,hybrid,multi-rig}-layout.ts` |
| `ui/project-and-for-you.md` | `packages/ui/src/routes.tsx`, `packages/ui/src/components/dashboard/vellum/` |
| `ui/library-specs-and-design-system.md` | `packages/ui/src/components/specs/`, `packages/daemon/src/domain/{spec-review-service,spec-library-service}.ts`, `../DESIGN.md` (pointer) |
| `cli-reference.md` | `packages/cli/src/index.ts`, `packages/cli/src/commands/*` |
### Commands: Post-North-Star Additions
- `packages/cli/src/commands/send.ts`: Commander command module for `send` — send message to agent terminal via reliable tmux two-step. Supports `--verify` and `--force`. Exports: sendCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/capture.ts`: Commander command module for `capture` — capture agent pane content. Supports `--lines N` and `--json`. Exports: captureCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/broadcast.ts`: Commander command module for `broadcast` — send to all agents in a rig or pod. Reports per-session delivery status. Exports: broadcastCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/transcript.ts`: Commander command module for `transcript` — composable transcript access via `--tail N` and `--grep "pattern"`. Exports: transcriptCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/stream.ts`: Commander command module for `rig stream` (PL-004 Phase A) — coordination L1 intake stream. Subcommands: `emit`, `list`, `show`, `archive`. Speaks only to the daemon HTTP API; does not touch POC filesystem state. Exports: streamCommand, StreamDeps. Related: `packages/cli/src/client.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/queue.ts`: Commander command module for `rig queue` (PL-004 Phase A) — coordination L3 queue plus inbox/outbox. Subcommands: `create`, `claim`, `unclaim`, `update`, `handoff`, `fallback`, `show`, `transitions`, `list`, `overdue`, `inbox-drop`, `inbox-absorb`, `inbox-deny`, `inbox-pending`, `outbox-record`, `outbox-list`. Hot-potato strict-rejection enforced at daemon. Exports: queueCommand, QueueDeps. Related: `packages/cli/src/client.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/config.ts`: Commander command module for `config` — read/write/reset config keys. Supports `--json`. Exports: configCommand. Related: `packages/cli/src/config-store.js`.
- `packages/cli/src/commands/preflight.ts`: Commander command module for `preflight` — system readiness checks. Supports `--json`. Exports: preflightCommand. Related: `packages/cli/src/system-preflight.js`, `packages/cli/src/config-store.js`.
- `packages/cli/src/commands/ask.ts`: Commander command module for `ask` — context evidence pack over transcripts + topology + chat. Supports `--json`. Exports: askCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/daemon-lifecycle.js`.
- `packages/cli/src/commands/chatroom.ts`: Commander command module for `chatroom` — durable group chat with subcommands `send`, `watch`, `history`, and `topic`. Exports: chatroomCommand. Related: `packages/cli/src/client.js`, `packages/cli/src/daemon-lifecycle.js`.
### CLI Infrastructure: Post-North-Star Additions
- `packages/cli/src/config-store.ts`: Config file management at `~/.openrig/config.json` with legacy fallback from `~/.rigged/config.json`. 5 locked keys with env var overrides. Precedence: CLI flag > env var > config file > default. Exports: ConfigStore and config helpers. Related: none (filesystem-only).
- `packages/cli/src/system-preflight.ts`: System readiness checks: Node.js version, tmux availability, writable directories, port availability. Every error follows the 3-part pattern (what + why + fix). Exports: SystemPreflight, PreflightCheck, PreflightResult. Related: `packages/cli/src/config-store.js`, `packages/cli/src/daemon-lifecycle.js`.
## UI
### App Entry And Routing
- `packages/ui/src/App.tsx`: Thin app wrapper that renders the TanStack Router provider. Exports: App. Related: `packages/ui/src/routes.js`.
- `packages/ui/src/globals.css`: Tailwind/theme tokens and global UI styling. Exports: none. Related: none.
- `packages/ui/src/main.tsx`: Bootstraps the React app, fonts, and global styles. Exports: none. Related: `packages/ui/src/App.js`, `packages/ui/src/globals.css`.
- `packages/ui/src/routes.tsx`: Declares the explorer-first route tree and root shell composition, including specs review/library routes, discovery/specs drawer bridges, and live-node full-details route `/rigs/$rigId/nodes/$logicalId`. Exports: router. Related: `packages/ui/src/components/AppShell.js`, `packages/ui/src/components/BootstrapWizard.js`, `packages/ui/src/components/BundleInspector.js`, `packages/ui/src/components/BundleInstallFlow.js`, +13 more.
### Components: Application Surfaces
- `packages/ui/src/components/ActivityFeed.tsx`: Rolling global activity/event overlay driven by SSE. Exports: ActivityFeed. Related: `packages/ui/src/hooks/useActivityFeed.js`.
- `packages/ui/src/components/AppShell.tsx`: Persistent explorer/workspace/drawer shell. Owns drawer selection context, discovery placement state, specs workspace provider, explorer visibility, and top-level discovery/specs/system toggles. Exports: DrawerSelectionContext, DrawerSelectionContextValue, DiscoveryPlacementContext, DiscoveryPlacementContextValue, ExplorerVisibilityContext, ExplorerVisibilityContextValue, NodeSelectionContext, AppShell, useDiscoveryPlacement, useDrawerSelection, useExplorerVisibility, useNodeSelection. Related: `packages/ui/src/components/ActivityFeed.js`, `packages/ui/src/components/Explorer.js`, `packages/ui/src/components/SharedDetailDrawer.js`, `packages/ui/src/components/SpecsWorkspace.js`, `packages/ui/src/hooks/useActivityFeed.js`, `packages/ui/src/hooks/useGlobalEvents.js`, `packages/ui/src/hooks/useRigSummary.js`.
- `packages/ui/src/components/BootstrapWizard.tsx`: Multi-step bootstrap planning/apply flow UI for both rig specs and `.rigbundle` archives. Includes the spec-or-bundle entry field and bundle-inspector handoff link. Exports: BootstrapWizard. Related: `packages/ui/src/components/RequirementsPanel.js`, `packages/ui/src/hooks/useBootstrap.js`.
- `packages/ui/src/components/BundleInspector.tsx`: Bundle inspection screen for manifest and integrity results. Renders `agents[]` plus schema-version badge for v2 pod bundles and legacy package content for v1 bundles. Exports: BundleInspector. Related: `packages/ui/src/hooks/useBundles.js`.
- `packages/ui/src/components/BundleInstallFlow.tsx`: Bundle install plan/apply screen. Labels the install as pod-aware or legacy from bootstrap `resolve_spec.detail.source`. Exports: BundleInstallFlow. Related: `packages/ui/src/hooks/useBundles.js`.
- `packages/ui/src/components/Dashboard.tsx`: Home dashboard that renders rig cards and high-level rig actions. Exports: Dashboard. Related: `packages/ui/src/components/RigCard.js`, `packages/ui/src/hooks/mutations.js`, `packages/ui/src/hooks/usePsEntries.js`, `packages/ui/src/hooks/useRigSummary.js`.
- `packages/ui/src/components/DiscoveryOverlay.tsx`: Session discovery and claim surface. Exports: DiscoveryOverlay. Related: `packages/ui/src/hooks/useDiscovery.js`, `packages/ui/src/hooks/useRigSummary.js`.
- `packages/ui/src/components/ImportFlow.tsx`: RigSpec validate/preflight/instantiate flow UI. Supports pod-aware `X-Rig-Root`, structured preflight diagnostics, and rebooted RigSpec terminology. Exports: ImportFlow. Related: `packages/ui/src/hooks/mutations.js`.
- `packages/ui/src/components/AgentSpecValidateFlow.tsx`: Standalone validate surface for one AgentSpec YAML, backed by `/api/agents/validate`. Exports: AgentSpecValidateFlow. Related: none.
- `packages/ui/src/components/WorkflowScaffold.tsx`: Shared page-shell primitives for multi-step/spec-review flows (`WorkflowHeader`, `WorkflowStepIndicator`, `WorkflowSection`, summary cards, code preview). Exports: WorkflowHeader, WorkflowStepIndicator, WorkflowSection, WorkflowSummaryGrid, WorkflowSummaryCard, WorkflowCodePreview. Related: none.
- `packages/ui/src/components/WorkspacePage.tsx`: Shared center-workspace page shell used by specs/library/live-details surfaces. Exports: WorkspacePage. Related: none.
- `packages/ui/src/components/SpecsWorkspace.tsx`: Local persisted workspace state for spec authoring/review tasks, drafts, and active task list. Exports: SpecsDraft, SpecsTask, SPECS_WORKSPACE_STORAGE_KEYS, SpecsWorkspaceProvider, useSpecsWorkspace. Related: none.
- `packages/ui/src/components/PackageDetail.tsx`: Package detail screen with install history, journal, and rollback actions. Exports: PackageDetail. Related: `packages/ui/src/hooks/usePackageDetail.js`.
- `packages/ui/src/components/PackageInstallFlow.tsx`: Legacy package validate/configure/plan/apply flow UI, explicitly labeled `(Legacy)`. Exports: PackageInstallFlow. Related: none.
- `packages/ui/src/components/PackageList.tsx`: Legacy package summary list/grid screen presented under the rebooted `SPECS` navigation, with an empty-state handoff into RigSpec import. Exports: PackageList. Related: `packages/ui/src/hooks/usePackages.js`.
- `packages/ui/src/components/RequirementsPanel.tsx`: Visualizes requirement probe results inside bootstrap flows. Exports: RequirementResult, RequirementsPanel. Related: none.
- `packages/ui/src/components/RigCard.tsx`: Dashboard card for one rig with counts, status, and primary actions. Exports: RigCard, RigSummary. Related: `packages/ui/src/hooks/useCountUp.js`, `packages/ui/src/hooks/usePsEntries.js`.
- `packages/ui/src/components/RigGraph.tsx`: Rig graph view that renders topology, discovery overlays, and focus interactions. Exports: RigGraph. Related: `packages/ui/src/components/RigNode.js`, `packages/ui/src/hooks/useDiscovery.js`, `packages/ui/src/hooks/useRigEvents.js`, `packages/ui/src/hooks/useRigGraph.js`.
- `packages/ui/src/components/RigNode.tsx`: Custom graph-node renderer for React Flow topology cards. Exports: RigNode. Related: none.
- `packages/ui/src/components/Sidebar.tsx`: App navigation sidebar. Exports: Sidebar. Related: none.
- `packages/ui/src/components/SnapshotPanel.tsx`: Snapshot list/create/restore panel shown beside rig graphs. Exports: SnapshotPanel. Related: `packages/ui/src/hooks/mutations.js`, `packages/ui/src/hooks/useSnapshots.js`.
### Components: North Star + Post-North-Star Additions
- `packages/ui/src/components/Explorer.tsx`: Hierarchical tree navigator — rigs → pods → agents with status indicators. Primary navigation surface. Click rig loads graph, click node opens detail drawer. Exports: Explorer. Related: `packages/ui/src/hooks/useRigSummary.js`, `packages/ui/src/hooks/usePsEntries.js`, `packages/ui/src/hooks/useNodeInventory.js`.
- `packages/ui/src/components/SharedDetailDrawer.tsx`: Unified drawer surface keyed by `DrawerSelection`. Routes to rig, node, system, discovery, or specs panels without leaving the current workspace. Exports: DrawerSelection, SharedDetailDrawer. Related: `packages/ui/src/components/DiscoveryPanel.js`, `packages/ui/src/components/NodeDetailPanel.js`, `packages/ui/src/components/RigDetailPanel.js`, `packages/ui/src/components/SpecsPanel.js`, `packages/ui/src/components/SystemPanel.js`.
- `packages/ui/src/components/RigDetailPanel.tsx`: Rig detail: identity, node summary, snapshots/actions, and runtime drawer tabs (`Info`, conditional `Env`, `Chat Room`). Exports: RigDetailPanel. Related: `packages/ui/src/hooks/useRigSummary.js`, `packages/ui/src/hooks/useSnapshots.js`, `packages/ui/src/hooks/useNodeInventory.js`.
- `packages/ui/src/components/RigEnvPanel.tsx`: Runtime env surface for service-backed rigs. Shows overall env state, per-service health, health gates, surfaces, logs, and teardown action. Exports: RigEnvPanel. Related: `packages/ui/src/hooks/useRigEnv.js`.
- `packages/ui/src/components/NodeDetailPanel.tsx`: Runtime-first node drawer. Shows rig/session/runtime identity, peers, directional edges, transcript helpers, compact spec summary, status, actions (tmux/cmux/resume/full-details), startup files, and recent events. Exports: NodeDetailPanel. Related: `packages/ui/src/components/LiveIdentityDisplay.js`, `packages/ui/src/hooks/useNodeDetail.js`, `packages/ui/src/lib/copy-text.js`, `packages/ui/src/lib/display-name.js`.
- `packages/ui/src/components/NodeDetailPlaceholder.tsx`: Empty state for node detail when no node is selected. Exports: NodeDetailPlaceholder. Related: none.
- `packages/ui/src/components/DiscoveryPanel.tsx`: Drawer-native discovery/adoption surface. Supports scan/list, draft-rig generation, placement-first bind/adopt, and pod/member targeting inside the shared drawer. Exports: DiscoveryPlacementTarget, DiscoveryPanel. Related: `packages/ui/src/hooks/useDiscovery.js`.
- `packages/ui/src/components/SpecsPanel.tsx`: Drawer-native spec library and authoring launcher. Presents a unified library list with `All / Apps / Rigs / Agents`, type/stability badges, richer managed-app rows, and review-route handoff. Exports: SpecsPanel. Related: `packages/ui/src/components/SpecsWorkspace.js`, `packages/ui/src/hooks/useSpecLibrary.js`.
- `packages/ui/src/components/RigChatPanel.tsx`: Chat room tab in rig drawer — send messages, watch live stream, view history. Exports: RigChatPanel. Related: `packages/ui/src/hooks/useRigChat.js`.
- `packages/ui/src/components/LiveIdentityDisplay.tsx`: Reusable runtime-identity subsection for peers, edges, transcript helpers, and compact spec summary. Used by the node drawer and full-details route. Exports: LiveIdentityDisplay. Related: none.
- `packages/ui/src/components/LiveNodeDetails.tsx`: Explicit center-workspace route for deep inspection of one live node. Composes runtime identity plus reusable spec display components. Exports: LiveNodeDetails. Related: `packages/ui/src/components/AgentSpecDisplay.js`, `packages/ui/src/components/LiveIdentityDisplay.js`, `packages/ui/src/hooks/useNodeDetail.js`.
- `packages/ui/src/components/RigSpecDisplay.tsx`: Canonical RigSpec display primitive used by draft review, library review, and live/workspace inspection flows. Supports a library-only managed-app Environment tab with compose preview, health gates, and surfaces. Exports: RigSpecDisplay. Related: `packages/ui/src/components/SpecTopologyPreview.js`.
- `packages/ui/src/components/AgentSpecDisplay.tsx`: Canonical AgentSpec display primitive used by preview, library, and live-details flows. Exports: AgentSpecDisplay. Related: none.
- `packages/ui/src/components/RigSpecReview.tsx`: Route-level rig review page that consumes `RigSpecDisplay` and specs workspace state. Exports: RigSpecReview. Related: `packages/ui/src/components/RigSpecDisplay.js`, `packages/ui/src/components/SpecsWorkspace.js`, `packages/ui/src/hooks/useSpecReview.js`.
- `packages/ui/src/components/AgentSpecReview.tsx`: Route-level agent review page that consumes `AgentSpecDisplay` and specs workspace state. Exports: AgentSpecReview. Related: `packages/ui/src/components/AgentSpecDisplay.js`, `packages/ui/src/components/SpecsWorkspace.js`, `packages/ui/src/hooks/useSpecReview.js`.
- `packages/ui/src/components/LibraryReview.tsx`: Library-entry review page that renders reusable display components plus provenance/source-state. Service-backed rigs surface managed-app copy, specialist identity, setup-prompt copy, and env-aware review details. Exports: LibraryReview. Related: `packages/ui/src/components/AgentSpecDisplay.js`, `packages/ui/src/components/RigSpecDisplay.js`, `packages/ui/src/hooks/useSpecLibrary.js`.
- `packages/ui/src/components/SpecTopologyPreview.tsx`: Lightweight topology preview for structured rig review models. Exports: SpecTopologyPreview. Related: none.
- `packages/ui/src/components/SystemPanel.tsx`: Drawer surface for system-wide event log/status tabs. Replaces the old status-bar role with a richer right-drawer system surface. Exports: SystemPanel. Related: `packages/ui/src/hooks/useActivityFeed.js`.
- `packages/ui/src/components/WorkspaceHome.tsx`: Landing page when no rig is selected. Entry point for explorer-first workflow. Exports: WorkspaceHome. Related: `packages/ui/src/components/AppShell.js`.
### Components: UI Primitives
- `packages/ui/src/components/ui/alert.tsx`: Wrapped/customized shadcn-style UI primitive for alert. Exports: Alert, AlertDescription, AlertTitle. Related: none.
- `packages/ui/src/components/ui/badge.tsx`: Wrapped/customized shadcn-style UI primitive for badge. Exports: Badge, BadgeProps, badgeVariants. Related: none.
- `packages/ui/src/components/ui/button.tsx`: Wrapped/customized shadcn-style UI primitive for button. Exports: Button, ButtonProps, buttonVariants. Related: none.
- `packages/ui/src/components/ui/card.tsx`: Wrapped/customized shadcn-style UI primitive for card. Exports: Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle. Related: none.
- `packages/ui/src/components/ui/dialog.tsx`: Wrapped/customized shadcn-style UI primitive for dialog. Exports: Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger. Related: none.
- `packages/ui/src/components/ui/input.tsx`: Wrapped/customized shadcn-style UI primitive for input. Exports: Input. Related: none.
- `packages/ui/src/components/ui/separator.tsx`: Wrapped/customized shadcn-style UI primitive for separator. Exports: Separator. Related: none.
- `packages/ui/src/components/ui/table.tsx`: Wrapped/customized shadcn-style UI primitive for table. Exports: Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow. Related: none.
- `packages/ui/src/components/ui/tabs.tsx`: Wrapped/customized shadcn-style UI primitive for tabs. Exports: Tabs, TabsContent, TabsList, TabsTrigger. Related: none.
- `packages/ui/src/components/ui/textarea.tsx`: Wrapped/customized shadcn-style UI primitive for textarea. Exports: Textarea. Related: none.
- `packages/ui/src/components/ui/tooltip.tsx`: Wrapped/customized shadcn-style UI primitive for tooltip. Exports: Tooltip, TooltipContent, TooltipProvider, TooltipTrigger. Related: none.
### Hooks
- `packages/ui/src/hooks/mutations.ts`: Shared mutation hooks for rig import, teardown, snapshot creation, and restore. `useImportRig` supports optional `rigRoot` and sends `X-Rig-Root` for pod-aware import. Exports: ImportError, useCreateSnapshot, useImportRig, useRestoreSnapshot, useTeardownRig. Related: none.
- `packages/ui/src/hooks/useActivityFeed.ts`: SSE-backed activity-feed model and event-formatting helpers. Exports: ActivityEvent, UseActivityFeedResult, eventColor, eventRoute, eventSummary, formatRelativeTime, useActivityFeed. Related: none.
- `packages/ui/src/hooks/useBootstrap.ts`: Bootstrap plan/apply hooks. Exports: BootstrapApplyResult, BootstrapPlanResult, useBootstrapApply, useBootstrapPlan. Related: none.
- `packages/ui/src/hooks/useBundles.ts`: Bundle inspect/install hooks. Typed for v2 inspect responses (`schemaVersion`, `agents`, integrity) and install-stage `detail.source` labeling. Exports: BundleInstallResult, InspectResult, useBundleInspect, useBundleInstall. Related: none.
- `packages/ui/src/hooks/useCountUp.ts`: Small animation helper for count-up telemetry. Exports: useCountUp. Related: none.
- `packages/ui/src/hooks/useDiscovery.ts`: Discovery polling plus claim/bind/adopt mutations and draft-rig generation helpers. Exports: DiscoveredSession, useAdoptSession, useBindSession, useClaimSession, useDiscoveredSessions, useDiscoveredSessionsConditional, useDiscoveryPoll, useDiscoveryScan. Related: none.
- `packages/ui/src/hooks/usePackageDetail.ts`: Package detail, journal, history, and rollback hooks. Exports: InstallSummary, JournalEntry, PackageInfo, useInstallHistory, useJournalEntries, usePackageInfo, useRollbackInstall. Related: none.
- `packages/ui/src/hooks/usePackages.ts`: Package summary list hook. Exports: PackageSummary, usePackages. Related: none.
- `packages/ui/src/hooks/usePsEntries.ts`: `/api/ps` summary hook. Exports: PsEntry, usePsEntries. Related: none.
- `packages/ui/src/hooks/useRigEvents.ts`: Rig-scoped SSE subscription and invalidation hook. Exports: UseRigEventsResult, useRigEvents. Related: none.
- `packages/ui/src/hooks/useRigGraph.ts`: Rig graph fetch/transformation hook. Exports: useRigGraph. Related: none.
- `packages/ui/src/hooks/useRigSummary.ts`: Rig summary list hook used across dashboard and shell surfaces. Includes `hasServices` so runtime/UI can gate managed-app env surfaces. Exports: RigSummary, useRigSummary. Related: none.
- `packages/ui/src/hooks/useSnapshots.ts`: Snapshot list hook for one rig. Exports: Snapshot, useSnapshots. Related: none.
### Hooks: North Star + Post-North-Star Additions
- `packages/ui/src/hooks/useNodeInventory.ts`: Fetches node inventory for a rig from the canonical `GET /api/rigs/:rigId/nodes` endpoint. Exports: useNodeInventory. Related: none.
- `packages/ui/src/hooks/useNodeDetail.ts`: Fetches extended node detail from `GET /api/rigs/:rigId/nodes/:logicalId`, including peers, edges, transcript helpers, and compact spec summary for the adopted-parity/live-identity drawer. Exports: NodeDetailData, useNodeDetail. Related: none.
- `packages/ui/src/hooks/useRigEnv.ts`: Fetches `GET /api/rigs/:rigId/env` for service-backed rig status, surfaces, and receipt data, with runtime-friendly refetch behavior. Exports: RigEnvData, useRigEnv. Related: none.
- `packages/ui/src/hooks/useRigChat.ts`: Chat send/watch/history hooks for the rig chat panel. Exports: useRigChat. Related: none.
- `packages/ui/src/hooks/useGlobalEvents.ts`: Global SSE subscription for explorer status updates. Exports: useGlobalEvents. Related: none.
- `packages/ui/src/hooks/useSpecLibrary.ts`: Spec library list and library-review fetch hooks. Typed for `sourceState: "library_item"` review results and `hasServices`-aware managed-app classification. Exports: SpecLibraryEntry, LibraryReview, LibraryRigReview, LibraryAgentReview, useSpecLibrary, useLibraryReview. Related: none.
- `packages/ui/src/hooks/useSpecReview.ts`: Structured spec-review hooks for raw YAML preview (`rig` and `agent`) over `/api/specs/review/*`. The rig review type now carries managed-app services metadata and compose preview. Exports: SpecGraphData, RigSpecReview, AgentSpecReview, useRigSpecReview, useAgentSpecReview. Related: none.
### Lib Utilities
- `packages/ui/src/lib/edge-styles.ts`: Edge-style resolver for graph links. Exports: EdgeStyleResult, getEdgeStyle. Related: none.
- `packages/ui/src/lib/graph-layout.ts`: Tree-layout helper for rig graph positioning. Exports: applyTreeLayout. Related: none.
- `packages/ui/src/lib/instantiate-status-colors.ts`: Color-class lookup for instantiation states. Exports: getInstantiateStatusColorClass. Related: none.
- `packages/ui/src/lib/query-client.ts`: Shared TanStack Query client singleton. Exports: queryClient. Related: none.
- `packages/ui/src/lib/restore-status-colors.ts`: Color-class lookup for restore states. Exports: getRestoreStatusColorClass. Related: none.
- `packages/ui/src/lib/status-colors.ts`: Generic rig/session status color mapping. Exports: getStatusColorClass. Related: none.
- `packages/ui/src/lib/utils.ts`: Shared UI utility helpers, currently `cn` class merging. Exports: cn. Related: none.
### Lib Utilities: North Star + Post-North-Star Additions
- `packages/ui/src/lib/display-id.ts`: Short ULID display utility — uses ULID tail (not head) for better uniqueness in same-view contexts. UI-only, no backend changes. Exports: shortId. Related: none.
- `packages/ui/src/lib/display-name.ts`: Pod name extraction from qualified logical IDs (e.g., "dev1" from "dev1.impl"). Exports: displayPodName, inferPodName. Related: none.
- `packages/ui/src/lib/build-setup-prompt.ts`: Managed-app setup-prompt generator used by library review copy surfaces. Exports: buildSetupPrompt. Related: none.
- `packages/ui/src/lib/copy-text.ts`: Clipboard copy utility for the "Copy tmux attach" and "Copy resume command" buttons. Exports: copyText. Related: none.
> No per-file flat dump. File-level detail belongs in the code; this codemap
> points at the source root and the module that explains it. The per-file
> index anti-pattern (old codemap) is retired, not relocated.
+65
View File
@@ -0,0 +1,65 @@
---
kind: as-built
title: As-Built Frontmatter — Pointer + As-Built-Unique Field
status: active
topics: [knowledge-and-context, frontmatter]
domains: [engineering-advisor, operating-advisor]
applies-when: |
Authoring or updating a doc under docs/as-built/. Tells you which
frontmatter convention governs these docs and the one field that is
unique to as-built docs.
siblings: [README.md]
prerequisite-reads: [README.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# As-Built Frontmatter — Pointer + As-Built-Unique Field
Every doc under `docs/as-built/` carries YAML frontmatter. The shape is
**not** defined here. It is the substrate-wide context-frontmatter
convention; this doc only points to it and documents the one field that
is unique to as-built docs.
## Canonical convention (do not duplicate — read it)
`openrig-work/conventions/frontmatter-for-context/README.md` is the
authoritative schema: required floor (`kind` + `title` + `status` +
`applies-when`), recommended fields (`topics`, `domains`, `siblings`,
`prerequisite-reads`), and the controlled vocabularies for `kind:`,
`topics:`, and `domains:`. Author against that convention. This doc adds
nothing to it except the field below.
## `kind: as-built`
These docs use `kind: as-built`. That value is in the convention's
controlled `kind:` vocabulary (first row of its "Controlled vocabulary —
`kind:`" table, source `openrig/docs/as-built/*`). Using it is conformant,
not an extension.
## `last-verified-against-source: <sha>` (as-built-unique)
As-built docs describe the running system. They drift when the source
drifts. The as-built-unique field records the exact commit the doc was
last verified against:
```yaml
last-verified-against-source: 7eaf524c
```
- **Value:** the short SHA of the source HEAD the doc was verified
against at its last edit. Pair with `last-updated: <iso-date>`.
- **Why it is here and not in the convention:** the convention is
substrate-wide; most context docs do not track a source SHA. This
field is meaningful only for docs that mirror code, i.e. as-built
docs. It is the per-module drift-detection anchor the
context-architecture-v1 mission dogfoods on its own production.
- **Discipline:** when re-verifying a module against a newer HEAD,
bump this field (and `last-updated`) and carry an inline
`re-confirmed <file:line> @HEAD` annotation on each load-bearing
claim that was re-checked.
## See also
- `openrig-work/conventions/frontmatter-for-context/README.md` — the canonical schema
- `README.md` — the as-built corpus map of territory
+36 -230
View File
@@ -1,238 +1,44 @@
# OpenRig UI As-Built
---
kind: as-built
title: ui.md — Reorganized into the Modular As-Built Tree (Redirect Stub)
status: superseded
topics: [knowledge-and-context]
domains: [engineering-advisor, operating-advisor, product-advisor]
applies-when: |
You followed an old reference to docs/as-built/ui.md. The monolith was
reorganized (slice-08, context-architecture-v1) into the ui/ module folder.
Go to README.md (map of territory) or codemap.md (use-case lookup), then the
named ui/ module.
siblings: [README.md, codemap.md, architecture.md]
prerequisite-reads: []
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
This document describes the current UI architecture and component system. The
brand/design rules live in `docs/DESIGN.md`; this file focuses on how the shipped UI
is assembled.
# ui.md was reorganized into the modular as-built tree
## Package Shape
This single-file UI monolith was split into a folder of independently-loadable,
frontmatter-tagged thematic modules (slice-08, `context-architecture-v1`). The
canonical as-built description of the shipped operator UI now lives in `ui/`.
This stub is a forwarding pointer so old references still resolve.
UI package: `packages/ui`
**Start here:**
Primary implementation areas:
- [`./README.md`](./README.md) — the map of territory and full module index.
- [`./codemap.md`](./codemap.md) — navigation index: use-case lookup table and
source-root pointers. Use this when you know *what* you need but not *which*
module.
- `src/routes.tsx` - TanStack Router route tree
- `src/components/AppShell.tsx` - global shell, rail, Explorer, drawer, preview stack
- `src/components/ui/` - reusable vellum and base UI primitives
- `src/components/graphics/` - runtime, tool, and actor marks
- `src/components/topology/` - host/rig/pod/seat graph, table, terminal, activity
- `src/components/project/` - workspace/mission/slice observability and project metadata primitives
- `src/components/for-you/` - attention feed and actionable queue cards
- `src/components/specs/` - Library and skill file viewing
- `src/components/preview/` - terminal/session preview panes
- `src/hooks/` - route data hooks and event consumption
- `src/lib/` - classifiers, formatters, layout helpers, brand helpers, activity logic
## Where the major content went
## Shell Model
The UI content is now the **4 modules under `ui/`**:
`AppShell` wraps every route with:
| Module | What moved here |
|---|---|
| [`ui/shell-and-routing.md`](ui/shell-and-routing.md) | Package shape, the `AppShell` shell model (rail / Explorer / center workspace / drawer / preview stack), the route tree, design primitives, the shared detail-drawer/viewer system, event/activity consumption. |
| [`ui/topology.md`](ui/topology.md) | The topology surface — host hybrid graph, table/terminal views, the activity-ring / hot-potato visual language, terminal-preview popovers, navigation/overlay contracts. |
| [`ui/project-and-for-you.md`](ui/project-and-for-you.md) | The operator destination surfaces — Project observability (workspace/mission/slice scope tabs), the For-You attention feed (5-card classifier + queue actions), the Dashboard landing on the vellum brand system. |
| [`ui/library-specs-and-design-system.md`](ui/library-specs-and-design-system.md) | The Library (`/specs`) UI — specs/applications/skills surfaces, the graphics layer, the current design constraints, and the design-system pointer to `../DESIGN.md`. |
- Desktop rail
- Route-aware Explorer sidebar
- Center workspace
- Shared detail drawer
- Preview stack
- Topology overlay state provider
- Shared drawer selection context
- Shared discovery placement context
The rail destinations are:
- Dashboard: `/`
- Topology: `/topology`
- For You: `/for-you`
- Project: `/project`
- Library: `/specs`
- Settings: `/settings`
- Advisor and Operator placeholders/settings links
The Explorer is contextual. It changes its tree based on the current destination
rather than behaving as a generic file browser.
## Route Model
Main routes:
- `/` - Dashboard
- `/topology` - host topology scope
- `/topology/rig/$rigId` - rig scope
- `/topology/pod/$rigId/$podName` - pod scope
- `/topology/seat/$rigId/$logicalId` - seat scope with live node details
- `/for-you` - attention feed
- `/project` - workspace project scope
- `/project/mission/$missionId` - mission scope
- `/project/slice/$sliceId` - slice scope
- `/specs` - Library
- `/specs/applications` - application section
- `/specs/skills/$skillToken` - skill viewer defaulting to `skill.md`
- `/specs/skills/$skillToken/file/$fileToken` - specific skill file viewer
- `/settings` - settings center
- `/search` - audit/history view
- `/lab/project-graphics-preview` - graphics preview lab route
Legacy routes remain for compatibility where needed, including package flows,
bootstrap flows, validation flows, and `/rigs/$rigId`.
## Design Primitives
The UI moved from route-specific one-off panels toward reusable primitives.
Base primitives:
- `VellumCard` - paper card with optional dark header, hard shadow, registration marks
- `VellumSheet` - side sheet/drawer with vellum-heavy surface and registration marks
- `RegistrationMarks` - corner registration marks
- `StatusPip` - semantic status only
- `SectionHeader`, `EmptyState`, `Button`, `Tabs`, `Table`, and form controls
Graphics primitives:
- `RuntimeMark` and `RuntimeBadge`
- `ToolMark` and `ToolBadge`
- `ActorMark` and `OperatorMoodMark`
- Runtime and tool normalization in `runtime-brand.ts` and `tool-brand.ts`
Project metadata primitives:
- `EventBadge`
- `QueueStateBadge`
- `TagPill`
- `ActorChip`
- `DateChip`
- `FlowChips`
- `ProofThumbnailGrid`
- `ProofPacketHeader`
These primitives centralize visual language for runtime identity, queue state,
actor flow, event labels, dates, tags, and proof images.
## Topology
Topology is a scoped workspace with graph, table, and terminal views.
Current topology pieces:
- `HostMultiRigGraph` renders the host-level hybrid React Flow graph.
- `HybridAgentNode` renders compact agent cards with runtime badges, context
percentage, token totals, activity state, terminal preview, and CMUX actions.
- `HybridPodGroupNode` renders soft dashed pod frames.
- `RigGroupNode` renders soft rig frames with registration marks and aggregate
activity.
- `ActivityRing` and card activity classes show active, needs-input, and blocked
states.
- `HotPotatoEdge` visualizes directional queue movement through the graph.
- `TopologyTableView` mirrors topology data in a dense table.
- `TopologyTerminalView` shows terminal-oriented topology state.
- `TerminalPreviewPopover` provides black-glass quick terminal preview above the
graph via a portal.
Important topology contracts:
- Graph/table/tree navigation resolves to seat URLs.
- Host-level graph uses cross-rig node ID prefixing.
- Expanded rig state is managed by `TopologyOverlayProvider`.
- Graph data is lazy-fetched for expanded rigs.
- Terminal preview actions are hover/focus visible.
- The terminal popover must escape React Flow stacking contexts and stay within
the viewport.
## Project Observability
Project is organized as a hierarchy:
- Workspace
- Mission
- Slice
The current route scope acts as a filter. Higher scopes show broader rollups;
lower scopes show more specific story, queue, proof, artifact, test, and topology
data.
Current project tabs:
- Story - narrative progress and queue body content
- Progress - status and activity rollup
- Artifacts - files, commits, proof, and outputs
- Tests - proof material, screenshots, and verification detail
- Queue - operational qitems with actions and drawer detail
- Topology - workflow/agent diagram where available
Project primitives translate raw queue and event data into readable badges,
chips, dates, flows, proof thumbnails, and action outcome panels.
## For You
For You is the attention-routing surface. It uses live event feed data plus queue
details to classify cards into:
- Action Required
- Approval
- Shipped
- Progress
- Observation
The card renderer prioritizes readable body content, proof thumbnails, actor
flow, friendly dates, and action affordances. Queue actions reuse existing
mission-control action endpoints.
## Library And Skills
`/specs` is the Library route. It contains specs, applications, context packs,
agent specs, agent images, and skills.
Skills are folder-based. The skill tree in Explorer treats each skill as a
folder. Clicking a skill opens a skill detail route that defaults to `skill.md`
case-insensitively. The skill detail page uses the existing `FileViewer` and
does not add a second in-page file browser; file navigation belongs in the
Explorer tree.
## Drawer And Viewer System
The shared detail drawer is used for transient focused detail:
- Queue item viewer
- File viewer
- Subspec preview
- Other detail selections
Drawer triggers carry root/path provenance so the viewer can fetch and render the
correct content. The drawer supports outside-click dismissal.
Image proof viewing is handled by `ProofImageViewer`, which respects the shell
layout and uses black-glass styling.
## Event And Activity Consumption
UI event consumption is centralized through shared event hooks so the app avoids
spawning duplicate SSE connections for related surfaces.
Current activity consumers include:
- For You feed hydration
- Topology activity rings and hot-potato movement
- Activity feed/system surfaces
- Rig event surfaces where appropriate
Reduced-motion preference is honored for pulse and packet animations.
## Graphics Layer
The graphics package is intentionally centralized:
- Runtime identity: Claude, Codex, Terminal, Unknown
- Tool identity: CMUX, tmux, VS Code, Terminal, file, markdown, config, code,
screenshot, proof, transcript, commit, folder, skill, video, trace
- Actor identity: human/operator, runtime agents, terminal fallback
The goal is to make dense operator surfaces scannable without adding more raw
metadata text.
## Current Design Constraints
- Use the shared primitives before creating new card styles.
- Keep vellum and black-glass separate.
- Keep status semantics separate from activity animation.
- Do not duplicate runtime/tool brand detection outside the central helpers.
- Do not add new daemon shape for UI polish unless the slice explicitly declares
and verifies that boundary.
- Do not make page-level content look like a raw terminal log unless the content
is actually terminal output.
The brand/design rules still live at `docs/DESIGN.md` (repo `docs/` root, by
design — see `ui/library-specs-and-design-system.md`).
@@ -0,0 +1,129 @@
---
kind: as-built
title: UI Library/Specs Surfaces + Design-System Pointer
status: active
topics: [specification-and-bundles, observability]
domains: [engineering-advisor, product-advisor]
applies-when: |
Need to know how the Library (`/specs`) UI is assembled — the spec/skills/
plugins surfaces, the spec-review + spec-library + live-identity flows that
feed it — or where the canonical visual/design-system spec lives.
siblings: [shell-and-routing.md]
prerequisite-reads: [../README.md, shell-and-routing.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# UI Library/Specs Surfaces + Design-System Pointer
The Library destination keeps `/specs` as the route and presents the product
label "Library": specs, applications, context packs, agent specs, agent
images, plugins, and skills.
> Verified against source at HEAD `7eaf524c`; package version **0.3.1**
> (slice-00 §1.1). Component/primitive names below are reconciled against
> `packages/ui/src/components/` at HEAD — NOT taken on trust from `ui.md`'s
> or `DESIGN.md`'s lists.
## 1. Library / specs surfaces
Components in `packages/ui/src/components/specs/` (re-confirmed at HEAD):
- `SpecsLibraryPage.tsx` — the `/specs` Library page (unified list:
All / Apps / Rigs / Agents; service-backed entries render as `APP`).
- `SpecsTable.tsx`, `SpecsTreeView.tsx` — list + Explorer tree.
- `SkillsIndexPage.tsx`, `SkillDetailPage.tsx` — folder-based skills.
The skill tree treats each skill as a folder; clicking a skill opens a
detail route defaulting to `skill.md` case-insensitively, rendered via the
shared `FileViewer` in the center workspace (no second in-page file
browser — file navigation belongs in the Explorer tree).
- `PluginsIndexPage.tsx`, `PluginDetailPage.tsx`, `AgentPluginsList.tsx` —
the plugin surfaces.
> Drift-note (slice-00 0.3.0-GT seam a): the plugin primitive is a **0.3.1**
> feature (git-ancestry proven; absent at `v0.3.0`, present at `v0.3.1`). Do
> NOT back-attribute the `/specs/plugins`, `/plugins/$pluginId` routes or
> these plugin components to 0.3.0. `ui.md` (which predates 0.3.x) has **no
> narrative for plugins at all** — these surfaces are authored from source +
> the slice-00 0.3.0-GT seam, not migrated.
## 2. Spec review / library / live-identity flows
These daemon-backed flows feed the Library UI (`architecture.md` §6
"Spec review and spec library flow", "Live identity / specs UI flow",
re-confirmed accurate at HEAD):
- **Raw YAML preview:** UI/CLI posts YAML to `/api/specs/review/rig` or
`/api/specs/review/agent`; `SpecReviewService` parses/validates/returns
structured review models; UI renders them through `RigSpecDisplay` /
`AgentSpecDisplay` (the same primitives reused for draft preview, library
review, and live full-details).
- **Filesystem-backed library:** `SpecLibraryService` scans builtin + user
roots (`packages/daemon/specs`, `~/.openrig/specs`, legacy fallback
`~/.rigged/specs`); each YAML is classified via structured review;
service-backed rigs are marked `hasServices`; `/api/specs/library` serves
list/get/review/sync.
- **CLI mirror:** `rig specs ls/show/preview/add/sync`; `rig specs add`
installs a single YAML spec or a full spec directory; `rig up` /
`rig bootstrap` resolve library names before other source kinds.
- **Live identity:** Explorer/graph selection opens the shared right drawer
(runtime-first node detail: live identity, peers, directional edges,
transcript helpers, compact spec summary); `Open Full Details` navigates to
`/rigs/$rigId/nodes/$logicalId` in the center workspace.
## 3. UI primitive inventory (reconciled against source)
> Drift-fix — `ui.md` "Design Primitives" (L75–107) omits `ProjectPill`.
> `docs/DESIGN.md` L195 lists it; re-confirmed at HEAD it is a real export
> (`packages/ui/src/components/project/ProjectMetaPrimitives.tsx:196`
> `export function ProjectPill`). Reconciled inventory below is from source,
> not from either doc's list.
- **Vellum/base** (`components/ui/`): `VellumCard`, `VellumSheet`,
`RegistrationMarks`, `StatusPip`, `SectionHeader`, `EmptyState`,
`Button`, `Tabs`, `Table`, form controls, plus `rig-stamp.tsx`
(`RigStamp`) — present at HEAD; not in ui.md's list.
- **Graphics** (`components/graphics/RuntimeMark.tsx`, exports re-confirmed):
`RuntimeMark`, `RuntimeBadge`, `ToolMark`, `ToolBadge`, `ActorMark`,
`OperatorMoodMark`; normalization in `lib/runtime-brand.ts` +
`lib/tool-brand.ts`.
- **Project metadata** (`components/project/ProjectMetaPrimitives.tsx`,
exports re-confirmed): `ProjectPill` (`:196`), `EventBadge` (`:224`),
`QueueStateBadge` (`:228`), `TagPill` (`:274`), `ActorChip` (`:283`),
`DateChip` (`:303`), `FlowChips` (`:315`), `ProofThumbnailGrid` (`:334`),
`ProofPacketHeader` (`:380`) — plus `QueueCountIcon` / `StatusDot` (in
source, not in ui.md/DESIGN.md primitive lists).
- **Viewers**: `FileViewer` (`components/drawer-viewers/FileViewer.tsx`),
`MarkdownViewer` (`components/markdown/MarkdownViewer.tsx`),
`ProofImageViewer`, `SessionPreviewPane` (`components/preview/`).
## 4. Design-system pointer (NOT a copy — Q1)
The canonical OpenRig visual/design system is **`docs/DESIGN.md`** (at the
repo `docs/` root, NOT under `docs/as-built/`). Q1 is ratified: DESIGN.md
stays at root, byte-identical, and this module **points to it rather than
copying it**. DESIGN.md is the source for: Vellum-paper vs Black-glass
surface languages, colour tokens (`packages/ui/src/globals.css` +
`tailwind.config.ts`), typography (`font-body` Inter / `font-headline` Space
Grotesk / `font-mono` JetBrains Mono), layout (48px rail + Explorer + center
+ drawer + preview stack), the core-primitive list, the graphics system, and
the interaction/motion/accessibility/do-and-do-not rules.
> Reconciliation note: DESIGN.md's primitive lists were independently
> verified against `packages/ui/src/components/` at HEAD — every primitive
> DESIGN.md names (Vellum, Graphics, Project-metadata, Topology, Preview)
> resolves to a real export at HEAD. DESIGN.md is accurate and carries no
> slice-00 numeric drift, so it is referenced as-is. Do not duplicate its
> content here; read `docs/DESIGN.md` directly for the visual spec.
## See also
- `docs/DESIGN.md` — the canonical visual/design-system spec (pointer; do
not copy).
- `shell-and-routing.md` — the `/specs` route family + shell + drawer.
- `../architecture/agent-spec-and-startup.md` — the spec parsing/resolution
contract behind the review flows.
- `../architecture/plugin-agent-image-context-pack.md` — the 0.3.1 content
layer behind the plugins/agent-image/context-pack Library surfaces.
- Source roots: `packages/ui/src/components/specs/`,
`packages/daemon/src/domain/{spec-review-service,spec-library-service}*`.
+377
View File
@@ -0,0 +1,377 @@
---
kind: as-built
title: UI Project Observability, For You, Dashboard
status: active
topics: [observability, coordination]
domains: [engineering-advisor, product-advisor, operating-advisor]
applies-when: |
Need to know how the operator-facing destination surfaces are built —
the For-You attention feed (5-card classifier + verb actions), the
Project workspace/mission/slice scope pages (tabbed rollups), and the
Dashboard landing surface on the vellum brand system. Author-mode
module — ui.md prose for these surfaces predates 0.3.x; every claim is
sourced to file:line at HEAD.
siblings: [shell-and-routing.md, ../architecture/mission-control.md]
prerequisite-reads: [../README.md, shell-and-routing.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# UI Project Observability, For You, Dashboard
The three operator-facing destination surfaces: **For You** (`/for-you`,
the attention feed), **Project** (`/project*`, the workspace/mission/slice
scope pages), and the **Dashboard** (`/`, the landing surface on the
vellum brand system). All read live daemon state; none adds UI-local
persistence beyond per-event soft-dismiss.
> **AUTHOR-HEAVY module.** `ui.md`'s Project Observability / For You /
> Graphics-Layer sections are thin and predate the 0.3.1 dashboard/vellum
> brand refresh. Every load-bearing claim carries `> Source: <file:line>
> @HEAD`; ambiguity is declared as an OPEN item, never smoothed. Paths
> are relative to `packages/ui/src/` unless prefixed `docs/`.
>
> Verified at HEAD `7eaf524c` (`git describe` → `v0.3.1-6-g7eaf524c`).
> Package version **0.3.1**; HEAD carries 6 unreleased release-0.3.2
> commits; no `v0.3.2` tag (daemon-core.md; slice-00 §1.1).
## 0. Release attribution (forensic seam — read first)
Re-verified at HEAD via `git cat-file -e <tag>:<path>`:
| Layer | Release | Forensic proof @HEAD |
|---|---|---|
| Project-observability foundation (For-You feed, feed-classifier, project scope pages, the Mission Control 7-verb vocabulary) | **0.3.0** | `v0.3.0:components/for-you/Feed.tsx`, `v0.3.0:lib/feed-classifier.ts`, `v0.3.0:components/project/ScopePages.tsx`, `v0.3.0:components/mission-control/components/VerbActions.tsx` all resolve at `v0.3.0` (slice-00 0.3.0-GT §1.5/§1.6/§1.7) |
| Vellum **brand-identity system** the Dashboard/For-You now render on (`dashboard/vellum/*`: CornerBracket, VellumDestinationCard, marks, graphics, single-source-of-truth barrel) | **0.3.1, NOT 0.3.0** | `git cat-file -e v0.3.0:components/dashboard/vellum/index.ts` → **ABSENT** ("exists on disk, but not in 'v0.3.0'"); `v0.3.1:` → present (slice-00 0.3.0-GT seam (b); §2 rows 1/2) |
> Source: re-run at HEAD `7eaf524c` —
> `git cat-file -e v0.3.0:packages/ui/src/components/dashboard/vellum/index.ts`
> fails; `v0.3.0:.../for-you/Feed.tsx`, `.../lib/feed-classifier.ts`,
> `.../project/ScopePages.tsx`, `.../mission-control/components/VerbActions.tsx`
> all resolve at `v0.3.0`. Vellum surface *primitives*
> (`components/ui/vellum-*.tsx`) shipped 0.3.0; the coherent vellum
> *brand system* under `dashboard/vellum/` is 0.3.1 — slice-00 0.3.0-GT
> seam (b) is the exact split. **Do not back-attribute the vellum brand
> system to 0.3.0.**
## 1. Route reality (source-verified at `routes.tsx`@HEAD — BINDING)
Before narrating any surface, each route was verified at
`packages/ui/src/routes.tsx`@HEAD (542 lines). The Phase-8.1 survey's
"missing route" expectations are grep-derived and partially wrong; this
table is authored from `routes.tsx` reality, not the survey:
| Path | Reality @HEAD | Component | Source |
|---|---|---|---|
| `/for-you` | **REAL destination route** | `Feed` | `routes.tsx:122-126` |
| `/project` | **REAL destination route** | `WorkspaceScopePage` | `routes.tsx:128-132` |
| `/project/mission/$missionId` | **REAL destination route** | `MissionScopePage` | `routes.tsx:134-138` |
| `/project/slice/$sliceId` | **REAL destination route** | `SliceScopePage` | `routes.tsx:140-144` |
| `/` (index) | **REAL destination route** | `Dashboard` | `routes.tsx:88-92` |
| `/mission-control` | **DELETED `<Navigate to="/for-you">` redirect-stub** | `() => <Navigate to="/for-you">` | `routes.tsx:440-444` |
| `/progress` | **`<Navigate to="/project">` redirect-stub** (folds into Project tabs) | `() => <Navigate to="/project">` | `routes.tsx:463-467` |
| `/slices` | **DELETED `<Navigate to="/project">` redirect-stub** | `() => <Navigate to="/project">` | `routes.tsx:447-451` |
| `/slices/$name` | **`<Navigate to="/project/slice/$sliceId">` redirect-stub** | `useParams` → `<Navigate>` | `routes.tsx:453-460` |
| `/steering` | **`<Navigate to="/project">` redirect-stub** | `() => <Navigate to="/project">` | `routes.tsx:470-474` |
| `/markdown` | **NOT a route** — `MarkdownViewer` is a component used inside `MissionScopePage` | (no route) | grep `routes.tsx`@HEAD: zero `path: "/markdown"` |
> Source: `routes.tsx:88-92`,`:122-144`,`:440-474` @HEAD; component
> imports `routes.tsx:40-41` (`Dashboard`, `Feed`), `:60-63`
> (`WorkspaceScopePage`/`MissionScopePage`/`SliceScopePage` from
> `components/project/ScopePages.js`) @HEAD.
> **Route-reality contract (slice-08 §10.7):** the **Mission Control
> *system*** lives at daemon/PL-005 (see `../architecture/mission-control.md`)
> — `/mission-control` is **NOT a UI destination**; it is a deleted
> redirect-stub (SC-18). The 7-verb *action vocabulary* surfaces in this
> module via `VerbActions` embedded in For-You cards, but the system
> itself is not this module's subject. `/progress`, `/slices`,
> `/steering` all fold into `/project` tabs — they are redirect-stubs,
> not surfaces to narrate.
## 2. For You — the attention feed (`/for-you` → `Feed`)
`Feed` is the operator's attention surface: a chronologically-sorted,
subscription-filtered, soft-dismissable card stream over the live
activity feed. Header reads `Attention` / `For You`; max width 720px.
> Source: `components/for-you/Feed.tsx:364-369` (`data-testid="for-you-feed"`,
> max-w-720 + `For You` header), feed-centerpiece design note `:3-12`
> (PRIMARY UX = the feed; subscriptions NOT dominating — LOAD-BEARING
> SC-16) @HEAD.
### 2.1 The 5-card classifier (0.3.0 spine)
`classifyFeed(events)` maps every `ActivityEvent` to exactly one of five
`FeedCardKind` values — `action-required`, `approval`, `shipped`,
`progress`, `observation` — then sorts by `receivedAt` descending.
**Nothing is silently dropped**: any unmatched event type falls through
to `observation`. Queue-visibility events are sub-classified by
`queueKind(type, state)` (e.g. `*.closed` → shipped; `human-gate` /
`pending-approval` → action-required; `closeout-pending-ratify` →
approval); a human-seat destination forces `action-required`.
> Source: `lib/feed-classifier.ts:9-14` (`FeedCardKind` union),
> `classifyEvent` `:145-218` (default-observation fallthrough L216-217),
> `queueKind` `:93-110`, `classifyFeed` `:220-223` (receivedAt-desc sort),
> `isHumanSeat` `:141-144` @HEAD.
The feed pipeline (`Feed.tsx`): `classifyFeed` → cap at
`HISTORY_LIMIT = 50` → hydrate each card's kind from the live queue-item
map + action-audit (`hydratedCardKind`: a recorded outcome on an
action/approval card → `approval`; a `done|closed|completed` qitem →
`shipped`) → **subscription filter** (`isCardKindSubscribed` against the
5 `feed.subscriptions.*` config keys; `action-required` is always
visible, `observation` only when the audit subscription is on) → the
transient **lens-chip** filter (All / Action req / Approvals / Shipped /
Progress / Audit; not persisted) → per-event-seq soft-dismiss filter.
> Source: `components/for-you/Feed.tsx:63` (`HISTORY_LIMIT = 50`),
> `:238` (`classifyFeed(events).slice(0, HISTORY_LIMIT)`),
> `hydratedCardKind` `:156-180`, subscription+lens+dismiss pipeline
> `:269-285` (subscription FIRST L280-282; lens L283; dismiss L284),
> `LENS_CHIPS` `:54-61` @HEAD;
> subscription forced/default rules `Feed.tsx:3-12` (action_required
> forced ON L9; observation gated on audit_log L10) @HEAD.
### 2.2 Queue-item hydration + proof previews
For cards carrying a `qitemId` payload, `useQueueItemMap` hydrates the
full queue-item body; for `shipped` cards `sliceForCard` matches a slice
by tag/text and `proofPreviewForSlice` pulls the first proof packet with
screenshots so the card renders an inline `ProofThumbnailGrid` →
`ProofImageViewer`. This is the slice-00 §1.5 "queue cards hydrate qitem
bodies + proof previews" foundation, live-wired.
> Source: `components/for-you/Feed.tsx:263` (`useQueueItemMap`),
> `sliceForCard` `:182-201`, `proofPreviewForSlice` `:203-213`,
> per-card proof wiring `:421-427`; `FeedCard.tsx` proof block
> `:453-471` (`ProofPacketHeader`+`ProofThumbnailGrid`),
> `ProofImageViewer` `:521` @HEAD.
### 2.3 Verb actions on action/approval cards (the 7-verb system; OPEN-3)
An actionable card (`action-required` or `approval`, no recorded
outcome, non-terminal qitem) embeds `VerbActions`. The **canonical
Mission Control action vocabulary is the 7-verb system** —
`MISSION_CONTROL_VERBS = [approve, deny, route, annotate, hold, drop,
handoff]` — defined at the Mission Control system level (slice-00
0.3.0-GT §1.6/seam (c): the vocabulary *originates in 0.3.0 source*).
> Source: `components/mission-control/hooks/useMissionControlAction.ts:5-15`
> (`MISSION_CONTROL_VERBS` 7-element const `:5-13` + `MissionControlVerb`
> type `:15`), `components/mission-control/components/VerbActions.tsx:82`
> (defaults to all 7 via `enabledVerbs = [...MISSION_CONTROL_VERBS]`),
> per-verb input needs `:97-99` (route/handoff→destination L97;
> annotate→annotation L98; hold/drop→reason L99) @HEAD; slice-00
> 0.3.0-GT §1.6 + seam (c).
> **OPEN — For-You verb-subset (slice-00 0.3.0-GT OPEN-3; NOT smoothed).**
> `VerbActions` accepts an `enabledVerbs` prop to restrict the offered
> verbs (`VerbActions.tsx:21-22`). The For-You `FeedCard` currently
> passes `enabledVerbs={["approve", "deny", "route"]}`
> (`FeedCard.tsx:492`). **The exact shipped For-You-surface verb subset
> is an unresolved velocity slice-01 ruling** (slice-00 0.3.0-GT OPEN-3:
> CHANGELOG `[0.3.1]` enumerates the full 7 on `FeedCard`, while
> source-material §6 frames it as a "subset" — the discrepancy is OPEN).
> Per the slice-08 contract this module describes the **7-verb
> system-level vocabulary only** and does NOT assert a definitive
> For-You verb subset. The `enabledVerbs` prop value above is reported
> as the literal current source state, explicitly NOT as a resolution
> of OPEN-3.
On mutation success `VerbActions` fires `onOptimisticOutcome`; `Feed`
keeps an optimistic-outcome map keyed by `qitemId` so the
`ActionOutcomePanel` receipt renders instantly without waiting for the
audit-log re-fetch (the audit re-fetch eventually surfaces the same
shape). A terminal qitem with no recorded outcome derives a fallback
receipt from its closure reason.
> Source: `components/for-you/Feed.tsx:224-236` (optimistic-outcome
> map + `setOptimisticOutcome`), `:426-428` (optimistic-first, audit
> fallback: `optimisticOutcomes.get ?? actionOutcomes.get ?? null`);
> `FeedCard.tsx:473-500` (`isActionableCard` gate L473 + `VerbActions`
> wiring L489-499), `isActionableCard` `:166-175`,
> `fallbackOutcomeFromQueueItem` `:177-198`, `ActionOutcomePanel`
> `:271-310`; `VerbActions.tsx:138-145` (`onOptimisticOutcome` on
> mutation `onSuccess`) @HEAD.
### 2.4 Card surface — vellum-coherent (0.3.1 brand layer)
`FeedCard` renders on the **0.3.1 vellum brand system**: a
`bg-stone-100/45 backdrop-blur` surface with a 3-stop ambient box-shadow
(no border), four `CornerBracket` marks registering the bounds through
the vellum, a mono-uppercase kind tag + colored dot, and runtime
graphics marks (`ActorMark` for sessions) — the slice-00 §1.7 "shared
graphics marks across drawers / proof rows / queue refs / story rows"
foundation, now expressed in the matured vellum vocabulary. Cards are
keyboard-dismissable (Backspace/Delete) and swipe-dismissable, with an
`UndoToast`.
> Source: `components/for-you/FeedCard.tsx:72-73` (`CARD_SURFACE_CLASS`),
> `:74-80` (`CARD_SHADOW_STYLE` 3-stop box-shadow), corner brackets
> `:401-404` (4× `<CornerBracket position=…>`), `KIND_DOT` `:33-39`,
> kind tag span `:410-414`, `ActorMark` import `:25` + usage `:229`;
> `CornerBracket` from the 0.3.1 brand barrel
> `dashboard/vellum/index.ts:17`; slice-00 0.3.0-GT seam (b) + §1.7 @HEAD.
### 2.5 Storytelling preview band
Above the legacy card list `Feed` renders a `StorytellingFeed` preview
built by `buildStorytellingFeedItems` from discovered missions
(`useMissionDiscovery` → `ProgressCard`, first 2) + slices
(`useSlices` → `ShippedCard` for shipped/done, `IncidentCard`
otherwise, capped at 3). Mission rows carry a daemon-derived
`status` so the "Getting Started"-style complete-and-hide filters
durably (`status === "complete"`), with an optimistic local hide +
best-effort `POST /api/missions/:id/complete` audit write that swallows
network errors so a partial-air-gapped daemon does not block the hide.
> Source: `components/for-you/Feed.tsx:319-343` (mission/slice adapters:
> `useMissionDiscovery` L319, `missionsWithStatus` L329-335,
> `buildStorytellingFeedItems` L336-343; adapter comment L305-318),
> `handleMarkMissionComplete` `:351-361` (best-effort `void fetch` L354,
> error-swallowed L357), preview render `:399-409`;
> `components/feed/cards/storytelling-cards.tsx:36` (`CardKind`),
> `ShippedCard` `:184`, `IncidentCard` `:235`, `ProgressCard` `:289`
> @HEAD.
## 3. Project — workspace / mission / slice scope pages (0.3.0 spine)
`/project*` mounts three scope pages, all built on a shared
`ScopeShell` + tabbed-rollup pattern (slice-00 §1.5 project
observability foundation). A `SHARED_TABS` set —
`overview / story / progress / artifacts / tests / queue / topology` —
drives `WorkspaceScopePage` and `MissionScopePage`; `SLICE_TABS`
reorders `story` first for `SliceScopePage` but `SliceScopePage`'s
`useState` default is `overview` (README + readiness first, not a
metric grid).
> Source: `components/project/ScopePages.tsx:75-76` (`SharedTab` /
> `SliceTab` types), `SHARED_TABS` `:78-86`, `SLICE_TABS` `:88-96`,
> `ScopeShell` `:137-166`, `TabNav` `:98-135` @HEAD.
### 3.1 WorkspaceScopePage (`/project`)
Reads the live workspace name (`useWorkspaceName`); honest empty-state
(`NO WORKSPACE CONNECTED` with an Open-settings action) when unset. The
`overview` tab renders `WorkspaceOverviewPanel`: slices grouped into
missions, then `partitionProjectMissions` splits them into a
two-column **Current Work / Archive** layout (slice-00 §1.5
"current/archive grouping"). Each mission card lists its slices as
`Link`s to `/project/slice/$sliceId` with a `QueueCountIcon` +
`StatusDot`. The other tabs are the scope rollups (§3.4).
> Source: `components/project/ScopePages.tsx:676-749` (`WorkspaceScopePage`;
> no-workspace empty-state guard `:682-693`, `workspace-scope-no-workspace`
> `:689`), `WorkspaceOverviewPanel` `:534-674` (mission bucketing
> `:536-551`, `partitionProjectMissions` `:552`, two-column panel `:631`,
> Current section `:632-651`, Archive section `:652-671`) @HEAD.
### 3.2 MissionScopePage (`/project/mission/$missionId`)
Same `ScopeShell`/`SHARED_TABS`. `overview` renders the mission README
(`useScopeMarkdown(missionPath, "README.md")` via `MarkdownViewer`)
above a slice rail; `progress` renders a `MissionProgressHeatmap` + the
mission `PROGRESS.md` + the shared `ScopeProgressRollup`. The `topology`
tab renders the **projected workflow spec graph** via `TopologyTab`
when the mission's README frontmatter declares a `workflow_spec` that is
in the `WorkflowSpecCache` (daemon returns `topology.specGraph`),
falling back to session-name aggregation otherwise.
> Source: `components/project/ScopePages.tsx:751-895` (`MissionScopePage`;
> `useMission` `:759`, `missionPath` `:760-761`, README/PROGRESS
> markdown `:762-763`, overview README section `:775`, progress
> heatmap `:832`, `mission-progress-readme` `:838`, spec-graph topology
> branch `:875-891` — `missionTopology` `:875`, `specGraph` check
> `:879`, session-name fallback `:890`) @HEAD.
### 3.3 SliceScopePage (`/project/slice/$sliceId`)
Default tab `overview` (`SliceOverviewTab` — README + current step +
readiness). Loading/error states are honest empty-states (the error
state names `rig config get workspace.slices_root` as the likely
misconfiguration). `progress` folds in `AcceptanceTab` (acceptance is
the canonical slice-scope progress proof); `story` renders `TimelineTab`
with curated `timeline.md` (`useSliceTimelineMarkdown`) above the
auto-captured event feed; `topology` renders the slice's
workflow-instance-aware `TopologyTab`.
> Source: `components/project/ScopePages.tsx:1187-1297` (`SliceScopePage`;
> default `overview` `:1192`, timeline md `:1204`, loading-state
> guard `:1206`, error-state guard `:1225` (slices_root remediation
> hint `:1239`), story=`TimelineTab` `:1258-1265`,
> progress=`AcceptanceTab` `:1269-1273`, topology `:1294`) @HEAD.
### 3.4 Shared scope rollups
`ScopeStoryRollup`, `ScopeProgressRollup`, `ScopeArtifactsRollup`,
`ScopeTestsRollup`, `ScopeQueueRollup`, `ScopeTopologyRollup` (the
non-overview tabs) all read from one `useProjectScopeRollup(missionId,
loadDetails)` hook so workspace and mission scopes share identical
rollup behavior over their respective slice sets — the slice-00 §1.5
"workspace/mission rollups" foundation. Detail fetching is gated on the
active tab (`active !== "overview"`) so the overview path stays cheap.
> Source: `components/project/ScopePages.tsx:198-217`
> (`useProjectScopeRollup`; `rowsForScope` `:193-196`),
> rollup components `:219-532`; gate `:679`,`:754` (`active !== "overview"`)
> @HEAD.
## 4. Dashboard — the landing surface (`/` → `Dashboard`)
`Dashboard` is a thin composition over the **0.3.1 vellum brand
system**: it imports `MidLayerContent`, `TopLayerContent`,
`DestinationsLayer` from `dashboard/vellum/index.js` — the SAME barrel
`/lab/vellum-lab` imports, so the production dashboard tracks the design
lab exactly (single source of truth). Real-data wiring: `useRigSummary`
→ totalRigs/totalAgents, `usePsEntries` → activeAgents, `useSpecLibrary`
→ librarySize, `window.location.hostname` → classification eyebrow. Per
a 2026-05-15 founder dispatch the heavy `BackLayerContent` /
`BackVellumSheet` back-layer was removed so the dashboard sits on the
page-level cream paper-grid; the barrel still exports them (used by the
lab).
> Source: `components/dashboard/Dashboard.tsx:1-52` (vellum-barrel
> import `:12-16`, single-source-of-truth note `:2-5`, real-data hooks
> `:29-39`, back-layer-removal note `:21-27`, render `:40-50`);
> `components/dashboard/vellum/index.ts:1-26` (barrel; `BackLayerContent`
> `:5` / `BackVellumSheet` `:6` still exported); slice-00 0.3.0-GT
> seam (b) + §2 rows 1/2 @HEAD.
## 5. Cross-cutting properties
- **Live daemon state, no UI-local persistence beyond soft-dismiss** —
every surface reads daemon hooks; the only UI-local state is the
per-event-seq dismiss set + transient lens chips + optimistic-outcome
map (`Feed.tsx:217` lens, `:224` optimistic map, `:240-241` dismiss
set; `ScopePages.tsx` `useState` tab state `:677`,`:753`,`:1192`)
@HEAD.
- **Honest empty/error states** — `WorkspaceScopePage` no-workspace
(`ScopePages.tsx:682-693`), `WorkspaceOverviewPanel` index-unavailable
(`:565-573`, label `:568`), `SliceScopePage` not-available
(`:1225-1245`, label `:1235`) all surface the cause + a remediation
pointer, never a blank screen @HEAD.
- **0.3.0 observability spine on the 0.3.1 vellum brand layer** — the
classifier / verb-action / scope-rollup *logic* is the 0.3.0
foundation (§0); the *visual surface* (vellum cards, corner brackets,
graphics marks, dashboard) is the 0.3.1 brand maturation. The split is
slice-00 0.3.0-GT seam (b); do not collapse either direction @HEAD.
## OPEN items (carried, not smoothed)
- **OPEN — For-You verb subset (slice-00 0.3.0-GT OPEN-3).** The exact
shipped For-You-surface verb subset is an unresolved velocity slice-01
ruling (CHANGELOG `[0.3.1]` "all 7" vs source-material §6 "subset"
discrepancy). This module describes the **7-verb system-level
vocabulary only** and reports the literal current `enabledVerbs`
prop value (§2.3) as source state, NOT as a resolution. Defer
For-You-subset enumeration to the pending velocity ruling.
- **OPEN — `/project` redirect-stub consolidation.** `/progress`,
`/slices`, `/steering` are `<Navigate to="/project">` stubs and
`/slices/$name` redirects into `/project/slice/$sliceId` (§1). The
former standalone surfaces fold into Project tabs; whether the stubs
are permanent or transitional is a product decision not resolvable
from source.
- No slice-00 numeric-drift OPEN (1–5) applies — this module carries no
migration / route-group / PL-004-event counts.
+163
View File
@@ -0,0 +1,163 @@
---
kind: as-built
title: UI Shell, Routing, Drawer System
status: active
topics: [observability]
domains: [engineering-advisor, product-advisor]
applies-when: |
Need to know how the UI shell (AppShell rail / Explorer / center workspace /
drawer / preview stack) is assembled, the actual route tree the shipped UI
mounts, or how the shared detail drawer and event consumption work.
siblings: [topology.md, project-and-for-you.md, library-specs-and-design-system.md]
prerequisite-reads: [../README.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# UI Shell, Routing, Drawer System
The `@openrig/ui` package is the shell-first, route-first, primitive-driven
operator surface. Brand/visual rules live in `docs/DESIGN.md` (pointer from
`library-specs-and-design-system.md`); this module is how the shell is
assembled and what routes it mounts.
> Verified against source at HEAD `7eaf524c`; package version **0.3.1**
> (slice-00 §1.1). UI footprint is **235** source files
> (`packages/ui/src`, `.ts`+`.tsx`, non-test; slice-00 §1.6 / D6).
## 1. Package shape
UI package: `packages/ui`. Primary implementation areas:
- `src/routes.tsx` — TanStack Router route tree.
- `src/components/AppShell.tsx` — global shell: rail, Explorer, drawer,
preview stack.
- `src/components/ui/` — reusable vellum + base UI primitives.
- `src/components/graphics/RuntimeMark.tsx` — runtime/tool/actor marks.
- `src/components/topology/` — graph/table/terminal topology surfaces.
- `src/components/project/`, `for-you/`, `dashboard/`, `feed/` —
observability surfaces.
- `src/components/specs/` — Library / skills / plugins surfaces.
- `src/components/{preview,markdown,drawer-viewers}/` — viewers.
- `src/hooks/`, `src/lib/` — route data hooks, classifiers, formatters,
layout/brand helpers.
## 2. Shell model
`AppShell` wraps every route. `AppShell.tsx` lays a 48px icon rail + a
route-aware Explorer sidebar + center workspace + shared right drawer +
preview stack + topology overlay provider + shared drawer-selection /
discovery-placement contexts.
The rail destinations (`AppShell.tsx` `RAIL_ICONS`, re-confirmed at HEAD)
are exactly six destination icons plus Advisor/Operator entries:
- Dashboard `/` (`rail-dashboard`)
- Topology `/topology` (`rail-topology`)
- For You `/for-you` (`rail-for-you`)
- Project `/project` (`rail-project`)
- Library `/specs` (`rail-specs`)
- Settings `/settings` (`rail-settings`)
The Explorer is contextual: its tree changes with the current destination
rather than acting as a generic file browser.
## 3. Route model
> Drift-fix D16 — `ui.md` "Route Model" (the L52–73 list) and
> `architecture.md` §2 "UI architecture" predate 0.3.x. The route table
> below is **re-derived from `packages/ui/src/routes.tsx` at HEAD** (542
> lines). The route tree is assembled at `routes.tsx:480`
> (`rootRoute.addChildren([...])`).
>
> Correction to the D16 expectation itself (source-verified at HEAD): the
> survey expected `/mission-control`, `/progress`, `/markdown` as net-new
> *real* routes. At HEAD `/mission-control` and `/progress` are **redirect
> stubs**, not destination routes, and there is **no `/markdown` route**.
> There IS a real `/files` route (markdown is rendered by the `MarkdownViewer`
> component inside file/drawer surfaces, not via a `/markdown` route). The
> route table is reported as source says, not as the survey predicted.
### Primary destination routes
| Path | Component | Notes |
|---|---|---|
| `/` | Dashboard (`indexRoute` `routes.tsx:88`) | rail destination |
| `/topology` | host topology (`:98`) | + rig/pod/seat scopes (see `topology.md`) |
| `/topology/rig/$rigId` | rig scope (`:104`) | |
| `/topology/pod/$rigId/$podName` | pod scope (`:110`) | |
| `/topology/seat/$rigId/$logicalId` | seat scope (`:116`) | live node details |
| `/for-you` | attention feed (`:122`) | rail destination |
| `/project` | workspace project scope (`:128`) | rail destination |
| `/project/mission/$missionId` | mission scope (`:134`) | |
| `/project/slice/$sliceId` | slice scope (`:140`) | |
| `/specs` | Library (`:146`) | rail destination |
| `/specs/applications` | applications section (`:152`) | |
| `/specs/skills` | skills index (`:160`) | |
| `/specs/skills/$skillToken` | skill viewer (`:166`) | defaults to `skill.md` |
| `/specs/skills/$skillToken/file/$fileToken` | skill file viewer (`:175`) | |
| `/specs/plugins` | plugins index (`:186`) | 0.3.1 (see `library-specs…`) |
| `/plugins/$pluginId` | plugin detail (`:201`) | 0.3.1 |
| `/specs/$specKind/$specName` | generic spec → library redirect (`:213`) | |
| `/files` | Files workspace (`:192`) | net-new vs ui.md/D16 |
| `/settings` | settings center (`:222`) | rail destination |
| `/settings/policies` | Policies (`:232`) | slice 27 Claude-compaction form |
| `/settings/log` | Log (`:237`) | slice 26 4-item Settings explorer |
| `/settings/status` | Status (`:242`) | |
| `/search` | audit/history view (`:248`) | |
### Lab routes (design experiments)
`/lab/project-graphics-preview` (`:254`), `/lab/card-previews` (`:262`),
`/lab/vellum-lab` (`:272`), `/lab/vellum-bg/{a-large,b-small,c-allover}`
(`:283`–`:293`). The vellum-lab + vellum-bg routes are the 0.3.1 vellum
brand-system experiment surface (slice-00 0.3.0-GT seam b: vellum brand
identity matured in 0.3.1; the `dashboard/vellum/*` system is 0.3.1).
### Legacy / compatibility routes
`/rigs/$rigId` (`:318`), `/rigs/$rigId/nodes/$logicalId` (`:324`),
`/import` (`:333`), `/packages`, `/packages/install`, `/packages/$packageId`
(`:339`–`:351`), `/bootstrap` (`:357`), `/agents/validate` (`:363`),
`/specs/rig` + `/specs/agent` review (`:372`/`:378`),
`/specs/library/$entryId` (`:384`), `/discovery` + `/discovery/inventory`
(`:395`/`:410`), `/bundles/inspect` + `/bundles/install` (`:416`/`:422`).
### Redirect stubs (deleted routes)
`routes.tsx:432`–`:474` mount `<Navigate>` redirects for removed routes —
NOT destination pages: `/context` → `/topology`; `/mission-control` →
`/for-you` (SC-18: `/mission-control` deleted, For-You replaces it);
`/slices` + `/slices/$name` → `/project`; `/progress` → `/project`;
`/steering` → `/project`. The Mission Control *system* still exists at the
daemon/PL-005 layer (`../architecture/mission-control.md`); only the old UI
*route* was retired in favour of For-You.
## 4. Drawer and viewer system
`SharedDetailDrawer` is the shared transient detail surface for queue-item
viewer, file viewer, subspec preview, and other detail selections. Drawer
triggers carry root/path provenance so the viewer fetches/render the correct
content; the drawer supports outside-click dismissal. Image proof viewing is
handled by `ProofImageViewer` with black-glass styling honouring the shell
layout. Skill detail uses Library Explorer navigation + `FileViewer`
(`components/drawer-viewers/FileViewer.tsx`) in the center workspace, not a
nested three-column browser.
## 5. Event and activity consumption
UI event consumption is centralized through shared event hooks so the app
avoids duplicate SSE connections for related surfaces. Current consumers: For
You feed hydration, topology activity rings + hot-potato movement, the
activity feed/system surfaces, and rig event surfaces. Reduced-motion
preference is honoured for pulse/packet animation. (Daemon SSE surfaces:
`/api/events`, `/api/stream/watch`, `/api/queue/watch` —
`architecture-rules-and-event-system.md` §2.4.)
## See also
- `topology.md` — graph/table/terminal topology surface.
- `project-and-for-you.md` — project observability + For-You feed.
- `library-specs-and-design-system.md` — Library/specs + DESIGN.md pointer.
- Source roots: `packages/ui/src/routes.tsx`,
`packages/ui/src/components/AppShell.tsx`.
+109
View File
@@ -0,0 +1,109 @@
---
kind: as-built
title: UI Topology — Graph/Table/Terminal, HotPotato, ActivityRing
status: active
topics: [observability, coordination]
domains: [engineering-advisor, operating-advisor]
applies-when: |
Need to know how the topology surface is built — the host hybrid graph,
the table/terminal views, the activity-ring / hot-potato visual language,
terminal-preview popovers, and the topology navigation/overlay contracts.
siblings: [shell-and-routing.md, project-and-for-you.md]
prerequisite-reads: [../README.md, shell-and-routing.md]
last-verified-against-source: 7eaf524c
last-updated: 2026-05-16
---
# UI Topology — Graph/Table/Terminal, HotPotato, ActivityRing
Topology is a scoped workspace with graph, table, and terminal views at the
`/topology` route family (`shell-and-routing.md` §3). It is the operator's
live picture of host → rig → pod → seat.
> Verified against source at HEAD `7eaf524c`; package version **0.3.1**
> (slice-00 §1.1). All component names below are re-confirmed against
> `packages/ui/src/components/topology/` at HEAD — `ui.md` and `DESIGN.md`
> name *exported symbols*; the source file that defines the hybrid nodes is
> `HybridTopologyNodes.tsx` (DESIGN.md L344 implementation reference).
## 1. Topology pieces
> Drift-fix — `ui.md` "Topology" (L108–137) lists `HybridAgentNode` /
> `HybridPodGroupNode` as if top-level files. Re-confirmed at HEAD: both are
> exports inside `packages/ui/src/components/topology/HybridTopologyNodes.tsx`
> (`HybridPodGroupNode` is `memo(...)` at `HybridTopologyNodes.tsx:94`;
> `HybridAgentNode` is `memo(HybridAgentNodeInner, ...)` at `:272`). The
> component names are accurate; their file location is consolidated.
Components in `packages/ui/src/components/topology/` (re-confirmed at HEAD):
- `HostMultiRigGraph.tsx` — host-level hybrid React Flow graph (multi-rig
single canvas).
- `HybridTopologyNodes.tsx` — exports `HybridAgentNode` (compact agent cards:
runtime badges, context %, token totals, activity state, terminal preview,
CMUX actions) and `HybridPodGroupNode` (soft dashed pod frames).
- `RigGroupNode.tsx` — soft rig frames with registration marks + aggregate
activity.
- `ActivityRing.tsx` — active / needs-input / blocked activity ring; card
activity classes in `activity-card-visuals.ts`.
- `HotPotatoEdge.tsx` — directional queue-movement edge animation.
- `TopologyTableView.tsx` — dense table mirror of topology data.
- `TopologyTerminalView.tsx` — terminal-oriented topology state.
- `TopologyTreeView.tsx` — tree navigation view.
- `TopologyViewModeTabs.tsx` — graph/table/terminal/tree mode switch.
- `TerminalPreviewPopover.tsx` — black-glass quick terminal preview, portaled
above the graph.
- `LaunchCmuxButton.tsx` — hover/focus CMUX launch action.
- `ScopePages.tsx` — host/rig/pod/seat scope page wrappers.
- `topology-overlay-context.tsx` — `TopologyOverlayProvider` (expanded-rig
state).
> Note (vs `DESIGN.md` "Topology" L205–216): DESIGN.md lists the same
> exported primitives (`HostMultiRigGraph`, `HybridAgentNode`,
> `HybridPodGroupNode`, `RigGroupNode`, `ActivityRing`, `HotPotatoEdge`,
> `TerminalPreviewPopover`, `TopologyTableView`, `TopologyTerminalView`) —
> reconciled against source: all present at HEAD. `TopologyTreeView` /
> `TopologyViewModeTabs` / `LaunchCmuxButton` exist in source but are not in
> DESIGN.md's primitive list (DESIGN.md is the brand primitive list, not an
> exhaustive component inventory; not a drift, a scope difference). DESIGN.md
> stays byte-identical (Q1).
## 2. Topology contracts
From `architecture.md` §2 "Current topology UI" + `ui.md` "Important
topology contracts", re-confirmed against source behaviour at HEAD:
- Graph / table / tree navigation all resolve to seat detail URLs
(`/topology/seat/$rigId/$logicalId`).
- The host-level graph uses cross-rig node-ID prefixing for multi-rig single
canvas.
- Expanded-rig state is owned by `TopologyOverlayProvider`
(`topology-overlay-context.tsx`); graph data is lazy-fetched for expanded
rigs only.
- Compact agent cards show context percentage, token totals, and activity
card tint; `ActivityRing` + activity classes surface active / needs-input /
blocked.
- `HotPotatoEdge` animates directional queue movement at graph zoom levels;
reduced-motion preference removes pulse/travel animation and keeps static
state signals.
- Terminal-preview actions are hover/focus-visible; the
`TerminalPreviewPopover` must escape React Flow stacking contexts (portaled
above the canvas) and stay within the viewport.
## 3. Layout helpers
Topology layout is computed by `src/lib/` helpers (re-confirmed at HEAD):
`graph-layout.ts`, `hybrid-layout.ts`, `multi-rig-layout.ts`,
`topology-activity.ts`, `activity-visuals.ts`. Runtime/tool identity on the
cards comes from the central `runtime-brand.ts` / `tool-brand.ts` +
`RuntimeMark.tsx` (do not duplicate brand logic — DESIGN.md "Do not";
restated here as the topology-card brand-source contract).
## See also
- `shell-and-routing.md` — the `/topology` route family and shell.
- `project-and-for-you.md` — sibling observability surface.
- `../architecture/coordination-primitive.md` — the queue movement the
hot-potato edge visualizes.
- Source root: `packages/ui/src/components/topology/`,
`packages/ui/src/lib/{graph,hybrid,multi-rig}-layout.ts`.