Repository navigation
fix(models): don't auto-hide rate-limited/timeout models on Test All - #3849
Conversation
When 'Auto-hide failed models' is on and a user runs Test All, a single throttled batch could silently hide working models. Rate-limit (429) and timeout failures are transient — the model is fine, the provider was just busy during the parallel test sweep. Hidden state persists across restarts and removes the model from /v1/models, so a transient blip becomes a permanent catalog gap that the user can only recover from by editing the DB or hand-toggling each row. This is especially severe on subscription-tier providers (Kiro, etc.) where parallel Test All reliably trips per-account rate limits. Fix: skip auto-hide for entries flagged rateLimited or isTimeout. Genuine failures (invalid model, schema mismatch, auth) are still hidden — the intended use of the toggle. Updated the regression test accordingly.
There was a problem hiding this comment.
Code Review
This pull request updates the auto-hide policy for batch model testing to prevent transient failures (like rate limits or timeouts) from triggering auto-hiding. However, the review identifies a critical bug where skipped or untested models (where the test entry is null or undefined) are also treated as persistent failures and silently auto-hidden. The reviewer suggests explicitly checking for a confirmed 'error' status before hiding a model, and updating the corresponding unit tests to assert that missing or empty entries are not hidden.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const ok = entry?.status === "ok"; | ||
| const transient = Boolean(entry?.rateLimited || entry?.isTimeout); | ||
| return { | ||
| status: ok ? "ok" : "error", | ||
| // User opted for "hide every failure": any non-ok result is auto-hidden when | ||
| // the toggle is on, including rate-limited / timed-out failures. | ||
| shouldHide: !ok && autoHideFailed, | ||
| // Hide only persistent failures. Transient (rate-limited, timeout) are | ||
| // surfaced on the icon but kept visible so a single throttled batch test | ||
| // does not silently wipe the catalog. | ||
| shouldHide: !ok && autoHideFailed && !transient, | ||
| }; |
There was a problem hiding this comment.
Critical Bug: Skipped or Untested Models are Silently Auto-Hidden
When a batch test is run, there are two scenarios where a model's test entry (entry) can be undefined or null:
- Early Stopping: The batch test runner in
src/app/api/models/test-all/route.tsstops early if it encounters consecutive rate limits (CONSECUTIVE_RATE_LIMIT_STOP_THRESHOLD). Any remaining models in the list are skipped and will not have an entry in the response. - API/Network Failures: If the
/api/models/test-allrequest returns a non-200 response (e.g., a 500 error or validation error) but succeeds at the HTTP/JSON level,result.resultswill beundefined, meaningentryisundefinedfor all models.
Under the current implementation, if entry is undefined or null, ok is evaluated as false, and transient is false. If autoHideFailed is enabled, shouldHide evaluates to true. This causes the client to silently auto-hide all skipped or untested models, permanently removing them from the catalog and /v1/models!
To prevent this, we should only auto-hide a model if we have an explicit, confirmed failure status (status: "error") from the test runner.
const ok = entry?.status === "ok";
const isError = entry?.status === "error";
const transient = Boolean(entry?.rateLimited || entry?.isTimeout);
return {
status: ok ? "ok" : "error",
// Hide only persistent failures. Transient (rate-limited, timeout) are
// surfaced on the icon but kept visible so a single throttled batch test
// does not silently wipe the catalog. Untested/skipped models (where entry is
// undefined/null due to early stop) must not be hidden.
shouldHide: isError && autoHideFailed && !transient,
};| assert.deepEqual(evaluateTestAllEntry({ status: "error", rateLimited: true }, false), { | ||
| status: "error", | ||
| shouldHide: false, |
There was a problem hiding this comment.
Update Test for Missing/Null/Empty Entries
Since we should only auto-hide models with an explicit "error" status (to prevent skipped/untested models from being hidden when a batch test stops early), the test "missing / null / empty entry is treated as a failure" at the bottom of this file (lines 57-63) needs to be updated to assert shouldHide: false.
Currently, that test is outside the modified diff hunk, so we cannot provide a direct code suggestion for it, but please update it manually to:
test("missing / null / empty entry is treated as a failure but NOT hidden", () => {
for (const entry of [undefined, null, {}]) {
const out = evaluateTestAllEntry(entry, true);
assert.equal(out.status, "error", `entry=${JSON.stringify(entry)} → error`);
assert.equal(out.shouldHide, false);
}
});…ll-no-autohide-transient-failures
…ard (cheaper-inference#3849) providerPageHelpers.ts 939→955 (+16: JSDoc on auto-hide policy + transient guard). Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
058946b
into
cheaper-inference:release/v3.8.25
|
Merged into |
…ributors Audited every commit since v3.8.24 and filled the gaps the [3.8.25] section was missing: a New Features section (compression engines + Compression Studios #3848, compression UI #3860, injection-guard #3857, kiro discovery #3836, Veo #3839, mimocode proxy #3837, Arena ELO flag #3821), 9 more Fixed entries (#3811/#3807/#3759/#3849/#3838/#3835/#3814/#3820/#3819), a Security section (CCR IDOR #3859, supply-chain #3824), and an Internal/Quality section. Every contributor and issue reporter is now credited.
* chore(release): continue v3.8.25 development cycle after main code-sync (r5) main fast-forwarded to release/v3.8.25 (#3863): unblocked Build+Docker via #3864, plus #3837 (mimocode proxy) and #3862 (trivy bump). This marker re-opens the umbrella PR for further v3.8.25 work. No version bump. * fix(db): persist the Keep-latest-backups retention setting (#3834) (#3867) * fix(oauth): clear GitLab Duo setup message instead of 500 (#3861) (#3868) * test(oauth): prove refresh_token preserved on real gemini-cli/antigravity dispatch (#3850) (#3869) * feat(compression-ui): unified compression config UI — per-engine pages + combos editor + menu + WS default-on (#3860) Integrated into release/v3.8.25 — feat(compression-ui): unified compression configuration UI (Compression Hub + per-engine Lite/Aggressive/Ultra pages + combos editor + sidebar entry + live-WS default-on). File-size re-baselined for sidebarVisibility.ts/chatCore.ts growth; orphan ws test relocated to a collected path. * docs(changelog): complete the v3.8.25 release notes + credit all contributors Audited every commit since v3.8.24 and filled the gaps the [3.8.25] section was missing: a New Features section (compression engines + Compression Studios #3848, compression UI #3860, injection-guard #3857, kiro discovery #3836, Veo #3839, mimocode proxy #3837, Arena ELO flag #3821), 9 more Fixed entries (#3811/#3807/#3759/#3849/#3838/#3835/#3814/#3820/#3819), a Security section (CCR IDOR #3859, supply-chain #3824), and an Internal/Quality section. Every contributor and issue reporter is now credited. * docs(changelog): restore + complete the v3.8.25 release notes Re-adds CHANGELOG.md (a prior server-side commit accidentally dropped it) with the complete, audited [3.8.25] section: New Features, the full Fixed list, Security & Hardening, and Internal/Quality — every contributor and issue reporter credited. * chore(release): finalize v3.8.25 — reconcile CHANGELOG + i18n mirrors, document OMNIROUTE_MAX_PENDING_MIGRATIONS, green the unit suite Release-gate reconciliation for v3.8.25: - CHANGELOG: dated 2026-06-14, linked #3826, rolled up file-size re-baselines (#3823/#3833), recorded the test-greening; re-synced all 41 i18n CHANGELOG mirrors. - Documented OMNIROUTE_MAX_PENDING_MIGRATIONS (#3416) in .env.example + ENVIRONMENT.md. - Greened the unit suite (was merged red on 4 CI shards): aligned 10 stale tests to this cycle's intended behavior (#3838/#3822/#3501/SOCKS5/Vertex-Express/Antigravity) and the same-provider 503 fall-through test; de-flaked the compression benchmark reproducibility and ServiceSupervisor crash tests. No production code changed. * ci(security): clear OpenSSF Scorecard code-scanning noise + harden workflow token permissions The Security tab held 155 open alerts, ALL from the advisory OpenSSF Scorecard tool (#3824) — supply-chain/posture scores, not code vulnerabilities — which drowned out real CodeQL findings. - scorecard.yml: stop uploading SARIF to the code-scanning tab (drop the upload-sarif step + the now-unused security-events: write). The run still produces the OpenSSF badge (publish_results) and a downloadable SARIF artifact. - TokenPermissions hardening (the high-severity, genuinely-valuable subset): set each workflow's top-level token to read-only and grant the exact writes at the job level that needs them — npm-publish (id-token/packages on publish jobs), docker-publish (packages on build), electron-release (contents on build/release, id-token/packages on publish-npm), build-fork (packages on build), claude (empty top-level; job grants its own). The 155 existing alerts were dismissed. Not adopting repo-wide SHA-pinning (143 PinnedDependencies advisories) — declined. * test(integration): align stale wiring/socks5 integration tests to this cycle's behavior These were red on the CI Integration job (pre-existing). No production code changed: - integration-wiring: the combos page no longer renders a per-page EmailPrivacyToggle (#3822 consolidated it into Settings → Appearance); the provider-detail test-result masking and upstream-proxy copy moved to decomposed components (#3501 BatchTestResultsModal / UpstreamProxyCard) — assertions now read the owning files. - api-routes-critical: SOCKS5 is now enabled by default (opt-out), so the disabled- rejection test must set ENABLE_SOCKS5_PROXY=false explicitly (an unset env now means enabled). (The ~32 live-Gemini integration tests are gated on OMNIROUTE_API_KEY and skip in CI; they only 'fail' locally when that key is present without a running server.)
…s on Test All (cheaper-inference#3849) With Auto-hide failed models on (default), a Test All sweep across 10+ models in parallel reliably trips per-account rate limits on subscription-tier providers, and the 429'd/timed-out models were auto-hidden — silently removing working models from /v1/models with no easy recovery. evaluateTestAllEntry now surfaces transient failures (rateLimited/isTimeout) as an 'error' icon but keeps them visible; only genuine (non-transient) failures are still auto-hidden. Integrated into release/v3.8.25. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
* chore(release): continue v3.8.25 development cycle after main code-sync (r5) main fast-forwarded to release/v3.8.25 (cheaper-inference#3863): unblocked Build+Docker via cheaper-inference#3864, plus cheaper-inference#3837 (mimocode proxy) and cheaper-inference#3862 (trivy bump). This marker re-opens the umbrella PR for further v3.8.25 work. No version bump. * fix(db): persist the Keep-latest-backups retention setting (cheaper-inference#3834) (cheaper-inference#3867) * fix(oauth): clear GitLab Duo setup message instead of 500 (cheaper-inference#3861) (cheaper-inference#3868) * test(oauth): prove refresh_token preserved on real gemini-cli/antigravity dispatch (cheaper-inference#3850) (cheaper-inference#3869) * feat(compression-ui): unified compression config UI — per-engine pages + combos editor + menu + WS default-on (cheaper-inference#3860) Integrated into release/v3.8.25 — feat(compression-ui): unified compression configuration UI (Compression Hub + per-engine Lite/Aggressive/Ultra pages + combos editor + sidebar entry + live-WS default-on). File-size re-baselined for sidebarVisibility.ts/chatCore.ts growth; orphan ws test relocated to a collected path. * docs(changelog): complete the v3.8.25 release notes + credit all contributors Audited every commit since v3.8.24 and filled the gaps the [3.8.25] section was missing: a New Features section (compression engines + Compression Studios cheaper-inference#3848, compression UI cheaper-inference#3860, injection-guard cheaper-inference#3857, kiro discovery cheaper-inference#3836, Veo cheaper-inference#3839, mimocode proxy cheaper-inference#3837, Arena ELO flag cheaper-inference#3821), 9 more Fixed entries (cheaper-inference#3811/cheaper-inference#3807/cheaper-inference#3759/cheaper-inference#3849/cheaper-inference#3838/cheaper-inference#3835/cheaper-inference#3814/cheaper-inference#3820/cheaper-inference#3819), a Security section (CCR IDOR cheaper-inference#3859, supply-chain cheaper-inference#3824), and an Internal/Quality section. Every contributor and issue reporter is now credited. * docs(changelog): restore + complete the v3.8.25 release notes Re-adds CHANGELOG.md (a prior server-side commit accidentally dropped it) with the complete, audited [3.8.25] section: New Features, the full Fixed list, Security & Hardening, and Internal/Quality — every contributor and issue reporter credited. * chore(release): finalize v3.8.25 — reconcile CHANGELOG + i18n mirrors, document OMNIROUTE_MAX_PENDING_MIGRATIONS, green the unit suite Release-gate reconciliation for v3.8.25: - CHANGELOG: dated 2026-06-14, linked cheaper-inference#3826, rolled up file-size re-baselines (cheaper-inference#3823/cheaper-inference#3833), recorded the test-greening; re-synced all 41 i18n CHANGELOG mirrors. - Documented OMNIROUTE_MAX_PENDING_MIGRATIONS (cheaper-inference#3416) in .env.example + ENVIRONMENT.md. - Greened the unit suite (was merged red on 4 CI shards): aligned 10 stale tests to this cycle's intended behavior (cheaper-inference#3838/cheaper-inference#3822/cheaper-inference#3501/SOCKS5/Vertex-Express/Antigravity) and the same-provider 503 fall-through test; de-flaked the compression benchmark reproducibility and ServiceSupervisor crash tests. No production code changed. * ci(security): clear OpenSSF Scorecard code-scanning noise + harden workflow token permissions The Security tab held 155 open alerts, ALL from the advisory OpenSSF Scorecard tool (cheaper-inference#3824) — supply-chain/posture scores, not code vulnerabilities — which drowned out real CodeQL findings. - scorecard.yml: stop uploading SARIF to the code-scanning tab (drop the upload-sarif step + the now-unused security-events: write). The run still produces the OpenSSF badge (publish_results) and a downloadable SARIF artifact. - TokenPermissions hardening (the high-severity, genuinely-valuable subset): set each workflow's top-level token to read-only and grant the exact writes at the job level that needs them — npm-publish (id-token/packages on publish jobs), docker-publish (packages on build), electron-release (contents on build/release, id-token/packages on publish-npm), build-fork (packages on build), claude (empty top-level; job grants its own). The 155 existing alerts were dismissed. Not adopting repo-wide SHA-pinning (143 PinnedDependencies advisories) — declined. * test(integration): align stale wiring/socks5 integration tests to this cycle's behavior These were red on the CI Integration job (pre-existing). No production code changed: - integration-wiring: the combos page no longer renders a per-page EmailPrivacyToggle (cheaper-inference#3822 consolidated it into Settings → Appearance); the provider-detail test-result masking and upstream-proxy copy moved to decomposed components (cheaper-inference#3501 BatchTestResultsModal / UpstreamProxyCard) — assertions now read the owning files. - api-routes-critical: SOCKS5 is now enabled by default (opt-out), so the disabled- rejection test must set ENABLE_SOCKS5_PROXY=false explicitly (an unset env now means enabled). (The ~32 live-Gemini integration tests are gated on OMNIROUTE_API_KEY and skip in CI; they only 'fail' locally when that key is present without a running server.)
…s on Test All (cheaper-inference#3849) With Auto-hide failed models on (default), a Test All sweep across 10+ models in parallel reliably trips per-account rate limits on subscription-tier providers, and the 429'd/timed-out models were auto-hidden — silently removing working models from /v1/models with no easy recovery. evaluateTestAllEntry now surfaces transient failures (rateLimited/isTimeout) as an 'error' icon but keeps them visible; only genuine (non-transient) failures are still auto-hidden. Integrated into release/v3.8.25. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
* chore(release): continue v3.8.25 development cycle after main code-sync (r5) main fast-forwarded to release/v3.8.25 (cheaper-inference#3863): unblocked Build+Docker via cheaper-inference#3864, plus cheaper-inference#3837 (mimocode proxy) and cheaper-inference#3862 (trivy bump). This marker re-opens the umbrella PR for further v3.8.25 work. No version bump. * fix(db): persist the Keep-latest-backups retention setting (cheaper-inference#3834) (cheaper-inference#3867) * fix(oauth): clear GitLab Duo setup message instead of 500 (cheaper-inference#3861) (cheaper-inference#3868) * test(oauth): prove refresh_token preserved on real gemini-cli/antigravity dispatch (cheaper-inference#3850) (cheaper-inference#3869) * feat(compression-ui): unified compression config UI — per-engine pages + combos editor + menu + WS default-on (cheaper-inference#3860) Integrated into release/v3.8.25 — feat(compression-ui): unified compression configuration UI (Compression Hub + per-engine Lite/Aggressive/Ultra pages + combos editor + sidebar entry + live-WS default-on). File-size re-baselined for sidebarVisibility.ts/chatCore.ts growth; orphan ws test relocated to a collected path. * docs(changelog): complete the v3.8.25 release notes + credit all contributors Audited every commit since v3.8.24 and filled the gaps the [3.8.25] section was missing: a New Features section (compression engines + Compression Studios cheaper-inference#3848, compression UI cheaper-inference#3860, injection-guard cheaper-inference#3857, kiro discovery cheaper-inference#3836, Veo cheaper-inference#3839, mimocode proxy cheaper-inference#3837, Arena ELO flag cheaper-inference#3821), 9 more Fixed entries (cheaper-inference#3811/cheaper-inference#3807/cheaper-inference#3759/cheaper-inference#3849/cheaper-inference#3838/cheaper-inference#3835/cheaper-inference#3814/cheaper-inference#3820/cheaper-inference#3819), a Security section (CCR IDOR cheaper-inference#3859, supply-chain cheaper-inference#3824), and an Internal/Quality section. Every contributor and issue reporter is now credited. * docs(changelog): restore + complete the v3.8.25 release notes Re-adds CHANGELOG.md (a prior server-side commit accidentally dropped it) with the complete, audited [3.8.25] section: New Features, the full Fixed list, Security & Hardening, and Internal/Quality — every contributor and issue reporter credited. * chore(release): finalize v3.8.25 — reconcile CHANGELOG + i18n mirrors, document OMNIROUTE_MAX_PENDING_MIGRATIONS, green the unit suite Release-gate reconciliation for v3.8.25: - CHANGELOG: dated 2026-06-14, linked cheaper-inference#3826, rolled up file-size re-baselines (cheaper-inference#3823/cheaper-inference#3833), recorded the test-greening; re-synced all 41 i18n CHANGELOG mirrors. - Documented OMNIROUTE_MAX_PENDING_MIGRATIONS (cheaper-inference#3416) in .env.example + ENVIRONMENT.md. - Greened the unit suite (was merged red on 4 CI shards): aligned 10 stale tests to this cycle's intended behavior (cheaper-inference#3838/cheaper-inference#3822/cheaper-inference#3501/SOCKS5/Vertex-Express/Antigravity) and the same-provider 503 fall-through test; de-flaked the compression benchmark reproducibility and ServiceSupervisor crash tests. No production code changed. * ci(security): clear OpenSSF Scorecard code-scanning noise + harden workflow token permissions The Security tab held 155 open alerts, ALL from the advisory OpenSSF Scorecard tool (cheaper-inference#3824) — supply-chain/posture scores, not code vulnerabilities — which drowned out real CodeQL findings. - scorecard.yml: stop uploading SARIF to the code-scanning tab (drop the upload-sarif step + the now-unused security-events: write). The run still produces the OpenSSF badge (publish_results) and a downloadable SARIF artifact. - TokenPermissions hardening (the high-severity, genuinely-valuable subset): set each workflow's top-level token to read-only and grant the exact writes at the job level that needs them — npm-publish (id-token/packages on publish jobs), docker-publish (packages on build), electron-release (contents on build/release, id-token/packages on publish-npm), build-fork (packages on build), claude (empty top-level; job grants its own). The 155 existing alerts were dismissed. Not adopting repo-wide SHA-pinning (143 PinnedDependencies advisories) — declined. * test(integration): align stale wiring/socks5 integration tests to this cycle's behavior These were red on the CI Integration job (pre-existing). No production code changed: - integration-wiring: the combos page no longer renders a per-page EmailPrivacyToggle (cheaper-inference#3822 consolidated it into Settings → Appearance); the provider-detail test-result masking and upstream-proxy copy moved to decomposed components (cheaper-inference#3501 BatchTestResultsModal / UpstreamProxyCard) — assertions now read the owning files. - api-routes-critical: SOCKS5 is now enabled by default (opt-out), so the disabled- rejection test must set ENABLE_SOCKS5_PROXY=false explicitly (an unset env now means enabled). (The ~32 live-Gemini integration tests are gated on OMNIROUTE_API_KEY and skip in CI; they only 'fail' locally when that key is present without a running server.)
…ributors Audited every commit since v3.8.24 and filled the gaps the [3.8.25] section was missing: a New Features section (compression engines + Compression Studios cheaper-inference#3848, compression UI cheaper-inference#3860, injection-guard cheaper-inference#3857, kiro discovery cheaper-inference#3836, Veo cheaper-inference#3839, mimocode proxy cheaper-inference#3837, Arena ELO flag cheaper-inference#3821), 9 more Fixed entries (cheaper-inference#3811/cheaper-inference#3807/cheaper-inference#3759/cheaper-inference#3849/cheaper-inference#3838/cheaper-inference#3835/cheaper-inference#3814/cheaper-inference#3820/cheaper-inference#3819), a Security section (CCR IDOR cheaper-inference#3859, supply-chain cheaper-inference#3824), and an Internal/Quality section. Every contributor and issue reporter is now credited.
…s on Test All (cheaper-inference#3849) With Auto-hide failed models on (default), a Test All sweep across 10+ models in parallel reliably trips per-account rate limits on subscription-tier providers, and the 429'd/timed-out models were auto-hidden — silently removing working models from /v1/models with no easy recovery. evaluateTestAllEntry now surfaces transient failures (rateLimited/isTimeout) as an 'error' icon but keeps them visible; only genuine (non-transient) failures are still auto-hidden. Integrated into release/v3.8.25. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
* chore(release): continue v3.8.25 development cycle after main code-sync (r5) main fast-forwarded to release/v3.8.25 (cheaper-inference#3863): unblocked Build+Docker via cheaper-inference#3864, plus cheaper-inference#3837 (mimocode proxy) and cheaper-inference#3862 (trivy bump). This marker re-opens the umbrella PR for further v3.8.25 work. No version bump. * fix(db): persist the Keep-latest-backups retention setting (cheaper-inference#3834) (cheaper-inference#3867) * fix(oauth): clear GitLab Duo setup message instead of 500 (cheaper-inference#3861) (cheaper-inference#3868) * test(oauth): prove refresh_token preserved on real gemini-cli/antigravity dispatch (cheaper-inference#3850) (cheaper-inference#3869) * feat(compression-ui): unified compression config UI — per-engine pages + combos editor + menu + WS default-on (cheaper-inference#3860) Integrated into release/v3.8.25 — feat(compression-ui): unified compression configuration UI (Compression Hub + per-engine Lite/Aggressive/Ultra pages + combos editor + sidebar entry + live-WS default-on). File-size re-baselined for sidebarVisibility.ts/chatCore.ts growth; orphan ws test relocated to a collected path. * docs(changelog): complete the v3.8.25 release notes + credit all contributors Audited every commit since v3.8.24 and filled the gaps the [3.8.25] section was missing: a New Features section (compression engines + Compression Studios cheaper-inference#3848, compression UI cheaper-inference#3860, injection-guard cheaper-inference#3857, kiro discovery cheaper-inference#3836, Veo cheaper-inference#3839, mimocode proxy cheaper-inference#3837, Arena ELO flag cheaper-inference#3821), 9 more Fixed entries (cheaper-inference#3811/cheaper-inference#3807/cheaper-inference#3759/cheaper-inference#3849/cheaper-inference#3838/cheaper-inference#3835/cheaper-inference#3814/cheaper-inference#3820/cheaper-inference#3819), a Security section (CCR IDOR cheaper-inference#3859, supply-chain cheaper-inference#3824), and an Internal/Quality section. Every contributor and issue reporter is now credited. * docs(changelog): restore + complete the v3.8.25 release notes Re-adds CHANGELOG.md (a prior server-side commit accidentally dropped it) with the complete, audited [3.8.25] section: New Features, the full Fixed list, Security & Hardening, and Internal/Quality — every contributor and issue reporter credited. * chore(release): finalize v3.8.25 — reconcile CHANGELOG + i18n mirrors, document OMNIROUTE_MAX_PENDING_MIGRATIONS, green the unit suite Release-gate reconciliation for v3.8.25: - CHANGELOG: dated 2026-06-14, linked cheaper-inference#3826, rolled up file-size re-baselines (cheaper-inference#3823/cheaper-inference#3833), recorded the test-greening; re-synced all 41 i18n CHANGELOG mirrors. - Documented OMNIROUTE_MAX_PENDING_MIGRATIONS (cheaper-inference#3416) in .env.example + ENVIRONMENT.md. - Greened the unit suite (was merged red on 4 CI shards): aligned 10 stale tests to this cycle's intended behavior (cheaper-inference#3838/cheaper-inference#3822/cheaper-inference#3501/SOCKS5/Vertex-Express/Antigravity) and the same-provider 503 fall-through test; de-flaked the compression benchmark reproducibility and ServiceSupervisor crash tests. No production code changed. * ci(security): clear OpenSSF Scorecard code-scanning noise + harden workflow token permissions The Security tab held 155 open alerts, ALL from the advisory OpenSSF Scorecard tool (cheaper-inference#3824) — supply-chain/posture scores, not code vulnerabilities — which drowned out real CodeQL findings. - scorecard.yml: stop uploading SARIF to the code-scanning tab (drop the upload-sarif step + the now-unused security-events: write). The run still produces the OpenSSF badge (publish_results) and a downloadable SARIF artifact. - TokenPermissions hardening (the high-severity, genuinely-valuable subset): set each workflow's top-level token to read-only and grant the exact writes at the job level that needs them — npm-publish (id-token/packages on publish jobs), docker-publish (packages on build), electron-release (contents on build/release, id-token/packages on publish-npm), build-fork (packages on build), claude (empty top-level; job grants its own). The 155 existing alerts were dismissed. Not adopting repo-wide SHA-pinning (143 PinnedDependencies advisories) — declined. * test(integration): align stale wiring/socks5 integration tests to this cycle's behavior These were red on the CI Integration job (pre-existing). No production code changed: - integration-wiring: the combos page no longer renders a per-page EmailPrivacyToggle (cheaper-inference#3822 consolidated it into Settings → Appearance); the provider-detail test-result masking and upstream-proxy copy moved to decomposed components (cheaper-inference#3501 BatchTestResultsModal / UpstreamProxyCard) — assertions now read the owning files. - api-routes-critical: SOCKS5 is now enabled by default (opt-out), so the disabled- rejection test must set ENABLE_SOCKS5_PROXY=false explicitly (an unset env now means enabled). (The ~32 live-Gemini integration tests are gated on OMNIROUTE_API_KEY and skip in CI; they only 'fail' locally when that key is present without a running server.)
Problem
When Auto-hide failed models is enabled (it defaults to
true) and a user runs Test All Models, every non-OK result is hidden — including transient failures like rate-limits and timeouts.On subscription-tier providers (Kiro, etc.) a single Test All sweep fires requests at 10+ models in parallel, which reliably trips the provider's per-account rate limit. The models that get 429'd or time out are then auto-hidden even though they work perfectly on the next request.
This is more than a cosmetic glitch:
modelCompatOverrides/ custom-modelisHidden) and survives server restarts.GET /v1/models, so OpenAI/Anthropic-compatible clients (and the catalog used by external tools) stop seeing it entirely.Net effect: one throttled Test All can silently wipe an entire provider's catalog, and the user has no obvious way to tell why their models "disappeared."
Root cause
evaluateTestAllEntry()inproviderPageHelpers.tshid any non-OK entry when the toggle was on:The
/api/models/test-allresponse already distinguishes transient failures via the typedrateLimitedandisTimeoutflags, but they weren't consulted.Fix
Skip auto-hide for entries flagged
rateLimitedorisTimeout. They still surface aserroron the per-row icon (so the user sees the test didn't pass), but the model stays visible. Genuine, persistent failures (upstream 400 "invalid model", schema mismatch, auth failure) are still auto-hidden — the intended use of the toggle.Tests
Updated the existing regression suite
tests/unit/test-all-model-status.test.tsto assert the new policy (transient failures showerrorbut are not hidden). All 4 cases pass:Repro (before this fix)
GET /v1/models. Clients can no longer select them until each row is manually un-hidden.