#!/usr/bin/env node /** * Framework Audit for Conversational Responses * * Invokes Tractatus framework services for conversational interactions * that don't trigger tool usage (Edit/Write/Bash). * * Triggered by: User prompt prefixed with "ff" or "fff" * * Usage: * node scripts/framework-audit-response.js \ * --prompt "Should we disable rate limiting?" \ * --type "boundary_question" \ * --response "full response text..." * * Returns: JSON with audit IDs */ const mongoose = require('mongoose'); const path = require('path'); // Parse CLI arguments function parseArgs() { const args = process.argv.slice(2); const parsed = {}; for (let i = 0; i < args.length; i += 2) { const key = args[i].replace(/^--/, ''); const value = args[i + 1]; parsed[key] = value; } return parsed; } /** * Main audit logic */ async function main() { const args = parseArgs(); const { prompt, type, response } = args; if (!prompt) { console.error('Error: --prompt required'); process.exit(1); } // Connect to MongoDB try { await mongoose.connect('mongodb://localhost:27017/tractatus_dev', { serverSelectionTimeoutMS: 2000 }); } catch (err) { console.error('MongoDB connection failed:', err.message); process.exit(1); } // Import all 6 framework services const BoundaryEnforcer = require('../src/services/BoundaryEnforcer.service'); const CrossReferenceValidator = require('../src/services/CrossReferenceValidator.service'); const MetacognitiveVerifier = require('../src/services/MetacognitiveVerifier.service'); const ContextPressureMonitor = require('../src/services/ContextPressureMonitor.service'); const InstructionPersistenceClassifier = require('../src/services/InstructionPersistenceClassifier.service'); const PluralisticDeliberationOrchestrator = require('../src/services/PluralisticDeliberationOrchestrator.service'); // Initialize services const sessionId = `ff-audit-${Date.now()}`; await BoundaryEnforcer.initialize(); await CrossReferenceValidator.initialize(); await MetacognitiveVerifier.initialize(); await ContextPressureMonitor.initialize(sessionId); await InstructionPersistenceClassifier.initialize(); await PluralisticDeliberationOrchestrator.initialize(); const auditIds = []; const decisions = []; // 1. BoundaryEnforcer - Check for VALUES/INNOVATION/WISDOM boundaries const boundaryKeywords = { VALUES: ['should we', 'better to', 'right to', 'worth', 'prioritize', 'trade-off', 'balance'], INNOVATION: ['new architecture', 'redesign', 'refactor entire', 'switch to', 'migrate to'], WISDOM: ['strategic', 'direction', 'long-term', 'vision', 'mission'], PURPOSE: ['why are we', 'goal is', 'trying to achieve'], AGENCY: ['automatically', 'without asking', 'on your behalf'] }; let detectedBoundaries = []; const promptLower = prompt.toLowerCase(); for (const [boundary, keywords] of Object.entries(boundaryKeywords)) { if (keywords.some(kw => promptLower.includes(kw))) { detectedBoundaries.push(boundary); } } if (detectedBoundaries.length > 0) { const action = { type: 'conversational_decision', description: `User prompt: ${prompt.substring(0, 100)}`, boundaries: detectedBoundaries, prompt: prompt }; const context = { sessionId, tool: 'conversation', type: type || 'unknown', trigger: 'ff_codeword' }; const result = BoundaryEnforcer.enforce(action, context); decisions.push({ service: 'BoundaryEnforcer', allowed: result.allowed, message: result.message, boundaries: detectedBoundaries }); } // 2. PluralisticDeliberationOrchestrator - Check for value conflicts const valueConflictKeywords = [ 'security vs performance', 'privacy vs convenience', 'speed vs safety', 'cost vs quality', 'accessibility vs', 'disable' ]; const hasValueConflict = valueConflictKeywords.some(kw => promptLower.includes(kw)); if (hasValueConflict || detectedBoundaries.includes('VALUES')) { const decision = { type: 'conversational_value_conflict', description: prompt, user_prompt: prompt }; const context = { sessionId, trigger: 'ff_codeword', boundaries: detectedBoundaries }; const result = PluralisticDeliberationOrchestrator.analyzeConflict(decision, context); decisions.push({ service: 'PluralisticDeliberationOrchestrator', frameworks: result.frameworks || [], stakeholders: result.stakeholders || [], urgency: result.urgency || 'UNKNOWN' }); } // 3. MetacognitiveVerifier - Verify reasoning quality if (response) { const action = { type: 'conversational_response', description: `Responding to: ${prompt.substring(0, 100)}`, user_prompt: prompt }; const reasoning = response.substring(0, 500); const context = { sessionId, trigger: 'ff_codeword', boundaries: detectedBoundaries, has_value_conflict: hasValueConflict }; const result = MetacognitiveVerifier.verify(action, reasoning, context); decisions.push({ service: 'MetacognitiveVerifier', decision: result.decision, confidence: result.confidence, issues: result.issues || [] }); } // 4. CrossReferenceValidator - Check against instruction history const instructionAction = { type: 'conversational_decision', description: prompt, user_prompt: prompt }; const validationResult = CrossReferenceValidator.validate(instructionAction, { sessionId, trigger: 'ff_codeword' }); decisions.push({ service: 'CrossReferenceValidator', conflicts: validationResult.conflicts || [], relevant_instructions: validationResult.relevantInstructions || [] }); // 5. ContextPressureMonitor - Update pressure metrics ContextPressureMonitor.analyzePressure({ sessionId, tool: 'conversation', action: 'ff_audit', prompt: prompt.substring(0, 100) }); decisions.push({ service: 'ContextPressureMonitor', status: 'analyzed' }); // 6. InstructionPersistenceClassifier - Classify if this creates new instruction const newInstructionKeywords = ['always', 'never', 'from now on', 'going forward', 'make sure']; const createsInstruction = newInstructionKeywords.some(kw => promptLower.includes(kw)); if (createsInstruction) { const classification = InstructionPersistenceClassifier.classify({ text: prompt, context: { sessionId, trigger: 'ff_codeword', type: 'user_prompt' }, timestamp: new Date(), source: 'conversation' }); decisions.push({ service: 'InstructionPersistenceClassifier', quadrant: classification.quadrant, persistence: classification.persistence, verification: classification.verificationRequirement }); } // Wait for async logging await new Promise(resolve => setTimeout(resolve, 500)); // Fetch audit IDs from recent logs const AuditLog = mongoose.model('AuditLog'); const recentLogs = await AuditLog.find({ sessionId, timestamp: { $gt: new Date(Date.now() - 5000) } }).select('_id service action').sort({ timestamp: -1 }); await mongoose.disconnect(); // Output results const output = { success: true, sessionId, auditCount: recentLogs.length, auditIds: recentLogs.map(log => log._id.toString()), decisions, servicesInvoked: [...new Set(recentLogs.map(log => log.service))], summary: { boundaries_detected: detectedBoundaries, value_conflict: hasValueConflict, creates_instruction: createsInstruction, services_count: decisions.length } }; console.log(JSON.stringify(output, null, 2)); process.exit(0); } main().catch(err => { console.error('Fatal error:', err.message); console.error(err.stack); process.exit(1); });