Files
OmniRoute/stryker.conf.json
Diego Rodrigues de Sa e Souza 34bde609ae chore(quality): close v3.8.28 cycle gate drift (re-baseline + nightly-mutation scope) (#4135)
* chore(quality): re-baseline v3.8.28 cycle drift (eslint/openapi/i18n)

The post-release push->main Quality Ratchet (run 27725117464) failed on 3
metrics that drifted during the v3.8.28 cycle from legitimate feature merges:
eslintWarnings 3769->3779, openapiCoverage.pct 38.3->37.6, i18nUiCoverage.pct
80.1->79.1. Reproduced locally on release/v3.8.29 (9f14c1294) — identical to CI.

None is hand-cleanable without gaming or unavailable infra:
- eslint +10: no-explicit-any is warn-level and allowed in tests (the drift is
  test `any`), plus 4 react-hooks/exhaustive-deps in RequestLoggerV2.tsx (a
  refresh-sensitive component — touching hook deps without UI tests is risky).
- openapi -0.7: the drop is from new INTERNAL routes (/api/tools/agent-bridge/*,
  LOCAL_ONLY) — documenting them in the public spec would game the metric.
- i18n -1.0: 37/41 locales need ~3000 translations via `npm run i18n:run`, which
  requires OMNIROUTE_TRANSLATION_API_KEY (not available locally).

Re-baselined to the real measured values per the documented v3.8.26 precedent
(_eslint_rebaseline_2026_06_16_v3826_forward_merge). Tighten at cycle end:
eslint/openapi via --require-tighten; i18n via i18n:run with creds.

* ci(mutation): scope nightly to 6 modules to fit the 180min budget

The full 8-module Stryker run timed out at the 180min nightly cap (run
27705123780: 16:47:33 -> 19:47:48 = exactly 180min; the prior 120min scheduled
run also timed out). #4078's DATA_DIR isolation made concurrency=4 safe but not
sufficient: the tap-runner re-spawns a node process per test file per mutant, so
spawn cost dominates and the two god-files chatCore.ts (5874 LOC) + combo.ts
(5282 LOC) — ~2/3 of the ~15k mutants — do not fit.

Removed both god-files from stryker.conf.json `mutate`. The 6 smaller modules fit
the budget and produce real mutation scores now; the god-files regain coverage
after the Onda 3 split into smaller units. Updated the nightly job name/comments
(8->6 modules). Removing entries from `mutate` does not affect the dry-run
baseline (it runs tap.testFiles, unchanged), so the all-green baseline is preserved.
2026-06-18 00:19:36 -03:00

262 lines
13 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/account-fallback-anthropic-quota.test.ts",
"tests/unit/account-fallback-route-restriction-403.test.ts",
"tests/unit/account-fallback-service.test.ts",
"tests/unit/api-key-rotator-health.test.ts",
"tests/unit/appearance-widget-settings-schema.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-terminal-status.test.ts",
"tests/unit/authz/routeGuard.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/build/check-circular-deps.test.ts",
"tests/unit/cache-sweeps.test.ts",
"tests/unit/cc-compatible-provider.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-route-coverage.test.ts",
"tests/unit/chat-route-edge-cases.test.ts",
"tests/unit/chatcore-compression-integration.test.ts",
"tests/unit/chatcore-extracted-modules-3821.test.ts",
"tests/unit/chatcore-imports-cleanly.test.ts",
"tests/unit/chatcore-sanitization.test.ts",
"tests/unit/chatcore-strip-stale-headers.test.ts",
"tests/unit/chatcore-translation-paths.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-failure-kind.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/codex-failover.test.ts",
"tests/unit/codex-stream-false.test.ts",
"tests/unit/collect-metrics-module-coverage.test.ts",
"tests/unit/combo-499-abort.test.ts",
"tests/unit/combo-auto-candidate-expansion.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-health-autopilot.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-max-depth-config.test.ts",
"tests/unit/combo-omnimodel-tag-stripping.test.ts",
"tests/unit/combo-prescreen.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-soft-penalty.test.ts",
"tests/unit/combo-round-robin-streaming-lock-3811.test.ts",
"tests/unit/combo-routing-engine.test.ts",
"tests/unit/combo-scoring-inspector.test.ts",
"tests/unit/combo-sessionless-pin-3825.test.ts",
"tests/unit/combo-strategies.test.ts",
"tests/unit/combo-strategy-fallbacks.test.ts",
"tests/unit/combo-streaming-empty-content-failover.test.ts",
"tests/unit/combo-target-defensive-modelstr.test.ts",
"tests/unit/complexity-aware-scoring-wiring.test.ts",
"tests/unit/context-pinning-tool-calls.test.ts",
"tests/unit/correctness/combo.property.test.ts",
"tests/unit/correctness/sanitizers.property.test.ts",
"tests/unit/custom-model-target-format.test.ts",
"tests/unit/db-reset-module-state.test.ts",
"tests/unit/domain-persistence.test.ts",
"tests/unit/embeddings-auth.test.ts",
"tests/unit/error-classification.test.ts",
"tests/unit/error-message-sanitization.test.ts",
"tests/unit/executor-antigravity.test.ts",
"tests/unit/executor-web-cookie-sweep.test.ts",
"tests/unit/gemini-web-missing-browser-3516.test.ts",
"tests/unit/guardrails-api-3496.test.ts",
"tests/unit/memory-embedding-remote.test.ts",
"tests/unit/memory-embedding-transformers.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/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/plan3-p0.test.ts",
"tests/unit/plugin-sandbox-permissions.test.ts",
"tests/unit/plugins-route-error-sanitization.test.ts",
"tests/unit/provider-error-rules.test.ts",
"tests/unit/provider-health-autopilot.test.ts",
"tests/unit/provider-health-matrix.test.ts",
"tests/unit/provider-request-failure-pipeline.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-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-streaming-consumption-usd.test.ts",
"tests/unit/rate-limit-enhanced.test.ts",
"tests/unit/rate-limit-manager.test.ts",
"tests/unit/responses-handler.test.ts",
"tests/unit/route-explainability.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/router-strategies.test.ts",
"tests/unit/service-combo-metrics.test.ts",
"tests/unit/services-branch-hardening.test.ts",
"tests/unit/services/combo-metrics-memory.test.ts",
"tests/unit/settings/authz-bypass.test.ts",
"tests/unit/skip-provider-breaker-consumer-2743.test.ts",
"tests/unit/sse-auth.test.ts",
"tests/unit/strict-random-deck.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/tools-filter-anthropic-format.test.ts",
"tests/unit/usage-service-hardening.test.ts",
"tests/unit/validate-response-quality.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 (5874 LOC) + combo.ts (5282 LOC) — the two",
"god-files — were REMOVED from `mutate`. They dominate ~2/3 of the ~15k mutants, and the",
"full 8-module run TIMED OUT at the 180min nightly cap (run 27705123780, concurrency=4 +",
"DATA_DIR isolation: started 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.",
"The 6 smaller modules below fit the budget and produce REAL mutation scores now; the two",
"god-files regain mutation coverage after the Onda 3 split into smaller units (re-add them",
"here — ideally as the split sub-modules). See project memory: Quality Gate v2 / Fase 9."
],
"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"
],
"_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."
}