
> VAR remembers what it has done. Each invocation resumes from the last completed stage unless the working tree has changed.

## How sessions work

When `vary var` runs, it writes a session file (`.vary-var-session.json`) in the project root. The session tracks:

| Field | Purpose |
|-------|---------|
| Session ID | Unique identifier for this validation cycle |
| Current stage | Where the pipeline is (e.g., `check`, `test`, `complete`) |
| Stage results | Pass/fail for each completed stage with summaries |
| Blockers | Active blocking issues that need fixing |
| Change fingerprint | Hash of the current change set |
| History | Timestamped entries for no-progress detection |

On the next invocation, VAR loads the session and checks whether the working tree still matches. If it does, the pipeline resumes from the first incomplete stage. If not, it resets to discovery.

## Change fingerprints

The fingerprint is a SHA-256 hash of the sorted list of changed file paths and their modification times. Two runs with the same changed files and mtimes produce the same fingerprint.

When you edit a file and re-run `vary var`, the fingerprint changes. VAR detects this drift and resets the session, because the prior stage results may no longer hold.

When you fix a blocker and re-run without touching other files, the fingerprint also changes (the fixed file has a new mtime). VAR resets and re-runs discovery, but this time check should pass.

## Session lifecycle

A typical session lifecycle:

| Step | What happens |
|------|-------------|
| First run | No session exists. VAR creates one, runs discovery, then proceeds through stages until something blocks or everything completes. |
| Re-run (same files) | Session loads, fingerprint matches. Resumes from the first incomplete stage. |
| Re-run (files changed) | Session loads, fingerprint differs. Resets to discovery and starts fresh. |
| Reset | `vary var --reset` deletes the session and starts from scratch. |

## No-progress detection

VAR tracks consecutive runs in the session history. If the same blockers appear across multiple runs with no improvement, it flags a no-progress warning:

```text
Warning: no progress detected across 3 consecutive runs.
Stuck at: check (2 errors)
Consider: reviewing the blockers below or running with --reset
```

This catches silent thrashing where you run `vary var` repeatedly without addressing the actual problem.

## Stateless mode

`--no-state` disables session persistence. VAR neither reads nor writes the session file. Every invocation starts from discovery.

| Use case | Why stateless |
|----------|--------------|
| CI pipelines | Each run should be independent |
| One-off checks | Avoid affecting saved state |
| Debugging | Suspect session corruption |

## Session file format

The session file is JSON. Its structure is internal and may change between compiler versions. Use `vary var --json` for machine-readable output instead of parsing this file.

Key fields for reference:

```json
{
  "sessionId": "...",
  "currentStage": "test",
  "stageResults": {
    "discovery": { "success": true, "summary": "9 files" },
    "check": { "success": true, "summary": "0 errors" }
  },
  "blockers": [],
  "changeSet": [
    { "path": "src/app.vary", "fingerprint": "a1b2c3..." }
  ],
  "lastUpdated": "2026-04-09T10:30:00Z"
}
```
