Repository navigation
✨ activity monitor: show sentinel and hold as pills on the PR's real stage instead of forcing needs-decision - #17334
Conversation
…stage instead of forcing needs-decision Sentinel alerts and hold-class labels are gates, not stages (owner decision 2026-11-08). The stage engine now routes a gated PR by its head's evidence like any other human hand-off — CI / 070 while checks run or fail, 071 on a reviewer question, 090-ready-for-human-merge when the head is otherwise clean — and keeps the gate reason on the route so the entry comment reads "Held: a sentinel alert is open on this PR. The hive never merges this head while the gate stands." and the dashboard popover still explains the stop. The gate remains a hard merge stop: the automerge lanes and the dashboard's delegated human-merge shortcuts refuse on the label itself, never on the stage number (tests pin a 090 PR with a sentinel alert or hold refused by the contributor, self-authored and trusted-author prefilters and by the dashboard's human-merge decision/outcome paths). Dashboard: a held 090 row's Merge queue cell reads "Held · sentinel · confirm intent" / "Held · hold" (amber ham-held, tooltip with the gate's reason, the route reason and the rule), never "Queued for merge"; the sentinel question's Approve / Let hive decide / direction / close actions stay available from that cell. needs-human keeps parking at 085. Fixes #17327 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
|
|
Hive status — updated in place; edits do not notify. Full history is in the Activity Monitor. @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. Evidence bundle `#17334851f3a8` sha256:b6acf5f641186863e0819174977aaaa444bfcd28827813930ff3deb80f20e55a — download from the dashboard or `hivectl review evidence #17334`. |
|
This PR also covers #17336 (stage-engine slice 1 of #17327: sentinel/hold as gates, hard-stop tests, goldens, changelog). Its merge should close #17336 too, but only a maintainer editing this PR body to add — hive: backend=omp model=anthropic/claude-opus-5-5 🐝 Hive Agent: |
|
merged by Hive trusted-author auto-merge: author @clubanderson holds role owner and GitHub permission admin on repo; CI green at 851f3a8. |
|
Thank you for your contribution! Your PR has been merged. We'd love to hear how your experience was: share feedback |
Fixes #17327
The rule (owner decision, clubanderson, 2026-11-08)
Sentinel alerts and
hold-class labels are gates, not stages. A PR's column reflects its real progress — CI running/red → CI; reviewer question / changes requested → Review; checks green + verdict approve (or no verdict required) →090-ready-for-human-merge(Merge queue). The sentinel/hold rides along as a pill: the Merge queue cell reads Held · sentinel · confirm intent / Held · hold (amber), never "Queued". The gate remains a hard merge stop: a parked PR never merges unattended.Before,
derive_pr.gotreatedPark.Holds/Park.Sentinelas an explicit park pinning the PR at085-needs-decision, so a green, reviewed, sentinel-only PR sat in Review / "Needs human" beside real reviewer questions, hiding the cheapest decisions.Changes
Stage engine
stagelabels/human.go:RouteHuman=routeProgress+withGates. NewRoute.GatesandGateReasonskeep "a sentinel alert is open on this PR" / "held by labelhold" on the route (so the decision popover still explains the stop) without steering the stage.ReadyCommentfor a held 090 adds "Held: …. The hive never merges this head while the gate stands." and asks to resolve the alert / lift the hold, then/lgtm/approve.HumanAuthorOwesAnswerno longer counts sentinel/hold as a reviewer ask.stageengine/derive_pr_classify.go:held,label:hold,sentinel,contributor-lane:sentinel-blockedmove out ofstageNeedsHumanReasonsinto astageHeldGateReasonsbranch that routes by evidence (needs-rebase/red → fixing;requires_human→ 071/085 by author; else 090 Human).derive_pr.go:adoptedPRDecisiononly keeps the park forneeds-human.HiveSupersederHardStopSentinel/Hold→ 085) andYieldsToAdoptionForuntouched on purpose: the superseder rule is an explicit owner stop, not a gate pill.-update(human-route,lane-reason-*,precedence) and spot-checked: green+approve+sentinel/hold → 090 with the gate reason; pending → 060; red → 071;requires_humanon a human author → 071; verdictnone→ 085 "no reviewer configured" (pre-existing rule); precedence final stages unchanged (only the intermediate opinion 085→090).Merge safety (checked the park facts, not the stage number)
labelBlockReason(sentinel,label:hold,label:do-not-merge*), contributor lanecontributor-lane:sentinel-blocked, trusted sweepsentinelLabelPresent. NewTestPrefilterGatedPRAt090IsRefusedpins a 090 PR with sentinel / hold / do-not-merge refused by the contributor, self-authored and trusted-author prefilters.delegatedHumanMergeDecision/Outcomecould previously approve/admit an owner-authored 090 PR wearing a hold label. NewdelegatedHumanMergeGatedmakes both step aside (policy's sentinel question /rail-holdanswers as before).TestDelegatedHumanMergeGatedPRIsNotDecidedproves 090 +SentinelAlert/hold/do-not-merge/*is refused.postHumanEntryre-explains on cause change for 090 too, so held → ready on the same head rewrites the comment (TestReadyEntryRewritesWhenGateLifts).Dashboard
stage_tracker_decision.go: a 090 row with a live sentinel alert (not the trusted-author notice) gets the sentinel question (Approve / Let hive decide / direction / close) instead of "Ready to merge";decisionForHumanMergealready handleshold.stageTrackerHeldWord/stageTrackerHeldTip(tracker-words.js), detourheldflag (tracker-row.js),ham-heldclass + aria/title (tracker-row-strip.js),stageTrackerSentinelInLanecovers a held 090 so no duplicatesentinelchip; CSS.ham-seg.active.ham-held { background: var(--amber) }with the ⏸ glyph.go generateregeneratedstatic/index.html. Node tests extended instage_tracker_sentinel_lane_test.go.Docs:
stage-labels.md(085/090 rows, lane-reason table, evidence routing table),activity-monitor.md,hive-merge.md,reference.mdstate the rule. Changelog fragmentchanged-sentinel-hold-pill-not-stage.md.Screenshots (fixture: green, reviewed PR #17301 with a sentinel alert; #17302 with a
holdlabel)Judgement calls — please check
needs-humanleft at 085. The decision covers sentinel and hold;needs-humanis an explicit human ask (someone deliberately labelled it), so I recommend it stays a stage. It would be a one-line move intostageHeldGateReasonsif you want it to follow.adoptedPRDecision(074 adoption) andHumanAuthorOwesAnswernow ignore holds/sentinel — a held human PR with CI green can be adopted; the lane still refuses to merge the copy while the gate stands.stagelabels,stageengine,automerge, targeteddashboardtests incl. the node harness) to avoid CI round-trips on goldens; they have no process management. CI is still the verdict.