← back to Designer Wallcoverings
pending-approval/anna-french-anomaly-resolution-2026-06-25.md
93 lines
# Anna French — 65-anomaly resolution plan (GATED, needs Steve sign-off)
**Date:** 2026-06-25
**Owner:** vp-dw-commerce
**Source:** `shopify/scripts/cadence/data/anna-french/anna-french-repair-commit-2026-06-25.json` (the COMMIT-mode audit; 455 products already repaired live, 65 anomalies safely skipped)
**Full per-item data:** `/tmp/af-anomaly-resolutions.json`
**Status:** read-only analysis complete; NO live writes performed in this pass.
---
## TL;DR
The 478-product AF repair landed; 65 products were safely **skipped** (never mis-written). They split:
| Class | Count | Disposition |
|---|---|---|
| **Handle collision (cross-type)** | **32** | ✅ **AUTO-FIXABLE** — propose media-suffix rule, gated commit |
| Multi-match, color inconclusive | 21 | ⚠️ NOT auto-resolvable from current signals — metafield-color pass or manual |
| Type mismatch (live typed opposite staging) | 10 | 🔍 Investigate — defer |
| GID missing (mirror stale/deleted) | 2 | 🔁 Re-sync mirror → cadence |
---
## 1. The 32 collisions — clean deterministic fix (the ask)
**Finding (verified 32/32):** every collision is a **Fabric (AF) and a Wallcovering (AT) of the same pattern+color** that computed the *identical* clean handle.
Example: `AF15119` (fabric "Cornwall Blush") wants `cornwall-blush-anna-french`, but `DWAT-65039` (wallcovering "Cornwall Blush") already holds it. Same pattern, different media — NOT a duplicate.
**Proposed rule:** keep the **wallcovering** on the bare handle; give the **fabric** a media qualifier:
`cornwall-blush-anna-french` (WC) → `cornwall-blush-fabric-anna-french` (fabric).
(Direction is a Steve decision — alternative is to suffix the wallcovering instead. Default proposed: suffix the fabric, since AT/wallcovering is the larger established cohort.)
**Execution (on approval):**
- Dry-run a `--collisions-only` variant of `anna-french-repair-inplace.mjs` that, for these 32, sets the disambiguated handle + completes the rest of the repair (SKU flip, sample fix, leak scrub) that was skipped.
- Idempotent + per-product, same as the main run. Captured audit JSON.
- ~32 products → minutes, $0 (Admin API + local PG).
**Decision needed:** (a) approve the media-suffix fix? (b) suffix the *fabric* or the *wallcovering*?
## 2. The 21 multi-matches — needs a better signal (no blind write)
Each `mfr_sku` matched **two** live products of the same type; the candidates carry **old-scheme handles** (`dwta-65099designerwallcovering`) with no color in them, so color can't disambiguate. 0/21 auto-resolved.
**Proposed next step (read-only, separate pass):** match the staging `color_name` against each candidate's live **color metafield / variant option**, not the handle. Items that still tie → manual review list for Steve. **No writes until a candidate is unambiguously chosen.**
## 3. The 10 type-mismatches — investigate (defer)
Staging says Wallcovering (AT, ×8) or Fabric (AF, ×2) but the only live candidate is typed the **opposite** (e.g. `AT57851` WC vs a live Fabric `dwtt-80280…`; `AF15124` fabric vs a live WC `cornwall-wallcoverings-af15124-…-thibaut`).
Either staging's deterministic type is wrong, or the live product needs a `product_type` correction. **Needs a judgment call per item — do NOT auto-flip type.** Defer to an investigation pass.
## 4. The 2 missing GIDs — mirror hygiene (defer)
`AT78737`, `AT78742`: chosen GID not found live (mirror stale or product deleted). **Re-sync `shopify_products` mirror, then re-plan**; if truly absent, they are net-new → land via the **metered cadence** (per standing rule: only cadence creates products).
---
## Recommendation
Approve **#1 (the 32 collisions)** now — it's deterministic and the clear win. Let me run **#2's read-only metafield-color pass** to shrink the 21 before any decision. Hold **#3/#4** for a separate investigation. Nothing here writes to live until you approve #1's direction.
---
## UPDATE 2026-06-25 — collision fix EXECUTED (Steve approved: fabric gets `-fabric`)
DB-driven via `dw_unified.anna_french_catalog.product_type` (type is authoritative; widths vary per pattern).
**DONE & verified live:**
- **Phase 1 — 52 fabrics → `-fabric-anna-french`** (handle-only). 52/52 verified live. Redirects: 20 created + **32 stale redirects corrected** (had pointed old→bare, now the wallcovering's).
- **Phase 2a — 30 single-match wallcoverings:** 26 already-correct (NOOP, fixed in the main run), **4 blocked by type-mismatch** (AT57851/57852/78734/15121 — live product typed Fabric, not Wallcovering).
**COLLISION FIX COMPLETE for all unambiguous cases.** Remaining = gated:
### Phase 2b — 14 DUPLICATE wallcoverings (NEEDS STEVE)
Each mfr_sku has **two** live products (the multi-match anomalies = real dupes). Resolving = pick canonical + **ARCHIVE the dupe** (never delete). Cannot auto-decide which is canonical.
| mfr_sku | product A | product B |
|---|---|---|
| AT23109 | 6948071407667 | 6948071637043 |
| AT23110 | 6948071538739 | 6948071342131 |
| AT24535 | 6948067016755 | 7552709558323 |
| AT24536 | 6948066951219 | 7552709623859 |
| AT24537 | 6948066852915 | 7552709722163 |
| AT24539 | 7552709787699 | 6948067049523 |
| AT24540 | 7552709853235 | 6948066918451 |
| AT24544 | 6948067213363 | 7552710017075 |
| AT24556 | 7552710574131 | 6948068098099 |
| AT24560 | 7552710770739 | 6948067639347 |
| AT24561 | 6948067573811 | 7552710901811 |
| AT24562 | 6948067508275 | 7552710934579 |
| AT9833 | 6948075798579 | 7552735215667 |
| AT9860 | 6948075307059 | 7552736591923 |
**Proposed canonical rule (needs OK):** keep the product whose variant SKU matches staging `dw_sku` (new DWAT scheme) and is ACTIVE w/ images; archive the legacy DWTA/DWTT twin. I can build a read-only side-by-side (status/images/SKU/created-date) for all 14 before any archive.
### Phase 2c — ~10 type-mismatches (investigate)
Live product typed opposite to staging (AT57851 etc.). Needs per-item judgment — do NOT auto-flip product_type.
### Phase 3 — 2 missing GIDs / net-new → metered cadence (only cadence creates products).