diff --git a/README.md b/README.md index 96572ce8d..58e07eace 100644 --- a/README.md +++ b/README.md @@ -614,6 +614,11 @@ docker run ghcr.io/terraphim/terraphim-server:latest #### Direct Download Download pre-built binaries from [GitHub Releases](https://github.com/terraphim/terraphim-ai/releases). +> **Note for fleet-internal agents:** GitHub Releases and crates.io are **not** the fleet-canonical +> channel for `terraphim_grep` and `terraphim_agent` — they track behind the private Gitea cargo +> registry. See [Release Channels](docs/src/release-channels.md) before reporting a version mismatch +> as a release failure. + ### Development Setup For development, see our comprehensive [Development Setup Guide](docs/src/development-setup.md) which covers: diff --git a/docs/plans/design-rg-release-channels-doc-2026-08-08.md b/docs/plans/design-rg-release-channels-doc-2026-08-08.md new file mode 100644 index 000000000..98f57c81b --- /dev/null +++ b/docs/plans/design-rg-release-channels-doc-2026-08-08.md @@ -0,0 +1,61 @@ +# Design Gate — #3184 fleet-internal release bless = Gitea private cargo + +## Problem +Agents treat crates.io / GitHub Releases as canonical for `terraphim_grep` and `terraphim_agent`. +Guardian blesses **1.21.1** on the Gitea private cargo registry while crates.io sits at 1.20.5 and the +GitHub release tag at v1.20.5 — so agents report false release failures. Nothing in-repo encodes the +channel precedence. Docs-only slice of ops issue #3183. + +## Decision (exact touchpoints) +1. NEW `docs/src/release-channels.md` — policy doc. Placed under the mdBook `src` root (verified + `docs/book.toml` → `src = "src"`) so it renders and sits beside existing `docs/src/release-process.md`. + The issue's `docs/release-channels.md` would be outside the book; this satisfies the same AC. +2. EDIT `docs/src/SUMMARY.md` — add `- [Release Channels](./release-channels.md)` near the + `Contributing`/`Branch Protection` block. +3. EDIT `README.md` `## Installation Methods` (~line 591), under `#### Direct Download` — note that + GitHub Releases are **not** the fleet-canonical channel; link to the new doc. + +## Ground truth (verified 2026-08-08, live) +- `GET {GITEA_URL}/api/v1/packages/terraphim/cargo/{name}` → HTTP 200, returns a **JSON array**, one + object per version. Fields per object: `id`, `owner.login`, `repository` (null), `creator`, + `type: "cargo"`, `name`, `version`, `html_url`, `created_at`. **There is no `latest` field** — the + doc must say "max version in the array", not "read `.latest`". List form: + `GET /api/v1/packages/terraphim?type=cargo`. +- Blessed: `terraphim_grep` 1.21.1 (3 versions), `terraphim_agent` 1.21.1 (3 versions). Package names + use underscores. +- Lag confirmed: crates.io 1.20.5 both crates; GitHub release v1.20.5; Gitea tag v1.21.0. +- Guardian verdict `CONDITIONAL_PASS`; lag = WARN checks `R6`/`R6cargo`/`R6cargo-rel`; `R6canon` PASS + = fleet bless 1.21.1. Smokes `R7:*` PASS, `path=terraphim-clients`, temp-root. +- Guardian lives at `/home/alex/projects/cto-executive-system/release-guardian/` (**not** `private/…` + as the issue states) — external to this repo: reference by name, never a relative link. + +## Acceptance criteria +- AC1 Doc states: canonical = Gitea cargo registry, owner `terraphim`; blessed 1.21.1 for grep+agent; + crates.io/GitHub lag is **CONDITIONAL, not failure** for fleet-internal; install smoke is temp-root + only with path install from `terraphim-clients` when the private sparse index is unavailable. +- AC2 README `Installation Methods` links to it. +- AC3 Doc names `release-guardian` for continuous checks and cites evidence + `reports/2026-08-08-terraphim-ai-clients.md` and `adf-ledger.jsonl` (as paths, not links). +- AC4 PR to `main`; structural-pr-review 5/5, zero P1/P2. + +## Non-goals +- Publishing to crates.io / GitHub Releases (ops #3183). No version bumps, no Cargo/CI changes. +- No automated registry checking in this repo (guardian owns it); no edits under + `cto-executive-system/`; no re-running smokes. + +## Test plan +- Unit: none — zero code changes; asserted by `git diff --stat` touching only `.md`. +- Links resolve (`ls` each target); `mdbook build docs` emits `release-channels.html`. +- Live (re-run and paste in PR): `curl -s -H "Authorization: token $GITEA_TOKEN" \ + "$GITEA_URL/api/v1/packages/terraphim/cargo/terraphim_grep" | jq -r '.[].version'` → includes 1.21.1. +- No wiremock: no in-repo code path consumes this API, so there is nothing to stub. + +## Gates +```bash +cargo fmt --all -- --check +cargo clippy --workspace --all-targets -- -D warnings # no-op, docs-only +cargo test --workspace # unchanged +mdbook build docs # book.toml is at docs/book.toml +``` +Pre-commit hooks must pass: conventional commit `docs(release): … Refs #3184`; secret scan — never +paste a `GITEA_TOKEN` value into the doc, use `$GITEA_TOKEN` placeholders only. diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index f5dd32425..590559e31 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -3,6 +3,7 @@ - [Introduction](./Introduction.md) - [Contributing](./CONTRIBUTE.md) - [Branch Protection and Security](./branch-protection.md) +- [Release Channels](./release-channels.md) - [Architecture](./Architecture.md) - [Claude Desktop Integration](./ClaudeDesktop.md) - [Design Decisions](./DesignDecisions.md) diff --git a/docs/src/release-channels.md b/docs/src/release-channels.md new file mode 100644 index 000000000..4da5cf036 --- /dev/null +++ b/docs/src/release-channels.md @@ -0,0 +1,95 @@ +# Release Channels + +This document defines which release channel is **canonical** for fleet-internal agents consuming +`terraphim_grep` and `terraphim_agent`, and how to interpret a version mismatch between channels. + +Read this before reporting a "release failure". A crates.io or GitHub Releases version that trails +the private registry is expected and is **not** a failure for fleet-internal work. + +## Channel precedence + +| Rank | Channel | Role | Authority | +|------|---------|------|-----------| +| 1 | Gitea private cargo registry (owner `terraphim`) | **Canonical for the fleet** | Blessed version — agents install from here | +| 2 | crates.io | Public mirror | Lags the canonical channel; informational | +| 3 | GitHub Releases (`terraphim/terraphim-ai` tags) | Public binary distribution | Lags the canonical channel; informational | + +The canonical channel is the **Gitea private cargo registry**, owner `terraphim`, hosted at +`$GITEA_URL`. Public channels are downstream publication targets, not the source of truth for what +the fleet is expected to run. + +## Currently blessed versions + +As verified on 2026-08-08: + +| Crate | Gitea (canonical) | crates.io | GitHub release tag | +|-------|-------------------|-----------|--------------------| +| `terraphim_grep` | **1.21.1** | 1.20.5 | v1.20.5 | +| `terraphim_agent` | **1.21.1** | 1.20.5 | v1.20.5 | + +The Gitea git tag is `v1.21.0`; the blessed **package** version is 1.21.1. Package names in the +registry use underscores (`terraphim_grep`, `terraphim_agent`), not hyphens. + +## Querying the canonical channel + +Per-package (returns a **JSON array**, one object per published version): + +```bash +curl -s -H "Authorization: token $GITEA_TOKEN" \ + "$GITEA_URL/api/v1/packages/terraphim/cargo/terraphim_grep" | jq -r '.[].version' +``` + +List all cargo packages for the owner: + +```bash +curl -s -H "Authorization: token $GITEA_TOKEN" \ + "$GITEA_URL/api/v1/packages/terraphim?type=cargo" +``` + +Each array element carries `id`, `owner.login`, `repository` (null), `creator`, `type` (`"cargo"`), +`name`, `version`, `html_url`, `created_at`. + +> **There is no `latest` field on this API.** The blessed version is the **maximum version present +> in the array** — compute it by semver ordering. Any agent or script that reads `.latest` is +> reading a field that does not exist and will produce a false negative. + +Never paste a token value into documentation, commit messages, or issue comments. Use the +`$GITEA_TOKEN` and `$GITEA_URL` environment variables (loaded via `source ~/.profile`). + +## Interpreting channel lag + +Public-channel lag is **CONDITIONAL, not a failure**, for fleet-internal purposes: + +- Gitea canonical version present and installable → fleet release is **good**. +- crates.io / GitHub Releases behind the canonical version → **warning only**. It is a publication + backlog item, tracked separately as ops work; it does not block fleet-internal consumers. +- Report a release failure only when the **canonical** channel is missing the expected version or + the package cannot be installed from it. + +Continuous verification of these channels is owned by `release-guardian`, which lives outside this +repository in the `cto-executive-system` project. Do not add automated registry checking here. + +Evidence for the 2026-08-08 assessment (paths within the `release-guardian` project, not links): + +- `reports/2026-08-08-terraphim-ai-clients.md` +- `adf-ledger.jsonl` + +The recorded verdict was `CONDITIONAL_PASS`: checks `R6`, `R6cargo` and `R6cargo-rel` were WARN +(public-channel lag), while `R6canon` PASSed — i.e. the fleet bless of 1.21.1 stands. Install smokes +`R7:*` PASSed. + +## Install smoke testing + +When the private sparse index is not reachable from the environment under test, the supported smoke +is a **path install from the `terraphim-clients` checkout, into a temporary root**: + +- Install path: `path=terraphim-clients` (local path install, not registry install). +- Destination: a **temp root only** — never the developer's or agent's real `~/.cargo/bin`. + +This keeps the smoke hermetic and prevents a smoke run from silently changing which binary the host +resolves. Do not substitute a crates.io install to "work around" an unreachable private index; that +tests a different, lagging artifact. + +## See also + +- [Release Process](./release-process.md) — how releases are built and published.