forked from bchanot/claude
feat(gitflow): push-guard hook denies Claude's git push in manual-push mode
Run B of manual-push mode (BDR-111). With `gitflow.autopush false`
nothing stops Claude from typing `git push` itself: the `ask` tier is
inert under auto mode. This adds the mechanical block the user chose.
- hooks/push-guard.sh (PreToolUse, matcher Bash|Monitor, timeout 10):
detects a push in the command text (strict, quote-stripped loose and
alias patterns; backslash-newline folded in bash, BSD sed/grep only),
reads gitflow.autopush in the payload cwd and in every literal -C/cd
dir the command names (global config counts outside a repo), denies
with the documented JSON form and a reason that tells the user to run
the command with `!`. Unparseable value = manual (fail closed); once
a push is detected an EXIT trap emits a static deny on any internal
error. jq missing = one stderr warning, allow (sibling-hook policy).
- settings.json: hook wiring; 18 deny entries closing the write forms
of the human-only toggle (any `git … config` spelling, section
removal/rename, `-c`, config env overrides, direct edits of git config
files); one soft_deny on pushing in manual mode in any form, with no
per-turn clearance; the routing-around rule names hook refusals.
- hooks/session-start.sh: `🔒 push : manual (autopush=false) — ! git push`
banner line when the key reads false (padding in bytes).
- lib/tests/push-guard.test.sh: 61 checks (push forms, over-blocks,
invalid value, global key, fail-closed trap, no-jq, wiring, banner).
Known limits are listed in the hook header; the soft_deny rule is the
backstop. Run C (skills that push on their own) and run D (fail-closed
readers everywhere) follow. Do not enable manual mode at work before C.
This commit is contained in:
@@ -230,6 +230,11 @@ if [ -n "$GF_REFRESHED" ]; then
|
||||
printf "│ 🪝 %-44s│\n" "${_gf_line:0:44}"
|
||||
unset _gf_line
|
||||
fi
|
||||
# ── manual-push mode (BDR-111): one lock line when this repo never auto-pushes ──
|
||||
# %-46s, not 44: bash printf pads by BYTES and "—" is 3 bytes (2 extra).
|
||||
if [ "$(git config --bool --default true gitflow.autopush 2>/dev/null)" = false ]; then
|
||||
printf "│ 🔒 %-46s│\n" "push : manual (autopush=false) — ! git push"
|
||||
fi
|
||||
if [ -n "$GRAPHIFY_HINT" ]; then
|
||||
printf "│ 🕸️ %-44s│\n" "${GRAPHIFY_HINT:0:44}"
|
||||
printf "│ %-40s│\n" "→ /graphify (AST, seconds) — you decide"
|
||||
|
||||
Reference in New Issue
Block a user