Context
Reported by @rothnic in PR #1777 — when runtime-fallback is in progress, the todo-continuation-enforcer fires on session.idle, uses the old rate-limited model, and causes a loop.
Related PR: #1777
Problem
The todo-continuation-enforcer hook monitors for idle sessions and injects continuation messages to keep work progressing. However, it has no awareness of the runtime-fallback system. When a model is rate-limited and runtime-fallback is processing:
- The rate-limited model request fails
- Runtime-fallback begins its retry/model-switch logic
- During the brief idle gap (while fallback resolves),
session.idle fires
- Todo-continuation-enforcer detects incomplete todos and injects a "continue" message
- This "continue" message goes to the old rate-limited model (not the fallback model)
- That request also fails → another idle → another continuation → loop
Root Cause
todo-continuation-enforcer/handler.ts has no check for whether a runtime-fallback is in progress
todo-continuation-enforcer/constants.ts sets ABORT_WINDOW_MS = 3000 (3 seconds) — if fallback resolution takes longer than 3s, the abort window expires and continuation fires
todo-continuation-enforcer/idle-event.ts processes session.idle events without consulting fallback state
- There is no shared "fallback in progress" signal between
runtime-fallback and todo-continuation-enforcer
Suggested Fix
Options (not mutually exclusive):
- Shared signal: Runtime-fallback sets a "fallback in progress" flag that todo-continuation checks before firing
- Extended abort window: Increase
ABORT_WINDOW_MS or make it dynamic based on fallback state
- Explicit suppression: Runtime-fallback explicitly suppresses continuation hooks during retry
- Model-aware continuation: Todo-continuation checks if the model it would use is currently rate-limited
Key Files
src/hooks/todo-continuation-enforcer/handler.ts — No fallback-in-progress check
src/hooks/todo-continuation-enforcer/idle-event.ts — Processes session.idle without consulting fallback state
src/hooks/todo-continuation-enforcer/constants.ts — ABORT_WINDOW_MS = 3000
src/hooks/runtime-fallback/fallback-state.ts — Fallback state management (no cross-hook signal)
src/hooks/runtime-fallback/event-handler.ts — Handles session events during fallback
cc @rothnic @davidakerr
Context
Reported by @rothnic in PR #1777 — when runtime-fallback is in progress, the todo-continuation-enforcer fires on
session.idle, uses the old rate-limited model, and causes a loop.Related PR: #1777
Problem
The
todo-continuation-enforcerhook monitors for idle sessions and injects continuation messages to keep work progressing. However, it has no awareness of the runtime-fallback system. When a model is rate-limited and runtime-fallback is processing:session.idlefiresRoot Cause
todo-continuation-enforcer/handler.tshas no check for whether a runtime-fallback is in progresstodo-continuation-enforcer/constants.tssetsABORT_WINDOW_MS = 3000(3 seconds) — if fallback resolution takes longer than 3s, the abort window expires and continuation firestodo-continuation-enforcer/idle-event.tsprocessessession.idleevents without consulting fallback stateruntime-fallbackandtodo-continuation-enforcerSuggested Fix
Options (not mutually exclusive):
ABORT_WINDOW_MSor make it dynamic based on fallback stateKey Files
src/hooks/todo-continuation-enforcer/handler.ts— No fallback-in-progress checksrc/hooks/todo-continuation-enforcer/idle-event.ts— Processessession.idlewithout consulting fallback statesrc/hooks/todo-continuation-enforcer/constants.ts—ABORT_WINDOW_MS = 3000src/hooks/runtime-fallback/fallback-state.ts— Fallback state management (no cross-hook signal)src/hooks/runtime-fallback/event-handler.ts— Handles session events during fallbackcc @rothnic @davidakerr