← Back to PRs

#21014: fix(cron): suppress main-session summary for HEARTBEAT_OK responses

by nickjlamb open 2026-02-19 15:03 View on GitHub →
size: S
## Summary Fixes #20941. When an isolated cron job with `delivery.mode = "announce"` returns `HEARTBEAT_OK`, the announce delivery correctly suppresses the external message — but the gateway still injects a `Cron: HEARTBEAT_OK` summary into the main session. This triggers the heartbeat system to relay it as a spurious reminder to the user. ## Root Cause In `src/cron/isolated-agent/run.ts`, `skipHeartbeatDelivery` gates the delivery block (preventing outbound sends and announce flow), but does **not** set `delivered = true`. The caller in `timer.ts` checks `!res.delivered` before injecting the summary into the main session — so the summary leaks through. ## Fix One-line change: treat heartbeat-only suppression as "delivered" so the caller skips main-session summary injection: ```typescript let delivered = skipMessagingToolDelivery || skipHeartbeatDelivery; ``` ## Tests Two new tests (175 total cron tests passing): 1. **HEARTBEAT_OK sets `delivered=true`** — verifies no announce flow fires and no outbound send occurs 2. **HEARTBEAT_OK with media still delivers** — verifies structured content (media URLs) bypasses heartbeat suppression as intended ## Checklist - [x] One-line fix in `run.ts` - [x] 2 new tests, 175 total cron tests passing - [x] No breaking changes — only affects the `delivered` flag when heartbeat suppression is active <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR fixes a bug where `HEARTBEAT_OK` responses from isolated cron jobs were leaking into the main session as spurious summaries. The fix correctly treats heartbeat suppression as "delivered" so the caller in `timer.ts` skips injecting `Cron: HEARTBEAT_OK` messages that would trigger unnecessary user notifications. The one-line change in `src/cron/isolated-agent/run.ts:594` is surgical and correct: - Previously: `let delivered = skipMessagingToolDelivery;` - Now: `let delivered = skipMessagingToolDelivery || skipHeartbeatDelivery;` This ensures that when `skipHeartbeatDelivery` is true (heartbeat-only response with no real content), the `delivered` flag is set, preventing the main session summary injection in `timer.ts:541`. Two comprehensive tests validate the behavior: - Test 1 verifies `HEARTBEAT_OK` sets `delivered=true` and suppresses both announce flow and outbound delivery - Test 2 verifies `HEARTBEAT_OK` with media still delivers (media bypasses heartbeat suppression via `isHeartbeatOnlyResponse`) The fix aligns with the existing heartbeat suppression logic where `isHeartbeatOnlyResponse` already checks for media/structured content and returns false when present, ensuring those payloads still get delivered. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk - The fix is a minimal one-line change that correctly addresses the root cause. The logic is sound: treating heartbeat suppression as "delivered" prevents spurious main-session summaries while preserving all existing delivery behavior for real content. Two comprehensive tests validate both the fix (HEARTBEAT_OK suppression) and the edge case (media still delivers). The change is well-contained with no breaking changes or unexpected side effects. - No files require special attention <sub>Last reviewed commit: 8dc7837</sub> <!-- greptile_other_comments_section --> <sub>(5/5) You can turn off certain types of comments like style [here](https://app.greptile.com/review/github)!</sub> <!-- /greptile_comment -->

Most Similar PRs