Skip to content

ADR-004: Incremental migration toward SnapDiff v2 architecture #166

Description

@pftg

Status 2026-08-24 — superseded by ADR-010, kept as the vision record

This issue's Phase 1–3 checklist has been overtaken by events. The consolidation
happened, but through ADR-008 → ADR-010 rather than these PR steps. Read
.ai/adr-010-everything-in-2.0.md first
; this issue is now the historical
record of where the idea started.

What actually shipped

The SnapDiff namespace exists, the config surface was inverted to a single
object, the test suite was split so rake test:canonical proves the
post-deletion state, and the comparison pipeline lost its driver indirection on
the 2.1 branch. The measured spike (.ai/endstate-spike-rewrite.md) found a
from-scratch rewrite only 23% smaller with 70% file reuse — "a rewrite that keeps
70% is consolidation wearing a rewrite costume" — so the vision was delivered by
consolidation, not by the rewrite this issue implies.

The release plan that replaced it

What the original adopter question here was gating

This issue was the adopter-feedback gate on shipping 2.0. That feedback now
exists and was decisive — two customer personas ran the real product and both
got a green bar on a page they had deliberately broken, inside ten minutes.
See .ai/experience-map.md for both journeys and .ai/adr-009-* for the full
research record.

Remaining, live


Original vision and phased plan (2026, superseded)

Vision

Consolidate the comparison pipeline from 25+ files / ~2,000 lines to 16 files / ~1,400 lines with 3 core objects: Comparison, Driver, Reporter.

Full ADR: .ai/adr-004-snap-diff-v2-vision.md
Migration plan: .ai/adr-004-migration-plan.md

Phase 1: Make Things More Alike (internal, no API changes)

  • PR 1: Add vocabulary aliases (baseline_path, current_path, Driver#load, Driver#mask)
  • PR 2: Merge DifferenceFinder into ImageCompare (delete 1 file)
  • PR 3: Unify quick_equal? and different? into lazy evaluation
  • PR 4: Merge StableScreenshoter into Screenshoter (delete 1 file)
  • PR 5: Move skip_area masking from comparison-time to capture-time
  • PR 6: Consolidate mattr_accessor into Config object (keep old API as delegates)

Phase 2: Separate Annotation from Reporting

  • PR 7: Extract annotation (draw rectangles, heatmaps) into AnnotationService
  • PR 8: Give Reporters::Default the record/finalize interface

Phase 3: Namespace Migration (needs major version)

  • PR 9: Add SnapDiff namespace aliases (additive, non-breaking)
  • PR 10: v2.0 — Make SnapDiff canonical, old namespace becomes shims

Constraints

  • Each PR keeps tests green and public API unchanged (until Phase 3)
  • No big-bang rewrite — Flocking Rules: make things more alike, then unify
  • Do NOT delete Reporters::Default — it generates annotation images the HTML reporter needs
  • Do NOT drop features: screenshot_section/group, median_filter, shift_distance_limit, LFS, delayed validation

Expected Outcome

Metric Current After Phase 1-2 After Phase 3
Files 25+ ~18 ~16
Lines ~2,000 ~1,600 ~1,400
Namespaces 2 2 (with aliases) 1 (SnapDiff)
Classes to understand pipeline 7 4 3
Config points 24 mattr_accessor 8 in Config + delegates 8 in Config

References

  • ADR-004 vision: .ai/adr-004-snap-diff-v2-vision.md
  • ADR-004 migration plan: .ai/adr-004-migration-plan.md
  • ADR-001 (driver protocol): resolved — BaseDriver sufficient
  • ADR-002 (HTML reporter): implemented in PR feat: add HTML reporter for visual diff dashboard #164
  • ADR-003 (ComparisonResult): superseded by this issue

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions