#!/usr/bin/env node /** * Framework Statistics Reporter * Displays comprehensive framework statistics for current session * * Triggered by "ffs" (Full Framework Stats) codeword * * Reports: * - Session context pressure and token usage * - Framework service invocation counts * - Recent audit log entries (last 10) * - Active instruction statistics * - Service health/initialization status */ const mongoose = require('mongoose'); const path = require('path'); const fs = require('fs'); // Load environment require('dotenv').config(); // Framework services const BoundaryEnforcer = require('../src/services/BoundaryEnforcer.service'); const MetacognitiveVerifier = require('../src/services/MetacognitiveVerifier.service'); const ContextPressureMonitor = require('../src/services/ContextPressureMonitor.service'); const CrossReferenceValidator = require('../src/services/CrossReferenceValidator.service'); const InstructionPersistenceClassifier = require('../src/services/InstructionPersistenceClassifier.service'); const PluralisticDeliberationOrchestrator = require('../src/services/PluralisticDeliberationOrchestrator.service'); async function getSessionStats() { const sessionStatePath = path.join(__dirname, '../.claude/session-state.json'); if (fs.existsSync(sessionStatePath)) { const sessionState = JSON.parse(fs.readFileSync(sessionStatePath, 'utf8')); // Extract pressure monitoring data const pressureData = sessionState.last_framework_activity?.ContextPressureMonitor; // Extract auto-compact events const autoCompacts = sessionState.auto_compact_events || []; // Extract component statistics const componentStats = sessionState.framework_components || {}; return { ...sessionState, pressureMonitoring: pressureData, autoCompactEvents: autoCompacts, componentStatistics: componentStats }; } return null; } async function getTokenCheckpoints() { const checkpointPath = path.join(__dirname, '../.claude/token-checkpoints.json'); if (fs.existsSync(checkpointPath)) { return JSON.parse(fs.readFileSync(checkpointPath, 'utf8')); } return null; } async function getInstructionStats() { const instructionPath = path.join(__dirname, '../.claude/instruction-history.json'); if (fs.existsSync(instructionPath)) { const history = JSON.parse(fs.readFileSync(instructionPath, 'utf8')); const active = history.instructions.filter(i => i.active); const byQuadrant = active.reduce((acc, i) => { acc[i.quadrant] = (acc[i.quadrant] || 0) + 1; return acc; }, {}); const byPersistence = active.reduce((acc, i) => { acc[i.persistence] = (acc[i.persistence] || 0) + 1; return acc; }, {}); return { total: history.instructions.length, active: active.length, inactive: history.instructions.length - active.length, byQuadrant, byPersistence, version: history.version, lastUpdated: history.last_updated }; } return null; } async function getAuditLogStats() { try { const db = require('../src/utils/db.util'); const collection = await db.getCollection('auditLogs'); // Get total count const total = await collection.countDocuments(); // Get counts by service const byService = await collection.aggregate([ { $group: { _id: '$service', count: { $sum: 1 } } }, { $sort: { count: -1 } } ]).toArray(); // Get recent entries (last 10) const recent = await collection.find() .sort({ timestamp: -1 }) .limit(10) .toArray(); // Get today's count const todayStart = new Date(); todayStart.setHours(0, 0, 0, 0); const todayCount = await collection.countDocuments({ timestamp: { $gte: todayStart } }); return { total, todayCount, byService: byService.reduce((acc, s) => { acc[s._id] = s.count; return acc; }, {}), recent: recent.map(r => ({ service: r.service, action: r.action, decision: r.decision, timestamp: r.timestamp, sessionId: r.context?.sessionId })) }; } catch (error) { console.error('Error fetching audit logs:', error.message); return null; } } async function main() { try { // Parse command-line arguments const args = process.argv.slice(2); const tokensArg = args.find(arg => arg.startsWith('--tokens=')); let currentTokens = null; let tokenBudget = null; if (tokensArg) { const tokensValue = tokensArg.split('=')[1]; const [current, budget] = tokensValue.split('/').map(t => parseInt(t.trim())); if (!isNaN(current) && !isNaN(budget)) { currentTokens = current; tokenBudget = budget; } } // Connect to MongoDB await mongoose.connect('mongodb://localhost:27017/tractatus_dev', { serverSelectionTimeoutMS: 2000 }); // Initialize framework services await BoundaryEnforcer.initialize(); await MetacognitiveVerifier.initialize(); await ContextPressureMonitor.initialize('framework-stats'); await CrossReferenceValidator.initialize(); await InstructionPersistenceClassifier.initialize(); await PluralisticDeliberationOrchestrator.initialize(); // Gather statistics const [sessionStats, tokenCheckpoints, instructionStats, auditStats] = await Promise.all([ getSessionStats(), getTokenCheckpoints(), getInstructionStats(), getAuditLogStats() ]); // Get current pressure stats const monitorStats = ContextPressureMonitor.getStats(); const pressureHistory = ContextPressureMonitor.getPressureHistory(); const latestPressure = pressureHistory && pressureHistory.length > 0 ? pressureHistory[pressureHistory.length - 1] : null; // Calculate real-time pressure if tokens provided let realTimePressure = null; if (currentTokens !== null && tokenBudget !== null) { realTimePressure = await ContextPressureMonitor.analyzePressure({ tokenUsage: currentTokens, tokenBudget: tokenBudget, messageCount: 1 }); } // Build report const report = { timestamp: new Date().toISOString(), session: sessionStats ? { sessionId: sessionStats.session_id, startTime: sessionStats.started, messageCount: sessionStats.message_count, tokenEstimate: sessionStats.token_estimate, actionCount: sessionStats.action_count, lastUpdated: sessionStats.last_updated, initialized: sessionStats.initialized } : null, tokenUsage: tokenCheckpoints ? { budget: tokenCheckpoints.tokenBudget, checkpoints: tokenCheckpoints.checkpoints, nextCheckpoint: tokenCheckpoints.checkpoints.find(c => !c.reached) } : null, contextPressure: realTimePressure ? { level: realTimePressure.level?.name || 'NORMAL', score: Math.round((realTimePressure.overall_score || 0) * 1000) / 10, tokenCount: currentTokens, tokenBudget: tokenBudget, source: 'real-time', timestamp: new Date().toISOString(), metrics: realTimePressure.metrics } : (sessionStats?.pressureMonitoring ? { level: sessionStats.pressureMonitoring.last_level || 'UNKNOWN', score: sessionStats.pressureMonitoring.last_score || 0, lastChecked: sessionStats.pressureMonitoring.timestamp, messageNumber: sessionStats.pressureMonitoring.message, tokenCount: sessionStats.pressureMonitoring.tokens, source: 'cached' } : (latestPressure ? { level: latestPressure.pressureLevel?.name || 'UNKNOWN', score: latestPressure.overallScore, timestamp: latestPressure.timestamp, metrics: latestPressure.metrics, source: 'history' } : (monitorStats ? { level: 'UNKNOWN', score: 0, stats: monitorStats, source: 'stats' } : null))), autoCompacts: sessionStats?.autoCompactEvents ? { total: sessionStats.autoCompactEvents.length, events: sessionStats.autoCompactEvents.map(e => ({ timestamp: e.timestamp, beforeTokens: e.before_tokens, afterTokens: e.after_tokens, reduction: e.reduction_percent, messageNumber: e.message_number, pressureBefore: e.pressure_before, pressureAfter: e.pressure_after })) } : { total: 0, events: [] }, componentStats: sessionStats?.componentStatistics ? Object.entries(sessionStats.componentStatistics).map(([name, stats]) => ({ name, validations: stats.validations_performed, blocks: stats.blocks_issued, lastActivity: stats.last_validation, tokenCount: stats.tokens })) : [], instructions: instructionStats, auditLogs: auditStats ? { total: auditStats.total, today: auditStats.todayCount, byService: auditStats.byService, recentCount: auditStats.recent.length } : null, frameworkServices: { BoundaryEnforcer: 'ACTIVE', MetacognitiveVerifier: 'ACTIVE', ContextPressureMonitor: 'ACTIVE', CrossReferenceValidator: 'ACTIVE', InstructionPersistenceClassifier: 'ACTIVE', PluralisticDeliberationOrchestrator: 'ACTIVE' } }; // Output formatted report console.log('\n╔════════════════════════════════════════════════════════════════╗'); console.log('║ TRACTATUS FRAMEWORK STATISTICS (ffs) ║'); console.log('╚════════════════════════════════════════════════════════════════╝\n'); // Session Info if (report.session) { console.log('📊 SESSION'); console.log(` Session ID: ${report.session.sessionId}`); console.log(` Start Time: ${new Date(report.session.startTime).toLocaleString()}`); console.log(` Message Count: ${report.session.messageCount}`); console.log(` Token Estimate: ${report.session.tokenEstimate?.toLocaleString() || 'N/A'}`); console.log(` Action Count: ${report.session.actionCount || 0}`); console.log(` Last Updated: ${new Date(report.session.lastUpdated).toLocaleString()}`); console.log(` Initialized: ${report.session.initialized ? 'Yes' : 'No'}`); console.log(); } // Token Usage if (report.tokenUsage && report.tokenUsage.budget) { const next = report.tokenUsage.nextCheckpoint; console.log('🎯 TOKEN BUDGET'); console.log(` Total Budget: ${report.tokenUsage.budget.toLocaleString()}`); if (next) { console.log(` Next Checkpoint: ${next.threshold.toLocaleString()} (${next.percentage}%)`); } const reached = report.tokenUsage.checkpoints.filter(c => c.reached).length; console.log(` Checkpoints: ${reached}/${report.tokenUsage.checkpoints.length} reached`); console.log(); } // Context Pressure if (report.contextPressure) { console.log('⚠️ CONTEXT PRESSURE'); console.log(` Level: ${report.contextPressure.level}`); console.log(` Overall Score: ${report.contextPressure.score}%`); console.log(` Data Source: ${report.contextPressure.source || 'unknown'}`); if (report.contextPressure.source === 'cached') { console.log(' ⚠️ WARNING: Showing cached data. Use --tokens=/ for real-time.'); } if (report.contextPressure.tokenCount) { console.log(` Token Count: ${report.contextPressure.tokenCount?.toLocaleString()}`); } if (report.contextPressure.tokenBudget) { console.log(` Token Budget: ${report.contextPressure.tokenBudget?.toLocaleString()}`); const percentUsed = ((report.contextPressure.tokenCount / report.contextPressure.tokenBudget) * 100).toFixed(1); console.log(` Tokens Used: ${percentUsed}%`); } if (report.contextPressure.lastChecked) { console.log(` Last Checked: ${new Date(report.contextPressure.lastChecked).toLocaleString()}`); console.log(` At Message: #${report.contextPressure.messageNumber}`); } if (report.contextPressure.timestamp && report.contextPressure.source !== 'cached') { console.log(` Calculated: ${new Date(report.contextPressure.timestamp).toLocaleString()}`); } if (report.contextPressure.metrics) { console.log(' Metrics:'); Object.entries(report.contextPressure.metrics).forEach(([metric, data]) => { if (data && typeof data === 'object' && 'normalized' in data) { console.log(` • ${metric}: ${(data.normalized * 100).toFixed(1)}%`); } }); } if (report.contextPressure.stats) { console.log(' Analysis Count:', report.contextPressure.stats.analysis_count); } console.log(); } // Degradation Score (NEW) if (realTimePressure && realTimePressure.degradation !== undefined) { console.log('⚠️ DEGRADATION ANALYSIS'); console.log(` Score: ${realTimePressure.degradation}%`); console.log(` Level: ${realTimePressure.degradationLevel}`); if (realTimePressure.degradationBreakdown) { console.log(' Breakdown:'); console.log(` • Error patterns: ${realTimePressure.degradationBreakdown.errorPattern}%`); console.log(` • Framework fade: ${realTimePressure.degradationBreakdown.frameworkFade}%${realTimePressure.degradationBreakdown.frameworkFade >= 50 ? ' ← CRITICAL' : ''}`); console.log(` • Context quality: ${realTimePressure.degradationBreakdown.contextQuality}%`); console.log(` • Behavioral: ${realTimePressure.degradationBreakdown.behavioral}%`); console.log(` • Task completion: ${realTimePressure.degradationBreakdown.taskCompletion}%`); } if (realTimePressure.degradationRecommendation) { console.log(` Recommendation: ${realTimePressure.degradationRecommendation}`); } console.log(); } // Auto-Compact Events if (report.autoCompacts) { console.log('🔄 AUTO-COMPACT EVENTS'); console.log(` Total Compactions: ${report.autoCompacts.total}`); if (report.autoCompacts.total > 0) { console.log('\n Recent Compactions:'); report.autoCompacts.events.slice(-5).forEach((event, idx) => { console.log(`\n ${idx + 1}. ${new Date(event.timestamp).toLocaleString()}`); console.log(` Message #${event.messageNumber}`); console.log(` Tokens: ${event.beforeTokens?.toLocaleString()} → ${event.afterTokens?.toLocaleString()} (${event.reduction}% reduction)`); if (event.pressureBefore) { console.log(` Pressure: ${event.pressureBefore} → ${event.pressureAfter}`); } }); } else { console.log(' No auto-compaction events recorded yet.'); console.log(' (Framework will log compactions as they occur)'); } console.log(); } // Component Statistics if (report.componentStats && report.componentStats.length > 0) { console.log('🔧 COMPONENT STATISTICS'); report.componentStats.forEach(comp => { console.log(`\n ${comp.name}:`); console.log(` Validations: ${comp.validations?.toLocaleString() || 'N/A'}`); if (comp.blocks !== undefined) { console.log(` Blocks Issued: ${comp.blocks}`); } if (comp.lastActivity) { console.log(` Last Active: ${new Date(comp.lastActivity).toLocaleString()}`); } }); console.log(); } // Instruction Stats if (report.instructions) { console.log('📋 INSTRUCTIONS'); console.log(` Total: ${report.instructions.total}`); console.log(` Active: ${report.instructions.active}`); console.log(` Inactive: ${report.instructions.inactive}`); console.log(` Version: ${report.instructions.version}`); console.log(' By Quadrant:'); Object.entries(report.instructions.byQuadrant).forEach(([quad, count]) => { console.log(` • ${quad}: ${count}`); }); console.log(' By Persistence:'); Object.entries(report.instructions.byPersistence).forEach(([pers, count]) => { console.log(` • ${pers}: ${count}`); }); console.log(); } // Audit Logs if (report.auditLogs) { console.log('📝 AUDIT LOGS'); console.log(` Total Decisions: ${report.auditLogs.total}`); console.log(` Today: ${report.auditLogs.today}`); console.log(' By Service:'); Object.entries(report.auditLogs.byService) .sort((a, b) => b[1] - a[1]) .forEach(([service, count]) => { console.log(` • ${service}: ${count}`); }); console.log(); } // Framework Services console.log('🔧 FRAMEWORK SERVICES'); Object.entries(report.frameworkServices).forEach(([service, status]) => { const icon = status === 'ACTIVE' ? '✓' : '✗'; console.log(` ${icon} ${service}: ${status}`); }); console.log(); console.log('╚════════════════════════════════════════════════════════════════╝\n'); // Also output JSON for programmatic access console.log('\n// JSON OUTPUT FOR PROGRAMMATIC ACCESS:'); console.log(JSON.stringify(report, null, 2)); await mongoose.disconnect(); process.exit(0); } catch (error) { console.error('Error generating framework statistics:', error); await mongoose.disconnect(); process.exit(1); } } main();