Alpha. Vary is under active development and not ready for production use. Syntax, APIs, performance, and behaviour may change between releases.
How it works
VAR runs a six-stage pipeline in dependency order. Each stage produces results that feed the next.
Pipeline overview
When you run vary var, the command executes these stages in order:
Discovery -> Check -> Test -> Mutation -> Review -> Classification
Each stage either runs, is skipped (not needed), or is blocked (a prerequisite failed). The decision policy makes this determination before each stage begins.
Stage 1: Discovery
Detects what changed. In a git repository, VAR runs git diff and git status against a base ref (defaulting to HEAD, configurable with --since-ref). Each changed file is classified:
| Category | Examples |
|---|---|
| Source | .vary files in src/, lib/, main directories |
| Test | .vary files in tests/, files matching test_*.vary |
| Config | vary.toml, .vary/, configuration files |
| Docs | .md, .txt, documentation directories |
| Build | Makefile, build.gradle, CI configuration |
| Other | Everything else |
Each file also gets a code area label (PURE_LOGIC, EFFECTS, BOUNDARIES) that the decision policy uses for significance scoring.
In non-git environments (extracted tarballs, CI scratch spaces), VAR falls back to filesystem scanning with modification-time detection.
Discovery also computes a change fingerprint: a SHA-256 hash of the sorted file paths and their modification times. This fingerprint is compared to the previous session to detect working-tree drift.
Stage 2: Check
Scoped static analysis. VAR runs the same checks as vary check, but only on changed files (source and test, excluding deleted). The result is a count of errors and warnings with per-file detail.
If check finds errors, the pipeline records them as blockers. Downstream stages may still run depending on the decision policy, but the terminal state will be BLOCKED.
Stage 3: Test
Targeted test execution. VAR discovers test files covering the changed modules using path-based heuristics:
| Heuristic | How it works |
|---|---|
| Adjacency | test_<module>.vary next to the source file |
| Directory scan | tests/ directory entries matching the module name |
Only the relevant tests run, not the full suite. The result is passed/failed/skipped counts with per-file detail.
Stage 4: Mutation
Source-level mutation testing on changed source files (test files and non-.vary files are excluded). Only runs when you pass --include-mutation or when the decision policy considers the change significant enough.
The mutation engine applies small code changes (replacing operators, flipping conditions, removing statements) and runs the targeted tests against each mutant. The result is a per-file and aggregate mutation score. The quality gate defaults to a 70% kill rate.
Stage 5: Review
Generates a review closeout packet. Only runs when you pass --include-review-packet. The packet covers what changed, what the checks and tests found, mutation scores if available, and a confidence level.
Stage 6: Classification
The final stage maps accumulated results and blockers into a terminal state:
| State | Condition |
|---|---|
| Complete | All executed stages passed |
| Blocked | One or more stages have hard failures |
| Partial | Some stages ran, others were skipped by budget or scope |
| Advisory | Informational run (e.g., discovery-only) with no blocking findings |
The classification also includes a recommendation (the next command to run) and a confidence level: high, medium, or low.
Resumption
On the next invocation, the pipeline loads the previous session. If the change fingerprint matches (no new edits), it resumes from the first incomplete stage. If the fingerprint changed, it resets to discovery.
The workflow is: run vary var, fix what it reports, run vary var again. Each cycle narrows the remaining work until the terminal state is COMPLETE.