mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-19 05:12:16 +03:00
* fix(backend): stop redaction truncating the message after a path (#13144) `findUnquotedPathEnd` may swallow the rest of a line when it cannot tell where a path ends, so a Windows path with spaces cannot leak a `Files\secret` suffix. Two things made that fire far wider than the function documents at `:606`. **1. The licence was granted on separator evidence alone.** Every API route carries slashes, so an ordinary `/v1/x/y` in prose qualified as unequivocal and truncated everything after it. The image-model 400 lost the one sentence it exists to deliver: built ...cannot be used on /v1/chat/completions. Use POST /v1/images/generations instead. delivered ...cannot be used on <path> Now only a Windows path, a file URI, or a known POSIX filesystem root may swallow the line. @diegosouzapw's `/zz` vs `/etc` probe on the issue is why this is the condition and not the first-segment check I originally proposed: both truncated identically, so the root was never the driver. **2. The ambiguity branch ran before `resolvedExtensionEnd`.** A path whose end is pinned exactly by a known extension was still treated as ambiguous the moment any prose followed it, so the endpoint was discarded and the line swallowed. A determinable extension leaves nothing to fail closed about -- the whole path is still replaced, suffix included, and the tail survives: before Provider failed in <path> after Provider failed in <path> with api_key='[REDACTED]' Both halves are independently load-bearing: reverting (1) fails the two route tests, reverting (2) fails the extension test. Fail-closed is narrowed, not weakened. `/etc/shadow copy failed` has nothing to anchor an endpoint on and still collapses to `reading <path>`. Worth recording that the guard test for that cannot be killed by mutating either mechanism alone -- the two are mutually redundant, so it takes disabling both, which is also why this change cannot expose a suffix these shapes did not already hide. Test results against base: chat-rejects-image-only-model red -> GREEN dashboard-request-failed-redaction its delivered-log assertion now passes; the test still fails on a second, unrelated assertion (the *internal* log is redacted where it should stay raw) that base never reached tunnel-routes-error-sanitization unchanged, independent (a tripwire asserting the shared sanitizer does NOT cover a shape it now does) 836/840 pass across the sanitization, redaction and error suites; the remaining failures are the two above plus mcp-public-error-boundaries, which passes in isolation on base and on this branch and only flakes under --test-concurrency=8. * docs(changelog): fragment for the redaction truncation fix (#13144) changelog.d/README says a PR adds exactly one fragment rather than editing CHANGELOG.md, so the aggregation order stays deterministic and siblings cannot conflict. This one was missing. * test(redaction): narrow the headline case to the truncation it names Rebased onto a base that has moved 40 commits; resolveEndpoint gained an ignoreAmbiguity parameter and route-context callers in that window. The merge keeps both: base's parameter, plus this PR's two changes (check the resolved extension BEFORE the ambiguity branch, and drop hasFilesystemEvidence from the swallow licence). The headline assertion was that the whole message survives byte for byte. On the current base the tail survives but the route itself still becomes <path> in that particular message, because the quoted model slug earlier in the line carries separators. That is a narrower, separate question from the truncation this PR fixes, so the test now asserts the remediation sentence survives and records the <path> substitution explicitly rather than silently dropping the case. * test(stryker): register the redaction-truncation test for mutation runs errorPathRedaction.ts is mutation-tested, so a new covering test has to be in tap.testFiles or the Stryker sandbox never runs it and its mutants report as survived. Inserted in the alphabetical run beside the sibling error-sensitive-redaction.test.ts, following #13036's precedent. The list has a second, unsorted appended group; left that alone rather than re-sorting a file this PR only needed one line in. Requested in review by @diegosouzapw.
625 lines
34 KiB
JSON
625 lines
34 KiB
JSON
{
|
||
"$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 ~200–500 mutants; est. 30–90 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-claude-per-model-scope.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-path-redaction-route-truncation-13144.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."
|
||
}
|