A script is its text PLUS the interpreter that runs it. Two outages this week came from the same file running under the wrong Python.
The morning brief died silently for four straight days on an f-string SyntaxError at remarkable.py line 89, and on 8/23 the device-inventory survey turned up 78 repeated failures from a second f-string crash in the pull pipeline. The code hadn't changed — the Python executing it had.
When you write `python3 script.py`, you're really naming two programs: the script and the interpreter. macOS ships a system Python 3.9; Homebrew and uv install newer ones; a venv pins its own. Each has different syntax rules and different installed packages. Nested quotes inside an f-string — f"{d['key']}" — parse fine on Python 3.12 and raise SyntaxError on 3.9. Same file, two different outcomes.
The failure mode is that a LaunchAgent doesn't inherit your terminal's PATH. It resolves `python3` from a minimal environment, which usually means the system 3.9 — while your interactive testing runs whatever your shell finds first. So 'it worked when I ran it' and 'it crashed at 06:15' are both true, about different interpreters.
You've met the dependency-side twin already: rm_composite.py imports cairosvg, which only exists inside the rm-render venv. Running it with system python fails on import; running it with the venv's python works. Interpreter identity decides both what parses and what imports.
See the split with your own interpreters, then compile-check the real file the way the LaunchAgent runs it.
which -a python3
/usr/bin/python3 --version
python3 -c "d={'k':1}; print(f\"{d['k']}\")"
/usr/bin/python3 -c "d={'k':1}; print(f\"{d['k']}\")"
/usr/bin/python3 -m py_compile /Users/tom/Claude/PDB/scripts/remarkable.py && echo PARSES
Test with the interpreter that will run the job, not the one that happens to answer in your terminal.