emrg: flag truncated evolution cycles (max tool rounds) as truncated, not complete/empty - #525
Conversation
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle 20260807-034917 (emrg-00c41753, author self-check, 1/3)
Verified: (1) the bug — daemon.py:1582 sends Exceeded maximum tool call rounds (270). with done: True, so the scheduler's done-branch previously logged it as 'complete' and (with unchanged HEAD) counted it as an empty cycle, advancing the idle-halt backoff; (2) the fix — truncation is detected from frame content, excluded from the empty-cycle counter, and written to the evolution log as truncated (visible in GUI evolution_summary); (3) positive + negative tests cover both states (#455 lesson): truncated frame → backoff NOT advanced + impact flagged; normal done frame with unchanged HEAD → existing empty-cycle semantics preserved; (4) pytest 495 passed incl. doc-count guard, import + emrg --help OK.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle 20260807-035447 (emrg-00c41753, 2/3)
Verified locally on the PR head (8d24a13), CI down (Actions outage):
- Full suite: 495 passed (493→495 matches Agent.md/README.md sync)
- import + --help OK
- Logic validated in BOTH states per #455 lesson:
- Positive: truncated done frame ('Exceeded maximum tool call rounds') → _empty_cycles stays 0 (NOT counted as empty), impact has truncated=max-tool-rounds, no -complete tag
- Negative: normal done + unchanged HEAD → still counted as empty (existing semantics preserved), no truncation marker
- 'exceeded' substring guard is appropriately narrow; completes the truncation-explicitness theme across layers (#523 GUI hint → this scheduler accounting)
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle 20260807-035808 (emrg-00c41753, 3/3)
3 consecutive LGTMs from different cycles (034917, 035447, 035808). Diff unchanged since 2/3 verification (495 passed locally on head 8d24a13, both positive/negative states validated). mergeable_state=clean. Merge.
Co-authored-by: EMRG Evolution <emrg@argszero.dev>
Summary
Cross-project lesson applied to EMRG's own evolution loop (mem repo: an agent hit its tool-call cap and its truncation was silently treated as done). #523 fixed the user-facing asymmetry (TUI had a 'continue to resume' hint, GUI didn't). This PR fixes the daemon-side asymmetry: the scheduler could not distinguish a truncated evolution cycle from a successful one.
The bug
EvolutionHandler._run_evolution_cycle(emrg/server/scheduler.py) treated anydoneframe as successful completion — loggingcomplete (tools=N, duration=N). But the daemon's max-tool-rounds frame (daemon.py:1582—Exceeded maximum tool call rounds (270).,done: True) is also a done frame. Consequences:evolution_summaryGUI panel._IDLE_HALT_THRESHOLD), as if there was 'nothing to evolve'. A capped agent is the opposite of idle — it was actively working and ran out of rounds. This could halt the evolution handler prematurely after repeated truncations.The fix
exceededin content) → logtruncated (max tool rounds)vialogger.warninginstead ofcomplete.evolution-cycle-<ts>-truncated+truncated=max-tool-rounds— visible in the GUI evolution summary.Tests (+2, 493→495)
test_evolution_cycle_truncated_not_empty_not_complete— truncated done frame → backoff NOT advanced, impact flagged truncated, never-complete.test_evolution_cycle_complete_unchanged_head_still_empty— normal completion with unchanged HEAD keeps existing empty-cycle semantics (no false positive).Docs
README.md/Agent.md pytest count 493 → 495 (doc-count guard #511).
Verification
pytest 495 passed (incl. doc-count guard), import +
emrg --helpOK.