From e1db4b036a7632a17c13a22f8a133ba34f3d5630 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 21 Sep 2026 15:28:54 +0100 Subject: [PATCH] fix(strip-history): strip inputs/ too, and print what actually remains The previous strip set left 71.58 MiB behind while every check reported success. Measured in a scratch clone: 269.43 MiB -> 81.13 MiB, with "VESPA/Multiplex blobs remaining (expect 0): 0" printed truthfully, and 71.58 MiB of that pool's content still present under inputs/fastq/. The cause is structural, not a typo in the path list. `git rev-list --objects` emits each object EXACTLY ONCE, paired with one of the paths it is reachable under. Those two blobs lived at both data/Multiplex_pool/ and inputs/fastq/; the census that chose the strip set saw only the first name, so inputs/ never appeared in it at all. Removing the path did not remove the content, and the post-strip grep for the stripped path returned 0 because it could not have returned anything else. A check that asks "is the path I just deleted absent" is a tautology, not evidence. So this does two things: - adds `inputs` and `logs_*.zip` (a committed CI log artefact no path class covered) to the strip set. Re-measured: 269.43 MiB -> 9.17 MiB, and the heaviest remaining path is the 7.71 MiB of LIVE .fastq.gz fixtures, which is the correct floor. - prints the heaviest REMAINING path aggregates after the rewrite. A path strip can never prove a blob is gone, because the blob may have a second name; the only honest verification is to look at what survived. The predicted figure was ~21 MiB and the run produced 81 MiB -- that gap was the entire signal, and nothing in the named checks would have raised it. The HEAD-tree-identity assertion is kept and still passes. It answers a different question -- did the strip set catch a LIVE file -- and it was never capable of detecting dead content that was missed. Still never runs on its own: refuses without --i-have-read-the-warnings, and the force-push commands remain printed instructions inside a heredoc. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01X3hgXxWm6umMgZkjYyHnnm --- scripts/strip-history.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/scripts/strip-history.sh b/scripts/strip-history.sh index 8148403..278a68a 100755 --- a/scripts/strip-history.sh +++ b/scripts/strip-history.sh @@ -113,6 +113,8 @@ git filter-repo --force --invert-paths \ --path 'data/VESPA_pool' \ --path 'data/Multiplex_pool' \ --path 'web' \ + --path 'inputs' \ + --path-glob 'logs_*.zip' \ --path-regex '^data/MiSeq_SOP/.*\.fastq$' \ --path-regex '(^|/)node_modules/' @@ -146,6 +148,23 @@ else fi echo " run the test suite in $WORK before believing any of this." +# A path-based strip CANNOT prove a blob is gone: the same blob can be reachable +# under a SECOND path, and `git rev-list --objects` names each object exactly +# once, so the census that chose the strip set credits it to one path only. +# Measured 2026-09-21: stripping data/Multiplex_pool left its 71.58 MiB intact +# under inputs/fastq/, and the pre-rewrite listing never mentioned inputs/ at +# all. The named checks above all passed while 71 MiB survived. So print what +# actually REMAINS and read it -- an unexpected heavy path here is the tell. +echo +echo " heaviest paths REMAINING (read this; do not trust the checks above alone):" +git rev-list --objects --all \ + | git cat-file --batch-check='%(objecttype) %(objectsize:disk) %(rest)' \ + | awk '$1=="blob" && $3!="" { + n=split($3,a,"/"); k=(n>=2 ? a[1]"/"a[2] : a[1]); s[k]+=$2; c[k]++ + } + END { for (k in s) printf " %10.2f MiB %6d %s\n", s[k]/1048576, c[k], k }' \ + | sort -rn | head -8 + cat <<'NEXT' ═══════════════════════════════════════════════════════════════════════════