From 0eab173c3b25001ded90e489bdbc2bd5e01d6138 Mon Sep 17 00:00:00 2001 From: TheFlow Date: Tue, 7 Oct 2025 01:18:32 +1300 Subject: [PATCH] feat: implement statistics tracking and missing methods in 3 governance services MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enhanced core Tractatus governance services with comprehensive statistics tracking, instruction management, and audit trail capabilities: **InstructionPersistenceClassifier (additions):** - Statistics tracking (total_classifications, by_quadrant, by_persistence, by_verification) - getStats() method for monitoring classification patterns - Automatic stat updates on each classify() call **CrossReferenceValidator (additions):** - Statistics tracking (total_validations, conflicts_detected, rejections, approvals, warnings) - Instruction history management (instructionHistory array, 100 item lookback window) - addInstruction() - Add classified instructions to history - getRecentInstructions() - Retrieve recent instructions with optional limit - clearInstructions() - Reset instruction history and cache - getStats() - Comprehensive validation statistics - Enhanced result objects with required_action field for test compatibility **BoundaryEnforcer (additions):** - Statistics tracking (total_enforcements, boundaries_violated, human_required_count, by_boundary) - Enhanced enforcement results with: * audit_record (timestamp, boundary_violated, action_attempted, enforcement_decision) * tractatus_section and principle fields * violated_boundaries array * boundary field for test assertions - getStats() method for monitoring boundary enforcement patterns - Automatic stat updates in all enforcement result methods Test Results: - Passing tests: 52/192 (27% pass rate, up from 30/192 - 73% improvement) - InstructionPersistenceClassifier: All singleton and stats tests passing - CrossReferenceValidator: Instruction management and stats tests passing - BoundaryEnforcer: Stats tracking and audit trail tests passing Remaining work: - ContextPressureMonitor needs: reset(), getPressureHistory(), recordError(), getStats() - MetacognitiveVerifier needs: enhanced verification checks and stats - ~140 tests still failing, mostly needing additional service enhancements The enhanced services now provide comprehensive visibility into governance operations through statistics and audit trails, essential for AI safety monitoring. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/services/BoundaryEnforcer.service.js | 47 ++++++++++++ .../CrossReferenceValidator.service.js | 74 +++++++++++++++++++ ...nstructionPersistenceClassifier.service.js | 41 ++++++++++ 3 files changed, 162 insertions(+) diff --git a/src/services/BoundaryEnforcer.service.js b/src/services/BoundaryEnforcer.service.js index a9d5cf89..c66ba5ae 100644 --- a/src/services/BoundaryEnforcer.service.js +++ b/src/services/BoundaryEnforcer.service.js @@ -132,6 +132,22 @@ class BoundaryEnforcer { // Compile boundary patterns this.boundaryPatterns = this._compileBoundaryPatterns(); + // Statistics tracking + this.stats = { + total_enforcements: 0, + boundaries_violated: 0, + human_required_count: 0, + allowed_count: 0, + by_boundary: { + VALUES: 0, + INNOVATION: 0, + WISDOM: 0, + PURPOSE: 0, + MEANING: 0, + AGENCY: 0 + } + }; + logger.info('BoundaryEnforcer initialized with Tractatus constraints'); } @@ -314,19 +330,36 @@ class BoundaryEnforcer { } _requireHumanJudgment(violations, action) { + this.stats.total_enforcements++; + this.stats.boundaries_violated++; + this.stats.human_required_count++; + const primaryViolation = violations[0]; + if (primaryViolation.boundary && this.stats.by_boundary[primaryViolation.boundary] !== undefined) { + this.stats.by_boundary[primaryViolation.boundary]++; + } return { allowed: false, humanRequired: true, requirementType: 'MANDATORY', reason: 'TRACTATUS_BOUNDARY_VIOLATION', + boundary: primaryViolation.boundary, + tractatus_section: primaryViolation.section, + principle: primaryViolation.principle, message: `This decision crosses Tractatus boundary ${primaryViolation.section}: ` + `"${primaryViolation.principle}"`, violations, + violated_boundaries: violations.map(v => v.boundary), action: 'REQUIRE_HUMAN_DECISION', recommendation: 'Present options to human for decision', userPrompt: this._generateBoundaryPrompt(violations, action), + audit_record: { + timestamp: new Date(), + boundary_violated: primaryViolation.boundary, + action_attempted: action.type || action.description, + enforcement_decision: 'BLOCKED' + }, timestamp: new Date() }; } @@ -362,6 +395,9 @@ class BoundaryEnforcer { } _allowAction(action, domain) { + this.stats.total_enforcements++; + this.stats.allowed_count++; + return { allowed: true, humanRequired: false, @@ -391,6 +427,17 @@ class BoundaryEnforcer { `Reason: ${reason}\n\n` + `Do you approve this action?`; } + + /** + * Get enforcement statistics + * @returns {Object} Statistics object + */ + getStats() { + return { + ...this.stats, + timestamp: new Date() + }; + } } // Singleton instance diff --git a/src/services/CrossReferenceValidator.service.js b/src/services/CrossReferenceValidator.service.js index 9c1c0c90..57967df4 100644 --- a/src/services/CrossReferenceValidator.service.js +++ b/src/services/CrossReferenceValidator.service.js @@ -40,6 +40,22 @@ class CrossReferenceValidator { this.lookbackWindow = 100; // How many recent messages to check this.relevanceThreshold = 0.4; // Minimum relevance to consider this.instructionCache = new Map(); // Cache classified instructions + this.instructionHistory = []; // Recent instruction history + + // Statistics tracking + this.stats = { + total_validations: 0, + conflicts_detected: 0, + rejections: 0, + approvals: 0, + warnings: 0, + by_severity: { + CRITICAL: 0, + WARNING: 0, + MINOR: 0, + INFO: 0 + } + }; logger.info('CrossReferenceValidator initialized'); } @@ -297,6 +313,9 @@ class CrossReferenceValidator { } _approvedResult(message, conflicts = []) { + this.stats.total_validations++; + this.stats.approvals++; + return { status: VALIDATION_STATUS.APPROVED, message, @@ -307,6 +326,11 @@ class CrossReferenceValidator { } _warningResult(conflicts, action) { + this.stats.total_validations++; + this.stats.warnings++; + this.stats.conflicts_detected += conflicts.length; + conflicts.forEach(c => this.stats.by_severity[c.severity]++); + const primaryConflict = conflicts[0]; const timeAgo = this._formatTimeAgo(primaryConflict.instruction.timestamp); @@ -323,6 +347,11 @@ class CrossReferenceValidator { } _rejectedResult(conflicts, action) { + this.stats.total_validations++; + this.stats.rejections++; + this.stats.conflicts_detected += conflicts.length; + conflicts.forEach(c => this.stats.by_severity[c.severity]++); + const primaryConflict = conflicts[0]; const timeAgo = this._formatTimeAgo(primaryConflict.instruction.timestamp); @@ -333,6 +362,7 @@ class CrossReferenceValidator { `'${primaryConflict.instructionValue}' ${timeAgo} ago`, conflicts, action: 'REQUEST_CLARIFICATION', + required_action: 'REQUEST_CLARIFICATION', recommendation: `Verify with user before proceeding`, instructionQuote: primaryConflict.instruction.text, requiredValue: primaryConflict.instructionValue, @@ -361,6 +391,50 @@ class CrossReferenceValidator { if (seconds < 86400) return `${Math.floor(seconds / 3600)} hours`; return `${Math.floor(seconds / 86400)} days`; } + + /** + * Add instruction to history + * @param {Object} instruction - Classified instruction + */ + addInstruction(instruction) { + // Add to beginning of array (most recent first) + this.instructionHistory.unshift(instruction); + + // Keep only lookbackWindow instructions + if (this.instructionHistory.length > this.lookbackWindow) { + this.instructionHistory = this.instructionHistory.slice(0, this.lookbackWindow); + } + } + + /** + * Get recent instructions + * @param {number} limit - Optional limit on number of instructions + * @returns {Array} Recent instructions + */ + getRecentInstructions(limit = this.lookbackWindow) { + return this.instructionHistory.slice(0, limit); + } + + /** + * Clear instruction history + */ + clearInstructions() { + this.instructionHistory = []; + this.instructionCache.clear(); + } + + /** + * Get validation statistics + * @returns {Object} Statistics object + */ + getStats() { + return { + ...this.stats, + instruction_history_size: this.instructionHistory.length, + cache_size: this.instructionCache.size, + timestamp: new Date() + }; + } } // Singleton instance diff --git a/src/services/InstructionPersistenceClassifier.service.js b/src/services/InstructionPersistenceClassifier.service.js index 7a192766..f4d47dae 100644 --- a/src/services/InstructionPersistenceClassifier.service.js +++ b/src/services/InstructionPersistenceClassifier.service.js @@ -105,6 +105,30 @@ class InstructionPersistenceClassifier { // Compile keyword patterns for efficient matching this.keywordPatterns = this._compileKeywordPatterns(); + // Statistics tracking + this.stats = { + total_classifications: 0, + by_quadrant: { + STRATEGIC: 0, + OPERATIONAL: 0, + TACTICAL: 0, + SYSTEM: 0, + STOCHASTIC: 0 + }, + by_persistence: { + HIGH: 0, + MEDIUM: 0, + LOW: 0, + VARIABLE: 0 + }, + by_verification: { + MANDATORY: 0, + REQUIRED: 0, + RECOMMENDED: 0, + OPTIONAL: 0 + } + }; + logger.info('InstructionPersistenceClassifier initialized'); } @@ -173,6 +197,12 @@ class InstructionPersistenceClassifier { } }; + // Track statistics + this.stats.total_classifications++; + this.stats.by_quadrant[quadrant]++; + this.stats.by_persistence[persistence]++; + this.stats.by_verification[verification]++; + logger.debug('Instruction classified', { text: text.substring(0, 50), quadrant, @@ -441,6 +471,17 @@ class InstructionPersistenceClassifier { } }; } + + /** + * Get classification statistics + * @returns {Object} Statistics object + */ + getStats() { + return { + ...this.stats, + timestamp: new Date() + }; + } } // Singleton instance