the-custodian/scripts/check_generated_only_commit.py
codex 02e69269c8
Some checks failed
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 2s
Reject generated-only commits / generated-commit-guard (push) Successful in 11s
Python Tests / pytest (push) Failing after 28s
Adopt staged generation and prepare weekly sizing and credential isolation
2026-10-19 12:42:11 +02:00

55 lines
2.2 KiB
Python

#!/usr/bin/env python3
"""Reject commits consisting only of generated indexes/projection refreshes.
Applies to every author: automation must accompany an actual source change.
--staged supports a pre-commit hook; BASE..HEAD checks every commit for CI.
"""
import argparse
from pathlib import PurePosixPath
import subprocess
def generated(path):
parsed = PurePosixPath(path.lower())
name = parsed.name
return (name in {"work-records.md", ".custodian-brief.md", "source-index.md",
"publication-index.md", "index.generated.md"}
# The root config is authored generator input, not its output.
# Keep similarly named evidence and generated-directory copies gated.
or (name.startswith("source-inventory")
and str(parsed) != "source-inventory.config.json")
or name.startswith("decision-packets")
or name.startswith("publication-index") or name.startswith("projection-refresh")
or str(parsed).startswith("generated/")
or str(parsed).startswith("docs/attended-window/")
or any(part in {"evidence", "decision-packets", "evidence-packets"}
for part in parsed.parts[:-1]))
def standalone(paths):
return bool(paths) and all(generated(path) for path in paths)
def git(*args):
return subprocess.check_output(["git", *args])
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--staged", action="store_true")
parser.add_argument("--range", default="HEAD^..HEAD")
args = parser.parse_args()
commits = [None] if args.staged else git("rev-list", "--reverse", args.range).decode().splitlines()
failed = []
for commit in commits:
raw = git("diff", "--cached", "--name-only", "-z") if commit is None else git(
"diff-tree", "--root", "--no-commit-id", "-r", "--name-only", "-z", commit)
paths = [path.decode() for path in raw.split(b"\0") if path]
if standalone(paths):
failed.append(commit or "staged")
if failed:
parser.exit(1, "Generated-only commits rejected: " + ", ".join(failed) + "\n")
if __name__ == "__main__":
main()