Repository navigation
Release v3.8.52 - #15083
Merged
Merged
Release v3.8.52#15083
Conversation
ulisestemichtome-create
approved these changes
Oct 4, 2026
diegosouzapw
marked this pull request as ready for review
October 7, 2026 23:56
Contributor
CI Coverage Report
Coverage artifact was not available for this run. |
Merged via /merge-batch (2026-10-16 wave, maintainer PRs). Validated on a second combined board of 8 PRs over release/v3.8.52@16d9205b8: typecheck:core, open-sse typecheck, eslint on changed files, file-size, changelog-integrity, complexity, cognitive-complexity, env-doc-sync and agent-skills-sync all green; focused tests 249/250 (node:test; the one red, kiro-content-stall-15260, passes 3/3 isolated — a 100 ms stall-timer flake under load) + 16/16 (vitest UI); boundary 774 = tip (inherited base-red). Remaining CI reds are the inherited base-red #15306.
…16811) Merged via /merge-batch (2026-10-16 wave, maintainer PRs). Validated on a second combined board of 8 PRs over release/v3.8.52@16d9205b8: typecheck:core, open-sse typecheck, eslint on changed files, file-size, changelog-integrity, complexity, cognitive-complexity, env-doc-sync and agent-skills-sync all green; focused tests 249/250 (node:test; the one red, kiro-content-stall-15260, passes 3/3 isolated — a 100 ms stall-timer flake under load) + 16/16 (vitest UI); boundary 774 = tip (inherited base-red). Remaining CI reds are the inherited base-red #15306.
Merged via /merge-batch (2026-10-16 wave, maintainer PRs). Validated on a second combined board of 8 PRs over release/v3.8.52@16d9205b8: typecheck:core, open-sse typecheck, eslint on changed files, file-size, changelog-integrity, complexity, cognitive-complexity, env-doc-sync and agent-skills-sync all green; focused tests 249/250 (node:test; the one red, kiro-content-stall-15260, passes 3/3 isolated — a 100 ms stall-timer flake under load) + 16/16 (vitest UI); boundary 774 = tip (inherited base-red). Remaining CI reds are the inherited base-red #15306.
Merged via /merge-batch (2026-10-16 wave, maintainer PRs). Validated on a second combined board of 8 PRs over release/v3.8.52@16d9205b8: typecheck:core, open-sse typecheck, eslint on changed files, file-size, changelog-integrity, complexity, cognitive-complexity, env-doc-sync and agent-skills-sync all green; focused tests 249/250 (node:test; the one red, kiro-content-stall-15260, passes 3/3 isolated — a 100 ms stall-timer flake under load) + 16/16 (vitest UI); boundary 774 = tip (inherited base-red). Remaining CI reds are the inherited base-red #15306.
…detect it at import (#16497) Merged via /merge-batch (2026-10-16 wave, maintainer PRs). Validated on a second combined board of 8 PRs over release/v3.8.52@16d9205b8: typecheck:core, open-sse typecheck, eslint on changed files, file-size, changelog-integrity, complexity, cognitive-complexity, env-doc-sync and agent-skills-sync all green; focused tests 249/250 (node:test; the one red, kiro-content-stall-15260, passes 3/3 isolated — a 100 ms stall-timer flake under load) + 16/16 (vitest UI); boundary 774 = tip (inherited base-red). Remaining CI reds are the inherited base-red #15306.
…lease tip (771 → 774, base-red #15306) (#16904) * chore(quality): re-seed the open-sse -> src boundary ceiling at the release tip (771 -> 773) #16874 seeded metrics.boundaryOpenSseToSrc at the 771 edges measured on 224ca60; two merges landed before it merged and each added one engine -> app edge, so check:boundary:ratchet was red on release/v3.8.52 from its first run (773 > 771) and failed the fast-gates of every PR. Absorb the two edges at the tip with a documented note; the ceiling only goes down from here. * chore(quality): follow the tip to 774 edges (+1 from #14619 while queued)
…trigger file (#16907) Merge-batch Track-B fix: src/lib/system/autoUpdate.ts — the Docker-trigger result spread now narrows with `written.ok === false` (TS2339 with strictNullChecks off). Merged origin/release/v3.8.52 (no conflicts). Focused tests: auto-update-docker-image-mode + auto-update-mode-detection 22/22 pass; vitest home-manual-update-command-docker 1/1 pass. Gates: typecheck:core OK, open-sse typecheck OK (0), complexity OK (3074 ≤ 3218), cognitive OK, file-size OK, agent-skills dry-run clean, eslint on changed files 0 errors, boundary 774 = release tip (no new open-sse→src edges). Remaining CI reds are inherited base-red #15306.
… audio, images, rerank, quota usage) (#16912) Merge-batch Track-B fix: tests/unit/nan-provider.test.ts — replaced the substring URL check flagged by CodeQL (js/incomplete-url-substring-sanitization) with an exact apiHint assertion. Bumped the public provider count 372 → 373 everywhere check-docs-counts-sync flags it (README, AGENTS.md, llm.txt + its 66 docs/i18n mirrors, package.json description, architecture/framework/guide docs, skills README + omni-auth/omni-providers SKILL.md, agentSkills.ts, 6 SVGs) — count number only. Merged origin/release/v3.8.52 twice (no conflicts). Focused tests: nan-provider + provider-node-reserved-prefix + providers-constants-split 37/37 pass. Gates: typecheck:core OK, open-sse typecheck OK, complexity/cognitive OK, file-size OK, agent-skills Generated: 0, eslint 0 errors, docs-counts-sync 0 strict drifts, docs-sync PASS, boundary 774 = tip. Remaining CI reds are inherited base-red #15306.
…vider (#16871) Merge-batch Track-B fix: open-sse/handlers/imageGeneration/providers/museImage.ts — reference-image bytes now go through toBlobBytes() (TS2322 on new Blob([Buffer])), and handleMuseImageGeneration is split into readRequestOptions/buildEditsForm/buildMuseRequest/sendMuseRequest/inlineSignedUrls helpers (the file now has 0 complexity/max-lines/cognitive violations, was +2/+1). The three src/ helpers (saveCallLog, fetchUntrustedRemoteImage, fetchWithTimeout) are injected by the image dispatcher, which already imported them, so the provider adds no open-sse → src boundary edges (774 = tip ceiling). Merged origin/release/v3.8.52 (no conflicts). Focused tests: muse-image-provider 11/11 pass. Gates: typecheck:core OK, open-sse typecheck OK (0), complexity/cognitive OK, file-size OK, agent-skills dry-run clean, eslint 0 errors, boundary ratchet OK. Remaining CI reds are inherited base-red #15306.
…fort enums (#16886) Merge-batch Track-B fix: open-sse/executors/dashscopeTts.ts — audioResponse() now takes Uint8Array<ArrayBuffer> (TS2345 on new Response(), same typing as audioSpeech.ts). The PR also added two open-sse → src boundary edges (776 vs tip ceiling 774); dashscopeTts now reaches resolveAlibabaProviderMediaBaseUrl / fetchRemoteMedia through engine modules that already import them (videoGeneration/dashscopeHandler.ts, utils/chatgptWebAttachments.ts re-export), so the boundary stays at 774. Merged origin/release/v3.8.52 twice (no conflicts). Focused tests: qwen-cloud-token-plan-media + qwen-token-plan-effort-enums + qwen-token-plan-tts + audio-speech-handler 47/47 pass; chatgpt-web cleanroom suites 21/21 pass. Gates: typecheck:core OK, open-sse typecheck OK (0), complexity/cognitive OK, file-size OK, agent-skills dry-run clean, eslint 0 errors, boundary ratchet OK (774/774), cycles ratchet OK (14/14). Remaining CI reds are inherited base-red #15306.
… detection counters (#16902) Merge-batch Track B. Fixes: (1) CodeQL js/redos (#1150) — the deliberately catastrophic custom pattern in tests/unit/pii-per-type-selection.test.ts is now assembled at runtime via ["(a","+)","+$"].join("") instead of a ReDoS-shaped literal; (2) CodeQL js/incomplete-url-substring-sanitization (#1151) — the 'example.com' substring check is replaced by an exact assertion on the stats snapshot keys (request/response already compared exactly); (3) dropped the unused UpdatePiiSettingsInput type export (only new dead export); (4) regenerated skills/omni-settings via the generator (SKILL.md + references/endpoints.md; dry-run Generated: 0). PII flags untouched (PII_REDACTION_ENABLED / PII_RESPONSE_SANITIZATION default false). Focused: 286/286 (30 PII/guardrail/inputSanitizer unit files), 58/58 after first tip merge, 19/19 after second. Gates: typecheck:core OK, open-sse typecheck OK, complexity/cognitive/file-size/dead-code OK, eslint+prettier clean. Boundary 774/771 inherited at prep time. CodeQL re-analysis on the new head was still queued (runner backlog) at merge time.
…ys elsewhere (#16941) ci: Turbopack back on the self-hosted build slot (64 GB); webpack stays elsewhere The .113 build box was raised from 48 to 64 GB on 2026-10-16. Measured there with a cgroup cap and swap off, the Turbopack build of this tree peaks at ~36 GB under the cap (49 GB uncapped: compile ~21 GB plus 31 static-generation workers at 17-21 GB) and finished in 23 min with three lint jobs running alongside - no swap, no OOM, memory PSI 0. That is what did not fit the 48 GB box next to the light runners (~200 red Builds between 10-06 and 10-16). The ci.yml Build therefore goes back to Turbopack when it lands on the opt-in slot (USE_VPS_RUNNER and USE_VPS_BUILD_RUNNER both 'true') and keeps webpack on the 16 GB hosted runners, which cannot hold it. The four nightly build:cli steps stay on webpack: they are backend-only and share the box with the light runners. Next 16.4.x regresses (33 GB in the compile phase alone) and must be re-measured before any bump. Tests follow the policy: heavy-build-queue pins the Turbopack switch to the runner condition again, ci-build-bundler-webpack keeps the nightlies on webpack and checks the Build switch is tied to the slot.
… finish (#16953) ci(nightly-schemathesis): give the webpack backend-only build time to finish The job's 30-minute cap predates the webpack switch (#16870). The run dispatched on 2026-10-17 (38982564979) compiled with webpack for 25 min on the busy .113 and was cancelled by the cap before the probes started, so the nightly stayed red for a reason unrelated to the contract fuzz. 120 minutes covers the backend-only build under load plus the probes. Guarded in tests/unit/ci-build-bundler-webpack.test.ts.
Merged via /merge-batch (2026-10-16 wave). Fixes applied on top of the port: the CodeQL incomplete-URL-substring alert in tests/unit/provider-daoxe-registry.test.ts now asserts the apiHint exactly; reconciled with #16912 (NaN.Builders, landed first) so both providers are registered and the count pins move once more; the public provider count goes 373 -> 374 (README, AGENTS.md, llm.txt + mirrors, package.json, generated skills — owner-approved, count-only lines). Focused tests 42/42 (DaoXE + NaN + reserved-prefix + constants-split); check:provider-consistency OK (374 canonical); check:docs-counts no strict drift (2 soft executor-count drifts are inherited from the tip); agent-skills-sync Generated 0; docs-sync PASS; boundary 774/774; eslint clean. Remaining CI reds are the inherited base-red #15306.
…and import preview (#16877) Merged via /merge-batch (2026-10-16 wave). Fixes applied on top of the port: providerTransfer.ts types the spread connection records as JsonRecord (clears the 3x TS2339 the API Route Typecheck reported) and splits findMatchingConnection / applyProviderTransfer into per-identity and per-node helpers (same order, same outcomes); ProviderTransferPanel.tsx extracts AccountPicker, PassphraseFields, PlanReview, FileChooser and useTransferRequest; the unused ProviderTransferImportBody export is gone; skills/omni-settings regenerated through the generator (owner-approved). Validated on the current tip: focused tests 15/15 (provider-transfer + credential-export-always-protected + hard-session-lease inventory) + 2/2 vitest UI; check-api-typecheck OK (within frozen baseline), typecheck:core OK, dead-code 360 <= 377, complexity/cognitive within baseline, file-size OK, agent-skills-sync Generated 0, boundary 774/774, eslint clean. Remaining CI reds are the inherited base-red #15306.
Declare the providerSpecificData fields that carry credentials (console API keys, Qwen/Alibaba/Volcengine/Xiaomi console cookies and tokens, Ollama Cloud usage cookies, nested OAuth/API-key/session fields) and run them through the same AES-GCM envelope as the top-level connection tokens: encrypted on every write, lazily decrypted in both connection views, legacy plaintext migrated on the next write, cookie-session dedup compared on plaintext, compliance audit redaction aligned with the dashboard sanitizer. Review evidence: focused suites 25/25 on the final head, complexity ratchets and file-size clean, targeted typecheck 0 errors.⚠️ base-red inherited: #15306 Co-authored-by: fabioKoruja00 <$(gh api users/fabioKoruja00 --jq .id)+fabioKoruja00@users.noreply.github.com>
…nge retention (#16958)⚠️ base-red inherited: #15306 ## Summary Authorization boundary fix on the destructive side of the backup surface. Restoring a backup became operator-only in #16899; destroying restore points still accepted any management credential: `DELETE /api/db-backups` (cleanup — keep the latest N / drop older than D days) gated on `isAuthenticated()` only, so a `manage`-scoped API key or an `oma_` access token could delete every stored restore point but one. Restore points are the recovery path after exactly that kind of leaked machine credential. **`PATCH /api/db-backups` is included on purpose and flagged for the owner's review.** The owner approved gating `DELETE`; `PATCH` is the closure of the same hole: it persists the same `keepLatest` / `retentionDays`, and `backupDbFile()` calls `cleanupDbBackups()` with no arguments after every backup (`src/lib/db/backup.ts:414`), which falls back to those persisted values (`backup.ts:84-91`). Gating `DELETE` alone is bypassable — a machine credential saves `keepLatest: 1`, then triggers a manual backup (`PUT`, still management-reachable) or simply waits for the next automatic one, and the pruning happens anyway. Both handlers now go through the existing `requireOperatorCredential()` (`src/lib/api/operatorCredential.ts`, #16680) with route-local 403 messages — no new export was added to the shared helper and `backup.ts` semantics are untouched. ## Behavior before / after | Handler | Credential | Before | After | | --- | --- | --- | --- | | `DELETE /api/db-backups` | none | 401 | 401 (unchanged) | | `DELETE /api/db-backups` | `manage` API key / `oma_` admin token | **200 — backups pruned** | **403**, settings and files untouched | | `DELETE /api/db-backups` | inference-only API key | 403 (`manage` scope) | 403 (unchanged) | | `DELETE /api/db-backups` | dashboard session / login disabled | 200 | 200 (unchanged) | | `DELETE /api/db-backups` | pipeline-stamped local CLI subject | 401 (`isAuthenticated()` never honored the stamp) | 200 | | `PATCH /api/db-backups` | none | 401 | 401 (unchanged) | | `PATCH /api/db-backups` | `manage` API key / `oma_` admin token | **200 — retention persisted (drives automatic pruning)** | **403**, settings untouched | | `PATCH /api/db-backups` | dashboard session / login disabled | 200 | 200 (unchanged) | | `PATCH /api/db-backups` | pipeline-stamped local CLI subject | 401 | 200 | | `GET` / `PUT /api/db-backups` | `manage` API key | 200 | 200 (unchanged — not destructive, covered by positive tests) | The CLI has no generated command for `PATCH`/`DELETE /api/db-backups` (`bin/cli/api-commands/system.mjs` only exposes `get-`/`post-api-db-backups`; `bin/cli/commands/backup.mjs` prunes its own local export directory), so nothing in `bin/` changes. ## Tests New sibling file `tests/unit/backup-cleanup-require-operator.test.ts` (same style as `tests/unit/backup-restore-require-operator.test.ts`): handlers invoked directly with a crafted `Request`, isolated `DATA_DIR`, four seeded restore points, retention settings read back before/after. Matrix per handler: no credential → 401; `manage` key, inference-only key, admin `oma_` token → 403 with the retention settings unchanged and all four files still on disk; dashboard session / local CLI subject / login disabled → 200 and the handler really does its job (PATCH persists and never prunes; DELETE prunes down to the requested count). Positive `GET` and `PUT` with a `manage` key → 200. - **RED** (commit `3429f715c0`, on the unfixed route): `ℹ tests 17 / pass 5 / fail 12` — root failure `actual: 200, expected: 403` on the manage-key `DELETE`; the unguarded handler then persisted `1/1` and pruned all four files, cascading into every later "nothing changed" assertion; plus `401 vs 200` for the local CLI subject on both handlers. - **GREEN** (fix commit `b9aba368db`): `17/17`; on the merged tree together with `backup-restore-require-operator` + `db-backup-extended`: `56/56`. - **Related suites** (`grep -rlE "db-backup|backup-restore|backup-export|operatorCredential|credential-export|cli-backup" tests/` → 30 files): 29 node:test files in 3 batches → 75/75, 117/117, 127/127; 1 vitest file (`tests/unit/ui/system-storage-backup-auth-envelope-14846.test.tsx`) → 2/2. No assertion removed or weakened anywhere. ## Validation | Check | Result | | --- | --- | | `npx prettier --check` (7 touched files) | OK | | `npx eslint --suppressions-location config/quality/eslint-suppressions.json` (route + test) | 0 errors | | `check-complexity-ratchets.mjs --base-ref <merge-base>` | OK (complexity 0 / cognitive 0 on new code) | | `check:file-size --base-ref <merge-base>` | OK (no frozen file grown) | | `scripts/dev/typecheck-touched.sh --base origin/release/v3.8.52` | 0 errors in touched files; 1 error in `tests/helpers/managementSession.ts(62,5)` TS2322 — file byte-identical to the base (inherited, same helper #16899 imports) | | `check:openapi-security-tiers` / `check:api-docs-refs` / `check:openapi-coverage` / `check:changelog-integrity` | PASS | | `check:docs-all` | docs-sync, frontmatter, doc-links PASS; `check:fabricated-docs` fails on `/api/balance` in `docs/reference/ENVIRONMENT.md:368` — file identical to the base (inherited) | | i18n doc mirrors (`npm run i18n:run -- --files=<3 docs>`) | translation backend answered **404** (`DEPLOYMENT_NOT_FOUND`), nothing written. The drift gate was already red on the base with 34 drifted sources, and all three docs I edited were already among them (state hash ≠ base content), so this PR adds no new drift entry; the 65 mirrors still need a real `i18n:run` once the backend is back. No blanket `--adopt` (it would mask the 34 genuine stale sources). | ## Removed / rewritten assertions, allowlist and suppression deltas None. `config/quality/eslint-suppressions.json` and `config/quality/test-masking-allowlist.json` untouched. ## References Refs #16899 (precedent: restoring a backup requires an operator credential). No issue to close. ## Out of scope - `docs/openapi.yaml` has no `delete` operation for `/api/db-backups` at all (only `get`/`post`/`patch`); adding one would change what the next `npm run build:cli-api` generates (a new `delete-api-db-backups` CLI command + locale keys), so the 403 is documented on `patch` only. - `bin/cli/api-commands/system.mjs` still describes `post-api-db-backups` as "Create database backup" (the pre-#16899 summary; `POST` is the restore-by-id). - Inherited base reds named above (#15306, `/api/balance` doc claim, `managementSession.ts` TS2322, i18n drift of 34 sources).
Merged via /merge-batch (2026-10-19). Evidence: validated on a combined board of the six new PRs over release/v3.8.52 — typecheck core/open-sse/API, ESLint on every changed file, complexity + cognitive within baseline, boundary + cycles ratchets, dead-code, test-masking, i18n new-key coverage, changelog-integrity, docs-sync, check:docs-all, env-doc-sync, provider-consistency, agent-skills 0-diff; 574 focused node tests (the only reds — vision-key-scope-locales and onnx-install-env-16225 — fail identically on the bare tip). CI reds are the inherited base-red #15306 (i18n drift of 18 sources, owned by #16980).
…he (#17121) Merged via /merge-batch (2026-10-19). Evidence: validated on a combined board of the six new PRs over release/v3.8.52 — typecheck core/open-sse/API, ESLint on every changed file, complexity + cognitive within baseline, boundary + cycles ratchets, dead-code, test-masking, i18n new-key coverage, changelog-integrity, docs-sync, check:docs-all, env-doc-sync, provider-consistency, agent-skills 0-diff; 574 focused node tests (the only reds — vision-key-scope-locales and onnx-install-env-16225 — fail identically on the bare tip). CI reds are the inherited base-red #15306 (i18n drift of 18 sources, owned by #16980).
Merged via /merge-batch (2026-10-19). Evidence: validated on a combined board of the six new PRs over release/v3.8.52 — typecheck core/open-sse/API, ESLint on every changed file, complexity + cognitive within baseline, boundary + cycles ratchets, dead-code, test-masking, i18n new-key coverage, changelog-integrity, docs-sync, check:docs-all, env-doc-sync, provider-consistency, agent-skills 0-diff; 574 focused node tests (the only reds — vision-key-scope-locales and onnx-install-env-16225 — fail identically on the bare tip). CI reds are the inherited base-red #15306 (i18n drift of 18 sources, owned by #16980).
) Merged via /merge-batch (2026-10-19). Evidence: validated on a combined board of the six new PRs over release/v3.8.52 — typecheck core/open-sse/API, ESLint on every changed file, complexity + cognitive within baseline, boundary + cycles ratchets, dead-code, test-masking, i18n new-key coverage, changelog-integrity, docs-sync, check:docs-all, env-doc-sync, provider-consistency, agent-skills 0-diff; 574 focused node tests (the only reds — vision-key-scope-locales and onnx-install-env-16225 — fail identically on the bare tip). CI reds are the inherited base-red #15306 (i18n drift of 18 sources, owned by #16980).
Merged via /merge-batch (2026-10-19). Maintainer merge of the current base on top: #17117 had resynced the RUNNER_BOX mirrors against the previous source; this PR changes that source and regenerates all 66 mirrors, so the RUNNER_BOX mirrors and its .i18n-state.json entry were taken from this PR and every other state entry from the base (i18n:check no longer lists RUNNER_BOX). Evidence: validated on a combined board of the six new PRs over release/v3.8.52 — typecheck core/open-sse/API, ESLint on every changed file, complexity + cognitive within baseline, boundary + cycles ratchets, dead-code, test-masking, i18n new-key coverage, changelog-integrity, docs-sync, check:docs-all, env-doc-sync, provider-consistency, agent-skills 0-diff; 574 focused node tests (the only reds — vision-key-scope-locales and onnx-install-env-16225 — fail identically on the bare tip). CI reds are the inherited base-red #15306 (i18n drift of 18 sources, owned by #16980).
…age floor (#15966) Merged via /merge-batch (2026-10-19). Maintainer merge of the current base on top: the README compatibility table had already been rebuilt on the base (kept), the v3.8.20 → v3.8.50 highlight was already fixed, and the single-bold-version rule now skips markdown table rows (the backticked `vX+` cell still carries the current-version claim) so the correct `**v3.8.51**` last-shipped column is not flagged; new test covers both directions. Evidence: PR test 16/16, check-docs-counts-sync, check:docs-all, typecheck core + open-sse, test-masking, 715 related docs/i18n/README/AGENTS tests green on the merged head. Remaining reds (lint unused-suppression entries, i18n drift) reproduce on the bare tip. Thanks @jonlwheat2-gif!
…2743) Merged via /merge-batch (2026-10-19). Maintainer merge of the current base on top: the slimming was redone against the current AGENTS.md (it had grown from 62k to 66k since this PR), keeping everything added since — new Hard Rule text, Bun environment, sync-back landings, root paths, Dual Auth recipe, .husky/_ worktree step — and carrying the #15966 coverage wording. Evidence (owner-approved agent-instruction surface change, 2026-10-19): AGENTS.md 66,144 → 39,848 bytes; all 23 Hard Rules kept and numbered 1–23, every short-form rule carries its full binding text in docs/ops/HARD_RULES_DETAIL.md under the same number; a lost-fact script over the base AGENTS.md found 555/677 lines verbatim and every distinctive fact of the reworded 121 in AGENTS.md or the linked docs; check-docs-counts-sync (incl. the #15966 coverage-floor claims), check:docs-all, the 30 *15159* tests, docs-counts/fabricated-docs tests, typecheck core + open-sse all green. Remaining lint red is the base unused-suppression entry being fixed separately. Thanks @wahidsadik371-coder!
Evidence: full npm run lint exit 0 on this branch (exit 2 on the bare tip, only the unused-suppression message); both files lint clean without the entries.
#17124) Merged via /merge-batch (2026-10-19). Maintainer fix on top: the new check loaded the catalog data module statically, so repo-checks-isolate-datadir flagged it; it now isolates DATA_DIR first and loads the module through a dynamic import (isolateDataDir needs only node built-ins, so the pre-npm-ci CI step still works). Evidence: merged with the current base and validated — the new gate passes (3 sourced, 71 legacy debt), its 16 tests pass, repo-checks-isolate-datadir 10/10 after the maintainer fix, 244/244 autoCombo vitest (mcp config), 506 related node tests incl. workflow/gate-manifest readers, ESLint, file-size, changelog-integrity, docs-sync, check-workflows, typecheck core + open-sse. Remaining CI reds are the inherited i18n base-red #15306.
Merged via /merge-batch (2026-10-19). Evidence (owner asked to verify and merge, 2026-10-19): scope is only docs/i18n mirrors of 20 sources x 66 locales + .i18n-state.json (no protected surfaces, catalogs or baselines). Merged with the base three times; 265 conflicts resolved (AUTHZ_GUIDE/REMOTE-MODE from #17098 taken from the base, README and QUALITY_GATES keep this translation plus the base one-line deltas, state merged entry by entry with every mirror matching its recorded hash). Content audit of 1,320 mirrors: no leaked think tags, duplicated paragraphs or broken headers; code-span drift vs current sources 118 (base 272); the one regression found (Hausa SEARCH_TOOLS_STUDIO Tabs heading) fixed on top. check:docs-all, i18n ratio/keys, openapi/api-docs gates, typecheck core + open-sse green; 266/269 mirror tests, the 3 reds fail identically on the base. Known follow-ups (not certified as fresh in the state): GUARDRAILS after #17111, RESILIENCE_GUIDE after #12743, ENVIRONMENT hold.
) Merged via /merge-batch (2026-10-19). Maintainer merge of the current base on top: migration renumbered 206 → 212 with an isSchemaAlreadyApplied guard for DBs that ran the old 206 file; the usage_history insert now lives in usageWriteRetry.insertEntry, so the two new columns moved there; OpenRouter cost_usd (#16640) is also stored as provider_cost_usd with the same precedence as the cost calculator; the per-key totals query (#17056) carries the stored cost; migration count 208 → 209 across docs, with README mirror state updated for the target bytes only (no stale section certified); usage-analytics-route clears the analytics response cache between tests. Evidence (owner-approved, incl. the count-only AGENTS.md/llm.txt/README mirror bumps): merged with the current base; npm run lint 0, typecheck core + open-sse 0, check:docs-all 0, docs-counts 0, file-size, test-masking, changelog-integrity, migration-numbering, env-doc-sync, complexity, cognitive, boundary, provider-consistency all 0; the 6 PR test files + usage-openrouter-cost 89/89; 228 files reading the changed modules 2322/2323 (kiro-content-stall-15260 timing flake under load, 3/3 in isolation); i18n mirror/state tests only show the 3 base-red #15306 failures. Thanks @thotypous!
The chunk output guard checked <think> leaks, fences, table rows and meta-prose, but not inline code. In the 2026-10-18 resync (#17100, #17117, #17122) every pass translated literals between backticks in 7-12 locales — the runner's own error message, `MemoryHigh=4G` split in two, `[Free]`, `// evidence:`, an npm command — and once dropped a backtick so every later span on the line re-paired. The hash-based drift check sees none of it, so each pass needed hand repairs. - The prompt now says explicitly that text between backticks is a literal. - validateTranslatedChunk() rejects a chunk whose output has fewer copies of any source inline code span (spans inside fences are not compared; a span that wraps across a soft line break is the same span; spans the translator adds are not a loss). A rejected chunk is retried like the other guards, and a doc whose chunk never validates fails instead of being written. Real run with the Codex backend, forced, on RUNNER_BOX for ar and hu (both had translated the runner message before): 2/2 translated on the first attempt, 0 problems in the 66 mirrors. Guard suite 30/30, the six pipeline test files 79/79. Refs #15306
…17129) formatMarkdown() in scripts/i18n/run-translation.mjs formatted each translated mirror with Prettier's defaults (80 columns) instead of the options the prettier --write CLI resolves for the same path (prettier.config.mjs + .editorconfig, printWidth 100). lint-staged then re-wrapped code fences at commit time, and the committed mirror no longer matched the target_hash recorded in .i18n-state.json. It now resolves the config for the target path with prettier.resolveConfig(fileName, { editorconfig: true }) and formats with it. Refs #17098
#17130) The k6, llm-security and schemathesis isolation suites run each workflow's "start the server" step against fake binaries: a fake `node` (started in the background by the step) writes the environment it booted with to $FIXTURE/server-env, and a fake `curl` answers the health loop. That curl passed immediately (k6, llm-security) or after 20 ms (schemathesis), so the step could return before the background server had written anything; the test then read no file (ENOENT) or, on its second boot, the previous boot's file — the "server must boot on the prepared DATA_DIR" mismatch seen once in #17100's CI. - The fake curl is healthy only once server-env exists, like a real health check (schemathesis: in its healthy mode); the previous boot's file is removed before each boot; the fake sleep in the health loop is 0.05 s. - Proven with a 0.3 s delay injected into the fake server's write: the previous suites fail (k6 1, llm-security 2, schemathesis 2 cases), the fixed ones pass (schemathesis keeps one failure only because the injected delay keeps its "dead" server alive for 0.3 s). Without injection: 14/14 across the three files, three runs. Refs #15306
…sk cache (#17133) In a source checkout the call-log artifact worker runs through tsx, and tsx indexes its whole disk cache (os.tmpdir()/tsx-<uid>) with one readdirSync the first time a thread transforms a file. On a shared dev box that directory reached ~585k entries and the worker's first write waited 5-7 s on the listing (0.4 s without it). callLogWorkerOptions() now starts a tsx-launched worker with TSX_DISABLE_CACHE=1 on top of the parent's environment; compiled workers (npm, standalone, Docker) keep the default options. Refs #17091, #17099
…17139) The catalog visibility switches (#13562) stay disabled until the settings load and while a save runs, and every wait in the suite used Testing Library's default 1 s. Inside the full Vitest UI suite on a loaded 4-vCPU runner the first load took longer: "expected <button> to have property 'disabled' with value false" after 1,203 ms in #17130's CI, while the file passes 8/8 on its own. All waits that depend on a settings round trip (waitFor and findBy*) now share a 5 s window; the assertions are unchanged. With every mocked response delayed 1.5 s the previous suite fails 7 of 8 cases and this one passes 8/8; without the delay 8/8 three times. Refs #15306
…rces across 66 locales (wave 1018) (#17142)
…17137) Merged via /merge-batch (2026-10-19). Board validation on the current base together with #17138: npm run lint 0, typecheck core + open-sse 0, check:docs-all 0, file-size, test-masking, changelog-integrity, env-doc-sync, complexity, cognitive, provider-consistency 0; 187 affected unit files 2093 pass with only the 3 base-red #15306 i18n state tests failing. CI reds are inherited (i18n state tests, Docs Sync drift, Gate / Quality, E2E 3/9 mobile sidebar fail on unrelated PRs too).
… routing (#17138) Merged via /merge-batch (2026-10-19). Maintainer merge of the current base: README mirrors keep the release re-translation and re-apply only this PR's count edit (478 to 467 in each locale's digit script) in the three touched contexts; the README catalog paragraph's stale per-model-rows count is corrected to 467 too; i18n state = release state + this PR's FREE_TIERS entry, README target hashes only (no stale section certified; drift list identical to the bare base). Follow-up fix: the free-catalog expansion test's Kilo floor 13 to 12 (auto-beta removal is this PR's intent) and the screenshot budget card regenerated (467) - the two tests CI flagged. Board with #17137: npm run lint 0, typecheck core + open-sse 0, check:docs-all 0, check:free-catalog-evidence PASS, 4 strict-zero-cost vitest files 38/38, 187 affected unit files green apart from the 3 base-red #15306 i18n state tests.
…n the sidebar background (#17154)
… the release branch (#17160)
… ci.yml's shards (#17156) The scheduled full sweep ran unit, vitest, integration and the package build as one Promise.all wave. The 2026-10-18 (omni-build) and 10-19 (omni-release) sweeps killed unit, integration and the build at their ceilings inside it. On 10-19 the webpack build (14-16 GB) pushed the 8-core, 20 GB omni-release slot past memory.high: the kernel throttled every lane and the app's resourcePressure guard, reading that cgroup, answered 503 inside unit tests (three false reds that pass in isolation on the tip). Both days the single unit process at --test-concurrency=4 had run ~29k of its ~32k tests at its 80 min ceiling, while ci.yml runs the same suite as 8 shards of 11-18 min. Unit now runs ci.yml's own shards (npm run test:unit:ci:shard, TEST_SHARD=i/N with N read from ci.yml's test-unit matrix), one per four cores of availableParallelism() (which honours the slot's cpu.max: 2 at a time on omni-release), each under a 40 min ceiling; integration, vitest and the package build follow, one at a time. Each lane is reported as it ends, and a failed shard is named in the gate detail, so a timed-out shard no longer surfaces a fixture's SQLITE_CANTOPEN line as the cause. Refs #15306
…bound (#17159) The `<5ms for 20 messages` check timed one call. Run alone, that call is cold (JIT warm-up) and took 5.3-7.9 ms in 6 of 10 local runs; inside the whole file it passes only because earlier cases happen to warm the code, and on busy hosted runners it still failed 4 of the last 32 PR Vitest jobs (18.23 ms, 5.26 ms), the most frequent Vitest red on PRs. Warm up with three calls, then assert on the fastest of ten timed runs. A pause only adds time, so the bound still catches a slower analysis: with 6 ms of busy work injected into analyzeSpecificity the test fails (6.33 ms). Run alone it now passes 10/10, the whole file 10/10, and 5/5 when sharing one core with a busy loop.
Brings main's 4 post-v3.8.51 commits (#16835, #16782, #16809, #16536) into the release ancestry so PR #15083 stops being CONFLICTING and runs CI again. Tree kept identical to the release tip (da38fc4): every main-only change is already on release in a newer form — evaluateComplexityRun() in validate-release-green.mjs, the USE_VPS_BUILD_RUNNER gate in ci.yml and nightly-release-green.yml, ONNXRUNTIME_NODE_INSTALL=skip in npm-ci-retry, the 375-provider counts (main says 358), and the four unit tests whose release versions are supersets of main's. The three main-only changelog.d fragments are dropped on purpose: the reconciler credits those commits from history.
Reconcile the living [3.8.52] CHANGELOG section against the full cycle (release/v3.8.51..0a1265e, 1,386 non-merge commits): fold the 74 pending changelog.d fragments, add bullets for the 53 commits that had none, patch PR links/credits on 50 bullets (closed-PR re-lands credited: #16988 ← #16982 @fabioKoruja00, #17040 ← #17003 @huynle-dev), regenerate the Contributors table (306 external), date the header (TBD → 2026-10-19) and resync the 66 i18n CHANGELOG mirrors.
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.52
Release candidate — flipped ready at Phase 0a.0a of
/generate-releaseon 2026-10-19 (release-freeze #17170; development continues onrelease/v3.8.53, PR #17171). Reconciled 2026-10-19 against the full cycle rangerelease/v3.8.51..release/v3.8.52(2f42a9ac19→c754707d0e) by the captain's commitc754707d0e. Mirrors the## [3.8.52] — 2026-10-19CHANGELOG section 1:1.This pull request will merge the reconciled
release/v3.8.52snapshot intomain. It is a record of what entered the branch; it is not evidence that the v3.8.52 tag, GitHub release, deployment, or homologation has been completed.The authoritative per-change ledger and release attribution live in
CHANGELOG.md→[3.8.52](1,442 bullets, too large to inline, mirrored across the i18n copies).📊 Reconciled release ledger
These counts are the top-level bullets physically present in the
[3.8.52]CHANGELOG section at thereconciliation head of #15083 — this PR; the reconciliation is the captain's commit c754707 pushed straight to the release branch (cut from branch tip
c754707d0edf250107a386168d4e324f51b24135).The Contributors table is deliberately excluded from the documented-change total.
By the numbers
Entries by type
At the same head:
release/v3.8.51..release/v3.8.52: 1391 commits total / 1387 non-merge / 4 merges;v3.8.51..HEAD(physical tag range): 6,392 commits — releases reachmainby squash, so the tagrange re-lists the un-squashed history of every prior cycle and is not a useful denominator;
mainafter the v3.8.51 tag and reached the branch through the sync-back are documented here too.The physical tag range and canonical development-cycle range are separate denominators because
the repository topology makes history outside the canonical cycle reachable from the tag range.
🏆 Top 25 contributors this cycle
By commits in
release/v3.8.51..release/v3.8.52, author identities consolidated via.mailmapandthe merged PR's GitHub login. Bots excluded. The maintainer's count includes the recreated PRs whose
original authors are credited in the ledger.
Highlights
quota-weightedbecomes the 20th combo strategy (skip exhausted accounts, draw by leftover quota ÷ in-flight load), alongside thenadirauto-router strategy and per-connectionmodelConcurrencycaps (feat(auto-combo): addnadirrouter strategy for prompt-aware model choice #13051, feat(sse): opt-in per-model concurrency caps per connection #13700)omniroute serve --headless/OMNIROUTE_HEADLESS=1) runs only the/v1/*proxy engine (feat(server): headless mode — OMNIROUTE_HEADLESS=1 / serve --headless (rail 3.8.53) #16079)/v1/modelscapability/context/kind filters andPOST /v1/models/queryshortlist; plugin catalog filters (freeOnly,toolsOnly,providersAllow); runtime-learnedreasoning_efforttiers (feat(providers): add Twinmind unofficial web chat provider #14131, feat(plugin): filter published catalog by capability presets #14554, feat(plugin): filter published catalog by provider with empty-result guard #15239)forcedModelpinning, atomic add/remove of models and combos (/api/keys/{id}/access), full-page access editor, calendar-week USD limits andUSAGE_LIMIT_IGNORE_UNPRICED(feat(api-keys): add per-key enforced model routing #16921, feat(api): add or remove models and combos on an API key atomically #14880, feat(dashboard): full-page API key access editor with tabs #14885, feat(usage): optional calendar weekly window for per-key USD limits #14603)npm run i18n:add-locale, README/CHANGELOG mirrors syncedREASONING_REPLAY_ENABLEDflag; Turbopack back on the self-hosted build slot (feat(services): add llmlingua-server supervisor installer and HTTP compression integration #12967, feat(runtime): add reasoning replay feature flag #12486)Measured product surface
Measured on the reconciliation head with
scripts/check/check-docs-counts-sync.mjs(live code, not prose);the denominators are intentionally kept separate:
🙌 Contributors and credit
The v3.8.52 CHANGELOG ledger contains 307 contributor rows: the maintainer plus 306 external
contributors (generated by
npm run release:contributors -- 3.8.52 --inject; every non-bot author ofthe 1,373 merged PRs is present — 0 missing on cross-check).
Credit audit performed at reconciliation (Hard Rule #16):
Co-authored-by).## Attributionsection of the PR body, but were squash-merged without aCo-authored-bytrailer, so GitHub attributes nothing to those people. Every one is credited in its bullet and in the Contributors table (--credit N=handle). GitHub-side attribution can only be repaired by carrying the trailer in the squash message from now on.Co-authored-by: fabioKoruja00 <$(gh api …)>in3c3edb9ef3(Fix/16836 encrypt provider specific secrets #16863) is cosmetic — the commit author is already @fabioKoruja00.[3.8.51]; fix(idempotency): namespace the replay key by the calling API key #15128 (@MumuTW) shipped in v3.8.51 without a bullet — its fragment now lands under[3.8.52].changelog.d/fragments were removed with their bullets; 8 fragments whose text already ships in[3.8.51]/[3.8.50]were dropped;[Unreleased]was left untouched.c754707d0e): the 74 remainingchangelog.d/fragments were folded, 53 commits with no bullet received one, 50 bullets had their PR link / credit patched; reconciler reportmismatches: [],dropped: [].Co-authored-by); fix(providers): pin uncloseai's context window at the provider level, not the model id #17039 → fix(providers): keep uncloseai's 65536 context window across /v1/models roster rotations #17067 is the same author (@opensource-elearning) and needs no extra credit; Fix formatting and headings in SECURITY.md #17027 (@gsmarcil) and Refactor error handling and add tests for 500 error sanitization #16973 (@juniorhillory-creator) were closed by their authors with nothing landed; fix(streaming): align credential gate resolver types #16983, docs: add plain-English overview of OmniRoute and Claude Code setup #16971 and the threestrdst7lockfile syncs were declined with no reuse; fix(docs): render linked pages with the default MDX component map #17065/fix(ci): register missing mutation coverage tests #17083/test(providers): regenerate the translate-path golden for the WorkBuddy compliance headers (#17046) #17104 are maintainer PRs.main's four post-v3.8.51 commits (fix(quality): reject incomplete complexity outcomes on main #16536, fix(ci): deliver ONNX install skip through explicit env #16782, fix(docs): validate aggregate provider counts on main #16809, ci: make the .113 omni-build slot opt-in on main (USE_VPS_BUILD_RUNNER) #16835) are in the branch ancestry through the-s oursback-merge0a1265ea(every change already lived on the release in a newer form) and are credited as bullets.Exact-head validation snapshot
The classifications below are bound to branch tip
c754707d0edf250107a386168d4e324f51b24135(the PR head at reconciliation); a partial, cancelled, skipped, stale, or advisory result is not
promoted to PASS. The PR is ready for review; the heavy
ci.ymlmatrix runs on every push to this branch and its live result is the reviewer's source of truth.npm run check:release-green -- --quick --full-cionc754707d0e(local, 13:37–14:42Z)ci.ymlstatic gates (lint / quality-gate / quality-extended)npm run check:changelog-integrityvsorigin/release/v3.8.52andnpm run check:docs-synconc754707d0ec754707d0e(lint-staged, docs-sync, any-budget, tracked-artifacts, ai-attribution)ci.ymlon the previous head0a1265ea81(PR → main, run started 13:17Z)Unit Tests fast-path (3/4)+(4/4)on0a1265ea81; local full unit suite on the same tree (running at push time, 4 ✖ so far)vision bridge key scope is translated without certifying stale locale content,the two source-delta mirror records describe current source and translated bytes(translation backlog, not code); the 3 localacp-*✖ are a stale localnode_modules(@agentclientprotocol/sdkabsent) — 21/21 pass isolated afternpm installdast-smokeon0a1265ea81The runner has received a shutdown signalat 13:27Z (self-hosted runner recycled mid-job) — re-run on the new headnpm run test:unit), production build chain (OMNIROUTE_USE_TURBOPACK=0 npm run build→build:cli→check:pack-artifact→check:pack-boot), vitest, integration — all local on0a1265ea81's treec754707d0eis the authoritative signalc754707d0eci.ymlon this pushAccordingly, this snapshot is not represented as release-green.
Open items before merge (STOP #1)
docs/reference/ENVIRONMENT.md,docs/architecture/RESILIENCE_GUIDE.md,docs/security/GUARDRAILS.md, …) reddens three pinned unit tests (vision-key-scope-locales,cli-env-quality-docs-mirrors,resilience-pre-dispatch-docs-mirrors) andDocs Sync (Strict)on every PR, this one included. It is a translation backlog, not a code defect: the re-translation wave is blocked on the translation backend (Codex weekly quota until ~2026-10-24; the other wallets have no balance). Owner decision 2026-10-19: ship v3.8.52 with the base-red documented; the wave lands onrelease/v3.8.53and reachesmainthrough the next sync-back./generate-release); the heavyci.ymlrun on the final head is the live gate — expect exactly the four reds above and nothing else.origin/mainto the homologation VPS (/deploy-vps-local, CI-artifact fast path) and the owner's explicit OK (STOP build(deps): bump actions/github-script from 7 to 8 #2) before any tag, GitHub release, Docker or npm publish._tasks/pipeline/_release-drain/bucket (6 parked plan-files) and 12hold-vps[defer]feature PRs can be drained against the deployed VPS during homologation; a failed live check never blocks this release.Evidence identifiers
Evidence