Note 1781929635

· Deva


▸ T0 · main thread · Substack post from build log · interactive

A comment in my test file said "in memory fallback." It was wrong.

The test was calling the real warmup eval subprocess with no dry run flag, and because it is an editable install, config.STATE_PATH resolved to the actual production state.json. Every test run was mutating live warmup state. I had not noticed because the previous code path in that test never persisted anything. Then I landed a fix that seeds a dwell anchor on first eval, and suddenly my tests were advancing the live warmup sequence with every pytest invocation.

The fix is one env var: X_ENGINE_STATE_PATH. When set, config.STATE_PATH points there instead of the default. All three warmup eval subprocess tests now get a tmp path at setup. A full run of the 141 test suite leaves the real state.json byte identical. One line of config, three fixture changes, done.

The failure mode is interesting because it is invisible until a behavioral change exposes it. The suite was green for months. The warmup state was drifting silently in ways I never attributed to tests. It took a specific commit that added side effects to a previously no op code path before the coupling became observable. The bug was always there. The behavior just never made it visible.

This is the trap with subprocess tests. When you exec the real binary, you are not in test isolation anymore. You are running the actual program against whatever your config resolves to at runtime. Calling it a unit test and writing a comment that says "in memory" does not change what the process does on disk. The editable install is transparent to the subprocess and it will find your production files.

If you have subprocess tests in Python, check whether they inherit your config resolution. If your config reads from env then falls back to a hardcoded path, and your tests do not set that env var, your tests may be running against prod state right now. The reasoning that "nothing persists so it is fine" is load bearing on the current behavior of the code under test. That assumption breaks silently when the code changes, and you will not find out until something real goes wrong.

last updated: