refactor: complete Phase 2 — migrate ralph-tracker and respawn-controller to managed timers

ralph-tracker.ts: Replace 4 manual timer/flag fields (_todoUpdateTimer, _loopUpdateTimer,
_todoUpdatePending, _loopUpdatePending) with 2 Debouncer instances.

respawn-controller.ts: Replace 10 manual timer fields (stepTimer, completionConfirmTimer,
noOutputTimer, detectionUpdateTimer, autoAcceptTimer, preFilterTimer, hookConfirmTimer,
clearFallbackTimer, stepConfirmTimer, stuckStateTimer) with CleanupManager + timerIds Map.
startTrackedTimer/cancelTrackedTimer preserved as wrappers for UI countdown display.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-03-01 16:43:45 +01:00
co-authored by Claude Opus 4.6
parent a8a6c1a648
commit 71276c5d6e
3 changed files with 113 additions and 221 deletions
+15 -60
View File
@@ -33,7 +33,7 @@ import {
PlanTaskStatus,
TddPhase,
} from './types.js';
import { ANSI_ESCAPE_PATTERN_SIMPLE, fuzzyPhraseMatch, todoContentHash, stringSimilarity } from './utils/index.js';
import { ANSI_ESCAPE_PATTERN_SIMPLE, fuzzyPhraseMatch, todoContentHash, stringSimilarity, Debouncer } from './utils/index.js';
import { MAX_LINE_BUFFER_SIZE } from './config/buffer-limits.js';
import { MAX_TODOS_PER_SESSION } from './config/map-limits.js';
import { RalphPlanTracker } from './ralph-plan-tracker.js';
@@ -454,17 +454,11 @@ export class RalphTracker extends EventEmitter {
/** Timestamp of last cleanup check for throttling */
private _lastCleanupTime: number = 0;
/** Debounce timer for todoUpdate events */
private _todoUpdateTimer: NodeJS.Timeout | null = null;
/** Debouncer for todoUpdate events */
private _todoDeb = new Debouncer(EVENT_DEBOUNCE_MS);
/** Debounce timer for loopUpdate events */
private _loopUpdateTimer: NodeJS.Timeout | null = null;
/** Flag indicating pending todoUpdate emission */
private _todoUpdatePending: boolean = false;
/** Flag indicating pending loopUpdate emission */
private _loopUpdatePending: boolean = false;
/** Debouncer for loopUpdate events */
private _loopDeb = new Debouncer(EVENT_DEBOUNCE_MS);
/** When true, prevents auto-enable on pattern detection */
private _autoEnableDisabled: boolean = true;
@@ -996,74 +990,34 @@ export class RalphTracker extends EventEmitter {
* Clear all debounce timers.
*/
private clearDebounceTimers(): void {
if (this._todoUpdateTimer) {
clearTimeout(this._todoUpdateTimer);
this._todoUpdateTimer = null;
}
if (this._loopUpdateTimer) {
clearTimeout(this._loopUpdateTimer);
this._loopUpdateTimer = null;
}
this._todoUpdatePending = false;
this._loopUpdatePending = false;
this._todoDeb.cancel();
this._loopDeb.cancel();
}
/**
* Emit todoUpdate event with debouncing.
*/
private emitTodoUpdateDebounced(): void {
this._todoUpdatePending = true;
if (this._todoUpdateTimer) {
clearTimeout(this._todoUpdateTimer);
}
this._todoUpdateTimer = setTimeout(() => {
if (this._todoUpdatePending) {
this._todoUpdatePending = false;
this._todoUpdateTimer = null;
this.emit('todoUpdate', this.todos);
}
}, EVENT_DEBOUNCE_MS);
this._todoDeb.schedule(() => this.emit('todoUpdate', this.todos));
}
/**
* Emit loopUpdate event with debouncing.
*/
private emitLoopUpdateDebounced(): void {
this._loopUpdatePending = true;
if (this._loopUpdateTimer) {
clearTimeout(this._loopUpdateTimer);
}
this._loopUpdateTimer = setTimeout(() => {
if (this._loopUpdatePending) {
this._loopUpdatePending = false;
this._loopUpdateTimer = null;
this.emit('loopUpdate', this.loopState);
}
}, EVENT_DEBOUNCE_MS);
this._loopDeb.schedule(() => this.emit('loopUpdate', this.loopState));
}
/**
* Flush all pending debounced events immediately.
*/
flushPendingEvents(): void {
if (this._todoUpdatePending) {
this._todoUpdatePending = false;
if (this._todoUpdateTimer) {
clearTimeout(this._todoUpdateTimer);
this._todoUpdateTimer = null;
}
if (this._todoDeb.isPending) {
this._todoDeb.cancel();
this.emit('todoUpdate', this.todos);
}
if (this._loopUpdatePending) {
this._loopUpdatePending = false;
if (this._loopUpdateTimer) {
clearTimeout(this._loopUpdateTimer);
this._loopUpdateTimer = null;
}
if (this._loopDeb.isPending) {
this._loopDeb.cancel();
this.emit('loopUpdate', this.loopState);
}
}
@@ -2373,7 +2327,8 @@ export class RalphTracker extends EventEmitter {
* Clean up all resources and release memory.
*/
destroy(): void {
this.clearDebounceTimers();
this._todoDeb.dispose();
this._loopDeb.dispose();
this.fixPlanWatcher.destroy();
this.stallDetector.destroy();
this.statusParser.destroy();