Repository navigation
π review dispatch: promote heads starved of a reviewer and say so in the tracker - #15239
Conversation
β¦tracker A head that lost its pending review kicks to the 45m TTL could sit behind webhook-event PRs indefinitely: PlanDispatch handed every free reviewer to the event-promoted front of the list and the only trace was plan.Waiting, consumed by autoscale and never persisted. Record the consecutive wait per head in the dispatch state, move heads starved for ReviewWaitStarvationCycles to the front inside the planner, and explain the wait in the review queue and tracker caption. Fixes #15229 Signed-off-by: Andrew Anderson <andy@clubanderson.com>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
@clubanderson is auto-promoted for contributor-lane merging on this PR: the last 5 merged PRs by this author in this hive's repositories have no revert or sentinel-alert evidence. CI, reviewer verdict, diff fences, soak, holds and branch protection still apply. |
Open PR overlap checkBase branch: Conflicts are checked with every PR merged onto the current tip of
|
|
Another agent tried to open a PR from |
|
@clubanderson this PR is held at Failing checks:
Next: the hive does not push to your branch. Push a new head (or reply here); CI and the review swarm re-run automatically and the PR returns to the normal path. |
|
Thank you for your contribution! Your PR has been merged. We'd love to hear how your experience was: share feedback |
There was a problem hiding this comment.
Read against the tree at 7596be6, diff first. The mechanism is sound and the state lifecycle closes; looks correct to me.
Ordering inside PlanDispatch (src/pkg/review/dispatch.go:655-669): pruneState runs first, so plan.State.Waits passed to promoteStarvedWaits only ever holds records for heads still open; the !RequireApproval || !FanOut early return at :659 leaves the records untouched rather than incrementing them, which is right β nothing was passed over that cycle. reconcileWaits (:1018-1051) runs after the slot loop, so a promoted head that got a reviewer disappears from Waiting and its record is dropped; one still waiting gains exactly one cycle. Cycles therefore means "consecutive planner cycles", as the doc comment says.
Promotion (:977-1013) is a stable partition β starved heads keep their relative order, then everyone else β and it happens on the prs slice before the per-PR gates, so the body's "every gate still applies" claim holds (the head still has to clear ownership, cooldown, TTL etc.). Match is by samePRHead (:2057), so a new push on the PR naturally resets the count because the record keys on HeadSHA.
Pruning (:2034-2040) keys openHeads on fullRepoName, and reconcileWaits stores fullRepoName in the record (:1046), so the two agree and stale records go when the head closes. The queue reason (review_queue.go:538-541) and tracker clause (stage_tracker.go) both try the full name then the bare one, matching how the rest of that file handles pr.Repo.
Body vs diff: every bullet in "Fix" is present; the #15139 narrative matches what Waiting did before (consumed by autoscale only, never persisted).
Small note, not a defect: main.go:11033 logs every waiting head at Info each cycle. On a busy hive with max_parallel_reviews spent that is one line per owed head per cycle; if it gets loud, the Promoted warn alone carries the actionable signal.
β hive: agent=reviewer-2 backend=copilot model=claude-fable-5.1 copilot=1.0.88
Fixes #15229
What happened to #15139
After round-1
changes_requestedand a fix push (headcf5adb194), only 2/5 perspectives reported; the remaining pending kicks expired at the 45m TTL (23:44Z) and were never re-dispatched because every cycle's free reviewers went to webhook-event PRs thatprioritizeEventPRsmoves to the front. The only trace wasplan.Waiting, consumed by autoscale and never persisted, logged, or shown β so the tracker said juststalled.Base
v6was correct (the file only exists on v6) and CI was green, so no retarget action is added.Fix
pkg/review/dispatch.go: persist per-headreview_waits(reason, consecutive cycles, first/last seen); heads waiting β₯ReviewWaitStarvationCycles(3) are moved to the front insidePlanDispatch, ahead of the caller's event promotion; pruned when the head closes.cmd/hive/main.go: log promotions (warn) and waits (info).pkg/github/review_queue.go: review-queue reason explains the wait ("waiting for a free reviewer: N consecutive cycles over Xm β¦ promoted ahead of the queue").pkg/dashboard/stage_tracker.go: review-pending caption names the missing coverage and the wait duration.Unit tests for planner wait tracking/promotion/threshold/pruning, review-queue reason, and tracker clause; no sleeps.