Variant
Software
2026

TypeScript, Node.js, pnpm, Commander.js, picocolors, tsup, Vitest, Biome, Husky, GitHub Actions, ES Modules,
Change intelligence for TypeScript monorepos. Reads a diff at the AST level to predict which tests a change actually needs — report-only until the false-skip rate is measured.
- Role
- Engineering
- Year
- 2026
- Type
- Software
Challenge
Monorepo tooling decides what a change affects from the file or package graph — Turborepo, Nx, `vitest --changed` and `jest --findRelatedTests` all treat any dependent of a touched file as affected, so a body-only edit can drag the whole downstream tree into the run. Cutting that finer means deciding from the exported surface instead: did a signature actually change, and does the dependent import the name that moved. The risk is asymmetric — an unnecessary test run costs minutes, a wrongly skipped one ships the bug, so every unknown in the analysis has to resolve toward running more tests, not fewer.
Approach
ts-morph diffs each changed file's exported surface symbol by symbol and classifies it as non-impacting, internal, or breaking; the result propagates through a persisted symbol index and reverse import graph (file → import → package → task), with the first hop gated per imported symbol. Anything the pipeline can't prove widens the result rather than narrowing it — non-TypeScript files become unanalyzed seeds, dynamic imports propagate as "names unknowable", and a lockfile or tsconfig change selects every test. It ships report-only: each prediction is logged with its head commit SHA, and a verify command reconciles that log against a Vitest or Jest JSON report so a false-skip rate accumulates before skipping is ever enabled.
Outcome
Published to npm as `@blzsky/variant` — 11 commands, tested across three operating systems and Node 20/22/24, with CLI startup gated under 200 ms by a benchmark job; hoisting a single ts-morph Project took impact analysis over a 10-file diff from 2.98 s to 0.99 s. The shadow-mode log earned its keep early: two under-selection bugs — unresolved tsconfig `paths` aliases and unread package `exports` maps — were each reproduced as a real false skip before being fixed. Test skipping stays off by design until a measured false-skip rate under 0.5% exists, and a release along the way cut ~4,300 lines of adjacent surface (tracer, remote cache, dev server) to keep the project on the one thing it does that the incumbents don't.
