Orchestrata Ultimate › Gates › commit-precheck
Gate: commit-precheck (SubagentStop)
| Purpose | Meet the commit gate while the worker still has the context, not at git commit after it has handed back |
| Where it runs | SubagentStop hook ~/.claude/hooks/precommit_gate_subagent.sh (registered in ~/.claude/settings.local.json); the coordinator runs ~/bin/precommit-check itself before each commit; every builder brief's DONE WHEN |
| Trigger | A subagent finishing after it edited .py files; by hand |
| Exact command | ~/bin/precommit-check <repo> [file…] (no files: every changed or new .py against HEAD) |
| Blocks | The hook returns {"decision": "block", "reason": ...} on a failure, at most 3 times per agent id. precommit-check exits with the gate's code and prints PRECHECK-OK or PRECHECK-FAIL <rc> |
| Ruling / ADR | RUL-035 (hooks at user level, scoped to the cwd project); runs the RUL-008 review; RUL-041 (the coordinator checks, workers fix) |
Why it exists
Mohamed, 2026-10-22: "you keep being blocked on lint every time ... when will you ever fix
that". Workers' DONE WHEN ran only ruff and py_compile; the blocking gate,
scripts/gate.py review-staged (code review plus test review, for example T4 module-scope
fixtures), ran for the first time at git commit, after the worker had handed back
(memory commit-gate-precheck).
How it works
~/bin/precommit-check (shell, read 2026-10-23):
- Resolve the repo root; collect the files (arguments, or
git diff --name-only HEADplus untracked.py); keep the ones that exist. - No files:
PRECHECK-OK (no .py changes). Noscripts/gate.py:PRECHECK-OK (no commit gate in <repo>)(codetools passes trivially). No.venv/bin/python:PRECHECK-FAIL, exit 2, as the commit hook would. - Put
<repo>/.venv/binfirst on PATH;ruff check --fixeach file. - Copy the index to
/var/tmp/precheck-index.XXXXXX,git addthe files into that copy underGIT_INDEX_FILE, and runenv -u PYTHONPATH .venv/bin/python scripts/gate.py review-staged --repo-root <repo>against it. The real index is never changed; the copy is removed on exit.
Measured (memory): 0.4 s when nothing needs review, about 5 s for one test file.
~/.claude/hooks/precommit_gate_subagent.sh (shell, read 2026-10-23): reads
agent_transcript_path and agent_id from the payload, collects the file_path of every
Edit, Write and MultiEdit tool call on a .py file, groups them by git root (only
roots with scripts/gate.py), runs precommit-check per root under timeout 240, and on
any failure blocks with the last 40 lines of output and an instruction: "Fix every finding
below, then re-run ~/bin/precommit-check <repo> <files> until it prints PRECHECK-OK, and
only then finish. Do not weaken tests or add waivers to get past it." After 3 blocks it
logs "gave up after 3 blocks" and lets the stop through. It never fails the session.
Evidence
~/.local/state/codetools/precheck-hook.log (13 lines on 2026-10-23): the pipe tests of
2026-10-22 21:48–21:50 (agent=probe-1) show rc=1 then rc=0 for the same file, the
fail-then-fix path; real firings follow from 21:51 (py_edits=7, py_edits=4,
py_edits=0). Memory commit-gate-precheck records the pipe tests: it caught T4, and
passed a clean file and a read-only worker.
Typical failures and how to fix them
| Symptom | Cause | Fix |
|---|---|---|
| The worker is blocked with T-rule or ruff findings | the gate works | The worker fixes them; see review-staged for each rule |
PRECHECK-FAIL no project interpreter |
the worktree has no venv | scripts/worktrees.py provision <path> |
No SubagentStop lines in the log after a dispatch that edited files |
the hook is not firing | Ask Mohamed to open /hooks (memory); check the file still exists |
| The hook file is gone | deploy/install-claude-config.sh mirrors claude/hooks/ into ~/.claude/hooks/ with rsync --delete and deleted it on 2026-10-23 00:00 |
Restore it from the newest ~/.claude/.backup-*; durable fix (commit it into claude/hooks/) is open (memory claude-config-deploy-deletes-user-hooks) |
Related
- Gates — master index
- Gate: review-staged
- Workflow — the worker's stop gate
- Dispatch ledger (the other SubagentStop hook)
- Claude hooks
- RUL-035