From 1bc0e602351e05fd539fdb6a600fdfd072f22efa Mon Sep 17 00:00:00 2001 From: Eric Gullickson <16152721+ericgullickson@users.noreply.github.com> Date: Sun, 11 Jan 2026 16:13:21 -0600 Subject: [PATCH] chore: Add hooks directory and update CLAUDE.md navigation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .claude/CLAUDE.md | 2 + .claude/hooks/CLAUDE.md | 38 ++++++++++++++++++ .claude/hooks/enforce-agent-model.sh | 58 ++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 .claude/hooks/CLAUDE.md create mode 100755 .claude/hooks/enforce-agent-model.sh diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 0e86b14..9bc8c9e 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -7,6 +7,7 @@ | `role-agents/` | Developer, TW, QR, Debugger agents | Delegating execution | | `agents/` | Domain agents (Feature, Frontend, Platform, Quality) | Domain-specific work | | `skills/` | Reusable skills | Complex multi-step workflows | +| `hooks/` | PreToolUse hooks (model enforcement) | Debugging hook behavior | | `output-styles/` | Output formatting templates | Customizing agent output | | `tdd-guard/` | TDD enforcement utilities | Test-driven development | @@ -24,4 +25,5 @@ | `skills/incoherence/` | Detect doc/code drift | Periodic audits | | `skills/prompt-engineer/` | Prompt optimization | Improving AI prompts | | `agents/` | Domain agents (Feature, Frontend, Platform, Quality) | Domain-specific work | +| `hooks/` | PreToolUse hooks (model enforcement) | Debugging hook behavior | | `.ai/workflow-contract.json` | Sprint process, skill integration | Issue workflow | diff --git a/.claude/hooks/CLAUDE.md b/.claude/hooks/CLAUDE.md new file mode 100644 index 0000000..f98cfdf --- /dev/null +++ b/.claude/hooks/CLAUDE.md @@ -0,0 +1,38 @@ +# hooks/ + +## Files + +| File | What | When to read | +| ---- | ---- | ------------ | +| `enforce-agent-model.sh` | Enforces correct model for Task tool calls | Debugging agent model issues | + +## enforce-agent-model.sh + +PreToolUse hook that ensures Task tool calls use the correct model based on `subagent_type`. + +### Agent Model Mapping + +| Agent | Required Model | +|-------|----------------| +| feature-agent | sonnet | +| first-frontend-agent | sonnet | +| platform-agent | sonnet | +| quality-agent | sonnet | +| developer | sonnet | +| technical-writer | sonnet | +| debugger | sonnet | +| quality-reviewer | opus | +| Explore | sonnet | +| Plan | sonnet | +| Bash | sonnet | +| general-purpose | sonnet | + +### Behavior + +- Blocks Task calls where `model` parameter doesn't match expected value +- Returns error message instructing Claude to retry with correct model +- Unknown agent types are allowed through (no enforcement) + +### Adding New Agents + +Edit the `get_expected_model()` function in `enforce-agent-model.sh` to add new agent mappings. diff --git a/.claude/hooks/enforce-agent-model.sh b/.claude/hooks/enforce-agent-model.sh new file mode 100755 index 0000000..203b350 --- /dev/null +++ b/.claude/hooks/enforce-agent-model.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# Enforces correct model usage for Task tool based on agent definitions +# Blocks Task calls that don't specify the correct model for the subagent_type + +# Read tool input from stdin +INPUT=$(cat) + +# Extract subagent_type and model from the input +SUBAGENT_TYPE=$(echo "$INPUT" | jq -r '.subagent_type // empty') +MODEL=$(echo "$INPUT" | jq -r '.model // empty') + +# If no subagent_type, allow (not an agent call) +if [[ -z "$SUBAGENT_TYPE" ]]; then + exit 0 +fi + +# Get expected model for agent type +# Most agents use sonnet, quality-reviewer uses opus +get_expected_model() { + case "$1" in + # Custom project agents + feature-agent|first-frontend-agent|platform-agent|quality-agent) + echo "sonnet" + ;; + # Role agents + developer|technical-writer|debugger) + echo "sonnet" + ;; + quality-reviewer) + echo "opus" + ;; + # Built-in agents - default to sonnet for cost efficiency + Explore|Plan|Bash|general-purpose) + echo "sonnet" + ;; + *) + # Unknown agent, no enforcement + echo "" + ;; + esac +} + +EXPECTED_MODEL=$(get_expected_model "$SUBAGENT_TYPE") + +# If agent not in mapping, allow (unknown agent type) +if [[ -z "$EXPECTED_MODEL" ]]; then + exit 0 +fi + +# Check if model matches expected +if [[ "$MODEL" != "$EXPECTED_MODEL" ]]; then + echo "BLOCKED: Agent '$SUBAGENT_TYPE' requires model: '$EXPECTED_MODEL' but got '${MODEL:-}'." + echo "Retry with: model: \"$EXPECTED_MODEL\"" + exit 1 +fi + +# Model matches, allow the call +exit 0