fix(heartbeat): stop self-authored status comments from defeating the rewake throttle (BLO-23081) - #1165
Open
allyblockcast[bot] wants to merge 1 commit into
Open
Conversation
… rewake throttle (BLO-23081) issue.comment_added was in both ISSUE_PROGRESS_ACTIVITY_ACTIONS and ISSUE_NEW_INPUT_ACTIVITY_ACTIONS, so the run that posts a routine status comment marks itself as progress, and the comment then reads as new input for the next evaluation. noProgressStreak never accumulates past 0, so the 2-consecutive-run threshold never engages for an agent following the documented comment-every-run protocol — measured at a 12.1min median re-wake interval on BLO-21953 instead of the intended 30min cap. Exclude comment_added from progress entirely (a bare comment carries no state change) and make the new-input check actor-aware: a comment from the evaluating agent itself no longer counts as either signal, while a comment from any other agent or a board user still bypasses the throttle immediately. evaluateIssueRewakeThrottle now takes raw activity rows (action/agentId/createdAt) instead of pre-computed booleans so the actor-aware logic is covered by direct unit tests. Co-Authored-By: Paperclip <noreply@paperclip.ing>
Author
Author
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: d3e6ea9
Critical Issues (0)
Important Issues (0)
Suggestions (0)
Strengths
- The core fix is correct:
ISSUE_PROGRESS_ACTIVITY_ACTIONSno longer includesissue.comment_added, and the newisIssueRewakeNewInputActivityhelper makes the new-input check actor-aware (row.agentId !== evaluatingAgentId), so a self-authored status comment can neither reset the no-progress streak nor count as fresh input for itself — while a comment from another agent or a board user (agentId === null) still bypasses the throttle immediately. This matches BLO-23081's acceptance criteria. - Verified the single-query refactor in
heartbeat.ts(server/src/services/heartbeat.ts:25595-25620) is behavior-preserving:ISSUE_PROGRESS_ACTIVITY_ACTIONSis a structural subset ofISSUE_NEW_INPUT_ACTIVITY_ACTIONS(built via spread), so filtering the combined query onaction in ISSUE_NEW_INPUT_ACTIVITY_ACTIONSstill returns every row needed for both the progress and new-input computations that now live insideevaluateIssueRewakeThrottle. - Confirmed
evaluateIssueRewakeThrottlehas exactly one caller (heartbeat.ts) via repo-wide grep, so widening its signature (agentId+ rawactivityRowsinstead of precomputedrunIdsWithIssueProgress/hasNewIssueInputSinceLastRun) is a safe interface change. - Failed-run recovery, streak escalation to the 30-minute cap, and the "comment alongside a real mutation still counts" case are all preserved and covered by new tests; test counts in both files (20 unit, 8 integration) match the PR description's claims.
agentIdis a non-nullstringparameter throughout the call chain (enqueueWakeup(agentId: string, ...)), so the newagentId: stringfield onIssueRewakeThrottleInputis type-safe with no optionality mismatch.
Recommended Action
- No blocking issues — safe to merge once CI is green.
1 task
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Aug 8, 2026
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.
Thinking Path
Linked Issues or Issue Description
Fixes: BLO-23081
Refs: BLO-21953 (where the defect was found and measured)
What Changed
issue-rewake-throttle.ts: removedissue.comment_addedfromISSUE_PROGRESS_ACTIVITY_ACTIONS— a bare comment no longer counts as issue-visible progress by itself; a run still counts as progress if it leaves a real mutation (status change, document, work product, etc.) behind, with or without an accompanying comment.isIssueRewakeNewInputActivity(row, evaluatingAgentId): acomment_addedrow only counts as new input when itsagentIddiffers from the evaluating agent (or isnull, i.e. a board user) — a self-authored status ping is excluded, a comment from anyone else still bypasses the throttle immediately.evaluateIssueRewakeThrottlenow takes rawactivityRows({ runId, action, agentId, createdAt }) plus the evaluatingagentId, instead of two pre-computed booleans (runIdsWithIssueProgress,hasNewIssueInputSinceLastRun) — the actor-aware decision now lives in the pure, directly-unit-testable function rather than being baked into the caller's SQL.heartbeat.ts: collapsed the two separate DB queries (progress rows scoped byrunId, new-input rows scoped bycreatedAt) into one query fetching{runId, action, agentId, createdAt}for the union of both conditions, and passes the raw rows straight intoevaluateIssueRewakeThrottle.issue-rewake-throttle.test.ts(unit, no DB) andheartbeat-issue-rewake-throttle.test.ts(embedded-Postgres integration) covering: self-authored comment doesn't reset the streak, foreign-agent/board-user comment still bypasses immediately, commenting alongside a real mutation still counts, failed-run recovery is unaffected, and escalation reaches the 30-minute cap within 6 no-progress runs.Verification
npx vitest run src/__tests__/issue-rewake-throttle.test.ts— 20/20 passed (pure unit tests, no DB).npx vitest run src/__tests__/heartbeat-issue-rewake-throttle.test.ts— 8/8 passed (embedded-Postgres integration, includes the pre-existing suite updated to use real mutations instead of comments for its "progress" fixtures, since a bare comment is no longer progress by design).npx tsc --noEmit -p server/tsconfig.json— clean.Risks
activityLog.agentIdcolumn already existed and is nullable for non-agent actors (board users), so the actor check degrades safely (null !== agentId→ always counts as new input) for those rows.issue-rewake-throttle.tshas exactly one caller (heartbeat.ts), confirmed via repo-wide grep before making the interface change.Model Used
Claude Sonnet 5 (
claude-sonnet-5[1m]), 1M context window, via Claude Code / Paperclip agent adapter. Read the throttle source and its caller, wrote the fix, rewrote/extended both test files, ran the embedded-Postgres integration suite andtsc --noEmitlocally before opening this PR.Checklist
Fixes: #/Closes #/Refs #OR (b) described the issue in-PR following the relevant issue templatehttps://paperclip.blockcast.net/BLO/issues/BLO-23081