Files
OmniRoute/tests/unit/virtualFactory-snapshot-quality.test.ts
Dizzle 2b276e2043 fix(auto-combo): stop neutral snapshot scoring on observed tier/quality/breaker (#12794)
Validado numa worktree combinada com a onda de roteamento/free-tier desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-api-typecheck OK (288), check-file-size OK após rebaseline, 84/85 nos testes focados.

Tratar breaker aberto como equivalente a fechado no scoring de snapshot é pior que não pontuar: afirma saúde onde há falha conhecida. Trocar as três constantes neutras por valor observado é a correção, e manter preço e orçamento fora do escopo mantém a PR revisável.

**Integração:** o `computeSnapshotWeights` conflitou com o #12731, que adiciona peso de `reliability` a partir de `failureRate`/`errorRate`. Os dois cobrem chaves diferentes e compõem — ficaram ambos: reliability do #12731, health via breaker e quality desta PR, quota neutro nos dois. Nenhum dos dois lados foi descartado.
2026-09-10 09:12:58 -03:00

76 lines
2.7 KiB
TypeScript

// tests/unit/virtualFactory-snapshot-quality.test.ts
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
computeSnapshotWeights,
type VirtualAutoComboCandidate,
} from "../../open-sse/services/autoCombo/virtualFactory.ts";
import type { ScoringWeights } from "../../open-sse/services/autoCombo/scoring.ts";
import { createModelCapabilityResolutionSnapshot } from "../../src/lib/modelCapabilities.ts";
describe("virtualFactory snapshot quality", () => {
it("factory-built candidate carries finite quality (attach path, both pools)", async () => {
// Exercises the REAL hydration path: push a raw candidate through
// attachPreparedCapabilityValues:547-598 (covers regular + family pools —
// both go through attach, so one call proves both).
const { attachPreparedCapabilityValues } =
await import("../../open-sse/services/autoCombo/virtualFactory.ts");
const raw: VirtualAutoComboCandidate[] = [
{
provider: "openai",
model: "gpt-4o",
modelStr: "openai/gpt-4o",
connectionId: null,
costPer1MTokens: 5,
},
];
const state = {
byTarget: new Map(),
resolvedSinceYield: 0,
resolutionSnapshot: createModelCapabilityResolutionSnapshot(),
};
const out = await attachPreparedCapabilityValues(raw, state);
const q = out[0]?.quality;
assert.ok(
typeof q === "number" && Number.isFinite(q) && q >= 0 && q <= 1,
`quality ${q} must be finite 0..1`
);
});
it("hot quality outranks cold through computeSnapshotWeights", () => {
const weights = {
quota: 0.1,
health: 0.1,
quality: 0.3,
taskFit: 0,
stability: 0,
tierPriority: 0,
costInv: 0,
latencyInv: 0,
} as ScoringWeights;
const cold: VirtualAutoComboCandidate = {
provider: "openai",
model: "gpt-4o",
modelStr: "openai/gpt-4o",
connectionId: null,
costPer1MTokens: 5,
quality: 0.5,
};
const hot: VirtualAutoComboCandidate = {
provider: "openai",
model: "gpt-4o",
modelStr: "openai/gpt-4o",
connectionId: null,
costPer1MTokens: 5,
quality: 0.9,
};
const sCold = computeSnapshotWeights([cold], weights).get("openai/gpt-4o")!;
const sHot = computeSnapshotWeights([hot], weights).get("openai/gpt-4o")!;
assert.ok(sHot > sCold, `hot ${sHot} should exceed cold ${sCold}`);
});
it("hydration stores a finite 0..1 quality (not NaN)", async () => {
const { getQualityScore } = await import("../../open-sse/services/routing/quality.ts");
const q = getQualityScore("openai", "gpt-4o");
assert.ok(typeof q === "number" && Number.isFinite(q) && q >= 0 && q <= 1);
});
});