Files
Codeman/src/types/respawn.ts
T
Ark0NandClaude Opus 4.6 2ee9ad72e8 refactor: SSE event handlers, LLM context optimization, @fileoverview docs (#29)
* refactor: extract SSE event handlers into named class methods

Replace ~80 inline addListener closures in connectSSE() with a
declarative _SSE_HANDLER_MAP array that drives registration in a
single loop. Each handler is now a named _on* method on CodemanApp,
making them individually addressable for LLM navigation.

Add SSE_EVENTS constant object in constants.js to eliminate magic
event-type strings scattered across the frontend.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: fix inaccuracies in CLAUDE.md

- Fix types barrel path: src/types.ts → src/types/index.ts
- Update app.js line count: ~12K → ~11.5K
- Correct route handler counts (113 → 111, per-group fixes)
- Add code style, ESM gotcha, env vars, route test, lifecycle log docs
- Add Node 22 CI note, test teardown timeout, port range

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: add mobile screenshots and QR auth security writeup to README

Add 3 mobile screenshots (landing, idle, active) and expand the
mobile section with QR auth security design details and a
touch-optimized interface subsection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: bundle xterm-zerolag-input as vendor IIFE and add pre-commit hook

Build and postinstall now bundle the local xterm-zerolag-input package
as an IIFE at vendor/xterm-zerolag-input.js with global LocalEchoOverlay
shim. Add git pre-commit hook that runs prettier --check on staged .ts
files to catch format issues before CI.

Also bump constants.js and app.js cache-bust versions to 0.3.0 and add
tunnel upload URL display row in settings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add cloudflared install support and interactive launch menu

- Add optional cloudflared dependency detection and installation
  across 6 distro families (macOS, Debian, Fedora, Arch, Alpine, SUSE)
- Add tunnel systemd service setup helper
- Replace post-install instructions with interactive launch menu
  (run now / systemd service / skip)
- Uninstall now cleans up both codeman-web and codeman-tunnel services

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: gitignore readme-preview.mjs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: WIP — SSE event constants, @fileoverview docs, CLAUDE.md compression

- Migrate broadcast() string literals → SseEvent.* typed constants
- Add @fileoverview with cross-domain references to all 13 type domain files
- Add @fileoverview to frontend JS modules (constants, mobile, voice, etc.)
- Add section dividers to route files for LLM scanability
- Compress CLAUDE.md: flat file list → domain table, fix counts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: optimize codebase for LLM context window efficiency

CLAUDE.md: 456 → 309 lines (32% reduction)
- Merge Commands into compact table, remove redundant bash block
- Convert Security section to dense table format
- Merge Performance + Resource Limits, Debugging + Troubleshooting
- Compress Tunnel, Memory Leak, Scripts, Screenshots sections
- Remove Key Patterns that duplicate @fileoverview in source files

Backend @fileoverview enhancements (10 priority files):
- session.ts: key methods, events, cross-domain refs
- respawn-controller.ts: state machine, idle detection layers
- ralph-tracker.ts: exports, circuit breaker, events
- ralph-loop.ts: lifecycle, persistence, events
- subagent-watcher.ts: watched patterns, teammate detection
- server.ts: coordination list, port interfaces
- state-store.ts: dual-file persistence, migration
- session-manager.ts: lifecycle methods, mutex guard
- hooks-config.ts: hook events list, categories
- sse-events.ts: category breakdown (~90 events, 17 categories)

Frontend app.js: add 6 section dividers, update @fileoverview line refs

Fix: escape glob `*/` in JSDoc that broke ESLint parser

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR #29 review bugs

- server.ts: replace hardcoded 'session:needsRefresh' with SseEvent constant
- install.sh: fix Alpine cloudflared install for non-root (download to tmpfile first)
- install.sh: replace Arch pacman (AUR-only) with direct binary download
- index.html: bump all 8 remaining cache-bust versions from v0.2.9 to v0.3.0
- mobile-handlers.js: fix @dependency annotation (keyboard-accessory.js, not constants.js)
- types/push.ts: fix layer number (4, not 5)
- subagent-watcher.ts: fix watched pattern path to include {session} segment
- constants.js: fix SSE_EVENTS count in @fileoverview (~73, not ~65)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 22:40:18 +01:00

300 lines
10 KiB
TypeScript

/**
* @fileoverview Respawn controller type definitions.
*
* Covers the autonomous session cycling system: configuration, presets,
* per-cycle metrics, aggregate health scoring, and adaptive timing.
*
* Key exports:
* - RespawnConfig — full respawn settings (idle timeout, AI checks, adaptive timing, skip-clear)
* - PersistedRespawnConfig — subset saved to disk for mux session recovery
* - RespawnPreset — named preset for quick setup (solo-work, team-lead, overnight-autonomous, etc.)
* - RespawnCycleMetrics — per-cycle outcome tracking (duration, idle reason, steps, tokens)
* - RespawnAggregateMetrics — aggregate stats across cycles (success rate, p90 duration)
* - RalphLoopHealthScore — composite 0-100 health score with 5 component scores
* - HealthStatus — 'excellent' | 'good' | 'degraded' | 'critical'
* - TimingHistory — rolling window of timing data for adaptive adjustments
* - CycleOutcome — 'success' | 'stuck_recovery' | 'blocked' | 'error' | 'cancelled'
*
* Cross-domain relationships:
* - RespawnConfig is embedded in AppConfig.respawn (app-state) and SessionState.respawnConfig (session)
* - RalphLoopHealthScore.components.circuitBreaker derives from CircuitBreakerStatus (ralph domain)
* - RespawnCycleMetrics.sessionId links to SessionState.id (session domain)
*
* Served at `GET /api/sessions/:id/respawn` (config + state).
*/
/**
* Configuration for the Respawn Controller
*
* The respawn controller keeps interactive sessions productive by
* automatically cycling through update prompts when Claude goes idle.
*/
export interface RespawnConfig {
/** How long to wait after seeing prompt before considering truly idle (ms) */
idleTimeoutMs: number;
/** The prompt to send for updating docs */
updatePrompt: string;
/** Delay between sending steps (ms) */
interStepDelayMs: number;
/** Whether to enable respawn loop */
enabled: boolean;
/** Whether to send /clear after update prompt */
sendClear: boolean;
/** Whether to send /init after /clear */
sendInit: boolean;
/** Optional prompt to send if /init doesn't trigger work */
kickstartPrompt?: string;
/** Time to wait after completion message before confirming idle (ms) */
completionConfirmMs?: number;
/** Fallback timeout when no output received at all (ms) */
noOutputTimeoutMs?: number;
/** Whether to auto-accept plan mode prompts by pressing Enter (not questions) */
autoAcceptPrompts?: boolean;
/** Delay before auto-accepting plan mode prompts when no output and no completion message (ms) */
autoAcceptDelayMs?: number;
/** Whether AI idle check is enabled */
aiIdleCheckEnabled?: boolean;
/** Model to use for AI idle check */
aiIdleCheckModel?: string;
/** Maximum characters of terminal buffer for AI check */
aiIdleCheckMaxContext?: number;
/** Timeout for AI check in ms */
aiIdleCheckTimeoutMs?: number;
/** Cooldown after WORKING verdict in ms */
aiIdleCheckCooldownMs?: number;
/** Whether AI plan mode check is enabled for auto-accept */
aiPlanCheckEnabled?: boolean;
/** Model to use for AI plan mode check */
aiPlanCheckModel?: string;
/** Maximum characters of terminal buffer for plan check */
aiPlanCheckMaxContext?: number;
/** Timeout for AI plan check in ms */
aiPlanCheckTimeoutMs?: number;
/** Cooldown after NOT_PLAN_MODE verdict in ms */
aiPlanCheckCooldownMs?: number;
// ========== P2-001: Adaptive Timing ==========
/** Whether to use adaptive timing based on historical patterns */
adaptiveTimingEnabled?: boolean;
/** Minimum value for adaptive completion confirm (ms) */
adaptiveMinConfirmMs?: number;
/** Maximum value for adaptive completion confirm (ms) */
adaptiveMaxConfirmMs?: number;
// ========== P2-002: Skip-Clear Optimization ==========
/** Whether to skip /clear when context is below threshold */
skipClearWhenLowContext?: boolean;
/** Token percentage threshold below which /clear is skipped (0-100) */
skipClearThresholdPercent?: number;
// ========== P2-004: Cycle Metrics ==========
/** Whether to track and persist cycle metrics */
trackCycleMetrics?: boolean;
}
// ========== P2-004: Respawn Cycle Metrics ==========
/**
* Outcome of a respawn cycle
*/
export type CycleOutcome =
| 'success' // Cycle completed normally
| 'stuck_recovery' // Stuck-state recovery triggered
| 'blocked' // Blocked by circuit breaker or exit signal
| 'error' // Error during cycle
| 'cancelled'; // Cancelled (e.g., controller stopped)
/**
* Metrics for a single respawn cycle.
* Persisted for post-mortem analysis of long-running loops.
*/
export interface RespawnCycleMetrics {
/** Unique cycle ID (session-id:cycle-number) */
cycleId: string;
/** Session ID this cycle belongs to */
sessionId: string;
/** Cycle number within the session */
cycleNumber: number;
/** Timestamp when cycle started */
startedAt: number;
/** Timestamp when cycle completed */
completedAt: number;
/** Total duration of cycle (ms) */
durationMs: number;
/** What triggered idle detection */
idleReason: string;
/** Time spent detecting idle (from start of watching to idle confirmed) */
idleDetectionMs: number;
/** Steps completed in this cycle */
stepsCompleted: string[];
/** Whether /clear was skipped (P2-002) */
clearSkipped: boolean;
/** Outcome of the cycle */
outcome: CycleOutcome;
/** Error message if outcome is 'error' */
errorMessage?: string;
/** Token count at start of cycle */
tokenCountAtStart?: number;
/** Token count at end of cycle */
tokenCountAtEnd?: number;
/** Completion confirm time used (may be adaptive) */
completionConfirmMsUsed: number;
}
/**
* Aggregate metrics across multiple cycles for health scoring.
*/
export interface RespawnAggregateMetrics {
/** Total cycles tracked */
totalCycles: number;
/** Successful cycles */
successfulCycles: number;
/** Cycles that required stuck-state recovery */
stuckRecoveryCycles: number;
/** Blocked cycles */
blockedCycles: number;
/** Error cycles */
errorCycles: number;
/** Average cycle duration (ms) */
avgCycleDurationMs: number;
/** Average idle detection time (ms) */
avgIdleDetectionMs: number;
/** 90th percentile cycle duration (ms) */
p90CycleDurationMs: number;
/** Success rate (0-100) */
successRate: number;
/** Last updated timestamp */
lastUpdatedAt: number;
}
// ========== P2-005: Ralph Loop Health Score ==========
/**
* Health status levels for the Ralph Loop system.
*/
export type HealthStatus = 'excellent' | 'good' | 'degraded' | 'critical';
/**
* Comprehensive health score for a Ralph Loop session.
* Aggregates multiple health signals into a single score.
*/
export interface RalphLoopHealthScore {
/** Overall health score (0-100) */
score: number;
/** Health status based on score thresholds */
status: HealthStatus;
/** Individual component scores (0-100 each) */
components: {
/** Based on recent cycle success rate */
cycleSuccess: number;
/** Based on circuit breaker state */
circuitBreaker: number;
/** Based on iteration stall metrics */
iterationProgress: number;
/** Based on AI checker error rate */
aiChecker: number;
/** Based on stuck-state recovery count */
stuckRecovery: number;
};
/** Human-readable summary of health */
summary: string;
/** Recommendations for improvement */
recommendations: string[];
/** Timestamp when score was calculated */
calculatedAt: number;
}
// ========== Timing History for Adaptive Timing ==========
/**
* Historical timing data for adaptive adjustments.
*/
export interface TimingHistory {
/** Rolling window of recent idle detection durations (ms) */
recentIdleDetectionMs: number[];
/** Rolling window of recent cycle durations (ms) */
recentCycleDurationMs: number[];
/** Calculated adaptive completion confirm value (ms) */
adaptiveCompletionConfirmMs: number;
/** Number of samples in rolling windows */
sampleCount: number;
/** Maximum samples to keep */
maxSamples: number;
/** Last updated timestamp */
lastUpdatedAt: number;
}
/**
* Named respawn configuration preset for quick setup
*/
export interface RespawnPreset {
/** Unique preset identifier */
id: string;
/** User-friendly preset name */
name: string;
/** Description of when to use this preset */
description?: string;
/** The respawn configuration (without enabled flag) */
config: Omit<RespawnConfig, 'enabled'>;
/** Duration in minutes (optional default) */
durationMinutes?: number;
/** Whether this is a built-in preset */
builtIn?: boolean;
/** Timestamp when created */
createdAt: number;
}
/**
* Persisted respawn configuration for mux sessions.
* Subset of RespawnConfig that gets saved to disk.
*/
export interface PersistedRespawnConfig {
/** Whether respawn was enabled */
enabled: boolean;
/** How long to wait after seeing prompt before considering truly idle (ms) */
idleTimeoutMs: number;
/** The prompt to send for updating docs */
updatePrompt: string;
/** Delay between sending steps (ms) */
interStepDelayMs: number;
/** Whether to send /clear after update prompt */
sendClear: boolean;
/** Whether to send /init after /clear */
sendInit: boolean;
/** Optional prompt to send if /init doesn't trigger work */
kickstartPrompt?: string;
/** Whether to auto-accept plan mode prompts by pressing Enter (not questions) */
autoAcceptPrompts?: boolean;
/** Delay before auto-accepting prompts (ms) */
autoAcceptDelayMs?: number;
/** Time to wait after completion message before confirming idle (ms) */
completionConfirmMs?: number;
/** Fallback timeout when no output received at all (ms) */
noOutputTimeoutMs?: number;
/** Whether AI idle check is enabled */
aiIdleCheckEnabled?: boolean;
/** Model to use for AI idle check */
aiIdleCheckModel?: string;
/** Maximum characters of terminal buffer for AI check */
aiIdleCheckMaxContext?: number;
/** Timeout for AI check in ms */
aiIdleCheckTimeoutMs?: number;
/** Cooldown after WORKING verdict in ms */
aiIdleCheckCooldownMs?: number;
/** Whether AI plan mode check is enabled for auto-accept */
aiPlanCheckEnabled?: boolean;
/** Model to use for AI plan mode check */
aiPlanCheckModel?: string;
/** Maximum characters of terminal buffer for plan check */
aiPlanCheckMaxContext?: number;
/** Timeout for AI plan check in ms */
aiPlanCheckTimeoutMs?: number;
/** Cooldown after NOT_PLAN_MODE verdict in ms */
aiPlanCheckCooldownMs?: number;
/** Duration in minutes if timed respawn was set */
durationMinutes?: number;
}