from pathlib import Path
BASELINE_DIR = Path(".github/baselines")
def read_baseline(name: str) -> dict[str, int]:
path = BASELINE_DIR / f"{name}.txt"
if not path.exists():
return {}
out: dict[str, int] = {}
for line in path.read_text(encoding="utf-8").splitlines():
line = line.split("#", 1)[0].strip()
if not line:
continue
key, _, count = line.rpartition(" ")
out[key] = int(count)
return out
def render_baseline(
findings: dict[str, int], title: str, regen: str = "just ratchet"
) -> str:
total = sum(findings.values())
body = "".join(f"{k} {findings[k]}\n" for k in sorted(findings))
return (
f"# Ratchet baseline: {title}\n"
f"#\n"
f"# Debt that predates the guard. This file may only SHRINK.\n"
f"# Regenerate with: {regen}\n"
f"#\n"
f"# {len(findings)} keys / {total} occurrences\n"
f"{body}"
)
def write_baseline(
name: str, findings: dict[str, int], title: str, regen: str = "just ratchet"
) -> None:
path = BASELINE_DIR / f"{name}.txt"
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(render_baseline(findings, title, regen), encoding="utf-8")
def ratchet(
name: str,
title: str,
findings: dict[str, int],
occurrences: dict[str, list[str]],
argv: list[str],
regen: str = "just ratchet",
) -> int:
if "--write-baseline" in argv:
write_baseline(name, findings, title, regen)
print(
f"{name}: wrote {len(findings)} keys "
f"/ {sum(findings.values())} occurrences"
)
return 0
base = read_baseline(name)
new = {k: v for k, v in findings.items() if k not in base}
worse = {k: v for k, v in findings.items() if k in base and v > base[k]}
stale = {k: v for k, v in base.items() if k not in findings}
better = {k: v for k, v in findings.items() if k in base and v < base[k]}
if new or worse:
print(f"{title}: NEW violations — this is the gate, not a suggestion.\n")
for key, count in sorted({**new, **worse}.items()):
was = f" (baseline {base[key]})" if key in base else ""
print(f" {key} x{count}{was}")
for line in occurrences.get(key, [])[:8]:
print(f" {line}")
print(
f"\nFix them, or — if this is deliberate — run `{regen}` "
f"and explain the new line in the PR description."
)
return 1
if stale or better:
print(f"{title}: the baseline is now STALE (you fixed something).\n")
for key, count in sorted(stale.items()):
print(f" fixed entirely, delete the line: {key} {count}")
for key, count in sorted(better.items()):
print(f" {base[key]} -> {count}, lower the number: {key}")
print(
f"\nRun `{regen}` and commit "
f"`.github/baselines/{name}.txt`."
)
return 1
print(
f"{title}: OK — {len(base)} known keys / {sum(base.values())} "
f"occurrences remaining (.github/baselines/{name}.txt)"
)
return 0