#!/usr/bin/env node /** * Framework Integration Hook * * Automatically invokes framework services during Claude Code tool execution. * This hook runs on every tool use and routes to appropriate framework services. * * Integrated Services: * - BoundaryEnforcer: Security, architectural, cross-project boundaries * - ContextPressureMonitor: Token/message pressure tracking * - CrossReferenceValidator: Instruction compliance validation * - MetacognitiveVerifier: Decision reasoning verification * - InstructionPersistenceClassifier: New instruction classification * - PluralisticDeliberationOrchestrator: Value conflict deliberation */ const path = require('path'); const fs = require('fs'); // Parse command line arguments const args = process.argv.slice(2); const toolName = args[0]; // 'Edit', 'Write', 'Read', 'Bash', etc. const toolArgsJson = args[1]; // JSON string of tool arguments // Exit early if no args (allow execution) if (!toolName || !toolArgsJson) { process.exit(0); } let toolArgs; try { toolArgs = JSON.parse(toolArgsJson); } catch (err) { // Invalid JSON, allow execution process.exit(0); } /** * Main framework integration logic */ async function integrateFramework() { const mongoose = require('mongoose'); // Connect to MongoDB try { await mongoose.connect('mongodb://localhost:27017/tractatus_dev', { serverSelectionTimeoutMS: 2000 }); } catch (err) { // MongoDB not available, skip framework (allow execution) process.exit(0); } // Import framework services const BoundaryEnforcer = require('../../src/services/BoundaryEnforcer.service'); const ContextPressureMonitor = require('../../src/services/ContextPressureMonitor.service'); const CrossReferenceValidator = require('../../src/services/CrossReferenceValidator.service'); const MetacognitiveVerifier = require('../../src/services/MetacognitiveVerifier.service'); const sessionId = 'claude-code-session-' + new Date().toISOString().split('T')[0]; try { // Route to appropriate framework service based on tool switch (toolName) { case 'Edit': case 'Write': await handleFileModification(toolArgs, sessionId); break; case 'Bash': await handleBashCommand(toolArgs, sessionId); break; case 'Read': await handleFileRead(toolArgs, sessionId); break; default: // Unknown tool, allow execution break; } await mongoose.disconnect(); process.exit(0); // Allow execution } catch (err) { console.error('[Framework Hook] Error:', err.message); await mongoose.disconnect(); // If framework service blocks, exit with code 1 if (err.blocked) { process.exit(1); // Block execution } process.exit(0); // Allow execution on errors } } /** * Handle file modifications (Edit, Write tools) */ async function handleFileModification(args, sessionId) { const BoundaryEnforcer = require('../../src/services/BoundaryEnforcer.service'); const CrossReferenceValidator = require('../../src/services/CrossReferenceValidator.service'); const MetacognitiveVerifier = require('../../src/services/MetacognitiveVerifier.service'); const filePath = args.file_path || args.path || 'unknown'; const content = args.new_string || args.content || ''; // Check boundaries const boundaryContext = { sessionId, action: 'file_modification', target: filePath, description: `Modify ${path.basename(filePath)}`, metadata: { tool: 'Edit/Write', contentLength: content.length } }; try { await BoundaryEnforcer.checkBoundaries(boundaryContext); } catch (err) { if (err.message.includes('boundary')) { throw { blocked: true, reason: err.message }; } } // Validate against instructions (if modifying governance files) const governanceFiles = ['CLAUDE.md', 'instruction-history.json', 'auth.middleware.js', 'auth.controller.js']; const isGovernanceFile = governanceFiles.some(f => filePath.includes(f)); if (isGovernanceFile) { await CrossReferenceValidator.validateAgainstInstructions({ sessionId, action: 'modify_governance_file', description: `Modifying ${path.basename(filePath)}`, context: { file: filePath } }); } // Metacognitive verification for security-critical files const securityFiles = ['auth', 'security', 'credential', 'jwt', 'password']; const isSecurityFile = securityFiles.some(keyword => filePath.toLowerCase().includes(keyword)); if (isSecurityFile) { await MetacognitiveVerifier.verifyDecision({ sessionId, action: 'modify_security_file', reasoning: `Modifying security-critical file: ${filePath}`, context: { file: filePath, security_impact: true, requires_approval: true } }); } } /** * Handle Bash command execution */ async function handleBashCommand(args, sessionId) { const BoundaryEnforcer = require('../../src/services/BoundaryEnforcer.service'); const command = args.command || ''; // Check for cross-project commands const crossProjectPatterns = ['/family-history/', '/sydigital/', 'cd ../']; const isCrossProject = crossProjectPatterns.some(pattern => command.includes(pattern)); if (isCrossProject) { await BoundaryEnforcer.checkBoundaries({ sessionId, action: 'bash_command', target: command, description: 'Cross-project bash command', metadata: { command: command.substring(0, 100) } }); } } /** * Handle file reads */ async function handleFileRead(args, sessionId) { // File reads are generally allowed, just track context pressure const ContextPressureMonitor = require('../../src/services/ContextPressureMonitor.service'); // Update pressure tracking (passive monitoring) // This doesn't block, just logs try { const sessionState = JSON.parse( fs.readFileSync(path.join(__dirname, '../../.claude/session-state.json'), 'utf8') ); await ContextPressureMonitor.analyzeContext({ sessionId, tokens: sessionState.token_estimate || 0, budget: 200000, messages: sessionState.message_count || 0 }); } catch (err) { // Ignore pressure monitoring errors } } // Run integration integrateFramework().catch(err => { console.error('[Framework Hook] Fatal error:', err.message); process.exit(0); // Allow execution on fatal errors });