Found while repairing a stale commit-graph during the #338 work.
The defect
plugins/ca/hooks/pre-bash.py matches the security gates on the command string, and git commit-graph write --reachable starts with git commit. So routine object-database maintenance is blocked as though it were a commit:
$ git commit-graph write --reachable
BLOCKED [H-09b]: This commit introduces crypto/TLS changes, but no security-gate
pass is recorded ... Run the crypto-compliance gate, then commit.
git commit-graph writes no objects, creates no commit, and cannot introduce a crypto or secret change. The same shape applies to git commit-tree (a plumbing command that does create a commit object, so that one is arguably in scope) and to anything else beginning git commit-.
Why it matters beyond the annoyance
The gate's message is actively misleading: it tells an operator to run the crypto-compliance gate for a command that touches no content. The available escapes are both wrong for the situation — record a security-gate pass that certifies nothing, or reach for /ca:override, which is exactly the "override invented to cover a coverage hole" that ADR-0022 and #308 exist to prevent.
It also bites at the worst moment: git commit-graph write is what you run to repair a stale graph, and a stale graph is what surfaces after a batch of --delete-branch merges. Today's sprint merged ~14 PRs that way and left six garbage-collected commits referenced by the graph.
Fix
Match the subcommand, not a prefix. git commit is the verb; git commit-graph is a different one. A word-boundary match on the subcommand token fixes the whole class:
- in scope:
git commit, git commit -m ..., git commit-tree
- not in scope:
git commit-graph
Acceptance criteria
- AC-1:
git commit-graph write --reachable is not gated by H-09b or H-10b.
- AC-2:
git commit and git commit -m "..." are still gated exactly as today.
- AC-3: a test pins both directions, so the prefix match cannot creep back.
- AC-4: audit the other command matchers in
pre-bash.py for the same prefix-vs-subcommand shape and fix any found (e.g. anything matching git add, git push, git checkout by prefix).
Relevant sources
core/pysrc/pre-bash.py (canonical; vendored to three plugins by tools/sync-core.py)
plugins/ca/hooks/tests/ — where the matcher tests live
Found while repairing a stale commit-graph during the #338 work.
The defect
plugins/ca/hooks/pre-bash.pymatches the security gates on the command string, andgit commit-graph write --reachablestarts withgit commit. So routine object-database maintenance is blocked as though it were a commit:git commit-graphwrites no objects, creates no commit, and cannot introduce a crypto or secret change. The same shape applies togit commit-tree(a plumbing command that does create a commit object, so that one is arguably in scope) and to anything else beginninggit commit-.Why it matters beyond the annoyance
The gate's message is actively misleading: it tells an operator to run the crypto-compliance gate for a command that touches no content. The available escapes are both wrong for the situation — record a security-gate pass that certifies nothing, or reach for
/ca:override, which is exactly the "override invented to cover a coverage hole" that ADR-0022 and #308 exist to prevent.It also bites at the worst moment:
git commit-graph writeis what you run to repair a stale graph, and a stale graph is what surfaces after a batch of--delete-branchmerges. Today's sprint merged ~14 PRs that way and left six garbage-collected commits referenced by the graph.Fix
Match the subcommand, not a prefix.
git commitis the verb;git commit-graphis a different one. A word-boundary match on the subcommand token fixes the whole class:git commit,git commit -m ...,git commit-treegit commit-graphAcceptance criteria
git commit-graph write --reachableis not gated by H-09b or H-10b.git commitandgit commit -m "..."are still gated exactly as today.pre-bash.pyfor the same prefix-vs-subcommand shape and fix any found (e.g. anything matchinggit add,git push,git checkoutby prefix).Relevant sources
core/pysrc/pre-bash.py(canonical; vendored to three plugins bytools/sync-core.py)plugins/ca/hooks/tests/— where the matcher tests live