# BACKLOG — Phase 1e (generic-harness corrections) Phase-namespaced backlog. Builder edits `## Build backlog`; Adversary edits `## Adversary findings`. ## Build backlog - [x] **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. - [x] **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. - [x] **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. - [x] **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 - [x] **F1e-1 [adversary]** *(CLOSED @2026-05-28, fix-verified cold on commit 6eabfdc)* — *`lifecycle.exec_in_app` silently swallows a failed `docker exec` (returns empty stdout, returncode ignored) → backup/restore data-continuity overlays go RED on a healthy recipe when the post-op container cycle is slow.* Found cold-verifying E1/HC3 (commit b7e6cbd) on custom-html: one opt-out run had backup=FAIL with `AssertionError: '' == 'original'` from `tests/custom-html/test_backup.py::test_backup_captures_state` — the marker `cat` returned empty. **CORRECTION (2026-05-28):** isolated, no-concurrency repro (3× opt-out + 1× default, install,backup,restore) — **4/4 PASS**, deploy-count=1 each. So the opt-out flag is **NOT** the trigger (my earlier "removes the ~1s generic-pytest timing buffer" theory is **withdrawn**); the original symptom coincided with parallel Builder e2e runs loading the node. Real trigger: load / concurrency slowing the post-backup container cycle into a window where `exec_in_app`'s `docker exec` fails. The **static defect is the same** regardless of trigger. **Root cause (static):** `exec_in_app` runs `docker exec …` and returns `proc.stdout` **without checking `returncode`**; when backup-bot cycles the app container post-op, `docker exec` can fail → empty stdout silently passed back as data. The backup/restore overlays read via `exec_in_app` immediately after the cycling op with no readiness retry, despite docstrings claiming immunity. (Secondary risk: a failed exec masquerading as `""` could also make a real failure spuriously *pass* in a different assertion.) **Repro (orig symptom):** under any concurrent same-recipe load, an opt-out `STAGES=install,backup,restore` custom-html run can show `test_backup_captures_state` empty-string AssertionError. **Status:** Builder pushed fix at **commit 6eabfdc** — `exec_in_app` now polls (re-resolve container + re-exec) until `rc==0` or 90s, then **raises** (never masks failed exec as empty). No assertion weakened. Adversary fix-verification in flight on `/tmp/adv-fix`. **Closes when:** cold-verified PASS under opt-out (and a reasonable concurrency probe), per Adversary close-rule. - [ ] **F1e-2 [adversary]** — *Two concurrent same-recipe runs collide on `~/.abra/recipes/` (rm-rf + abra-fetch race).* Found during a controlled 2-concurrent custom-html test (PR=8001, PR=8002): run-a died at `subprocess.CalledProcessError: 'abra recipe fetch custom-html -n' rc=1`; run-b completed all-green. Cause: `runner/run_recipe_ci.py::fetch_recipe` does `rm -rf ~/.abra/recipes/` then `abra recipe fetch -n` — concurrent execution on the same recipe races on the same directory. Domain/volume/secret isolation hold (different PRs ⇒ different domains), but the shared recipe checkout is a serialisation point. **Why it matters:** §6/D-gate requires "two concurrent !testme runs don't collide." Drone caps `MAX_TESTS=1-2` today so practical impact is bounded, but as breadth scales (D10) this surfaces. Pre-existing in 1d; orthogonal to E1/HC3; not blocking E1. **Fix direction:** per-run recipe snapshot dir (`~/.abra/recipes/` may need to be run-scoped, or a flock around fetch+checkout, or move PR-head clones out of the shared abra dir). **Status:** Filed for HC4 / no-regression scope.