From 55aa3cc01ab79897df37b40b9829fc37e49d1b0c Mon Sep 17 00:00:00 2001 From: Cemil ILIK Date: Wed, 24 Jun 2026 22:17:58 +0300 Subject: [PATCH 1/2] fix(cli,ci): correct relavium --version + the release-smoke tarball install path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two defects in the 2.L packaging (ADR-0051), each of which would block or spoil the first publish; both surfaced after the tag-triggered Release CLI run. 1. `relavium --version` reported the hardcoded `0.0.0` sentinel, never the package version — it was never wired to package.json (the program.ts comment deferred it to "packaging (2.L)"). tsup now injects the manifest version at build time via a `__RELAVIUM_CLI_VERSION__` esbuild `define`; program.ts reads it behind a `typeof` guard and falls back to `0.0.0-dev` on a source run (tsx/vitest, no define). Bundled `relavium --version` → `0.1.0`; source → `0.0.0-dev`. 2. The cross-OS install-smoke failed on ubuntu/macOS/Windows: `npm install -g artifact/relavium-X.tgz` — a slash-bearing arg without `./` — is read by npm as a GitHub `owner/repo` shorthand and git-cloned (`Permission denied (publickey)`), never as the local tarball. Prefix with `./` so npm classifies it as a file spec (verified via npm-package-arg: bare → git, `./` → file). The publish job is gated on green smoke, so nothing was published. Also assert `relavium --version == package.json` in the smoke matrix so a version-wiring regression is caught before publish — the old smoke only ran `--help`, which is why #1 slipped. Refs: ADR-0051 Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/release.yml | 9 ++++++++- apps/cli/src/program.ts | 10 ++++++++-- apps/cli/tsup.config.ts | 12 +++++++++++- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dd7ee4ca..47114ceb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -102,9 +102,16 @@ jobs: shell: bash run: | set -euo pipefail - TGZ=$(ls artifact/*.tgz) + # The `./` prefix is load-bearing: npm reads a slash-bearing arg without it + # (`artifact/relavium-X.tgz`) as a GitHub `owner/repo` shorthand and tries to git-clone it. + # `./artifact/…` forces the local-file spec. (Verified via npm-package-arg.) + TGZ="./$(ls artifact/*.tgz)" npm install -g "$TGZ" echo "## relavium --help" && relavium --help >/dev/null + echo "## relavium --version matches the published package version" + VER="$(relavium --version)" + PKG="$(node -p "require('./apps/cli/package.json').version")" + test "$VER" = "$PKG" || { echo "relavium --version=$VER != package.json $PKG"; exit 1; } echo "## relavium provider list" && relavium provider list echo "## relavium run (sequential) --json (exit 0)" relavium run apps/cli/src/harness/fixtures/sequential.relavium.yaml --input n=21 --json diff --git a/apps/cli/src/program.ts b/apps/cli/src/program.ts index 0b401aae..9a317e57 100644 --- a/apps/cli/src/program.ts +++ b/apps/cli/src/program.ts @@ -10,8 +10,14 @@ export interface BuildProgramOptions { readonly context?: CommandContext; } -/** CLI version — a constant for now; wired to `package.json` during packaging (workstream 2.L). */ -export const CLI_VERSION = '0.0.0'; +/** + * CLI version. `tsup` replaces `__RELAVIUM_CLI_VERSION__` with the `package.json` version at build time + * (see tsup.config.ts `define`); a source run (tsx/vitest — no define) falls back to a dev sentinel, since an + * unbundled process has no published version. `typeof` keeps the source path from a ReferenceError. (2.L, ADR-0051.) + */ +declare const __RELAVIUM_CLI_VERSION__: string | undefined; +export const CLI_VERSION = + typeof __RELAVIUM_CLI_VERSION__ === 'string' ? __RELAVIUM_CLI_VERSION__ : '0.0.0-dev'; /** * The position-independent global flags are owned by `extractGlobalOptions` (options.ts), not diff --git a/apps/cli/tsup.config.ts b/apps/cli/tsup.config.ts index 0b4b7d15..2f5dd21f 100644 --- a/apps/cli/tsup.config.ts +++ b/apps/cli/tsup.config.ts @@ -1,7 +1,13 @@ -import { cpSync, rmSync } from 'node:fs'; +import { cpSync, readFileSync, rmSync } from 'node:fs'; import { defineConfig } from 'tsup'; +// Stamp the published version into the bundle at build time (see `define` below + program.ts). Read from +// THIS package's manifest (resolved beside the config, not via cwd) so it is correct from any build entry point. +const { version } = JSON.parse( + readFileSync(new URL('./package.json', import.meta.url), 'utf8'), +) as { version: string }; + /** * The CLI distribution bundle (2.L, [ADR-0051](../../docs/decisions/0051-cli-distribution-thin-bundle-private-engine.md)). * @@ -44,6 +50,10 @@ export default defineConfig({ dts: false, noExternal: [/^@relavium\//], external: THIRD_PARTY_EXTERNAL, + // Replace the `__RELAVIUM_CLI_VERSION__` token (program.ts) with the literal package version, so the + // bundled `relavium --version` reports the real version with no runtime file read. Source runs (tsx/vitest) + // have no define and fall back to a dev sentinel. + define: { __RELAVIUM_CLI_VERSION__: JSON.stringify(version) }, banner: { js: '#!/usr/bin/env node' }, // The inlined `@relavium/db` resolves its drizzle migrations via `new URL('../drizzle', import.meta.url)`, // which — once bundled — points beside THIS bundle, not the db package. So ship the migration set alongside From 424b3634d8c653f292d4fd52b3b4a6ae1b96cda3 Mon Sep 17 00:00:00 2001 From: Cemil ILIK Date: Wed, 24 Jun 2026 22:18:00 +0300 Subject: [PATCH 2/2] =?UTF-8?q?docs(roadmap):=20mark=202.L=20Done=20(PR=20?= =?UTF-8?q?#49)=20across=20the=20status=20surfaces=20=E2=80=94=20next=20pi?= =?UTF-8?q?ckup=202.S?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2.L (CLI packaging, distribution & install verification) merged via PR #49, closing the last Phase-3 go/no-go exit criterion (#7) — so the Phase-2 spine is complete and all seven criteria now hold. Move 2.L from "next pickup" into the Landed/Done list and re-point the next pickup to 2.S (media host-wiring, the first additive lane — off the M3 critical path and the go/no-go). Audited every status surface; updated only the live trackers and left the static plan views (Mermaid DAGs, wave/dependency tables, exit-criteria definitions) unchanged per their own "the plan, not a live tracker" framing. - current.md: 2.L Done entry + next pickup 2.S; re-tense the NPM_TOKEN maintainer obligation ("once 2.L lands" → "now that 2.L has landed (PR #49)"). - phase-2-cli.md: §2.L heading ✅ Done badge; header status line; Remaining-build-order banner; drop the 2.L row from the pickup queue and renumber 2.S/2.R/chat/2.J to 1–4; re-tense the gate-closing-backbone, 2.K-closed, and 2.S-timing bullets. - CLAUDE.md, README.md: append the 2.L packaging deliverable to the landed Phase-2 list; next pickup 2.S; all seven Phase-3 exit criteria now hold. - runbooks/release-a-surface.md: Status "draft" → "partial — CLI (npm) flow complete (2.L)". ADR-0051's "(today a stub)" aside about the runbook is left unedited: ADRs are append-only (CLAUDE.md rule 9) and it is a harmless point-in-time authoring note. Co-Authored-By: Claude Opus 4.8 (1M context) --- CLAUDE.md | 6 ++++-- README.md | 6 ++++-- docs/roadmap/current.md | 17 +++++++++------ docs/roadmap/phases/phase-2-cli.md | 33 +++++++++++++++--------------- docs/runbooks/release-a-surface.md | 2 +- 5 files changed, 36 insertions(+), 28 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 1ef017cd..efa4608f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -54,8 +54,10 @@ commands with OS-keychain storage landed (2.C — PR #45, behind ADR-0019 + ADR- 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). The next pickup is 2.L (packaging & install verification — the last -gate-closing spine PR). For live status, per-PR history, +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**. The next pickup is 2.S (media host-wiring — the first additive +lane, off the M3 critical path and the Phase-3 go/no-go). 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. diff --git a/README.md b/README.md index 30707120..facd4bf6 100644 --- a/README.md +++ b/README.md @@ -95,8 +95,10 @@ multi-provider failover, cost governance, and multimodal media I/O. **Phase 2 (t underway** — 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, and the read commands (`list` / `logs` / `status` / `gate list`) -over durable history have landed (milestone **M3** reached). For live status and the full roadmap, see +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). For live status and the full roadmap, see [docs/roadmap/current.md](docs/roadmap/current.md) and the [roadmap](docs/roadmap/README.md). diff --git a/docs/roadmap/current.md b/docs/roadmap/current.md index 446c0f1c..6be3e9f5 100644 --- a/docs/roadmap/current.md +++ b/docs/roadmap/current.md @@ -28,8 +28,8 @@ and the [reference specs](../reference/). > **Live maintainer obligations:** (1) mark the CI `ci` job a **required check** in GitHub branch > protection (carried from Phase 0; optionally add `TURBO_TOKEN`/`TURBO_TEAM` secrets for the -> cross-runner remote cache); (2) once **2.L** lands, add the **`NPM_TOKEN`** repo secret + npm 2FA so the -> tag-triggered `Release CLI` workflow can publish (the actual `npm publish` is maintainer-gated, +> cross-runner remote cache); (2) now that **2.L** has landed (PR #49), add the **`NPM_TOKEN`** repo secret + npm 2FA +> so the tag-triggered `Release CLI` workflow can publish (the actual `npm publish` is maintainer-gated, > [ADR-0051](../decisions/0051-cli-distribution-thin-bundle-private-engine.md) / > [release-a-surface.md](../runbooks/release-a-surface.md)). @@ -64,10 +64,15 @@ idempotent, secret-input fail-closed), ✅ Done (PR #47, 2026-06-24) behind no new ADR) — **fully closing 2.K's deferred gate-resume half**; and **2.I** (the read commands `list` / `logs` / `status` / `gate list` over durable history — go/no-go #2, the read side; surfaces the pending `gateId`s the 2.G `gate` command points at), ✅ Done (PR #48, 2026-06-24) -(no new ADR — an additive workflow-agnostic `@relavium/db` read seam + a `@relavium/core` `parseAgent`). -**Next pickup:** **2.L** (packaging, distribution & install verification — go/no-go #7, the last gate-closing -spine PR; once it lands all seven Phase-3 exit criteria hold); the full status-aware -order is the +(no new ADR — an additive workflow-agnostic `@relavium/db` read seam + a `@relavium/core` `parseAgent`); +and **2.L** (packaging, distribution & install verification — go/no-go #7, the last gate-closing spine PR: the +`tsup` engine-inlined ESM bundle, the bundle-closure drift guard, and the tag-triggered cross-OS install-smoke +`Release CLI` workflow), ✅ Done (PR #49, 2026-06-24) behind +[ADR-0051](../decisions/0051-cli-distribution-thin-bundle-private-engine.md) — **closing go/no-go #7, so the +Phase-2 spine is complete and all seven Phase-3 exit criteria now hold (Phase 3 may start)**. +**Next pickup:** **2.S** (media host-wiring — the largest additive lane, carrying the lone `EgressCapability.fetch` +SSRF security review; off the M3 critical path and the Phase-3 go/no-go, so it completes in-phase without blocking +Phase 3); the full status-aware order is the [Remaining build order](phases/phase-2-cli.md#remaining-build-order) queue. The CLI also lands the inbound MCP client (2.R, [ADR-0034](../decisions/0034-mcp-client-sdk-dependency.md)) off the M3 critical path. See the [Phase 2 workstreams](phases/phase-2-cli.md) and the diff --git a/docs/roadmap/phases/phase-2-cli.md b/docs/roadmap/phases/phase-2-cli.md index f4e4d065..a960c279 100644 --- a/docs/roadmap/phases/phase-2-cli.md +++ b/docs/roadmap/phases/phase-2-cli.md @@ -1,6 +1,6 @@ # Phase 2 — CLI -> Status: In progress (Product Phase 1, build phase 2). **2.A** (CLI skeleton + process contract) and **2.B** (config resolution) are ✅ **Done (PR #40, 2026-06-22)**, behind [ADR-0047](../../decisions/0047-cli-framework-commander-ink-clack.md) + [ADR-0048](../../decisions/0048-toml-config-parser.md); **2.D** (`run` → engine, the M3 keystone) is ✅ **Done (PR #41, 2026-06-22)**, and **2.F** (the `--json` CI machine-output contract) is ✅ **Done (PR #42, 2026-06-22)**, behind [ADR-0049](../../decisions/0049-cli-machine-output-contract.md), and **2.K** (the engine regression harness) is ✅ **Done (PR #43, 2026-06-23)** — so **global milestone M3 is reached**; **2.H** (durable run history) is ✅ **Done (PR #44, 2026-06-23)**, behind [ADR-0050](../../decisions/0050-cli-history-db-at-rest-posture.md); and **2.C** (provider/key commands — OS keychain via `@napi-rs/keyring`) is ✅ **Done (PR #45, 2026-06-23)**, behind [ADR-0019](../../decisions/0019-cli-node-keychain-library.md) + [ADR-0006](../../decisions/0006-os-keychain-for-api-keys.md); and **2.E** (the `ink` streaming TUI) is ✅ **Done (PR #46, 2026-06-24)**, behind [ADR-0047](../../decisions/0047-cli-framework-commander-ink-clack.md); and **2.G** (the interactive human-gate prompt + `relavium gate` cross-process resume) is ✅ **Done (PR #47, 2026-06-24)**, behind [ADR-0047](../../decisions/0047-cli-framework-commander-ink-clack.md) (`@clack/prompts`; no new ADR) — **fully closing 2.K's deferred gate-resume half**; and **2.I** (the read commands `list` / `logs` / `status` / `gate list` over durable history) is ✅ **Done (PR #48, 2026-06-24)** (no new ADR — additive `@relavium/db` read seam + `@relavium/core` `parseAgent`). The status-aware order for everything still open (next pickup: **2.L**) is the [Remaining build order](#remaining-build-order) queue. +> Status: In progress (Product Phase 1, build phase 2). **2.A** (CLI skeleton + process contract) and **2.B** (config resolution) are ✅ **Done (PR #40, 2026-06-22)**, behind [ADR-0047](../../decisions/0047-cli-framework-commander-ink-clack.md) + [ADR-0048](../../decisions/0048-toml-config-parser.md); **2.D** (`run` → engine, the M3 keystone) is ✅ **Done (PR #41, 2026-06-22)**, and **2.F** (the `--json` CI machine-output contract) is ✅ **Done (PR #42, 2026-06-22)**, behind [ADR-0049](../../decisions/0049-cli-machine-output-contract.md), and **2.K** (the engine regression harness) is ✅ **Done (PR #43, 2026-06-23)** — so **global milestone M3 is reached**; **2.H** (durable run history) is ✅ **Done (PR #44, 2026-06-23)**, behind [ADR-0050](../../decisions/0050-cli-history-db-at-rest-posture.md); and **2.C** (provider/key commands — OS keychain via `@napi-rs/keyring`) is ✅ **Done (PR #45, 2026-06-23)**, behind [ADR-0019](../../decisions/0019-cli-node-keychain-library.md) + [ADR-0006](../../decisions/0006-os-keychain-for-api-keys.md); and **2.E** (the `ink` streaming TUI) is ✅ **Done (PR #46, 2026-06-24)**, behind [ADR-0047](../../decisions/0047-cli-framework-commander-ink-clack.md); and **2.G** (the interactive human-gate prompt + `relavium gate` cross-process resume) is ✅ **Done (PR #47, 2026-06-24)**, behind [ADR-0047](../../decisions/0047-cli-framework-commander-ink-clack.md) (`@clack/prompts`; no new ADR) — **fully closing 2.K's deferred gate-resume half**; and **2.I** (the read commands `list` / `logs` / `status` / `gate list` over durable history) is ✅ **Done (PR #48, 2026-06-24)** (no new ADR — additive `@relavium/db` read seam + `@relavium/core` `parseAgent`); and **2.L** (packaging, distribution & install verification) is ✅ **Done (PR #49, 2026-06-24)**, behind [ADR-0051](../../decisions/0051-cli-distribution-thin-bundle-private-engine.md) — **closing go/no-go #7, so the Phase-2 spine is complete and all seven Phase-3 exit criteria now hold**. The status-aware order for everything still open (next pickup: **2.S**) is the [Remaining build order](#remaining-build-order) queue. - **Related**: [../README.md](../README.md), [phase-1-engine-and-llm.md](phase-1-engine-and-llm.md), [phase-3-desktop.md](phase-3-desktop.md), [../../reference/cli/commands.md](../../reference/cli/commands.md), [../../reference/contracts/config-spec.md](../../reference/contracts/config-spec.md), [../../reference/desktop/keychain-and-secrets.md](../../reference/desktop/keychain-and-secrets.md), [../../reference/contracts/sse-event-schema.md](../../reference/contracts/sse-event-schema.md), [../../reference/desktop/database-schema.md](../../reference/desktop/database-schema.md), [../../architecture/execution-model.md](../../architecture/execution-model.md), [../../architecture/shared-core-engine.md](../../architecture/shared-core-engine.md) @@ -451,7 +451,7 @@ its fixture + scenario format is documented in `conformance/replay.ts`) through the injectable `ProviderResolver`, and the reserved `live-api` (`on: schedule`) job in `.github/workflows/ci.yml` is the nightly variant that re-records + diffs them. -### 2.L — Packaging, distribution, and install verification +### 2.L — Packaging, distribution, and install verification — ✅ **Done (PR #49)** Make the CLI installable and verify the published artifact behaves like local dev. Behind [ADR-0051](../../decisions/0051-cli-distribution-thin-bundle-private-engine.md) (the bundle boundary — @@ -664,26 +664,25 @@ This is the status × plan view; the dependency rationale for every row lives in [Ordered waves](#ordered-waves-each-wave-is-internally-parallel-waves-gate-left-to-right) — this table does not restate them, it only sequences what remains. -> **Status (2026-06-24):** ✅ **2.A · 2.B · 2.D · 2.F · 2.K · 2.H · 2.C · 2.E · 2.G · 2.I** done — **M3 reached** · next pickup: **2.L**. -> (2.I shipped the read side — `list`/`logs`/`status`/`gate list` over durable history (PR #48) — so go/no-go #2 -> now holds. The remaining gate-closing PR is **2.L** (package & publish); the four additive lanes (2.S, 2.R, -> chat, 2.J) complete in-phase but don't block Phase 3.) +> **Status (2026-06-24):** ✅ **2.A · 2.B · 2.D · 2.F · 2.K · 2.H · 2.C · 2.E · 2.G · 2.I · 2.L** done — **M3 reached, Phase-2 spine complete, all 7 Phase-3 go/no-go exit criteria hold (Phase 3 may start)** · next pickup: **2.S**. +> (2.L shipped the published, install-verified binary (PR #49) — so go/no-go #7 now holds and **every Phase-2 +> spine/gate PR is done**; the four additive lanes (2.S, 2.R, chat, 2.J) complete in-phase but don't block Phase 3.) | Next | Lane | Why now | Blockers (all met on arrival) | |---|---|---|---| -| **1. 2.L** package & publish | ◆ spine | go/no-go #7 — **all 7 [exit criteria](#exit-criteria-go--no-go) hold here → Phase 3 may start** | 2.K whole ✓ (via 2.G) | -| **2. 2.S** media host-wiring | additive | biggest lane + the lone SSRF security review; **first** among the additive lanes — never tailed | 2.D · 2.H ✓ | -| **3. 2.R** MCP client | additive | inbound MCP tools | 2.B ✓ · 2.C ✓ | -| **4. 2.M → 2.N–2.Q** chat | additive | agent-first chat surface | 2.C ✓ · 2.H ✓ · 2.E ✓ | -| **5. 2.J** create / import / export | additive | cheap filler — drop into any low-energy slot | 2.A ✓ | - -- **Gate-closing backbone — `2.L` (last spine PR):** 2.I closed go/no-go #2, so **2.L** (the published binary) - is the only remaining exit-criteria PR (2.K + 2.H + 2.C + 2.E + 2.G + 2.I are done). The remaining four - (**2.S, 2.R, chat, 2.J**) complete in-phase but do **not** block starting Phase 3. +| **1. 2.S** media host-wiring | additive | biggest lane + the lone SSRF security review; **first** among the additive lanes — never tailed | 2.D · 2.H ✓ | +| **2. 2.R** MCP client | additive | inbound MCP tools | 2.B ✓ · 2.C ✓ | +| **3. 2.M → 2.N–2.Q** chat | additive | agent-first chat surface | 2.C ✓ · 2.H ✓ · 2.E ✓ | +| **4. 2.J** create / import / export | additive | cheap filler — drop into any low-energy slot | 2.A ✓ | + +- **Gate-closing backbone — complete (`2.L` landed, PR #49):** with the published, install-verified binary + shipped, every exit-criteria/spine PR is done (2.K + 2.H + 2.C + 2.E + 2.G + 2.I + 2.L), so **all seven + Phase-3 go/no-go criteria hold and Phase 3 may start**. The remaining four (**2.S, 2.R, chat, 2.J**) complete + in-phase but do **not** block starting Phase 3. - **2.K is fully closed (via 2.G).** Its deferred gate-resume scenario was exercised once the - gate pause/resume surface shipped, so 2.L (step 2) is now unblocked on the 2.K front. + gate pause/resume surface shipped, which unblocked **2.L** — now landed (PR #49). - **The one judgement call — 2.S timing.** Front-load it as the *first* additive lane - (step 3); never tail it behind chat / MCP / filler. It is the long pole, carries the only + (now the next pickup); never tail it behind chat / MCP / filler. It is the long pole, carries the only dedicated security review (the `EgressCapability.fetch` SSRF mechanism), and its injectable ports are inherited by desktop ([§3.B](phase-3-desktop.md)) + VS Code ([§4.N](phase-4-vscode.md)). Pull it even earlier (right after 2.H) if de-risking that security review outweighs reaching diff --git a/docs/runbooks/release-a-surface.md b/docs/runbooks/release-a-surface.md index 5f2202c6..0a402263 100644 --- a/docs/runbooks/release-a-surface.md +++ b/docs/runbooks/release-a-surface.md @@ -1,6 +1,6 @@ # Release a Surface -> Status: draft — to be expanded +> Status: partial — the CLI (npm) release flow is complete (2.L, ADR-0051); the desktop (`.dmg`) and VS Code (`.vsix`) sections are still to be expanded This runbook will describe how to cut a release for each Phase-1 Relavium surface. The three surfaces ship through three different channels, but they all build on the same