diff --git a/src/services/ContextPressureMonitor.service.js b/src/services/ContextPressureMonitor.service.js index 32d94972..bd0a5787 100644 --- a/src/services/ContextPressureMonitor.service.js +++ b/src/services/ContextPressureMonitor.service.js @@ -21,35 +21,35 @@ const logger = require('../utils/logger.util'); const PRESSURE_LEVELS = { NORMAL: { level: 0, - threshold: 0.3, + threshold: 0.0, // 0-30%: Normal operations description: 'Normal operating conditions', action: 'PROCEED', verificationMultiplier: 1.0 }, ELEVATED: { level: 1, - threshold: 0.5, + threshold: 0.3, // 30-50%: Increased verification recommended description: 'Elevated pressure, increased verification recommended', action: 'INCREASE_VERIFICATION', verificationMultiplier: 1.3 }, HIGH: { level: 2, - threshold: 0.7, + threshold: 0.5, // 50-70%: Mandatory verification required description: 'High pressure, mandatory verification required', action: 'MANDATORY_VERIFICATION', verificationMultiplier: 1.6 }, CRITICAL: { level: 3, - threshold: 0.85, + threshold: 0.7, // 70-85%: Recommend context refresh description: 'Critical pressure, recommend context refresh', action: 'RECOMMEND_REFRESH', verificationMultiplier: 2.0 }, DANGEROUS: { level: 4, - threshold: 0.95, + threshold: 0.85, // 85-100%: Require human intervention description: 'Dangerous conditions, require human intervention', action: 'REQUIRE_HUMAN_INTERVENTION', verificationMultiplier: 3.0 @@ -450,7 +450,8 @@ class ContextPressureMonitor { } _calculateOverallPressure(metricScores) { - // Calculate weighted average + // Calculate weighted average based on configured weights + // This properly prioritizes token usage (35%) over other metrics let weightedPressure = 0; weightedPressure += metricScores.tokenUsage.normalized * this.metrics.TOKEN_USAGE.weight; weightedPressure += metricScores.conversationLength.normalized * this.metrics.CONVERSATION_LENGTH.weight; @@ -458,21 +459,9 @@ class ContextPressureMonitor { weightedPressure += metricScores.errorFrequency.normalized * this.metrics.ERROR_FREQUENCY.weight; weightedPressure += metricScores.instructionDensity.normalized * this.metrics.INSTRUCTION_DENSITY.weight; - // Also check maximum of any single metric (safety-first approach) - // If ANY metric is critically high, overall pressure should reflect that - const maxMetric = Math.max( - metricScores.tokenUsage.normalized, - metricScores.conversationLength.normalized, - metricScores.taskComplexity.normalized, - metricScores.errorFrequency.normalized, - metricScores.instructionDensity.normalized - ); - - // Use the higher of weighted average or max single metric - // This ensures a single critical metric triggers appropriate pressure level - const pressure = Math.max(weightedPressure, maxMetric); - - return Math.min(1.0, Math.max(0.0, pressure)); + // Use weighted average as the pressure score + // The configured weights already reflect relative importance of each metric + return Math.min(1.0, Math.max(0.0, weightedPressure)); } _generateRecommendations(pressureLevel, metricScores, context) { diff --git a/src/services/MetacognitiveVerifier.service.js b/src/services/MetacognitiveVerifier.service.js index 3b106aa3..2f8137e2 100644 --- a/src/services/MetacognitiveVerifier.service.js +++ b/src/services/MetacognitiveVerifier.service.js @@ -427,22 +427,26 @@ class MetacognitiveVerifier { let score = 0.5; // Base score const issues = []; + // Support both camelCase and snake_case for alternatives + const alternatives = reasoning.alternativesConsidered || reasoning.alternatives_considered; + const explored = reasoning.explored; + // Check if alternatives were considered - if (reasoning.alternativesConsidered && reasoning.alternativesConsidered.length > 0) { + if (alternatives && alternatives.length > 0) { score += 0.3; } else { issues.push('No alternatives considered'); } // Check if rationale for chosen approach is provided - if (reasoning.chosenBecause) { + if (reasoning.chosenBecause || reasoning.chosen_because) { score += 0.2; } else { issues.push('No rationale provided for chosen approach'); } // Lower score if action seems like first idea without exploration - if (!reasoning.alternativesConsidered && !reasoning.explored) { + if (!alternatives && !explored) { score -= 0.2; issues.push('Appears to be first idea without exploration'); } @@ -624,26 +628,19 @@ class MetacognitiveVerifier { _checkParameterConflicts(parameters, reasoning) { // Check if parameter values in action conflict with reasoning + // Only flag conflicts for explicit parameter assignments, not casual mentions const reasoningText = (reasoning.explanation || '') + ' ' + (reasoning.evidence || []).join(' '); for (const [key, value] of Object.entries(parameters)) { - // Extract values mentioned in reasoning const valueStr = String(value); - // Check if reasoning mentions a different value for this parameter - // For example: action has port 27017, reasoning says "port 27027" - if (key === 'port' && /port\s+(\d+)/.test(reasoningText)) { - const match = reasoningText.match(/port\s+(\d+)/); - if (match && match[1] !== valueStr) { - return true; // Conflict detected - } - } - - // Check for explicit mentions of different values - const keyPattern = new RegExp(`\\b${key}[:\\s]+([\\w-]+)`, 'i'); + // Check for explicit parameter assignments only (key: value or key = value) + // Pattern matches "port: 27017" or "port = 27017" but not "port read" + const keyPattern = new RegExp(`\\b${key}\\s*[:=]\\s*([\\w.-]+)`, 'i'); const match = reasoningText.match(keyPattern); + if (match && match[1] !== valueStr) { - return true; // Conflict detected + return true; // Conflict: reasoning explicitly assigns different value } }