# Mirror-Image Hunt — Act 1 Review (445–512) vs Earlier (1–444)

**Hypothesis (Michael):** some Review pieces may be horizontal (left–right) mirror images of an
earlier-drop GAN, even if only a single frame matches a single earlier frame.

**Verdict: NEGATIVE.** No Review piece is a deliberate mirror of a specific earlier piece. Every
"match" is explained by generic pixel-art symmetry and nearest-neighbour hubness, not by flipping.

## Method
- Loaded all 512 GIFs; every frame downsampled to native **32×32 RGB, PIL NEAREST**.
- Frame pools: **4,028** Review frames (445–512), **22,753** Earlier frames (1–444).
- Distance = **MAD** (mean absolute difference over the 3,072 RGB values, normalised to [0,1] by /255).
  0 = identical.
- For each Review frame: computed its **horizontal mirror** (`np.fliplr` on the 32×32 image) and found
  the single best Earlier frame (min MAD). Nearest neighbour found via BLAS L2 for speed, exact MAD
  reported for the winner.
- **Confound controls:**
  - `self_symmetry_dist` = MAD(frame, fliplr(frame)) — how symmetric the Review frame already is.
  - `best_plain_dist` = best UNflipped match to any earlier frame (baseline).
  - `plain_dist_at_mirror_frame` = unflipped match for the *same* review frame → **flip-gain** =
    plain@same − mirror. A true mirror needs a **large positive flip-gain** (flipping helps a lot) AND
    mirror ≪ self-symmetry (it matches the earlier piece better than it matches its own reflection).

## Calibration / sanity
- frame vs own unflipped self = 0.000 (verified).
- Self-symmetry across the 68 pieces: min 0.029 / median 0.161 / max 0.314 — many pieces are already
  near-symmetric, exactly the confound to beat.

## Distribution of best mirror-match distance (68 review pieces)
- min **0.034** / median **0.136** / max **0.237**; pctiles 10/25/75/90 = 0.087 / 0.110 / 0.166 / 0.195.
- No clean elite tier. The smallest distances belong to **washed-out light-pink noise frames** matching
  a single bright "hub" frame, **GAN 77** (essence *another*), which is the best-mirror target for 8
  different review pieces (121, 27, 111 are lesser hubs). Classic nearest-neighbour hubness — a bright,
  low-detail frame is everyone's nearest neighbour whether flipped or not.

## The real signal is absent
- **Flip-gain is tiny everywhere.** Max flip-gain over all 68 pieces = **+0.024** (rv462). The
  close-distance tier has flip-gain ≈ 0 (rv458 'soup' vs earl77: mirror 0.034 vs plain 0.035, gain
  +0.001 — flipping does nothing).
- **Strict true-mirror gate** (mirror_dist < 0.05 AND flip-gain > 0.03 AND beats self-symmetry by 0.03):
  **0 pieces.**
- The two pieces where flipping helps most are loose family resemblances, not mirrors:
  - **rv462 'never' → earl138 'only' (robo):** flip-gain +0.024, but mirror_dist 0.112 (≈28 gray-levels
    avg diff). Both are near-symmetric blocky robot faces; the mirrored review is visually identical to
    the unmirrored review. Robo-family resemblance.
  - **rv490 'knee' → earl88 (skull):** flip-gain +0.024, mirror_dist 0.107. Same story.

## Top mirror matches (ranked by mirror_dist)
| rv | essence | mirD | bestPlain | selfSym | flip-gain | earlier | drop | ess | read |
|----|---------|------|-----------|---------|-----------|---------|------|-----|------|
| 458 | soup | 0.034 | 0.035 | 0.029 | +0.001 | 77 | skull | another | bright-noise hub, not mirror |
| 453 | solve | 0.044 | 0.041 | 0.034 | −0.003 | 77 | skull | another | plain beats mirror |
| 497 | define | 0.051 | 0.050 | 0.062 | ~0 | 77 | skull | another | hub |
| 461 | buyer | 0.051 | 0.046 | 0.064 | neg | 77 | skull | another | hub, plain wins |
| 474 | truth | 0.062 | 0.064 | 0.064 | small | 77 | skull | another | hub |
| 468 | random | 0.085 | 0.086 | 0.113 | ~0 | 74 | skull | ankle | loose |
| 457 | poem | 0.087 | 0.085 | 0.147 | neg | 146 | robo | hollow | plain wins |
| 499 | sound | 0.091 | 0.087 | 0.090 | neg | 121 | skull | audit | hub, plain wins |
| 460 | tonight | 0.095 | 0.098 | 0.126 | +0.003 | 27 | skull | addict | loose |
| 456 | coffee | 0.096 | 0.102 | 0.124 | +0.006 | 74 | skull | ankle | loose |

## Strongest "flip helps" candidates (ranked by flip-gain — the meaningful axis)
| rv | essence | mirD | plain@same | flip-gain | selfSym | earlier | read |
|----|---------|------|-----------|-----------|---------|---------|------|
| 462 | never | 0.112 | 0.137 | +0.024 | 0.201 | 138 robo 'only' | robo family, mirror≈self |
| 490 | knee | 0.107 | 0.131 | +0.024 | 0.122 | 88 skull | family |
| 501 | project | 0.166 | 0.182 | +0.016 | 0.173 | 213 solstice | loose |
| 445 | collect | 0.212 | 0.228 | +0.016 | 0.157 | 270 solstice | loose |

Even the best flip-gain (0.024) is dwarfed by the match distance itself (0.11), i.e. flipping shaves a
sliver off an already-poor match. A genuine mirror reprise would look like mirror_dist ≈ 0.01–0.03 with
flip-gain ≈ 0.05–0.15. Nothing in the set approaches that.

## Outputs
- `mirror_matches.json` — per review piece: best_mirror_earlier_gan, earlier_frame, review_frame,
  mirror_dist, best_plain_dist, plain_dist_at_mirror_frame, self_symmetry_dist, mirror_beats_plain_margin.
- `mirror_pngs/01..10_*.png` — top-10 by mirror_dist, panels [review | mirrored review | earlier].
- `mirror_pngs/flipgain_01..04_*.png` — the flip-gain leaders.
- Scripts: `extract_frames.py`, `mirror_compare.py`, `aggregate.py`, `analyze.py`, `render.py`.
- Cached arrays: `review_frames.npy`, `earlier_frames.npy`, `*_idx.json`, `mir_*.npy`, `plain_*.npy`, `selfsym.npy`.

## Bottom line
The hypothesis does not hold at the single-frame pixel level. The closest "mirror" matches are bright
low-detail noise frames snapping to a hub frame (GAN 77), where flipping changes nothing; the pieces
where flipping *does* help are loose intra-family (robo/skull) resemblances at MAD ≈ 0.11, far from a
mirror. If Act 1 hides mirror reprises, they are not present as near-exact horizontal flips of any single
32×32 frame.
