diff --git a/.claude/hooks/trigger-word-checker.js b/.claude/hooks/trigger-word-checker.js new file mode 100755 index 00000000..0f887988 --- /dev/null +++ b/.claude/hooks/trigger-word-checker.js @@ -0,0 +1,34 @@ +#!/usr/bin/env node +/** + * Trigger Word Checker Hook + * + * Detects "ff" and "ffs" code words in user prompts and provides + * immediate instruction to Claude on how to handle them. + * + * This runs on EVERY user message to ensure triggers are never missed. + */ + +const input = JSON.parse(process.argv[2] || '{}'); +const userMessage = input.text || ''; + +// Normalize: trim whitespace, lowercase for matching +const normalized = userMessage.trim().toLowerCase(); + +// Check for "ffs" trigger (exact match or standalone word) +if (normalized === 'ffs' || /\bffs\b/.test(normalized)) { + console.log('\x1b[33m⚠️ CODE WORD DETECTED: "ffs"\x1b[0m'); + console.log('\x1b[36mClaude MUST run: node scripts/framework-stats.js\x1b[0m'); + console.log('\x1b[36mSee inst_082 and CLAUDE.md lines 66-88\x1b[0m'); + process.exit(0); +} + +// Check for "ff" prefix trigger +if (normalized.startsWith('ff ')) { + console.log('\x1b[33m⚠️ CODE WORD DETECTED: "ff"\x1b[0m'); + console.log('\x1b[36mClaude MUST run: node scripts/framework-audit-response.js --prompt "..." --type "boundary_question"\x1b[0m'); + console.log('\x1b[36mSee inst_078 and CLAUDE.md lines 48-64\x1b[0m'); + process.exit(0); +} + +// No trigger words found - continue normally +process.exit(0); diff --git a/.claude/settings.json b/.claude/settings.json index 6c00f6d8..f1a39195 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -11,6 +11,17 @@ } ] } + ], + "UserPromptSubmit": [ + { + "hooks": [ + { + "type": "command", + "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/trigger-word-checker.js", + "timeout": 2 + } + ] + } ] } } diff --git a/docs/TRIGGER_WORD_ENFORCEMENT.md b/docs/TRIGGER_WORD_ENFORCEMENT.md new file mode 100644 index 00000000..cde8f7cb --- /dev/null +++ b/docs/TRIGGER_WORD_ENFORCEMENT.md @@ -0,0 +1,88 @@ +# Trigger Word Enforcement Architecture + +## Problem +Claude failed to recognize "ffs" code word despite inst_082 being active. This was a **trigger recognition failure**, not a missing instruction issue. + +## Root Cause +- inst_082 (ffs trigger) exists and is marked active: true +- inst_078 (ff trigger) exists and is marked active: true +- Both are HIGH persistence, SYSTEM quadrant +- scripts/framework-stats.js and scripts/framework-audit-response.js both exist +- **BUT**: No architectural enforcement to ensure Claude checks for trigger words on EVERY user message + +## Solution +Created `.claude/hooks/trigger-word-checker.js` that runs on every user prompt submission: + +```javascript +// Detects: +// - "ffs" (exact match or word boundary) → framework-stats.js +// - "ff " (prefix) → framework-audit-response.js +``` + +Registered in `.claude/settings.json`: +```json +"UserPromptSubmit": [ + { + "hooks": [ + { + "type": "command", + "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/trigger-word-checker.js", + "timeout": 2 + } + ] + } +] +``` + +## How It Works + +1. **User types "ffs"** +2. Hook runs BEFORE Claude processes the message +3. Hook outputs: `⚠️ CODE WORD DETECTED: "ffs"` +4. Hook provides instruction: `Claude MUST run: node scripts/framework-stats.js` +5. Claude sees the hook output and executes the command + +## Testing + +```bash +# Test ffs trigger +node .claude/hooks/trigger-word-checker.js '{"text":"ffs"}' +# Output: ⚠️ CODE WORD DETECTED: "ffs" +# Claude MUST run: node scripts/framework-stats.js + +# Test ff trigger +node .claude/hooks/trigger-word-checker.js '{"text":"ff what are the boundary rules?"}' +# Output: ⚠️ CODE WORD DETECTED: "ff" +# Claude MUST run: node scripts/framework-audit-response.js --prompt "..." --type "boundary_question" + +# Test normal message (no output) +node .claude/hooks/trigger-word-checker.js '{"text":"please fix the bug"}' +# (silent - no trigger detected) +``` + +## Philosophy +**Governance is enforced architecturally, not documented.** + +Relying on voluntary compliance (Claude remembering to check for triggers) = framework fade. +Architectural enforcement (hook that runs on EVERY message) = reliable governance. + +## Files Modified +- `.claude/hooks/trigger-word-checker.js` - New hook script +- `.claude/settings.json` - Registered UserPromptSubmit hook + +## References +- inst_082: ffs trigger definition +- inst_078: ff trigger definition +- CLAUDE.md lines 48-64: ff documentation +- CLAUDE.md lines 66-88: ffs documentation + +## Future Enhancements +If Claude Code doesn't support UserPromptSubmit hooks natively: +1. Add to session-init.js output as prominent reminder +2. Create a PreToolUse hook that checks user's last message +3. Add to system prompt injection if hook system insufficient + +--- +**Created**: 2025-10-25 +**Issue**: Claude didn't recognize "ffs" code word +**Fix**: Architectural hook enforcement