aiwg
Version:
Deployment tool and support utility for AI context. Copies agents, skills, commands, rules, and behaviors into the paths each AI platform reads (Claude Code, Codex, Copilot, Cursor, Warp, OpenClaw, and 6 more) so one source of truth works across 10 platfo
1,141 lines (903 loc) • 35.3 kB
Markdown
# Oversight Layer
**Status**: Implemented (Issue #25)
**Purpose**: Autonomous health monitoring and intervention for long-running agent loops
## Overview
The Oversight layer provides autonomous health monitoring and intervention capabilities that prevent pathological loop behaviors without requiring human oversight for every iteration. This is critical for long-running agent loops that may execute overnight or in unattended environments.
### Why Oversight Matters
Long-running iterative loops can exhibit problematic patterns that waste resources and produce poor outcomes:
- **Stuck loops**: Repeating the same error 3+ times without progress
- **Oscillation**: Undoing and redoing changes in cycles
- **Objective deviation**: Drifting from the original task goal
- **Resource burn**: Exceeding time/budget constraints without value
- **Quality regression**: Tests passing → failing, coverage dropping
Without oversight, these patterns can persist for many iterations, burning through API budgets and producing no useful output. The Oversight layer detects these patterns early and intervenes autonomously.
### Five Intervention Levels
The Oversight layer responds to detected issues with escalating intervention levels:
| Level | Action | When Used | Example |
|-------|--------|-----------|---------|
| **LOG** | Record observation, continue | Low severity, monitoring only | Minor inefficiency detected |
| **WARN** | Inject warning into next prompt | Medium severity, course correction | Progress slowing down |
| **REDIRECT** | Force strategy change | High severity, current approach failing | Stuck loop detected |
| **PAUSE** | Halt and request human approval | Critical severity, uncertain path | Resource budget approaching limit |
| **ABORT** | Terminate loop, save state | Emergency, unrecoverable issue | Critical test regression |
## Architecture
The Oversight layer consists of four coordinated components:
```
┌─────────────────────────────────────────────────────────────┐
│ Overseer │
│ (Coordinates all oversight activities after each iteration) │
└──────────────┬──────────────────────────────────────────────┘
│
┌───────┴────────┬─────────────┬─────────────┐
│ │ │ │
┌──────▼──────┐ ┌─────▼────┐ ┌────▼─────┐ ┌────▼──────┐
│ Behavior │ │Intervention│ │Escalation│ │ Human │
│ Detector │ │ System │ │ Handler │ │ Feedback │
│ │ │ │ │ │ │ │
│ Analyzes │ │ Applies │ │ Alerts │ │ Approves/ │
│ iteration │─▶│ corrective │─▶│ humans │◀─│ Rejects │
│ history │ │ actions │ │ via Gitea│ │ │
└─────────────┘ └────────────┘ └──────────┘ └───────────┘
```
## Component 1: Overseer
**File**: `tools/ralph-external/lib/overseer.mjs`
**Role**: Main coordination hub for all oversight activities
### Purpose
The Overseer orchestrates health checks after each iteration, coordinating behavior detection, intervention application, and human escalation. It maintains an audit trail of all oversight decisions and system health metrics.
### Health Check Protocol
After each iteration, the Overseer executes this protocol:
1. **Add to history** - Store iteration result in history buffer
2. **Detect behaviors** - Run BehaviorDetector analysis
3. **Process interventions** - For each detection, determine and apply intervention
4. **Auto-escalate** - If critical issues detected, notify humans via EscalationHandler
5. **Determine status** - Compute overall health (healthy/warning/critical/paused/aborted)
6. **Create health check** - Record metrics, detections, interventions, status
7. **Persist log** - Write to `.aiwg/ralph-external/overseer/` for audit trail
8. **Callback** - Notify orchestrator of results
### Metrics Monitored
The Overseer tracks these key metrics:
| Metric | Purpose | Threshold Example |
|--------|---------|-------------------|
| **Progress rate** | Completion % per iteration | < 2% avg = stuck |
| **Error patterns** | Repeated failures | Same error 3+ times = critical |
| **Resource usage** | Iterations vs budget | 2x budget = burn |
| **Time elapsed** | Wall-clock duration | Approaching timeout |
| **Quality trajectory** | Tests/coverage trends | Coverage drop >10% = regression |
### Integration with Other Layers
The Overseer integrates with:
- **Orchestrator**: Receives iteration results, returns health check decisions
- **Memory Layer**: Stores learnings about successful interventions
- **Control Layer**: Provides health metrics for PID controller adaptation
- **Gitea Tracker**: Creates issues for critical/emergency escalations
### API
```javascript
import { Overseer } from './lib/overseer.mjs';
// Create overseer
const overseer = new Overseer(loopId, taskDescription, {
storagePath: '.aiwg/ralph-external/overseer',
detectorOptions: { /* custom thresholds */ },
interventionOptions: { /* custom strategies */ },
escalationOptions: {
repo: 'owner/repo',
giteaUrl: 'https://git.integrolabs.net/api/v1'
},
autoEscalate: true,
onHealthCheck: (healthCheck) => {
console.log(`Health: ${healthCheck.status}`);
}
});
// After each iteration
const healthCheck = await overseer.check(iterationResult);
if (healthCheck.status === 'paused') {
// Wait for human approval
await waitForApproval();
interventionSystem.resume('Human approved continuation');
}
// Get current health
const health = overseer.getHealth();
console.log(`Status: ${health.status}`);
console.log(`Detections: ${JSON.stringify(health.latestHealthCheck.detections)}`);
// Generate report
const report = overseer.generateReport();
await fs.writeFile('overseer-report.md', report);
```
### Configuration
```javascript
const overseer = new Overseer(loopId, taskDescription, {
// Storage location
storagePath: '.aiwg/ralph-external/overseer',
// Detector thresholds
detectorOptions: {
thresholds: {
stuck: {
sameErrorCount: 3, // Same error 3+ times = stuck
noProgressIterations: 5 // No progress for 5 iters = stuck
},
oscillation: {
undoRedoCycles: 2, // 2+ undo/redo cycles = oscillation
fileChurnThreshold: 0.8 // 80% files reverted = oscillation
},
deviation: {
objectiveSimilarity: 0.5, // <50% similarity = deviation
scopeCreepRatio: 1.5 // 1.5x scope = creep
},
resource: {
costMultiplier: 2.0, // 2x budget = burn
iterationMultiplier: 2.0 // 2x iterations = burn
},
regression: {
testPassToFail: true, // Tests failing = regression
coverageDropPercent: 10 // 10% coverage drop = regression
}
}
},
// Auto-escalation
autoEscalate: true, // Automatically notify humans for critical issues
// Callbacks
onHealthCheck: (healthCheck) => {
// Called after each health check
}
});
```
## Component 2: BehaviorDetector
**File**: `tools/ralph-external/lib/behavior-detector.mjs`
**Role**: Pattern detection in iteration history
### Purpose
The BehaviorDetector analyzes iteration history to identify pathological patterns. It implements research-backed detection heuristics that catch common failure modes early.
### Detection Types
#### 1. Stuck Loop Detection
**Pattern**: Same error repeated 3+ times with minimal progress
**Detection Logic**:
- Extract error messages from recent iterations (window: 5)
- Count occurrences of each unique error
- Check if progress rate < 2% per iteration
- Severity: `critical` if 5+ occurrences, `high` if 3+ occurrences
**Evidence Collected**:
```javascript
{
repeatedError: "TypeError: Cannot read property 'length' of null",
occurrences: 5,
avgProgressRate: 0.01, // 1% per iteration
recentBlockers: [
"Missing null check in validateInput()",
"Unhandled promise rejection",
// ...
]
}
```
**Recommendations**:
- Change approach or strategy
- Break task into smaller sub-tasks
- Request human intervention
- Review and address root cause
#### 2. Oscillation Detection
**Pattern**: Undo/redo cycles - alternating between approaches
**Detection Logic**:
- Track file changes per iteration
- Compare iteration N with N-2 to detect reverts
- Count cycles where >80% of files from N-2 reappear in N
- Trigger: 2+ undo/redo cycles in recent window
**Evidence Collected**:
```javascript
{
undoRedoCycles: 3,
recentFileChanges: [
['src/auth.ts', 'src/login.ts'], // Iteration N-2
['src/api.ts', 'src/routes.ts'], // Iteration N-1
['src/auth.ts', 'src/login.ts'], // Iteration N (reverted!)
]
}
```
**Recommendations**:
- Commit to one approach instead of alternating
- Review feedback quality - may be conflicting
- Pause and assess which approach is better
- Request human decision on direction
#### 3. Deviation Detection
**Pattern**: Work drifting from original objective
**Detection Logic**:
- Compare recent iteration learnings with original objective
- Use keyword similarity (simple NLP - production should use embeddings)
- Flag iterations with <50% similarity to objective
- Trigger: 2+ recent iterations below threshold
**Evidence Collected**:
```javascript
{
originalObjective: "Fix authentication tests",
deviationExamples: [
{
iteration: 7,
similarity: 0.3, // 30% keyword overlap
artifacts: ['src/api-docs.md', 'README.md'] // Not auth-related
}
],
averageSimilarity: 0.35
}
```
**Recommendations**:
- Review original objective and criteria
- Realign current work with stated goals
- Confirm scope with human if uncertain
- Document any necessary scope changes
#### 4. Resource Burn Detection
**Pattern**: Exceeding time/iteration budgets without value
**Detection Logic**:
- Compare actual iterations vs estimated max iterations
- Trigger: >2x estimated iterations used
- Severity escalates at 2.5x multiplier
**Evidence Collected**:
```javascript
{
estimatedIterations: 10,
actualIterations: 22,
iterationRatio: 2.2, // 220% of budget
completionPercent: 45, // Only 45% done
efficiency: 0.02 // 2% progress per iteration
}
```
**Recommendations**:
- Consider aborting if little progress made (if <50% complete)
- Increase iteration budget if task is viable (if >50% complete)
- Analyze why estimates were incorrect
- Break remaining work into smaller tasks
- Request human decision on continuation
#### 5. Regression Detection
**Pattern**: Quality going backwards (tests failing, coverage dropping)
**Detection Logic**:
- Track test pass/fail status across iterations
- Track code coverage percentage
- Flag: tests passing → failing transitions
- Flag: coverage drops >10%
**Evidence Collected**:
```javascript
{
regressions: [
{
iteration: 8,
message: 'Tests went from passing to failing'
},
{
iteration: 9,
message: 'Coverage dropped 12.5%',
from: 85.0,
to: 72.5
}
]
}
```
**Recommendations**:
- Stop making changes that break tests
- Fix tests instead of deleting or disabling them
- Review anti-laziness rules (`@.claude/rules/anti-laziness.md`)
- Restore previous working state if needed
### Thresholds Configuration
Thresholds are tunable per detection type:
```javascript
import { BehaviorDetector, THRESHOLDS } from './lib/behavior-detector.mjs';
const detector = new BehaviorDetector({
thresholds: {
stuck: {
sameErrorCount: 3, // Default: 3
noProgressIterations: 5 // Default: 5
},
oscillation: {
undoRedoCycles: 2, // Default: 2
fileChurnThreshold: 0.8 // Default: 80%
},
deviation: {
objectiveSimilarity: 0.5, // Default: 50%
scopeCreepRatio: 1.5 // Default: 1.5x
},
resource: {
costMultiplier: 2.0, // Default: 2x budget
iterationMultiplier: 2.0 // Default: 2x iterations
},
regression: {
testPassToFail: true, // Default: true
coverageDropPercent: 10 // Default: 10%
}
}
});
// Run detection
const detections = detector.detect(iterationHistory);
detections.forEach(det => {
console.log(`[${det.severity}] ${det.type}: ${det.message}`);
console.log('Recommendations:', det.recommendations);
});
```
### False Positive Mitigation
The detector uses multiple signals to reduce false positives:
1. **Stuck detection** requires BOTH repeated error AND stalled progress
2. **Oscillation** requires sustained pattern (2+ cycles, not just one revert)
3. **Deviation** requires multiple recent iterations, not just one outlier
4. **Resource burn** considers completion percentage (don't abort if 90% done)
5. **Regression** tracks trends, not single-iteration anomalies
## Component 3: InterventionSystem
**File**: `tools/ralph-external/lib/intervention-system.mjs`
**Role**: Automated response to detected issues
### Purpose
The InterventionSystem receives detections from the BehaviorDetector and applies appropriate interventions based on severity. It maintains pause state and generates actionable feedback for the next iteration.
### Intervention Level Mapping
The system maps detection severity to intervention levels:
```javascript
// Severity → Intervention mapping
switch (detection.severity) {
case 'critical':
// Critical = PAUSE or ABORT depending on type
if (type === 'resource_burn' || type === 'regression') {
return 'abort'; // Unrecoverable
}
return 'pause'; // Needs human decision
case 'high':
// High = REDIRECT or WARN depending on type
if (type === 'stuck' || type === 'oscillation') {
return 'redirect'; // Force strategy change
}
return 'warn'; // Strong warning
case 'medium':
return 'warn'; // Inject warning
case 'low':
default:
return 'log'; // Monitor only
}
```
### Intervention Actions
#### LOG Level
**Action**: Record observation, continue execution
```javascript
{
level: 'log',
reason: 'Minor inefficiency detected',
detection: { /* ... */ },
timestamp: '2026-02-03T10:00:00Z',
action: 'Logged detection for monitoring'
}
```
**Use case**: Low-severity observations that don't require intervention but should be tracked for pattern analysis.
#### WARN Level
**Action**: Inject warning into next prompt
The system generates a warning message that includes:
- Detection type and severity
- Specific recommendations
- Type-specific guidance
```javascript
const warning = `⚠️ OVERSEER WARNING: Loop stuck: Same error repeated 5 times
Recommended actions:
1. Change approach or strategy
2. Break task into smaller sub-tasks
3. Request human intervention
You are making the same error repeatedly. Stop and try a different approach.`;
// Warning is prepended to next iteration's prompt
const modifiedPrompt = interventionSystem.injectWarning(originalPrompt, warning);
```
**Use case**: Medium-severity issues where course correction is needed but autonomous recovery is still possible.
#### REDIRECT Level
**Action**: Force strategy change with explicit override
The system generates a strategy override directive that replaces the current approach:
```javascript
// For stuck detection
strategyOverride = `OVERRIDE: Change approach immediately.
The current method is not working. You have hit "Missing null check" 5 times.
Try a completely different solution strategy.`;
// For oscillation
strategyOverride = `OVERRIDE: Stop alternating between approaches.
Analyze which approach is better and commit to it.
No more back-and-forth changes.`;
// For deviation
strategyOverride = `OVERRIDE: Return to original objective.
Original objective: "Fix authentication tests".
All work must align with this goal.`;
```
**Use case**: High-severity issues where the current approach is clearly failing and a hard pivot is required.
#### PAUSE Level
**Action**: Halt execution, require human approval to continue
```javascript
{
level: 'pause',
reason: 'Resource budget approaching limit',
requiresApproval: true,
detection: { /* ... */ }
}
// System updates state
interventionSystem.isPaused = true;
interventionSystem.pauseReason = detection.message;
// Callback fires
onPause(intervention);
// Console output
╔═══════════════════════════════════════════════════════════╗
║ OVERSEER: LOOP PAUSED ║
║ Reason: Resource budget approaching limit ║
╚═══════════════════════════════════════════════════════════╝
```
**Resume from pause**:
```javascript
interventionSystem.resume('Human approved continuation after budget increase');
```
**Use case**: Critical issues where human judgment is required before proceeding.
#### ABORT Level
**Action**: Terminate loop, save state for forensics
```javascript
{
level: 'abort',
reason: 'Critical test regression - tests passing → failing',
requiresApproval: true,
abortReason: detection.message,
detection: { /* ... */ }
}
// Callback fires
onAbort(intervention);
// Console output
╔═══════════════════════════════════════════════════════════╗
║ OVERSEER: LOOP ABORTED ║
║ Reason: Critical test regression ║
╚═══════════════════════════════════════════════════════════╝
```
**Use case**: Emergency situations where continuing would cause damage (e.g., cascading test failures, uncontrolled resource burn).
### Escalation Paths
The InterventionSystem escalates to humans when:
1. **Automatic**: Any PAUSE or ABORT intervention (if `autoEscalate: true`)
2. **Conditional**: REDIRECT interventions with critical severity
3. **Never**: LOG and WARN interventions (stay autonomous)
### API
```javascript
import { InterventionSystem } from './lib/intervention-system.mjs';
const interventionSystem = new InterventionSystem({
onIntervention: (intervention) => {
console.log(`Applied ${intervention.level}: ${intervention.reason}`);
},
onPause: (intervention) => {
console.log('Loop paused, waiting for approval...');
},
onAbort: (intervention) => {
console.log('Loop aborted, saving state...');
}
});
// Apply intervention based on detection
const intervention = interventionSystem.intervene(detection);
// Check pause status
const { isPaused, reason } = interventionSystem.getPauseStatus();
if (isPaused) {
// Wait for human approval
const approved = await promptHumanForApproval(reason);
if (approved) {
interventionSystem.resume('Human approved continuation');
} else {
// Abort the loop
}
}
// Get intervention summary
const summary = interventionSystem.getSummary();
console.log(`Total interventions: ${summary.total}`);
console.log(`By level:`, summary.byLevel);
console.log(`By type:`, summary.byType);
```
## Component 4: EscalationHandler
**File**: `tools/ralph-external/lib/escalation-handler.mjs`
**Role**: Human notification via multiple channels
### Purpose
The EscalationHandler manages human escalation when autonomous intervention is insufficient. It supports multiple notification channels with graceful degradation.
### Escalation Channels
#### 1. Desktop Notifications
**Platform**: Linux (notify-send), graceful fallback if unavailable
```javascript
// Sends desktop notification
sendDesktopNotification(level, context);
// Urgency mapping
urgency = {
'info': 'low',
'warning': 'normal',
'critical': 'critical',
'emergency': 'critical'
}
// Example notification
// Title: Ralph Overseer: CRITICAL
// Message: Loop stuck: Same error repeated 5 times
// Loop: ralph-ext-001
// Iteration: 7
```
**Features**:
- Non-blocking (failures don't halt execution)
- Urgency-based prioritization
- Includes loop ID and iteration number
#### 2. Gitea Issue Creation
**Trigger**: CRITICAL and EMERGENCY escalations
Creates a Gitea issue with full context:
```markdown
## Agent Loop Overseer Alert
**Loop ID:** ralph-ext-001
**Task:** Fix authentication tests
**Iteration:** 7
**Timestamp:** 2026-02-03T10:00:00Z
### Issue
Loop stuck: Same error repeated 5 times with minimal progress
### Detection
- **Type:** stuck
- **Severity:** critical
- **Message:** Loop stuck: Same error repeated 5 times
**Evidence:**
```json
{
"repeatedError": "Missing null check in validateInput()",
"occurrences": 5,
"avgProgressRate": 0.01
}
```
**Recommendations:**
1. Change approach or strategy
2. Break task into smaller sub-tasks
3. Request human intervention
### Intervention
- **Level:** pause
- **Reason:** Loop stuck - requires human decision
### Actions Required
- [ ] Review loop state and iteration history
- [ ] Determine if loop should continue or abort
- [ ] Provide guidance on how to proceed
*Automated escalation from Ralph External Loop Overseer*
```
**Labels applied**: `ralph-overseer`, `critical`, `automated`
**Configuration**:
```javascript
const escalationHandler = new EscalationHandler({
giteaTokenPath: '~/.config/gitea/token',
giteaUrl: 'https://git.integrolabs.net/api/v1',
repo: 'owner/repo'
});
```
#### 3. Webhook Support
**Optional**: For integration with external systems
```javascript
const escalationHandler = new EscalationHandler({
webhookUrl: 'https://example.com/webhook/ralph-alerts'
});
// Sends JSON payload
{
"level": "critical",
"context": {
"loopId": "ralph-ext-001",
"taskDescription": "Fix auth tests",
"iterationNumber": 7,
"reason": "Loop stuck",
"detection": { /* ... */ },
"intervention": { /* ... */ }
},
"timestamp": "2026-02-03T10:00:00Z"
}
```
**Use cases**:
- Slack/Discord notifications
- PagerDuty integration
- Custom monitoring dashboards
### Escalation Levels
```javascript
export const ESCALATION_LEVELS = {
INFO: 'info', // Informational, no action required
WARNING: 'warning', // Attention needed
CRITICAL: 'critical', // Immediate review required
EMERGENCY: 'emergency' // Urgent intervention required
};
```
**Mapping from intervention levels**:
| Intervention | Escalation | Channels |
|-------------|------------|----------|
| LOG | INFO | Desktop only |
| WARN | WARNING | Desktop only |
| REDIRECT (high) | WARNING | Desktop only |
| REDIRECT (critical) | CRITICAL | Desktop + Gitea |
| PAUSE | CRITICAL | Desktop + Gitea |
| ABORT | EMERGENCY | Desktop + Gitea + Webhook |
### API
```javascript
import { EscalationHandler, ESCALATION_LEVELS } from './lib/escalation-handler.mjs';
const escalationHandler = new EscalationHandler({
giteaTokenPath: '~/.config/gitea/token',
giteaUrl: 'https://git.integrolabs.net/api/v1',
repo: 'roctinam/ai-writing-guide',
webhookUrl: 'https://example.com/webhook', // Optional
enableNotifications: true
});
// Escalate to human
const escalation = await escalationHandler.escalate(
ESCALATION_LEVELS.CRITICAL,
{
loopId: 'ralph-ext-001',
taskDescription: 'Fix authentication tests',
iterationNumber: 7,
level: 'critical',
reason: 'Loop stuck: Same error repeated 5 times',
detection: { /* ... */ },
intervention: { /* ... */ }
}
);
// Check what channels were used
console.log('Escalation channels:', escalation.channels);
// ['desktop_notification', 'gitea_issue']
// If Gitea issue was created
if (escalation.issueNumber) {
console.log(`Issue created: ${escalation.issueUrl}`);
}
// Get escalation log
const log = escalationHandler.getLog();
const summary = escalationHandler.getSummary();
```
## Usage Examples
### Example 1: Stuck Loop Caught and Redirected
```javascript
// Iteration 5 completes with same error as iterations 2, 3, 4
const iteration5 = {
number: 5,
status: 'failed',
analysis: {
failureClass: 'Missing null check in validateInput()',
blockers: ['Unhandled null pointer'],
completionPercentage: 12, // Minimal progress
artifactsModified: ['src/validation.ts']
}
};
// Overseer runs health check
const healthCheck = await overseer.check(iteration5);
// BehaviorDetector finds stuck pattern
healthCheck.detections = [
{
type: 'stuck',
severity: 'high',
message: 'Loop stuck: Same error repeated 5 times with minimal progress',
evidence: {
repeatedError: 'Missing null check in validateInput()',
occurrences: 5,
avgProgressRate: 0.01
},
recommendations: [
'Change approach or strategy',
'Break task into smaller sub-tasks'
]
}
];
// InterventionSystem applies REDIRECT
healthCheck.interventions = [
{
level: 'redirect',
reason: 'Loop stuck - forcing strategy change',
strategyOverride: `OVERRIDE: Change approach immediately.
The current method is not working. You have hit "Missing null check" 5 times.
Try a completely different solution strategy.`
}
];
// Next iteration receives modified prompt with override
// Agent is forced to try a different approach
```
**Result**: Loop recovers by iteration 6 with new strategy, avoiding wasted iterations.
### Example 2: Resource Burn Triggers Pause
```javascript
// Iteration 22 of a loop estimated at 10 iterations
const iteration22 = {
number: 22,
context: { maxIterations: 10 },
analysis: {
completionPercentage: 45 // Only 45% done after 220% budget
}
};
const healthCheck = await overseer.check(iteration22);
// BehaviorDetector finds resource burn
healthCheck.detections = [
{
type: 'resource_burn',
severity: 'critical',
message: 'Resource burn: Used 22/10 iterations (220% of budget)',
evidence: {
estimatedIterations: 10,
actualIterations: 22,
iterationRatio: 2.2,
completionPercent: 45,
efficiency: 0.02
},
recommendations: [
'Consider aborting if little progress made',
'Request human decision on continuation'
]
}
];
// InterventionSystem triggers PAUSE
healthCheck.interventions = [
{
level: 'pause',
reason: 'Resource budget exceeded - human decision required',
requiresApproval: true
}
];
// Overseer auto-escalates to human
await overseer.escalate(intervention, iteration22);
// Desktop notification sent
// Gitea issue created
// Loop paused, waiting for approval
╔═══════════════════════════════════════════════════════════╗
║ OVERSEER: LOOP PAUSED ║
║ Reason: Resource budget exceeded ║
╚═══════════════════════════════════════════════════════════╝
// Human reviews Gitea issue, decides to increase budget and resume
interventionSystem.resume('Human approved: Budget increased to 30 iterations');
```
**Result**: Human prevents uncontrolled resource burn, adjusts budget, loop continues productively.
### Example 3: Test Regression Aborts Loop
```javascript
// Iteration 8: Tests were passing in iteration 7, now failing
const iteration8 = {
number: 8,
analysis: {
testsPassing: false, // Was true in iteration 7
coveragePercent: 72.5, // Was 85.0 in iteration 7
artifactsModified: ['src/auth.ts']
}
};
const healthCheck = await overseer.check(iteration8);
// BehaviorDetector finds regression
healthCheck.detections = [
{
type: 'regression',
severity: 'critical',
message: 'Regression detected: 2 quality regressions',
evidence: {
regressions: [
{
iteration: 8,
message: 'Tests went from passing to failing'
},
{
iteration: 8,
message: 'Coverage dropped 12.5%',
from: 85.0,
to: 72.5
}
]
},
recommendations: [
'Stop making changes that break tests',
'Fix tests instead of deleting or disabling them',
'Review anti-laziness rules'
]
}
];
// InterventionSystem triggers ABORT
healthCheck.interventions = [
{
level: 'abort',
reason: 'Critical test regression - aborting to prevent further damage',
abortReason: 'Tests passing → failing, coverage dropped 12.5%',
requiresApproval: true
}
];
// Overseer escalates as EMERGENCY
await overseer.escalate(intervention, iteration8);
// Desktop notification (critical urgency)
// Gitea issue created with label 'emergency'
// Webhook triggered
// Loop aborted
╔═══════════════════════════════════════════════════════════╗
║ OVERSEER: LOOP ABORTED ║
║ Reason: Critical test regression ║
╚═══════════════════════════════════════════════════════════╝
// State saved to .aiwg/ralph-external/ for forensics
```
**Result**: Loop terminated before further damage, full context preserved for human investigation and recovery.
## Tuning the Oversight Layer
### Balancing Sensitivity vs False Positives
The Oversight layer uses conservative defaults to minimize false positives while catching genuine issues. Tuning depends on your project:
#### High-Stakes Projects (e.g., security, compliance)
**Increase sensitivity** - catch issues earlier, accept some false positives:
```javascript
const overseer = new Overseer(loopId, taskDescription, {
detectorOptions: {
thresholds: {
stuck: {
sameErrorCount: 2, // Trigger after 2 occurrences (vs 3)
noProgressIterations: 3 // Shorter window (vs 5)
},
resource: {
costMultiplier: 1.5, // Trigger at 150% budget (vs 200%)
iterationMultiplier: 1.5
},
regression: {
coverageDropPercent: 5 // Stricter (vs 10%)
}
}
},
autoEscalate: true // Escalate all critical issues immediately
});
```
**Trade-off**: More human interventions, but earlier detection of problems.
#### Experimental/Exploratory Projects
**Decrease sensitivity** - allow more autonomy, reduce interruptions:
```javascript
const overseer = new Overseer(loopId, taskDescription, {
detectorOptions: {
thresholds: {
stuck: {
sameErrorCount: 5, // More tolerant (vs 3)
noProgressIterations: 8 // Longer window (vs 5)
},
resource: {
costMultiplier: 3.0, // Trigger at 300% budget (vs 200%)
iterationMultiplier: 3.0
},
deviation: {
objectiveSimilarity: 0.3 // Allow more exploration (vs 0.5)
}
}
},
autoEscalate: false // Only escalate on explicit abort
});
```
**Trade-off**: More wasted iterations possible, but fewer interruptions to flow.
#### Production Continuous Integration
**Strict thresholds** - fail fast, preserve clean state:
```javascript
const overseer = new Overseer(loopId, taskDescription, {
detectorOptions: {
thresholds: {
stuck: {
sameErrorCount: 3,
noProgressIterations: 3 // Fail faster in CI
},
regression: {
testPassToFail: true,
coverageDropPercent: 1 // Any coverage drop = abort
}
}
},
autoEscalate: true,
interventionOptions: {
// Abort immediately on regression
onIntervention: (intervention) => {
if (intervention.detection?.type === 'regression') {
intervention.level = 'abort';
}
}
}
});
```
**Trade-off**: Aggressive termination, but protects main branch quality.
### When to Use Stricter Thresholds
Use tighter thresholds when:
1. **High cost of errors** - Security vulnerabilities, data loss risks
2. **Limited budget** - API costs matter, iteration count capped
3. **Unattended execution** - Running overnight, need early termination
4. **CI/CD pipelines** - Must preserve clean state
5. **Regulated environments** - Compliance requires audit trails
Use looser thresholds when:
1. **Exploratory work** - Research, prototyping, learning
2. **Complex tasks** - Expected to require many iterations
3. **High tolerance for waste** - Cost isn't a primary concern
4. **Human monitoring** - Someone watching and can intervene manually
5. **Iterative refinement** - Quality expected to fluctuate during development
### Monitoring Overseer Effectiveness
Track these metrics to tune thresholds:
```javascript
// Generate report after loop completes
const report = overseer.generateReport();
// Key metrics to review:
// - Detection counts by type
// - Intervention counts by level
// - False positive rate (interventions that weren't helpful)
// - True positive rate (interventions that prevented waste)
```
**Tuning indicators**:
| Observation | Likely Issue | Adjustment |
|------------|--------------|------------|
| Many LOG detections, no higher levels | Thresholds too loose | Tighten slightly |
| Frequent PAUSE/ABORT, loops often successful | Thresholds too tight | Loosen slightly |
| Stuck detections but oscillation missed | Oscillation threshold too high | Lower file churn threshold |
| Resource burn detected too late | Cost multiplier too high | Lower multiplier |
| False regressions (coverage drops briefly then recovers) | Single-iteration sensitivity too high | Require sustained trend |
## References
- **Implementation**: Issue #25 - Autonomous Overseer
- **Research**: `@.claude/rules/anti-laziness.md` - Avoidance pattern detection
- **Integration**: `@.claude/rules/hitl-patterns.md` - Human-in-the-loop gates
- **Architecture**: `.aiwg/architecture/ralph-external-architecture.md` - Overall system design
## See Also
- `README-memory.md` - Memory Layer (feeds learning to Overseer)
- `README-intelligence.md` - Intelligence Layer (receives intervention feedback)
- `README-control.md` - Control Layer (uses health metrics for adaptation)
- `docs/ralph-external-security.md` - Security considerations for oversight
*Generated documentation for Ralph External Loop Oversight Layer - autonomous health monitoring and intervention for long-running iterative tasks.*