tankslab.com/recall/source

tests/test_leftovers.py

148 lines, exactly as they ship in the download.

#!/usr/bin/env python3 """ test_leftovers.py - each safety rule, proven able to refuse. The cleanup step moves files on a stranger's machine. Every rule below has a case that FAILS if the rule is removed, because a safety rail nobody has watched fail is not a safety rail - and this package shipped a redactor with two leaks in it today, found by someone else, so its author's reading of his own guards is not evidence. python3 tests/test_leftovers.py """ from __future__ import annotations import contextlib import io import os import sys import tempfile from pathlib import Path BIN = Path(__file__).resolve().parent.parent / "bin" sys.path.insert(0, str(BIN)) import leftovers # noqa: E402 def main() -> int: fails: list[str] = [] # Quarantine goes to HOME. A test that writes into the real one leaves litter on # the machine of whoever runs it, which is precisely the manner this package is # supposed to be an argument against. sandbox = tempfile.mkdtemp() os.environ["HOME"] = sandbox quiet = contextlib.redirect_stdout(io.StringIO()) # RULE 5 - nothing is offered unless the import was verified. with quiet: r = leftovers.offer(Path("/tmp/nonexistent.db"), verified=False) if not r["refused"]: fails.append("RULE 5: offered cleanup without a verified import") if r["moved"]: fails.append("RULE 5: moved something without a verified import") # RULE 6 - transcripts are never a candidate, at any privilege. for p in (Path.home() / ".claude" / "projects", Path.home() / ".claude" / "projects" / "anything" / "x.jsonl", Path.home() / ".ssh", Path.home() / ".claude" / "settings.json"): if not leftovers._protected(p): fails.append(f"RULE 6: {p} was NOT protected") # RULE 4 - only positively identified things are candidates. # # The directory is taken from the source table rather than written here, so this # test names nothing either. import sources dedicated = sources.dedicated_store_dirs()[0] dedicated.mkdir(parents=True, exist_ok=True) store = dedicated / "store.db" store.write_bytes(b"x" * 10) (dedicated / "logs").mkdir(exist_ok=True) (dedicated / "logs" / "a.log").write_text("hi") (dedicated / "someones-actual-work").mkdir(exist_ok=True) (dedicated / "someones-actual-work" / "thesis.txt").write_text("do not touch") (dedicated / "random.txt").write_text("neither") got = {c["path"].name for c in leftovers.candidates(store)} if "someones-actual-work" in got: fails.append("RULE 4: offered an unidentified directory") if "random.txt" in got: fails.append("RULE 4: offered an unidentified file") if "store.db" not in got or "logs" not in got: fails.append(f"RULE 4: failed to identify what it SHOULD offer (got {got})") # RULE 4, THE HARDER HALF - a NAME is not an identification. # # "archive", "backups" and "logs" are ordinary words people use for their own # folders. When the database is somewhere the old tool never owned - which is # exactly what `import --path` allows - those directories belong to the USER, and # offering them while asserting they are "its backups" invites someone to type # MOVE on their own data. Only the store and its own sidecars may be offered # there. Without the gate this case hands back logs/archive/backups and the test # goes red, which is the point of writing it. loose = Path(tempfile.mkdtemp()) loose_store = loose / "old.db" loose_store.write_bytes(b"x" * 10) for name in ("logs", "archive", "backups"): (loose / name).mkdir() (loose / name / "mine.txt").write_text("the user's own work") loose_got = {c["path"].name for c in leftovers.candidates(loose_store)} strays = loose_got - {"old.db", "old.db-wal", "old.db-shm"} if strays: fails.append("RULE 4: outside the tool's own directory it offered " f"name-matched folders it never identified: {sorted(strays)}") if "old.db" not in loose_got: fails.append("RULE 4: the database itself should still be offered (got " f"{loose_got})") # RULE 2 - the default is keep; only the typed word acts. # " MOVE " is deliberately ABSENT from this list: the code strips whitespace, and # someone who pastes the word with a space around it did type it. Rejecting that # would be pedantry, not safety. Lowercase "move" IS rejected - the word has to be # typed as shown, so it cannot be reached by a habitual "y". for answer in ("", "y", "yes", "Y", "n", "no", "move", "MOVE!", "MOVEE", "delete"): # NOTE the signature. offer() calls input_fn(prompt), so a lambda written as # `lambda a=answer: a` receives the PROMPT and returns it - the answer under # test is never used, nothing ever matches "MOVE", and the assertion passes # no matter what the code does. That exact mistake was here, and mutation # testing found it: weakening the guard to accept "" and "Y" did not turn # this test red. A test that cannot fail is worse than no test. with contextlib.redirect_stdout(io.StringIO()): r = leftovers.offer(store, verified=True, input_fn=lambda _prompt, a=answer: a) if r["moved"]: fails.append(f"RULE 2: answer {answer!r} MOVED something; only exact 'MOVE' may") if not store.exists(): fails.append("RULE 2: the store was moved despite no confirmation") # RULE 3 - the confirmed action MOVES, it does not delete. # Rebuild the fixture: the rule-2 loop should have left it untouched, but this # test must not depend on that to be meaningful. store.write_bytes(b"x" * 10) (dedicated / "logs").mkdir(exist_ok=True) (dedicated / "logs" / "a.log").write_text("hi") with contextlib.redirect_stdout(io.StringIO()): r = leftovers.offer(store, verified=True, input_fn=lambda _prompt: "MOVE") if not r["moved"]: fails.append("RULE 3: exact 'MOVE' did not move anything - the guard is stuck shut") else: for src, dest in r["moved"]: if src.exists(): fails.append(f"RULE 3: {src} still in place after a move") if not dest.exists(): fails.append(f"RULE 3: {dest} does not exist - data was DESTROYED, not moved") for f in fails: print(" FAIL " + f, file=sys.stderr) if fails: print("\nLEFTOVERS SAFETY TEST FAILED", file=sys.stderr) return 1 print("leftovers safety test OK - refuses without verification, protects transcripts,") print(" offers only identified items (and only inside the tool's own directory),") print(" defaults to keep, and moves rather than deletes") return 0 if __name__ == "__main__": sys.exit(main())