aicodeman 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +403 -0
  3. package/dist/ai-checker-base.d.ts +175 -0
  4. package/dist/ai-checker-base.d.ts.map +1 -0
  5. package/dist/ai-checker-base.js +424 -0
  6. package/dist/ai-checker-base.js.map +1 -0
  7. package/dist/ai-idle-checker.d.ts +53 -0
  8. package/dist/ai-idle-checker.d.ts.map +1 -0
  9. package/dist/ai-idle-checker.js +141 -0
  10. package/dist/ai-idle-checker.js.map +1 -0
  11. package/dist/ai-plan-checker.d.ts +52 -0
  12. package/dist/ai-plan-checker.d.ts.map +1 -0
  13. package/dist/ai-plan-checker.js +103 -0
  14. package/dist/ai-plan-checker.js.map +1 -0
  15. package/dist/bash-tool-parser.d.ts +191 -0
  16. package/dist/bash-tool-parser.d.ts.map +1 -0
  17. package/dist/bash-tool-parser.js +598 -0
  18. package/dist/bash-tool-parser.js.map +1 -0
  19. package/dist/cli.d.ts +12 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +460 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/config/buffer-limits.d.ts +59 -0
  24. package/dist/config/buffer-limits.d.ts.map +1 -0
  25. package/dist/config/buffer-limits.js +74 -0
  26. package/dist/config/buffer-limits.js.map +1 -0
  27. package/dist/config/map-limits.d.ts +40 -0
  28. package/dist/config/map-limits.d.ts.map +1 -0
  29. package/dist/config/map-limits.js +52 -0
  30. package/dist/config/map-limits.js.map +1 -0
  31. package/dist/file-stream-manager.d.ts +148 -0
  32. package/dist/file-stream-manager.d.ts.map +1 -0
  33. package/dist/file-stream-manager.js +351 -0
  34. package/dist/file-stream-manager.js.map +1 -0
  35. package/dist/hooks-config.d.ts +31 -0
  36. package/dist/hooks-config.d.ts.map +1 -0
  37. package/dist/hooks-config.js +115 -0
  38. package/dist/hooks-config.js.map +1 -0
  39. package/dist/image-watcher.d.ts +86 -0
  40. package/dist/image-watcher.d.ts.map +1 -0
  41. package/dist/image-watcher.js +275 -0
  42. package/dist/image-watcher.js.map +1 -0
  43. package/dist/index.d.ts +11 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +54 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/mux-factory.d.ts +13 -0
  48. package/dist/mux-factory.d.ts.map +1 -0
  49. package/dist/mux-factory.js +19 -0
  50. package/dist/mux-factory.js.map +1 -0
  51. package/dist/mux-interface.d.ts +145 -0
  52. package/dist/mux-interface.d.ts.map +1 -0
  53. package/dist/mux-interface.js +9 -0
  54. package/dist/mux-interface.js.map +1 -0
  55. package/dist/plan-orchestrator.d.ts +123 -0
  56. package/dist/plan-orchestrator.d.ts.map +1 -0
  57. package/dist/plan-orchestrator.js +500 -0
  58. package/dist/plan-orchestrator.js.map +1 -0
  59. package/dist/prompts/index.d.ts +9 -0
  60. package/dist/prompts/index.d.ts.map +1 -0
  61. package/dist/prompts/index.js +9 -0
  62. package/dist/prompts/index.js.map +1 -0
  63. package/dist/prompts/planner.d.ts +14 -0
  64. package/dist/prompts/planner.d.ts.map +1 -0
  65. package/dist/prompts/planner.js +83 -0
  66. package/dist/prompts/planner.js.map +1 -0
  67. package/dist/prompts/research-agent.d.ts +10 -0
  68. package/dist/prompts/research-agent.d.ts.map +1 -0
  69. package/dist/prompts/research-agent.js +143 -0
  70. package/dist/prompts/research-agent.js.map +1 -0
  71. package/dist/push-store.d.ts +41 -0
  72. package/dist/push-store.d.ts.map +1 -0
  73. package/dist/push-store.js +168 -0
  74. package/dist/push-store.js.map +1 -0
  75. package/dist/ralph-config.d.ts +67 -0
  76. package/dist/ralph-config.d.ts.map +1 -0
  77. package/dist/ralph-config.js +134 -0
  78. package/dist/ralph-config.js.map +1 -0
  79. package/dist/ralph-loop.d.ts +124 -0
  80. package/dist/ralph-loop.d.ts.map +1 -0
  81. package/dist/ralph-loop.js +418 -0
  82. package/dist/ralph-loop.js.map +1 -0
  83. package/dist/ralph-tracker.d.ts +1081 -0
  84. package/dist/ralph-tracker.d.ts.map +1 -0
  85. package/dist/ralph-tracker.js +3343 -0
  86. package/dist/ralph-tracker.js.map +1 -0
  87. package/dist/respawn-controller.d.ts +1182 -0
  88. package/dist/respawn-controller.d.ts.map +1 -0
  89. package/dist/respawn-controller.js +2754 -0
  90. package/dist/respawn-controller.js.map +1 -0
  91. package/dist/run-summary.d.ts +123 -0
  92. package/dist/run-summary.d.ts.map +1 -0
  93. package/dist/run-summary.js +325 -0
  94. package/dist/run-summary.js.map +1 -0
  95. package/dist/session-lifecycle-log.d.ts +36 -0
  96. package/dist/session-lifecycle-log.d.ts.map +1 -0
  97. package/dist/session-lifecycle-log.js +101 -0
  98. package/dist/session-lifecycle-log.js.map +1 -0
  99. package/dist/session-manager.d.ts +97 -0
  100. package/dist/session-manager.d.ts.map +1 -0
  101. package/dist/session-manager.js +224 -0
  102. package/dist/session-manager.js.map +1 -0
  103. package/dist/session.d.ts +686 -0
  104. package/dist/session.d.ts.map +1 -0
  105. package/dist/session.js +2025 -0
  106. package/dist/session.js.map +1 -0
  107. package/dist/state-store.d.ts +189 -0
  108. package/dist/state-store.d.ts.map +1 -0
  109. package/dist/state-store.js +730 -0
  110. package/dist/state-store.js.map +1 -0
  111. package/dist/subagent-watcher.d.ts +345 -0
  112. package/dist/subagent-watcher.d.ts.map +1 -0
  113. package/dist/subagent-watcher.js +1469 -0
  114. package/dist/subagent-watcher.js.map +1 -0
  115. package/dist/task-queue.d.ts +108 -0
  116. package/dist/task-queue.d.ts.map +1 -0
  117. package/dist/task-queue.js +235 -0
  118. package/dist/task-queue.js.map +1 -0
  119. package/dist/task-tracker.d.ts +306 -0
  120. package/dist/task-tracker.d.ts.map +1 -0
  121. package/dist/task-tracker.js +488 -0
  122. package/dist/task-tracker.js.map +1 -0
  123. package/dist/task.d.ts +73 -0
  124. package/dist/task.d.ts.map +1 -0
  125. package/dist/task.js +177 -0
  126. package/dist/task.js.map +1 -0
  127. package/dist/team-watcher.d.ts +53 -0
  128. package/dist/team-watcher.d.ts.map +1 -0
  129. package/dist/team-watcher.js +313 -0
  130. package/dist/team-watcher.js.map +1 -0
  131. package/dist/templates/case-template.md +461 -0
  132. package/dist/templates/claude-md.d.ts +26 -0
  133. package/dist/templates/claude-md.d.ts.map +1 -0
  134. package/dist/templates/claude-md.js +74 -0
  135. package/dist/templates/claude-md.js.map +1 -0
  136. package/dist/tmux-manager.d.ts +181 -0
  137. package/dist/tmux-manager.d.ts.map +1 -0
  138. package/dist/tmux-manager.js +1405 -0
  139. package/dist/tmux-manager.js.map +1 -0
  140. package/dist/transcript-watcher.d.ts +110 -0
  141. package/dist/transcript-watcher.d.ts.map +1 -0
  142. package/dist/transcript-watcher.js +338 -0
  143. package/dist/transcript-watcher.js.map +1 -0
  144. package/dist/tunnel-manager.d.ts +54 -0
  145. package/dist/tunnel-manager.d.ts.map +1 -0
  146. package/dist/tunnel-manager.js +251 -0
  147. package/dist/tunnel-manager.js.map +1 -0
  148. package/dist/types.d.ts +1139 -0
  149. package/dist/types.d.ts.map +1 -0
  150. package/dist/types.js +215 -0
  151. package/dist/types.js.map +1 -0
  152. package/dist/utils/buffer-accumulator.d.ts +111 -0
  153. package/dist/utils/buffer-accumulator.d.ts.map +1 -0
  154. package/dist/utils/buffer-accumulator.js +172 -0
  155. package/dist/utils/buffer-accumulator.js.map +1 -0
  156. package/dist/utils/claude-cli-resolver.d.ts +26 -0
  157. package/dist/utils/claude-cli-resolver.d.ts.map +1 -0
  158. package/dist/utils/claude-cli-resolver.js +78 -0
  159. package/dist/utils/claude-cli-resolver.js.map +1 -0
  160. package/dist/utils/cleanup-manager.d.ts +165 -0
  161. package/dist/utils/cleanup-manager.d.ts.map +1 -0
  162. package/dist/utils/cleanup-manager.js +274 -0
  163. package/dist/utils/cleanup-manager.js.map +1 -0
  164. package/dist/utils/index.d.ts +19 -0
  165. package/dist/utils/index.d.ts.map +1 -0
  166. package/dist/utils/index.js +19 -0
  167. package/dist/utils/index.js.map +1 -0
  168. package/dist/utils/lru-map.d.ts +140 -0
  169. package/dist/utils/lru-map.d.ts.map +1 -0
  170. package/dist/utils/lru-map.js +234 -0
  171. package/dist/utils/lru-map.js.map +1 -0
  172. package/dist/utils/nice-wrapper.d.ts +13 -0
  173. package/dist/utils/nice-wrapper.d.ts.map +1 -0
  174. package/dist/utils/nice-wrapper.js +17 -0
  175. package/dist/utils/nice-wrapper.js.map +1 -0
  176. package/dist/utils/opencode-cli-resolver.d.ts +21 -0
  177. package/dist/utils/opencode-cli-resolver.d.ts.map +1 -0
  178. package/dist/utils/opencode-cli-resolver.js +67 -0
  179. package/dist/utils/opencode-cli-resolver.js.map +1 -0
  180. package/dist/utils/regex-patterns.d.ts +64 -0
  181. package/dist/utils/regex-patterns.d.ts.map +1 -0
  182. package/dist/utils/regex-patterns.js +74 -0
  183. package/dist/utils/regex-patterns.js.map +1 -0
  184. package/dist/utils/stale-expiration-map.d.ts +159 -0
  185. package/dist/utils/stale-expiration-map.d.ts.map +1 -0
  186. package/dist/utils/stale-expiration-map.js +277 -0
  187. package/dist/utils/stale-expiration-map.js.map +1 -0
  188. package/dist/utils/string-similarity.d.ts +108 -0
  189. package/dist/utils/string-similarity.d.ts.map +1 -0
  190. package/dist/utils/string-similarity.js +189 -0
  191. package/dist/utils/string-similarity.js.map +1 -0
  192. package/dist/utils/token-validation.d.ts +39 -0
  193. package/dist/utils/token-validation.d.ts.map +1 -0
  194. package/dist/utils/token-validation.js +59 -0
  195. package/dist/utils/token-validation.js.map +1 -0
  196. package/dist/utils/type-safety.d.ts +33 -0
  197. package/dist/utils/type-safety.d.ts.map +1 -0
  198. package/dist/utils/type-safety.js +35 -0
  199. package/dist/utils/type-safety.js.map +1 -0
  200. package/dist/web/public/app.js +491 -0
  201. package/dist/web/public/app.js.br +0 -0
  202. package/dist/web/public/app.js.gz +0 -0
  203. package/dist/web/public/index.html +1675 -0
  204. package/dist/web/public/index.html.br +0 -0
  205. package/dist/web/public/index.html.gz +0 -0
  206. package/dist/web/public/manifest.json +8 -0
  207. package/dist/web/public/mobile.css +1 -0
  208. package/dist/web/public/mobile.css.br +0 -0
  209. package/dist/web/public/mobile.css.gz +0 -0
  210. package/dist/web/public/ralph-wizard.js +1037 -0
  211. package/dist/web/public/ralph-wizard.js.br +0 -0
  212. package/dist/web/public/ralph-wizard.js.gz +0 -0
  213. package/dist/web/public/styles.css +1 -0
  214. package/dist/web/public/styles.css.br +0 -0
  215. package/dist/web/public/styles.css.gz +0 -0
  216. package/dist/web/public/sw.js +67 -0
  217. package/dist/web/public/sw.js.br +0 -0
  218. package/dist/web/public/sw.js.gz +0 -0
  219. package/dist/web/public/upload.html +155 -0
  220. package/dist/web/public/upload.html.br +0 -0
  221. package/dist/web/public/upload.html.gz +0 -0
  222. package/dist/web/public/vendor/xterm-addon-fit.min.js +1 -0
  223. package/dist/web/public/vendor/xterm-addon-fit.min.js.br +0 -0
  224. package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
  225. package/dist/web/public/vendor/xterm-addon-unicode11.min.js +1 -0
  226. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.br +0 -0
  227. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
  228. package/dist/web/public/vendor/xterm-addon-webgl.min.js +2 -0
  229. package/dist/web/public/vendor/xterm-addon-webgl.min.js.br +0 -0
  230. package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
  231. package/dist/web/public/vendor/xterm.css +209 -0
  232. package/dist/web/public/vendor/xterm.css.br +0 -0
  233. package/dist/web/public/vendor/xterm.css.gz +0 -0
  234. package/dist/web/public/vendor/xterm.min.js +9 -0
  235. package/dist/web/public/vendor/xterm.min.js.br +0 -0
  236. package/dist/web/public/vendor/xterm.min.js.gz +0 -0
  237. package/dist/web/schemas.d.ts +479 -0
  238. package/dist/web/schemas.d.ts.map +1 -0
  239. package/dist/web/schemas.js +448 -0
  240. package/dist/web/schemas.js.map +1 -0
  241. package/dist/web/server.d.ts +207 -0
  242. package/dist/web/server.d.ts.map +1 -0
  243. package/dist/web/server.js +5784 -0
  244. package/dist/web/server.js.map +1 -0
  245. package/package.json +110 -0
  246. package/scripts/postinstall.js +390 -0
@@ -0,0 +1,1182 @@
1
+ /**
2
+ * @fileoverview Respawn Controller for autonomous Claude Code session cycling
3
+ *
4
+ * The RespawnController manages automatic respawning of Claude Code sessions.
5
+ * When Claude finishes working (detected by completion message + output silence),
6
+ * it automatically cycles through update → clear → init steps to keep the session productive.
7
+ *
8
+ * ## State Machine
9
+ *
10
+ * ```
11
+ * WATCHING → CONFIRMING_IDLE → SENDING_UPDATE → WAITING_UPDATE → SENDING_CLEAR → WAITING_CLEAR
12
+ * ↑ │ │
13
+ * │ │ (new output) ▼
14
+ * │ └─────────────► SENDING_INIT → WAITING_INIT → MONITORING_INIT ────────┘
15
+ * │ │
16
+ * │ ▼ (if no work triggered)
17
+ * └──────────────────────── SENDING_KICKSTART → WAITING_KICKSTART ──┘
18
+ * ```
19
+ *
20
+ * ## Idle Detection (Updated for Claude Code 2024+)
21
+ *
22
+ * Primary detection: Completion message pattern "for Xm Xs" (e.g., "✻ Worked for 2m 46s")
23
+ * Confirmation: No new output for configurable duration (default 5s)
24
+ * Fallback: No output at all for extended period (default 30s)
25
+ *
26
+ * ## Configuration
27
+ *
28
+ * - `sendClear`: Whether to send /clear after update (default: true)
29
+ * - `sendInit`: Whether to send /init after clear (default: true)
30
+ * - `kickstartPrompt`: Optional prompt if /init doesn't trigger work
31
+ * - `completionConfirmMs`: Time to wait after completion message (default: 10000)
32
+ * - `noOutputTimeoutMs`: Fallback timeout with no output at all (default: 30000)
33
+ *
34
+ * @module respawn-controller
35
+ */
36
+ import { EventEmitter } from 'node:events';
37
+ import { Session } from './session.js';
38
+ import { type AiCheckResult, type AiCheckState } from './ai-idle-checker.js';
39
+ import { type AiPlanCheckResult } from './ai-plan-checker.js';
40
+ import type { TeamWatcher } from './team-watcher.js';
41
+ import type { RespawnCycleMetrics, RespawnAggregateMetrics, RalphLoopHealthScore, TimingHistory } from './types.js';
42
+ /**
43
+ * Detection layers for multi-signal idle detection.
44
+ * Each layer provides a confidence signal that Claude has finished working.
45
+ */
46
+ /** Active timer info for UI display */
47
+ export interface ActiveTimerInfo {
48
+ name: string;
49
+ remainingMs: number;
50
+ totalMs: number;
51
+ }
52
+ export interface DetectionStatus {
53
+ /** Layer 0: Stop hook received (highest priority - definitive signal) */
54
+ stopHookReceived: boolean;
55
+ /** Timestamp when Stop hook was received */
56
+ stopHookTime: number | null;
57
+ /** Layer 0: idle_prompt notification received (definitive signal) */
58
+ idlePromptReceived: boolean;
59
+ /** Timestamp when idle_prompt was received */
60
+ idlePromptTime: number | null;
61
+ /** Layer 1: Completion message detected ("for Xm Xs") */
62
+ completionMessageDetected: boolean;
63
+ /** Timestamp when completion message was last seen */
64
+ completionMessageTime: number | null;
65
+ /** Layer 2: Output silence - no new output for threshold duration */
66
+ outputSilent: boolean;
67
+ /** Milliseconds since last output */
68
+ msSinceLastOutput: number;
69
+ /** Layer 3: Token count stability - tokens haven't changed */
70
+ tokensStable: boolean;
71
+ /** Last observed token count */
72
+ lastTokenCount: number;
73
+ /** Milliseconds since token count changed */
74
+ msSinceTokenChange: number;
75
+ /** Layer 4: Working patterns absent - no spinners/activity words */
76
+ workingPatternsAbsent: boolean;
77
+ /** Milliseconds since last working pattern */
78
+ msSinceLastWorking: number;
79
+ /** Layer 5: AI idle check status */
80
+ aiCheck: AiCheckState | null;
81
+ /** Overall confidence level (0-100) */
82
+ confidenceLevel: number;
83
+ /** Human-readable status for UI */
84
+ statusText: string;
85
+ /** What the controller is currently waiting for */
86
+ waitingFor: string;
87
+ /** Active countdown timers */
88
+ activeTimers: ActiveTimerInfo[];
89
+ /** Recent action log entries (last 10) */
90
+ recentActions: ActionLogEntry[];
91
+ /** Current phase description */
92
+ currentPhase: string;
93
+ /** Next expected action */
94
+ nextAction: string;
95
+ /** Stuck-state detection metrics */
96
+ stuckState: {
97
+ /** How long the controller has been in the current state (ms) */
98
+ currentStateDurationMs: number;
99
+ /** Warning threshold (ms) */
100
+ warningThresholdMs: number;
101
+ /** Recovery threshold (ms) */
102
+ recoveryThresholdMs: number;
103
+ /** Number of recovery attempts made */
104
+ recoveryAttempts: number;
105
+ /** Maximum allowed recoveries */
106
+ maxRecoveries: number;
107
+ /** Whether a warning has been emitted for current state */
108
+ isWarned: boolean;
109
+ };
110
+ }
111
+ /**
112
+ * Respawn sequence states.
113
+ *
114
+ * The controller cycles through these states:
115
+ * ```
116
+ * WATCHING → SENDING_UPDATE → WAITING_UPDATE →
117
+ * SENDING_CLEAR → WAITING_CLEAR →
118
+ * SENDING_INIT → WAITING_INIT →
119
+ * MONITORING_INIT → (maybe SENDING_KICKSTART → WAITING_KICKSTART) →
120
+ * WATCHING (repeat)
121
+ * ```
122
+ *
123
+ * Steps can be skipped via config (`sendClear: false`, `sendInit: false`).
124
+ */
125
+ export type RespawnState =
126
+ /** Watching for idle, ready to start respawn sequence */
127
+ 'watching'
128
+ /** Completion message detected, waiting for output silence to confirm */
129
+ | 'confirming_idle'
130
+ /** AI checker is analyzing terminal output for IDLE/WORKING verdict */
131
+ | 'ai_checking'
132
+ /** About to send the update docs prompt */
133
+ | 'sending_update'
134
+ /** Waiting for update to complete */
135
+ | 'waiting_update'
136
+ /** About to send /clear command */
137
+ | 'sending_clear'
138
+ /** Waiting for clear to complete */
139
+ | 'waiting_clear'
140
+ /** About to send /init command */
141
+ | 'sending_init'
142
+ /** Waiting for init to complete */
143
+ | 'waiting_init'
144
+ /** Monitoring if /init triggered work */
145
+ | 'monitoring_init'
146
+ /** About to send kickstart prompt */
147
+ | 'sending_kickstart'
148
+ /** Waiting for kickstart to complete */
149
+ | 'waiting_kickstart'
150
+ /** Controller stopped (not running) */
151
+ | 'stopped';
152
+ /**
153
+ * Configuration options for the RespawnController.
154
+ */
155
+ export interface RespawnConfig {
156
+ /**
157
+ * How long to wait after seeing prompt before considering truly idle.
158
+ * Prevents premature cycling when user is about to type.
159
+ * @default 10000 (10 seconds)
160
+ */
161
+ idleTimeoutMs: number;
162
+ /**
163
+ * The prompt to send when updating docs.
164
+ * Sent at the start of each respawn cycle.
165
+ * @default 'write a brief progress summary to CLAUDE.md noting what you accomplished, then continue working.'
166
+ */
167
+ updatePrompt: string;
168
+ /**
169
+ * Delay between sending steps (ms).
170
+ * Gives Claude time to process each command.
171
+ * @default 1000 (1 second)
172
+ */
173
+ interStepDelayMs: number;
174
+ /**
175
+ * Whether the respawn loop is enabled.
176
+ * When false, start() will be a no-op.
177
+ * @default true
178
+ */
179
+ enabled: boolean;
180
+ /**
181
+ * Whether to send /clear after update prompt completes.
182
+ * Resets Claude's context for fresh start.
183
+ * @default true
184
+ */
185
+ sendClear: boolean;
186
+ /**
187
+ * Whether to send /init after /clear completes.
188
+ * Re-initializes Claude with CLAUDE.md context.
189
+ * @default true
190
+ */
191
+ sendInit: boolean;
192
+ /**
193
+ * Optional prompt to send if /init doesn't trigger work.
194
+ * Used as a fallback when /init completes but Claude doesn't start working.
195
+ * @default undefined
196
+ */
197
+ kickstartPrompt?: string;
198
+ /**
199
+ * Time to wait after completion message before confirming idle (ms).
200
+ * After seeing "for Xm Xs" pattern, waits this long with no new output.
201
+ * @default 10000 (10 seconds)
202
+ */
203
+ completionConfirmMs: number;
204
+ /**
205
+ * Fallback timeout when no output received at all (ms).
206
+ * If no terminal output for this duration, assumes idle even without completion message.
207
+ * @default 30000 (30 seconds)
208
+ */
209
+ noOutputTimeoutMs: number;
210
+ /**
211
+ * Whether to auto-accept plan mode prompts by pressing Enter.
212
+ * When Claude enters plan mode and presents a plan for approval, output stops
213
+ * without a completion message. This feature detects that state and sends Enter
214
+ * to accept the plan. Does NOT auto-accept AskUserQuestion prompts (those are
215
+ * blocked via the elicitation_dialog hook signal).
216
+ * @default true
217
+ */
218
+ autoAcceptPrompts: boolean;
219
+ /**
220
+ * Delay before auto-accepting plan mode prompts (ms).
221
+ * After no output for this duration AND no completion message detected
222
+ * AND no elicitation dialog signaled, sends Enter to accept the plan.
223
+ * Must be shorter than noOutputTimeoutMs.
224
+ * @default 8000 (8 seconds)
225
+ */
226
+ autoAcceptDelayMs: number;
227
+ /**
228
+ * Whether AI idle check is enabled.
229
+ * When enabled, spawns a fresh Claude CLI to analyze terminal output
230
+ * and provide a definitive IDLE/WORKING verdict before starting respawn.
231
+ * @default true
232
+ */
233
+ aiIdleCheckEnabled: boolean;
234
+ /**
235
+ * Model to use for AI idle check.
236
+ * @default 'claude-opus-4-5-20251101'
237
+ */
238
+ aiIdleCheckModel: string;
239
+ /**
240
+ * Maximum characters of terminal buffer to send to AI checker.
241
+ * @default 16000
242
+ */
243
+ aiIdleCheckMaxContext: number;
244
+ /**
245
+ * Timeout for the AI check in ms.
246
+ * @default 90000 (90 seconds)
247
+ */
248
+ aiIdleCheckTimeoutMs: number;
249
+ /**
250
+ * Cooldown after WORKING verdict in ms.
251
+ * @default 180000 (3 minutes)
252
+ */
253
+ aiIdleCheckCooldownMs: number;
254
+ /**
255
+ * Whether AI plan mode check is enabled for auto-accept.
256
+ * When enabled, spawns a fresh Claude CLI to confirm the terminal is
257
+ * showing a plan mode approval prompt before auto-accepting.
258
+ * @default true
259
+ */
260
+ aiPlanCheckEnabled: boolean;
261
+ /**
262
+ * Model to use for AI plan mode check.
263
+ * @default 'claude-opus-4-5-20251101' (thinking enabled by default)
264
+ */
265
+ aiPlanCheckModel: string;
266
+ /**
267
+ * Maximum characters of terminal buffer to send to plan checker.
268
+ * @default 8000
269
+ */
270
+ aiPlanCheckMaxContext: number;
271
+ /**
272
+ * Timeout for the AI plan check in ms.
273
+ * @default 60000 (60 seconds, allows time for thinking)
274
+ */
275
+ aiPlanCheckTimeoutMs: number;
276
+ /**
277
+ * Cooldown after NOT_PLAN_MODE verdict in ms.
278
+ * @default 30000 (30 seconds)
279
+ */
280
+ aiPlanCheckCooldownMs: number;
281
+ /**
282
+ * Enable stuck-state detection.
283
+ * Detects when the controller stays in the same state for too long.
284
+ * @default true
285
+ */
286
+ stuckStateDetectionEnabled: boolean;
287
+ /**
288
+ * Threshold for stuck-state warning in ms.
289
+ * If state doesn't change for this duration, emits a warning.
290
+ * @default 300000 (5 minutes)
291
+ */
292
+ stuckStateWarningMs: number;
293
+ /**
294
+ * Threshold for stuck-state recovery in ms.
295
+ * If state doesn't change for this duration, triggers recovery action.
296
+ * @default 600000 (10 minutes)
297
+ */
298
+ stuckStateRecoveryMs: number;
299
+ /**
300
+ * Maximum consecutive stuck-state recoveries before giving up.
301
+ * @default 3
302
+ */
303
+ maxStuckRecoveries: number;
304
+ /**
305
+ * Enable adaptive timing based on historical patterns.
306
+ * Adjusts completion confirm timeout dynamically.
307
+ * @default true
308
+ */
309
+ adaptiveTimingEnabled?: boolean;
310
+ /**
311
+ * Minimum adaptive completion confirm timeout (ms).
312
+ * @default 5000
313
+ */
314
+ adaptiveMinConfirmMs?: number;
315
+ /**
316
+ * Maximum adaptive completion confirm timeout (ms).
317
+ * @default 30000
318
+ */
319
+ adaptiveMaxConfirmMs?: number;
320
+ /**
321
+ * Skip /clear when context usage is low.
322
+ * @default true
323
+ */
324
+ skipClearWhenLowContext?: boolean;
325
+ /**
326
+ * Context threshold percentage below which to skip /clear.
327
+ * @default 30
328
+ */
329
+ skipClearThresholdPercent?: number;
330
+ /**
331
+ * Enable tracking of respawn cycle metrics.
332
+ * @default true
333
+ */
334
+ trackCycleMetrics?: boolean;
335
+ /**
336
+ * Minimum confidence level required to trigger idle detection.
337
+ * Below this threshold, the controller waits for more signals.
338
+ * @default 65
339
+ */
340
+ minIdleConfidence?: number;
341
+ /**
342
+ * Confidence weight for completion message detection.
343
+ * @default 40
344
+ */
345
+ confidenceWeightCompletion?: number;
346
+ /**
347
+ * Confidence weight for output silence.
348
+ * @default 25
349
+ */
350
+ confidenceWeightSilence?: number;
351
+ /**
352
+ * Confidence weight for token stability.
353
+ * @default 20
354
+ */
355
+ confidenceWeightTokens?: number;
356
+ /**
357
+ * Confidence weight for working pattern absence.
358
+ * @default 15
359
+ */
360
+ confidenceWeightNoWorking?: number;
361
+ }
362
+ /**
363
+ * Events emitted by RespawnController.
364
+ *
365
+ * @event stateChanged - Fired when state machine transitions
366
+ * @event respawnCycleStarted - Fired when a new cycle begins
367
+ * @event respawnCycleCompleted - Fired when a cycle finishes
368
+ * @event stepSent - Fired when a command is sent to the session
369
+ * @event stepCompleted - Fired when a step finishes (ready indicator detected)
370
+ * @event detectionUpdate - Fired when detection status changes (for UI)
371
+ * @event error - Fired on errors
372
+ * @event log - Fired for debug logging
373
+ */
374
+ /** Timer info for countdown display */
375
+ export interface TimerInfo {
376
+ name: string;
377
+ durationMs: number;
378
+ endsAt: number;
379
+ reason?: string;
380
+ }
381
+ /** Action log entry for detailed UI feedback */
382
+ export interface ActionLogEntry {
383
+ type: string;
384
+ detail: string;
385
+ timestamp: number;
386
+ }
387
+ export interface RespawnEvents {
388
+ /** State machine transition */
389
+ stateChanged: (state: RespawnState, prevState: RespawnState) => void;
390
+ /** New respawn cycle started */
391
+ respawnCycleStarted: (cycleNumber: number) => void;
392
+ /** Respawn cycle finished */
393
+ respawnCycleCompleted: (cycleNumber: number) => void;
394
+ /** Command sent to session */
395
+ stepSent: (step: string, input: string) => void;
396
+ /** Step completed (ready indicator detected) */
397
+ stepCompleted: (step: string) => void;
398
+ /** Detection status update for UI display */
399
+ detectionUpdate: (status: DetectionStatus) => void;
400
+ /** Auto-accept sent for plan mode approval */
401
+ autoAcceptSent: () => void;
402
+ /** AI idle check started */
403
+ aiCheckStarted: () => void;
404
+ /** AI idle check completed with verdict */
405
+ aiCheckCompleted: (result: AiCheckResult) => void;
406
+ /** AI idle check failed */
407
+ aiCheckFailed: (error: string) => void;
408
+ /** AI idle check cooldown state changed */
409
+ aiCheckCooldown: (active: boolean, endsAt: number | null) => void;
410
+ /** AI plan check started */
411
+ planCheckStarted: () => void;
412
+ /** AI plan check completed with verdict */
413
+ planCheckCompleted: (result: AiPlanCheckResult) => void;
414
+ /** AI plan check failed */
415
+ planCheckFailed: (error: string) => void;
416
+ /** Timer started for countdown display */
417
+ timerStarted: (timer: TimerInfo) => void;
418
+ /** Timer cancelled */
419
+ timerCancelled: (timerName: string, reason?: string) => void;
420
+ /** Timer completed */
421
+ timerCompleted: (timerName: string) => void;
422
+ /** Verbose action log for detailed UI feedback */
423
+ actionLog: (action: ActionLogEntry) => void;
424
+ /** Error occurred */
425
+ error: (error: Error) => void;
426
+ /** Debug log message */
427
+ log: (message: string) => void;
428
+ /** Stuck state warning emitted */
429
+ stuckStateWarning: (state: RespawnState, durationMs: number) => void;
430
+ /** Stuck state recovery triggered */
431
+ stuckStateRecovery: (state: RespawnState, durationMs: number, attempt: number) => void;
432
+ /** Respawn blocked by external signal */
433
+ respawnBlocked: (data: {
434
+ reason: string;
435
+ details: string;
436
+ }) => void;
437
+ }
438
+ /**
439
+ * RespawnController - Automatic session cycling for continuous Claude work.
440
+ *
441
+ * Monitors a Claude Code session for idle state and automatically cycles
442
+ * through update → clear → init steps to keep the session productive.
443
+ *
444
+ * ## How It Works
445
+ *
446
+ * 1. **Idle Detection**: Watches for completion message ("for Xm Xs" pattern)
447
+ * 2. **Confirmation**: Waits for output silence (no new tokens for 5s)
448
+ * 3. **Update**: Sends configured prompt (e.g., "update all docs")
449
+ * 4. **Clear**: Sends `/clear` to reset context (optional)
450
+ * 5. **Init**: Sends `/init` to re-initialize with CLAUDE.md (optional)
451
+ * 6. **Kickstart**: If /init doesn't trigger work, sends fallback prompt (optional)
452
+ * 7. **Repeat**: Returns to watching state for next cycle
453
+ *
454
+ * ## Idle Detection (Updated for Claude Code 2024+)
455
+ *
456
+ * Primary: Completion message with time duration (e.g., "✻ Worked for 2m 46s")
457
+ * The pattern "for Xm Xs" indicates Claude finished work and reports duration.
458
+ *
459
+ * Confirmation: After seeing completion message, waits for output silence.
460
+ * If no new output for `completionConfirmMs` (default 10s), confirms idle.
461
+ *
462
+ * Fallback: If no output at all for `noOutputTimeoutMs` (default 30s), assumes idle.
463
+ *
464
+ * Working indicators: Thinking, Writing, spinner characters, etc. reset detection.
465
+ *
466
+ * ## Events
467
+ *
468
+ * - `stateChanged`: State machine transition
469
+ * - `respawnCycleStarted`: New cycle began
470
+ * - `respawnCycleCompleted`: Cycle finished
471
+ * - `stepSent`: Command sent to session
472
+ * - `stepCompleted`: Step finished
473
+ * - `log`: Debug messages
474
+ *
475
+ * @extends EventEmitter
476
+ * @example
477
+ * ```typescript
478
+ * const respawn = new RespawnController(session, {
479
+ * updatePrompt: 'continue working on the task',
480
+ * completionConfirmMs: 10000, // Wait 10s after completion message
481
+ * });
482
+ *
483
+ * respawn.on('respawnCycleCompleted', (cycle) => {
484
+ * console.log(`Completed cycle ${cycle}`);
485
+ * });
486
+ *
487
+ * respawn.start();
488
+ * ```
489
+ */
490
+ export declare class RespawnController extends EventEmitter {
491
+ /** The session being controlled */
492
+ private session;
493
+ /** Optional team watcher for team-aware idle detection */
494
+ private teamWatcher;
495
+ /** Current configuration */
496
+ private config;
497
+ /** Current state machine state */
498
+ private _state;
499
+ /** Timer for step delays */
500
+ private stepTimer;
501
+ /** Timer for completion confirmation (Layer 2) */
502
+ private completionConfirmTimer;
503
+ /** Timer for no-output fallback (Layer 5) */
504
+ private noOutputTimer;
505
+ /** Timer for periodic detection status updates */
506
+ private detectionUpdateTimer;
507
+ /** Timer for auto-accepting plan mode prompts */
508
+ private autoAcceptTimer;
509
+ /** Timer for pre-filter silence detection (triggers AI check) */
510
+ private preFilterTimer;
511
+ /** Whether any terminal output has been received since start/last-auto-accept */
512
+ private hasReceivedOutput;
513
+ /** Whether an elicitation dialog (AskUserQuestion) was detected via hook signal */
514
+ private elicitationDetected;
515
+ /** Whether a Stop hook was received (definitive idle signal from Claude Code) */
516
+ private stopHookReceived;
517
+ /** Timestamp when Stop hook was received */
518
+ private stopHookTime;
519
+ /** Whether an idle_prompt notification was received (60s+ idle signal) */
520
+ private idlePromptReceived;
521
+ /** Timestamp when idle_prompt was received */
522
+ private idlePromptTime;
523
+ /** Timer for short confirmation after hook signal (handles race conditions) */
524
+ private hookConfirmTimer;
525
+ /** Confirmation delay after hook signal before confirming idle (ms) */
526
+ private static readonly HOOK_CONFIRM_DELAY_MS;
527
+ /** Number of completed respawn cycles */
528
+ private cycleCount;
529
+ /** Timestamp of last terminal activity */
530
+ private lastActivityTime;
531
+ /** Buffer for recent terminal output (uses BufferAccumulator to reduce GC pressure) */
532
+ private terminalBuffer;
533
+ /** Whether a prompt indicator was detected */
534
+ private promptDetected;
535
+ /** Whether a working indicator was detected */
536
+ private workingDetected;
537
+ /** Reference to terminal event handler (for cleanup) */
538
+ private terminalHandler;
539
+ /** AI idle checker instance */
540
+ private aiChecker;
541
+ /** AI plan mode checker instance */
542
+ private planChecker;
543
+ /** Timestamp when plan check was started (to detect stale results) */
544
+ private planCheckStartTime;
545
+ /** Unique ID for current AI check request (to detect stale results) */
546
+ private _currentAiCheckId;
547
+ /** Timer for /clear step fallback (sends /init if no prompt detected) */
548
+ private clearFallbackTimer;
549
+ /** Timer for step completion confirmation (waits for silence after completion) */
550
+ private stepConfirmTimer;
551
+ /** Fallback timeout for /clear step (ms) - sends /init without waiting for prompt */
552
+ private static readonly CLEAR_FALLBACK_TIMEOUT_MS;
553
+ /** Active timers being tracked for UI display */
554
+ private activeTimers;
555
+ /** Recent action log entries (for UI display, max 20) */
556
+ private recentActions;
557
+ /** Timestamp when the current state was entered */
558
+ private stateEnteredAt;
559
+ /** Timer for stuck-state detection */
560
+ private stuckStateTimer;
561
+ /** Whether a stuck-state warning has been emitted for current state */
562
+ private stuckStateWarned;
563
+ /** Number of stuck-state recovery attempts */
564
+ private stuckRecoveryCount;
565
+ /** Historical timing data for adaptive adjustments */
566
+ private timingHistory;
567
+ /** Current cycle being tracked */
568
+ private currentCycleMetrics;
569
+ /** Timestamp when idle detection started for current cycle */
570
+ private idleDetectionStartTime;
571
+ /** Recent cycle metrics (rolling window for aggregate calculation) */
572
+ private recentCycleMetrics;
573
+ /** Maximum number of cycle metrics to keep in memory */
574
+ private static readonly MAX_CYCLE_METRICS_IN_MEMORY;
575
+ /** Aggregate metrics across all tracked cycles */
576
+ private aggregateMetrics;
577
+ /** Layer 1: Timestamp when completion message was detected */
578
+ private completionMessageTime;
579
+ /** Layer 2: Timestamp of last terminal output received */
580
+ private lastOutputTime;
581
+ /** Layer 3: Last observed token count */
582
+ private lastTokenCount;
583
+ /** Layer 3: Timestamp when token count last changed */
584
+ private lastTokenChangeTime;
585
+ /** Layer 4: Timestamp when last working pattern was seen */
586
+ private lastWorkingPatternTime;
587
+ /**
588
+ * Patterns indicating Claude is ready for input (legacy fallback).
589
+ * Used as secondary signals, not primary detection.
590
+ */
591
+ private readonly PROMPT_PATTERNS;
592
+ /**
593
+ * Patterns indicating Claude is actively working.
594
+ * When detected, resets all idle detection timers.
595
+ * Note: ✻ and ✽ removed - they appear in completion messages too.
596
+ */
597
+ private readonly WORKING_PATTERNS;
598
+ /**
599
+ * Rolling window buffer for working pattern detection.
600
+ * Prevents split-chunk issues where "Thinking" arrives as "Thin" + "king".
601
+ * Size: 300 chars should be enough to catch any split pattern.
602
+ */
603
+ private workingPatternWindow;
604
+ private static readonly WORKING_PATTERN_WINDOW_SIZE;
605
+ /**
606
+ * Minimum time without working patterns before considering idle (ms).
607
+ * Increased from 3s to 8s to avoid false positives during tool execution gaps.
608
+ */
609
+ private static readonly MIN_WORKING_PATTERN_ABSENCE_MS;
610
+ /**
611
+ * Creates a new RespawnController.
612
+ *
613
+ * @param session - The Session instance to control
614
+ * @param config - Partial configuration (merged with defaults)
615
+ */
616
+ constructor(session: Session, config?: Partial<RespawnConfig>);
617
+ /**
618
+ * Validate configuration values and reset invalid ones to defaults.
619
+ * Ensures timeouts are positive and logically consistent.
620
+ */
621
+ private validateConfig;
622
+ /** Wire up AI checker events to controller events (removes existing listeners first to prevent duplicates) */
623
+ private setupAiCheckerListeners;
624
+ /** Wire up plan checker events to controller events (removes existing listeners first to prevent duplicates) */
625
+ private setupPlanCheckerListeners;
626
+ /**
627
+ * Get the current state machine state.
628
+ * @returns Current RespawnState
629
+ */
630
+ get state(): RespawnState;
631
+ /**
632
+ * Get the current respawn cycle count.
633
+ * Increments each time a new cycle starts.
634
+ * @returns Number of cycles started
635
+ */
636
+ get currentCycle(): number;
637
+ /**
638
+ * Check if the controller is currently running.
639
+ * @returns True if state is not 'stopped'
640
+ */
641
+ get isRunning(): boolean;
642
+ /**
643
+ * Get current detection status for UI display.
644
+ * Shows all detection layers and their current state.
645
+ * @returns DetectionStatus object
646
+ */
647
+ getDetectionStatus(): DetectionStatus;
648
+ /**
649
+ * Start periodic detection status updates for UI.
650
+ * Emits 'detectionUpdate' event every 2s while running.
651
+ */
652
+ private startDetectionUpdates;
653
+ /**
654
+ * Stop periodic detection status updates.
655
+ */
656
+ private stopDetectionUpdates;
657
+ /**
658
+ * Transition to a new state.
659
+ * Emits 'stateChanged' event with old and new states.
660
+ * No-op if already in the target state.
661
+ *
662
+ * @param newState - State to transition to
663
+ * @fires stateChanged
664
+ */
665
+ private setState;
666
+ /**
667
+ * Emit a timestamped log message.
668
+ * @param message - Log message content
669
+ * @fires log
670
+ */
671
+ private log;
672
+ /** Set team watcher for team-aware idle detection */
673
+ setTeamWatcher(watcher: TeamWatcher): void;
674
+ /**
675
+ * Start watching the session for idle state.
676
+ *
677
+ * Begins monitoring terminal output for idle indicators.
678
+ * When idle is detected, starts the respawn cycle.
679
+ *
680
+ * No-op if:
681
+ * - `config.enabled` is false
682
+ * - Already running (state !== 'stopped')
683
+ *
684
+ * @fires stateChanged - Transitions to 'watching'
685
+ */
686
+ start(): void;
687
+ /**
688
+ * Stop the respawn controller.
689
+ *
690
+ * Clears all timers, removes terminal listener, and sets state to 'stopped'.
691
+ * Safe to call multiple times.
692
+ *
693
+ * @fires stateChanged - Transitions to 'stopped'
694
+ */
695
+ stop(): void;
696
+ /**
697
+ * Pause respawn without stopping.
698
+ *
699
+ * Clears timers but keeps listening to terminal.
700
+ * State is preserved; won't trigger idle detection while paused.
701
+ * Use resume() to continue.
702
+ */
703
+ pause(): void;
704
+ /**
705
+ * Resume respawn after pause.
706
+ *
707
+ * If in 'watching' state, immediately checks for idle condition.
708
+ * Otherwise, continues from current state.
709
+ * Re-setups terminal listener if it was removed (e.g., after stop()).
710
+ */
711
+ resume(): void;
712
+ /**
713
+ * Set up terminal output listener on the session.
714
+ * Removes any previous listener first to avoid duplicates.
715
+ */
716
+ private setupTerminalListener;
717
+ /**
718
+ * Process terminal data for idle/working detection using multi-layer approach.
719
+ *
720
+ * Detection Layers:
721
+ * 1. Completion message ("for Xm Xs") - PRIMARY signal
722
+ * 2. Output silence - confirms completion
723
+ * 3. Token stability - additional confirmation
724
+ * 4. Working pattern absence - supports idle detection
725
+ * 5. No-output fallback - catches edge cases
726
+ *
727
+ * @param data - Raw terminal output data
728
+ */
729
+ private handleTerminalData;
730
+ /**
731
+ * Handle update step completion.
732
+ * Called when ready indicator detected in waiting_update state.
733
+ * Proceeds to clear, init, or completes cycle based on config.
734
+ * @fires stepCompleted - With step 'update'
735
+ */
736
+ private checkUpdateComplete;
737
+ /**
738
+ * Handle /clear step completion.
739
+ * Proceeds to init or completes cycle based on config.
740
+ * @fires stepCompleted - With step 'clear'
741
+ */
742
+ private checkClearComplete;
743
+ /**
744
+ * Handle /init step completion.
745
+ * If kickstart is configured, monitors for work.
746
+ * Otherwise completes cycle.
747
+ * @fires stepCompleted - With step 'init' (if no kickstart)
748
+ */
749
+ private checkInitComplete;
750
+ /**
751
+ * Start monitoring to see if /init triggered work.
752
+ * Enters 'monitoring_init' state and waits 3s grace period.
753
+ * If no work detected, sends kickstart prompt.
754
+ */
755
+ private startMonitoringInit;
756
+ /**
757
+ * Handle monitoring timeout when /init didn't trigger work.
758
+ * Sends kickstart prompt as fallback.
759
+ * @fires stepCompleted - With step 'init'
760
+ */
761
+ private checkMonitoringInitIdle;
762
+ /**
763
+ * Send the kickstart prompt to get Claude working.
764
+ * @fires stepSent - With step 'kickstart'
765
+ */
766
+ private sendKickstart;
767
+ /**
768
+ * Handle kickstart step completion.
769
+ * @fires stepCompleted - With step 'kickstart'
770
+ */
771
+ private checkKickstartComplete;
772
+ /** Clear all timers (step, completion confirm, no-output, pre-filter, step confirm, auto-accept, hook confirm, and clear fallback) */
773
+ private clearTimers;
774
+ /**
775
+ * Start or restart the stuck-state detection timer.
776
+ * Emits warning after stuckStateWarningMs, triggers recovery after stuckStateRecoveryMs.
777
+ */
778
+ private startStuckStateTimer;
779
+ /**
780
+ * Check if the controller is stuck in the current state.
781
+ * Emits warnings and triggers recovery actions as appropriate.
782
+ */
783
+ private checkStuckState;
784
+ /**
785
+ * Handle stuck-state recovery by resetting to a known good state.
786
+ * Uses escalating recovery strategies based on current state.
787
+ */
788
+ private handleStuckStateRecovery;
789
+ /**
790
+ * Get stuck-state metrics for UI display.
791
+ */
792
+ getStuckStateMetrics(): {
793
+ currentStateDurationMs: number;
794
+ warningThresholdMs: number;
795
+ recoveryThresholdMs: number;
796
+ recoveryAttempts: number;
797
+ maxRecoveries: number;
798
+ isWarned: boolean;
799
+ };
800
+ /**
801
+ * Start a tracked timer with UI countdown support.
802
+ * Emits timerStarted event and tracks the timer for UI display.
803
+ */
804
+ private startTrackedTimer;
805
+ /**
806
+ * Cancel a tracked timer and emit cancellation event.
807
+ */
808
+ private cancelTrackedTimer;
809
+ /**
810
+ * Get all active timers with remaining time for UI display.
811
+ */
812
+ getActiveTimers(): ActiveTimerInfo[];
813
+ /**
814
+ * Log an action for detailed UI feedback.
815
+ * Keeps the last 20 entries.
816
+ */
817
+ private logAction;
818
+ /**
819
+ * Get recent action log entries.
820
+ */
821
+ getRecentActions(): ActionLogEntry[];
822
+ /**
823
+ * Check if data contains a completion message pattern.
824
+ * Matches "for Xh Xm Xs" time duration patterns.
825
+ */
826
+ private isCompletionMessage;
827
+ /**
828
+ * Check if data contains working patterns.
829
+ * Uses rolling window to catch patterns split across chunks (e.g., "Thin" + "king").
830
+ */
831
+ private hasWorkingPattern;
832
+ /**
833
+ * Clear the working pattern rolling window.
834
+ * Called when starting a new detection cycle.
835
+ */
836
+ private clearWorkingPatternWindow;
837
+ /**
838
+ * Extract token count from data if present.
839
+ * Returns null if no token pattern found.
840
+ */
841
+ private extractTokenCount;
842
+ /**
843
+ * Start the no-output fallback timer.
844
+ * If no output for noOutputTimeoutMs, triggers idle detection as safety net
845
+ * (used when AI check is disabled or has too many errors).
846
+ */
847
+ private startNoOutputTimer;
848
+ /**
849
+ * Reset the no-output fallback timer.
850
+ * Called whenever output is received.
851
+ */
852
+ private resetNoOutputTimer;
853
+ /**
854
+ * Start the pre-filter timer.
855
+ * Fires after completionConfirmMs of silence. When it fires, checks if
856
+ * all pre-filter conditions are met and starts the AI check if so.
857
+ * This provides an additional path to AI check even without a completion message.
858
+ */
859
+ private startPreFilterTimer;
860
+ /**
861
+ * Reset the pre-filter timer.
862
+ * Called whenever output is received.
863
+ */
864
+ private resetPreFilterTimer;
865
+ /**
866
+ * Attempt to start an AI idle check.
867
+ * Checks if AI check is enabled, not on cooldown, and not already checking.
868
+ * Falls back to direct idle confirmation if AI check is unavailable.
869
+ *
870
+ * @param reason - What triggered this attempt (for logging)
871
+ */
872
+ private tryStartAiCheck;
873
+ /**
874
+ * Start the AI idle check.
875
+ * Transitions to 'ai_checking' state and runs the check asynchronously.
876
+ *
877
+ * @param reason - What triggered this check (for logging)
878
+ */
879
+ private startAiCheck;
880
+ /**
881
+ * Reset the auto-accept timer.
882
+ * Called whenever output is received. After autoAcceptDelayMs of silence
883
+ * (without a completion message), sends Enter to accept prompts.
884
+ */
885
+ private resetAutoAcceptTimer;
886
+ /**
887
+ * Start the auto-accept timer.
888
+ * Fires after autoAcceptDelayMs of no output when no completion message
889
+ * and no elicitation dialog was detected. Only handles plan mode approvals.
890
+ */
891
+ private startAutoAcceptTimer;
892
+ /**
893
+ * Cancel the auto-accept timer.
894
+ * Called when a completion message is detected (normal idle flow handles it).
895
+ */
896
+ private cancelAutoAcceptTimer;
897
+ /**
898
+ * Attempt to auto-accept a plan mode prompt by sending Enter.
899
+ * Two-stage gate:
900
+ * 1. Strict regex pre-filter — check if terminal buffer contains plan mode UI elements
901
+ * 2. AI confirmation — spawn Opus to classify buffer as PLAN_MODE or NOT_PLAN_MODE
902
+ *
903
+ * Only sends Enter if both stages confirm (or pre-filter only if AI disabled).
904
+ *
905
+ * @fires autoAcceptSent
906
+ * @fires planCheckStarted
907
+ */
908
+ private tryAutoAccept;
909
+ /**
910
+ * Check if the terminal buffer matches plan mode pre-filter patterns.
911
+ * Only checks the last 2000 chars (plan mode UI appears at the bottom).
912
+ *
913
+ * Must find:
914
+ * - Numbered option pattern (e.g., "1. Yes", "2. No")
915
+ * - Selection indicator (❯ or > followed by number)
916
+ * Must NOT find:
917
+ * - Recent working patterns (spinners, "Thinking", etc.) in the tail
918
+ */
919
+ private isPlanModePreFilterMatch;
920
+ /**
921
+ * Start an AI plan check to confirm plan mode before auto-accepting.
922
+ * Async — result handled by then/catch.
923
+ *
924
+ * @param buffer - Terminal buffer to analyze
925
+ * @fires planCheckStarted
926
+ * @fires planCheckCompleted
927
+ * @fires planCheckFailed
928
+ */
929
+ private startPlanCheck;
930
+ /**
931
+ * Send the actual Enter keystroke for auto-accept.
932
+ * Factored out so both pre-filter-only and AI-confirmed paths can call it.
933
+ * @fires autoAcceptSent
934
+ */
935
+ private sendAutoAcceptEnter;
936
+ /**
937
+ * Signal that an elicitation dialog (AskUserQuestion) was detected via hook.
938
+ * This prevents auto-accept from firing, since the user needs to make a selection.
939
+ * The flag is cleared when working patterns are detected (new turn starts).
940
+ */
941
+ signalElicitation(): void;
942
+ /**
943
+ * Signal that a Stop hook was received from Claude Code.
944
+ * This is a DEFINITIVE signal that Claude has finished responding.
945
+ * Skips AI idle check and uses a short confirmation period to handle race conditions.
946
+ *
947
+ * @fires log
948
+ */
949
+ signalStopHook(): void;
950
+ /**
951
+ * Signal that an idle_prompt notification was received from Claude Code.
952
+ * This fires after 60+ seconds of Claude waiting for user input.
953
+ * This is a DEFINITIVE signal that Claude is idle.
954
+ *
955
+ * @fires log
956
+ */
957
+ signalIdlePrompt(): void;
958
+ /**
959
+ * Start a short confirmation timer after receiving a hook signal.
960
+ * This handles race conditions where a hook arrives but Claude immediately starts new work.
961
+ *
962
+ * @param hookType - Which hook triggered this ('stop' or 'idle_prompt')
963
+ */
964
+ private startHookConfirmTimer;
965
+ /**
966
+ * Reset hook-based detection state.
967
+ * Called when hooks are cancelled due to new activity.
968
+ */
969
+ private resetHookState;
970
+ /**
971
+ * Signal that the transcript indicates completion.
972
+ * This is a supporting signal from transcript file monitoring.
973
+ * Unlike hooks, this doesn't immediately trigger idle - it boosts confidence.
974
+ */
975
+ signalTranscriptComplete(): void;
976
+ /**
977
+ * Signal that the transcript indicates plan mode.
978
+ * This helps prevent auto-accept from triggering on AskUserQuestion.
979
+ */
980
+ signalTranscriptPlanMode(): void;
981
+ /**
982
+ * Start completion confirmation timer.
983
+ * After completion message, waits for output silence then triggers AI check.
984
+ */
985
+ private startCompletionConfirmTimer;
986
+ /**
987
+ * Cancel completion confirmation if new activity detected.
988
+ */
989
+ private cancelCompletionConfirm;
990
+ /**
991
+ * Start step confirmation timer for waiting states.
992
+ * Waits for output silence before proceeding to next step.
993
+ * This ensures Claude has finished processing before we send the next command.
994
+ */
995
+ private startStepConfirmTimer;
996
+ /**
997
+ * Cancel step confirmation if working patterns detected.
998
+ */
999
+ private cancelStepConfirm;
1000
+ /**
1001
+ * Called when idle is confirmed through any detection layer.
1002
+ * @param reason - What triggered the confirmation
1003
+ */
1004
+ private onIdleConfirmed;
1005
+ /**
1006
+ * Handle confirmed idle detection.
1007
+ * Starts a new respawn cycle.
1008
+ * @fires respawnCycleStarted
1009
+ */
1010
+ private onIdleDetected;
1011
+ /**
1012
+ * Send the update docs prompt (first step of cycle).
1013
+ * Uses RALPH_STATUS RECOMMENDATION if available, otherwise falls back to configured prompt.
1014
+ * @fires stepSent - With step 'update'
1015
+ */
1016
+ private sendUpdateDocs;
1017
+ /**
1018
+ * Send /clear command.
1019
+ * Starts a 10-second fallback timer - if no prompt is detected after /clear,
1020
+ * proceeds to /init anyway (workaround for when Claude doesn't show prompt after /clear).
1021
+ * @fires stepSent - With step 'clear'
1022
+ */
1023
+ private sendClear;
1024
+ /**
1025
+ * Send /init command.
1026
+ * @fires stepSent - With step 'init'
1027
+ */
1028
+ private sendInit;
1029
+ /**
1030
+ * Complete the current respawn cycle.
1031
+ * Returns to watching state for next cycle.
1032
+ * @fires respawnCycleCompleted
1033
+ */
1034
+ private completeCycle;
1035
+ /**
1036
+ * Check if already idle and start cycle if so.
1037
+ * Used when resuming from pause.
1038
+ */
1039
+ private checkIdleAndMaybeStart;
1040
+ /**
1041
+ * Update configuration at runtime.
1042
+ *
1043
+ * Merges provided config with existing config.
1044
+ * Takes effect immediately for new operations.
1045
+ *
1046
+ * @param config - Partial configuration to merge
1047
+ * @fires log - With updated config details
1048
+ */
1049
+ updateConfig(config: Partial<RespawnConfig>): void;
1050
+ /**
1051
+ * Get current configuration.
1052
+ * @returns Copy of current config (safe to modify)
1053
+ */
1054
+ getConfig(): RespawnConfig;
1055
+ /**
1056
+ * Get comprehensive status information.
1057
+ *
1058
+ * Useful for debugging and monitoring.
1059
+ *
1060
+ * @returns Status object with:
1061
+ * - state: Current state machine state
1062
+ * - cycleCount: Number of cycles started
1063
+ * - lastActivityTime: Timestamp of last activity
1064
+ * - timeSinceActivity: Milliseconds since last activity
1065
+ * - promptDetected: Whether prompt indicator seen
1066
+ * - workingDetected: Whether working indicator seen
1067
+ * - detection: Multi-layer detection status
1068
+ * - config: Current configuration
1069
+ */
1070
+ getStatus(): {
1071
+ state: RespawnState;
1072
+ cycleCount: number;
1073
+ lastActivityTime: number;
1074
+ timeSinceActivity: number;
1075
+ promptDetected: boolean;
1076
+ workingDetected: boolean;
1077
+ detection: DetectionStatus;
1078
+ config: RespawnConfig;
1079
+ };
1080
+ /**
1081
+ * Get the current completion confirm timeout, potentially adjusted by adaptive timing.
1082
+ * Uses historical idle detection durations to calculate an optimal timeout.
1083
+ *
1084
+ * @returns Completion confirm timeout in milliseconds
1085
+ */
1086
+ getAdaptiveCompletionConfirmMs(): number;
1087
+ /**
1088
+ * Record timing data from a completed cycle for adaptive adjustments.
1089
+ *
1090
+ * @param idleDetectionMs - Time spent detecting idle
1091
+ * @param cycleDurationMs - Total cycle duration
1092
+ */
1093
+ private recordTimingData;
1094
+ /**
1095
+ * Recalculate the adaptive completion confirm timeout based on historical data.
1096
+ * Uses the 75th percentile of recent idle detection times as the new timeout,
1097
+ * with a 20% buffer for safety.
1098
+ */
1099
+ private updateAdaptiveTiming;
1100
+ /**
1101
+ * Get the current timing history for monitoring.
1102
+ * @returns Copy of timing history
1103
+ */
1104
+ getTimingHistory(): TimingHistory;
1105
+ /**
1106
+ * Determine whether to skip the /clear step based on current context usage.
1107
+ * Skips if token count is below the configured threshold percentage.
1108
+ *
1109
+ * @returns True if /clear should be skipped
1110
+ */
1111
+ private shouldSkipClear;
1112
+ /**
1113
+ * Start tracking metrics for a new cycle.
1114
+ * Called when a respawn cycle begins.
1115
+ */
1116
+ private startCycleMetrics;
1117
+ /**
1118
+ * Record a completed step in the current cycle.
1119
+ * @param step - Name of the step (e.g., 'update', 'clear', 'init')
1120
+ */
1121
+ private recordCycleStep;
1122
+ /**
1123
+ * Complete the current cycle metrics with outcome.
1124
+ * Adds to recent metrics and updates aggregates.
1125
+ *
1126
+ * @param outcome - Outcome of the cycle
1127
+ * @param errorMessage - Optional error message if outcome is 'error'
1128
+ */
1129
+ private completeCycleMetrics;
1130
+ /**
1131
+ * Update aggregate metrics with a new cycle's data.
1132
+ * @param metrics - The completed cycle metrics
1133
+ */
1134
+ private updateAggregateMetrics;
1135
+ /**
1136
+ * Get aggregate metrics for monitoring.
1137
+ * @returns Copy of aggregate metrics
1138
+ */
1139
+ getAggregateMetrics(): RespawnAggregateMetrics;
1140
+ /**
1141
+ * Get recent cycle metrics for analysis.
1142
+ * @param limit - Maximum number of metrics to return (default: 20)
1143
+ * @returns Recent cycle metrics, newest first
1144
+ */
1145
+ getRecentCycleMetrics(limit?: number): RespawnCycleMetrics[];
1146
+ /**
1147
+ * Calculate a comprehensive health score for the Ralph Loop system.
1148
+ * Aggregates multiple health signals into a single score (0-100).
1149
+ *
1150
+ * @returns Health score with component breakdown
1151
+ */
1152
+ calculateHealthScore(): RalphLoopHealthScore;
1153
+ /**
1154
+ * Calculate score based on recent cycle success rate.
1155
+ */
1156
+ private calculateCycleSuccessScore;
1157
+ /**
1158
+ * Calculate score based on circuit breaker state.
1159
+ */
1160
+ private calculateCircuitBreakerScore;
1161
+ /**
1162
+ * Calculate score based on iteration progress.
1163
+ */
1164
+ private calculateIterationProgressScore;
1165
+ /**
1166
+ * Calculate score based on AI checker health.
1167
+ */
1168
+ private calculateAiCheckerScore;
1169
+ /**
1170
+ * Calculate score based on stuck-state recovery count.
1171
+ */
1172
+ private calculateStuckRecoveryScore;
1173
+ /**
1174
+ * Generate health recommendations based on component scores.
1175
+ */
1176
+ private generateHealthRecommendations;
1177
+ /**
1178
+ * Generate a human-readable health summary.
1179
+ */
1180
+ private generateHealthSummary;
1181
+ }
1182
+ //# sourceMappingURL=respawn-controller.d.ts.map