From 208a079f4230edd520f5aa92288ae48247340910 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 19 Apr 2026 17:14:54 -0500 Subject: feat(hooks): shared _common.py helpers + systemMessage AI-attribution warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consolidates stdin-parse and response-emit across the two confirm hooks into `hooks/_common.py` (stdlib-only, sibling symlinked alongside the hooks it serves). Net ~28 lines less duplication. Adds a `systemMessage` banner alongside the confirmation modal when the commit message or PR title/body contains AI-attribution patterns: - Co-Authored-By: Claude|Anthropic|GPT|AI trailers - 🤖 robot emoji - "Generated with Claude Code" / similar footers - "Created with …" / "Assisted by …" variants Scanning targets structural leak patterns only — bare mentions of "Claude" or "Anthropic" in diff context don't fire, so discussing the tools themselves in a commit message doesn't false-positive. Clean-room synthesis from GowayLee/cchooks (MIT) — specifically, the systemMessage-alongside-reason pattern and event-aware stdin helpers. --- hooks/git-commit-confirm.py | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'hooks/git-commit-confirm.py') diff --git a/hooks/git-commit-confirm.py b/hooks/git-commit-confirm.py index bea6410..ad2dd66 100755 --- a/hooks/git-commit-confirm.py +++ b/hooks/git-commit-confirm.py @@ -28,22 +28,19 @@ Wire in ~/.claude/settings.json (or per-project .claude/settings.json): } """ -import json import re import subprocess import sys +from _common import read_payload, respond_ask, scan_attribution + MAX_FILES_SHOWN = 25 MAX_MESSAGE_LINES = 30 def main() -> int: - try: - payload = json.loads(sys.stdin.read()) - except (json.JSONDecodeError, ValueError): - return 0 # malformed; don't block - + payload = read_payload() if payload.get("tool_name") != "Bash": return 0 @@ -58,14 +55,14 @@ def main() -> int: reason = format_confirmation(message, staged, stats, author) - output = { - "hookSpecificOutput": { - "hookEventName": "PreToolUse", - "permissionDecision": "ask", - "permissionDecisionReason": reason, - } - } - print(json.dumps(output)) + hits = scan_attribution(message) + system_message = ( + f"WARNING — commit message contains AI-attribution patterns: " + f"{'; '.join(hits)}. Policy forbids AI credit in commits." + if hits else None + ) + + respond_ask(reason, system_message=system_message) return 0 -- cgit v1.2.3