From 76d825ce76ba77d7e3e2031da1b326df4f3339b2 Mon Sep 17 00:00:00 2001 From: backryun Date: Wed, 12 Aug 2026 18:17:17 -0300 Subject: [PATCH] =?UTF-8?q?fix(ci):=20base-reds=20round=203b=20=E2=80=94?= =?UTF-8?q?=20stale=20sibling=20tests=20+=20mode-pack=20weight=20contract?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - check-docs-counts-sync.test.ts: drop the imports/subtests of the four helpers #10196 removed from the gate script (readMcpFactsFromSource, listLocalizedDocs, makeRequiredCountsValidator, checkFreeTierInventory) — the new-API tests that #10196 added stay; the file now loads again under the node runner - quota-connection-recovery.test.ts: convert from vitest APIs to node:test — the file lives in tests/unit/*.test.ts (node-runner glob) and the vitest runtime crashes when imported outside vitest, killing the whole shard entry - modePacks.ts: re-normalize all six mode packs to sum 1.0 — #8940 added sessionAvailability: 0.05 to every pack without rebalancing (1.05 total); ratios preserved exactly (÷1.05), so post-normalizeScoringWeights behavior is unchanged; restores the declared sum-to-1.0 contract the 4235 test pins Refs #9985 --- open-sse/services/autoCombo/modePacks.ts | 123 ++++++++++--------- tests/unit/check-docs-counts-sync.test.ts | 51 -------- tests/unit/quota-connection-recovery.test.ts | 25 ++-- 3 files changed, 76 insertions(+), 123 deletions(-) diff --git a/open-sse/services/autoCombo/modePacks.ts b/open-sse/services/autoCombo/modePacks.ts index 5c0bfd54cc..267dfceeec 100644 --- a/open-sse/services/autoCombo/modePacks.ts +++ b/open-sse/services/autoCombo/modePacks.ts @@ -14,84 +14,85 @@ export const MODE_PACKS: Record = { // Prioritize latency → health. tierPriority replaces 0.05 from stability. // tierAffinity/specificityMatch stay at 0 (manifest-routing-only weights). "ship-fast": { - quota: 0.14, - health: 0.28, - costInv: 0.05, - latencyInv: 0.32, - taskFit: 0.1, - stability: 0.0, - tierPriority: 0.05, + quota: 0.1333, + health: 0.2667, + costInv: 0.0476, + latencyInv: 0.3048, + taskFit: 0.0952, + stability: 0, + tierPriority: 0.0476, tierAffinity: 0, specificityMatch: 0, - contextAffinity: 0.01, - sessionAvailability: 0.05, + contextAffinity: 0.0095, + sessionAvailability: 0.0476, resetWindowAffinity: 0, - connectionDensity: 0.05, + connectionDensity: 0.0476, }, // Prioritize cost. tierPriority replaces 0.05 from stability. "cost-saver": { - quota: 0.14, - health: 0.19, - costInv: 0.37, - latencyInv: 0.05, - taskFit: 0.1, - stability: 0.05, - tierPriority: 0.05, + quota: 0.1333, + health: 0.181, + costInv: 0.3524, + latencyInv: 0.0476, + taskFit: 0.0952, + stability: 0.0476, + tierPriority: 0.0476, tierAffinity: 0, specificityMatch: 0, - contextAffinity: 0.0, - sessionAvailability: 0.05, + contextAffinity: 0, + sessionAvailability: 0.0476, resetWindowAffinity: 0, - connectionDensity: 0.05, + connectionDensity: 0.0476, }, // Prioritize task fitness. tierPriority replaces 0.05 from latencyInv. "quality-first": { - quota: 0.1, - health: 0.18, - costInv: 0.05, - latencyInv: 0.05, - taskFit: 0.37, - stability: 0.15, - tierPriority: 0.05, + quota: 0.0952, + health: 0.1714, + costInv: 0.0476, + latencyInv: 0.0476, + taskFit: 0.3524, + stability: 0.1429, + tierPriority: 0.0476, tierAffinity: 0, specificityMatch: 0, - contextAffinity: 0.0, - sessionAvailability: 0.05, + contextAffinity: 0, + sessionAvailability: 0.0476, resetWindowAffinity: 0, - connectionDensity: 0.05, + connectionDensity: 0.0476, }, // Prioritize quota availability. tierPriority replaces 0.05 from taskFit. "offline-friendly": { - quota: 0.37, - health: 0.28, - costInv: 0.1, - latencyInv: 0.05, - taskFit: 0.0, - stability: 0.1, - tierPriority: 0.05, + quota: 0.3524, + health: 0.2667, + costInv: 0.0952, + latencyInv: 0.0476, + taskFit: 0, + stability: 0.0952, + tierPriority: 0.0476, tierAffinity: 0, specificityMatch: 0, - contextAffinity: 0.0, - sessionAvailability: 0.05, + contextAffinity: 0, + sessionAvailability: 0.0476, resetWindowAffinity: 0, - connectionDensity: 0.05, + connectionDensity: 0.0476, }, // #4235 `:reliable` — prioritize healthy, low-variance providers (high availability). - // health (circuit-breaker) + stability (latency std-dev) dominate; weights sum to 1.0. + // health (circuit-breaker) + stability (latency std-dev) dominate; weights sum to ~1.0 + // (re-normalized after #8940 added sessionAvailability without rebalancing — #9985). "reliability-first": { - quota: 0.14, - health: 0.37, - costInv: 0.04, - latencyInv: 0.05, - taskFit: 0.1, - stability: 0.2, - tierPriority: 0.05, + quota: 0.1333, + health: 0.3524, + costInv: 0.0381, + latencyInv: 0.0476, + taskFit: 0.0952, + stability: 0.1905, + tierPriority: 0.0476, tierAffinity: 0, specificityMatch: 0, - contextAffinity: 0.0, - sessionAvailability: 0.05, + contextAffinity: 0, + sessionAvailability: 0.0476, resetWindowAffinity: 0, - connectionDensity: 0.05, + connectionDensity: 0.0476, }, // Chaos mode — priority: health > stability > taskFit > latency. // Selects top-N healthy providers for parallel dispatch. Favors providers with @@ -100,19 +101,19 @@ export const MODE_PACKS: Record = { // to picking the most stable providers); connectionDensity boosted slightly to // prefer providers with multiple accounts (more resilient to per-account rate limits). "chaos-mode": { - quota: 0.05, - health: 0.42, - costInv: 0.02, - latencyInv: 0.03, - taskFit: 0.2, - stability: 0.18, - tierPriority: 0.02, + quota: 0.0476, + health: 0.4, + costInv: 0.019, + latencyInv: 0.0286, + taskFit: 0.1905, + stability: 0.1714, + tierPriority: 0.019, tierAffinity: 0, specificityMatch: 0, - contextAffinity: 0.03, - sessionAvailability: 0.05, + contextAffinity: 0.0286, + sessionAvailability: 0.0476, resetWindowAffinity: 0, - connectionDensity: 0.05, + connectionDensity: 0.0476, }, }; diff --git a/tests/unit/check-docs-counts-sync.test.ts b/tests/unit/check-docs-counts-sync.test.ts index 5557e5f10c..e91e18ba58 100644 --- a/tests/unit/check-docs-counts-sync.test.ts +++ b/tests/unit/check-docs-counts-sync.test.ts @@ -8,9 +8,6 @@ import { tallyDrift, readProviderTotal, countLocales, - readMcpFactsFromSource, - listLocalizedDocs, - makeRequiredCountsValidator, } from "../../scripts/check/check-docs-counts-sync.mjs"; // Explicit types for the .mjs exports — keep the test at 0 no-explicit-any warnings. @@ -27,11 +24,6 @@ const tally = tallyDrift as ( ) => { strict: number; soft: number; lines: string[] }; const readTotal = readProviderTotal as () => number; const locales = countLocales as () => number; -const mcpFacts = readMcpFactsFromSource as () => { tools: number; scopes: number } | null; -const localizedDocs = listLocalizedDocs as (relativePath: string) => string[]; -const requireCounts = makeRequiredCountsValidator as ( - requirements: { label: string; value: number }[] -) => (content: string) => { ok: boolean; detail: string }; const here = path.dirname(fileURLToPath(import.meta.url)); const GATE = path.resolve(here, "../../scripts/check/check-docs-counts-sync.mjs"); @@ -100,31 +92,6 @@ test("countLocales reads a real, positive locale count from config/i18n.json", ( assert.ok(locales() >= 40, "i18n config should define at least 40 locales"); }); -test("source-only MCP fallback matches the canonical inventory and scope union", () => { - assert.deepEqual(mcpFacts(), { tools: 107, scopes: 32 }); -}); - -test("localized-doc discovery returns every locale root document", () => { - const readmes = localizedDocs("README.md"); - assert.equal(readmes.length, 42); - assert.ok(readmes.includes("docs/i18n/pt-BR/README.md")); - assert.ok(readmes.includes("docs/i18n/zh-CN/README.md")); -}); - -test("required-count validator reports precisely which live markers are missing", () => { - const validate = requireCounts([ - { label: "providers", value: 327 }, - { label: "MCP tools", value: 107 }, - { label: "MCP scopes", value: 32 }, - ]); - assert.equal(validate("327 providers; 107 tools; 32 scopes").ok, true); - const stale = validate("290 providers; 104 tools; 31 scopes"); - assert.equal(stale.ok, false); - assert.match(stale.detail, /providers=327/); - assert.match(stale.detail, /MCP tools=107/); - assert.match(stale.detail, /MCP scopes=32/); -}); - // --- live gate smoke ----------------------------------------------------------------- test("the gate exits 0 against the current (synced) repo state", () => { @@ -138,7 +105,6 @@ test("the gate exits 0 against the current (synced) repo state", () => { // down to 1.37B, because no gate watched that number. import { checkFreeTierHeadline, - checkFreeTierInventory, extractHeadlineClaims, } from "../../scripts/check/check-docs-counts-sync.mjs"; @@ -180,23 +146,6 @@ test("free-tier gate passes when a file carries no headline at all", () => { assert.equal(checkHeadline("no figures here", TOTALS).ok, true); }); -const checkInventory = checkFreeTierInventory as ( - content: string, - totals: { pools: number; models: number } -) => { ok: boolean; detail: string }; - -test("free-tier inventory gate accepts the live pool/model counts", () => { - assert.equal( - checkInventory("43 provider pools / 522 model budget entries", { pools: 43, models: 522 }).ok, - true - ); -}); - -test("free-tier inventory gate rejects stale model counts", () => { - const result = checkInventory("43 provider pools / 516 models", { pools: 43, models: 522 }); - assert.equal(result.ok, false); - assert.match(result.detail, /live catalog has 43 pools \/ 522 model budget entries/); -}); // --- Generic numeric-claim gate (engines / MCP tools / scopes / CLI) -------- // Extends the same drift guard to the counts that silently drifted in v3.8.49: diff --git a/tests/unit/quota-connection-recovery.test.ts b/tests/unit/quota-connection-recovery.test.ts index fe23a591ee..4e7b3a0241 100644 --- a/tests/unit/quota-connection-recovery.test.ts +++ b/tests/unit/quota-connection-recovery.test.ts @@ -1,4 +1,5 @@ -import { describe, expect, it, vi } from "vitest"; +import { describe, it, mock } from "node:test"; +import assert from "node:assert/strict"; import { CREDITS_EXHAUSTED_STATUS, isCreditsExhaustedReprobeCandidate, @@ -17,7 +18,7 @@ describe("connectionRecovery — credits_exhausted reprobe", () => { testStatus: CREDITS_EXHAUSTED_STATUS, rateLimitedUntil: new Date(nowMs - 5000).toISOString(), }; - expect(isRecoverableCooldownConnection(conn, nowMs)).toBe(false); + assert.equal(isRecoverableCooldownConnection(conn, nowMs), false); }); it("should reprobe credits_exhausted when >30m has elapsed since lastErrorAt", () => { @@ -27,7 +28,7 @@ describe("connectionRecovery — credits_exhausted reprobe", () => { testStatus: CREDITS_EXHAUSTED_STATUS, lastErrorAt: thirtyOneMinAgo, }; - expect(isCreditsExhaustedReprobeCandidate(conn, nowMs)).toBe(true); + assert.equal(isCreditsExhaustedReprobeCandidate(conn, nowMs), true); }); it("should NOT reprobe credits_exhausted when <30m has elapsed since lastErrorAt", () => { @@ -37,7 +38,7 @@ describe("connectionRecovery — credits_exhausted reprobe", () => { testStatus: CREDITS_EXHAUSTED_STATUS, lastErrorAt: tenMinAgo, }; - expect(isCreditsExhaustedReprobeCandidate(conn, nowMs)).toBe(false); + assert.equal(isCreditsExhaustedReprobeCandidate(conn, nowMs), false); }); it("should reprobe credits_exhausted if no timestamp is present (first tick after startup)", () => { @@ -45,7 +46,7 @@ describe("connectionRecovery — credits_exhausted reprobe", () => { id: "conn-1", testStatus: CREDITS_EXHAUSTED_STATUS, }; - expect(isCreditsExhaustedReprobeCandidate(conn, nowMs)).toBe(true); + assert.equal(isCreditsExhaustedReprobeCandidate(conn, nowMs), true); }); it("selectRecoverableConnections includes both transient cooldowns and expired credits_exhausted", () => { @@ -69,18 +70,18 @@ describe("connectionRecovery — credits_exhausted reprobe", () => { [activeTransient, expiredCredits, freshCredits], nowMs ); - expect(selected.map((c) => c.id)).toEqual(["t-1", "c-1"]); + assert.deepEqual(selected.map((c) => c.id), ["t-1", "c-1"]); }); it("runConnectionRecoveryTick calls clearConnectionError for reprobe candidates", async () => { - const loadConnections = vi.fn().mockResolvedValue([ + const loadConnections = mock.fn(async () => [ { id: "c-1", testStatus: CREDITS_EXHAUSTED_STATUS, lastErrorAt: new Date(nowMs - thirtyMinMs - 1000).toISOString(), }, ]); - const clearConnectionError = vi.fn().mockResolvedValue(undefined); + const clearConnectionError = mock.fn(async () => undefined); const res = await runConnectionRecoveryTick({ nowMs, @@ -88,8 +89,10 @@ describe("connectionRecovery — credits_exhausted reprobe", () => { clearConnectionError, }); - expect(res.recovered).toBe(1); - expect(res.recoveredIds).toEqual(["c-1"]); - expect(clearConnectionError).toHaveBeenCalledWith("c-1", expect.anything()); + assert.equal(res.recovered, 1); + assert.deepEqual(res.recoveredIds, ["c-1"]); + assert.equal(clearConnectionError.mock.callCount(), 1); + assert.equal(clearConnectionError.mock.calls[0].arguments[0], "c-1"); + assert.notEqual(clearConnectionError.mock.calls[0].arguments[1], undefined); }); });