Files
cc-ci-orchestrator/cc-ci-plan/plan-phase-settings-ci-server-config.md
T
autonomic-bot aa1f897820 plan: queue settings — minimal CI-server settings.toml + SKIP_CANONICALS_FOR_UPGRADE (sonnet, after dash)
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).
2026-06-17 09:44:22 +00:00

6.1 KiB

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 <autonomic-bot@noreply.git.autonomic.zone>; 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.