A deterministic, fail-open human-sign-off gate for high-stakes commits.
commitward matches a commit's diff against a checkpoint registry and blocks the commit
(exit 2) only when a guarded change fires and no one has acknowledged it with a
HITL-ACK: trailer in the commit message. It is fail-open by construction: a missing
binary, a git error, an unreadable registry — anything that isn't a deliberate,
unacknowledged fire — lets the commit through. The gate never blocks on its own failure.
It is not a linter and not a CI framework. It is one small, greppable primitive: approval, not correctness, for agentic commits where a human (or an orchestrator) must sign off on a narrow set of high-stakes changes.
Part of the Barnett Studios agentic-harness toolkit → cxpak · commitward · abproof · …
As a git hook (most common):
# from your repo, install a commit-msg hook that runs commitward
./install-hook.shThe hook is fail-open and disables with COMMITWARD_HITL=off. If your repo uses a global
core.hooksPath, the installer warns and tells you how to target that directory instead.
As a CLI:
brew tap Barnett-Studios/tap && brew install commitward # macOS/Linux
cargo install commitward # any platform
commitward --base origin/main --format markdownAs a container image:
docker run --rm -v "$PWD:/repo" ghcr.io/barnett-studios/commitward \
--base origin/main --format markdownAs a library crate (in-process, e.g. for another Rust tool):
[dependencies]
commitward = "0.1"use commitward::{compile, detect, exit_class, load_checkpoints, merge};A checkpoint fires on one of three modes: paths (regex over changed file paths),
content (regex over added lines, with content_exempt_paths), or a code-driven
semantic check. commitward ships a default global baseline; a repo adds or overrides
checkpoints in .commitward/checkpoints.yaml (repo entries override global ones by name).
version: "1"
checkpoints:
- name: agent-instructions-self-mod
summary: "Editing agent-governing instructions"
paths:
- "(^|/)CLAUDE\\.md$"
- "(^|/)rules/.*\\.md$"
- name: destructive-ops
summary: "A destructive shell command was added"
content:
- "\\brm\\s+-rf\\b"
content_exempt_paths:
- "(^|/)docs/"Regex is the Rust regex crate: no look-around, no back-references.
When a checkpoint fires, the commit is blocked (exit 2) until the message carries a matching trailer:
Refactor the gate registry
HITL-ACK: gate-self-mod reviewed with the owner
An acknowledged fire returns exit 1 (fired, but allowed to proceed) — distinct from exit 0 (nothing fired). Only exit 2 blocks.
| Code | Meaning |
|---|---|
0 |
no checkpoint fired — or any fail-open path (missing git/registry, parse error) |
1 |
at least one checkpoint fired and all fired checkpoints are acknowledged |
2 |
at least one checkpoint fired and is unacknowledged — human sign-off required |
64 |
usage error (bad flag / missing argument) |
See CONTRACT.md for the full interface and the fail-open guarantee.
For consumption by another tool or from a container, commitward gate reads a JSON request on
stdin and writes a {schema_version, status, body} response envelope on stdout — the diff and
registries inlined, so it needs no git, no network, and no mounts:
$ echo '{"name_status":"M\tCLAUDE.md","commit_msg":"docs: x",
"global_registry_yaml":"version: \"1\"\ncheckpoints:\n - name: cm\n summary: s\n paths:\n - CLAUDE\n"}' \
| docker run --rm -i --network none ghcr.io/barnett-studios/commitward gate
{"schema_version":"1","status":"ok","body":{"fired":[{"name":"cm",...}],"unacked":["cm"],"exit_class":2}}Request fields (all optional; evaluation fails open on absent inputs): diff, name_status
(git diff --name-status), commit_msg, global_registry_yaml, repo_registry_yaml,
base_repo_registry_yaml (for checkpoint-removed detection). The block decision is carried in
body.exit_class (0 none fired · 1 fired-but-all-acked · 2 unacked fire), not the process exit
code — the process exits 0 on any successful evaluation, so a consumer never mistakes a fired gate
for a transport failure. A malformed request yields status:"error" + a non-zero exit. The native
git-reading CLI above stays the path for commit-msg hooks and standalone use.
Licensed under either of MIT or Apache-2.0 at your option. Unless you explicitly state otherwise, any contribution you intentionally submit for inclusion in the work shall be dual-licensed as above, without any additional terms.
Built by Barnett Studios — part of the agentic-harness toolkit: cxpak · commitward · cascadr · abproof · cordon · slicr.