What:!testme on gitea PR #10 (drone build 35, 2026-10-05) rendered a summary card whose embedded app screenshot was custom-html-tiny's — while the run itself was genuinely gitea, level 5, all tests passing. Cosmetics-only bug; verdicts were never affected.
Root cause chain (evidence in /var/lib/cc-ci-runs/35/):
/var/lib/cc-ci-runs/ still holds old-era run dirs numbered up to 1377; drone's build counter restarted when its DB was re-created (2026-09-27), so new build numbers collide with old dirs (35 was one, first hit because that old dir happened to contain a screenshot).
The run reused the collided dir without cleaning it — fresh results.json/summary.* landed next to the May-31 fossil screenshot.png (its mtime was still May 31; size 12950 B = exactly custom-html-tiny's real screenshot per test_blank_threshold_brackets_observed_sizes).
screenshot.capture()'s SCREENSHOT-hook branch skipped the snap when out_path already existed ("the hook may have saved it" — no hook in the repo saves the PNG; every SCREENSHOT hook only navigates). So capture() returned the fossil as "captured" and the card embedded it.
results.fresh_artifact_dir(path): at run start remove ONLY the files/dirs this run owns (results.json, summary.html/png, badge.svg, lint.txt, screenshot.png, junit/); anything else in the dir is left untouched; never raises.
run_recipe_ci.py calls it right after computing run_artifact_dir.
screenshot.capture(): the hook branch now ALWAYS snaps (same settle + blank-retry path as the default branch) — a pre-existing file is never trusted.
Evidence:
Unit: 4 new tests (owned-only removal / dir creation / odd entries; fake-playwright capture regression proving a fossil out_path is overwritten and the hook still fires). Full unit suite: 319 passed, only the 4 pre-existing main failures (identical set on f675941).
Live E2E (cold, host, custom-html-tiny full stages with a simulated collision: pre-seeded fossil screenshot.png + ghost results.json in the run dir): fossil wiped, fresh PNG captured (screenshot: captured), results.json recipe=custom-html-tiny level=5, summary.html mentions only custom-html-tiny, teardown clean (no leftover stacks/volumes).
scripts/lint.sh: PASS (branch is rebased on post-#44 main, which already fixed the two pre-existing lint failures).
Dependency: stacked on #44 (merged) — the branch starts at the squashed #44 commit.
NOT merged — for operator review.
**What:** `!testme` on gitea PR #10 (drone build 35, 2026-10-05) rendered a summary card whose embedded app screenshot was **custom-html-tiny's** — while the run itself was genuinely gitea, level 5, all tests passing. Cosmetics-only bug; verdicts were never affected.
**Root cause chain (evidence in `/var/lib/cc-ci-runs/35/`):**
1. `/var/lib/cc-ci-runs/` still holds **old-era run dirs numbered up to 1377**; drone's build counter restarted when its DB was re-created (2026-09-27), so new build numbers collide with old dirs (35 was one, first hit because that old dir happened to contain a screenshot).
2. The run reused the collided dir **without cleaning it** — fresh `results.json`/`summary.*` landed next to the May-31 fossil `screenshot.png` (its mtime was still May 31; size 12950 B = exactly custom-html-tiny's real screenshot per `test_blank_threshold_brackets_observed_sizes`).
3. `screenshot.capture()`'s SCREENSHOT-hook branch **skipped the snap when `out_path` already existed** ("the hook may have saved it" — no hook in the repo saves the PNG; every `SCREENSHOT` hook only navigates). So `capture()` returned the fossil as "captured" and the card embedded it.
**Fix (cosmetics-only, R7 — verdict/level logic untouched):**
- `results.fresh_artifact_dir(path)`: at run start remove ONLY the files/dirs this run owns (`results.json`, `summary.html/png`, `badge.svg`, `lint.txt`, `screenshot.png`, `junit/`); anything else in the dir is left untouched; never raises.
- `run_recipe_ci.py` calls it right after computing `run_artifact_dir`.
- `screenshot.capture()`: the hook branch now ALWAYS snaps (same settle + blank-retry path as the default branch) — a pre-existing file is never trusted.
**Evidence:**
- Unit: 4 new tests (owned-only removal / dir creation / odd entries; fake-playwright capture regression proving a fossil `out_path` is overwritten and the hook still fires). Full unit suite: **319 passed**, only the 4 pre-existing main failures (identical set on f675941).
- Live E2E (cold, host, custom-html-tiny full stages with a **simulated collision**: pre-seeded fossil `screenshot.png` + ghost `results.json` in the run dir): fossil wiped, fresh PNG captured (`screenshot: captured`), `results.json` recipe=custom-html-tiny level=5, `summary.html` mentions only custom-html-tiny, teardown clean (no leftover stacks/volumes).
- `scripts/lint.sh`: PASS (branch is rebased on post-#44 main, which already fixed the two pre-existing lint failures).
**Dependency:** stacked on #44 (merged) — the branch starts at the squashed #44 commit.
NOT merged — for operator review.
!testme gitea PR #10 (drone build 35, 2026-10-05) rendered a summary card whose
app screenshot was custom-html-tiny's — a fossil from a May-31 run dir with the
same number. Root cause chain:
- /var/lib/cc-ci-runs/ keeps old-era run dirs numbered up to 1377; drone's
build counter restarted when its DB was re-created (2026-09-27), so new
builds collide with old dirs (35 was one).
- the run reused the collided dir without cleaning it: fresh results.json/
summary.* landed NEXT TO the old screenshot.png.
- screenshot.capture()'s SCREENSHOT-hook branch skipped the actual snap when
out_path already existed ('the hook may have saved it' — no hook does), so
capture() 'succeeded' without writing and the card embedded the fossil.
Fix, cosmetics-only (R7 — verdict logic untouched):
- results.fresh_artifact_dir(): at run start, remove ONLY the files/dirs this
run owns (results.json, summary.*, badge.svg, lint.txt, screenshot.png,
junit/) from its artifact dir; anything else is left alone; never raises.
- run_recipe_ci calls it right after computing run_artifact_dir.
- screenshot.capture(): the hook branch ALWAYS snaps (same settle/blank-retry
path as the default branch) — a pre-existing file is never trusted.
Unit tests: fresh_artifact_dir (owned-only removal, dir creation, odd entries)
+ capture() fake-playwright regression proving a fossil out_path is overwritten.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What:
!testmeon gitea PR #10 (drone build 35, 2026-10-05) rendered a summary card whose embedded app screenshot was custom-html-tiny's — while the run itself was genuinely gitea, level 5, all tests passing. Cosmetics-only bug; verdicts were never affected.Root cause chain (evidence in
/var/lib/cc-ci-runs/35/):/var/lib/cc-ci-runs/still holds old-era run dirs numbered up to 1377; drone's build counter restarted when its DB was re-created (2026-09-27), so new build numbers collide with old dirs (35 was one, first hit because that old dir happened to contain a screenshot).results.json/summary.*landed next to the May-31 fossilscreenshot.png(its mtime was still May 31; size 12950 B = exactly custom-html-tiny's real screenshot pertest_blank_threshold_brackets_observed_sizes).screenshot.capture()'s SCREENSHOT-hook branch skipped the snap whenout_pathalready existed ("the hook may have saved it" — no hook in the repo saves the PNG; everySCREENSHOThook only navigates). Socapture()returned the fossil as "captured" and the card embedded it.Fix (cosmetics-only, R7 — verdict/level logic untouched):
results.fresh_artifact_dir(path): at run start remove ONLY the files/dirs this run owns (results.json,summary.html/png,badge.svg,lint.txt,screenshot.png,junit/); anything else in the dir is left untouched; never raises.run_recipe_ci.pycalls it right after computingrun_artifact_dir.screenshot.capture(): the hook branch now ALWAYS snaps (same settle + blank-retry path as the default branch) — a pre-existing file is never trusted.Evidence:
out_pathis overwritten and the hook still fires). Full unit suite: 319 passed, only the 4 pre-existing main failures (identical set onf675941).screenshot.png+ ghostresults.jsonin the run dir): fossil wiped, fresh PNG captured (screenshot: captured),results.jsonrecipe=custom-html-tiny level=5,summary.htmlmentions only custom-html-tiny, teardown clean (no leftover stacks/volumes).scripts/lint.sh: PASS (branch is rebased on post-#44 main, which already fixed the two pre-existing lint failures).Dependency: stacked on #44 (merged) — the branch starts at the squashed #44 commit.
NOT merged — for operator review.