feat: state-aware idle detection with backoff and max idle duration#29
Open
malpou wants to merge 23 commits intocomputerlovetech:mainfrom
Open
feat: state-aware idle detection with backoff and max idle duration#29malpou wants to merge 23 commits intocomputerlovetech:mainfrom
malpou wants to merge 23 commits intocomputerlovetech:mainfrom
Conversation
…rser Add IdleConfig dataclass, idle state tracking on RunState (consecutive_idle, cumulative_idle_time, mark_idle, reset_idle), IDLE_STATE_MARKER constant, parse_duration() for human-readable durations (30s, 5m, 6h), and frontmatter field constants for the idle configuration block. Co-authored-by: Ralphify <noreply@ralphify.co>
…XCEEDED status Co-authored-by: Ralphify <noreply@ralphify.co>
Detect <!-- ralph:state idle --> marker in agent output, emit ITERATION_IDLE events, apply exponential backoff delays between idle iterations, reset idle tracking on non-idle iterations, and stop the loop when cumulative idle time exceeds idle.max. Co-authored-by: Ralphify <noreply@ralphify.co>
Add _validate_idle() to parse the idle frontmatter block with support for duration strings (30s, 5m, 1h) and numeric values. Validates all sub-fields (delay, backoff, max_delay, max) and rejects unknown fields. Co-authored-by: Ralphify <noreply@ralphify.co>
Add dimmed idle indicator (◇) for idle iterations and show "Stopped (idle):" summary when a run ends due to max idle time. Co-authored-by: Ralphify <noreply@ralphify.co>
Document the new idle detection feature across CLI reference, quick reference, writing prompts guide, changelog, codebase map, and the new-ralph skill. Adds frontmatter field reference, usage examples, and contributor guidance for the idle detection system. Co-authored-by: Ralphify <noreply@ralphify.co>
TestValidateIdle unit tests already cover all validation error cases. Remove 9 duplicate integration tests from TestIdleFrontmatter, keeping only the 3 happy-path tests that verify CLI wiring. Co-authored-by: Ralphify <noreply@ralphify.co>
Collapse TestComputeIdleDelay from 6 individual tests into 2 parametrized tests. Remove test_idle_backoff_delay_applied which relied on wall-clock timing assertions (covered by the unit-level backoff math tests). Co-authored-by: Ralphify <noreply@ralphify.co>
Co-authored-by: Ralphify <noreply@ralphify.co>
…fy duration parser Co-authored-by: Ralphify <noreply@ralphify.co>
…er duration fields Co-authored-by: Ralphify <noreply@ralphify.co>
…ard-condition tests Co-authored-by: Ralphify <noreply@ralphify.co>
Co-authored-by: Ralphify <noreply@ralphify.co>
…pts, and changelog Co-authored-by: Ralphify <noreply@ralphify.co>
The IDLE_FIELD_DELAY/BACKOFF/MAX_DELAY/MAX constants were only referenced in one function. Inline them as string literals to reduce the diff footprint. Co-authored-by: Ralphify <noreply@ralphify.co>
Parametrize non-idle engine tests, merge mark/reset idle tests into one, remove redundant no-idle CLI test and events test already covered by integration tests. Co-authored-by: Ralphify <noreply@ralphify.co>
Replace duplicate YAML example with cross-reference to cli.md, keeping only the prompt-writing guidance relevant to this page. Co-authored-by: Ralphify <noreply@ralphify.co>
Populate stdout_text from the full streamed output in streaming mode and from captured stdout in blocking mode, so the engine can check the complete agent output for markers not present in result_text. Co-authored-by: Ralphify <noreply@ralphify.co>
The idle detection in _run_agent_phase now checks agent.stdout_text when result_text doesn't contain the idle marker, ensuring idle state is detected even when the marker appears in streamed output but not in the final result field. Co-authored-by: Ralphify <noreply@ralphify.co>
Cover the new stdout_text fallback path in idle detection (engine) and verify stdout_text is populated in both streaming and blocking modes. Co-authored-by: Ralphify <noreply@ralphify.co>
Replace the static log_info("Waiting...") message with structured
DELAY_STARTED and DELAY_ENDED events so the console emitter can render
a live countdown timer.
Co-authored-by: Ralphify <noreply@ralphify.co>
…tter Add _DelayCountdown renderable that shows a ticking countdown for inter-iteration delays, and wire up DELAY_STARTED/DELAY_ENDED event handlers in ConsoleEmitter. Co-authored-by: Ralphify <noreply@ralphify.co>
Co-authored-by: Ralphify <noreply@ralphify.co>
2 tasks
Contributor
Author
kasperjunge
reviewed
Mar 24, 2026
Collaborator
kasperjunge
left a comment
There was a problem hiding this comment.
Thanks for the thorough work here — the implementation is solid and well-tested, and the idle token waste problem from #28 is real.
I'm interested in the idea of structured state communication between agents and the engine, and I can see the opportunity for a richer state system down the road (idle, blocked, waiting_for_review, etc.). However, this is a significant addition to the framework's surface area, and I want to take more time to think through the design before committing to a pattern.
A few things I'm weighing:
- Whether the engine should own backoff logic, or whether a simpler agent-driven approach (e.g.
<!-- ralph:delay 60s -->) would cover the immediate need with less complexity - How a state system fits into the longer-term direction of the framework
- Whether we want to introduce structured agent→engine communication as a first-class concept now or later
I'm going to leave this open for now while I think on it. Appreciate the PR and the detailed issue — both are really helpful for framing the problem space.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Closes #28.
<!-- ralph:state idle -->, the engine applies configurable backoff delays between iterationsdelay × backoff^(consecutive_idle - 1), capped atmax_delaymaxcumulative idle time limit that stops the loop automaticallyidlefrontmatter block withdelay,backoff,max_delay, andmaxfields30s,5m,6h,1dITERATION_IDLEevent type with distinct console renderingTest plan
mkdocs build --strictpasses with zero warnings