#!/usr/bin/env python3 from __future__ import annotations import subprocess import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] BLOCKED_PREFIXES = (".codex-input/", ".codex-artifacts/") BLOCKED_SUFFIXES = (".db-wal", ".db-shm") LARGE_FILE_LIMIT = 20 * 1024 * 1024 LARGE_FILE_ALLOWLIST_PREFIXES = ( "artifacts/evidence/accuracy/", "docs/assets/", "frontend/public/portfolio/", "output/pdf/", ) def tracked_files() -> list[str]: result = subprocess.run( ["git", "ls-files", "-z"], cwd=ROOT, check=True, capture_output=True, ) return [item for item in result.stdout.decode("utf-8").split("\0") if item] def main() -> int: violations: list[str] = [] for relative in tracked_files(): normalized = relative.replace("\\", "/") if normalized.startswith(BLOCKED_PREFIXES): violations.append(f"{normalized}: local agent scratch must not be tracked") continue if normalized.endswith(BLOCKED_SUFFIXES): violations.append(f"{normalized}: transient database state must not be tracked") continue path = ROOT / relative if not path.is_file(): continue size = path.stat().st_size if size > LARGE_FILE_LIMIT and not normalized.startswith( LARGE_FILE_ALLOWLIST_PREFIXES ): violations.append( f"{normalized}: {size} bytes exceeds the " f"{LARGE_FILE_LIMIT}-byte tracked-file budget" ) if violations: print("Repository hygiene violations:", file=sys.stderr) for violation in violations: print(f" - {violation}", file=sys.stderr) return 1 print("Repository hygiene check passed.") return 0 if __name__ == "__main__": raise SystemExit(main())