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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ gateway; engine stays local, Phase 2) — split across build phase 5 (managed in
phase 6 (cloud execution + portal); the engine is identical across all three (ADR-0012..0015).
**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.**
(Conversational Authoring and the First-Class CLI) is in progress, with an interlude —
Phase 2.6.5 (Core reliability remediation) — running between remediation Waves 1 and 2:
14 of 47 items closed, including all eight P0 blockers (ADR-0078–ADR-0084, merged 2026-08-24).**
See [docs/roadmap/current.md](docs/roadmap/current.md) for live status.

## The non-negotiable rules
Expand Down
7 changes: 7 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ PR #75, 2026-07-13). The phase is a full-screen Home-managed CLI with conversati
browsers, competitor-breadth tools, settings/theming/`en`+`tr` localization, and the
run-ops resume follow-up.

**An interlude is running between Wave 1 and Wave 2 of the remediation: Phase 2.6.5 (Core reliability),
14 of 47 items closed** — `W0` (PR #82, 2026-08-11) and `W1`, the eight P0 blockers plus `CR-92`, merged
2026-08-24 (PR #83) behind [ADR-0078](docs/decisions/0078-ordered-durable-append-and-the-terminal-outbox.md)–[ADR-0084](docs/decisions/0084-consent-before-a-local-mcp-spawn.md):
ordered durable append, cross-process run ownership, the durable effect journal, untrusted compaction summaries,
the stream-grammar seam obligation, engine-side input admission and resume identity, and consent before a local
MCP spawn. No new product surface — only the invariants an existing surface already claims.

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;
Expand Down
2 changes: 1 addition & 1 deletion docs/decisions/0069-string-width-for-the-cli-renderer.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

- **Status**: Accepted
- **Date**: 2026-07-10 (accepted 2026-07-11)
- **Related**: [ADR-0068](0068-full-screen-tui-renderer-ink7-harness.md) · [ADR-0047](0047-cli-render-seam-and-framework-free-cores.md) · [ADR-0067](0067-node-supported-floor-22-reaffirm-better-sqlite3.md)
- **Related**: [ADR-0068](0068-full-screen-tui-renderer-ink7-harness.md) · [ADR-0047](0047-cli-framework-commander-ink-clack.md) · [ADR-0067](0067-node-supported-floor-22-reaffirm-better-sqlite3.md)

> **Accepted on 2026-07-11** when the maintainer merged PR #74 (2.6.F) into `main` — the merge carries the
> `string-width` dependency, which is the [CLAUDE.md](../../CLAUDE.md) rule 2 approval this ADR gated. The code in
Expand Down
4 changes: 2 additions & 2 deletions docs/reference/shared-core/database-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ erDiagram

#### `llm_providers`

Registered LLM providers. The actual API key never lives here — only a reference; the key is stored in the OS keychain (see [keychain-and-secrets.md](keychain-and-secrets.md)).
Registered LLM providers. The actual API key never lives here — only a reference; the key is stored in the OS keychain (see [keychain-and-secrets.md](../desktop/keychain-and-secrets.md)).

| Column | Type | Constraints |
|--------|------|-------------|
Expand Down Expand Up @@ -849,7 +849,7 @@ This realizes the concurrent-process write requirement recorded in the [ADR-0064

At-rest encryption of `history.db` is **per-surface**:

- **Desktop:** opened with SQLCipher. The passphrase is derived from a stable machine secret (combined with the OS keychain entry) so the database opens on restart without prompting the user; see [keychain-and-secrets.md](keychain-and-secrets.md).
- **Desktop:** opened with SQLCipher. The passphrase is derived from a stable machine secret (combined with the OS keychain entry) so the database opens on restart without prompting the user; see [keychain-and-secrets.md](../desktop/keychain-and-secrets.md).
- **CLI (Phase 2):** opened with `better-sqlite3` **unencrypted**, guarded by owner-only OS file permissions — `~/.relavium/` at `0700` and `history.db` (with its `-wal`/`-shm` sidecars) at `0600`, set with an explicit `chmod` (umask-independent, applied even to a pre-existing directory). On Windows, POSIX mode bits do not apply (`chmod` is a no-op); protection falls to the per-user `%USERPROFILE%` NTFS ACL. The file holds **no credentials** — keys stay in the OS keychain ([ADR-0006](../../decisions/0006-os-keychain-for-api-keys.md)) and the engine masks secrets at the bus before persistence ([ADR-0036](../../decisions/0036-run-loop-substrate-event-bus-and-execution-host.md)) — so the unencrypted-at-rest content is run data (prompts, outputs, costs), not secrets. Rationale and the cross-surface Phase-3 follow-on: [ADR-0050](../../decisions/0050-cli-history-db-at-rest-posture.md).

The per-project `runs.db` is **not** encrypted on any surface because it is intentionally git-committed and contains only non-sensitive run metadata (no prompts, completions, or tokens).
Expand Down
21 changes: 14 additions & 7 deletions docs/roadmap/current.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ flowchart TD
W0["Wave 0 — One true baseline<br/>baseline ✅ · CI truth · numbers"]
W1["Wave 1 — Stop the bleeding ✅<br/>3 CRITICALs · cost cap · ADR-0074"]
LEDGER["#W15-1 — realized-cost ledger ✅<br/>ADR-0076 + ADR-0077"]
P265["Phase 2.6.5 — Core reliability<br/>46 CR items · 8 P0 ADRs · 9 closed<br/>absorbs the hostile-MCP class"]
P265["Phase 2.6.5 — Core reliability<br/>47 CR items · 8 P0 blockers behind ADR-0078–0084<br/>W0+W1 closed (14)<br/>absorbs the hostile-MCP class"]
W2["Wave 2 — Shut the doors<br/>fs jail · secrets · config trust<br/>certifies 2.5.5 EXIT 1–3"]
W3["Wave 3 — Clear the ground<br/>god-file decomposition · CLI net"]
W4a["Wave 4a — The spine<br/>2.6.A/D/H/K + 2 ADRs"]
Expand Down Expand Up @@ -464,16 +464,23 @@ gaps**: effect journal, stdio MCP consent-before-spawn, run lease, compaction tr
input admission, event-log ordering. Three separate reviews landing on the same seven points is not opinion.

The full, self-contained work list is
[phase-2.6.5-core-reliability-remediation.md](phases/phase-2.6.5-core-reliability-remediation.md) — **46 items**
[phase-2.6.5-core-reliability-remediation.md](phases/phase-2.6.5-core-reliability-remediation.md) — **47 items**
(`CR-01`…`CR-95`) with evidence, fix, acceptance criteria and a decision/ADR/gate register, written so the work
can be done from that document alone. An adversarial plan review on 2026-08-10 corrected the phase boundary,
the exit rule and the execution order, and added two items (`CR-17` resume identity, `CR-63` `input_schema`
docs-only).
docs-only); `CR-64` came from the Batch 1 triage and `CR-21b` from ADR-0082 §10, which is why the total has
moved since the list was first written.

> **Live status — 6 of 46 closed, merged 2026-08-11 (PR #82).** The prerequisite (`#W15-1`), the oracle
> (`CR-90`, `CR-91`) and all of `W0` (`CR-01`–`CR-03`). `CR-64` was added in the same batch and is open.
> **Next is the durability spine — `CR-10` first**, and it is ADR-first: no code until the decision is
> recorded. Per-item history and the carried-forward gaps live in the phase document.
> **Live status — 14 of 47 closed. `W0` and `W1` are both done.**
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
>
> - **Batch 1, merged 2026-08-11 (PR #82)** — the prerequisite (`#W15-1`), the oracle (`CR-90`, `CR-91`) and
> all of `W0` (`CR-01`–`CR-03`). `CR-64` was added in the same batch and is open.
> - **Batch 2, merged 2026-08-24 (PR #83)** — all of `W1`: the eight P0 blockers plus `CR-92`, behind
> ADR-0078…ADR-0084. A comprehensive review of the assembled PR found seven further defects, six of them in
> the W1 code itself; all seven were fixed and mutation-verified before merge.
>
> **Next is `W2` — liveness and deadlines.** Per-item history, the seven post-review findings and the
> carried-forward gaps live in the phase document.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

**This is the corrected execution order, and it is what the graph above shows:**

Expand Down
48 changes: 48 additions & 0 deletions docs/roadmap/deferred-tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,54 @@ Severity is the review's verified rating. Check an item off in the PR that resol
there is concrete surface demand or telemetry showing operators need an earlier signal.
*(1.AC; ADR-0028; config-spec.md; workflow-yaml-spec.md)*

## Phase 2.6.5 `W1` residuals (PR #83, merged 2026-08-24)

Named rather than left implicit, because every one of them was examined during `W1` and consciously left
open — an unstated residual reads as an oversight, and the review that found the seven `PR83-*` defects said
so directly: these "should remain visible rather than disappear behind the green test suite."

- [ ] **Terminal-outbox drain, callable from any surface ([ADR-0078](../decisions/0078-ordered-durable-append-and-the-terminal-outbox.md) §4/§5).**
`drainTerminalOutbox` is a `WorkflowEngine` method, and `run`/`gate` are the only commands that construct
one — `chat`, `agent run` and the bare-invocation Home run on `AgentSession` and have no engine to drain
with. `PR83-06` corrected the documentation and made `relavium status` NAME a run whose terminal is held
(`terminalHeld` in `--json`), but the drain itself is still reachable from two commands only. The real fix
lifts it off the engine onto its host ports (`store` + `terminalOutbox` + `runLeases` + `mediaReferences`),
so any surface can call it at startup. **Acceptance:** a held terminal is retried before `status` reads the
run; a drain failure stays non-fatal and preserves the entry; the entry is removed only once the exact
terminal is durably present. Deliberately NOT done inside `status` as a read command — draining claims a run
lease, and a status read must not take ownership of a run another process may be finishing.
*(packages/core/src/engine/engine.ts; apps/cli/src/commands/status.ts; ADR-0078 §4/§5)*

- [ ] **Check-then-write symlink window on the append-only files.** The MCP grant store and the terminal
outbox both `lstat` a path and then append to it by name, and their comments admit the window. On POSIX a
descriptor-based open with `O_NOFOLLOW | O_APPEND | O_CREAT` followed by `fstat`/`fchmod` closes it. Recorded
as defense-in-depth rather than a blocker: the present threat already requires write access to the user's
`~/.relavium` directory. *(apps/cli/src/engine/{mcp-consent,terminal-outbox}.ts)*

- [ ] **Consent overflow can be approved without being read ([ADR-0084](../decisions/0084-consent-before-a-local-mcp-spawn.md) §7).**
The prompt shows 12 arguments / environment entries and states how many more exist, asking the user to open
the artifact. That bounds terminal abuse well, but a declaration whose dangerous part sits in the hidden tail
can still be approved. A premium trust experience would require an explicit view/acknowledge step when
overflow exists. *(apps/cli/src/mcp/consent-prompt.ts; ADR-0084 §7)*

- [ ] **The effect audit's occurrence is coarser than its type promises ([ADR-0080](../decisions/0080-durable-effect-journal-and-the-tiered-effect-contract.md)).**
`effect-journal-store.ts` records openly that the provider-attempt and provider tool-call identity are not
threaded to dispatch. Nothing load-bearing depends on them — the dedup key is the identity and the resume
gate reads the scope — but an operator-facing journal should eventually carry the exact occurrence
`EffectAttemptId` describes. *(packages/db/src/effect-journal-store.ts)*

- [ ] **An authored `pattern` with no `max_length` can still stall the process ([ADR-0083](../decisions/0083-input-admission-and-a-resume-that-verifies-its-own-identity.md) §4).**
`max_length` bounds the input a catastrophic regex chews on, and it is checked first — but only when the
author supplied it. ADR-0083 accepts this floor explicitly. A stronger contract would require `max_length`
whenever `pattern` is present, or admit only a demonstrably safe regex subset. *(packages/shared/src/workflow.ts; ADR-0083 §4)*

- [ ] **Two SonarCloud CRITICALs are declines, not debt — mark them Accepted in the UI.**
`WorkflowEngine#emitDurable`'s closure (23) and `dispatch` (22) are both over the cognitive-complexity
threshold and neither can be split without harm: in both, the branches ARE the ordering the surrounding
comments exist to protect. `#emitDurable`'s extraction would reinsert the microtask hop that reordered the
log once already. Resolving them requires a maintainer action in SonarCloud, not a code change.
*(packages/core/src/engine/engine.ts; packages/core/src/tools/registry.ts)*

## Interpolation engine (1.L2) follow-ups

> A comprehensive multi-dimensional pre-merge review of **1.L2** (PR #15, merged 2026-06-12) confirmed
Expand Down
54 changes: 50 additions & 4 deletions docs/roadmap/phases/phase-2.6.5-core-reliability-remediation.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Phase 2.6.5 — Core reliability remediation (interlude)

- **Status**: in progress — the prerequisite and the oracle are closed; the durability spine is next
- **Opened**: 2026-08-09 · **Plan corrected**: 2026-08-10 · **First batch merged**: 2026-08-11 (PR #82)
- **Status**: in progress — **`W0` and `W1` are closed** (14 of 47 items); `W2` is next
- **Opened**: 2026-08-09 · **Plan corrected**: 2026-08-10 · **First batch merged**: 2026-08-11 (PR #82) ·
**`W1` merged**: 2026-08-24 (PR #83)
- **Predecessor**: Wave 1 of the 2.5.5 remediation (complete — PR #81), then the `#W15-1` realized-cost
ledger implementation (**complete 2026-08-10**, ADR-0076 + ADR-0077 — see [Prerequisite](#prerequisite))
- **Successor**: Wave 2 of the 2.5.5 remediation, **reduced** — this phase absorbs Wave 2's hostile-MCP
Expand Down Expand Up @@ -120,8 +121,46 @@ shape.
>
> `CR-64` was **added** in the same batch (from the YAML/git-native review triage); it is open.
>
> **Next: the durability spine**, `CR-10` → `CR-11` → `CR-92` → `CR-12`, in that order and ADR-first. The
> oracle exists specifically to prove it, and `CR-10` is the item everything else assumes.
> **Next after Batch 1 was the durability spine**, `CR-10` → `CR-11` → `CR-92` → `CR-12` — a dependency
> chain, recorded here as the history of why that order was chosen. Batch 2 below is the whole of `W1`: those
> four plus the independent `CR-13`, `CR-14`, `CR-15`, `CR-16` and `CR-17` lines, and its table is ordered by
> ADR rather than by the chain.
>
> **Batch 2 — `W1`, merged to `main` 2026-08-24 (PR #83).** All eight P0 blockers plus `CR-92` — nine items
> behind **seven** ADRs, since `CR-92` shares `CR-10`'s and `CR-15`/`CR-17` share one. Each item had an Opus
> and a Sonnet review round folded before the next one started.
>
> | Item | Closed | ADR |
> |------|--------|-----|
> | `CR-10` | 2026-08-11 | [ADR-0078](../../decisions/0078-ordered-durable-append-and-the-terminal-outbox.md) |
> | `CR-92` | 2026-08-11 | with `CR-10`'s |
> | `CR-11` | 2026-08-17 | [ADR-0079](../../decisions/0079-cross-process-run-ownership-lease-and-fencing-token.md) |
> | `CR-12` | 2026-08-18 | [ADR-0080](../../decisions/0080-durable-effect-journal-and-the-tiered-effect-contract.md) |
> | `CR-13` | 2026-08-18 | [ADR-0081](../../decisions/0081-the-compaction-summary-is-untrusted-and-the-system-prompt-is-branded.md) |
> | `CR-14` | 2026-08-19 | [ADR-0082](../../decisions/0082-the-stream-grammar-is-a-seam-obligation-and-every-attempt-has-a-deadline.md) |
> | `CR-15` · `CR-17` | 2026-08-19 | [ADR-0083](../../decisions/0083-input-admission-and-a-resume-that-verifies-its-own-identity.md) |
> | `CR-16` | 2026-08-20 | [ADR-0084](../../decisions/0084-consent-before-a-local-mcp-spawn.md) |
>
> **A comprehensive review of the assembled PR found seven further defects, all fixed before merge** — and
> they are recorded here rather than quietly folded in, because six of the seven were defects in the W1 code
> *itself*: this batch's own mechanisms failing the guarantees they were written to establish. Three were
> reproduced with executable counterexamples before any fix was written.
>
> | Id | Severity | What was wrong |
> |----|----------|----------------|
> | `PR83-01` | High | The compare-and-append guard checked only that the log's max EQUALLED the caller's belief, never that the incoming event was AHEAD of it. Sequence gaps are legitimate, so a stale terminal's number is both unique and lower: one appended behind durable work, `applyDerived` marked the run finished, and the outbox drain deleted its recovery entry on that false success. |
> | `PR83-02` | High | `JSON.stringify` deletes a property whose value is `undefined`, so a legitimately-`undefined` tool result replayed as the envelope's own metadata object. The in-memory journal held results BY REFERENCE, which is why no core test saw it. |
> | `PR83-03` | High | A caller cancellation landing before `openDeadline` was forwarded to the provider controller but never latched, so `race()` had nothing to observe and waited out the 120 s deadline against a provider that ignores its signal. |
> | `PR83-04` | Medium | A proven non-dispatch (missing host capability) left its row `prepared` forever — unresolved, resume-blocking, never swept. The existing test asserted that state directly under a comment saying the point was to avoid it. |
> | `PR83-05` | Medium | SQLite `settle` discarded the `changes` count, so a missing or already-terminal row reported durable success for an effect that may have landed. |
> | `PR83-06` | Medium | Exit 5 told users recovery happens "on the next `relavium` start"; only `run` and `gate` drain the outbox, so `status` could never resolve it. |
> | `PR83-07` | Low | `database-schema.md` said effect retention was unimplemented while this PR ships both sweeps, and drew the run→lease edge as exactly-one for a row that is created on acquire and deleted on release. |
>
> The **six code defects** are mutation-verified — each test was confirmed to FAIL with its fix reverted.
> `PR83-07` is a documentation correction with nothing executable to mutate; it was verified against the
> shipped `effect-retention.ts` and the lease row's actual lifecycle. Two additional
> coverage gaps surfaced that way and are now pinned: the fold-failure path's `contentCommitted` stamp, and
> the guard that omits the `mapped` projection when a node configured no `output_mapping`.
>
> **Carried forward, named rather than implied.** ADR-0077's required regression (a ledger write refused while
> a sibling's `#failure` already suppressed the abort) is unbuilt, and `#runAttempt`'s money-durability arm is
Expand Down Expand Up @@ -841,6 +880,13 @@ mark.** Wave 1's completion claim was wrong twice before this discipline was ado
caught it a third time: `CR-14` and `CR-92` were both implemented and both still carried an OPEN heading here
(*"needs an ADR"*, *"in the durability spine"*), which is precisely the failure the criterion exists to catch.

**And a fourth time, from the outside.** A comprehensive review of the assembled PR found six defects in the
code this register vouches for — the mechanisms of `CR-10`, `CR-12` and `CR-14` failing the guarantees they
were written to establish (see `PR83-01`…`PR83-06` in [Progress](#progress)). Every one is fixed and
mutation-verified, and the register rows below name the tests that now hold them. The lesson is the one the
criterion already encodes, sharpened: reading the code you wrote is necessary and not sufficient, because the
reader shares the author's assumptions. Three of the six were only settled by an executable counterexample.

| Item | ADR | The code that closes it | The test that would fail if it were reverted |
|------|-----|--------------------------|-----------------------------------------------|
| `CR-10` | — | `packages/core/src/engine/append-audit.ts` — a `RunStore` decorator recording asks, commits and outcomes per run | `append-audit.test.ts` + the certification against a real `history.db`. The property is **not** a log assertion: streamed events take sequence numbers and are never persisted, so a healthy run's log reads `[0,1,2,3,5,10,…]` and a lost event is byte-identical to a skipped one. The audit supplies the witness the log cannot. |
Expand Down
Loading