diff --git a/docs/superpowers/evidence/pre-commit-pytest-scope-fix-2026-05-14.json b/docs/superpowers/evidence/pre-commit-pytest-scope-fix-2026-05-14.json new file mode 100644 index 0000000..0e51bfd --- /dev/null +++ b/docs/superpowers/evidence/pre-commit-pytest-scope-fix-2026-05-14.json @@ -0,0 +1,26 @@ +{ + "intent": "Tighten pre-push pytest scope so it only runs tests for python_pkg subpackages that actually have a tests/ directory, preventing wasted runs and OOM during force-push.", + "scope": [ + "scripts/pytest_changed_packages.py", + "Non-goal: changing mypy/pylint/bandit/prettier hook scoping" + ], + "changes": [ + "_affected_packages() now filters out subpackage names whose python_pkg//tests/ directory does not exist on disk (covers deleted packages left over in rewritten history).", + "Root-level python_pkg/.py paths only trigger run-all when the file exists AND is conftest.py or __init__.py; stray root files from rewritten history are now silently skipped instead of running the full suite." + ], + "verification": [ + { + "command": "python -c 'from pytest_changed_packages import _affected_packages; ...'", + "result": "pass", + "evidence": "deleted-only paths -> set(); valid pkg path -> {steam_backlog_enforcer}; stray python_pkg/geo_data.py -> set(); existing python_pkg/conftest.py -> None (run all)." + } + ], + "risks": [ + "If a future package is added without a tests/ dir, it will be silently skipped on push.", + "Stray python_pkg/.py files added in the future would no longer trigger run-all unless they are conftest.py or __init__.py." + ], + "rollback": [ + "git revert ", + "Re-run pre-commit run --hook-stage pre-push --all-files to confirm prior behavior." + ] +} diff --git a/scripts/pytest_changed_packages.py b/scripts/pytest_changed_packages.py index 3e9456e..3f176bf 100755 --- a/scripts/pytest_changed_packages.py +++ b/scripts/pytest_changed_packages.py @@ -23,21 +23,32 @@ _MIN_SUBPACKAGE_DEPTH = 2 _PER_PACKAGE_MEM = "2G" +_RUN_ALL_TRIGGERS = frozenset({"conftest.py", "__init__.py"}) + + def _affected_packages(files: list[str]) -> set[str] | None: """Return subpackage names touched by *files*, or ``None`` for all. - Returns ``None`` when a root-level ``python_pkg/`` file is modified, - meaning every test should run. + Returns ``None`` only when a *currently existing* root-level + ``python_pkg/`` shared file (``conftest.py`` / ``__init__.py``) is + modified. Stray root-level files from rewritten history, or paths + pointing at deleted/non-existent subpackages, are silently skipped so + pre-push doesn't run the whole suite for irrelevant diffs. """ packages: set[str] = set() + root = Path("python_pkg") for path in files: parts = PurePosixPath(path).parts if len(parts) < _MIN_SUBPACKAGE_DEPTH or parts[0] != "python_pkg": continue if len(parts) == _MIN_SUBPACKAGE_DEPTH: - # Root-level file like python_pkg/conftest.py - run everything. - return None - packages.add(parts[1]) + name = parts[1] + if name in _RUN_ALL_TRIGGERS and (root / name).is_file(): + return None + continue + pkg = parts[1] + if (root / pkg / "tests").is_dir(): + packages.add(pkg) return packages