SUMMARY: Implemented 6 framework refinements identified from incident analysis (inst_049 and inst_025 violations). These enhancements provide architectural enforcement for patterns that previously relied on voluntary compliance. ENHANCEMENTS IMPLEMENTED: 1. Instruction Analytics Script (Priority 8) - scripts/analyze-instruction-violations.js - Analyzes instruction-history.json for usage patterns - Identifies most violated instructions - Calculates enforcement effectiveness (hook vs. voluntary) - Shows 97.2% voluntary compliance, 75% hook enforcement - Recommendations for converting voluntary → architectural 2. Framework Incidents Database (Priority 7) - .claude/framework-incidents.json - Structured tracking of framework violations - INC-001: Ignored user hypothesis (70k tokens wasted) - INC-002: Deployment directory flattening (inst_025 violation) - Statistics: 2 incidents, 75k tokens wasted, 4.5 hours lost 3. Loop Detector Module (Priorities 3 & 4) - scripts/framework-components/LoopDetector.js - Detects "stuck in loop" patterns - Triggers: 3+ edits to same file, repeated action types - Feeds into MetacognitiveVerifier and ContextPressureMonitor - Calculates pressure contribution (5-40 points by severity) 4. Action Pattern Tracker (Priority 3 & 4) - scripts/track-action-patterns.js - Tracks edit/write actions to detect repetition - Alerts after 3 consecutive edits to same file - Maintains action history (last 100 actions) - Recommendations for metacognitive verification 5. Pre-Deployment Validation (Priority 5) - scripts/validate-deployment.js - Validates rsync/scp commands against inst_025 - Detects directory structure flattening - Suggests separate commands for different directories - Prevents 4th documented occurrence of deployment errors 6. User Suggestion Tracker (Priority 6) - scripts/track-user-suggestions.js - Implements inst_049: "Test user hypothesis first" - Tracks user technical hypotheses - Flags untested hypotheses as HIGH priority - Integrates with MetacognitiveVerifier for compliance USAGE: Instruction Analytics: node scripts/analyze-instruction-violations.js Loop Detection: node scripts/track-action-patterns.js --check node scripts/track-action-patterns.js --summary Deployment Validation: node scripts/validate-deployment.js --command "rsync ..." User Suggestions: node scripts/track-user-suggestions.js --add "hypothesis text" node scripts/track-user-suggestions.js --check-untested IMPACT: - Converts 6 voluntary compliance patterns to architectural enforcement - Prevents repeat of documented 75k token waste - Provides visibility into framework effectiveness - Establishes foundation for future hook integration METRICS FROM ANALYTICS: - Active Instructions: 40 - Voluntary Compliance: 97.2% - Hook Enforcement: 75.0% - Recorded Violations: 2 - Tokens Wasted: 75,000 NEXT STEPS: - Integrate LoopDetector into MetacognitiveVerifier.service.js - Add Pre-Deployment Validation to Bash command validator hook - Wire User Suggestion Tracker into BoundaryEnforcer checks - Document successful compliance patterns (7 STRATEGIC instructions at 100%) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
233 lines
5.8 KiB
JavaScript
233 lines
5.8 KiB
JavaScript
/**
|
|
* Loop Detector
|
|
*
|
|
* Detects "stuck in loop" patterns that indicate:
|
|
* - Repeated failed attempts on same problem
|
|
* - Same file being edited multiple times without progress
|
|
* - User frustration signals
|
|
*
|
|
* Used by:
|
|
* - MetacognitiveVerifier (triggers verification on loop detection)
|
|
* - ContextPressureMonitor (elevates pressure on loop detection)
|
|
*
|
|
* Copyright 2025 Tractatus Project
|
|
* Licensed under Apache License 2.0
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
class LoopDetector {
|
|
constructor(options = {}) {
|
|
this.silent = options.silent || false;
|
|
this.actionPatternsPath = path.join(__dirname, '../../.claude/action-patterns.json');
|
|
this.sessionStatePath = path.join(__dirname, '../../.claude/session-state.json');
|
|
|
|
// Thresholds
|
|
this.thresholds = {
|
|
same_file_edits: 3, // Alert after 3 edits to same file
|
|
consecutive_actions: 5, // Within last 5 actions
|
|
user_frustration_phrases: [
|
|
'you ignored me',
|
|
'i told you',
|
|
'not working',
|
|
'still broken',
|
|
'same error',
|
|
'again',
|
|
'why are you'
|
|
]
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Load action patterns
|
|
*/
|
|
loadActionPatterns() {
|
|
try {
|
|
if (fs.existsSync(this.actionPatternsPath)) {
|
|
return JSON.parse(fs.readFileSync(this.actionPatternsPath, 'utf8'));
|
|
}
|
|
} catch (err) {
|
|
if (!this.silent) {
|
|
console.warn(`LoopDetector: Could not load action patterns: ${err.message}`);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Detect loops based on action patterns
|
|
*/
|
|
detectLoop() {
|
|
const patterns = this.loadActionPatterns();
|
|
if (!patterns || !patterns.actions || patterns.actions.length === 0) {
|
|
return {
|
|
detected: false,
|
|
type: null,
|
|
severity: 'NONE',
|
|
details: null
|
|
};
|
|
}
|
|
|
|
// Check 1: Repeated file edits
|
|
const fileEditLoop = this.detectRepeatedFileEdits(patterns);
|
|
if (fileEditLoop.detected) {
|
|
return fileEditLoop;
|
|
}
|
|
|
|
// Check 2: Same action type repeated
|
|
const actionLoop = this.detectRepeatedActionType(patterns);
|
|
if (actionLoop.detected) {
|
|
return actionLoop;
|
|
}
|
|
|
|
// Check 3: User frustration signals (would need message history)
|
|
// TODO: Implement if message history tracking is added
|
|
|
|
return {
|
|
detected: false,
|
|
type: null,
|
|
severity: 'NONE',
|
|
details: null
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Detect repeated edits to same file
|
|
*/
|
|
detectRepeatedFileEdits(patterns) {
|
|
const recentActions = patterns.actions.slice(-this.thresholds.consecutive_actions);
|
|
|
|
// Group by file
|
|
const fileGroups = {};
|
|
recentActions.forEach(action => {
|
|
if (action.type === 'edit' || action.type === 'write') {
|
|
if (!fileGroups[action.file]) {
|
|
fileGroups[action.file] = [];
|
|
}
|
|
fileGroups[action.file].push(action);
|
|
}
|
|
});
|
|
|
|
// Check for files edited multiple times
|
|
for (const [file, actions] of Object.entries(fileGroups)) {
|
|
if (actions.length >= this.thresholds.same_file_edits) {
|
|
return {
|
|
detected: true,
|
|
type: 'repeated_file_edit',
|
|
severity: 'MEDIUM',
|
|
details: {
|
|
file: file,
|
|
count: actions.length,
|
|
recent_count: actions.length,
|
|
message: `File edited ${actions.length} times in last ${this.thresholds.consecutive_actions} actions`,
|
|
recommendation: 'Pause and run MetacognitiveVerifier to assess approach'
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
return { detected: false };
|
|
}
|
|
|
|
/**
|
|
* Detect repeated action type (e.g., multiple failed bash commands)
|
|
*/
|
|
detectRepeatedActionType(patterns) {
|
|
const recentActions = patterns.actions.slice(-this.thresholds.consecutive_actions);
|
|
|
|
// Count consecutive actions of same type
|
|
let consecutiveCount = 1;
|
|
let currentType = null;
|
|
|
|
for (let i = recentActions.length - 1; i >= 0; i--) {
|
|
const action = recentActions[i];
|
|
if (currentType === null) {
|
|
currentType = action.type;
|
|
} else if (action.type === currentType) {
|
|
consecutiveCount++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (consecutiveCount >= 3) {
|
|
return {
|
|
detected: true,
|
|
type: 'repeated_action_type',
|
|
severity: 'LOW',
|
|
details: {
|
|
action_type: currentType,
|
|
count: consecutiveCount,
|
|
message: `${consecutiveCount} consecutive ${currentType} actions`,
|
|
recommendation: 'Consider if current approach is effective'
|
|
}
|
|
};
|
|
}
|
|
|
|
return { detected: false };
|
|
}
|
|
|
|
/**
|
|
* Get loop status for MetacognitiveVerifier
|
|
*/
|
|
getLoopStatus() {
|
|
const loop = this.detectLoop();
|
|
|
|
if (!loop.detected) {
|
|
return {
|
|
in_loop: false,
|
|
should_verify: false
|
|
};
|
|
}
|
|
|
|
return {
|
|
in_loop: true,
|
|
should_verify: loop.severity === 'MEDIUM' || loop.severity === 'HIGH',
|
|
loop_type: loop.type,
|
|
severity: loop.severity,
|
|
details: loop.details
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Calculate pressure contribution for ContextPressureMonitor
|
|
*/
|
|
calculatePressureContribution() {
|
|
const loop = this.detectLoop();
|
|
|
|
if (!loop.detected) {
|
|
return 0;
|
|
}
|
|
|
|
// Pressure contribution based on severity
|
|
const pressureMap = {
|
|
'LOW': 5,
|
|
'MEDIUM': 15,
|
|
'HIGH': 25,
|
|
'CRITICAL': 40
|
|
};
|
|
|
|
return pressureMap[loop.severity] || 0;
|
|
}
|
|
|
|
/**
|
|
* Log loop detection result
|
|
*/
|
|
log(message, level = 'info') {
|
|
if (this.silent) return;
|
|
|
|
const colors = {
|
|
info: '\x1b[36m',
|
|
warn: '\x1b[33m',
|
|
error: '\x1b[31m',
|
|
success: '\x1b[32m',
|
|
reset: '\x1b[0m'
|
|
};
|
|
|
|
const color = colors[level] || colors.reset;
|
|
console.log(`${color}[LoopDetector] ${message}${colors.reset}`);
|
|
}
|
|
}
|
|
|
|
module.exports = LoopDetector;
|