Repository navigation
feat(core): round-robin weights are priority tiers, not shares - #1124
Conversation
In a round-robin node a target's weight now names its priority tier: selection rotates evenly inside the top tier and falls through to the next tier only once every member above it has failed or is unavailable for the dispatch. The tier key is the pre-demotion weight (configured weight after schedules, preferences and learned adjustments). A quota-demoted target sorts below every live tier instead of being smeared into the middle by the 0.01 factor — ordered and weighted modes keep that factor and their ranking unchanged. A nested group tiers by its own weight scaled by its leaves' average pre-demotion weight, and counts as demoted only when every door under it is demoted. Sessions stick within the active tier: a pick made in a lower tier while the top tier was down no longer strands the session there once the tier recovers. Decisions now record each candidate's tier alongside its weights so a tiered choice can be explained after the fact. The routing skill docs describe the new reading of weights. Weighted mode is untouched: it remains the proportional mode for pools that want shares.
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 19 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fcd4b09f3d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // so a recovered tier takes the session back instead of stranding it on the fallback. The | ||
| // draw's weights are the tier keys: equal inside a tier, so the rotation there stays even. | ||
| // Weighted draws keep the whole candidate set and the effective weights, exactly as before. | ||
| const pool = node.selection === "round-robin" ? topTier(positions) : positions |
There was a problem hiding this comment.
Update expected-share reporting for tier-scoped draws
For a healthy round-robin pool with weights [2, 1], draws now always select the first target, but memberOf in packages/core/src/model-route-review.ts still calculates expectedShare from proportional weights across all candidates, reporting 33% for the fallback instead of 0%. This reaches users through route_stats as a share the weight “promised”; moreover, §3.4 of routing-review.md explicitly instructs the reviewing agent to raise weights for these supposedly underused members after 30 draws. Consequently, correctly idle fallback tiers generate misleading diagnostics and recommendations that can undermine the configured priorities. Make the expectation calculation and underuse guidance tier-aware alongside this selection change.
Useful? React with 👍 / 👎.
| const head = tiers[byTier(from)[0]] | ||
| return from.filter((position) => { | ||
| const tier = tiers[position] | ||
| return tier.demoted === head.demoted && tier.weight === head.weight |
There was a problem hiding this comment.
Normalize computed weights before comparing priority tiers
When mathematically equal effective weights reach this comparison through different computations, floating-point rounding can split them into separate tiers and permanently starve one member. For example, an equal-weight round-robin parent containing a three-leaf nested group and a direct leaf, with a global schedule factor of 0.1, gives the group a weight of (0.1 + 0.1 + 0.1) / 3 = 0.10000000000000002 through factor(), versus 0.1 for the direct leaf. The group therefore becomes the sole top-tier candidate, and the direct leaf receives no new sessions while the group is available. Previously that rounding difference had only a negligible effect on proportional rotation. Normalize tier keys or consistently account for rounding in both tier ordering and equality so equivalent computed weights still rotate together.
Useful? React with 👍 / 👎.
Closes #1122.
What changes
In a
round-robinpool,weightsstop being proportional shares and become priority tiers:Tier order interpretation (flagged in #1122)
The ruling said "lowest weight" first, but the fleet's pools already use weight as preference — alternate at 2 over main at 1 so alternate burns first, Go leaves at 3/2 atop luna-plan, the DeepSeek plan pool's weight-100 guard ahead of PAYG. This PR implements higher weight = earlier tier; a literal ascending reading would invert all of those pools. Reversing is the tier comparator and nothing else.
Demotion rule
The tier key is the pre-demotion effective weight (the
tracedWeightOflayers throughadjustment). Quota demotion's 0.01 factor would smear a demoted heavyweight into the middle tiers, so instead:orderedandweightedranking keeps using the final effective weight exactly as today.Per-mode delta
round-robin: tiered, as above. The session draw and sticky honor are scoped to the active tier, and the failover tail is tier-ordered, so one dispatch exhausts a tier before touching the next. Route decisions record each candidate'stiersentry (pre-demotion weight + demoted flag) next to the existingweights/layers.ordered: no change.weighted: no change — it remains the proportional mode (random draw by ratio) for pools that genuinely want shares; the ruling redefines round-robin only.Seam
Tiering lives in
nextTarget's walk, the one place that sees each child's full weight trace and demotion state.selectSessionTargetis unchanged — the walk passes it only the active tier's candidates with the (uniform) tier weight.factor()learned to average theadjustmentlayer for a group's tier key; its default layer is the existing behavior.Tests
New
ModelRoute round-robin tiers (#1122)block inpackages/core/test/model-route.test.ts(9 tests): single-tier even rotation; two-tier strict fall-through (never drawn while a top member is ready; engages when all have failed/left, within a walk and across dispatches); sticky return to a recovered tier; rotation persisting across dispatches; unset weight tiering with weight 1; a demoted weight-100 leaf sorting below live 2/1 tiers and serving last; a nested route reference as a tier member at both weight directions; a fully-demoted group dropping as one demoted member.Typecheck clean; the route family — 11 files (
model-route,-credential,-autonomy,-limits,-schedule,-tuning,-tuning-schedule,model-routes-expand,model-route-stats-tool,model-resolver,location-layer) — 310 pass, 0 fail.Docs
routing-config.mdandrouting-review.mdnow describe weights as ratios inweightedpools and priority tiers inround-robinpools.Known follow-up (not in this PR)
The route review's
expectedShare(§3.4 "underused members") still models round-robin expectation as proportional, so a lower tier's members will read as underused while a higher tier is healthy. Thetiersdata now recorded on decisions is what a tier-aware review needs; flagging here rather than widening this change.Not deployed
This PR does not update the laptop's running server; deploy is a separate step after merge.
Need help on this PR? Tag
@codesmith-botwith what you need.