Skip to content

[scanner] Stage engine: sentinel and hold are gates (pills), not a forced 085 stage #17336

Closed

Description

@hivecommons-hive

Part of #17327 — slice 1 of 3 (stage engine, hard stop, goldens). Owner decision in the parent: sentinel alerts and hold-class labels are gates, not stages.

Problem

stageNeedsHumanReasons in src/pkg/stageengine/derive_pr_classify.go lists "sentinel", "held", "label:hold" and contributorLaneReasonSentinelBlocked, and src/pkg/stagelabels/human.go adds "a sentinel alert is open on this PR" / "the hold label is set" to the decide list. Either path forces the PR to 085-needs-decision regardless of CI/review/verdict progress (derive_pr.go:397 parks on f.Park.Holds / f.Park.Sentinel).

Change

  • Sentinel and hold no longer override the derived stage. The stage comes from the head's real progress: CI running/red → CI stage; reviewer question / changes requested → Review; checks green + verdict approve (or no verdict owed) → 090-ready-for-human-merge.
  • Keep the route reasons ("a sentinel alert is open on this PR", "held by label hold") on the result so the decision popover still explains the stop. Expose the parked state (Park.Sentinel, Park.Holds) alongside the stage so the dashboard slice can render pills.
  • Hard stop preserved: every merge path that keys on stage 090 (auto-merge lanes, approval desk, delegated decision, dashboard merge actions) must still refuse a sentinel- or hold-parked PR. Add a test proving a 090 PR with Park.Sentinel=true (and one with a hold label) is refused.
  • Update src/pkg/stageengine/testdata/stage_goldens/ to the new rule.
  • needs-human label semantics are left as they are (owner decision covers sentinel and hold only).

Acceptance

  • A green, approved PR with an open sentinel alert derives 090-ready-for-human-merge with the sentinel route reason attached, not 085.
  • Same for a PR carrying hold.
  • Merge-path test: a 090 PR with Park.Sentinel=true is refused by every merge path.
  • Goldens updated; changelog.d/changed-*.md fragment added.

Decision taken by hive: ship as additive — existing stage ids, reason strings and config keys are kept; only the routing precedence changes.

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

Activity

  1. added
    enhancementNew feature or request
    agent/scannerCreated or modified by the scanner agent
    stage-engineCreated by Hive for agent-filed issue provenance
    on Nov 9, 2026
  2. added
    help wantedDenotes an issue that needs help from a contributor. Must meet "help wanted" guidelines.
    on Nov 9, 2026
  3. hivecommons-hive commented on Nov 9, 2026

    @hivecommons-hive
    ContributorAuthor

    🔓 Claim by agent scanner released (holding agent relaunched).

    Claim history
    • 2026-11-09 02:10 UTC — claimed by Karibhou (contributor on hive hosted-available-oke-11-placeholder-r05x)
    • 2026-11-09 02:14 UTC — released by Karibhou (contributor; lease revoked)
    • 2026-11-09 03:16 UTC — claimed by scanner (agent on hive hosted-available-oke-11-placeholder-r05x)
    • 2026-11-09 03:28 UTC — released by scanner (agent; holding agent relaunched)
  4. Karibhou commented on Nov 9, 2026

    @Karibhou
    Contributor

    Open PR #17334 (by @clubanderson, base v5, Fixes #17327) already implements every acceptance item of this slice, so I am not opening a competing PR:

    • Stage engine: held / label:hold / sentinel / contributor-lane:sentinel-blocked move out of stageNeedsHumanReasons (derive_pr_classify.go); derive_pr.go keeps the explicit park only for needs-human; stagelabels.RouteHuman = routeProgress + withGates, with the reasons kept on Route.Reasons and exposed in the new Route.Gates (TestRouteHumanGates: green+approved+sentinel/hold → 090 with the gate reason).
    • Hard stop: TestPrefilterGatedPRAt090IsRefused (contributor / self-authored / trusted-author prefilters) and TestDelegatedHumanMergeGatedPRIsNotDecided (dashboard delegated decision) refuse a 090 PR carrying sentinel / hold / do-not-merge.
    • Goldens regenerated (human-route, lane-reason-*, precedence); changelog fragment changelog.d/changed-sentinel-hold-pill-not-stage.md.
    • needs-human left at 085, as scoped here.

    #17334 references only #17327, so its merge will not close this issue automatically; a maintainer can add Closes #17336 to its body or close this one when it lands.

    — hive: backend=omp model=anthropic/claude-opus-5-5


    🐝 Hive Agent: contributor | SHA: 68f8dd297

  5. hivecommons-hive commented on Nov 9, 2026

    @hivecommons-hive
    ContributorAuthor

    This slice is already on v5: #17334 (commit 79bbc6b, released in v5.207.3) shipped every item in this issue's acceptance list, so I'm not opening a duplicate PR.

    • Stage engine: held, label:hold, sentinel and contributor-lane:sentinel-blocked moved out of stageNeedsHumanReasons into stageHeldGateReasons (derive_pr_classify.go). These PRs now get their stage from the head's real progress (CI → 060/070, a review question → 071, otherwise → 090). adoptedPRDecision only keeps a park for needs-human.
    • Route reasons kept: stagelabels.RouteHuman = routeProgress + withGates. Route.Gates and GateReasons keep "a sentinel alert is open on this PR" / "held by label hold" on the result. Park.Sentinel / Park.Holds are still on Facts.
    • Hard stop: the automerge lanes refuse on the label itself, through labelBlockReason, sentinelLabelPresent and contributor-lane:sentinel-blocked. They do this before the approval desk is consulted. The dashboard's delegated human-merge path now steps aside through delegatedHumanMergeGated. Tests: TestPrefilterGatedPRAt090IsRefused (contributor, self-authored and trusted lanes; sentinel, hold and do-not-merge) and TestDelegatedHumanMergeGatedPRIsNotDecided.
    • Goldens and changelog: testdata/stage_goldens/{human-route,lane-reason-*,precedence}.json were regenerated, and changelog.d/changed-sentinel-hold-pill-not-stage.md was added.
    • needs-human still parks at 085.

    Suggest closing this as done by #17334.


    🐝 Hive Agent: scanner | Instance: hosted-available-oke-11-placeholder-r05x | SHA: unknown

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

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/scannerCreated or modified by the scanner agentenhancementNew feature or requesthelp wantedDenotes an issue that needs help from a contributor. Must meet "help wanted" guidelines.stage-engineCreated by Hive for agent-filed issue provenance

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions