Repository navigation
✨ tracker: rework pickup signal on the waiting-on chip - #15281
Conversation
A PR row returned to its author (071 / 072) now carries rework{state,
actor, requested_at, since, evidence, mode, ahead, head}: requested
(evidence queued when the fix sits on the clanker's hub queue),
acknowledged (PR updated_at moved after the request and the hive's own
nudge), in_progress (the clanker relay took the fix-pr task) or pushed
(head moved; 050 on the next sweep). Derived from the stage record, the
PR list and the contributor fix queue — no extra GitHub calls.
The waiting-on / adoption pill appends the state word, its tooltip and
the row tooltip say since when, and a state change at an unchanged stage
writes the row event line. fixqueue.Dispatch records when it left the
queue.
Fixes #15280
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 |
Open PR overlap checkBase branch: Conflicts are checked with every PR merged onto the current tip of
|
|
@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. |
|
Another agent tried to open a PR from |
There was a problem hiding this comment.
Intent alignment — the diff delivers what #15280 asks for (rework{state, actor, requested_at, since, evidence} on 071/072 rows, chip suffix, tooltip, event line, no new GitHub calls) with no unrelated scope. One in-scope gap in the state rules:
Hive's own Reroute note is read as the contributor acknowledging. src/pkg/dashboard/api_repo_item_decision_reroute.go:235-236 records the reroute (store.NoteReroute(...), which sets RerouteAt) and then posts the <!-- hive:rerouted … --> comment, which bumps the PR's updated_at. src/pkg/dashboard/stage_tracker_rework.go:160-166 builds the activity floor from requested, rec.LastNudgeAt and rec.EnteredAt only — rec.RerouteAt is not in it. When the reroute lands as queued (relay busy / refused, so FixWorkFor returns Queued, not InFlight), the queued evidence set at :152-157 is then overwritten at :166-169 once updated_at passes the floor + 2 min: the pill reads waiting on @target · acknowledged and the tooltip says "@target acknowledged · activity on the PR" when the only activity was the hive's own note. That is exactly the (a)-vs-(b) confusion the issue asks to remove. Dispatched reroutes are unaffected (InFlight returns early at :141-147).
floor := requested
if rec.LastNudgeAt.After(floor) {
floor = rec.LastNudgeAt
}
if rec.EnteredAt.After(floor) {
floor = rec.EnteredAt
}
if rec.RerouteAt.After(floor) {
floor = rec.RerouteAt
}
Worth a 16th case in TestStageTrackerReworkFor: RerouteTo set, RerouteAt = requested+30m, fix queued for the target, UpdatedAt = RerouteAt+30s → expect requested/queued, not acknowledged.
— hive: agent=adjudicator-3 backend=copilot model=claude-fable-5.1 copilot=1.0.88
There was a problem hiding this comment.
Correctness review (read at head 16914ca; stage_tracker_rework.go, stagelabels/store.go, automerge_stage_labels.go, fixqueue.go).
1. acknowledged is derived from PR updated_at, which the hive's own writes bump — a 24h-stalled row will read as "acknowledged"
src/pkg/dashboard/stage_tracker_rework.go:165-179 sets acknowledged/activity when it.UpdatedAt > max(requested, LastNudgeAt, EnteredAt) + 2min. Only the hive's initial writes are excluded by that floor. Every later hive-side write on the PR also bumps updated_at: the stage/stalled label after the 24h dwell (stagelabels.go:272-273, :138), needs-rebase / ci-failing modifier flips, label healing, takeover/reroute comments, operator holds. The stalled label is literally "nobody is working it" (stagelabels.go:24), and this code turns it into waiting on @x · acknowledged and an event line "@x acknowledged the rework request". Maintainer review comments produce the same false positive.
The record the tracker already holds solves this: Record.LastActivityAt (store.go:277-282) is "when somebody other than the hive last touched the item … Stalled measures quiet time from here, never from the PR's updated_at (which the hive's own writes bump)" (#12534). It is refreshed every reconcile cycle for every PR, including 071/072 (automerge_stage_labels.go:1058-1067, store.go:646-690; own comments are netted out via OwnComments).
Suggested fix — use LastActivityAt and fall back to updated_at only for records that predate it:
--- a/src/pkg/dashboard/stage_tracker_rework.go
+++ b/src/pkg/dashboard/stage_tracker_rework.go
@@ -162,20 +162,30 @@ func stageTrackerReworkFor(...) *StageTrackerRework {
- // Acknowledged: the PR moved after the request and after the hive's own
- // last comment on it — somebody replied or edited.
- if it.UpdatedAt != nil {
+ // Acknowledged: somebody other than the hive touched the PR after the
+ // request. The record's LastActivityAt already nets out the hive's own
+ // labels and comments (hivecommons/hive#12534); updated_at is only the
+ // fallback for records written before it existed, and the hive's later
+ // writes (stage/stalled, modifier flips) bump it too.
+ activity, slack := rec.LastActivityAt, time.Duration(0)
+ if activity.IsZero() && it.UpdatedAt != nil {
+ activity, slack = *it.UpdatedAt, reworkActivitySlack
+ }
+ if !activity.IsZero() {
floor := requested
if rec.LastNudgeAt.After(floor) {
floor = rec.LastNudgeAt
}
if rec.EnteredAt.After(floor) {
floor = rec.EnteredAt
}
- if u := *it.UpdatedAt; u.After(floor.Add(reworkActivitySlack)) && !u.After(now.Add(reworkActivitySlack)) {
+ if u := activity; u.After(floor.Add(slack)) && !u.After(now.Add(reworkActivitySlack)) {
out.State, out.Evidence, out.Mode, out.Ahead = reworkStateAcknowledged, reworkEvidenceActivity, "", 0
out.Since = &u
return out
}
}Please add a TestStageTrackerReworkFor case for it: rec.LastActivityAt = requested−1m, UpdatedAt = requested+3h (hive label write) → expect requested, not acknowledged. None of the 15 current cases exercise a hive write after the nudge (stage_tracker_rework_test.go:60-98).
2. (advisory) pushed cannot be detected on a 071 row that was never nudged
stage_tracker_rework.go:128 requires rec.NudgeHead != "". A 071 row dated from EnteredAt (the "071 without a nudge" case, :107-113) has no head to compare against, so a new push falls through to acknowledged via activity rather than pushed. Not blocking — the stage engine still routes to 050 next sweep — but the chip will say "acknowledged" for a push, and the PR body's state table does not mention the gap. Worth a note in dashboard-sections.md or a Head captured at stage entry in a follow-up.
— hive: agent=adjudicator backend=copilot model=claude-fable-5.1 copilot=1.0.88
|
Hive filed review findings that do not block this PR as backlog items:
Cap: 10 backlog item(s) per PR per day. |
|
@clubanderson this PR is held at Why:
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 |
Fixes #15280
What
A PR row returned to its author (
stage/071-needs-author/stage/072-returned-to-contributor) now carries areworkobject on the stage tracker payload, and the waiting-on / adoption pill says whether the rework has been picked up — not just who the hive waits on.State rules (all from data the tracker already holds — no new GitHub calls)
requestedrequested_at= first nudge on the current head (NudgeStart()), else stage entry; nothing moved sincerequestedqueued(+ahead)acknowledgedactivityupdated_at> max(request, hive's last nudge, stage entry) + 2 min slack (reply / review-thread answer / edit; reactions don't bump it)in_progressclaim(+mode)fix-prdispatch (fixqueue.Dispatch.At, new)pushedcommit(+head)NudgeHead; the stage engine already routes 071/072 → 050 on the next sweep (transition table), the chip readsre-review pendingmeanwhileSPA
waiting on @x · no response/· queued/· acknowledged/· working/· re-review pending(presence dot kept; same ids/classes; no raw colours; notoLocaleTimeString).Rework:line: "rework requested 1 hour ago (…) · no response from @x yet", "@x acknowledged · activity on the PR 20 min ago", "@x's clanker picked up the rework 5 min ago (spawn)", "@x pushed a new head 1 min ago · re-review pending".stageTrackerEventText: "@x acknowledged the rework request", "@x's clanker picked up the rework", "@x pushed a new head — re-review pending".Tests
TestStageTrackerReworkFor— table-driven, fixed clock, 15 cases (no sleep).TestStageTrackerReworkPayload— throughbuildStageTrackerwithMarkNudged+ fix-queue override.TestStageTrackerReworkJS— node: chip text/title/aria, adoption pill, event text, state map.TestDispatchAt— fixqueue dispatch timestamp.go test ./pkg/dashboard/... ./pkg/github/automerge/... ./pkg/stagelabels/... ./pkg/fixqueue/...green;golangci-lint run0 issues; api-reference citations re-fixed.Docs
src/docs/dashboard-sections.md(new "Rework pickup on the waiting-on pill" paragraph),src/docs/operator-reference.md,changelog.d/added-rework-pickup-signal.md.