Repository navigation
fix(call-logs): versioned error_type vocabulary with unknown fail-open - #13281
Merged
diegosouzapw merged 64 commits intoSep 15, 2026
Merged
diegosouzapw merged 64 commits into
diegosouzapw merged 64 commits into
Conversation
maxmad64bis
force-pushed
the
fix/n63-error-type
branch
2 times, most recently
from
September 10, 2026 19:02
4503187 to
bebf4f2
Compare
This was referenced Sep 12, 2026
- ERROR_TYPE_CONTRACT v1 derived from PROVIDER_ERROR_TYPES + unknown - classifyCallLogError: status===0 ? (empty?null:classifier??unknown) : status<400 ? null : (classifier??unknown), never throws - getErrorTypeBreakdown: ELSE unclassified + NOT IN vocab + ERROR_TYPE_CUTOVER_ISO - changelog fragment
maxmad64bis
force-pushed
the
fix/n63-error-type
branch
from
September 14, 2026 16:17
bebf4f2 to
75970e3
Compare
…heaper-inference#13204) (cheaper-inference#13233) Merged after reconciling against the tip. `docs/architecture/QUALITY_GATES.md` conflicted: this PR adds the `check:vitest-exclusions` row while the tip had meanwhile rewritten the `check:model-lifecycle` description (cheaper-inference#12535). Resolved to the tip's table plus the new row. - `check:vitest-exclusions`: OK, 11 excluded files, each tracked and referenced - ESLint over the changed files: exit 0 - `npm run test:vitest` (the config this PR edits): 472 of 473. The one red, `tests/unit/autoCombo/provider-family-combos.test.ts`, is not touched by this PR and passes 11/11 in isolation on both this branch and the pure tip — a load flake from the full run, not a regression.⚠️ base-red inherited: cheaper-inference#12732
…r-inference#12849) (cheaper-inference#13248) Merged after renumbering. `176_provider_connection_synced_models_at.sql` collided with `176_xp_action_counts.sql` (cheaper-inference#12651), which made the migration runner abort on every DB open. Renamed to **177**; the doc count moves 173 → 174 across README.md, AGENTS.md, llm.txt and the i18n mirrors (operator-approved, 206 numeric substitutions and nothing else). - `check:migration-numbering`: OK, 174 migrations, no duplicates - `check:docs-counts` migrations: ✓ - 84/84 across the NVIDIA suite plus the seven DB-touching suites the collision had taken down - ESLint and `typecheck:core`: exit 0 Heads-up for whoever lands next: **177 is claimed by eight other open PRs** (cheaper-inference#13610, cheaper-inference#13602, cheaper-inference#13580, cheaper-inference#13554, cheaper-inference#13405, cheaper-inference#13331, cheaper-inference#13177, cheaper-inference#13116) and 176 by cheaper-inference#13373 and cheaper-inference#13102. With this merged, all of them need to renumber at merge time — `check:migration-numbering` forbids new gaps, so the next free number is always the only valid one.⚠️ base-red inherited: cheaper-inference#12732
…k, docs provider count, agent-skills sync (cheaper-inference#13216) 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.
…, Sinhala, Burmese, Khmer (59 locales) (cheaper-inference#13660) 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: cheaper-inference#12732 — the eight red checks fail identically on unrelated PRs cut from the same base (e.g. cheaper-inference#13197); every gate is green locally after merging the base.
…xt mirrors (cheaper-inference#13674) Unblocks the pre-commit docs-sync gate on the release tip.
…inference#12867 pipeline extraction, a legacy-DB boot abort and the catalog readers (cheaper-inference#13349) Merged after a real reconciliation — this PR and cheaper-inference#13069 fixed the same cheaper-inference#12867 regression (the non-streaming leg losing failure classification and credential refresh) with different strategies, and cheaper-inference#13069 landed first. Rather than stacking two implementations, the tip's was kept and this PR was trimmed to what the tip still lacked. **Dropped, already on the tip:** - non-streaming credential refresh and failure-state persistence → cheaper-inference#13069 (`applyProviderFailureClassification`); the `persistProviderFailureState` hook this PR added would have been dead code - body-derived rate-limit lock and non-JSON body message → already in the tip's pipeline (`chat-rate-limit-body-lock` passes there) - codex image-generation stringify of a sanitized error body → cheaper-inference#12945 (`stringifyImageErrorForLog`, which would otherwise be declared twice — TS2393) - the two test realignments (`hard-session-lease` inventory wording, kiro stream reader) → cheaper-inference#12945 **Kept, missing on the tip:** - **upstream error `code`/`type` in the pipeline error outcome** — ported onto the tip's implementation. Running this PR's own test against the tip returned `errorCode: undefined` instead of `missing_project_id`, so a config-class Antigravity 422 still degraded into an account cooldown. - legacy `call_logs` boot abort (index created after column healing) - malformed operator custom-models row no longer kills every `auto/*` pool (`virtualFactory.ts` 1219 → 1230, annotated) - realigned guards **Evidence on the reconciled tree** - 104 of 106 focused assertions. The 2 red (`models-catalog-route`, `provider-node-reserved-prefix`) fail identically on the pure tip. Against the tip, this PR turns 7 previously red cases green. - ESLint, `typecheck:core`, `check:open-sse-typecheck` (0 errors), `check:changelog-integrity`: all clean - changelog fragment rewritten to claim only what this PR still delivers Unblocking this also surfaced a repo-wide red: the eight llm.txt mirrors added by cheaper-inference#13660 kept the pre-cheaper-inference#13216/cheaper-inference#13248 counts, which failed the pre-commit `docs-sync` gate for everyone. Fixed separately in cheaper-inference#13674. `skills/cli-tunnel/SKILL.md` needed no change — cheaper-inference#13216 already landed the identical edit.⚠️ base-red inherited: cheaper-inference#12732
… test flake, pack provenance + pack policy (cheaper-inference#12959) Merged after salvaging what still applies. The doc-count half of this PR is superseded — it moved migrations 169 → 171 while the tip is already at 174, and the provider count landed via cheaper-inference#13216 — so every docs, diagram and llm.txt mirror change was reset to the tip's version and its changelog fragment dropped. Merging it as it stood would have regressed the counts. Kept, none of it on the tip: - `scripts/build/pack-artifact-policy.ts`: `@omniroute/opencode-plugin-v2/` added to the allowlist — cheaper-inference#12870 shipped the v2 plugin without widening it, so every packed file under it read as unexpected - `scripts/quality/validate-release-green.mjs`: points the pack provenance guard at `HEAD` instead of `origin/main`, which is structurally unreachable from a release branch mid-cycle - `12058-models-catalog-canonical-self-aliased.test.ts`: pins `CATALOG_BUILD_TIMEOUT_MS` out of the way of a cold catalog build on a loaded runner; assertions unchanged 54/54 across those three suites, ESLint exit 0, changelog integrity OK.⚠️ base-red inherited: cheaper-inference#12732
…erence#12969) Merged after reconciling the whole stack onto the tip, operator-reviewed before merge. The core ownership fix for GHSA-wvxc-jp3v-5mg5 had already landed via cheaper-inference#13211 with a different implementation of the same endpoint. This branch carries a stricter one, built up in layers: this PR, cheaper-inference#13262 (explicit scope, audit log, atomic sweep), cheaper-inference#13297 (revoked, deactivated, banned or expired keys rejected) and cheaper-inference#13374 (owner-scoped file half, chunked instance sweep — SEC-C/SEC-D). The stack's implementation was kept over cheaper-inference#13211's because it is stricter on every point: - **route:** with cheaper-inference#13211, a request carrying BOTH a dashboard session cookie and an API key swept the whole instance. Here a presented key always scopes the sweep to that key; only a session without a key sweeps all tenants; neither returns 401. Instance-wide and row-deleting sweeps log at warn as an audit trail, and a failing sweep returns a sanitized 500. - **`deleteCompletedBatches`:** takes an explicit `{ apiKeyId } | { allTenants: true }`. An omitted or blank key throws instead of widening, and passing both throws. - **files:** a key sweep only soft-deletes files the caller owns (`deleteFileOwnedBy`), so a batch referencing another tenant's or an unowned file never nulls its content. - **transactions:** key mode is all-or-nothing across chunks; instance mode commits per 200-id chunk so a large sweep never holds one write lock on the table. cheaper-inference#13211's own test was aligned to the explicit-scope API with its assertions unchanged. Its seed now creates the file with the batch's owner, as an upload through that key does in production — without that, SEC-C correctly leaves the unowned file intact. - 51/51 across the six batch suites (cheaper-inference#13211's test, this stack's ownership and route-scope tests, `batch-deletion`, `batch-deletion-route-logic`, `files-delete-owned-by`) - ESLint, `typecheck:core`, complexity, cognitive-complexity, changelog integrity: clean⚠️ base-red inherited: cheaper-inference#12732
…nference#13286) (cheaper-inference#13418) Chains `npm run test:unit:serial` onto the plain `npm test` script, so the quarantined serial suite is no longer skipped when contributors run `npm test` (cheaper-inference#13286). The existing `test-serial-quarantine` guard now covers `test` too. 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!
…-inference#13273) (cheaper-inference#13401) Masks every `*-api-key` header spelling (`x-goog-api-key`, `api-key`, `xi-api-key`) in the request-log pipeline by matching on the hyphen-compacted key, and adds `xi-api-key` to the payload redaction set (cheaper-inference#13273). The new test drives the real `createRequestLogger` / `protectPayloadForLog` paths. 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!
…heaper-inference#13403) Fixes the stale `jina-ai/` prefix in the second Jina assertion of `models-catalog-route.test.ts`. The catalog emits `jina/…` (the first Jina test already expected it), so this clears a base red on the release branch. 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!
…heaper-inference#13308) (cheaper-inference#13404) Prunes `db_backups/` after the health-check-repair `VACUUM INTO` snapshot (cheaper-inference#13308). That path never ran retention, so every restart of a healthy database added another full-size copy. It now uses the same `DB_BACKUP_MAX_FILES` / `DB_BACKUP_RETENTION_DAYS` limits as `backup.ts`, importing `backupRetention` directly to avoid the import cycle. Maintainer additions: merged the current release branch and rebaselined `src/lib/db/core.ts` 1745→1767 in `file-size-baseline.json` with a dated annotation (legitimate growth). Chosen over cheaper-inference#13540, which did the same with a fire-and-forget dynamic import. 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!
…ction (cheaper-inference#12776) (cheaper-inference#13406) Carries `context_length` through the MCP `list_models_catalog` projection when the upstream model record has it, and omits it otherwise (cheaper-inference#12776). Covered by the new case in `mcp-model-catalog.test.ts`. 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!
…rence#13409) "Test all models" no longer sends image/music/video generation-only models through a chat completion, which triggered real billable generations (cheaper-inference#13376). `detectTestKind` flags them via `isNonChatGeneration` and `runSingleModelTest` skips them; chat+image models, embeddings and models without metadata are unaffected (8 new cases plus updated `model-test-runner` shapes). 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!
…heaper-inference#13412) Adds CJK quota-exhaustion messages (GLM/z.ai 5-hour window, Kimi, Qwen/DashScope, MiniMax, plus Japanese and Korean phrasings) to the 429 quota classifier. They are now `quota_exhausted` (cooldown + failover) instead of a transient `rate_limit` retry loop (cheaper-inference#13194). The patterns go into the recoverable `QUOTA_PATTERNS` only, not the terminal set, and a guard case keeps the Chinese transient "请求过于频繁" as `rate_limit`. Chosen over cheaper-inference#13536. 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!
…otAll regex (cheaper-inference#13413) Eval runner: a case whose upstream call failed can no longer score as passed when the grading regex happens to match the error text (cheaper-inference#13137), and regex grading compiles with dotAll so `.` spans newlines in multi-line answers, for both string and `RegExp` patterns (cheaper-inference#13138). Chosen over cheaper-inference#13542 / cheaper-inference#13530, which each covered half. 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!
…on (cheaper-inference#13414) The eval runner sends `x-omniroute-compression: off` and `x-omniroute-no-memory: true`, so cases measure the model rather than injected output styles or retrieved memory (cheaper-inference#13139). Both headers are the existing per-request opt-outs honored by `chatCore` (`open-sse/handlers/chatCore/headers.ts`). 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!
…heaper-inference#13411) The media-providers web-search example card now sends `provider` in the request body. `POST /v1/search` selects the provider from `body.provider`, so the card was silently hitting the default provider (cheaper-inference#13245). 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!
…per-inference#13410) De-duplicates the `agy` and `antigravity` model catalogs into `antigravitySharedModels.ts`, with an explicit per-surface add/remove delta (cheaper-inference#12724). Verified behavior-neutral: every exported catalog constant of both modules serializes byte-identically before and after (201-line JSON dump). Maintainer fix: `buildSurfaceCatalog` returned `readonly { id: string; [k: string]: unknown }[]`, which erased the element type. `name` became `unknown`, and the `RegistryEntry.models` assignments failed with 4× TS2322 under `check:open-sse-typecheck` (not covered by `typecheck:core`). It is now generic (`<T extends { id: string }>`), so the literal model shape flows through. 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!
…ifting at messages[0] (cheaper-inference#13425) (cheaper-inference#13427) Memory injection merges into an Anthropic-shaped top-level `system` field (string or text-block array) instead of prepending a `role: "system"` message at `messages[0]`, which Anthropic rejects with a 400 (cheaper-inference#13425). Handled on both the system-first path (xiaomi-mimo) and the general path. Chosen over cheaper-inference#13549, which covered only the string case. Maintainer fix: widened `ChatRequest.system` to `string | Array<{ type; text?; … }>`. Assigning the block array to the `string`-typed field raised 2× TS2322 under `check:open-sse-typecheck`. 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!
…nce#13369) (cheaper-inference#13433) The CLI readiness budget is configurable through `OMNIROUTE_READY_TIMEOUT_MS` or `omniroute serve --ready-timeout <ms>` (default unchanged at 60s). The timeout warning prints the budget it actually used and suggests a larger value, for slow cold starts such as Windows (cheaper-inference#13369). Documented in `ENVIRONMENT.md` and `TROUBLESHOOTING.md`, with 11 resolver 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!
…heaper-inference#12779) (cheaper-inference#13340) Adds the Microsoft 365 Copilot (BizChat) provider guide for the existing `copilot-m365-web` provider (alias `m365copilot`, `open-sse/config/providers/registry/copilot-m365-web`), including the WebSocket credential capture flow, and links it from the docs index and the web-cookie guide (cheaper-inference#12779). 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!
…bility (fixes cheaper-inference#13467) (cheaper-inference#13539) Adds a `DISABLE_IOREG_STRATEGY=1` escape hatch to the macOS `ioreg` strategy in `getMachineIdRaw()`, so `machineId.test.ts` can reach the fallback strategies on darwin instead of always resolving the real hardware UUID (cheaper-inference#13467). Maintainer note: this branch also carried the "force passed=false when upstream call failed" eval commit, which already landed in cheaper-inference#13413. The branch was reset to the current release tip plus only the ioreg commit (authorship preserved) so the squash carries just this change. 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!
…-only DISABLE_IOREG_STRATEGY (cheaper-inference#13692) Clears the two env-doc drifts the batch introduced. `check:env-doc-sync` is back to the pre-existing base-red set (cheaper-inference#12732). `check-env-doc-sync` unit suite: 13 structural cases green; the 2 live-data cases stay red on the same inherited vars.
…es-delete-completed-authz) (cheaper-inference#13684) Batch sweep enforces the caller's API-key policy (allowedEndpoints/schedule/usage/rate limit; the /api/v1 pathname now resolves its endpoint category for every /v1 route), commits per 200-batch chunk in key mode, guards against no-progress loops, rejects a scope naming both a key and allTenants; 8 covering tests registered for the mutation gate. Remaining CI reds are release base-reds (cheaper-inference#12732), reproduced identically on the base tip. Refs cheaper-inference#12969, cheaper-inference#13680, cheaper-inference#13681, cheaper-inference#13685, cheaper-inference#13377
- PROVIDER_ERROR_TYPES is now `as const`, so ErrorTypeContract is the real literal union instead of `string`; classifyProviderError and classifyCallLogError return the narrowed types. - Move ERROR_TYPE_CUTOVER_ISO and the vocabulary SQL above the JSDoc so the doc block sits on getErrorTypeBreakdown again; build the IN-list lazily so an import cycle can never read the contract before it is initialised. - Tests: drop the duplicated classify assertions, clean up every inserted row in finally blocks, reset the DB handle after the file, and cover that legacy NULL rows keep their pre_migration/unclassified buckets next to the new `unknown` value (counts sum to the failure total) and that the log export / BigQuery projection passes both NULL and `unknown` through.
…pStatus (cheaper-inference#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)
…heaper-inference#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).
…aper-inference#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 (cheaper-inference#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 cheaper-inference#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 cheaper-inference#12732 * fix(models): resolve auto-combo target metadata once per catalog build cheaper-inference#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 cheaper-inference#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 cheaper-inference#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 cheaper-inference#12732 * test(resilience): list credentialHealthCheck in the configuration-only key set cheaper-inference#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 cheaper-inference#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). cheaper-inference#12959 pointed the provenance ref at HEAD, but the cheaper-inference#10427 guard still stops at 'dist/BUILD_SHA is missing' before it ever reaches the ancestry check — reproduced on tip + cheaper-inference#13635 + cheaper-inference#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 cheaper-inference#12732 * docs(env): document OMNIROUTE_SYNCED_CATALOG_STALE_AFTER_MS cheaper-inference#13248 (cheaper-inference#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 cheaper-inference#13635 and cheaper-inference#13361; this touches a different region of .env.example so it does not collide with either. Refs cheaper-inference#12732
…gian, Armenian (66 locales) (cheaper-inference#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: cheaper-inference#12732
…3582) 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 (cheaper-inference#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 (cheaper-inference#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.
…r-inference#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!
…heaper-inference#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 (cheaper-inference#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` (cheaper-inference#12674, cheaper-inference#12698). Superset of cheaper-inference#12675, cheaper-inference#12973 and cheaper-inference#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 (cheaper-inference#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 (cheaper-inference#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 (cheaper-inference#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 (cheaper-inference#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!
…aper-inference#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
merged commit Sep 15, 2026
3266d16
into
cheaper-inference:release/v3.8.51
4 of 7 checks passed
diegosouzapw
pushed a commit
that referenced
this pull request
Sep 15, 2026
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 #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 #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!
diegosouzapw
added a commit
to maxmad64bis/OmniRouteFork
that referenced
this pull request
Sep 15, 2026
- Extract the guard into toStoredErrorType() (callLogs/format.ts) with a Zod enum built once instead of on every write; saveCallLog stores its result. null stays NULL, contract values pass, anything else is unknown. - Test the guard for real: the exported function with out-of-vocabulary values, and saveCallLog end to end with a classifier family that drifted out of the frozen contract (fails without the guard: stores the drifted string). - Drop the SCHEMA_SQL error_type column: migration 158 already adds it on fresh installs, and restore the PRAGMA table_info column test instead of the cwd-dependent source-text search; drop the "migration evaluated and dropped" test that only asserted a string was absent. - Restore cheaper-inference#13281's changelog fragment and rename this PR's own fragment to 13441 with the right link.
diegosouzapw
pushed a commit
that referenced
this pull request
Sep 15, 2026
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; #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!
diegosouzapw
added a commit
to maxmad64bis/OmniRouteFork
that referenced
this pull request
Sep 15, 2026
…tent - The live-provider guard hid every keyless search provider: duckduckgo-free (served with empty credentials), searxng-search and anonymous context7 have no provider_connections row, so their traffic vanished from /api/search/stats and /api/v1/search/analytics while the aggregate totals still counted it. Providers with authType "none" in the search registry are now always live, and a keyed provider is also live through its registry credential fallback (perplexity-search on a `perplexity` key). - NULL and '-' provider rows and keyed providers whose connection was deleted stay hidden, and getSearchAggregateStats applies the same guard so `total` always equals the per-provider breakdown. - Tests use real registry ids (brave-search, tavily-search, duckduckgo-free, searxng-search, context7, perplexity-search) and cover the analytics route. - Restore cheaper-inference#13281's changelog fragment that this branch had deleted.
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
cheaper-inference#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 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!
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…ce#13441) 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 cheaper-inference#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 cheaper-inference#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 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!
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…erence#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; cheaper-inference#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 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
Call-log error types were free text on the way in and whatever-history-had on the way out — typos and stale values flowed straight into the analytics breakdowns. This PR turns
error_typeinto a versioned vocabulary (ERROR_TYPE_CONTRACT v1, derived fromPROVIDER_ERROR_TYPESso it can't drift): unclassifiable failures now log as explicitunknowninstead of ambiguousnull, successes staynull, and the read path maps any free-text history tounclassifiedinstead of leaking it. Change type: DB.Related Issues
Follows the
error_typecolumn work (migration 158, #12832). Search-ghost guards and the error-type index come as separate follow-ups; pricing provenance is out of scope.Validation
npm run lintnpm run lintleft unchecked: full-repo lint not replayed locally (targeted typecheck clean); will confirm on CI.Tests Added Or Updated
tests/unit/call-log-error-type.test.ts(10 → 14): unclassifiable 403 →unknown,status 0with error →unknown,status 0without error →null, success-with-body staysnull, vocabulary sync withPROVIDER_ERROR_TYPES, version constant, boundary cutover behavior (pre-cutover NULL →pre_migration, free-text history →unclassified). Siblingdb-provider-stats2/2 green (NULL-only inserts, unaffected).Coverage Notes
Write path (
src/lib/usage/callLogs/format.ts:176) and read path (src/lib/db/callLogStats.ts:299,CASE+ generatedNOT IN) both covered, including the raw-SQL history inserts the write path can no longer produce.ERROR_TYPE_CUTOVER_ISOcovered by the boundary test (literal interpolated only in theCASE; SQL comment and JSDoc cite the name). SQL column staysTEXTwithout CHECK — the contract lives in TS plus read-mapping, so a durable constraint is a future migration.Reviewer Notes
Base
release/v3.8.51(81bf3cc). One commit, 5 files. Fail-open by construction: no throw on the INSERT path, no log line is ever lost — unknown becomesunknown, never dropped. Accept-called-out hardening: yesterday's free-text value stops passing through as itself and reads back asunknown/unclassified; history rows are never migrated (thepre_migration/unclassifiedbuckets already cover them, including late upgraders).status < 400with an error body staysnull(inherited classifier behavior, unchanged). Newsrc/lib/db → open-sse/servicesimport is a constants leaf, no cycle (errorClassifier.tsimports nothing fromsrc/lib/db). Fragmentchangelog.d/fixes/13281-error-type-contract.md.