Conversation
|
This PR may help with several open cron issues: Issues this could address:
Related PRs:
Could you clarify which specific cron bugs this addresses? Would help with issue triage. |
| const { entry, sessionKey, storePath } = resolveHeartbeatSession(cfg, agentId, heartbeat); | ||
|
|
||
| // Skip heartbeat if HEARTBEAT.md exists but has no actionable content. | ||
| // This saves API calls/costs when the file is effectively empty (only comments/headers). | ||
| // EXCEPTION: Don't skip for exec events - they have pending system events to process. | ||
| // EXCEPTION: Don't skip for exec events or if there are pending system events (from cron, etc.) | ||
| const isExecEventReason = opts.reason === "exec-event"; | ||
| const hasPendingSystemEvents = hasSystemEvents(sessionKey); | ||
| const workspaceDir = resolveAgentWorkspaceDir(cfg, agentId); |
There was a problem hiding this comment.
[P1] hasSystemEvents(sessionKey) can throw before the heartbeat-file check
hasSystemEvents calls requireSessionKey and will throw if resolveHeartbeatSession returns an empty/invalid sessionKey. Previously the empty-heartbeat-file optimization would just try to read HEARTBEAT.md and could skip cleanly; with this change an invalid/misconfigured session key can now crash the runner before it gets to the try/catch around reading the file.
If this can happen (e.g., malformed heartbeat.session config), consider guarding the check or treating invalid session keys as “no pending events” so heartbeat runner can still proceed/skip predictably.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/infra/heartbeat-runner.ts
Line: 463:470
Comment:
[P1] `hasSystemEvents(sessionKey)` can throw before the heartbeat-file check
`hasSystemEvents` calls `requireSessionKey` and will throw if `resolveHeartbeatSession` returns an empty/invalid `sessionKey`. Previously the `empty-heartbeat-file` optimization would just try to read `HEARTBEAT.md` and could skip cleanly; with this change an invalid/misconfigured session key can now crash the runner before it gets to the try/catch around reading the file.
If this can happen (e.g., malformed `heartbeat.session` config), consider guarding the check or treating invalid session keys as “no pending events” so heartbeat runner can still proceed/skip predictably.
How can I resolve this? If you propose a fix, please make it concise.| // Enqueue a system event (simulates cron job) | ||
| resetSystemEventsForTest(); | ||
| enqueueSystemEvent("⏰ Reminder: Check your tasks", { sessionKey }); | ||
|
|
||
| replySpy.mockResolvedValue([{ text: "Got your reminder! Checking tasks now." }]); | ||
| const sendWhatsApp = vi.fn().mockResolvedValue({ | ||
| messageId: "m1", | ||
| toJid: "jid", | ||
| }); |
There was a problem hiding this comment.
[P2] Test enqueues a system event but doesn’t assert it was actually consumed
This test verifies the heartbeat runs when events exist, but it doesn’t check that the system-event queue is drained/cleared. A regression where events remain pending (or are processed repeatedly) would still pass. It may be worth asserting queue size/hasSystemEvents(sessionKey) becomes false after runHeartbeatOnce if that’s the intended behavior.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/infra/heartbeat-runner.returns-default-unset.test.ts
Line: 1046:1054
Comment:
[P2] Test enqueues a system event but doesn’t assert it was actually consumed
This test verifies the heartbeat runs when events exist, but it doesn’t check that the system-event queue is drained/cleared. A regression where events remain pending (or are processed repeatedly) would still pass. It may be worth asserting queue size/`hasSystemEvents(sessionKey)` becomes false after `runHeartbeatOnce` if that’s the intended behavior.
How can I resolve this? If you propose a fix, please make it concise.|
Confirming this fix works! 🎉 I've been running OpenClaw from source with this PR (along with #7077 and #7230) and my cron jobs are now firing correctly. Specifically, I had cron jobs that were silently failing because:
With this fix applied, cron-triggered system events are properly delivered even when HEARTBEAT.md is empty. Tested with both Thanks for tracking this down! |
|
Hello, we have had a lot of cron fixes go out. Are you still having issues? |
bfc1ccb to
f92900f
Compare

Fixes #2323
Cron jobs seems to have broken after #1535
The reason seems to be an early return that was added in the PR above, that would not the
system eventsqueue clear ifHEARTBEAT.mdis empty.Cron jobs are pushed to system events when executed, and hence the change ensures that if there are pending system events they should be executed irrespective of the
heartbeat.mdfile being empty.Greptile Overview
Greptile Summary
This PR adjusts the heartbeat runner’s “empty HEARTBEAT.md” early-return behavior so that pending system events (e.g., cron-triggered reminders queued into the per-session system-events queue) still cause a heartbeat run. It adds tests covering the new behavior (run when HEARTBEAT.md is effectively empty but system events exist; still skip when empty and no events).
The change integrates with existing heartbeat logic by checking the session’s system-events queue before applying the cost-saving skip, ensuring cron/system-event delivery isn’t blocked by an empty heartbeat file.
Confidence Score: 4/5
sessionKeyresolution could be invalid andhasSystemEventsmay throw earlier than before.(2/5) Greptile learns from your feedback when you react with thumbs up/down!
Context used:
dashboard- CLAUDE.md (source)dashboard- AGENTS.md (source)