← back to Newmor Onboard
Newmor onboard cycle 1: reconciliation + metafield map artifacts (TK-10670)
a9b82b85f56564909c55ef742b9f4fcf863c5217 · 2026-08-18 09:21:58 -0700 · steve@designerwallcoverings.com
Files touched
A .gitignoreA README.mdA artifacts/METAFIELD-MAP.mdA artifacts/RECONCILIATION.md
Diff
commit a9b82b85f56564909c55ef742b9f4fcf863c5217
Author: steve@designerwallcoverings.com <steve@designerwallcoverings.com>
Date: Tue Aug 18 09:21:58 2026 -0700
Newmor onboard cycle 1: reconciliation + metafield map artifacts (TK-10670)
---
.gitignore | 7 +++++++
README.md | 5 +++++
artifacts/METAFIELD-MAP.md | 41 +++++++++++++++++++++++++++++++++++++++++
artifacts/RECONCILIATION.md | 43 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 96 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..08240ae
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+node_modules/
+.env*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d4cdd3a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+# newmor-onboard (TK-10670)
+Refresh + complete the existing Newmor line (registry id 56) under series DWNM-.
+Distributor: LBI Boyd. All specs -> Shopify metafields, never body_html.
+See artifacts/RECONCILIATION.md + artifacts/METAFIELD-MAP.md.
+Pricing PARKED (no cost basis). Catalog refresh BLOCKED (Norman/newmor-agent down).
diff --git a/artifacts/METAFIELD-MAP.md b/artifacts/METAFIELD-MAP.md
new file mode 100644
index 0000000..0fcdcfc
--- /dev/null
+++ b/artifacts/METAFIELD-MAP.md
@@ -0,0 +1,41 @@
+# Newmor → Shopify spec→METAFIELD mapping (TK-10670)
+
+HARD RULE (Steve, 2026-08-18): **all spec/metafield info goes into Shopify METAFIELDS, never body_html.**
+`body_html` stays clean marketing prose only. This map is the enforcement contract for the
+(gated) publish/backfill.
+
+Source: `newmor_catalog` columns → Shopify metafield. Namespace defaults to `custom.*`;
+FINAL namespace/keys must be reconciled against the existing DW live metafield schema
+(verify from a live Newmor/commercial product in cycle 2 before any write) so we don't fork keys.
+
+| catalog column | Shopify target | metafield type | notes |
+|-----------------------|-----------------------------------|-------------------------|-------|
+| width / width_inches | `custom.width` | dimension | coverage 787/1294 — gap |
+| length | `custom.roll_length` | dimension | coverage 1045/1294 |
+| coverage | `custom.coverage` | single_line_text_field | EMPTY (0) — needs refresh |
+| repeat_v | `custom.pattern_repeat_vertical` | dimension | EMPTY (0) — needs refresh |
+| repeat_h | `custom.pattern_repeat_horizontal`| dimension | EMPTY (0) — needs refresh |
+| match_type | `custom.pattern_match` | single_line_text_field | EMPTY (0) — needs refresh |
+| material | `custom.material` | single_line_text_field | coverage 617/1294 |
+| finish | `custom.finish` | single_line_text_field | EMPTY (0) — needs refresh |
+| fire_rating | `custom.fire_rating` | single_line_text_field | EMPTY (0) — commercial line, IMPORTANT |
+| application | `custom.application` | single_line_text_field | EMPTY (0) — needs refresh |
+| features | `custom.features` | list.single_line_text | |
+| color_primary | `custom.color_primary` | single_line_text_field | |
+| color_secondary | `custom.color_secondary` | single_line_text_field | |
+| color_hex / dominant_color_hex | `custom.color_hex` | color | |
+| us_distributor | `custom.us_distributor` | single_line_text_field | = "LBI Boyd" (Steve-confirmed) |
+| product_type | Shopify **product_type** (native) | — | NOT a metafield |
+| collection | Shopify **tag/collection** | — | NOT a metafield |
+| product_url | `custom.vendor_url` | url | |
+
+## body_html policy
+- KEEP: marketing prose (pattern story, designer, base options). Current bodies are clean
+ (only 46/1284 mention a spec token) — light cleanup, not systemic.
+- STRIP from body if present: width/repeat/fire-rating/match/coverage → move to the metafields above.
+
+## Data-gap flag (feeds refresh branch)
+repeat_v/repeat_h, finish, fire_rating, application, match_type, coverage are ALL empty in
+`newmor_catalog`. For a **commercial** line, fire_rating + application + match are material specs.
+→ the catalog REFRESH (via Norman/newmor-agent, currently DOWN) must recapture these before
+the metafield backfill is meaningful.
diff --git a/artifacts/RECONCILIATION.md b/artifacts/RECONCILIATION.md
new file mode 100644
index 0000000..f985bde
--- /dev/null
+++ b/artifacts/RECONCILIATION.md
@@ -0,0 +1,43 @@
+# Newmor SKU normalization reconciliation (TK-10670)
+
+Goal: bring the 543 mfr-coded LIVE Newmor products onto the canonical `DWNM-58xxxx` series
+(Steve-ruled), deduping against the existing 1,294-row `newmor_catalog` (which already holds
+the DWNM codes). NO new series. NO duplicates.
+
+## Data topology (verified 2026-08-18, cycle 1)
+- `newmor_catalog`: 1,294 rows; **1,285 already carry a distinct `DWNM-58xxxx` `dw_sku`** (9 lack one).
+ Keyed internally by `mfr_sku` + legacy numeric REST id (`shopify_product_id`, e.g. 7810541092915).
+- `shopify_products` (live mirror): 544 Newmor rows; **543 still mfr-coded** (`Brushed Steel BST-008`),
+ only 1 already DWNM. Its `dw_sku` column is ALSO mfr-coded (not the DWNM code). Keyed by
+ GraphQL gid (`gid://shopify/Product/4351...`) — a DIFFERENT id space than the catalog.
+- ⇒ catalog↔live can only be bridged by `mfr_sku`. The numeric-REST-id ↔ gid map is absent.
+
+## Match quality (the blocker)
+- Raw exact mfr_sku join: 126/544.
+- Normalized (upper+trim) join: **126/544 = 23.2%** — no better.
+- Root cause: many LIVE `mfr_sku` are malformed collection-level junk
+ (`ARONA-COMMERCIAL-WALLCOVERING-ARONA`, sku `Arona -`) while catalog codes are clean (`AR-103`).
+
+## Decision (DTD-committed, cycle 1)
+A 543-row live SKU rewrite off a 23%-confident map is unsafe → **HOLD the gated rewrite.**
+Cycle 2+ must raise match confidence first:
+1. Fuzzy pattern-code extraction: pull the trailing `[A-Z]{2,4}-\d{2,4}` code from both live sku
+ and catalog mfr_sku, match on that; then match residuals by pattern_name + color_name.
+2. Re-measure; only when a high-confidence tier (target ≥ ~90%) exists do we draft the gated rewrite.
+3. Assign DWNM to the 9 catalog rows lacking `dw_sku`.
+
+## Staged artifact (reversible)
+`newmor_sku_reconcile` table in dw_unified (Mac2 staging). Drop-to-undo. Columns:
+`shopify_id, handle, live_sku, mfr_sku, k(normalized), target_dwnm, has_target, live_already_ok`.
+Current: 126 matched / 418 unmatched-flagged / 0 already-ok.
+
+## Gated (NOT executed — pending-approval when ready)
+- Live variant-SKU rewrite on the 543 products (customer-facing).
+- Publish of the ~751 catalog rows not yet on Shopify.
+- Any live price write (BLOCKED separately — see pricing branch).
+
+## Branch status
+- SKU normalization: IN PROGRESS (match rate too low → cycle-2 fuzzy pass).
+- Metafield map: DEFINED (see METAFIELD-MAP.md); backfill gated + depends on refresh.
+- Catalog refresh: BLOCKED — newmor-agent (Norman, :9695) is DOWN in pm2.
+- Pricing: PARKED — `newmor_catalog` has 0/1294 cost; needs LBI Boyd cost list (vendor-price-ingest).
(oldest)
·
back to Newmor Onboard
·
Cycle1 fix: 3-bucket disposition + never-overwrite metafield b4d774a →