← back to Dw Sku Integrity
TK-10900: plan evidence updated — content-match SHIPPED + contrarian-hardened (Carnegie 70% safe)
e5896e1cf953548ac976c379bdd3ce58aca95121 · 2026-08-31 02:19:53 -0700 · codex-10896
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M evidence/TK-10900-rescrape-workplan.md
Diff
commit e5896e1cf953548ac976c379bdd3ce58aca95121
Author: codex-10896 <steve@designerwallcoverings.com>
Date: Mon Aug 31 02:19:53 2026 -0700
TK-10900: plan evidence updated — content-match SHIPPED + contrarian-hardened (Carnegie 70% safe)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
evidence/TK-10900-rescrape-workplan.md | 50 +++++++++++++++++++++-------------
1 file changed, 31 insertions(+), 19 deletions(-)
diff --git a/evidence/TK-10900-rescrape-workplan.md b/evidence/TK-10900-rescrape-workplan.md
index 9e1ea06..908336b 100644
--- a/evidence/TK-10900-rescrape-workplan.md
+++ b/evidence/TK-10900-rescrape-workplan.md
@@ -95,35 +95,47 @@ per-item verified, reversible + ledgered — identical guardrails to the TK-1089
## Verified content-match evidence (Carnegie, the 3,921-row canary)
-Measured this session, not assumed (VERIFY-BEFORE-ACTING):
+Measured this session by the actual tool (`content-match-gen.mjs`), not assumed. Two things the
+schemas forced (see the build insights): catalog `product_type` vocab does NOT match Shopify's
+(Shopify blanks are 99.8% `Upholstery`; the catalog splits one code across
+`Upholstery`/`Windows`/`Museum Display Cases`/`Wallcoverings`), and catalog schemas differ
+(`carnegie_catalog` has `color_number`; `knoll_catalog`/`rebelwalls_catalog` only `color_name`) —
+so the tool is schema-adaptive and uses `product_type` as a **bucket** (wall/fabric/other), not a key.
```
-raw-title exact match ....................... 0 / 3,921 (catalog stores no "Carnegie " prefix)
-title→pattern+color, mfr_sku suffix kept .... 35 unique / 3,872 "ambiguous" (suffix noise)
-title→pattern+color, base code (pre-"-") .... 1,825 unique (46.5%) / 2,082 width-ambiguous / 14 miss
+title→(pattern,color), base-code collapse, bucket TIEBREAK only (v1) .. 3,439 matched (87.7%) — UNSAFE
+ └─ contrarian (Cody) Defect B: single-candidate keys skipped the bucket check →
+ wall-only catalog codes (Abbey 61 -> 7394A61 'Upholstered Walls/Panels') stamped onto
+ Upholstery rows. Blast radius: 1,523 wall-only single-base keys.
+title→(pattern,color), bucket-compat HARD PRECONDITION (v2, shipped) ... 2,745 matched (70.0%) — SAFE
+ 694 cross_class_mismatch → review · 468 variant-fork ambiguous → review · 14 parse-miss
```
-The 2,082 residual are same-title Upholstery/Wallcovering pairs (`Arctic 11 => 7360A11 | 7360WA11`);
-the blank rows are `product_type='Upholstery'`, which selects the non-`W` base variant → expected
-**>90% unique** once the `product_type`/width tiebreak is added. The 14 no-match rows are the true
-tail for Program D (fresh scrape).
+**70.0% is the honest, safe rate** — every emitted code is bucket-compatible with the row. The 694
+cross-class + 468 ambiguous (1,162 total) defer to human review / Program D re-scrape rather than
+risk a wrong write ("a false-positive SKU is worse than a blank"). Expect similar or higher safe
+rates on clean-catalog vendors (no mint-`mfr_sku` indirection).
---
## Execution shape (per program, all gated writes fired by Steve)
-### Program A — `content-match-gen.mjs` (new; sibling of `staging-link-gen.mjs`)
+### Program A — `content-match-gen.mjs` (SHIPPED; sibling of `staging-link-gen.mjs`)
1. Read canonical blank-`dw_sku` active rows for the vendor (title, product_type, shopify_id).
-2. Read `<vendor>_catalog` → build `pattern_name + color_number → code` map, where
- `code = mfr_sku` (mint-catalog vendors) else `dw_sku`, **base-code cleaned** (strip `-<suffix>`),
- **excluding any greenfield-mint code** (reuse the `/tmp/_ledcodes.txt` reverted-mint exclude).
-3. Parse each Shopify `title` → `pattern + trailing color number`; join on the **strict uniqueness
- key `(normalized pattern, normalized color, product_type)`** — `product_type` is part of the KEY,
- not a post-hoc tiebreaker. Emit a write **only when that key maps 1:1 to exactly one base code**.
- Anything not strictly 1:1 (ambiguous, multi-code, or parse-miss) → **no-write + manual-review
- queue**, never a best-guess. Rationale (codex-confirmed 2026-08-31): a false-positive SKU written
- at scale is worse than leaving the row blank. Unique matches → `apply-plans-content-match/<vendor>/
- {apply,undo}.sql` + `restore-map.json`, `shopify_id`-keyed + blank-guarded.
+2. Schema-adaptively read `<vendor>_catalog` (detect `color_number` vs `color_name`) → build
+ `(pattern_name, color) → {baseCode → set(product_type bucket)}` map, where `code = mfr_sku`
+ (mint-catalog vendors) else `dw_sku`, **base-code cleaned** (strip only trailing `-<alpha>`
+ suffixes so numeric-hyphenated real codes survive), **excluding greenfield-mint + reverted-ledger
+ codes** (`/tmp/_ledcodes.txt`).
+3. Parse each Shopify `title` → `pattern + trailing color token`; look up `(pattern, color)`. Emit a
+ write **only when the key resolves to exactly ONE base code AND that code's catalog `product_type`
+ bucket is compatible with the row's bucket** (wall↔wall, fabric↔fabric; `other` passes). `product_type`
+ is a compatibility **precondition + tiebreak**, NOT a key component (its cross-source vocab mismatch
+ would otherwise cause misses). Anything else — multi-code fork, cross-class, parse-miss, no-map —
+ → **no-write + `review-queue.json`**, never a best-guess. Rationale (codex + contrarian, 2026-08-31):
+ a false-positive SKU is worse than a blank; the bucket precondition is what stops the Abbey-61 class.
+ Unique+compatible matches → `apply-plans-content-match/<vendor>/{apply,undo}.sql` + `restore-map.json`,
+ `shopify_id`-keyed + blank-guarded.
4. `preflight-check.mjs` (GO) → **Steve fires** → `verify` (GO) → ledger. Canary smallest vendor first
(Harlequin 1 → Arte 1 → Pierre Frey 4 → … → Carnegie 3,921 last).
5. Per-item verify sample (unbuyable-recovery methodology) before scaling each vendor.
← e47fdb5 TK-10900/A: fix cross-class wrong-write (contrarian Defect B
·
back to Dw Sku Integrity
·
TK-10900/A: graceful schema-gate + bucket_guard flag (sweep- 9aea723 →