# Gate Cleanliness Procedure

> **Purpose:** Deterministic working tree cleanliness verification for gate/retest workflows.

**Environment**: All verification commands use canonical contexts per [verifier-environment-spec.md](verifier-environment-spec.md)

## Quick Reference

```bash
# Check current cleanliness (no baseline needed)
./scripts/gate-cleanliness-check.sh --check-clean

# Save baseline before tests
./scripts/gate-cleanliness-check.sh --save-baseline

# Check against baseline after tests
./scripts/gate-cleanliness-check.sh --check

# JSON output (for tooling/integration)
./scripts/gate-cleanliness-check.sh --check-clean --format json
```

## Problem Statement

Gate/retest workflows need to verify that the working tree is clean AFTER running tests. However, some files are **expected** to be generated during normal operations:

1. **vectl plan artifacts**: `plan.yaml`, `plan-dashboard.html`
2. **Test reports**: Generated during test execution
3. **Cache files**: Created by tooling

Previously, the retest step could not distinguish expected generated files from unexpected code changes, leading to false positives.

## Solution: Two Approaches

### Approach 1: Expected Files List (Recommended for most cases)

The script uses a whitelist of expected generated files stored in `.anima/gate/expected-generated.txt`.

**When to use:**
- Files are consistently generated across all runs
- Files don't change based on test execution
- Simple, stateless verification is sufficient

**How it works:**
1. Script reads `.anima/gate/expected-generated.txt`
2. Gets current `git status --porcelain`
3. Filters out files in the expected list
4. Reports any remaining dirty files as unexpected

### Approach 2: Baseline Diff (For workflow-specific changes)

Capture git status before tests, compare after tests.

**When to use:**
- Files that may or may not be modified depending on workflow
- Need to distinguish between "already dirty before" and "newly dirty"
- Multiple sequential operations that each modify files

**How it works:**
1. Before tests: `./scripts/gate-cleanliness-check.sh --save-baseline`
2. After tests: `./scripts/gate-cleanliness-check.sh --check`
3. Script compares current status against baseline
4. Only reports files that became dirty AFTER the baseline was saved

## File Locations

```
scripts/
└── gate-cleanliness-check.sh      # Main verification script

.anima/gate/
├── expected-generated.txt         # Whitelist of expected files
└── baseline-status.txt            # Pre-test baseline (generated)
```

## Exit Codes

| Code | Meaning |
|------|---------|
| 0 | Clean (no unexpected changes) |
| 1 | Dirty (unexpected changes found) |
| 2 | Missing baseline (run --save-baseline first) |
| 3 | Invalid arguments |

## Adding New Expected Files

1. **Edit** `.anima/gate/expected-generated.txt`
2. **Add** one file per line (comments start with `#`)
3. **Test** with `./scripts/gate-cleanliness-check.sh --check-clean`

Example:
```
# Custom generated report
reports/coverage.html

# Dashboard generated by workflow
dashboard/index.html
```

## Integration Patterns

### Pattern A: Gate Step (Simple)

```bash
# Run tests
uv run pytest tests/

# Check cleanliness
./scripts/gate-cleanliness-check.sh --check-clean
```

### Pattern B: Gate Step with Baseline

```bash
# Before test phase
./scripts/gate-cleanliness-check.sh --save-baseline

# Run tests (may generate expected files)
uv run pytest tests/

# After test phase
./scripts/gate-cleanliness-check.sh --check
```

### Pattern C: CI/CD Integration

```yaml
# .github/workflows/gate.yml
- name: Check cleanliness
  run: |
    ./scripts/gate-cleanliness-check.sh --check-clean --format json
```

## Decision Matrix

| Scenario | Approach | Command |
|----------|----------|---------|
| vectl-generated files | Expected list | `--check-clean` |
| Test reports (always) | Expected list | `--check-clean` |
| Pre/post comparison | Baseline | `--save-baseline` + `--check` |
| CI/CD pipeline | Expected list | `--check-clean --format json` |
| Strict (no exceptions) | Either + `--strict` | `--check-clean --strict` |

## Troubleshooting

### "Baseline not found"

**Problem:** Running `--check` without `--save-baseline`

**Solution:**
```bash
./scripts/gate-cleanliness-check.sh --save-baseline
./scripts/gate-cleanliness-check.sh --check
```

### "Unexpected changes found" but files are expected

**Problem:** Files not in whitelist

**Solution:**
1. Check if file should be in `.gitignore` (if truly temporary)
2. Add to `.anima/gate/expected-generated.txt` (if consistently generated)

### False positives on specific workflow

**Problem:** Some workflows legitimately modify different files

**Solution:**
```bash
# Use baseline approach for that workflow
./scripts/gate-cleanliness-check.sh --save-baseline
# ... run workflow ...
./scripts/gate-cleanliness-check.sh --check
```

## Related

- [vectl Guide](../.agents/instructions.md) - Plan management
- [INTERFACES.md](../INTERFACES.md) - API contracts