Release v3.8.50 - #8875
Open
diegosouzapw wants to merge 3030 commits into
Open
Conversation
|
Hey, please if possible do a release, we are died behind v3.8.48 still |
6 tasks
Owner
Author
|
Thanks for sending this PR. Please resolve mandatory items and retest. Re-open after cleanup if scope/mergeability blocking is fixed. |
Owner
Author
|
Thanks for sending this PR. Please resolve mandatory items and retest. Re-open after cleanup if scope/mergeability blocking is fixed. |
Owner
Author
|
test step5 |
Owner
Author
|
Thanks for sending this PR. Please resolve mandatory items and retest. Re-open after cleanup if scope/mergeability blocking is fixed. |
1 similar comment
Owner
Author
|
Thanks for sending this PR. Please resolve mandatory items and retest. Re-open after cleanup if scope/mergeability blocking is fixed. |
This was referenced Aug 11, 2026
Validado em lote combinado (batch-0824g) contra o tip de release/v3.8.50: typecheck:core limpo, gates estáticos OK, 62/62 testes focados passando (endpoint/parser/schema/static-model + catálogo). Canonicaliza metadados de endpoint legados (video/audio) para IDs específicos por operação, mantendo compatibilidade retroativa via `normalizeModelSupportedEndpoints` (valores antigos `audio`/`video` continuam válidos como entrada e são normalizados na escrita). Obrigado pela contribuição, primeira PR bem-vinda!
Validado em lote combinado (batch-0824g) contra o tip de release/v3.8.50: typecheck:core limpo, gates estáticos OK, 62/62 testes focados passando (23/23 do PR entre glm-5.3-catalog-and-effort-tiers.test.ts e zai-catalog-glm52.test.ts). Aditivo, espelha exatamente o padrão já existente glm-5.2-max. Obrigado pela contribuição, primeira PR bem-vinda!
…mit peer IP, and add 429 Retry-After (#S1 #S2 #S4) (#11418) Validado em lote combinado (batch-0824g) contra o tip de release/v3.8.50: typecheck:core limpo, gates estáticos OK, 62/62 testes focados passando (S1/S2/S4, tests/unit/security-s1-s2-s4.test.ts, 9/9). Boa integração com o padrão já existente de peer IP stamped por HMAC (resolveStampedPeer/OMNIROUTE_PEER_STAMP_TOKEN) — reusa em vez de reimplementar, e o header confiável só é honrado quando o stamp token está configurado. S2 remove corretamente a disclosure de topologia hardcoded do agent-card. Obrigado pela contribuição!
`Fast Quality Gates` has been failing on every open PR against release/v3.8.50 with "2 gate(s) failed: mutation-test-coverage lockfile". Neither belongs to any feature branch, so they are drained here. check:lockfile — a transitive dev/optional entry (libxmljs2 → brace-expansion@2.1.4) landed with a `resolved` URL pointing at registry.npmmirror.com instead of registry.npmjs.org, which lockfile-lint rejects as a supply-chain policy violation. Verified before touching it: the recorded `integrity` (sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==) is byte-identical to the official npmjs tarball's, so the package content is the same and this is a provenance slip — someone's install ran behind the mirror registry — not a tampered package. Repointed the URL; `integrity` untouched. It was the only non-npmjs host in the lockfile (2690 npmjs entries). check:mutation-test-coverage — two covering unit tests were missing from stryker.conf.json's tap.testFiles, so their mutant kills did not count: repro-glm-iso-reset-24h-cap (accountFallback.ts) and repro-combo-persisted-cooldown-preskip (comboPredicates.ts). Inserted in place. Both gates verified green locally. The diff is three lines: re-serializing either file would have reordered a curated list for no reason. Co-authored-by: Xiangzhe <bakryun0718@proton.me>
CodeQL js/incomplete-url-substring-sanitization, alerts #860 and #861: volcengineConsoleAutoLogin accepted any cookie whose `domain` merely *contained* "volcengine.com". That check is an authorization decision, not a string test. The console auto-login harvests `digest`, `AccountID`, `csrfToken` and `userInfo` out of the Playwright context and persists them as the operator's Volcengine credentials, so a cookie set by `volcengine.com.attacker.tld` — or `notvolcengine.com` — was captured and stored as a provider connection. Add `matchesCookieDomain()` (open-sse/utils/cookieDomain.ts): exact host or dot-boundary suffix, leading dots and case normalized on both sides, failing closed on an empty expected domain. Same shape as the existing `isAdobeCookieDomain` in adobeFireflyBrowserLogin.ts, which already got this right. While sweeping the class, inAppLoginService's cookie capture had the identical weakness — `c.domain.includes(domain.replace(/^\./, ""))` — with the identical consequence: a look-alike host's cookie stored as the operator's credential. CodeQL did not flag it because the expected domain comes from TOKEN_EXTRACTION_CONFIGS rather than a literal. Both callsites now share the helper. tests/unit/volcengine-cookie-domain-suffix.test.ts — 5 tests, red before the fix, covering the real domains, seven look-alikes, empty/missing input, and the config-supplied path. Co-authored-by: Xiangzhe <bakryun0718@proton.me>
…k the release PR The living release PR #8875 was CONFLICTING, which makes GitHub skip EVERY pull_request workflow silently (no ci.yml, no semgrep, no DAST). Back-merging main restores a computable merge ref. Strategy `-s ours`: main is a stale snapshot of the release line (PR #11088 was merged into main from a release-tip base, dragging ~5094 files). All 7 main-only commits were verified as already represented on this branch: - #11088 ollama capability routing -> ported here as #11271 (6d4c484) - #11075 shared passthrough providers -> ported here as #11165 (92ef3c7) - #10055 getModelsDevPricing memoization -> present (modelsDevSync.ts) - #10026 hide health-check excluded models -> present and extended (catalog.ts) - /_tasks anchored gitignore hardening -> present (.gitignore:288) - nanoid/dompurify Dependabot bumps -> identical versions main-only files intentionally NOT carried over: - changelog.d/fixes/10286-gemini-3-5-flash-thinking.md + its regression test: the fix landed here as #10450 and was then deliberately superseded by 2764812 "eliminate Gemini 3.5 Flash". The test fails on this branch by design. - public/providers/hackclub.svg: provider removed here (migration 162). - docs/superpowers/**/2026-08-23-qdrant-*: planning artifacts belong in _tasks/ (AGENTS.md), never under docs/.
diegosouzapw
marked this pull request as ready for review
August 24, 2026 22:55
Contributor
CI Coverage Report
Coverage artifact was not available for this run. |
| assert.equal(res.status, 200); | ||
| const card = (await res.json()) as { url?: string; supportedInterfaces?: { url?: string }[] }; | ||
| assert.ok(card.url, "card must have a url"); | ||
| assert.ok(card.url.startsWith("https://gateway.example.com"), `expected gateway.example.com, got ${card.url}`); |
| assert.ok(card.url.startsWith("https://gateway.example.com"), `expected gateway.example.com, got ${card.url}`); | ||
| if (card.supportedInterfaces && card.supportedInterfaces.length > 0) { | ||
| assert.ok( | ||
| card.supportedInterfaces[0].url?.startsWith("https://gateway.example.com"), |
| const res = await mod.GET(request); | ||
| assert.equal(res.status, 200); | ||
| const card = (await res.json()) as { url?: string }; | ||
| assert.ok(card.url?.startsWith("https://custom.example.com"), `expected custom.example.com, got ${card.url}`); |
| const res = await mod.GET(request); | ||
| assert.equal(res.status, 200); | ||
| const card = (await res.json()) as { url?: string }; | ||
| assert.ok(card.url?.startsWith("https://gateway.example.com"), `expected gateway.example.com, got ${card.url}`); |
…ne connect bodies Two base-reds on the v3.8.50 tip, found by the release pre-flight. 1. #11355 regressed #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 #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. #11277/#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).
… 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. #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:
#11355 inverted the startup-cooldown contract (preserve future quota cooldowns),
#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: #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.
PR #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 #11418
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 #10432 (guard #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.
…n test The #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.
…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.
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.
…, 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 #11284/#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 #11284
…he 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 #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.
`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.
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 #11397 onward, which landed without a fragment) are reconciled separately.
…ered 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).
… the 42 i18n mirrors
…ABRT 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 #10692
…nt 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 #10692
…tegration 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 #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 #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: #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 #10692
…en 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 #10448; four test files render it without mocking next/navigation and died on 'invariant expected app router to be mounted'. The sibling created alongside #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 (#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. #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 #10692
…enerate the omni-inference skill Two gates in the Lint job, both inherited — each was hidden behind the one before it. i18n value drift: #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 #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 #10692
… 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 #8855 autofill sentinels, the data-1p-ignore / data-lpignore guards and the dead-status round-trip are intact. The #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 #10692
…acts 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 #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, #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 #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: #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 #10692
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🚀 Release v3.8.50
Living release notes — reconciled on 2026-08-25 against the complete v3.8.50 development
cycle. This body is a derived summary; the authoritative per-change record and the complete
attribution ledger live in
CHANGELOG.md(## [3.8.50]), which carries 1,041 bullets and246 external contributors.
Note
The previous RELEASE HOLD on this PR was lifted on 2026-08-25 — its premise did not hold.
That block claimed the Video Bridge follow-up train was unshippable because a "canonical
acceptance audit" classified nine workstreams as 0 complete / 9 partial. The canonical
source says the opposite.
_tasks/research/2026-08-16-video-bridge-follow-up-backlog.mdcarries
status: parkedandexecution_authorized: false, states verbatim that thebaseline is "implementado, mergeado, implantado, validado ao vivo e encerrado", that
"não existe pendência de produto, release, segurança, documentação, teste ou restauração
que bloqueie o fechamento dessa feature", and that the nine items explicitly "não pertencem
ao escopo do PR entregue".
Those nine are parked, unauthorised future work — not unmet acceptance criteria. The
earlier reconciliation read a backlog as a checklist. Verified independently: issue #9760 is
CLOSED (2026-08-15) and its baseline SHA
dc562d93cais an ancestor of this branch.This PR is out of draft. Merging still waits on the operator's explicit go at the release
STOP gates — the hold that remains is procedural, not a defect claim.
📊 What is in the reconciled candidate
1,590 commits in the canonical release cycle
(
1,505non-merge) · 1,343 merged PRs,206 closed-unmerged and 5 open in the final
GitHub census · 259 external contributors in the release ledger.
Highlights: first-class unified search; OmniConductor/A2A agent interoperability;
Codex App Server transport; expanded multimodal and provider routing; strict-zero-cost and
quota-aware scheduling; 15-factor Auto-Combo across 19 public strategies; Electron remote-server
mode; OmniCopilot and CLI integrations; resilient Responses/Chat streaming; provider, model,
security, SQLite, packaging and cross-platform hardening; and a complete public-documentation,
provenance and contributor-credit reconciliation.
📖 Full per-change changelog with original PRs and contributor attribution:
CHANGELOG.md→[3.8.50]Highlights
✨ New Features
Unified search is now a first-class API and agent surface: provider-backed
POST /v1/search, MCP search tools, X Search, source-aware errors, configurable timeouts andSSRF-hardened upstream handling
(#10988,
#10738).
OmniConductor and agent interoperability: A2A task delegation, fleet-derived Agent Card
skills, a dashboard Conductor panel, and Faro text/voice interaction
(#8080,
#8119,
#8221,
#8222,
#8223).
Codex App Server transport: a self-contained
codex-app-serverprovider bridges OpenAIResponses requests to the Codex CLI through capability-token-protected JSON-RPC/WebSocket,
with a Docker sidecar, health and authentication probes, dashboard sign-in/apply-local flows,
and no direct OAuth-token replay by OmniRoute
(#11205 — thanks
@arminanton).
Multimodal routing expanded across image, speech, music, OCR and video surfaces, including
Chat/Responses modality bridges and provider-aware fallback. The previously authorized base
Video Bridge delivery remains credited through
#9760; the later 18-commit follow-up
train is deliberately excluded from shipped claims while the release HOLD remains.
Routing and quota controls now include strict-zero-cost routing, adaptive admission,
atomic RPM rolling leases, quota-aware scheduling, connection-scoped session behavior,
exclusive managed leases and 15-factor Auto-Combo scoring across 19 public strategies
(#9259,
#9262,
#10126,
#10362,
#10965).
Final-cycle configurability and observability adds a bounded per-request combo-attempt
budget, per-connection rate-limit queue waits, runtime-learned reasoning-effort tiers,
credential-safe admission snapshots and embedding-model discovery from the providers that are
actually configured
(#11239 — thanks
@pacocartones,
#11251,
#11232,
#11252 — thanks
@maxmad64bis,
#11268 — thanks
@backryun and reporter
@im-ecorp, and
#11249 — thanks
@rafacpti23).
Provider and client expansion includes Electron remote-server mode, native
OmniCopilot/VS Code model-picker support, Radar catalog integration, a detached CLI tray,
the Prime Agent CLI catalog and exact model context/input/output constraints
(#8799,
#8908,
#10418,
#10697,
#11166).
Measured product surface at the reconciled candidate: 345 providers; 1,275 distinct
model IDs; 446 per-model free-budget rows across 38 pools; 54 recurring/keyless free-forever
providers; 35 CLI/agent integrations; 110 MCP tools across 33 scopes; 102 executor
implementations; and 160 migrations. These denominators are intentionally separate and are
measured from their canonical sources.
🐛 Bug Fixes
Harden provider fallback, account cooldown, whole-provider circuit breakers and per-model
lockouts so transient quota, account, model and provider failures remain isolated at the
narrowest valid scope.
Repair Responses and Chat streaming fidelity across reasoning, parallel tool calls, usage
frames, empty completions, CJK deltas, image/tool payloads, synthetic user turns and
client-specific transport contracts.
Close security and privacy gaps around search SSRF handling, API-key cache keys, Redis
exposure, management-route authorization, provider-supplied URLs and headers, image validation,
credential handling and log redaction.
Apply the final security sweep and its exact-candidate follow-up: protect legacy settings
export/import, make MITM and root-CA management local-only and spawn-capable, reject
cloud-metadata search overrides, authenticate and owner-scope A2A task access, and warn when the
CLI exposes an unauthenticated server on a non-loopback interface. The candidate follow-up also
fails search redirects and DNS resolution closed against private/metadata destinations and keeps
REST and JSON-RPC A2A scope semantics consistent without serializing owner identifiers
(#11261 — implementation, advisory
reports and shared A2A-auth foundation credited together to
@backryun,
@ntdat812,
@koushiksaravanan,
@highlightime,
@mado90 and
@rafaelfiguereod-stack).
Drain the frozen-tip base-red and regression queue, then make its candidate fixtures
hermetic across OpenCode JSONC configuration, Qdrant route requests, database initialization,
reasoning-effort tiers and touched-file formatting. The detailed ledger retains the originating
issue/PR credits instead of treating the drain as new sole authorship
(#11280 — thanks
@backryun).
Harden the Codex App Server transport after the feat(codex): self-contained codex app-server transport (executor + provider + sign-in) #11205 security review: app-server
execution approvals are denied by default, the default sandbox is
workspace-write,environment-sourced capability tokens are bound to environment-sourced or operator-local
URLs, and authenticated readiness probes no longer follow redirects
(#11281, a maintainer hardening
follow-up to #11205; original delivery
thanks @arminanton).
Land the rebased security and self-hosted-operator integration delta: a build-only
better-sqlite3guard with bounded Next.js heap/worker behavior, credential-echo refusal plusOCR/moderation/call-log redaction, GitHub Copilot CLI wire identity and Claude routing/discovery
corrections, a clean CC
model_not_foundresponse and no-auth alias compatibility overrides.The rebase deliberately excluded fixes that had already landed, so they are not double-claimed
here
(#10952 — thanks
@arminanton). The commit history preserves the ported-author
credits, including @rqzbeh,
yidecodeand the originalfix(auth): add opencode/opencode-zen to search pairs for credential resolution (#10892) #10899/fix(executors): report WS readyState in Meta AI timeout error (#10727) #10916 authors; the build guard was re-derived from the now-closed fix: use Node 22 LTS + raise build heap to 6144 MB -- Node 24 crashes… [defer to 3.8.51] #10060 against the
current release base rather than presenting that PR as merged.
Correct provider and model behavior across Codex, Claude, Gemini, GLM, Muse Spark, AWS Polly,
Antigravity, Kiro, Cursor, OpenCode, Copilot, AgentRouter and KIE Nano Banana 2, with the
original authors retained in the complete CHANGELOG ledger.
Align the
node:sqliteandsql.jsfallback adapters withbetter-sqlite3, includingplain-object rows,
undefined→ SQLNULLbind normalization and compatible named-parameterbehavior
(#11205 — thanks
@arminanton).
Stabilize builds and deployment across Node/npm, Turbopack/webpack escape paths, standalone
native dependencies, Docker, Electron, Windows, macOS and systemd, including cross-platform
tool spawning and published-artifact compatibility.
Close the final-cycle defects in quota-window ordering, Windows
file://imports andCLIProxy process discovery, LM Studio embedding aliases, OpenRouter key validation/auth export,
sql.jsartifact boot parity, OpenCode Go quota snapshots and the retired Hack Club surface(#11241,
#11238,
#11260,
#11263,
#11264,
#11266,
#11267,
#11262); the complete CHANGELOG keeps
both implementer and original-reporter credit for every item.
📝 Maintenance
Aggregate the complete v3.8.50 change ledger into one version-scoped section while preserving
[Unreleased]byte-for-byte and consuming fragments only in the same successful operation thatwrites their bullets.
Reconcile original PRs, replacements, cherry-picks, side-branch carriers, direct commits and
coauthor trailers so closing, replacing or conflict-resolving a PR does not erase the original
contributor.
Remove the Raycast protocol service/executor and the Hailuo Web, Felo Web, Qwen Web,
Microsoft Designer Web, Gemini Web image-generation and EdgeTTS surfaces after the
provenance/compliance review. The five direct
g4f.spacehosted gateways remain, with theirmetadata corrected so OmniRoute no longer attributes them to the unrelated
xtekky/gpt4freeproject.Record the verified MIT lineage of the Grok Web implementation in the README and
THIRD_PARTY_NOTICES.md, including direct and transitive sources, while distinguishingmaterial adaptations from projects that were only consulted.
Retain and explicitly ratify the two existing 30%-headroom file-size commits in v3.8.50 —
44fd0eddand
fbbef4ea—while retaining the global 1,000-line cap for new files.
Restore the exact React Compiler suppression inventory instead of shipping a broad lint
regression. The focused repair is included; the final suppressions-aware whole-repository lint
result remains explicitly pending in the gate table below.
Refresh README, provider references and rendered diagrams from physical measurements so
provider/model/free-tier, CLI, MCP, routing, executor, migration and test counts agree with
the candidate.
Refresh the public people sections: the exact contributor census,
600+contributor artwork,GitHub-attributed Top Contributors ranking, public sponsors, dated Acknowledgments star counts,
repaired project links and required upstream lineage/notices.
Refresh OmniRoute in Action from the 2026-08-23 dashboard snapshot: 1,070 tracked videos —
YouTube 809, TikTok 137 and Instagram 124 — representing 7,467,359 known views across 639
channels/profiles; 81 videos were added in the prior seven days and 530 in the prior 30 days.
🙌 Contributors and credit
Thanks to everyone whose work landed in v3.8.50. The regenerated
CHANGELOG.mdcontributor tableis the complete release ledger; this body stays condensed so GitHub can render it reliably.
The v3.8.50 ledger contains 259 external contributors, plus the maintainer, across
260 contributor rows.
The all-history census at the frozen candidate contains exactly 638 normalized human Git
identities: 406 commit-author identities, including the maintainer, plus 232
coauthor-only identities found in explicit
Co-authored-bytrailers. The union is therefore638, and the largest honest
artwork bucket is 👥 600+ Contributors — not 650+, 700+ or 800+.
The census uses all reachable commits, exact case-normalized e-mail identities and joins
numeric/non-numeric GitHub noreply variants only when they encode the same handle. Bots, apps,
service accounts and placeholders are excluded. No
.mailmapexists, and ambiguous same-nameidentities remain separate.
Every credited item is represented in the complete release ledger by its merged PR, original
PR/report, coauthor trailer, direct-commit disposition or explicit carrier. Exact Patch-ID
comparison proves reuse when it matches; it is not presented as proof that every large,
unpatchable or conceptually similar closed PR was never used.
Evidence
Frozen candidate and two audited histories
The candidate OID, tree, physical/canonical range totals and coverage split were frozen and read
back after the reconciliation merge. The GitHub PR census was then read independently from the live
repository. The documented-change categories and contributor counts above come from the regenerated
candidate ledger; any later ledger edit requires regeneration and recount before this body is used.
Two histories are reported deliberately.
v3.8.49..HEADis the physical tag range, whileed2db6cb19..HEADis the canonical v3.8.50 development cycle. Their counts differ because therepository's release and merge topology makes history outside the canonical cycle reachable
through the physical tag range.
The frozen-head extractor reports 1,361 CHANGELOG-covered canonical non-merge commits and
144 reconciled residual commits. The residual set consists of 143 commits without inline PR
references plus the test-only
#8134carrier with an inline reference; each was classified byfirst-parent topology, PR carrier, side branch, no-op/revert, direct maintenance rollup or explicit
HOLD. No PR-associated commit is silently treated as covered merely because it lacks an inline
reference.
Deferred next-cycle scope — completed and read back
Of the owner's original six-PR retarget set, only these three remain open and eligible to move
from
release/v3.8.50torelease/v3.8.51in the reconciliation snapshot:#10060 and
#11138 are closed, while
#10952 merged into v3.8.50; none is
eligible for retargeting now.
Final read-back status: 3/3 PASS — #10409, #11083 and #11146 target
release/v3.8.51. The branch was created from the then-live v3.8.50 tip3192eb88d5550de4c3fd9985564f6b5641e9d681.This explicitly authorized GitHub housekeeping operation is not an additional product-acceptance
HOLD. The branch and all three
baseRefNamevalues were read back from GitHub. Every other open PRbased on v3.8.50 was outside this exact authorization and remains untouched; none is claimed as
retargeted.
Quality evidence and exact-candidate gates
ALLOW_CHANGELOG_REMOVALS=1 npm run check:changelog-integritypassed after reporting the same 27 transformations. The override documents approved reconciliation; it does not turn the strict result above into PASS.npm run check:tracked-artifactson the exact candidate.npm run check:docs-allon the exact candidate; 66 informational stale-version warnings remained.npm run typecheck:coreon the exact candidate.npm run linton the exact candidate.@giscus/react,@pierre/diffs,@pierre/theming,@splinetool/runtime,chroma-js,elkjs). This is not clean and is not represented as PASS.anybudgetnpm run check:any-budget:t11on the exact candidate.npm run test:unitwas stopped at the explicit 30-minute cutoff before its dashboard/serial phases. Two failures were observed; the#9147event-loop pinning regression reproduced in isolation, while the TLS case passed 76/76 in an isolated file rerun. No aggregate PASS is claimed.npm run test:vitest: 389/405 passed, 16 timeouts, zero assertion mismatches. One diagnostic rerun passed 2/2, but the complete gate remains red.npm run check:cycleson the exact candidate (428 files).A cancelled, queued, stale, partial or report-only check is not represented as PASS. Every result
above is bound to the frozen candidate; any BASE-RED, FLAKY, RED, EXPECTED FAIL, HOLD or NOT RUN
result retains that classification.
Video Bridge remains a canonical product-acceptance HOLD. In addition, the dependency-license
policy is BASE-RED, the isolated
#9147performance regression is RED, the complete Vitestmatrix is FLAKY / RED, and the live PR head diverged after the candidate freeze. For those
reasons this PR remains open in Draft.
Release blockers preventing readiness
#9147still fails in isolation by pinning the event loop.release/v3.8.50head advanced to07d1816a...after the frozen candidate was pushed.This PR must remain Draft and must not be called release-green while the HOLD above exists.
The following is the future release procedure, not an action authorized or executed by this
reconciliation. After the functional HOLD and policy BASE-RED are resolved and verified:
release/v3.8.50head.release/v3.8.51; leave every other openv3.8.50-base PR untouched.
discard these counts and repeat the delta audit.
is empty and no blocking gate remains.
For this closeout, the terminal state is intentionally: PR #8875 open, Draft, unmerged,
untagged and unpublished.