Skip to content

[v3.8.50] fix(models): keep model catalogs responsive - #9199

Merged
diegosouzapw merged 10 commits into
diegosouzapw:release/v3.8.50from
xz-dev:fix/model-catalog-affinity-invalidation
Aug 11, 2026
Merged

diegosouzapw merged 10 commits into
diegosouzapw:release/v3.8.50from
xz-dev:fix/model-catalog-affinity-invalidation

Conversation

@xz-dev

@xz-dev xz-dev commented Aug 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Use the existing narrow touchConnectionLastUsed() path for session-affinity lastUsedAt / consecutiveUseCount bookkeeping instead of the generic catalog-invalidating provider update.
  • Prepare one build-local virtual-auto candidate snapshot for all 38 built-in catalog entries instead of rebuilding the same connection/settings/registry candidate base 38 times.
  • Keep regular and family no-auth pools distinct, clone nested connection allowlists per materialization, and preserve request-time API-key/channel exclusions.
  • Yield cooperatively after preparation and every eight built-in entries so unrelated requests can run during a cold catalog build.
  • Detach invalidated in-flight generations and guard publication by catalog version plus key ownership, so a settings/connection mutation during a yield cannot serve or cache the obsolete generation.

The prepared snapshot is local to one catalog build. This PR adds no global/stale candidate cache and does not change authentication, cache-key partitioning, TTLs, provider routing, or response shape.

Related Issues

Production Diagnosis

A bounded diagnostic image on the downstream production shape identified the cold-builder hotspot before implementation:

Authenticated Primary catalog: 41.064 s
Unrelated dashboard heartbeats: 163 / 164 exceeded the 3 s probe timeout
builtin-auto stage: 11.836 s and 14.676 s in independent builds
complete observed builder: 30.912 s

Hidden-model lookup and unrestricted-key permission projection were separately measured in milliseconds and were not changed.

A local exact-output comparison across all 38 built-ins showed:

one-shot preparation per ID: 598 ms
one shared build-local preparation: 95 ms
speedup: 6.29x
exact deep parity: true

The first reviewed immutable canary (bb15de989, image digest sha256:8a47bcfe…) was isolated-smoke healthy but correctly rejected by the guarded production acceptance and automatically restored to the prior healthy digest:

Concurrent Primary / Supplemental: 23.822 s / 39.715 s
Unrelated heartbeat:              13 / 13 exceeded 3 s
Primary-only / Supplemental-only: 15.528 s / 17.612 s

A V8 profile of the request-serving Node child plus deterministic SQL instrumentation identified the remaining synchronous work: each 38-entry materialization repeated 316 capability-table prepares (272 model_capabilities + 44 model_capability_overrides). The follow-up now resolves those values once per unique provider/model in the catalog-only build snapshot, yields every 16 new resolutions, and performs zero capability-table prepares during materialization. Runtime routing keeps its prior on-demand path. All 38 serialized outputs remain byte/hash identical.

A revised immutable canary and final Pi refresh measurements will be appended after refreshed CI and image validation. These figures are operational evidence, not a portable CI performance threshold.

Validation

Choose the change type and focused loop from the
Contribution Golden Path. CI remains authoritative for repository-wide tests, coverage, and the production build.

  • Change type: routing / model catalog
  • Public authenticated responsiveness regression added
  • Hard-invalidation-during-yield regression added
  • Focused catalog/auto/cache/auth tests
  • ESLint, Prettier, TypeScript, cycles, dead-code, test-discovery, runner-API, and diff gates
  • Refreshed PR CI reviewed; feature-relevant jobs passed and current-base failures are documented below

Local evidence on release/v3.8.50 base b532894a3e628f2ba03a52b17aeaa264c0b9c895:

Public authenticated heartbeat regression
  old source: RED (catalog monopolized the event loop)
  candidate:  GREEN (heartbeat completes before catalog publication)

Mutation during cooperative build
  before generation guard: RED (post-mutation caller joined obsolete in-flight work)
  candidate:               GREEN (current generation builds and publishes separately)

Catalog capability snapshot follow-up
  old source: 5 RED / 5 new tests
  candidate:  prepared materialization SQL prepares 316 -> 0
  output:     all 38 entries, 90,114 bytes, exact SHA-256 parity
  final focused catalog/cache/auto suite: 44 passed

Focused Node catalog/auto/cache/auth/invalidation tests: 69 passed
Targeted auto-family/paid Vitest tests:                  15 passed
Full Vitest suite:                                      291 passed / 34 files
npm run typecheck:core:                                  passed
npm run lint:                                            passed
npm run check:cycles:                                    passed
npm run check:dead-code:                                 passed
npm run check:test-discovery:                            passed
npm run check:test-runner-api:                           passed
Prettier + git diff --check:                             passed

The repository-wide Node runner emitted no assertion failure but did not exit before explicit GNU timeout limits at both 600 s and 1200 s. No test processes remained afterward.

Refreshed CI follow-up (e0e422c3f)

Successful feature-relevant jobs: change classification, merge integrity, Semgrep (both jobs), docs gates, full Vitest fast path, ESLint warning ratchet, and DAST smoke.

The remaining red statuses are not introduced by this PR:

  • Fast Quality Gates: check:file-size reports the same three production freezes and one test freeze on the current release/v3.8.50 head cfb44dab9; none of those files or the baseline is changed by this PR.
  • Unit shards: the PR merge build exposes 11 stale Codex/Claude fingerprint, transform mirror, content-type, and golden expectations already present on cfb44dab9. An isolated focused run of the same nine files on that exact base reproduced all 11 failures (177 tests; 166 pass; 11 fail). The catalog responsiveness regression itself passes in CI.
  • Build (advisory): GitHub terminated the hosted runner with a shutdown signal while Next.js was compiling; no compiler error was reported.

No unrelated baseline, snapshot, fingerprint, or generated-file repair is included in this focused PR.

Tests Added Or Updated

  • Added tests/integration/model-catalog-responsiveness-9199.test.ts:
    • starts an authenticated cold GET /v1/models?prefix=alias;
    • proves an unrelated public health request completes before catalog publication;
    • verifies the complete catalog response and one response-cache builder run.
  • Extended tests/unit/model-catalog-runtime-invalidation.test.ts:
    • preserves affinity bookkeeping without an unnecessary rebuild;
    • preserves hard invalidation for catalog-affecting connection changes;
    • proves capability/context/models.dev capability writes advance the catalog generation while no-op writes do not;
    • proves mutations during cooperative capability preparation detach obsolete in-flight work and prevent stale cache publication.
  • Extended tests/unit/auto-combo-context-advertising.test.ts:
    • proves catalog-only capability snapshots are complete and cooperatively prepared;
    • proves runtime preparation retains existing on-demand behavior;
    • proves advertised limits and category filters consume prepared values without repeated DB resolution.

Reviewer Notes

  • No schema migration, feature flag, API response shape, credential behavior, or global candidate cache.
  • Capability values are attached only when the built-in catalog explicitly opts in; runtime auto routing still prepares fresh state, resolves capabilities on demand, and applies API-key/channel candidate exclusions per request.
  • Regular/category pools keep the reliability-curated no-auth allowlist; family pools preserve the existing identity-selector bypass.
  • Prepared candidates and nested allowedConnectionIds are cloned before per-entry derivation.
  • A pre-mutation caller may finish its own coherent snapshot; post-mutation callers cannot join it, and its late completion cannot overwrite the current cache.
  • Independent final review: APPROVE, including a separate stale-background-refresh interleaving probe.

@xz-dev
xz-dev marked this pull request as ready for review August 2, 2026 07:17
@xz-dev
xz-dev requested a review from diegosouzapw as a code owner August 2, 2026 07:17
@xz-dev xz-dev changed the title [v3.8.50] fix(models): preserve catalog during affinity bookkeeping [v3.8.50] fix(models): keep model catalogs responsive Aug 2, 2026
xz-dev added a commit to xz-dev/OmniRoute that referenced this pull request Aug 3, 2026
Resolve synced capabilities and persisted overrides from one build-local view instead of repeating per-target SQLite reads. Keep ordinary runtime lookups on demand and preserve catalog generation invalidation.

Refs: diegosouzapw#9199
xz-dev added a commit to xz-dev/OmniRoute that referenced this pull request Aug 3, 2026
Port PR diegosouzapw#9199 capability snapshotting onto the unified input/output token override candidate. Load both override keys from one build-local view while preserving runtime, invalidation, and persistedOverrides behavior.

Refs: diegosouzapw#9199
@xz-dev

xz-dev commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up: capability SQL removed, production canary still rejected

Pushed 404501086 (fix(models): bulk-load catalog capability snapshots) to this PR.

Deterministic evidence

  • Before: catalog preparation performed 1,128 per-target capability-related SQLite prepares in the production integration profile (model_capabilities 672, capability overrides 304, context overrides 152).
  • After: exactly one bulk read per table; total preparation prepares are 7 (the 3 capability reads plus 4 existing non-capability loads), and materialization performs 0 SQL prepares.
  • Default runtime preparation performs 0 catalog-only bulk reads.
  • All 38 built-in auto outputs remain byte-identical: 90,114 bytes, SHA-256 d56e5c7aaac71d4c2442888c0d1867354eabab19e99953f3c107f215ce6bb7cb.
  • Focused behavior, alias/override parity, invalidation races, prototype/composite-key safety, full Vitest, typecheck, lint, cycles, dead-code, formatting, mutation registration, and responsiveness tests pass. Independent review: C0/I0/M0.

CI

Head 404501086 passed merge integrity, Fast Quality, Vitest, all four unit shards, DAST, ESLint, Semgrep, docs, and classification. The only red check is the advisory Build job: GitHub canceled npm run build during Next compilation without a compiler/test error; the parent workflow succeeded.

Immutable production canary

Built integration revision ff79490c6 as immutable digest sha256:65e6ea4594687fe1a2a5aecc7d2b7a00ee7d235b7c2ba51845022c43dc234738 (build run 30777554903). Isolated image smoke passed.

The rollback-default production canary was rejected:

  • Primary: 7.920s (under 15s)
  • Supplemental: 20.159s (over 15s)
  • Heartbeats: 6 timeouts and 3 non-200 samples

The harness restored the exact prior digest/revision and compose hash. A fresh post-rollback check confirmed healthy, restart count 0, root 307, SQLite quick_check OK, and unchanged Redis/Warp/Caddy identities and states.

Conclusion: repeated capability SQL was real waste but is not the remaining dominant blocker. I am profiling the new candidate's concurrent cold Primary+Supplemental build before making another narrow change. Whole-build cross-key coalescing remains out of scope unless a pure identical internal stage is measured and safely fingerprinted.

@xz-dev

xz-dev commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Measured pricing-hotspot follow-up

A rollback-default concurrent production CPU profile against the immutable prior candidate completed safely and restored the exact accepted digest afterward.

Profile evidence

  • Primary catalog: HTTP 200, 20.672s
  • Supplemental catalog: HTTP 200, 11.094s
  • Both responses were non-empty
  • The dominant JavaScript frame mapped exactly to getModelsDevPricing() (_0-ot5g8._.js, line 32, column 3277): 37.38% self CPU
  • The associated anonymous/native frame was 43.43% self CPU
  • SQLite prepare itself was only 2.32%; capability all was below 1%
  • Inspector closure, exact rollback digest/revision/compose hash, health, restart count, DB integrity, and unrelated-service identities were independently reverified

The source-level RED then observed 109 identical models.dev pricing reads/parses in one authenticated cold /v1/models build.

Fix

  • bbcfdd388 — reuse one build-local pricing snapshot during final enrichment and yield once before publication
  • 65fa33a3e — record the measured follow-up in the changelog

This does not add cross-request or cross-key coalescing. Ordinary enrichCatalogModelEntry() callers retain their existing fresh-read behavior; only one catalog build shares the identical internal pricing stage. Existing catalog-generation invalidation still prevents obsolete work from repopulating the published cache after the cooperative yield.

Validation

  • RED: pricing reads actual 109, expected 1
  • GREEN: responsiveness integration 2/2
  • Intentional no-yield mutation: count stayed 1 but heartbeat ordering failed, proving the cooperation assertion independently detects the yield
  • Existing pricing parity 3/3
  • Capability snapshot parity/SQL 4/4
  • Runtime invalidation/race 5/5
  • Scoped tests 20/20
  • Core TypeScript, targeted ESLint, Prettier, dead-code, and git diff --check: pass
  • Built-in auto outputs remain exactly 38 entries / 90,114 bytes / SHA-256 d56e5c7aaac71d4c2442888c0d1867354eabab19e99953f3c107f215ce6bb7cb
  • Independent code review: C0/I0/M0
  • Independent test review: C0/I0/M0

CI is now running on head 65fa33a3e. No merge is being requested or performed.

diegosouzapw pushed a commit to xz-dev/OmniRoute that referenced this pull request Aug 11, 2026
Resolve synced capabilities and persisted overrides from one build-local view instead of repeating per-target SQLite reads. Keep ordinary runtime lookups on demand and preserve catalog generation invalidation.

Refs: diegosouzapw#9199
@diegosouzapw
diegosouzapw force-pushed the fix/model-catalog-affinity-invalidation branch from 65fa33a to 8627239 Compare August 11, 2026 02:02
xz-dev added 10 commits August 11, 2026 09:48
Related to diegosouzapw#8697.

Focused follow-up to diegosouzapw#8728; this does not replace or supersede that contribution.
Resolve synced capabilities and persisted overrides from one build-local view instead of repeating per-target SQLite reads. Keep ordinary runtime lookups on demand and preserve catalog generation invalidation.

Refs: diegosouzapw#9199
Production profiling showed per-model models.dev pricing reads and JSON parsing dominated cold catalog builds. Reuse one build-local pricing snapshot during enrichment and yield before publication so queued health checks can run, while preserving fresh reads for ordinary callers.
@diegosouzapw
diegosouzapw force-pushed the fix/model-catalog-affinity-invalidation branch from 8627239 to b2f00dc Compare August 11, 2026 12:59
@diegosouzapw
diegosouzapw merged commit 36959c3 into diegosouzapw:release/v3.8.50 Aug 11, 2026
3 of 5 checks passed
shardqa added a commit to shardqa/OmniRoute that referenced this pull request Aug 11, 2026
- conol-web registry: fix import path to conolModels (4 levels, not 3)
- conolDiscovery: import getProviderOutboundGuard from outboundUrlGuardPolicy
- modelSelectModalHelpers: close unclosed function brace
- videoGeneration: drop duplicate handleFalVideoGeneration import
- catalogCache: restore test-only SWR accessor hooks removed by diegosouzapw#9199
- gateways: close regolo entry + drop duplicated chatanywhere block
- wasm_signer_bg: stub so Turbopack resolves the TinyCMS wasm import
@xz-dev xz-dev mentioned this pull request Aug 11, 2026
10 of 11 tasks
diegosouzapw added a commit that referenced this pull request Aug 12, 2026
…s (base-red round 3)

Storm-merge splices repaired in the base-fix PR #10131:
- doctor.ts: AppConfig missing brokerSocketPath
- conol-web.ts: Buffer not assignable to BodyInit (Uint8Array)
- tinycms.ts: TinyCmsExecutor.execute return matches BaseExecutor (response/url/transformedBody)
- tinycmsSigner.ts: encodeInto never-narrowing guard + dead wasm URL fallback (Turbopack)
- virtualFactory.ts: options slot for resolutionSnapshot
- bottleneckPatch.ts: insufficient-overlap casts (as unknown as)
- imageCombo.ts: narrow handleImageGeneration union result
- browser-worker.ts: AppConfig + turn.capabilities splice
- conolDiscovery.ts: getProviderOutboundGuard from Policy module
- catalog.ts: drop removed SWR hooks (getCatalogStaleWhileRevalidateMs + accessors), CatalogCachePolicy -> inline settings, resolve 4-arg call
- catalogCache.ts: remove dead inFlight/promise refs
- chat.ts: add isProviderBreakerFailureStatus import
- model-catalog-cache-swr-8728.test.ts: align to #9199 new API (policy injection removed)
adevwithpurpose pushed a commit to adevwithpurpose/OmniRoute that referenced this pull request Aug 12, 2026
…l/deepai corruption, migrations, docs, ratchets, dashboard-typecheck

Base-red fix for issue diegosouzapw#9985 after the 2026-08-11 merge storm (99 PRs).

Real defects fixed:
- gateways.ts: close regolo entry (was swallowing naga-ac + chatanywhere from diegosouzapw#9421), drop stale duplicate chatanywhere entry (diegosouzapw#9594)
- conol-web + deepai registry: correct ../shared import depth + deepai executor:default
- modelSelectModalHelpers: close isProviderModelHidden (diegosouzapw#9011)
- driverFactory.test.ts: restore eaten test-closing brace (diegosouzapw#9173)
- usageTracking: remove duplicate cache_* props
- modelCapability{Overrides,ResolutionSnapshot,Capabilities}: max_token -> max_output_tokens (diegosouzapw#9199 vs diegosouzapw#8908) + test align
- videoGeneration: drop duplicate handleFalVideoGeneration import (mediaGeneration/fal canonical, diegosouzapw#9982)
- responseSanitizer: cast input_tokens_details before .cached_tokens access
- EditConnectionModal: missing alibaba code fields, hoist validationPsd, providerPageHelpers Badge variant union
- FreeBudgetCard: t() -> labels.noApiKey
- peerRouting + cliRuntime: ProcessEnv typing
- image-combo.test.ts: type any -> unknown
- fal.test.ts: moved to tests/unit/services (collected path) 14 tests green
- remove duplicate 143_job_registry.sql (146 canonical), KNOWN_GAPS fix

Docs/ratchets (owner-authorized rebaselines, annotated):
- CHANGELOG 3.8.50 living section restored + 42 i18n mirrors
- MCP-SERVER.md 104->105 tools + i18n
- ENVIRONMENT.md/.env.example: ADOBE_FIREFLY_CHROME_HEADED + DEBUG_CLAUDE_NONSTREAM
- fabricated-docs allowlist: TELEGRAM proposal env vars
- file-size: 5 grown files + proxyFetch 1207->1220
- dead-code 230->248, codeql 2->9 (drift from merged PRs, not this PR)
- untrack _tasks symlink; agent-skills-sync --apply (config-codex-cli)
adevwithpurpose pushed a commit to adevwithpurpose/OmniRoute that referenced this pull request Aug 12, 2026
…s (base-red round 3)

Storm-merge splices repaired in the base-fix PR diegosouzapw#10131:
- doctor.ts: AppConfig missing brokerSocketPath
- conol-web.ts: Buffer not assignable to BodyInit (Uint8Array)
- tinycms.ts: TinyCmsExecutor.execute return matches BaseExecutor (response/url/transformedBody)
- tinycmsSigner.ts: encodeInto never-narrowing guard + dead wasm URL fallback (Turbopack)
- virtualFactory.ts: options slot for resolutionSnapshot
- bottleneckPatch.ts: insufficient-overlap casts (as unknown as)
- imageCombo.ts: narrow handleImageGeneration union result
- browser-worker.ts: AppConfig + turn.capabilities splice
- conolDiscovery.ts: getProviderOutboundGuard from Policy module
- catalog.ts: drop removed SWR hooks (getCatalogStaleWhileRevalidateMs + accessors), CatalogCachePolicy -> inline settings, resolve 4-arg call
- catalogCache.ts: remove dead inFlight/promise refs
- chat.ts: add isProviderBreakerFailureStatus import
- model-catalog-cache-swr-8728.test.ts: align to diegosouzapw#9199 new API (policy injection removed)
diegosouzapw added a commit that referenced this pull request Aug 12, 2026
…sh (#10198)

The Build CI job is advisory, so eight module-level defects from eight
different PRs accumulated on release/v3.8.50 until `npm run build` failed
with 7 Turbopack errors and `npm run lint` with 14.

Build (link-time):
- modelSelectModalHelpers.ts: a lost `}` swallowed PROVIDER_TEST_CHUNK_SIZE
  into isProviderModelHidden's body (#9011).
- videoGeneration.ts: handleFalVideoGeneration imported twice; the standalone
  falHandler.ts is superseded by the provider-neutral mediaGeneration/fal.ts
  and is removed here (#9982 over #9969).
- catalog.ts: re-exported and called the injectable SWR policy that #9199
  deliberately replaced with a fixed 30s bound. Fixed on the consumer side —
  restoring the accessor would resurrect the unbounded window #9199 removed
  after measuring a 41s catalog build in production.
- tinycmsSigner.ts: generated wasm-bindgen glue kept a sidecar
  `new URL('wasm_signer_bg.wasm', import.meta.url)` that no file backs;
  Turbopack resolves it statically. The module ships inlined as WASM_BASE64
  and the only caller always passes it explicitly (#8736/#10087).
- conolDiscovery.ts: imported getProviderOutboundGuard from outboundUrlGuard,
  which does not export it. Fixed on the consumer side: outboundUrlGuard.ts is
  loaded by the packaged CLI without a tsconfig, so it must stay free of
  `@/`-aliased imports (#7682).

Runtime (the build never caught this one):
- catalogCache.ts::scheduleBackgroundRefresh had two dangling statements
  referencing undeclared `inFlight`/`promise`, so EVERY stale-while-revalidate
  read threw a ReferenceError. Surfaced by realigning the #8728 suite, which
  #9199 left asserting a removed contract.

Lint:
- driverFactory.test.ts: a case inserted between the preceding test's `finally`
  and its `});` left the file unparseable, so the SQLite driver-cascade suite
  (26 tests) had not run since 2026-08-11 (#9173).
- providerModelsConfig.ts: imported an executor directly, crossing the G14
  boundary; routed through a new open-sse/services/zaiWebCredentials.ts (#8451).
- image-combo.test.ts: 11 `any` violations, now typed (#9499).

Validation: npm run build exit 0, npm run lint clean, typecheck:core clean,
41/41 tests green across the affected suites.

Refs #9011 #9982 #9199 #8728 #8736 #10087 #8974 #9173 #8451 #9499

Co-authored-by: backryun <bakryun0718@proton.me>
diegosouzapw added a commit that referenced this pull request Aug 12, 2026
* fix(quality): green release/v3.8.50 base-reds round 2 — gateways/conol/deepai corruption, migrations, docs, ratchets, dashboard-typecheck

Base-red fix for issue #9985 after the 2026-08-11 merge storm (99 PRs).

Real defects fixed:
- gateways.ts: close regolo entry (was swallowing naga-ac + chatanywhere from #9421), drop stale duplicate chatanywhere entry (#9594)
- conol-web + deepai registry: correct ../shared import depth + deepai executor:default
- modelSelectModalHelpers: close isProviderModelHidden (#9011)
- driverFactory.test.ts: restore eaten test-closing brace (#9173)
- usageTracking: remove duplicate cache_* props
- modelCapability{Overrides,ResolutionSnapshot,Capabilities}: max_token -> max_output_tokens (#9199 vs #8908) + test align
- videoGeneration: drop duplicate handleFalVideoGeneration import (mediaGeneration/fal canonical, #9982)
- responseSanitizer: cast input_tokens_details before .cached_tokens access
- EditConnectionModal: missing alibaba code fields, hoist validationPsd, providerPageHelpers Badge variant union
- FreeBudgetCard: t() -> labels.noApiKey
- peerRouting + cliRuntime: ProcessEnv typing
- image-combo.test.ts: type any -> unknown
- fal.test.ts: moved to tests/unit/services (collected path) 14 tests green
- remove duplicate 143_job_registry.sql (146 canonical), KNOWN_GAPS fix

Docs/ratchets (owner-authorized rebaselines, annotated):
- CHANGELOG 3.8.50 living section restored + 42 i18n mirrors
- MCP-SERVER.md 104->105 tools + i18n
- ENVIRONMENT.md/.env.example: ADOBE_FIREFLY_CHROME_HEADED + DEBUG_CLAUDE_NONSTREAM
- fabricated-docs allowlist: TELEGRAM proposal env vars
- file-size: 5 grown files + proxyFetch 1207->1220
- dead-code 230->248, codeql 2->9 (drift from merged PRs, not this PR)
- untrack _tasks symlink; agent-skills-sync --apply (config-codex-cli)

* fix(changelog): reformat two feature fragments to the bullet convention (#9239, #9490)

* fix(quality): prune stale ESLint suppressions (base-red)

* fix(quality): resolve open-sse type errors + catalog/build regressions (base-red round 3)

Storm-merge splices repaired in the base-fix PR #10131:
- doctor.ts: AppConfig missing brokerSocketPath
- conol-web.ts: Buffer not assignable to BodyInit (Uint8Array)
- tinycms.ts: TinyCmsExecutor.execute return matches BaseExecutor (response/url/transformedBody)
- tinycmsSigner.ts: encodeInto never-narrowing guard + dead wasm URL fallback (Turbopack)
- virtualFactory.ts: options slot for resolutionSnapshot
- bottleneckPatch.ts: insufficient-overlap casts (as unknown as)
- imageCombo.ts: narrow handleImageGeneration union result
- browser-worker.ts: AppConfig + turn.capabilities splice
- conolDiscovery.ts: getProviderOutboundGuard from Policy module
- catalog.ts: drop removed SWR hooks (getCatalogStaleWhileRevalidateMs + accessors), CatalogCachePolicy -> inline settings, resolve 4-arg call
- catalogCache.ts: remove dead inFlight/promise refs
- chat.ts: add isProviderBreakerFailureStatus import
- model-catalog-cache-swr-8728.test.ts: align to #9199 new API (policy injection removed)

* fix(quality): align UI test fixtures to current component contracts (base-red vitest)

- setup-wizard: provide required serverState prop (component gained it in a merged PR)
- grok-device-oauth-modal: next-intl stub resolves grok flow keys to EN labels
- provider-quota-widget: label now inline (PR #8916 removed AutoRefreshButtonLabel extraction) — test the widget
- use-provider-connections-cursor-refresh + phase1f: match /api/providers?provider=<id> query form; hoist heavy dynamic imports to module scope (timeout flake)
- home-topology: mock next/navigation useRouter (component added node-click navigation)
- cooling/lobe/AutoComboCatalog: raise cold-import describe timeouts to 30-60s
- request-logger-*: align to current detail-view contract

* fix(search): guard params.token undefined in serper headers (typecheck base-red)

* fix(search): guard token headers + non-null providerConfig (typecheck base-red)

* fix(changelog): restore base CHANGELOGs eaten by merge auto-resolve (43 files)

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: backryun <bakryun0718@proton.me>
diegosouzapw pushed a commit that referenced this pull request Aug 13, 2026
… (waves A-E)

Real defects fixed:
- src/lib/db/apiKeys.ts: #9313's empty-allowlist early return bypassed the group
  permission check, silently disabling group deny rules (#8817) for every key
  without a per-key allowlist; fall-through restored, restricted+[] deny-all kept
- open-sse/utils/proxyFetch.ts: #10032 re-appended the raw transport error to the
  propagated message, reintroducing the proxy user:password leak #9837 closed;
  new redactProxyDetailsInMessage() keeps the reason, redacts URL/credentials
- .github/workflows/quality.yml: #10134 added the TS7 ratchet as a separate
  blocking step AFTER the aggregated gates — the exact #8542 masking mechanism;
  folded into the non-fail-fast loop (still blocking, still PR-only) ⚠️ CI edit,
  gate-strengthening — explicit owner sign-off requested on the PR
- src/i18n/messages/ko.json: 3 machine-mistranslation regressions caught by the
  #8244 glossary checker (장애인→비활성화됨, 양말5://→socks5://, 비클로드→Claude가 아닌)

Stale sibling tests aligned to deliberately-moved contracts (each cites its mover):
request-log-detail-layout + -stream (#9245 intl provider), repro-8542 pin update,
quality-rail-gate-membership (#10134 shape), agentSkills-routes 45→46 (#9058),
cloudflare-ai-catalog-8717 (#8804 supersedes #8808), executor-xai (#9994),
vision-bridge-claude-wire (#9463 minimax→openai), sse-auth forced-pin (#8893),
tls-proxy-context (strengthened leak guards), rate-limit-local-error-classification
(#9164/#9342), minimax-thinking-signature (#9463), codebuddy-cn (#9723 +1 test),
github-copilot-custom-model (#9050), providers-g4f-batch3 (#9584),
synced-capability-warmup (#9199, stricter), sidebar-tools-group (#8221),
oauth-modal-grok-cli-paste (#9245); agentSkills/catalog.ts comment 45→46;
file-size rebaseline for proxyFetch (+19, annotated)

Refs #9985
diegosouzapw pushed a commit that referenced this pull request Aug 13, 2026
…lignments

Real defects:
- base/reasoningEffort.ts: the stale duplicate cherry-pick #9612 re-added the
  codex minimal→low rewrite that #9883 had deliberately removed (OMP minimal
  passthrough); block removed again
- cursorImages.ts: #9840 wired prepareCursorImageForWire (sharp re-encode,
  fail-closed) into the SHARED resolveCursorImages, breaking zai-web and
  conol-web image uploads (HTTP 400 'undecodable'); new prepareForWire opt-out,
  Cursor default path unchanged (8 cursor suites green)
- modelCapabilities/snapshot: catalog prepare still issued 323 per-model reads
  of model_context_overrides + max_input_tokens overrides, violating #9199's
  bulk-load contract; both now resolve from the snapshot single pass
- v1-models-discovery-conformance: re-pinned to the bounded 30s SWR window
  (#9199/#10198) — the old 'stale-first regardless of age' contract is gone

Stale tests aligned (movers cited inline): codex-tools-strict-default (#9828
redundant-oneOf strip), devin-providers (#9245 i18n), db-migrationrunner-
constants-split (147→151 renumber #8228), gitlab-duo-oauth-setup (#9245),
chatcore-extracted-modules (#9161 outbound-protocol keying)

compression-api CI failures were cascade artifacts of codex-tools-strict-default
failing in the same force-exit shard process — no own defect (171/171 local).

Refs #9985
diegosouzapw added a commit that referenced this pull request Aug 13, 2026
* fix(ci): clear base-reds on release/v3.8.50 (round 3)

- CHANGELOG.md: restore the top [Unreleased] section dropped by the #10189
  reconcile (docs-sync gate: first section must be Unreleased)
- env-doc-sync: document CONDUCTOR_ORCHESTRATOR_TOKEN + CONDUCTOR_SPOKESPERSON_URL
  in .env.example/ENVIRONMENT.md; allowlist the CI-only GITHUB_STEP_SUMMARY and
  TS7_BASE_REF (ts7 ratchet signals); drop a stray merge artifact line
- providers: restore the audited chatanywhere metadata entry that base-reds
  round 2 dropped together with its duplicate — the provider was half-wired
  (registry+endpoint without APIKEY metadata), which is what the wave3 test
  catches; re-pin providers-constants-split at the measured 228
- docs counts: 338 -> 339 (today's +2 void-ai/helixmind, -1 Puter) via
  gen:provider-reference + README/AGENTS/llm.txt/package.json/diagrams/i18n mirrors
- file-size ratchet: annotated rebaseline for the two pre-existing drifts
  (ModelSelectModal 1138, gateways 1250) following the 2026-08-11 precedent

Refs #9985

* fix(ci): base-reds round 3b — stale sibling tests + mode-pack weight contract

- check-docs-counts-sync.test.ts: drop the imports/subtests of the four helpers
  #10196 removed from the gate script (readMcpFactsFromSource, listLocalizedDocs,
  makeRequiredCountsValidator, checkFreeTierInventory) — the new-API tests that
  #10196 added stay; the file now loads again under the node runner
- quota-connection-recovery.test.ts: convert from vitest APIs to node:test —
  the file lives in tests/unit/*.test.ts (node-runner glob) and the vitest
  runtime crashes when imported outside vitest, killing the whole shard entry
- modePacks.ts: re-normalize all six mode packs to sum 1.0 — #8940 added
  sessionAvailability: 0.05 to every pack without rebalancing (1.05 total);
  ratios preserved exactly (÷1.05), so post-normalizeScoringWeights behavior
  is unchanged; restores the declared sum-to-1.0 contract the 4235 test pins

Refs #9985

* fix(ci): base-reds round 3c — vitest siblings, weights default, secrets FP, mutation tap

- DistributeProxiesButton.test.tsx: wrap renders in NextIntlClientProvider —
  #9245 localized the component (useTranslations) and left the test without
  the intl context, failing all 14 cases
- scoring.ts: re-normalize DEFAULT_WEIGHTS to sum 1.0 (same #8940 class as the
  mode packs — sessionAvailability added without rebalancing; ratios preserved)
- .gitleaks.toml: generalize the kimi sponsor-banner localStorage-key allowlist
  to -v\d+ — #10200 bumped v1→v2 and the stale regex regressed the secrets
  ratchet with a false positive
- stryker.conf.json: register 6 covering unit tests in tap.testFiles (4 modules)
  so their mutant kills count — unblocks check:mutation-test-coverage --strict

Refs #9985

* fix(ci): base-reds round 3d — inspector factor gap, stale registry/gap tests, i18n key sync

- comboScoringInspector: add cacheAffinity/sessionAvailability/connectionDensity
  to FACTOR_KEYS + the factor-key type — calculateScore() weighs them but the
  breakdown omitted them, so the explained contributions never summed to the
  reported score (inspector bug, red on the pure tip)
- combo-scoring-inspector.test: make the explicit-weights override sum-neutral
  (±0.05 shift) so it stays valid for any DEFAULT_WEIGHTS values — the hardcoded
  override only summed to 1.0 against the pre-#8940 defaults, which is also why
  explicit weights silently fell back to 'default' on the tip
- unorouter-registry.test: align to the canonical .com host (api.unorouter.ai
  301-redirects there, verified live) and to wave4's live model discovery
  (passthrough, no static seed) — the .ai/auto-model expectations were stale
- check-migration-numbering.test: 147 left KNOWN_GAPS when
  147_api_keys_model_access_mode.sql landed — assert absent (same as 143)
- i18n: sync-ui pass — 35,914 missing UI keys stamped as __MISSING__ placeholders
  across 42 locales (mechanical; greens the pt-BR key-presence integrity test;
  coverage pct unchanged by design — translation is a separate workstream)

Refs #9985

* fix(ci): base-reds round 3e — 2 real defects + 14 stale sibling tests (waves A-E)

Real defects fixed:
- src/lib/db/apiKeys.ts: #9313's empty-allowlist early return bypassed the group
  permission check, silently disabling group deny rules (#8817) for every key
  without a per-key allowlist; fall-through restored, restricted+[] deny-all kept
- open-sse/utils/proxyFetch.ts: #10032 re-appended the raw transport error to the
  propagated message, reintroducing the proxy user:password leak #9837 closed;
  new redactProxyDetailsInMessage() keeps the reason, redacts URL/credentials
- .github/workflows/quality.yml: #10134 added the TS7 ratchet as a separate
  blocking step AFTER the aggregated gates — the exact #8542 masking mechanism;
  folded into the non-fail-fast loop (still blocking, still PR-only) ⚠️ CI edit,
  gate-strengthening — explicit owner sign-off requested on the PR
- src/i18n/messages/ko.json: 3 machine-mistranslation regressions caught by the
  #8244 glossary checker (장애인→비활성화됨, 양말5://→socks5://, 비클로드→Claude가 아닌)

Stale sibling tests aligned to deliberately-moved contracts (each cites its mover):
request-log-detail-layout + -stream (#9245 intl provider), repro-8542 pin update,
quality-rail-gate-membership (#10134 shape), agentSkills-routes 45→46 (#9058),
cloudflare-ai-catalog-8717 (#8804 supersedes #8808), executor-xai (#9994),
vision-bridge-claude-wire (#9463 minimax→openai), sse-auth forced-pin (#8893),
tls-proxy-context (strengthened leak guards), rate-limit-local-error-classification
(#9164/#9342), minimax-thinking-signature (#9463), codebuddy-cn (#9723 +1 test),
github-copilot-custom-model (#9050), providers-g4f-batch3 (#9584),
synced-capability-warmup (#9199, stricter), sidebar-tools-group (#8221),
oauth-modal-grok-cli-paste (#9245); agentSkills/catalog.ts comment 45→46;
file-size rebaseline for proxyFetch (+19, annotated)

Refs #9985

* fix(ci): base-reds round 3f — waves F-J: 9 more real defects + stale sibling sweep

Real production defects fixed (all red on the pure tip, each with its origin):
- routeGuard.ts: #8949 accidentally DELETED the /api/providers/[id]/login
  local-only pattern — the route spawns a browser, so the loopback gate for a
  process-spawning route was gone (Hard Rules #15/#17); restored (314 guard
  tests green)
- agentSkills generator: #9058's category dispatch gave the config category an
  empty body, wiping skills/config-codex-cli/SKILL.md at the #10131 sync;
  fixed + SKILL.md regenerated via the official generator
- imageRegistry: #9982 broke same-provider bare aliasing (antigravity preview
  id sent upstream unresolved); new resolveSameProviderBareAlias() keeps the
  fal cross-provider fix intact
- imageRegistry: #9982's prefix strip handed the bare nano-banana ids to fal-ai,
  violating the pinned 2026-07-31 operator decision (adobe-firefly owns them);
  fal entries made prefix-only (dispatch already re-prefixes)
- mediaGeneration/fal.ts: the missing-credential 401 guard was lost when #10198
  deleted the superseded falHandler — tests were hitting the live network
- bottleneckPatch/rateLimitManager: #9041's merge clobbered #9604, resurrecting
  the Bottleneck v2.19.5 heartbeat bug (reservoir never refills); patched the
  library defect at the root and re-aligned chat-rate-limit-body-lock to the
  working reservoir contract
- processSupervisor.mjs: #9761 regressed the Node spawn to bare "node" (the
  #9156 launchd bug) and dropped #9209's ipv4first args; both restored
- openai-responses/pureHelpers: #9423's Agent null-sentinel was unreachable on
  the schemaless JSON-string path; gate extended
- i18n en.json: #8222's regen reverted the #9976 unclosed-tag fix and #8559's
  combo-cooldown copy; #9038 shipped 40 t() calls with no messages (runtime
  MISSING_MESSAGE); all restored/added + official sync-ui stamps, and vi's
  zero-marker policy re-established via the sanctioned translation backend

Stale sibling tests aligned (movers cited inline): chat-helpers (#9447),
executor-antigravity (#9351), video-fal-grok (#9982), visionBridge (#9759),
web-session-credentials (#8974), production-build-module-integrity (positive
anchor added), agentSkills-generator/skillManifestsLint/skills-injection/
agentSkillTools-mcp/listCapabilities-a2a (#9058), memory-settings (#10010),
model-catalog-policy-invalidation (#8906), model-alias-seed (#9485),
reactive-context-compaction (#8949), combo-provider-wildcard (broken upsert
helper), oauth-google-loopback (43-locale resurrected-key removal)

Validation: 501/501 across the 47 touched test files; typecheck:core, lint,
file-size, docs-sync all green.

Refs #9985

* fix(ci): base-reds round 3g — wave K/L: 4 more real defects + stale alignments

Real defects:
- base/reasoningEffort.ts: the stale duplicate cherry-pick #9612 re-added the
  codex minimal→low rewrite that #9883 had deliberately removed (OMP minimal
  passthrough); block removed again
- cursorImages.ts: #9840 wired prepareCursorImageForWire (sharp re-encode,
  fail-closed) into the SHARED resolveCursorImages, breaking zai-web and
  conol-web image uploads (HTTP 400 'undecodable'); new prepareForWire opt-out,
  Cursor default path unchanged (8 cursor suites green)
- modelCapabilities/snapshot: catalog prepare still issued 323 per-model reads
  of model_context_overrides + max_input_tokens overrides, violating #9199's
  bulk-load contract; both now resolve from the snapshot single pass
- v1-models-discovery-conformance: re-pinned to the bounded 30s SWR window
  (#9199/#10198) — the old 'stale-first regardless of age' contract is gone

Stale tests aligned (movers cited inline): codex-tools-strict-default (#9828
redundant-oneOf strip), devin-providers (#9245 i18n), db-migrationrunner-
constants-split (147→151 renumber #8228), gitlab-duo-oauth-setup (#9245),
chatcore-extracted-modules (#9161 outbound-protocol keying)

compression-api CI failures were cascade artifacts of codex-tools-strict-default
failing in the same force-exit shard process — no own defect (171/171 local).

Refs #9985

* fix(test): compression-api — register both describes before the runner starts

The DATA_DIR setup + route/db top-level awaits sat BETWEEN the two describes;
under --test-force-exit (the CI unit-runner flag) the process exits once the
already-registered tests finish, so on slow CI machines the whole second
describe died as 'Promise resolution is still pending' — the recurring
CI-only shard-2 failure that never reproduced locally without the flag.
Moved to the top of the file; 10/10 under --test-force-exit locally.

Refs #9985

* fix(quality): freeze modelCapabilities.ts at 1006 (annotated) — snapshot routing growth

Refs #9985

* fix(quality): move the modelCapabilities freeze into the frozen map (nested schema)

Refs #9985

* fix(i18n): translate all 39,718 pending UI keys across 42 locales (owner-approved)

Mass-translated every __MISSING__ placeholder via the official i18n:sync-ui
--translate-markers pipeline (operator backend), restoring i18nUiCoverage to the
100 baseline (was 89.9 after the merge-storm UI landings + the 42 keys #9038
never shipped).

Post-pass repairs, all caught by the existing gates:
- glossary: retired renderings the machine reintroduced normalized again
  (提供商→提供者 zh-CN/zh-TW, 鏈接→連結, 文檔→文件, 調用→呼叫, 供應商→提供者,
  響應→回應, 不活躍→未啟用 zh-TW; 클로드→Claude, 옴니루트→OmniRoute ko);
  DATA_DIR forbidden rendering avoided via 数据文件夹 rephrase
- ICU integrity: 120 values with renamed/dropped {params} repaired (39
  positional renames, 81 reset to the en source — functional over fluent)

Validation: glossary/pt-BR/vi/deno-relay/settings-keys/value-drift/google-
loopback suites 76/76; placeholder diff en×42 locales = 0; worst-locale
coverage = 100.0%.

Refs #9985

---------

Co-authored-by: backryun <bakryun0718@proton.me>
shardqa added a commit to shardqa/OmniRoute that referenced this pull request Aug 13, 2026
- conol-web registry: fix import path to conolModels (4 levels, not 3)
- conolDiscovery: import getProviderOutboundGuard from outboundUrlGuardPolicy
- modelSelectModalHelpers: close unclosed function brace
- videoGeneration: drop duplicate handleFalVideoGeneration import
- catalogCache: restore test-only SWR accessor hooks removed by diegosouzapw#9199
- gateways: close regolo entry + drop duplicated chatanywhere block
- wasm_signer_bg: stub so Turbopack resolves the TinyCMS wasm import

# Conflicts:
#	src/app/api/v1/models/catalogCache.ts
#	src/shared/constants/providers/apikey/gateways.ts
backryun added a commit to backryun/OmniRoute that referenced this pull request Aug 21, 2026
… mutations

diegosouzapw#9147 (d5e4c0f) added cooperative yields inside the catalog builder,
so reaching the in-flight registration no longer fits in a single
setImmediate tick. The two diegosouzapw#9199 detachment tests mutated catalog state
after one tick — before the first build had registered — so the
post-mutation caller started the only build (runs=1) and the second
assertion saw 1 instead of 2.

Poll on __getCatalogBuilderRunsForTest() until the first build is
registered, then mutate. Detachment semantics under test are unchanged.
5/5 green.
backryun added a commit to backryun/OmniRoute that referenced this pull request Aug 21, 2026
… mutations

diegosouzapw#9147 (d5e4c0f) added cooperative yields inside the catalog builder,
so reaching the in-flight registration no longer fits in a single
setImmediate tick. The two diegosouzapw#9199 detachment tests mutated catalog state
after one tick — before the first build had registered — so the
post-mutation caller started the only build (runs=1) and the second
assertion saw 1 instead of 2.

Poll on __getCatalogBuilderRunsForTest() until the first build is
registered, then mutate. Detachment semantics under test are unchanged.
5/5 green.
diegosouzapw pushed a commit that referenced this pull request Aug 25, 2026
…refresh

`/v1/models` has passed a third argument to `getUnifiedModelsResponse()`
(`{ scheduleBackgroundRefresh: (task) => after(task) }`) ever since #10198, but
#9199 had already removed the parameter: the function takes two, so the object
was silently dropped and `catalogCache` kept scheduling the stale-while-
revalidate rebuild with `setTimeout(..., 0)`. The builder is overwhelmingly
synchronous under the single-threaded App Router, so it pinned the event loop
before the stale response was flushed — the #8728 guarantee did not exist.

- `catalogCache` now imports `after` from `next/server` and exposes
  `defaultBackgroundRefreshScheduler`, which defers to `after()` and falls back
  to a macrotask outside a Next request scope (instrumentation warm-up, tests).
- `resolveCachedCatalogResponse` takes `scheduleBackgroundRefresh` and
  `getStaleWhileRevalidateMs` on its existing options object.
- `getUnifiedModelsResponse` accepts the options object the route already passes
  and propagates the scheduler.

The excess argument was invisible to CI: `tsconfig.typecheck-core.json` is a
curated 27-file allowlist, `check:dashboard-typecheck` only covers
`src/app/(dashboard)`, and `next.config.mjs` sets `ignoreBuildErrors: true`.

Closes #11551
ntdat812 added a commit to ntdat812/OmniRoute that referenced this pull request Aug 26, 2026
diegosouzapw#11551)

`src/app/api/v1/models/route.ts` passes a third argument to
`getUnifiedModelsResponse`:

    { scheduleBackgroundRefresh: (task) => after(task) }

but the function has accepted two parameters since diegosouzapw#9199 removed the injection
point, so the object was silently discarded. `catalogCache` never imported
`after` at all and kept scheduling the stale-while-revalidate rebuild with
`setTimeout(…, 0)`.

`setTimeout(…, 0)` only yields a turn of the event loop — the rebuild still
runs while the response is in flight, so a catalog build that blocks for
hundreds of milliseconds delays the stale body the client was promised. That
is the flush-before-rebuild guarantee diegosouzapw#8728 was written for, and it was not
in effect.

- `catalogCache` gains an exported `BackgroundRefreshScheduler` and a
  `defaultBackgroundRefreshScheduler` built on `after()`, falling back to a
  macrotask when called outside a Next request scope (unit tests, scripts)
  where `after()` throws and flush ordering is meaningless anyway.
- `resolveCachedCatalogResponse` takes `scheduleBackgroundRefresh` and
  `getStaleWhileRevalidateMs` on its existing options object. Neither
  participates in the cache key.
- `getUnifiedModelsResponse` accepts the third argument the route has been
  passing all along and forwards it.

No behaviour change for callers that inject nothing beyond where the rebuild
runs.

Closes diegosouzapw#11551
TheDemonTuan added a commit to TheDemonTuan/OmniRoute that referenced this pull request Aug 26, 2026
* fix(release): restore diegosouzapw#10534 quota recovery and validate the volcengine connect bodies

Two base-reds on the v3.8.50 tip, found by the release pre-flight.

1. diegosouzapw#11355 regressed diegosouzapw#10534. It replaced the per-window recovery check with an
   unconditional `hasActiveCooldown()` stop, which is right for an
   upstream-derived cooldown but also blocks the case diegosouzapw#10534 exists for: a
   Claude-subscription 429 persists a SYNTHETIC 1h rateLimitedUntil because the
   upstream sends no parseable reset. When the later poll shows every governing
   window has really reset with quota left, holding that synthetic cooldown just
   deadlocks the connection for an hour.

   The orphaned `windowStillExhaustedAfterRealReset()` helper and the three
   unused claudeExtraUsage imports that ESLint flagged were the fingerprint of
   this regression, not dead code: they are the two halves of the original gate.
   Re-wired as `isQuotaExhaustedCooldownReleasable()`, deliberately narrow —
   only lastErrorType "quota_exhausted" is eligible, one still-exhausted or
   unknown-reset window keeps the lock, and an extra-usage POLICY block stays
   locked even though its quota windows do look recovered in the same fetch.
   diegosouzapw#11277/diegosouzapw#11355 semantics are untouched (both guards still pass).

   Regression guard: tests/unit/provider-limits-recovery.test.ts already pinned
   this contract and was red on the tip. 15/15 now.

2. The three volcengine-plan connect routes read `request.json()` and handed the
   raw fields to a headless-browser login service after ad-hoc typeof checks
   (`check:route-validation:t06`, Hard Rule #7). `String(body.code ?? "")` turned
   123 into "123" and an absent code into "", both reaching the service as a
   plausible SMS code. Now parsed with Zod schemas, before the session lookup, so
   a malformed body answers 400 instead of a misleading 404.

   New: tests/unit/volcengine-plan-connect-validation.test.ts (8 cases, red
   before the fix). Gate: 687 route files scanned, PASS.

Also drops a genuinely dead import (formatVideoTimestamp in videoBridge.ts —
only used inside the helpers module that defines it).

* fix(release): drain the v3.8.50 docs/golden/GLM base-reds and restore a masked assert

Second base-red batch from the release pre-flight, measured on the .113 with a
clean npm ci (the devbox tree resolves eslint-plugin-react-hooks 7.1.1 from a
stray pnpm store instead of the lockfile 7.0.1 and reports 925 phantom errors).

Provider count 350 -> 352, one root cause behind three reds. Two providers
landed this cycle (volcengine-agent-plan, volcengine-coding-plan) without
regenerating the artifacts that quote the count:

  - docs/reference/PROVIDER_REFERENCE.md regenerated (gen:provider-reference).
  - README / AGENTS / llm.txt (+42 mirrors) / package.json description / 4 SVG
    diagrams updated, including the section heading AND the anchor that links to
    it, so the link does not break.
  - tests/snapshots/provider/translate-path.json regenerated. The diff is purely
    additive: 46 insertions, 0 deletions, exactly the two new providers.

GLM effort tiers. diegosouzapw#11415 added the explicit glm-5.3-max tier and left two
sibling vitest specs pinning the old 16-model inventory and an empty tier list
for it. Aligned to the shipped contract (inventory order matches glmProvider.ts;
glm-5.3-max declares ["max"]).

Test-masking. Four assert reductions surfaced once the deleted-file signal was
resolved. Three are legitimate and are allowlisted with their reasoning:
diegosouzapw#11355 inverted the startup-cooldown contract (preserve future quota cooldowns),
diegosouzapw#11280 replaced two unrolled hops with a 3-hop loop that asserts MORE, and the
Gemini 3.5 Flash retirement removed the models those capability asserts described.

The fourth was real masking: diegosouzapw#10960 rewrote the oneproxy status test to install a
stream mock, immediately overwrite it with a passthrough to the real fetch, and
assert `calls.length >= 0` — always true. Restored to assert what the test name
claims (the JSON-RPC tools/call carries omniroute_oneproxy_stats and its result
reaches the caller), with a scope note that it pins the MCP client contract
rather than the commander wiring.

Also allowlists the Gemini 3.5 Flash test deletion as _deletedWithReplacement
(the model was retired by 2764812; gemini-models-parser.test.ts pins the new
"excluded from the parsed list" contract), and rebaselines bundleSize
8045 -> 8461 with per-entry measurements — every entrypoint stays far below its
absolute budget.

* test(a2a): call the agent-card route handlers with a NextRequest

PR diegosouzapw#11418 (S2 topology sanitisation) removed the hardcoded
localhost:20128 from both well-known agent-card routes and made them
derive the base URL from `request.nextUrl.origin` via
`getBaseUrl(request)` (src/lib/wellKnown.ts). That changed the handler
contract: `GET` now requires the request Next.js always passes it.

Three sibling test files were never aligned and still invoked the
handler as a bare `GET()`, so every case blew up with
`TypeError: Cannot read properties of undefined (reading nextUrl)`
before reaching a single assertion — 8 base-reds from one moved
contract, not from a skill-count drift.

Align the callers to the shipped contract with a local
`makeCardRequest()` helper mirroring tests/unit/security-s1-s2-s4.test.ts
(a Request with a defined `nextUrl`). No assertion was removed,
loosened or skipped; the assert counts are unchanged and the cases now
actually execute.

Refs diegosouzapw#11418

* test(router-eval): give spawned CLI children an explicit DATA_DIR

The router-eval CLI test spawns the CLI with spawnSync and asserts stderr stays empty. NODE_TEST_CONTEXT is inherited by those children, so since diegosouzapw#10432 (guard diegosouzapw#10428) resolveWritableDataDir() detects a test context with no DATA_DIR and warns on stderr before falling back to a throwaway dir - 194 chars that broke three cases. Pass an isolated DATA_DIR in the child env (the resolution the guard message itself prescribes) instead of loosening the assertions.

* test(quota): freeze the clock in the GLM absolute-ISO-reset regression test

The diegosouzapw#11353 regression test pins an ABSOLUTE upstream reset instant
(2026-08-29 21:01:21) in its production fixture body but measured the
resulting cooldown against the real wall clock. The remaining window
therefore shrank every day: from 2026-08-25 it dropped under the
5-day floor the two assertions use, and past 2026-08-29 it would
parse to null and collapse onto the 24h WEEKLY_QUOTA_COOLDOWN_MS
default - a guaranteed future red.

The shipped parser (parseIsoDateTimeResetMs / parseDayGranularityResetMs
/ buildWeeklyQuotaFallback / checkFallbackError) is correct: it returned
the real multi-day reset, just measured from today instead of the
fixtures NOW. Freeze Date at NOW via node:test mock timers in the two
time-dependent cases so they assert the parser rather than the calendar.
No assertion weakened, no production code touched.

* test(providers): use a non-reserved prefix in the CC-compatible node create cases

93da24c ("fix(providers): reject reserved provider prefixes on
compatible-node create/update") made createProviderNodeSchema reject any
prefix that is a built-in REGISTRY id or alias. "cc" is the alias of the
built-in `claude` provider, so the two provider-nodes create cases in
cc-compatible-provider.test.ts started getting a 400 schema rejection
before the route ever reached its feature-flag gate (403) or the create
path (201) — the guard PR updated its own tests but missed this sibling
file, leaving a base-red on release/v3.8.50.

The operator-chosen prefix is incidental to what these cases assert (the
ENABLE_CC_COMPATIBLE_PROVIDER gate, the dedicated
anthropic-compatible-cc- id prefix, baseUrl sanitization and the nulled
modelsPath), so switch it to a non-reserved "cc-proxy". No assertion was
removed or loosened.

* fix(quality): drain the three v3.8.50 inventory/coverage base-reds

All three guards were drifting behind legitimate cycle growth, not catching a
defect. Nothing was weakened: no assertion removed, no floor lowered, no
blanket-allow added.

providers-constants-split: APIKEY_PROVIDERS 231 -> 233. The delta is exactly the
two Volcano Ark plan providers (volcengine-agent-plan, volcengine-coding-plan)
added to the regional family in d732cf6. The invariant the guard exists for
still holds, measured on the tip: 233 merged keys, 233 unique, family sum 233
(gateways 92 + frontier-labs 25 + inference-hosts 29 + enterprise-cloud 17 +
regional 43 + specialty-media 27) with an empty cross-family duplicate set and
an empty symmetric difference between the merged object and the family union -
so the six files are still a strict partition, no loss and no dup.

openapi-coverage: the operation floor (34.6%) is untouched. The cycle grew the
denominator 985 -> 1002 while covered only moved 343 -> 345 (34.4%). Fixed by
DOCUMENTING five real public operations rather than moving the floor, taking it
to 350/1002 = 34.9%: GET /api/health, GET /api/v1/voices, POST
/api/v1/speech-to-text, POST /api/v1/text-to-speech/{voiceId} and GET
/api/v1/explain/routing. Each entry was written from the route source (auth
mode, path-param pattern, limit clamp, upstream relay behaviour and the 400 /
401 / 429 branches), not from memory.

hard-session-lease-bypass-inventory: three new connection-query sites
classified, none silenced. open-sse/services/combo.ts
(readConnectionForCooldownGate) reads the row backing the pre-dispatch
persisted-cooldown gate, so it sits on the routing path and joins the class-B
list next to combo/providerWildcard.ts and autoComboCandidates.ts.
src/lib/providers/volcenginePlanBinding.ts and
src/lib/providers/volcPlanAutoSyncBackfill.ts are connection persistence, not
dispatch - the first resolves update-vs-create during connect, the second is a
one-shot boot backfill of a providerSpecificData flag with no upstream call -
so both stay class C alongside oauth/connectionPersistence.ts.

* fix(release): drain two v3.8.50 base-reds (volcengine vision metadata, antigravity BYOP contract)

Two unrelated real reds on the release tip:

* fix(providers): flag MiniMax M3 as multimodal on the Volcengine Ark plans.
  d732cf6 ("feat(volcengine): add Ark plan providers") added
  volcengine-agent-plan/minimax-m3 and volcengine-coding-plan/minimax-m3
  without supportsVision, breaking the LEDGER-4 invariant that every
  minimax-m3 registry entry except PromptQL (text-only upstream) is flagged
  multimodal. Every other provider carrying the model (opencode-zen,
  opencode-go, bazaarlink, ollama-cloud, codebuddy-cn, trae) sets it.
  Registry metadata defect, not a stale test.

* test(antigravity): align the empty-projectId onboarding test to the
  contract shipped by diegosouzapw#11284/diegosouzapw#11358 (6de542b). That change made an
  onboardUser 200 whose body carries NO cloudaicompanionProject mean Google
  BYOP — no project was created and none ever will be — so it short-circuits
  before the retry loadCodeAssist. The older test still mocked onboardUser
  with the bare { done: true } BYOP shape while asserting the retry path, so
  it pinned a contract that was deliberately moved. The mock now returns a
  real onboarding-success body; every assertion is kept, and the id in the
  onboard body deliberately differs from the expected one so the test still
  proves the projectId came from the retry discovery.

Refs diegosouzapw#11284

* fix(cli): do not treat a tmpfs mount as proof a config path reaches the host

hasBindMountAt() accepted ANY mount as evidence that a would-be CLI config
write reaches the operator's host: it matched on the mount point alone and
never looked at the filesystem type. An in-memory mount therefore cleared the
ephemeral flag, so guardCliConfigWrite() let the write through and both
POST /api/cli-tools/apply and the dashboard's guide-settings writer answered
200 instead of the safe 422 that diegosouzapw#10057 added.

That is the exact case the guard exists to refuse, and the worst one: a
container running with `--tmpfs /tmp` (or a home on tmpfs) loses the file even
before the container is recreated, while the UI reports success.

Parse the filesystem type from mountinfo (the field after the lone "-"
separator) and skip mounts backed by RAM or kernel state. Real bind mounts
(ext4/xfs/nfs/virtiofs/fuse.*) still count, including one nested under a tmpfs
path, so the compose `host` profile is unaffected. A line carrying no
separator proves nothing and is skipped too.

Regression cover added to tests/unit/container-env-detect.test.ts; this also
un-reds tests/unit/cli-tools-apply-container-422.test.ts and
tests/unit/api/cli-tools/apply-container-guard.test.ts, which were failing on
any box whose /tmp is a tmpfs.

* chore(docs): commit the next-dev agent-rules block into AGENTS.md

`next dev` writes and re-adds this block (see
node_modules/next/dist/server/lib/generate-agent-files.js), so leaving it out of
a diff only recreates the uncommitted change on the next dev run. Committing it
keeps the working tree clean, which is what the block's own note prescribes.

* docs(changelog): aggregate the 363 changelog.d fragments into [3.8.50]

Release reconciliation (Phase 0a.1). `scripts/release/aggregate-changelog.mjs`
folds each changelog.d/<section>/*.md fragment into its heading in the living
[3.8.50] section and deletes the fragment, which is the whole point of the
fragment convention: two PRs never touch the same file, so the CHANGELOG never
conflicts mid-cycle and no bullet is eaten by a merge auto-resolve.

Section bullets 731 -> 1041. The remaining uncovered commits (mostly merges from
diegosouzapw#11397 onward, which landed without a fragment) are reconciled separately.

* docs(changelog): reconcile the v3.8.50 section with the cycle's uncovered commits

Adds 131 consolidated bullets (45 features, 71 fixes, 15 maintenance)
covering the ~490 user-facing commits and the ~100 chore/ci/test/refactor/docs
commits that landed in the cycle without a CHANGELOG entry, grouped by
subsystem and citing their PR references.

Uncovered report: 594 -> 175 (the remainder are commits carrying no #N in
their subject, which the matcher can never resolve; they are covered in
prose).

* docs(changelog): date the 3.8.50 header, inject contributors and sync the 42 i18n mirrors

* fix(ci): raise the unit-shard heap ceiling to 8192 MB to stop the SIGABRT OOM

The 8 unit shards run under V8 coverage instrumentation, which retains far more
memory than the bare suite. With the 4096 MB ceiling they began aborting with
exit 134 ("Ineffective mark-compacts near heap limit") at ~4086 MB as the
provider catalogue grew during the v3.8.50 cycle: every test in the shard passed
and the process died at the end, which reads as a test failure without being one.

Aligns test:unit:ci:shard and test:unit:serial with the 8192 MB the non-sharded
variants already use. GitHub-hosted runners have 16 GB, so the headroom is real.
Validated by the CI run on this commit — the shards are the gate.

Refs diegosouzapw#10692

* fix(ci): set NODE_OPTIONS on the unit-shard step and prune stale eslint suppressions

The previous heap bump only touched test:unit:ci:shard, i.e. the node the shard
script spawns. The process that actually runs out of memory is the `c8` wrapper
around it — it aggregates ~577 MB of raw V8 coverage JSON — so the ceiling stayed
at the V8 default (~4 GB) and the shards kept aborting at ~4083 MB, byte for byte
the same failure. Setting NODE_OPTIONS on the step covers c8 and every child,
which is the pattern the coverage-merge job already uses.

Also prunes three eslint suppression entries whose violations no longer exist:
videoBridgeContactSheet.ts and videoBridgeRuntime.ts (no-unused-vars, fixed
during this cycle) and cli-oneproxy-commands.test.ts (no-explicit-any 14 -> 13,
a consequence of restoring the real mock in that test). Stale entries make
`npm run lint` exit 2 with 'There are suppressions left that do not occur
anymore'. Pruned and verified on an uncontaminated checkout, not the devbox.

Refs diegosouzapw#10692

* fix(ci): drain four inherited base-reds in packaging, electron and integration tests

All four predate this session — each reproduces identically on f95b03d (2026-08-24),
so none is a cycle regression. Draining them here because the release pre-flight is
where inherited reds get resolved.

1. Package Artifact: the job runs `build:cli`, which assembles dist/ but never writes
   dist/BUILD_SHA — only `build:release` does, via write-build-sha.mjs. The diegosouzapw#10427
   provenance guard inside check:pack-artifact then rejects the artifact as
   untraceable, and rejects it even under OMNIROUTE_ALLOW_CANARY_BUILD. The job's
   build+validate pair was structurally incompatible and failed 100% of the time.
   Stamps the SHA between the two steps.

2. Electron Package Smoke: electron/package.json's build.files allowlist enumerates
   each lib/*.js by hand and never got lib/loginHeaderCapture.js, added alongside its
   require() in diegosouzapw#9984. The file therefore stayed out of app.asar and the packaged app
   died at startup on 'Cannot find module ./lib/loginHeaderCapture'.

3. proxy-pipeline: the breaker assertion grepped chat.ts for executeChatWithBreaker(,
   but that call moved behind the chatDispatch.ts seam. Rather than drop the check,
   it now pins both hops — chat.ts dispatches through the seam and the seam calls the
   breaker — so the extraction cannot silently take the breaker off the path.

4. skills-pipeline: diegosouzapw#9058 began encoding skill tool names as omr_skill_<base64url>
   because providers require ^[a-zA-Z0-9_-]+$, and these assertions still expected the
   raw name@version. They now derive the expected name from encodeSkillToolName(), the
   same helper production uses, so the test tracks the contract instead of duplicating
   it. Only the assertions about names on the wire were converted; the identifiers
   passed straight to skillExecutor.execute() stay raw, because those are not encoded.

Integration suite for these two files: 54/55. The one still red —
'web_search fallback preserves Responses API output' — is a separate pre-existing
defect, deliberately left failing rather than papered over: on the /v1/responses path
resolveSearchCredentials() returns null for the seeded serper-search connection, so
executeWebSearch.ts:185-200 falls through to the cheapest fallbackOnly provider
(duckduckgo-free) and the results come back empty. The sibling chat-path test seeds
identically and does resolve serper-search. Needs its own investigation.

Refs diegosouzapw#10692

* test(vitest): realign five sibling-test contracts unmasked by the green mcp shard

None of these are cycle regressions. The Vitest job runs test:vitest (mcp shard)
then test:vitest:ui; the mcp shard was failing on a missing glm-5.3-max and aborted
the job before the ui shard ever ran. Fixing that shard this cycle unmasked 34 ui
failures that had been broken since 18-23 Aug — four separate PRs that moved a
contract and updated their own tests but not their siblings.

- ProviderCard gained useRouter() in diegosouzapw#10448; four test files render it without
  mocking next/navigation and died on 'invariant expected app router to be mounted'.
  The sibling created alongside diegosouzapw#10448 already had the mock — it just was not
  applied to the other four consumers.

- SkillCoverage gained a required config category. The four fixtures in
  agent-skills-page still described only api/cli, so the component read
  config.have off undefined. Values were chosen per scenario rather than pasted:
  full coverage gets 2/2 so its bar stays emerald, the amber fixture gets 3/4 so it
  stays amber. CoverageBar renders api -> config -> cli, so the new bar lands in the
  MIDDLE and the cli assertions moved from index [1] to [2]; without that the cli
  checks would have passed while measuring the config bar. The aria test now pins
  all three bars.

- CliAgentsPage hardcoded AGENT_IDS, which had already drifted once (6 -> 8 with
  omp/letta, per its own comment) and drifted again with prime-agent (diegosouzapw#11166). It is
  now derived from CLI_TOOLS. This is why an agent missing from that list is not
  cosmetic: it never enters the status map, defaults to not_installed, and adds a
  phantom card to the filter and count tests. Deriving keeps the fixture in sync by
  construction instead of waiting for the next agent.

- claudeTlsClient asserted proxyUrl was undefined inside a test literally named
  'falls back to env var when per-call proxyUrl not provided' — it pinned the old
  behaviour where testOverride bypassed proxy resolution. diegosouzapw#10910 moved resolution
  ahead of the override on purpose ('so test overrides and the real path both see
  it'), so the assertion now checks the fallback the test name promises.

test:vitest:ui goes from 34 failures to 14. The remaining 14 sit in six files none
of this commit touches (AutoComboCatalog, CoolingConnectionsPanel, ProxyRegistryManager
x2, connectionsSearchFilter) plus one claudeTlsClient case that passes in isolation
and only fails in the full run — i.e. cross-file pollution. They need a clean
environment to judge: this devbox resolves part of its tree through a stray pnpm
store and has already produced one phantom failure count this cycle.

Refs diegosouzapw#10692

* fix(i18n): unstale trafficInspectorSubtitle across 32 locales and regenerate the omni-inference skill

Two gates in the Lint job, both inherited — each was hidden behind the one before it.

i18n value drift: diegosouzapw#11283 rewrote sidebar.trafficInspectorSubtitle in en.json without
touching the 42 translations, so 32 locales kept serving a sentence the English no
longer says. Most take the documented __MISSING__: placeholder, which makes the
runtime serve the corrected English until the translation pipeline catches up.
Three do not:

  - vi cannot take a placeholder at all — tests/unit/i18n-vi-completeness.test.ts
    bans any __MISSING__/__TODO__ value outright, so it needs a real translation.
  - pt and pt-BR are translated for real rather than placeheld, because a placeholder
    there means this project's own maintainer reads the sidebar in English.

Each file changed by exactly one line; the JSON was not reserialised wholesale.

agent-skills-sync: skills/omni-inference/SKILL.md was missing the ElevenLabs voices
and speech-to-text routes added by diegosouzapw#11312, so the generator reported one file out of
date and the gate exited 2. Regenerated — purely additive, 48 lines, no deletions.

Verified: check-ui-value-drift PASS, i18n:check-ui-coverage PASS (42 locales),
i18n-vi-completeness 5/5, check:agent-skills-sync 46 unchanged.

Refs diegosouzapw#10692

* test(vitest): pay heavy module imports at collection time, not out of the per-test budget

The remaining ui-shard reds were one class, not six bugs: every one of them did
`await import(<heavy component>)` INSIDE an `it()`, so Vite's transform of the
dependency graph was billed to that test's timeout. Measured costs against the
budgets they had to fit in:

  ProxyRegistryManager   86s import vs 30s / 60s / 5s budgets (render itself: 567ms)
  claudeTlsClient       ~12s import vs 5s default
  useProviderConnections  1050-line hook, whole dashboard graph, vs 5s default

That is why they looked like cross-file pollution: on an idle box the import
squeaked under the limit, and under the ui suite's 20 parallel workers it did not.
Running claudeTlsClient ALONE on a loaded box reproduces it — the trigger is CPU
contention, not a neighbouring file. The sibling chatgptTlsClient/grokTlsClient
tests import the same graph and never fail, because they import statically at
module scope, where the cost falls on the collection phase which has no per-test
budget. Every fix here does the same: static import or a beforeAll with its own
budget.

AutoComboCatalog also explains its own blast radius: the timeout aborted inside an
open act(), leaking an unbalanced act scope that then failed the file's three
remaining tests in ~20ms with 'overlapping act() calls'. One slow import, four reds.

CoolingConnectionsPanel is the one production change. It imported providerText from
the ../providerPageHelpers barrel, but that symbol is DEFINED in the
../providerCredentialText leaf and only re-exported by the barrel — which drags
providerRegistry (352 providers) and the rest of the provider-page graph into a
"use client" component for one string helper. Verified before accepting: the
component used nothing else from the barrel, the barrel has no top-level
side-effect to lose (the empty-registry hazard this repo has hit before does not
apply), typecheck:core is clean, and the panel's first test drops from ~4s to 95ms.
The import was suboptimal, never broken — the screen was not failing for users.

No assertion was weakened anywhere. expect() counts are unchanged (25/25, 4/4) or
up by one (AutoComboCatalog 11 -> 12); the diegosouzapw#8855 autofill sentinels, the
data-1p-ignore / data-lpignore guards and the dead-status round-trip are intact.

The diegosouzapw#5918 TDZ guard was proven still live by mutation, not by absence of red:
moving useProxyBatchOperations(load) above its const reproduced
'ReferenceError: Cannot access load before initialization' in 207ms, then the
production file was restored (diff empty).

tests/unit/ui under load: 17 failed files / 45 failed tests -> 4 failed files /
4 failed tests, none of them these. The four left are compression-guidance-7530,
compressionPanel, compressionUltraTier and lobe-provider-icons-stepfun, untouched
and uninvestigated.

Refs diegosouzapw#10692

* test(integration): realign three suites to security and version contracts that moved

All three are the sibling-test gap again: a PR moved a contract, updated its own
tests, and left these behind. None is a production defect — in two of the three the
production side is a deliberate security fix.

v1-contracts-behavior (4 failures, one cause): the job env sets INITIAL_PASSWORD,
which makes isAuthRequired() true, and diegosouzapw#9320 (b07182c) made the /v1 catalogue
gate on-by-default instead of opt-in via settings.requireAuthForModels. The four
contract reads were calling the catalogue routes with no credential and correctly
getting 401. Bisected the job's four env vars to confirm INITIAL_PASSWORD alone
reproduces it (5 pass / 4 fail with it, 9 / 0 without). The tests now send a Bearer
token; the shape assertions are untouched, and the auth contract itself stays owned
by tests/unit/v1-models-auth-leak-9320.test.ts rather than being duplicated here.

opencode-config-startup: two independent drifts. OPENCODE_VERSION was pinned to
1.18.8 while the installed opencode-ai is 1.18.18 (Dependabot 7f69589, diegosouzapw#10626) —
now read from require("opencode-ai/package.json").version, which is exactly as
strict but cannot drift on the next bump. And the no-limit-metadata case asserted
limit === undefined, but diegosouzapw#11054 made the generator always emit a limit; it now pins
the actual fallback {context: 128_000, output: 8_192} instead of an absence.

memory-pipeline: diegosouzapw#11040 (GHSA-cpv3-xr7r-xf8q) made the resolved caller principal
always win over a caller-supplied apiKeyId, so a spoofed id can no longer write into
another principal's store. That PR updated the unit sibling but not this one. The
test now asserts the stronger property — and deliberately not just the absence: the
spoofed principal's store is empty AND the caller can still read the entry, which
proves the write was redirected rather than dropped and keeps the emptiness check
from passing vacuously with a disabled store. (The old assertion was count === 0,
which a switched-off memory store would satisfy.)

Assertion counts: 43 -> 43, 13 -> 14, 76 -> 81. Nothing weakened or removed.
Verified: 24/24 pass, with and without the CI env vars.

Refs diegosouzapw#10692

* fix(ci): drain the electron packaging regression, the models-catalog e2e assertion and 10 integration reds

Electron Package Smoke — a packaging defect that had been hidden behind another
packaging defect for nine days. Once the loginHeaderCapture fix let the main process
start, the server underneath died on 'Cannot find module next': resources/app/server.js
shipped without resources/app/node_modules.

electron-builder discards the ROOT node_modules in code, not by configuration —
app-builder-lib/out/util/filter.js:42 has a hard-coded `if (relative === "node_modules")
return false` that runs before any filter pattern. The second extraResources entry
pointing INTO ../.build/electron-standalone/node_modules is what sidesteps it, because
those relative paths are never equal to "node_modules". diegosouzapw#10325 removed that entry as an
apparent duplicate and flipped the test to assert "exactly once", freezing the
regression as if it were the contract. Restored, and the unit guard now pins both
entries — proven by mutation: reverting package.json to the post-diegosouzapw#10325 shape fails the
guard 3/4, restoring it passes 4/4.

group-b-quota-plans-config — the assertion was impossible to satisfy on ANY route, and
the page was never broken. layout.tsx hands the whole message catalogue to
NextIntlClientProvider, React serialises that prop into the RSC payload, and en.json
carries "Internal Server Error" twice, so page.content() always contains it: probing
/dashboard, /dashboard/costs, /dashboard/settings and /login showed the string present
with every page rendering fine, and a pageerror probe on the failing run captured zero
client exceptions. This is the same trap that killed the sibling not.toContain("500")
in fc77100 ("raw HTML is unreliable") — that one was removed, this one was kept.
Now asserts on rendered text, which still catches a real error boundary. The pageerror
capture stays: the CI failure carried no stack trace, which is why it was misread twice.

Integration — 10 of the 14 shard-2 reds, all sibling-test gaps behind security fixes:
monitoring health now takes a Request and requires management auth (GHSA-mvf8-qc78-5mxm);
the OAuth import routes moved to requireManagementAuth (GHSA-mg76) — the test accepts
both guard shapes and gained a stronger anchor that every exported handler awaits a
guard on its own request, mutation-verified; skill tool names are derived from
encodeSkillToolName() and the fake upstream now returns the encoded name so
decodeSkillToolName() is exercised too; previous_response_id now fails closed (diegosouzapw#10262);
proxy_logs persist as an async batch (diegosouzapw#11182) so the test flushes first;
providerQuotaOverrides joined GET /api/resilience (diegosouzapw#9871); the reasoning fixture used a
model that stopped being thinking-incompatible, replaced and pinned with a premise
assert so it cannot rot silently again.

A vacuous assert.ok(true, "all 10 streams completed without hanging") was replaced with
real anchors — content must arrive on every stream and the active Timeout count must not
grow.

Four are deliberately left red rather than aligned, each now tracked: diegosouzapw#11551 (the
/v1/models after() wiring is dead — the route passes a third argument to a two-parameter
function and catalogCache never imports after, so the diegosouzapw#8728 contract is unimplemented),
diegosouzapw#11552 (~27% of requests emit an extra discarded upstream call; the delivered
distribution is exactly 0.70, so weighted routing is correct and the waste is the real
finding), the fixed-account combo pin (aligning it would destroy the per-step attribution
the test exists for), and the web_search fallback already tracked as diegosouzapw#11524.

Package Artifact — the provenance stamp I added last round used git rev-parse HEAD, which
under pull_request is the ephemeral merge commit and therefore never an ancestor of the
release branch. Now takes the PR head sha.

Refs diegosouzapw#10692

* test(ui): unmount before asserting so the auto-sync timer cannot outlive the test

Vitest went red on 'synchronizes upstream models only when autoFetchModels is
explicitly true' with new URL throwing inside a fetch dispatched from
Timeout._onTimeout (useProviderModels.ts:69). It is intermittent: green in the two
previous CI runs, green every time in isolation, red only under the ui suite's 20
parallel workers.

The hook schedules its auto-sync in a setTimeout whose callback only checks the
 flag on entry — and that flag stays false while the component is
mounted. Both tests asserted first and unmounted last, so under contention the
timer escaped the test window, fired after afterEach had already run
vi.unstubAllGlobals(), and reached the REAL fetch with a relative URL.

Unmounting before the assertions closes the window: cleanup flips , the
callback returns early, and the calls already recorded on fetchMock are still there
to assert against. No assertion changed.

Not a regression from this cycle — the file's last change is fd76271 (diegosouzapw#10603).
Fixed rather than tracked because an intermittent red in a blocking job is worse
than a permanent one: it teaches people to re-run instead of to look.

Refs diegosouzapw#10692

* fix(search): prefer the configured search connection over duckduckgo-free

When no explicit provider is requested and the auto-selected cheapest
provider has no credentials, executeWebSearch ran the fallbackOnly loop
first. duckduckgo-free (costPerQuery 0, authType none) always won there
with an empty credentials object, so a configured paid connection such as
serper-search was silently ignored and the caller got success:true with
zero results.

Move the sweep for other credentialed regular providers ahead of the
fallbackOnly loop (and exclude fallbackOnly ids from it, so a free
last-resort provider never outranks a configured one on cost). The
fallbackOnly loop stays as the true last resort.

The chat path only appeared correct because duckduckgo-free happened to
fail there and handleSearch retried the alternate provider; on
/v1/responses it "succeeded" with no results.

Closes diegosouzapw#11524

* fix(api): restore the after() injection point for the /v1/models SWR refresh

`/v1/models` has passed a third argument to `getUnifiedModelsResponse()`
(`{ scheduleBackgroundRefresh: (task) => after(task) }`) ever since diegosouzapw#10198, but
diegosouzapw#9199 had already removed the parameter: the function takes two, so the object
was silently dropped and `catalogCache` kept scheduling the stale-while-
revalidate rebuild with `setTimeout(..., 0)`. The builder is overwhelmingly
synchronous under the single-threaded App Router, so it pinned the event loop
before the stale response was flushed — the diegosouzapw#8728 guarantee did not exist.

- `catalogCache` now imports `after` from `next/server` and exposes
  `defaultBackgroundRefreshScheduler`, which defers to `after()` and falls back
  to a macrotask outside a Next request scope (instrumentation warm-up, tests).
- `resolveCachedCatalogResponse` takes `scheduleBackgroundRefresh` and
  `getStaleWhileRevalidateMs` on its existing options object.
- `getUnifiedModelsResponse` accepts the options object the route already passes
  and propagates the scheduler.

The excess argument was invisible to CI: `tsconfig.typecheck-core.json` is a
curated 27-file allowlist, `check:dashboard-typecheck` only covers
`src/app/(dashboard)`, and `next.config.mjs` sets `ignoreBuildErrors: true`.

Closes diegosouzapw#11551

* fix(sse): stop re-summarizing a universal handoff that never parses

A universal handoff whose summary comes back unparseable persists nothing,
so shouldGenerateUniversalHandoff keeps answering "generate" and the very
next model switch in the same session re-issues the same full-history
summarization call and discards the answer again — forever.

With a switch-heavy combo strategy (weighted, random, round-robin, p2c) the
models alternate on almost every turn, so that background call lands on a
large fraction of requests: an upstream call whose response nobody reads is
real money on a paid provider and real quota on a metered one. Measured on
the weighted 70/30 matrix, that inflated the observed openai share to 0.895
where routing actually delivered 0.70, and at the unit level 199 of 200
model switches issued a fresh discarded summarization call.

Back off per (session, combo) after an answer that is not a usable handoff:
exponential 5min -> 1h, cleared on the first successful generation, capped
at 500 tracked keys. Deliberately narrow — a transient upstream failure
(!response.ok) is NOT tracked, so it still retries on the next switch, which
is the behavior the context-relay path already depends on.

After the fix, same harness at n=200: 201 upstream calls for 200 requests
(1 extra, 0.5%), and the measured openai share equals the delivered share
(0.725). The unit guard drops 199 discarded calls to 1.

Refs diegosouzapw#11552

* fix(sse): honor per-step connection pins instead of rotating accounts on fallback

A combo step pinned with an explicit `connectionId` (or a request pinned via
`x-omniroute-connection`) is an operator instruction, not a hint. The generic
account-fallback branch in handleSingleModelChat excluded the pinned connection
after an upstream failure and re-selected a sibling account of the same provider,
so a priority combo repeating one provider/model with two different fixed accounts
ran both attempts under the FIRST step: the second step, with its own pin, never
executed and per-step attribution (comboStepId / comboExecutionKey) was wrong.

Gate the rotation on `!hasForcedConnection`, matching the antigravity
stream-readiness, pre-response-timeout and account-semaphore branches that already
let pinned steps fall through to combo orchestration. Cooldown recording via
markAccountUnavailable is unchanged, and unpinned selection still excludes burned
connections.

Refs tests/integration/combo-routing-e2e.test.ts

* fix(ci): point the pack-artifact provenance gate at the branch under test

The guard added for diegosouzapw#10427 checks ancestry against origin/main by default. That
is the right ref at publish time (npm-publish.yml runs on main), but in a
pull_request context it can never hold: while the PR is open its head is by
construction not an ancestor of main, and the shallow checkout does not even
bring origin/main into the local graph, so the probe answers false regardless.
The job therefore failed 100% of the time and only became visible now that it
stopped being cancelled behind Build.

Pre-merge the one checkable invariant is that the stamp matches the branch under
test, so resolve the ref from refs/pull/<N>/head — which exists on origin even
for fork PRs, unlike head.ref, which only exists on the author's repository.

* test(dashboard): open the proxy toolbar overflow menu before bulk assign

PR diegosouzapw#9870 moved the proxy-registry bulk-assign action into the toolbar's
"More actions" (…) overflow menu, which renders its items only while open.
The e2e smoke flow still clicked the testid directly, so the locator never
resolved and the test burned its full 180s budget.

Open the menu first and assert it is visible before clicking; every existing
assertion is unchanged.

* fix(dashboard): restore expert-mode manual model entry in the combo builder

PR diegosouzapw#8285 (global model search) replaced the expert-mode "Manual model"
block positionally with the new GlobalModelSearchPanel, dropping the only
way to type a provider/model pair by hand in expert mode. The supporting
state and handlers (manualModelInput, manualModelError,
manualModelHasDuplicate, handleAddManualModel) survived as dead code, so
neither typecheck nor lint flagged the loss.

Re-render the block above the search panel, unchanged from its pre-diegosouzapw#8285
form. Regression guard: tests/e2e/combos-flow.spec.ts "expert mode shows
a single-page combo form with manual model entry", which had been failing
with a 180s timeout on locator.fill for combo-manual-model-input.

* test(api): accept the post-diegosouzapw#9320 auth gate on the /v1/models e2e check

b07182c (diegosouzapw#9320) inverted the catalog auth rule: /v1/models now requires auth
whenever management auth is configured, unless requireAuthForModels is explicitly
false. The e2e harness boots with INITIAL_PASSWORD set, so the endpoint has been
answering 401 since 2026-08-04 and this check has been red ever since — invisible
only because the job kept being cancelled behind Build.

Mirror the sibling /api/providers check in this same file: assert the catalog
shape whenever the catalog is actually served, and otherwise pin the auth gate by
status AND error type, so a 401 from an unrelated misroute cannot pass for the
deliberate one.

---------

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: Xiangzhe <diegosouza.pw@gmail.com>
Co-authored-by: Xiangzhe <bakryun0718@proton.me>
Co-authored-by: TheDemonTuan <nguyenviettuanbp@gmail.com>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
)

* fix(models): preserve catalog on affinity bookkeeping

Related to diegosouzapw#8697.

Focused follow-up to diegosouzapw#8728; this does not replace or supersede that contribution.

* docs(changelog): record model catalog affinity fix

* fix(models): keep cold catalog builds responsive

* docs(changelog): record catalog responsiveness fix

* fix(models): snapshot auto candidate capabilities

* fix(models): invalidate capability catalog snapshots

* test(models): register catalog invalidation coverage

* fix(models): bulk-load catalog capability snapshots

Resolve synced capabilities and persisted overrides from one build-local view instead of repeating per-target SQLite reads. Keep ordinary runtime lookups on demand and preserve catalog generation invalidation.

Refs: diegosouzapw#9199

* fix(models): snapshot catalog pricing once per build

Production profiling showed per-model models.dev pricing reads and JSON parsing dominated cold catalog builds. Reuse one build-local pricing snapshot during enrichment and yield before publication so queued health checks can run, while preserving fresh reads for ordinary callers.

* docs(changelog): record catalog pricing snapshot
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…sh (diegosouzapw#10198)

The Build CI job is advisory, so eight module-level defects from eight
different PRs accumulated on release/v3.8.50 until `npm run build` failed
with 7 Turbopack errors and `npm run lint` with 14.

Build (link-time):
- modelSelectModalHelpers.ts: a lost `}` swallowed PROVIDER_TEST_CHUNK_SIZE
  into isProviderModelHidden's body (diegosouzapw#9011).
- videoGeneration.ts: handleFalVideoGeneration imported twice; the standalone
  falHandler.ts is superseded by the provider-neutral mediaGeneration/fal.ts
  and is removed here (diegosouzapw#9982 over diegosouzapw#9969).
- catalog.ts: re-exported and called the injectable SWR policy that diegosouzapw#9199
  deliberately replaced with a fixed 30s bound. Fixed on the consumer side —
  restoring the accessor would resurrect the unbounded window diegosouzapw#9199 removed
  after measuring a 41s catalog build in production.
- tinycmsSigner.ts: generated wasm-bindgen glue kept a sidecar
  `new URL('wasm_signer_bg.wasm', import.meta.url)` that no file backs;
  Turbopack resolves it statically. The module ships inlined as WASM_BASE64
  and the only caller always passes it explicitly (diegosouzapw#8736/diegosouzapw#10087).
- conolDiscovery.ts: imported getProviderOutboundGuard from outboundUrlGuard,
  which does not export it. Fixed on the consumer side: outboundUrlGuard.ts is
  loaded by the packaged CLI without a tsconfig, so it must stay free of
  `@/`-aliased imports (diegosouzapw#7682).

Runtime (the build never caught this one):
- catalogCache.ts::scheduleBackgroundRefresh had two dangling statements
  referencing undeclared `inFlight`/`promise`, so EVERY stale-while-revalidate
  read threw a ReferenceError. Surfaced by realigning the diegosouzapw#8728 suite, which
  diegosouzapw#9199 left asserting a removed contract.

Lint:
- driverFactory.test.ts: a case inserted between the preceding test's `finally`
  and its `});` left the file unparseable, so the SQLite driver-cascade suite
  (26 tests) had not run since 2026-08-11 (diegosouzapw#9173).
- providerModelsConfig.ts: imported an executor directly, crossing the G14
  boundary; routed through a new open-sse/services/zaiWebCredentials.ts (diegosouzapw#8451).
- image-combo.test.ts: 11 `any` violations, now typed (diegosouzapw#9499).

Validation: npm run build exit 0, npm run lint clean, typecheck:core clean,
41/41 tests green across the affected suites.

Refs diegosouzapw#9011 diegosouzapw#9982 diegosouzapw#9199 diegosouzapw#8728 diegosouzapw#8736 diegosouzapw#10087 diegosouzapw#8974 diegosouzapw#9173 diegosouzapw#8451 diegosouzapw#9499

Co-authored-by: backryun <bakryun0718@proton.me>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
) (diegosouzapw#10131)

* fix(quality): green release/v3.8.50 base-reds round 2 — gateways/conol/deepai corruption, migrations, docs, ratchets, dashboard-typecheck

Base-red fix for issue diegosouzapw#9985 after the 2026-08-11 merge storm (99 PRs).

Real defects fixed:
- gateways.ts: close regolo entry (was swallowing naga-ac + chatanywhere from diegosouzapw#9421), drop stale duplicate chatanywhere entry (diegosouzapw#9594)
- conol-web + deepai registry: correct ../shared import depth + deepai executor:default
- modelSelectModalHelpers: close isProviderModelHidden (diegosouzapw#9011)
- driverFactory.test.ts: restore eaten test-closing brace (diegosouzapw#9173)
- usageTracking: remove duplicate cache_* props
- modelCapability{Overrides,ResolutionSnapshot,Capabilities}: max_token -> max_output_tokens (diegosouzapw#9199 vs diegosouzapw#8908) + test align
- videoGeneration: drop duplicate handleFalVideoGeneration import (mediaGeneration/fal canonical, diegosouzapw#9982)
- responseSanitizer: cast input_tokens_details before .cached_tokens access
- EditConnectionModal: missing alibaba code fields, hoist validationPsd, providerPageHelpers Badge variant union
- FreeBudgetCard: t() -> labels.noApiKey
- peerRouting + cliRuntime: ProcessEnv typing
- image-combo.test.ts: type any -> unknown
- fal.test.ts: moved to tests/unit/services (collected path) 14 tests green
- remove duplicate 143_job_registry.sql (146 canonical), KNOWN_GAPS fix

Docs/ratchets (owner-authorized rebaselines, annotated):
- CHANGELOG 3.8.50 living section restored + 42 i18n mirrors
- MCP-SERVER.md 104->105 tools + i18n
- ENVIRONMENT.md/.env.example: ADOBE_FIREFLY_CHROME_HEADED + DEBUG_CLAUDE_NONSTREAM
- fabricated-docs allowlist: TELEGRAM proposal env vars
- file-size: 5 grown files + proxyFetch 1207->1220
- dead-code 230->248, codeql 2->9 (drift from merged PRs, not this PR)
- untrack _tasks symlink; agent-skills-sync --apply (config-codex-cli)

* fix(changelog): reformat two feature fragments to the bullet convention (diegosouzapw#9239, diegosouzapw#9490)

* fix(quality): prune stale ESLint suppressions (base-red)

* fix(quality): resolve open-sse type errors + catalog/build regressions (base-red round 3)

Storm-merge splices repaired in the base-fix PR diegosouzapw#10131:
- doctor.ts: AppConfig missing brokerSocketPath
- conol-web.ts: Buffer not assignable to BodyInit (Uint8Array)
- tinycms.ts: TinyCmsExecutor.execute return matches BaseExecutor (response/url/transformedBody)
- tinycmsSigner.ts: encodeInto never-narrowing guard + dead wasm URL fallback (Turbopack)
- virtualFactory.ts: options slot for resolutionSnapshot
- bottleneckPatch.ts: insufficient-overlap casts (as unknown as)
- imageCombo.ts: narrow handleImageGeneration union result
- browser-worker.ts: AppConfig + turn.capabilities splice
- conolDiscovery.ts: getProviderOutboundGuard from Policy module
- catalog.ts: drop removed SWR hooks (getCatalogStaleWhileRevalidateMs + accessors), CatalogCachePolicy -> inline settings, resolve 4-arg call
- catalogCache.ts: remove dead inFlight/promise refs
- chat.ts: add isProviderBreakerFailureStatus import
- model-catalog-cache-swr-8728.test.ts: align to diegosouzapw#9199 new API (policy injection removed)

* fix(quality): align UI test fixtures to current component contracts (base-red vitest)

- setup-wizard: provide required serverState prop (component gained it in a merged PR)
- grok-device-oauth-modal: next-intl stub resolves grok flow keys to EN labels
- provider-quota-widget: label now inline (PR diegosouzapw#8916 removed AutoRefreshButtonLabel extraction) — test the widget
- use-provider-connections-cursor-refresh + phase1f: match /api/providers?provider=<id> query form; hoist heavy dynamic imports to module scope (timeout flake)
- home-topology: mock next/navigation useRouter (component added node-click navigation)
- cooling/lobe/AutoComboCatalog: raise cold-import describe timeouts to 30-60s
- request-logger-*: align to current detail-view contract

* fix(search): guard params.token undefined in serper headers (typecheck base-red)

* fix(search): guard token headers + non-null providerConfig (typecheck base-red)

* fix(changelog): restore base CHANGELOGs eaten by merge auto-resolve (43 files)

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: backryun <bakryun0718@proton.me>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…0213)

* fix(ci): clear base-reds on release/v3.8.50 (round 3)

- CHANGELOG.md: restore the top [Unreleased] section dropped by the diegosouzapw#10189
  reconcile (docs-sync gate: first section must be Unreleased)
- env-doc-sync: document CONDUCTOR_ORCHESTRATOR_TOKEN + CONDUCTOR_SPOKESPERSON_URL
  in .env.example/ENVIRONMENT.md; allowlist the CI-only GITHUB_STEP_SUMMARY and
  TS7_BASE_REF (ts7 ratchet signals); drop a stray merge artifact line
- providers: restore the audited chatanywhere metadata entry that base-reds
  round 2 dropped together with its duplicate — the provider was half-wired
  (registry+endpoint without APIKEY metadata), which is what the wave3 test
  catches; re-pin providers-constants-split at the measured 228
- docs counts: 338 -> 339 (today's +2 void-ai/helixmind, -1 Puter) via
  gen:provider-reference + README/AGENTS/llm.txt/package.json/diagrams/i18n mirrors
- file-size ratchet: annotated rebaseline for the two pre-existing drifts
  (ModelSelectModal 1138, gateways 1250) following the 2026-08-11 precedent

Refs diegosouzapw#9985

* fix(ci): base-reds round 3b — stale sibling tests + mode-pack weight contract

- check-docs-counts-sync.test.ts: drop the imports/subtests of the four helpers
  diegosouzapw#10196 removed from the gate script (readMcpFactsFromSource, listLocalizedDocs,
  makeRequiredCountsValidator, checkFreeTierInventory) — the new-API tests that
  diegosouzapw#10196 added stay; the file now loads again under the node runner
- quota-connection-recovery.test.ts: convert from vitest APIs to node:test —
  the file lives in tests/unit/*.test.ts (node-runner glob) and the vitest
  runtime crashes when imported outside vitest, killing the whole shard entry
- modePacks.ts: re-normalize all six mode packs to sum 1.0 — diegosouzapw#8940 added
  sessionAvailability: 0.05 to every pack without rebalancing (1.05 total);
  ratios preserved exactly (÷1.05), so post-normalizeScoringWeights behavior
  is unchanged; restores the declared sum-to-1.0 contract the 4235 test pins

Refs diegosouzapw#9985

* fix(ci): base-reds round 3c — vitest siblings, weights default, secrets FP, mutation tap

- DistributeProxiesButton.test.tsx: wrap renders in NextIntlClientProvider —
  diegosouzapw#9245 localized the component (useTranslations) and left the test without
  the intl context, failing all 14 cases
- scoring.ts: re-normalize DEFAULT_WEIGHTS to sum 1.0 (same diegosouzapw#8940 class as the
  mode packs — sessionAvailability added without rebalancing; ratios preserved)
- .gitleaks.toml: generalize the kimi sponsor-banner localStorage-key allowlist
  to -v\d+ — diegosouzapw#10200 bumped v1→v2 and the stale regex regressed the secrets
  ratchet with a false positive
- stryker.conf.json: register 6 covering unit tests in tap.testFiles (4 modules)
  so their mutant kills count — unblocks check:mutation-test-coverage --strict

Refs diegosouzapw#9985

* fix(ci): base-reds round 3d — inspector factor gap, stale registry/gap tests, i18n key sync

- comboScoringInspector: add cacheAffinity/sessionAvailability/connectionDensity
  to FACTOR_KEYS + the factor-key type — calculateScore() weighs them but the
  breakdown omitted them, so the explained contributions never summed to the
  reported score (inspector bug, red on the pure tip)
- combo-scoring-inspector.test: make the explicit-weights override sum-neutral
  (±0.05 shift) so it stays valid for any DEFAULT_WEIGHTS values — the hardcoded
  override only summed to 1.0 against the pre-diegosouzapw#8940 defaults, which is also why
  explicit weights silently fell back to 'default' on the tip
- unorouter-registry.test: align to the canonical .com host (api.unorouter.ai
  301-redirects there, verified live) and to wave4's live model discovery
  (passthrough, no static seed) — the .ai/auto-model expectations were stale
- check-migration-numbering.test: 147 left KNOWN_GAPS when
  147_api_keys_model_access_mode.sql landed — assert absent (same as 143)
- i18n: sync-ui pass — 35,914 missing UI keys stamped as __MISSING__ placeholders
  across 42 locales (mechanical; greens the pt-BR key-presence integrity test;
  coverage pct unchanged by design — translation is a separate workstream)

Refs diegosouzapw#9985

* fix(ci): base-reds round 3e — 2 real defects + 14 stale sibling tests (waves A-E)

Real defects fixed:
- src/lib/db/apiKeys.ts: diegosouzapw#9313's empty-allowlist early return bypassed the group
  permission check, silently disabling group deny rules (diegosouzapw#8817) for every key
  without a per-key allowlist; fall-through restored, restricted+[] deny-all kept
- open-sse/utils/proxyFetch.ts: diegosouzapw#10032 re-appended the raw transport error to the
  propagated message, reintroducing the proxy user:password leak diegosouzapw#9837 closed;
  new redactProxyDetailsInMessage() keeps the reason, redacts URL/credentials
- .github/workflows/quality.yml: diegosouzapw#10134 added the TS7 ratchet as a separate
  blocking step AFTER the aggregated gates — the exact diegosouzapw#8542 masking mechanism;
  folded into the non-fail-fast loop (still blocking, still PR-only) ⚠️ CI edit,
  gate-strengthening — explicit owner sign-off requested on the PR
- src/i18n/messages/ko.json: 3 machine-mistranslation regressions caught by the
  diegosouzapw#8244 glossary checker (장애인→비활성화됨, 양말5://→socks5://, 비클로드→Claude가 아닌)

Stale sibling tests aligned to deliberately-moved contracts (each cites its mover):
request-log-detail-layout + -stream (diegosouzapw#9245 intl provider), repro-8542 pin update,
quality-rail-gate-membership (diegosouzapw#10134 shape), agentSkills-routes 45→46 (diegosouzapw#9058),
cloudflare-ai-catalog-8717 (diegosouzapw#8804 supersedes diegosouzapw#8808), executor-xai (diegosouzapw#9994),
vision-bridge-claude-wire (diegosouzapw#9463 minimax→openai), sse-auth forced-pin (diegosouzapw#8893),
tls-proxy-context (strengthened leak guards), rate-limit-local-error-classification
(diegosouzapw#9164/diegosouzapw#9342), minimax-thinking-signature (diegosouzapw#9463), codebuddy-cn (diegosouzapw#9723 +1 test),
github-copilot-custom-model (diegosouzapw#9050), providers-g4f-batch3 (diegosouzapw#9584),
synced-capability-warmup (diegosouzapw#9199, stricter), sidebar-tools-group (diegosouzapw#8221),
oauth-modal-grok-cli-paste (diegosouzapw#9245); agentSkills/catalog.ts comment 45→46;
file-size rebaseline for proxyFetch (+19, annotated)

Refs diegosouzapw#9985

* fix(ci): base-reds round 3f — waves F-J: 9 more real defects + stale sibling sweep

Real production defects fixed (all red on the pure tip, each with its origin):
- routeGuard.ts: diegosouzapw#8949 accidentally DELETED the /api/providers/[id]/login
  local-only pattern — the route spawns a browser, so the loopback gate for a
  process-spawning route was gone (Hard Rules diegosouzapw#15/diegosouzapw#17); restored (314 guard
  tests green)
- agentSkills generator: diegosouzapw#9058's category dispatch gave the config category an
  empty body, wiping skills/config-codex-cli/SKILL.md at the diegosouzapw#10131 sync;
  fixed + SKILL.md regenerated via the official generator
- imageRegistry: diegosouzapw#9982 broke same-provider bare aliasing (antigravity preview
  id sent upstream unresolved); new resolveSameProviderBareAlias() keeps the
  fal cross-provider fix intact
- imageRegistry: diegosouzapw#9982's prefix strip handed the bare nano-banana ids to fal-ai,
  violating the pinned 2026-07-31 operator decision (adobe-firefly owns them);
  fal entries made prefix-only (dispatch already re-prefixes)
- mediaGeneration/fal.ts: the missing-credential 401 guard was lost when diegosouzapw#10198
  deleted the superseded falHandler — tests were hitting the live network
- bottleneckPatch/rateLimitManager: diegosouzapw#9041's merge clobbered diegosouzapw#9604, resurrecting
  the Bottleneck v2.19.5 heartbeat bug (reservoir never refills); patched the
  library defect at the root and re-aligned chat-rate-limit-body-lock to the
  working reservoir contract
- processSupervisor.mjs: diegosouzapw#9761 regressed the Node spawn to bare "node" (the
  diegosouzapw#9156 launchd bug) and dropped diegosouzapw#9209's ipv4first args; both restored
- openai-responses/pureHelpers: diegosouzapw#9423's Agent null-sentinel was unreachable on
  the schemaless JSON-string path; gate extended
- i18n en.json: diegosouzapw#8222's regen reverted the diegosouzapw#9976 unclosed-tag fix and diegosouzapw#8559's
  combo-cooldown copy; diegosouzapw#9038 shipped 40 t() calls with no messages (runtime
  MISSING_MESSAGE); all restored/added + official sync-ui stamps, and vi's
  zero-marker policy re-established via the sanctioned translation backend

Stale sibling tests aligned (movers cited inline): chat-helpers (diegosouzapw#9447),
executor-antigravity (diegosouzapw#9351), video-fal-grok (diegosouzapw#9982), visionBridge (diegosouzapw#9759),
web-session-credentials (diegosouzapw#8974), production-build-module-integrity (positive
anchor added), agentSkills-generator/skillManifestsLint/skills-injection/
agentSkillTools-mcp/listCapabilities-a2a (diegosouzapw#9058), memory-settings (diegosouzapw#10010),
model-catalog-policy-invalidation (diegosouzapw#8906), model-alias-seed (diegosouzapw#9485),
reactive-context-compaction (diegosouzapw#8949), combo-provider-wildcard (broken upsert
helper), oauth-google-loopback (43-locale resurrected-key removal)

Validation: 501/501 across the 47 touched test files; typecheck:core, lint,
file-size, docs-sync all green.

Refs diegosouzapw#9985

* fix(ci): base-reds round 3g — wave K/L: 4 more real defects + stale alignments

Real defects:
- base/reasoningEffort.ts: the stale duplicate cherry-pick diegosouzapw#9612 re-added the
  codex minimal→low rewrite that diegosouzapw#9883 had deliberately removed (OMP minimal
  passthrough); block removed again
- cursorImages.ts: diegosouzapw#9840 wired prepareCursorImageForWire (sharp re-encode,
  fail-closed) into the SHARED resolveCursorImages, breaking zai-web and
  conol-web image uploads (HTTP 400 'undecodable'); new prepareForWire opt-out,
  Cursor default path unchanged (8 cursor suites green)
- modelCapabilities/snapshot: catalog prepare still issued 323 per-model reads
  of model_context_overrides + max_input_tokens overrides, violating diegosouzapw#9199's
  bulk-load contract; both now resolve from the snapshot single pass
- v1-models-discovery-conformance: re-pinned to the bounded 30s SWR window
  (diegosouzapw#9199/diegosouzapw#10198) — the old 'stale-first regardless of age' contract is gone

Stale tests aligned (movers cited inline): codex-tools-strict-default (diegosouzapw#9828
redundant-oneOf strip), devin-providers (diegosouzapw#9245 i18n), db-migrationrunner-
constants-split (147→151 renumber diegosouzapw#8228), gitlab-duo-oauth-setup (diegosouzapw#9245),
chatcore-extracted-modules (diegosouzapw#9161 outbound-protocol keying)

compression-api CI failures were cascade artifacts of codex-tools-strict-default
failing in the same force-exit shard process — no own defect (171/171 local).

Refs diegosouzapw#9985

* fix(test): compression-api — register both describes before the runner starts

The DATA_DIR setup + route/db top-level awaits sat BETWEEN the two describes;
under --test-force-exit (the CI unit-runner flag) the process exits once the
already-registered tests finish, so on slow CI machines the whole second
describe died as 'Promise resolution is still pending' — the recurring
CI-only shard-2 failure that never reproduced locally without the flag.
Moved to the top of the file; 10/10 under --test-force-exit locally.

Refs diegosouzapw#9985

* fix(quality): freeze modelCapabilities.ts at 1006 (annotated) — snapshot routing growth

Refs diegosouzapw#9985

* fix(quality): move the modelCapabilities freeze into the frozen map (nested schema)

Refs diegosouzapw#9985

* fix(i18n): translate all 39,718 pending UI keys across 42 locales (owner-approved)

Mass-translated every __MISSING__ placeholder via the official i18n:sync-ui
--translate-markers pipeline (operator backend), restoring i18nUiCoverage to the
100 baseline (was 89.9 after the merge-storm UI landings + the 42 keys diegosouzapw#9038
never shipped).

Post-pass repairs, all caught by the existing gates:
- glossary: retired renderings the machine reintroduced normalized again
  (提供商→提供者 zh-CN/zh-TW, 鏈接→連結, 文檔→文件, 調用→呼叫, 供應商→提供者,
  響應→回應, 不活躍→未啟用 zh-TW; 클로드→Claude, 옴니루트→OmniRoute ko);
  DATA_DIR forbidden rendering avoided via 数据文件夹 rephrase
- ICU integrity: 120 values with renamed/dropped {params} repaired (39
  positional renames, 81 reset to the en source — functional over fluent)

Validation: glossary/pt-BR/vi/deno-relay/settings-keys/value-drift/google-
loopback suites 76/76; placeholder diff en×42 locales = 0; worst-locale
coverage = 100.0%.

Refs diegosouzapw#9985

---------

Co-authored-by: backryun <bakryun0718@proton.me>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…refresh

`/v1/models` has passed a third argument to `getUnifiedModelsResponse()`
(`{ scheduleBackgroundRefresh: (task) => after(task) }`) ever since diegosouzapw#10198, but
diegosouzapw#9199 had already removed the parameter: the function takes two, so the object
was silently dropped and `catalogCache` kept scheduling the stale-while-
revalidate rebuild with `setTimeout(..., 0)`. The builder is overwhelmingly
synchronous under the single-threaded App Router, so it pinned the event loop
before the stale response was flushed — the diegosouzapw#8728 guarantee did not exist.

- `catalogCache` now imports `after` from `next/server` and exposes
  `defaultBackgroundRefreshScheduler`, which defers to `after()` and falls back
  to a macrotask outside a Next request scope (instrumentation warm-up, tests).
- `resolveCachedCatalogResponse` takes `scheduleBackgroundRefresh` and
  `getStaleWhileRevalidateMs` on its existing options object.
- `getUnifiedModelsResponse` accepts the options object the route already passes
  and propagates the scheduler.

The excess argument was invisible to CI: `tsconfig.typecheck-core.json` is a
curated 27-file allowlist, `check:dashboard-typecheck` only covers
`src/app/(dashboard)`, and `next.config.mjs` sets `ignoreBuildErrors: true`.

Closes diegosouzapw#11551
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants