testsAndMisc/docs/superpowers/evidence/file-length-test-venv-blindspot-2026-07-25.json
Krzysztof kuhy Rudnicki 1b0a8dff46 python_pkg: the file-length test was blind to its own CI venv
It walked the working tree and skipped vendored trees by hard-coded directory
name. `.venv` was listed; `.ci-mirror-venv` — created inside the repo by the
pre-push CI mirror — was not, so the walk descended into it and died with a
UnicodeDecodeError on a joblib fixture that is deliberately encoded big5. A
crash, not a report: every real violation was hidden behind it.

Venvs are now found by their pyvenv.cfg marker, so any venv is pruned whatever
it is named, and the walk prunes in place instead of visiting thousands of
third-party files to filter them afterwards. Lines are counted from bytes, so a
line count cannot depend on an encoding. third_party/ joins the vendored skip
set — it holds upstream MCP servers, which this repo's 500-line rule never
governed.

Two regression tests come with it: a venv under an unlisted name holding an
oversized, undecodable module is pruned, and the line counter handles big5.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 16:32:32 +02:00

36 lines
3.4 KiB
JSON

{
"intent": "Make the 500-line file-length test see the repo's real Python sources. It walked the whole working tree and skipped vendored trees by hard-coded directory NAME, so the venv that the pre-push CI mirror creates in-repo (.ci-mirror-venv, not the listed .venv) was walked — and the test died with a UnicodeDecodeError on a joblib fixture that is deliberately not UTF-8, hiding every real violation behind a crash.",
"scope": [
"python_pkg/tests/test_file_length.py - the walk, the line count, and two new regression tests",
"Non-goal: changing the 500-line limit itself, or which non-venv directories count as vendored beyond adding third_party/"
],
"changes": [
"Virtual environments are detected by their pyvenv.cfg marker instead of by name, so any venv anyone drops in the tree is pruned whatever it is called. Naming them one at a time is precisely what failed here.",
"The walk uses os.walk and prunes in place, so a venv's thousands of third-party files are never visited at all rather than visited and filtered.",
"Lines are counted from bytes (read_bytes().splitlines()), so a line count can never depend on a file's encoding — that is what turned a non-UTF-8 vendored fixture into a test error.",
"third_party/ joins the vendored skip set: it holds vendored upstream MCP servers (blender-mcp's 2813-line addon.py, wander-agent's 1835-line server.py, ...) which the repo's own 500-line rule does not govern.",
"Two regression tests added: a fake venv under an unlisted name containing an oversized, undecodable module is pruned; and _line_count handles a big5-encoded file."
],
"verification": [
{
"command": "python -m pytest python_pkg/tests/test_file_length.py -q",
"result": "pass",
"evidence": "3 passed. Before the fix: UnicodeDecodeError on .ci-mirror-venv/.../test_func_inspect_special_encoding.py. Immediately after the walk was fixed the test reported 8 real violations (6 vendored third_party/ files plus session_autopsy's detectors.py 559 and parse.py 511); third_party/ is now skipped as vendored and the two session_autopsy files were split under 500 lines, so the run is green on merit rather than by exemption."
},
{
"command": "python -m pytest python_pkg -q (full suite with coverage gate)",
"result": "pass",
"evidence": "876 passed; TOTAL coverage 100% (3874 statements, 1124 branches), fail_under=100 satisfied. Test files are coverage-omitted, so the new helpers add no coverage debt."
}
],
"risks": [
"A source file placed inside a directory that happens to contain a pyvenv.cfg is no longer checked. That is the intended trade: such a directory IS a virtualenv.",
"third_party/ is now unchecked wholesale. Vendored upstream code was never meant to satisfy this repo's line limit, but a first-party file misfiled under third_party/ would slip past.",
"Counting lines from bytes treats a lone CR as a line break where the old text read did too (str.splitlines and bytes.splitlines split on the same set for ASCII control characters), so counts are unchanged for real source files."
],
"rollback": [
"git revert the commit; the test returns to name-based skipping and will again crash on any in-repo venv.",
"After rollback, re-run python -m pytest python_pkg/tests/test_file_length.py and confirm it errors rather than reporting violations - that is the old behaviour."
]
}