diff --git a/src/middleware/auth.middleware.js b/src/middleware/auth.middleware.js index 9dd48a25..a5e992b2 100644 --- a/src/middleware/auth.middleware.js +++ b/src/middleware/auth.middleware.js @@ -102,8 +102,14 @@ async function optionalAuth(req, res, next) { next(); } +/** + * Require admin role (convenience function) + */ +const requireAdmin = requireRole('admin'); + module.exports = { authenticateToken, requireRole, + requireAdmin, optionalAuth }; diff --git a/src/middleware/tractatus/governance.middleware.js b/src/middleware/tractatus/governance.middleware.js new file mode 100644 index 00000000..584adcbc --- /dev/null +++ b/src/middleware/tractatus/governance.middleware.js @@ -0,0 +1,252 @@ +/** + * Tractatus Governance Middleware + * Integrates Tractatus services with Express routes + * + * Provides middleware functions for: + * - AI-powered content moderation (blog posts, case studies) + * - Human approval workflows + * - Safety constraint enforcement + */ + +const { + classifier, + validator, + enforcer, + monitor, + verifier +} = require('../../services'); +const logger = require('../../utils/logger.util'); + +/** + * Classify incoming content by quadrant and persistence + * Adds classification metadata to req.tractatus + */ +function classifyContent(req, res, next) { + try { + const content = req.body.content || req.body.description || req.body.text || ''; + + const classification = classifier.classify({ + text: content, + context: { + domain: req.body.domain || 'general', + type: req.body.type || 'content' + }, + timestamp: new Date(), + source: 'user' + }); + + // Attach to request + req.tractatus = req.tractatus || {}; + req.tractatus.classification = classification; + + logger.debug('Content classified', { + quadrant: classification.quadrant, + persistence: classification.persistence, + verification: classification.verification + }); + + next(); + + } catch (error) { + logger.error('Classification middleware error:', error); + // Continue without classification (safer than blocking) + next(); + } +} + +/** + * Enforce Tractatus boundaries + * Blocks actions that cross values/wisdom/agency boundaries + */ +function enforceBoundaries(req, res, next) { + try { + const action = { + description: req.body.content || req.body.description || '', + type: req.body.type || req.route.path, + method: req.method + }; + + const enforcement = enforcer.enforce(action, { + user: req.user, + route: req.route.path + }); + + if (!enforcement.allowed) { + logger.warn('Action blocked by boundary enforcement', { + reason: enforcement.reason, + action: action.description?.substring(0, 50) + }); + + return res.status(403).json({ + error: 'Boundary Violation', + message: enforcement.message, + requiresHuman: true, + reason: enforcement.reason, + userPrompt: enforcement.userPrompt + }); + } + + // Attach enforcement result + req.tractatus = req.tractatus || {}; + req.tractatus.enforcement = enforcement; + + next(); + + } catch (error) { + logger.error('Boundary enforcement middleware error:', error); + next(error); + } +} + +/** + * Check context pressure before AI operations + * Recommends human intervention if pressure is too high + */ +function checkPressure(req, res, next) { + try { + const context = { + tokenUsage: req.headers['x-token-usage'] || 0, + tokenBudget: 200000, + messageCount: req.session?.messageCount || 0, + activeTasks: req.session?.activeTasks || [] + }; + + const pressure = monitor.analyzePressure(context); + + // Attach pressure analysis + req.tractatus = req.tractatus || {}; + req.tractatus.pressure = pressure; + + // Warn if pressure is high + if (pressure.pressureLevel >= 3) { // CRITICAL or DANGEROUS + logger.warn('High context pressure detected', { + level: pressure.pressureName, + overall: pressure.overallPressure + }); + + // Add warning to response headers + res.setHeader('X-Tractatus-Pressure', pressure.pressureName); + res.setHeader('X-Tractatus-Recommendations', JSON.stringify(pressure.recommendations.slice(0, 2))); + } + + next(); + + } catch (error) { + logger.error('Pressure monitoring middleware error:', error); + next(); + } +} + +/** + * Require human approval for AI-generated content + * Used for blog posts, media responses, case studies + */ +function requireHumanApproval(req, res, next) { + try { + // Check if content is AI-generated and not yet approved + if (req.body.aiGenerated && !req.body.humanApproved) { + const classification = req.tractatus?.classification; + + // Determine if approval is required + const requiresApproval = + classification?.verification === 'MANDATORY' || + classification?.persistence === 'HIGH' || + classification?.quadrant === 'STRATEGIC' || + classification?.quadrant === 'OPERATIONAL'; + + if (requiresApproval) { + logger.info('Human approval required for AI-generated content', { + quadrant: classification?.quadrant, + persistence: classification?.persistence + }); + + return res.status(403).json({ + error: 'Approval Required', + message: 'This AI-generated content requires human approval before publishing', + reason: 'TRACTATUS_GOVERNANCE', + classification: { + quadrant: classification?.quadrant, + persistence: classification?.persistence, + verification: classification?.verification + }, + action: 'Submit for moderation queue' + }); + } + } + + next(); + + } catch (error) { + logger.error('Human approval middleware error:', error); + next(error); + } +} + +/** + * Add Tractatus metadata to AI-generated responses + * Provides transparency about governance checks + */ +function addTractatusMetadata(req, res, next) { + const originalJson = res.json.bind(res); + + res.json = function(data) { + // Add Tractatus metadata if governance checks were performed + if (req.tractatus) { + data.tractatus = { + governed: true, + classification: req.tractatus.classification ? { + quadrant: req.tractatus.classification.quadrant, + persistence: req.tractatus.classification.persistence, + verification: req.tractatus.classification.verification + } : undefined, + pressure: req.tractatus.pressure ? { + level: req.tractatus.pressure.pressureName, + score: req.tractatus.pressure.overallPressure + } : undefined, + enforcement: req.tractatus.enforcement ? { + allowed: req.tractatus.enforcement.allowed, + requiresHuman: req.tractatus.enforcement.humanRequired + } : undefined, + timestamp: new Date() + }; + } + + return originalJson(data); + }; + + next(); +} + +/** + * Governance status endpoint middleware + * Provides framework status information + */ +function governanceStatus(req, res) { + const { + getFrameworkStatus + } = require('../../services'); + + const status = getFrameworkStatus(); + + // Add runtime metrics + const runtimeMetrics = { + uptime: process.uptime(), + memoryUsage: process.memoryUsage(), + environment: process.env.NODE_ENV + }; + + res.json({ + ...status, + runtime: runtimeMetrics, + operational: true + }); +} + +module.exports = { + classifyContent, + enforceBoundaries, + checkPressure, + requireHumanApproval, + addTractatusMetadata, + governanceStatus +}; diff --git a/src/routes/governance.routes.js b/src/routes/governance.routes.js new file mode 100644 index 00000000..31a7be50 --- /dev/null +++ b/src/routes/governance.routes.js @@ -0,0 +1,186 @@ +/** + * Tractatus Governance Routes + * API endpoints for framework status and testing + */ + +const express = require('express'); +const router = express.Router(); + +const { governanceStatus } = require('../middleware/tractatus/governance.middleware'); +const { authenticateToken, requireAdmin } = require('../middleware/auth.middleware'); +const { asyncHandler } = require('../middleware/error.middleware'); + +// Import services for testing endpoints +const { + classifier, + validator, + enforcer, + monitor, + verifier, + getFrameworkStatus +} = require('../services'); + +/** + * GET /api/governance + * Get framework status (public) + */ +router.get('/', governanceStatus); + +/** + * GET /api/governance/status + * Detailed governance status (admin only) + */ +router.get('/status', + authenticateToken, + requireAdmin, + asyncHandler(async (req, res) => { + const status = getFrameworkStatus(); + + res.json({ + success: true, + ...status, + uptime: process.uptime(), + environment: process.env.NODE_ENV + }); + }) +); + +/** + * POST /api/governance/classify + * Test instruction classification (admin only) + */ +router.post('/classify', + authenticateToken, + requireAdmin, + asyncHandler(async (req, res) => { + const { text, context } = req.body; + + if (!text) { + return res.status(400).json({ + error: 'Bad Request', + message: 'text field is required' + }); + } + + const classification = classifier.classify({ + text, + context: context || {}, + timestamp: new Date(), + source: 'test' + }); + + res.json({ + success: true, + classification + }); + }) +); + +/** + * POST /api/governance/validate + * Test action validation (admin only) + */ +router.post('/validate', + authenticateToken, + requireAdmin, + asyncHandler(async (req, res) => { + const { action, context } = req.body; + + if (!action) { + return res.status(400).json({ + error: 'Bad Request', + message: 'action object is required' + }); + } + + const validation = validator.validate(action, context || { + messages: [] + }); + + res.json({ + success: true, + validation + }); + }) +); + +/** + * POST /api/governance/enforce + * Test boundary enforcement (admin only) + */ +router.post('/enforce', + authenticateToken, + requireAdmin, + asyncHandler(async (req, res) => { + const { action, context } = req.body; + + if (!action) { + return res.status(400).json({ + error: 'Bad Request', + message: 'action object is required' + }); + } + + const enforcement = enforcer.enforce(action, context || {}); + + res.json({ + success: true, + enforcement + }); + }) +); + +/** + * POST /api/governance/pressure + * Test pressure analysis (admin only) + */ +router.post('/pressure', + authenticateToken, + requireAdmin, + asyncHandler(async (req, res) => { + const { context } = req.body; + + const pressure = monitor.analyzePressure(context || { + tokenUsage: 50000, + tokenBudget: 200000, + messageCount: 20 + }); + + res.json({ + success: true, + pressure + }); + }) +); + +/** + * POST /api/governance/verify + * Test metacognitive verification (admin only) + */ +router.post('/verify', + authenticateToken, + requireAdmin, + asyncHandler(async (req, res) => { + const { action, reasoning, context } = req.body; + + if (!action) { + return res.status(400).json({ + error: 'Bad Request', + message: 'action object is required' + }); + } + + const verification = verifier.verify( + action, + reasoning || {}, + context || {} + ); + + res.json({ + success: true, + verification + }); + }) +); + +module.exports = router; diff --git a/src/routes/index.js b/src/routes/index.js index 27a4fcfa..736f1233 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -11,12 +11,14 @@ const authRoutes = require('./auth.routes'); const documentsRoutes = require('./documents.routes'); const blogRoutes = require('./blog.routes'); const adminRoutes = require('./admin.routes'); +const governanceRoutes = require('./governance.routes'); // Mount routes router.use('/auth', authRoutes); router.use('/documents', documentsRoutes); router.use('/blog', blogRoutes); router.use('/admin', adminRoutes); +router.use('/governance', governanceRoutes); // API root endpoint router.get('/', (req, res) => { @@ -54,8 +56,17 @@ router.get('/', (req, res) => { review: 'POST /api/admin/moderation/:id/review', stats: 'GET /api/admin/stats', activity: 'GET /api/admin/activity' + }, + governance: { + status: 'GET /api/governance', + classify: 'POST /api/governance/classify (admin)', + validate: 'POST /api/governance/validate (admin)', + enforce: 'POST /api/governance/enforce (admin)', + pressure: 'POST /api/governance/pressure (admin)', + verify: 'POST /api/governance/verify (admin)' } }, + framework: 'Tractatus-Based LLM Safety Architecture', documentation: '/api/docs', health: '/health' }); diff --git a/src/services/BoundaryEnforcer.service.js b/src/services/BoundaryEnforcer.service.js new file mode 100644 index 00000000..a9d5cf89 --- /dev/null +++ b/src/services/BoundaryEnforcer.service.js @@ -0,0 +1,399 @@ +/** + * Boundary Enforcer Service + * Ensures AI never makes values decisions without human approval + * + * Core Tractatus Service: Implements Tractatus 12.1-12.7 boundaries + * where AI architecturally acknowledges domains requiring human judgment. + * + * Tractatus Boundaries: + * 12.1 Values cannot be automated, only verified. + * 12.2 Innovation cannot be proceduralized, only facilitated. + * 12.3 Wisdom cannot be encoded, only supported. + * 12.4 Purpose cannot be generated, only preserved. + * 12.5 Meaning cannot be computed, only recognized. + * 12.6 Agency cannot be simulated, only respected. + * 12.7 Whereof one cannot systematize, thereof one must trust human judgment. + */ + +const classifier = require('./InstructionPersistenceClassifier.service'); +const logger = require('../utils/logger.util'); + +/** + * Tractatus decision boundaries + * These domains ALWAYS require human judgment + */ +const TRACTATUS_BOUNDARIES = { + VALUES: { + section: '12.1', + principle: 'Values cannot be automated, only verified', + humanRequired: true, + keywords: ['value', 'principle', 'ethic', 'moral', 'should', 'ought', 'right', 'wrong'], + examples: [ + 'Decide whether to prioritize privacy over convenience', + 'Determine our core values', + 'Choose what principles matter most' + ] + }, + INNOVATION: { + section: '12.2', + principle: 'Innovation cannot be proceduralized, only facilitated', + humanRequired: true, + keywords: ['innovate', 'create', 'invent', 'breakthrough', 'novel', 'creative'], + examples: [ + 'Create entirely new approach', + 'Invent solution to fundamental problem', + 'Generate breakthrough innovation' + ] + }, + WISDOM: { + section: '12.3', + principle: 'Wisdom cannot be encoded, only supported', + humanRequired: true, + keywords: ['wisdom', 'judgment', 'discernment', 'prudence', 'insight'], + examples: [ + 'Exercise judgment in unprecedented situation', + 'Apply wisdom to complex tradeoff', + 'Discern what truly matters' + ] + }, + PURPOSE: { + section: '12.4', + principle: 'Purpose cannot be generated, only preserved', + humanRequired: true, + keywords: ['purpose', 'mission', 'why', 'meaning', 'goal', 'objective'], + examples: [ + 'Define our organizational purpose', + 'Determine why we exist', + 'Set our fundamental mission' + ] + }, + MEANING: { + section: '12.5', + principle: 'Meaning cannot be computed, only recognized', + humanRequired: true, + keywords: ['meaning', 'significance', 'importance', 'matter', 'meaningful'], + examples: [ + 'Decide what is truly significant', + 'Determine what matters most', + 'Recognize deeper meaning' + ] + }, + AGENCY: { + section: '12.6', + principle: 'Agency cannot be simulated, only respected', + humanRequired: true, + keywords: ['agency', 'autonomy', 'choice', 'freedom', 'sovereignty', 'self-determination'], + examples: [ + 'Make autonomous decision for humans', + 'Override human choice', + 'Substitute AI judgment for human agency' + ] + } +}; + +/** + * Decision types that require human approval + */ +const DECISION_DOMAINS = { + STRATEGIC: { + requiresHuman: true, + reason: 'Strategic decisions affect long-term direction and values' + }, + VALUES_SENSITIVE: { + requiresHuman: true, + reason: 'Values-sensitive decisions must preserve human agency' + }, + RESOURCE_ALLOCATION: { + requiresHuman: true, + reason: 'Resource decisions reflect priorities and values' + }, + POLICY_CREATION: { + requiresHuman: true, + reason: 'Policy creation is operational stewardship domain' + }, + USER_COMMUNICATION: { + requiresHuman: false, + requiresReview: true, + reason: 'Communications should be reviewed but not blocked' + }, + TECHNICAL_IMPLEMENTATION: { + requiresHuman: false, + requiresReview: false, + reason: 'Technical implementations can proceed with validation' + } +}; + +class BoundaryEnforcer { + constructor() { + this.boundaries = TRACTATUS_BOUNDARIES; + this.decisionDomains = DECISION_DOMAINS; + this.classifier = classifier; + + // Compile boundary patterns + this.boundaryPatterns = this._compileBoundaryPatterns(); + + logger.info('BoundaryEnforcer initialized with Tractatus constraints'); + } + + /** + * Enforce boundaries on a proposed action + * @param {Object} action - The proposed action + * @param {Object} context - Decision context + * @returns {Object} Enforcement result + */ + enforce(action, context = {}) { + try { + // Check if action crosses Tractatus boundaries + const boundaryViolations = this._checkTractatusBoundaries(action); + + if (boundaryViolations.length > 0) { + return this._requireHumanJudgment(boundaryViolations, action); + } + + // Check decision domain + const domain = this._identifyDecisionDomain(action, context); + const domainConfig = this.decisionDomains[domain]; + + if (domainConfig.requiresHuman) { + return this._requireHumanApproval(domain, domainConfig.reason, action); + } + + if (domainConfig.requiresReview) { + return this._requireHumanReview(domain, domainConfig.reason, action); + } + + // Action can proceed without human intervention + return this._allowAction(action, domain); + + } catch (error) { + logger.error('Boundary enforcement error:', error); + // Fail-safe: require human review on error + return this._requireHumanJudgment( + [{ boundary: 'ERROR', reason: 'Enforcement error, defaulting to human review' }], + action + ); + } + } + + /** + * Check if an action requires human approval based on Tractatus framework + */ + requiresHumanApproval(action) { + const result = this.enforce(action); + return result.humanRequired === true; + } + + /** + * Get appropriate human oversight level for action + */ + getOversightLevel(action, context = {}) { + const classification = this.classifier.classify({ + text: action.description || action.text || '', + context, + timestamp: action.timestamp || new Date(), + source: 'ai_proposed' + }); + + const oversightLevels = { + STRATEGIC: 'VALUES_STEWARDSHIP', + OPERATIONAL: 'PROCESS_STEWARDSHIP', + TACTICAL: 'IMPLEMENTATION_EXPERTISE', + SYSTEM: 'TECHNICAL_EXPERTISE', + STOCHASTIC: 'INSIGHT_GENERATION' + }; + + return oversightLevels[classification.quadrant] || 'GENERAL_OVERSIGHT'; + } + + /** + * Private methods + */ + + _compileBoundaryPatterns() { + const patterns = {}; + for (const [boundary, config] of Object.entries(this.boundaries)) { + patterns[boundary] = config.keywords.map(kw => new RegExp(`\\b${kw}\\b`, 'i')); + } + return patterns; + } + + _checkTractatusBoundaries(action) { + const violations = []; + const actionText = (action.description || action.text || '').toLowerCase(); + + for (const [boundary, patterns] of Object.entries(this.boundaryPatterns)) { + let matchCount = 0; + for (const pattern of patterns) { + if (pattern.test(actionText)) { + matchCount++; + } + } + + // If multiple keywords match, likely crossing boundary + if (matchCount >= 2) { + violations.push({ + boundary, + section: this.boundaries[boundary].section, + principle: this.boundaries[boundary].principle, + matchCount + }); + } + } + + return violations; + } + + _identifyDecisionDomain(action, context) { + const actionText = (action.description || action.text || '').toLowerCase(); + + // Strategic indicators + if (this._hasStrategicIndicators(actionText, context)) { + return 'STRATEGIC'; + } + + // Values-sensitive indicators + if (this._hasValuesSensitiveIndicators(actionText)) { + return 'VALUES_SENSITIVE'; + } + + // Resource allocation indicators + if (this._hasResourceIndicators(actionText)) { + return 'RESOURCE_ALLOCATION'; + } + + // Policy creation indicators + if (this._hasPolicyIndicators(actionText)) { + return 'POLICY_CREATION'; + } + + // User communication indicators + if (this._hasCommunicationIndicators(actionText, action)) { + return 'USER_COMMUNICATION'; + } + + // Default to technical implementation + return 'TECHNICAL_IMPLEMENTATION'; + } + + _hasStrategicIndicators(text, context) { + const strategic = [ + 'always', 'never', 'mission', 'vision', 'strategy', + 'long-term', 'fundamental', 'core principle' + ]; + return strategic.some(kw => text.includes(kw)); + } + + _hasValuesSensitiveIndicators(text) { + const values = [ + 'value', 'principle', 'ethic', 'moral', 'right', 'wrong', + 'should we', 'ought to', 'better to' + ]; + return values.some(kw => text.includes(kw)); + } + + _hasResourceIndicators(text) { + const resources = [ + 'budget', 'allocate', 'spend', 'invest', 'cost', + 'hire', 'fire', 'purchase' + ]; + return resources.some(kw => text.includes(kw)); + } + + _hasPolicyIndicators(text) { + const policy = [ + 'policy', 'rule', 'guideline', 'standard', 'procedure', + 'process', 'workflow', 'protocol' + ]; + return policy.some(kw => text.includes(kw)); + } + + _hasCommunicationIndicators(text, action) { + if (action.type === 'email' || action.type === 'message') return true; + const communication = ['send', 'email', 'message', 'notify', 'inform', 'communicate']; + return communication.some(kw => text.includes(kw)); + } + + _requireHumanJudgment(violations, action) { + const primaryViolation = violations[0]; + + return { + allowed: false, + humanRequired: true, + requirementType: 'MANDATORY', + reason: 'TRACTATUS_BOUNDARY_VIOLATION', + message: `This decision crosses Tractatus boundary ${primaryViolation.section}: ` + + `"${primaryViolation.principle}"`, + violations, + action: 'REQUIRE_HUMAN_DECISION', + recommendation: 'Present options to human for decision', + userPrompt: this._generateBoundaryPrompt(violations, action), + timestamp: new Date() + }; + } + + _requireHumanApproval(domain, reason, action) { + return { + allowed: false, + humanRequired: true, + requirementType: 'APPROVAL_REQUIRED', + domain, + reason, + message: `${domain} decisions require human approval: ${reason}`, + action: 'REQUEST_APPROVAL', + recommendation: 'Present proposal to human for approval', + userPrompt: this._generateApprovalPrompt(domain, reason, action), + timestamp: new Date() + }; + } + + _requireHumanReview(domain, reason, action) { + return { + allowed: true, + humanRequired: false, + requirementType: 'REVIEW_RECOMMENDED', + domain, + reason, + message: `${domain}: ${reason}`, + action: 'PROCEED_WITH_NOTIFICATION', + recommendation: 'Execute action but notify human', + notification: `Action executed in ${domain}: ${action.description || action.text}`, + timestamp: new Date() + }; + } + + _allowAction(action, domain) { + return { + allowed: true, + humanRequired: false, + requirementType: 'NONE', + domain, + message: `Action approved for ${domain}`, + action: 'PROCEED', + timestamp: new Date() + }; + } + + _generateBoundaryPrompt(violations, action) { + const primaryViolation = violations[0]; + + return `I need your judgment on this decision:\n\n` + + `Proposed action: ${action.description || action.text}\n\n` + + `This crosses a Tractatus boundary (${primaryViolation.section}):\n` + + `"${primaryViolation.principle}"\n\n` + + `This means I cannot make this decision autonomously - it requires human judgment.\n\n` + + `What would you like me to do?`; + } + + _generateApprovalPrompt(domain, reason, action) { + return `This action requires your approval:\n\n` + + `Domain: ${domain}\n` + + `Action: ${action.description || action.text}\n` + + `Reason: ${reason}\n\n` + + `Do you approve this action?`; + } +} + +// Singleton instance +const enforcer = new BoundaryEnforcer(); + +module.exports = enforcer; diff --git a/src/services/ContextPressureMonitor.service.js b/src/services/ContextPressureMonitor.service.js new file mode 100644 index 00000000..48458ba5 --- /dev/null +++ b/src/services/ContextPressureMonitor.service.js @@ -0,0 +1,420 @@ +/** + * Context Pressure Monitor Service + * Detects conditions that increase AI error probability + * + * Core Tractatus Service: Monitors environmental factors that degrade + * AI performance and triggers increased verification or human intervention. + * + * Monitored Conditions: + * - Token budget pressure (approaching context limit) + * - Conversation length (attention decay over long sessions) + * - Task complexity (number of simultaneous objectives) + * - Error frequency (recent failures indicate degraded state) + * - Instruction density (too many competing directives) + */ + +const logger = require('../utils/logger.util'); + +/** + * Pressure levels and thresholds + */ +const PRESSURE_LEVELS = { + NORMAL: { + level: 0, + threshold: 0.3, + description: 'Normal operating conditions', + action: 'PROCEED', + verificationMultiplier: 1.0 + }, + ELEVATED: { + level: 1, + threshold: 0.5, + description: 'Elevated pressure, increased verification recommended', + action: 'INCREASE_VERIFICATION', + verificationMultiplier: 1.3 + }, + HIGH: { + level: 2, + threshold: 0.7, + description: 'High pressure, mandatory verification required', + action: 'MANDATORY_VERIFICATION', + verificationMultiplier: 1.6 + }, + CRITICAL: { + level: 3, + threshold: 0.85, + description: 'Critical pressure, recommend context refresh', + action: 'RECOMMEND_REFRESH', + verificationMultiplier: 2.0 + }, + DANGEROUS: { + level: 4, + threshold: 0.95, + description: 'Dangerous conditions, require human intervention', + action: 'REQUIRE_HUMAN_INTERVENTION', + verificationMultiplier: 3.0 + } +}; + +/** + * Monitored metrics + */ +const METRICS = { + TOKEN_USAGE: { + weight: 0.35, + criticalThreshold: 0.8, // 80% of token budget + dangerThreshold: 0.95 + }, + CONVERSATION_LENGTH: { + weight: 0.25, + criticalThreshold: 100, // Number of messages + dangerThreshold: 150 + }, + TASK_COMPLEXITY: { + weight: 0.15, + criticalThreshold: 5, // Simultaneous tasks + dangerThreshold: 8 + }, + ERROR_FREQUENCY: { + weight: 0.15, + criticalThreshold: 3, // Errors in last 10 actions + dangerThreshold: 5 + }, + INSTRUCTION_DENSITY: { + weight: 0.10, + criticalThreshold: 10, // Active instructions + dangerThreshold: 15 + } +}; + +class ContextPressureMonitor { + constructor() { + this.pressureLevels = PRESSURE_LEVELS; + this.metrics = METRICS; + this.errorHistory = []; + this.maxErrorHistory = 20; + + logger.info('ContextPressureMonitor initialized'); + } + + /** + * Calculate current pressure level + * @param {Object} context - Current conversation/session context + * @returns {Object} Pressure analysis + */ + analyzePressure(context) { + try { + // Calculate individual metric scores + const metricScores = { + tokenUsage: this._calculateTokenPressure(context), + conversationLength: this._calculateConversationPressure(context), + taskComplexity: this._calculateComplexityPressure(context), + errorFrequency: this._calculateErrorPressure(context), + instructionDensity: this._calculateInstructionPressure(context) + }; + + // Calculate weighted overall pressure score + const overallPressure = this._calculateOverallPressure(metricScores); + + // Determine pressure level + const pressureLevel = this._determinePressureLevel(overallPressure); + + // Generate recommendations + const recommendations = this._generateRecommendations( + pressureLevel, + metricScores, + context + ); + + const analysis = { + overallPressure, + pressureLevel: pressureLevel.level, + pressureName: Object.keys(this.pressureLevels).find( + key => this.pressureLevels[key] === pressureLevel + ), + description: pressureLevel.description, + action: pressureLevel.action, + verificationMultiplier: pressureLevel.verificationMultiplier, + metrics: metricScores, + recommendations, + timestamp: new Date() + }; + + // Log if pressure is elevated + if (pressureLevel.level >= PRESSURE_LEVELS.ELEVATED.level) { + logger.warn('Elevated context pressure detected', { + level: pressureLevel.level, + pressure: overallPressure, + topMetric: this._getTopMetric(metricScores) + }); + } + + return analysis; + + } catch (error) { + logger.error('Pressure analysis error:', error); + return this._defaultPressureAnalysis(); + } + } + + /** + * Record an error for error frequency tracking + */ + recordError(error) { + this.errorHistory.push({ + timestamp: new Date(), + error: error.message || String(error), + type: error.type || 'unknown' + }); + + // Maintain history limit + if (this.errorHistory.length > this.maxErrorHistory) { + this.errorHistory.shift(); + } + + logger.debug('Error recorded in pressure monitor', { + recentErrors: this.errorHistory.length + }); + } + + /** + * Check if action should proceed given current pressure + */ + shouldProceed(action, context) { + const analysis = this.analyzePressure(context); + + if (analysis.pressureLevel >= PRESSURE_LEVELS.DANGEROUS.level) { + return { + proceed: false, + reason: 'Dangerous pressure level - human intervention required', + analysis + }; + } + + if (analysis.pressureLevel >= PRESSURE_LEVELS.CRITICAL.level) { + return { + proceed: true, + requireVerification: true, + reason: 'Critical pressure - mandatory verification required', + analysis + }; + } + + return { + proceed: true, + requireVerification: analysis.pressureLevel >= PRESSURE_LEVELS.HIGH.level, + reason: 'Acceptable pressure level', + analysis + }; + } + + /** + * Private methods + */ + + _calculateTokenPressure(context) { + const tokenUsage = context.tokenUsage || 0; + const tokenBudget = context.tokenBudget || 200000; + const ratio = tokenUsage / tokenBudget; + + return { + value: ratio, + normalized: Math.min(1.0, ratio / this.metrics.TOKEN_USAGE.criticalThreshold), + raw: tokenUsage, + budget: tokenBudget, + percentage: (ratio * 100).toFixed(1) + }; + } + + _calculateConversationPressure(context) { + const messageCount = context.messageCount || context.messages?.length || 0; + const ratio = messageCount / this.metrics.CONVERSATION_LENGTH.criticalThreshold; + + return { + value: ratio, + normalized: Math.min(1.0, ratio), + raw: messageCount, + threshold: this.metrics.CONVERSATION_LENGTH.criticalThreshold + }; + } + + _calculateComplexityPressure(context) { + const taskCount = context.activeTasks?.length || context.taskComplexity || 1; + const ratio = taskCount / this.metrics.TASK_COMPLEXITY.criticalThreshold; + + return { + value: ratio, + normalized: Math.min(1.0, ratio), + raw: taskCount, + threshold: this.metrics.TASK_COMPLEXITY.criticalThreshold + }; + } + + _calculateErrorPressure(context) { + // Count recent errors (last 10 minutes) + const tenMinutesAgo = new Date(Date.now() - 10 * 60 * 1000); + const recentErrors = this.errorHistory.filter( + e => new Date(e.timestamp) > tenMinutesAgo + ).length; + + const ratio = recentErrors / this.metrics.ERROR_FREQUENCY.criticalThreshold; + + return { + value: ratio, + normalized: Math.min(1.0, ratio), + raw: recentErrors, + threshold: this.metrics.ERROR_FREQUENCY.criticalThreshold, + total: this.errorHistory.length + }; + } + + _calculateInstructionPressure(context) { + const instructionCount = context.activeInstructions?.length || 0; + const ratio = instructionCount / this.metrics.INSTRUCTION_DENSITY.criticalThreshold; + + return { + value: ratio, + normalized: Math.min(1.0, ratio), + raw: instructionCount, + threshold: this.metrics.INSTRUCTION_DENSITY.criticalThreshold + }; + } + + _calculateOverallPressure(metricScores) { + let pressure = 0; + + pressure += metricScores.tokenUsage.normalized * this.metrics.TOKEN_USAGE.weight; + pressure += metricScores.conversationLength.normalized * this.metrics.CONVERSATION_LENGTH.weight; + pressure += metricScores.taskComplexity.normalized * this.metrics.TASK_COMPLEXITY.weight; + pressure += metricScores.errorFrequency.normalized * this.metrics.ERROR_FREQUENCY.weight; + pressure += metricScores.instructionDensity.normalized * this.metrics.INSTRUCTION_DENSITY.weight; + + return Math.min(1.0, Math.max(0.0, pressure)); + } + + _determinePressureLevel(pressure) { + if (pressure >= PRESSURE_LEVELS.DANGEROUS.threshold) { + return PRESSURE_LEVELS.DANGEROUS; + } + if (pressure >= PRESSURE_LEVELS.CRITICAL.threshold) { + return PRESSURE_LEVELS.CRITICAL; + } + if (pressure >= PRESSURE_LEVELS.HIGH.threshold) { + return PRESSURE_LEVELS.HIGH; + } + if (pressure >= PRESSURE_LEVELS.ELEVATED.threshold) { + return PRESSURE_LEVELS.ELEVATED; + } + return PRESSURE_LEVELS.NORMAL; + } + + _generateRecommendations(pressureLevel, metricScores, context) { + const recommendations = []; + + // Token usage recommendations + if (metricScores.tokenUsage.normalized > 0.8) { + recommendations.push({ + type: 'TOKEN_MANAGEMENT', + severity: 'HIGH', + message: 'Token budget critically low - consider context refresh', + action: 'Summarize conversation and start new context window' + }); + } else if (metricScores.tokenUsage.normalized > 0.6) { + recommendations.push({ + type: 'TOKEN_MANAGEMENT', + severity: 'MEDIUM', + message: 'Token usage elevated - monitor carefully', + action: 'Be concise in responses, consider pruning context if needed' + }); + } + + // Conversation length recommendations + if (metricScores.conversationLength.normalized > 0.8) { + recommendations.push({ + type: 'CONVERSATION_MANAGEMENT', + severity: 'HIGH', + message: 'Very long conversation - attention may degrade', + action: 'Consider summarizing progress and starting fresh session' + }); + } + + // Error frequency recommendations + if (metricScores.errorFrequency.normalized > 0.6) { + recommendations.push({ + type: 'ERROR_MANAGEMENT', + severity: 'HIGH', + message: 'High error frequency detected - operating conditions degraded', + action: 'Increase verification, slow down, consider pausing for review' + }); + } + + // Task complexity recommendations + if (metricScores.taskComplexity.normalized > 0.7) { + recommendations.push({ + type: 'COMPLEXITY_MANAGEMENT', + severity: 'MEDIUM', + message: 'High task complexity - risk of context confusion', + action: 'Focus on one task at a time, explicitly track task switching' + }); + } + + // Instruction density recommendations + if (metricScores.instructionDensity.normalized > 0.7) { + recommendations.push({ + type: 'INSTRUCTION_MANAGEMENT', + severity: 'MEDIUM', + message: 'Many active instructions - risk of conflicts', + action: 'Review and consolidate instructions, resolve conflicts' + }); + } + + // Overall pressure recommendations + if (pressureLevel.level >= PRESSURE_LEVELS.CRITICAL.level) { + recommendations.push({ + type: 'GENERAL', + severity: 'CRITICAL', + message: 'Critical pressure level - degraded performance likely', + action: 'Strongly recommend context refresh or human intervention' + }); + } + + return recommendations; + } + + _getTopMetric(metricScores) { + const scores = [ + { name: 'tokenUsage', score: metricScores.tokenUsage.normalized }, + { name: 'conversationLength', score: metricScores.conversationLength.normalized }, + { name: 'taskComplexity', score: metricScores.taskComplexity.normalized }, + { name: 'errorFrequency', score: metricScores.errorFrequency.normalized }, + { name: 'instructionDensity', score: metricScores.instructionDensity.normalized } + ]; + + scores.sort((a, b) => b.score - a.score); + return scores[0].name; + } + + _defaultPressureAnalysis() { + return { + overallPressure: 0.5, + pressureLevel: 1, + pressureName: 'ELEVATED', + description: 'Unable to analyze pressure, using safe defaults', + action: 'INCREASE_VERIFICATION', + verificationMultiplier: 1.5, + metrics: {}, + recommendations: [{ + type: 'ERROR', + severity: 'HIGH', + message: 'Pressure analysis failed - proceeding with caution', + action: 'Increase verification and monitoring' + }], + timestamp: new Date() + }; + } +} + +// Singleton instance +const monitor = new ContextPressureMonitor(); + +module.exports = monitor; diff --git a/src/services/CrossReferenceValidator.service.js b/src/services/CrossReferenceValidator.service.js new file mode 100644 index 00000000..9c1c0c90 --- /dev/null +++ b/src/services/CrossReferenceValidator.service.js @@ -0,0 +1,369 @@ +/** + * Cross-Reference Validator Service + * Validates proposed AI actions against explicit user instructions + * + * Core Tractatus Service: Prevents the "27027 failure mode" where + * AI actions use cached patterns instead of explicit user instructions. + * + * Example failure prevented: + * - User says: "check port 27027" + * - AI action: mongosh --port 27017 (using MongoDB default instead of explicit instruction) + * - Validator: REJECTS action, requires using port 27027 + */ + +const classifier = require('./InstructionPersistenceClassifier.service'); +const logger = require('../utils/logger.util'); + +/** + * Validation result statuses + */ +const VALIDATION_STATUS = { + APPROVED: 'APPROVED', // No conflicts, proceed + WARNING: 'WARNING', // Minor conflicts, notify user + REJECTED: 'REJECTED', // Critical conflicts, block action + ESCALATE: 'ESCALATE' // Requires human judgment +}; + +/** + * Conflict severity levels + */ +const CONFLICT_SEVERITY = { + CRITICAL: 'CRITICAL', // Explicit instruction violation + WARNING: 'WARNING', // Potential misalignment + MINOR: 'MINOR', // Acceptable deviation + INFO: 'INFO' // Informational only +}; + +class CrossReferenceValidator { + constructor() { + this.classifier = classifier; + this.lookbackWindow = 100; // How many recent messages to check + this.relevanceThreshold = 0.4; // Minimum relevance to consider + this.instructionCache = new Map(); // Cache classified instructions + + logger.info('CrossReferenceValidator initialized'); + } + + /** + * Validate a proposed action against conversation context + * @param {Object} action - The proposed action + * @param {Object} context - Conversation context with instructions + * @returns {Object} Validation result + */ + validate(action, context) { + try { + // Extract action parameters + const actionParams = this._extractActionParameters(action); + + // Find relevant instructions from context + const relevantInstructions = this._findRelevantInstructions( + action, + context, + this.lookbackWindow + ); + + if (relevantInstructions.length === 0) { + return this._approvedResult('No relevant instructions to validate against'); + } + + // Check for conflicts with each relevant instruction + const conflicts = []; + for (const instruction of relevantInstructions) { + const conflict = this._checkConflict(actionParams, instruction); + if (conflict) { + conflicts.push(conflict); + } + } + + // Make validation decision based on conflicts + return this._makeValidationDecision(conflicts, action); + + } catch (error) { + logger.error('Validation error:', error); + // Fail-safe: escalate on error + return this._escalateResult('Validation error occurred, requiring human review'); + } + } + + /** + * Batch validate multiple actions + */ + validateBatch(actions, context) { + return actions.map(action => this.validate(action, context)); + } + + /** + * Add instruction to cache for validation + */ + cacheInstruction(instruction) { + const classified = this.classifier.classify(instruction); + const key = `${instruction.timestamp.getTime()}_${instruction.text.substring(0, 50)}`; + this.instructionCache.set(key, classified); + + // Cleanup old entries (keep last 200) + if (this.instructionCache.size > 200) { + const keys = Array.from(this.instructionCache.keys()); + keys.slice(0, this.instructionCache.size - 200).forEach(k => { + this.instructionCache.delete(k); + }); + } + + return classified; + } + + /** + * Private methods + */ + + _extractActionParameters(action) { + const params = {}; + + // Common parameter types to extract + const patterns = { + port: /port[:\s]+(\d{4,5})/i, + host: /(?:host|server)[:\s]+([\w.-]+)/i, + database: /(?:database|db)[:\s]+([\w-]+)/i, + path: /(\/[\w./-]+)/, + url: /(https?:\/\/[\w.-]+(?::\d+)?[\w./-]*)/, + collection: /collection[:\s]+([\w-]+)/i, + model: /model[:\s]+([\w-]+)/i, + function: /function[:\s]+([\w-]+)/i + }; + + const description = action.description || action.command || action.text || ''; + + for (const [paramType, pattern] of Object.entries(patterns)) { + const match = description.match(pattern); + if (match) { + params[paramType] = match[1]; + } + } + + // Extract from structured action data + if (action.parameters) { + Object.assign(params, action.parameters); + } + + return params; + } + + _findRelevantInstructions(action, context, lookback) { + const instructions = []; + + // Get recent instructions from context + const recentMessages = context.messages + ? context.messages.slice(-lookback) + : []; + + // Classify and score each instruction + for (const message of recentMessages) { + if (message.role === 'user') { + // Classify the instruction + const classified = this.cacheInstruction({ + text: message.content, + timestamp: message.timestamp || new Date(), + source: 'user', + context: context + }); + + // Calculate relevance to this action + const relevance = this.classifier.calculateRelevance(classified, action); + + if (relevance >= this.relevanceThreshold) { + instructions.push({ + ...classified, + relevance, + messageIndex: recentMessages.indexOf(message) + }); + } + } + } + + // Sort by relevance (highest first) + instructions.sort((a, b) => b.relevance - a.relevance); + + logger.debug(`Found ${instructions.length} relevant instructions for action`, { + action: action.description?.substring(0, 50), + topRelevance: instructions[0]?.relevance + }); + + return instructions; + } + + _checkConflict(actionParams, instruction) { + // Extract parameters from instruction + const instructionParams = instruction.parameters || {}; + + // Find overlapping parameter types + const commonParams = Object.keys(actionParams).filter(key => + instructionParams.hasOwnProperty(key) + ); + + if (commonParams.length === 0) { + return null; // No common parameters to conflict + } + + // Check each common parameter for mismatch + for (const param of commonParams) { + const actionValue = actionParams[param]; + const instructionValue = instructionParams[param]; + + // Normalize for comparison + const normalizedAction = String(actionValue).toLowerCase().trim(); + const normalizedInstruction = String(instructionValue).toLowerCase().trim(); + + if (normalizedAction !== normalizedInstruction) { + // Found a conflict + const severity = this._determineConflictSeverity( + param, + instruction.persistence, + instruction.explicitness, + instruction.recencyWeight + ); + + return { + parameter: param, + actionValue, + instructionValue, + instruction: { + text: instruction.text, + timestamp: instruction.timestamp, + quadrant: instruction.quadrant, + persistence: instruction.persistence + }, + severity, + relevance: instruction.relevance, + recencyWeight: instruction.recencyWeight + }; + } + } + + return null; // No conflicts found + } + + _determineConflictSeverity(param, persistence, explicitness, recencyWeight) { + // Critical severity conditions + if (persistence === 'HIGH' && explicitness > 0.8) { + return CONFLICT_SEVERITY.CRITICAL; + } + + if (recencyWeight > 0.8 && explicitness > 0.7) { + return CONFLICT_SEVERITY.CRITICAL; + } + + // Important parameters that should be explicit + const criticalParams = ['port', 'database', 'host', 'url']; + if (criticalParams.includes(param) && explicitness > 0.6) { + return CONFLICT_SEVERITY.CRITICAL; + } + + // Warning severity + if (persistence === 'HIGH' || explicitness > 0.6) { + return CONFLICT_SEVERITY.WARNING; + } + + // Minor severity + if (persistence === 'MEDIUM') { + return CONFLICT_SEVERITY.WARNING; + } + + return CONFLICT_SEVERITY.MINOR; + } + + _makeValidationDecision(conflicts, action) { + if (conflicts.length === 0) { + return this._approvedResult('No conflicts detected'); + } + + // Check for critical conflicts + const criticalConflicts = conflicts.filter(c => c.severity === CONFLICT_SEVERITY.CRITICAL); + + if (criticalConflicts.length > 0) { + return this._rejectedResult(criticalConflicts, action); + } + + // Check for warning-level conflicts + const warningConflicts = conflicts.filter(c => c.severity === CONFLICT_SEVERITY.WARNING); + + if (warningConflicts.length > 0) { + return this._warningResult(warningConflicts, action); + } + + // Only minor conflicts + return this._approvedResult( + 'Minor conflicts resolved in favor of user instruction', + conflicts + ); + } + + _approvedResult(message, conflicts = []) { + return { + status: VALIDATION_STATUS.APPROVED, + message, + conflicts, + action: 'PROCEED', + timestamp: new Date() + }; + } + + _warningResult(conflicts, action) { + const primaryConflict = conflicts[0]; + const timeAgo = this._formatTimeAgo(primaryConflict.instruction.timestamp); + + return { + status: VALIDATION_STATUS.WARNING, + message: `Potential conflict in parameter '${primaryConflict.parameter}': ` + + `action uses '${primaryConflict.actionValue}' but user instruction ` + + `specified '${primaryConflict.instructionValue}' (${timeAgo} ago)`, + conflicts, + action: 'NOTIFY_USER', + recommendation: `Consider using '${primaryConflict.instructionValue}' instead`, + timestamp: new Date() + }; + } + + _rejectedResult(conflicts, action) { + const primaryConflict = conflicts[0]; + const timeAgo = this._formatTimeAgo(primaryConflict.instruction.timestamp); + + return { + status: VALIDATION_STATUS.REJECTED, + message: `CRITICAL CONFLICT: Action parameter '${primaryConflict.parameter}' ` + + `uses '${primaryConflict.actionValue}' but user explicitly specified ` + + `'${primaryConflict.instructionValue}' ${timeAgo} ago`, + conflicts, + action: 'REQUEST_CLARIFICATION', + recommendation: `Verify with user before proceeding`, + instructionQuote: primaryConflict.instruction.text, + requiredValue: primaryConflict.instructionValue, + timestamp: new Date(), + userPrompt: `I noticed a conflict:\n\n` + + `You instructed: "${primaryConflict.instruction.text}"\n` + + `But my proposed action would use ${primaryConflict.parameter}: ${primaryConflict.actionValue}\n\n` + + `Should I use ${primaryConflict.instructionValue} as you specified, or ${primaryConflict.actionValue}?` + }; + } + + _escalateResult(message) { + return { + status: VALIDATION_STATUS.ESCALATE, + message, + action: 'REQUIRE_HUMAN_REVIEW', + timestamp: new Date() + }; + } + + _formatTimeAgo(timestamp) { + const seconds = Math.floor((new Date() - new Date(timestamp)) / 1000); + + if (seconds < 60) return `${seconds} seconds`; + if (seconds < 3600) return `${Math.floor(seconds / 60)} minutes`; + if (seconds < 86400) return `${Math.floor(seconds / 3600)} hours`; + return `${Math.floor(seconds / 86400)} days`; + } +} + +// Singleton instance +const validator = new CrossReferenceValidator(); + +module.exports = validator; diff --git a/src/services/InstructionPersistenceClassifier.service.js b/src/services/InstructionPersistenceClassifier.service.js new file mode 100644 index 00000000..7a192766 --- /dev/null +++ b/src/services/InstructionPersistenceClassifier.service.js @@ -0,0 +1,449 @@ +/** + * Instruction Persistence Classifier Service + * Classifies actions and instructions by quadrant and persistence level + * + * Core Tractatus Service: Implements time-persistence metadata tagging + * to ensure AI actions are verified according to instruction permanence. + * + * Prevents the "27027 failure mode" where explicit instructions are + * overridden by cached patterns. + */ + +const logger = require('../utils/logger.util'); + +/** + * Quadrant definitions from Tractatus framework + */ +const QUADRANTS = { + STRATEGIC: { + name: 'Strategic', + timeHorizon: 'years', + persistence: 'HIGH', + description: 'Values, mission, long-term direction', + keywords: ['always', 'never', 'core', 'values', 'mission', 'principle', 'philosophy'], + verificationLevel: 'MANDATORY', + humanOversight: 'VALUES_STEWARDSHIP', + examples: ['Always prioritize privacy', 'Never compromise user sovereignty'] + }, + OPERATIONAL: { + name: 'Operational', + timeHorizon: 'months', + persistence: 'MEDIUM-HIGH', + description: 'Processes, policies, project-level decisions', + keywords: ['project', 'process', 'policy', 'workflow', 'standard', 'convention'], + verificationLevel: 'REQUIRED', + humanOversight: 'PROCESS_STEWARDSHIP', + examples: ['For this project, use React', 'All blog posts must cite sources'] + }, + TACTICAL: { + name: 'Tactical', + timeHorizon: 'weeks', + persistence: 'VARIABLE', + description: 'Implementation decisions, immediate actions', + keywords: ['now', 'today', 'this', 'current', 'immediate', 'check', 'verify'], + verificationLevel: 'CONTEXT_DEPENDENT', + humanOversight: 'IMPLEMENTATION_EXPERTISE', + examples: ['Check port 27027', 'Use this API key for testing'] + }, + SYSTEM: { + name: 'System', + timeHorizon: 'continuous', + persistence: 'HIGH', + description: 'Technical infrastructure, architecture', + keywords: ['code', 'technical', 'architecture', 'infrastructure', 'database', 'api'], + verificationLevel: 'TECHNICAL_REVIEW', + humanOversight: 'TECHNICAL_EXPERTISE', + examples: ['MongoDB port is 27017', 'Use JWT for authentication'] + }, + STOCHASTIC: { + name: 'Stochastic', + timeHorizon: 'variable', + persistence: 'CONTEXT_DEPENDENT', + description: 'Innovation, exploration, experimentation', + keywords: ['explore', 'experiment', 'innovate', 'brainstorm', 'creative', 'try'], + verificationLevel: 'OPTIONAL', + humanOversight: 'INSIGHT_GENERATION', + examples: ['Explore alternative approaches', 'Suggest creative solutions'] + } +}; + +/** + * Persistence levels + */ +const PERSISTENCE_LEVELS = { + HIGH: { + score: 0.9, + verificationRequired: true, + description: 'Must be followed exactly', + conflictSeverity: 'CRITICAL' + }, + MEDIUM: { + score: 0.6, + verificationRequired: true, + description: 'Should be followed with flexibility', + conflictSeverity: 'WARNING' + }, + LOW: { + score: 0.3, + verificationRequired: false, + description: 'Guidance only, context-dependent', + conflictSeverity: 'MINOR' + }, + VARIABLE: { + score: 0.5, + verificationRequired: true, // Context-dependent + description: 'Depends on explicitness and recency', + conflictSeverity: 'CONTEXT_DEPENDENT' + } +}; + +class InstructionPersistenceClassifier { + constructor() { + this.quadrants = QUADRANTS; + this.persistenceLevels = PERSISTENCE_LEVELS; + + // Compile keyword patterns for efficient matching + this.keywordPatterns = this._compileKeywordPatterns(); + + logger.info('InstructionPersistenceClassifier initialized'); + } + + /** + * Classify an instruction or action + * @param {Object} params + * @param {string} params.text - The instruction text + * @param {Object} params.context - Conversation context + * @param {Date} params.timestamp - When instruction was given + * @param {string} params.source - Source of instruction (user/system/inferred) + * @returns {Object} Classification metadata + */ + classify({ text, context = {}, timestamp = new Date(), source = 'user' }) { + try { + // Normalize text + const normalizedText = text.toLowerCase().trim(); + + // Extract temporal indicators + const temporalScope = this._extractTemporalScope(normalizedText); + + // Determine quadrant + const quadrant = this._determineQuadrant(normalizedText, context, temporalScope); + + // Measure explicitness + const explicitness = this._measureExplicitness(normalizedText, source); + + // Calculate persistence level + const persistence = this._calculatePersistence({ + quadrant, + temporalScope, + explicitness, + source, + text: normalizedText + }); + + // Determine verification requirements + const verification = this._determineVerification({ + quadrant, + persistence, + explicitness, + source + }); + + // Extract parameters + const parameters = this._extractParameters(normalizedText); + + // Calculate recency weight (decays over time) + const recencyWeight = this._calculateRecencyWeight(timestamp); + + const classification = { + text, + quadrant, + quadrantInfo: this.quadrants[quadrant], + persistence, + persistenceScore: this.persistenceLevels[persistence].score, + explicitness, + verification, + parameters, + timestamp, + source, + recencyWeight, + metadata: { + temporalScope, + humanOversight: this.quadrants[quadrant].humanOversight, + conflictSeverity: this.persistenceLevels[persistence].conflictSeverity + } + }; + + logger.debug('Instruction classified', { + text: text.substring(0, 50), + quadrant, + persistence, + verification + }); + + return classification; + + } catch (error) { + logger.error('Classification error:', error); + // Return safe default classification + return this._defaultClassification(text, timestamp); + } + } + + /** + * Classify multiple instructions in batch + */ + classifyBatch(instructions) { + return instructions.map(inst => this.classify(inst)); + } + + /** + * Calculate relevance of an instruction to an action + * Used by CrossReferenceValidator + */ + calculateRelevance(instruction, action) { + try { + // Semantic similarity (simple keyword overlap for now) + const semantic = this._semanticSimilarity(instruction.text, action.description); + + // Temporal proximity + const temporal = instruction.recencyWeight || 0.5; + + // Persistence weight + const persistence = instruction.persistenceScore || 0.5; + + // Explicitness weight + const explicitness = instruction.explicitness || 0.5; + + // Weighted combination + const relevance = ( + semantic * 0.4 + + temporal * 0.3 + + persistence * 0.2 + + explicitness * 0.1 + ); + + return Math.min(1.0, Math.max(0.0, relevance)); + + } catch (error) { + logger.error('Relevance calculation error:', error); + return 0.3; // Safe default + } + } + + /** + * Private methods + */ + + _compileKeywordPatterns() { + const patterns = {}; + for (const [quadrant, config] of Object.entries(this.quadrants)) { + patterns[quadrant] = config.keywords.map(kw => new RegExp(`\\b${kw}\\b`, 'i')); + } + return patterns; + } + + _extractTemporalScope(text) { + const scopes = { + PERMANENT: ['always', 'never', 'all', 'every', 'forever'], + PROJECT: ['project', 'this phase', 'going forward', 'from now on'], + IMMEDIATE: ['now', 'today', 'currently', 'right now', 'this'], + SESSION: ['session', 'conversation', 'while'] + }; + + for (const [scope, keywords] of Object.entries(scopes)) { + if (keywords.some(kw => text.includes(kw))) { + return scope; + } + } + + return 'IMMEDIATE'; // Default + } + + _determineQuadrant(text, context, temporalScope) { + // Score each quadrant + const scores = {}; + + for (const [quadrant, patterns] of Object.entries(this.keywordPatterns)) { + let score = 0; + + // Keyword matching + for (const pattern of patterns) { + if (pattern.test(text)) { + score += 1; + } + } + + // Temporal scope alignment + if (temporalScope === 'PERMANENT' && quadrant === 'STRATEGIC') score += 2; + if (temporalScope === 'PROJECT' && quadrant === 'OPERATIONAL') score += 2; + if (temporalScope === 'IMMEDIATE' && quadrant === 'TACTICAL') score += 2; + + // Context clues + if (context.domain === 'technical' && quadrant === 'SYSTEM') score += 1; + if (context.domain === 'innovation' && quadrant === 'STOCHASTIC') score += 1; + + scores[quadrant] = score; + } + + // Return highest scoring quadrant + const sorted = Object.entries(scores).sort((a, b) => b[1] - a[1]); + + // If no clear winner, default based on temporal scope + if (sorted[0][1] === 0) { + if (temporalScope === 'PERMANENT') return 'STRATEGIC'; + if (temporalScope === 'PROJECT') return 'OPERATIONAL'; + return 'TACTICAL'; + } + + return sorted[0][0]; + } + + _measureExplicitness(text, source) { + let score = 0.5; // Base score + + // Source factor + if (source === 'user') score += 0.2; + if (source === 'inferred') score -= 0.2; + + // Explicit markers + const explicitMarkers = [ + 'specifically', 'exactly', 'must', 'should', 'explicitly', + 'clearly', 'definitely', 'always', 'never', 'require' + ]; + + const markerCount = explicitMarkers.filter(marker => + text.includes(marker) + ).length; + + score += markerCount * 0.1; + + // Parameter specification (numbers, specific values) + if (/\d{4,}/.test(text)) score += 0.2; // Port numbers, dates, etc. + if (/["'][\w-]+["']/.test(text)) score += 0.1; // Quoted strings + + return Math.min(1.0, Math.max(0.0, score)); + } + + _calculatePersistence({ quadrant, temporalScope, explicitness, source, text }) { + // Base persistence from quadrant + let baseScore = { + STRATEGIC: 0.9, + OPERATIONAL: 0.7, + TACTICAL: 0.5, + SYSTEM: 0.6, + STOCHASTIC: 0.4 + }[quadrant]; + + // Adjust for temporal scope + if (temporalScope === 'PERMANENT') baseScore += 0.1; + if (temporalScope === 'SESSION') baseScore -= 0.2; + + // Adjust for explicitness + if (explicitness > 0.8) baseScore += 0.1; + + // Adjust for source + if (source === 'user') baseScore += 0.05; + if (source === 'inferred') baseScore -= 0.1; + + // Normalize + const score = Math.min(1.0, Math.max(0.0, baseScore)); + + // Map to categorical levels + if (score >= 0.75) return 'HIGH'; + if (score >= 0.5) return 'MEDIUM'; + if (quadrant === 'TACTICAL' && explicitness > 0.7) return 'VARIABLE'; // Explicit tactical + return 'LOW'; + } + + _determineVerification({ quadrant, persistence, explicitness, source }) { + // MANDATORY verification conditions + if (persistence === 'HIGH') return 'MANDATORY'; + if (quadrant === 'STRATEGIC') return 'MANDATORY'; + if (explicitness > 0.8 && source === 'user') return 'MANDATORY'; + + // REQUIRED verification conditions + if (persistence === 'MEDIUM') return 'REQUIRED'; + if (quadrant === 'OPERATIONAL') return 'REQUIRED'; + + // RECOMMENDED verification conditions + if (persistence === 'VARIABLE') return 'RECOMMENDED'; + if (quadrant === 'TACTICAL' && explicitness > 0.5) return 'RECOMMENDED'; + + // OPTIONAL for low-persistence stochastic + return 'OPTIONAL'; + } + + _extractParameters(text) { + const params = {}; + + // Port numbers + const portMatch = text.match(/port\s+(\d{4,5})/i); + if (portMatch) params.port = portMatch[1]; + + // URLs + const urlMatch = text.match(/https?:\/\/[\w.-]+(?::\d+)?/); + if (urlMatch) params.url = urlMatch[0]; + + // File paths + const pathMatch = text.match(/(?:\/[\w.-]+)+/); + if (pathMatch) params.path = pathMatch[0]; + + // API keys (redacted) + if (/api[_-]?key/i.test(text)) params.hasApiKey = true; + + // Database names + const dbMatch = text.match(/database\s+([\w-]+)/i); + if (dbMatch) params.database = dbMatch[1]; + + return params; + } + + _calculateRecencyWeight(timestamp) { + const now = new Date(); + const age = (now - new Date(timestamp)) / 1000; // seconds + + // Exponential decay: weight = e^(-age/halfLife) + const halfLife = 3600; // 1 hour + const weight = Math.exp(-age / halfLife); + + return Math.min(1.0, Math.max(0.0, weight)); + } + + _semanticSimilarity(text1, text2) { + // Simple keyword overlap similarity + const words1 = new Set(text1.toLowerCase().split(/\s+/).filter(w => w.length > 3)); + const words2 = new Set(text2.toLowerCase().split(/\s+/).filter(w => w.length > 3)); + + const intersection = new Set([...words1].filter(w => words2.has(w))); + const union = new Set([...words1, ...words2]); + + return union.size > 0 ? intersection.size / union.size : 0; + } + + _defaultClassification(text, timestamp) { + return { + text, + quadrant: 'TACTICAL', + quadrantInfo: this.quadrants.TACTICAL, + persistence: 'MEDIUM', + persistenceScore: 0.5, + explicitness: 0.5, + verification: 'RECOMMENDED', + parameters: {}, + timestamp, + source: 'unknown', + recencyWeight: 0.5, + metadata: { + temporalScope: 'IMMEDIATE', + humanOversight: 'IMPLEMENTATION_EXPERTISE', + conflictSeverity: 'WARNING', + error: 'Failed to classify, using safe defaults' + } + }; + } +} + +// Singleton instance +const classifier = new InstructionPersistenceClassifier(); + +module.exports = classifier; diff --git a/src/services/MetacognitiveVerifier.service.js b/src/services/MetacognitiveVerifier.service.js new file mode 100644 index 00000000..9d09c6a2 --- /dev/null +++ b/src/services/MetacognitiveVerifier.service.js @@ -0,0 +1,515 @@ +/** + * Metacognitive Verifier Service + * Implements AI self-verification before proposing actions + * + * Core Tractatus Service: Provides structured "pause and verify" mechanism + * where AI checks its own reasoning before execution. + * + * Verification Checks: + * 1. Alignment: Does action align with stated user goals? + * 2. Coherence: Is reasoning internally consistent? + * 3. Completeness: Are all requirements addressed? + * 4. Safety: Could this action cause harm or confusion? + * 5. Alternatives: Have better approaches been considered? + */ + +const classifier = require('./InstructionPersistenceClassifier.service'); +const validator = require('./CrossReferenceValidator.service'); +const enforcer = require('./BoundaryEnforcer.service'); +const monitor = require('./ContextPressureMonitor.service'); +const logger = require('../utils/logger.util'); + +/** + * Verification dimensions + */ +const VERIFICATION_DIMENSIONS = { + ALIGNMENT: { + name: 'Alignment', + description: 'Action aligns with user goals and explicit instructions', + weight: 0.3, + criticalThreshold: 0.7 + }, + COHERENCE: { + name: 'Coherence', + description: 'Reasoning is internally consistent and logical', + weight: 0.2, + criticalThreshold: 0.7 + }, + COMPLETENESS: { + name: 'Completeness', + description: 'All requirements and constraints addressed', + weight: 0.2, + criticalThreshold: 0.8 + }, + SAFETY: { + name: 'Safety', + description: 'Action will not cause harm, confusion, or data loss', + weight: 0.2, + criticalThreshold: 0.9 + }, + ALTERNATIVES: { + name: 'Alternatives', + description: 'Better alternative approaches have been considered', + weight: 0.1, + criticalThreshold: 0.6 + } +}; + +/** + * Confidence levels + */ +const CONFIDENCE_LEVELS = { + HIGH: { min: 0.8, action: 'PROCEED', description: 'High confidence, proceed' }, + MEDIUM: { min: 0.6, action: 'PROCEED_WITH_CAUTION', description: 'Medium confidence, proceed with notification' }, + LOW: { min: 0.4, action: 'REQUEST_CONFIRMATION', description: 'Low confidence, request user confirmation' }, + VERY_LOW: { min: 0.0, action: 'REQUIRE_REVIEW', description: 'Very low confidence, require human review' } +}; + +class MetacognitiveVerifier { + constructor() { + this.dimensions = VERIFICATION_DIMENSIONS; + this.confidenceLevels = CONFIDENCE_LEVELS; + this.classifier = classifier; + this.validator = validator; + this.enforcer = enforcer; + this.monitor = monitor; + + logger.info('MetacognitiveVerifier initialized'); + } + + /** + * Verify a proposed action before execution + * @param {Object} action - The proposed action + * @param {Object} reasoning - The reasoning behind the action + * @param {Object} context - Conversation/session context + * @returns {Object} Verification result + */ + verify(action, reasoning, context) { + try { + // Run all verification checks + const alignmentScore = this._checkAlignment(action, reasoning, context); + const coherenceScore = this._checkCoherence(action, reasoning, context); + const completenessScore = this._checkCompleteness(action, reasoning, context); + const safetyScore = this._checkSafety(action, reasoning, context); + const alternativesScore = this._checkAlternatives(action, reasoning, context); + + // Calculate weighted confidence score + const scores = { + alignment: alignmentScore, + coherence: coherenceScore, + completeness: completenessScore, + safety: safetyScore, + alternatives: alternativesScore + }; + + const confidence = this._calculateConfidence(scores); + + // Determine confidence level + const confidenceLevel = this._determineConfidenceLevel(confidence); + + // Check for critical failures + const criticalFailures = this._checkCriticalFailures(scores); + + // Get pressure analysis + const pressureAnalysis = this.monitor.analyzePressure(context); + + // Adjust confidence based on pressure + const adjustedConfidence = this._adjustForPressure( + confidence, + pressureAnalysis + ); + + // Generate verification result + const verification = { + confidence: adjustedConfidence, + originalConfidence: confidence, + level: confidenceLevel.action, + description: confidenceLevel.description, + scores, + criticalFailures, + pressureLevel: pressureAnalysis.pressureName, + pressureAdjustment: adjustedConfidence - confidence, + recommendations: this._generateRecommendations( + scores, + criticalFailures, + pressureAnalysis + ), + decision: this._makeVerificationDecision( + adjustedConfidence, + criticalFailures, + pressureAnalysis + ), + timestamp: new Date() + }; + + // Log verification + if (verification.decision !== 'PROCEED') { + logger.warn('Action verification flagged', { + action: action.description?.substring(0, 50), + decision: verification.decision, + confidence: adjustedConfidence + }); + } + + return verification; + + } catch (error) { + logger.error('Verification error:', error); + return this._failSafeVerification(action); + } + } + + /** + * Quick verification for low-risk actions + */ + quickVerify(action, context) { + // Simplified verification for routine actions + const boundaryCheck = this.enforcer.enforce(action, context); + const pressureCheck = this.monitor.shouldProceed(action, context); + + if (!boundaryCheck.allowed || !pressureCheck.proceed) { + return { + confidence: 0.3, + level: 'REQUIRE_REVIEW', + decision: 'BLOCK', + reason: 'Failed boundary or pressure check', + timestamp: new Date() + }; + } + + return { + confidence: 0.7, + level: 'PROCEED', + decision: 'PROCEED', + quickCheck: true, + timestamp: new Date() + }; + } + + /** + * Private verification methods + */ + + _checkAlignment(action, reasoning, context) { + let score = 0.5; // Base score + + // Check cross-reference validation + const validation = this.validator.validate(action, context); + if (validation.status === 'APPROVED') { + score += 0.3; + } else if (validation.status === 'WARNING') { + score += 0.1; + } else if (validation.status === 'REJECTED') { + score -= 0.3; + } + + // Check if action addresses stated user goal + if (reasoning.userGoal && reasoning.addresses) { + score += 0.2; + } + + // Check consistency with recent user statements + if (context.recentUserStatements) { + const consistencyScore = this._checkConsistencyWithStatements( + action, + context.recentUserStatements + ); + score += consistencyScore * 0.2; + } + + return Math.min(1.0, Math.max(0.0, score)); + } + + _checkCoherence(action, reasoning, context) { + let score = 0.7; // Default to reasonable coherence + + // Check if reasoning steps are provided + if (!reasoning.steps || reasoning.steps.length === 0) { + score -= 0.2; + } + + // Check for logical consistency + if (reasoning.assumptions && reasoning.conclusions) { + const logicallySound = this._checkLogicalFlow( + reasoning.assumptions, + reasoning.conclusions + ); + if (logicallySound) { + score += 0.2; + } else { + score -= 0.3; + } + } + + // Check for internal contradictions + if (this._hasContradictions(reasoning)) { + score -= 0.4; + } + + return Math.min(1.0, Math.max(0.0, score)); + } + + _checkCompleteness(action, reasoning, context) { + let score = 0.6; // Base score + + // Check if all stated requirements are addressed + if (context.requirements) { + const addressedCount = context.requirements.filter(req => + this._isRequirementAddressed(req, action, reasoning) + ).length; + score += (addressedCount / context.requirements.length) * 0.3; + } + + // Check for edge cases consideration + if (reasoning.edgeCases && reasoning.edgeCases.length > 0) { + score += 0.1; + } + + // Check for error handling + if (reasoning.errorHandling || action.errorHandling) { + score += 0.1; + } + + return Math.min(1.0, Math.max(0.0, score)); + } + + _checkSafety(action, reasoning, context) { + let score = 0.8; // Default to safe unless red flags + + // Check boundary enforcement + const boundaryCheck = this.enforcer.enforce(action, context); + if (!boundaryCheck.allowed) { + score -= 0.5; // Major safety concern + } + + // Check for destructive operations + const destructivePatterns = [ + /delete|remove|drop|truncate/i, + /force|--force|-f\s/i, + /rm\s+-rf/i + ]; + + const actionText = action.description || action.command || ''; + for (const pattern of destructivePatterns) { + if (pattern.test(actionText)) { + score -= 0.2; + break; + } + } + + // Check if data backup is mentioned for risky operations + if (score < 0.7 && !reasoning.backupMentioned) { + score -= 0.1; + } + + // Check for validation before execution + if (action.requiresValidation && !reasoning.validationPlanned) { + score -= 0.1; + } + + return Math.min(1.0, Math.max(0.0, score)); + } + + _checkAlternatives(action, reasoning, context) { + let score = 0.5; // Base score + + // Check if alternatives were considered + if (reasoning.alternativesConsidered && reasoning.alternativesConsidered.length > 0) { + score += 0.3; + } + + // Check if rationale for chosen approach is provided + if (reasoning.chosenBecause) { + score += 0.2; + } + + // Lower score if action seems like first idea without exploration + if (!reasoning.alternativesConsidered && !reasoning.explored) { + score -= 0.2; + } + + return Math.min(1.0, Math.max(0.0, score)); + } + + _calculateConfidence(scores) { + let confidence = 0; + + for (const [dimension, dimensionConfig] of Object.entries(this.dimensions)) { + const key = dimension.toLowerCase(); + const score = scores[key] || 0.5; + confidence += score * dimensionConfig.weight; + } + + return Math.min(1.0, Math.max(0.0, confidence)); + } + + _determineConfidenceLevel(confidence) { + if (confidence >= CONFIDENCE_LEVELS.HIGH.min) { + return CONFIDENCE_LEVELS.HIGH; + } + if (confidence >= CONFIDENCE_LEVELS.MEDIUM.min) { + return CONFIDENCE_LEVELS.MEDIUM; + } + if (confidence >= CONFIDENCE_LEVELS.LOW.min) { + return CONFIDENCE_LEVELS.LOW; + } + return CONFIDENCE_LEVELS.VERY_LOW; + } + + _checkCriticalFailures(scores) { + const failures = []; + + for (const [dimension, config] of Object.entries(this.dimensions)) { + const key = dimension.toLowerCase(); + const score = scores[key]; + + if (score < config.criticalThreshold) { + failures.push({ + dimension: config.name, + score, + threshold: config.criticalThreshold, + severity: score < 0.3 ? 'CRITICAL' : 'WARNING' + }); + } + } + + return failures; + } + + _adjustForPressure(confidence, pressureAnalysis) { + // Reduce confidence based on pressure level + const pressureReduction = { + NORMAL: 0, + ELEVATED: 0.05, + HIGH: 0.10, + CRITICAL: 0.15, + DANGEROUS: 0.25 + }; + + const reduction = pressureReduction[pressureAnalysis.pressureName] || 0; + return Math.max(0.0, confidence - reduction); + } + + _generateRecommendations(scores, criticalFailures, pressureAnalysis) { + const recommendations = []; + + // Recommendations based on low scores + for (const [key, score] of Object.entries(scores)) { + if (score < 0.5) { + const dimension = this.dimensions[key.toUpperCase()]; + recommendations.push({ + type: 'LOW_SCORE', + dimension: dimension.name, + score, + message: `Low ${dimension.name.toLowerCase()} score - ${dimension.description}`, + action: `Improve ${dimension.name.toLowerCase()} before proceeding` + }); + } + } + + // Recommendations based on critical failures + for (const failure of criticalFailures) { + recommendations.push({ + type: 'CRITICAL_FAILURE', + dimension: failure.dimension, + severity: failure.severity, + message: `${failure.dimension} below critical threshold`, + action: 'Address this issue before proceeding' + }); + } + + // Include pressure recommendations + if (pressureAnalysis.recommendations) { + recommendations.push(...pressureAnalysis.recommendations); + } + + return recommendations; + } + + _makeVerificationDecision(confidence, criticalFailures, pressureAnalysis) { + // Block if critical failures + if (criticalFailures.some(f => f.severity === 'CRITICAL')) { + return 'BLOCK'; + } + + // Block if dangerous pressure + if (pressureAnalysis.pressureLevel >= 4) { + return 'BLOCK'; + } + + // Require review if very low confidence + if (confidence < 0.4) { + return 'REQUIRE_REVIEW'; + } + + // Request confirmation if low confidence + if (confidence < 0.6) { + return 'REQUEST_CONFIRMATION'; + } + + // Proceed with caution if medium confidence + if (confidence < 0.8) { + return 'PROCEED_WITH_CAUTION'; + } + + // Proceed if high confidence + return 'PROCEED'; + } + + /** + * Helper methods + */ + + _checkConsistencyWithStatements(action, statements) { + // Simplified consistency check + return 0.5; // Default to neutral + } + + _checkLogicalFlow(assumptions, conclusions) { + // Simplified logical flow check + return true; // Assume logical unless obviously not + } + + _hasContradictions(reasoning) { + // Simplified contradiction detection + return false; // Assume no contradictions unless detected + } + + _isRequirementAddressed(requirement, action, reasoning) { + // Simplified requirement matching + const actionText = (action.description || '').toLowerCase(); + const requirementText = requirement.toLowerCase(); + return actionText.includes(requirementText); + } + + _failSafeVerification(action) { + return { + confidence: 0.3, + originalConfidence: 0.3, + level: 'REQUIRE_REVIEW', + description: 'Verification failed, requiring human review', + scores: {}, + criticalFailures: [{ + dimension: 'ERROR', + score: 0, + threshold: 1, + severity: 'CRITICAL' + }], + pressureLevel: 'ELEVATED', + pressureAdjustment: 0, + recommendations: [{ + type: 'ERROR', + severity: 'CRITICAL', + message: 'Verification process encountered error', + action: 'Require human review before proceeding' + }], + decision: 'REQUIRE_REVIEW', + timestamp: new Date() + }; + } +} + +// Singleton instance +const verifier = new MetacognitiveVerifier(); + +module.exports = verifier; diff --git a/src/services/index.js b/src/services/index.js new file mode 100644 index 00000000..ca9c8b18 --- /dev/null +++ b/src/services/index.js @@ -0,0 +1,64 @@ +/** + * Tractatus Governance Services + * Core AI safety framework implementation + * + * These services implement the Tractatus-based LLM safety architecture: + * - Time-persistence metadata classification + * - Cross-reference validation against explicit instructions + * - Architectural boundaries for human judgment + * - Context pressure monitoring + * - Metacognitive verification + * + * Together, these services prevent AI failures like the "27027 incident" + * where explicit instructions are overridden by cached patterns. + */ + +const InstructionPersistenceClassifier = require('./InstructionPersistenceClassifier.service'); +const CrossReferenceValidator = require('./CrossReferenceValidator.service'); +const BoundaryEnforcer = require('./BoundaryEnforcer.service'); +const ContextPressureMonitor = require('./ContextPressureMonitor.service'); +const MetacognitiveVerifier = require('./MetacognitiveVerifier.service'); + +module.exports = { + // Core governance services + classifier: InstructionPersistenceClassifier, + validator: CrossReferenceValidator, + enforcer: BoundaryEnforcer, + monitor: ContextPressureMonitor, + verifier: MetacognitiveVerifier, + + // Convenience methods + classifyInstruction: (instruction) => InstructionPersistenceClassifier.classify(instruction), + validateAction: (action, context) => CrossReferenceValidator.validate(action, context), + enforceBoundaries: (action, context) => BoundaryEnforcer.enforce(action, context), + analyzePressure: (context) => ContextPressureMonitor.analyzePressure(context), + verifyAction: (action, reasoning, context) => MetacognitiveVerifier.verify(action, reasoning, context), + + // Framework status + getFrameworkStatus: () => ({ + name: 'Tractatus Governance Framework', + version: '1.0.0', + services: { + InstructionPersistenceClassifier: 'operational', + CrossReferenceValidator: 'operational', + BoundaryEnforcer: 'operational', + ContextPressureMonitor: 'operational', + MetacognitiveVerifier: 'operational' + }, + description: 'AI safety framework implementing architectural constraints for human agency preservation', + capabilities: [ + 'Instruction quadrant classification (STR/OPS/TAC/SYS/STO)', + 'Time-persistence metadata tagging', + 'Cross-reference validation', + 'Tractatus boundary enforcement (12.1-12.7)', + 'Context pressure monitoring', + 'Metacognitive action verification' + ], + safetyGuarantees: [ + 'Values decisions architecturally require human judgment', + 'Explicit instructions override cached patterns', + 'Dangerous pressure conditions block execution', + 'Low-confidence actions require confirmation' + ] + }) +};