From 8f06f9578448e80a0b5b20463ef7edb2c373341a Mon Sep 17 00:00:00 2001 From: Leo Miranda Date: Thu, 29 Jan 2026 04:18:10 +0000 Subject: [PATCH] Add "RFC-Hook-Efficiency-Improvements" --- RFC-Hook-Efficiency-Improvements.-.md | 371 ++++++++++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 RFC-Hook-Efficiency-Improvements.-.md diff --git a/RFC-Hook-Efficiency-Improvements.-.md b/RFC-Hook-Efficiency-Improvements.-.md new file mode 100644 index 0000000..e2764a1 --- /dev/null +++ b/RFC-Hook-Efficiency-Improvements.-.md @@ -0,0 +1,371 @@ +# RFC: Hook Efficiency Improvements + +**Status:** Proposal +**Created:** 2026-01-28 +**Author:** Claude Code Analysis +**Priority:** Medium +**Estimated Effort:** 2-3 sprints + +--- + +## Executive Summary + +Analysis of the 16 hooks across 12 plugins revealed significant inefficiencies in trigger timing, matcher precision, and redundant operations. This RFC proposes changes to reduce session startup latency, minimize per-edit overhead, and eliminate duplicate logic. + +--- + +## Current State + +### Hook Inventory + +| Plugin | Event | Matcher | Script | Lines | +|--------|-------|---------|--------|-------| +| projman | SessionStart | - | startup-check.sh | 119 | +| pr-review | SessionStart | - | startup-check.sh | 31 | +| claude-config-maintainer | SessionStart | - | enforce-rules.sh | 69 | +| data-platform | SessionStart | - | startup-check.sh | 55 | +| viz-platform | SessionStart | - | inline echo | 1 | +| cmdb-assistant | SessionStart | - | startup-check.sh | 67 | +| contract-validator | SessionStart | - | auto-validate.sh | 196 | +| doc-guardian | PostToolUse | `Write\|Edit\|MultiEdit` | notify.sh | 75 | +| code-sentinel | PreToolUse | `Write\|Edit\|MultiEdit` | security-check.sh | 63 | +| data-platform | PostToolUse | `Edit\|Write` | schema-diff-check.sh | 139 | +| contract-validator | PostToolUse | `Edit\|Write` | breaking-change-check.sh | 175 | +| project-hygiene | PostToolUse | `Write\|Edit` | cleanup.sh | 29 | +| cmdb-assistant | PreToolUse | NetBox MCP tools | validate-input.sh | 80 | +| git-flow | PreToolUse | `Bash` | branch-check.sh | 103 | +| git-flow | PreToolUse | `Bash` | commit-msg-check.sh | 75 | +| clarity-assist | UserPromptSubmit | - | vagueness-check.sh | 217 | + +**Total:** 16 hooks, ~1,493 lines of shell code + +### Performance Impact + +**Per session startup:** +- 7 bash processes spawned +- 3 Python invocations +- 4 HTTP calls (Gitea API, NetBox API) +- Estimated 200-500ms added latency + +**Per file edit:** +- 4 bash processes spawned (PostToolUse hooks) +- 1 bash process spawned (PreToolUse - code-sentinel) +- Multiple `find` and `git` commands +- Each hook independently parses JSON stdin + +--- + +## Issues Identified + +### Issue 1: SessionStart Hook Overload + +**Problem:** 7 hooks run on every session, regardless of whether the user will use that plugin. + +**Affected plugins:** +- projman +- pr-review +- claude-config-maintainer +- data-platform +- viz-platform +- cmdb-assistant +- contract-validator + +**Specific concerns:** +- `projman` makes HTTP calls to Gitea API to check open issues +- `cmdb-assistant` makes HTTP calls to NetBox API +- `data-platform` spawns Python and attempts PostgreSQL connection +- `contract-validator` computes MD5 hashes of all plugin files +- `viz-platform` just echoes "loaded" - zero value + +### Issue 2: Duplicate Logic Across Hooks + +**Problem:** Multiple hooks implement the same checks. + +| Check | Implemented by | +|-------|----------------| +| MCP venv exists | projman, pr-review, data-platform | +| Git remote vs .env mismatch | projman, pr-review | +| JSON stdin parsing | 8 different hooks | +| File path extraction from JSON | 8 different hooks | + +### Issue 3: Overly Broad Matchers + +**Problem:** Some hooks trigger far more often than needed. + +| Hook | Matcher | Problem | +|------|---------|---------| +| git-flow/branch-check.sh | `Bash` | Triggers on every bash command | +| git-flow/commit-msg-check.sh | `Bash` | Triggers on every bash command | +| project-hygiene/cleanup.sh | `Write\|Edit` | Runs `find` on entire project every edit | +| data-platform/schema-diff-check.sh | `Edit\|Write` | Checks every file, then pattern-matches | + +### Issue 4: clarity-assist Always-On + +**Problem:** `vagueness-check.sh` (217 lines) runs on every user prompt. + +- Parses prompt +- Runs multiple regex matches +- Uses `bc` for floating-point calculations +- Adds latency to every message + +**Current behavior:** Opt-out (runs unless `CLARITY_ASSIST_AUTO_SUGGEST=false`) +**Recommended:** Opt-in (disabled unless explicitly enabled) + +### Issue 5: No Shared Utilities + +**Problem:** Each hook implements its own: +- JSON parsing +- File path extraction +- Prefix output formatting +- Early exit conditions + +--- + +## Proposed Changes + +### Change 1: Consolidate SessionStart into Single Dispatcher + +**Create:** `scripts/hooks/session-dispatcher.sh` + +```bash +#!/bin/bash +# Single entry point for all SessionStart checks +# Runs common checks once, dispatches to plugins only when relevant + +# Common checks (run once) +check_marketplace_health() { ... } +check_mcp_venvs() { ... } +check_git_remote() { ... } + +# Plugin-specific checks (conditional) +if is_projman_project; then + source_plugin_check "projman" +fi +``` + +**Benefits:** +- Single process instead of 7 +- Common checks run once +- Plugin checks only run if relevant + +**Files to modify:** +- Create `scripts/hooks/session-dispatcher.sh` +- Create `scripts/hooks/lib/common.sh` (shared functions) +- Update all plugin `hooks.json` to remove SessionStart +- Add single SessionStart hook at marketplace level + +### Change 2: Add Path-Based Filtering to PostToolUse Hooks + +**Current:** Hooks spawn, parse stdin, check path, usually exit. + +**Proposed:** Check path relevance before detailed processing. + +```bash +# At top of each PostToolUse hook +FILE_PATH=$(echo "$INPUT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | ...) + +# Immediate exit for irrelevant paths +case "$FILE_PATH" in + */node_modules/*|*/.git/*|*/venv/*|*/__pycache__/*) + exit 0 ;; +esac +``` + +**Affected hooks:** +- doc-guardian/notify.sh +- data-platform/schema-diff-check.sh +- contract-validator/breaking-change-check.sh +- project-hygiene/cleanup.sh + +### Change 3: Smarter git-flow Bash Hooks + +**Current:** Both hooks trigger on every Bash command. + +**Option A:** Early command check before full parsing +```bash +# Quick check - if not git command, exit immediately +if ! echo "$INPUT" | grep -q '"command".*git'; then + exit 0 +fi +``` + +**Option B:** Combine into single hook +```bash +# Single git-flow hook that handles both branch and commit validation +``` + +**Files to modify:** +- `plugins/git-flow/hooks/branch-check.sh` +- `plugins/git-flow/hooks/commit-msg-check.sh` +- Optionally merge into `plugins/git-flow/hooks/git-validator.sh` + +### Change 4: Remove viz-platform SessionStart Hook + +**Current:** +```json +{ + "event": "SessionStart", + "type": "command", + "command": "echo 'viz-platform plugin loaded'" +} +``` + +**Proposed:** Delete entirely. Provides zero value. + +**Files to modify:** +- `plugins/viz-platform/hooks/hooks.json` - remove the hook + +### Change 5: Make clarity-assist Opt-In + +**Current:** Enabled by default, check `CLARITY_ASSIST_AUTO_SUGGEST=false` to disable. + +**Proposed:** Disabled by default, check `CLARITY_ASSIST_AUTO_SUGGEST=true` to enable. + +```bash +# Change from: +AUTO_SUGGEST="${CLARITY_ASSIST_AUTO_SUGGEST:-true}" + +# To: +AUTO_SUGGEST="${CLARITY_ASSIST_AUTO_SUGGEST:-false}" +``` + +**Files to modify:** +- `plugins/clarity-assist/hooks/vagueness-check.sh` (line 11) +- `plugins/clarity-assist/README.md` (document opt-in) + +### Change 6: Create Shared Hook Library + +**Create:** `scripts/hooks/lib/common.sh` + +```bash +#!/bin/bash +# Shared utilities for all hooks + +# Parse file_path from JSON stdin +extract_file_path() { + echo "$1" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | \ + head -1 | sed 's/.*"file_path"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' +} + +# Parse command from JSON stdin +extract_command() { + echo "$1" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('command',''))" 2>/dev/null +} + +# Standard prefix output +hook_output() { + local prefix="$1" + shift + echo "[$prefix] $*" +} + +# Check if path is in ignorable location +is_ignored_path() { + case "$1" in + */node_modules/*|*/.git/*|*/venv/*|*/__pycache__/*|*/.venv/*) + return 0 ;; + esac + return 1 +} +``` + +**Benefits:** +- Consistent behavior across hooks +- Single place to fix bugs +- Reduced code duplication + +### Change 7: Optimize project-hygiene Cleanup + +**Current:** Runs `find` across entire project on every edit. + +**Proposed:** +1. Only run cleanup after significant operations (not every edit) +2. Use more targeted paths +3. Add cooldown period (don't run if ran in last 5 minutes) + +```bash +# Add cooldown +LAST_RUN_FILE="/tmp/project-hygiene-last-run" +if [[ -f "$LAST_RUN_FILE" ]]; then + LAST_RUN=$(cat "$LAST_RUN_FILE") + NOW=$(date +%s) + if (( NOW - LAST_RUN < 300 )); then + exit 0 # Skip if ran in last 5 minutes + fi +fi +``` + +**Files to modify:** +- `plugins/project-hygiene/hooks/cleanup.sh` + +--- + +## Implementation Order + +### Phase 1: Quick Wins (Low effort, high impact) +1. Remove viz-platform SessionStart hook +2. Make clarity-assist opt-in +3. Add early exit to git-flow hooks + +### Phase 2: Optimizations (Medium effort) +4. Add path filtering to PostToolUse hooks +5. Add cooldown to project-hygiene +6. Create shared hook library + +### Phase 3: Architecture (Higher effort) +7. Consolidate SessionStart into dispatcher +8. Refactor all hooks to use shared library + +--- + +## Testing Plan + +### Before changes +- Measure session startup time (10 runs, average) +- Measure time to complete 10 file edits +- Count hook invocations via logging + +### After each phase +- Re-measure all metrics +- Verify no functionality lost +- Test on both dev machine and Raspberry Pi (hotport) + +### Expected improvements +- SessionStart: 200-500ms → 50-100ms (4-5x faster) +- Per-edit overhead: 100-200ms → 20-50ms (4x faster) +- Process spawns: 7 SessionStart + 5 per-edit → 1 SessionStart + 2-3 per-edit + +--- + +## Risks and Mitigations + +| Risk | Mitigation | +|------|------------| +| Breaking existing functionality | Comprehensive test plan, phase rollout | +| Shared library versioning | Keep library in marketplace root, plugins reference via relative path | +| User config migration (clarity-assist) | Document in CHANGELOG, mention in release notes | + +--- + +## Open Questions + +1. Should we support a `hooks.json` path matcher natively? (Would require Claude Code changes) +2. Should SessionStart hooks be lazy-loaded on first plugin command instead? +3. Is the shared library approach compatible with plugins being installed independently? + +--- + +## References + +- Analysis performed: 2026-01-28 +- Total hooks analyzed: 16 +- Total shell code: ~1,493 lines +- Plugins affected: 12 + +--- + +## Changelog + +| Date | Change | +|------|--------| +| 2026-01-28 | Initial RFC created |