mirror of
https://github.com/mvschwarz/openrig.git
synced 2026-11-09 03:39:51 -10:00
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:
1 parent
7eaf524cc4
commit
16b85d9c41
23 files changed
+4275
-1773
No files matched your search
@@ -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/`.
|
||||
+53
-1142
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`.
|
||||
@@ -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).
|
||||
@@ -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
@@ -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.
|
||||
@@ -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
@@ -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}*`.
|
||||
@@ -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.
|
||||
@@ -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`.
|
||||
@@ -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`.
|
||||
Reference in new issue
Block a user