From 61cd3a596023c78c741443df726c1155d30d475d Mon Sep 17 00:00:00 2001 From: Cipher208 <269750686+Cipher208@users.noreply.github.com> Date: Wed, 7 Oct 2026 01:14:32 +0200 Subject: [PATCH] fix(hooks): run the uv hooks with --locked so lock drift is loud A bare `uv run` re-resolves and rewrites uv.lock whenever pyproject.toml has drifted from it. Inside a pre-commit hook that is destructive in a way that takes a while to see: the rewrite lands on a file the hook is not allowed to change, pre-commit stashes the commit, the auto-fix conflicts with the stash, and it rolls everything back with "Stashed changes conflicted with hook auto-fixes". The commit silently never happens, and uv.lock is left modified in the working tree. That is how the five Dependabot PRs could each leave the lock stale: locally the first commit attempt would have quietly repaired it. --locked stops the rewrite and, unlike --frozen, actually fails: measured on a drifted lock, `uv run --locked` exits 2 with "The lockfile at `uv.lock` needs to be updated, but `--locked` was provided", where `--frozen` exits 0 and proceeds against the stale lock. Drift now blocks the commit instead of being swallowed, matching the `uv lock --check` gate added to CI in d12e941. The two `--isolated --with ruff` invocations are left alone: --isolated ignores the project, so they never touch the lock. --- .pre-commit-config.yaml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d00b4eb..9f7b58c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,9 +29,15 @@ repos: pass_filenames: false # F-gate: full test suite on commit (code changed) + # --locked, not --frozen: a bare `uv run` re-resolves and REWRITES + # uv.lock whenever pyproject.toml has drifted, which stashes the commit + # in progress and rolls it back ("Stashed changes conflicted with hook + # auto-fixes") — the commit silently never happens. --frozen stops the + # rewrite but still exits 0 against a stale lock; --locked stops the + # rewrite AND fails (exit 2) so the drift is loud. Verified both ways. - id: pytest-gate name: pytest gate (full suite) - entry: uv run --with-editable . --extra dev pytest tests/ -q --junitxml=/tmp/precommit_gate.xml + entry: uv run --locked --with-editable . --extra dev pytest tests/ -q --junitxml=/tmp/precommit_gate.xml language: system pass_filenames: false stages: [pre-commit] @@ -42,7 +48,7 @@ repos: # (scripts/_*.py) broke pushes without being part of them. - id: prepush-gate name: pre-push gate (ruff isolated + mypy 10 dirs) - entry: bash -c 'uv run --isolated --with ruff python -m ruff check $(git ls-files "*.py") && uv run --isolated --with ruff python -m ruff format --check $(git ls-files "*.py") && uv run --with-editable . --extra dev --extra embeddings mypy features/ shared/ mcp_server/ rag/ hooks/ wiki/ lifecycle/ graph/ core/ autohooks/ eval/' + entry: bash -c 'uv run --isolated --with ruff python -m ruff check $(git ls-files "*.py") && uv run --isolated --with ruff python -m ruff format --check $(git ls-files "*.py") && uv run --locked --with-editable . --extra dev --extra embeddings mypy features/ shared/ mcp_server/ rag/ hooks/ wiki/ lifecycle/ graph/ core/ autohooks/ eval/' language: system pass_filenames: false stages: [pre-push] @@ -50,7 +56,7 @@ repos: - id: prepush-pytest name: pre-push pytest gate - entry: bash -c 'ARIEL_HASH_EMBEDDINGS=1 uv run --with-editable . --extra dev pytest tests/ -q --junitxml=/tmp/prepush_gate.xml' + entry: bash -c 'ARIEL_HASH_EMBEDDINGS=1 uv run --locked --with-editable . --extra dev pytest tests/ -q --junitxml=/tmp/prepush_gate.xml' language: system pass_filenames: false stages: [pre-push]