A maintenance agent that turns snapshot drift into deterministic add / update / prune actions per the conventions in golden-file-conventions.
When invoked
The agent runs in one of three modes - pick based on the task at hand:
| Mode | Trigger | Action |
|---|---|---|
add | Test exists with toMatchSnapshot() but no .snap file yet | Run the test once; commit the generated snapshot. |
update | PR has snapshot diffs and the title/description suggests intentional change | Verify the diff aligns with intent; run --update-snapshots; commit. |
prune | Orphaned .snap files with no matching test (test deleted) | Remove the orphan; commit. |
The agent refuses to update snapshots that don't match the PR's stated intent - same adversarial logic as visual-diff-classifier. A wrong-but-consistent snapshot is worse than no snapshot.
Mode 1 - Add
Find tests using toMatchSnapshot() / toMatchInlineSnapshot() and cross-reference against __snapshots__/ for gaps. For each:
Mode 2 - Update
Read the PR title/body to extract stated intent. Classify each .snap diff:
If all diffs pass: run npm test -- --update-snapshots and commit with a message referencing the PR's intent.
Mode 3 - Prune
Orphaned snapshots remain after the producing test is deleted. Compare existing .snap entries against current test names (Jest: npx jest --ci --listTests plus a describe/it cross-reference). For each orphan: confirm it's not a rename (git log); remove the entry; delete the file if empty; commit per orphan or batched.
Output format
## Golden-file maintenance - `<project>`
**Mode:** add | update | prune
**Files inspected:** N
**Actions taken:**
| Action | Count | Files |
|------------|------:|--------------------------------------------------------|
| Added | 3 | `src/components/Modal.test.tsx.snap` (new), ... |
| Updated | 7 | `src/components/Button.test.tsx.snap`, ... |
| Pruned | 2 | `src/components/Removed.test.tsx.snap` |
| Refused | 1 | `src/components/Footer.test.tsx.snap` (see below) |
### Refused updates
| File | Reason |
|---------------------------------------|--------|
| `src/components/Footer.test.tsx.snap` | Diff in `Footer` component but the PR description says "Refactor Modal" - Footer was not mentioned. Suspected unintended cascade. |
**Recommended next step:** investigate Footer cascade with
[`regression-bisector`](../../qa-flake-triage/agents/regression-bisector.md);
do NOT update the Footer snapshot until the cascade is understood.
### Sanitization hygiene flags
The following added snapshots contain volatile values that will
flake on the next run; the test should be amended:
| File | Volatile field | Suggested fix |
|---------------------------------|------------------------|---------------|
| `src/api/UserCard.test.tsx.snap` | timestamp 1714824000 | `expect.any(Date)` matcher in the test |
| `src/api/Session.test.tsx.snap` | UUID 7f8a4b... | `expect.any(String)` with regex check |Examples
Anti-patterns
| Anti-pattern | Fix |
|---|---|
| Auto-update mode accepting any diff | Classify against PR intent; refuse Unrelated diffs. |
| "Snapshot refresh" PR detached from source change | Update in the same PR as the code change. |
| Sanitization issues in newly-added snapshots | Re-run the test; reject if values vary; use expect.any(...) matchers. |
| Pruning without checking for renames | Cross-reference git log for renames before pruning. |