Flaky test finder
Flakiness is an empirical claim, and it is the one kind of test problem where reasoning
from the source is actively misleading. A test that looks obviously order-dependent may be
solid; a test that looks pure may fail one run in forty on a loaded machine.
So this skill measures first and reads second.
Procedure
1. Measure the rate
<skill-dir> is the directory this SKILL.md was loaded from — the skill installs outside
your project, so its script is named by full path, never relatively.
bash <skill-dir>/scripts/rerun.sh "pnpm vitest run path/to/file.test.ts" 30
Runs the command N times, reports pass/fail per run, the observed failure rate, and a
Wilson confidence interval for the true rate. The interval is the point: three failures
in ten runs and three in a hundred are very different findings, and a bare percentage hides
which one you have.
If the failure rate is 0 over a decent number of runs, say so plainly — "not reproduced in
N runs" is a real result. Do not go on to diagnose a flake you could not observe.
2. Split ordering from isolation
The two commonest causes look identical from the failure message. Distinguish them:
- Run the single test alone, many times. Failing alone means it is not
order-dependent — look at timing, environment and external state.
- Run the whole file, then the whole suite. If it only fails in the larger set, it is
shared state or ordering — something before it leaves a mutation behind.
- If the runner supports a random seed, vary it. A failure rate that moves with the seed is
ordering by definition.
3. Find the shared thing
When it is ordering or isolation, the cause is almost always one of a short list, and it
is worth checking them in order rather than reading the test top to bottom:
- module-level mutable state, a cache, or a singleton that survives between tests
- a fake clock, timezone or locale set by one test and not restored
- database or filesystem state without a per-test transaction or temp directory
- an unawaited promise from an earlier test landing during this one
- a shared port, fixture file, or environment variable
4. Prove the fix by re-measuring
Apply the fix, then run step 1 again with at least as many iterations. The claim "fixed" is
only supported by a second measurement with a comparable interval. A single green run
proves nothing about a test that failed one time in twenty.
5. If it cannot be fixed now, quarantine deliberately
Say so explicitly, with the rate, and prefer an annotation the runner reports over a silent
skip. A quarantined test that nobody can see becomes a deleted test.
Output
- Rate — failures over runs, with the interval, and the exact command measured
- Class — ordering, isolation, timing, environment, or not reproduced
- Evidence — which of the step-2 runs differed, and how
- Cause — the specific shared thing, with the line
- Post-fix rate — the second measurement, or an explicit "not yet re-measured"
What this skill deliberately does not do
- It does not diagnose from the source without measuring. That is the failure mode
this skill exists to replace.
- It does not add a retry. Retries hide the rate and convert a known flake into an
unknown one. If a retry is genuinely the right call, that is the author's decision to
make explicitly, not a fix to apply quietly.
- It does not delete or
skip a test to make a suite green.
- It does not claim a fix from one passing run.
- It does not run suites that mutate shared infrastructure — a test command touching a
shared database, a live API or a deployment is not re-run thirty times. It says why and
asks for an isolated target.
- It does not report a rate without saying how many runs produced it.
When this is the wrong tool
- The test fails every single time. That is not flakiness, it is a bug with a
reproduction already in hand — diagnose it from the failure instead. Measuring a 100%
rate tells you nothing you did not already know.
- The test does not exist yet and you are deciding what to cover. That is a coverage
question, not a reliability one.
- The failures started immediately after a dependency bump. Check the bump first: a
changed default explains a whole class of new intermittency.
1---2name: flaky-test-finder3description: Proves whether a test is flaky instead of reasoning about it, by re-running it many times and reporting the observed failure rate, then narrowing the cause to ordering, shared state, timing or environment. Use when a test fails intermittently, passes on retry, fails only in CI, or the user suspects flakiness.4---56# Flaky test finder78Flakiness is an empirical claim, and it is the one kind of test problem where reasoning9from the source is actively misleading. A test that looks obviously order-dependent may be10solid; a test that looks pure may fail one run in forty on a loaded machine.1112So this skill measures first and reads second.1314## Procedure1516### 1. Measure the rate1718`<skill-dir>` is the directory this SKILL.md was loaded from — the skill installs outside19your project, so its script is named by full path, never relatively.2021```22bash <skill-dir>/scripts/rerun.sh "pnpm vitest run path/to/file.test.ts" 3023```2425Runs the command N times, reports pass/fail per run, the observed failure rate, and a26Wilson confidence interval for the true rate. **The interval is the point**: three failures27in ten runs and three in a hundred are very different findings, and a bare percentage hides28which one you have.2930If the failure rate is 0 over a decent number of runs, say so plainly — "not reproduced in31N runs" is a real result. Do not go on to diagnose a flake you could not observe.3233### 2. Split ordering from isolation3435The two commonest causes look identical from the failure message. Distinguish them:3637- Run the single test **alone**, many times. Failing alone means it is not38 order-dependent — look at timing, environment and external state.39- Run the whole file, then the whole suite. If it only fails in the larger set, it is40 **shared state or ordering** — something before it leaves a mutation behind.41- If the runner supports a random seed, vary it. A failure rate that moves with the seed is42 ordering by definition.4344### 3. Find the shared thing4546When it is ordering or isolation, the cause is almost always one of a short list, and it47is worth checking them in order rather than reading the test top to bottom:4849- module-level mutable state, a cache, or a singleton that survives between tests50- a fake clock, timezone or locale set by one test and not restored51- database or filesystem state without a per-test transaction or temp directory52- an unawaited promise from an earlier test landing during this one53- a shared port, fixture file, or environment variable5455### 4. Prove the fix by re-measuring5657Apply the fix, then run step 1 again with at least as many iterations. The claim "fixed" is58only supported by a second measurement with a comparable interval. A single green run59proves nothing about a test that failed one time in twenty.6061### 5. If it cannot be fixed now, quarantine deliberately6263Say so explicitly, with the rate, and prefer an annotation the runner reports over a silent64skip. A quarantined test that nobody can see becomes a deleted test.6566## Output67681. **Rate** — failures over runs, with the interval, and the exact command measured692. **Class** — ordering, isolation, timing, environment, or not reproduced703. **Evidence** — which of the step-2 runs differed, and how714. **Cause** — the specific shared thing, with the line725. **Post-fix rate** — the second measurement, or an explicit "not yet re-measured"7374## What this skill deliberately does not do7576- **It does not diagnose from the source without measuring.** That is the failure mode77 this skill exists to replace.78- **It does not add a retry.** Retries hide the rate and convert a known flake into an79 unknown one. If a retry is genuinely the right call, that is the author's decision to80 make explicitly, not a fix to apply quietly.81- **It does not delete or `skip` a test to make a suite green.**82- **It does not claim a fix from one passing run.**83- **It does not run suites that mutate shared infrastructure** — a test command touching a84 shared database, a live API or a deployment is not re-run thirty times. It says why and85 asks for an isolated target.86- **It does not report a rate without saying how many runs produced it.**8788## When this is the wrong tool8990- **The test fails every single time.** That is not flakiness, it is a bug with a91 reproduction already in hand — diagnose it from the failure instead. Measuring a 100%92 rate tells you nothing you did not already know.93- **The test does not exist yet** and you are deciding what to cover. That is a coverage94 question, not a reliability one.95- **The failures started immediately after a dependency bump.** Check the bump first: a96 changed default explains a whole class of new intermittency.