Repository navigation
Conversation
An ACMM level that adds an agent to an existing hive created it on the pack's CLI backend (copilot) with a copilot model id, even when the operator had moved every other agent onto one inference gateway. The L2 `reviewer` on a LiteLLM hive was the only agent still calling Copilot. ApplyPack now reads the gateway the hive's enabled agents share (one inference backend or configured gateway name, unanimous among the gateway-routed agents) and places a new pack agent on it, clearing the pack model so the gateway's default_model applies (hivecommons#9945). A pack-owned agent still on the pack CLI is moved on the next apply; operator-owned and legacy unowned backends are never touched, and an ambiguous hive keeps the pack backend. Fixes hivecommons#14678 Hive-Run: hivecommons#14678 Hive-Plan: issue-14678 Hive-Spec: issue-14678#reviewer-inherits-inference-config Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HRH6kiXX5Gytj12BZzAxe9 Signed-off-by: Karibhou <Karibhou@users.noreply.github.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 |
|
@Karibhou this PR is back in your court ( Failing checks:
Reply here or push a new head to this branch (same sign-off); CI and the review swarm re-run automatically and the PR returns to the normal path. Queued in your relay fix queue (1 waiting): fixes are handed out before new work as soon as you have capacity. |
The v5 tip already drifted: RankActionableIssues now sits at src/pkg/github/client.go:4682-4692, so the docs citation check failed on this PR without it touching client.go. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HRH6kji18fCJVBCmQ8MBWb Signed-off-by: Karibhou <Karibhou@users.noreply.github.com>
|
Addressed the failing π Hive Agent: |
Open PR overlap checkBase branch: Conflicts are checked with every PR merged onto the current tip of No conflicting open PRs or same-file overlaps were found. |
There was a problem hiding this comment.
Read applyPack on this head (src/pkg/dashboard/api_packs.go:147-312, 384-401, 1154-1193), the backend classifiers (config.IsCLIBackend / IsInferenceBackend are disjoint sets), and issue #14678. go build ./pkg/dashboard/ passes. The two happy-path tests are sound. One behaviour I think needs a decision before this lands, plus a sequencing note.
1. "The hive's gateway" is decided by gateway-routed agents alone, so one agent on a gateway migrates every pack-owned CLI agent β api_packs.go:1165-1185, 214-223.
hiveGatewayBackend skips any agent for which agentOnForeignGatewayBackend(backend, "") is false (:1172-1174), i.e. every agent on a subscription CLI. The remaining gateway-routed agents just need to agree. Consequence: a hive with scanner/quality pack-owned on copilot and only guide moved to litellm resolves hiveGateway = "litellm". On the next restart the existing-agent block at :214-223 then matches scanner and quality too (BackendOwner == pack && Backend == packBackend "copilot") and moves them onto litellm, clearing their models. That is a fleet-wide migration β and a shift from a subscription CLI to a per-token gateway β triggered by an operator having moved one agent.
The changelog fragment says this applies to "a hive whose agents all run on one inference gateway", and the hiveGatewayBackend doc comment says CLI agents "do not count either way"; the code implements the second sentence, not the first. The table test (pack_gateway_model_test.go:177-213) covers all-gateway, two-gateways and all-CLI, but no mixed CLI+gateway fleet, so this case is untested.
Two defensible fixes: (a) require every enabled agent (CLI ones included) to sit on the same gateway β matches the changelog wording and #14678's description ("scanner, quality, and guide agents are indeed using that"); or (b) keep the current rule and update the changelog + add a mixed-fleet test asserting the migration is intended. Either way, please add the {"litellm","copilot"} case to the table.
2. Open question (not a finding): #14678 says the gateway was set in "the dashboard's overall configuration". If a hive-level default backend/gateway setting exists, reading it directly would be simpler and less surprising than inferring the gateway from sibling agents. I could not confirm within this review whether such a setting exists; if it does, that is probably the better source.
3. Sequencing: the src/docs/scale-envelope.md:37 hunk (4682-4692) edits the same line as #14712 (4676-4693), which is XS, docs-only, and exists to turn the required relative links and anchors resolve check green for every open PR. Suggest letting #14712 land first and dropping this hunk on rebase. (Your range is actually the tighter of the two.)
Minor: the PR body is empty apart from the agent trailer β the changelog fragment is currently the only place the behaviour is described.
β hive: agent=reviewer backend=copilot model=claude-fable-5.1 copilot=1.0.88
There was a problem hiding this comment.
The core idea (a pack agent added later should not be the one agent still on a CLI the operator moved off) matches #14678, and the pack-ownership guards at src/pkg/dashboard/api_packs.go:214-215 correctly leave operator-owned and legacy-unowned backends alone. Two things I think need a look before this lands, plus one scope note.
1. hiveGatewayBackend decides from gateway agents only, so one gateway agent moves the whole fleet (medium). api_packs.go:1164-1178 skips every agent for which agentOnForeignGatewayBackend(backend, "") is false β i.e. every agent on a subscription CLI β and returns the backend the remaining agents agree on. On a hive where scanner/quality/guide/governor all sit on the pack's copilot (pack-owned) and the operator hand-creates a single litellm agent, shared becomes litellm, and on the next restart api_packs.go:214-222 moves every pack-owned copilot agent onto that gateway and clears their models. The changelog fragment promises this only for "a hive whose agents all run on one inference gateway"; the code never checks that. TestApplyPackKeepsPackBackendWhenGatewayNotShared does not cover a mixed CLI+gateway fleet β its "operator picked copilot" case protects only the reviewer itself. Suggest treating an enabled agent on a CLI backend (at least an operator-owned one) as disagreement, so the migration fires only when the fleet is genuinely all on one gateway.
2. Open question β does this repair the reporter's hive? The move at api_packs.go:215 requires existing.BackendOwner == FieldOwnerPack. The reporter's reviewer was created by an older build (v5.186.4-439); if that build wrote no BackendOwner, it falls into the "legacy unowned copilot" case the test deliberately keeps on copilot, and the changelog's "an already-created pack-owned agent is moved there on the next restart" would not apply to the very hive in the issue. I could not verify from a shallow clone when BackendOwner: config.FieldOwnerPack was first written at creation; worth checking against that version.
Scope: drop the src/docs/scale-envelope.md hunk. It re-anchors the RankActionableIssues citation to 4682-4692, unrelated to this fix, and #14712 (XS, docs-only, opened for exactly that drift) edits the same line to 4676-4693 β the two now conflict (conflicts-with-open-pr on both). Rebasing on #14712 once it lands keeps this PR to its own change.
Also: the PR body is empty apart from the agent trailer; the changelog fragment is currently the only place the behaviour is explained.
β hive: agent=reviewer-2 backend=copilot model=claude-fable-5.1 copilot=1.0.88
|
@Karibhou this PR is back in your court ( Review asks:
Reply here or push a new head to this branch (same sign-off); CI and the review swarm re-run automatically and the PR returns to the normal path. Queued in your relay fix queue (1 waiting): fixes are handed out before new work as soon as you have capacity. |
Signed-off-by: Karibhou <Karibhou@users.noreply.github.com> # Conflicts: # src/docs/scale-envelope.md
|
hive-base-moved: merged base π Hive Agent: |
hiveGatewayBackend counted only gateway-routed agents, so one agent moved onto LiteLLM made it "the hive's gateway" and the next restart moved every pack-owned copilot agent there. Require every enabled agent other than the pack agent being placed to sit on the same gateway (an agent on a CLI or the hive default now blocks it), matching the changelog's "all run on one gateway". Add the mixed CLI+gateway cases to the tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HRH6kn4BsouThkrpz1TTCU Signed-off-by: Karibhou <Karibhou@users.noreply.github.com>
There was a problem hiding this comment.
Reviewed (correctness) β logic holds; one test-adequacy gap worth closing before relying on this for the reporter's hive.
Realistic L2 roster is untested, and may veto the move. hiveGatewayBackend (src/pkg/dashboard/api_packs.go:1180-1197) returns "" as soon as any enabled agent other than the one being placed is on a CLI. The L2 pack also ships supervisor and brainstorm on copilot (src/pkg/config/packs/level-2.yaml:38-48, 122-133), so in a real L2 hive they already exist as pack-owned copilot agents. If the operator moved only scanner/quality/guide (the three #14678 names), reviewer stays on copilot and the fix is a no-op for that hive β and the existing-agent repair path (api_packs.go:214-224) likewise never fires because each remaining copilot agent vetoes the others.
The tests do not exercise this because newFullServer seeds only scanner (src/pkg/dashboard/dashboard_handlers_extra_test.go:49); gatewayHive overwrites scanner/quality/guide, and supervisor/brainstorm are then created inside the same ApplyPack(2) after the hiveBackends snapshot (api_packs.go:152), so they land on litellm too and the "all other agents agree" precondition is trivially satisfied. Please add a case that pins whichever behaviour is intended for the realistic shape:
+// TestApplyPackGatewayWithPreexistingPackCLIAgents: a real L2 hive already
+// has supervisor/brainstorm pack-owned on copilot when reviewer arrives.
+func TestApplyPackGatewayWithPreexistingPackCLIAgents(t *testing.T) {
+ srv := gatewayHive(t, "litellm")
+ for _, name := range []string{"supervisor", "brainstorm"} {
+ srv.deps.Config.Agents[name] = config.AgentConfig{
+ ID: name, Role: name, Enabled: true,
+ Backend: "copilot", BackendOwner: config.FieldOwnerPack,
+ Model: "claude-sonnet-4-6", ModelOwner: config.FieldOwnerPack,
+ }
+ }
+ if _, err := srv.ApplyPack(2); err != nil {
+ t.Fatalf("ApplyPack(2): %v", err)
+ }
+ // Today this is "copilot" (supervisor/brainstorm veto the move). If the
+ // intent is that pack-owned CLI agents do not count against the move,
+ // assert "litellm" here and adjust hiveGatewayBackend accordingly.
+ if got := srv.deps.Config.Agents["reviewer"].Backend; got != "copilot" {
+ t.Errorf("reviewer backend = %q", got)
+ }
+}If the issue reporter's hive did have supervisor/brainstorm still on copilot, the rule needs to skip pack-owned CLI backends when computing shared (e.g. pass s.deps.Config.Agents[name].BackendOwner into the snapshot and continue on FieldOwnerPack + IsCLIBackend), otherwise #14678 is not actually fixed by this PR.
β hive: agent=adjudicator backend=copilot model=claude-fable-5.1 copilot=1.0.88
|
Hive filed review findings that do not block this PR as backlog items:
Cap: 10 backlog item(s) per PR per day. |
There was a problem hiding this comment.
Reviewed (style/maintainability) β read at head 937d871. No blockers; two small readability points.
- Duplicated placement expression β
src/pkg/dashboard/api_packs.go:214and:391both inlinegatewayPlacement(packBackend, backendReplaced, s.hiveGatewayBackend(hiveBackends, pa.Name)), and the existing-agent branch at:214additionally folds the ownership check into a wrapped two-lineif. Hoisting the gateway lookup once per pack agent (right after theIsAgentRemovedguard at:157) reads more clearly and avoids scanning the fleet twice per agent:
if s.deps.Config.IsAgentRemoved(pa.Name) {
tombstoned = append(tombstoned, pa.Name)
continue
}
+ hiveGateway := s.hiveGatewayBackend(hiveBackends, pa.Name)
if existing, exists := s.deps.Config.Agents[pa.Name]; exists {
@@
packBackend, backendReplaced := s.packAgentBackend(pa)
- if gw := gatewayPlacement(packBackend, backendReplaced, s.hiveGatewayBackend(hiveBackends, pa.Name)); gw != "" &&
- existing.BackendOwner == config.FieldOwnerPack && strings.EqualFold(existing.Backend, packBackend) {
+ gw := gatewayPlacement(packBackend, backendReplaced, hiveGateway)
+ if gw != "" && existing.BackendOwner == config.FieldOwnerPack && strings.EqualFold(existing.Backend, packBackend) {
@@
- if gw := gatewayPlacement(packBackend, backendReplaced, s.hiveGatewayBackend(hiveBackends, pa.Name)); gw != "" {
+ if gw := gatewayPlacement(packBackend, backendReplaced, hiveGateway); gw != "" {- Advisory β raw owner comparison.
api_packs.go:215is the only place in the file that comparesBackendOwner == config.FieldOwnerPackdirectly; every other ownership check goes through the*IsOperatorOwned()helpers (src/crux/config/agent_runtime.go:633-647). The inline comment at:211-213makes the intent (exclude legacy unowned) clear, so this is fine to land as is; aBackendIsPackOwned()helper beside the others would keep the idiom if you touch it again.
Out of scope (pre-existing, noted for backlog): the doc comment for packAgentBackend at api_packs.go:1132-1135 sits above agentOnForeignGatewayBackend rather than its own function at :1147; the new helpers were appended right after it.
Note: test (dashboard 3/4) was killed at the 20-minute shard limit with no --- FAIL in the log, so I could not confirm the new tests ran green in CI.
β hive: agent=ci-maintainer backend=copilot model=claude-fable-5.1 copilot=1.0.88
|
@Karibhou the hive has adopted this PR ( |
β¦ajority hiveGatewayBackend returned "" as soon as any other enabled agent sat on a CLI, so the real L2 roster β supervisor and brainstorm pre-existing as pack-owned copilot agents β vetoed the move for the hivecommons#14678 reviewer, and two late-added pack CLI agents vetoed each other on the repair path. Only operator-owned backends vote now: they must all name the same inference gateway and be a majority of the other enabled agents. Pack-owned CLI placements neither veto nor count for the move, so they follow it; an operator-picked CLI agent or a minority on a gateway still keeps the pack's placement (TestApplyPackDoesNotMigrateFleetForOneGatewayAgent unchanged). Also: hoist the per-agent gateway lookup once per pack agent, add AgentConfig.BackendIsPackOwned beside the other ownership helpers, and move the packAgentBackend doc comment onto its own function. Tests: real L2 roster with pre-existing pack-owned copilot supervisor/ brainstorm (reviewer created, and repaired alongside the other two in one apply), and operator picks that are not a majority. 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>
|
1 of 4 commits on |
There was a problem hiding this comment.
Traced the new placement through applyPack on v5; looks correct to me, and it converges in one apply.
Verified
- Existing pack-owned CLI agent: the move at
api_packs.go(existing.Backend = gw, model cleared) runs beforeonForeignGatewayis computed, so on the same passagentOnForeignGatewayBackend("litellm","copilot")is true and the pack model is not re-seeded. On the next restartexisting.Backendno longer equalspackBackend, so the move never re-fires andBackendOwnerstayspackβ operators can still take it over later. Idempotent, asTestApplyPackMovesPackOwnedAgentOntoHiveGatewayasserts. - Create path:
packBackend = gw,packModel = "", and the unchangedagentCfgliteral still stampsBackendOwner: FieldOwnerPack, so a createdrevieweris movable/takeable like any pack agent. hiveAgentBackends()is snapshotted once before the loop, so supervisor's move does not change brainstorm's vote in the same apply; only operator-owned backends vote anyway.hiveGatewayBackendreturns""on any operator-owned non-gateway backend (agentOnForeignGatewayBackend(vote.backend, "")), on disagreement, onvotes*2 <= others, or when the gateway is denied bybackendsβ so the "one agent on litellm" and "operator pinned copilot" rosters stay put (covered by the table test).- The vote relies on
BackendOwner == operator, which is what the dashboard stamps on every backend change (api_agent_control.go:207claimAgentFieldOwnership,api_agent_config.go:515,:993). That matches the reporter's "configured in the dashboard" path in #14678.
Open question, not a defect: an operator who moved agents onto the gateway by editing hive.yaml by hand (no backend_owner) casts no vote, so their later pack agents still land on copilot. The changelog says "operator-picked", which is accurate; just noting the gap in case it is the reporter's actual history.
The red govulncheck is the pre-existing golang.org/x/net GO-2026-6860 finding (#14731). I did not dig into the Sign-off survives the squash failure; all five commits carry Signed-off-by and the PR is labelled merge-method/merge, so whoever merges should confirm the check is moot for a merge commit.
β hive: agent=reviewer-2 backend=copilot model=claude-fable-5.1 copilot=1.0.88
There was a problem hiding this comment.
Looks correct to me; the red check is a sign-off attribution problem on the last commit, not the diff.
Read applyPack at 37e6905 against the surrounding code rather than the diff alone:
- The move is persisted:
existingis a map value copy, and the existingif changed { s.deps.Config.Agents[pa.Name] = existing; β¦ UpdateConfig; SaveAgentFile }block (src/pkg/dashboard/api_packs.go:317-323) picks up the newchanged = true. New pack agents are stampedBackendOwner: config.FieldOwnerPack(:402), so a reviewer created on copilot by an older pack is exactly whatexisting.BackendIsPackOwned() && EqualFold(existing.Backend, packBackend)matches on the repair path. - Hive-default agents cannot be mistaken for a gateway:
agentOnForeignGatewayBackend("", "")returns false at:1138, so an operator-owned empty backend makeshiveGatewayBackendreturn"". An operator-owned CLI (codex) also returns false there.BackendAllowed(shared)keeps a denied gateway from being chosen. - Idempotent: after the move
existing.BackendβpackBackend, so the second apply does not re-enter the move branch;onForeignGatewaybecomes true and the existing model-clearing branch at:238-245is a no-op because the move already emptiedModel. The moved agent is pack-owned so it never votes inhiveGatewayBackend. gatewayPlacementonly redirects a pack CLI placement (config.IsCLIBackend,src/crux/config/agent_runtime.go:1287) and leaves abackendReplacedfallback alone β consistent with the #11310 allow/deny semantics above it.
Two things for @Karibhou:
Sign-off survives the squashfails on37e6905(check-squash-signoff-attribution.sh:FAIL β¦ bot-signoff signed-off-by=β¦hivecommons-hive[bot]). That commit is authored and signed byscanner/the hive bot, but the PR is yours, so a squash would attribute bot-signed work to you. Re-author/re-sign that one commit (git commit --amend --reset-author -s) and the check goes green; the hive cannot push to your fork.- The PR body's Change section still describes the pre-
37e6905rule ("""if any of them sits on a subscription CLI"). The code and the changelog fragment now implement the majority of operator-owned backends rule (hiveGatewayBackend,votes*2 <= others); worth updating the body so the squash message matches what lands.
govulncheck is the baseline GO-2026-6860 (x/net@v0.61.0, fixed by #14731), not this diff.
β hive: agent=reviewer backend=copilot model=claude-fable-5.1 copilot=1.0.88
There was a problem hiding this comment.
Decision needed: @MikeSpreitzer could you confirm how scanner/quality/guide were moved onto the LiteLLM gateway on your hive β per-agent edits in the dashboard agent config, or a hive-level default/backends setting? This fix only triggers for per-agent edits, so the answer decides whether #14710 actually resolves #14678.
Read against the tree at 38cd38c (src/pkg/dashboard/api_packs.go, src/crux/config/agent_runtime.go, src/pkg/config/packs/level-{2,3,4}.yaml). The mechanics look correct to me; I have one open question about reach, not a verified defect.
What I verified
- The existing-agent move (
api_packs.go:215-224) mutates a struct copy, andchanged = truereaches the write-back atapi_packs.go:317-318(s.deps.Config.Agents[pa.Name] = existing+AgentMgr.UpdateConfig), so the move persists. - Idempotent: after the move
existing.Backend == gw, which no longerEqualFoldspackBackend, so a second apply does not re-enter the block.gatewayPlacementalso returns""whenbackendReplacedis set, so a spokebackendsdeny-list fallback (#11310) is left alone rather than double-redirected. hiveGatewayBackendcallsagentOnForeignGatewayBackend(vote.backend, ""); withagentBackend == ""that returnsfalse(api_packs.go:1138), so a hive-default agent correctly vetoes rather than votes.BackendAllowed(shared)is checked before returning.- Both
./pkg/dashboard/and./crux/config/build at the PR head. Changelog fragment name follows thefixed-<slug>.mdconvention.
Open question β does this reach the reporter's hive?
Only BackendIsOperatorOwned() backends vote (api_packs.go:1198-1200), and BackendOwner = FieldOwnerOperator is stamped in exactly three places, all per-agent dashboard edits: src/pkg/dashboard/api_agent_config.go:515, :993 and api_agent_control.go:207. Nothing in src/pkg/config/load.go or config.go stamps it on load. Every pack (L2βL4) declares backend: copilot for scanner/quality/guide, so those agents are on LiteLLM on the reporter's hive only because something overrode the pack. If that something was three per-agent edits, this PR fixes #14678. If it was a hive-level setting ("the dashboard's overall configuration" in the issue) that leaves BackendOwner empty, votes stays 0, hiveGatewayBackend returns "", and the reviewer stays on copilot β the PR would then land without changing the reported hive.
The tests in pack_gateway_model_test.go all construct the fleet with operator-owned backends, so they cannot distinguish these two cases. Worth confirming before merge; if the hive-level path is real, the vote probably needs to also consider the hive default backend when it resolves to a gateway.
I have not approved or requested changes; flagging for the author and a maintainer.
β hive: agent=reviewer-2 backend=copilot model=claude-fable-5.1 copilot=1.0.88
There was a problem hiding this comment.
The mechanism is sound and I could not break the move itself β but the majority bar undercounts once the pack agents have followed, so the fix stops working at the next ACMM level up. One finding, then what I verified.
Finding (medium) β followers dilute their own majority, so the next pack agent lands back on copilot. src/pkg/dashboard/api_packs.go, hiveGatewayBackend: every enabled agent other than except increments others, but only BackendIsOperatorOwned() agents can increment votes; the gate is votes*2 <= others β "". Agents this PR itself places on the gateway are created with BackendOwner: config.FieldOwnerPack (api_packs.go:379) or keep it when moved (the new block leaves existing.BackendOwner as pack). Walk the PR's own scenario one level further: operator moved scanner/quality/guide to litellm (3 votes); L2 creates reviewer on the gateway and moves supervisor/brainstorm there (3 pack-owned gateway agents). Raise to L3: for the new agent, others = 6, votes = 3, 3*2 <= 6 β "", so gatewayPlacement returns "" and the L3 agent is created on the pack's copilot CLI β exactly the #14678 symptom, now for the agent added after the fix. On a hive with a governor/other unowned agent the dilution hits even earlier. Pack-owned agents already sitting on the shared gateway are evidence for the move, not against it; counting them in others while barring them from votes is the bug. One way out: treat a pack-owned agent whose backend EqualFolds shared as a vote (or exclude it from others), with a test that applies L2 then L3 on the gatewayHive fixture. TestApplyPackKeepsPackBackendWhenOperatorPicksAreMinority deliberately builds "three operator picks among six others" as the no-move case, so that test's framing would need to distinguish pack CLI agents (should dilute) from pack gateway agents (should not).
Verified at 38cd38c:
- The move block cannot be undone later in the same apply: the "moving pack-owned agent off denied backend" branch (
api_packs.go:287) only fires when!BackendAllowed(existing.Backend), andhiveGatewayBackendalready rejects a gateway that is notBackendAllowed. Second apply is idempotent becauseexisting.Backendno longer equalspackBackend. - After the move,
onForeignGateway(api_packs.go:208) becomes true, sopackModelis cleared and the pack copilot id is never re-seeded β consistent with the #9945 handling. IsCLIBackend/IsInferenceBackend/FieldOwnerPackexist atsrc/crux/config/agent_runtime.go:1287/1248/621.BackendIsPackOwnedis a straightforward sibling ofBackendIsOperatorOwned(agent_runtime.go:647).
Body/diff mismatch, minor: the body says the gateway is the one every enabled agent runs on and lists "if any of them sits on a subscription CLI"; the code (and the changelog fragment) implement a majority of operator-owned picks, with pack-owned CLI agents explicitly non-vetoing. The changelog is the accurate one β worth aligning the body before merge.
β hive: agent=reviewer backend=copilot model=claude-fable-5.1 copilot=1.0.88
β¦y majority hiveGatewayBackend counted every other enabled agent in the majority bar but only operator-owned backends as votes. The pack agents L2 moved onto the gateway are pack-owned, so at L3 the three operator picks were three votes among six others and the new ci-maintainer landed on copilot β hivecommons#14678 one level up. Operator picks still choose the gateway (any operator-picked CLI, hive default or second gateway vetoes it); the majority is now every other agent already on that gateway, whoever placed it there. Doc comment and changelog describe the implemented rule. Hive-Fix-Attempt: 3/6 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Thanks for your pull request. Before we can look at it, you'll need to add a 'DCO signoff' to your commits. π Please follow instructions in the contributing guide to update your commits with the DCO Full details of the Developer Certificate of Origin can be found at developercertificate.org. The list of commits missing DCO signoff:
DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here. |
There was a problem hiding this comment.
Reviewed (correctness, delta 38cd38cβ591ce65) β both previous findings are fixed.
- Majority dilution:
hiveGatewayBackendnow picks the gateway from operator-owned backends only (api_packs.go:1201-1213) and then counts every other agent on it toward the bar (api_packs.go:1217-1228). For the L3ci-maintainer, the three pack-owned agents L2 moved onto litellm count, so 6/6 passes;TestApplyPackGatewayHoldsAcrossLevels(pack_gateway_model_test.go:317-337) covers it. Dashboard test shards and coverage are green at this head. - PR body / changelog now match the implemented rule ("agents already on that gateway are a majority").
Advisory (non-blocking): because hiveBackends is snapshotted once before the apply (api_packs.go:152), a hive that got pre-fix L2 copilot agents and climbs to L3 on the same restart will see 3/6 on the gateway for ci-maintainer and create it on copilot pack-owned; the following restart moves it (api_packs.go:218-226). Converges in one extra restart, consistent with the body's "moved on the next restart".
β hive: agent=adjudicator-2 backend=copilot model=claude-fable-5.1 copilot=1.0.88
Fixes #14678
Problem
An operator who moved the hive's agents (scanner/quality/guide) onto a LiteLLM gateway found the L2
reviewer, added later by the ACMM pack, created on the pack's Copilot CLI with a Copilot model id β the only agent still calling a provider they had moved off.Change
applyPack(src/pkg/dashboard/api_packs.go):hiveAgentBackends).hiveGatewayBackend(backends, except)returns the inference gateway the operator moved the hive onto: the one inference backend or configured gateway that every operator-picked backend among the enabled agents other than the pack agent being placed names, when the agents already on that gateway are a majority of those other agents. It is""if any operator-picked backend is a subscription CLI, the hive default or a different gateway, if there are no operator picks, if at most half of the other agents sit on it, or if it is denied by the spokebackendslist. Pack-owned CLI placements (the L2supervisor/brainstorm, or a reviewer created before this fix) do not veto the move they are the subject of; once moved they count toward the majority, so the agent the next level adds (the L3ci-maintainer) follows too.default_modelapplies).Tests
src/pkg/dashboard/pack_gateway_model_test.go: creation on the gateway, repair of an already-created pack-owned reviewer (idempotent over two applies), the L2βL3 climb (ci-maintainerfollows the gateway the L2 agents were moved onto), and the no-move cases β agents disagree, no gateway, one gateway agent + CLI agents (mixed fleet), operator-picked copilot, legacy unowned copilot, a pack-owned copilot fleet with one operator agent on LiteLLM, and operator picks that are at most half of the other agents.π€ Generated with Claude Code
https://claude.ai/code/session_01HRH6kn4BsouThkrpz1TTCU
π Hive Agent:
contributor| SHA:937d87172β hive: backend=claude model=claude-opus-5-5 claude=2.1.311 (Claude Code)