Files
OmniRoute/stryker.conf.json
Innokentiy Solntsev dd70dbdaa0 fix(sse): Anthropic OAuth 403 "Request not allowed" is a per-request refusal — cooldown with backoff instead of an instant ban (#12859) (#12864)
* fix(sse): Anthropic OAuth 403 "Request not allowed" is a per-request refusal, not a ban

A single upstream 403 on the `claude` OAuth connection was classified
FORBIDDEN and written as the terminal `banned` connection state
(chatCore -> writeTerminalStatus). From then on every request to that
provider was short-circuited with "All 1 connection(s) banned by
upstream - please reconnect in the dashboard" without touching Anthropic,
until an operator reconnected.

Anthropic's OAuth surface answers a small fraction of otherwise-valid
requests with 403 {"type":"permission_error","message":"Request not
allowed"}. On the reporting install the same token returned 200 forty
seconds before the 403 and again right after the connection was
re-enabled; a revoked or expired token is a 401 authentication_error, not
this. It is a refusal of one request, not of the credential.

Classify it as the new non-terminal PROVIDER_ERROR_TYPES.REQUEST_REJECTED
(scoped to provider `claude` and the "Request not allowed" body) and list
that type in authTerminalStatus.isNonTerminalProviderError, mirroring the
Cloudflare FINGERPRINT_REJECTION precedent. The combo layer still falls
through to the next target for the failing request; the connection stays
active for the next one. Any other claude 403 keeps its previous
classification.

Tests: error-classifier.test.ts covers the Anthropic body, the
gateway-flattened "[403]: Request not allowed" message, the same body from
a non-Anthropic provider (still FORBIDDEN), other claude 403s (unchanged),
and the helpers; anthropic-request-not-allowed-not-a-ban.test.ts pins
resolveTerminalConnectionStatus() -> null for the new type even with a
`permanent` fallback verdict, and `banned` for a generic claude 403.

* fix(sse): cooldown with backoff and streak escalation for REQUEST_REJECTED (#12859)

Not "ignore the 403" either: if Anthropic ever made "Request not allowed"
systematic, re-sending every request into it would be the wrong thing to
do to an OAuth account. chatCore now handles REQUEST_REJECTED explicitly:

- exclude the connection via setConnectionRateLimitUntil for a growing
  cooldown (5 -> 15 -> 45 min) so a sporadic refusal costs minutes, not a
  reconnect, and a systematic one cannot become a stream of 403s;
- escalate to the terminal `banned` state only for 3 refusals within a
  60-minute window (services/requestRejectedStreak.ts, in-memory per
  connection; a restart forgets the streak, erring towards more cooldowns
  rather than an operator-undone ban), with a last_error that says so;
- probe-origin failures record but never cool down or ban (#9817).

The existing "request not allowed" text rule (5 s) is unaffected:
markAccountUnavailable skips a connection that already has a future
rateLimitedUntil, so the minute-scale cooldown written here wins.

Tests: request-rejected-streak.test.ts pins the window/threshold/backoff
arithmetic; anthropic-request-not-allowed-cooldown-escalation.test.ts drives
the real chat route against a mocked 403 upstream on a `claude` OAuth
connection: 300 s cooldown, then 900 s, then banned on the third refusal;
a different claude 403 body still bans on the first response.

* chore(changelog): name the #12859 fragment after its PR (#12864)

* refactor(sse): move the REQUEST_REJECTED branch into a chatCore leaf; register its tests for mutation coverage

chatCore.ts is frozen at 5984 lines by the file-size ratchet; the branch
body now lives in open-sse/handlers/chatCore/requestRejectedFailure.ts
(chatCore: 5974 -> 5983). stryker.conf.json tap.testFiles gains the two new
DB-backed tests so their mutant kills count (check:mutation-test-coverage).

* fix(sse): count refusal episodes, reset on success, keep the dashboard honest (#12859 review)

Review findings on the first cut of the REQUEST_REJECTED handling:

- A burst of in-flight requests that all got the 403 within seconds
  produced streak 1, 2, 3 and a ban from one upstream event. The streak
  now counts cooldown *episodes*: a refusal that lands while the
  connection is already excluded is the same event and is not counted.
- Nothing reset the streak on a healthy response, so sporadic refusals
  on a busy install could still accumulate to a ban. chatHelpers'
  onRequestSuccess now clears it (only a real success does - the recovery
  tick's clearAccountError is an elapsed cooldown, not a success).
  Clearing the cooldown by hand in the dashboard clears it too.
- The third rung of the ladder was unreachable (the third refusal
  escalates): the ladder is now 5 -> 15 min, sourced from COOLDOWN_MS next
  to the existing 5 s "request not allowed" rule, with a note on why that
  rule is superseded for claude. The 60-min window becomes a 24 h
  staleness bound - "consecutive" is defined by successes, not by time.
- Probe-origin refusals no longer touch the streak (#9817).
- The cooldown is written like every other connection-level cooldown:
  ISO rateLimitedUntil + testStatus "unavailable" (+ lastErrorAt), so the
  dashboard shows the countdown and the recovery tick restores "active".
- One refusal is re-seeded from the persisted row after a restart so a
  crash loop cannot reset the count on every boot.

Docs: RESILIENCE_GUIDE terminal states + CODEBASE_DOCUMENTATION resilience
row mention the streak module. Tests cover the burst, the success reset,
the seed, and the ISO/unavailable shape end-to-end through the chat route.

* chore(sse): drop unrelated Prettier churn in auth.ts / providers route

* style(api): keep providers route Prettier-clean

* refactor(sse): share the "exclude connection for a cooldown" leaf between GEO_BLOCKED, GCP_PROJECT_REQUIRED and the new branch

The release tip moved chatCore.ts to its frozen 5984 lines, so the
REQUEST_REJECTED branch cannot add a single net line. The GEO_BLOCKED and
GCP_PROJECT_REQUIRED branches were the same eight statements with different
constants and log wording; both now call
open-sse/handlers/chatCore/connectionCooldown.ts::excludeConnectionForCooldown
(behaviour, probe guard and log lines preserved verbatim). chatCore.ts ends
9 lines below the base it branched from.

* chore(chatCore): tighten the cooldown comments to keep the file under its size ceiling

After merging release/v3.8.51, chatCore.ts sat at 6150 lines against a
frozen ceiling of 6146. Condense the explanatory comments this PR added
to the GEO_BLOCKED and GCP_PROJECT_REQUIRED branches; no code change.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: insoln <is@careerum.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
2026-09-17 16:26:08 -03:00

623 lines
34 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"$schema": "https://stryker-mutator.io/schemas/stryker-schema.json",
"_comment": [
"Mutation testing for the ~8 critical modules (Task 11 — Fase 7).",
"NIGHTLY ONLY — DO NOT run on every PR. Mutation testing is expensive:",
" - Each mutant requires a full test suite execution.",
" - The 8 modules produce ~200500 mutants; est. 3090 min per run.",
" - Wired to the nightly CI workflow (.github/workflows/nightly-mutation.yml),",
" NOT to the 'lint' / 'quality-gate' PR jobs.",
"",
"TEST RUNNER — @stryker-mutator/tap-runner (NOT vitest):",
" The 8 critical modules are covered by node:test files in tests/unit/",
" (run via `node --import tsx --test`), NOT by vitest. The vitest config",
" only includes a small set of .test.tsx + open-sse/**/__tests__ files, so",
" the vitest-runner would find ZERO covering tests for these modules. The",
" tap-runner spawns each node:test file individually and parses its TAP",
" output, which matches how this repo actually exercises the modules.",
" Each test file is loaded with tsx (TypeScript/ESM) + the project polyfill,",
" the same way `npm run test:unit` runs.",
"",
"Install before running (not bundled to avoid E2E / CI bloat):",
" npm install --save-dev @stryker-mutator/core @stryker-mutator/tap-runner",
"",
"Run manually:",
" npm run test:mutation # full run (slow — nightly budget)",
" npx stryker run --dryRunOnly # validate the baseline only (no mutants)",
" (single-module probe: temporarily narrow `mutate` + `tap.testFiles` in this file)",
"",
"VALIDATED 2026-06-15: `npx stryker run --dryRunOnly` exits 0 — all 129 covering",
"test files run green in the Stryker sandbox and the perTest coverage map builds for",
"all 8 instrumented modules (15k+ mutants). The baseline dry-run takes ~20 min with",
"concurrency=1; the full mutation phase runs on top (advisory, capped by the workflow",
"timeout). So the nightly produces REAL mutation scores for the 8 modules.",
"",
"Mutation score per module → quality-baseline.json key 'mutationScore.<module>'",
"Direction: up (score can only improve; ratchet blocks drops — wired in a later INT phase)."
],
"packageManager": "npm",
"incremental": true,
"incrementalFile": "reports/mutation/stryker-incremental.json",
"testRunner": "tap",
"plugins": ["@stryker-mutator/tap-runner"],
"tap": {
"testFiles": [
"tests/unit/10085-compatible-generic-vs-uuid-credential.test.ts",
"tests/unit/7993-noauth-proxy-routing.test.ts",
"tests/unit/8200-perplexity-web-401-cooldown.test.ts",
"tests/unit/8247-accountfallback-model-unhealthy.test.ts",
"tests/unit/8248-accountfallback-nvidia-degraded.test.ts",
"tests/unit/8332-combo-vision-fallback.test.ts",
"tests/unit/8376-econnrefused-breaker.test.ts",
"tests/unit/8396-cooldown-429-cap.test.ts",
"tests/unit/8488-capability-filter-fail-closed.test.ts",
"tests/unit/8779-agy-prefix-credential-lookup.test.ts",
"tests/unit/account-fallback-anthropic-quota.test.ts",
"tests/unit/account-fallback-cf1010-no-retry-8775.test.ts",
"tests/unit/account-fallback-lockout-eviction.test.ts",
"tests/unit/account-fallback-retry-after-json.test.ts",
"tests/unit/account-fallback-route-restriction-403.test.ts",
"tests/unit/account-fallback-service.test.ts",
"tests/unit/chat-correlation-id-exhaustion.test.ts",
"tests/unit/combo-pin-implicit-allowlist.test.ts",
"tests/unit/combo-predicates-epoch-cooldown.test.ts",
"tests/unit/combo/execute-target-gates.test.ts",
"tests/unit/moonshot-quota-writeback.test.ts",
"tests/unit/accountfallback-ratelimit-400-4976.test.ts",
"tests/unit/adaptive-admission-route-matrix.test.ts",
"tests/unit/adaptive-admission-runtime.test.ts",
"tests/unit/adobe-firefly.test.ts",
"tests/unit/aihorde-optional-api-key.test.ts",
"tests/unit/agentrouter-error-rules.test.ts",
"tests/unit/agentrouter-lock-scope-10334.test.ts",
"tests/unit/alibaba-free-tier-exhaustion.test.ts",
"tests/unit/anthropic-thinking-signature-recovery.test.ts",
"tests/unit/anthropic-request-not-allowed-cooldown-escalation.test.ts",
"tests/unit/anthropic-request-not-allowed-not-a-ban.test.ts",
"tests/unit/agy-family-not-connection-cooldown.test.ts",
"tests/unit/agy-quota-exhaustion-threshold.test.ts",
"tests/unit/antigravity-429-quota-cooldown.test.ts",
"tests/unit/antigravity-429-quota-tdd.test.ts",
"tests/unit/antigravity-prefer-stored-project.test.ts",
"tests/unit/api-key-policy-noauth-allowed-connections.test.ts",
"tests/unit/api-key-rotator-health.test.ts",
"tests/unit/chat-routing-synced-inventory-11089.test.ts",
"tests/unit/openai-compatible-per-upstream-402-health.test.ts",
"tests/unit/opencode-400-model-unavailable.test.ts",
"tests/unit/quota-window-label.test.ts",
"tests/unit/repro-combo-persisted-cooldown-preskip.test.ts",
"tests/unit/repro-glm-iso-reset-24h-cap.test.ts",
"tests/unit/security-route-guard-tiers.test.ts",
"tests/unit/egress-ip-lock-10880.test.ts",
"tests/unit/egress-lock-allowlist-10880.test.ts",
"tests/unit/api/jobs.test.ts",
"tests/unit/appearance-widget-settings-schema.test.ts",
"tests/unit/auth-anonymous-fallback-toggle.test.ts",
"tests/unit/auth-antigravity-account-retry-v2.test.ts",
"tests/unit/auth-clear-account-error.test.ts",
"tests/unit/auth-disable-cooling-2997.test.ts",
"tests/unit/auth-extract-api-key.test.ts",
"tests/unit/auth-noauth-fallback-loop-3061.test.ts",
"tests/unit/auth-ollama-cloud-per-model-403-3027.test.ts",
"tests/unit/auth-opencode-zen-noauth-fallback.test.ts",
"tests/unit/auth-passthrough-per-model-402-12242.test.ts",
"tests/unit/auth-terminal-status.test.ts",
"tests/unit/authz/credential-export-always-protected.test.ts",
"tests/unit/authz/discovery-routes-local-only.test.ts",
"tests/unit/authz/oauth-autoimport-local-only.test.ts",
"tests/unit/authz/route-guard-local-prefix.test.ts",
"tests/unit/authz/route-guard-skills-collect.test.ts",
"tests/unit/authz/route-guard-tunnel-processes-local-only.test.ts",
"tests/unit/authz/route-guard-version-get-exemption.test.ts",
"tests/unit/authz/route-guard-vnc-session-local-only.test.ts",
"tests/unit/authz/routeGuard.test.ts",
"tests/unit/auto-combo-candidates-locked-model-visible.test.ts",
"tests/unit/auto-combo-context-advertising.test.ts",
"tests/unit/auto-combo-engine.test.ts",
"tests/unit/auto-combo-scoring-clamp.test.ts",
"tests/unit/breaker-network-error-guard.test.ts",
"tests/unit/bug-7940-gemini-retrydelay.test.ts",
"tests/unit/bug-9204-agy-provider-alias-credentials.test.ts",
"tests/unit/build/check-circular-deps.test.ts",
"tests/unit/cache-sweeps.test.ts",
"tests/unit/capability-filter.test.ts",
"tests/unit/cc-bridge-openai-image-7777.test.ts",
"tests/unit/cc-compatible-provider.test.ts",
"tests/unit/chat-adaptive-admission-binding.test.ts",
"tests/unit/chat-combo-live-test.test.ts",
"tests/unit/chat-context-relay.test.ts",
"tests/unit/chat-cooldown-aware-retry.test.ts",
"tests/unit/chat-helpers.test.ts",
"tests/unit/chat-stream-early-eof-failover.test.ts",
"tests/unit/chatgpt-web-codex.test.ts",
"tests/unit/chat-route-coverage.test.ts",
"tests/unit/chat-route-edge-cases.test.ts",
"tests/unit/chatcore-codex-account-pool.test.ts",
"tests/unit/chatcore-compression-integration.test.ts",
"tests/unit/chatcore-executor-helpers.test.ts",
"tests/unit/chatcore-executor-proxy.test.ts",
"tests/unit/chatcore-extracted-modules-3821.test.ts",
"tests/unit/chatcore-header-drop-warn-dedupe-10315.test.ts",
"tests/unit/chatcore-headers.test.ts",
"tests/unit/chatcore-imports-cleanly.test.ts",
"tests/unit/chatcore-log-truncation.test.ts",
"tests/unit/chatcore-memory-extraction.test.ts",
"tests/unit/chatcore-memory-skills-injection.test.ts",
"tests/unit/chatcore-non-streaming-sse.test.ts",
"tests/unit/chatcore-passthrough-tool-names.test.ts",
"tests/unit/chatcore-request-format.test.ts",
"tests/unit/chatcore-sanitization.test.ts",
"tests/unit/chatcore-semantic-cache-store.test.ts",
"tests/unit/chatcore-semantic-cache.test.ts",
"tests/unit/chatcore-strip-stale-headers.test.ts",
"tests/unit/chatcore-telemetry-helpers.test.ts",
"tests/unit/chatcore-translation-paths.test.ts",
"tests/unit/chatcore-upstream-timeouts.test.ts",
"tests/unit/check-error-helper.test.ts",
"tests/unit/check-route-guard-membership.test.ts",
"tests/unit/check-test-discovery.test.ts",
"tests/unit/circuit-breaker-abort-provider-trip-7907.test.ts",
"tests/unit/circuit-breaker-client-abort.test.ts",
"tests/unit/circuit-breaker-failure-kind.test.ts",
"tests/unit/circuit-breaker-local-execution.test.ts",
"tests/unit/circuit-breaker-registry-cap.test.ts",
"tests/unit/circuit-breaker-resolved-5xx-12254.test.ts",
"tests/unit/circuit-breaker-stream-controller-4602.test.ts",
"tests/unit/overloaded-not-provider-breaker.test.ts",
"tests/unit/claude-code-parity.test.ts",
"tests/unit/claude-effort-suffix-strip.test.ts",
"tests/unit/claude-oauth-provider.test.ts",
"tests/unit/claude-passthrough-stream-boolean.test.ts",
"tests/unit/claude-passthrough-thinking-2454.test.ts",
"tests/unit/cli-simulate.test.ts",
"tests/unit/cline-response-envelope.test.ts",
"tests/unit/clinepass-provider.test.ts",
"tests/unit/cliproxyapi-dedicated-credential-7645.test.ts",
"tests/unit/cliproxyapi-model-mapping-dispatch.test.ts",
"tests/unit/codex-failover.test.ts",
"tests/unit/codex-quota-selection-hydration.test.ts",
"tests/unit/codex-responses-to-chat-9161.test.ts",
"tests/unit/codex-same-account-transport-retry-9708.test.ts",
"tests/unit/codex-session-affinity-reset-aware-5903.test.ts",
"tests/unit/codex-stream-false.test.ts",
"tests/unit/codex-turn-state.test.ts",
"tests/unit/collect-metrics-module-coverage.test.ts",
"tests/unit/combo-499-abort.test.ts",
"tests/unit/combo-account-allowlist-3266.test.ts",
"tests/unit/combo-attempt-body-isolation-7847.test.ts",
"tests/unit/combo-auto-candidate-expansion.test.ts",
"tests/unit/combo-breaker-429.test.ts",
"tests/unit/combo-cache-invalidation.test.ts",
"tests/unit/combo-config.test.ts",
"tests/unit/combo-context-relay.test.ts",
"tests/unit/combo-diagnostics-trace.test.ts",
"tests/unit/combo-dispatch-prelude.test.ts",
"tests/unit/combo-headroom-strategy.test.ts",
"tests/unit/combo-health-dashboard.test.ts",
"tests/unit/combo-health-route.test.ts",
"tests/unit/combo-hedging.test.ts",
"tests/unit/combo-least-used-account.test.ts",
"tests/unit/combo-lockout-quota-reset-6863.test.ts",
"tests/unit/combo-max-depth-config.test.ts",
"tests/unit/combo-model-lockout-honors-reset-1308.test.ts",
"tests/unit/combo-model-scoped-400-advance.test.ts",
"tests/unit/combo-omnimodel-tag-stripping.test.ts",
"tests/unit/combo-param-validation-fallback-4519.test.ts",
"tests/unit/combo-prescreen.test.ts",
"tests/unit/combo-priority-quota-exhaustion-cutoff-5923.test.ts",
"tests/unit/combo-provider-cooldown-sibling.test.ts",
"tests/unit/combo-provider-cooldown.test.ts",
"tests/unit/combo-provider-diversity-wiring.test.ts",
"tests/unit/combo-quality-validator-reasoning.test.ts",
"tests/unit/combo-quota-exhaustion-only-fallback.test.ts",
"tests/unit/combo-quota-share-cooldown-wait.test.ts",
"tests/unit/combo-quota-soft-penalty.test.ts",
"tests/unit/combo-resource-404-health.test.ts",
"tests/unit/combo-round-robin-streaming-lock-3811.test.ts",
"tests/unit/combo-roundrobin-compat-fallback-6238.test.ts",
"tests/unit/combo-routing-engine.test.ts",
"tests/unit/combo-rr-diagnostics-11462.test.ts",
"tests/unit/combo-rr-fallback-advance-948.test.ts",
"tests/unit/combo-rr-sticky-9router.test.ts",
"tests/unit/combo-scoring-inspector.test.ts",
"tests/unit/combo-selected-connection-success.test.ts",
"tests/unit/combo-sessionless-pin-3825.test.ts",
"tests/unit/combo-skip-conn-disable-plugin-block-7806.test.ts",
"tests/unit/combo-speed-telemetry-6875.test.ts",
"tests/unit/combo-strategies.test.ts",
"tests/unit/combo-strategy-fallbacks.test.ts",
"tests/unit/combo-stream-readiness-fallback.test.ts",
"tests/unit/combo-streaming-empty-content-failover.test.ts",
"tests/unit/combo-strict-random-distribution-3959.test.ts",
"tests/unit/combo-system-prompt-templates-5501.test.ts",
"tests/unit/combo-target-defensive-modelstr.test.ts",
"tests/unit/combo-vision-aware-routing.test.ts",
"tests/unit/combo-weighted-all-targets-cooling-down.test.ts",
"tests/unit/combo/auto-quota-cutoff.test.ts",
"tests/unit/combo/auto-status-penalty-4540.test.ts",
"tests/unit/combo/combo-exhausted-skip.test.ts",
"tests/unit/combo/combo-target-timeout-standards.test.ts",
"tests/unit/combo/effective-max-concurrency.test.ts",
"tests/unit/combo/protected-priority-stop-status-13439.test.ts",
"tests/unit/combo/quota-connection-eligibility.test.ts",
"tests/unit/combo/quota-weighted-stale-402.test.ts",
"tests/unit/combo/quota-weighted-strategy.test.ts",
"tests/unit/combo/recovery-hint.test.ts",
"tests/unit/combo/reset-window-strategy-9330.test.ts",
"tests/unit/complexity-aware-scoring-wiring.test.ts",
"tests/unit/compression-header-verification.test.ts",
"tests/unit/context-pinning-tool-calls.test.ts",
"tests/unit/cooldown-epoch-string-3954.test.ts",
"tests/unit/correctness/combo.property.test.ts",
"tests/unit/correctness/sanitizers.property.test.ts",
"tests/unit/cursor-renewal.test.ts",
"tests/unit/custom-model-target-format.test.ts",
"tests/unit/daily-reset-dst-gap.test.ts",
"tests/unit/daily-reset-tz-threading.test.ts",
"tests/unit/db-reset-module-state.test.ts",
"tests/unit/db-server-tool-executions-migration.test.ts",
"tests/unit/db/stats-dbstat-optional.test.ts",
"tests/unit/ddg-circuit-breaker-null-content-6999-7000.test.ts",
"tests/unit/domain-persistence.test.ts",
"tests/unit/embedding-account-cooldown-10347.test.ts",
"tests/unit/embedding-cooldown-integration-10347.test.ts",
"tests/unit/embeddings-auth.test.ts",
"tests/unit/error-classification.test.ts",
"tests/unit/error-message-sanitization.test.ts",
"tests/unit/error-sanitizer-sk-key-qv45.test.ts",
"tests/unit/error-sensitive-redaction.test.ts",
"tests/unit/execute-chat-resource-pressure-breaker.test.ts",
"tests/unit/executor-antigravity.test.ts",
"tests/unit/executor-contract-violation-terminal.test.ts",
"tests/unit/executor-devin-cli-agentic-acp.test.ts",
"tests/unit/executor-web-cookie-sweep.test.ts",
"tests/unit/explicit-inactive-probe-w2.test.ts",
"tests/unit/false-terminal-401-quota.test.ts",
"tests/unit/follow-up-transcript.test.ts",
"tests/unit/format-provider-error-cause.test.ts",
"tests/unit/forwarded-header-budget.test.ts",
"tests/unit/free-badge-provider-gate.test.ts",
"tests/unit/fusion-vision-panel-3378.test.ts",
"tests/unit/gemini-deprecated-model-lockout.test.ts",
"tests/unit/gemini-web-capabilities-9356.test.ts",
"tests/unit/gemini-web-missing-browser-3516.test.ts",
"tests/unit/github-model-not-supported-lockout.test.ts",
"tests/unit/grok-cli-oauth.test.ts",
"tests/unit/guardrails-api-3496.test.ts",
"tests/unit/guardrails/combo-vision-provider-id-12112.test.ts",
"tests/unit/guardrails/visionBridge-responses-9597.test.ts",
"tests/unit/headroom-codex-quota-snapshot-6379.test.ts",
"tests/unit/headroom-proxy-lifecycle.test.ts",
"tests/unit/idempotency-fusion-collision.test.ts",
"tests/unit/isLocalStreamLifecycleError-abort-shape.test.ts",
"tests/unit/issue-6343-v0-web-alias-collision.test.ts",
"tests/unit/issue-6638-ollama-quota.test.ts",
"tests/unit/issue-6686-quota-preflight-coverage.test.ts",
"tests/unit/issue-7071-ollama-session-quota.test.ts",
"tests/unit/kimi-quota-reset-recovery.test.ts",
"tests/unit/least-used-rotation-10945.test.ts",
"tests/unit/lkgp-stale-pin-exhaustion-11911.test.ts",
"tests/unit/search-432-plan-limit-cooldown.test.ts",
"tests/unit/livews-forward-backoff-4604.test.ts",
"tests/unit/local-token-budget-429-skips-cooldown.test.ts",
"tests/unit/management-auth-hardening.test.ts",
"tests/unit/mark-account-unavailable-numeric-epoch-guard.test.ts",
"tests/unit/masked-200-exhaustion-fallback-6427.test.ts",
"tests/unit/mcp-connect-scope.test.ts",
"tests/unit/memory-embedding-remote.test.ts",
"tests/unit/memory-embedding-transformers.test.ts",
"tests/unit/middleware-header-strip-5849.test.ts",
"tests/unit/middleware-hooks-error-sanitization.test.ts",
"tests/unit/model-catalog-runtime-invalidation.test.ts",
"tests/unit/model-cooldowns-route-auth.test.ts",
"tests/unit/model-cooldowns-route.test.ts",
"tests/unit/model-lockout-decay.test.ts",
"tests/unit/model-lockout-exact-cooldown-cap.test.ts",
"tests/unit/model-lockout-5xx-exact-scope.test.ts",
"tests/unit/model-lockout-max-cooldown.test.ts",
"tests/unit/native-codex-turn-pin-10379.test.ts",
"tests/unit/native-codex-turn-pin-model-scoped-fallback.test.ts",
"tests/unit/no-memory-header.test.ts",
"tests/unit/noauth-autocombo-lockout-7623.test.ts",
"tests/unit/noauth-model-lockout.test.ts",
"tests/unit/provider-401-ambiguous-runtime.test.ts",
"tests/unit/agnes-cn-provider.test.ts",
"tests/unit/mcp-restart-route-13012.test.ts",
"tests/unit/antigravityUpstreamError.test.ts",
"tests/unit/issue-13089-roundrobin-live-ws-events.test.ts",
"tests/unit/ollama-404-model-lockout-11071.test.ts",
"tests/unit/non-streaming-client-translate.test.ts",
"tests/unit/non-streaming-provider-leg.test.ts",
"tests/unit/non-streaming-sse-terminal-typescan-4459.test.ts",
"tests/unit/nvidia-410-model-scope.test.ts",
"tests/unit/nvidia-passthrough-models-6773.test.ts",
"tests/unit/nvidia-quota-phase1.test.ts",
"tests/unit/oauth-providers-config.test.ts",
"tests/unit/oauth-redirect-uri-mismatch.test.ts",
"tests/unit/observability-fase04.test.ts",
"tests/unit/observability-payloads.test.ts",
"tests/unit/ollama-cloud-weekly-quota-cooldown-3709.test.ts",
"tests/unit/openapi-security-tiers.test.ts",
"tests/unit/claude-to-openai-glm-user-turn.test.ts",
"tests/unit/opencode-autocombo-search-pair.test.ts",
"tests/unit/opencode-muse-spark-min-output.test.ts",
"tests/unit/opencode-v2-config-11070.test.ts",
"tests/unit/openrouter-free-model-credits-exhausted.test.ts",
"tests/unit/openrouter-passthrough-models.test.ts",
"tests/unit/openrouter-quota-6842.test.ts",
"tests/unit/permanent-failure-hammering-other-providers.test.ts",
"tests/unit/persist-429-cooldown-account-fallback.test.ts",
"tests/unit/plan3-p0.test.ts",
"tests/unit/plugin-sandbox-permissions.test.ts",
"tests/unit/plugins-route-error-sanitization.test.ts",
"tests/unit/probe-gate-autodisable.test.ts",
"tests/unit/probe-production-path.test.ts",
"tests/unit/probe-testall-isolation.test.ts",
"tests/unit/provider-breaker-halfopen-recovery.test.ts",
"tests/unit/provider-error-rules.test.ts",
"tests/unit/provider-execution-pipeline.test.ts",
"tests/unit/provider-health-matrix.test.ts",
"tests/unit/provider-request-failure-pipeline.test.ts",
"tests/unit/providers-route-codex-account-pool.test.ts",
"tests/unit/proxy-logs-egress-lookup-10880.test.ts",
"tests/unit/public-client-ids-3493.test.ts",
"tests/unit/publicCreds.test.ts",
"tests/unit/qoder-oauth-config.test.ts",
"tests/unit/quota-exhaustion-cutoff-opencode.test.ts",
"tests/unit/quota-groups-route.test.ts",
"tests/unit/quota-key-models-route.test.ts",
"tests/unit/quota-policy-generalization.test.ts",
"tests/unit/quota-pool-log-route.test.ts",
"tests/unit/quota-scoring-alias-lookup-10877.test.ts",
"tests/unit/quota-streaming-consumption-usd.test.ts",
"tests/unit/rate-limit-enhanced.test.ts",
"tests/unit/rate-limit-execution-timeout-message-4165.test.ts",
"tests/unit/rate-limit-local-capacity-classification.test.ts",
"tests/unit/rate-limit-local-error-classification.test.ts",
"tests/unit/rate-limit-manager.test.ts",
"tests/unit/rate-limit-queue-timeout-lockout.test.ts",
"tests/unit/repro-7503-no-choices.test.ts",
"tests/unit/repro-9486.test.ts",
"tests/unit/repro-9630-combo-false-503.test.ts",
"tests/unit/repro-antigravity-404-family-cooldown-hijack.test.ts",
"tests/unit/repro-combo-persisted-cooldown-preskip.test.ts",
"tests/unit/repro-glm-iso-reset-24h-cap.test.ts",
"tests/unit/reset-aware-request-scope-12600.test.ts",
"tests/unit/resilience-connections.test.ts",
"tests/unit/responses-handler.test.ts",
"tests/unit/responses-passthrough-openai-compatible.test.ts",
"tests/unit/retry-after-provenance.test.ts",
"tests/unit/rotation-config-omniroute.test.ts",
"tests/unit/route-explainability.test.ts",
"tests/unit/route-guard-acp-agents-local-only.test.ts",
"tests/unit/route-guard-cli-tools-settings-local-only.test.ts",
"tests/unit/route-guard-cursor-agent-availability.test.ts",
"tests/unit/route-guard-cursor-refresh.test.ts",
"tests/unit/route-guard-forge-jcode-settings-local-only.test.ts",
"tests/unit/route-guard-grok-build-settings-local-only.test.ts",
"tests/unit/route-guard-middleware-local-only.test.ts",
"tests/unit/route-guard-plugins-local-only.test.ts",
"tests/unit/route-guard-private-lan.test.ts",
"tests/unit/route-guard-provider-login-local-only.test.ts",
"tests/unit/route-guard-qwen-settings-local-only.test.ts",
"tests/unit/route-guard-skills-execute-local-only.test.ts",
"tests/unit/router-strategies.test.ts",
"tests/unit/routing-adaptive-e2e.test.ts",
"tests/unit/rule12-error-sanitization-sweep.test.ts",
"tests/unit/serial/combo-health-autopilot.test.ts",
"tests/unit/serial/combo-quota-share-cooldown-wait-timing.test.ts",
"tests/unit/serial/combo-strategy-fallbacks-half-open-timing.test.ts",
"tests/unit/serial/provider-health-autopilot.test.ts",
"tests/unit/server-owned-tool-loop-flag.test.ts",
"tests/unit/server-owned-tool-loop.test.ts",
"tests/unit/skill-execution-fence.test.ts",
"tests/unit/skills-interception-server-owned.test.ts",
"tests/unit/service-combo-metrics.test.ts",
"tests/unit/service-provider-plugin-registry.test.ts",
"tests/unit/services-branch-hardening.test.ts",
"tests/unit/services/bifrost-route-guard.test.ts",
"tests/unit/services/combo-metrics-memory.test.ts",
"tests/unit/session-affinity-generic-7274.test.ts",
"tests/unit/settings/authz-bypass.test.ts",
"tests/unit/skip-provider-breaker-consumer-2743.test.ts",
"tests/unit/sse-auth-antigravity-credits.test.ts",
"tests/unit/sse-auth-codex-account-pool.test.ts",
"tests/unit/sse-auth-exclusive-leases.test.ts",
"tests/unit/sse-auth-resource-404.test.ts",
"tests/unit/sse-auth.test.ts",
"tests/unit/stable-json.test.ts",
"tests/unit/stream-early-eof-breaker.test.ts",
"tests/unit/stream-recovery-toolcall.test.ts",
"tests/unit/stream-readiness.test.ts",
"tests/unit/strict-random-deck.test.ts",
"tests/unit/strip-reasoning-header.test.ts",
"tests/unit/system-role-extraction.test.ts",
"tests/unit/t23-t24-fallback-resilience.test.ts",
"tests/unit/tag-routing.test.ts",
"tests/unit/thundering-herd.test.ts",
"tests/unit/token-refresh-race-comprehensive.test.ts",
"tests/unit/token-refresh-service.test.ts",
"tests/unit/tool-loop-usage.test.ts",
"tests/unit/tools-filter-anthropic-format.test.ts",
"tests/unit/tproxy-route.test.ts",
"tests/unit/trae-publiccred.test.ts",
"tests/unit/types-barrel-model-cooldown.test.ts",
"tests/unit/universal-quota-aware-routing.test.ts",
"tests/unit/upstream-error-passthrough.test.ts",
"tests/unit/upstream-retry-hints-toggle.test.ts",
"tests/unit/upstream-timeout-connection-tier.test.ts",
"tests/unit/upstream-timeout-model-override.test.ts",
"tests/unit/usage-service-hardening.test.ts",
"tests/unit/validate-response-quality.test.ts",
"tests/unit/vertex-passthrough-model-lockout.test.ts",
"tests/unit/video-bridge-drilldown-consumer-route.test.ts",
"tests/unit/video-bridge-drilldown-route.test.ts",
"tests/unit/video-bridge-memory-suppression.test.ts",
"tests/unit/video-bridge-route-security.test.ts",
"tests/unit/xai-agent-tools-passthrough.test.ts",
"tests/unit/combo/connection-aware-expansion.test.ts",
"tests/unit/chatgpt-web-runtime-block.test.ts",
"tests/unit/felo-web-runtime-block.test.ts",
"tests/unit/microsoft-designer-web-runtime-block.test.ts",
"tests/unit/qwen-web-runtime-block.test.ts",
"tests/unit/tunnel-routes-error-sanitization.test.ts",
"tests/unit/auth-grok-cli-402-shared-wallet.test.ts",
"tests/unit/chat-correlation-id-exhaustion.test.ts",
"tests/unit/cline-401-oauth-12594.test.ts",
"tests/unit/cliproxyapi-unknown-provider-400-12800.test.ts",
"tests/unit/combo-predicates-epoch-cooldown.test.ts",
"tests/unit/combo/combo-skipped-targets-summary.test.ts",
"tests/unit/context-handoff-native-passthrough-bug.test.ts",
"tests/unit/guardrails/visionBridge12111Repro.test.ts",
"tests/unit/guardrails/visionBridgeRouter.test.ts",
"tests/unit/issue-11912-opencode-roundrobin-collapse.test.ts",
"tests/unit/opencode-400-model-unavailable.test.ts",
"tests/unit/strong-credential-token-linear-scan.test.ts",
"tests/unit/provider-401-ambiguous-runtime.test.ts",
"tests/unit/13601-header-drop-count-surfaced.test.ts",
"tests/unit/combo-identical-error-streak.test.ts",
"tests/unit/semantic-cache-no-truncated-writes.test.ts"
],
"nodeArgs": [
"--import",
"tsx",
"--import",
"./open-sse/utils/setupPolyfill.ts",
"--import",
"./tests/_setup/isolateDataDir.ts",
"--test-reporter=tap",
"-r",
"{{hookFile}}",
"{{testFile}}"
]
},
"_mutate_godfiles_excluded_comment": [
"2026-06-18 (Onda 2 budget): chatCore.ts + combo.ts — the two god-files — were REMOVED",
"from `mutate`. They dominated ~2/3 of the ~15k mutants; the full 8-module run TIMED OUT",
"at the 180min nightly cap (run 27705123780: 16:47:33 -> killed 19:47:48 = exactly 180min;",
"the prior 120min scheduled run also timed out). #4078 made concurrency safe but the",
"tap-runner re-spawns a node process per test file PER MUTANT, so spawn cost dominates and",
"15k mutants does not fit.",
"",
"2026-06-18 (Onda 3 / Fase 9 T5 re-add): the combo.ts god-file was split into 11 small",
"leaf modules under open-sse/services/combo/ (PRs #4162/#4175/#4186/#4196/#4204). The",
"routing LOGIC that justified combo.ts being in `mutate` now lives in those leaves, so the",
"10 well-covered combo/* leaves are ADDED back to `mutate` here (comboStructure/autoStrategy/",
"validateQuality/shadowRouting/targetSorters/comboPredicates/rrState/comboData + the reset-aware",
"quota pair quotaScoring/quotaStrategies, added after #4204 (D7b) merged). They are covered by",
"the 24 combo-*.test.ts files already in tap.testFiles (quota by combo-prescreen/combo-config/",
"combo-strategy-fallbacks). types.ts is omitted (pure type declarations produce 0 mutants).",
"",
"chatCore/* leaves: a covering-test audit found 6 with direct unit coverage (batch g:",
"comboContextCache/idempotency/passthroughHelpers/responseHeaders/sanitization/upstreamTimeouts).",
"A follow-up then added DEDICATED unit tests for 6 more leaves (tests/unit/chatcore-headers,",
"-log-truncation, -memory-extraction, -non-streaming-sse, -passthrough-tool-names,",
"-executor-helpers — wired into tap.testFiles above) and added those leaves as batch h",
"(headers/logTruncation/memoryExtraction/nonStreamingSse/passthroughToolNames/executorHelpers).",
"A later follow-up added dedicated tests (NO mock.module — unavailable under the tap-runner; used",
"fetch-override + crafted inputs + temp-DATA_DIR) for telemetryHelpers (both fns, all branches) and",
"memorySkillsInjection (getSkillsProviderForFormat fully + injectMemoryAndSkills guards/empty-DB",
"path) and added them as batch i.",
"",
"The FINAL chatCore leaf, semanticCache.ts, was added to batch i once its cache-HIT block had a",
"fixture: chatcore-semantic-cache now SEEDS the real cache via setCachedResponse (the in-memory",
"store getCachedResponse checks first — no mock.module needed) under the exact signature",
"checkSemanticCache rebuilds, so the HIT branch runs end-to-end (status 200 / 'semantic' / 'HIT' /",
"the stream + content-type ternaries / the cost fallback / the side-effect calls all get killed).",
"ALL 15 chatCore leaves are now mutated.",
"",
"STILL EXCLUDED (follow-ups, NOT in `mutate` yet):",
" - combo.ts + chatCore.ts barrels: their handleComboChat/handleChatCore CORES were not",
" split (out of scope — Fase 3 ChatCoreContext refactor). The barrels are now thin-ish",
" but still large; keep excluded until the cores are split.",
"See project memory: Quality Gate v2 / Fase 9 (project-combo-split)."
],
"mutate": [
"open-sse/services/accountFallback.ts",
"src/sse/services/auth.ts",
"src/server/authz/routeGuard.ts",
"open-sse/utils/error.ts",
"open-sse/utils/publicCreds.ts",
"src/shared/utils/circuitBreaker.ts",
"open-sse/services/combo/comboStructure.ts",
"open-sse/services/combo/autoStrategy.ts",
"open-sse/services/combo/validateQuality.ts",
"open-sse/services/combo/shadowRouting.ts",
"open-sse/services/combo/targetSorters.ts",
"open-sse/services/combo/comboPredicates.ts",
"open-sse/services/combo/rrState.ts",
"open-sse/services/combo/comboData.ts",
"open-sse/services/combo/quotaScoring.ts",
"open-sse/services/combo/quotaStrategies.ts",
"open-sse/handlers/chatCore/comboContextCache.ts",
"open-sse/handlers/chatCore/idempotency.ts",
"open-sse/handlers/chatCore/passthroughHelpers.ts",
"open-sse/handlers/chatCore/responseHeaders.ts",
"open-sse/handlers/chatCore/sanitization.ts",
"open-sse/handlers/chatCore/upstreamTimeouts.ts",
"open-sse/handlers/chatCore/headers.ts",
"open-sse/handlers/chatCore/logTruncation.ts",
"open-sse/handlers/chatCore/memoryExtraction.ts",
"open-sse/handlers/chatCore/nonStreamingSse.ts",
"open-sse/handlers/chatCore/passthroughToolNames.ts",
"open-sse/handlers/chatCore/executorHelpers.ts",
"open-sse/handlers/chatCore/telemetryHelpers.ts",
"open-sse/handlers/chatCore/memorySkillsInjection.ts",
"open-sse/handlers/chatCore/semanticCache.ts"
],
"_ignorePatterns_comment": [
"ignorePatterns = files NOT copied into the Stryker sandbox. It does NOT scope",
"what gets mutated (that is the `mutate` array above). The test files MUST be",
"copied so the tap-runner can find covering tests, so DO NOT ignore tests/ here.",
"We only exclude heavy, mutation-irrelevant trees to keep sandbox creation fast:",
"build output, coverage, the huge docs/i18n translation tree, and other worktrees."
],
"ignorePatterns": [
".next",
"dist",
"dist-electron",
".build",
"coverage",
"playwright-report",
"test-results",
"reports",
"docs/i18n",
".worktrees",
".stryker-tmp"
],
"reporters": ["progress", "html", "json"],
"htmlReporter": {
"fileName": "reports/mutation/mutation.html"
},
"jsonReporter": {
"fileName": "reports/mutation/mutation.json"
},
"coverageAnalysis": "perTest",
"timeoutMS": 60000,
"timeoutFactor": 2.5,
"concurrency": 4,
"disableTypeChecks": true,
"checkers": [],
"thresholds": {
"high": 70,
"low": 50,
"break": null
},
"tempDirName": ".stryker-tmp",
"cleanTempDir": true,
"_tapTestFiles_comment": [
"tap.testFiles is the explicit set of node:test files that cover the 8 mutated",
"modules (union of files importing any of them), MINUS a few timing/heap/streaming-",
"sensitive integration tests that can flake under Stryker concurrent runners and",
"would break the required all-green baseline dry-run (e.g. body-timeout-integration,",
"heap-pressure, sse-heartbeat-integration, *-stream-readiness, chatcore-memory-pressure).",
"It is enumerated (not a broad glob) so the Stryker dry-run stays tractable for the",
"nightly budget — a glob over the full ~1300-file unit suite would make the per-test",
"dry-run take hours. coverageAnalysis:perTest then narrows which files run per mutant.",
"Regenerate the base union after adding/renaming covering tests, then re-prune flaky ones:",
" grep -rlE \"circuitBreaker|publicCreds|accountFallback|routeGuard|services/auth|chatCore|services/combo|utils/error|public-client|account-fallback|route-guard|circuit-breaker\" tests/unit --include=\"*.test.ts\" | sort -u"
],
"dryRunTimeoutMinutes": 30,
"_concurrency_comment": "concurrency=4 (was 1): the covering node:test files used to share SQLite/module state via the default DATA_DIR (~/.omniroute), so running them concurrently in the Stryker sandbox caused cross-file races that failed the all-green baseline. tap.nodeArgs now imports ./tests/_setup/isolateDataDir.ts, which gives each spawned test process its own temp DATA_DIR — eliminating the shared on-disk DB, so concurrency>1 is deterministic. A/B verified 2026-06-17: dry-run at concurrency=4 fails WITHOUT the isolation import (account-fallback-service tap exit 9) and passes WITH it. Raise further only if the runner has spare cores."
}