fix(pr-daemon): rate-limit and coalesce hints

Every hint costs the receiving session a full model turn. The daemon sent
one per forge event with no quiet period, so a busy PR produced 20+ in a
day and sometimes repeated a payload verbatim.

Reasons are now banked per PR and role until a hint actually goes out, so
a busy pane or a cooldown delays one but never loses it. After a hint,
the next waits hintCooldownSeconds (default 300) and carries everything
that accumulated. A payload identical to the last is dropped, as is a ci
hint to a land session whose worktree already holds that head commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Miguel Palhas
2026-08-28 17:18:50 +01:00
parent aff0e38dd3
commit e90137b17c
3 changed files with 76 additions and 9 deletions
+8
View File
@@ -145,6 +145,14 @@ skill on arrival if it doesn't have it.
bump `updated_at` and move nothing in the snapshot, so no hint is sent at all.
With webhooks the filter is sharper still, by event action.
**Hints are rate-limited per PR and role.** Every hint costs the receiving
session a full model turn, so after one goes out the next waits
`hintCooldownSeconds` (default 300) and arrives carrying every reason that
accumulated meanwhile. A hint identical to the last one sent is dropped, and so
is a `ci` hint to a `land` session whose own worktree already holds that head
commit — it pushed it. Reasons are banked until they are actually delivered, so
a busy pane or a cooldown delays a hint but never loses one.
**An epoch guards the first run.** `~/.local/state/reviewer/epoch` is written
once; PRs created before it never spawn a session, so switching the daemon on
doesn't wake every open PR you have. It gates creation only — start a session