refactor: split god files into focused modules (phase 4, steps 2-4)

Split 3 large files into 11 focused sub-modules via composition:

ralph-tracker.ts (3,868 → ~2,400 LOC):
- ralph-plan-tracker.ts: plan task tracking, checkpoints, history
- ralph-fix-plan-watcher.ts: @fix_plan.md file watching
- ralph-stall-detector.ts: iteration stall detection
- ralph-status-parser.ts: RALPH_STATUS block parsing, circuit breaker

respawn-controller.ts (3,611 → ~3,200 LOC):
- respawn-patterns.ts: pure pattern detection functions
- respawn-adaptive-timing.ts: adaptive timing with percentile calc
- respawn-metrics.ts: cycle metrics tracking + aggregation
- respawn-health.ts: pure health scoring functions

session.ts (2,418 → ~1,800 LOC):
- session-cli-builder.ts: CLI argument construction
- session-auto-ops.ts: auto-compact/clear automation
- session-task-cache.ts: task description LRU cache

All external APIs preserved via delegation. Events forwarded
through parent classes. Zero behavioral changes — all 436 tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-03-01 04:04:35 +01:00
co-authored by Claude Opus 4.6
parent 8d2d51e8f0
commit e7a9cbe442
16 changed files with 4429 additions and 2937 deletions
+134
View File
@@ -0,0 +1,134 @@
/**
* @fileoverview Adaptive timing controller for respawn idle detection.
*
* Extracted from respawn-controller.ts for modularity. Tracks historical timing
* data and adjusts the completion confirm timeout dynamically based on the 75th
* percentile of recent idle detection durations.
*
* @module respawn-adaptive-timing
*/
import type { TimingHistory } from './types.js';
/**
* Configuration for adaptive timing bounds.
*/
export interface AdaptiveTimingConfig {
/** Minimum adaptive completion confirm timeout (ms) */
adaptiveMinConfirmMs: number;
/** Maximum adaptive completion confirm timeout (ms) */
adaptiveMaxConfirmMs: number;
}
/**
* Manages adaptive timing for respawn idle detection.
*
* Uses historical idle detection durations to calculate an optimal completion
* confirm timeout. The timeout is based on the 75th percentile of recent
* durations with a 20% safety buffer, clamped to configured bounds.
*/
export class RespawnAdaptiveTiming {
private timingHistory: TimingHistory;
constructor(private config: AdaptiveTimingConfig) {
this.timingHistory = {
recentIdleDetectionMs: [],
recentCycleDurationMs: [],
adaptiveCompletionConfirmMs: 10000, // Start with default
sampleCount: 0,
maxSamples: 20, // Keep last 20 samples for rolling average
lastUpdatedAt: Date.now(),
};
}
/**
* Record timing data from a completed cycle for adaptive adjustments.
*
* @param idleDetectionMs - Time spent detecting idle
* @param cycleDurationMs - Total cycle duration
*/
recordTimingData(idleDetectionMs: number, cycleDurationMs: number): void {
const history = this.timingHistory;
// Add to rolling windows
history.recentIdleDetectionMs.push(idleDetectionMs);
history.recentCycleDurationMs.push(cycleDurationMs);
// Trim to max samples
if (history.recentIdleDetectionMs.length > history.maxSamples) {
history.recentIdleDetectionMs.shift();
}
if (history.recentCycleDurationMs.length > history.maxSamples) {
history.recentCycleDurationMs.shift();
}
history.sampleCount = history.recentIdleDetectionMs.length;
history.lastUpdatedAt = Date.now();
// Recalculate adaptive timing
this.updateAdaptiveTiming();
}
/**
* Get the current adaptive completion confirm timeout.
* Returns the calculated value, or the default if not enough samples.
*
* @returns Completion confirm timeout in milliseconds
*/
getAdaptiveCompletionConfirmMs(): number {
// Need at least 5 samples before adjusting
if (this.timingHistory.sampleCount < 5) {
return this.timingHistory.adaptiveCompletionConfirmMs;
}
return this.timingHistory.adaptiveCompletionConfirmMs;
}
/**
* Get the current timing history for monitoring.
* @returns Copy of timing history
*/
getTimingHistory(): TimingHistory {
return { ...this.timingHistory };
}
/**
* Reset all timing history.
*/
reset(): void {
this.timingHistory = {
recentIdleDetectionMs: [],
recentCycleDurationMs: [],
adaptiveCompletionConfirmMs: 10000,
sampleCount: 0,
maxSamples: 20,
lastUpdatedAt: Date.now(),
};
}
/**
* Recalculate the adaptive completion confirm timeout based on historical data.
* Uses the 75th percentile of recent idle detection times as the new timeout,
* with a 20% buffer for safety.
*/
private updateAdaptiveTiming(): void {
const history = this.timingHistory;
const minMs = this.config.adaptiveMinConfirmMs;
const maxMs = this.config.adaptiveMaxConfirmMs;
if (history.recentIdleDetectionMs.length < 5) return;
// Sort for percentile calculation
const sorted = [...history.recentIdleDetectionMs].sort((a, b) => a - b);
// Use 75th percentile with 20% buffer
const p75Index = Math.floor(sorted.length * 0.75);
const p75Value = sorted[p75Index];
const withBuffer = Math.round(p75Value * 1.2);
// Clamp to configured bounds
const clamped = Math.max(minMs, Math.min(maxMs, withBuffer));
history.adaptiveCompletionConfirmMs = clamped;
}
}