Skip to content

Commit 9715e04

Browse files
Merge branch 'v6' into feat/v6-agent-github-cap-controls
2 parents f55e50d + 9b37bd0 commit 9715e04

31 files changed

Lines changed: 1576 additions & 36 deletions

‎CHANGELOG.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ Hive did not historically maintain a complete changelog. This file starts a prag
1111

1212
## Unreleased
1313

14+
## 2026-11-09 (v6.4.6)
15+
16+
### Fixed
17+
18+
- **An issue the issue filter keeps off the agent queue no longer asks you to ADMIT it while an open pull request closes it.** The your-turn inbox listed projectbluefin/actions#733, a sec-check finding, as `agent_finding_not_admitted` ("add `triage/accepted`") while sec-check's own fix PR projectbluefin/actions#734, which closes it on merge, was open: the filter's rows carry no linked PRs, so the covered-by-PR rule never saw it. The dashboard now reads the closing references of the repository's open and held PRs it already has (no extra GitHub call) and shows such an issue as waiting on that PR ("Waits on PR #N, which closes it"); the ADMIT ask comes back if the PR closes unmerged.
19+
- The 085 comment on a fork PR parked on a fork-guarded check (such as a fork Canary) now follows the head. On projectbluefin/utah-packages#917 a maintainer's Canary passed on `8d7a655`, the author then rebased the same patch onto a newer `main` (`82ef790`), and the PR stayed at 085 while its comment still asked for a run on an earlier head. The comment is now rewritten in place for each new head while the PR stays parked, and it says that a run on an earlier head does not cover the new one, because a rebase or a merge of the base changes the code the check runs.
20+
- **The red-main sweep stops asking for classic branch protection the App cannot read.** `ReadBranchRules`, which the red-main sweep, the merge lane and the dashboard's merge-lane and ACMM views use for required checks, called `GET /repos/{o}/{r}/branches/{branch}/protection/required_status_checks` on every read. An App without Administration permission gets a 403 there every time, so on a live hive `hive:red_main` spent about 330 REST calls an hour on failures (it sweeps every active repo every 10 minutes). The answer was already being taken from the rulesets endpoint, which stays read every pass. A 403, or a 404 other than "Branch not protected", from classic protection is now remembered per repo and branch for `HIVE_REQUIRED_CHECKS_FORBIDDEN_TTL` (default 1h, the same knob the auto-merge required-checks cache uses) and replayed with the same result, so each repo costs one classic call an hour instead of six. "Branch not protected", 5xx and rate-limit errors are not remembered.
21+
1422
## 2026-11-09 (v6.4.5)
1523

1624
### Fixed

‎changelog.d/fixed-agent-finding-covered-by-pr.md‎

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
- **A per-agent GitHub API hourly cap now applies without the fleet key.** `agents.<name>.github_api_hourly_cap` was read only when `agents.github_api_hourly_cap` was also set, so `agents.reviewer.github_api_hourly_cap: 600` on its own left the reviewer at the default 300. The override now applies on its own, and a replica or review head that has none of its own takes its base agent's. `0` still means no cap at either level. See [Runtime and quota](src/docs/operator-reference/runtime-and-quota.md).
1+
- **A replica takes its base agent's GitHub API hourly cap even before the next reload.** A replica or review head (`reviewer-2`, …) with no `agents.<name>.github_api_hourly_cap` of its own now takes its base agent's override directly, so an override set on the base applies to its replicas at once instead of after the config is next reloaded. The lookup order is the agent's own value, then the base agent's, then `agents.github_api_hourly_cap`, then the default of 300; `0` means no cap at either level. See [Runtime and quota](src/docs/operator-reference/runtime-and-quota.md).
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- **A session recycle no longer leaves Copilot agents on a bare `copilot` that asks approval for every command.** When a restart replaced a Copilot agent's session, a pane-poll tick still running for the old session could read the new, still-empty pane against the old start time, call it hung for hours, and start the hang diagnostic. The diagnostic killed the freshly relaunched session, typed `copilot` with no `--allow-all`, `--model` or deny flags, and returned at once because its context was already cancelled, so the agent ran that CLI until the next restart. On a hosted hive this happened to every Copilot agent at each 6-hour recycle; the architect then sat 4h50m at "Do you want to run this command?". The hang detector now skips a poller whose launch was cancelled, and the diagnostic re-checks under the manager lock before each step that touches the session.

‎changelog.d/fixed-fork-guard-card-new-head.md‎

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- The hive no longer merges `main` into a fork PR parked at 085 on a maintainer-run fork-guarded check (such as a fork Canary) after a restart or a rate-limited pass. The branch-update guard read only an in-memory index that has no entry for the head in those windows, so on projectbluefin/utah-packages#917 the App merged `main` five times in 22 hours and each merge discarded the run the PR was waiting for. When the index has nothing, the guard now falls back to the PR's stage record: it holds the update while a recorded guard check is red on the exact head (or while the head's checks cannot be read), and lets it through once every guarded check is green.

‎changelog.d/fixed-red-main-classic-protection-403.md‎

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- **An agent refused because the hive's shared GitHub API budget is low is now told so, with the reset time, and keeps working.** When the App installation's remaining core budget fell under `github.agent_reserve_floor`, the proxy's 429 and pane nudge said "hourly cap reached" and "stop all GitHub reads for this session", the wording for an agent's own `agents.github_api_hourly_cap`. On knuckle (2026-11-08) sec-check was refused at 379/400 and abandoned its whole audit. The reserve refusal now says the shared budget is low (not the agent's cap), gives the reset time and `Retry-After`, and tells the agent to pause GitHub reads until then and carry on with local work. The cap refusal's wording is unchanged.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- A `requires_human` from a review whose GitHub reads the hive proxy refused (the reviewer hit `agents.github_api_hourly_cap`, or the shared bucket fell below `github.agent_reserve_floor`) is no longer recorded as a verdict, whatever words the reviewer used. The proxy now remembers when it last refused each agent, and the review relay sets aside a `requires_human` with no in-scope finding, no high-risk marker and no already-landed PR when its agent was refused after the perspective was dispatched. The perspective is asked again after `review.pending_ttl`, the same path as the rate-limited "could not read" case. Before, summaries such as "GitHub reads stopped at the user's request after the hourly cap; … could not be verified" or "not assessed: GitHub API cap prevented reading" were not recognised, and projectbluefin/utah-packages#959, projectbluefin/utah#1161 and projectbluefin/finpilot#659 parked at `stage/085-needs-decision` on 2026-11-09. The expiry that follows such a set-aside, or any expiry whose every row went to an agent the proxy refused after the row was sent, no longer spends `review.max_redispatch`: the planner waits for the refusal's `Retry-After` (at most an hour past `pending_ttl`), re-asks, and counts it in the dispatch state's `cap_redispatches[]`, bounded separately at 8 before the usual `review-dispatch-exhausted` hold. Before, a reviewer capped for about 2h15m on one head still ended in that hold and a person was asked.

‎src/cmd/hive/main.go‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4330,6 +4330,9 @@ func (b *boot) bootProxyWith(deps bootProxyDeps) {
43304330
stopWriteCounters := b.githubProxy.StartWriteCounterPersistence(proxy.WriteCountersPath)
43314331
b.preShutdownHooks.add("flush-write-counters", stopWriteCounters)
43324332
b.githubProxy.SetAgentGitHubBudgetConfig(b.cfg.AgentGitHubAPIHourlyCap, b.cfg.GitHubAgentReserveFloor)
4333+
// A review whose reads this proxy refused is no verdict, and its
4334+
// expiry does not spend review.max_redispatch (projectbluefin/utah-packages#959).
4335+
github.SetAgentGitHubRefusalFunc(b.githubProxy.AgentGitHubRefusal)
43334336
if b.agentMgr != nil {
43344337
b.githubProxy.SetAgentGitHubBudgetNudgeFunc(b.agentMgr.SendGitHubAPIBudgetNudge)
43354338
}

0 commit comments

Comments
 (0)