From aa1f89782041a94956554831a79c2c7f69fe4379 Mon Sep 17 00:00:00 2001 From: autonomic-bot Date: Wed, 17 Jun 2026 09:44:22 +0000 Subject: [PATCH] =?UTF-8?q?plan:=20queue=20settings=20=E2=80=94=20minimal?= =?UTF-8?q?=20CI-server=20settings.toml=20+=20SKIP=5FCANONICALS=5FFOR=5FUP?= =?UTF-8?q?GRADE=20(sonnet,=20after=20dash)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Operator 2026-06-17. Introduce a minimal, extensible server-level settings.toml for the cc-ci server; first value SKIP_CANONICALS_FOR_UPGRADE (bool, default false, false on this server). When true, resolve_upgrade_base bypasses the canonical and uses the main-tip predecessor — codifying that canonicals are an optional optimization for the upgrade base. Scoped to the upgrade base only (promote/--quick separate). Runs after canon/dash (builds on the final resolver). --- cc-ci-plan/agents.toml | 2 + .../plan-phase-settings-ci-server-config.md | 87 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 cc-ci-plan/plan-phase-settings-ci-server-config.md diff --git a/cc-ci-plan/agents.toml b/cc-ci-plan/agents.toml index 039944a..a0e375a 100644 --- a/cc-ci-plan/agents.toml +++ b/cc-ci-plan/agents.toml @@ -164,4 +164,6 @@ phases = [ { id = "canon", plan = "plan-phase-canon-canonical-sweep.md", status = "STATUS-canon.md", models = { builder = "claude-opus-4-8", adversary = "claude-opus-4-8" } }, # fix incomplete per-recipe run history on the CI dashboard (capped at latest 100 Drone builds; 362 runs exist) — source from local /var/lib/cc-ci-runs (opus) — see plan-phase-dash-*.md (operator 2026-06-17) { id = "dash", plan = "plan-phase-dash-recipe-history.md", status = "STATUS-dash.md", models = { builder = "claude-opus-4-8", adversary = "claude-opus-4-8" } }, + # minimal CI-server settings.toml + SKIP_CANONICALS_FOR_UPGRADE (default false; canonicals are optional for the upgrade base) — see plan-phase-settings-*.md (operator 2026-06-17) + { id = "settings", plan = "plan-phase-settings-ci-server-config.md", status = "STATUS-settings.md", models = { builder = "claude-sonnet-4-6", adversary = "claude-sonnet-4-6" } }, ] diff --git a/cc-ci-plan/plan-phase-settings-ci-server-config.md b/cc-ci-plan/plan-phase-settings-ci-server-config.md new file mode 100644 index 0000000..e16700d --- /dev/null +++ b/cc-ci-plan/plan-phase-settings-ci-server-config.md @@ -0,0 +1,87 @@ +# Phase `settings` — minimal CI-server settings.toml + `SKIP_CANONICALS_FOR_UPGRADE` + +**Mission (operator-specified 2026-06-17):** introduce a **minimal, extensible server-level settings file** +(TOML) for the cc-ci server, and add its first value: **`SKIP_CANONICALS_FOR_UPGRADE`** (bool, **default +`false`**, and `false` on this server). When `true`, the upgrade tier resolves its base **without +canonicals** — i.e. it falls back to the main-tip predecessor — codifying that canonicals are an optional +optimization (a switch an operator can flip). The settings file is structured to hold **other CI-server +configs** later, but ship it minimal (just this one value for now). + +State files: `STATUS-settings.md`, `BACKLOG-settings.md`, `REVIEW-settings.md`, `JOURNAL-settings.md`. DECISIONS.md shared. + +## 1. Background + +Canonicals are an optimization + robustness aid for the upgrade base, **not** a requirement: the upgrade +tier already falls back to main-tip when no canonical exists (and the install/backup/restore/custom tiers +never use canonicals). This flag makes that explicit and operator-controllable: a server can run the +upgrade tier purely off main-tip (real predecessor), ignoring the warm-canonical layer entirely — useful +for a deployment that doesn't run the canonical sweep, for debugging, or for a simpler setup. + +This server keeps `false` (canonicals on — the optimized/robust path); the flag is the documented escape +hatch. + +## 2. Design + +**A. A minimal server settings file + loader.** +- A server-level TOML (today cc-ci server config is scattered env vars like `MAX_TESTS`, `CCCI_RUNS_DIR`). + Add a small settings layer that reads a TOML once. Suggested home: a host path the harness reads (e.g. + `/srv/cc-ci/settings.toml`), with a tracked `settings.toml.example` documenting the keys + defaults — OR + extend any existing cc-ci config module if one fits. **Builder: check for an existing cc-ci config + mechanism first and extend it rather than spawn a parallel one.** +- **Defaults baked into the loader** → an absent file, or an absent key, yields the default (so this server + needs no file to behave as today). Stdlib only (`tomllib`). Validate: unknown keys warn-and-ignore; + wrong type errors clearly. Per-server: the file is a host override, not committed config (a tracked + `.example` is fine; the live file is operator-managed and must carry **no secrets** — secrets stay in + sops). +- Keep it **minimal + extensible**: one `[ci]`/`[upgrade]` table with the single key now, shaped so future + CI-server configs slot in without a redesign. + +**B. `SKIP_CANONICALS_FOR_UPGRADE` (bool, default `false`).** +- Wire into `resolve_upgrade_base` (`run_recipe_ci.py`): guard the canonical (`version`) branch — when the + flag is `true`, **skip the canonical lookup entirely** and fall through to the existing main-tip ref path + (→ skip if head == main-tip). Effectively: behave as if no canonical exists. +- **Scope it narrowly to the upgrade BASE** (its name says so). Do NOT change canonical *promotion* or the + `--quick` warm-reattach with this flag — those are separate optimizations (a future `SKIP_CANONICAL_SWEEP` + / `SKIP_QUICK` could gate them; out of scope here — note in DECISIONS). +- **Note the sweep interaction** (document, don't fight it): with the flag `true`, a cold-on-latest sweep + run's upgrade tier resolves base = main-tip = head → the upgrade tier **skips** (no predecessor delta + without the canonical). That's consistent — an "upgrade" in a cold-on-latest run only exists relative to + the canonical. PR runs are unaffected (base = main-tip = real predecessor). This server runs `false`, so + no change here. + +## 3. Gates + +**M1 — implemented + unit-tested.** Settings loader (TOML, stdlib, defaults, validation, graceful on +absent/malformed file); `SKIP_CANONICALS_FOR_UPGRADE` wired into `resolve_upgrade_base`. Unit tests: flag +`false` (and absent file / absent key) → canonical used exactly as today; flag `true` → canonical branch +skipped, resolver returns the main-tip/skip path; malformed file handled. Adversary cold-verifies: the +**default is false** (this server's behavior is byte-for-byte unchanged); `true` genuinely bypasses the +canonical (not just cosmetically); the loader can't crash the harness on a bad/absent file; scope is the +upgrade base only (promote/`--quick` untouched). + +**M2 — verified on the server.** The live server reads the settings (file present with +`SKIP_CANONICALS_FOR_UPGRADE = false`, or absent → default false) and the upgrade path **still uses +canonicals — unchanged**. Then a controlled demonstration: flip it `true` (in a test/scratch context, not +permanently), show the upgrade base resolves to main-tip (canonical bypassed), then restore `false`. +Confirm the harness actually picks up the file on the server. Fresh Adversary PASS on both milestones → +`## DONE`. + +## 4. Guardrails + +- **Default `false`; this server stays `false`** — the change must be a no-op for current behavior. A + regression to the default upgrade-base path fails the gate. +- **Minimal + extensible** — one setting now, structured for more; do not over-build a config framework. +- **Stdlib only** for the loader; **no secrets** in settings.toml (config only; secrets stay in sops). +- **Narrow scope** — the flag affects only the upgrade-base resolver, not promotion or `--quick`. +- Never weaken a test. Commit author `autonomic-bot `; push every + commit. If the settings file lives at a host path requiring a deploy, treat it as a host change (loops + may deploy if clean + verify health, else file for the orchestrator). + +## 5. Definition of Done + +A minimal, extensible CI-server `settings.toml` (+ tracked `.example`, defaults in the loader) is read by +the harness; `SKIP_CANONICALS_FOR_UPGRADE` (default `false`, `false` on this server) is wired into the +upgrade-base resolver so `true` bypasses the canonical (main-tip path) and `false`/absent leaves current +behavior byte-for-byte unchanged; unit-tested; verified live on the server (false = unchanged; true = +canonical bypassed, then restored). Scope limited to the upgrade base (promote/`--quick` noted as separate). +M1 + M2 fresh Adversary PASSes in REVIEW-settings.md.