Files
cc-ci/machine-docs/REVIEW-samever.md
autonomic-bot f97ed0299a
All checks were successful
continuous-integration/drone/push Build is passing
review(samever): Adversary orientation — samever phase started; awaiting M1 claim
2026-06-17 04:11:09 +00:00

3.3 KiB
Raw Blame History

REVIEW — phase samever (Adversary writes here)

Phase: samever — step back to older base when canonical == head version (no same-version upgrade) SSOT: /srv/cc-ci/cc-ci-plan/plan-phase-samever-older-base-fallback.md Adversary loop started: 2026-06-17T04:09Z Adversary clone: /srv/cc-ci/cc-ci-adv


Gate verdicts

(none yet — waiting for Builder M1 claim)


Orientation @2026-06-17T04:09Z

Phase samever plan created 2026-06-17T03:56Z. Builder has not yet started (no STATUS-samever.md).

Root cause confirmed (cold-read of resolver, lines 133148 of run_recipe_ci.py):

rec = canonical.read_registry(recipe)
if rec and rec.get("version"):
    return BasePlan(
        "version",
        rec["version"],
        None,
        f"last-green (warm canonical, status={rec.get('status')})",
    )

The warm-canonical path returns canonical["version"] WITHOUT checking if it equals the head version. The resolver is not passed the head's semantic version (only head_ref, a commit sha), so it cannot compare.

Current unit tests (8 tests in tests/unit/test_upgrade_base.py) — none cover canonical==head:

  • test_upgrade_not_in_stages_skip
  • test_expected_na_upgrade_skip_even_with_canonical_and_override
  • test_explicit_override_wins_over_canonical
  • test_last_green_warm_canonical_is_primary ← uses canonical["version"]="0.6.0+3.1.1", HEAD="aaaa1111head" (different version — correct but doesn't test the same-version edge)
  • test_main_tip_fallback_when_no_last_green
  • test_head_equals_main_tip_skip
  • test_no_canonical_no_main_skip
  • test_expected_na_other_rung_does_not_suppress_upgrade

Key utilities available for the fix:

  • warm_reconcile.recipe_tags(recipe) — returns all git tags from recipe clone
  • warm_reconcile.sort_versions(tags) — ascending sort of version tags (coop-cloud semver)
  • warm_reconcile.latest_version(tags) — the newest tag
  • Head version read from compose.yml: coop-cloud.${STACK_NAME}.version label at abra.recipe_dir(recipe)/compose.yml (head checkout already at that path when resolver runs)

M1 verification plan (what I'll cold-verify when claimed):

  1. Resolver reads head version from compose.yml (inspect the parsing — look for compose YAML read + coop-cloud.*version label extraction)
  2. New chain: override → (canonical if canonical≠head_version) → (newest older published if canonical==head_version) → main-tip → skip
  3. Unit tests added: at minimum canonical==head→step_back, canonical≠head→unchanged, no_older_published→skip, version ordering correct
  4. Run python -m pytest tests/unit/test_upgrade_base.py -v cold from own clone
  5. Confirm OVERRIDE, EXPECTED_NA, main-tip, skip paths are untouched (regression: existing 8 tests still pass)
  6. Teeth check: a "broken base" scenario should still fail (unit test or from plan F1d-2 evidence)

M2 verification plan:

  1. Cold-on-latest run on an enrolled recipe whose canonical == latest (seed the canonical to latest, then trigger cold run)
  2. Evidence in logs: base_version < head_version (not a no-op, not a skip)
  3. Re-run discourse #4 or equivalent version-bump PR → UNAFFECTED (canonical→head path still uses canonical)
  4. Spot-check ≥1 other recipe

Adversary findings

(empty — phase not yet started)


Break-it probes log

(none yet)