* fix(providers): refresh uncloseai free-model roster after upstream rotation
hermes.ai.unturf.com rotated its lineup: /v1/models now serves exactly one
model (Lorbus/Qwen3.6-27B-int4-AutoRound, vllm, max_model_len 65536) while
every previously catalogued id (adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic,
qwen3.6:27b, gemma4:31b) returns 404 on /v1/chat/completions. Requests routed
through the static seed failed although the provider itself is healthy — a
live completion against the new id succeeds.
- registry seed: replace the three dead ids with the live one (+contextLength)
- FREE_MODEL_BUDGETS: 3 rows -> 1 (catalog totals 443 -> 441; counts synced in
README and free-tier-budget.svg)
- noauth authHint: verified-live-model pointer updated; PROVIDER_REFERENCE.md
regenerated
- regression test pins the live id and forbids the retired ids in both the
registry seed and the free catalog
Verified live on 2026-09-15 against https://hermes.ai.unturf.com/v1/models
and /v1/chat/completions.
* docs(providers): sync free-tier entry count after uncloseai merge
The uncloseai roster refresh (3 entries -> 1) dropped the live free-tier
catalog total from 491 to 489 once merged with the current release tip.
README.md and free-tier-budget.svg still quoted 491 after the merge;
update both to the real count so check:docs-counts-sync stays green.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
---------
Co-authored-by: anon <anon@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* security(deps): pin and verify tls-client native artifacts
* docs(changelog): link tls-client provenance PR
* security(runtime): harden TLS and public error boundaries
* security(runtime): resolve CodeQL error-boundary findings
* security(lmarena): close public stream error boundary
* fix(lmarena): normalize public error statuses
* chore(quality): rebaseline chatCore.ts for the surviving log-boundary hardening
open-sse/handlers/chatCore.ts 6219 -> 6287. This is the one part of #11742 that
survived the rebase: sanitizeErrorMessage on the plugin onError hook, on the
semaphore-timeout path and on failureMessage before it reaches console.log and
the call log, sanitizeUpstreamDetails on the malformed-response log, and
getSafeErrorMetadata + try/catch where hostile (Proxy) metadata could throw.
That is the LOG boundary, which is broader than Hard Rule #12 (responses). The
rest of the PR was dropped as already landed on the tip.
* test(catalog): pin the 2026-09-02 free-tier re-audit facts for gemini, ollama-cloud, groq, nara and mistral
* feat(providers): add xKiro (5M tokens/day free plan, 39 pinned free models)
* fix(catalog): re-audit gemini, ollama-cloud, groq, nara and mistral against official pages
* docs(providers): xKiro in the provider reference, counts and free-tier headline (~1.66B)
* fix(catalog): restore the console-verified Mistral 1B pool and harden its regression test
* docs(free-tiers): move headline to the re-audited ~1.50B and refresh pool counts
* chore(free-tiers): retire stale Groq free-tier text and preset model; fix catalog header
* docs(providers): align the remaining visible provider/executor counts with the catalog
* docs(providers): align remaining free-tier count chips and metadata
* docs(free-tiers): state the evidence-comment rule honestly and retire the last "14.4K RPD" Groq texts
* docs(free-tiers): retire the stale Gemini onboarding quota text
* docs(free-tier): refresh catalog-entry counts to 442 after base sync
* docs(providers): re-sync provider and free-tier counts after merging release/v3.8.51
* docs(providers): re-sync residual counts after the base merge
* docs(free-tiers): restore README spacing lost in the merge and re-sync the guide counts
* docs(free-tiers): re-sync numbers after merging release/v3.8.51 (Cerebras reclassified upstream)
* fix(docs): keep the NaraRouter plans endpoint out of the API-path checker; rebaseline gateways.ts (+3)
* chore(quality): rebaseline gateways.ts file-size cap for the xKiro entry (+20)
---------
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
* fix(providers): remove the chipotle/pepper provider (#13131)
amelia.chipotle.com (the reverse-engineered Amelia chat-widget backend
chipotle/pepper-1 talked to) now returns 404 on every route, including
root, from its Azure Application Gateway — confirmed live 2026-09-15.
This regressed from a WS handshake timeout (#4037, June 2026) to a
fully decommissioned host, so the upstream protocol cannot be fixed.
Owner decided to retire the provider entirely (Option B), following
the phind/kluster quiet-removal precedent: no REMOVED_PROVIDERS.md
entry (reserved for operator takedowns), just a one-line note under
FREE_TIERS.md "Removed / no free tier".
Removed every surface: executor, registry entry, executors/index.ts
and providers/index.ts wiring, noauth provider catalog entry,
ProviderIcon generic-fallback set, the autoCombo exclusion-list
comment, the chipotle_error code from the sanitizer allowlist,
PROVIDER_REFERENCE.md (regenerated), and every doc/test reference.
Regression test: tests/unit/issue-13131-chipotle-provider-removed.test.ts
asserts the provider is fully gone from the executor registry, the
provider REGISTRY and the noauth catalog, and that the executor module
no longer resolves — not a live-network repro (flaky/third-party).
Several existing tests used "chipotle" only as a generic noAuth-provider
example (proxy scoping, error classification, onboarding, fallback
text) with no chipotle-specific behavior under test; those were
re-pointed at another still-existing noAuth provider
(cloudflare-playground / duckduckgo-web) rather than weakened.
* test(providers): document the agnes-cn/chipotle count coincidence (#13131)
provider-node-reserved-prefix.test.ts's REGISTRY id+alias walk was
already red on the base tip (414 vs. expected 412) from agnes-cn
(#13399, +id/+alias). Removing chipotle's REGISTRY id/alias in this
PR nets it back to 412, making the test pass again without a numeric
edit — record why in a comment so it doesn't read as an untracked
coincidence later.
Lands the combined-board reconciliation of today's JxnLexn wave as one follow-up: i18n fill for #12471/#13555's new keys (real vi translations), free-tier count 446→452, file-size rebaseline for #13556. check-new-key-coverage PASS; only the three pre-existing file-size reds remain.
Batch 3 (last) of the locale-expansion plan: ha, yo, ig, am, uz, ka, hy on every surface — dashboard catalog, docs mirror (22-file core + llm.txt + CHANGELOG), CLI catalog, README flag block, locale tables and 🌐 language bars. Also closes the key gap the batch-1 (43 keys) and batch-2 (10 keys) catalogs carried since their base merges, fixes the Igbo "Model" copy and allowlists the Uzbek cognate. Translation-ratio baseline covers 65 locales.
⚠️ base-red inherited: #12732
Removes the obsolete Together $25 signup credit (`together-signup-credit`, 25M one-time tokens) from `FREE_MODEL_BUDGETS` and updates the Together notes in `FREE_TIERS.md` (#12526). Approved by the maintainer. Chosen over #12766, which targeted `main` and only touched the doc.
Maintainer additions: propagated the catalog change to every derived number instead of hand-estimating it. The regenerated budget card (`gen-budget-card-svg.mjs`) computes first month ~2.07B (the doc said ~2.08B), 443 catalog entries (436 active + 7 discontinued) and one-time credits ~601M. README, `FREE_TIERS.md`, `FREE-TIERS-GUIDE.md` (Together row removed) and `docs/diagrams/free-tier-budget.svg` were aligned to those values, and Prettier-formatted. `check:docs-counts` and the budget-card, docs-counts and free-catalog tests pass (99 cases).
Validated in one consolidated batch of this series (37 PRs boarded together on `release/v3.8.51`): `typecheck:core`, `check:open-sse-typecheck` and `check:dashboard-typecheck` clean; ESLint clean on every changed file; file-size, complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync and migration-numbering gates green (only the pre-existing `open-sse/utils/stream.ts` file-size red remains, inherited from the base); 3,743 focused `node:test` cases plus 34 vitest cases green.
Thanks @KooshaPari!
Batch 2 of the locale expansion across the dashboard catalog, docs mirrors, CLI catalog, README, locale index and the site. 51 → 59 locales.
Also: the translator restores the ICU literal escape around angle placeholders, and the docs chunker splits oversized sections before translating.
⚠️ base-red inherited: #12732 — the eight red checks fail identically on unrelated PRs cut from the same base (e.g. #13197); every gate is green locally after merging the base.
Merged after reconciling against the tip. The one conflict was `docs/reference/PROVIDER_REFERENCE.md`, a generated file — regenerated with `npm run gen:provider-reference` (358 unique IDs) rather than hand-merged.
The three base-reds this PR targets, re-checked on the reconciled tree:
- `check:docs-counts`: **exit 0** — provider count 356 → 358 in AGENTS.md, llm.txt, the i18n mirrors and the SVG diagrams was its last red
- `check:open-sse-typecheck`: OK, 0 errors
- `check:agent-skills-sync`: exit 0 (`skills/cli-tunnel/SKILL.md` → `tunnel create [type]`)
- `autoCombo.test.ts` under the mcp vitest config: 63/63
- ESLint over the changed files: exit 0
AGENTS.md, llm.txt and SKILL.md are agent-instruction surfaces; the operator approved them for this PR explicitly.
Estender o gate de contagens para headings, rankings, catálogo, pesos, quality gate e o diagrama de scoring é exatamente o tipo de trabalho que evita a classe inteira em vez de um caso.
Falo por experiência desta campanha: o `check:docs-counts` caiu **duas vezes** hoje pela mesma causa — contagem de migration escrita à mão em três arquivos mais 41 mirrors, desatualizando a cada migration nova (#12970 e #13209). Cada superfície que este PR passa a cobrir é uma que deixa de virar base-red na mão de quem vier depois.
Revalidei sobre o tip: **19/19**, `check:docs-counts-sync` com 0 drifts, `check:docs-all` PASS, `check:doc-links` PASS.
**Integração:** dois conflitos.
1. `scripts/check/check-docs-counts-sync.mjs` — o bloco de leitura de fatos conflitou com os imports de free-tier que entraram pelo #12786/#12744 nesta campanha. Aditivo, os dois conjuntos ficaram.
2. `docs/diagrams/auto-combo-scoring.mmd` — o seu rótulo dizia `reliability (0.0000)`, mas o #12731 mergeou horas antes e passou a dar peso de reliability a todo mode pack. Ficou o rótulo do tip, `reliability (0.0000 DEFAULT, 0.03 packs, 0.04 reliable)`, que é o número real agora.
Batch 1 of the locale expansion: Greek, Croatian, Serbian, Lithuanian, Estonian, Latvian, Slovenian, Maltese and Irish across the dashboard catalog, docs mirrors, CLI catalog, README, locale index and the site. 42 → 51 locales.
Also fixes the ICU literal escape the translation backend dropped around angle placeholders, four translations that invented or renamed a placeholder, the language bars that linked to mirrors that do not exist, and the migration count drift (171 → 172).
⚠️ base-red inherited: #12732 — the four unit shards and Fast Quality Gates fail identically on unrelated PRs cut from the same base.
Validado numa worktree combinada com a onda de roteamento/free-tier desta leva sobre `release/v3.8.51`: typecheck:core limpo, check-api-typecheck OK (288), check-file-size OK após rebaseline, 84/85 nos testes focados.
`reliability-first` que não pesava reliability é o defeito mais constrangedor possível num mode pack, e a causa é clara: `modePacks.ts:13` substituía os defaults por inteiro. Financiar os novos pesos com `quota`/`costInv`/`tierPriority` mantendo cada pack somando 1.0 é a parte que exige cuidado e você fez.
Manter `quality-first` em 0.03, igual ao default, para que ele não fique mais fraco que `balanced`, é o tipo de detalhe que só aparece quando se checa a tabela inteira.
**Integração:** conflitou com o #12794 no `computeSnapshotWeights`; os dois compõem e ambos ficaram.
Contadores de docs fora de sincronia com o código, aprovado pelo dono em chat por tocar `AGENTS.md` e `skills/cli-tunnel/SKILL.md` (Hard Rule — superfície de instrução de agente). Nenhuma instrução mudou.
`Docs Gates` acusava 6 drifts STRICT. Dois vieram da minha leva de 16 PRs: migrations 169 → **171** (#12707 trouxe a 173, #12867 a 174) e estratégias de roteamento 19 → **20** (#12789 registrou a `quota-weighted`). Contei os arquivos em vez de confiar na memória: `ls src/lib/db/migrations/*.sql | wc -l` → 171.
Os 41 mirrors de `docs/i18n/*/llm.txt` foram regenerados com `scripts/i18n/sync-llm-mirrors.mjs` — o gate exige cópia exata da raiz.
O outro braço, `check:agent-skills-sync` acusando `GENERATED: + cli-tunnel`, era herdado (o corpo do #12866 já o registrava). O `SKILL.md` commitado documentava `tunnel create [type]`, um argumento que a CLI **não aceita** — conferido em `bin/cli/commands/tunnel.mjs:21`, que declara `.command("create")` puro. Saída do gerador, não escrita à mão.
| gate | antes | depois |
|---|---|---|
| `check:docs-counts` | 6 drifts STRICT | **0** |
| `check:docs-sync` | FAIL — 41 mirrors divergentes | **PASS** |
| `check:agent-skills-sync` | `+ cli-tunnel` | **UNCHANGED: 46 skills** |
* test(catalog): pin the 2026-09-02 free-tier re-audit facts for gemini, ollama-cloud, groq, nara and mistral
* fix(catalog): re-audit gemini, ollama-cloud, groq, nara and mistral against official pages
* fix(catalog): restore the console-verified Mistral 1B pool and harden its regression test
* docs(free-tiers): move headline to the re-audited ~1.50B and refresh pool counts
* chore(free-tiers): retire stale Groq free-tier text and preset model; fix catalog header
* feat(catalog): eligibilityGate field and gatedRecurringTokens total
* docs(free-tiers): state the evidence-comment rule honestly and retire the last "14.4K RPD" Groq texts
* feat(check): docs-counts gate validates the eligibility-gated free-tier figure
* fix(docs): budget card reads computeFreeModelTotals() instead of regex-parsing the catalog
* docs(free-tiers): retire the stale Gemini onboarding quota text
* feat(radar): carry eligibilityGate through the feed schema, the merge and the summary API
* feat(dashboard): show the eligibility-gated free-tier figure apart from the headline
* docs(free-tier): refresh catalog-entry counts to 442 after base sync
* feat(catalog): ModelScope as the first eligibility-gated pool; document the gated bucket and how we count
* docs(free-tiers): restore README spacing lost in the merge and re-sync the guide counts
* docs(free-tiers): correct the unsummed-catalog comparison figure to the current catalog
* docs(free-tiers): re-sync numbers after merging release/v3.8.51 (Cerebras reclassified upstream)
* docs(free-tiers): re-sync numbers after merging PR1 (Cerebras reclassified upstream)
* fix(docs): keep the NaraRouter plans endpoint out of the API-path checker; rebaseline gateways.ts (+3)
* fix(catalog): keep eligibility-gated rows out of every headline-adjacent figure
The eligibility gate was honored by the steady headline and the pool count, but
three adjacent figures still counted gated rows: the credit reductions feeding
steadyWithRecurringCreditsTokens/firstMonthRealisticTokens, the uncappedProviders
list ("permanently free, no cap"), and the docs gate's free-forever provider set,
which was built from freeType alone.
- computeFreeModelTotals: filter !isGated in the recurring-credit, one-time-credit
and uncapped predicates; gatedProviders semantics unchanged (steady rows only).
- check-docs-counts-sync: exclude eligibility-gated rows from the FOREVER set,
which moves the live free-forever count 53 -> 52 (the base's value). README,
promise-pillars.svg and FREE-TIERS-GUIDE re-synced.
- gen-budget-card-svg: skip gated one-time credits like the totals do, and fail
loudly on `--out` without a path.
- Tests: gated one-time credit does not move firstMonthRealisticTokens; a gated
uncapped row is not in uncappedProviders; shipped gated rows carry no credit
tokens; the committed budget card is byte-identical to a fresh generation.
* test(catalog): allow eligibilityGate in the no-per-row-rating key allowlist
The allowlist landed on the base with #12318, after this branch's field was designed;
eligibilityGate says who may claim a quota, not how much a row can be trusted.
---------
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: diegosouzapw <diegosouzapw24@gmail.com>
* test(catalog): pin the 2026-09-02 free-tier re-audit facts for gemini, ollama-cloud, groq, nara and mistral
* fix(catalog): re-audit gemini, ollama-cloud, groq, nara and mistral against official pages
* fix(catalog): restore the console-verified Mistral 1B pool and harden its regression test
* docs(free-tiers): move headline to the re-audited ~1.50B and refresh pool counts
* chore(free-tiers): retire stale Groq free-tier text and preset model; fix catalog header
* docs(free-tiers): state the evidence-comment rule honestly and retire the last "14.4K RPD" Groq texts
* docs(free-tiers): retire the stale Gemini onboarding quota text
* docs(free-tier): refresh catalog-entry counts to 442 after base sync
* docs(free-tiers): restore README spacing lost in the merge and re-sync the guide counts
* docs(free-tiers): re-sync numbers after merging release/v3.8.51 (Cerebras reclassified upstream)
* fix(docs): keep the NaraRouter plans endpoint out of the API-path checker; rebaseline gateways.ts (+3)
---------
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Validado sobre o tip de release/v3.8.51 — e o PR ficou completo depois que o autor adicionou a tabela de preços.
O que fazia o teste falhar antes não era a lista free (que o PR já tinha corrigido em `LEGACY_FREE_PROVIDERS` e `tierDefaults.json`), e sim que `classifyTier` cai no ramo cost-based e todos os modelos Cerebras estavam declarados com `input: 0, output: 0` — $0/M ≤ threshold devolve 'free' de qualquer jeito. A tabela de preços resolve isso na raiz.
Confirmei o `gpt-oss-120b` a $0,35/$0,75 de forma independente contra a fonte pública, o que corrobora o resto da tabela. **4/4** no teste-guarda e **25/25** somando free-tier-catalog e free-models; typecheck:core limpo. Obrigado, @HouMinXi.
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 #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.
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.
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>
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.
The weight table said stability accounts for "low latency stdDev / error rate". Grep errorRate in scoring.ts and you find it declared on ProviderCandidate and read nowhere — while combo.ts pulls 24 hours of usage history behind a ten-sample floor, falls back to real-time metrics, and hands every candidate an errorRate the scorer ignores. Two candidates, one failing 1% of calls and one failing 99%, scored identically at 0.459486.
This declares reliability as a sixteenth factor: 1 - failureRate, using the same formula, field precedence and rate-bounding speedRanking.ts already applies, so a corrupt reading means "nothing observed" rather than "fails every call". It ships at weight 0, leaving the ranking unchanged to the digit — the honest default, since which weight this deserves is a product call backed by traffic the author does not have. Two declared-but-silent factors already ship (cacheAffinity, resetWindowAffinity), so the pattern is not new. The stability row now describes what that factor actually computes: latency variance.
The rest is the mechanical 15 → 16 across nineteen documents and the forty-two llm.txt mirrors — sourced from check:docs-counts rather than a grep, the first real use of the gate #12316 extended.
Protected-surface note: this PR touches AGENTS.md, llm.txt and its 42 mirrors, and skills/omni-combos-routing/SKILL.md. Every changed line in those 45 files is a digit substitution and nothing else — masking all digits makes the removed and added lines identical, with no sentence added, removed or reworded. Reviewed and approved on that basis before merging.
Verified on the author's rebased head: check:docs-counts green (the gate that now enforces the count this PR moves), typecheck:core clean, and 71/71 focused tests across scoring-reliability-factor, combo-scoring-weights-schema-coverage, check-docs-counts-sync, lkgp-enabled-context, intelligent-routing-options and the combo-matrix auto integration suite.
Thanks @maxmad64bis — shipping the factor at weight 0 and saying plainly that the weight is someone else's call is the right way to land this.
mcp-tools-107.{mmd,svg} -> mcp-tools.{mmd,svg} and
auto-combo-12factor.{mmd,svg} -> auto-combo-scoring.{mmd,svg}: filenames that
embed a canonical count fossilize the moment the count moves (107 -> 110,
12 -> 15 factors already happened). All referencers updated — diagrams index,
AUTO-COMBO.md (+ its pl/zh-CN/zh-TW mirrors' links) and the check:docs-counts
file list.
Fase 2 da auditoria código×docs 2026-08-31: ~90 divergências corrigidas em README/llm.txt(+42 espelhos)/SVGs/AGENTS.md/25+ docs; correções semânticas (breaker 8/12/2 + DEGRADED, webhooks sem eventos fantasma, ROUTE_GUARD_TIERS completo, API_REFERENCE sem fantasmas, reasoning 200); gate check:docs-counts endurecido (versão em prosa, patterns anti-evasão, superfície +llm.txt/mcp-server/omni-mcp/tier-flow) +5 testes; fonte do gerador de agent-skills corrigida (107/32 → 110/33) e mesma família varrida do Copilot prompt, 39 locales, skills/README, CONTRIBUTING e 2 guias.
* fix(ci): clear the base-reds the 2026-08-30 afternoon merge batch left on release/v3.8.51 (round 5)
- docs-counts / check-docs-counts-sync test: #12103 (Perplexity Agent) made it 352
providers; README, AGENTS.md, llm.txt (+42 i18n mirrors), package.json description
and the 4 README diagrams still said 351.
- api-route-typecheck: #11971 passes a third `{ featureEnabled }` argument to
appendNoThinkingVariants() that the helper never accepted (TS2554 — and the flag
silently did nothing); the helper now honours it. src/lib/skills/interception.ts
narrowed a mapped object with a `Record<string, string>` predicate (TS2677) —
predicate typed with the actual element shape.
Gates: check:docs-counts OK (test 28/28), check:docs-sync PASS, check:api-typecheck
OK (289 frozen). Refs #12103, #11971
* docs(env): document RATE_LIMIT_EXECUTION_MAX_WAIT_MS (#12027 added it to .env.example only)
* fix(ci): round 5b — freeze the react-hooks compiler-rule violations, align 7 tests to merged contracts
No new ESLint warnings: the exact CI command (lint:json --max-warnings 0) reports 278
problems on the tip — 226 from eslint-plugin-react-hooks 7 compiler rules
(set-state-in-effect 167, immutability 36, refs/static-components/purity/
preserve-manual-memoization) that were masked until the lockfile change of
dfc84ba030 invalidated the ESLint cache, plus 46 no-explicit-any in
tests/unit/call-log-cap.test.ts (#12026). Velocity phase: frozen with
`eslint --suppress-all` (+668 suppressions); the 5 now-unused
`eslint-disable react-hooks/immutability` directives and one unused import removed.
Verified: lint:json --max-warnings 0 → 0 problems.
Tests aligned to contracts merged this afternoon (all reproduced red on the pure tip):
- providers-constants-split: 235 → 236 (Perplexity Agent, #12103)
- sse-auth: a forced pin outside allowedConnections now yields no credential
instead of silently falling back (#12080)
- with-chat-admission-10786: withInjectionGuard(postHandler, { logger: null }) (#12117)
- hard-session-lease-bypass-inventory: classify src/app/api/oauth/codex/import/route.ts (#12116)
- usage-service-hardening: OpenCode Go official usage API shape (#12124)
- i18n placeholder parity: apiManager.restrictedToConnections rewritten as a plain
ICU plural (`{count, plural, one {# connection} other {# connections}}`) in en,
vi, pt-BR and the 40 __MISSING__ mirrors — the parity extractor counts every
`{word}` including the old literal `{s}`
Refs #12103, #12080, #12117, #12116, #12124, #12026
* fix(ci): run the ESLint warnings job on the box with an 8 GB heap; reserved-prefix set 398 → 400
The cold full lint with the react-hooks 7 compiler rules is killed on the 7 GB hosted
runner with no message (status null → exit 1, JSON never written) — it only looked
green while the ESLint cache was warm. tests/unit/provider-node-reserved-prefix.test.ts
aligned to the two prefixes the afternoon batch registered (#12103).
* test(ci): document the lint-guard runner exception; #9147 event-loop gap 400 → 800 ms
quality-rail-gate-membership pinned lint-guard to ubuntu-latest; the cold full lint is
OOM-killed there, so the job now runs on omni-light with an 8 GB heap — the test keeps
fast-gates pinned and asserts the documented exception. With the catalog at 352
providers the hosted shards measure 410–633 ms gaps on 9147-catalog-eventloop-yield
(3 runs); 800 ms still fails a true pin. Re-tighten with the v4.0 catalog split.
* chore(quality): summarize the ESLint report on failure — a red lint:json printed nothing
--format json --output-file swallows every problem; a red 'No new ESLint warnings' job
gave zero output (three blind debugging rounds in #12144), and a killed process (OOM,
status null) was equally silent. On any non-zero exit the runner now prints the problem
count and the first 60 'file:line rule — message' lines from the report.
* chore(lint): freeze react-hooks/immutability for the 5 UI test harnesses in the suppressions file
The rule fires for these files in CI but not locally (compiler analysis divergence),
so the inline eslint-disable directives read as 'unused directive' warnings locally.
A suppressions entry is symmetric: suppressed where the rule fires, tolerated as
unpruned (--pass-on-unpruned-suppressions) where it does not. Found via the new
lint:json failure summary.
release/v3.8.51 retired Raycast, Hailuo, Qwen Web, Designer Web and Felo and
added migrations 163–168 without touching the numbers README, AGENTS.md,
llm.txt (and its 42 mirrors), package.json and the README diagrams quote:
351 providers (was 357/353/350), 166 migrations (was 160). The strict
docs-counts gate was already red on a pristine release/v3.8.51; the v3.8.50
sync-back's release-green pass surfaced it.
Rebased onto the current release/v3.8.51 tip as part of a combined provider-retirement/provenance merge batch (Designer Web, Felo Web, Runtime, GPL-derived removal, Qwen Web already landed). Large conflict set (this is the biggest PR in the batch — the common ChatGPT Web provider touches chat, images, count-tokens, session leases, and combos). Conflicts resolved:
- `open-sse/config/providers/registry/chatgpt-web/*`, `open-sse/executors/chatgpt-web*`, `open-sse/handlers/imageGeneration/providers/chatgptWeb.ts`, and their tests: kept deleted, matching the PR's stated scope.
- `open-sse/config/providers/registry/minimax/web/index.ts`, `open-sse/handlers/imageGeneration/providers/geminiWeb.ts`, `open-sse/executors/gemini-web.ts`'s stale image-mode branch: base-drift collisions against already-merged sibling retirements (#11691, #11708) — kept deleted / dropped the dead code, since this PR's own branch forked before those merged.
- `src/shared/constants/reservedProviderPrefixes.ts`, `open-sse/executors/index.ts`, `executorProxy.ts`, `virtualFactory.ts`, `autoStrategy.ts`, `src/lib/db/providers.ts`, `src/sse/handlers/chat.ts`: combined the Designer + Runtime (Felo/Qwen) + common-ChatGPT-Web retirement guard calls at each shared chokepoint — compute-once-then-OR pattern, consistent with prior combinations in this batch.
- `src/sse/services/model.ts` / `src/sse/handlers/chatHelpers.ts`: adopted this PR's new `getModelInfoOrRetirementResponse()` central wrapper (a real improvement over ad-hoc try/catch), and extended it to also catch the Designer + Runtime retirement errors it didn't originally cover, so the consolidation doesn't regress the other two mechanisms.
- `src/app/api/v1/images/edits/route.ts`: this PR moved the retirement check earlier (before `enforceApiKeyPolicy`) but left the old later call+catch block in place from base drift — removed the now-redundant duplicate `resolveImageRouteModel()` call and merged the Designer catch into the earlier one.
- `open-sse/config/imageRegistry.ts`, `tests/snapshots/executors/executor-map.json` (`keyCount` recomputed to 133), `tests/snapshots/provider/translate-path.json`: same "both sides inserted a different retired provider at the same slot" pattern — resolved by dropping both.
- `tests/unit/chatcore-executor-proxy.test.ts`, `provider-node-reserved-prefix.test.ts`, `combo-auto-candidate-expansion.test.ts`, `messages-count-tokens-route.test.ts`, `virtual-auto-combo.test.ts`: split into independent per-mechanism test blocks (established pattern); `virtual-auto-combo.test.ts`'s old "includes cookie web-session providers" positive-inclusion test (which used chatgpt-web as its example) was retired along with the provider and replaced by this PR's negative-exclusion test for the same slot.
- `docs/architecture/ARCHITECTURE.md`, `CODEBASE_DOCUMENTATION.md` (+ 4 i18n mirrors), `README.md`, `FREE-TIERS-GUIDE.md`, `docs/diagrams/free-tier-budget.svg`, `docs/screenshots/free-tier-budget-card.svg`, `docs/reference/PROVIDER_REFERENCE.md`: recomputed every stale count from the real merged state — 104 executors (`countFiles` gate logic), 351 providers (regenerated via `gen:provider-reference`), 152/351 `hasFree` entries, 445/438/7 free-tier catalog rows, 13 ToS-avoid providers, budget-card regenerated via its real generator script. One doc conflict (`oauth/` module list) needed picking HEAD's side specifically — theirs still listed the already-removed `raycast` module instead of the real `openference`.
- `config/quality/test-masking-allowlist.json`: additive merge of the PR's 17 `_deletedWithReplacement` entries alongside the batch's existing ones (one real duplicate-key mistake in my first pass, caught and fixed via a `object_pairs_hook` duplicate-key check before finalizing).
Also fixed two real, unrelated-to-my-merge issues surfaced by the focused suite:
- `tests/unit/resolve-web-provider-host.test.ts`: the PR's own test had a typo — it asserted `perplexity-web`'s resolved host as `"perplexity.ai"`, but the provider's registered `website` is `"https://www.perplexity.ai"` and the resolver returns the URL's `host` verbatim (no www-stripping), so the correct value is `"www.perplexity.ai"` (consistent with the same test's own `url` assertion).
- `tests/unit/hard-session-lease-bypass-inventory.test.ts`: this golden call-site inventory was already stale on the pristine post-#11713 tip (confirmed via a throwaway probe worktree) — `src/lib/db/providers.ts`'s 3 connection-fallback sites and a third `src/app/api/providers/route.ts` site were never added to the golden list by the earlier-merged #11698/#11720 PRs. Updated it to the real current inventory (dated inline comments explain each delta and which PR introduced it), plus this PR's own legitimate deltas (image-edits duplicate-call removal, `ChatGptWebExecutor.execute()` site removed).
Focused suite green (433/433 across executor-proxy, reserved-prefix, hard-session-lease-bypass-inventory, resolve-web-provider-host, retirement/runtime-block/source-retirement/management-retirement/image-handler-retirement, migration-168, combo-auto-candidate-expansion, virtual-auto-combo, executor-map-golden and siblings), plus `typecheck:core`, `check-file-size`, and `check-changelog-integrity` clean. Thanks for the thorough provenance-hold retirement work — appreciated.
Rebased onto the current release/v3.8.51 tip as part of a combined provider-retirement/provenance merge batch (Designer Web, Felo Web, Runtime, GPL-derived removal all landed together already). Conflicts resolved:
- `src/shared/constants/providerRetirement.ts`: add/add conflict — combined `felo-web`/`felo` (already-merged) with `qwen-web`/`qw` into one `RUNTIME_RETIRED_PROVIDER_IDS` set, kept both `assertRuntimeProviderAvailable`/`assertRuntimeModelProviderAvailable` helpers.
- `open-sse/config/providers/registry/minimax/web/index.ts`: modify/delete — kept deleted (file is hailuo-web's registry entry, already retired by #11691; this PR's own change to it was just a comment reword on a since-removed target).
- `open-sse/executors/index.ts`, `executorProxy.ts`, `virtualFactory.ts`, `autoStrategy.ts`, `model.ts`, `chat.ts`, `chatHelpers.ts`, `auth.ts`, `src/lib/db/providers.ts`, `reservedProviderPrefixes.ts`: combined the Designer + Runtime (Felo + Qwen) retirement guard calls at each shared chokepoint — compute-once-then-OR pattern, consistent with the prior Designer+Felo combination.
- `src/shared/constants/providers/web-cookie.ts`, `tests/snapshots/provider/translate-path.json`, `tests/snapshots/executors/executor-map.json`: both sides had inserted a different retired provider (qwen-web vs. already-retired raycast/hailuo-web) at the same dict position — resolved by dropping both. `executor-map.json`'s `keyCount` recomputed to 135 (matches actual merged `entries`).
- `tests/unit/chatcore-executor-proxy.test.ts`, `tests/unit/provider-node-reserved-prefix.test.ts`: split into independent Felo/Qwen test blocks (established pattern for coexisting retirement-mechanism tests); recomputed `RESERVED_PREFIX_COUNT` to 398 (Designer+Felo+Qwen tombstones on top of the post-#11691 REGISTRY, verified via direct module evaluation, not hand-derived).
- `config/quality/test-masking-allowlist.json`: additive merge of Qwen's `_deletedWithReplacement` entries alongside Designer's.
- `README.md` + all `docs/i18n/*/README.md` mirrors, `docs/getting-started/FREE-TIERS-GUIDE.md`, `docs/reference/FREE_TIERS.md`, `docs/diagrams/free-tier-budget.svg`, `docs/screenshots/free-tier-budget-card.svg`: recomputed the free-tier catalog counts (447 entries / 440 active / 7 discontinued) from the actual merged `freeModelCatalog.data.ts`, regenerated the budget-card SVG via its real generator (`scripts/research/gen-budget-card-svg.mjs`), and dropped the retired Qwen quick-start row / QWEN MODELS section from every i18n README (identical unlocalized block across all 34 locales).
- Also fixed a duplicate-import merge artifact in `src/lib/db/providers.ts` (`isRuntimeRetiredProviderId` imported twice) caught by `typecheck:core`, and rebaselined `file-size-baseline.json` for the combined retirement-guard growth (`virtualFactory.ts` +3, with justification).
Focused suite green (345/345 across executor-proxy, reserved-prefix, migration-167, qwen-web-retirement, virtual-auto-combo, web-cookie/session, executor-map-golden and siblings), plus `typecheck:core` and `check-file-size`/`check-changelog-integrity` clean. Thanks for the provenance-hold retirement work — appreciated.
Merged via /merge-batch (v3.8.51 provenance sweep). Boarded and validated together with the batch's other retirement PRs in a combined worktree — full gate suite green. This PR's conflicts (against #11720's Designer retirement, both introducing a retirement-guard mechanism across executors/index.ts, executorProxy.ts, providers.ts, reservedProviderPrefixes.ts, auth.ts, chat.ts, chatHelpers.ts, model.ts) were reconciled by combining both guards at every chokepoint, with the shared reserved-prefix count recomputed (not guessed) at 400. Re-validated with this PR's own 72 node:test + 20 vitest focused tests, all passing, and pushed before merge. Thank you.
Merged via /merge-batch (2026-08-26, v3.8.51). Boarded no worktree combinado; validação única: typecheck/complexity/cognitive-complexity/file-size/changelog verdes, lint nos mesmos 228 achados pré-existentes confirmados contra o tip puro, testes focados passando. Obrigado pela contribuição.
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
Merged into release/v3.8.51 via batch validation: xquik provider suites green on the combined tree (193 node:test assertions incl. your 7 new cases), check:provider-consistency OK (353 canonical providers), static gates green. Well-scoped fallbackOnly X-provider with clean citation building — thanks @kriptoburak!
Retargetado para release/v3.8.51 (release/v3.8.50 está congelada — freeze issue #11439). Validado em lote combinado (batch-0824h2, junto de #11435/#11436/#11437) contra o tip de release/v3.8.51: typecheck:core limpo, gates estáticos OK, 127/127 testes focados passando.
Investigação sólida com repro real via container isolado, três causas independentes identificadas e corrigidas com testes de regressão dedicados para cada uma. Obrigado pela contribuição!
Merged after conflict resolution: the 5 conflicting test files were the base-red drains that #11201 already landed on the tip — kept the tip versions; the feature content is untouched. Validated on the combined batch board + this branch: codex-app-server + codex-gpt56-catalog 25/25, typecheck:core clean, docs-counts green (351 providers), provider-consistency 268/351/0. The opt-in codex-app-server transport (JSON-RPC-over-WS, turn/completed-awaited close, Responses SSE bridge) leaves the default codex path untouched. Thank you @arminanton — a 3.4k-line transport with the docs wave and tests to match!
Merged after count reconciliation: the branch's regenerated docs claimed 57 free forever / 157 migrations from its older base; gate-verified values on the current tip are 56 free forever (Logfare carries a Free badge via gateways.ts freeNote but has no freeModelCatalog per-model entries, so the live-code counter stays at 56) and 159 migrations — the README/SVGs now match the check:docs-counts output exactly. provider-consistency OK at 267 registry / 349 canonical. logfare-registry 4/4, icon + KNOWN_PNGS + discovery-set membership all verified present. Closes#10644. Thank you @jonlwheat2-gif!
Validated against code before merge: 159 migration files on disk, 56 free-forever (Hack Club removal), 40 pools — counts verified, not trusted. check:docs-counts exit 0 (HARD failures drained; the 2 remaining soft executors-count notes are pre-existing on the tip) and check:test-discovery OK (orphan moved into the collected tree). These reds came from #11103/#11123 merging without the count regen — thanks for sweeping them @yourspraveen!
⭐5 — Provider x-search de primeira classe (SuperGrok/xAI x_search) em POST /v1/search e MCP omniroute_x_search. Fallback de credenciais xai-oauth→xao→xai; distinto de web search e do X Developer MCP.
Reconciliado com o release tip (que já incluía #10981 "skip catalog-default SearXNG" deste mesmo lote): merge trouxe 5 conflitos reais de contagem gerada (llm.txt/README.md/AGENTS.md/PROVIDER_REFERENCE.md/SVGs/46 mirrors i18n, todos verificados como bump puro 347→348, sem perda de conteúdo do HEAD) + 1 conflito real de mergeable=CONFLICTING.
Durante a validação, os 3 testes novos de SearXNG expuseram um bug real de interação com #10981: `isUnconfiguredLoopbackSearchProvider()` checava o baseUrl ESTÁTICO do catálogo em vez do baseUrl efetivo (após override de `provider_options.baseUrl` ou `providerSpecificData.baseUrl` da conexão), então QUALQUER request a searxng-search — mesmo com override customizado — era rejeitado como se fosse o default não-configurado. Corrigido em `open-sse/handlers/search.ts` (resolve o baseUrl efetivo via `resolveSearchBaseUrl()` antes do skip-check, tanto para o provider primário quanto o alternate). Um teste do próprio #10988 que assumia o comportamento pré-#10981 (default localhost:8888 sempre atendido) foi atualizado para refletir o comportamento já mesclado e intencional (503 quando não configurado).
Validação completa: typecheck limpo, 70/70 testes unit (search-route/search-registry/x-search-provider/searxng-loopback-default), 24/24 vitest MCP, 14/14 integration (search-providers-catalog), lint limpo nos arquivos tocados, docs-counts-sync OK (2 drifts soft pré-existentes, não relacionados), gates estáticos (file-size/complexity/cognitive/dead-code/changelog) todos OK.
⭐5 — Adiciona GET/HEAD /readyz como re-export de /healthz para probes de readiness estilo Kubernetes pararem de 404. Mesmos corpos/status de lifecycle; não é liveness probe. Testes de paridade + matcher omission. Fecha #10850.
Canonical provider id renamed freepik → magnific (Magnific Mystic official API), with a permanent redirect + runtime alias so old freepik/<model> traffic and /dashboard/providers/freepik URLs keep working. Existing provider=freepik connection rows are rewritten to magnific by migration 160.
Closes#10604.
Validated in an isolated worktree boarded onto origin/release/v3.8.50 (0 conflicts, 138 files):
- Focused suite: 54/54 tests pass (magnific-image-handler, provider-validation-image-only, provider-alias-uniqueness, redirects-cli-renames).
- check-file-size, check-changelog-integrity: OK.
- typecheck:core: clean.
- check-complexity / check-cognitive-complexity: OK, both under baseline.
Co-authored-by: RaviTharuma <RaviTharuma@users.noreply.github.com>
Merged — carried forward the PR's own real value (the first 2 commits: ignore ad-hoc BOT_TOKEN/BOT_URL in env-doc-sync, plus the lock-in test). The branch had accumulated 7 more commits chasing the moving release tip across several rebases (each one re-fixing base-reds that had already moved again by the next rebase) — dropped those since they no longer apply to the current tip, and cherry-picked just the 2 with lasting value, preserving your authorship. 14/14 focused tests pass, changelog gate green. Thanks!
Today's merge-train batch1 (#10722 Token Kiosk, #10729 Cursor) each added one
new APIKEY_PROVIDERS entry, bringing the live provider count to 343 — the
hardcoded '342' in README.md, AGENTS.md, llm.txt, package.json's description,
PROVIDER_REFERENCE.md, and 4 hero/comparison SVGs went stale as a result.
check:docs-counts (STRICT) now passes; regenerated PROVIDER_REFERENCE.md via
npm run gen:provider-reference. The v3.8.50 growth-log table row in README.md
(line 66) is left as-is — it's a historical point-in-time snapshot, not a
live claim.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Merged via merge-train (release/v3.8.50, batch1 2026-08-20) — static gates (typecheck/file-size/complexity/cognitive/changelog) green on the combined tree; test:unit reds observed in the boarded run were verified pre-existing on the pure release tip (unrelated flake), not caused by this PR. Thanks for the contribution!
Counts (check:docs-counts STRICT, 8 drifts → 0):
- 153 → 154 migrations in README.md, AGENTS.md and llm.txt (+ its 42 i18n mirrors,
which must stay byte-identical to the root file)
- 340 → 341 providers in README.md, AGENTS.md, llm.txt, the package.json description
and the 4 SVG diagrams; PROVIDER_REFERENCE.md regenerated via gen:provider-reference
(the new entry is the cloudflare-playground no-auth provider)
Undocumented environment variables:
- 13 CLI_*_BIN vars that exist in cliRuntime but were in neither ENVIRONMENT.md nor
.env.example (kilo, opencode, hermes, forge, jcode, deepseek-tui, codewhale, smelt,
pi, crush, omp, letta, windsurf — windsurf ships no default command)
- OMNIROUTE_DEBUG and OMNIROUTE_HEALTHCHECK_PATH, read in code but absent from
.env.example
- CLI_CURSOR_BIN documents both fallbacks (agent, then cursor)
Front-matter: bump the seven CLI/reference docs this effort touched from the stale
3.8.40/2026-06-28 stamp to the current release.
Out of scope but blocking check:docs-all, fixed with evidence: ENVIRONMENT.md and
.env.example still documented the Adobe Firefly CDP Chrome runtime removed in #9255.
Seven of its variables are read nowhere in the codebase and its source file no longer
exists; surviving vars are repointed at adobeFireflyBrowserLogin.ts and CHROME_PATH at
its real readers. The two Gemini CLI auth vars the run launcher scrubs from the child
env are added to the fabricated-docs external-tool allowlist, next to the existing
CODEX_HOME/COPILOT_PROVIDER_BASE_URL entries.
npm run check:docs-all now exits 0 for the first time on this base.