emrg: scheduler cycle heartbeat + next-run persistence (rant 2026-08-25T09:25:32) - #973
Conversation
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle (1/3)
Reviewed the full diff (3 files, +312/−1, scheduler cycle heartbeat + next-run persistence, rant 2026-08-25T09:25:32 items ③ and ④).
Design check (③ heartbeat): <task>.heartbeat.json written on every tool frame (round + tool_count mirrored from the daemon frames) + periodic 60s writer; removed in the run() finally path via _clear_heartbeat(); a daemon killed mid-cycle leaves status=running and the next TaskHandler init restores progress + logs interrupted at round X — makes the 8-24/8-25 silent-death incidents diagnosable from emrgd.log alone. heartbeat_task is created before the try block so the finally's cancel() is always safe. Best-effort writes (try/except pass) never affect the running cycle.
Design check (④ next-run): ~/.emrg/next-run/<task>.json persists the scheduled slot; _resume_wait_timeout folds it in one-shot — only ever shortens (min(wait_timeout, remaining)), an already-passed slot runs immediately (0.0), stale files ignored, cleared state deletes the file. Symmetric with the heartbeat: mid-cycle → heartbeat survives; mid-wait → next-run survives.
Verification (local, independent of CI): checked out the PR head — uv run pytest tests/test_scheduler.py tests/test_doc_counts.py -q → 96 passed including the 3 new tests (heartbeat tracking+clearing, interrupted-cycle reporting, next-run persistence across restart with one-shot/expired/stale/cleared sub-states — both positive and negative branches covered). Agent.md 1058→1061 matches the +3 test functions (doc-count guard green). CI double-green (run 32811638111: test + test-windows). No issues — solid observability/persistence PR.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle (2/3)
Re-verified this cycle: head unchanged (9da76a78, same commit reviewed at 1/3), CI still double-green (run 32811638111: test + test-windows pass), mergeable CLEAN.
Re-confirmed the two design invariants on the same code:
- ③ heartbeat:
_heartbeat_loopcreated before the cycle try-block → finally always cancels safely;_write_heartbeatbest-effort (never raises); interrupted-cycle detection reads status=running only. - ④ next-run:
_resume_wait_timeoutis one-shot (clears_resume_next_run_at), only shortens the wait, expired slot → 0.0 immediate run.
Local verification from the 1/3 review stands: 96 passed (scheduler + doc-count, incl. 3 new tests, both positive/negative branches). No issues — consistent with the first vote.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle (3/3)
Third independent review of 9da76a78 (scheduler cycle heartbeat + next-run persistence, 3 files, +312/−1). Head unchanged since 2/3; CI double-green (run 32811638111: test + test-windows pass); mergeable CLEAN. No ❌ in the review history.
Both design invariants re-confirmed on the same code (③ heartbeat written per tool-frame + cleared on clean end, interrupted cycles reported on restart; ④ next-run persisted one-shot, only shortens, expired slot runs immediately). Local verification stands from the 1/3 review: 96 passed incl. 3 new tests with both positive/negative branches. Three consecutive LGTMs across cycles — merging.
Uh oh!
There was an error while loading. Please reload this page.
Implements stages ③④ of rant 2026-08-25T09:25:32 (daemon crash observability): TaskHandler cycle-progress heartbeat persistence + scheduler next-run persistence. Stages ①② (exit records + crash log) already merged via #970 (5080dad).
Changes
emrg/server/scheduler.py
_cycle_progressnow records current stage, round, and a last-activity timestamp while a TaskHandler cycle is running; persisted as a heartbeat file (<task-runs-dir>/<name>.heartbeat.json) alongside the existing saturation state, written after each round update (write order fixed so the persisted round never lags the in-memory state)tests/test_scheduler.py (+3 tests)
test_slowdown_state_persisted_across_restart)Agent.md — doc-count guard synced (1058→1061 for the 3 new tests)
Verification
from emrg.client.app import run_clientOK,python -m emrg --helpOKRant (verbatim)