My site runs on Babashka and Clojure. Last week I asked: is there any Python left in the live path? The answer matters because every runtime you keep is a debugger you must maintain — and every shell-out is a failure mode with someone else’s name on it.

The hunt

Surface searched Found
scripts/, careerbot/bin/, lifeos/bin/, CI config, bb.edn One live python3 shell-out (a test hashing a file)
daglog/legacy/ Two retired .py files — museum pieces, excluded by design
Blog prose Mentions only — docs are allowed to talk about Python

One call site. That’s the whole list, which is exactly why it was worth killing.

The kill

The test shelled out to python3 -c "import hashlib..." to hash a file. Babashka runs on the JVM, so the replacement is three lines of Java interop — MessageDigest SHA-256, zero new dependencies, zero subprocesses. Same hash, one fewer runtime, one fewer “command not found” in CI at 3am.

The guard (and proving it bites)

Deleting code isn’t a result; a guard is. So the preflight now starts with a checker that fails on any Python invocation shape outside legacy/:

The moral

Determinism isn’t a vibe — it’s the count of runtimes you must reason about. One runtime, pinned versions, data as EDN, snapshot builds: that’s what “immutable state” means in practice. Every shell-out you delete is a 3am page you never receive.