From c27ea982dcff199624592c565b710f399d526d71 Mon Sep 17 00:00:00 2001 From: notque Date: Thu, 14 May 2026 03:14:21 +0000 Subject: [PATCH] feat(hooks): register suggest-compact + ruff-format-gate; fix error-learner timeout false positives Proposal B (STRONG 3.0/3.0): Register pretool-ruff-format-gate.py in PreToolUse:Bash - Blocks git push when ruff format --check finds violations - Only activates on projects with pyproject.toml [tool.ruff] section - RUFF_FORMAT_GATE_BYPASS=1 escape hatch; advisory deny via permissionDecision Proposal A (MODERATE 2.4/3.0): Register suggest-compact.py in PreToolUse (no matcher) - Advisory: counts Edit/Write calls, nudges /compact at 50-call threshold - ADR-103 backed; never registered despite being complete - Always exits 0; advisory only Proposal D (STRONG 3.0/3.0): Fix error-learner.py timeout false-positive detection - detect_error() was flagging tool outputs containing "timeout" in config strings (e.g., "timeout=2000", "stdin_timeout", "PASS: all hooks now have timeout caps", "Graduated: timeout/abc123") as genuine timeout errors - Adds 5 targeted false-positive phrases to existing exclusion list - 7/7 test cases pass; real timeout errors ("request timed out") still caught --- .claude/settings.json | 16 ++++++++++++++++ hooks/error-learner.py | 7 +++++++ 2 files changed, 23 insertions(+) diff --git a/.claude/settings.json b/.claude/settings.json index b319ab4e..417ab294 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -104,6 +104,16 @@ } ], "PreToolUse": [ + { + "hooks": [ + { + "type": "command", + "command": "python3 \"$HOME/.claude/hooks/suggest-compact.py\"", + "description": "Advisory: suggests /compact when Edit/Write call count reaches threshold (ADR-103)", + "timeout": 2000 + } + ] + }, { "matcher": "Bash|Write|Edit", "hooks": [ @@ -129,6 +139,12 @@ "command": "python3 \"$HOME/.claude/hooks/ci-merge-gate.py\"", "description": "Gate: block merge to main/master when CI checks are red", "timeout": 3000 + }, + { + "type": "command", + "command": "python3 \"$HOME/.claude/hooks/pretool-ruff-format-gate.py\"", + "description": "Ruff format gate: blocks git push when ruff format --check finds violations (Python projects with pyproject.toml only)", + "timeout": 5000 } ] }, diff --git a/hooks/error-learner.py b/hooks/error-learner.py index f8e0f5a3..f3a01829 100755 --- a/hooks/error-learner.py +++ b/hooks/error-learner.py @@ -114,6 +114,13 @@ def detect_error(event: dict) -> tuple[bool, str]: "failed over", "failover", "not found in cache", + # Timeout false positives: "timeout" appears in config output, + # import lines, and success messages — not as an actual error. + "timeout=", # e.g. timeout=2000 in hook config output + "stdin_timeout", # e.g. from stdin_timeout import ... + "timeout caps", # e.g. "PASS: all hooks now have timeout caps" + "timeout/", # e.g. "Graduated: timeout/abc123 → ..." + "read_stdin(timeout", # e.g. raw = read_stdin(timeout=2) ] if any(phrase in output_lower for phrase in false_positive_phrases): return False, ""