Repository navigation
Conversation
…er-inference#8541) combo.ts documented the cooldown-aware 429 retry as "available to ALL combo strategies", but the gate feeding it — isComboCooldownWaitEligible() — admits only quota-share and auto. The two statements sit ~1200 lines apart in the same file. Two tests in combo-quota-share-cooldown-wait-timing.test.ts had been rewritten to match the comment, so they asserted behavior no code path could produce and were red on the base branch. Resolved toward the NARROW contract (comments + tests follow the gate), because three sources already agree with it and only the prose disagreed: - comboConfig.ts:52 — the predicate itself - tests/unit/combo-config.test.ts:328 — asserts priority/fill-first are NOT eligible, with its own cheaper-inference#7360 rationale - src/lib/resilience/settings.ts:99 — "quota-share and auto combos, and only for transient (non quota_exhausted) reasons" Widening instead would not have been a comment fix: the same predicate raises the per-target timeout floor via resolveComboTargetTimeoutMsForCombo, so it would also lift the default per-target timeout from 120s to 150s for every strategy, and would require deleting the combo-config.test.ts assertions above. That is a deliberate feature change, not base-red cleanup. Changes: - combo.ts: correct the two scope comments. Comment-only — no non-comment line is touched, and the file stays at exactly 3640 lines so the frozen file-size baseline is unaffected. - timing test "short 429 cooldown": assert priority propagates the 429 without redispatching. The stubbed 2nd dispatch still returns 200, so asserting 429 is positive proof no wait fired, not merely an absence check. - timing test "quota_exhausted lock": moved from priority to quota-share and the model order flipped. On a non-eligible strategy the branch it guards never opens, so it was asserting against unreachable code. The flip is required because cheaper-inference#8508 (3070925) made lastStatus last-write-wins so status and message always come from the same target — with the 403 target last the response crystallizes 403 and the `status === 429` guard never opens. Putting the 429 target last makes the allow-list the thing actually under test. Verified the rewritten quota_exhausted test is non-vacuous with a positive control: swapping the lock reason to rate_limit (both targets 429, errorCodes [429]) turns the same shape into 12 upstream dispatches instead of 2. Local: timing file 4/4 green on 3 consecutive runs; combo-config 44/44 unchanged; combo-cooldown-retry + cooldown-aware-retry-budget + resilience-settings-combo-cooldown-wait + quota-share-strategy + chat-cooldown-aware-retry 77/77; 8486 regression guard green. typecheck, lint, check:file-size, check:known-symbols clean. Complexity 2169/956 — identical to the base, so the ratchet red is the pre-existing base-red tracked by cheaper-inference#8580.
Repositioning this PR: it is not an alternative to #8559I opened this without noticing that @DinonowDev had already sent #8559 for the same issue, five hours earlier. My mistake — I searched the issue tracker for #8541 and never searched open PRs. #8559 is the better piece of work on its own terms: it carries the gate, the settings type, the ResilienceTab UI, i18n and I framed #8541 as an either/or (widen the gate vs narrow the contract). That framing was wrong. These two PRs are not competing answers to one question — they are two different kinds of change that happen to touch the same lines:
The base-red is blocking #8548, #8580, #8582 and #8592 now; whether cooldown-wait should generalize to all strategies is a deliberate product decision. Bundling them means the second decision inherits the first one's time pressure. Suggested sequencingNothing here rejects #8559's direction. If the generalization is what the project wants, this PR costs it only a few comment lines and two test assertions to re-flip on rebase. The reverse order puts an on-by-default routing change onto the release branch as a side effect of a red-CI cleanup. If the maintainers would rather take #8559 first and have it absorb the base-red, I'll close this — say the word and it's gone, no attachment. One practical note on #8559, offered as helpIts check rollup is 3 entries — For reference, this PR's own red is |
|
Closing as superseded by #8559 (option A), not option B. Why this PR cannot land#8541 left two resolutions open:
#8559 merged at
Salvage: noneThe quota_exhausted / model-order concern this PR fixed by switching to No further rebase planned. |
Closes #8541.
The contradiction
combo.tsdocumented the cooldown-aware 429 retry as available to every combo strategy; the gate that reaches it admits only two. The statements sit ~1200 lines apart in the same file.combo.ts:2717commentcombo.ts:2719commentcomboConfig.ts:52quota-shareorautoonlyTwo tests in
tests/unit/serial/combo-quota-share-cooldown-wait-timing.test.tshad been rewritten to match the comment, so they asserted behavior no code path could produce. They are red on the base branch and surface onUnit Tests fast-path, making every PR→release/**that selects them red.Which side won, and why
#8541 left A (widen the gate) vs B (narrow the contract) open. B. The issue framed this as "comments + test vs implementation", but it is actually test vs test — a third source already asserts the narrow contract directly, and a fourth documents it:
So three sources agree with the gate and only the prose disagreed.
Widening would also not have been a comment fix.
resolveComboTargetTimeoutMsForCombouses the same predicate to raise the per-target timeout floor, so option A would lift the default per-target timeout from 120s to 150s for every strategy, and require deleting the assertions above. That is a deliberate feature change; if the generalization is still wanted it belongs in its own PR, not in base-red cleanup.Changes
open-sse/services/combo.ts— correct the two scope comments.Comment-only:
git difffiltered to non-comment lines is empty. The file stays at exactly 3640 lines, so the frozen file-size baseline is untouched (an earlier, wordier draft pushed it to 3651 > 3642 and was tightened rather than rebaselined — this file is mid-decomposition under #3501 and should not grow).Timing test — "short 429 cooldown" — assert
prioritypropagates the 429 without redispatching.The stub still returns 200 on a hypothetical 2nd dispatch, so asserting 429 is positive proof that no wait fired, not merely an absence check.
Timing test — "quota_exhausted lock" — moved from
prioritytoquota-share, model order flipped.Two separate defects, neither covered by #8541:
priorityit was asserting against unreachable code — vacuous regardless of A or B.30709255c)lastStatusis last-write-wins, so the surfaced status and message always come from the same target. The branch requiresstatus === 429; with the 403 target dispatched last, the response crystallizes 403 and the wait is never even considered. That is why this test reports403 !== 429— a precondition failure, so its actual subject never ran. Putting the 429 target last makes the allow-list the thing genuinely under test.Non-vacuousness
The rewritten quota_exhausted test was checked against a positive control before being trusted: swap the lock reason to
rate_limit(both targets 429,errorCodes: [429]) and the same shape waits and re-dispatches to 12 upstream calls instead of 2. So the 2 asserted calls are barrier 1 (the allow-list) doing its job, not an absence of wait machinery.Verification
combo-quota-share-cooldown-wait-timing.test.tscombo-config.test.tscombo-cooldown-retry+cooldown-aware-retry-budget+resilience-settings-combo-cooldown-wait+quota-share-strategy+chat-cooldown-aware-retrycombo-antigravity-missing-project-reset-8486.test.tsnpm run typecheck:corenpm run lintnpm run check:file-sizenpm run check:known-symbolsnpm run check:complexity-ratchetsBase
Branched off
4053e2314rather than therelease/v3.8.49tip, matching the other in-flight combo PRs.check:complexity-ratchetsreports 2169/956 vs frozen 2130/951 — byte-identical to the base, so this PR contributes zero. That is the pre-existing base-red owned by #8580.Fast Quality Gateswill stay red until #8580 merges; see #8542 for why the fail-fast ordering means a later gate cannot demonstrate its own fix.Scope note
This closes the
Unit Tests fast-pathhalf of the base-red. It does not touchisComboCooldownWaitEligible— no runtime behavior changes in this PR.