[object Object]

← back to Dw Unbuyable Recovery Pilot

auto-data-snapshot: 2026-08-30T23:23:51 (1 data files) — data/cost-sourcing-feasibility.md

47d9d7f096171604bc8d127a16958809559958b0 · 2026-08-30 23:37:13 -0700 · auto-commit-fleet

Files touched

Diff

commit 47d9d7f096171604bc8d127a16958809559958b0
Author: auto-commit-fleet <steve@designerwallcoverings.com>
Date:   Sun Aug 30 23:37:13 2026 -0700

    auto-data-snapshot: 2026-08-30T23:23:51 (1 data files) — data/cost-sourcing-feasibility.md
---
 data/cost-sourcing-feasibility.md | 81 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/data/cost-sourcing-feasibility.md b/data/cost-sourcing-feasibility.md
new file mode 100644
index 0000000..2c4262e
--- /dev/null
+++ b/data/cost-sourcing-feasibility.md
@@ -0,0 +1,81 @@
+# Cost-Sourcing Feasibility Matrix — Unbuyable ACTIVE Recovery (TK-10978)
+
+Follow-on to TK-10875 (Wolf Gordon 224 + Scalamandre 144 recovered — both had joinable staging cost, SHIPPED). This matrix ranks the **top ~20 cost-BLOCKED vendors** (their `<vendor>_catalog` staging tables have empty cost columns) so Steve's cost-sourcing greenlight is concrete, vendor-by-vendor.
+
+**All findings from read-only local `dw_unified` (/tmp socket) reads + scraper SKILL.md reads. $0. No scrapes, no writes, no gated actions.**
+
+## The reframe that changes the ROI ranking
+
+"Unbuyable" ≠ "needs a cost." A product is sellable in **two** ways:
+
+1. **Priceable** — we have a real published price or a cost to compute one (`cost/0.65/0.85`). Needs cost SOURCED. This is the classic cost-blocked case.
+2. **Quote-only** — the line legitimately publishes **no price** (bespoke / contract / trade-quote). These recover via the **Pierre-Frey pattern** (already proven live): sellable variant is the `$4.25` sample + `quotes` tag + `Needs-Price`, product price NULL. **No cost needs sourcing at all** — this is a variant-build job, not a cost-sourcing job.
+
+The registry flag `do_not_price=t` marks the policy quote-only lines. This splits the backlog cleanly and is the single most important input to sequencing.
+
+## Matrix (sorted by unbuyable count)
+
+| Vendor | Unbuyable | Class | Staging cost col populated? | Scraper fetches cost? | Blocker | Effort |
+|---|---:|---|---|---|---|---|
+| **Phillipe Romano** | 8274 | TRADE-PORTAL (private label; source = York/Brewster) | `phillipe_romano_catalog` price_trade **0/3503**, price_retail 474/3503 | Partial — retail only, no trade cost | Steve cost list OR gated York/Brewster trade-portal scrape (yorkwall.com login). Source vendor is York/Brewster per registry | HIGH |
+| **Koroseal** | 2448 | TRADE-PORTAL / quasi-QUOTE (contract vinyl, `buy_from=Direct`) | `koroseal_catalog` **no price/cost columns at all** | No — scraper captures specs/images only | Koroseal contract line is loginforprice; needs Steve cost list OR gated login scrape. No price scaffolding exists | HIGH |
+| **Phillip Jeffries** | 2338 | QUOTE-ONLY (`do_not_price=t`, `buy_from=Direct`) | `pj_catalog` **no price/cost columns** | No | None for cost — recover via **quotes-tag path** (no cost needed). PJ is trade-quote by policy | LOW (quotes path) |
+| **China Seas** | 1776 | QUOTE-ONLY (`do_not_price=t`; Quadrille house) | `china_seas_catalog` **no price cols**; `quadrille_house_catalog` cost_price 0/1942 | No | **quotes-tag path** — no cost needed | LOW (quotes path) |
+| **Coordonné** | 1299 | FEED-FIRST priceable (`display_prices=t`, discount 20%) | `coordonne_catalog` price_retail **3676/6460**, price_trade 0 | Partial — retail captured, no net cost | Have list retail for ~57%; either apply 20% trade discount to net + `/0.65/0.85`, OR re-scrape to fill remaining retail. Cheapest priceable win | MED |
+| **Pierre Frey** | 659 | QUOTE-ONLY (confirmed in skill; `buy_from=Schumacher`) | `pierre_frey_catalog` our_price 0/1161 | No — skill states "QUOTE-ONLY, no per-SKU price even in portal" | **quotes-tag path already proven for PF** — no cost needed. Pure variant-build | LOW (quotes path) |
+| **Maya Romanoff** | 620 | UNKNOWN → likely TRADE/QUOTE (`buy_from=Quintus`) | `maya_catalog` **no price/cost cols** | No — scraper is sitemap→products.json, no price | Needs investigation: is MR priced or quote? Dedicated scraper-manager exists but doesn't fetch cost. Likely Steve cost list | MED |
+| **Rebel Walls** | 494 | FEED-FIRST priceable (public price storefront, no auth) | `rebelwalls_catalog` price_retail **4382/4383**, price_per_sqft_* 4133/4383; price_trade 449 | **YES** — public per-m² price fully captured | Nearly all retail present already. Compute DW sell from per-m² retail (per-sqft cols populated). Best pure-feed win | LOW |
+| **Arte** | 489 | FEED-FIRST priceable (customer-facing, discount 0) | `arte_catalog` cost 0/1991, price 0/1991 | Colorway scraper captures color/SKU, **not price** | Re-scrape needs a price source; Arte colorway scraper is DOM-based for colorways only. Needs cost list or price-capturing scrape | MED |
+| **Quadrille** | 443 | QUOTE-ONLY (`do_not_price=t`; Quadrille house) | `quadrille_house_catalog` cost_price 0/1942 | No | **quotes-tag path** — no cost needed | LOW (quotes path) |
+| **Alan Campbell** | 434 | QUOTE-ONLY (`do_not_price=t`; Quadrille house) | `quadrille_house_catalog` cost_price 0/1942 | No | **quotes-tag path** — no cost needed | LOW (quotes path) |
+| **Vahallan** | 390 | UNKNOWN (registry 'Vahallan' → shared `vendor_catalog`, no cost; dedicated `vahallan_catalog` exists, no price cols) | `vahallan_catalog` **no price/cost cols** | No — no SKILL.md for Vahallan | Needs investigation: table mapping ambiguous (2 registry rows). Likely quote/handmade. Confirm table + pricing model first | MED (invest.) |
+| **CMO Paris** | 344 | FEED-FIRST priceable (`display_prices=t`, no `do_not_price`) | `cmo_paris_catalog` cost 0/345, price 0/345 | Shared-engine scraper, no dedicated cost logic | Re-scrape with price capture OR Steve cost list. Small count | MED |
+| **Malibu Wallpaper** | 339 | TRADE-PORTAL (private label = WallQuest; cost EXISTS but SKU-remap needed) | `malibu_catalog` cost 0/3718; **`wallquest_catalog` net_cost 2085/2515 (source has cost!)** | **YES** (WallQuest browserbase login captures net_cost=cost) | Cost exists in the WallQuest source table but Malibu unbuyable SKUs join only **1/339** by mfr_sku/dw_sku — needs a private-label SKU-reconcile, not a fresh scrape | MED (reconcile) |
+| **Architectural Fabrics** | 328 | TRADE-PORTAL (Fabricut-family; `buy_from=Duralee`) | `fabricut_catalog` price_trade **0/1333**, price_retail/vendor_msrp 1263/1333 | **YES** (scraper schema has price_trade col; Fabricut login) — but trade col currently empty | Have MSRP; net cost from Fabricut trade portal (login exists). Or derive from MSRP × discount. Fabricut portal is a known CF-challenge target | MED |
+| **AS Creation** | 327 | FEED-FIRST priceable (retail scrape returned currency only) | `as_creation_catalog` price_retail **0/6166** (price_currency=EUR filled) | Partial — scrape got currency but no number | Re-scrape to capture the numeric price (structure is there, extraction missed the value). Cheap fix | MED |
+| **Suncloth** | 254 | QUOTE-ONLY (`do_not_price=t`; Quadrille house) | `quadrille_house_catalog` cost_price 0/1942 | No | **quotes-tag path** — no cost needed | LOW (quotes path) |
+| **Home Couture** | 229 | QUOTE-ONLY (`do_not_price=t`; Quadrille house) | `quadrille_house_catalog` cost_price 0/1942 | No | **quotes-tag path** — no cost needed | LOW (quotes path) |
+| **Thibaut** | 203 | FEED-FIRST priceable (cost already exists — mostly recovered) | `thibaut_catalog` net_cost **3670/6057**, your_cost 3625/6057 | **YES** — Thibaut scraper captures net_cost | These 203 are the join-gap tail; cost exists for most Thibaut. Likely a TK-10875-style join recovery, NOT cost-blocked | LOW |
+
+## Class rollup
+
+| Class | Vendors | ~Unbuyable | What it needs |
+|---|---|---:|---|
+| **QUOTE-ONLY (recover via quotes-tag, NO cost needed)** | Phillip Jeffries, China Seas, Pierre Frey, Quadrille, Alan Campbell, Suncloth, Home Couture | **~5,689** | Variant-build only (Pierre-Frey pattern). Zero cost sourcing. |
+| **FEED-FIRST-$0 (cost/price re-scrapeable, no login)** | Rebel Walls, Coordonné, AS Creation, CMO Paris, Arte | ~2,953 | (Re)scrape the public price the extractor missed / derive DW sell |
+| **TRADE-PORTAL (gated login scrape or SKU-reconcile)** | Phillipe Romano, Koroseal, Malibu, Architectural Fabrics | ~11,389 | Gated trade-portal scrape (SPEND if Browserbase/2captcha) OR Steve cost list |
+| **JOIN-GAP tail (cost already exists — TK-10875-style)** | Thibaut | ~203 | Join recovery, not cost sourcing |
+| **UNKNOWN (needs investigation first)** | Maya Romanoff, Vahallan | ~1,010 | Confirm table + pricing model before classing |
+
+## Recommended sequencing
+
+### Track 0 — the "free" prize (do FIRST, no cost sourcing at all): QUOTE-ONLY quotes-tag recovery
+**~5,689 unbuyable across 7 vendors** (PJ, China Seas, Pierre Frey, Quadrille, Alan Campbell, Suncloth, Home Couture) recover with **zero cost input** — they are legitimately quote-only (`do_not_price=t` / confirmed in PF skill). Build the `$4.25`-sample + `quotes` tag + `Needs-Price` variant (the **already-live Pierre Frey pattern**). This is the highest-ROI move: biggest recovery, no cost list, no gated scrape, no spend. **This is a variant-build job, not the cost-sourcing job Steve is greenlighting — so it likely doesn't even need his cost greenlight; it needs a quotes-path build ticket.**
+
+### Track A — gated scrapes / internal reconciles (agent can execute once armed)
+Ranked by ROI (recovery per unit effort):
+1. **Rebel Walls (494)** — public price storefront, `price_retail` 4382/4383 + per-sqft cols already populated. Pure compute → sell price. Cheapest priceable win, no login, no spend.
+2. **Malibu (339)** — cost EXISTS in `wallquest_catalog` (net_cost 2085/2515); needs a **private-label SKU-reconcile** (Malibu↔WallQuest join is 1/339 today). Internal DB work, no new scrape.
+3. **Coordonné (1299)** — retail 3676/6460 + 20% trade discount known; derive net + DW sell for the 57% we have, re-scrape the rest. Feed-first, no login.
+4. **AS Creation (327)** — extractor got currency but not the number; a targeted re-scrape fixes the numeric-price extraction. Feed-first.
+5. **CMO Paris (344)** / **Arte (489)** — re-scrape with price capture (shared-engine / colorway scraper doesn't currently fetch price). Feed-first, low count.
+6. **Architectural Fabrics / Fabricut (328)** — MSRP present; net cost via Fabricut trade portal (login exists) **or** derive from MSRP × discount. **GATED + possible SPEND** — Fabricut is a known Cloudflare-challenge target (may need Browserbase/2captcha → cost-tracker).
+
+### Track B — needs Steve to supply a trade cost list (no scrapeable price exists)
+1. **Phillipe Romano (8274)** — biggest single prize but hardest. Private label; source = York/Brewster trade portal (yorkwall.com login). Either Steve supplies the PR/York cost list OR a gated York/Brewster trade-portal scrape. No retail exists for 87% of rows. **Split by collection to make tractable.**
+2. **Koroseal (2448)** — contract vinyl, loginforprice, no price scaffolding in staging at all. Steve cost list OR gated Direct login scrape.
+3. **Maya Romanoff (620)** — investigate first (priced vs quote?); scraper doesn't fetch cost. Likely Steve cost list.
+
+### Track C — investigate before classing
+- **Vahallan (390)** — ambiguous table mapping (2 registry rows, `vendor_catalog` vs `vahallan_catalog`, neither has cost). Confirm the real feed + whether it's quote/handmade before assigning a track.
+- **Thibaut tail (203)** — almost certainly a TK-10875-style join recovery (cost already staged); verify and fold into the Wolf-Gordon/Scalamandre recovery pattern, not the cost-sourcing effort.
+
+## The one-line recommendation for Steve
+
+**Greenlight Track 0 (quotes-tag build, ~5,689 recovered, $0, no cost list) immediately — it's the largest recovery and needs no cost at all. Then Track A feed-first/reconcile (Rebel Walls → Malibu → Coordonné → AS Creation, ~2,459 more, mostly $0 local/no-login). Hold Track B (Phillipe Romano 8274 + Koroseal 2448) for a cost-list decision — those two alone are ~44% of the backlog but are the ones that genuinely can't be scraped.**
+
+## Uncertainty flags (not fabricated — marked UNKNOWN in the matrix)
+- **Maya Romanoff** and **Vahallan** classed UNKNOWN — no cost columns and no cost-fetching scraper; could be quote-only OR need a cost list. Do not assume priceable.
+- **Malibu 1/339 join** — the low join rate is real (measured); root cause (SKU-form remap vs genuinely-absent WallQuest rows) not yet confirmed. Reconcile effort could be small (remap) or larger (missing source rows).
+- **Coordonné / AS Creation** — retail present but partial/malformed; assumed re-scrape fixes it, not verified end-to-end.
+- Registry `buy_from` (Pierre Frey→Schumacher, Maya→Quintus, Fabricut→Duralee) implies the real cost owner may be the distributor, not the named brand — affects where a cost list would come from.

← 7c8e401 TK-10978 Scalamandre add-roll recovery complete: 124 acted +  ·  back to Dw Unbuyable Recovery Pilot  ·  TK-10978: VERIFY correction — Track 0 quote-only 'free prize 5a24ba1 →