Repository navigation
Add SentinelCommit: a Claude-powered semantic pre-commit guardrail - #1
Merged
Merged
Conversation
added 5 commits
September 19, 2026 12:27
…examples and tests
… found in testing
…ll three hazard classes offline
Dripar
added a commit
that referenced
this pull request
Sep 19, 2026
Add SentinelCommit: a Claude-powered semantic pre-commit guardrail
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
A Git pre-commit hook that reads the staged diff, reasons about it with Claude, and refuses the commit when it finds a runtime hazard a linter structurally cannot see — with a ready-to-paste patch in the terminal.
It targets three defect classes, deliberately narrow:
TRANSACTION_FAULTIDEMPOTENCY_RISKRACE_CONDITIONStyle, naming and formatting are explicitly not blocking — the linter already owns those.
Design decisions worth reviewing
Two-tier gate. Tier 1 is deterministic and free: empty diffs, docs, config, images and lockfiles never reach the API. Only code-bearing diffs cost a call.
Fail open, always. Missing key, dead network, timeout, malformed response, crashed interpreter — every failure path exits
0with a warning. A guardrail that blocks a commit because its own dependency is down trains the team to run--no-verifyreflexively, which disables it permanently. Blocking is reserved for the one case where the model actively asserts a hazard.Structured outputs, not a forced tool call.
output_config.formatwith a JSON Schema guarantees a schema-valid verdict, and composes cleanly with adaptive thinking — which is where the quality on this task actually comes from. No regex or string matching anywhere in the decision path.Dashboard. A blocked commit leaves no trace in git history, so the tool's most valuable moments are invisible to
git log. Verdicts are appended to.git/sentinel-audit.jsonlanddashboard.pyjoins them against the DAG. Stdlib only — no Flask, no npm, no build step.Bugs caught while testing this
Both were found by running it, not by reading it:
command -v python3, which resolves to the Microsoft Store stub — it exists, is executable, prints "Python was not found" and exits non-zero, so Git treated it as a hook failure. Now each candidate is probed, and any exit status other than0/1fails open.os.path.splitext("LICENSE")andsplitext(".gitignore")both return an empty extension, so extensionless files and dotfiles fell straight through the zero-token gate. Fixed with a filename allowlist; both cases are now regression-tested.A third, caught by a cross-check over the examples:
event_idis a parameter in the race-condition fixture, so it matched the idempotency rule first and reported the wrong hazard. Rules are now ordered by specificity.Testing
git commit(reject, then pass)Not tested: the live API path. Every run used
SENTINEL_MOCK=1— there was no API key on the build machine. The request shape is built to the current SDK, but it has never made a real call. That is the first thing a reviewer should exercise.Try it