Repository navigation
π Hold relayed merges to the contributor-lane policy - #13192
Conversation
The merge-request relay (hive-merge β merge-request watcher β MergePR as the App) gated on agent authority, merge-eligible.json at a pinned head, labels and positive CI, but never on the contributor-lane policy the auto-merge sweep enforces. A scanner's merge request therefore landed an untrusted-tier contributor PR (green at stage/060, never soaked) that the lane would have refused on tier and soak alone. - Split the contributor-lane sweep's evaluation out of its merge tail (evaluateContributorLanePR) and expose Engine.RelayMergeRefusal, which runs the same gates read-only: tier admission, association, diff fences, control labels, review verdict, CI with min_head_age, soak, human-merge paths and head-SHA pinning. App, trusted-bot and trusted-author-role authors keep today's relay behaviour. - Add a MergeRequestPolicyGate hook on the GitHub client; the watcher consults it before any branch update, denies terminally (.denied) with the gate named in the agent's result, audits merge_request_refused, and fails closed on unreadable evidence through the bounded retry path. The hive installs the auto-merge engine's RelayMergeRefusal through the request-relay supervisor, so rebuilt clients re-arm it. - classifyMergeEligibility no longer lists PRs parked on a human decision (stage/085-needs-decision, or the issue-side stage/045 spelling). Signed-off-by: Andy 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 repository have no revert or sentinel-alert evidence. CI, reviewer verdict, diff fences, soak, holds and branch protection still apply. |
|
merged by Hive trusted-author auto-merge: author @clubanderson holds role owner and GitHub permission admin on repo; CI green at 29e852a. |
|
Thank you for your contribution! Your PR has been merged. We'd love to hear how your experience was: share feedback |
* π In-progress sweep and claim read fall back to the hub's claim ledger (#13133) * π In-progress sweep and claim read fall back to the hub's claim ledger A ledger claim whose hive:claim marker comment was suppressed by the per-issue comment budget read as 'no claim' to SweepInProgressIssues and annotateIssueClaims, which stripped stage/020-claimed and flipped the issue back to 010-actionable while the scheduler still withheld it. Fixes #13132 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π Refresh scale-envelope citation after client.go field insertion Signed-off-by: Andrew Anderson <andy@clubanderson.com> --------- Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π 085 entry comment follows the decision cause; flag @maintainer placeholder questions (#13139) * π 085 entry comment follows the decision cause; flag @maintainer placeholder questions A PR parked at stage/085-needs-decision gets its entry comment once per stage visit. When the maintainer clears the cause the comment named (sentinel alert) and a different lane fence keeps the PR at 085 (workflow-path), the stage does not change and nothing tells them why the PR is still parked. The stage store now remembers the cause digest of each entry comment per stage+head and postHumanEntry re-posts for a cause this visit has not explained; each distinct cause is posted once per head and records from before the change count as explained. Reviewer decision questions copied the policy example's literal @maintainer, which GitHub notifies nobody for. The policy now asks for a real approver login and the 085 comment marks a placeholder mention. Fixes #13137 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * changelog: fragment for #13139 Generated by changelog-fragment-guard from the PR title (#5675). Edit the wording freely, or replace this file with the no-changelog label if the change is not user-visible. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Signed-off-by: clubanderson <407614+clubanderson@users.noreply.github.com> --------- Signed-off-by: Andrew Anderson <andy@clubanderson.com> Signed-off-by: clubanderson <407614+clubanderson@users.noreply.github.com> Co-authored-by: clubanderson <407614+clubanderson@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * π Moves within 070/071/072 re-attribute the fix, not a regression (#13140) * π Moves within 070/071/072 re-attribute the fix, not a regression 072 β 070 on hive-signoff-attribution (the hive's own follow-up commit broke the squash sign-off gate, so the hive takes the breakage back) and 072 β 071 when the author kind is learned late were flagged regressed, with a stage-regressed comment and tracker chip, because 070 < 072 numerically. Nothing moved backwards for the author; IsRegression now treats the fixing family as one state split by who owes the fix. Fixes #13138 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * changelog: fragment for #13140 Generated by changelog-fragment-guard from the PR title (#5675). Edit the wording freely, or replace this file with the no-changelog label if the change is not user-visible. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Signed-off-by: clubanderson <407614+clubanderson@users.noreply.github.com> --------- Signed-off-by: Andrew Anderson <andy@clubanderson.com> Signed-off-by: clubanderson <407614+clubanderson@users.noreply.github.com> Co-authored-by: clubanderson <407614+clubanderson@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * π fix: route requires_human contributor PRs to stage/085 before admission reasons (#13152) Backport of #13117 to v5, in the engine-native form that landed on v6 with the v5βv6 top-up (#13141, ed14048): requiresHumanStage gives the trusted-lane role check and contributor-lane admission reasons a weak 085 opinion when the head's reviewer verdict is already requires_human, resolveStage keeps that weak 085 whatever the tier, and RouteHuman's fresh-head exit no longer applies when the verdict is requires_human. A requires_human verdict on an untrusted contributor-lane PR therefore derives stage/085-needs-decision instead of 050-review-pending + stalled. Stage goldens regenerated with -update (44 cases, all route=fresh/verdict=requires_human 050 β 085). transition_table.go untouched. Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π fix: withhold review-fix pushes for hive-attributed PRs under a person login (#13150) Backport of #13125 to v5. fixPushAllowed delegated to hiveAuthored, so contributor-relay PRs (person login, `β hive:` trailer) still got a hive-signed fix commit that the squash sign-off gate rejects as bot-signoff. The push now requires an agent/App login author, or a PR the stage reconciler adopted in place (stage/074-adopted-by-hive, the v5 exception the v6 top-up kept); the fix is proposed in the review otherwise. (cherry picked from commit 31662b0) Signed-off-by: Andrew Anderson <andy@clubanderson.com> * β¨ Sidebar x/y count pills for Overview and Governor (#13148) * β¨ Sidebar x/y count pills for Overview and Governor Overview shows open issues / open PRs from the stage tracker working set (GET /api/stage-tracker items by kind); Governor shows the shared actionableNow.issues / .prs split from /api/status, the same numbers the Governor tiles print. Both reuse .badge-count .oc-nav-count and stay hidden until their feed has answered once. Closes #13147 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * changelog: fragment for #13148 Generated by changelog-fragment-guard from the PR title (#5675). Edit the wording freely, or replace this file with the no-changelog label if the change is not user-visible. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Signed-off-by: clubanderson <407614+clubanderson@users.noreply.github.com> --------- Signed-off-by: Andrew Anderson <andy@clubanderson.com> Signed-off-by: clubanderson <407614+clubanderson@users.noreply.github.com> Co-authored-by: clubanderson <407614+clubanderson@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * π unpark: answer `/hive approve` on a PR and name the lane's release action (#13163) Backport of #13092 (fixes #13087 on v6) to v5. `/hive approve` on a pull request was silently skipped by the un-park sweep unless the PR sat at `stage/085-needs-decision`, and the 085 entry comment never said what would actually release the hold. The sweep now answers `/hive approve` on any open PR once per comment (marker- deduplicated, no label writes) with what the merge lane will do with it, and `stage/085-needs-decision` comments carry a "How to release it" list supplied by the lane, naming manual-only merges explicitly. Deviations from the v6 change: v5 has no review hold-release ledger (#13088 is v6-only), so no lane consumes `/hive approve` on a PR here. The reply therefore acknowledges the comment and names the v5 release lever β a trusted merger's GitHub Approve review on the exact head β instead of recording a release; the "no active hold" and "predates the latest verdict" branches are not ported. Lane actions use the same wording and the existing #13041 "What to do" block is kept. Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π fix: offer superseded PR decisions without auto-close (v5) (#13155) * π fix: lead superseded contributor PR threads with the close/keep-open decision Backport of #13120 to v5 (additive rendering only). - Review comments render the hive-decision-question as visible text at the top; the HTML marker is unchanged. - A review marked <!-- hive-redundant-of: #N --> shows "no-op merge: duplicate of #N" instead of the numeric score headline. - The supersession sweep notice states the recommendation (close as superseded) and the other choices. (cherry picked from commit d0c869e) Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π fix: offer superseded PR decisions without auto-close Backport of #13118 to v5. Superseded contributor PRs now appear in the Review Queue with close / keep-open actions even when supersession_sweep.close_contributor_prs is unset. The sweep emits a detected-contributor audit event on every detection (and kept-open when hive/keep-open is present), including when its notice is already present. The queue reader accepts detection and legacy grace entries; existing auto-close guards and grace events remain intact. An explicit keep-open label suppresses the recommendation, and disabled auto-close shows no countdown and never promises an automatic close. Deviation from v6: the your-turn inbox (dashboard ownership rules, SupersessionStatusOption, superseded_recommended_close) is v6-only and is not ported; only the Review Queue half lands here. Signed-off-by: Andrew Anderson <andy@clubanderson.com> --------- Signed-off-by: Andrew Anderson <andy@clubanderson.com> * fix: show the running release semver in the dashboard (#13130) (#13161) Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: MikeSpreitzer <14296719+MikeSpreitzer@users.noreply.github.com> * fix: match agent token-cache files exactly when re-owning (#13123) (#13160) Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: gregoryhunt <31053269+gregoryhunt@users.noreply.github.com> * π docs: describe Prow dco-signoff labels as coexisting with hive's dco pair (#13131) Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> * π entrypoint: provision users and token caches for replicas: copies (#13171) * π entrypoint: provision users and token caches for replicas: copies A replicas: copy (<agent>-2 .. <agent>-N) is derived in memory by ExpandAgentReplicas and stripped on save, so the entrypoint never saw its name: no hive-<agent>-N user, no private token group, no pre-created token cache. The manager ran it as a bare uid:node and the token write created the cache dev:node 0600, so every gh call in the replica was blocked with token_cache_unavailable, permanently. Move the inline agent-name collection into hive_collect_agent_names and expand replicas there with the same naming and 2..MaxAgentReplicas bound as config.replicaAgentName, so replicas are provisioned at boot like declared agents. Raising replicas on a running hive still needs a restart for the new copies, the same as an agent added through the API. Fixes #13166 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CoYvUkv8Gp4AHGWLo97nqb Signed-off-by: Gregory Hunt <greg@on-board.ai> * π changelog fragment for #13166 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CoYvUkv8Gp4AHGWLo97nqb Signed-off-by: Gregory Hunt <greg@on-board.ai> --------- Signed-off-by: Gregory Hunt <greg@on-board.ai> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * π fix(fleetreport): exclude nudge-recovered stalls from agent-stall evidence (#13172) v5 backport of #13099. A stall that the harness nudge recovered is self-recovery working (#12814) and is no longer counted toward the fleet-report defect bar; only unrecovered stalls remain evidence. (cherry picked from commit 9802648) Closes #13157 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * ci: make the dco-squash default-branch fetch actually run (#13159) The 'Make the default branch resolvable' step used --depth=0, which git rejects ('depth 0 is not a positive number'), and the failure was masked by '|| true', so the step was dead code and the check only worked because actions/checkout fetch-depth: 0 happened to populate the ref. Drop --depth=0 and || true and verify the ref so a fetch failure fails the step visibly. (cherry picked from commit c35db2f) Closes #13158 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π Findings blocked on an unmerged PR are parked, unclaimable, and don't ping fork authors (#13143) A review-backlog finding whose evidence file exists only on the reviewed PR (absent on its base branch) is filed with the blocked label and a <!-- hive:blocked-on pr=owner/repo#N --> marker, without help wanted. A blocked issue lands in the filtered bucket, derives no stage label, and IssueClaimBlockReason refuses every automated claim on it; a sweep after each stage-label sync lifts the label once the tracked PR merges or closes and strips help wanted while it is open. hive-open-issue comment --blocked-on-pr <n> posts the same neutral note through the issue-request watcher with @-mentions stripped, and the scanner prompts point at it instead of @-mentioning the fork author. The contributor lane keeps a session off an issue it just failed, abandoned or had its lease revoked on for governor.claims.reclaim_cooldown_s (default 6h) instead of handing it back every ten minutes when the global failure cooldown lapses. Fixes #13142 Part of #12999 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π Fix TestCampaignDeleteRemovesArchiveOnly order dependence (#13195) GET /api/campaigns folds completed runs from the package-global lifecycle timeline store (lifecycleStore singleton) into the list. Under -shuffle a stage-completion journey for acme/repo!graph-a:node-a recorded by an earlier test leaked in and the unfiltered list returned 3 campaigns instead of 2. Reset the singleton at the top of the test like the other campaign/run tests already do. Reproduced deterministically by replaying the CI shuffle seed 1792510983440914831 on dashboard slice 1/2 before; passes after. Fixes #13167 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π Fix TestBootDashboardWithClassifier data race on log sink (#13194) bootDashboardWith launches backfillRecentMergedPRs in a goroutine that logs through b.logger; the test read log.String() from an unsynchronised strings.Builder while that goroutine was still writing, which -race flags intermittently. Use the package's existing goroutine-safe syncLogBuffer as the sink instead. Reproduced 1/900 with -count=300 -race -cpu 1,2,4 before; 0/900 after, plus -count=200 -race -shuffle=on clean. Fixes #13168 Fixes #13169 Fixes #13170 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π Hold relayed merges to the contributor-lane policy (#13192) The merge-request relay (hive-merge β merge-request watcher β MergePR as the App) gated on agent authority, merge-eligible.json at a pinned head, labels and positive CI, but never on the contributor-lane policy the auto-merge sweep enforces. A scanner's merge request therefore landed an untrusted-tier contributor PR (green at stage/060, never soaked) that the lane would have refused on tier and soak alone. - Split the contributor-lane sweep's evaluation out of its merge tail (evaluateContributorLanePR) and expose Engine.RelayMergeRefusal, which runs the same gates read-only: tier admission, association, diff fences, control labels, review verdict, CI with min_head_age, soak, human-merge paths and head-SHA pinning. App, trusted-bot and trusted-author-role authors keep today's relay behaviour. - Add a MergeRequestPolicyGate hook on the GitHub client; the watcher consults it before any branch update, denies terminally (.denied) with the gate named in the agent's result, audits merge_request_refused, and fails closed on unreadable evidence through the bounded retry path. The hive installs the auto-merge engine's RelayMergeRefusal through the request-relay supervisor, so rebuilt clients re-arm it. - classifyMergeEligibility no longer lists PRs parked on a human decision (stage/085-needs-decision, or the issue-side stage/045 spelling). Signed-off-by: Andy Anderson <andy@clubanderson.com> * β¨ Webhook deliveries wake the eval loop and refresh the stage tracker in seconds (#13165) * β¨ Webhook deliveries wake the eval loop and refresh the stage tracker A verified GitHub webhook that invalidates cached PR/issue state now asks the governor loop for an early, debounced eval cycle (governor. webhook_wake_debounce_s / webhook_wake_min_gap_s) that re-enriches only the dirty PRs, so eval_interval_webhook_s is a safe base tick and GitHub calls go down. The loop re-checks webhook health as the 2x eval_interval_s window closes and falls back to eval_interval_s at once, logging one line per transition; /api/status reports evalMode, lastWakeReason, lastWakeAt. Every status publish invalidates the /api/stage-tracker cache and sends a stage-tracker SSE event the SPA refetches on. The spoke handles pull_request_review_comment and the hub relays it plus issues. Closes #13164 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π± Fix webhook waker coalesced expectation in test Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π± Only nudge the stage tracker over SSE once it has been served Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π± Expose webhook wake pacing keys in the governor Settings UI Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π Refresh api-reference citations after server.go line shift Signed-off-by: Andrew Anderson <andy@clubanderson.com> --------- Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π Fix TestKickHitsβ¦ flake by gating the kick response (#13201) The test pressed K three times and asserted exactly one POST left, relying on the second press being processed before the first response cleared kickPending. The fixture answers instantly, so when the test goroutine is descheduled between presses (CI under -race load) the first kickResultMsg lands first, kickPending is cleared and the second press issues a second request. Hold the /api/kick/scanner response with the fixture's existing gate() until all three presses have been processed (same pattern as the ACMM exactly-once test), then release it and assert the queued footer. Fixes #13191 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π fix: honor contributor target branches (#13190) Hive-Run: #13146 Hive-Plan: contributor-dispatch-target-branch Hive-Spec: contributor-dispatch#wrong-base-verdict Signed-off-by: hanthor <5840441+hanthor@users.noreply.github.com> Co-authored-by: hanthor <5840441+hanthor@users.noreply.github.com> Co-authored-by: clubanderson <407614+clubanderson@users.noreply.github.com> * π fix: let a trusted human's approval clear the review gate and deliver fix kicks before governor kicks (#13188) The merge-lane review gate skipped the trusted-human-approval lookup for any changes-requested outcome, and classified the head from the perspective map rather than the aggregate verdict, so a requires_human head read as changes-requested:style to the gate and an owner's APPROVED review on the exact head never cleared it. The gate now follows the normalized aggregate verdict (new requires-human outcome) and a trusted human's approval on the head overrides every non-approved outcome; the review_evaluated audit line records human_approver and overrode. Review-plan fix kicks (a maintainer's changes_requested review or /hive decision) were assembled after the governor kick to the same agent, so the governor kick owned the agent and the fix kick timed out every cycle; fix kicks now go first, and an undelivered review/fix kick is logged and audited by PR. Signed-off-by: Andy Anderson <andy@clubanderson.com> * [scanner] fix: stop EPIPE false failures in contribute-k8s workload test (#13198) contains() piped the full generated YAML into grep -qF; grep exits on the first match, printf then hits EPIPE, and set -o pipefail turns a genuine match into 'FAIL: valid name kata-clh is emitted'. Compare with a bash substring match instead, which reads the whole haystack. Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> * π Evidence: resolve PR outcomes from the review-outcome ledger (#13187) The Evidence card's "Outcome by author kind" reported every PR this hive reviewed but did not merge as "outcome unknown" (33 of 137 in a 24h window on hive's own spoke), although the governor's review-outcome ledger had already resolved 29 of them with a GetPRState call. - pkg/evidence: new optional `outcome` block on the bundle (source, state, at, merged_by/merged_at/closed_at) with Validate + JSON schema rules; FoldPRs honours it (OutcomeKnown, MergedElsewhere, Closed) and ApplyOutcomeHints applies ledger rows at read time to PRs whose records state no outcome. - pkg/github: Client.RecordReviewEvidenceOutcome stamps the newest bundle for a PR merged by someone else (with an `unrecorded` merge event naming the merger) or closed without merge, under reviewEvidenceMu; never touches a bundle that already states an outcome. No GitHub API calls. - cmd/hive: recordReviewOutcomesAt calls it after ledger.Resolve. - pkg/dashboard: summary adds merged_elsewhere per author kind and missing.prs_outcome_from_ledger; prs_outcome_unknown now means truly unresolved; the card footnote shows the merged-elsewhere / closed / open breakdown. A separate `outcome` block is used instead of `backfill` because Validate requires backfilled:true alongside `backfill` and readers treat backfilled bundles as carrying no live verdicts or CI. Fixes #13186 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * β¨ Self-report evidence: hive display name and clickable spoke URL (#13217) Runtime-error self-report issues now carry the reporting hive's display name and dashboard URL: the Evidence table gains 'hive name' and 'spoke' rows and each 'Affected hives (N)' line renders 'name (hive id) (instance β¦) β [open](url) β owner(s) β¦'. The spoke emits both best-effort (project.name; dashboard.public_url else hub.dashboard_url) only when hub-managed, so anonymous hives stay anonymous. The hub relay overlays its authoritative project_name and vanity URL and fills the rows for spokes that predate the fields, the same enrichment pattern as owner(s). Rendering is byte-identical when the fields are absent, so older reports and issues are unchanged. Signed-off-by: Andrew Anderson <andy@clubanderson.com> * β¨ Evidence cards: plain-English grade and summary (#13213) Every Evidence panel now shows a server-computed letter grade (A+ β¦ C-, or β when there is not enough data) in the header and a one-sentence plain-English summary under it. Rubrics and summary generators are pure functions in pkg/evidence/grade.go, exposed additively as cards[key] on /api/evidence/summary. Dense stats, denominators and "what this does not show" move behind the β popover; the CI gate card's disclosed line drops to the muted small size so nothing in a card exceeds the title size. Fixes #13204 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π Release agent issue claims on relaunch and pace rate-limit relaunches across the fleet (#13210) * π Release agent issue claims on relaunch and pace rate-limit relaunches across the fleet An agent claim (2h TTL) survived the hive rollouts that killed the holding agent: nothing released it, and the π marker on the forge read as live until until= even when the ledger had dropped it, because issueclaim.Latest ignored hive:release markers. The scanner's claim on an issue therefore parked it at stage/020-claimed for two hours across two image rolls with nothing working it. - agent.Manager gains a relaunch observer fired on every fresh CLI launch; cmd/hive wires it to Ledger.ReleaseAgentClaims, which drops only that agent's KindAgent claims and fires OnReleased. - The release hook posts the release comment for the relaunch reason, and the release marker now carries at=; issueclaim.Latest marks the latest claim Released when a later release marker names its identity. - Rate-limit relaunches of Copilot agents are spaced fleet-wide (30s) on top of the per-agent 300s cooldown, so the agents that tripped GitHub's limit during the boot stagger do not all re-validate together 300s later. Signed-off-by: Andy Anderson <andy@clubanderson.com> * π test: assert expiry posts nothing without a sleep (sleep ratchet) Signed-off-by: Andy Anderson <andy@clubanderson.com> --------- Signed-off-by: Andy Anderson <andy@clubanderson.com> * π fix: register covering-PR-close and claim reshuffle edges as expected stage transitions (#13136) * π fix: register covering-PR-close and claim reshuffle edges as expected stage transitions Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> * test: 045β020 is a non-regression hop, not an undrawn regression Every backward issue edge among 010β040 is drawn now, and IsRegression never flags a move out of 045, so the old 'undrawn regression' sample is expected. Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> * π docs: 040 falls are narrated on the PR, not commented on the issue The three 040 β 010/030/020 edges were labelled "(backward hop, commented)" in both the stateDiagram and transition_table.go, but the issue reconciler only comments regressions whose previous stage is before 040 (issue_stage_labels.go: a covering PR's own falls are narrated on the PR). Relabel them "narrated on the PR" and widen the prose enumeration of drawn issue fallbacks to include 030 β 020 and the 040 falls. Hive-Fix-Attempt: 1/6 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> --------- Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * π pr titles: one emoji convention β π docs, π proposal β enforced where the hive opens the PR (#13209) A hive-authored docs PR was opened as "π docs: β¦" and failed the repository's required PR Type check: the agent prompt and AGENTS.md said π for docs while review_priority.go read π as docs too, so nothing told the agent the two differ (π is the proposal emoji). Define the convention once (PRTitleEmoji* in pkg/github/pr_title.go), make review_priority draw from it, spell the convention out in the hive-open-pr instructions and AGENTS.md/CONTRIBUTING.md, and have the pr-request watcher correct a leading emoji that contradicts the Conventional Commits type before CreatePR. A title with no emoji is never given one, so repositories that gate on a bare header are untouched. Signed-off-by: Andy Anderson <andy@clubanderson.com> * π stage labels: hive-signed commits on a contributor PR go back to the author, not 070 (#13207) A human's or clanker's PR whose commits GitHub links to the hive App (a hive follow-up, or a contributor committing from a hive pod with the App's noreply address) was routed to stage/070-fixing under hive-signoff-attribution. No hive lane pushes to a non-App branch, so the PR sat where nothing could act (pluk#315, promptargs#303, rationguard#303, dibs#438, hivecommons.github.io#222 on 2026-10-20). Route it by author kind (071 human / 072 clanker, 070 only when self-authored) and tell the human author once per head exactly what to run (git commit --amend --reset-author -s && git push --force-with-lease, or the git rebase --exec form). The clanker's 072 nudge carries the same ask. Also classify the trusted-author lane's review-gate holds (no-review-bundle / awaiting-review-approval) as 050-review-pending: they had no stage opinion, so a PR carried no stage label at all until the swarm's verdict was noted. Signed-off-by: Andy Anderson <andy@clubanderson.com> * π Hub auth-check: let signed webhook relays reach hosted spokes (#13233) The hub relays GitHub App webhooks to the managing spoke at /api/webhook/github, but the hosted Ingress auth_request gate (handleSaaSAuthCheck -> isSaaSPublicPath) did not list that path, so nginx answered every relayed POST with an auth-signin 302 to the hub login page and the spoke never saw a delivery: webhooks.healthy=false, events_1h=0 on every hosted hive while the hub relayed hundreds of events an hour. Add the path to publicExactPaths as spokeWebhookRelayPath and make webhook.go's relay target the same constant so they cannot drift. This opens nothing: the spoke's handleGitHubWebhook fails closed without GITHUB_WEBHOOK_SECRET and verifies X-Hub-Signature-256 before doing any work. Fixes #13231 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π Evidence CI gate: resolve required checks per repo like the merge gate (#13227) The Evidence CI-gate panel judged every merged PR's bundle snapshot against the global auto_merge.required_checks, so on a multi-repo hive the primary repo's gate check (e.g. build-gate) was demanded of repos that never run it: Console showed 70 suspected missing_required breaches, none real. The merge gate resolves the set per repo (branch protection, else AutoMergeConfig.RequiredCheckSetForRepo), and green snapshots missing a config-required check were never queued for GitHub confirmation, so they could never be cleared. - EvidenceCIPolicy resolves the config set per repo through the same RequiredCheckSetForRepo helper the gate uses; the per-repo sets are exposed as repo_required_checks for the card copy. - collectCIRecovery queues green merges missing a config-required check (ciRecoveryGateDue), using the client's gate resolver (Client.ConfigRequiredChecksForRepo), so the trail's branch-protection read confirms or clears them; red/none remain due, pending is not. - Suspected vs confirmed is unchanged: a required check that truly never ran stays suspected, a required red on the merged head is a breach. Fixes #13225 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π fix: superseded close requires a recorded supersession state (#13238) Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> * π fix: stop owner advice counting on-demand agents as missing a cadence (#13237) Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: AN0099 <91515465+AN0099@users.noreply.github.com> * π fix: fall back to docker.io when mirror.gcr.io throttles; deterministic embedded short hash (#13229) * π fix: fall back to docker.io when mirror.gcr.io throttles and make the embedded short hash deterministic Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> * fix: resolve ${BASE_REGISTRY} in the SUID/cap fixture builders test_manifest_caps_runtime.sh and test_image_suid_inventory.sh lift the runtime FROM line out of src/Dockerfile verbatim; with the registry now parameterised as ${BASE_REGISTRY} the unexpanded placeholder became an empty prefix ("/node:26-slim") and docker build rejected the stage name. Resolve it the way docker build does: BASE_REGISTRY from the environment, else the Dockerfile's ARG default. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> --------- Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * π± images: refresh CA trust bundle and distrust two roots (#13230) * π± images: refresh CA trust bundle and distrust two roots Distrust emSign ECC Root CA - G3 and Comodo AAA Services root in the spoke, contributor, hub, CI-runner and OSS-scanner images (no fixed distro ca-certificates package is published yet), and point Node-based CLIs at the regenerated system store via NODE_OPTIONS=--use-openssl-ca. Add src/deploy/test_image_ca_distrust.sh and run it from docker.yml so the built spoke image is proven to reject the test chains. Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π± ci-runner image: assert Comodo AAA root absent-or-disabled Ubuntu 24.04's ca-certificates no longer ships Comodo_AAA_Services_root, so asserting the negated entry failed the build. Assert instead that no un-negated entry remains, and keep the check on the generated pem. Signed-off-by: Andrew Anderson <andy@clubanderson.com> --------- Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π Run the duplicate-PR guard before the live-claim filter so a covered issue stays at 040 (#13242) An issue whose agent claim was still live when its PR opened was withheld by FilterLiveIssueClaims as bucket "claimed" before ApplyDuplicatePRGuard could bucket it "claimed_by_pr". Every eval sweep after the PR opened therefore re-derived stage/020-claimed under the event-driven 040, and the stage store recorded a 040 -> 020 regression that the dashboard rendered as a red regressed chip on nearly every claimed issue. Reorder the guards so the open PR outranks the live claim, which also gives the ledger's OpenIssuesOf the full open-issue list. Signed-off-by: Andy Anderson <andy@clubanderson.com> * π Publish the dashboard status snapshot before the serial kick dispatch (#13182) * π Publish the dashboard status snapshot before the serial kick dispatch The eval cycle built and published the full dashboard snapshot only after dispatchAgentKicks, which delivers kicks serially and waits up to the input-prompt timeout per agent. On the hosted hive a cycle with ten due agents spent 13.5 minutes in that phase, so /api/status (and the stage tracker, agent states and governor.nextKickAt derived from it) showed the previous cycle's data the whole time; a pod rolled mid-dispatch never published its evaluation at all. Publish an interim snapshot before the kicks when any are due, and keep the end-of-cycle publish. Stale-build drops in UpdateStatusIfFresh are now logged at Warn and counted in a new statusStaleDrops payload field so a frozen snapshot can be attributed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Andy Anderson <andy@clubanderson.com> * docs: refresh api-reference citations after rebase Signed-off-by: Andy Anderson <andy@clubanderson.com> --------- Signed-off-by: Andy Anderson <andy@clubanderson.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * β¨ Evidence outcome card: record reverts and issue re-opens as change failures (#13244) * β¨ Evidence outcome card: record reverts and issue re-opens as change failures The Outcome by author kind card hardcoded reverted_14d to nil and never saw issue re-opens, so it could not say whether agent-written work gets undone more often than human work (Insight 3). - Read the existing reverted_by links into reverted_14d per author kind. - Detect reverts from text already fetched (pull_request closed webhook, PR state fetch, merged-PR backfill): Revert "β¦ (#N)" titles, Reverts #N, This reverts commit <sha>; resolve to merged bundles within 14 d and write reverted_by back-links. No new per-PR GitHub calls. - Record issue re-opens: when the claim ledger voids a merged claim for a reopened issue, stamp the closing PR's bundle with issue_reopens (new schema field) if within 14 d of the merge. - Card: issue_reopened_14d, change_failures and change_failure_rate = (reverts + re-opens) Γ· merged per kind; grade rubric and plain summary include re-opens; β text names both signals, the window and the detection method. - Docs and changelog fragment. Fixes #13241 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π scale-envelope: re-anchor client.go citation shifted by PRState fields Signed-off-by: Andrew Anderson <andy@clubanderson.com> --------- Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π fix: acknowledge /hive approve on hive-authored PRs only for trusted mergers (#13185) * fix: acknowledge /hive approve on hive-authored PRs only for trusted mergers Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> * fix: require a trusted merger for /hive approve on the trusted-author lane too Address review findings on #13185: the trusted-author lane also releases a requires_human hold only on a trusted merger's Approve (mergeReviewGate), so gate its acknowledgement the same way; drop the duplicate "trusted merger on App lane" test row in favour of an untrusted trusted-author-lane case; and reword maintainer-commands.md so the "not a trusted merger" reply is not scoped to the contributor lane. Hive-Fix-Attempt: 1/6 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> --------- Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * π fix: show the feedback form in the popover and surface submission errors (#13173) * fix: show the feedback form in the popover and surface submission errors Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: MikeSpreitzer <14296719+MikeSpreitzer@users.noreply.github.com> * fix: keep header feedback and theme buttons from overlapping the ACMM bubble Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: MikeSpreitzer <14296719+MikeSpreitzer@users.noreply.github.com> * fix: address review findings on the feedback submission error path - Log every rejected /api/feedback/report (read, too-large, invalid JSON, validation) through the guarded s.logger with the "feedback:" prefix instead of a single global slog.Warn. - Stop passing the raw non-JSON error body through feedbackStripQuery, which truncated it at the first ? or #. - Gate the "before the request completed" toast suffix on whether fetch resolved, and console.error the caught error so the pointer to the browser console is true. - Make the wiring test assert the new message fragment and console log. - Fold the #13135 bullet into the single changelog fragment. Hive-Fix-Attempt: 1/6 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> --------- Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: MikeSpreitzer <14296719+MikeSpreitzer@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * β¨ feat: separate current repository consent from follow policy (#13193) * β¨ feat: separate current repository consent from follow policy Add shared deselect-current and follow-policy operations and expose them through hives repos. Preserve exclusions and provenance, reject implicit legacy conversion, and reuse commit/projection/reload without enrollment. Hive-Run: #12571 Hive-Plan: ecosystem-onboarding/independent-selection-controls Hive-Spec: #12571#5 Hive-Spec: #13153#3 Hive-Spec: #13153#8 Co-authored-by: hanthor <5840441+hanthor@users.noreply.github.com> Signed-off-by: mendezr <mendezr@users.noreply.github.com> * fix: reconcile SetFollowNewRepositories with the landed preset-adopt declaration v5 already declares ProfileSet.SetFollowNewRepositories (bool, error) in preset_adopt.go; drop the duplicate from selection_ops.go and adapt the --follow-new-repos caller and its tests to the two-value signature. Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> (cherry picked from commit 42084bf) --------- Signed-off-by: mendezr <mendezr@users.noreply.github.com> Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: mendezr <mendezr@users.noreply.github.com> Co-authored-by: hanthor <5840441+hanthor@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> * β¨ Review swarm honours review_models for cross-family perspective reviews (#13250) Thread agents.<reviewer>.review_models selection into the per-perspective swarm kicks: each DispatchKick carries the author model and the selected {backend, model}, the perspective prompt reuses the queue kick's 'Independent review' overlay text, and skip / requires_human fallbacks withhold the kick or place a human hold. Add review.perspective_models to pin a model per perspective. Stamp author_model and review_model into pending records and collected verdicts (falling back to the reviewer's launch model), add a per-author-family and same-family vs cross-family breakdown to the reviewer-accuracy summary, the Evidence Accuracy card and /api/evidence/summary, and store same_family on evidence verdicts. Fixes #13243 Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π images: CA-distrust check passes platform and ignores docker stderr (#13247) * π images: CA-distrust check passes platform and ignores docker stderr The arm64 docker.yml lane runs the cross-built image on an amd64 runner; docker prints a platform-mismatch warning on stderr that the node probe captured via 2>&1 and reported as unexpected output, failing the build that publishes the fixed candidate image. Pass --platform from the matrix and read only the probe's stdout line. Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π images: CA-distrust check drops --platform, prints docker stderr on odd rc docker run --platform fails (rc=125) on the arm64 lane against the locally loaded PR image; stdout-only parsing is sufficient to ignore the QEMU platform warning. Show docker's stderr when curl returns a code the check does not understand. Signed-off-by: Andrew Anderson <andy@clubanderson.com> --------- Signed-off-by: Andrew Anderson <andy@clubanderson.com> * π fix: require header auth for Commons API (#13259) Hive-Run: #13245 Hive-Plan: API query-token removal Hive-Spec: issue-13245#api-header-auth Signed-off-by: hanthor <5840441+hanthor@users.noreply.github.com> Co-authored-by: hanthor <5840441+hanthor@users.noreply.github.com> * β¨ feat: hivectl hives hub add/list/show/remove tracks hubs and discovers their Hives (#13189) * feat: hivectl hives hub add/list/show/remove with read-only hub discovery Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> * ci: retrigger build after registry 429 on arm64 image pull Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> --------- Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: fan out hub webhook relays to every hive tracking the repository (#13228) Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: clubanderson <407614+clubanderson@users.noreply.github.com> * [scanner] feat: cross-process lock and expected-revision commit for ProfileStore (#13200) Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> * π fix: do not self-report model_discovery_degraded for a not-licensed Copilot 403 (#13256) * fix: do not self-report model_discovery_degraded for a not-licensed Copilot 403 Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> * changelog: fragment for #13256 Generated by changelog-fragment-guard from the PR title (#5675). Edit the wording freely, or replace this file with the no-changelog label if the change is not user-visible. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Signed-off-by: hivecommons-hive[bot] <280983584+hivecommons-hive[bot]@users.noreply.github.com> * chore: make the changelog fragment a bullet entry and drop the autofix duplicate Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> --------- Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Signed-off-by: hivecommons-hive[bot] <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * [scanner] fix: harden hives web with Host/Origin checks, no-store headers and token-free history (#13196) Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> * feat(dashboard): activity monitor shows a 'triage needed' action chip on Open issues (#13268) An issue sitting at Open with the needs-triage label still shows only the grey Open chevron, so a reader cannot tell it from an issue nobody has looked at. Report needs-triage as a tracker modifier so the action column reads "triage needed" (amber) and the tooltip headline says "Open Β· triage needed", mirroring the existing hold treatment. Signed-off-by: Andy Anderson <andy@clubanderson.com> * π images: tolerate ca-certificates packages dropping the withdrawn roots; bump runner gh to 2.102.1 Both breakages post-date the v5 commits this top-up carries and fail every image build on v5 today too: - Debian trixie 20250419+deb13u1 / Alpine ca-certificates-20261020-r0 / Ubuntu noble package refreshes already drop the emSign ECC Root CA - G3 and Comodo AAA Services entries, so the unconditional `sed && grep -q` distrust step in src/Dockerfile, Dockerfile.contributor, Dockerfile.hub, .oss-scanner/Dockerfile and src/deploy/ci-runners/Dockerfile fails the build. Each entry is now rewritten only when present; the final tests still prove the roots are absent from the regenerated bundle. Applied from the in-flight v5 fix #13266 (scanner/fix-hub-ca-bundle) so the next top-up merges cleanly. - cli.github.com's apt repo no longer serves gh 2.102.0 (only 2.102.1), so the CI runner image PR gate failed on `apt-get install gh=2.102.0`. Signed-off-by: Andrew Anderson <andy@clubanderson.com> --------- Signed-off-by: Andrew Anderson <andy@clubanderson.com> Signed-off-by: clubanderson <407614+clubanderson@users.noreply.github.com> Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com> Signed-off-by: Gregory Hunt <greg@on-board.ai> Signed-off-by: Andy Anderson <andy@clubanderson.com> Signed-off-by: hanthor <5840441+hanthor@users.noreply.github.com> Signed-off-by: mendezr <mendezr@users.noreply.github.com> Signed-off-by: hivecommons-hive[bot] <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: clubanderson <407614+clubanderson@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: hivecommons-hive[bot] <280983584+hivecommons-hive[bot]@users.noreply.github.com> Co-authored-by: MikeSpreitzer <14296719+MikeSpreitzer@users.noreply.github.com> Co-authored-by: gregoryhunt <31053269+gregoryhunt@users.noreply.github.com> Co-authored-by: Gregory Hunt <greg@on-board.ai> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: James Reilly <jreilly1821@gmail.com> Co-authored-by: hanthor <5840441+hanthor@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: AN0099 <91515465+AN0099@users.noreply.github.com> Co-authored-by: RaΓΊl MΓ©ndez <18744521+mendezr@users.noreply.github.com> Co-authored-by: mendezr <mendezr@users.noreply.github.com>
Problem
Observed live 2026-10-20 on hivecommons/docs#401: a PR from an untrusted-tier contributor (labels
stage/060-reviewed+contributor-lane:claim-tier-untrusted, never 090/095, no 30-minute soak, configrequire_tiers: merger,trusted,soak 30m) was merged by the hive at 15:27Z via the merge-request relay:Root cause
The relay path (
hive-mergeβStartMergeRequestWatcherβhandleOneMergeRequestβMergePR) gates on: agent authority + merge-eligible.json at the pinned head (bindMergeAuthz/classifyMergeEligibility), write allowlist, repo pause/scope, human-merge paths, and positive CI (which includesmin_head_age). It never evaluated the contributor-lane policy β tier admission withinrequire_tiers, contributor soak, review verdict β thattrySweepContributorLanePRenforces in the auto-merge lane. So any agent's merge request bypassed the lane for a contributor-authored PR.classifyMergeEligibilityalso did not treat a needs-decision park as blocking.Fix
pkg/github/automerge: split the contributor-lane sweep intoevaluateContributorLanePR(all gates, read-only in relay mode) + the merge tail; newEngine.RelayMergeRefusal(ctx, repo, number, expectSHA)runs the same evaluation and returns""(allow), a refusal naming the gate (e.g.contributor-lane:claim-tier-untrusted (author tier "untrusted", require_tiers merger, trusted),contributor-lane:soaking(remaining=27m) (β¦ soak is 30m0s β¦),pending: head pushed β¦ (auto_merge.min_head_age β¦)), or an error (fail closed). App / trusted-bot / trusted-author-role authors keep today's behaviour.pkg/github:MergeRequestPolicyGatehook +SetMergeRequestPolicyGate; the watcher consults it before any branch update, denies terminally (.denied) with the reason in the result the agent reads, auditsmerge_request_refused, and routes gate errors through the bounded retry path.cmd/hive:relayLanePolicyGate(autoMergeOpts)wires the engine's gate intostartRequestRelays(re-armed on every client rebuild by the relay supervisor);classifyMergeEligibilitynow parksstage/085-needs-decision/stage/045-needs-decisionPRs as not eligible.hive-merge.md; changelog fragment.Relay honouring of
hold,sentinel-alert,do-not-merge*,needs-rebaseand needs-decision labels is now pinned by tests on both the eligibility classifier and the lane gate.Tests
pkg/github/automerge:TestRelayMergeRefusalUntrustedTierScannerRequest(the docs#401 reproduction β fails on v5, passes here),TestRelayMergeRefusalSoakAndHeadAge,TestRelayMergeRefusalAllowsWhatTheLaneWouldMerge,TestRelayMergeRefusalHiveAuthoredAndTrustedAuthorsPassThrough,TestRelayMergeRefusalPolicyScope,TestRelayMergeRefusalFailsClosed,TestRelayMergeRefusalTextpkg/github:TestMergeRequestPolicyGateRefusalDeniesAndAudits,TestMergeRequestPolicyGateErrorRetriesWithoutMerging,TestMergeRequestPolicyGateAllowsAndNilGateKeepsBehaviourcmd/hive:TestClassifyMergeEligibility_RelayControlLabels,TestClassifyMergeEligibility_ParkedRedPRStaysFailing,TestNeedsDecisionParkLabel,TestBindMergeAuthz_RefusesParkedHeldAndSentinelTargets,TestRelayLanePolicyGateWiringcd src && go build ./... && go test ./cmd/hive/... ./pkg/github/...passes; coveragepkg/github90.0%,pkg/github/automerge90.7%, new functions 100%.