diff --git a/changelog.d/fixes/9554-file-size-inherited-drift-reconcile.md b/changelog.d/fixes/9554-file-size-inherited-drift-reconcile.md new file mode 100644 index 0000000000..095d7609d2 --- /dev/null +++ b/changelog.d/fixes/9554-file-size-inherited-drift-reconcile.md @@ -0,0 +1 @@ +- **fix(quality):** reconcile the accumulated file-size drift on `release/v3.8.50` — 13 files sat above their frozen LOC on the clean tip (measured by the gate itself), turning the absolute-mode check (nightly / local) permanently red while the PR-mode base-relative check (#8522) let every innocent PR pass. The per-PR rebaselines were lost across successive conflict resolutions of this hot file during the 08-05/06 merge batch. Frozen values updated to the measured tip for the 11 grown files (each annotated with its owning merged PR: #9024 #9324 #9329 #9193 #9332 #9228 #9260 #8934 #9196 #9163) and `open-sse/executors/default.ts` / `kiro.ts` (above the 1000 cap with no entry) added to the frozen set. diff --git a/config/quality/eslint-suppressions.json b/config/quality/eslint-suppressions.json index b25bdbca91..7373467d5b 100644 --- a/config/quality/eslint-suppressions.json +++ b/config/quality/eslint-suppressions.json @@ -1,4 +1,5 @@ { + "_comment": "Congelamento da divida ESLint da migracao TypeScript 7 (release/v3.8.50, 2026-08-05; regenerado 2026-08-06 apos prune de entradas orfas). Gerado pelo modo nativo `eslint --suppress-all --suppressions-location config/quality/eslint-suppressions.json` (NODE_OPTIONS=--max-old-space-size=12288). Politica: violacao PRE-EXISTENTE fica suprimida aqui; violacao NOVA (fora deste arquivo) e vermelho imediato e deve ser corrigida, nunca adicionada. Entradas que deixarem de ocorrer sao podadas com `eslint --prune-suppressions` (o job 'No new ESLint warnings' falha com supressoes orfas). A baseline eslintWarnings em config/quality/quality-baseline.json e 0 — o valor real medido com estas supressoes aplicadas.", "open-sse/executors/blackbox-web.ts": { "@typescript-eslint/no-explicit-any": { "count": 1 @@ -903,21 +904,11 @@ "count": 1 } }, - "src/app/api/v1/audio/speech/route.ts": { - "no-restricted-imports": { - "count": 1 - } - }, "src/app/api/v1/audio/transcriptions/route.ts": { "no-restricted-imports": { "count": 1 } }, - "src/app/api/v1/audio/translations/route.ts": { - "no-restricted-imports": { - "count": 1 - } - }, "src/app/api/v1/batches/[id]/cancel/route.ts": { "no-restricted-imports": { "count": 1 @@ -963,11 +954,6 @@ "count": 2 } }, - "src/app/api/v1/images/generations/route.ts": { - "no-restricted-imports": { - "count": 1 - } - }, "src/app/api/v1/management/proxies/assignments/route.ts": { "no-restricted-imports": { "count": 1 @@ -3229,7 +3215,7 @@ }, "tests/unit/translator-claude-to-gemini.test.ts": { "@typescript-eslint/no-explicit-any": { - "count": 17 + "count": 15 } }, "tests/unit/translator-claude-to-openai.test.ts": { @@ -3382,4 +3368,4 @@ "count": 5 } } -} \ No newline at end of file +} diff --git a/config/quality/file-size-baseline.json b/config/quality/file-size-baseline.json index 9d5ad1055d..c2724a9f11 100644 --- a/config/quality/file-size-baseline.json +++ b/config/quality/file-size-baseline.json @@ -177,9 +177,9 @@ "tests/unit/account-fallback-service.test.ts": 1563, "tests/unit/batch_api.test.ts": 1324, "tests/unit/cc-compatible-provider.test.ts": 1217, - "tests/unit/chatcore-translation-paths.test.ts": 2776, + "tests/unit/chatcore-translation-paths.test.ts": 2876, "tests/unit/chatgpt-web.test.ts": 3148, - "tests/unit/combo-routing-engine.test.ts": 3449, + "tests/unit/combo-routing-engine.test.ts": 3457, "tests/unit/db-migration-runner.test.ts": 1499, "tests/unit/deepseek-web.test.ts": 1092, "tests/unit/executor-codex.test.ts": 1339, @@ -195,12 +195,12 @@ "tests/unit/response-sanitizer.test.ts": 1063, "tests/unit/route-edge-coverage.test.ts": 1241, "tests/unit/search-handler-extended.test.ts": 1071, - "tests/unit/sse-auth.test.ts": 1600, + "tests/unit/sse-auth.test.ts": 1610, "tests/unit/stream-utils.test.ts": 2445, "tests/unit/token-refresh-service.test.ts": 1378, "tests/unit/translator-openai-responses-req.test.ts": 1194, "tests/unit/translator-openai-to-gemini.test.ts": 1616, - "tests/unit/translator-openai-to-kiro.test.ts": 1250, + "tests/unit/translator-openai-to-kiro.test.ts": 1275, "tests/unit/translator-resp-gemini-to-openai.test.ts": 1234, "tests/unit/usage-service-hardening.test.ts": 1483, "tests/unit/vscode-token-routes.test.ts": 1256, @@ -343,9 +343,9 @@ "_rebaseline_pr1043_minimax_tts": "Upstream port decolua/9router#1043 (toanalien) own growth: audioSpeech.ts 965->1061 (+96). Adds MiniMax T2A v2 TTS dispatch (handleMinimaxSpeech + hexToBytes helper) — provider entry was already in audioRegistry (format: minimax-tts) but no handler existed, falling through to the OpenAI-compatible default that fails (T2A has custom shape + hex-encoded audio + base_resp envelope). New branch sits next to the other inline provider branches (xiaomi-mimo, coqui, tortoise, aws-polly) — extracting would just create indirection. Covered by tests/unit/minimax-tts-1043.test.ts (3 tests, GREEN: success, base_resp error, invalid-hex).", "_rebaseline_pr4592_exclude_exhausted_auto": "Reconcile #4592 already-merged growth: combo.ts 2991->3036 (+45, terminal-status quota-cutoff exclusion in buildAutoCandidates + opt-in gate). Fast-gate PR->release does not run check:file-size.", "open-sse/executors/antigravity.ts": 1528, - "open-sse/executors/base.ts": 1623, + "open-sse/executors/base.ts": 1635, "open-sse/executors/chatgpt-web.ts": 3241, - "open-sse/executors/codex.ts": 1534, + "open-sse/executors/codex.ts": 1562, "open-sse/executors/cursor.ts": 1560, "open-sse/executors/deepseek-web.ts": 1148, "open-sse/executors/grok-web.ts": 1044, @@ -356,7 +356,7 @@ "open-sse/handlers/search.ts": 1536, "open-sse/handlers/videoGeneration.ts": 1063, "open-sse/mcp-server/schemas/tools.ts": 1505, - "open-sse/mcp-server/server.ts": 1407, + "open-sse/mcp-server/server.ts": 1411, "open-sse/mcp-server/tools/advancedTools.ts": 1120, "open-sse/services/accountFallback.ts": 1966, "open-sse/services/adobeFireflyClient.ts": 2385, @@ -367,7 +367,7 @@ "open-sse/translator/response/openai-responses.ts": 1204, "open-sse/utils/cursorAgentProtobuf.ts": 1505, "open-sse/utils/stream.ts": 2889, - "src/app/(dashboard)/dashboard/HomePageClient.tsx": 1381, + "src/app/(dashboard)/dashboard/HomePageClient.tsx": 1388, "src/app/(dashboard)/dashboard/analytics/ComboHealthTab.tsx": 1031, "src/app/(dashboard)/dashboard/api-manager/ApiManagerPageClient.tsx": 3117, "src/app/(dashboard)/dashboard/cache/media/MediaPageClient.tsx": 1067, @@ -377,7 +377,7 @@ "src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.tsx": 2615, "src/app/(dashboard)/dashboard/health/page.tsx": 1165, "src/app/(dashboard)/dashboard/providers/[id]/components/modals/EditConnectionModal.tsx": 1316, - "src/app/(dashboard)/dashboard/providers/page.tsx": 1923, + "src/app/(dashboard)/dashboard/providers/page.tsx": 1928, "src/app/(dashboard)/dashboard/runtime/RuntimePageClient.tsx": 1201, "src/app/(dashboard)/dashboard/settings/components/PricingTab.tsx": 1019, "src/app/(dashboard)/dashboard/settings/components/ProxyRegistryManager.tsx": 1464, @@ -386,7 +386,7 @@ "src/app/(dashboard)/dashboard/settings/components/SystemStorageTab.tsx": 1573, "src/app/(dashboard)/dashboard/usage/components/BudgetTab.tsx": 1028, "src/app/(dashboard)/dashboard/usage/components/EvalsTab.tsx": 2148, - "src/app/(dashboard)/dashboard/usage/components/ProviderLimits/index.tsx": 1109, + "src/app/(dashboard)/dashboard/usage/components/ProviderLimits/index.tsx": 1119, "src/app/api/providers/[id]/models/route.ts": 2250, "src/app/api/v1/models/catalog.ts": 1549, "src/lib/tokenHealthCheck.ts": 1021, @@ -402,11 +402,13 @@ "src/shared/components/RequestLoggerV2.tsx": 1629, "src/shared/components/analytics/charts.tsx": 1035, "src/shared/services/cliRuntime.ts": 1122, - "src/sse/handlers/chat.ts": 1845, + "src/sse/handlers/chat.ts": 1877, "src/sse/services/auth.ts": 2508, "tests/unit/account-fallback-service.test.ts": 1572, "tests/unit/provider-validation-specialty.test.ts": 2985, - "open-sse/executors/hyperagent.ts": 1026 + "open-sse/executors/hyperagent.ts": 1026, + "open-sse/executors/default.ts": 1042, + "open-sse/executors/kiro.ts": 1069 }, "_rebaseline_2026_07_27_v3849_train2": "Merge-train 2 (7 PRs) — owner-approved 2026-07-27. Single entry: chatCore.ts 4955->5006 (#8595, Responses multi-turn image compaction before the context hard-reject). Genuine irreducible growth at the existing compaction chokepoint in handleChatCore — the PR adds a last-resort retry against the concrete budget plus the estimateFinalInputTokens helper, both wired at the pre-existing call site rather than a new branch. Covered by tests/unit/8560-responses-image-compaction.test.ts (4 tests).", "_rebaseline_2026_07_27_v3849_train3": "Merge-train 3 (13 PRs) — owner-approved 2026-07-27. Both entries are genuine irreducible growth at existing chokepoints, not new branches: src/lib/db/apiKeys.ts 1518->1529 (#8805 cx/* ≡ codex/* API-key model permissions); open-sse/handlers/chatCore.ts 5006->5020 (#8806 real response payload into plugin onResponse hooks). Covered by tests/unit/db-apiKeys-crud.test.ts (4 new cases) and the two plugin-hook test files updated in #8806 respectively.", @@ -421,5 +423,6 @@ "_rebaseline_2026_08_01_8964_response_sanitizer": "PR #8964 own growth: responseSanitizer.ts 1115->1128. Keep cost_in_usd_ticks / server_side_tool_usage(_details) through sanitizeResponsesApiResponse allowlists so native xAI tool responses retain usage.", "_rebaseline_2026_08_02_v3850_agentrouter_responses": "Release v3.8.50 AgentRouter/Codex compatibility reconciliation. open-sse/executors/base.ts 1562->1578: #9190 wires AgentRouter's selected Claude/OpenAI/Responses protocol through the existing executor URL, auth, identity-header and fingerprint chokepoints; the reusable alternate resolver remains outside base.ts. open-sse/utils/stream.ts 2887->2889: #9213 evaluates Responses ID and usage normalization independently so response.completed always receives finite usage.total_tokens instead of short-circuiting after an ID rewrite. tests/unit/chatcore-translation-paths.test.ts 2769->2776: #9191 updates the existing Claude-Code bridge assertions for the dynamic AgentRouter wire image. PR #9224 offsets its own chatCore growth by extracting the AgentRouter protocol decisions into chatCore/agentRouterProtocol.ts, leaving chatCore below its frozen ceiling. Covered by agentrouter executor/chatCore protocol tests, chatcore translation-path tests, and responses-commentary-passthrough tests.", "_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_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)." } diff --git a/src/app/(dashboard)/dashboard/tools/agent-bridge/components/SetupWizard.tsx b/src/app/(dashboard)/dashboard/tools/agent-bridge/components/SetupWizard.tsx index 94d3701dcd..0b300448b2 100644 --- a/src/app/(dashboard)/dashboard/tools/agent-bridge/components/SetupWizard.tsx +++ b/src/app/(dashboard)/dashboard/tools/agent-bridge/components/SetupWizard.tsx @@ -293,7 +293,7 @@ export function SetupWizard({ {selectedModels.size > 0 && (

- {selectedModels.size} model{selectedModels.size !== 1 ? "s" : ""} selected. You'll map them to OmniRoute models in the next screen. + {selectedModels.size} model{selectedModels.size !== 1 ? "s" : ""} selected. You'll map them to OmniRoute models in the next screen.

)} diff --git a/tests/unit/catalog-order-contract.test.ts b/tests/unit/catalog-order-contract.test.ts index 3c25d645cd..e1c5c0248b 100644 --- a/tests/unit/catalog-order-contract.test.ts +++ b/tests/unit/catalog-order-contract.test.ts @@ -79,14 +79,14 @@ test("catalog /v1/models: exact provider-grouped order (blocks === distinct owne const conn2 = await seedConnection("anthropic"); const conn3 = await seedConnection("opencode"); - await modelsDb.replaceSyncedAvailableModelsForConnection("openai", (conn1 as any).id, [ + await modelsDb.replaceSyncedAvailableModelsForConnection("openai", (conn1 as { id: string }).id, [ { id: "gpt-4", name: "GPT-4" }, { id: "gpt-3.5-turbo", name: "GPT-3.5 Turbo" }, ]); - await modelsDb.replaceSyncedAvailableModelsForConnection("anthropic", (conn2 as any).id, [ + await modelsDb.replaceSyncedAvailableModelsForConnection("anthropic", (conn2 as { id: string }).id, [ { id: "claude-3-opus", name: "Claude 3 Opus" }, ]); - await modelsDb.replaceSyncedAvailableModelsForConnection("opencode", (conn3 as any).id, [ + await modelsDb.replaceSyncedAvailableModelsForConnection("opencode", (conn3 as { id: string }).id, [ { id: "kimi-k2", name: "Kimi K2" }, { id: "glm-4", name: "GLM-4" }, ]); @@ -120,7 +120,7 @@ test("catalog /v1/models: exact provider-grouped order (blocks === distinct owne test("catalog /v1/models: combo block appears first", async () => { const conn = await seedConnection("openai"); - await modelsDb.replaceSyncedAvailableModelsForConnection("openai", (conn as any).id, [ + await modelsDb.replaceSyncedAvailableModelsForConnection("openai", (conn as { id: string }).id, [ { id: "gpt-4", name: "GPT-4" }, ]); await combosDb.createCombo({ diff --git a/tests/unit/check-rtl-ratchet.test.ts b/tests/unit/check-rtl-ratchet.test.ts new file mode 100644 index 0000000000..b508d3bb99 --- /dev/null +++ b/tests/unit/check-rtl-ratchet.test.ts @@ -0,0 +1,37 @@ +// #8828 RTL layout ratchet — countViolations unit contract. +// Moved from tests/unit/scripts/ (a path no runner collects: the node:test +// globs stop at an explicit subdir list and vitest.config.ts never included +// it, so the file NEVER ran) and converted from vitest to node:test, the +// runner that collects tests/unit/*.test.ts. +import { test } from "node:test"; +import assert from "node:assert/strict"; + +import { countViolations } from "../../scripts/check/check-rtl-ratchet.mjs"; + +test("counts physical directional utilities", () => { + assert.equal(countViolations(''), 1); + assert.equal(countViolations(''), 2); + assert.equal(countViolations('
'), 2); +}); + +test("ignores logical utilities, which already mirror", () => { + assert.equal(countViolations(''), 0); + assert.equal(countViolations('
'), 0); +}); + +test("ignores a class already scoped to an rtl: variant", () => { + assert.equal(countViolations('
'), 0); + // Only the unscoped half of a pair counts. + assert.equal(countViolations('
'), 1); +}); + +test("ignores left/right paired on one element, which spans both edges", () => { + assert.equal(countViolations('
'), 0); + // A lone edge offset is still directional. + assert.equal(countViolations('
'), 1); +}); + +test("does not match unrelated identifiers containing the prefixes", () => { + assert.equal(countViolations('
'), 0); + assert.equal(countViolations("const marginLeft = 2;"), 0); +}); diff --git a/tests/unit/scripts/check-rtl-ratchet.test.ts b/tests/unit/scripts/check-rtl-ratchet.test.ts deleted file mode 100644 index b179a05c76..0000000000 --- a/tests/unit/scripts/check-rtl-ratchet.test.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { describe, it, expect } from "vitest"; - -import { countViolations } from "../../../scripts/check/check-rtl-ratchet.mjs"; - -describe("check-rtl-ratchet — countViolations", () => { - it("counts physical directional utilities", () => { - expect(countViolations('')).toBe(1); - expect(countViolations('')).toBe(2); - expect(countViolations('
')).toBe(2); - }); - - it("ignores logical utilities, which already mirror", () => { - expect(countViolations('')).toBe(0); - expect(countViolations('
')).toBe(0); - }); - - it("ignores a class already scoped to an rtl: variant", () => { - expect(countViolations('
')).toBe(0); - // Only the unscoped half of a pair counts. - expect(countViolations('
')).toBe(1); - }); - - it("ignores left/right paired on one element, which spans both edges", () => { - expect(countViolations('
')).toBe(0); - // A lone edge offset is still directional. - expect(countViolations('
')).toBe(1); - }); - - it("does not match unrelated identifiers containing the prefixes", () => { - expect(countViolations('
')).toBe(0); - expect(countViolations("const marginLeft = 2;")).toBe(0); - }); -});