← back to Dw Unbuyable Recovery Pilot
tk11041-innovations-reconcile/README.md
68 lines
# TK-11041 — Innovations missing-cohort reconciliation (feed-first / local)
Child of **TK-10978** (unbuyable recovery). Agent `iterm-tk11041-innovations`, finalizer `/root`, chain depth 1.
**READ-ONLY. No Shopify writes. No dw_unified writes. No catalog activation. No send/deploy.**
## Objective
Determine, deterministically, whether the **51** ACTIVE, sample-only Phillipe-Romano
private-label Innovations products can be made buyable from any **local / feed-first**
source before falling back to the gated Innovations vendor line-sheet request.
## Cohort (deterministic — reproduces exactly 51)
```
vendor='Phillipe Romano' AND status='ACTIVE'
AND NOT has_product_variant -- unbuyable: only the $4.25 memo Sample
AND supplier_name ~* 'innov'
```
8 collections: CSO, ENS, FLN, PRO, SKL, TTM, VCO, WHL.
## Files
| File | Role |
|---|---|
| `reconcile.mjs` | Read-only generator → `data/innovations-recovery-map.{json,csv}` + `data/reconcile-summary.json` |
| `lib/provenance.mjs` | **Source-provenance guard** (the narrow hardening) — pure, unit-tested |
| `test/provenance.test.mjs` | Proves the guard on positive/negative + LIVE corrupted rows |
| `verification/e2e-proof.json` | R1 evidence bundle |
Run: `node reconcile.mjs && node --test test/provenance.test.mjs`
## Result — BLOCKED_ON_VENDOR_LINESHEET (0/51 locally recoverable)
Every candidate local recovery path returns **zero** for the cohort:
| Recovery key | Hits across 51 |
|---|---|
| `sp.sku = innovations_catalog.dw_sku` | 0 |
| `sp.dw_sku = innovations_catalog.dw_sku` | 0 |
| `sp.mfr_sku = innovations_catalog.mfr_sku` | 0 |
| feed-first pattern-token word-match on `pattern_name` | 0 |
### Why (provenance)
- The 51 carry only **DW-internal collection codes** (`CSO-001`, `ENS-01`, …) in `mfr_sku`,
private-label `La <Pattern>` titles, an empty `dw_sku`, **no real Innovations item number,
and no price**. Their underlying pattern tokens (Turino, Renegado, Bologna, Youngstown,
Sieno, Udino, Orvito) **do not appear** anywhere in `innovations_catalog.pattern_name`.
- `innovations_catalog` (341 rows) is a scrape of the **Innovations USA (`DWIN-`) line** — a
*different* product line (295 of its linked products are vendor `Innovations USA`), not the
Phillipe-Romano private-label. It is also **corrupted**: 236/341 rows have **no
`product_url`** and **81/341** carry a fabricated *pattern-name-tail* code
(`Sum`**`atra`** → `atra-1`, `Maz`**`arin`** → `arin-1`). Only **99/341** rows are
trustworthy sources.
**Conclusion:** there is no honest local source; backfilling the 51 from `innovations_catalog`
would fabricate customer-facing identity/price (same failure the TK-10981 HOLD flagged).
Recovery genuinely requires the **gated vendor line-sheet** already drafted for Steve
(`pending-approval/_done/2026-08-31-TK11041-innovations-pricing-request-letter.md`). On receipt,
match the line-sheet on pattern+colorway and stage the proven add-yard variant
(`net_trade/0.65/0.85` per yard via `scripts/innovations-reprice/stage-innov-reprice.mjs`) —
that Shopify write stays gated.
## Hardening shipped
`lib/provenance.classifyCatalogSource(row)` gates any `*_catalog` row before it is trusted as a
recovery source: rejects no-provenance rows, placeholder codes (`TRUE`/`NULL`), lowercase-tail
truncations, and codes that are a tail of the pattern name. This turns the TK-10981 "plausible
shape ≠ proof" caveat into an executable guard the reprice/backfill path can call, so a future
re-scrape cannot silently reintroduce fabricated identity data. `test/` proves it (7/7),
including a LIVE assertion that **0** of the catalog's fabricated rows are wrongly trusted.