Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.1 KiB
REVIEW — phase nixenv (Adversary)
Phase plan: /srv/cc-ci/cc-ci-plan/plan-phase-nixenv-shared-runtime-env.md
SSOT for verification. Verdicts below; cold-runs only.
Status: M1 PASS @ 2026-06-17T17:40Z (claim 8b8fc1f). M2 gated behind, not yet claimed.
M1 — PASS @ 2026-06-17T17:40Z — claim 8b8fc1f
Single-source harness runtime env — cold-verified, all 6 DoD items. Verdict formed from the phase plan (SSOT), the code, and my OWN cold builds/evals — JOURNAL-nixenv.md NOT consulted (anti-anchoring preserved).
- Builds succeed, both hosts (no collision).
nix build .?submodules=1#…cc-ci-hetzner…toplevel→ EXIT 0;…#…cc-ci…toplevel→ EXIT 0. (A transient SQLite eval-cache "busy" from running both in parallel waserror (ignored), not a build failure.) - Single source (greps).
withPackages→ 1 hit (packages.nix:17ccciPyEnv);pytest playwright→ 1 hit (same line);ccciRuntimeToolsdefined once (packages.nix:45), referenced bycc-ci-run(:68) + both host configs.nightly-sweep.nixhas NOwithPackages, NOpython3, NO/run/current-system/sw/binPATH prepend —runtimeInputs = [ pkgs.cc-ci-run ]andexec cc-ci-run …. The DEFECT-3 host-PATH patch is GONE. - Superset-or-equal — inspected the BUILT wrapper PATH.
cc-ci-runstorezxlx9jnylh7la5m48bsqb1wfm5l9r0bdexport PATHcarries all 15 store dirs: python3-3.12.8-env, abra-0.13.0-beta, docker-27.5.1, git-2.47.2, git-lfs-3.6.1, bash-5.2p37, coreutils-9.5, util-linux-2.39.4, curl-8.12.1, jq-1.7.1, gnused-4.9, gnugrep-3.11, gnutar-1.35, openssl-3.3.3, procps-4.0.4 — and ends:$PATH(PREPEND, inherited PATH retained → nothing from any path lost). Covers the full union of all 3 prior lists;git-lfs+opensslare the only additions. Nothing dropped. - Sweep ≡ Drone entrypoint (parity by construction). Built
cc-ci-nightly-sweepreferences the BYTE-IDENTICALzxlx9jnylh7la5m48bsqb1wfm5l9r0bd-cc-ci-run; both hosts'pkgs.cc-ci-runresolve that SAME store path;.drone.yml:83runscc-ci-run runner/run_recipe_ci.py(host systemPackages wrapper = same path). Same store path ⇒ identical pyEnv + tooling + PLAYWRIGHT_BROWSERS_PATH on Drone path AND timer sweep. - Host divergence removed. Both
configuration.nixsystemPackages lines are textually identical (pkgs.ccciRuntimeTools ++ [ pkgs.openssh ]). The pre-refactorcc-ci-vs-hetznergit-lfsone-off divergence (my prep flag #1) is ELIMINATED: builtcc-citoplevelsw/binnow containsgit-lfs,openssl,script(util-linux) — tools it previously lacked.opensshcorrectly kept host-only (ssh client, not a recipe tool); it remains on both hosts so the Drone path's inherited PATH is unchanged for it. - Future-dep propagation (by construction).
ccciRuntimeToolsis the lone definition; it feedscc-ci-run.runtimeInputs(→ Drone path via.drone.yml, → sweep viaexec cc-ci-run) AND both hosts'systemPackages(→ Drone runner host PATH). One edit to that list reaches every consumer. Proven structurally via the reference graph; no working-tree mutation needed.
No defects, no VETO. Faithful refactor — one shared definition, three references, DEFECT-3 class
structurally eliminated. M2 (deploy via nixos-rebuild switch + live parity witness: gitea LFS
roundtrip green under BOTH Drone path and a real timer fire) remains to be claimed/verified.
(prior) Cold-prep notes
Cold-prep — enumeration of the CURRENT (pre-refactor) declarations @ HEAD dd6712c
The M1 superset-or-equal proof must show the new shared set ⊇ the union of all of these. Captured from the code (SSOT), independent of any Builder narrative:
(A) nix/modules/harness.nix — cc-ci-run (Drone entrypoint) runtimeInputs:
pyEnv abra docker git coreutils util-linux
pyEnv = python3.withPackages [ pytest playwright ]- env:
PLAYWRIGHT_BROWSERS_PATH=${playwright-driver.browsers},PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
(B) nix/modules/nightly-sweep.nix — sweep runtimeInputs:
bash abra docker git curl jq gnused gnugrep gnutar coreutils util-linux procps
- DUPLICATE
pyEnv = python3.withPackages [ pytest playwright ] - same PLAYWRIGHT env
- DEFECT-3 patch:
export PATH="/run/current-system/sw/bin:/run/wrappers/bin:$PATH"(host-PATH prepend)
(C) Drone runner path — nix/modules/drone-runner.nix:
PATH = mkForce "/run/current-system/sw/bin:/run/wrappers/bin" → recipe shell-outs resolve from
host environment.systemPackages, NOT a runtimeInputs list.
(D) Host systemPackages (feeds C):
nix/hosts/cc-ci/configuration.nix:curl git jq openssh← NO git-lfsnix/hosts/cc-ci-hetzner/configuration.nix:curl git git-lfs jq openssh
UNION the shared set must cover (≥):
python3+pytest+playwright (pyEnv) · playwright browsers · abra docker git git-lfs coreutils util-linux bash curl jq gnused gnugrep gnutar procps openssh
Plan §2 also names openssl as a recipe shell-out → expect it present too.
Pre-noted suspicions to break on M1/M2 (cold, not yet verdicts):
- Host divergence:
cc-ciconfig lacksgit-lfsbuthetznerhas it. Which config is the LIVEssh cc-ciserver running, and doesgit-lfsactually resolve there today? If the shared set is applied to both host configs, cc-ci should GAIN git-lfs. Verify both configs end identical. - Nothing dropped: any token in the union missing from the shared set = blast-radius break.
- Sweep parity by construction: plan wants sweep to invoke
cc-ci-run(same entrypoint) — if it instead keeps a parallel list, "single source" is not actually achieved; grep must prove no module declares its own harness dep list. - DEFECT-3 patch removal: the host-PATH prepend should be gone/subsumed; if removed, git-lfs etc. must now come from the shared runtimeInputs, else the sweep regresses.
- Live witness: gitea
test_lfs_roundtripmust stay GREEN under BOTH Drone path and a real timer fire from the unified env.