Validado em lote numa worktree combinada com os 14 PRs desta campanha de error-boundary sobre o tip de `release/v3.8.51`: `typecheck:core` limpo e **120/120** nos 23 arquivos de teste que os PRs trazem.
Um ponto que só apareceu no tree combinado: **#12465 e #12466 criam o mesmo arquivo novo** `open-sse/utils/streamReadiness.ts` (que não existe no tip) com desenhos divergentes de cancelamento — `cancelled` + `releaseLock` imediato num, `readInFlight`/`cancelRequested` com `cancelReader` fire-and-forget no outro. Adotei a versão do #12466, que difere e defere o release do lock para quando a leitura em voo termina, e validei a escolha rodando as suítes dos **dois** PRs contra ela: 21/21 no readiness compartilhado e 22/22 incluindo o boundary do Perplexity.
Validado em worktree combinada sobre o tip de release/v3.8.51: os dois boardaram sem conflito, typecheck:core limpo, check-file-size sem violação nova (as duas restantes — codex.ts e stream.ts — são drift anterior) e 51/51 nos 5 arquivos de teste que os PRs trazem.
Validado em worktree combinada sobre o tip de release/v3.8.51: os dois boardaram sem conflito, typecheck:core limpo, check-file-size sem violação nova (as duas restantes — codex.ts e stream.ts — são drift anterior) e 51/51 nos 5 arquivos de teste que os PRs trazem.
17 de 18 checks verdes, **zero falhas** — incluindo os quatro shards de unit, Vitest, CodeQL, semgrep, Docs Gates, Merge integrity e o **Fast Quality Gates**, que era exatamente o que o rebaseline do `RoutingTab.tsx` (1606→1607, a linha do seletor que acompanha a nova versão de identidade) veio consertar.
O único check restante, `No new ESLint warnings`, ficou enfileirado sem iniciar (duração 0) atrás da saturação de runners de hoje. Cobri os dois comandos que ele executa, localmente e sobre este HEAD:
- `npm run check:codeql-ratchet` → **0 alertas abertos** contra baseline 6 (sem regressão).
- `npx eslint --max-warnings 0` nos 9 arquivos de código que esta branch altera → **exit 0**, nenhum warning.
Conteúdo: os dois commits do #12402 que não estavam subsumidos, com autoria do @ggiak preservada pelo cherry-pick `-x`, mais o rebaseline e o fragmento de changelog que faltava. `typecheck:core` limpo e **138/138** nos testes focados. As três versões (`claudeCodeClient.ts`, `Dockerfile`, `compose.yml`) conferem em 2.1.258, e `npm view @anthropic-ai/claude-code@2.1.258` resolve — o Dockerfile instala esse pin exato.
Validado em lote numa worktree combinada com os 9 PRs desta leva sobre o tip de `release/v3.8.51` (já com a leva anterior dentro): os nove boardaram **sem um único conflito**, `typecheck:core` limpo e **80/80** nos 6 arquivos de teste que os PRs trazem.
O crescimento de arquivo próprio da leva foi rebaselinado num registro datado (`_rebaseline_2026_09_03_hartmark_batch`): `combos/page.tsx` 5012→5018 (#12355, tratar o estado degradado quando o bundling de tiktoken de um provider sem relação falha) e `open-sse/services/combo.ts` 4023→4036 (#12338, os fixes do universal-handoff). As violações restantes (`codex.ts`, `stream.ts`) foram medidas também no tip puro e são drift da base, não desta leva.
Obrigado, @hartmark.
Validado em lote numa worktree combinada com os 9 PRs desta leva sobre o tip de `release/v3.8.51` (já com a leva anterior dentro): os nove boardaram **sem um único conflito**, `typecheck:core` limpo e **80/80** nos 6 arquivos de teste que os PRs trazem.
O crescimento de arquivo próprio da leva foi rebaselinado num registro datado (`_rebaseline_2026_09_03_hartmark_batch`): `combos/page.tsx` 5012→5018 (#12355, tratar o estado degradado quando o bundling de tiktoken de um provider sem relação falha) e `open-sse/services/combo.ts` 4023→4036 (#12338, os fixes do universal-handoff). As violações restantes (`codex.ts`, `stream.ts`) foram medidas também no tip puro e são drift da base, não desta leva.
Obrigado, @hartmark.
Validado em lote numa worktree combinada com os 9 PRs desta leva sobre o tip de `release/v3.8.51` (já com a leva anterior dentro): os nove boardaram **sem um único conflito**, `typecheck:core` limpo e **80/80** nos 6 arquivos de teste que os PRs trazem.
O crescimento de arquivo próprio da leva foi rebaselinado num registro datado (`_rebaseline_2026_09_03_hartmark_batch`): `combos/page.tsx` 5012→5018 (#12355, tratar o estado degradado quando o bundling de tiktoken de um provider sem relação falha) e `open-sse/services/combo.ts` 4023→4036 (#12338, os fixes do universal-handoff). As violações restantes (`codex.ts`, `stream.ts`) foram medidas também no tip puro e são drift da base, não desta leva.
Obrigado, @hartmark.
Validado em lote numa worktree combinada com os 9 PRs desta leva sobre o tip de `release/v3.8.51`: `typecheck:core` limpo, `check:provider-consistency` OK (273 entradas REGISTRY, **356** providers canônicos), `check-docs-counts-sync` exit 0 e **300/300** nos testes que a leva toca.
O crescimento de arquivo que os PRs empilham uns sobre os outros foi rebaselinado num único registro datado (`_rebaseline_2026_09_03_houminxi_batch`), com a decomposição por arquivo: `providers/page.tsx` +18 (import CSV do #12504 + busca do #12495 no mesmo painel), `accountFallback.ts` +6 (o #12566 sobre o rebaseline que o #12590 já registrou — os dois tocam `checkFallbackError`) e `chatCore.ts` +3 (invalidez de cache de quota no 429 do #12325). As violações restantes (`codex.ts`, `stream.ts`) foram medidas também no tip puro e são drift da base, não desta leva.
Validado em lote numa worktree combinada com os 9 PRs desta leva sobre o tip de `release/v3.8.51`: `typecheck:core` limpo, `check:provider-consistency` OK (273 entradas REGISTRY, **356** providers canônicos), `check-docs-counts-sync` exit 0 e **300/300** nos testes que a leva toca.
O crescimento de arquivo que os PRs empilham uns sobre os outros foi rebaselinado num único registro datado (`_rebaseline_2026_09_03_houminxi_batch`), com a decomposição por arquivo: `providers/page.tsx` +18 (import CSV do #12504 + busca do #12495 no mesmo painel), `accountFallback.ts` +6 (o #12566 sobre o rebaseline que o #12590 já registrou — os dois tocam `checkFallbackError`) e `chatCore.ts` +3 (invalidez de cache de quota no 429 do #12325). As violações restantes (`codex.ts`, `stream.ts`) foram medidas também no tip puro e são drift da base, não desta leva.
Validado em lote numa worktree combinada com os 9 PRs desta leva sobre o tip de `release/v3.8.51`: `typecheck:core` limpo, `check:provider-consistency` OK (273 entradas REGISTRY, **356** providers canônicos), `check-docs-counts-sync` exit 0 e **300/300** nos testes que a leva toca.
O crescimento de arquivo que os PRs empilham uns sobre os outros foi rebaselinado num único registro datado (`_rebaseline_2026_09_03_houminxi_batch`), com a decomposição por arquivo: `providers/page.tsx` +18 (import CSV do #12504 + busca do #12495 no mesmo painel), `accountFallback.ts` +6 (o #12566 sobre o rebaseline que o #12590 já registrou — os dois tocam `checkFallbackError`) e `chatCore.ts` +3 (invalidez de cache de quota no 429 do #12325). As violações restantes (`codex.ts`, `stream.ts`) foram medidas também no tip puro e são drift da base, não desta leva.
Validado em lote numa worktree combinada com os 9 PRs desta leva sobre o tip de `release/v3.8.51`: `typecheck:core` limpo, `check:provider-consistency` OK (273 entradas REGISTRY, **356** providers canônicos), `check-docs-counts-sync` exit 0 e **300/300** nos testes que a leva toca.
O crescimento de arquivo que os PRs empilham uns sobre os outros foi rebaselinado num único registro datado (`_rebaseline_2026_09_03_houminxi_batch`), com a decomposição por arquivo: `providers/page.tsx` +18 (import CSV do #12504 + busca do #12495 no mesmo painel), `accountFallback.ts` +6 (o #12566 sobre o rebaseline que o #12590 já registrou — os dois tocam `checkFallbackError`) e `chatCore.ts` +3 (invalidez de cache de quota no 429 do #12325). As violações restantes (`codex.ts`, `stream.ts`) foram medidas também no tip puro e são drift da base, não desta leva.
Validado em lote numa worktree combinada com os 9 PRs desta leva sobre o tip de `release/v3.8.51`: `typecheck:core` limpo, `check:provider-consistency` OK (273 entradas REGISTRY, **356** providers canônicos), `check-docs-counts-sync` exit 0 e **300/300** nos testes que a leva toca.
O crescimento de arquivo que os PRs empilham uns sobre os outros foi rebaselinado num único registro datado (`_rebaseline_2026_09_03_houminxi_batch`), com a decomposição por arquivo: `providers/page.tsx` +18 (import CSV do #12504 + busca do #12495 no mesmo painel), `accountFallback.ts` +6 (o #12566 sobre o rebaseline que o #12590 já registrou — os dois tocam `checkFallbackError`) e `chatCore.ts` +3 (invalidez de cache de quota no 429 do #12325). As violações restantes (`codex.ts`, `stream.ts`) foram medidas também no tip puro e são drift da base, não desta leva.
Validado em lote numa worktree combinada com os 9 PRs desta leva sobre o tip de `release/v3.8.51`: `typecheck:core` limpo, `check:provider-consistency` OK (273 entradas REGISTRY, **356** providers canônicos), `check-docs-counts-sync` exit 0 e **300/300** nos testes que a leva toca.
O crescimento de arquivo que os PRs empilham uns sobre os outros foi rebaselinado num único registro datado (`_rebaseline_2026_09_03_houminxi_batch`), com a decomposição por arquivo: `providers/page.tsx` +18 (import CSV do #12504 + busca do #12495 no mesmo painel), `accountFallback.ts` +6 (o #12566 sobre o rebaseline que o #12590 já registrou — os dois tocam `checkFallbackError`) e `chatCore.ts` +3 (invalidez de cache de quota no 429 do #12325). As violações restantes (`codex.ts`, `stream.ts`) foram medidas também no tip puro e são drift da base, não desta leva.
Validado em lote numa worktree combinada com os 9 PRs desta leva sobre o tip de `release/v3.8.51`: `typecheck:core` limpo, `check:provider-consistency` OK (273 entradas REGISTRY, **356** providers canônicos), `check-docs-counts-sync` exit 0 e **300/300** nos testes que a leva toca.
O crescimento de arquivo que os PRs empilham uns sobre os outros foi rebaselinado num único registro datado (`_rebaseline_2026_09_03_houminxi_batch`), com a decomposição por arquivo: `providers/page.tsx` +18 (import CSV do #12504 + busca do #12495 no mesmo painel), `accountFallback.ts` +6 (o #12566 sobre o rebaseline que o #12590 já registrou — os dois tocam `checkFallbackError`) e `chatCore.ts` +3 (invalidez de cache de quota no 429 do #12325). As violações restantes (`codex.ts`, `stream.ts`) foram medidas também no tip puro e são drift da base, não desta leva.
* feat(video): redact transcript fields in the in-memory pending-request snapshot (#12430 item 6)
trackPendingRequest (open-sse/handlers/chatCore.ts) stored the raw client
body (with video transcript/audioTranscript cues) under `clientRequest`,
live-exposed via /api/usage/call-logs (pendingDetails), /api/logs/[id] and
/api/conversations while a request is in-flight. P2a redacted the persisted
detailed-log snapshot but not this in-memory copy.
Add redactPendingBody() to videoBridgeSnapshotRedaction.ts (sibling to
logClientRawRequestRedacted from P2a): when videoBridgeObserved, returns the
redacted clone from redactVideoTranscriptFieldsForLog; otherwise returns the
exact same reference. Wire it into the trackPendingRequest call site
(chatCore.ts:934), keeping the file within its frozen 5976-line budget
(5971 -> 5974).
* feat(video): substring-redact transcript in derived-prompt dispatch logs (#12430 item 4)
Extend applyVideoBridgeLogRedaction with a string-content branch:
pipeline-strategy stages, smart-auto-pipeline, and context-handoff
summaries embed the transcript as a substring of a rendered prompt
string rather than an exact array part, so the existing exact
part-array match silently skipped them. Adds a mutually-exclusive
string branch (Array.isArray vs typeof === "string") that does a
replaceAll of the trusted fullText literal against a lazily cloned
message, reusing the existing rootClone/clonedContainers/clonedMessages
clone-on-write pattern so siblings keep original references and the
input is never mutated.
* fix(authz): hard-gate every credential export and CLI-config write
GHSA-5926-2w35-7h4q: `POST /api/providers/{id}/claude-auth/export` and
`.../codex-auth/export` gate on `requireManagementAuth(request)` with no
`alwaysRequireAuth`, and neither path was in ALWAYS_PROTECTED_API_PATHS. Under
`requireLogin=false` — the local-first default — both fail open, so anyone who
knows a connection id downloads the operator's raw Claude/Codex OAuth
access_token / refresh_token (plus the Codex id_token).
This is the third recurrence of one class. GHSA-mghq-58h3-qcqj added
/api/db-backups; GHSA-v7g9-7f55-5g46 added the /api/settings/*-json siblings
mghq had missed; these two are the siblings both missed. So the fix is written
against the class, not the two reported routes.
Sweeping every route that hands out stored credentials, dumps captured traffic,
or writes the operator's CLI config turned up four more on the fail-open tier:
- GET /api/logs/export — dumps call_logs (prompts and responses) and proxy_logs
for up to 168h.
- /api/cli-tools/codex-profiles — GET leaks the operator's account label; PUT
writes attacker-supplied auth.json and config.toml straight into the host's
Codex CLI config. Its only guard is ensureCliConfigWriteAllowed() with no
targetPath, which checks CLI_ALLOW_CONFIG_WRITES — default true. Paired with
the POST that stores an arbitrary profile, that is: save a profile holding the
attacker's auth.json, apply it, and the operator's CLI now runs on attacker
credentials (or, via config.toml, an attacker base URL).
- {claude,codex}-auth/apply-local and providers/agy-auth/apply-local — write a
stored credential into ~/.codex/auth.json and
~/.gemini/antigravity-cli/antigravity-oauth-token.
The traffic-inspector HAR exports were already covered by LOCAL_ONLY.
Routes with a dynamic segment cannot be expressed in the exact/prefix list — a
`/api/providers/` prefix would hard-gate the whole provider surface and break
every keyless install — so this adds ALWAYS_PROTECTED_API_PATTERNS, mirroring
the existing LOCAL_ONLY_API_PATTERNS, and `isAlwaysProtectedPath` consults both.
The apply-local routes get ALWAYS_PROTECTED rather than LOCAL_ONLY on purpose:
it closes the anonymous hole without breaking an operator driving the dashboard
through a tunnel.
Deliberately NOT adding `{ alwaysRequireAuth: true }` at the handlers. Tier 2 is
the architecture's designated mechanism and the guard runs before the handler; a
second copy of the same decision inside each route is exactly the kind of
duplicate that drifts out of sync (cf. the dashboardCsrf prefix scan that had to
be unified in #11417).
tests/unit/authz/credential-export-always-protected.test.ts — 5 tests, red
before the fix. Written as an inventory of the whole class rather than two more
assertions, plus negative cases: the neighbouring provider routes must stay on
MANAGEMENT, and a connection id containing a slash must not slip past `[^/]+`.
openapi.yaml marks the seven newly-gated operations `x-always-protected`, and
openapi-security-tiers.test.ts now resolves `{param}` placeholders so it can
validate the pattern entries too.
Reported by @skeletonsec.
Closes GHSA-5926-2w35-7h4q
* chore(quality): register the credential-export authz test in stryker tap.testFiles
The new tests/unit/authz/credential-export-always-protected.test.ts covers
src/server/authz/routeGuard.ts, so check:mutation-test-coverage --strict fails
until it is listed — its mutant kills would not count otherwise.
Inserted in place (no re-serialization: a JSON round-trip on this file reorders
~10 curated entries that are already out of alphabetical order, cf. #11438).
* feat(video): redact raw client-snapshot transcript fields in the detailed log (#12150 P2)
clientRawRequest.body is captured before the guardrail chain runs and persisted
verbatim by reqLogger.logClientRawRequest, so it retained the client's raw
transcript/audioTranscript cue text on video parts even after P1's description
redaction. Add redactVideoTranscriptFieldsForLog (new, dependency-light module)
and wire it at the logClientRawRequest call site, gated on videoBridgeObserved:
redacts the structured transcript fields in the LOGGED copy only, never the
body sent to the provider or returned to the client.
* refactor(video): extract the guarded client-snapshot log call to keep chatCore within its size budget
Fast Quality Gates check:file-size flagged chatCore.ts growing past its
frozen ceiling (5985 > 5976) from the P2a wiring. Move the guarded
logClientRawRequest call into logClientRawRequestRedacted (new export
in videoBridgeSnapshotRedaction.ts, which already owns the redaction),
collapsing the inline if-block at the chatCore.ts call site to a single
call. Net -4 lines vs the pre-P2a base. Behavior unchanged: non-observed
still logs the exact same clientRawRequest.body reference; observed
still logs the redacted clone.
Validado em lote numa worktree combinada com #12524, #12538, #12277 e #12367 sobre o tip de release/v3.8.51: os quatro boardaram sem conflito (áreas disjuntas — zai-web, nvidia, clova, cursor/devin/fable). typecheck:core limpo, check:provider-consistency OK (272 entradas REGISTRY, 355 providers canônicos), check:known-symbols OK, e 305/305 nos testes tocados pelos quatro PRs. Os IDs de modelo adicionados foram conferidos individualmente. Obrigado, @backryun.
Validado em lote numa worktree combinada com #12524, #12538, #12277 e #12367 sobre o tip de release/v3.8.51: os quatro boardaram sem conflito (áreas disjuntas — zai-web, nvidia, clova, cursor/devin/fable). typecheck:core limpo, check:provider-consistency OK (272 entradas REGISTRY, 355 providers canônicos), check:known-symbols OK, e 305/305 nos testes tocados pelos quatro PRs. Os IDs de modelo adicionados foram conferidos individualmente. Obrigado, @backryun.
Validado em lote numa worktree combinada com #12524, #12538, #12277 e #12367 sobre o tip de release/v3.8.51: os quatro boardaram sem conflito (áreas disjuntas — zai-web, nvidia, clova, cursor/devin/fable). typecheck:core limpo, check:provider-consistency OK (272 entradas REGISTRY, 355 providers canônicos), check:known-symbols OK, e 305/305 nos testes tocados pelos quatro PRs. Os IDs de modelo adicionados foram conferidos individualmente. Obrigado, @backryun.
* feat(api): conductor task creation route (repeat support)
* feat(a2a): record memoryHits consulted per task (observability, 2.7)
* feat(dashboard): repeat action in orchestration drawer (2.6 — repeat only)
* fix(dashboard): require every field each repeat contract needs before enabling the action
* feat(dashboard): memory-used drawer section + fase2 i18n/changelog (2.7)
* fix(dashboard): validate memoryHits shape before rendering + locale wording fixes
* fix(dashboard,a2a): stop memoryHits leaking into repeats, harden drawer guard + status clamp
Final whole-branch review fix wave for the Orchestration Canvas Fase 2 PR-C.
- a2a: `createTask` stores a COPY of `input.metadata` instead of aliasing it, so the
observability `memoryHits` written by `executeA2ATaskWithState` no longer leak into
`task.input.metadata`, into the persisted `a2a_tasks.input_json`, or into the drawer's
"Repeat" body (a repeated task was born carrying the previous run's memory snippets,
even with the `OMNIROUTE_A2A_MEMORY_HITS=0` kill-switch on).
- dashboard: `repeatReqFor` strips `memoryHits` from the a2a repeat metadata, so tasks
persisted before the copy-fix do not propagate them either.
- dashboard: the "Memory used" section now requires all four rendered fields (id, key,
type, snippet) to be strings — `{ id: "x", key: { a: 1 } }` used to throw "Objects are
not valid as a React child" and take the whole drawer down.
- dashboard: an `/a2a` action answered with a JSON-RPC error under HTTP 200 is reported as
a failure (`RPC <code>`, code only — never the upstream message) instead of a success
toast; the secured-deployment rejection keeps surfacing the sanitized `HTTP 400`.
- api: the conductor task-creation route clamps a hub status outside 400-599 to 502, so an
out-of-range status can no longer turn a hub refusal into a `RangeError`.
- dashboard: the History tab's `onActionDone` keeps the drawer mounted (and refreshes the
range) instead of closing it, so the repeat/cancel confirmation is actually visible.
- a2a: documented the recall owner-id limitation — `task.owner` is a SHA-256 key prefix
while memory rows are keyed by the DB api-key id, and no hash-to-id lookup exists today,
so recall only resolves under the keyless posture.
* refactor(dashboard): split drawer repeat helpers and test file under the size/complexity gates
---------
Co-authored-by: Markus Hartung <diegosouzapw@users.noreply.github.com>
* fix(video): re-anchor log-redaction fullText from the finished guardrail payload so PII/credential maskers can't reopen the transcript leak
* docs(video): clarify P1 transcript-retention scope and re-anchor; list P2 surfaces (#12430)
* feat(db): a2a task history module over migration-002 tables
* feat(a2a): persist task lifecycle to a2a_tasks with 30d retention purge
* feat(api): a2a task history listing + historical detail fallback
* feat(dashboard): orchestration History tab (Airflow-grid) over persisted runs (2.2)
* fix(dashboard): assert history preset window + loading and time axis in the grid
* chore(dashboard): history i18n + changelog
* fix(dashboard): explicit history purge cascade + keep live drawer off the History tab
* docs: document OMNIROUTE_A2A_HISTORY_RETENTION_DAYS
* refactor(dashboard): split HistoryTab helpers under the complexity ratchet
---------
Co-authored-by: Markus Hartung <diegosouzapw@users.noreply.github.com>
Migrates the Claude, Grok, LMArena, Notion and Perplexity web-cookie transports from the tls-client-node/Koffi sidecar to the exactly pinned wreq-js 3.2.0 runtime, keeping the per-provider browser/OS profiles, making request cookies ephemeral, bounding and generation-protecting the shared native transport pool, removing the legacy downloader and repair path, and carrying the native binding and license evidence through the npm, standalone, Electron, Docker and Bun packaging surfaces.
This is the consolidation of the two competing migrations, and the consolidation was decided by evidence rather than by preference. #11753's six suites were installed over this implementation and run as an independent specification: 31 of 36 passed. All five failures are artefacts of #11753 being the older design, not coverage gaps —
- two hardcode the 3.0.0 pin in their assertions (this branch pins 3.2.0, which is what the release tip already resolves; #11753's 3.0.0 would have conflicted);
- one reads open-sse/services/chatgptTlsClient.ts, deleted when #11754 retired ChatGPT Web, so the test is stale against the current tip;
- two import WREQ_JS_NATIVE_BINARY_NAMES / resolveWreqJsNativeBinaryName, which this branch redesigned into WREQ_JS_NATIVE_BINDINGS / resolveWreqJsNativeBinding plus WREQ_JS_VERSION — a rename from modelling natives as file names to modelling them as package bindings, verified as an API difference rather than a lost capability (the linux-x64-gnu .node is present and serviceable).
This branch is also the strict superset by scope: 7 files exclusive to it, including the wreq-js Rust license inventory and notices, .trivyignore, open-sse/utils/tlsClient.ts and assembleStandalone.mjs. #11753 had one exclusive file, its changelog fragment. Nothing needed porting, so #11753 is superseded rather than merged, and the changelog entry credits both.
Reconciled on merge: clean against the tip. The new migration suite (tests/unit/tls-client-wreq-migration.test.ts, 1374 lines, 31 cases) is frozen at its exact LOC with the rationale — it shares one native-transport harness, so splitting it mid-merge would duplicate that harness for no coverage gain. Verified that no existing cap moves.
Verified: 182/182 across the eight TLS, native-manifest, postinstall, standalone-bundle, pack-artifact and provider-validation suites, typecheck:core clean, check:cycles OK, check-changelog-integrity OK, check-file-size OK, and every changed TypeScript file parses.
Restores ChatGPT Web on a clean-room browser transport, merged on the operator's explicit decision.
Worth stating precisely, because this touches a provenance decision: the PR does not revert #11754. It narrows RETIRED_COMMON_CHATGPT_WEB_PROVIDER_IDS to the single GPL-derived alias cgpt-web and registers chatgpt-web as a separate clean-room id. The old implementation stays retired and blocked; the retirement machinery, its error code and its 410 contract are untouched. All four retirement suites agree with that distinction and pass unchanged.
The 44 protected agent-instruction surfaces this PR touches (AGENTS.md, llm.txt and its 42 mirrors, README) were verified rather than trusted: masking digits and comparing the removed and added line sets gives 264 lines on each side, identical — every change is a provider-count substitution, with no sentence added, removed or reworded.
Reconciled on merge: clean against the tip, with the two chat chokepoints this PR grows (src/sse/handlers/chat.ts +40, open-sse/handlers/chatCore.ts +30) recorded in the file-size baseline under an annotation. Verified that exactly those two caps move and nothing else, so the #12411 ratchet holds. The rebaseline is carried on this branch rather than left in a validation worktree — the propagation mistake that put the 2026-09-02 merge waves base-red in #12434.
Verified: 504/504 across the PR's 44 test files plus all four chatgpt-web retirement suites, check:provider-consistency OK (272 REGISTRY entries, 355 canonical providers), check-file-size OK, and every changed TypeScript file parses.
Thanks @backryun — separating the clean-room id from the retired alias, instead of reopening the old one, is what made this reviewable.
P1 of #12150: transcript text no longer reaches call logs or durable memory in the clear.
Reconciled on merge — the two persisted-requestBody assertions were failing, and the failure signature was misleading enough to be worth recording. They reported "expected: true, actual: false", which reads like the redaction not applying. It was not: pollForCallLog waited at most 120 tries x 20ms = 2.4s for the asynchronous SQLite write, then returned null, so assert.ok(row) failed before any redaction assertion ran. The observed durations were 5253ms and 4467ms against that 2.4s ceiling — a starved runner, not a leak. The control test failing alongside the positive one was the tell: a real redaction defect would break one direction, not both.
Replaced the fixed try count with a 30s wall-clock deadline: far past any healthy write, still bounded, and a fast machine still returns on the first pass. A privacy test should not depend on how busy the box is.
Verified: 4/4 three consecutive times under synthetic load, and 3/3 unloaded beforehand. Note the synthetic load reached ~7, below the ~38 where the original failure appeared, but the budget is now 12.5x larger and deadline-based rather than count-based.
Closes the two remaining unresolved provider-asset records without weakening the provenance boundary: public/providers/nimble-search.svg is removed because no sufficient redistribution evidence is recorded, and Nimble Search renders with the internal generic icon before any CDN tier while staying fully functional; Opper is registered in the local SVG resolver with its existing bytes proven against opper-ai/provider-omniroute at immutable commit 9aacef7d6a, recording the MIT repository license from that same commit while keeping trademarkClearance null.
Validated in a combined worktree with the batch's ready set boarded onto the current tip: parse sweep clean on every changed TypeScript file, typecheck:core clean, check:dashboard-typecheck OK (207 pre-existing errors, all within baseline), check:cycles OK, check-file-size OK, 203/205 focused node tests and 94/94 vitest — the two failures belong to #12427, which is held back.
The service operator asked in writing (2026-08-30) that their service be
removed from OmniRoute entirely: executor, registry entry, no-auth catalog
entry and alias, icon mapping, env var, docs rows, dedicated tests and
snapshots, and every passing mention in comments, fixtures and CHANGELOG
entries. Provider count drops from 355 to 354 on every canonical surface.
Co-authored-by: Markus Hartung <diegosouzapw@users.noreply.github.com>
The #11461 × #11513 merge ate the closing '],' + '},' of the maxai entry in
webSessionCredentials.ts — 11 syntax errors (TS1005/1137/1128) on the tip,
which also masked one real TS2322 the MaxAI block introduced in the models
route (providerSpecificData is unknown on the connection; cast to the exact
shape resolveMaxaiCredential already takes, zero runtime change).
API Route Typecheck gate: OK — 289 pre-existing, all baselined. typecheck:core: 0.
Three regressions inherited by every PR rebased onto release/v3.8.51, caught and documented with the exact failing output.
The one that mattered most: src/shared/providers/webSessionCredentials.ts did not parse. The UC merge (#11513) inserted the uc: entry inside maxai.storageKeys and lost the array's closing ], plus the entry's }, leaving `ERROR: Expected "]" but found ":"` at line 351. That module is imported by the provider API routes, bulk-web-session, autoCombo's virtualFactory, keepaliveThreshold and dashboard components, so the break was live on the tip and flooded unrelated catalog tests with transform failures. That was my conflict resolution, not the contributor's code — thank you for catching it and for tracing it to the root commit rather than patching around the symptom.
Also fixed: the duplicate bin/cli/utils/volatileEnvPath.mjs entry in PACK_ARTIFACT_REQUIRED_PATHS (findMissingArtifactPaths reported it twice), and UC image models made prefix-addressable without letting them claim historical bare model ids belonging to other providers.
Reconciled on merge: #12394 landed the busy_timeout/probe work first, so src/lib/db/core.ts takes the tip's side. probeUtils.ts is the union of both rather than either side — this PR's message regex is wider (SQLite also reports "database table is locked", "database schema is locked" and "database is busy"), while #12394 added the driver code/errcode path that keeps a transient lock from being classified as corruption and renaming the database away. Taking either alone would have dropped the other half; this PR's own ENOENT test is what surfaced it.
Verified: 76/76 across uc-image, probe-9541-repro, web-session-contract, pack-artifact-policy, bulk-web-session-import and exclusive-connection-leases, and every changed .ts file parses.
Thanks @backryun.
GET /v1/providers/gemini-business/models returned nothing because gemini-business had no RegistryEntry: the listing route resolves the provider through getRegistryEntry and filters the unified catalog by owned_by, and open-sse/config/providers/index.ts only registered gemini and gemini-web.
Adds a registry entry mirroring gemini_webProvider — id gemini-business, alias gembiz, cookie auth — with the twelve ids from the executor's MODEL_CATEGORY_MAP. Each model is declared toolCalling: false, supportsReasoning: false, the same live-behaviour contract applied to gemini-web in #9356: the executor returns plain text, hard-wires the thinking mode and parses no tool calls.
Reconciled on merge: the only conflict was the reserved-prefix count assertion, which the tip had moved. Took the tip's text and measured the real value with this PR applied — 406 to 408, the gemini-business id plus its gembiz alias — rather than carrying the branch's number.
Validated in a combined worktree with all 25 PRs of this batch boarded together (typecheck:core clean, 443/443 node-runner plus 14/14 vitest, all static gates green), and re-verified standalone on the current tip after the other 24 landed: 33/33 across provider-node-reserved-prefix, gemini-business-model-registry-12107 and web-cookie-validation-fallback, with check:provider-consistency OK at 272 REGISTRY entries and 355 canonical providers.
Thanks @pacocartones.
The gamification anomalies page had hard-coded English for its loading state, Status column header and Suspicious badge, and was the only standalone non-redirect dashboard page without a sidebar entry. Both are fixed: the strings come from the common catalog, and the page joins the Gamification sidebar group as a hideable section item shown only by the "all" preset, like its siblings. The loading and empty states also become role="status" aria-live="polite" live regions with aria-busy, matching profile/page.tsx and health/page.tsx. Three new keys in en.json, propagated to the other 42 locales with the __MISSING__ sentinel.
Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.
Thanks @pacocartones.
The API key permissions modal silently dropped allowedCombos entries its Combo picker cannot render — routing-rule names such as rt-*, which matchesComboAccessRule() already honours. Stored entries rendered as zero selected, and clicking All then Restrict then Save persisted allowedCombos: [], which is deny-all for combo requests.
Those entries now survive the All toggle, are listed read-only under the combo list so the header count and the list agree, and are saved back verbatim. The UI does not learn routing-rule semantics (option 1 from the issue). The Allowed Combos section moves out of the frozen ApiManagerPageClient.tsx into its own component following the UsageLimitSettings pattern.
Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.
Thanks @pacocartones.
GET /v1/models with MODELS_CATALOG_PREFIX_MODE=canonical dropped every chat row of a provider whose registry alias is undefined (antigravity) or equal to its own id (agy, most built-ins). Each emission loop pushes alias/model only when includeAlias, and canonicalProviderId/model only when the ids differ — for a self-aliased provider both are the same string, so neither fired. #11918 fixed the class for custom nodes but not built-ins, and not the static loop. The alias row is now treated as the canonical row whenever the ids coincide, across the static, synced, custom and alias-backed loops; the canonical branch's !== alias guard is untouched, so dual and alias output cannot double up. Docs that described the omission as intended are corrected.
Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.
Thanks @pacocartones.
CircuitBreaker.execute() treated every resolved promise as a success, but handleChatCore() reports most upstream failures by resolving with { success: false, status: 5xx }. On the chat path that spurious _onSuccess() decayed failureCount right before the call site's _onFailure() for the same attempt, so a provider answering 503s indefinitely stayed CLOSED at failureCount: 1 and kept receiving traffic — the breaker was structurally unable to open. Combo dispatches hit the same cancellation through the shared per-provider breaker.
execute() now takes an optional per-call classifyResult; without it the resolved-means-success contract every throw-based caller relies on is unchanged. executeChatWithBreaker() passes ignore and the chat path accounts for the outcome exactly once where the request context lives, so a combo success is no longer counted twice.
Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.
Thanks @pacocartones.
The retryable chat_admission_busy 503 advertised a fixed Retry-After of 1s or 2s while the heavyweight lease it waits on is held for the entire SSE lifetime. Clients that honour the header — Codex CLI, agent fan-out — re-sent the same ~1 MiB /v1/responses body every second into a gate that could not have cleared, producing the queue_timeout retry storm that persisted even after OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT was raised.
ChatAdmissionController now tracks each live heavy lease's acquisition time and derives the hint from observed occupancy: the larger of the queue window the waiter already exhausted and the age of the youngest live lease, rounded up and capped at 60s. Both builders floor it at the historical 1s / 2s, so an idle gate answers exactly as before. Using the youngest rather than the oldest lease avoids a pessimistic hint when several slots are in flight.
Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.
Thanks @pacocartones.
The Leaderboard rendered apiKeyId.slice(0, 8)… under a column translated as "name". The route now enriches each entry with the key's display name — route-local, so the shared getTopN helper and the federation leaderboard stay id-only — and the page renders name ?? shortId with the full id in a title attribute. The lookup selects only id and name from api_keys, chunked at 200 ids, with unknown ids and blank names omitted; no key material leaves the DB layer.
Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.
Thanks @pacocartones.
The Profile page already rendered a streak card but fed it a hard-coded useState(0) with a "streak data comes from future API" note — while streaks.ts tracked per-key streaks all along and the MCP gamification_profile tool already returned them. GET /api/gamification/level now returns streak: { current, longest } next to level: the key's own streak with apiKeyId, the operator-wide maximum otherwise, matching the aggregate mode getAggregateXp uses (#3484). No new route, no OpenAPI change, no new i18n keys; a missing or zero streak keeps the card hidden exactly as before.
Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.
Thanks @pacocartones.
When a built-in provider's id or alias reserves the prefix of an existing OpenAI/Anthropic-compatible node — v3.8.50 added openference with alias of, shadowing nodes created earlier with prefix of — the runtime error `No active credentials for provider: openference` gave the operator nothing to act on. It now explains that the prefix routed to the built-in, names the shadowed node, and logs an AUTH warning. Precedence is unchanged and the lookup runs only on the credential-failure path when no connection was tried, so the hot routing path is byte-identical.
Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.
Thanks @pacocartones.
getDbInstance() ran PRAGMA journal_mode = WAL as the connection's first statement, before PRAGMA busy_timeout, and openSqliteDatabase() passes no driver-level timeout. A process opening the database while another closed its WAL connection — checkpoint plus WAL delete hold an EXCLUSIVE lock for a few hundred microseconds — therefore died with `database is locked` instead of waiting. That is the flake behind exclusive-connection-leases.test.ts on release/v3.8.51 runs 33525300898 and 33493797519 and on unrelated PR runs.
The second half is worse than the flake: isTransientProbeError matched /SQLITE_BUSY/ against error.message, but both drivers report the plain text `database is locked` and put the code in .code / .errcode. A transient lock during the corruption probe therefore took the corrupt-database path and renamed the file to storage.sqlite.probe-failed-… with "Manual recovery required". The probe now recognises the drivers' real BUSY/PROTOCOL/IOERR signals.
Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.
Thanks @pacocartones.
validateScoreChange() — the documented 1000 XP/min per-API-key limit plus the velocity anomaly check — was exported but never called, so the award path applied every XP delta unconditionally. It now runs before addXp; a rejected award is logged at warn level and skipped, and the fire-and-forget path never throws.
The second finding is the one that made the first invisible: getRecentXp's window query was inert. created_at is stored by the table default as YYYY-MM-DD HH:MM:SS and was compared lexically against a JS ISO string, so same-day rows never matched and the limit could not have tripped even if it had been wired. The window start is now computed in SQLite, matching the style computeZScore already used.
Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.
Thanks @pacocartones.
Four files embedded the U+0000 separator of a memo/group key as a raw NUL byte rather than the \\0 escape the codebase uses for the same idiom elsewhere. The runtime value is identical, but the raw byte trips the binary heuristics of git, GitHub and ripgrep: git diff --numstat reported `- -`, the introducing PRs rendered three of the files as "Binary file not shown", and rg silently skipped them in recursive mode. Rewritten as escapes, with a guard test keeping raw NUL bytes out of src/, open-sse/ and tests/.
Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.
Thanks @pacocartones.
getBestVisionModel() validates a configured fixedModel with hasUsableCredentialsForModel() before short-circuiting (#8430). auto / auto/* ids are virtual combos with no provider row, so that check always reported a confirmed false and the combo was silently discarded in favour of global auto-selection — it never got the chance to rotate its members. This mirrors the exemption the reroute guard in visionBridge.ts already carries; concrete fixedModel ids keep the #8430 fall-through unchanged.
Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.
Thanks @pacocartones.
The opt-in Codex quota auto-ping pinned gpt-5.1-codex-mini. OpenAI shut that model down on 2026-07-23 and the repo's own lifecycle registry already rejects it on the request path, but the scheduler never consulted that gate — every window slide sent a dead id, hit the 15-minute failure cooldown, and retried the same id forever. The ping model now resolves per tick from the provider catalog through isModelSelectable(), the same gate chatCore uses, with the registry import kept lazy because this module sits on the instrumentation boot path (#12074). When nothing is selectable the provider is paused before any throttle slot, usage read or executor call, with one warning per state change.
Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.
Thanks @pacocartones.
The least-used strategy ranked candidates by lastUsedAt alone, so after a 429 excluded the active account the replacement could be one that was merely oldest while still carrying its own backoff — it served a single request before the next one settled on a healthy account, the one-request detour with two cache misses reported on Codex. least-used now applies the backoffLevel tie-break the round-robin fallback branch already had, ahead of the existing never-used / oldest / priority order.
Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.
Thanks @pacocartones.
* fix(memory): point the rerank-providers dynamic import at the real db module
#11390 landed with a dynamic import of the localDb barrel, which #12052 had
already removed from the base (and which Hard Rule #2 forbids) — the API
Route Typecheck gate reds on the tip with TS2307. getCachedProviderNodes
lives in src/lib/db/readCache.
* chore(quality): ratchet the api-typecheck baseline down (163 stale entries gone)
Regenerated with --update on a faithful npm ci environment (the .113 box)
against the current tip plus the rerank-providers import fix — the gate now
reads OK at 289 pre-existing errors, all baselined. No new entries added.
Adds uncensored.com as two OpenAI-compatible providers mirroring UC's own surfaces: uc, the persona/subscription side over WebSocket with a durable Clerk credential minting a short-lived per-connect token (no API key, un-metered), as a full multimodal port — chat, tools, vision, doc-RAG, image, video, TTS; and uc-direct, the metered Developer API over REST with X-api-key. Same underlying models, two billing surfaces.
Reconciled on merge. 57 files conflicted; only seven carried UC content, the rest was drift from the older release line and took the tip's side.
- executors/index.ts: the tip has since refactored the executor map to lazy dynamic imports, so uc is registered in that shape. uc-direct needs no entry — it routes through the default OpenAI-compatible executor.
- imageGeneration.ts: the branch still carried the retired designerWeb import alongside ucImage; kept only the UC one.
- config/providers/index.ts, webSessionCredentials.ts and web-cookie.ts resolved additively against the MaxAI entries #11461 put on the tip an hour earlier.
- web-cookie.ts: the uc entry declared no serviceKinds, required since #11392, so provider validation would have thrown at load. Declared ["llm"]. uc-direct already declared it at the end of its own entry — an earlier pass of mine added a second one after id and TypeScript caught the duplicate (TS1117); the author's placement is what shipped.
Every count was measured against the merged tree rather than taken from the branch, and all three would have been wrong: reserved prefixes are 406, not 399; APIKEY_PROVIDERS is 237, not 234; providers are 355. PROVIDER_REFERENCE.md regenerated, the count updated across README/AGENTS.md/llm.txt and its 42 mirrors, package.json and 6 SVGs — every changed line in the protected surfaces is a digit substitution and nothing else, verified by masking digits and comparing the removed and added sets (90 lines each, identical). The executor-map golden snapshot went 134 -> 135.
The branch's file-size-baseline.json predates #12411's ratchet re-tightening and was discarded rather than merged; imageGeneration.ts (+12 for the uc-image format branch) was entered against the current baseline under a _rebaseline annotation, and no other cap moves.
Verified: typecheck:core clean, check:provider-consistency OK (271 REGISTRY entries, 355 canonical providers), check:docs-counts exit 0, check-file-size OK, check:cycles OK, 119/119 across the PR's test files, and 2/2 executor-map-golden.
Thanks @arminanton — two providers for two real billing surfaces, rather than one entry pretending to be both, is the right modelling.
MaxAI joins as a first-class signed provider: 13 chat models discovered live from /models/get_config plus 6 image models, routed through the standard /v1 endpoints with per-request X-Authorization signing, browserless onboarding, prompted tool-calling, vision input, image generation and document RAG.
Reconciled on merge — worth reading, because the branch forked 227 commits back and 77 files conflicted. Only five carried MaxAI content; the rest was drift from the older release line and took the tip's side, taking the diff from 113 files to 37 (then 93 as counted against the current base).
- executors/index.ts: the tip has since refactored the executor map to lazy dynamic imports, so MaxAI is registered in that shape rather than the branch's static import.
- imageRegistry.ts: kept only the maxai block. The branch still carried microsoft-designer-web, which #11754 retired.
- models/route.ts: the conflicting hunk was an unrelated Vertex/Anthropic URL change, not MaxAI — tip's side.
- volcengine agent-plan/coding-plan registries: git auto-merged both sides and produced a duplicated supportsVision key, which TypeScript rejects (TS1117). Removed.
One real integration break that only the combined state shows: the MaxAI entry declared no serviceKinds, which #11392 made required a few hours ago. Provider validation threw at load time and check:provider-consistency crashed outright. Declared ["llm"] — the image kinds derive from imageRegistry, per the convention in that PR's backfill.
Every count was measured rather than taken from the branch, and each would have been wrong: reserved prefixes are 402, not the 397 the branch computed from its stale 395 base; providers are 353, not 354. PROVIDER_REFERENCE.md regenerated, the count updated across README/AGENTS.md/llm.txt and its 42 mirrors, package.json and 6 SVGs — every changed line in those files is a digit substitution and nothing else, verified by masking digits and comparing the removed and added sets (90 lines, identical). The executor-map golden snapshot was regenerated: keyCount 133 -> 134.
The branch's file-size-baseline.json predates #12411's ratchet re-tightening, so it was discarded rather than merged — taking it would have silently undone that. The three files this PR grows (proxyFetch.ts +20 for the Windows/firefox_150 TLS profile, imageGeneration.ts +12, models/route.ts +48) were entered against the current baseline under one _rebaseline annotation; no other cap moves.
Verified: typecheck:core clean, check:provider-consistency OK (269 REGISTRY entries, 353 canonical providers), check:docs-counts exit 0, check-file-size OK, check:cycles OK, and 79/79 across the MaxAI suites plus 21/21 reserved-prefix and 2/2 executor-map-golden.
Thanks @arminanton — the provider work itself is thorough; it was the 227 commits of base that needed the attention.