79 lines
5.2 KiB
Markdown
79 lines
5.2 KiB
Markdown
# REVIEW — phase `settings` (Adversary)
|
|
|
|
SSOT: /srv/cc-ci/cc-ci-plan/plan-phase-settings-ci-server-config.md
|
|
Gates: M1 (loader + flag + release-tag-first fallback, unit-tested) · M2 (verified live on server)
|
|
|
|
Status: **awaiting Builder bootstrap.** No `STATUS-settings.md` / claim yet as of 2026-06-17T16:45Z.
|
|
`dash` phase is DONE (M1+M2 PASS, commit 7507cf4) — this is the next phase.
|
|
|
|
## Baseline captured (pre-change, for the "false = byte-for-byte unchanged" guardrail)
|
|
|
|
Cold-read of the code I'll be verifying against (no anchoring — code + plan only):
|
|
|
|
- `resolve_upgrade_base` is in `runner/run_recipe_ci.py:112`. Current no-canonical chain:
|
|
`canonical(version, w/ samever step-back) → main-tip (recipe_branch_commit "main") → skip`.
|
|
The plan (§2.C) inserts **newest release tag < head** BEFORE main-tip on every no-canonical path.
|
|
- The samever helper to reuse: `warm_reconcile.newest_older_version(tags, version)`
|
|
(`runner/warm_reconcile.py:161`) — newest version-tag strictly older than `version`, keyed on
|
|
`version_key`. The fallback MUST reuse this (no divergent version ordering) per §2.C / M1.
|
|
- `recipe_tags(recipe)` = `git -C <recipe_dir> tag` (`warm_reconcile.py:267`) — tag source.
|
|
- NO existing TOML config module today: CI-server config is scattered `os.environ.get(...)`
|
|
(`CCCI_*`, `ABRA_DIR`, `MAX_TESTS`, etc.). No `settings.toml` tracked. So a NEW minimal loader is
|
|
justified (verify: minimal, extensible, stdlib `tomllib` only, defaults baked in, graceful on
|
|
absent/malformed file/unknown key).
|
|
|
|
## Verification checklist I will run when M1 is CLAIMED
|
|
- [ ] Default is `false` → this server's upgrade-base resolution byte-for-byte unchanged.
|
|
- [ ] flag false + canonical present → canonical (unchanged).
|
|
- [ ] flag false + NO canonical → **newest release tag < head** (NOT main-tip).
|
|
- [ ] no canonical AND no older release tag → main-tip.
|
|
- [ ] none → skip.
|
|
- [ ] flag true → canonical lookup BYPASSED → same release-tag-first fallback.
|
|
- [ ] absent file / absent key → default false; malformed file → no crash, clear handling.
|
|
- [ ] fallback REUSES `samever`'s helper (no parallel version-ordering impl).
|
|
- [ ] scope narrow: promotion + `--quick` warm-reattach UNTOUCHED by the flag.
|
|
- [ ] loader cannot crash the harness on a bad/absent file.
|
|
|
|
## Verdicts
|
|
|
|
### M1: PASS @2026-06-17T17:00Z (claim fed2678 / code cd19c1b) — cold-verified
|
|
|
|
Verified from my own clone, fresh shell, against plan §2/§3/§5 + the code — not the Builder's
|
|
narrative. Read JOURNAL only AFTER writing this verdict (contextualization only).
|
|
|
|
**Tests (re-run cold):**
|
|
- `test_upgrade_base.py` + `test_settings.py` → **32 passed**.
|
|
- Full unit suite → **315 passed** (no regression).
|
|
- ruff check → `All checks passed!`; ruff format → `4 files already formatted`.
|
|
|
|
**Independent probes (I patched the I/O boundaries myself — did NOT rely on Builder's fixtures):**
|
|
- *Loader* (real TOML files written to /tmp): absent/empty/absent-key → `False`; `true`→True,
|
|
`false`→False; malformed TOML → WARN + `False` (no crash); string value → `TypeError` (clear msg);
|
|
**int `1` for bool → TypeError** (no silent truthy coercion — good); unknown key + unknown table →
|
|
warn-and-ignore, valid key still honored; `[upgrade]` as scalar → warn + defaults. `$CCCI_SETTINGS`
|
|
path override honored. Real `get()` with no `/etc/cc-ci/settings.toml` (absent on host) → `False`.
|
|
- *Resolver matrix* (my own monkeypatch of canonical/recipe_tags/main/flag):
|
|
- false + canonical(≠head) → canonical **unchanged**; tags & main provably NOT consulted (raised if so).
|
|
- false + no canonical → **newest release tag < head** (`10.7.1+26.6.2`), main NOT consulted.
|
|
- false + no canonical + only-head tag → main-tip. false + nothing → skip.
|
|
- **true + canonical present → BYPASS → release tag `10.7.1`, NOT canonical `10.5.0`.**
|
|
- true + canonical + no older tag → routes full chain → main-tip.
|
|
|
|
**Guardrails checked:**
|
|
- *Default false / no-op for the default path:* canonical-present resolution (this server's steady
|
|
state) is byte-for-byte unchanged — proven by the probe that asserts tags/main are never consulted.
|
|
NOTE: the no-canonical fallback IS intentionally changed even under false (release-tag-first), per
|
|
plan §2.C "always-on … improves this server too" and M1's mandated test
|
|
`…prefers_release_tag_over_main_tip`. That is the spec, not a regression — it only fires for recipes
|
|
with no canonical (un-promoted), giving a real release base instead of a WIP main-tip.
|
|
- *Reuses samever helper:* fallback calls `warm_reconcile.newest_older_version(recipe_tags(r), head)`
|
|
— the SAME single-source ordering helper as the step-back. No divergent version ordering.
|
|
- *Narrow scope:* `skip_canonicals` is read ONLY at `run_recipe_ci.py:154` in `resolve_upgrade_base`.
|
|
`promote_canonical` / `should_promote_canonical` / `--quick` (951/965/1102) do not touch it.
|
|
- *Stdlib only:* loader imports `os, sys, tomllib, dataclasses` — no third-party.
|
|
- *No secrets:* `settings.toml.example` is config + docs only, default `false`, explicit "NO SECRETS".
|
|
- *Cannot crash harness:* any bad/absent file degrades to defaults (WARN); only a present wrong-TYPE
|
|
value raises (loud, intended).
|
|
|
|
No defects. No VETO. M1 cold-PASS. → M2 (live server) may be claimed.
|