Skip to content

chore(harden): deterministic size gate - ratchet + top-level-unit gate - #139

Open
monkytheluffy wants to merge 1 commit into
mainfrom
pi-bg/20261019-220637-2580903
Open

monkytheluffy wants to merge 1 commit into
mainfrom
pi-bg/20261019-220637-2580903

Conversation

@monkytheluffy

Copy link
Copy Markdown
Collaborator

harden-repo skill applied to ppgrid (Python): size ratchet (non-blank line budgets, no-growth) + top-level-unit export gate, wired into CI + pre-commit hook. Append-only: 5 files, 159 insertions, 0 deletions (ci.yml, AGENTS.md, pyproject.toml, scripts/size_ratchet.py, size-ratchet.json).

Adversarial review: PASS (3537407, 37m) — all 10 checklist items verified by independent re-run:

  • both failure modes proven live: NEW BLOAT (900-line scratch → FAIL rc=1) and GROWTH (+100 lines to ratcheted file → FAIL rc=1); export gate fires on one added top-level def
  • pre-commit hook proven both directions (temp commit blocked; clean commit passed full chain)
  • ratchet seed byte-exact: reviewer's independent non-blank counts match the JSON exactly; --update regenerates byte-identical
  • test parity with base under equal conditions: 623 passed / 2 skipped (worker's 609/16 was a venv extras artifact, not a commit effect)
  • ruff check + format clean; CI job mirrors existing legs (fetch-depth 0, uv 3.13, --all-extras --locked)

Findings (ranked):

  • LOW (acceptable): pyproject.toml per-file-ignores entry is load-bearing - with base config (select = ["ALL"]) the new script fails ruff 7 errors (S404/S601/S602/T201); the entry follows the table's existing convention
  • NIT: scripts/size_ratchet.py:66 - nonexistent --base ref dies with raw CalledProcessError traceback instead of a clean gate message (CI fetch-depth 0 makes the ref always present; cosmetic)
  • NIT: scripts/size_ratchet.py:101 - ast.parse on a non-Python base version of a >2000-line file raises uncaught SyntaxError (not reachable in this repo's CI today)

HUMAN-GATED (ppgrid): Andryo merges.

@monkytheluffy

Copy link
Copy Markdown
Collaborator Author

Adversarial review — monky (orchestrator lane, 2026-10-20)

VERDICT: PASS — no blockers. 5 files, +159/-0, pure gate, zero app-code changes.

Verified by execution (scratch worktree @ c0de4a5):

  • Gate on branch: SIZE GATE: OK (4 ratcheted) rc=0, with and without --base main
  • GROWTH mode: +100 lines to pipeline.py → GROWTH 6894 > budget 6794 rc=1
  • NEW BLOAT mode: new 850-line file → rc=1
  • EXPORT GATE mode: committed top-level def on pipeline.py (6794 lines) → EXPORT GATE: 114 top-level units (was 112) rc=1 (gate diffs base...HEAD, so committed state — correct for CI)
  • Test-file x3: 2000-line tests/ file passes, 2500-line fails at 2400
  • ruff check + ruff format --check (CI's exact --extra dev invocations): clean; the per-file-ignores names are valid
  • CI wiring: standalone size job, no name clash with test/test-main/artifact, fetch-depth: 0 for the base ref, python 3.13 pin matches the other legs, push-to-main gets empty GITHUB_BASE_REF → ratchet-only as documented
  • Baseline integrity: all 4 ratcheted values match current main
  • AGENTS.md "pre-commit hook" claim: TRUE — the local hook runs size_ratchet.py --base HEAD (ratchet-only at commit)

Findings (ranked):

  1. LOW — test-file budget is double-multiplied. The growth check is n > ratchet[rel] * mult, so a ratcheted test file gets TEST_MULT applied to its stored budget on top of the already-multiplied 800×3 flag. A test file ratcheted at 2500 lines would only fail at 7500 — 3x looser than the AGENTS.md reading ("ratcheted files may only shrink"; x3 is the flag budget). Latent today: no test file is ratcheted yet. One-token fix if the shrink-only reading is intended (gate on ratchet[rel], or store the multiplied budget at --update).
  2. LOW — pre-commit hook is not reproducible from the repo. The size-gate line is appended to the local (untracked) .git/hooks/pre-commit; .pre-commit-config.yaml carries only the ruff hooks, so a fresh clone + pre-commit install loses the gate. Suggested fix: add it to the config as a local hook (entry: uv run python scripts/size_ratchet.py --base HEAD, pass_filenames: false) so pre-commit install reproduces it everywhere.
  3. INFO — new >2000-line files fail the export gate (git show base:rel misses → prev=0 → any top-level unit fails). That is the intended force-a-split-from-day-one behavior; noting so nobody reads it as a false positive.
  4. INFO — stale ratchet entries are never pruned. A file that shrinks below the flag keeps its budget entry forever (harmless; the JSON stays small).
  5. INFO — AST parse is strict-UTF-8 while line counting is errors="replace". A non-UTF-8 .py crashes the gate with a traceback (still exit 1) instead of a gate FAIL line; the test leg catches syntax issues first in practice.

Findings 1-2 are worth a follow-up commit but do not block the merge: the gate as shipped is deterministic, strictly fails on growth, and is wired into CI + pre-commit on this box.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant