diff --git a/machine-docs/BACKLOG-settings.md b/machine-docs/BACKLOG-settings.md index c6937b6..e9d6294 100644 --- a/machine-docs/BACKLOG-settings.md +++ b/machine-docs/BACKLOG-settings.md @@ -15,10 +15,10 @@ - [x] **B6 (M1 claim)** — clean tree, push, claim M1 in STATUS-settings.md. ### M2 (after M1 PASS) -- [ ] **B7** — deploy to cc-ci (`/etc/cc-ci` git pull + nixos-rebuild if needed); confirm harness reads +- [x] **B7** — deploy to cc-ci (`/etc/cc-ci` git pull + nixos-rebuild if needed); confirm harness reads settings (absent → default false; or file present false). -- [ ] **B8** — live evidence (a): a recipe WITHOUT a canonical resolves base to newest release tag `< head` +- [x] **B8** — live evidence (a): a recipe WITHOUT a canonical resolves base to newest release tag `< head` (not raw main-tip). -- [ ] **B9** — live evidence (b): flip `SKIP_CANONICALS_FOR_UPGRADE = true` (scratch) → a canonical-bearing +- [x] **B9** — live evidence (b): flip `SKIP_CANONICALS_FOR_UPGRADE = true` (scratch) → a canonical-bearing recipe ALSO resolves to the release-tag base (canonical bypassed); then restore false. -- [ ] **B10 (M2 claim)** — claim M2; on fresh PASS of M1+M2 → `## DONE`. +- [x] **B10 (M2 claim)** — claim M2; on fresh PASS of M1+M2 → `## DONE`. diff --git a/machine-docs/JOURNAL-settings.md b/machine-docs/JOURNAL-settings.md index 429a46b..bf70556 100644 --- a/machine-docs/JOURNAL-settings.md +++ b/machine-docs/JOURNAL-settings.md @@ -82,3 +82,23 @@ M2 plan (after M1 PASS): - Deploy: ensure `/etc/cc-ci` is at the phase commit (git pull); settings.py is pure-python loaded at runtime from the checkout, so no nixos-rebuild needed for the harness to pick it up (the `cc-ci-run` wrapper execs python on the checkout's runner/). Confirm on server. + +## 2026-06-17 — M1 PASS + M2 verified live, claimed + +M1 Adversary cold-PASS (REVIEW-settings.md @17:00Z, no VETO). Advanced to M2. +Deployed phase commit to `/etc/cc-ci` via `git pull --ff-only` (HEAD 99d6bbc); no nixos-rebuild needed +(pure runner python read at runtime; the nightly sweep runs from /etc/cc-ci and Drone reads the same +absolute settings path). Added `scripts/show-upgrade-base.py` — a faithful, lightweight live probe that +calls the DEPLOYED `resolve_upgrade_base` against live settings + canonical registry + recipe tags, +avoiding a heavy per-recipe deploy/test/teardown while still proving the real resolution decision on the +server. Chose this over full `cc-ci-run runner/run_recipe_ci.py` runs (samever's approach) because my +change is purely in base RESOLUTION, not tier execution — the BasePlan is the whole claim. + +Evidence-(b) recipe choice: scanned all 16 canonical recipes; only `gitea` has canonical≠head +(3.5.3 vs 3.6.0), making it the cleanest bypass demo — flag false reads the canonical +("last-green (warm canonical, status=idle)"), flag true bypasses to the release-tag path +("no-canonical fallback: newest release tag older than head 3.6.0..."). The resolved version is 3.5.3 +both ways (the canonical happens to equal the newest predecessor tag), so the REASON string is the proof +of bypass — honest and matches the plan wording "ALSO resolve to that release-tag base (canonical +bypassed)". All other recipes are in steady state (canon==head) where step-back and the fallback share +the same helper and so coincide. Server restored to steady state (settings.toml absent → false). diff --git a/machine-docs/STATUS-settings.md b/machine-docs/STATUS-settings.md index 370be60..247a51d 100644 --- a/machine-docs/STATUS-settings.md +++ b/machine-docs/STATUS-settings.md @@ -3,10 +3,10 @@ **Phase:** server-level `settings.toml` + `SKIP_CANONICALS_FOR_UPGRADE` + release-tag-first no-canonical fallback. Plan: `/srv/cc-ci/cc-ci-plan/plan-phase-settings-ci-server-config.md`. -## Gate: M1 CLAIMED, awaiting Adversary +## Gate: M1 PASS (Adversary @2026-06-17T17:00Z, REVIEW-settings.md) · M2 CLAIMED (see below) -**Commit:** `cd19c1b` (feat: settings loader + flag + fallback + unit tests). Tree clean, pushed to -origin/main. +**M1 commit:** `cd19c1b` (feat: settings loader + flag + fallback + unit tests) — Adversary cold-PASS, +no VETO. **M2 deployed:** `99d6bbc` on `/etc/cc-ci`. Tree clean, pushed to origin/main. ### WHAT is claimed (M1 — implemented + unit-tested) 1. **Settings loader** `runner/harness/settings.py` — stdlib `tomllib`, one `[upgrade]` table with @@ -73,4 +73,64 @@ nix shell nixpkgs#python311Packages.pytest -c python3 -c "import sys; sys.path.i needing reformat — confirmed present at HEAD f68f1c5, NOT in this phase's diff. Not fixed here (narrow scope). My 5 phase files are ruff-clean + format-clean. -## M2 — NOT yet claimed (live server verification). Pending M1 PASS. +--- + +## Gate: M2 CLAIMED, awaiting Adversary @2026-06-17T17:25Z + +M1 is Adversary-PASS (REVIEW-settings.md verdict @17:00Z, fed2678/cd19c1b). M2 = verified live on cc-ci. + +**Deployed:** `/etc/cc-ci` at **99d6bbc** (pushed to origin/main; the deployed checkout the nightly +sweep runs from, and the absolute path the Drone recipe-CI runner reads). No nixos-rebuild needed — the +change is pure runner Python loaded at runtime from the checkout. Live settings file +`/etc/cc-ci/settings.toml` is **ABSENT** → default false (server steady state restored after the test). + +### WHAT is claimed (M2) +- The live server harness reads the settings file from the host path `/etc/cc-ci/settings.toml` + (absent → default false), confirmed by the flag value flipping with the file's presence. +- **(a)** A recipe **without** a canonical (`keycloak`, no `canonical.json`) resolves its upgrade base + to the **newest release tag `< head`** (`10.7.1+26.6.2`), NOT the raw main-tip. +- **(b)** With `SKIP_CANONICALS_FOR_UPGRADE = true` (scratch file), a **canonical-bearing** recipe + (`gitea`, canonical `3.5.3+1.24.2-rootless`) resolves to the **release-tag base** (canonical + BYPASSED) — proven by the reason changing from `last-green (warm canonical, status=idle)` to + `no-canonical fallback: newest release tag older than head 3.6.0+1.24.2-rootless`. Scratch file then + removed → restored to false (reason back to `last-green (warm canonical)`). +- Default false ⇒ this server's canonical-bearing path is unchanged (gitea false → `last-green` base). + +### HOW to verify (cold, on the server, from /etc/cc-ci or your own clone) +The probe runs the EXACT deployed `resolve_upgrade_base` against live settings + live canonical registry +(`/var/lib/ci-warm//canonical.json`) + live recipe tags (`~/.abra/recipes/`). Faithful, no +deploy/teardown. + +``` +ssh cc-ci +cd /etc/cc-ci && git rev-parse --short HEAD # 99d6bbc (or later) +ls /etc/cc-ci/settings.toml # ABSENT -> default false + +# CASE 1 — flag false (default, no file): (a) keycloak, plus gitea unchanged +HOME=/root cc-ci-run scripts/show-upgrade-base.py keycloak gitea + +# CASE 2 — flag true (scratch), then RESTORE +printf '[upgrade]\nskip_canonicals_for_upgrade = true\n' > /etc/cc-ci/settings.toml +HOME=/root cc-ci-run scripts/show-upgrade-base.py gitea keycloak +rm -f /etc/cc-ci/settings.toml # restore default false +HOME=/root cc-ci-run scripts/show-upgrade-base.py gitea +``` + +### EXPECTED (verbatim BasePlan lines observed @17:20–17:25Z) +- CASE 1 (false): + - `keycloak` → `BasePlan(kind='version', version='10.7.1+26.6.2', ref='', reason='no-canonical fallback: newest release tag older than head 10.8.0+26.6.3')` (canonical=None; newest_release_tag