From d75931374549c0f47dfbe4ca70fcc7ab966d6702 Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Thu, 14 May 2026 21:21:40 +0200 Subject: [PATCH] perf(pre-commit): default_stages=[pre-commit] so push only runs pytest+prettier All hooks without an explicit stage are now commit-only. Pre-push surface shrinks to pytest-coverage (scoped) and prettier (scoped+ isolated). Force-pushing already-audited history no longer re-scans the divergent file diff with codespell/shellcheck/secrets/etc. --- .../pre-commit-default-stages-2026-05-14.json | 32 +++++++++++++++++++ meta/.pre-commit-config.yaml | 6 ++++ 2 files changed, 38 insertions(+) create mode 100644 docs/superpowers/evidence/pre-commit-default-stages-2026-05-14.json diff --git a/docs/superpowers/evidence/pre-commit-default-stages-2026-05-14.json b/docs/superpowers/evidence/pre-commit-default-stages-2026-05-14.json new file mode 100644 index 0000000..414c791 --- /dev/null +++ b/docs/superpowers/evidence/pre-commit-default-stages-2026-05-14.json @@ -0,0 +1,32 @@ +{ + "intent": "Make `git push` cheap by restricting the pre-push stage to only pytest-coverage and prettier. All other hooks default to commit-stage only, so a force-push of already-committed (already-audited) history does not re-run the full lint suite on the divergent file diff.", + "scope": [ + "meta/.pre-commit-config.yaml — add default_stages: [pre-commit].", + "Non-goals: do not modify .git/hooks/pre-push wrapper; do not change hook arguments or per-hook excludes; do not drop any hook from commit stage." + ], + "changes": [ + "Added `default_stages: [pre-commit]` to the global block.", + "Effect: hooks without an explicit `stages:` directive (general pre-commit-hooks suite, ruff, ruff-format, codespell, shellcheck, check-no-secrets, no-binaries, ai-evidence-contract, ai-multifile-contract, append-only-sessions, no-polling-antipatterns, no-noqa, check-python-location, remove-empty-dirs) now run on commit only.", + "Pre-push surface reduced to: pytest-coverage (scoped via scripts/pytest_changed_packages.py) + prettier (scoped + isolated systemd-run scope)." + ], + "verification": [ + { + "command": "pre-commit validate-config meta/.pre-commit-config.yaml", + "result": "pass", + "evidence": "exit 0" + }, + { + "command": "git push --force origin main", + "result": "pending", + "evidence": "next step after this commit" + } + ], + "risks": [ + "If a commit is made bypassing hooks (forbidden by policy), pre-push will not catch lint/secret issues. Mitigation: existing repo rule forbids --no-verify; ai-evidence-contract hook also runs on commit.", + "Hooks like `check-added-large-files` and `check-no-secrets` no longer run on push. Acceptable because they ran on every commit that produced the pushed history." + ], + "rollback": [ + "Remove the `default_stages: [pre-commit]` line to restore previous behavior (hooks running on every stage).", + "Run `pre-commit install --hook-type pre-commit --hook-type pre-push --overwrite` and then restore the custom .git/hooks/pre-push wrapper if it was clobbered." + ] +} diff --git a/meta/.pre-commit-config.yaml b/meta/.pre-commit-config.yaml index e99d2fa..186ab17 100644 --- a/meta/.pre-commit-config.yaml +++ b/meta/.pre-commit-config.yaml @@ -11,6 +11,12 @@ default_language_version: python: python3 +# By default every hook runs ONLY at commit-time. Pre-push runs only the +# hooks that explicitly opt in via `stages: [pre-push]` (currently +# pytest-coverage + prettier). This keeps `git push` cheap; commit-time +# already enforces the full lint suite. +default_stages: [pre-commit] + # Fail fast on first error (set to false to see all errors) fail_fast: false