From 0226167b4907798b0cccba3f91e744fc5b97a3e0 Mon Sep 17 00:00:00 2001 From: autonomic-bot Date: Thu, 28 May 2026 02:53:22 +0100 Subject: [PATCH] chore(1e): bootstrap Phase 1e loop state + settle HC1/HC2/HC3 decisions Co-Authored-By: Claude Opus 4.7 (1M context) --- machine-docs/BACKLOG-1e.md | 19 +++++++++++++++ machine-docs/DECISIONS.md | 47 ++++++++++++++++++++++++++++++++++++++ machine-docs/JOURNAL-1e.md | 23 +++++++++++++++++++ machine-docs/STATUS-1e.md | 38 ++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+) create mode 100644 machine-docs/BACKLOG-1e.md create mode 100644 machine-docs/JOURNAL-1e.md create mode 100644 machine-docs/STATUS-1e.md diff --git a/machine-docs/BACKLOG-1e.md b/machine-docs/BACKLOG-1e.md new file mode 100644 index 0000000..a56d8fa --- /dev/null +++ b/machine-docs/BACKLOG-1e.md @@ -0,0 +1,19 @@ +# BACKLOG — Phase 1e (generic-harness corrections) + +Phase-namespaced backlog. Builder edits `## Build backlog`; Adversary edits `## Adversary findings`. + +## Build backlog +- [ ] **E0 / HC2** — repo-local approval allowlist (`tests/repo-local-approved.txt`, default-deny); + gate `discovery.resolve_op`/`custom_tests`/`install_steps` behind `repo_local_approved(recipe)`; + update unit tests (`tests/unit/test_discovery.py`) for approved vs non-approved. +- [ ] **E1 / HC3** — generic-by-default (additive); op/assertion split. Orchestrator performs each + mutating op once; runs generic test_.py (unless opt-out) + overlay test_.py. Opt-out: + `CCCI_SKIP_GENERIC` / `CCCI_SKIP_GENERIC_` / `recipe_meta.SKIP_GENERIC`. Pre-op seed via + optional `tests//ops.py`. Migrate generic + overlays to assertion-only. Keep count==1. +- [ ] **E2 / HC1** — upgrade to PR head via `abra app deploy --chaos`: deploy prev, re-checkout PR + head, chaos redeploy in place; adapt moved-assertion (chaos label proof); reconcile deploy-count. +- [ ] **E3 / HC4** — docs (docs/testing.md, enroll-recipe.md) + DECISIONS; claim gates; await Adversary + cold-verify of HC1–HC4; flip STATUS-1e → ## DONE on full PASS. + +## Adversary findings +(none yet) diff --git a/machine-docs/DECISIONS.md b/machine-docs/DECISIONS.md index 1194d45..cf5d201 100644 --- a/machine-docs/DECISIONS.md +++ b/machine-docs/DECISIONS.md @@ -332,3 +332,50 @@ SSOT: `cc-ci-plan/plan-phase1d-generic-test-suite.md`. Resolves the §6 open dec recipe repo's `tests/` (snapshotted after fetch, per the existing volatile-checkout handling). Generic tier files live in `tests/_generic/` (assertion-only, use the shared live-deployment fixtures). + +--- + +## Phase 1e — generic-harness corrections (HC1–HC4) + +Three operator-review corrections to the Phase-1d shared harness, settled here (plan §5). + +- **HC2 — repo-local approval allowlist (form/location + workflow).** PR-author-controlled code + (`install_steps.sh`, repo-local `test_*.py`) runs on the CI host with `/run/secrets/*` present, so it + is **default-deny**. Allowlist file: **`tests/repo-local-approved.txt`** (checked into the cc-ci + repo, git-auditable). Format: one recipe name per line; `#` comments + blank lines ignored; a lone + `*` is NOT a wildcard (no global opt-in — every recipe is explicit). **Default: empty ⇒ no recipe + trusts repo-local code.** Discovery (`resolve_op`/`custom_tests`/`install_steps`) consults the + repo-local source **only** when `repo_local_approved(recipe)` is true; otherwise precedence is + **cc-ci > generic** only and repo-local is discovered-but-not-executed. **Workflow:** a cc-ci + maintainer reviews a recipe's repo-local tests, then adds the recipe name to + `tests/repo-local-approved.txt` in a cc-ci PR — a deliberate, reviewable act. The gate is centralized + in `discovery.py` (one reader) so the unit tests pin it. + +- **HC3 — generic-by-default opt-out flag (name/granularity + recipe_meta).** Generic assertions run + **additively** alongside any overlay by default. Opt-out, in increasing specificity (any one skips): + env **`CCCI_SKIP_GENERIC`** (truthy ⇒ skip generic for ALL ops), env + **`CCCI_SKIP_GENERIC_`** (e.g. `CCCI_SKIP_GENERIC_UPGRADE` ⇒ skip generic for that op only), and + declarative **`recipe_meta.SKIP_GENERIC`** = a list of op names (or `["all"]`) so the opt-out is + per-recipe and visible in git, not a hidden global. Truthy = `1/true/yes/on` (case-insensitive). + **Op-vs-assertion split:** a mutating op (upgrade/backup/restore) is performed **once by the + orchestrator** (the harness owns the op); then the generic assertion file (unless opted out) and the + overlay assertion file both evaluate the **shared post-op state**. Op results that an assertion needs + (pre-upgrade identity, backup snapshot_id) are passed op→assertions via a run-scoped JSON state file + at `$CCCI_OP_STATE_FILE` (read by `harness.generic.op_state()`); never logged. Overlays that need to + **seed pre-op state** (data-continuity markers, the backup→restore mutation) ship an optional + `tests//ops.py` with `pre_install/pre_upgrade/pre_backup/pre_restore(domain, meta)` callables + the orchestrator runs **before** the op (repo-local `ops.py` is allowlist-gated like other repo-local + code). Overlay `test_.py` files are now **assertion-only** (they no longer call `generic.do_*`). + +- **HC1 — DG4.1 deploy-count vs the in-place chaos upgrade.** The upgrade tier now upgrades to the + **PR head** (code under test), not a published tag: deploy the previous published version (base), + **re-checkout the PR head** (recorded as the recipe repo HEAD right after fetch, before any + version-tag checkout), then **`abra app deploy --chaos`** in place = the upgrade. The deploy-count + guard counts **`abra app new` installs only** (`_record_deploy()` fires in `deploy_app()`, NOT in the + chaos redeploy, which calls `abra.deploy` directly) — so a run is still **deploy-count == 1** and the + legitimate in-place chaos upgrade is not flagged. **Moved assertion (adapted):** prev→PR-head may not + bump the coop-cloud version label, so `assert_upgraded` accepts ANY of: version-label change, image + change, or a **chaos label** now present carrying the PR-head commit (a chaos deploy stamps + `coop-cloud..chaos`/`.chaos-version`) — the chaos label IS the proof PR-head was deployed. + Non-PR `!testme` (no SRC/REF): "PR head" = the catalogue current checkout, so upgrade is prev→current + — still a genuine move via chaos. (Exact chaos label name verified on the live abra during E2.) diff --git a/machine-docs/JOURNAL-1e.md b/machine-docs/JOURNAL-1e.md new file mode 100644 index 0000000..c7777ef --- /dev/null +++ b/machine-docs/JOURNAL-1e.md @@ -0,0 +1,23 @@ +# JOURNAL — Phase 1e (generic-harness corrections) + +Append-only Builder log: what I did + verifying command/output + next. + +## 2026-05-28 — Phase 1e bootstrap + orientation +- Read the phase plan (`plan-phase1e-harness-corrections.md`) + plan.md §6.1/§7/§9. Phase 1d is DONE + (STATUS-1d ## DONE, DG1–DG8 Adversary PASS). Studied the harness: `runner/run_recipe_ci.py` + (deploy-once orchestrator), `runner/harness/{discovery,generic,lifecycle,abra}.py`, `tests/conftest.py`, + `tests/_generic/*`, the overlays (custom-html/keycloak/cryptpad/n8n/matrix-synapse), and + `tests/unit/test_discovery.py`. +- Access re-verified: `ssh cc-ci 'hostname && whoami'` → `nixos` / `root`. +- Settled the three open decisions (HC1 deploy-count, HC2 allowlist, HC3 opt-out) in DECISIONS.md. +- Created STATUS-1e / BACKLOG-1e / JOURNAL-1e. Order of work: E0 (HC2) → E1 (HC3) → E2 (HC1) → E3. +- Key design notes: + - HC3 op/assertion split: orchestrator performs each mutating op once; generic + overlay both run as + assertions after. Op results (pre-upgrade identity, snapshot_id) passed via run-scoped + `$CCCI_OP_STATE_FILE`. Overlays that seed pre-op state move that into an optional + `tests//ops.py` (`pre_(domain, meta)`); overlay `test_.py` become assertion-only. + - HC1: re-checkout PR head (recorded as recipe HEAD right after fetch) then `abra app deploy --chaos`; + moved-assertion accepts the chaos label as proof PR-head deployed; deploy-count counts only + `deploy_app` (app new), not the in-place chaos redeploy. + +Next: E0 — implement the HC2 allowlist + discovery gate + unit tests. diff --git a/machine-docs/STATUS-1e.md b/machine-docs/STATUS-1e.md new file mode 100644 index 0000000..a97f9a8 --- /dev/null +++ b/machine-docs/STATUS-1e.md @@ -0,0 +1,38 @@ +# STATUS — Phase 1e (generic-harness corrections HC1–HC4) + +**Phase plan (SSOT):** `/srv/cc-ci/cc-ci-plan/plan-phase1e-harness-corrections.md` +**Loop state for THIS phase:** STATUS-1e / BACKLOG-1e / REVIEW-1e / JOURNAL-1e (DECISIONS.md shared). +Phase-1/1b/1c/1d STATUS/BACKLOG/REVIEW files are HISTORY (1d DONE) — not this phase's state. + +## Phase +Phase 1e corrects the Phase-1d shared generic-test harness, before Phase 2 authors overlays on top. +Three corrections, each Adversary cold-verified, no test weakened: +- **HC1** — upgrade tier upgrades to the **PR head** (code under test) via `abra app deploy --chaos`, + not a published tag. +- **HC2** — repo-local (PR-authored) `test_*.py`/`install_steps.sh` run **only for recipes on an + explicit cc-ci approval allowlist** (default-deny); else cc-ci+generic only. +- **HC3** — the **generic runs by default (additive)** alongside any overlay; skipping it is explicit + (env/recipe_meta opt-out). Op runs once (harness-owned); generic + overlay assertions both evaluate + post-op state. +- **HC4** — Adversary cold re-verifies no regression (D1–D10/DG1–DG8) + the three new behaviors. + +## Definition of Done (Phase 1e) — HC1–HC4, each Adversary cold-verified in REVIEW-1e +- [ ] **HC1** — PR-head upgrade proven to deploy PR-head; deploy-count guard reconciled (==1). +- [ ] **HC2** — repo-local ignored for a non-approved recipe, run for an approved one. +- [ ] **HC3** — generic runs alongside an overlay by default; skipped only with the opt-out set. +- [ ] **HC4** — no regression cold-verified; deploy-once + teardown still sacred. + +## Milestones (plan §3) +- **E0** — HC2 trust gate (allowlist, default-deny). *Accept: repo-local ignored unless approved.* +- **E1** — HC3 additive + op/assertion split. *Accept: overlay+generic both run; opt-out skips; count=1.* +- **E2** — HC1 upgrade-to-PR-head. *Accept: upgrade demonstrably deploys PR-head.* +- **E3** — HC4 cold re-verification + docs → DONE. + +## In flight +E0 (HC2) — implementing the repo-local approval allowlist + discovery gate + unit tests. + +## Gate +(none claimed yet) + +## Blocked +(none) — bootstrap access re-verified @2026-05-28: `ssh cc-ci` ok (root, NixOS).