feat: implement statistics tracking and missing methods in 3 governance services
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 <noreply@anthropic.com>
This commit is contained in:
parent
e8cc023a05
commit
0eab173c3b
3 changed files with 162 additions and 0 deletions
|
|
@ -132,6 +132,22 @@ class BoundaryEnforcer {
|
||||||
// Compile boundary patterns
|
// Compile boundary patterns
|
||||||
this.boundaryPatterns = this._compileBoundaryPatterns();
|
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');
|
logger.info('BoundaryEnforcer initialized with Tractatus constraints');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -314,19 +330,36 @@ class BoundaryEnforcer {
|
||||||
}
|
}
|
||||||
|
|
||||||
_requireHumanJudgment(violations, action) {
|
_requireHumanJudgment(violations, action) {
|
||||||
|
this.stats.total_enforcements++;
|
||||||
|
this.stats.boundaries_violated++;
|
||||||
|
this.stats.human_required_count++;
|
||||||
|
|
||||||
const primaryViolation = violations[0];
|
const primaryViolation = violations[0];
|
||||||
|
if (primaryViolation.boundary && this.stats.by_boundary[primaryViolation.boundary] !== undefined) {
|
||||||
|
this.stats.by_boundary[primaryViolation.boundary]++;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
allowed: false,
|
allowed: false,
|
||||||
humanRequired: true,
|
humanRequired: true,
|
||||||
requirementType: 'MANDATORY',
|
requirementType: 'MANDATORY',
|
||||||
reason: 'TRACTATUS_BOUNDARY_VIOLATION',
|
reason: 'TRACTATUS_BOUNDARY_VIOLATION',
|
||||||
|
boundary: primaryViolation.boundary,
|
||||||
|
tractatus_section: primaryViolation.section,
|
||||||
|
principle: primaryViolation.principle,
|
||||||
message: `This decision crosses Tractatus boundary ${primaryViolation.section}: ` +
|
message: `This decision crosses Tractatus boundary ${primaryViolation.section}: ` +
|
||||||
`"${primaryViolation.principle}"`,
|
`"${primaryViolation.principle}"`,
|
||||||
violations,
|
violations,
|
||||||
|
violated_boundaries: violations.map(v => v.boundary),
|
||||||
action: 'REQUIRE_HUMAN_DECISION',
|
action: 'REQUIRE_HUMAN_DECISION',
|
||||||
recommendation: 'Present options to human for decision',
|
recommendation: 'Present options to human for decision',
|
||||||
userPrompt: this._generateBoundaryPrompt(violations, action),
|
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()
|
timestamp: new Date()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -362,6 +395,9 @@ class BoundaryEnforcer {
|
||||||
}
|
}
|
||||||
|
|
||||||
_allowAction(action, domain) {
|
_allowAction(action, domain) {
|
||||||
|
this.stats.total_enforcements++;
|
||||||
|
this.stats.allowed_count++;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
allowed: true,
|
allowed: true,
|
||||||
humanRequired: false,
|
humanRequired: false,
|
||||||
|
|
@ -391,6 +427,17 @@ class BoundaryEnforcer {
|
||||||
`Reason: ${reason}\n\n` +
|
`Reason: ${reason}\n\n` +
|
||||||
`Do you approve this action?`;
|
`Do you approve this action?`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get enforcement statistics
|
||||||
|
* @returns {Object} Statistics object
|
||||||
|
*/
|
||||||
|
getStats() {
|
||||||
|
return {
|
||||||
|
...this.stats,
|
||||||
|
timestamp: new Date()
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Singleton instance
|
// Singleton instance
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,22 @@ class CrossReferenceValidator {
|
||||||
this.lookbackWindow = 100; // How many recent messages to check
|
this.lookbackWindow = 100; // How many recent messages to check
|
||||||
this.relevanceThreshold = 0.4; // Minimum relevance to consider
|
this.relevanceThreshold = 0.4; // Minimum relevance to consider
|
||||||
this.instructionCache = new Map(); // Cache classified instructions
|
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');
|
logger.info('CrossReferenceValidator initialized');
|
||||||
}
|
}
|
||||||
|
|
@ -297,6 +313,9 @@ class CrossReferenceValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
_approvedResult(message, conflicts = []) {
|
_approvedResult(message, conflicts = []) {
|
||||||
|
this.stats.total_validations++;
|
||||||
|
this.stats.approvals++;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: VALIDATION_STATUS.APPROVED,
|
status: VALIDATION_STATUS.APPROVED,
|
||||||
message,
|
message,
|
||||||
|
|
@ -307,6 +326,11 @@ class CrossReferenceValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
_warningResult(conflicts, action) {
|
_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 primaryConflict = conflicts[0];
|
||||||
const timeAgo = this._formatTimeAgo(primaryConflict.instruction.timestamp);
|
const timeAgo = this._formatTimeAgo(primaryConflict.instruction.timestamp);
|
||||||
|
|
||||||
|
|
@ -323,6 +347,11 @@ class CrossReferenceValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
_rejectedResult(conflicts, action) {
|
_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 primaryConflict = conflicts[0];
|
||||||
const timeAgo = this._formatTimeAgo(primaryConflict.instruction.timestamp);
|
const timeAgo = this._formatTimeAgo(primaryConflict.instruction.timestamp);
|
||||||
|
|
||||||
|
|
@ -333,6 +362,7 @@ class CrossReferenceValidator {
|
||||||
`'${primaryConflict.instructionValue}' ${timeAgo} ago`,
|
`'${primaryConflict.instructionValue}' ${timeAgo} ago`,
|
||||||
conflicts,
|
conflicts,
|
||||||
action: 'REQUEST_CLARIFICATION',
|
action: 'REQUEST_CLARIFICATION',
|
||||||
|
required_action: 'REQUEST_CLARIFICATION',
|
||||||
recommendation: `Verify with user before proceeding`,
|
recommendation: `Verify with user before proceeding`,
|
||||||
instructionQuote: primaryConflict.instruction.text,
|
instructionQuote: primaryConflict.instruction.text,
|
||||||
requiredValue: primaryConflict.instructionValue,
|
requiredValue: primaryConflict.instructionValue,
|
||||||
|
|
@ -361,6 +391,50 @@ class CrossReferenceValidator {
|
||||||
if (seconds < 86400) return `${Math.floor(seconds / 3600)} hours`;
|
if (seconds < 86400) return `${Math.floor(seconds / 3600)} hours`;
|
||||||
return `${Math.floor(seconds / 86400)} days`;
|
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
|
// Singleton instance
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,30 @@ class InstructionPersistenceClassifier {
|
||||||
// Compile keyword patterns for efficient matching
|
// Compile keyword patterns for efficient matching
|
||||||
this.keywordPatterns = this._compileKeywordPatterns();
|
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');
|
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', {
|
logger.debug('Instruction classified', {
|
||||||
text: text.substring(0, 50),
|
text: text.substring(0, 50),
|
||||||
quadrant,
|
quadrant,
|
||||||
|
|
@ -441,6 +471,17 @@ class InstructionPersistenceClassifier {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get classification statistics
|
||||||
|
* @returns {Object} Statistics object
|
||||||
|
*/
|
||||||
|
getStats() {
|
||||||
|
return {
|
||||||
|
...this.stats,
|
||||||
|
timestamp: new Date()
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Singleton instance
|
// Singleton instance
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue