From 7fb09e4a17172cb692363b096a057a0e97fc9f19 Mon Sep 17 00:00:00 2001 From: Markus Hartung Date: Wed, 19 Aug 2026 18:43:32 -0300 Subject: [PATCH] fix(ci): drain ESLint/dead-code/vitest base-reds on release/v3.8.50 (#9985) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ESLint: freeze 6 React Compiler rules (react-hooks/set-state-in-effect, preserve-manual-memoization, immutability, static-components, refs, purity) newly enabled by eslint-plugin-react-hooks v7 and never suppressed, via --suppress-rule (219 -> 0 errors, same pattern as the existing no-location-assign-relative-destination precedent). - check:dead-code: remove 2 symbols dead since PR #10148 (src/lib/quota/providerCapabilities.ts, ProviderQuotaMonitor interface), rebaseline the unattributable residual +1 (418 -> 416, documented). - tests/unit/autoCombo/tieredRotation.test.ts: widen one test's timeout to 20000ms — 200 synchronous selectProvider() calls were hitting vitest's 5000ms default under shared-devbox contention; assertion unchanged. Refs #9985. --- ...asereds-eslint-deadcode-vitest-20260819.md | 20 + config/quality/eslint-suppressions.json | 677 +++++++++++++++++- config/quality/quality-baseline.json | 3 +- src/lib/quota/providerCapabilities.ts | 37 - src/lib/quota/providerQuotaTelemetry.ts | 6 - tests/unit/autoCombo/tieredRotation.test.ts | 40 +- 6 files changed, 722 insertions(+), 61 deletions(-) create mode 100644 changelog.d/maintenance/release-v3850-basereds-eslint-deadcode-vitest-20260819.md delete mode 100644 src/lib/quota/providerCapabilities.ts diff --git a/changelog.d/maintenance/release-v3850-basereds-eslint-deadcode-vitest-20260819.md b/changelog.d/maintenance/release-v3850-basereds-eslint-deadcode-vitest-20260819.md new file mode 100644 index 0000000000..905d338575 --- /dev/null +++ b/changelog.d/maintenance/release-v3850-basereds-eslint-deadcode-vitest-20260819.md @@ -0,0 +1,20 @@ +- **fix(ci):** drain three more base-reds on `release/v3.8.50` (#9985). ESLint was reporting + 219 errors locally (vs. 25 in the last CI run) — all from `react-hooks/set-state-in-effect`, + `react-hooks/preserve-manual-memoization`, `react-hooks/immutability`, + `react-hooks/static-components`, `react-hooks/refs` and `react-hooks/purity`, six React + Compiler lint rules that `eslint-plugin-react-hooks` v7 turns on by default and that were + never frozen in `config/quality/eslint-suppressions.json` after the dependency bump. Froze + the pre-existing violations for those six rules via ESLint's native + `--suppress-rule`/`--suppressions-location` mechanism (the same pattern already used for + `@next/next/no-location-assign-relative-destination`) — no application code changed, no rule + disabled, only genuinely-new violations stay blocking. `check:dead-code` was at 418 against a + 415 baseline: removed the unused `src/lib/quota/providerCapabilities.ts` file and the unused + `ProviderQuotaMonitor` interface in `providerQuotaTelemetry.ts` (both dead since PR #10148, + 2026-08-18, confirmed via `grep`/knip cross-reference), landing at 416; the residual +1 could + not be attributed to a single recent commit after checking every dead-list entry touched + since the 2026-08-14 baseline measurement, so it is rebaselined with the investigation + recorded in `quality-baseline.json`. `tests/unit/autoCombo/tieredRotation.test.ts`'s + "rotates across all 43 Cerebras connection IDs" case was hitting vitest's 5000ms default + timeout on a 200-iteration synchronous `selectProvider()` loop under shared-devbox + contention (load average 40-60+ observed) — widened its explicit timeout to 20000ms; the + assertion itself is unchanged. diff --git a/config/quality/eslint-suppressions.json b/config/quality/eslint-suppressions.json index 8006cbb2f3..2c4434e5a8 100644 --- a/config/quality/eslint-suppressions.json +++ b/config/quality/eslint-suppressions.json @@ -296,6 +296,109 @@ "src/app/(dashboard)/dashboard/HomePageClient.tsx": { "react-hooks/exhaustive-deps": { "count": 1 + }, + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/a2a/page.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/acp-agents/page.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/activity/ActivityFeedClient.tsx": { + "react-hooks/purity": { + "count": 1 + }, + "react-hooks/refs": { + "count": 1 + }, + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/analytics/CacheHealthTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/analytics/ComboHealthTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/analytics/ProviderUtilizationTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/analytics/RouteExplainabilityTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/api-manager/ApiManagerPageClient.tsx": { + "react-hooks/immutability": { + "count": 4 + }, + "react-hooks/preserve-manual-memoization": { + "count": 2 + }, + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/audit/A2aAuditTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/audit/ComplianceTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/audit/McpAuditTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/batch/components/wizard/CostEstimateStep.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/batch/components/wizard/JsonlValidationStep.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/batch/files/page.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/cache/components/CacheEntriesTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/cache/components/ReasoningCacheTab.tsx": { + "react-hooks/purity": { + "count": 1 + }, + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/cache/page.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 } }, "src/app/(dashboard)/dashboard/cli-agents/CliAgentsPageClient.tsx": { @@ -306,6 +409,119 @@ "src/app/(dashboard)/dashboard/cli-code/components/AntigravityToolCard.tsx": { "react-hooks/exhaustive-deps": { "count": 1 + }, + "react-hooks/immutability": { + "count": 3 + }, + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/cli-code/components/ClaudeClassifierCompatToggle.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/cli-code/components/ClaudeToolCard.tsx": { + "react-hooks/immutability": { + "count": 3 + }, + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/cli-code/components/CliProfileAutoSyncToggles.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/cli-code/components/ClineToolCard.tsx": { + "react-hooks/immutability": { + "count": 3 + }, + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/cli-code/components/CliproxyapiToolCard.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/cli-code/components/CodexToolCard.tsx": { + "react-hooks/immutability": { + "count": 4 + }, + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/cli-code/components/DroidToolCard.tsx": { + "react-hooks/immutability": { + "count": 3 + }, + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/cli-code/components/HermesAgentToolCard.tsx": { + "react-hooks/immutability": { + "count": 1 + }, + "react-hooks/purity": { + "count": 1 + }, + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/cli-code/components/KiloToolCard.tsx": { + "react-hooks/immutability": { + "count": 3 + }, + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/cli-code/components/OpenClawToolCard.tsx": { + "react-hooks/immutability": { + "count": 3 + }, + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/combos/ComboControlCenterClient.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/combos/page.tsx": { + "react-hooks/immutability": { + "count": 1 + }, + "react-hooks/set-state-in-effect": { + "count": 7 + } + }, + "src/app/(dashboard)/dashboard/conductor/ConductorPageClient.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/conductor/FaroChat.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/conversations/page.tsx": { + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/costs/components/ApiKeyUsageLimitCard.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 } }, "src/app/(dashboard)/dashboard/costs/costExplorerUtils.ts": { @@ -313,11 +529,258 @@ "count": 1 } }, + "src/app/(dashboard)/dashboard/costs/quota-share/components/PoolWizard.tsx": { + "react-hooks/set-state-in-effect": { + "count": 3 + } + }, + "src/app/(dashboard)/dashboard/costs/quota-share/hooks/usePoolUsage.ts": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/costs/quota-share/hooks/usePools.ts": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/costs/useApiKeyUsageLimits.ts": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/discovery/DiscoveryPageClient.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.tsx": { + "react-hooks/immutability": { + "count": 3 + } + }, + "src/app/(dashboard)/dashboard/endpoint/components/A2ADashboard.tsx": { + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/endpoint/components/MCPDashboard.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/endpoint/components/NotionSourceCard.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/endpoint/components/ObsidianSourceCard.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/free-provider-rankings/page.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/health/ProviderHealthAutopilotCard.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/health/ProviderHealthMatrixCard.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/health/TelemetryCard.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/mcp/page.tsx": { + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/memory/components/EditMemoryModal.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/memory/components/QdrantConfigCard.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/memory/components/tabs/MemoriesTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/memory/hooks/useEngineStatus.ts": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/memory/hooks/useMemorySettings.ts": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, "src/app/(dashboard)/dashboard/playground/components/tabs/ApiTab.tsx": { "react-hooks/exhaustive-deps": { "count": 1 } }, + "src/app/(dashboard)/dashboard/plugins/[name]/config/page.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/plugins/page.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/provider-stats/page.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + }, + "react-hooks/static-components": { + "count": 7 + } + }, + "src/app/(dashboard)/dashboard/providers/[id]/components/CustomModelsSection.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/providers/[id]/components/ModelCompatPopover.tsx": { + "react-hooks/refs": { + "count": 4 + }, + "react-hooks/set-state-in-effect": { + "count": 3 + } + }, + "src/app/(dashboard)/dashboard/providers/[id]/components/ProviderCcAliasSection.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/providers/[id]/components/ProviderInterceptionSection.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/providers/[id]/components/ProviderParamFilterSection.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/providers/[id]/components/modals/EditCompatibleNodeModal.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/providers/[id]/components/modals/EditConnectionModal.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/providers/[id]/hooks/useProviderConnections.ts": { + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/providers/[id]/hooks/useProviderSettings.ts": { + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/providers/components/AddCompatibleProviderModal.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/providers/hooks/useProviderModels.ts": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/providers/hooks/useProviderUrlFilters.ts": { + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/providers/hooks/useRiskAcknowledged.ts": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/providers/page.tsx": { + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/providers/services/components/DarioAccountPanel.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/providers/services/components/NinerouterModelList.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/radar/RadarCatalogTable.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/radar/intel/page.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/radar/page.tsx": { + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/radar/setup/page.tsx": { + "react-hooks/preserve-manual-memoization": { + "count": 1 + }, + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/relay/RelayProxyClient.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/resilience/connections/components/ResilienceConnectionsClient.tsx": { + "react-hooks/purity": { + "count": 1 + }, + "react-hooks/refs": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/runtime/components/ModelCooldownsCard.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/settings/components/AccessTokensTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, "src/app/(dashboard)/dashboard/settings/components/AppearanceTab.tsx": { "@next/next/no-img-element": { "count": 4 @@ -326,16 +789,75 @@ "src/app/(dashboard)/dashboard/settings/components/AuthzSection.tsx": { "no-restricted-syntax": { "count": 1 + }, + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/settings/components/FallbackChainsEditor.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/settings/components/IPFilterSection.tsx": { + "react-hooks/immutability": { + "count": 1 } }, "src/app/(dashboard)/dashboard/settings/components/MitmProxyTab.tsx": { "@next/next/no-html-link-for-pages": { "count": 1 + }, + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/settings/components/ModelCapabilityOverridesTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/settings/components/ModelsDevSyncTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/settings/components/OneproxyTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/settings/components/PayloadRulesTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/settings/components/PoliciesPanel.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/settings/components/PricingTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 2 } }, "src/app/(dashboard)/dashboard/settings/components/ProviderAccountRoutingCard.tsx": { "react-hooks/exhaustive-deps": { "count": 1 + }, + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 7 + } + }, + "src/app/(dashboard)/dashboard/settings/components/RoutingStrategyCard.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 } }, "src/app/(dashboard)/dashboard/settings/components/SessionInfoCard.tsx": { @@ -343,11 +865,92 @@ "count": 1 } }, + "src/app/(dashboard)/dashboard/settings/components/SystemStorageTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/settings/components/proxy/GlobalConfigTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/settings/components/proxy/SubscriptionTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, "src/app/(dashboard)/dashboard/tools/agent-bridge/components/AgentList.tsx": { "no-restricted-syntax": { "count": 3 } }, + "src/app/(dashboard)/dashboard/tools/agent-bridge/components/ModelSelectorModal.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/tools/agent-bridge/components/SetupWizard.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/tools/traffic-inspector/components/CustomHostsManager.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/translator/components/MonitorTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/usage/components/EvalsTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/usage/components/ProviderLimits/useCodexResetCreditRedemption.ts": { + "react-hooks/immutability": { + "count": 2 + } + }, + "src/app/(dashboard)/dashboard/usage/components/RateLimitStatus.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/usage/components/SessionsTab.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/webhooks/WebhooksPageClient.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/webhooks/components/AddWebhookWizard.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/dashboard/webhooks/components/WebhookDeliveriesPanel.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/(dashboard)/home/ProviderQuotaWidget.tsx": { + "react-hooks/purity": { + "count": 1 + }, + "react-hooks/refs": { + "count": 1 + }, + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, "src/app/(dashboard)/home/page.tsx": { "no-restricted-imports": { "count": 1 @@ -1003,6 +1606,16 @@ "count": 1 } }, + "src/app/global-error.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/app/status/page.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, "src/domain/costRules.ts": { "no-restricted-syntax": { "count": 1 @@ -1286,14 +1899,50 @@ "count": 1 } }, + "src/shared/components/KiroAuthModal.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, "src/shared/components/LanguageSelector.tsx": { "@next/next/no-img-element": { "count": 1 } }, + "src/shared/components/ModelSelectModal.tsx": { + "react-hooks/set-state-in-effect": { + "count": 4 + } + }, + "src/shared/components/OAuthModal.tsx": { + "react-hooks/set-state-in-effect": { + "count": 4 + } + }, + "src/shared/components/PricingModal.tsx": { + "react-hooks/immutability": { + "count": 1 + } + }, "src/shared/components/ProxyConfigModal.tsx": { "react-hooks/exhaustive-deps": { "count": 1 + }, + "react-hooks/immutability": { + "count": 1 + }, + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/shared/components/ReasoningRoutingRules.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/shared/components/RequestLoggerDetail.sections.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 } }, "src/shared/components/RequestLoggerV2.tsx": { @@ -1304,6 +1953,27 @@ "src/shared/components/Sidebar.tsx": { "@next/next/no-img-element": { "count": 1 + }, + "react-hooks/set-state-in-effect": { + "count": 2 + } + }, + "src/shared/components/UsageStats.tsx": { + "react-hooks/preserve-manual-memoization": { + "count": 1 + }, + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/shared/components/analytics/useProviderDailyUsage.ts": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, + "src/shared/components/compression/ComboCompressionModeSelect.tsx": { + "react-hooks/set-state-in-effect": { + "count": 1 } }, "src/shared/contracts/quota.ts": { @@ -1311,6 +1981,11 @@ "count": 1 } }, + "src/shared/hooks/cli/useToolBatchStatuses.ts": { + "react-hooks/set-state-in-effect": { + "count": 1 + } + }, "src/shared/services/apiKeyResolver.ts": { "no-restricted-imports": { "count": 1 @@ -3304,4 +3979,4 @@ "count": 5 } } -} +} \ No newline at end of file diff --git a/config/quality/quality-baseline.json b/config/quality/quality-baseline.json index c8cbd07d94..3c4b9e5191 100644 --- a/config/quality/quality-baseline.json +++ b/config/quality/quality-baseline.json @@ -102,8 +102,9 @@ "_rebaseline_2026_07_28_v3849_release": "75.5 -> 99 (+23.5). Aperto EXIGIDO pelo modo --require-tighten do ratchet: a métrica melhorou de verdade no ciclo v3.8.49. A causa é o workflow assíncrono de tradução, que finalmente alcançou o denominador em EN — as rebaselines anteriores (v3.8.39/.44/.47) foram todas afrouxamentos registrando o atraso das traduções, e agora ele foi pago. O coletor SUBTRAI os placeholders (present - placeholder em scripts/quality/collect-metrics.mjs), então os 317 marcadores __MISSING__ que esta release introduziu para o drift de valor já estão descontados dos 99 — o número é honesto, não inflado por placeholder. Medido pelo collect-metrics do CI no run 30404226939." }, "deadExports": { - "value": 415, + "value": 416, "direction": "down", + "_rebaseline_2026_08_19_v3850_basereds_9985": "415 -> 416. Measured on release/v3.8.50 tip 14a480453 during the #9985 base-red drain. Removed the 2 genuinely-dead symbols traced to a specific recent change (PR #10148, 2026-08-18): the unused src/lib/quota/providerCapabilities.ts file and the unused ProviderQuotaMonitor interface in providerQuotaTelemetry.ts (418 -> 416). The remaining +1 could not be attributed to a single recent commit after checking every dead-list entry touched since the 2026-08-14 baseline measurement (most are pre-existing debt on files edited for unrelated reasons); rebaselining the residual 1 rather than guessing at removals. Structural cleanup stays tracked in #3501.", "_rebaseline_2026_08_09_v3850_post_sweep": "227 -> 230. Measured by npm run check:dead-code on the unmodified release/v3.8.50 tip 382449d593 during the mandatory --full-ci pre-flight. The +3 is inherited cycle drift from the authorized merge sweep; this repair adds no production exports. Rebaseline records the actual tip so ci.yml quality-gate can run, while structural cleanup remains separate debt.", "_rebaseline_2026_07_01_v3843_release": "225->227 (+2). v3.8.43 cycle drift, surfaced in the Quality Ratchet job after eslintWarnings was rebaselined (check:dead-code runs there). 227 = measured by check:dead-code (knip) on the release tip 4635076eb. The 5 CI fixes add 0 dead exports: safeHttpHref in linkify.ts is module-local AND used (called by linkifyText); no new exports; test files are not scanned. Tighten via --update next cycle.", "dedicatedGate": true, diff --git a/src/lib/quota/providerCapabilities.ts b/src/lib/quota/providerCapabilities.ts deleted file mode 100644 index cc5ec32a76..0000000000 --- a/src/lib/quota/providerCapabilities.ts +++ /dev/null @@ -1,37 +0,0 @@ -export interface ProviderCapabilities { - providerId: string; - quotaApi: boolean; - usageApi: boolean; - rateLimitHeaders: boolean; - streaming: boolean; - toolUse: boolean; - coding: boolean; - vision: boolean; - longContext: boolean; -} - -const registry = new Map(); - -export function registerProviderCapabilities(capabilities: ProviderCapabilities): void { - registry.set(capabilities.providerId, { ...capabilities }); -} - -export function getProviderCapabilities(providerId: string): ProviderCapabilities { - return ( - registry.get(providerId) ?? { - providerId, - quotaApi: false, - usageApi: false, - rateLimitHeaders: false, - streaming: false, - toolUse: false, - coding: false, - vision: false, - longContext: false, - } - ); -} - -export function listProviderCapabilities(): ProviderCapabilities[] { - return [...registry.values()].map((capabilities) => ({ ...capabilities })); -} diff --git a/src/lib/quota/providerQuotaTelemetry.ts b/src/lib/quota/providerQuotaTelemetry.ts index cd9a29f2ad..05955690c6 100644 --- a/src/lib/quota/providerQuotaTelemetry.ts +++ b/src/lib/quota/providerQuotaTelemetry.ts @@ -48,12 +48,6 @@ export interface ProviderConnectionForQuota { [key: string]: unknown; } -export interface ProviderQuotaMonitor { - providerId: string; - supportedDimensions(): Promise; - fetchQuotaState(connection: ProviderConnectionForQuota): Promise; -} - export type QuotaSourceKind = "provider_api" | "response_headers" | "configured" | "estimated" | "unknown"; diff --git a/tests/unit/autoCombo/tieredRotation.test.ts b/tests/unit/autoCombo/tieredRotation.test.ts index dd2974b7bb..ae5142a7d5 100644 --- a/tests/unit/autoCombo/tieredRotation.test.ts +++ b/tests/unit/autoCombo/tieredRotation.test.ts @@ -175,23 +175,31 @@ describe("scorePool with connectionDensity", () => { }); describe("Per-Connection Rotation", () => { - it("rotates across all 43 Cerebras connection IDs, not just one", () => { - const cerebrasCandidates: ProviderCandidate[] = Array.from({ length: 43 }, (_, i) => - makeCandidate({ - provider: "cerebras", - model: "llama-3.1-70b", - connectionId: `cerebras-conn-${i + 1}`, - }) - ); - const config = makeConfig("smart"); + it( + "rotates across all 43 Cerebras connection IDs, not just one", + () => { + const cerebrasCandidates: ProviderCandidate[] = Array.from({ length: 43 }, (_, i) => + makeCandidate({ + provider: "cerebras", + model: "llama-3.1-70b", + connectionId: `cerebras-conn-${i + 1}`, + }) + ); + const config = makeConfig("smart"); - const seenConnections = new Set(); - for (let i = 0; i < 200; i++) { - const result = selectProvider(config, cerebrasCandidates, "coding"); - if (result.connectionId) seenConnections.add(result.connectionId); - } - expect(seenConnections.size).toBeGreaterThanOrEqual(10); - }); + const seenConnections = new Set(); + for (let i = 0; i < 200; i++) { + const result = selectProvider(config, cerebrasCandidates, "coding"); + if (result.connectionId) seenConnections.add(result.connectionId); + } + expect(seenConnections.size).toBeGreaterThanOrEqual(10); + }, + // 200 synchronous selectProvider() calls over a 43-connection pool are CPU-bound and + // vitest's 5000ms default is too tight under shared-devbox contention (load avg 40+ + // observed alongside parallel test/tsc/lint runs) — the assertion itself is unchanged, + // only the execution-time budget is widened. Refs #9985. + 20000 + ); it("different combos maintain independent round-robin state", () => { const candidates: ProviderCandidate[] = Array.from({ length: 5 }, (_, i) =>