You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
So any edit to sync.ts pulls all ~700 lines into scope. This is the mechanism already documented in #34.
2. #100 changed what no-coverage means.#100 decoupled mutation testing from Postgres via vitest.stryker.config.ts, which was the right call for runtime (30min → <2min). But it means the DB half of sync.ts — syncConnection and everything under it — can no longer be exercised at all during mutation, so those mutants report no-coverage instead of being killed by the DB-backed tests that do cover them in pnpm test.
vitest.stryker.config.ts states this plainly and treats it as a feature:
Mutants covered only by those report as NoCoverage rather than Survived, which is honest signal about unit-test strength instead of a container tax.
That reasoning holds. What was missed is that thresholds.break = 60 was never re-tuned for the new, structurally lower scores.
Impact
Any PR touching a DB-heavy file under src/lib now fails this gate regardless of the change's quality. 67 of the 145 non-error mutants in sync.ts are unreachable by construction, so the file cannot clear 60% no matter how well the diff is tested. #102 was the first PR to hit this; every subsequent one touching sync.ts, plaid/sync.ts, or the query modules will too.
main has no branch protection, so this is currently advisory — but it trains everyone to merge through a red check, which defeats the gate.
Exclude no-coverage from the score, or re-tune thresholds.break, acknowledging that no-coverage is now the expected state for DB-backed code rather than a signal of weak tests.
Split the config so DB-backed files are mutated against a real Postgres in a separate, slower job, and unit-only files stay in the fast path.
(1) is the most honest and helps every future PR; (2) is the cheapest.
Context
Found while merging #102 (fixes #91). That PR was merged with the gate red, with the baseline comparison recorded on the PR.
Related: #34 (raise coverage on sync.ts / reports.ts — the other half of this problem), #100 (introduced the no-coverage shift).
Symptom
PR #102 — a 2-line behavior fix in
src/lib/simplefin/sync.tsplus 2 new tests — failedmutation (diff)at 28.07% againstthresholds.break = 60.The red was not caused by the diff. Stryker run locally on a clean checkout of
main'ssync.tsreturns exactly the same numbers:mainbaselineThe PR's own mutants were killed. The score is entirely pre-existing debt in lines the PR never touched.
Mechanism — two things compounding
1. Whole-file scoping.
scripts/mutate-diff.shbuilds--mutatefrom file paths:So any edit to
sync.tspulls all ~700 lines into scope. This is the mechanism already documented in #34.2. #100 changed what no-coverage means. #100 decoupled mutation testing from Postgres via
vitest.stryker.config.ts, which was the right call for runtime (30min → <2min). But it means the DB half ofsync.ts—syncConnectionand everything under it — can no longer be exercised at all during mutation, so those mutants report no-coverage instead of being killed by the DB-backed tests that do cover them inpnpm test.vitest.stryker.config.tsstates this plainly and treats it as a feature:That reasoning holds. What was missed is that
thresholds.break = 60was never re-tuned for the new, structurally lower scores.Impact
Any PR touching a DB-heavy file under
src/libnow fails this gate regardless of the change's quality. 67 of the 145 non-error mutants insync.tsare unreachable by construction, so the file cannot clear 60% no matter how well the diff is tested. #102 was the first PR to hit this; every subsequent one touchingsync.ts,plaid/sync.ts, or the query modules will too.mainhas no branch protection, so this is currently advisory — but it trains everyone to merge through a red check, which defeats the gate.Options
--since/ diff integration so the gate reflects the diff's own quality rather than whole-file legacy debt. This is the "reconsider the gate shape" half of Raise mutation coverage on sync.ts / reports.ts (and other large touched files) to ≥60% #34 and fixes the root cause.thresholds.break, acknowledging that no-coverage is now the expected state for DB-backed code rather than a signal of weak tests.(1) is the most honest and helps every future PR; (2) is the cheapest.
Context
Found while merging #102 (fixes #91). That PR was merged with the gate red, with the baseline comparison recorded on the PR.
Related: #34 (raise coverage on
sync.ts/reports.ts— the other half of this problem), #100 (introduced the no-coverage shift).