Skip to content

✨ Activity Monitor: Adopt now and Reroute to another clanker for PRs waiting on a contributor's clanker - #15085

Merged
clubanderson merged 4 commits into
v5from
feat/adopt-now-reroute
Oct 29, 2026
Merged

clubanderson merged 4 commits into
v5from
feat/adopt-now-reroute

Conversation

@clubanderson

Copy link
Copy Markdown
Member

Fixes #15082

What

A PR waiting on its author's clanker (stage 072 returned-to-contributor / 071 needs-author, e.g. #15038 "Returned to contributor · waiting on @Danathar") offered only Hold / Re-evaluate / Mark needs-human / Open / Copy. The ⋯ row menu (and the per-PR sub-row menu under an issue, #15056) now carries two operator actions, both through runRowAction and POST /api/repos/{o}/{r}/items/{n}/decision:

Adopt now — hive takes it over

  • Menu item with consequence line closes the contributor's PR after hive opens its copy; their commits + sign-off are preserved; confirm with don't-ask-again (hive.tracker.confirm.decide:adopt-now); the confirm adds a line when the author's hive is online right now.
  • {"decision":"adopt","force":true} → handleRepoItemAdoptNow: stage record NoteAdoptionForced(by), attributed <!-- hive:adoption-requested by=<login> force=true --> note, adoption/supersede label, SweepNudge so the automerge sweep runs the existing supersede adoption path (adoptContributorPR / supersedeAdoptedPR, PR 15016/15011) at once. The forced mark bypasses presence, both grace windows and maintainer_policy (incl. never); hold still blocks. Marker: hive:adopted … reason=operator-forced by=@login; when the author's hive is online the adoption comment says the maintainer took it over.
  • Ledger (✨ Activity monitor: decision badge shows what you chose and what hive did next #14992): operatorActionFromBody maps adopt+force → adopt-now (and adopt → adopt, reroute → reroute with target); audit repo_item_decision_adopt_now carries action=adopt-now.
  • Toast: Adopted → #N (hive's copy), contributor PR will close when #N merges. when the sweep lands within the handler's wait, else Adoption forced: hive opens its copy on the pass now running.

Reroute to another clanker

  • Submenu of currently-online registered contributor clankers (@login · hive · online 12m ago · 1 in hand|idle) plus any available (N online), from takeover.clankers[] — the same hub facts as /api/contribute/fleet. Disabled with no clankers online — use Adopt now when none.
  • {"decision":"reroute","to":"<login>|any"} → handleRepoItemReroute → ContributeWSHub.Reroute: reuses the contributor fix queue — fixQueue().Enqueue(target, item) → dispatchFixes → sendFixTask (task_assign kind fix-pr, interrupt priority) → awaitFixTaskRefusal. This is exactly the mechanism the stage-072 nudge uses to offer rework to the author's own relay (ContributeWSHub.Nudge, hive#12436). The item carries RerouteFrom/RerouteBy/RerouteReason so the task instruction tells the target whose PR it is and that they either push the fix (if the branch allows) or open a replacement PR carrying the author's commits + sign-off. The PR's return reason (failing check / reviewer's requested changes) plus the operator's comment is the reason shipped.
  • Author notified by <!-- hive:rerouted to=@X by=@op reason=… -->; row shows a rerouted → @X pill with a presence dot; toast Rerouted → @X (dispatched now, preempt) / (queued; N ahead).
  • governor.reroute.pickup_timeout (default 30m): if the target's relay has not taken the task (not in flight) the hive falls back to Adopt now by itself — withdraws the queued item, marks the forced adoption, posts a lapsed=true note, raises a warning system alert + repo_item_reroute_fallback audit entry, nudges the sweep.

Needs-human popover + Let hive decide

  • Once the nudge grace has elapsed and the engine is not adopting on its own, the row carries decision_needed (blocker_reason: adoption:<why>, options Adopt now / Reroute / Hold) so both appear in decision_needed.options[] (✨ Activity Monitor: needs-human popover says what to decide and offers the actions #14995); Reroute there is a required choice list.
  • Delegated rule grace-elapsed-adopt-now: "Let hive decide" picks Adopt now when the grace already elapsed, and the dashboard runs it as a forced adoption.

Tests

  • Go: api_repo_item_takeover_test.go (force adopt → comment/label/audit/toast, queued form, guards; reroute 409 when none online, fix-pr dispatch + marker + store, pickup-lapse fallback, candidate filtering; tracker takeover{} + disabled reasons + reroute pill; store marks; delegated rule), automerge_adopt_now_test.go (forced adoption bypasses presence / grace / maintainer_policy: never, wording online vs offline, hold still stops it), operator-actions ledger mapping.
  • Node fixtures (stdin-fed): stage_tracker_takeover_ui_test.go — menu items, consequence line, disabled reasons, confirms, reroute popover options, toasts.
  • Config golden updated for the new governor.reroute block.

Docs

docs/dashboard-sections.md (row actions), docs/labels-and-control-signals.md (operator-forced and hive:rerouted markers), docs/operator-reference.md, changelog.d/added-adopt-now-reroute.md.

SPA: dashboardSetInterval only (none added), [hidden] not inline styles, CSS tokens only.

@kubestellar-prow kubestellar-prow Bot added the dco-signoff: yes Indicates the PR's author has signed the DCO. label Oct 28, 2026
@kubestellar-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign danathar for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Open PR overlap check

Base branch: v5

Conflicts are checked with every PR merged onto the current tip of v5, so a PR that only needs a rebase is not reported as conflicting with its siblings.

PR Title Relation Files
#15219 🐛 fix: preserve human and owner PRs during delegated decisions CONFLICT src/pkg/delegatedecision/policy.go
src/pkg/github/automerge/automerge_contributor_adopt.go
#15122 🐛 Write-back containment: per-kind gate for every unsolicited GitHub write, with backfill guard CONFLICT src/docs/api-reference.md
#15184 📖 docs: refresh operator decision API reference same files src/docs/api-reference.md
#14807 ✨ dashboard: stream Job pod logs in the terminal pane for sandbox.runtime: job agents CONFLICT src/docs/api-reference.md
#15206 🐛 Activity Monitor: delegated adopt-supersede reports executing → adopted/could-not-adopt, routes workflow-path to the workflows blocker, re-adoption survives the mutation journal CONFLICT src/pkg/dashboard/api_repo_item_decide_delegated.go
src/pkg/delegatedecision/policy.go
#15104 🐛 Activity Monitor: Rebase, then merge as maintainer; fixer owns parked conflicting PRs; dismiss self-inflicted changes_requested same files src/cmd/hive/main.go
src/docs/api-reference.md
src/docs/dashboard-sections.md
src/docs/operator-reference.md
src/pkg/dashboard/api_repo_item_decision.go
src/pkg/dashboard/server.go
src/pkg/dashboard/stage_tracker.go
src/pkg/dashboard/stage_tracker_decision.go
src/pkg/dashboard/stage_tracker_row_actions_test.go
src/pkg/dashboard/static/index.html
#15240 🐛 Never adopt a person's PR: owner/human-authored PRs return to their author instead of the contributor-offline lane CONFLICT src/pkg/delegatedecision/policy.go
src/pkg/github/automerge/automerge_contributor_adopt.go
#15239 🐛 review dispatch: promote heads starved of a reviewer and say so in the tracker same files src/cmd/hive/main.go
src/pkg/dashboard/stage_tracker.go
#15208 🐛 fix: decidePR answers capability-gap, not adopt-supersede, for heads the App cannot adopt CONFLICT src/pkg/delegatedecision/policy.go
#15216 🐛 Sentinel: a dashboard Approve releases the head for good; skip Prow-rejected /lgtm + /approve same files src/docs/dashboard-sections.md
src/docs/operator-reference.md
src/pkg/dashboard/api_repo_item_decision.go
#15223 ✨ Soak countdown on every soak pill, with the live timer on hover same files src/pkg/dashboard/stage_tracker.go
src/pkg/dashboard/static/index.html
src/pkg/github/automerge/automerge_stage_labels.go
src/pkg/stagelabels/store.go
#15228 ✨ tracker: waiting-on chip shows human or bot icon instead of text qualifier same files src/pkg/dashboard/static/index.html
#15186 🐛 Activity Monitor: one coherent post-decision state for Let hive decide rows; 060 reviewed in CI / Review CONFLICT src/pkg/dashboard/operator_actions.go
src/pkg/dashboard/static/index.html
#15236 🐛 Prefer covering PR progress in Activity Monitor messages same files src/pkg/dashboard/stage_tracker.go
#15200 🐛 fix: tracker history column wears a history mark, not a ✓ same files src/docs/dashboard-sections.md
src/pkg/dashboard/operator_actions_test.go
src/pkg/dashboard/static/index.html
#15134 🐛 Delegated decision on a capability gap: model the blocker, stop the un-park/re-park loop, name the missing App permission CONFLICT src/docs/api-reference.md
src/pkg/dashboard/stage_tracker_row_actions_test.go
src/pkg/dashboard/static/index.html

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness review (head bd9e232)

1. Pickup fallback fires after the target finished the work (medium). reroutePickupLapsed (src/pkg/dashboard/api_repo_item_decision_reroute.go:604-620) treats "not in flight AND not queued AND head unchanged" as a lapse. But ReroutePickedUp (contribute_reroute.go:207-222) only scans InFlight, and a finished task_complete removes the dispatch via CompleteDispatch (contribute_fixqueue.go:504; fixqueue.go:338-355). The reroute prompt tells the target to open a replacement PR when it cannot push (contribute_fixqueue.go fixPRRerouteInstruction), which leaves the original head unchanged — so a target that does exactly what it was told within 30m gets a lapsed=true note, a forced adoption and a second hive copy. TestRepoItemReroutePickupLapseFallsBackToAdoptNow only covers the never-dispatched case. "Neither queued nor in flight" after a dispatch means completed or Resolved (a refusal goes back to the queue via Requeue), so it should end the reroute, not fall back:

	if hub != nil && !hub.RerouteQueued(to, repoFull, number) {
		// Neither queued nor in flight: the relay completed the task
		// (fixed in place or opened a replacement PR) or the PR left 072.
		// Either way there is nothing to fall back from.
		store.ClearReroute(key, false, now)
		return false
	}

(replacing the head-comparison block at :616-623; the head check stays useful only as an extra reason to clear.)

2. Fallback timer and queued item are in-memory only (medium). armReroutePickup is called solely from the decision handler (api_repo_item_decision_reroute.go:523) with time.AfterFunc; the fix queue is also process-local. After a dashboard restart the record keeps RerouteTo/RerouteAt (persisted, store.go), the row keeps the rerouted → @X pill, but nothing re-arms the window and the item is gone from the target's queue — so the #15082 guarantee "falls back to Adopt now with an alert" is silently lost. Suggest re-arming on startup (or in the stage-tracker sweep) for every record with RerouteTo != "", with max(0, RerouteAt+timeout-now).

3. Engine still nudges/adopts around the reroute (low). The PR body says the author's hive "must not race the target", but Reroute cancels the author's queue only once (contribute_reroute.go:176). nudgeContributor (automerge_contributor_nudge.go:258-287) checks only nudgeDue and re-enqueues the PR on the author's queue at the renudge interval; adoptionDue likewise ignores rec.Rerouted. Nothing in src/pkg/github/automerge reads the reroute fields. Suggest skipping the nudge (and the grace-based adoption) while rec.Rerouted(obs.HeadSHA) != "".

— hive: agent=adjudicator backend=copilot model=claude-fable-5.1 copilot=1.0.88

@hivecommons-hive hivecommons-hive Bot removed the stage/071-needs-author Human-authored PR: CI red, changes requested or conflicting; diagnosis posted, the author must act label Oct 29, 2026
@hivecommons-hive hivecommons-hive Bot added stage/050-review-pending Review swarm requested; awaiting a verdict for the current head stage/071-needs-author Human-authored PR: CI red, changes requested or conflicting; diagnosis posted, the author must act and removed stage/050-review-pending Review swarm requested; awaiting a verdict for the current head stage/071-needs-author Human-authored PR: CI red, changes requested or conflicting; diagnosis posted, the author must act labels Oct 29, 2026
…waiting on a contributor's clanker

A PR at stage 072/071 waiting on its author's hive offered only Hold /
Re-evaluate / Mark needs-human / Open / Copy. Two operator actions end the
wait:

- Adopt now — hive takes it over: decision `adopt` + `force: true` marks
  the stage record forced, posts an attributed adoption-requested note,
  sets adoption/supersede and nudges the sweep, which runs the existing
  supersede adoption at once, bypassing presence, grace and
  maintainer_policy (hold still stops it). Marker reads
  `reason=operator-forced by=@login`; an online author is told the
  maintainer took it over. Audit `repo_item_decision_adopt_now`
  (`action=adopt-now`). Toast "Adopted → #N (hive's copy), contributor PR
  will close when #N merges".
- Reroute to another clanker: decision `reroute` + `to: <login>|any`
  enqueues the PR's follow-up work on the target's contributor fix queue
  and dispatches it as a fix-pr task_assign interrupt (the 072 nudge path),
  posts `hive:rerouted to=@x by=@op reason=…`, shows a "rerouted → @x" pill
  with presence, and falls back to Adopt now when the target has not picked
  the task up within governor.reroute.pickup_timeout (default 30m), with a
  system alert and audit entry. Disabled with "no clankers online — use
  Adopt now" when nothing is online.

Both appear in the Needs-human popover options once the nudge grace has
elapsed, and "Let hive decide" picks Adopt now (grace-elapsed-adopt-now)
then. Go tests for the handlers, the fallback, the tracker payload and the
engine bypass; node fixture tests for the menu, consequence line, disabled
reasons, confirms and popover.

Fixes #15082

Signed-off-by: Andrew Anderson <andy@clubanderson.com>
Signed-off-by: Andrew Anderson <andy@clubanderson.com>
Signed-off-by: Andrew Anderson <andy@clubanderson.com>
Signed-off-by: Andrew Anderson <andy@clubanderson.com>
@clubanderson
clubanderson force-pushed the feat/adopt-now-reroute branch from 8ab9932 to d217f4a Compare October 29, 2026 01:40
@github-actions github-actions Bot added the conflicts-with-open-pr Open PR has a merge conflict with another open PR label Oct 29, 2026
@hivecommons-hive hivecommons-hive Bot added stage/050-review-pending Review swarm requested; awaiting a verdict for the current head and removed stage/071-needs-author Human-authored PR: CI red, changes requested or conflicting; diagnosis posted, the author must act labels Oct 29, 2026
@hivecommons-hive hivecommons-hive Bot added stage/071-needs-author Human-authored PR: CI red, changes requested or conflicting; diagnosis posted, the author must act and removed stage/050-review-pending Review swarm requested; awaiting a verdict for the current head labels Oct 29, 2026
@hivecommons-hive

Copy link
Copy Markdown
Contributor

@clubanderson this PR is held at stage/071-needs-author and the hive will not merge it yet.

Failing checks:

  • overlayfs-exec-guard

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.

@github-actions

Copy link
Copy Markdown
Contributor

Thank you for your contribution! Your PR has been merged.

We'd love to hear how your experience was: share feedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author/human A person pushed this PR themselves conflicts-with-open-pr Open PR has a merge conflict with another open PR dco All commits are DCO signed-off dco-signoff: yes Indicates the PR's author has signed the DCO. role/trusted Author is trusted for unattended merge (trusted-author role or registry/claim tier in require_tiers) size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. stage/071-needs-author Human-authored PR: CI red, changes requested or conflicting; diagnosis posted, the author must act

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Activity Monitor: Adopt now and Reroute to another clanker for PRs waiting on a contributor's clanker

1 participant