fix(db,combo): clear the NEW base-reds the 08-06 merge batch introduced

The tip moved while the first sweep PR (#9600) was in review, and three fresh
base-reds landed with it — same classes as before, all reproduced on the pure
tip 9995bc4893:

1. ANOTHER migration collision: #9061 shipped 134_ccr_blocks.sql onto the slot
   134_proxy_logs_egress_ip.sql (#9291) has held since 08-04. getMigrationFiles()
   throws on collision, so every DB-touching test died at bootstrap again.
   Renumbered to 139 (next free slot). No retroactive guard needed this time:
   both statements are IF NOT EXISTS, and no DB can have applied it as 134 —
   the runner refused to run at all while the collision existed.
2. BROKEN IMPORT killing the combo module graph: #8894 imported
   preferAntigravityConnectionsWithStoredProject from
   ../antigravityProjectPersistence.ts — a module that exists NOWHERE in the
   repo (it came from an unmerged sibling branch). Anything importing
   quotaStrategies.ts died with ERR_MODULE_NOT_FOUND. Implemented the helper in
   the real persistence module (antigravityProjectPersist.ts, #8491) with the
   semantics the call site needs — prefer connections that already carry a
   stored projectId, never emptying the pool — and pointed the import there.
   New regression suite tests/unit/antigravity-prefer-stored-project.test.ts
   (5/5), including an import-graph probe that reproduces the break shape.
3. Sibling-test drift from #9106 (gemini-3.1-pro-high now user-callable): its
   own suites were updated but provider-models-route.test.ts was not. Expected
   discovery list realigned; testFrozen 1784->1787 justified in the baseline
   (irreducible +2 after comment compression; gate counts split-newlines).

Also regenerated tests/snapshots/provider/translate-path.json — addition-only:
devin-cli-agentic, raycast, regolo (today's provider merges), zero removals.

image-generation-route 20/20 (was import-dead), provider-models-route 59/59,
antigravity-prefer-stored-project 5/5, provider-translate-path-golden 3/3.

Refs #9298
This commit is contained in:
diegosouzapw
2026-08-07 04:08:35 -03:00
parent e4f55c7d92
commit e8936f53f4
7 changed files with 166 additions and 11 deletions

View File

@@ -371,7 +371,7 @@
"tests/unit/model-sync-route.test.ts": 1016,
"tests/unit/models-catalog-route.test.ts": 1636,
"tests/unit/perplexity-web.test.ts": 1355,
"tests/unit/provider-models-route.test.ts": 1784,
"tests/unit/provider-models-route.test.ts": 1787,
"tests/unit/provider-validation-specialty.test.ts": 2985,
"tests/unit/providers-page-utils.test.ts": 1106,
"tests/unit/response-sanitizer.test.ts": 1063,
@@ -607,5 +607,6 @@
"_rebaseline_2026_08_05_9323_agentrouter_waf_retry": "PR #9323 (fix(agentrouter): retry on 400 content-blocked + burst guard) own growth: open-sse/executors/base.ts 1578->1623 (check-file-size.mjs conta via split(\"\\n\").length; wc -l ve 1622). As +45 linhas sao o WAF_RETRY_CONFIG + o burst guard via gateOutboundRequest() para o WAF do agentrouter.org, com comentarios explicando o porque de cada mitigacao e cobertos por tests/unit/base-executor-waf-retry.test.ts e tests/unit/wafRateLimit.test.ts. Crescimento funcional legitimo, nao inchaco.",
"_rebaseline_2026_08_05_9529_own_growth": "PR #9529 own growth (base release/v3.8.50 medida EXATAMENTE nos frozen antigos, entao o modo base-relative #8522 nao cobre): open-sse/services/rateLimitManager.ts 1060->1105 (+45: helper applyLimiterSettings() que re-arma o heartbeat do reservoir apos updateSettings — fix do bug Bottleneck 2.19.5 que congelava a fila weighted; TDD em tests/unit/ratelimit-reservoir-refresh.test.ts); tests/integration/chat-pipeline.test.ts 1592->1598 (+6: User-Agent do codex derivado de getCodexClientVersion() em vez de literal pinado — teste-irmao alinhado ao contrato); tests/unit/provider-validation-specialty.test.ts 2980->2985 (+5: cobertura NOVA claude-web 429 -> valid:false, alinhamento #9406); open-sse/translator/response/openai-responses.ts 1174->1204 (+30: buildResponsesReasoningSummaryDelta MOVIDA do leaf pureHelpers.ts para o host — a funcao do #9500 muta stream state e violava o contrato do leaf puro; o LOC total do par host+leaf nao cresceu, o pureHelpers encolheu o mesmo tanto). Crescimento por fix de producao + cobertura adicional + realocacao arquitetural, nao inchaco.",
"_rebaseline_2026_08_06_v3850_inherited_drift_reconcile": "Reconciliacao 2026-08-06 do drift ACUMULADO da release/v3.8.50 apos o lote de merges de 08-05/06: 13 arquivos acima do frozen no tip puro 8180b49ce1 (medidos pelo proprio gate). O modo PR base-relative (#8522) deixa PRs inocentes passarem, e os rebaselines individuais dos PRs se perderam nas resolucoes sucessivas de conflito deste hot-file — o drift so aparece no modo absoluto (nightly/local). Crescimentos funcionais dos PRs mergeados: #9024 topology click-nav src/app/(dashboard)/dashboard/HomePageClient.tsx; #9324 OpenRouter enrich src/app/(dashboard)/dashboard/providers/page.tsx; #9329 quota card ordering src/app/(dashboard)/dashboard/usage/components/ProviderLimits/index.tsx; #9193 context-window suffixes src/sse/handlers/chat.ts; #9332 nested Claude server tool ids open-sse/executors/base.ts; #9228 strip orphaned tool outputs open-sse/executors/codex.ts; #9236 nvidia tool-name normalize open-sse/executors/default.ts; #9314 nested tool_call validation open-sse/executors/kiro.ts; #9260 caller identity REST hops open-sse/mcp-server/server.ts; #8934 cache breakpoints tests tests/unit/chatcore-translation-paths.test.ts; #9193 suffix tests tests/unit/combo-routing-engine.test.ts; #9196 reasoning-on-tool-finish tests tests/unit/sse-auth.test.ts; #9163 GPT-5.6 Max reasoning tests tests/unit/translator-openai-to-kiro.test.ts. default.ts e kiro.ts entram no frozen (estavam sem entrada, acima do cap 1000). Atualizacao pos-medicao (a base avancou durante o ciclo do PR): src/sse/handlers/chat.ts 1857->1877 (#9184 affinity EOF evict) e open-sse/executors/default.ts 1027->1042 (#9005 Kimi K3 tool-name backfill).",
"_rebaseline_2026_08_06b_v3850_sweepreds_drift": "Segunda reconciliacao de 2026-08-06 (/sweep-reds sobre o tip puro 2ddbbc61a6): 3 arquivos voltaram a passar do frozen apos os merges do mesmo dia, com atribuicao 1:1 por commit. (1) src/app/(dashboard)/dashboard/providers/page.tsx 1928->1944 e (2) open-sse/executors/base.ts 1635->1640, ambos do #9515 (feat(radar): flag-gated signed free-model catalog overlay, commit e7f6b1d130) — o overlay do Radar entra por wiring nos chokepoints ja existentes (a resolucao/verificacao do catalogo assinado mora fora destes dois arquivos); +16 e +5 linhas liquidas nao sao extraiveis sem inventar um leaf por callsite. (3) open-sse/services/accountFallback.ts 1966->1972 do #8704 (commit c4527f97bd), +6 linhas de dados em CREDITS_EXHAUSTED_SIGNALS ('has been exhausted', fixes #8631). src/sse/handlers/chat.ts 1880>1877 tambem estava violando e NAO entra aqui de proposito: e drenado por encolhimento na PR #9598, sem rebaseline. Crescimento proprio DESTA PR: src/lib/db/migrationRunner.ts 1077->1084 (+7) — o guard retroativo em isSchemaAlreadyApplied para os arquivos renumerados 137/138, exigido pela propria mensagem de erro de colisao do runner (ambas as migracoes sao ALTER TABLE ADD COLUMN puro, nao idempotente). Dois `case` + dois `return hasColumn(...)` + 3 linhas de comentario dentro do switch existente; nao extraivel."
"_rebaseline_2026_08_06b_v3850_sweepreds_drift": "Segunda reconciliacao de 2026-08-06 (/sweep-reds sobre o tip puro 2ddbbc61a6): 3 arquivos voltaram a passar do frozen apos os merges do mesmo dia, com atribuicao 1:1 por commit. (1) src/app/(dashboard)/dashboard/providers/page.tsx 1928->1944 e (2) open-sse/executors/base.ts 1635->1640, ambos do #9515 (feat(radar): flag-gated signed free-model catalog overlay, commit e7f6b1d130) — o overlay do Radar entra por wiring nos chokepoints ja existentes (a resolucao/verificacao do catalogo assinado mora fora destes dois arquivos); +16 e +5 linhas liquidas nao sao extraiveis sem inventar um leaf por callsite. (3) open-sse/services/accountFallback.ts 1966->1972 do #8704 (commit c4527f97bd), +6 linhas de dados em CREDITS_EXHAUSTED_SIGNALS ('has been exhausted', fixes #8631). src/sse/handlers/chat.ts 1880>1877 tambem estava violando e NAO entra aqui de proposito: e drenado por encolhimento na PR #9598, sem rebaseline. Crescimento proprio DESTA PR: src/lib/db/migrationRunner.ts 1077->1084 (+7) — o guard retroativo em isSchemaAlreadyApplied para os arquivos renumerados 137/138, exigido pela propria mensagem de erro de colisao do runner (ambas as migracoes sao ALTER TABLE ADD COLUMN puro, nao idempotente). Dois `case` + dois `return hasColumn(...)` + 3 linhas de comentario dentro do switch existente; nao extraivel.",
"_rebaseline_2026_08_06c_v3850_sweepreds_pr2": "Segunda PR do /sweep-reds (fix/release-v3.8.50-basereds-0806b): tests/unit/provider-models-route.test.ts 1784->1787 (medido pelo gate, que conta split(\"\\n\").length) (+2 apos compressao de comentarios) — alinhamento de contrato forcado por dois merges do dia: #9106 tornou gemini-3.1-pro-high user-callable (a entry do alias entra na lista esperada do teste de discovery-retry, +1 linha de dado + 1 de comentario) e ff012ff420 adicionou onboardUser como bootstrap hop (exclusao no mock, ja comprimida a 1 linha). Nao ha o que encolher sem apagar o comentario que explica o porque."
}

View File

@@ -22,6 +22,43 @@ import { updateProviderConnection } from "@/lib/db/providers";
* Best-effort / non-fatal by design: a persistence failure must never block
* the in-flight request, which already has the discovered id in hand.
*/
/**
* Selection-side companion of the persistence write path (#8894): given a pool
* of Antigravity/AGY connections, prefer the ones that already carry a stored
* projectId — they can serve a request without the `loadCodeAssist` discovery
* round-trip. "Prefer", not "require": when NO connection has a stored project
* the pool is returned unchanged, so a fresh install never empties its
* candidate list.
*
* Sync on purpose (called inside the quota-strategy connection expansion, which
* builds candidate lists without awaiting per-connection work). Tolerates
* `providerSpecificData` arriving either parsed or as the raw DB JSON string.
*/
export function preferAntigravityConnectionsWithStoredProject<T extends Record<string, unknown>>(
connections: T[]
): T[] {
if (!Array.isArray(connections) || connections.length === 0) return connections;
const hasStoredProject = (connection: T): boolean => {
if (typeof connection.projectId === "string" && connection.projectId) return true;
let psd = connection.providerSpecificData;
if (typeof psd === "string") {
try {
psd = JSON.parse(psd);
} catch {
return false;
}
}
return Boolean(
psd &&
typeof psd === "object" &&
typeof (psd as Record<string, unknown>).projectId === "string" &&
(psd as Record<string, unknown>).projectId
);
};
const withStoredProject = connections.filter(hasStoredProject);
return withStoredProject.length > 0 ? withStoredProject : connections;
}
export async function persistDiscoveredAntigravityProjectId(
connectionId: string | undefined | null,
discoveredProjectId: string | undefined | null,

View File

@@ -45,7 +45,7 @@ import {
type QuotaFetchCacheConfig,
} from "./quotaScoring.ts";
import { rankByHeadroom, type HeadroomSaturation } from "./headroomRanking.ts";
import { preferAntigravityConnectionsWithStoredProject } from "../antigravityProjectPersistence.ts";
import { preferAntigravityConnectionsWithStoredProject } from "../antigravityProjectPersist.ts";
import { isQuotaExhaustedForRequest } from "../../../src/domain/quotaCache.ts";
const RESET_AWARE_CONNECTION_CACHE_TTL_MS = 30_000;

View File

@@ -1488,6 +1488,29 @@
"stream": "devin://acp/stdio"
}
},
"devin-cli-agentic": {
"format": "claude",
"headers": {
"apiKey": {
"Accept": "text/event-stream",
"Authorization": "Bearer <TOK>",
"Content-Type": "application/json"
},
"nonStream": {
"Authorization": "Bearer <TOK>",
"Content-Type": "application/json"
},
"oauth": {
"Accept": "text/event-stream",
"Authorization": "Bearer <TOK>",
"Content-Type": "application/json"
}
},
"url": {
"nonStream": "devin://acp/stdio",
"stream": "devin://acp/stdio"
}
},
"dgrid": {
"format": "openai",
"headers": {
@@ -4274,6 +4297,52 @@
"stream": "https://chat.qwen.ai/api/v2/chat/completions"
}
},
"raycast": {
"format": "openai",
"headers": {
"apiKey": {
"Accept": "text/event-stream",
"Authorization": "Bearer <TOK>",
"Content-Type": "application/json"
},
"nonStream": {
"Authorization": "Bearer <TOK>",
"Content-Type": "application/json"
},
"oauth": {
"Accept": "text/event-stream",
"Authorization": "Bearer <TOK>",
"Content-Type": "application/json"
}
},
"url": {
"nonStream": "https://backend.raycast.com/api/v1/ai",
"stream": "https://backend.raycast.com/api/v1/ai"
}
},
"regolo": {
"format": "openai",
"headers": {
"apiKey": {
"Accept": "text/event-stream",
"Authorization": "Bearer <TOK>",
"Content-Type": "application/json"
},
"nonStream": {
"Authorization": "Bearer <TOK>",
"Content-Type": "application/json"
},
"oauth": {
"Accept": "text/event-stream",
"Authorization": "Bearer <TOK>",
"Content-Type": "application/json"
}
},
"url": {
"nonStream": "https://api.regolo.ai",
"stream": "https://api.regolo.ai"
}
},
"reka": {
"format": "openai",
"headers": {

View File

@@ -0,0 +1,52 @@
/**
* Regression guard for the #8894 import break: quotaStrategies.ts imported
* `preferAntigravityConnectionsWithStoredProject` from a module that never
* landed (`antigravityProjectPersistence.ts`), killing the whole combo module
* graph with ERR_MODULE_NOT_FOUND on the release tip. The helper now lives in
* the real persistence module (`antigravityProjectPersist.ts`); these tests pin
* its selection semantics.
*
* Run: node --import tsx/esm --test tests/unit/antigravity-prefer-stored-project.test.ts
*/
import { test } from "node:test";
import assert from "node:assert/strict";
import { preferAntigravityConnectionsWithStoredProject } from "../../open-sse/services/antigravityProjectPersist.ts";
const withProject = { id: "a", projectId: "proj-1" };
const withNestedProject = { id: "b", providerSpecificData: { projectId: "proj-2" } };
const withStringPsd = { id: "c", providerSpecificData: '{"projectId":"proj-3"}' };
const withoutProject = { id: "d", projectId: null, providerSpecificData: {} };
const withBrokenPsd = { id: "e", providerSpecificData: "{not json" };
test("prefers connections that already carry a stored projectId", () => {
const pool = [withoutProject, withProject, withNestedProject];
assert.deepEqual(
preferAntigravityConnectionsWithStoredProject(pool).map((c) => c.id),
["a", "b"]
);
});
test("reads projectId from a raw JSON-string providerSpecificData", () => {
const pool = [withoutProject, withStringPsd];
assert.deepEqual(
preferAntigravityConnectionsWithStoredProject(pool).map((c) => c.id),
["c"]
);
});
test("never empties the pool: no stored project anywhere → unchanged", () => {
const pool = [withoutProject, withBrokenPsd];
assert.deepEqual(preferAntigravityConnectionsWithStoredProject(pool), pool);
});
test("empty input passes through", () => {
assert.deepEqual(preferAntigravityConnectionsWithStoredProject([]), []);
});
test("the quota-strategy module graph resolves (the #8894 break shape)", async () => {
// Importing quotaStrategies transitively exercises the fixed import path; the
// pre-fix tip died here with ERR_MODULE_NOT_FOUND before any test could run.
const mod = await import("../../open-sse/services/combo/quotaStrategies.ts");
assert.ok(mod, "quotaStrategies must be importable");
});

View File

@@ -934,14 +934,8 @@ test("provider models route retries Antigravity discovery endpoints before retur
// After PR #2219, the discovery flow calls loadCodeAssist first as a project
// bootstrap; treat all bootstrap calls as non-fatal failures so the test
// exercises the discovery retry path.
// `onboardUser` joined loadCodeAssist as a bootstrap hop (ff012ff420: fall back
// to onboardUser when loadCodeAssist fails). It must be excluded here too —
// otherwise it consumes the single 503 below and discovery never retries,
// which is a mock-ordering artifact, not a routing change.
if (
urlString.includes("/v1internal:loadCodeAssist") ||
urlString.includes("/v1internal:onboardUser")
) {
// onboardUser is a bootstrap hop too (ff012ff420) — else it eats the single 503 below.
if (urlString.includes(":loadCodeAssist") || urlString.includes(":onboardUser")) {
return new Response("nope", { status: 503 });
}
seenUrls.push(urlString);
@@ -990,6 +984,8 @@ test("provider models route retries Antigravity discovery endpoints before retur
"https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels",
]);
assert.deepEqual(body.models, [
// #9106: both alias ids are user-callable now, so the upstream echo survives the filter.
{ id: "gemini-3.1-pro-high", name: "Gemini 3.1 Pro (High)" },
{ id: "gemini-pro-agent", name: "Gemini 3.1 Pro (High)" },
{ id: "gemini-3.6-flash-high", name: "Gemini 3.6 Flash (High)" },
{ id: "gemini-3.6-flash-medium", name: "Gemini 3.6 Flash (Medium)" },