claim(2w): WC5 promote-on-green-cold proven — green cold run advances canonical (1.10.0→1.11.0); --quick never promotes; only cold advances

should_promote_canonical (enrolled+green+cold+latest) + promote_canonical
(re-seed canonical at green-verified latest, snapshot+registry, old known-good
replaced only on green). +5 unit (70 pass). Live: custom-html canonical advanced
1.10.0+1.28.0 → 1.11.0+1.29.0 via a full green cold run; snapshot refreshed; idle;
per-run app torn down. WC6 nightly sweep next.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-29 04:08:14 +01:00
parent cf5999cdda
commit 125453df20
4 changed files with 140 additions and 1 deletions

View File

@ -342,3 +342,19 @@ judged sufficient. No finding. **WC1.1 FULLY closed (keycloak + traefik).**
Phase-2w verified: WC1, WC1.1, WC1.2, WC2, WC3, WC4, WC7. Remaining: WC5, WC6, WC8, WC9.
Adversary now idle → safe for live cold runs. Building W3 WC5 (promote-on-green-cold) next.
## 2026-05-29 — W3 WC5 promote-on-green-cold built + proven; claiming. (WC6 next.)
should_promote_canonical(recipe,ref,overall,quick) = is_enrolled & green & cold & on-latest(no ref);
promote_canonical(recipe,head_ref) = deploy warm-<recipe> at latest (reattach retained volume if any,
else fresh) → healthy → undeploy → seed_canonical (snapshot+registry, atomic; old known-good replaced
ONLY on green so it's never lost). Wired into main() after a green cold run; non-fatal on failure.
+5 unit tests (70 pass). LIVE: set custom-html canonical to 1.10.0+1.28.0, ran full cold (no REF),
all tiers green + deploy-count=1 → promote advanced canonical 1.10.0→1.11.0+1.29.0, snapshot refreshed,
idle, per-run cust-* torn down, traefik/kc still 200. WC5 proven; claimed.
Mechanism note: cold runs still use FRESH per-run domains (unchanged); promote re-deploys the
canonical at latest separately (one extra deploy) so the old known-good is never at risk on a red run
(DECISIONS Phase-2w WC5). Next: WC6 nightly sweep (systemd timer: nixos-rebuild switch FIRST then
serial cold sweep over enrolled recipes; need canonical.enrolled_recipes() + a nightly-sweep nix
module). Building WC6 code while the Adversary verifies WC5.