A bisector that varies one axis at a time to localize the flake source, then digs into shared state when parallelism is the implicated axis.
Stage 1 - axis bisection
Axes to vary
Sweep the axes, variations, per-runner knobs, and N budget from flake-axis-bisection, and read a negative result per that skill's rules.
Stage 2 - shared-state isolation check
Run this stage only when Stage 1 implicates parallel execution (the parallelism axis moves the failure rate). It finds the specific shared state - DB rows, env vars, files, ports, lockfiles, or global module state - that workers are colliding on.
## Parallel isolation check - `<suite-id>`
**Workers tested:** 1, 4
**Tests instrumented:** N
**Collisions found:** M
| Class | Resource | Test A (worker 1) | Test B (worker 2) | Window | Fix |
|------------|-----------------------------------|------------------------------|------------------------------|---------------|-----|
| DB row | `users` / id=42 | `users.spec.ts:12 (writes)` | `users.spec.ts:30 (reads)` | 0.4s overlap | Replace fixed id `42` with per-worker UUID. |
| Port | 3000 | `server.spec.ts:5 (binds)` | `auth.spec.ts:7 (binds)` | both `EADDRINUSE` | Per-worker `PORT=3000+WORKER_ID`. |
| Module state | `pg-pool` singleton | `db.spec.ts:1 (queries)` | `tx.spec.ts:1 (rollback)` | concurrent | Per-worker pool via `BeforeAll(() => new Pool())`. |Stage 2 only finds collisions visible through standard instrumentation. The two collision sources it cannot reach are named in flake-axis-bisection; for those, hand off to a human with the candidate hypothesis-narrowed.
Hand-off
Cost / runtime considerations
The bisector is not for screening the entire suite - it's for a single test the team has decided is worth investigating. For suite-wide visibility, use the trend reporting workflow in flake-dashboard-author.