The label only protects against reclaims that honour it. The runner
hosts also run jobs we do not control: runner-2 has a second act_runner
registered with gitea.egl.lan on the same Docker daemon, and
opencode-devbox's workflows run raw `docker system prune -af` in 7
places. No prune removes an image a running container uses, so the
smoke step now starts a holder (`ci-reclaim-docker.sh hold`: --rm,
--network none, sleep 3600) right after the preflight, and the
always() cleanup step runs `release` (holder + image). Unprotected now:
only the seconds between the build step's load and the holder starting.
Verified on an isolated docker:29-dind: an unlabelled held image survives
raw system prune and image prune -af (control without holder: deleted);
hold fails on a missing image; holder is AutoRemove + network none;
release removes holder and image; reclaim behaviour unchanged.
Task logs of run 740: runner-a1 received task 2721 (smoke-studio) at
22:53:02Z and task 2722 (build-variant) at 22:58:38Z while 2721 was still
running. Other runners (runner-1/2/3) have capacity 1. 12e66aa said all
jobs share one daemon; corrected in CHANGELOG, AGENTS.md, the script
header and the lint.yml comment. No behaviour change.
v1.12.2 run 740: build-variant's `docker system prune -af --volumes`
untagged pi-devbox:smoke-studio 30 ms after smoke-studio loaded it, so
every studio assertion failed and the -studio tags were not published.
All jobs share the runner's Docker daemon, and a smoke image is unused
between smoke-test.sh's one-shot `docker run`s.
- scripts/ci-reclaim-docker.sh: the same reclaim, per object type, but
never prunes an image labelled se.jordbo.pi-devbox.ci-smoke-image;
labelled orphans are swept after 6h. `assert-protected IMG` is the
smoke preflight; `lint WORKFLOW...` rejects raw system/image prunes.
- smoke jobs: label their image, assert it, tag it per run
(pi-devbox:smoke[-studio]-<run_id>), remove it in an always() step.
- all five reclaim sites call the script; lint.yml runs the guard.
- Job order unchanged: studio jobs still gate only the -studio tags.
Verified on an isolated docker:29-dind (old prune deletes a labelled
image; new reclaim keeps it, removes unlabelled + 1970-created labelled
images, spares an in-use image, no errors); actionlint, shellcheck,
lint-shell, check-workflow-shell, check-doc-drift all clean.