installer-upgrade-stale-file-prune-manifest
Solution written to /workspace/solution.md (224 lines) and fully verified.
install.sh used cp -R for upgrades, which only adds/overwrites files. Files removed from the checkout in a newer version were never deleted. There was no record of installer-owned files, so pruning couldn't distinguish managed files from user-added files. .bak-<utc> rule backups were also unbounded.
install.sh)write_manifest — records find-generated, sed-normalized, LC_ALL=C sorted relpaths into $DEST/.install-manifest, before cp -R.prune_stale — reads the previous manifest first and removes only entries absent from the new checkout → user-added files are never touched.prune_stale → write_manifest → cp -R → cap_backups.cap_backups — LC_ALL=C ls -1 -- <glob> | LC_ALL=C sort -r | tail -n +6 removes all but the newest 5, guarded with || true so set -euo pipefail doesn't abort when no backups exist.sed to the curated-PATH stub tuple (its absence causes exit 127 only in stubbed tests); compute prune counts as produced - cap (7 − 5 = 2, not 3).b.txt removed on upgrade; unchanged files kept; new d.txt installed; manifest updated and old entry gone.userfile.txt added between installs survived.exit=127 without a sed stub; passes once sed is added.REPRO-SNIPPET OK.# Evidence - Problem class: installer-upgrade-stale-file-prune-manifest - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-22T18:19:09.671Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "terminal-jail install.sh upgrade pruned stale installed files: record an .install-manifest (sorted relpaths of checkout files) inside the installed tree BEFORE the cp -R; on re-install prune exactly manifest-listed files absent from the new checkout (never user-added files). Cap differing-rule .bak-<utc> backups to newest 5 via LC_ALL=C ls|sort -r|tail -n +6. Test-class lesson: installer tests with curated PATH stubs need every tool the new pipeline uses added to the stub tuple (sed was missed -> exit 127 only in curated tests, not real env); prune-count assertions must be arithmetic-checked (7 installs - 5 kept = 2 prunes, not 3).", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "installer-upgrade-stale-file-prune-manifest", "provider": "openrouter", "solved_at": "2026-09-22T18:19:09.672Z", "version": ""}