fix(db): persist WAL busy counter across restarts - #13218
Merged
diegosouzapw merged 207 commits intoSep 15, 2026
Merged
diegosouzapw merged 207 commits into
diegosouzapw merged 207 commits into
Conversation
maxmad64bis
force-pushed
the
fix/wal-busy-counter
branch
from
September 10, 2026 13:45
c76caea to
ec4ff6f
Compare
…iegosouzapw#12884) Um `ALL_TARGETS_SKIPPED` 503 que não diz qual janela esgotou é opaco justamente no momento em que o operador mais precisa saber. Alinhar os rótulos de janela AUTH com os da API de uso fecha a outra metade: dois nomes para a mesma coisa fazem o dashboard e o erro parecerem discordar. Revalidei sobre o tip: **6/6**, typecheck:core limpo, check-file-size OK. **Dois consertos meus na sua branch.** 1. `typecheck:core` falhava com `TS2345` em `comboAttemptLoop.ts` (linhas 130 e 416): o `QuotaSkipTarget` declarava `connectionId?: string`, mas o `ResolvedComboTarget` carrega `string | null` para alvo não-pinado. Alarguei para `string | null` no tipo de diagnóstico em vez de estreitar o call site — o módulo só **lê** o campo e a linha 29 já narrowa com `typeof === "string"`, então null não custa nada ali. Isso apareceu porque o `comboAttemptLoop` mudou de forma no diegosouzapw#12746/diegosouzapw#12811, mergeados nesta mesma campanha depois que você cortou a branch. 2. O `roundRobinCombo.ts` foi de 1198 para 1205 e cruzou o teto de 1200 para arquivo novo. Congelei com justificativa: o arquivo já nasceu em 1198 quando o diegosouzapw#12811 o levantou de dentro do `combo.ts`, e os diagnósticos em si vivem no `quotaSkipDiagnostics.ts`, sob o cap. Registrei que a próxima extração natural é o corpo do attempt loop, mas que ele acabou de ser movido e deve assentar antes de ser cortado de novo.
…iegosouzapw#12715) Fila sem teto que segura a request seis minutos até o cliente abortar é pior que 503 imediato: consome slot, mascara a saturação e ainda entrega erro no fim. Um orçamento `maxWaitMs` por conexão compartilhado entre gate, slot padrão do provider e fila do Bottleneck é a forma certa — o teto tem que ser um só, senão cada camada espera o seu. O `max(perConn, upstream)` no `executionMaxWaitMs` é o detalhe que evita a correção matar request em voo, que seria trocar um defeito por outro. Registro a atribuição: você manteve o diegosouzapw#12635 aberto para o @Tushar49 e creditou a percepção dele (providers lentos precisam de 2min→10min por conexão) enquanto adiciona o encanamento que faltava. É o jeito certo de construir sobre PR de outra pessoa sem tomar o crédito. Sobre o `npm run lint` desmarcado com a nota do eslint quebrado no ambiente: deixar em branco e explicar vale mais que marcar sem ter rodado. Rodei aqui: limpo. Revalidei sobre o tip: **13/13**, typecheck:core limpo, check-file-size OK. O `file-size-baseline.json` conflitou com os rebaselines desta campanha — resolvido aditivamente, JSON revalidado com `json.load`.
…diegosouzapw#12717) Uma conversa que nunca chegou a parada limpa e não sinaliza nada é o pior estado possível de UI: indistinguível de uma que terminou. O incidente que você cita no comentário do teste — stream pesado em reasoning estourando o cap do coletor no meio, deixando a conversa presa sem sinal — é exatamente o caso que justifica o badge. Separar `resolveTurnCompletionState` de `resolveConversationStalledState` também está certo: `tool_call_pending` é um estado legítimo em voo, não uma conversa travada. Revalidei sobre o tip: **29/29**, typecheck:core limpo. **Nota de integração.** O `tests/unit/responses-continuation-store.test.ts` conflitou com o diegosouzapw#12854, que anexa a própria bateria ao mesmo arquivo. Reconstruí o arquivo como append limpo — versão do tip mais o seu bloco de 184 linhas, verificado por `esbuild` antes de rodar. Registro por que importa: na primeira tentativa eu apenas retirei os marcadores de conflito, e isso enfiou os seus testes **dentro** de um objeto literal não terminado do diegosouzapw#12854. Compilava como erro de transform, não como conflito — só apareceu ao rodar. Resolver JSON e teste "aditivamente" sem verificar a sintaxe depois é armadilha; ficou a lição.
…eights, quality gate and scoring diagram now covered (diegosouzapw#12507) 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 (diegosouzapw#12970 e diegosouzapw#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 diegosouzapw#12786/diegosouzapw#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 diegosouzapw#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.
…les (diegosouzapw#13229) `check:mutation-test-coverage --strict` has been failing Fast Quality Gates on every open PR against release/v3.8.51. It grew from 2 missing entries to 5 in roughly an hour, so it is drifting faster than PRs land. Four test files cover a mutated module without being listed, so their mutant kills do not count: open-sse/services/accountFallback.ts <- openai-compatible-per-upstream-402-health src/sse/services/auth.ts <- openai-compatible-per-upstream-402-health <- quota-window-label src/shared/utils/circuitBreaker.ts <- combo/execute-target-gates open-sse/services/combo/comboStructure.ts <- combo-pin-implicit-allowlist Registration only — no test or module is touched, and no gate is weakened; the listing is what makes those kills count in the first place. Inserted in place, never through a JSON round-trip: re-serializing this file reorders the ~10 curated entries that are already out of alphabetical order (learned the hard way in diegosouzapw#11438). check:mutation-test-coverage now reports no drift. check:tracked-artifacts OK, prettier clean. Worth noting for whoever adds the next test: this gate fires whenever a NEW test happens to cover one of the 31 mutated modules, which is easy to do without realising. Registering it in the same commit is cheaper than a CI round-trip.
diegosouzapw#13228) CodeQL js/useless-regexp-character-escape (diegosouzapw#994-diegosouzapw#997) on one line, and it is a real defect rather than the usual query noise. The assertion built its pattern in a TEMPLATE literal: new RegExp(`\(\s*${String(tos?.actual)}\s*\)`) JavaScript resolves the escapes before RegExp ever sees the string: `\(` becomes "(" and `\s` becomes the LETTER "s". The compiled pattern was `(s*16s*)` — a capture group around optional "s" characters — so it matched any heading merely CONTAINING the number. The literal parentheses this guard exists to require were never checked, and it passed on exactly the headings it was written to reject: /(s*16s*)/.test("### Caution — clauses worth checking 16") // true Doubled the backslashes so they survive the template literal, and routed the interpolated value through an `escapeRegExp` helper — the count is a number today, but interpolating an unescaped value into a regex source is the same class of bug one refactor away. Added a second test that pins the behaviour rather than the spelling: the pattern must REJECT a heading carrying the count without parentheses, and accept it with them (including inner whitespace). Before this fix that test fails. 4/4 green against the real docs/reference/FREE_TIERS.md heading.
…w#13211) GHSA-wvxc-jp3v-5mg5: `DELETE /api/v1/batches/delete-completed` deleted the completed batches of EVERY api key on the instance and nulled the contents of every file those batches referenced. Any ordinary inference key reached it — including one with `scopes: []` — and no victim key, batch id or file id was needed. Two defects stacked in one endpoint: - `deleteCompletedBatches()` carried no `api_key_id` predicate. The file SELECT, the checkpoint DELETE and the batch DELETE were all instance-wide. - The route only checked that SOME key was present (`!scope.apiKeyId` → 401), never that the caller owned anything, and called the helper bare. The helper now takes `apiKeyId` and scopes all three statements to it; the route passes the caller's key and omits it only for session auth, so the operator's own dashboard keeps its instance-wide cleanup and an API key clears only its own completed batches. None of this is a new pattern. `listBatches(apiKeyId?)` and `countBatches(apiKeyId?)` in the same module already scope by `api_key_id`, and `batches/[id]/route.ts` already gates per-record access with `scopeCheck` — session auth sees everything, a key sees only its own. This one helper was the one that never got it, which is why the fix reuses the shape instead of inventing a second convention. tests/unit/batch-delete-completed-ownership-wvxc.test.ts — 5 tests, 4 red before the fix, including the two that prove the cross-tenant destruction (another key's batch survives; another key's file content survives). It also pins the instance-wide dashboard sweep so the fix cannot be "tightened" into breaking the operator's own cleanup, and a source guard that the route never calls the helper bare again. Reported privately via GHSA-wvxc-jp3v-5mg5. Closes GHSA-wvxc-jp3v-5mg5
…pw#13213) * chore(deps): drain the Dependabot queue — 7 of 10 alerts Lockfile-only bumps; no manifest touched, so nothing changes for consumers. Root package-lock.json: hono 4.13.0 -> 4.13.7 (diegosouzapw#215 diegosouzapw#216 diegosouzapw#217, medium, patched 4.13.5) csv-parse 7.0.1 -> 7.0.2 (diegosouzapw#213, medium) joi 18.2.3 -> 18.2.8 (diegosouzapw#211 diegosouzapw#212, low, patched 18.2.4/18.2.5) @omniroute/opencode-plugin: toml 4.1.1 -> 4.3.0 (diegosouzapw#209, HIGH, patched 4.1.2) @omniroute/opencode-plugin-v2: esbuild 0.28.1 -> 0.28.2 (diegosouzapw#210, low) — the direct copy only; see below. The plugin-v2 diff looks large but is one package: esbuild ships 27 platform binaries, each carrying version + resolved + integrity. Three alerts stay open, deliberately: diegosouzapw#218 extract-zip (HIGH) and diegosouzapw#214 adm-zip (medium) have NO published patch. Both are dev-scope. Closing them needs an upstream release or a decision to replace the dependency — neither belongs in a lockfile bump. diegosouzapw#210 esbuild is only half-closed. `node_modules/esbuild` is on 0.28.2, but `tsup` pins `esbuild: ^0.27.0`, so its nested copy stays at 0.27.7 — inside the vulnerable range (>= 0.27.3, < 0.28.1). Updating tsup does not move it (8.5.1 is already current). Forcing it would take an `overrides` entry pushing a major of esbuild inside the bundler, which is exactly the change that breaks a build silently, for a LOW dev-only alert. Left for an upstream tsup release. check:lockfile passes on all three, including the workspace lock/manifest consistency check. check:tracked-artifacts OK. * chore(deps): bump js-yaml to 4.3.2 (root + electron) Two more HIGH alerts arrived after the first sweep: diegosouzapw#220 js-yaml (root package-lock.json) >= 4.0.0, < 4.3.2 diegosouzapw#219 js-yaml (electron/package-lock.json) >= 4.0.0, < 4.3.2 The root's own js-yaml was already on 5.4.1; the vulnerable copies were the ones nested under @yarnpkg/parsers, lockfile-lint, xmlbuilder2 (root) and the direct dependency in electron. All now 4.3.2. Four version lines, nothing else. diegosouzapw#221 smol-toml (HIGH, <= 1.7.0) is NOT closed here. The root is on 1.8.0; the vulnerable 1.6.1 sits under @openai/codex-security, which pins it as an EXACT version rather than a range, so `npm update` cannot move it. Bumping codex-security itself (0.1.24 -> 0.1.26) does not help — 0.1.26 pins the same 1.6.1 — so that bump was reverted rather than carried along for no benefit. Closing diegosouzapw#221 needs an upstream codex-security release or an `overrides` entry, the same trade already declined for diegosouzapw#210/tsup: forcing a transitive pin from outside is how a build breaks silently. Note that @openai/codex-security is also the package carrying the unpatched extract-zip (diegosouzapw#218), so one upstream release would likely clear both. * chore(deps): override smol-toml to 1.8.0 and raise the js-yaml floor Closes diegosouzapw#221 (smol-toml, HIGH, DoS via malformed TOML, vulnerable <= 1.7.0). @openai/codex-security pins smol-toml at 1.6.1 as an EXACT version, so no `npm update` reaches it. This repo already uses `overrides` as its standard tool for exactly that situation — the block carries 20+ entries, including the scoped-by-parent form and the `qs`/`fast-uri`/`ip-address` entries that back earlier security bumps — so a scoped override is the idiomatic fix here, not a new mechanism: "@openai/codex-security": { "smol-toml": "^1.8.0" } The nested copy deduplicates to the root's existing 1.8.0, which two other consumers (the root itself and knip) already run, so the version is proven in this tree. The whole lockfile diff is the 14 lines of the removed 1.6.1 entry. Also raised the `@yarnpkg/parsers` js-yaml floor from ^4.3.1 to ^4.3.2, so the override documents the patched version rather than permitting the vulnerable one it was written against. Not fixed, and not fixable by version — verified against the npm registry rather than trusting the advisory metadata: diegosouzapw#218 extract-zip — latest published IS 2.0.1, the vulnerable version. Dev scope, via @openai/codex-security. No release to move to. diegosouzapw#214 adm-zip — latest published IS 0.6.0, the top of the vulnerable range (>= 0.5.9, <= 0.6.0). RUNTIME scope, via onnxruntime-node's ^0.5.16, and the repo already overrides adm-zip to ^0.6.0. No release to move to. Both need an upstream fix or a decision to replace the dependency; neither is a lockfile change. adm-zip being runtime rather than dev makes it the one worth tracking. diegosouzapw#210 esbuild stays open too. A flat `overrides: { esbuild: ^0.28.2 }` in opencode-plugin-v2 does close it — npm then reports 0 vulnerabilities — but it requires regenerating that lockfile from scratch: 823 lines, 96 packages moved, for a LOW dev-only alert, and a major esbuild bump inside tsup cannot be validated here without a real install of that package. Tried, measured, reverted. Left for an upstream tsup release. check:lockfile OK on all lockfiles including the workspace consistency check; check:tracked-artifacts OK; prettier clean.
… it (diegosouzapw#12918) Boarded with 13 sibling PRs into one worktree off release/v3.8.51 and validated as a set: 132 focused tests pass across all 15 test files in the batch, typecheck:core is clean, check-changelog-integrity reports no lost base bullets, and check-file-size is green. Your PR merged without conflict against its siblings. Thank you — the write-up made this reviewable: measuring the behaviour on the release tip and showing the before/after table meant the defect could be confirmed rather than taken on faith.
…a turn (diegosouzapw#12920) Boarded with 13 sibling PRs into one worktree off release/v3.8.51 and validated as a set: 132 focused tests pass across all 15 test files in the batch, typecheck:core is clean, check-changelog-integrity reports no lost base bullets, and check-file-size is green. Your PR merged without conflict against its siblings. Thank you — the write-up made this reviewable: measuring the behaviour on the release tip and showing the before/after table meant the defect could be confirmed rather than taken on faith.
…t anthropic (diegosouzapw#12921) Boarded with 13 sibling PRs into one worktree off release/v3.8.51 and validated as a set: 132 focused tests pass across all 15 test files in the batch, typecheck:core is clean, check-changelog-integrity reports no lost base bullets, and check-file-size is green. Your PR merged without conflict against its siblings. Thank you — the write-up made this reviewable: measuring the behaviour on the release tip and showing the before/after table meant the defect could be confirmed rather than taken on faith.
…pplies (diegosouzapw#12896) Boarded with 13 sibling PRs into one worktree off release/v3.8.51 and validated as a set: 132 focused tests pass across all 15 test files in the batch, typecheck:core is clean, check-changelog-integrity reports no lost base bullets, and check-file-size is green. Your PR merged without conflict against its siblings. Thank you — the write-up made this reviewable: measuring the behaviour on the release tip and showing the before/after table meant the defect could be confirmed rather than taken on faith.
…_tokens (diegosouzapw#13007) Boarded with 13 sibling PRs into one worktree off release/v3.8.51 and validated as a set: 132 focused tests pass across all 15 test files in the batch, typecheck:core is clean, check-changelog-integrity reports no lost base bullets, and check-file-size is green. Your PR merged without conflict against its siblings. Thank you — the write-up made this reviewable: measuring the behaviour on the release tip and showing the before/after table meant the defect could be confirmed rather than taken on faith.
…13066) (diegosouzapw#13083) Boarded with 13 sibling PRs into one worktree off release/v3.8.51 and validated as a set: 132 focused tests pass across all 15 test files in the batch, typecheck:core is clean, check-changelog-integrity reports no lost base bullets, and check-file-size is green. Your PR merged without conflict against its siblings. Thank you — the write-up made this reviewable: measuring the behaviour on the release tip and showing the before/after table meant the defect could be confirmed rather than taken on faith.
…lots (diegosouzapw#13110) Boarded with 13 sibling PRs into one worktree off release/v3.8.51 and validated as a set: 132 focused tests pass across all 15 test files in the batch, typecheck:core is clean, check-changelog-integrity reports no lost base bullets, and check-file-size is green. Your PR merged without conflict against its siblings. Thank you — the write-up made this reviewable: measuring the behaviour on the release tip and showing the before/after table meant the defect could be confirmed rather than taken on faith.
…etions (diegosouzapw#13070) (diegosouzapw#13087) Boarded with 13 sibling PRs into one worktree off release/v3.8.51 and validated as a set: 132 focused tests pass across all 15 test files in the batch, typecheck:core is clean, check-changelog-integrity reports no lost base bullets, and check-file-size is green. Your PR merged without conflict against its siblings. Thank you — the write-up made this reviewable: measuring the behaviour on the release tip and showing the before/after table meant the defect could be confirmed rather than taken on faith.
…osouzapw#12930) Boarded with 13 sibling PRs into one worktree off release/v3.8.51 and validated as a set: 132 focused tests pass across all 15 test files in the batch, typecheck:core is clean, check-changelog-integrity reports no lost base bullets, and check-file-size is green. Your PR merged without conflict against its siblings. Thank you — the write-up made this reviewable: measuring the behaviour on the release tip and showing the before/after table meant the defect could be confirmed rather than taken on faith.
Boarded with 13 sibling PRs into one worktree off release/v3.8.51 and validated as a set: 132 focused tests pass across all 15 test files in the batch, typecheck:core is clean, check-changelog-integrity reports no lost base bullets, and check-file-size is green. Your PR merged without conflict against its siblings. Thank you — the write-up made this reviewable: measuring the behaviour on the release tip and showing the before/after table meant the defect could be confirmed rather than taken on faith.
diegosouzapw#13104) Boarded with 13 sibling PRs into one worktree off release/v3.8.51 and validated as a set: 132 focused tests pass across all 15 test files in the batch, typecheck:core is clean, check-changelog-integrity reports no lost base bullets, and check-file-size is green. Your PR merged without conflict against its siblings. Thank you — the write-up made this reviewable: measuring the behaviour on the release tip and showing the before/after table meant the defect could be confirmed rather than taken on faith.
…apw#13009) Approved by the maintainer for the agent-instruction surface it touches: the SKILL.md change is regenerated output from the corrected parser (`resilience set` -> `resilience set <name>`), restoring the required argument the published page had been hiding. No hand-written directive was added. Boarded with 13 sibling PRs and validated as a set: 132 focused tests pass, typecheck:core clean, changelog integrity and file-size gates green. Thank you — the table contrasting the declared argument against the published page is what made the second case (an agent told to run `resilience set` with no argument) visible as more than cosmetic.
…ouzapw#13024) Merged with a rebaseline commit added on top of your branch: check:file-size freezes the gateways catalog at 1462 lines, so any new entry fails the gate on arrival. The annotation covers this entry and EURouter's (diegosouzapw#13025) together, following the route every previous gateway entry took (diegosouzapw#11786 seekai, diegosouzapw#10987 logfare, diegosouzapw#10668 tabitoken, diegosouzapw#10531 freebuff, diegosouzapw#11631 1min.ai) — the file is declarative data already split into six family files, so splitting it for two entries would break the semantic-families rule. Validated in a combined worktree with 13 sibling PRs: 132 focused tests pass, typecheck:core clean, file-size green after the rebaseline. Thank you for stating plainly what you did not verify. "The endpoint exists and is key-gated; catalog, streaming and tool calls not exercised" is worth more than a confident entry that turns out to be guesswork, and the conservative entry that follows from it — empty models, no capability declared, hasFree false with the billing shape spelled out — is exactly right.
…ouzapw#12985) (diegosouzapw#13025) Rebased onto the release tip after diegosouzapw#13024 landed: both PRs extend the same three registration files, so the sibling merge turned this into a conflict. The resolution is additive — both catalog entries kept, both registry imports kept, both base URLs kept — and EURouter stays in AGGREGATOR_PROVIDER_IDS while GreenPT stays out, exactly as each PR argued. 14 provider tests pass on the rebased branch and the file-size gate is green under the annotated rebaseline. Thank you for re-checking the endpoint live instead of trusting the report, and for the sovereignty caveat. Naming the upstreams from EURouter's own catalog — Claude Sonnet served by AWS Bedrock, 19 models owned by openai — and then writing an apiHint that says routing rather than residency is the kind of care that keeps a provider entry honest. The test asserting the copy contains none of "residency", "stays in the EU", "EU-hosted" or "sovereign" is a good guard against that drifting later.
…gosouzapw#12179 (diegosouzapw#12925) Rebased onto the tip and completed, per the maintainer's call to finish the wiring rather than merge the capability alone. What changed since your version: The tip had already cleared the TS2554 by deleting the 16th argument, leaving a comment that the highWaterMark stays at the helper default. So the base-red you found is gone, but the 64 KB diegosouzapw#12179 asked for was still not applied and your new parameter had no caller. glm.ts now passes it, which is what turns the capability into the fix. Your test file also hung the runner: every stream createSSEStream builds arms a 10s idle watchdog via setInterval in start, and nothing cancelled them, so node:test waited on a non-empty event loop long after the assertions passed. Cancelling each readable in an after hook runs the cancel handler that clears the timer — the file now reports in about 7 seconds. Worth knowing for future stream tests. Your five assertions are unchanged and all pass. Reading the writable's desiredSize to measure the queue budget the stream was actually built with, rather than standing in for it, is the detail that makes this testable at all — and the 0-budget case pinning `??` against `||` is the kind of thing that silently rots otherwise. Thank you also for separating your own red checks from the base's and reporting what you found there. That is how diegosouzapw#12919's identical failures got explained instead of chased.
…ouzapw#13196) Correct: `URL.pathname` is a URL path, so on Windows it yields `/C:/...` and `path.resolve` produces the doubled `C:\C:\` prefix. `fileURLToPath` is the right decoder and also un-escapes `%20`. All 37 WebDAV tests green here. --- Validated in one consolidated worktree cut from `release/v3.8.51`, boarded together with the other 13 PRs of this batch — zero merge conflicts between them. - `typecheck:core` clean - complexity 2799 / baseline 3218 and cognitive-complexity 1265 / baseline 1437 — both under baseline - 71 focused assertions green across the 13 test files this batch adds or touches⚠️ base-red inherited: diegosouzapw#12732 — `Docs Gates (fast-path)`, `Merge integrity`, `No new ESLint warnings`, `Unit Tests fast-path` and `Fast Quality Gates` all reproduce on the pure `release/v3.8.51` tip (provider count 356 vs the 358 the modules define, SKILL.md drift, and `open-sse/utils/stream.ts` at 3115 > frozen 3098). None of them touch this diff. Thanks @anhtahaylove — the root-cause write-up, the measured before/after numbers and the red-before-green proof on every one of these made the batch reviewable as a unit.
…ommit charge (diegosouzapw#13187) Aligns the two hand-typed local scripts with `test:unit:ci`, which already ran at concurrency 4; `--test-force-exit` was likewise the one flag `test` was missing. CI scripts are untouched. --- Validated in one consolidated worktree cut from `release/v3.8.51`, boarded together with the other 13 PRs of this batch — zero merge conflicts between them. - `typecheck:core` clean - complexity 2799 / baseline 3218 and cognitive-complexity 1265 / baseline 1437 — both under baseline - 71 focused assertions green across the 13 test files this batch adds or touches⚠️ base-red inherited: diegosouzapw#12732 — `Docs Gates (fast-path)`, `Merge integrity`, `No new ESLint warnings`, `Unit Tests fast-path` and `Fast Quality Gates` all reproduce on the pure `release/v3.8.51` tip (provider count 356 vs the 358 the modules define, SKILL.md drift, and `open-sse/utils/stream.ts` at 3115 > frozen 3098). None of them touch this diff. Thanks @anhtahaylove — the root-cause write-up, the measured before/after numbers and the red-before-green proof on every one of these made the batch reviewable as a unit.
…et token (diegosouzapw#13175) Real abuse vector: the bot-webhook branch reached `proxyChat()` — which mints an API key and spends upstream quota — with nothing proving the caller was Telegram. Fail-closed 503 when the secret is unset is the right default. --- Validated in one consolidated worktree cut from `release/v3.8.51`, boarded together with the other 13 PRs of this batch — zero merge conflicts between them. - `typecheck:core` clean - complexity 2799 / baseline 3218 and cognitive-complexity 1265 / baseline 1437 — both under baseline - 71 focused assertions green across the 13 test files this batch adds or touches⚠️ base-red inherited: diegosouzapw#12732 — `Docs Gates (fast-path)`, `Merge integrity`, `No new ESLint warnings`, `Unit Tests fast-path` and `Fast Quality Gates` all reproduce on the pure `release/v3.8.51` tip (provider count 356 vs the 358 the modules define, SKILL.md drift, and `open-sse/utils/stream.ts` at 3115 > frozen 3098). None of them touch this diff. Thanks @anhtahaylove — the root-cause write-up, the measured before/after numbers and the red-before-green proof on every one of these made the batch reviewable as a unit.
…es out (diegosouzapw#13171) The sniff loop abandoned the upstream reader when `withBodyTimeout()` rejected. The `handedOff` flag correctly spares the two success paths from cancellation; the second test guards that direction. --- Validated in one consolidated worktree cut from `release/v3.8.51`, boarded together with the other 13 PRs of this batch — zero merge conflicts between them. - `typecheck:core` clean - complexity 2799 / baseline 3218 and cognitive-complexity 1265 / baseline 1437 — both under baseline - 71 focused assertions green across the 13 test files this batch adds or touches⚠️ base-red inherited: diegosouzapw#12732 — `Docs Gates (fast-path)`, `Merge integrity`, `No new ESLint warnings`, `Unit Tests fast-path` and `Fast Quality Gates` all reproduce on the pure `release/v3.8.51` tip (provider count 356 vs the 358 the modules define, SKILL.md drift, and `open-sse/utils/stream.ts` at 3115 > frozen 3098). None of them touch this diff. Thanks @anhtahaylove — the root-cause write-up, the measured before/after numbers and the red-before-green proof on every one of these made the batch reviewable as a unit.
- recordBusy() ran a synchronous INSERT exactly when the checkpoint reported the database as contended, which can hold the event loop for up to busy_timeout (2s). Busy events are now counted in memory only (pendingBusyDelta) and flushBusyTotal() adds the delta with one additive UPSERT from a clean (non-busy) TRUNCATE or passive scheduler tick, and best-effort from stopWalMaintenance() at shutdown/restart. A failed flush keeps the delta for the next clean tick; there is no retry loop. - Boot still restores the persisted total (max of the in-memory and stored values), now tested for real: a child Node process (outside the test runner gate) drives startWalMaintenance/stopWalMaintenance against a real SQLite file with scripted busy/clean checkpoint results and asserts the restore, zero writes while busy, the flush on the clean tick, the single flush at stop and the restore after restart.
…us (diegosouzapw#13730) 2a6d058 added an early return in runSingleModelTest that skips image/music/ video-only models so a chat test never triggers a billable generation. The returned object omitted httpStatus, which SingleModelTestResult requires (TS2741 — this is the API Route Typecheck red on release/v3.8.51). It was not only a type error. src/app/api/models/test/route.ts passes result.httpStatus straight to NextResponse.json(body, { status }), so the status was undefined, Next fell back to 200, and a skipped test reached the client as an HTTP success with status: "error" in the body. Answer 422 rather than the 409 the managed-lease return uses: the request is well-formed, the model's modality just cannot be exercised by a chat test. TDD: the new case seeds an images-only custom model, replaces fetch with a throwing stub, and asserts the skip fires with a numeric 422 and no dispatch. It failed with httpStatus undefined before the one-line fix and passes after. model-test-runner + model-test-modality-guard-13376: 35/35 check-api-typecheck: OK (the TS2741 is gone)
…iegosouzapw#13722) `check:agent-skills-sync` (ci.yml:lint) has been failing on release/v3.8.51 because the generated skills/cli-serve/SKILL.md no longer matches the command catalog. fc111dc (make startup readiness budget configurable) added the `--ready-timeout <ms>` flag to bin/cli/commands/serve.mjs without regenerating the skill. This is the generator's output, unedited: a single added line listing the flag, which exists at bin/cli/commands/serve.mjs:62. No other skill changed (Generated: 1 · Unchanged: 45 before, Generated: 0 · Unchanged: 46 after).
…gosouzapw#13635) * docs: bring the provider count to the live 358 across the reference, diagrams and llm.txt mirrors * chore(skills): regenerate the cli-tunnel SKILL.md for the tunnel create positional * test: clear the ESLint errors in the volcengine upsert and resource-pressure tests * test(autoCombo): complete the mode-pack ProviderCandidate fixtures for the open-sse typecheck * fix(ci): allow the opencode-plugin-v2 workspace package in the pack artifact policy * docs: list the WAL, vacuum, sql.js and pressure self-restart env vars in .env.example * refactor(db): move the synced-model provider purge into its persistence module to break the models/providers cycle * test(memory): use a plain label for the rerank loopback key fixture so gitleaks stays at zero * chore(ci): register the eleven covering unit tests in stryker tap.testFiles * test(grok-cli): run the reset-credit tests on a fixture clock inside the captured token window * test(combo): seed real provider connections for the reset-aware strategy tests * fix(db): keep operator custom models out of the listing-only synced catalog reader * fix(i18n): translate the new settings and combo keys for vi and pt-BR and restore the zh-TW glossary term * fix(sse): carry the upstream error code and type through the provider execution pipeline * test(sse): re-point the chatCore and combo source guards at the split modules and refresh the translate-path golden * fix(oauth): keep the server-only OAuth constants out of the provider detail client bundle * test: align the sql.js, webpack, injection-scan and error-boundary guards with their merged contracts * docs(changelog): record the v3.8.51 base-red sweep * fix(sse): anchor the glued-prefix sk- credential pattern so error redaction scans in linear time * docs(changelog): note the linear credential scan in the base-red sweep --------- Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
…bo catalog event-loop pin, unweighted quota-share, resilience key set, pack-gate stamp, synced-catalog env doc (diegosouzapw#13678) * fix(combo): rotate unweighted quota-share targets instead of pinning the first The combo resolver turns an unset step weight into 0 (comboStructure.ts), and diegosouzapw#10881 made normalizeWeight treat 0 as disabled plus return definition order when the total weight is 0. A quota-share combo without explicit weights therefore had no DRR quanta and dispatched every request to its first target — the combo-matrix/quota-share integration suite saw openai six times out of six. An all-zero set is now an unweighted combo and shares evenly; an explicit 0 still disables a target when its siblings are weighted. Refs diegosouzapw#12732 * fix(models): resolve auto-combo target metadata once per catalog build diegosouzapw#12046 derives vision/modalities for the built-in auto/* combos by resolving catalog metadata for every target of every combo. The ~40 auto combos share one candidate pool and the loop neither memoized nor yielded, so the diegosouzapw#9147 fixture (60 connections, 720 synced models) went from a ~4s build with a 167ms longest event-loop gap to ~11s and a 860-1070ms gap on an idle box — past the 800ms contract and past diegosouzapw#12628's 8s cold-build bound, which is why the test came back 500 catalog_build_timeout on every release-green run. Metadata depends only on the target's provider/model/connection scope within a build, so memoize it per build and yield between misses. Same fixture: 2.3-3.1s build, 56-72ms longest gap. The 9147 test is unchanged. Refs diegosouzapw#12732 * test(resilience): list credentialHealthCheck in the configuration-only key set diegosouzapw#12043 added credentialHealthCheck.intervalMinutes to DEFAULT_RESILIENCE_SETTINGS and to the /api/resilience GET projection. It is operator configuration (the background sweep cadence), not runtime breaker state, but the exact key-set assertion was never updated, so resilience-http-e2e failed on the release tip. The providerBreakers/runtime absence checks stay as they were. Refs diegosouzapw#12732 * fix(ci): stamp BUILD_SHA before the release-green pack gate validates check:pack-artifact assembles dist/ through build:cli, which never writes dist/BUILD_SHA (only build:release does). diegosouzapw#12959 pointed the provenance ref at HEAD, but the diegosouzapw#10427 guard still stops at 'dist/BUILD_SHA is missing' before it ever reaches the ancestry check — reproduced on tip + diegosouzapw#13635 + diegosouzapw#13436, the first tree whose Turbopack build compiles. ci.yml sequences build -> stamp -> validate; the validator now does the same in both entry points, keeping PACK_GATE_ENV for the validate step. The guard is unchanged: an unstamped dist/ or one built from another commit still fails. On that tree the stamped gate passes: 'BUILD_SHA 5cb3ae5d9 is on the release line'. Refs diegosouzapw#12732 * docs(env): document OMNIROUTE_SYNCED_CATALOG_STALE_AFTER_MS diegosouzapw#13248 (diegosouzapw#12849) added the override for when a connection's synced model list stops being authoritative, but neither .env.example nor ENVIRONMENT.md lists it, so the env/docs contract gate reports it as code-only. The other five vars that gate reports are already added by diegosouzapw#13635 and diegosouzapw#13361; this touches a different region of .env.example so it does not collide with either. Refs diegosouzapw#12732
…gian, Armenian (66 locales) (diegosouzapw#13727) 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: diegosouzapw#12732
Partial updates keep the fields the client left out. Update/PATCH schemas that carried `.default()` re-applied those defaults under `.partial()`, so renaming a disabled reasoning-routing rule turned it back on, a playground preset lost its params and a proxy edit reset `family` to `auto`. The new `partialWithoutDefaults` helper strips defaults before `.partial()`; a scan test fails if any exported update schema ever leaks a default again. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
…ion (diegosouzapw#13612) Pool validation no longer rewrites `inactive` or `dead` proxies to `active`: `validateProxyPool` only ever touched rows that were already live. Covered by 8 status × probe combinations plus case and null variants. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
…edule (diegosouzapw#13736) The radar-server only consumes the stable asset, so a catalog merge on the active release branch waited for the Monday 06:17 UTC cron and the feed sat up to a week behind the README (2026-09-14: the Together signup-credit row removed in d6e62ae only left the feed after a manual dispatch). Trigger on release/** pushes for the same catalog paths and move the schedule to 03:17 UTC daily, ahead of the server's 04:23 UTC publish cycle.
…ouzapw#13217) The combo PUT route and the dashboard modal stop stripping nine live config keys (`queueDepth`, `maxComboDepth`, `fallbackDelayMs`, `handoffProviders`, `manifestRouting`, `complexityAwareRouting`, `pipeline_enabled`, `shadowRouting`, `evalRouting`, plus `queueTimeoutMs` in the modal); only the three dead keys that nothing reads are removed. Route tests assert every live key survives a PUT. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
…iegosouzapw#13577) A write that does not send a proxy `status` (subscription refresh, bulk import, PATCH) no longer turns a disabled or dead proxy back on; the stored status is kept. Real DB-backed tests through `upsertProxy`, the subscription sync against a local feed and `handleProxyUpdate`. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
… Zen, OpenCode and OpenCode Go (diegosouzapw#13471) Registers Muse Spark 1.3 (with its effort aliases) on OpenCode Zen, OpenCode and OpenCode Go with `targetFormat: openai-responses` and a 1M context window, so the model no longer falls back to `/chat/completions` (diegosouzapw#12674, diegosouzapw#12698). Superset of diegosouzapw#12675, diegosouzapw#12973 and diegosouzapw#13111, whose authors are credited in the PR. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
…llback warning (diegosouzapw#13613) The opencode plugin v2 reads its management token from `OMNIROUTE_MANAGEMENT_API_KEY` (the plugin option still wins) and warns once at startup when it has to fall back to the inference key. Eight cases through the real plugin setup, env isolated, asserting the Bearer header on `/api/*`. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
…ile and rename (diegosouzapw#13607) The plugin v2 on-disk catalog snapshot is written to a temp file and renamed into place, snapshots from a newer format version are refused instead of parsed, and size-cap or I/O give-ups now warn instead of failing silently. Nine cases, four of which fail on the old code. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
…dget 429s (diegosouzapw#13606) `token_limit_exceeded` joins `REQUEST_SCOPED_UPSTREAM_ERROR_CODES`: chatCore's local Tier-2 check answers 429 with that code, but `shouldSkipConnDisable` did not know it and cooled a healthy connection down for a request-sized problem. Combo exhaustion treats it as request-scoped too. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
…ceeds its time bound (diegosouzapw#13438) A cold `/v1/models` catalog build that exceeds its time bound now answers 503 with `Retry-After` instead of a 500, and the timed-out build stays joinable so the next retry does not start another cold build. Seven cases; the first fails on the tip (500 → 503). Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
…gosouzapw#13279) Combo test probes are aborted when the dashboard client disconnects (`AbortSignal.any` over the route's own timeout and `request.signal`), instead of running to completion for nobody. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
diegosouzapw#13281) `error_type` becomes a versioned vocabulary: a failure the classifier cannot place is stored as `unknown` instead of NULL, and any stored value outside the vocabulary reads back as `unclassified` in the breakdown. Maintainer rework before merge (kept the idea, no default behavior change): - `PROVIDER_ERROR_TYPES` is `as const`, so `ErrorTypeContract` is a real union and the classifier functions return the narrowed type. - The constants moved above the JSDoc that documents `getErrorTypeBreakdown`; the vocabulary SQL is built on first use so an import cycle cannot read it before it exists. - Legacy NULL rows keep landing in the `pre_migration`/`unclassified` bucket without vanishing or double counting, and the log export / BigQuery row pass both NULL and `"unknown"` through unchanged — both covered by tests. Duplicate assertions removed; every seeded row is cleaned up in `finally`. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
) A write-boundary guard for `error_type`: `toStoredErrorType()` validates what `saveCallLog` stores against the vocabulary (Zod enum built once), as defense in depth on top of diegosouzapw#13281. Maintainer rework before merge (kept the idea, no default behavior change): - Dropped the redundant `SCHEMA_SQL` column (migration 158 already creates it) and the string-absence "migration 177" test; the real `PRAGMA table_info` test is back. - Restored diegosouzapw#13281's changelog fragment, which this branch had deleted, and renamed this PR's own fragment to `13441-error-type-write-guard.md`. - The guard is now exercised for real: the exported function is tested with out-of-vocabulary values and an end-to-end drift test that changes a classifier family at runtime. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
…ted as secrets (diegosouzapw#13729) The labels wvxc-route-401/wvxc-route-500 sat right after a key*.id argument and cleared the gitleaks generic-api-key length and entropy floors; renamed to route401/route500 with a docblock stating the measured rule. Test-only; .gitleaks.toml untouched. Reviewed by 3 rounds of /omni-code-review (37 agents).
…w#13641) Search stats and recent searches stop surfacing ghost rows: NULL and `-` providers are always hidden, and, behind the new `SEARCH_STATS_HIDE_DELETED_CONNECTIONS` flag (default off), traffic of a keyed provider whose connection was deleted is hidden too. Totals use the same guard as the per-provider rows, so they always agree. Maintainer rework before merge (kept the idea, no default behavior change): - Keyless providers from the search registry (`duckduckgo-free`, `searxng-search`, anonymous `context7`) and providers served through a credential fallback (`perplexity-search` on a `perplexity` key) stay visible in both modes — the original filter dropped them because they have no `provider_connections` row. - Tests use real registry ids and cover flag off (historical stats) and flag on, including the analytics route; diegosouzapw#13281's changelog fragment restored. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
… and make the guard find them (diegosouzapw#13436) Fixes the production build break from `node:fs` reaching client bundles (`oauth.ts → cursorAgentCliVersion.ts` through the codebuddy-cn registry) and widens the client-bundle guard so it finds any Node builtin, not just the one that broke. Maintainer rework before merge (kept the idea, no default behavior change): - The guard was 11× slower (3.8s → ~40s) because resolved edges were not cached; with resolved edges and per-file verdicts cached it runs in ~4.6s. - Bare builtins that Next's client build polyfills (`path`, `os`, `crypto`, `buffer`, … from Next's own `resolve.fallback` list) are allowed consistently; `node:` imports are always flagged; a drift test fails if Next stops polyfilling an allowlisted name. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
…uzapw#13605) Proxy credentials containing a literal `%` no longer throw `URIError`: every `decodeURIComponent` on proxy user/password is guarded. Maintainer rework before merge (kept the idea, no default behavior change): - HTTP proxies still failed because undici's `ProxyAgent` decodes the credentials itself; the dispatcher now builds undici's `Basic` token with the safe decoder and passes it as `token`, so a literal `%` works there too. - The three remaining unguarded sites (`mappers.ts`, `proxySubscription/parse.ts`, `subscriptionService.ts`) are guarded; tests run the real `createProxyDispatcher` against a local HTTP CONNECT proxy and a local SOCKS5 server that record what they received. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
…osouzapw#13280) Seven routing/quota caches (quality states, account buckets, quota-fetcher/saturation/header caches, learned rate limits) sit behind a shared bounded map with LRU/TTL eviction instead of growing without bound. The learned-limits cap of 200 that the tip declared was never enforced. Maintainer rework before merge (kept the idea, no default behavior change): - Eviction logging goes through the project logger, aggregated (first eviction, then one summary line per minute per map) instead of a `console.warn` per eviction. - `refetch-lazy` and `hard-expire` behaved identically and are collapsed into `ttl`; protected entries (saturated account buckets, evaluator quality scores) are never evicted; caps raised to 2048–4096 so normal deployments never evict, with tests showing 300 learned limits and 600 cached entries all kept. Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
diegosouzapw
merged commit Sep 15, 2026
62cd277
into
diegosouzapw:release/v3.8.51
3 of 7 checks passed
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
The WAL busy counter survives restarts: it is persisted in `key_value` and restored at boot, so the health output no longer resets to zero after every restart. Maintainer rework before merge (kept the idea, no default behavior change): - `recordBusy()` no longer writes synchronously on the contended path (with `busy_timeout = 2000` that could block the event loop for up to 2s); it accumulates in memory and `flushBusyTotal()` upserts the delta on a clean passive/TRUNCATE tick or best-effort at stop. - The boot wiring is tested for real: a child Node process drives `startWalMaintenance` against a real SQLite file (restore at boot, zero writes while busy, one flush at stop, restore after restart). Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 d61b804: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests. Thanks @maxmad64bis!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The stuck-checkpoint counter on the health page resets to zero on every restart. That's exactly when you need it: you restart to clear a stuck WAL, and the evidence of how often it stuck is gone. This PR saves the counter in the existing settings table (one atomic
+1per stuck event) and restores it at boot. The health endpoint itself is untouched and still reads from memory. Continues #12853, which made stuck checkpoints visible — this keeps the count across restarts. (Unrelated to #12998, which was about log wording and closed as superseded.)Related Issues
Follow-up to the WAL observability work in #12853. No new endpoint, no new setting, no schema change. If saving ever fails, the scheduler carries on — memory stays the source of truth for the session.
Validation
npm run lintTests Added Or Updated
Six new cases in
wal-maintenance.test.ts: merge picks the higher value, corrupt or missing rows read as 0, memory updates before the database write, a failing database keeps the scheduler alive, two writers on one shared file add up (5+7=12), restart keeps the total and resets the streak. Gates ona0c69ca25e: 17 pass, 0 fail, 1 pre-existing skip,typecheck:coreclean, file-size OK, eslint clean. The boot path itself can't run under test (the test gate returns early by design), so a composition test covers it.Coverage Notes
The pure helpers are fully pinned (higher value wins, fractions floored, negatives and garbage read as 0). The shared-file test proves real SQL on the driver's cascade; it runs sequentially, not under real contention. The restart test asserts the streak resets to 0 while the total survives.
Reviewer Notes
Two honest limits. Under heavy lock contention the save itself can hit a busy database and that increment is lost on disk (kept in memory) — so the counter can undercount precisely the contention it tracks. After a restart with failed saves, boot restores the lower stored value; it never goes backward below a shown value, but the unflushed gap is gone. Also not durable on the in-browser driver (no flush yet). No write-back of the merged value by design — that would turn multi-process addition into last-writer-wins.