diff --git a/AGENTS.md b/AGENTS.md
index 431fa7f2..b7c62d6f 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -22,17 +22,10 @@ Turborepo + pnpm monorepo (`packages/shared`, `packages/llm`, `packages/core`,
**cloud** (BYOK-central, Phase 2), and **managed** (Relavium's own keys via a metered egress
gateway; engine stays local, Phase 2) — split across build phase 5 (managed inference) and
phase 6 (cloud execution + portal); the engine is identical across all three (ADR-0012..0015).
-**Status: Phase 1 in progress — milestone M1 (LLM seam proven) reached (PR #9, 2026-06-07);**
-`@relavium/llm` (the seam + all three adapters) is landed and green. Phase 0 (M0) landed
-the monorepo + `@relavium/shared` + CI + `@relavium/db`. The
-[`@relavium/core` engine](docs/roadmap/phases/phase-1-engine-and-llm.md) has since landed the full
-run-loop + node stack — parser, interpolation, DAG/`RunPlan`, the run loop + `RunEventBus`, the tool
-registry, the `AgentRunner`, the six node-type handlers, the human gate, checkpoint/resume, node retry,
-the expression sandbox, and the pre-egress budget governor — plus the agent-first `AgentSession` (1.V),
-**completing milestone 1.m4** (PRs #13–#26); then the **1.U** end-to-end Node harness landed (**PR #27,
-2026-06-16**), **reaching milestone M2** (the engine runs end-to-end) — the Phase-1 engine critical path is
-complete, and Phase 2 (the CLI) is unblocked. The remaining Phase-1 work is the additive agent-first +
-multimodal sub-spines; see [docs/roadmap/current.md](docs/roadmap/current.md) for live status.
+**Status: Phase 1 is complete; Phase 2 (CLI) is feature-complete (v0.1.1 release cut, publish
+pending); Phase 2.5 (CLI Consolidation) is complete (M2.5-4, 2026-07-08); Phase 2.6
+(Conversational Authoring and the First-Class CLI) is next up.**
+See [docs/roadmap/current.md](docs/roadmap/current.md) for live status.
## The non-negotiable rules
diff --git a/CLAUDE.md b/CLAUDE.md
index e940bbc1..37fe48b3 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -38,98 +38,25 @@ A run executes in one of **three execution modes** behind the one `LLMProvider`
engine is identical across all three. See [ADR-0012](docs/decisions/0012-managed-inference-dual-mode.md) to [ADR-0015](docs/decisions/0015-managed-mode-data-handling-and-compliance.md)
and [docs/architecture/managed-inference.md](docs/architecture/managed-inference.md).
-**Status:** Phase 1 is **complete** (2026-06-21). The engine runs end-to-end behind
-the `LLMProvider` seam: YAML→DAG parse, the multi-model run loop (agent + the six
-non-agent node handlers) with live streaming, per-node-boundary checkpoint/resume
-(cross-process), node retry, provider failover, cost governance, the human gate, and
-multimodal media I/O (input, inline output, and the async generation job loop). All
-three adapters (Anthropic, OpenAI/DeepSeek, Gemini) and the agent-first `AgentSession`
-entry point (multi-turn sessions, persistence, export-to-workflow) are shipped.
-**Phase 2 (CLI) is underway and milestone M3 is reached** — the CLI skeleton (2.A) and config
-resolution (2.B) landed (PR #40), `relavium run` is wired to the engine
-(2.D, the M3 keystone — PR #41), the `--json` CI machine-output contract
-landed (2.F — PR #42, ADR-0049), the engine regression harness (2.K — PR #43)
-completes M3, and durable run history landed (2.H — PR #44, ADR-0050); the provider/key
-commands with OS-keychain storage landed (2.C — PR #45, behind ADR-0019 + ADR-0006); the `ink`
-streaming TUI landed (2.E — PR #46, behind ADR-0047); the interactive human-gate prompt + the
-out-of-band `relavium gate` cross-process resume landed (2.G — PR #47, behind ADR-0047), **fully closing
-2.K's deferred gate-resume half**; and the read commands `list` / `logs` / `status` / `gate list` over durable
-history landed (2.I — PR #48, no new ADR); and CLI packaging, distribution & install verification landed
-(2.L — PR #49, behind ADR-0051) — the last gate-closing spine PR, **closing go/no-go #7 so all seven Phase-3
-exit criteria now hold and Phase 3 may start**; and media host-wiring landed (2.S — PR #52, behind ADR-0042–0046,
-no new ADR), **the first additive lane done**; and the agent-first `relavium chat` REPL landed (2.M — PR #54,
-2026-06-26, no new ADR — covered by ADR-0024/0047/0028/0050/0029; `read_media` **input** access split into a
-dedicated, security-reviewed follow-up, so 2.M's REPL shipped without it); and the rest of the agent-first chat
-family landed — `relavium chat-resume` (2.N), `chat-list` (2.O), `chat-export` + the in-REPL `/export` (2.P),
-and `chat --json` + one-shot `agent run` (with `--fixture` cassette replay) (2.Q) — **PR #55, no new ADR**,
-completing the agent-first CLI lane; and **2.R (the inbound MCP client) is ✅ Done** — the `@relavium/mcp`
-foundation (the SDK-fenced package, the dependency-free JSON-Schema→Zod compiler, the fail-loud connect-all
-manager) landed **PR #56**, and the host wiring (chat + run + one-shot `agent run`), the network transports
-(`http`/`sse`/`websocket`) behind the SSRF floor, named secrets via the isolated `mcp-secret:*` keychain
-namespace, the by-name `ref` form, and the real-spawn e2e landed **PR #57 (2026-06-27)** — behind
-[ADR-0034](docs/decisions/0034-mcp-client-sdk-dependency.md) + [ADR-0052](docs/decisions/0052-inbound-mcp-client-package-lifecycle-registration.md)
-+ [ADR-0053](docs/decisions/0053-mcp-network-transport-egress-security.md). 2.R was off the M3 critical path and
-the Phase-3 go/no-go, so it adds capability without gating; and **2.J** (the `create`/`import`/`export` YAML
-lifecycle) landed **PR #58 (2026-06-28)** — **with it every Phase-2 workstream is complete and the CLI is
-feature-complete (published v0.1.1)**. **Phase 2.5 (CLI Consolidation) is now underway:** its spine's secure
-base **2.5.A** — the shared `assembleToolEnv` tool-environment factory (host `fs`+`process` arms, the
-advertise-filter, **EA1** `tool_unavailable`, **EA2** real failed-turn usage) wired into both the chat and
-run paths — landed **PR #60 (2026-06-28)**, behind [ADR-0055](docs/decisions/0055-cli-host-capability-seam-tool-environment-factory.md),
-**reaching milestone M2.5-1**; the `egress`/`os` arms + write-capable chat are deferred to 2.5.E/ADR-0057; and
-**2.5.B** (the bare-invocation interactive Home — the TTY-gated bare `relavium` → a read-only management strip
-over `history.db` that graduates into in-process chat, one ink tree + one SIGINT/SIGTERM lifecycle + bracketed
-paste) landed **PR #61 (2026-06-29)**, behind [ADR-0054](docs/decisions/0054-cli-bare-invocation-interactive-home.md);
-and **2.5.C** (the in-app command system — a curated **two-registry** model: the shell `COMMAND_MANIFEST`
-(`commander` + `--help --json` + the `executeCommand` dispatch) vs the in-REPL `REPL_COMMANDS` (a filterable `/`
-palette + slash commands in **both** chat and the bare Home, no command in both); `/help`, the `notice` channel,
-`/workflows`, `/cost`, and `/doctor` — fast tier plus a `--deep` tier with a **redacted** provider-key probe + a
-**read-only** MCP-status report that never connects/spawns (a security-review decision); the `name + args` slash
-dispatch + a context-aware footer hint-bar) landed **PR #62 (2026-06-30)**, behind [ADR-0056](docs/decisions/0056-cli-in-app-slash-command-system-and-manifest.md);
-and **2.5.E** (the reseat-less chat mode system — ask / plan / accept-edits / auto on `Shift+Tab` + `/mode` — the
-fail-closed per-tool `confirmAction` floor (`[y]/[a]/[n]` + a session once/always cache), the `Esc` mid-turn abort
-(EA7), and the host arms closing the 2.5.A deferral: a write-capable `fs` tier + **protected paths** refused in
-every mode incl. `auto`, the SSRF-hardened `egress` arm shared with media, and the `os` arm as a governed action
-class — wired live into `relavium chat`, one-shot `agent run`, and the Home, each activating the regime before its
-first turn) is ✅ **Done (PR #63, 2026-07-03)**, behind [ADR-0057](docs/decisions/0057-cli-chat-modes-and-per-tool-approval.md)
-(**Accepted** after the mandatory holistic security review); a same-PR chat-UX follow-up also landed — a host tool
-EXECUTION failure on the interactive surface (a file-not-found READ) is fed back to the model to recover
-(`recoverToolFailures`, scoped to IDEMPOTENT tools via a stamped `ToolExecutionError.recoverable`; a governed /
-side-effecting failure stays fail-fast) plus a static secret-free `tool_failed` chat hint. **With 2.5.E the CLI
-Consolidation spine (2.5.A/B/C/E) is complete.** The first experience-arm workstream **2.5.D** (chat input
-ergonomics + the `@`-mention / `!`-shell **pending-attachment "chip" model**) is ✅ **Done (PR #64, 2026-07-03)**,
-behind [ADR-0061](docs/decisions/0061-cli-input-layer-file-injection-and-shell-escape.md) (**Accepted** after a
-two-round maintainer security review): the accepted file / command output is queued as a compact chip and expanded
-into the shared UNTRUSTED nonce-fenced frame only at submit (byte-identical model context, a clean prompt); the
-`[chat]` command allowlist resolves as a **coupled unit** (a project setting either the exact or glob array owns
-the whole allowlist); and **2.5.F** (the ADR-0062 context-history commands) is ✅ **Done (PR #65, merged 2026-07-05)**,
-behind [ADR-0062](docs/decisions/0062-context-compaction-and-cli-history-commands.md): **`/clear`** — a host-level
-fresh-session lifecycle swap across `relavium chat`, `chat-resume`, and the in-Home chat, rebinding the same agent
-under a new `sessionId` (TTY-interactive only, rejected under `--json`/plain per ADR-0049) — plus the two
-compaction-moment UX polishes (a `session:compacting` "Summarizing…" event amending ADR-0036, and the footer
-context-fullness indicator via a pure `@relavium/llm` `contextWindowForModel` helper), completing the ADR-0062
-compaction story alongside the earlier-landed model-summarised `/compact` + deterministic `/trim` + automatic
-compaction. **2.5.G** (onboarding wizard + Home `/models` + the live model catalog) is ✅ **Done (PR #66,
-2026-07-07)** — its scope expanded to **Option A** (a **live** model catalog + a complete model-pricing story that
-governs cost) behind three ADRs ([ADR-0063](docs/decisions/0063-cli-config-write-contract.md)
-config-write, [ADR-0064](docs/decisions/0064-live-model-catalog.md) live catalog,
-[ADR-0065](docs/decisions/0065-provider-economics-and-extensibility.md) provider economics); all 12 steps landed,
-plus the post-2.5.G model-UX follow-up ([ADR-0059](docs/decisions/0059-cli-mid-session-model-reseat.md) mid-session reseat +
-[ADR-0066](docs/decisions/0066-normalized-reasoning-effort-control.md) reasoning-effort). With it **milestone
-M2.5-2** is reached. The additive lane **2.5.H** (reasoning render + live-turn feedback + an actionable error taxonomy — behind
-**EA6**, a dual-envelope `agent:reasoning` stream event that *amends* [ADR-0036](docs/decisions/0036-run-loop-substrate-event-bus-and-execution-host.md);
-no new top-level ADR) is ✅ **Done (PR #67, 2026-07-07)**, reaching milestone **M2.5-3** with 2.5.E; and the consolidation
-lanes **2.5.I** (regression harness + DB concurrency hardening: `loadFull` read-txn snapshot, `BEGIN IMMEDIATE` writes with a
-deterministic `SQLITE_BUSY` retry, the concurrent chat+run + cassette-chain + perf-budget e2es, an advisory Windows CI lane) and
-**2.5.J** (docs-debt: the accurate unencrypted-history posture per ADR-0050 + `NO_COLOR`/`FORCE_COLOR`/`--color` resolution) are
-✅ **Done (2.5-close-out, 2026-07-08)** — **reaching milestone M2.5-4, so Phase 2.5 is complete** — landed with the doable-now
-Batch A–E backlog (test-hardening; 2.5.H TUI polish; `AgentParseError` line/col; the ADR-0057 approval/security batch — `[c]`
-reject-with-reason + non-TTY policy + SCOPE-denial recovery + Ctrl+T-in-approval + the Trojan-Source bidi floor, behind an
-append-only ADR-0057 amendment; the profile-aware advertise-filter + the in-house `.gitignore` matcher), each implement → Opus →
-Sonnet with a security-review pass on the approval batch. Deferred to a focused follow-up (both refactor the security-sensitive
-`gate.ts` resume path): the `relavium budget resume` command + secret re-provide on gate resume; the session `{{ctx.*}}`
-interpolation stays with the Proposed [ADR-0060](docs/decisions/0060-session-ctx-prompt-interpolation.md) (Phase-2.6).
-For live status, per-PR history, milestone dates, and open obligations, see the canonical home
-[docs/roadmap/current.md](docs/roadmap/current.md); [README.md](README.md) is the public overview.
+**Status: Phase 1 is complete** (2026-06-21) — the engine runs end-to-end behind the
+`LLMProvider` seam with all three adapters, `AgentSession`, multimodal I/O, and the full
+run-loop. **Phase 2 (CLI) is feature-complete** (v0.1.1 release cut, publish pending):
+`relavium chat` / `chat-resume` / `agent run`, `relavium run` with `--json`, the
+inbound MCP client, and the full YAML lifecycle (`create`/`import`/`export`).
+**Phase 2.5 (CLI Consolidation) is complete** (M2.5-4, PR #69, 2026-07-08): the bare-invocation
+Home, the two-registry command system (`/` palette + shell commands), per-tool
+approval/modes (ask/plan/accept-edits/auto), `@`-mention file injection, context
+compaction, the onboarding wizard + live model catalog, reasoning rendering, and regression
+hardening. **Phase 2.6 (Conversational Authoring and the First-Class CLI) is next up**
+— a full-screen Home-managed CLI with conversational workflow authoring, management
+browsers, competitor-breadth tools, settings/theming/`en`+`tr` localization, and the
+run-ops resume follow-up.
+
+For live status, per-PR history, milestone dates, and open obligations, see the canonical
+home [docs/roadmap/current.md](docs/roadmap/current.md);
+[README.md](README.md) is the public overview;
+[docs/roadmap/phases/phase-2.6-conversational-authoring.md](docs/roadmap/phases/phase-2.6-conversational-authoring.md)
+has the full Phase 2.6 plan.
## Non-negotiable rules for AI agents
@@ -202,7 +129,7 @@ These apply to every AI agent in this repo, regardless of model, runner, or tool
## Build, test, lint
-Once Phase 0 lands the monorepo, all work goes through pnpm + Turborepo:
+All work goes through pnpm + Turborepo:
```bash
pnpm install
diff --git a/README.md b/README.md
index dc78c15f..13bf182a 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ machine unless you choose it.
## Why Relavium?
-- **Four surfaces, one engine.** Desktop (Tauri), CLI, VS Code, and (Phase 2) the web
+- **Four surfaces, one engine.** Desktop (Tauri), CLI, VS Code, and (planned) the web
portal run the _identical_ pure-TypeScript engine. No Python sidecar, no single-tool
lock-in — every surface is a first-class execution target.
- **A chat-to-workflow continuum.** Other tools make every session ephemeral. Relavium
@@ -23,16 +23,16 @@ machine unless you choose it.
- **You own your LLM seam.** Multi-provider routing with fallback chains
(`[claude → gpt-4o → gemini]`) is first-class through Relavium's own `@relavium/llm`
abstraction over the official provider SDKs — no Vercel AI SDK, no LangChain.
-- **Local-first by design.** Phase 1 ships with zero cloud and no account required; keys
- live in your OS keychain. BYOK-local stays first-class forever; Phase 2 _adds_ optional
- managed inference and cloud execution on the same engine.
+- **Local-first by design.** Zero cloud, no account required. Your API keys live in your
+ OS keychain — never in plaintext, never in logs. Optional managed inference and cloud
+ execution are planned extensions on the same engine.
- **Workflows are git objects.** `.relavium.yaml` files are diffable, reviewable,
PR-able, and shareable — team infrastructure, not a proprietary JSON blob or buried
Python.
- **Multimodal, end-to-end.** Image / audio / video as input and output — including
rule-driven media generation — flow through the same seam and engine.
-## Highlights (Phase 1)
+## Highlights
- **Chat-to-workflow export** — turn a proven session into a reusable `.relavium.yaml`.
- **Persistent, resumable agent sessions** — no run is ever ephemeral.
@@ -41,7 +41,12 @@ machine unless you choose it.
- **Checkpoint & resume** — pause and resume at any node boundary, even across processes.
- **Human gates with timeout policy** — pause for an approve / reject / input decision.
- **Per-node cost waterfall** — token and dollar attribution per node, per model.
-- **Local-first, zero-install posture** — BYOK, OS keychain, no sign-up in Phase 1.
+- **Interactive Home** — a bare `relavium` invocation opens a management center: start agents,
+ monitor runs, browse history, manage providers.
+- **MCP client** — agents consume tools from external MCP servers over stdio, HTTP, SSE, and
+ WebSocket, with secrets in the keychain.
+- **Live model catalog** — browse and switch models mid-session; per-model cost tracking.
+- **Local-first, zero-install posture** — BYOK, OS keychain, no sign-up.
## Getting started
@@ -76,7 +81,7 @@ flowchart TD
D[Desktop · Tauri]
C[CLI]
V[VS Code extension]
- P[Web portal · Phase 2]
+ P[Web portal · planned]
end
subgraph Engine["@relavium/core — one pure-TypeScript engine"]
WE[WorkflowEngine]
@@ -98,47 +103,39 @@ One engine, **two co-equal entry points** — `WorkflowEngine` (runs YAML pipeli
`AgentSession` (runs conversational chat) — sharing the same tool registry, the same
`@relavium/llm` multi-provider seam, and the same event bus. The engine has **zero
platform-specific imports**, so the same source runs in the Tauri WebView, the VS Code
-host, the Node CLI, and (Phase 2) a Bun server. Supporting packages: `@relavium/shared`
-(Zod contracts), `@relavium/db` (Drizzle — SQLite locally, PostgreSQL in Phase 2), and
+host, the Node CLI, and (planned) a Bun server. Supporting packages: `@relavium/shared`
+(Zod contracts), `@relavium/db` (Drizzle — SQLite locally, PostgreSQL planned), and
`@relavium/ui` (ReactFlow canvas + shadcn). See [docs/architecture/](docs/architecture/).
## Execution modes
One engine, three modes behind the one `LLMProvider` seam:
-- **Local (BYOK)** — Phase 1 default. Your keys, your machine, zero Relavium data.
-- **Managed inference** — Phase 2, opt-in. Relavium's metered keys; the engine still runs
- locally.
-- **Cloud execution** — Phase 2. Run workflows on cloud workers for 24/7 automation and
+- **Local (BYOK)** — the default. Your keys, your machine, zero Relavium data.
+- **Managed inference** — planned. Relavium's metered keys; the engine still runs locally.
+- **Cloud execution** — planned. Run workflows on cloud workers for 24/7 automation and
team sharing.
## Status
-**Phase 1 — Engine and LLM is complete** (2026-06-21): the engine runs end-to-end on
-local-first BYOK — workflow parsing, DAG execution, live streaming, checkpoint/resume,
-multi-provider failover, cost governance, and multimodal media I/O. **Phase 2 (the CLI) is
-feature-complete** — the CLI skeleton, config resolution, `relavium run` (wired to the engine), its
-`--json` CI machine-output contract, the engine regression harness, durable local run history, the
-provider/key commands (API keys in the OS keychain), the live `ink` streaming TUI, the human-gate
-prompt + out-of-band `relavium gate` resume, the read commands (`list` / `logs` / `status` / `gate list`)
-over durable history, and the published, cross-OS-installable `npm i -g relavium` binary (packaging &
-install verification) have landed (milestone **M3** reached; with packaging shipped, all seven Phase-3
-go/no-go exit criteria now hold). The first additive lanes have since landed too — media host-wiring
-(a generative media-output fixture runs end-to-end on the CLI); the full agent-first chat family: the
-`relavium chat` REPL plus session resume / list / export, a headless `chat --json` event stream, and a
-one-shot `agent run` with deterministic offline `--fixture` replay (the first user-facing `AgentSession`
-surface); and the **inbound MCP client** — agents consume external MCP servers' tools over stdio + the
-`http`/`sse`/`websocket` network transports (behind an SSRF floor and isolated keychain-resolved secrets),
-proven by a real-spawn end-to-end test; and the **YAML-authoring lifecycle** — `relavium create` (a wizard
-scaffolding an agent or a minimal single-agent workflow), `import`, and a share-safe `export` (re-serialized
-from the validated AST, no provider key by construction). With every in-phase workstream merged, the CLI is
-cut as **v0.1.1** (the public npm publish is the pending final maintainer step). **Phase 2.5 (CLI
-Consolidation) is complete** (milestone **M2.5-4**, 2026-07-08) — the conversational Home, the slash-command
-system, reseat-less chat modes with per-tool approval, context compaction, a live model catalog with provider
-economics, reasoning render, and the closing consolidation lanes (regression harness + DB-concurrency
-hardening + documentation reconciliation) have all landed. For live status and the full roadmap, see
-[docs/roadmap/current.md](docs/roadmap/current.md) and the
-[roadmap](docs/roadmap/README.md).
+The engine is complete and the CLI is feature-complete (cut as **v0.1.1**, npm publish pending).
+What's shipped:
+
+- **Agent sessions** — `relavium chat` with persistent, resumable, exportable multi-turn sessions.
+- **Workflow engine** — `relavium run` executes `.relavium.yaml` pipelines with live streaming,
+ checkpoint/resume, multi-model fallback, cost governance, and human gates.
+- **Interactive Home** — the bare `relavium` invocation opens a management center with a
+ slash-command system, per-tool approval modes (ask/plan/accept-edits/auto), and context compaction.
+- **MCP client** — agents consume tools from external MCP servers over stdio + network
+ transports, with secrets in the OS keychain.
+- **Live model catalog** — onboard with a wizard, browse models, switch mid-session, track
+ per-model cost.
+- **YAML authoring** — `relavium create` (wizard), `import`, and share-safe `export`.
+
+**Next: Phase 2.6 (Conversational Authoring and the First-Class CLI)** — a full-screen
+Home-managed CLI with conversational workflow authoring, management browsers, competitor-breadth
+tools, settings/theming, and `en`/`tr` localization. For live status and the full roadmap, see
+[docs/roadmap/current.md](docs/roadmap/current.md) and the [roadmap](docs/roadmap/README.md).
## Documentation
diff --git a/docs/roadmap/README.md b/docs/roadmap/README.md
index 2292540a..65a3a128 100644
--- a/docs/roadmap/README.md
+++ b/docs/roadmap/README.md
@@ -89,7 +89,7 @@ flowchart LR
P1E["Phase 1
engine + llm
CRITICAL PATH"]
P2["Phase 2
CLI
(first engine consumer)"]
P25["Phase 2.5
CLI consolidation
(Home + modes + root-cause)"]
- P26["Phase 2.6
conversational authoring
(@relavium/authoring)"]
+ P26["Phase 2.6
conversational authoring
+ first-class CLI"]
P3["Phase 3
desktop
(Tauri agent center)"]
P4["Phase 4
VS Code
(standalone ext)"]
P0 --> P1E --> P2 --> P25 --> P26 --> P3 --> P4
@@ -127,7 +127,7 @@ contract and a green CI gate.
| **1** | Build the two engine packages everything depends on — `@relavium/llm` (the provider-agnostic `LLMProvider` seam, 3 adapters, fallback runner, cost) and `@relavium/core` (YAML→DAG, runner, checkpoint/resume, retry) — proven end-to-end from a Node harness. **The critical path.** | Phase 0 | A Node harness runs a 3-node workflow end-to-end with live streaming, canonical events, checkpoint/resume, retry, and provider fallback; all 3 adapters pass conformance (fixtures on PR, live nightly); no vendor type crosses the seam; zero platform imports. | [phases/phase-1-engine-and-llm.md](phases/phase-1-engine-and-llm.md) |
| **2** | Ship the `relavium` CLI as the **first real engine consumer** and the engine's **regression harness** — `run / list / logs / gate / status`, an `ink` TUI, and a deterministic `--json` CI mode. | Phase 1 | A 3-node workflow runs via `relavium run` with the live TUI; durable history powers `list`/`logs`/`status`; human-gate pause/resume works interactively and via `relavium gate`; `--json` NDJSON is asserted by a green no-TTY CI regression harness; keys live only in the keychain (or documented fallback); `npm i -g relavium` verified on macOS/Linux/Windows. | [phases/phase-2-cli.md](phases/phase-2-cli.md) |
| **2.5** | Consolidate the CLI into a conversation-first **Home** at the bare invocation, with a slash palette, reseat-less chat modes + per-tool approval, onboarding, and reasoning rendering — plus the bounded engine amendments and docs-debt Phase 2 deferred. Fixes the capability-gap root cause (advertised-but-unwired tools → bare `internal`). | Phase 2 | `relavium` (TTY) opens Home; `--json`/CI/non-TTY keep help + exit `0` (regression-harness proven); the built-in agent's tools actually work and `capability_unavailable` never surfaces as `internal`; modes + per-tool approval + mid-turn abort ship with no one-key bypass; the required ADRs are Accepted. | [phases/phase-2.5-cli-consolidation.md](phases/phase-2.5-cli-consolidation.md) |
-| **2.6** | Promote the authoring core to a shared `@relavium/authoring` package, let a chat **author** standards-valid `.relavium.yaml` (model-generated, pre-flight-validated), switch models mid-session, and reach competitor-parity polish. Realises *"Start as an agent. Ship the workflow."* at the terminal. | Phase 2.5 | `@relavium/authoring` is the shared core (CLI consumes it; `create` runs the catalog-aware pre-flight); a conversational request yields a strict-valid workflow YAML; mid-session `/models` reseat works with the context-loss notice; `{{ctx.*}}` interpolation lands; the required ADRs are Accepted. | [phases/phase-2.6-conversational-authoring.md](phases/phase-2.6-conversational-authoring.md) |
+| **2.6** | Make the CLI a **first-class, Home-centric product** *(re-scoped 2026-07-08)*: a full-screen Home from which everything is managed (providers/keys, models, MCP, settings, workflows, agents, gates), a three-level run drill-down over attributed durable history, competitor-breadth tools (edit/search/find/todo/ask-user/working web search), settings + theming + `en`/`tr` localization, onboarding v2 with the Relavium-account stub, the run-ops resume follow-up — plus the original spine: promote the authoring core to a shared `@relavium/authoring` package and let a chat **author** standards-valid `.relavium.yaml`. Realizes *"Start as an agent. Ship the workflow. Own every run."* at the terminal. | Phase 2.5 | `relavium` (TTY) opens a full-screen Home managing everything — no routine task needs a shell subcommand, and the ADR-0049 `--json`/CI contract is byte-unbroken; a conversational request yields a strict-valid, catalog-validated workflow YAML; the toolbelt ships mode-gated behind a security-reviewed render contract; `{{ctx.*}}` lands; run history is attributed + drillable (list → run → node); `en`+`tr` ship with CI key-parity; the required ADRs are Accepted. | [phases/phase-2.6-conversational-authoring.md](phases/phase-2.6-conversational-authoring.md) |
| **3** | Ship the Tauri v2 desktop **agent-management center**: ReactFlow canvas, live run monitoring, local SQLite history, OS keychain — offline, no account. **NOT an IDE** ([ADR-0007](../decisions/0007-desktop-is-not-an-ide.md)). | Phase 2.6 | Signed builds on macOS/Windows/Linux launch to a working agent center; build + run a 3-node workflow on the canvas with live streaming and per-node cost — all offline; SQLite history supports trace/Gantt/replay/retry-from-node; gates pause/resume; no secret crosses into the WebView; ADR-0010 perf gate passes; per-platform Playwright e2e green. | [phases/phase-3-desktop.md](phases/phase-3-desktop.md) |
| **4** | Ship the standalone VS Code extension that **bundles `@relavium/core` in-process**: right-click run, sidebar + status-bar monitor, human-gate webview — with **no desktop app required**. Closes Product Phase 1. | Phase 3 | With only the extension installed: right-click a file → pick a workflow → watch streaming in the sidebar/status bar → approve a gate in a webview → run completes; same canonical events + same local SQLite history as CLI/desktop; keys only in `SecretStorage`; import-zone check passes; `relavium.relavium` published and installs on macOS/Windows/Linux. | [phases/phase-4-vscode.md](phases/phase-4-vscode.md) |
| **5** | **Product Phase 2 — managed inference (the first Phase-2 deliverable, Option B).** The opt-in `managed` execution mode: the engine stays **local**, only LLM egress is proxied through Relavium's gateway behind a new `ManagedGatewayProvider`, calling providers with Relavium's own keys and selling metered usage. Accounts/device-flow auth, key vault + pools, real-time metering (reserve→settle, UNIQUE `request_id`), quota/budget caps, merchant-of-record billing (prepaid + overage), cheap-default routing, abuse controls, no-prompt-logging, usage dashboard. **BYOK stays first-class.** | All of Phase 1 (0–4), shipped + battle-tested ([ADR-0008](../decisions/0008-local-first-phase-1-cloud-phase-2.md)); **plus R1**: provider-ToS confirmation + merchant-of-record + DPA/KVKK/GDPR ([ADR-0012](../decisions/0012-managed-inference-dual-mode.md)) | R1 gate met; a user logs in via device flow, **explicitly** opts into managed, and a workflow runs in `managed` mode with the engine still local and only egress proxied (no silent mode crossing); `ManagedGatewayProvider` is behind the unchanged seam (engine/types untouched); metering is idempotent (UNIQUE `request_id`) + nightly-reconciled; quota/hard-cap + merchant-of-record billing fire; no prompt logging by default; **BYOK unchanged and first-class.** | [phases/phase-5-managed-inference.md](phases/phase-5-managed-inference.md) |
diff --git a/docs/roadmap/current.md b/docs/roadmap/current.md
index 591a7970..a800e35b 100644
--- a/docs/roadmap/current.md
+++ b/docs/roadmap/current.md
@@ -7,9 +7,13 @@
- **Related**: [README.md](README.md), [phases/phase-2.5-cli-consolidation.md](phases/phase-2.5-cli-consolidation.md), [phases/phase-2-cli.md](phases/phase-2-cli.md), [deferred-tasks.md](deferred-tasks.md), [../project-structure.md](../project-structure.md), [../tech-stack.md](../tech-stack.md)
This page tracks what is active **right now** and the immediate next concrete actions.
-The full phase plan and the global milestone spine are in [README.md](README.md); the
-granular work breakdown for the active phase (now **Phase 2.5**) is in
-[phases/phase-2.5-cli-consolidation.md](phases/phase-2.5-cli-consolidation.md).
+The full phase plan and the global milestone spine are in [README.md](README.md).
+**Phase 2.5 (CLI Consolidation) is complete** (milestone **M2.5-4**, PR #69, 2026-07-08) — its
+breakdown, now historical, is in
+[phases/phase-2.5-cli-consolidation.md](phases/phase-2.5-cli-consolidation.md). The next phase,
+**Phase 2.6 — Conversational Authoring and the First-Class CLI** (Planned; unblocked by the 2.5
+close; re-scoped 2026-07-08), is in
+[phases/phase-2.6-conversational-authoring.md](phases/phase-2.6-conversational-authoring.md).
## Where we are
@@ -205,8 +209,8 @@ scrollback elision loss; + a one-shot `agent run` hint-leak). **With 2.5.E this
consolidation lanes **2.5.I** (regression harness + DB concurrency hardening — `loadFull` read-txn snapshot,
`BEGIN IMMEDIATE` writes with a deterministic `SQLITE_BUSY` retry, the concurrent chat+run + cassette-chain +
perf-budget e2es, an advisory Windows CI lane) and **2.5.J** (docs-debt: the accurate unencrypted-history
-posture per ADR-0050, and `NO_COLOR`/`FORCE_COLOR`/`--color` resolution) are ✅ **Done (2.5-close-out,
-2026-07-08)** — **reaching milestone M2.5-4, so Phase 2.5 is complete** — landed alongside the doable-now
+posture per ADR-0050, and `NO_COLOR`/`FORCE_COLOR`/`--color` resolution) are ✅ **Done (2.5-close-out, PR #69,
+2026-07-08)** — **reaching milestone M2.5-4, so Phase 2.5 is complete, merged to `main`** — landed alongside the doable-now
Batch A–E backlog (test-hardening; 2.5.H TUI polish; `AgentParseError` line/col; the ADR-0057 approval/security
batch — `[c]` reject-with-reason, non-TTY policy, SCOPE-denial recovery, Ctrl+T-in-approval, the Trojan-Source
bidi floor, behind an append-only ADR-0057 amendment; the profile-aware advertise-filter + the in-house
@@ -238,8 +242,15 @@ keychain no-raw-key IPC test.
## Not started yet
-The surfaces and the cloud — everything after the engine critical path: the desktop app
-(Phase 3) and the VS Code extension (Phase 4), then **Product Phase 2** — first **managed
+The immediate next phase is **Phase 2.6 — Conversational Authoring and the First-Class CLI**
+([phase-2.6-conversational-authoring.md](phases/phase-2.6-conversational-authoring.md), Planned,
+unblocked by the 2.5 close and **re-scoped 2026-07-08** from maintainer UX findings + a competitor
+research pass + the deferred-tasks triage): a full-screen, Home-managed CLI (browsers for
+workflows/runs/agents, provider + MCP + settings management, onboarding v2 with the Relavium-account
+stub), competitor-breadth tools under the governance floor, settings/theming/`en`+`tr` localization,
+the run-ops resume follow-up — plus the original spine: the shared `@relavium/authoring` package and
+a chat that **authors** standards-valid `.relavium.yaml`. Then the surfaces and the cloud —
+everything after the engine critical path: the desktop app (Phase 3) and the VS Code extension (Phase 4), then **Product Phase 2** — first **managed
inference** ([phase-5-managed-inference.md](phases/phase-5-managed-inference.md), the opt-in
`managed` gateway, engine still local), then the **cloud execution layer and web portal**
([phase-6-cloud-execution-portal.md](phases/phase-6-cloud-execution-portal.md)), the two
diff --git a/docs/roadmap/deferred-tasks.md b/docs/roadmap/deferred-tasks.md
index 4fec707f..3fd55a36 100644
--- a/docs/roadmap/deferred-tasks.md
+++ b/docs/roadmap/deferred-tasks.md
@@ -2,7 +2,9 @@
> Status: Living
-> Last updated: 2026-07-05
+> Last updated: 2026-07-08 — the Phase-2.6 rewrite triaged every open item; the now-doable ones carry a
+> **Scheduled → 2.6.X** marker pointing at their [phase-2.6](phases/phase-2.6-conversational-authoring.md)
+> workstream (they stay unchecked until the PR that lands them).
- **Related**: [current.md](current.md), [README.md](README.md), [phases/phase-0-foundations.md](phases/phase-0-foundations.md)
@@ -32,6 +34,7 @@ Severity is the review's verified rating. Check an item off in the PR that resol
a superseding ADR**. Recommendation: ship (A) now, do (B) in its own governed PR. **Full analysis, current
version table, per-dependency verdicts, migration plans, and open questions:
[phases/node-runtime-upgrade.md](phases/node-runtime-upgrade.md).** Out of scope for Phase 2.5.F.
+ **Scheduled → 2.6.F** (both halves: the immediate dev/CI bump + the governed floor decision).
*(package.json engines + .nvmrc + pnpm-workspace catalog @types/node + tech-stack.md; cross-phase)*
@@ -57,10 +60,10 @@ Severity is the review's verified rating. Check an item off in the PR that resol
URL validation are construction-time / seam-ingestion-time policy; they catch malformed URLs but cannot
catch DNS rebinding or a public hostname resolving to a private IP. **Scope split (resolving the earlier "Phase 2" framing):** the **media** url-carrier mechanism is **pulled into 1.AF** on a new bytes-shaped media-egress capability ([ADR-0043](../decisions/0043-media-egress-failover-rematerialization-ssrf.md)); the **CLI tool** `EgressCapability.fetch` **landed in 2.5.E** ([ADR-0057](../decisions/0057-cli-chat-modes-and-per-tool-approval.md)) — `apps/cli/src/engine/tool-host/egress.ts` over the shared `connectValidated` connect-by-validated-IP mechanism (`packages/db/src/safe-egress.ts`), with the Host/`:authority`-header strip; the **desktop** surface's fetch hook still lands when the desktop implements it. *(packages/core/src/tools/types.ts; security-review.md; media → 1.AF/ADR-0043; CLI tool → 2.5.E/ADR-0057; desktop → surface fetch hook)*
- [ ] **MCP SDK network transport — upgrade to connect-by-validated-IP ([ADR-0053](../decisions/0053-mcp-network-transport-egress-security.md) §2).** 2.R ships **pre-connect host validation** as the floor for the `http` (Streamable HTTP) / `websocket` MCP transports — the `@modelcontextprotocol/sdk` opens its **own** socket, architecturally distinct from the `EgressCapability.fetch` hook above. When the SDK transport exposes an injectable `fetch`/dialer hook, upgrade to **connect-by-validated-IP**: resolve DNS → validate the IP against the shared range-block primitive → connect to that IP, re-validating on each redirect hop — closing the residual DNS-rebind window. **The dialer + redirect re-validation MUST enforce the authored `host:port`** (ADR-0053 §3 / SEC-EGRESS-3), not just the host: an `allow_local_endpoint` server is permitted exactly its declared `host:port`, so a resolved/redirected target on a *different* port of the same permitted-private host (`:6379`/`:5432`/`:22`/the Docker socket) must be re-blocked. (2.R's pre-connect floor is host:port-safe by construction — the SDK dials exactly the one authored url — so this constraint binds the dialer, not the floor.) Each MCP network mechanism gets a dedicated security-review pass when it lands. *(packages/mcp/src; ADR-0053 §2/§3; ADR-0043 mechanism)*
-- [ ] **MCP `stdio` spawn — import-trust/consent gate + `npx` dependency pinning ([ADR-0052](../decisions/0052-inbound-mcp-client-package-lifecycle-registration.md) §2).** Spawning a declared `stdio` MCP server runs arbitrary local code / an `npx`-installed package. 2.R treats a server declared in the user's **own** committed YAML as author trust; the **imported/shared untrusted workflow** case is out of baseline scope. When the import/share path matures, gate the first spawn of a server from an untrusted-provenance `.relavium.yaml` behind explicit consent, and pin the `npx` package version/integrity for the built-in auto-install servers. *(packages/mcp/src; apps/cli; ADR-0052 §2; ADR-0029 trust model)*
+- [ ] **MCP `stdio` spawn — import-trust/consent gate + `npx` dependency pinning ([ADR-0052](../decisions/0052-inbound-mcp-client-package-lifecycle-registration.md) §2).** Spawning a declared `stdio` MCP server runs arbitrary local code / an `npx`-installed package. 2.R treats a server declared in the user's **own** committed YAML as author trust; the **imported/shared untrusted workflow** case is out of baseline scope. When the import/share path matures, gate the first spawn of a server from an untrusted-provenance `.relavium.yaml` behind explicit consent, and pin the `npx` package version/integrity for the built-in auto-install servers. **Scheduled → 2.6.B** (the authoring/import path this consent gate protects matures there). *(packages/mcp/src; apps/cli; ADR-0052 §2; ADR-0029 trust model)*
- [x] **MCP host boundary — strip `McpConnectError.cause` from `--json` / event output (2.R Step 3, [ADR-0052](../decisions/0052-inbound-mcp-client-package-lifecycle-registration.md) §2).** *Resolved in the 2.R Step 3 host wiring:* `startMcpClientFailLoud` (apps/cli/src/engine/mcp-servers.ts) wraps an `McpError` into a typed `CliError` whose message is the secret-free MCP summary with **no** `{ cause }` attached, and the top-level `--json` renderer (apps/cli/src/process/render-error.ts) serializes only `{ type, code, message }` — never `cause`. Regression-locked by `run.test.ts` (`expect(err.cause).toBeUndefined()`). *(apps/cli; packages/mcp/src/errors.ts; 2.R Step 3)*
-- [ ] **MCP network transport — header-based auth ([ADR-0052](../decisions/0052-inbound-mcp-client-package-lifecycle-registration.md) §6).** 2.R injects `{{secrets.*}}` only into a **stdio** child's `env`; the network (`http`/`websocket`) specs carry only `{ url }`, so a network server's `env` is **rejected at parse** (fail-closed, never silently dropped). When network MCP servers need credentials, add a host-resolved auth-header field (e.g. `Authorization: 'Bearer {{secrets.}}'`) wired through the SDK transport's `requestInit`/headers, resolved from the same isolated `mcp-secret:*` namespace and never logged/serialized. *(packages/mcp/src/sdk-http.ts; apps/cli/src/engine/mcp-servers.ts; ADR-0052 §6)*
-- [ ] **MCP follow-ups (non-security).** A durable cross-invocation **tool-list cache** (mcp-integration.md ~1h per-`(command,args)`, with a transport-covering key) — 2.R re-runs discovery per process ([ADR-0052](../decisions/0052-inbound-mcp-client-package-lifecycle-registration.md) §3); and a generalized **`SecretResolver`** seam beyond the 2.R `mcp-secret:*` keychain namespace ([ADR-0052](../decisions/0052-inbound-mcp-client-package-lifecycle-registration.md) §6); and reconciling the `types.ts` `ToolId` "register dynamically" comment to "host-side assembled" when 2.R touches `packages/core`; and **mid-call abort propagation** — the engine's `AbortSignalLike` is not forwarded to the in-flight MCP `tools/call` (the SDK transport wants a DOM `AbortSignal`), so a turn cancel tears the connection down but does not cancel an in-flight call (`@relavium/mcp` `manager.ts`). *(packages/mcp/src; packages/core; Phase-3)*
+- [ ] **MCP network transport — header-based auth ([ADR-0052](../decisions/0052-inbound-mcp-client-package-lifecycle-registration.md) §6).** 2.R injects `{{secrets.*}}` only into a **stdio** child's `env`; the network (`http`/`websocket`) specs carry only `{ url }`, so a network server's `env` is **rejected at parse** (fail-closed, never silently dropped). When network MCP servers need credentials, add a host-resolved auth-header field (e.g. `Authorization: 'Bearer {{secrets.}}'`) wired through the SDK transport's `requestInit`/headers, resolved from the same isolated `mcp-secret:*` namespace and never logged/serialized. **Scheduled → 2.6.I.** *(packages/mcp/src/sdk-http.ts; apps/cli/src/engine/mcp-servers.ts; ADR-0052 §6)*
+- [ ] **MCP follow-ups (non-security).** A durable cross-invocation **tool-list cache** (mcp-integration.md ~1h per-`(command,args)`, with a transport-covering key) — 2.R re-runs discovery per process ([ADR-0052](../decisions/0052-inbound-mcp-client-package-lifecycle-registration.md) §3); and a generalized **`SecretResolver`** seam beyond the 2.R `mcp-secret:*` keychain namespace ([ADR-0052](../decisions/0052-inbound-mcp-client-package-lifecycle-registration.md) §6); and reconciling the `types.ts` `ToolId` "register dynamically" comment to "host-side assembled" when 2.R touches `packages/core`; and **mid-call abort propagation** — the engine's `AbortSignalLike` is not forwarded to the in-flight MCP `tools/call` (the SDK transport wants a DOM `AbortSignal`), so a turn cancel tears the connection down but does not cancel an in-flight call (`@relavium/mcp` `manager.ts`). **The tool-list-cache + mid-call-abort halves are scheduled → 2.6.I** (the rest stays opportunistic). *(packages/mcp/src; packages/core; Phase-3)*
- [ ] **Streaming media triad (`media_start`/`media_delta`/`media_end`) — host-deferred ([ADR-0046](../decisions/0046-inline-media-out-via-generate-streaming-triad-deferred.md) §4).**
1.AG Section B delivers inline media-out through the non-streaming `generate()` path (the in-flight
`media` `ContentPart` is de-inlined at `#emitDurable`). The **streaming** triad stays RESERVED: its Node
@@ -76,13 +79,14 @@ Severity is the review's verified rating. Check an item off in the PR that resol
Responses API `image_generation` built-in tool — a **separate request surface** the Chat-Completions
adapter does not call. Wire the Responses-API path (request + `image_generation_call` output-item parse →
the already-defined providerExecuted media shape) when a Phase-1 model needs it. *(packages/llm/src/adapters/openai.ts; post-1.AG)*
-- [ ] **Per-model `media_surface` lookup — HOST WIRING deferred (1.AG Section C → 1.AH).** Section C added
- `AgentRunnerDeps.resolveMediaSurface?(model) → MediaSurface` (the inline-vs-generative routing discriminator,
- default `'chat'`; tests inject it). The production wiring — the host reading `model_catalog.media_surface` (the
- column landed in Section A) and supplying the lookup — is **1.AH host-wiring**, exactly like the D12/D15/D17
- host-wiring obligations. Until then `resolveMediaSurface` is absent and **every** model routes inline (`'chat'`),
- so no generative model is runtime-reachable in Phase 1; the engine mechanism + the OpenAI-image adapter are proven
- via injected-surface tests. *(packages/core/src/engine/agent-runner.ts; host catalog read → 1.AH)*
+- [x] **Per-model `media_surface` lookup — wired by the CLI (✅ PR #52, 2.S; verified + checked off 2026-07-08).**
+ Section C added `AgentRunnerDeps.resolveMediaSurface?(model) → MediaSurface` (the inline-vs-generative routing
+ discriminator, default `'chat'`; tests inject it). The production wiring — the host reading
+ `model_catalog.media_surface` and supplying the lookup — landed with 2.S: `media-wiring.ts` supplies
+ `catalog.resolveMediaSurface` (the `model_catalog` projection) and `build-engine.ts` threads it into
+ `AgentRunnerDeps`, so a generative model routes by its catalog surface on the CLI. The sibling D15/D17/D8
+ host-wiring items were checked off at PR #52; this one was missed then. The desktop/VS Code surfaces reuse the
+ same injectable port (Phase-3/Phase-4). *(apps/cli/src/engine/media-wiring.ts + build-engine.ts; PR #52)*
- [ ] **Verified generative model rates + `MODEL_PRICING` rows (1.AG Section C → 1.AH).** The Section C cost
mechanism (pre-egress estimate + the one realized `cost:updated`) reuses `estimateMediaCost`/`mediaCost`, which
**degrade to 0 on a missing rate** (H4). No generative model rows were added to `MODEL_PRICING` — fabricating
@@ -291,11 +295,13 @@ Severity is the review's verified rating. Check an item off in the PR that resol
- [ ] **Run-submission idempotency / request-dedup (open — evaluate carefully).** Distinct from the content-addressed
media cache and any managed-mode metering `request_id`: should an identical run-create request be
de-duplicated so a double-submit does not start two runs? **Open:** a Phase-1 engine run-create hook vs a
- surface concern. Low-stakes; recorded so it is not lost. *(WorkflowEngine run-create; 1.N)*
+ surface concern. Low-stakes; recorded so it is not lost. **Scheduled → 2.6.H** (the Home can start a
+ workflow there, making double-submit real). *(WorkflowEngine run-create; 1.N)*
- [ ] **i18n CI key-parity + data/code separation (Phase 2+ surface).** When the desktop / CLI / VS Code
surfaces add i18n: a CI test that **fails** on a missing/extra translation key (parity), **zero conditional
logic in translation data** (data ≠ code), and a dead/unused-string lint. Recorded now; lands with the
- Phase-2/3/4 surface i18n work (no consumer yet). *(a `docs/standards/` entry or skill; Phases 2–4)*
+ Phase-2/3/4 surface i18n work (no consumer yet). **Scheduled → 2.6.L** (the CLI `en`+`tr` catalog is the
+ first consumer). *(a `docs/standards/` entry or skill; Phases 2–4)*
- [ ] **Pre-egress token-estimate accuracy — watch item (1.AC).** The ADR-0028 governor blocks on
`worstCaseNextEstimate(maxTokens)` from `[defaults].max_tokens_estimate`. Record the open
question: does the estimate need provider-accurate token counting (from the seam's model meta /
@@ -375,7 +381,8 @@ Severity is the review's verified rating. Check an item off in the PR that resol
`{{ inputs }}`/`{{ ctx }}` in system fields must add a parse-time gate **rejecting** untrusted
`run.outputs`/`read_file` references there (analogous to the secret-taint gate — do **not** drop the field
from `nodeReferenceSites`, which would remove the existing secret-leak protection). A pinning test already
- asserts an untrusted `run.outputs` value never reaches the system string. *(medium · packages/core/src/interpolation/analyze.ts, collect.ts; SEC-1)*
+ asserts an untrusted `run.outputs` value never reaches the system string.
+ **Scheduled → 2.6.D.** *(medium · packages/core/src/interpolation/analyze.ts, collect.ts; SEC-1)*
- [ ] **Multimodal tool-result through the adjacent-message + redaction paths** — all 1.O coverage exercises
text/JSON tool args + content; confirm image/media tool-result blocks survive the Anthropic adjacent-role
merge (no dropped blocks / no double-merge with `stripReasoningParts`) and the redaction path. *(low · packages/llm/src/adapters/anthropic.ts; 1.AF)*
@@ -447,17 +454,17 @@ Severity is the review's verified rating. Check an item off in the PR that resol
the target gate's decision immediately, but a *remaining* pending gate (multi-gate run, crash-while-paused)
is rehydrated without re-arming its timer, so its deadline is lost until the next restart. The data needed
(`timeoutAction` + `expiresAt`) is now persisted on `human_gate:paused` (PR #22), so no backfill — Phase-2
- crash-reconciliation re-arms from the log against a real clock. *(low · packages/core/src/engine/engine.ts `#seedFromCheckpoint`; Phase-2)*
+ crash-reconciliation re-arms from the log against a real clock. **Scheduled → 2.6.K.** *(low · packages/core/src/engine/engine.ts `#seedFromCheckpoint`; Phase-2)*
- [ ] **Content-level workflow-identity guard on resume** — `resumeFromCheckpoint` compares the surrogate
`workflowId` (catches resuming a *different* workflow → `workflow_mismatch`), but not a *same-slug,
edited-content* workflow. The stronger guard rides on the frozen `runs.workflow_definition_snapshot` column
([database-schema.md](../reference/desktop/database-schema.md)) — a Phase-2 persistence concern wired with
- the real `RunStore`, not the event-derived in-memory state. *(low · packages/core/src/engine/engine.ts; Phase-2)*
+ the real `RunStore`, not the event-derived in-memory state. **Scheduled → 2.6.H.** *(low · packages/core/src/engine/engine.ts; Phase-2)*
- [ ] **Cross-process concurrent gate-resolve (TOCTOU)** — idempotent re-delivery holds within a process
(`#resolvedGates`) and across processes once the prior process's `human_gate:resumed` is persisted (the
checkpoint reconstructs `resolvedGateIds`). The residual window — two processes loading the *same* still-pending
gate before either persists — is closed by a store-level uniqueness constraint on `human_gate:resumed` per
- `(runId, gateId)`, a Phase-2 SQLite/cloud-store guarantee, not the in-memory reference. *(low · checkpoint.ts/engine.ts; Phase-2 store)*
+ `(runId, gateId)`, a Phase-2 SQLite/cloud-store guarantee, not the in-memory reference. **Scheduled → 2.6.H.** *(low · checkpoint.ts/engine.ts; Phase-2 store)*
## AgentSession (1.V) follow-ups
@@ -482,7 +489,8 @@ Severity is the review's verified rating. Check an item off in the PR that resol
pass-through but does **not** handle a `BudgetPauseError`: a non-`AgentTurnError` throw rolls the user message
back and re-raises (a session has no pause/resume gate machinery in 1.V). The run path maps a budget pause to
a `paused` node outcome via the human-gate seam; a budgeted session needs the analogous suspend/resume
- lifecycle. Wire it when sessions gain a budget (surface phases). *(medium · packages/core/src/engine/agent-session.ts; ADR-0028)*
+ lifecycle. Wire it when sessions gain a budget (surface phases). **Scheduled → 2.6.K** (with the EA4-ride
+ sibling below). *(medium · packages/core/src/engine/agent-session.ts; ADR-0028)*
- [ ] **Per-session tool narrowing (ADR-0029 narrow-only).** 1.V grants the bound agent's `tools` verbatim; a
session cannot yet **narrow** them per-session (it may only ever narrow, never widen). Add a session-level
narrow when a surface needs to restrict a session's tools below the agent's grant.
@@ -518,7 +526,7 @@ Severity is the review's verified rating. Check an item off in the PR that resol
> untrusted injection) shipped. These bounded pieces were deliberately deferred (each is additive; the
> confidentiality floor + jail + injection framing hold without them):
-- [x] **Advisory `.gitignore` / `.relaviumignore` completion trim — DONE (2.5-close Step 15, Batch E).** A
+- [x] **Advisory `.gitignore` / `.relaviumignore` completion trim — DONE (2.5-close Step 15, Batch E; PR #69).** A
dependency-free, ReDoS-safe in-house matcher ([gitignore.ts](../../apps/cli/src/render/tui/gitignore.ts)) folds
the workspace-root `.gitignore` + `.relaviumignore` into the `@`-mention candidate filter (comments/blanks, `!`
negation, dir-only `/`, anchoring, `*`/`**`/`?` globs; a LINEAR two-pointer glob matcher — no regex, so no
@@ -527,10 +535,10 @@ Severity is the review's verified rating. Check an item off in the PR that resol
fs-capability enforcement. Documented subset limits: nested per-dir ignore files + `[a-z]` char classes deferred
(they only UNDER-hide, never a security gap). *(apps/cli/src/render/tui/gitignore.ts + mention.ts; ADR-0061)*
- [ ] **`@`-glob / directory expansion.** Single-file injection ships; `@src/**/*.ts` glob / whole-directory
- expansion is deferred (ADR-0061). *(low · apps/cli/src/render/tui/mention.ts)*
+ expansion is deferred (ADR-0061). **Scheduled → 2.6.E.** *(low · apps/cli/src/render/tui/mention.ts)*
- [ ] **`@`-mention of a binary / media file.** The reader fail-closes on a binary file (parity with `read_file`);
a durable media-handle injection path (ADR-0031) is a follow-up. *(low · apps/cli/src/render/tui/mention.ts)*
-- [x] **Strip Unicode bidi/format controls at the shared display boundary — DONE (2.5-close Step 14, D-5).** The
+- [x] **Strip Unicode bidi/format controls at the shared display boundary — DONE (2.5-close Step 14, D-5; PR #69).** The
shared `stripTerminalControls` (chat-projection.ts) now strips the Trojan-Source reordering family (U+202A–202E,
U+2066–2069, LRM/RLM/ALM) at every display boundary; ZWJ/ZWNJ preserved; the source uses `\u` escapes (no literal
bidi bytes). *(apps/cli/src/render/tui/chat-projection.ts)*
@@ -541,17 +549,17 @@ Severity is the review's verified rating. Check an item off in the PR that resol
> reseat-less mode system + per-tool approval + mid-turn abort + the host arms shipped. These bounded pieces
> were deliberately deferred (each is additive, none blocks the mode system's security guarantees):
-- [x] **`[c]` reject-with-typed-reason approval prompt — DONE (2.5-close Step 14, D-1).** A `[c]` at the approval
+- [x] **`[c]` reject-with-typed-reason approval prompt — DONE (2.5-close Step 14, D-1; PR #69).** A `[c]` at the approval
prompt opens a keyboard-owning reason-input sub-mode (both `relavium chat` + the Home); on submit it rejects with
the sanitized + 300-char-bounded reason via the existing `ToolApprovalDecision.reject.reason` seam. The floor is
unchanged. *(apps/cli/src/render/tui/chat-input.ts + chat-ink.tsx + home-controller.ts)*
-- [x] **Conversationally recover from a SCOPE denial in chat — DONE (2.5-close Step 14, D-3).** The `recoverable`
+- [x] **Conversationally recover from a SCOPE denial in chat — DONE (2.5-close Step 14, D-3; PR #69).** The `recoverable`
flag moved to the base `ToolDispatchError`; exactly two `tool_denied`s opt in — `ToolPolicyError('media_scope_denied')`
and the fs **pure scope-tier escape** (`FsScopeDeniedError` from `assertInScope`) — so on the `recoverToolFailures`
surfaces the model is fed the denial and adapts to an in-bounds path. The confidentiality / protected-path / symlink
/ SSRF / user / guardrail denials stay FATAL. *(packages/core/src/tools/errors.ts; apps/cli/src/engine/tool-host/fs.ts; ADR-0057)*
- [x] **Plain / non-TTY non-interactive approval policy — DONE (2.5.E "High 9" + consolidated in 2.5-close Step 14,
- D-2).** A non-interactive driver (plain non-TTY / `--json` / one-shot `agent run`) uses the one canonical
+ D-2; PR #69).** A non-interactive driver (plain non-TTY / `--json` / one-shot `agent run`) uses the one canonical
`nonInteractiveApprovalPrompt` — every governed dispatch is DENIED (never a hang, never an auto-approve).
*(apps/cli/src/chat/chat-mode.ts; apps/cli/src/commands/chat.ts + agent-run.ts)*
- [ ] **Approval-consent-line zero-width hardening (2.5-close Step 14 security-review, optional).** The shared render
@@ -559,21 +567,21 @@ Severity is the review's verified rating. Check an item off in the PR that resol
highest-trust surface — the approval consent line's target (`formatApprovalTarget` → `sanitizeInline`) — still
passes NON-reordering zero-width chars (ZWSP U+200B / word-joiner U+2060 / BOM U+FEFF), which the provider-URL echo
already strips. Running the stricter zero-width superset on the consent-line target would be defense-in-depth. Not
- a CVE gap (those chars cannot reorder a command to masquerade). *(low · apps/cli/src/render/tui/chat-projection.ts)*
+ a CVE gap (those chars cannot reorder a command to masquerade). **Scheduled → 2.6.M** (with tool-render v2). *(low · apps/cli/src/render/tui/chat-projection.ts)*
- [ ] **Extract the `[c]` reason-capture to a shared pure reducer (2.5-close Step 14 review, test-parity).** The
reason-capture keystroke glue is duplicated inline in `ChatApp` (chat-ink.tsx) and the Home controller; the shared
primitives (`reduceApprovalKey`, `sanitizeApprovalReason`, `reduceEditorMotion`) are unit-tested and the Home path
has an integration test, but the ChatApp inline copy has no direct test (matching the existing no-ChatApp-integration
boundary). Extracting the capture step to one pure reducer (like the mention/effort submodes) would let both
- surfaces test the same function. *(low · apps/cli/src/render/tui/chat-ink.tsx + home-controller.ts)*
+ surfaces test the same function. **Scheduled → 2.6.M** (with tool-render v2). *(low · apps/cli/src/render/tui/chat-ink.tsx + home-controller.ts)*
- [ ] **Live `web_search` / `http_request` egress credential resolver.** `assembleToolEnv` accepts an
`egressCredentialResolver` and the egress arm attaches it host-side as a Bearer, but the chat/Home session-host does
not yet wire it to the keychain — so a `web_search` needing a provider key currently 401s (surfaced, never a crash).
- Wire the provider-key resolver through when the chat surface needs authenticated egress. *(low · apps/cli/src/chat/session-host.ts)*
+ Wire the provider-key resolver through when the chat surface needs authenticated egress. **Scheduled → 2.6.M** (the `web_search` activation). *(low · apps/cli/src/chat/session-host.ts)*
- [ ] **Session-level budget pause/resume (rides the EA4 machine).** The EA4 pause/resume state landed for mid-turn
abort + approval; the ADR-0028 session budget `pause_for_approval` can now ride the same machine (today a chat
cost-cap trip settles the turn loudly as `budget_exceeded` — the REPL is the approval gate). See also the 1.V
- session-budget follow-up above. *(medium · apps/cli/src/chat + agent-session.ts)*
+ session-budget follow-up above. **Scheduled → 2.6.K.** *(medium · apps/cli/src/chat + agent-session.ts)*
- [ ] **`relavium budget resume` CLI command (2.5-close Step 15 / Batch E — DEFERRED to a focused follow-up).** The
engine ALREADY supports resuming a budget-paused run (`engine.resume(runId, budgetGateId, decision)`,
budget-governor.ts / checkpoint.ts `isBudgetGate`), and `relavium gate` deliberately EXCLUDES budget gates
@@ -582,9 +590,11 @@ Severity is the review's verified rating. Check an item off in the PR that resol
resume machinery (so the clean form extracts a shared resume core rather than duplicating). Low, dependency-free.
**Why deferred (maintainer call, 2026-07-08):** it modifies the security-sensitive `gate.ts` cross-process resume
path and is coupled to the secret-re-provide follow-up below (both refactor that path), so both are best landed
- together with fresh context rather than at the tail of the 2.5-close session. *(low · apps/cli/src/commands/{gate,budget}.ts + manifest.ts + dispatch.ts; ADR-0028)*
+ together with fresh context rather than at the tail of the 2.5-close session. **Scheduled → 2.6.K** (that
+ focused follow-up). *(low · apps/cli/src/commands/{gate,budget}.ts + manifest.ts + dispatch.ts; ADR-0028)*
- [ ] **`project`-tier `extraRoots` allowlist (carried from 2.5.A).** The `project` fs tier behaves as
- workspace-only until the path-allowlist lands (it can only NARROW the jail, never open a hole). *(low · apps/cli/src/engine/tool-host/assemble.ts)*
+ workspace-only until the path-allowlist lands (it can only NARROW the jail, never open a hole).
+ **Scheduled → 2.6.M** (the `[chat].extra_roots` config key is the missing source). *(low · apps/cli/src/engine/tool-host/assemble.ts)*
- [ ] **fs hard-link aliasing — the pnpm virtual-store read exemption (accepted residual, ADR-0057 review record).**
The hard-link aliasing READ guard (`st.nlink > 1` ⇒ refused) is disabled ONLY for pnpm's `node_modules/.pnpm/…`
virtual store (`isPnpmStorePath`), so dependency-source reads work on Linux (where pnpm hard-links). The bounded
@@ -601,7 +611,7 @@ Severity is the review's verified rating. Check an item off in the PR that resol
fs, a host for egress, a server for mcp) would make `always` track what the user actually reviewed. Pairs with:
surface the MCP server/tool in `ToolActionPreview` (today `mcp_call`/`web_search` return a BLANK preview, so
F3 correctly forbids caching their `always`) — a structured `{mcpServer,mcpTool}` preview would turn the
- blank-check downgrade into a real, reviewable, cacheable per-server grant. *(medium · apps/cli/src/chat/chat-mode.ts + packages/core/src/tools/{types,registry,builtins}.ts + run-event.ts)*
+ blank-check downgrade into a real, reviewable, cacheable per-server grant. **Scheduled → 2.6.M.** *(medium · apps/cli/src/chat/chat-mode.ts + packages/core/src/tools/{types,registry,builtins}.ts + run-event.ts)*
- [ ] **fs `.relavium` sensitive-read/write segment vs. the `~/.relavium/tmp` sandboxed root (latent).** Both the
read floor (`SENSITIVE_READ_DIR_SEGMENTS`) and the write floor (`PROTECTED_DIR_SEGMENTS`) match a `.relavium`
segment anywhere, so they would refuse the sanctioned `tmpDir` scratch root — inert today (no call site wires
@@ -642,7 +652,7 @@ Severity is the review's verified rating. Check an item off in the PR that resol
writer committing between them could yield a run row + event/step reads from different snapshots. Lower
impact than the session case: run history is **event-sourced** and the checkpoint fold tolerates partial
state, so a torn read self-heals on the next fold. If tightened, wrap the caller-level reconstruction in one
- read transaction (as `loadFull` now does). *(low · packages/db run-history-store consumers + the resume
+ read transaction (as `loadFull` now does). **Scheduled → 2.6.H.** *(low · packages/db run-history-store consumers + the resume
caller; surfaced during 2.5.I S1 review)*
- [ ] **The CLI chat persister writes a turn non-atomically — messages then session totals in separate
auto-committed statements.** `apps/cli/src/chat/persister.ts` appends the user + assistant messages and then
@@ -651,7 +661,7 @@ Severity is the review's verified rating. Check an item off in the PR that resol
guarantees *snapshot* consistency (both reads see one DB snapshot) but not *turn* atomicity — a snapshot can
observe messages ahead of their totals. To make "totals always match the returned messages" hold, wrap each
turn's message-appends + `updateSession` in one host-side `db.transaction` (BEGIN IMMEDIATE). Bounded, host-side.
- *(low · apps/cli/src/chat/persister.ts; surfaced during 2.5.I S2 review)*
+ **Scheduled → 2.6.H.** *(low · apps/cli/src/chat/persister.ts; surfaced during 2.5.I S2 review)*
- [ ] **`relavium run` maps any `run:paused` to exit 3 (gate-paused); revisit when media host-wiring lands.**
`run.ts` returns `EXIT_CODES.gatePaused` (3) for any `run:paused`, which is correct in 2.D because a
human gate is the **only** `run:paused` source (no `mediaStore`/media-job host is wired, so a media-only
@@ -659,7 +669,7 @@ Severity is the review's verified rating. Check an item off in the PR that resol
1.AG §D — can never be emitted). When the media host capability lands (the same surface as the deferred
media-egress work, ~2.S), a media-only park would be reported as "gate-paused" with no gate; at that point
decide whether exit 3 (and the rendered message) should distinguish a gate park from a media park.
- *(low · apps/cli/src/commands/run.ts; media host-wiring / 2.S)*
+ **Scheduled → 2.6.K.** *(low · apps/cli/src/commands/run.ts; media host-wiring / 2.S)*
- [ ] **`relavium budget resume [--approve | --abort]` is documented but has no numbered
workstream.** [commands.md](../reference/cli/commands.md) (canonical) specifies it as the non-interactive
operator path for a run suspended at a budget cap (`budget:paused`, `on_exceed: pause_for_approval` —
@@ -667,7 +677,8 @@ Severity is the review's verified rating. Check an item off in the PR that resol
reuses **2.G's** cross-process resume substrate (a budget pause resolves through the same checkpoint reload
+ resume path as a human gate, behind a budget-specific command + flags), so it is a small follow-up once
2.G lands — candidate home: alongside 2.I, or its own short workstream. **Deliberately out of 2.G** (a
- distinct ADR-0028 surface, not in 2.G's acceptance). *(low · apps/cli/src/commands/; ADR-0028)*
+ distinct ADR-0028 surface, not in 2.G's acceptance). **Scheduled → 2.6.K** (single tracking point: the
+ Batch-E entry above). *(low · apps/cli/src/commands/; ADR-0028)*
- [ ] **Re-provide `secret`-typed inputs on cross-process resume.** The durable `run:started.inputs` are
**masked** (a `secret` input is persisted as `{ secret: true, ref }`, never plaintext — ADR-0006/0036), so a
fresh-process `relavium gate` resume cannot restore the real value. 2.G **fails closed (exit 2)** when a
@@ -680,7 +691,7 @@ Severity is the review's verified rating. Check an item off in the PR that resol
guarantee (allow-with-re-provisioning), demands the stdin-not-argv secret discipline (`provider set-key` pattern)
+ a mandatory security-review pass, and is coupled to the `budget resume` command above (both refactor the
`gate.ts` resume path). Best landed together with fresh context, not at the tail of the 2.5-close session.
- *(medium · apps/cli/src/commands/gate.ts; ADR-0006)*
+ **Scheduled → 2.6.K** (that focused follow-up). *(medium · apps/cli/src/commands/gate.ts; ADR-0006)*
### 2.I read-command follow-ups (PR #48 multi-agent review, 2026-06-24)
@@ -696,7 +707,7 @@ Severity is the review's verified rating. Check an item off in the PR that resol
*commands* (`relavium list` / `loadLatestRunPerWorkflow` still return the full set) — genuinely unneeded at
single-user CLI scale; add a cursor API before the desktop/cloud surfaces drive these reads at volume.
*(low → scale · packages/db/src/run-history-store.ts; database-schema.md)*
-- [x] **`AgentParseError` line/column — DONE (2.5-close Step 13, `fix(core)`).** `agentSyntaxErrorFrom` (the
+- [x] **`AgentParseError` line/column — DONE (2.5-close Step 13, `fix(core)`; PR #69).** `agentSyntaxErrorFrom` (the
agent sibling of parser.ts's `syntaxErrorFrom`) now threads `LineCounter` positions into a positioned
`YAMLParseError`: optional 1-based `line`/`column` fields (parity with `WorkflowSyntaxError`) plus a folded
`(source — line L, column C)` locator in the message so the position reaches every `.message`-surfacing
@@ -718,6 +729,7 @@ Severity is the review's verified rating. Check an item off in the PR that resol
`AgentParseError` as an exit-2 invocation fault. Also relativize the `source` label at the `chat`/`agent run`
call site (`agent-source.ts` passes the ABSOLUTE `source.path`, unlike the catalog's workspace-relative `rel`;
no secret leak — it is the user-typed path — but it contradicts the parser docstring's "workspace-relative").
+ **Scheduled → 2.6.B** (the conversational-authoring loop needs these diagnostics visible).
*(medium · apps/cli/src/chat/agent-source.ts + session-host.ts + commands/agent-run.ts + run.ts)*
- [ ] **Residual read-command test pins.** A few low-risk coverage gaps remain after the PR's test additions:
`pendingHumanGates` with `expiresAt` present and with multiple simultaneous gates; `list --json` no-project
@@ -745,10 +757,11 @@ Severity is the review's verified rating. Check an item off in the PR that resol
`sandboxed`-minus-tmp). It did **not** land in 2.5.E — carried forward under the *Phase 2.5.E follow-ups*
entry above (single tracking point). *(low · apps/cli/src/engine/tool-host/assemble.ts; ADR-0057; built-in-tools.md fs-tier note)*
- [x] **Write-capable chat — RESOLVED in 2.5.E.** *Landed in 2.5.E ([ADR-0057](../decisions/0057-cli-chat-modes-and-per-tool-approval.md), PR #63, merged 2026-07-03):* the `relavium chat` default profile is now the full-capability `chat-read-write` host — `write_file` is wired and gated by the per-tool approval floor (denied in the default `ask` mode as `tool_denied`, not `tool_unavailable`); a declared `full` tier is still **clamped to `project`** for the chat surface (an unjailed read exfiltrates `~/.ssh` / `~/.aws`, a write-capable chat shares that risk). *(apps/cli/src/chat/session-host.ts; ADR-0057)*
-- [ ] **Profile-unaware advertise-filter.** `wiredToolIds` narrows the grant by which `ToolHost` **arm** is wired,
- not by the profile's *read-only* posture — `write_file` is still advertised on a read-only chat host and only
- fail-closes at dispatch (`tool_unavailable`). Correct and safe (the dispatch backstop is authoritative), but a
- profile-aware advertise-filter would stop offering an always-denied tool. *(low · apps/cli/src/engine/tool-host/assemble.ts)*
+- [x] **Profile-unaware advertise-filter — DONE (2.5-close Step 15, Batch E; PR #69).** `wiredToolIds` now takes a
+ `{ readOnly }` option: on a read-only host a WRITE-class (`fsWrite`) tool is no longer advertised (its `fs` arm is
+ wired but always denies the write — an always-denied advertisement), the advertise-side complement to the
+ read-only fs arm's dispatch refusal. The default (read-write) is unchanged, so the live `chat-read-write` session
+ host is inert. *(apps/cli/src/engine/tool-host/assemble.ts)*
- [ ] **Residual fs TOCTOU on the PARENT directory (no `openat` in Node).** The read path (`readJailedFile`)
and the write paths (append + temp/rename) all open the FINAL component with `O_NOFOLLOW`, so a final-component
symlink swapped in after the jail's `realpath` fails closed. The unclosable residual is a swap of a PARENT
@@ -769,10 +782,12 @@ Severity is the review's verified rating. Check an item off in the PR that resol
would need `toolName` threading for marginal gain (write-only messages *are* prefixed); (c) the generic
`guarded()` catch-all stays **reason-only** (the I3 boundary). Re-open only if a concrete need appears.
*(nit · apps/cli/src/engine/tool-host/)*
-- [ ] **Two transitively-covered test gaps.** A chat-session-dispatches-`git_status` e2e (the process arm + the
- session→host dispatch are each tested; the union covers it) and a persister fold of a failed-turn's **real**
- tokens (the fold is error-agnostic and tested; the failed-turn flush fires `turn_completed`). Add explicit
- pins opportunistically. *(low · apps/cli/src/**/*.test.ts; testing.md)*
+- [x] **Two transitively-covered test gaps — DONE (2.5-close Step 11, Batch A; PR #69).** Both now have an
+ explicit pin: the chat-session-dispatches-`git_status` e2e was ADDED this round (session-host.test.ts —
+ "dispatches git_status through the process arm end-to-end", asserting the tool_result folded back with a clean
+ `{"exitCode":0}`); the failed-turn **real**-token persister fold was CONFIRMED already explicitly pinned
+ (persister.test.ts — "flushes the running cost on a failed turn so a resumed budget governor sees the true
+ spend"). *(apps/cli/src/chat/session-host.test.ts + persister.test.ts; testing.md)*
## Schema / validation hardening
@@ -808,7 +823,9 @@ Severity is the review's verified rating. Check an item off in the PR that resol
/ `GEMINI_API_KEY` / `DEEPSEEK_API_KEY`) as CI secrets. Until then live coverage is a known gap.
**Decided (2026-06-21, maintainer): defer to Phase-2 workstream 2.K** — enable the live-nightly lane
together with the 2.K regression harness rather than as a pre-Phase-2 ops chore; fixture coverage holds
- the line until then.
+ the line until then. **Update (2026-07-08): 2.K has shipped; this is now a Phase-2.6 in-window
+ maintenance obligation** (see [phase-2.6](phases/phase-2.6-conversational-authoring.md) §"In-window
+ maintenance obligations") — enable when CI provider keys are available.
*(minor → keys · ci.yml, packages/llm/src/conformance/*.conformance.test.ts)*
- [ ] **Leakwatch secret-scanning CI gate** — CI has no secret-scan step. The HodeTech standard
scanner is **Leakwatch** (never gitleaks); the blocking `ci.yml` step is wired once a
@@ -837,21 +854,23 @@ Severity is the review's verified rating. Check an item off in the PR that resol
vs a frozen number captured at the parent `RootApp`'s render) is verified only by tracing + the type-shape guard,
not by a regression test. Adding a harness is a first-of-its-kind test-architecture decision for `apps/cli`
(a new devDependency; possibly an ADR) — track it, then a smoke test could tick a fake clock across two
- `store.tick()`-driven renders and assert the displayed elapsed advances. *(low · apps/cli/src/render/tui/home-app.tsx
+ `store.tick()`-driven renders and assert the displayed elapsed advances. **Scheduled → 2.6.F** (behind the
+ full-screen renderer + harness ADR). *(low · apps/cli/src/render/tui/home-app.tsx
+ chat-ink.tsx; testing.md "every bug fix lands with a regression test")*
-- [ ] **Compact abort hint during token streaming.** The `Esc to stop` affordance shows on the pre-first-token
- status line but not once the answer streams (the content line needs the width) — yet `Esc` aborts throughout the
- turn (EA7). A follow-up could keep a compact hint in the footer during streaming. *(low · apps/cli/src/render/tui/chat-ink.tsx)*
-- [ ] **Bound the EXPANDED reasoning panel by rendered LINES, not just chars.** The panel body is bounded to
- `MAX_LIVE_TOKEN_CHARS` (4000) chars, which can wrap to 60+ lines of narrow prose in the live (non-``)
- region, re-painted each frame — a taller-than-viewport live block that can flicker on a short terminal (the same
- risk class the `liveTokens` answer stream already carries; the panel is opt-in + collapsed by default, so LOW).
- A follow-up could tail the expanded body to the last N rendered lines. *(low · apps/cli/src/render/tui/chat-ink.tsx)*
-- [ ] **Allow `Ctrl+T` / `/thinking` during a pending approval.** The fail-closed approval keyboard-ownership
- (ADR-0057) swallows every key except `[y]/[a]/[n]/[esc]` — including the reasoning toggle, the one moment a user
- might most want to expand the thinking to inform the decision. `toggle-reasoning` is a pure view flip (zero
- session effect), so it would be safe to let it bypass the swallow. Deliberately left fail-closed for now (the
- approval floor is security-sensitive). *(low · apps/cli/src/render/tui/chat-input.ts)*
+- [x] **Compact abort hint during token streaming — DONE (2.5-close Step 12, Batch B; PR #69).** A pure
+ `streamingAbortHint(busy)` renders a compact dim `Esc to stop` line beneath the streaming CONTENT (a STATUS line
+ already carries its inline hint), so the abort affordance persists for the whole turn (EA7). *(apps/cli/src/render/tui/chat-projection.ts + chat-ink.tsx)*
+- [x] **Bound the EXPANDED reasoning panel by rendered LINES, not just chars — DONE (2.5-close Step 12, Batch B; PR #69).**
+ `formatReasoningPanel` now tails the expanded body to the last `MAX_REASONING_PANEL_LINES` (12) RENDERED rows
+ (each logical line counts as `ceil(len/columns)` wrapped rows; a single over-budget line is head-sliced), so a
+ full 4000-char buffer cannot wrap into a flickering, screen-filling panel on a short terminal. The live width is
+ threaded via a `columns` prop (ChatApp reads `process.stdout?.columns`; the Home passes its resize-tracked
+ `size.cols`). *(apps/cli/src/render/tui/chat-projection.ts + chat-ink.tsx + home-app.tsx)*
+- [x] **Allow `Ctrl+T` / `/thinking` during a pending approval — DONE (2.5-close Step 14, D-4; PR #69).**
+ `reduceApprovalKey` whitelists exactly the view-only reasoning toggle (Ctrl-without-meta `t` → `toggle-reasoning`,
+ a pure store repaint with zero session/approval/decision effect) through the fail-closed swallow, so a user can
+ expand the thinking to inform the decision; every other key (mode cycle, edits, the most-permissive approve/reject
+ chord) stays swallowed. *(apps/cli/src/render/tui/chat-input.ts)*
## Sonar code-quality backlog
diff --git a/docs/roadmap/phases/phase-2.5-cli-consolidation.md b/docs/roadmap/phases/phase-2.5-cli-consolidation.md
index 939f38c1..9425a9bc 100644
--- a/docs/roadmap/phases/phase-2.5-cli-consolidation.md
+++ b/docs/roadmap/phases/phase-2.5-cli-consolidation.md
@@ -1,6 +1,8 @@
# Phase 2.5 — CLI Consolidation and Conversational Home
-> Status: In progress. **2.5.A** (shared tool-environment factory + capability-gap root-cause fix) is
+> Status: ✅ **COMPLETE** (milestone **M2.5-4**, merged to `main` via **PR #69**, 2026-07-08) — all workstreams
+> **2.5.A–J** shipped; the go/no-go exit criteria hold; Phase 2.6 (conversational authoring) is next. History below.
+> **2.5.A** (shared tool-environment factory + capability-gap root-cause fix) is
> ✅ **Done (PR #60, 2026-06-28)**, behind [ADR-0055](../../decisions/0055-cli-host-capability-seam-tool-environment-factory.md)
> — **milestone M2.5-1 (secure base) reached**. Spine continues: **2.5.B** (Home) ✅ → **2.5.C** (slash registry
> + palette + `/help`/`/doctor`/`/workflows`/`/cost` + footer hint-bar) ✅ **Done (PR #62, 2026-06-30)**
@@ -14,9 +16,9 @@
> **Done (PR #66, 2026-07-07)** behind [ADR-0063](../../decisions/0063-cli-config-write-contract.md)/[ADR-0064](../../decisions/0064-live-model-catalog.md)/[ADR-0065](../../decisions/0065-provider-economics-and-extensibility.md)
> (+ the ADR-0059/0066 model-UX follow-up) — **milestone M2.5-2 reached**. The consolidation lanes **2.5.I**
> (harness + concurrency) and **2.5.J** (docs-debt + `NO_COLOR`/`FORCE_COLOR`/`--color`) ✅ **Done (2.5-close-out,
-> 2026-07-08)** — **milestone M2.5-4 reached**, alongside the doable-now Batch A–E backlog (two `gate.ts`-resume
-> items — `budget resume` + secret re-provide — deferred to a focused follow-up; `extraRoots` blocked on its
-> config source). **Phase 2.5 is complete.**
+> PR #69, 2026-07-08)** — **milestone M2.5-4 reached**, alongside the doable-now Batch A–E backlog (two
+> `gate.ts`-resume items — `budget resume` + secret re-provide — deferred to a focused follow-up; `extraRoots`
+> blocked on its config source). **Phase 2.5 is complete — merged to `main` via PR #69.**
- **Related**: [../README.md](../README.md), [phase-2-cli.md](phase-2-cli.md), [phase-2.6-conversational-authoring.md](phase-2.6-conversational-authoring.md), [phase-3-desktop.md](phase-3-desktop.md), [../../reference/cli/commands.md](../../reference/cli/commands.md), [../../reference/cli/chat-session.md](../../reference/cli/chat-session.md), [../../reference/cli/regression-harness.md](../../reference/cli/regression-harness.md), [../../decisions/README.md](../../decisions/README.md) (ADR-0054–0057)
@@ -517,9 +519,9 @@ follow-up) lands with EA2's accuracy surface.
truncation is visible; each operational error class renders an actionable recovery hint with the session
intact; the seam is not modified.
-### 2.5.I — Regression harness and concurrency hardening — ✅ **Done (2.5-close, 2026-07-08)**
+### 2.5.I — Regression harness and concurrency hardening — ✅ **Done (2.5-close, PR #69, 2026-07-08)**
-> **Status:** ✅ **Done (2.5-close-out, 2026-07-08).** `loadFull` is wrapped in a single read transaction
+> **Status:** ✅ **Done (2.5-close-out, PR #69, 2026-07-08).** `loadFull` is wrapped in a single read transaction
> (torn-read guard); every multi-statement write txn is `BEGIN IMMEDIATE` with a bounded, deterministic
> `SQLITE_BUSY`/`SQLITE_LOCKED` retry (`withBusyRetry`, over the pre-existing WAL + `busy_timeout`); the
> concurrent chat+run e2e (two-connection coexistence + two-process contention), the `Home → chat → resume →
@@ -545,9 +547,9 @@ Windows.
performance budgets (Home cold-open at 1000 sessions; 80×24 minimum) hold; the harness gates the
backward-compatibility exit criterion.
-### 2.5.J — Documentation reconciliation and dead-code cleanup — ✅ **Done (2.5-close, 2026-07-08)**
+### 2.5.J — Documentation reconciliation and dead-code cleanup — ✅ **Done (2.5-close, PR #69, 2026-07-08)**
-> **Status:** ✅ **Done (2.5-close-out, 2026-07-08).** The "encrypted history" wording is corrected to the
+> **Status:** ✅ **Done (2.5-close-out, PR #69, 2026-07-08).** The "encrypted history" wording is corrected to the
> accurate CLI posture (unencrypted, protected by `0700`/`0600` + keychain, ADR-0050) across `uvp.md` /
> `vision.md` / the CLI tutorial + the README milestone spine; color resolution honors `--color` /
> `--no-color` > `NO_COLOR` (any non-empty ⇒ off) > `FORCE_COLOR` (`0`/`false` ⇒ off, the supports-color
@@ -575,7 +577,8 @@ correct); reconcile the roadmap status surfaces (`docs/roadmap/current.md`,
[phase-2-cli.md](phase-2-cli.md), [CLAUDE.md](../../../CLAUDE.md)) now that **2.R and 2.J have both
landed**, and complete the central roadmap narrative for 2.5/2.6 ([../README.md](../README.md) — the phase
index and the dependency graph already include them; reconcile the milestone-spine prose); handle the
-`NO_COLOR` / `FORCE_COLOR` env standards (today only the `--no-color` flag is honoured).
+`NO_COLOR` / `FORCE_COLOR` env standards — now resolved per the `--color` / `--no-color` > `NO_COLOR` > `FORCE_COLOR` > default-on order,
+orthogonal to `--json`/CI, with a full test matrix.
**Acceptance:** no tracked doc claims the CLI `history.db` is encrypted; the roadmap reflects the landed
state; `NO_COLOR` is honoured.
@@ -587,7 +590,7 @@ state; `NO_COLOR` is honoured.
| M2.5-1 Secure base ✅ **(PR #60, 2026-06-28)** | 2.5.A | Root-cause closed (capability gap + merge asymmetry); host seam reviewed |
| M2.5-2 Home + entry + onboarding ✅ **(PR #66, 2026-07-07)** | 2.5.B + 2.5.C + 2.5.D + 2.5.F + 2.5.G | First-class entry + ergonomics + onboarding |
| M2.5-3 Modes + observability ✅ **(2026-07-07)** | 2.5.E + 2.5.H | Safe reseat-less mode system + per-tool approval + reasoning render + actionable errors |
-| M2.5-4 Consolidation ✅ **(2.5-close, 2026-07-08)** | 2.5.I + 2.5.J | Harness + concurrency + docs-debt (+ the doable-now Batch A–E backlog; two `gate.ts`-resume items deferred to a follow-up) |
+| M2.5-4 Consolidation ✅ **(2.5-close, PR #69, 2026-07-08)** | 2.5.I + 2.5.J | Harness + concurrency + docs-debt (+ the doable-now Batch A–E backlog; two `gate.ts`-resume items deferred to a follow-up) |
## Sequencing & parallelization
@@ -607,6 +610,8 @@ parallel at any point.
## Exit criteria (go / no-go → Phase 2.6)
+> ✅ **All five met** at phase close (PR #69, 2026-07-08) — Phase 2.6 (conversational authoring) is unblocked.
+
1. `relavium` opens Home in a TTY; the `--json` / CI / non-TTY backward-compatibility is proven by the
extended regression harness.
2. The capability-gap root cause is closed (`tool_unavailable`, real usage, advertise-filter, merge
diff --git a/docs/roadmap/phases/phase-2.6-conversational-authoring.md b/docs/roadmap/phases/phase-2.6-conversational-authoring.md
index 2f229ea7..fd209b25 100644
--- a/docs/roadmap/phases/phase-2.6-conversational-authoring.md
+++ b/docs/roadmap/phases/phase-2.6-conversational-authoring.md
@@ -1,226 +1,690 @@
-# Phase 2.6 — Conversational Authoring and Parity
+# Phase 2.6 — Conversational Authoring and the First-Class CLI
-> Status: Planned. Depends on the Phase 2.5 spine (the wired tool-environment and the per-tool
-> approval / mode system). Spine: 2.6.A (`@relavium/authoring` package) → 2.6.B (conversational
-> authoring agent). Additive: 2.6.C / D / E.
+> Status: Planned — **next up**. Depends on the Phase 2.5 spine (the wired tool-environment and the
+> per-tool approval / mode system), which is **complete** (M2.5-4, PR #69, 2026-07-08), so this phase is
+> now unblocked.
+>
+> **Rewritten 2026-07-08** (after the Phase-2.5 close), expanding the original authoring-and-parity scope
+> into the phase that makes the CLI a **first-class, Home-centric product**. The rewrite folds three
+> inputs: the maintainer's CLI-experience findings, a competitor research pass (opencode, Claude Code,
+> Codex CLI, Gemini CLI, Temporal/`gh run`-class run tooling, Aider/Goose/Amp/Cursor/Copilot), and a
+> line-by-line triage of [../deferred-tasks.md](../deferred-tasks.md) (the now-doable items are pulled in
+> below, each mapped to a workstream). Workstreams **2.6.A–E keep their original identities** (they are
+> referenced by ADR-0058/0059/0060 and the deferred-tasks doc); **2.6.F–M are new**.
>
> **Note (2026-07-07):** **2.6.C**'s mid-session `/models` model **reseat shipped early in 2.5.G** (ADR-0059,
-> PR #66, merged 2026-07-07); the "mid-session model switching" mentions in the Goal / Outcomes / In-scope /
-> Milestones / Exit-criteria below are therefore already realized — see §2.6.C. This phase is otherwise Planned.
-
-- **Related**: [../README.md](../README.md), [phase-2.5-cli-consolidation.md](phase-2.5-cli-consolidation.md), [phase-2-cli.md](phase-2-cli.md), [phase-3-desktop.md](phase-3-desktop.md), [phase-4-vscode.md](phase-4-vscode.md), [../../reference/contracts/workflow-yaml-spec.md](../../reference/contracts/workflow-yaml-spec.md), [../../reference/contracts/agent-yaml-spec.md](../../reference/contracts/agent-yaml-spec.md), [../../reference/shared-core/node-types.md](../../reference/shared-core/node-types.md), [../../decisions/README.md](../../decisions/README.md) (ADR-0058–0060)
-
-The second half of the consolidation work, split out from
-[phase-2.5-cli-consolidation.md](phase-2.5-cli-consolidation.md) because it is ADR-heavy and depends on
-that spine. It realises the product's tagline — *"Start as an agent. Ship the workflow."* — at the
-terminal: a conversation can now **author** a standards-valid Relavium workflow/agent, switch models
-mid-session, and reach competitor-parity ergonomics.
+> PR #66, merged 2026-07-07); 2.6.C is retained for the residual per-model cost-breakdown read and as the
+> cross-reference home.
+
+- **Related**: [../README.md](../README.md), [phase-2.5-cli-consolidation.md](phase-2.5-cli-consolidation.md), [phase-2-cli.md](phase-2-cli.md), [phase-3-desktop.md](phase-3-desktop.md), [phase-5-managed-inference.md](phase-5-managed-inference.md), [node-runtime-upgrade.md](node-runtime-upgrade.md), [../deferred-tasks.md](../deferred-tasks.md), [../../reference/cli/commands.md](../../reference/cli/commands.md), [../../reference/cli/home.md](../../reference/cli/home.md), [../../reference/cli/chat-session.md](../../reference/cli/chat-session.md), [../../reference/shared-core/built-in-tools.md](../../reference/shared-core/built-in-tools.md), [../../reference/contracts/config-spec.md](../../reference/contracts/config-spec.md), [../../reference/contracts/workflow-yaml-spec.md](../../reference/contracts/workflow-yaml-spec.md), [../../reference/contracts/agent-yaml-spec.md](../../reference/contracts/agent-yaml-spec.md), [../../decisions/README.md](../../decisions/README.md) (ADR-0058–0060 + the new ADRs below)
+
+The second half of the consolidation work begun in
+[phase-2.5-cli-consolidation.md](phase-2.5-cli-consolidation.md), now widened into the phase that finishes
+the CLI as a product. It realizes the tagline — *"Start as an agent. Ship the workflow. Own every run."* —
+**entirely inside the terminal**: a conversation authors a standards-valid workflow, the Home starts and
+monitors it, the run history is drillable to per-node detail, and every management task (providers, models,
+MCP, settings, gates) is doable from the Home without dropping to a shell subcommand. When this phase
+closes, `relavium` in a terminal is a first-class experience on par with the best agentic CLIs — while
+keeping the postures they lack: OS-keychain-only secrets, a fail-closed approval floor, and git-committable
+YAML artifacts.
+
+## TL;DR
+
+Phase 2.6 makes bare `relavium` a **full-screen, Home-centric** product. Key outcomes in 5 milestones:
+
+- **Conversational authoring** — a free-text request produces a strict-valid `.relavium.yaml`,
+ authored and run from the Home; `{{ctx.*}}` interpolation and `agent run --input` land.
+- **Everything managed from the Home** — providers, MCP servers, agents, workflows, runs, and
+ run-ops (budget/gate resume) with no shell subcommand required.
+- **Drillable, attributed run history** — list → run → node drill-down with per-node model/agent/cost
+ attribution, bounded tool traces, and cross-process live watch.
+- **Competitor-toolbelt parity** — `edit_file`, `search_files`, `find_files`, `todo`, `ask_user`,
+ working `web_search`, each YAML-selectable and mode-gated.
+- **Settings, theming, localization** — `/settings` over the config-write contract; three built-in
+ themes (default / high-contrast / colorblind-safe); `en` + `tr` i18n with CI key-parity.
+- **Onboarding v2** — two auth paths: BYOK (live) + Relavium-account stub (disabled, Phase 5).
+- **13 workstreams** (2.6.A–M), substrate-first: 2.6.F (full-screen TUI + Node 22 floor) runs first.
## Goal
-Let a `relavium chat` conversation produce a **standards-valid** `.relavium.yaml` from a free-text
-request, promote the existing authoring core into a shareable `@relavium/authoring` package so every
-surface can consume it, enable mid-session model switching, and close the remaining parity polish — all
-on top of the Phase 2.5 tool-environment and approval system.
+Make the bare `relavium` invocation a **full-screen, Home-centric** surface from which the entire product
+is used and managed; close the **tool-breadth gap** against competitor CLIs (edit, search, find, todo,
+ask-user, working web search) under the existing governance floor; land **conversational authoring** on the
+shared `@relavium/authoring` core; give runs a **three-level drill-down** (list → run → node) over durable,
+attributed history; and ship **settings, theming, and localization** — all without breaking the `--json` /
+CI / non-TTY contract ([ADR-0049](../../decisions/0049-cli-machine-output-contract.md)) or any existing
+subcommand.
## Outcomes (Definition of Done)
-- A `@relavium/authoring` package (`@relavium/authoring`) wraps parse / validate / serialize / scaffold
- for workflows and agents; the CLI's `create` / `import` / `export` consume it; desktop and VS Code can
- too.
-- Every authored artifact passes a single `validateAuthoredWorkflow` pre-flight (parse **and** catalog
- validation); a failure returns a field-named, secret-free error the model self-corrects against.
-- A conversational authoring agent turns a free-text request into a strict-valid `.relavium.yaml`, writes
- it only under accept-edits/auto with a scope-tiered host, and offers to `/run` it.
-- `/models` switches the bound model **mid-session** (a host-side reseat), carrying cost/turn and
- persisting per-message model attribution — with an explicit tool-context-loss notice.
-- Session `{{ctx.*}}` prompt interpolation lands, unblocking `agent run --input`; parity polish
- (`/rewind`, `/fork`, advanced `@`-injection, markdown render, `/theme`) ships.
+- `relavium` on a TTY opens a **full-screen** (alternate-screen) Home with a scroll/auto-follow viewport;
+ the inline renderer remains as an escape hatch; `--json` / `CI` / non-TTY behavior is byte-identical to
+ today (regression-harness proven).
+- **Everything is manageable from the Home**: provider + key CRUD, model picking, MCP server CRUD +
+ status, settings (theme/language/preferences), workflow start/monitor/history with node-level
+ drill-down, agent start (any catalog agent) + session resume, gate resolution (human **and** budget),
+ and authoring (wizard + conversational). No routine task requires a shell subcommand; subcommands stay
+ first-class for scripting/CI and are never removed.
+- A `@relavium/authoring` package is the shared authoring core; a conversational request produces a
+ strict-valid, catalog-validated `.relavium.yaml`, written only under approval, offered to run it in-place.
+- The **toolbelt** reaches competitor breadth — `edit_file`, `search_files`, `find_files`, todo/plan,
+ `ask_user`, an actually-working `web_search` — each engine-pure, YAML-selectable, mode-gated, and
+ rendered first-class (collapsible detail, diffs at the approval prompt) behind a security-reviewed
+ render contract.
+- Session `{{ctx.*}}` interpolation lands (ADR-0060) and `agent run --input` is unblocked.
+- Run history is **attributed and drillable**: per-node model/agent/cost durable, a bounded secret-free
+ tool trace, gate-resolve TOCTOU closed at the store, crashed runs reconciled, cross-process runs
+ watchable live at node granularity.
+- The CLI speaks **`en` and `tr`** over a string catalog with CI key-parity, and ships a real theme system
+ (default + high-contrast + colorblind-safe) with the color-free path staying legible.
+- The onboarding wizard offers **two auth paths** — BYOK (live) and *Sign in with a Relavium account*
+ (visible, disabled, honestly labeled as coming with managed inference) — behind an Accepted
+ forward-design ADR.
## Scope
### In scope
-- The `@relavium/authoring` package promotion + catalog-aware pre-flight back-port; the conversational
- authoring agent + its product-side knowledge pack; mid-session model reseat; session `{{ctx.*}}`
- interpolation; and the parity/polish lane.
+The workstreams below: the authoring spine (2.6.A/B/D), the platform + full-screen TUI foundation (2.6.F),
+the Home management surfaces (2.6.G/H/I/J/K), the experience arms (2.6.C residual, 2.6.E, 2.6.L, 2.6.M),
+and the deferred-tasks items each workstream absorbs (mapped in the
+[pull-in table](#deferred-tasks-pulled-into-this-phase)).
### Explicitly out of scope (→ Phase 3 / later)
-- Full-fidelity reseat tool-context (the persister/schema extension, 1.X/1.Z); `read_media` input (D12); in-app
- scrollback/pager; a multi-pane dashboard. Tracked in [../deferred-tasks.md](../deferred-tasks.md). (`/compact`
- model-summarised compaction was originally listed here as Phase 3; it **shipped in 2.5.F** per
- [ADR-0062](../../decisions/0062-context-compaction-and-cli-history-commands.md) (PR #65). The **live provider
- `/v1/models` fetch** was likewise listed here; it is now **built in 2.5.G** per
- [ADR-0064](../../decisions/0064-live-model-catalog.md) — the Option-A live model catalog.)
+- **Chat sub-agent spawn** (a child-session engine model — the largest deliberate parity gap left; it
+ belongs with the Phase-3 desktop multi-agent center and needs its own ADR; `invoke_agent` stays
+ workflow-only).
+- The **`read_media` D12 cluster** (host `MediaReadAccess`, scope population, the result-shape contract)
+ and `@`-mention of media files — the dedicated, security-reviewed follow-up stands.
+- **Full-fidelity reseat tool-context** (the 1.X/1.Z persister/schema extension) — the reseat keeps its
+ text-only-transcript notice.
+- **File-snapshot undo** (opencode-style revert of a message *and its file changes*) — 2.6.E ships
+ conversation-level `/rewind`/`/fork` only.
+- **retry-from-node** ([ADR-0040](../../decisions/0040-node-retry-budget-above-the-chain.md) Part B — needs the
+ run-attempt model). The 2.6.G run-detail browser must be designed so a later "retry from this node"
+ action slots in without rework, but the engine work is Phase 3.
+- The **workflow-run `egress`/`os` arms** stay unwired (the recorded 2.5.E design boundary:
+ `build-engine.ts` wires `fs`+`process` only). Revisiting that boundary requires its own ADR — it is not
+ quietly reopened here.
+- A multi-pane dashboard (desktop canvas territory), `output_schema` deep JSON-Schema conformance (new
+ validator dependency), the `plugin` ToolSource loader, and cursor pagination for the read commands
+ (scale-gated). Tracked in [../deferred-tasks.md](../deferred-tasks.md).
+
+### In-window maintenance obligations (not workstreams)
+
+Two items from [deferred-tasks.md](../deferred-tasks.md) fall inside the likely phase window and should be
+actioned during it (maintainer calls, not workstreams): the **OpenAI Sora 2 shutdown (2026-09-24)** —
+retarget or disable the 1.AH A3 Sora adapter arm before the date — and **enabling the live-nightly
+conformance lane** (CI provider keys), which also unblocks the deferred media-in conformance fixtures.
+Both stay tracked in their canonical [deferred-tasks.md](../deferred-tasks.md) entries.
## Work breakdown
### 2.6.A — `@relavium/authoring` package promotion + catalog-aware pre-flight
-The authoring core already exists in-tree (`apps/cli/src/authoring/authoring.ts`, landed with 2.J):
-it wraps `parseWorkflow` / `serializeWorkflow` / `parseAgent` / `buildAuthored` / `detectAndParse` from
-`@relavium/core` and drives the `create` / `import` / `export` commands. **Decision (maintainer):**
-promote it to a shared `@relavium/authoring` package so desktop ([phase-3-desktop.md](phase-3-desktop.md))
-and VS Code ([phase-4-vscode.md](phase-4-vscode.md)) can consume the same authoring core, not just the CLI.
+Unchanged from the original plan. The authoring core exists in-tree (`apps/cli/src/authoring/authoring.ts`,
+landed with 2.J) and is promoted to a shared `@relavium/authoring` package so desktop
+([phase-3-desktop.md](phase-3-desktop.md)) and VS Code ([phase-4-vscode.md](phase-4-vscode.md)) can consume
+the same core.
**Tasks:**
-- Scaffold `packages/authoring` (`@relavium/authoring`) — pure TS, platform-free (engine-purity holds)
- — and **extract-and-decouple** the existing `apps/cli/src/authoring/` core into it (it is **not** a free
- move: the core imports `CliError`, `discoverCatalog`, and `findProjectConfigDir` from `apps/cli`, which
- a package may not import — a forbidden `packages → apps` back-edge). Cut those three: replace `CliError`
- with a platform-free typed error the CLI maps to exit codes at the boundary; keep catalog **discovery**
- and `findProjectConfigDir` CLI-side and pass the catalog **in**. Add an import-zone lint fence (Phase-0
- seam-fence pattern) banning `packages/authoring → apps/cli`. Follow the add-package procedure
- ([.claude/skills/add-package/SKILL.md](../../../.claude/skills/add-package/SKILL.md)).
+- Scaffold `packages/authoring` — pure TS, platform-free — and **extract-and-decouple** the existing core
+ (it is **not** a free move: `CliError`, `discoverCatalog`, and `findProjectConfigDir` are `apps/cli`
+ imports a package may not take — a forbidden `packages → apps` back-edge). Replace `CliError` with a
+ platform-free typed error the CLI maps to exit codes at the boundary; keep catalog **discovery** and
+ `findProjectConfigDir` CLI-side and pass the catalog **in**. Add an import-zone lint fence banning
+ `packages/authoring → apps/cli`. Follow
+ [.claude/skills/add-package/SKILL.md](../../../.claude/skills/add-package/SKILL.md).
- Expose a single `validateAuthoredWorkflow(yaml, catalog)` = `parseWorkflow` **+**
- `validateWorkflowWithCatalog` pre-flight. The existing `create` / `import` / `export` pre-flight is
- **parse-only** (it does not call the catalog validator — only the run path does); **back-port** the
- catalog-aware pre-flight so wizard-authored and conversationally-authored artifacts share one front
- end and `create` can never accept a model/modality the run path rejects.
-- Add direct unit tests for the authoring core (`detectAndParse` / `buildAuthored` /
- `validateAuthoredWorkflow`) — today only the command wrappers are tested.
+ `validateWorkflowWithCatalog`, and **back-port** it into `create`/`import`/`export` (today those are
+ parse-only; only the run path catalog-validates), so `create` can never accept a model/modality the run
+ path rejects.
+- Add direct unit tests for `detectAndParse` / `buildAuthored` / `validateAuthoredWorkflow` (today only the
+ command wrappers are tested).
**Acceptance:** `@relavium/authoring` builds and imports **only** `@relavium/core` + `@relavium/shared`
-(lint-fence enforced — no `apps/cli` back-edge); the CLI consumes it with `create` / `import` / `export`
-round-tripping **unchanged** (regression-tested); `create` runs the same catalog-aware pre-flight the run
-path uses; the core is directly unit-tested. **Required ADR: `@relavium/authoring` package +
-conversational-authoring pre-flight contract.**
+(lint-fence enforced); the CLI consumes it with `create`/`import`/`export` round-tripping **unchanged**
+(regression-tested); `create` runs the same catalog pre-flight the run path uses; the core is directly
+unit-tested. **Required ADR:** [ADR-0058](../../decisions/0058-relavium-authoring-package-and-conversational-authoring.md)
+(Proposed → Accepted when this workstream begins).
-### 2.6.B — Conversational workflow/agent authoring agent
+### 2.6.B — Conversational + wizard authoring in the Home
-A `relavium chat` request such as *"define a workflow with these agents…"* produces a strict-valid
-`.relavium.yaml`. This is the sibling of `chat-export` (which **replays** a transcript into a workflow);
-here the model **generates** the artifact.
+The original conversational-authoring workstream, plus the in-Home wizard surface and two absorbed
+deferred items.
**Tasks:**
-- Add an authoring agent (an `--agent` profile or a `/author` mode) whose system prompt references a
- **product-side knowledge pack** — a model-readable cheat-sheet **derived from** the canonical specs
- ([node-types.md](../../reference/shared-core/node-types.md),
+- **Conversational authoring** (unchanged): an authoring agent (an `--agent` profile or a `/author` mode)
+ whose system prompt references a **product-side knowledge pack derived — never restated** — from
+ [node-types.md](../../reference/shared-core/node-types.md),
[workflow-yaml-spec.md](../../reference/contracts/workflow-yaml-spec.md),
- [agent-yaml-spec.md](../../reference/contracts/agent-yaml-spec.md)) and the Zod schemas, plus a minimal
- valid example per node type. The knowledge is **derived, never restated** ([CLAUDE.md](../../../CLAUDE.md)
- #8); a check proves no schema is duplicated. It **must not** live under `.claude/skills/` — those are
- repo-development (Claude Code) procedures and the Relavium **product** agent never reads `.claude/`.
-- The self-correct loop reuses the same `detectAndParse` / `validateAuthoredWorkflow` pre-flight: model →
- YAML → pre-flight → field-named, secret-free error → model fixes (improve `AgentParseError` to carry
- line/col, a Phase-2 follow-up).
-- The artifact is written only under accept-edits/auto with the scope-tiered host (2.5.A/2.5.E), then the
- Home offers *"Run it now with `/run`?"* — closing the author → run loop on one screen.
-- **Discoverability of the UVP (proactive, opt-out):** because *"Start as an agent. Ship the workflow."*
- is the product's promise, a chat that has run several tool turns or produced a reusable plan surfaces a
- quiet, dismissible hint — *"turn this session into a workflow with `/export`"* — so the tagline is
- discovered, not buried in a slash command. Opt-out via config; never interrupts a turn.
-
-**Acceptance:** a free-text request yields a strict-valid `.relavium.yaml` that passes the same pre-flight
-as `relavium run`; an invalid draft is corrected via the secret-free error loop; the file is written only
-with approval; the proactive `/export` hint appears (and is dismissible); a knowledge-restate check passes.
-A security review of the write surface + the authored artifact's secret-taint gate passes. **Required ADR:
-shared with 2.6.A.**
-
-### 2.6.C — Mid-session model reseat (`/models` mid-chat)
-
-> **Note (2026-07-07):** ADR-0059 was pulled forward and the `/models` mid-chat reseat **shipped early in
-> 2.5.G**'s model-UX follow-up (PR #66, merged 2026-07-07). This workstream is retained for any residual
-> Phase-2.6 polish and as the cross-reference home.
-
-A session binds one model for its lifetime ([ADR-0024](../../decisions/0024-agent-first-entry-point-agentsession.md);
-the fallback plan is memoized). Switching the **model** mid-chat is therefore a host-side **reseat**:
-reconstruct the transcript (`reconstructSessionState`) and start a new `AgentSession.resume` bound to the
-new model/provider, carrying cost/turn. (Mode changes do **not** reseat — that is the reseat-less mode
-system in 2.5.E.)
-
-**Tasks:** mid-chat `/models` performs the reseat; persist per-message `modelId` (the `session_messages`
-schema already has the column — only the CLI persister wiring is missing); surface an explicit, shared
-notice on the `chat-resume` family that **prior tool calls and file contents are not carried to the new
-model** (the transcript is text-only; full-fidelity tool-context is Phase 3); show a per-model cost
-breakdown.
-
-**Acceptance:** `/models` mid-chat continues the conversation on a new model from the next turn; cost/turn
-carry; per-message model attribution persists; the context-loss notice is shown; "carries full context" is
-never claimed. [ADR-0059](../../decisions/0059-cli-mid-session-model-reseat.md) is **Accepted (2026-07-06)** and
-its refinement of [ADR-0024](../../decisions/0024-agent-first-entry-point-agentsession.md) is recorded **in
-place** on ADR-0024 (the dated `> Amended 2026-07-06 …` note + the Related forward-link, documentation-style §7),
-since it refines without reversing. **Required ADR: mid-session reseat (model-only) — refines ADR-0024 (done).**
+ [agent-yaml-spec.md](../../reference/contracts/agent-yaml-spec.md) and the Zod schemas (one minimal
+ example per node type; a no-duplication check gates acceptance; never under `.claude/` — the product
+ agent does not read repo-development skills). Self-correct loop: model → YAML → `detectAndParse` /
+ `validateAuthoredWorkflow` → field-named, secret-free error → model fixes. The artifact is written only
+ under accept-edits/auto with the scope-tiered host, then the surface offers *"Run it now?"* — closing
+ author → run on one screen.
+- **In-Home authoring wizards**: bring `relavium create`'s wizard into the Home/chat palette (`/create` →
+ an ink-native agent/workflow wizard over the same injectable prompter seam), so authoring starts from
+ the Home, not only from a shell command.
+- **`AgentParseError` reaches the chat surfaces** *(deferred pull-in)*: a malformed `.agent.yaml` on
+ `chat --agent` / `agent run` currently collapses to a generic exit-1 internal error; resolve the design
+ call (wrap into `CliError('invalid_invocation')` at `resolveChatAgent`, or teach the top-level renderer
+ to render a typed `AgentParseError` as an exit-2 invocation fault), revise the pinned test deliberately,
+ and relativize the echoed source path. The conversational self-correct loop depends on these diagnostics
+ being visible.
+- **Import consent gate** *(deferred pull-in, security)*: gate the first spawn of an MCP `stdio` server
+ declared by an **untrusted-provenance** imported artifact behind explicit consent, and pin `npx` package
+ versions for auto-install servers ([ADR-0052](../../decisions/0052-inbound-mcp-client-package-lifecycle-registration.md) §2)
+ — the authoring/import path this phase matures is exactly the surface that makes this live.
+- **Discoverability of the UVP** (unchanged): the proactive, dismissible, config-opt-out *"turn this
+ session into a workflow with `/export`"* hint.
+
+**Acceptance:** a free-text request yields a strict-valid `.relavium.yaml` passing the same pre-flight as
+`relavium run`; an invalid draft is corrected via the secret-free loop; files are written only with
+approval; `/create` works from the Home; a malformed agent YAML surfaces its field-named, positioned
+diagnostic on every surface; the untrusted-import consent gate holds; a security review of the write
+surface + the secret-taint gate + the import gate passes. **Required ADR:** shared with 2.6.A (ADR-0058).
+
+### 2.6.C — Mid-session model reseat (shipped early) — residual
+
+> **Shipped early in 2.5.G** (ADR-0059, PR #66, 2026-07-07): the `/models` mid-chat reseat, per-message
+> `modelId` attribution, and the context-loss notice. Retained for the residual below and as the
+> cross-reference home.
+
+**Tasks:** the per-model **cost breakdown** read (`/cost` gains a per-model section over the shipped
+attribution columns); verify the context-loss notice covers the whole `chat-resume` family.
+
+**Acceptance:** `/cost` shows per-model spend for a reseated session; the notice is asserted on resume
+surfaces. **Required ADR:** none (ADR-0059 is Accepted).
### 2.6.D — Session `{{ctx.*}}` prompt interpolation
-The agent system prompt is passed verbatim today (no template resolution), and `agent run --input` is
-reserved/rejected until this lands. The conversational authoring agent and reseat both want session
-context, so the Phase-2 deferral is pulled forward.
+Unchanged in intent; one absorbed deferred item makes the security mandate explicit.
+
+**Tasks:** resolve `{{ctx.*}}` in the session system prompt per
+[ADR-0060](../../decisions/0060-session-ctx-prompt-interpolation.md) — template substitution only, with the
+**per-variable provenance/taint marker** on `SessionContext` (`--input`-derived values are untrusted by
+provenance and never resolve in system position); unblock `agent run --input k=v`. *(Deferred pull-in:)*
+land the **parse-time gate on system-bound fields** — when trusted `{{inputs}}`/`{{ctx}}` are admitted into
+system positions, untrusted `run.outputs`/`read_file` references there are rejected at parse (the analyze/
+collect gate), preserving the existing secret-taint protection.
+
+**Acceptance:** `{{ctx.*}}` resolves in a session prompt with the taint rule enforced and tested;
+`agent run --input` is accepted and reaches the prompt; the ADR-0060 mandatory security review passes.
+**Required ADR:** ADR-0060 (Proposed → Accepted).
-**Tasks:** resolve `{{ctx.*}}` in the session system prompt against session-scoped variables (an engine
-follow-up); unblock `agent run --input k=v`.
+### 2.6.E — Chat & input parity polish
-**Acceptance:** `{{ctx.*}}` resolves in a session prompt; `agent run --input` is accepted and reaches the
-prompt. **Required ADR: session `{{ctx.*}}` interpolation** (engine amendment).
+The competitor-parity chat ergonomics (the theme system moved to 2.6.L; tool-call rendering moved to
+2.6.M). Everything here is TTY-interactive-only; the non-interactive contract is untouched.
-### 2.6.E — Parity and polish
+**Tasks:**
+
+- **Markdown + code-block rendering** in the transcript (minimal in-house renderer preferred; a markdown
+ dependency, if chosen, needs an ADR); syntax highlighting stays Phase 3.
+- **Advanced `@`-injection**: glob / directory expansion respecting ignore files (the ADR-0061 follow-up;
+ the in-house matcher from the 2.5 close is the substrate).
+- **`/rewind` + `/fork`** at conversation level: rewind truncates to a chosen prior message and continues
+ (via the `/clear`-style host-swap + `reconstructSessionState` machinery); fork branches a session into a
+ new `sessionId` preserving the original. File-change revert is explicitly out (see out-of-scope).
+- **Type-ahead message queue**: messages typed while a turn runs are queued (navigate/edit the queue), sent
+ on turn end — with a steer-now affordance considered (send-as-interrupt).
+- **Input history search**: `Ctrl+R` reverse search over per-project prompt history.
+- **`$EDITOR` compose** (`Ctrl+G`): edit the pending prompt in the external editor.
+- **`/copy`**: copy the last assistant reply (OSC-52 with a plain fallback).
+- **`/help` v2**: a full-screen, sectioned help screen (commands, keybindings, modes) replacing the flat
+ text list, once 2.6.F's renderer lands.
+
+**Acceptance:** each affordance works in chat and the in-Home chat; `--json`/plain surfaces reject or
+ignore them exactly as the ADR-0049 contract requires; the message queue and rewind have reducer-level
+tests. **Required ADR:** none, unless a markdown dependency is chosen (then a small dedicated ADR).
+
+### 2.6.F — Platform floor + the full-screen TUI foundation
+
+The substrate workstream — it runs **first** because the browsers (2.6.G), settings screens (2.6.L), and
+render-v2 (2.6.M) all build on it.
+
+**Tasks:**
-The competitor-parity ergonomics that are valuable but not on the spine: `/rewind` + `/fork` (the engine
-already has per-node-boundary checkpoints to build on); advanced `@`-injection (glob/directory, respecting
-ignore files); basic markdown + code-block rendering with a table layout (syntax highlighting is Phase 3;
-a markdown dependency, if chosen, needs an ADR); `/theme` with at least one **high-contrast** and one
-**colorblind-safe** theme (and semantic markers — `✓`/`✗`/`⏸` — that survive `--no-color`/`NO_COLOR`, so
-the experience is not colour-dependent, degrading to ASCII equivalents — `[v]`/`[x]`/`[||]` — when the
-terminal lacks Unicode support so the glyphs never render as broken boxes). Note any screen-reader limitations of the raw-mode TUI as a
-documented constraint with a non-TTY fallback.
+- **Node dev/CI bump now**: `.nvmrc` 22 → 24 (Active LTS) — one line, non-breaking, no ADR.
+- **Supported-floor decision** *(maintainer decision, recommended: take it early in-phase)*: raise the
+ published floor 20.12 → `>=22` — a SemVer-major for `relavium` that restores `better-sqlite3` prebuild
+ coverage (Node 20 is EOL) and unlocks ink 7 / `node:sqlite` / eslint 10 / vitest 5. Full analysis:
+ [node-runtime-upgrade.md](node-runtime-upgrade.md). This **supersedes
+ [ADR-0021](../../decisions/0021-node-sqlite-driver-better-sqlite3.md)** → its own governed PR behind a
+ superseding ADR. Ink 7 is evaluated in the same governed PR but adopted only if the floor is raised to
+ `>=22`; otherwise the renderer ships on the current ink major.
+- **Full-screen renderer**: an alternate-screen (DECSET 1049) mode for the Home + chat with a real
+ viewport — scrollback inside the app (PgUp/PgDn, wheel where supported), **auto-follow** that pauses when
+ the user scrolls up and resumes at bottom, and the input pinned to the bottom row. This structurally
+ fixes the current bug where long responses clip/truncate content beyond the terminal height — scrolling
+ up must reveal the full response from the beginning without top-truncation. The inline (scrollback)
+ renderer is **retained** and byte-identical for non-TTY/CI; an explicit escape hatch (`--no-alt-screen`
+ or a config key) keeps the inline mode available on a TTY. If the full-screen renderer is deferred or
+ the inline mode is active, a separate inline-viewport fix must backfill the scrollback-preservation
+ behavior for long responses so that content above the visible area is never lost. Renderer choice is
+ orthogonal to session state (switching relaunches the view in place, conversation intact). The run TUI's
+ persistent plain-text exit summary is preserved on unmount.
+- **TUI component test harness** *(deferred pull-in)*: the first CLI component-render harness (a new
+ devDependency — part of this workstream's ADR), so render-cadence bugs (the 2.5.H frozen-clock class)
+ get regression tests; add performance regression thresholds (frame time / render count) for the
+ full-screen frame loop.
+- Resize/degrade behavior and the documented screen-reader constraint (raw-mode TUI) with the non-TTY
+ fallback — carried from the original 2.6.E and owned here.
+
+**Acceptance:** bare `relavium` on a TTY opens the full-screen Home; scroll + auto-follow work; the
+`--json` / CI / non-TTY paths are byte-identical to today (harness-proven); the floor-bump ADR is Accepted
+and released as a SemVer-major with migration notes; the component harness runs in CI with at least the
+frozen-clock regression pinned. **Required ADRs:** the ADR-0021-superseding floor ADR + a full-screen
+renderer & TUI-harness ADR.
+
+### 2.6.G — Home management browsers: workflows, runs, agents
+
+The interactive browsers that make the Home the management center. The interaction model follows the
+proven three-level drill-down (list → detail → step detail) with `gh run`-style progressive disclosure
+(every screen hints the next action) and picker-on-omitted-id semantics. The maintainer's separate-command
+sketch (`/active-workflows`, `/workflow-run-history`, …) is **deliberately simplified** into two tabbed
+browsers with argument deep-links — same reach, fewer commands.
+
+**Tasks:**
+
+- **`/workflows` browser** (Home + chat): tabs **Defined | Active | History**, deep-linkable as
+ `/workflows [defined|active|history]`.
+ - *Defined*: the disk catalog (slug, name, node count, last-run status/age; invalid files flagged) with
+ actions — **Run** (foreground: graduate into the live run view), **Run detached** (print the runId,
+ stay in Home), **Export**, reveal path. Starting a run from the Home is new — `run` stays shell-first
+ for scripting, but the Home can now launch.
+ - *Active*: live runs (status, current node, attempt, elapsed, cost) — including runs owned by **other
+ processes** via a poll-based `run_events` tail (seq + WAL make this feasible today), disclosed as
+ node-boundary granularity; a gate-/budget-blocked run shows the resolve affordance inline. Esc detaches
+ without killing; cancel is offered with its cooperative semantics.
+ - *History*: finished runs (status glyph, short id, workflow, relative start, duration, **cost** — the
+ differentiator no competitor CLI lists) with keystroke filters (status/workflow) — no query DSL. Enter
+ → **run detail**: header (status, timing, totals, entry point) + node table (per-node status, duration,
+ attempt, tokens, cost) + a "jump to first failed node" key. Enter on a node → **node detail**: the
+ input / output / duration / tokens / error quintet plus the bounded tool-trace and event timeline
+ (Scheduled/Started/Completed triplets collapsed into one expandable row).
+- **`/agents` browser** (Home + chat): tabs **Defined | Sessions**. *Defined*: the agent catalog with
+ **"start a chat with this agent"** (closing the Home's built-in-agent-only gap). *Sessions*: recent +
+ in-progress sessions — Enter resumes **in place** (the in-Home chat machinery), with a detail view
+ (transcript summary, cost, model attribution).
+- **Actionable Home strip**: the Attention/Continue rows become focusable — a gate row opens an inline
+ resolve card (approve / reject / input, via 2.6.K's shared resume core), a failed run opens its detail,
+ a session row resumes, a run row opens detail. The strip refreshes on an idle tick while the Home is
+ open (today it is snapshot-static).
+- **Liveness**: wire `engine.reconcile()` (never invoked today) on Home open and the browser/status reads,
+ so crashed runs settle `run:failed{internal}` instead of showing as zombie `running` rows; expired gates
+ settle per their timeout policy via 2.6.K's re-arm.
+- Non-interactive parity: extend the read *commands* minimally (`relavium list --runs`, `status `
+ for finished runs, `logs --follow/--failed`) so scripting keeps pace with the TUI —
+ [ADR-0049](../../decisions/0049-cli-machine-output-contract.md)-conformant.
+
+**Acceptance:** every action above works from the Home without a shell command; the three-level drill-down
+is complete over 2.6.H's data; a run started in another terminal is watchable live at node granularity;
+zombie runs reconcile; the browsers degrade at <80×24; the machine-output contract is untouched
+(harness-proven). **Required ADR:** management browsers + run drill-down contract (shared with 2.6.H).
+
+### 2.6.H — Durable run detail: the history data layer
+
+The store/engine half that 2.6.G's browsers read. Today the durable record is node-boundary-only and
+unattributed (step rows never carry agent/model/input; `run_costs.modelId` is always NULL; the firehose is
+never persisted; several consistency gaps are recorded in the deferred doc). This workstream makes the
+durable record complete enough for a first-class drill-down — additively.
+
+**Tasks:**
+
+- **Step attribution**: populate `step_executions.agentId/agentSnapshot/modelId/inputJson` and
+ `run_costs.modelId` from the events the engine already has; give `node:skipped` a step row (thread
+ `nodeType` additively); widen the `StepRecord` projection (output/error/tokens) + a step-detail read.
+- **Exact per-node cost**: an optional `nodeCostMicrocents` on `node:completed` — an additive run-event
+ schema field amending [ADR-0036](../../decisions/0036-run-loop-substrate-event-bus-and-execution-host.md)
+ append-only (optional for backward-compat with existing `--json` consumers; when present, the per-node
+ cost is exact, not a cumulative-delta approximation) — so parallel fan-out attributes exactly instead of
+ via cumulative deltas; carry final totals on `run:failed` / `run:cancelled` (closing the documented
+ undercount).
+- **Bounded durable tool trace** *(ADR decision)*: persist secret-free per-step tool **summaries** —
+ toolId, the sanitized approval-preview target, outcome (ok/denied/failed), duration — never args or
+ result bytes; the token/reasoning firehose stays unpersisted (the ADR-0036 posture holds). This is what
+ the node-detail screen shows as "tool activity".
+- **Store-level gate uniqueness** *(deferred pull-in)*: a uniqueness constraint on `human_gate:resumed`
+ per `(runId, gateId)`, closing the cross-process gate-resolve TOCTOU window at the store.
+- **Consistency fixes** *(deferred pull-ins)*: wrap the run-resume reconstruction reads
+ (`loadRun` + `loadRunEvents` + `loadStepExecutions`) in one read transaction; make the chat persister's
+ per-turn writes atomic (`BEGIN IMMEDIATE` per turn); the **content-level workflow-identity guard** on
+ resume over the frozen `runs.workflow_definition_snapshot`.
+- **Run-submission idempotency** *(deferred pull-in)*: a dedup guard for Home-launched runs (double-Enter
+ must not start two runs).
+
+**Acceptance:** a finished run's detail (attribution, exact per-node cost, tool summaries, skipped nodes)
+is fully reconstructable from `history.db`; the TOCTOU constraint holds under a concurrent two-process
+test; the schema/event changes are additive and `--json` consumers are unaffected; migration provided.
+**Required ADR:** shared with 2.6.G (browsers + durable run-detail; amends ADR-0036 additively).
+
+### 2.6.I — Provider & MCP management from the Home
+
+Closing the two biggest "must drop to shell / must hand-edit TOML" gaps: provider/key CRUD outside the
+onboarding wizard, and MCP servers, which today are managed **only** by hand-editing `[[mcp_servers]]`
+config (there is no `relavium mcp` command at all; the only runtime visibility is `/doctor --deep`).
+
+**Tasks:**
-**Acceptance:** `/rewind`/`/fork` work over the checkpoint substrate; `@`-injection handles globs/dirs;
-markdown/code-blocks render; `/theme` switches themes including the high-contrast and colorblind-safe
-options; the colour-free path stays legible via semantic markers.
+- **`/providers`** (Home + chat palette): list providers with key status + redacted live verify; add a
+ provider (SSRF-validated base URL rules unchanged); set key (masked, keychain-only — the wizard's tested
+ `set-key` path); remove key (confirmed destructive); test. All over the existing `runProviderCommand`
+ cores — no new key-handling code paths.
+- **`/mcp`** (Home + chat palette): list registered servers with a **read-only** status report (the
+ `/doctor --deep` machinery — never connects/spawns on open); add / edit / remove server registrations
+ (stdio + `http`/`sse`/`websocket` behind the existing SSRF floor); named secrets set via a masked prompt
+ into the isolated `mcp-secret:*` keychain namespace — **never** into TOML (env placeholders only).
+- **`relavium mcp list/add/remove/test`** shell family for scripting parity (`--json`-conformant).
+- **Config-write extension** *(ADR)*: extend the
+ [ADR-0063](../../decisions/0063-cli-config-write-contract.md) typed-setter contract to structured
+ `[[mcp_servers]]` writes (which config file owns a tool-written registration, the comment-loss caveat,
+ atomicity, secret-incapability by construction).
+- **Deferred MCP cluster** *(pull-ins)*: the durable cross-invocation **tool-list cache** (~1h TTL,
+ transport-covering key — startup latency); **network header auth**
+ (`Authorization: Bearer {{secrets.}}` via the SDK transport's headers, resolved from
+ `mcp-secret:*`, never logged/serialized — [ADR-0052](../../decisions/0052-inbound-mcp-client-package-lifecycle-registration.md) §6);
+ **mid-call abort propagation** (the engine's `AbortSignalLike` forwarded to the in-flight `tools/call`,
+ so a mid-turn Esc cancels an MCP call instead of only tearing down); optionally the generalized
+ `SecretResolver` seam alongside header auth.
+
+**Acceptance:** providers and MCP servers are fully manageable from the Home and the shell; a network
+server with header auth connects with its secret resolved from the keychain; discovery startup is
+measurably faster with the cache; Esc aborts an in-flight MCP call; the mandatory security review of the
+secret handling + config-write surface passes. **Required ADR:** MCP management surface + config-write
+extension (extends ADR-0063; sits on ADR-0052/0053).
+
+### 2.6.J — Onboarding v2: two auth paths + the Relavium-account stub
+
+The first-run wizard gains the product's future shape without pulling Phase 5 forward.
+
+**Tasks:**
+
+- **Auth-path select** as the wizard's first step:
+ - **(a) Connect a provider (bring your own API key)** — the existing, live flow (provider select →
+ masked key → live validation with cause-aware retry → keychain → starter default model), unchanged.
+ - **(b) Sign in with a Relavium account** — **visible but disabled** ("coming with managed inference"),
+ rendered dimmed with an honest one-line note. Discoverable from day one, selectable never (this
+ phase).
+- **The account-auth forward-design ADR** (Accepted in this phase; **implemented in Phase 5**,
+ [phase-5-managed-inference.md](phase-5-managed-inference.md), riding
+ [ADR-0012](../../decisions/0012-managed-inference-dual-mode.md)–[ADR-0015](../../decisions/0015-managed-mode-data-handling-and-compliance.md)).
+ It records the decided shape so the stub is honest:
+ - The account API key **determines entitlement server-side** — an individual subscription or an
+ organization membership activates automatically from what the key is provisioned for; the user never
+ picks at login.
+ - **No-subscription UX is a first-class state, never a dead end**: a typed, actionable message with the
+ BYOK path offered on the same screen.
+ - **BYOK always coexists**: a signed-in user with no (or an exhausted) subscription keeps full BYOK
+ provider use; at-limit degrades gracefully (finish the turn → wait/upgrade → BYOK fallback).
+ - Mechanics reserved for Phase 5: key-paste first (copy from the account portal), browser OAuth +
+ device-code later; keychain storage; plan-gated features; org-forced login method.
+- Optional wizard polish once 2.6.L lands: a theme step; the outro points at `/help` + `/models`.
+
+**Acceptance:** a keyless first run shows both paths with (b) disabled and honestly labeled; path (a) is
+regression-proven unchanged; the forward-design ADR is Accepted with Phase-5 ownership explicit.
+**Required ADR:** onboarding auth paths + Relavium-account forward design.
+
+### 2.6.K — Run-ops: the resume-path follow-up (budget resume, secret re-provide, gate lifecycle)
+
+The focused follow-up the 2.5 close deliberately deferred — both headline items refactor the
+security-sensitive `gate.ts` cross-process resume path, so they land together with fresh context.
+
+**Tasks:**
+
+- **Extract a shared cross-process resume core** from `gate.ts` (snapshot reload → checkpoint reconstruct →
+ `resumeFromCheckpoint` → drive) that the gate command, the budget command, and 2.6.G's inline resolve
+ card all consume.
+- **`relavium budget resume [--approve|--abort]`** *(deferred pull-in)*: the documented command
+ over the engine's existing budget-gate resume; plus the Home affordance on budget-paused rows.
+- **Secret re-provide on resume** *(deferred pull-in, security)*: let the operator re-supply a
+ `secret`-typed input on a cross-process resume (stdin-only, `provider set-key` discipline; or keychain
+ re-resolution keyed by the input `ref` (its stable identifier in the workflow YAML)),
+ relaxing today's fail-closed `MaskedSecret` exit-2 — behind a
+ **mandatory security review** (this deliberately relaxes a fail-closed guarantee into
+ allow-with-re-provisioning).
+- **Gate timeout re-arm on rehydration** *(deferred pull-in)*: re-arm a still-pending gate's persisted
+ `expiresAt`/`timeoutAction` against a real clock on reconcile/resume, so a crash-while-paused run's
+ deadline is honored.
+- **Exit-code fidelity** *(deferred pull-in)*: distinguish a gate park from a media-only park on
+ `run:paused` (media parks are reachable since 2.S) in the human message and, if decided, the exit code —
+ documented in [commands.md](../../reference/cli/commands.md).
+- **Session budget pause/resume** *(deferred pull-in, engine)*: the chat cost-cap `pause_for_approval`
+ rides the EA4 pause/resume machine (today it settles the turn loudly) — the ADR-0028 session arm.
+
+**Acceptance:** a budget-paused run is resumable from the CLI and the Home; a secret-bearing run is
+resumable via re-provide with the security review passed; timers re-arm; a chat hitting its cost cap can
+pause-and-approve instead of failing the turn; the shared resume core is the only resume path (no
+duplication). **Required ADR:** none new (rides ADR-0028/ADR-0006); the security review is the gate.
+
+### 2.6.L — `/settings`, the theme system, and localization
+
+The personalization arm: a settings surface over an extended config-write contract, a real theme system,
+and the first localized agentic CLI (a genuine differentiator — competitor i18n is white space).
+
+**Tasks:**
+
+- **Theme system**: a palette abstraction replacing the hardcoded literal ink colors; named built-ins —
+ `default`, `high-contrast`, `colorblind-safe` (the accessibility pair carried from the original 2.6.E),
+ and a terminal-respecting `ansi` theme (`NO_COLOR`/`--no-color` overrides every theme identically: all
+ color codes dropped, semantic markers degraded — the `ansi` theme is not a color-free bypass);
+ `[preferences].theme` (schema-present, read by nothing today) finally read; **`/theme`** switcher with
+ live preview. Semantic markers (`✓`/`✗`/`⏸`) survive `--no-color`/`NO_COLOR` and degrade to ASCII
+ (`[v]`/`[x]`/`[||]`) without Unicode.
+- **`/settings`** (Home + chat): a sectioned screen (appearance / language / chat defaults / update
+ channel) over the **extended** [ADR-0063](../../decisions/0063-cli-config-write-contract.md) typed-setter
+ (new keys: `theme`, `language`; still global-preferences-only, atomic, secret-incapable by construction —
+ project files stay hand-authored).
+- **i18n foundation**: an in-house string catalog (data ≠ code — zero conditional logic in translation
+ data; no runtime dependency expected, else ADR); `[preferences].language`; locales **`en` + `tr`**
+ in-phase; a CI **key-parity test** (fails on missing/extra keys) + a dead-string lint — landing the
+ deferred i18n standard as a `docs/standards/` entry. Acceptance includes IME-safe input and
+ wide-character-aware layout, laying the groundwork for future CJK locales.
+- Diagnostics/`--json` output stays English-stable (machine contract); localization applies to the
+ interactive surfaces.
+
+**Acceptance:** `/settings` edits persist atomically and round-trip; themes switch live incl. the
+accessibility pair; the color-free path stays legible; interactive surfaces run fully in `tr` with
+CI-enforced key parity; diagnostics and `--json` remain English-stable per
+[ADR-0049](../../decisions/0049-cli-machine-output-contract.md); the machine-output contract is
+character-for-character unaffected. **Required ADR:** i18n +
+theming architecture.
+
+### 2.6.M — The first-class toolbelt: breadth + rendering
+
+Closing the tool gap against competitor CLIs. Today the registry has 13 built-ins with **no** file
+edit/patch, **no** content search, **no** find, **no** todo, **no** ask-user, and a dormant `web_search`
+(needs an unwired credential resolver). Every addition is engine-pure (Zod args, `llmVisibleParams`,
+policy class, bounded results), documented in
+[built-in-tools.md](../../reference/shared-core/built-in-tools.md), selectable in agent/workflow YAML, and
+sits under the existing governance floor (advertise-filter + fail-closed approval + protected-path/
+sensitive-read floors).
+
+**Tasks:**
+
+- **`edit_file`** — exact old→new string replacement (+ `replace_all`, uniqueness guard, read-before-edit
+ safety), `fs_write`-governed with a **diff preview** at the approval prompt. The single biggest gap.
+- **`search_files`** — bounded in-house content search (workspace-jailed, sensitive-read floor,
+ ignore-file-respecting; linear matcher — no regex-DoS surface), idempotent.
+- **`find_files`** — glob file finding across the tree (mtime-sorted, bounded), idempotent — promoting the
+ current read_file/list_directory glob options into a first-class discovery tool.
+- **Todo/plan tool** — a structured, session-scoped task list the model maintains, rendered as a live TUI
+ checklist (persists across compaction); ungoverned (no host arm).
+- **`ask_user`** — a structured mid-turn question (options + free text) on interactive surfaces via a
+ keyboard-owning overlay; typed `tool_unavailable` on non-interactive surfaces; workflows keep
+ `human_gate`.
+- **`web_search` activation** *(deferred pull-in)*: wire the `egressCredentialResolver` from the keychain
+ (today a configured search 401s) and document the config-pinned provider contract; `http_request`
+ unchanged.
+- **`extra_roots`** *(deferred pull-in)*: the `[chat].extra_roots` config key + factory wiring, unblocking
+ the `project` fs tier's documented allowlist (narrow-only, never a jail hole).
+- **Tool-call rendering v2** (with 2.6.F's renderer): keep the collapsed one-line annotation as the
+ default, add a **details view** (a `/details` toggle or transcript overlay) revealing *sanitized,
+ bounded* target/arg previews and result summaries, and **diff rendering** (width-adaptive stacked /
+ side-by-side) for `edit_file`/`write_file` at the approval prompt and in details. This deliberately
+ revises 2.5's never-render-args posture — it is sanctioned only via the ADR + a security review (every
+ string through the shared sanitize floor; secrets structurally excluded; bounded).
+- **Target-scoped approval cache** *(deferred pull-in)*: key `[a]lways` grants by `(toolId, target class)`
+ (path prefix / host / MCP server) instead of tool id alone, and give `mcp_call`/`web_search` a structured
+ `{server, tool}`/query preview so their blank-preview once-only downgrade becomes a real reviewable
+ grant.
+- **Default chat agent grant review**: widen the built-in agent's grant to the new idempotent read tools
+ (search/find/todo); write/exec/egress stay opt-in via mode + approval.
+
+**Acceptance:** the toolbelt covers read / edit / search / find / exec / web / todo / ask-user; each tool
+is YAML-selectable and correctly mode-gated on every surface; render v2 ships with diffs and the details
+toggle behind a passed security review; the approval cache is target-scoped; the tool-gap table in the
+research record is closed or explicitly deferred per item. **Required ADR:** toolbelt additions +
+tool-render/approval-preview contract (extends ADR-0029/ADR-0057 posture).
+
+## Deferred-tasks pulled into this phase
+
+The [deferred-tasks.md](../deferred-tasks.md) triage (2026-07-08) mapped these confirmed-open items into
+workstreams — each stays checked off **only** in the PR that lands it:
+
+| Deferred item (deferred-tasks.md) | Lands in |
+|---|---|
+| Node floor: dev/CI bump + supported-floor decision (EOL Node 20) | 2.6.F |
+| CLI render-layer (ink component) test harness | 2.6.F |
+| `AgentParseError` invisible on `chat --agent` / `agent run` | 2.6.B |
+| MCP `stdio` import-trust/consent gate + `npx` pinning (ADR-0052 §2) | 2.6.B |
+| Parse-time gate on system-bound fields (trusted `{{ctx}}`) | 2.6.D |
+| `@`-glob / directory expansion (ADR-0061) | 2.6.E |
+| Cross-process gate-resolve TOCTOU (store uniqueness) | 2.6.H |
+| Run-resume torn-read wrap · chat-persister turn atomicity | 2.6.H |
+| Content-level workflow-identity guard on resume | 2.6.H |
+| Run-submission idempotency / double-submit dedup | 2.6.H |
+| MCP tool-list cache · network header auth (§6) · mid-call abort | 2.6.I |
+| `relavium budget resume` command (documented, unimplemented) | 2.6.K |
+| Re-provide `secret`-typed inputs on cross-process resume | 2.6.K |
+| Re-arm a still-pending gate's timeout on rehydration | 2.6.K |
+| `run:paused` gate-park vs media-park exit distinction | 2.6.K |
+| Session budget pause/resume (EA4 ride; 1.V follow-up) | 2.6.K |
+| i18n CI key-parity + data/code separation standard | 2.6.L |
+| Live `web_search`/`http_request` egress credential resolver | 2.6.M |
+| `project`-tier `extraRoots` allowlist (config source now exists) | 2.6.M |
+| Target-scoped approval cache + structured MCP preview | 2.6.M |
+| Approval-consent-line zero-width hardening · shared `[c]` reducer | 2.6.M (with render v2) |
+
+Items evaluated and **kept deferred** (Phase-3/1.AH homes, SDK-blocked, accepted residuals, or
+scale-gated) remain in [deferred-tasks.md](../deferred-tasks.md) with their reasons — notably the
+`read_media` D12 cluster, chat sub-agents, retry-from-node, the desktop tool host, and the media/seam
+1.AH cluster.
## Milestones
| In-phase | Completed by | Outcome |
|----------|--------------|---------|
-| M2.6-1 Authoring core shared | 2.6.A | `@relavium/authoring` + catalog-aware pre-flight |
-| M2.6-2 Conversational authoring | 2.6.B + 2.6.D | "define a workflow…" produces valid YAML; `{{ctx.*}}` lands |
-| M2.6-3 Reseat + parity | 2.6.C + 2.6.E | Mid-session model switch + parity polish |
+| M2.6-1 Foundation | 2.6.F | Node floor decided/shipped; full-screen renderer + TUI harness — the substrate for every arm |
+| M2.6-2 Authoring core shared | 2.6.A | `@relavium/authoring` + catalog-aware pre-flight |
+| M2.6-3 Conversational authoring | 2.6.B + 2.6.D | "define a workflow…" → valid YAML in the Home; `{{ctx.*}}` lands |
+| M2.6-4 The Home-managed CLI | 2.6.G + 2.6.H + 2.6.I + 2.6.J + 2.6.K | Every management task doable from Home; drillable, attributed run history; onboarding v2 |
+| M2.6-5 First-class experience | 2.6.C + 2.6.E + 2.6.L + 2.6.M | Toolbelt parity + settings/theme/i18n + chat polish — **phase close** |
## Sequencing & parallelization
-2.6.A first (the package + shared pre-flight). Then 2.6.B (conversational authoring, depends on A + the
-2.5.E approval/write path) in parallel with 2.6.C (reseat) and 2.6.D ({{ctx.*}}); 2.6.E is additive
-polish throughout.
+```mermaid
+flowchart LR
+ F["2.6.F
floor + full-screen
foundation"] --> G["2.6.G
browsers"]
+ F --> L["2.6.L
settings · theme · i18n"]
+ F --> E["2.6.E
chat polish"]
+ H["2.6.H
run-detail data"] --> G
+ K["2.6.K
run-ops resume core"] --> G
+ A["2.6.A
authoring package"] --> B["2.6.B
conversational authoring"]
+ D["2.6.D
ctx interpolation"] --> B
+ M["2.6.M
toolbelt"] -. render v2 after F .-> F
+ I["2.6.I
provider + MCP mgmt"]
+ J["2.6.J
onboarding v2"]
+```
+
+**2.6.F runs first** (the floor decision + renderer + harness gate every TUI-heavy arm). Then two parallel
+spines: **(i) authoring** — 2.6.A → 2.6.B, with 2.6.D alongside; **(ii) experience** — 2.6.H and 2.6.K
+early (data + resume core), then 2.6.G on top; 2.6.I and 2.6.J are independent and can land any time;
+2.6.M's engine-pure tools can start immediately (only its render-v2 half waits on F); 2.6.E and 2.6.L
+follow F. 2.6.C's residual is a small read, any time.
## Dependencies
-- **Phase 2.5** complete — specifically 2.5.A (the wired write-capable tool-environment) and 2.5.E
- (accept-edits per-tool approval), which gate the authoring write surface.
-- **2.J** (the in-tree authoring core that 2.6.A promotes) — landed.
-
-## Exit criteria (go / no-go)
-
-1. `@relavium/authoring` is the shared authoring core; the CLI consumes it; `create` runs the catalog-aware
- pre-flight.
-2. A conversational request produces a strict-valid `.relavium.yaml` (pre-flight-proven, security-reviewed);
- the knowledge pack is derived, not restated.
-3. Mid-session `/models` reseat works with the context-loss notice and per-message attribution.
-4. `{{ctx.*}}` interpolation lands and `agent run --input` is unblocked.
-5. The required ADRs are Accepted.
+- **Phase 2.5** complete — specifically 2.5.A (the wired tool-environment), 2.5.E (per-tool approval /
+ modes), 2.5.B/C (the Home + the two-registry command model), and ADR-0063 (config-write) — all met.
+- **2.J** (the in-tree authoring core 2.6.A promotes) — landed.
+- The Node supported-floor decision (2.6.F) gates the ink-7 evaluation but **not** the rest of the phase
+ (every workstream must land on the current floor if the maintainer defers the bump).
+
+## Exit criteria (go / no-go → Phase 3)
+
+1. `relavium` on a TTY opens the **full-screen Home**; `--json` / CI / non-TTY behavior is byte-identical
+ (regression-harness proven); the inline renderer remains available.
+2. **The Home manages everything**: providers/keys, models, MCP servers, settings, workflow
+ start/monitor/history with node-level drill-down, agent start/resume, gate + budget resolution, and
+ authoring — no routine task requires a shell subcommand. (Subcommands and the ADR-0049 machine surface
+ are untouched and permanent; whether to de-emphasize interactive duplicates in `--help` is a phase-end
+ review decision, never a removal.)
+3. A conversational request produces a strict-valid, catalog-validated `.relavium.yaml`
+ (pre-flight-proven, security-reviewed); the knowledge pack is derived, not restated; `{{ctx.*}}` lands
+ and `agent run --input` is unblocked.
+4. The **toolbelt** ships (`edit_file`, `search_files`, `find_files`, todo, `ask_user`, working
+ `web_search`) — YAML-selectable, mode-gated, rendered with diffs/details behind a passed security
+ review.
+5. Run history is attributed and drillable (list → run → node with the quintet + tool summaries); the
+ gate TOCTOU is store-closed; crashed runs reconcile; cross-process live watch works.
+6. `/settings`, the theme system (incl. the accessibility pair), and **`en`+`tr`** localization ship with
+ CI key-parity.
+7. The required ADRs are Accepted, and every touched spec's canonical home
+ ([commands.md](../../reference/cli/commands.md), [home.md](../../reference/cli/home.md),
+ [chat-session.md](../../reference/cli/chat-session.md),
+ [built-in-tools.md](../../reference/shared-core/built-in-tools.md),
+ [config-spec.md](../../reference/contracts/config-spec.md),
+ [database-schema.md](../../reference/desktop/database-schema.md)) is updated — no docs-debt carried
+ out of the phase.
## Required ADRs
-Drafted as **Proposed** alongside this plan; each is reviewed and finalized (→ Accepted) when its
-workstream begins.
-
-1. [ADR-0058](../../decisions/0058-relavium-authoring-package-and-conversational-authoring.md) —
- `@relavium/authoring` package + conversational-authoring pre-flight contract (2.6.A/2.6.B).
-2. [ADR-0059](../../decisions/0059-cli-mid-session-model-reseat.md) — mid-session model reseat;
- refines [ADR-0024](../../decisions/0024-agent-first-entry-point-agentsession.md) (2.6.C).
-3. [ADR-0060](../../decisions/0060-session-ctx-prompt-interpolation.md) — session `{{ctx.*}}`
- interpolation, unblocking `agent run --input` (2.6.D).
+> **This table is the canonical tracker for ADR status, owning workstream, and disposition across
+> the phase.** Workstream sections reference it rather than restating ADR details.
+
+| # | ADR | Topic | Status | Workstream |
+|---|-----|-------|--------|------------|
+| 1 | [ADR-0058][] | `@relavium/authoring` + conversational authoring | Proposed | 2.6.A / 2.6.B |
+| 2 | [ADR-0059][] | Mid-session model reseat | **Accepted** (shipped 2.5.G) | 2.6.C (residual) |
+| 3 | [ADR-0060][] | Session `{{ctx.*}}` interpolation | Proposed | 2.6.D |
+| 4 | *(new)* | Node supported-floor bump (`>=22`; supersedes ADR-0021) | Drafted when 2.6.F starts | 2.6.F |
+| 5 | *(new)* | Full-screen TUI renderer + component test harness | Drafted when 2.6.F starts | 2.6.F |
+| 6 | *(new)* | Management browsers + durable run detail (amends ADR-0036) | Drafted when 2.6.G starts | 2.6.G / 2.6.H |
+| 7 | *(new)* | MCP management surface + config-write extension (extends ADR-0063) | Drafted when 2.6.I starts | 2.6.I |
+| 8 | *(new)* | Onboarding auth paths + Relavium-account forward design (rides ADR-0012–0015) | Drafted when 2.6.J starts | 2.6.J |
+| 9 | *(new)* | Toolbelt additions + tool-render/approval-preview contract (extends ADR-0029/ADR-0057) | Drafted when 2.6.M starts | 2.6.M |
+| 10 | *(new)* | i18n + theming architecture | Drafted when 2.6.L starts | 2.6.L |
+
+[ADR-0058]: ../../decisions/0058-relavium-authoring-package-and-conversational-authoring.md
+[ADR-0059]: ../../decisions/0059-cli-mid-session-model-reseat.md
+[ADR-0060]: ../../decisions/0060-session-ctx-prompt-interpolation.md
+
+> **Conditional:** 2.6.E requires a small dedicated ADR **only if** a markdown rendering dependency is
+> chosen (the in-house renderer is preferred); if the in-house path is taken, no 2.6.E ADR is needed.
+>
+> **Deferred:** A future validator-dependency ADR will be needed for `output_schema` deep JSON-Schema
+> conformance (currently out of scope for this phase; tracked in
+> [deferred-tasks.md](../deferred-tasks.md)).
## Risks & mitigations
| Risk | Mitigation |
|------|------------|
-| Authoring knowledge drifts from the specs (restate) | Derive from the Zod schemas / reference docs; a no-duplication check is an acceptance gate ([CLAUDE.md](../../../CLAUDE.md) #8) |
-| Authored YAML smuggles secrets | The authored artifact passes the existing `parseWorkflow` secret-taint gate; the write surface is security-reviewed |
-| Reseat sells a false promise | An explicit context-loss notice; full-fidelity tool-context is Phase 3 |
-| Package promotion over-engineers a CLI-only need | The maintainer decision is multi-surface (desktop/VS Code also consume); the add-package ADR records the rationale |
+| **Scope breadth** — thirteen workstreams invite drift | Milestone gating (M2.6-1..5); the additive arms (E/L parts, M render-v2) can defer individual items without breaking the spine; the pull-in table keeps deferred-tasks as the single overflow home |
+| Full-screen renderer performance/fragility on ink | The floor bump unlocks ink 7; the component harness carries performance regression thresholds; the inline renderer is retained as a first-class fallback, and non-TTY paths never change |
+| Rendering args/diffs leaks sensitive data (reverses a 2.5 posture) | Sanctioned only by the toolbelt-additions ADR + a mandatory security review; every string passes the shared sanitize floor; bounded previews; secrets structurally excluded (keychain-only, never in tool args by construction) |
+| Secret re-provide relaxes a fail-closed guarantee | stdin-only discipline, keychain re-resolution preferred, mandatory security review, and the shared resume core keeps one audited path |
+| Authoring knowledge drifts from the specs (restate) | Derived from the Zod schemas / reference docs; a no-duplication check is an acceptance gate |
+| Authored YAML smuggles secrets | The `parseWorkflow` secret-taint gate + the write-surface security review |
+| Browser complexity balloons | Hard cap at the three-level drill-down; keystroke filters, no query DSL; tabs + deep-links instead of six commands; the desktop canvas stays the rich escape hatch |
+| i18n churn destabilizes strings | Data ≠ code catalog; CI key-parity + dead-string lint land **with** the first locale, not after |
+| ADR load stalls the phase | ADRs are drafted per-workstream as Proposed when the workstream starts (the 2.5 pattern), not all up front |
+| Competitor-copy erodes Relavium's posture | Patterns are stolen, postures are not: keychain-only secrets, fail-closed approval, YAML-first artifacts, and the ADR-0049 machine contract are non-negotiable filters on every borrowed idea |
Part of [roadmap/](../README.md). Carry-over hardening lives in [../deferred-tasks.md](../deferred-tasks.md).