← back to Designer Wallcoverings
auto-save: 2026-07-27T20:24:23 (9 files) — shopify/scripts/data/tk135/audit-grid.png shopify/scripts/data/tk135/audit-thumbs/ shopify/scripts/data/tk135/bakeoff-grid.png shopify/scripts/data/tk135/bakeoff-thumbs/ shopify/scripts/data/tk135/material-sample200-unmatched.tsv
7ff5efd785f55e82049b90ac9f7297d8792d7cee · 2026-07-27 20:24:29 -0700 · Steve Abrams
Files touched
A shopify/scripts/data/tk135/audit-grid.pngA shopify/scripts/data/tk135/audit-thumbs/1495138402416.jpgA shopify/scripts/data/tk135/audit-thumbs/4509315170355.jpgA shopify/scripts/data/tk135/audit-thumbs/7375645245491.jpgA shopify/scripts/data/tk135/audit-thumbs/7422637310003.jpgA shopify/scripts/data/tk135/audit-thumbs/7866927120435.jpgA shopify/scripts/data/tk135/audit-thumbs/7878155206707.jpgA shopify/scripts/data/tk135/bakeoff-grid.pngA shopify/scripts/data/tk135/bakeoff-thumbs/1495150952560.jpgA shopify/scripts/data/tk135/bakeoff-thumbs/1497253183600.jpgA shopify/scripts/data/tk135/bakeoff-thumbs/6829062881331.jpgA shopify/scripts/data/tk135/bakeoff-thumbs/7584977715251.jpgA shopify/scripts/data/tk135/bakeoff-thumbs/7855831384115.jpgA shopify/scripts/data/tk135/bakeoff-thumbs/7855840002099.jpgA shopify/scripts/data/tk135/bakeoff-thumbs/7882757308467.jpgA shopify/scripts/data/tk135/bakeoff-thumbs/7882828120115.jpgA shopify/scripts/data/tk135/bakeoff-thumbs/7896279056435.jpgA shopify/scripts/data/tk135/bakeoff-thumbs/7896475795507.jpgA shopify/scripts/data/tk135/material-sample200-unmatched.tsvA shopify/scripts/data/tk135/material-sample200.tsvA shopify/scripts/data/tk135/vision-bakeoff-10.tsvA shopify/scripts/data/tk17/batchA-full-run.jsonA shopify/scripts/tk135-material-classifier-dryrun.js
Diff
commit 7ff5efd785f55e82049b90ac9f7297d8792d7cee
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Jul 27 20:24:29 2026 -0700
auto-save: 2026-07-27T20:24:23 (9 files) — shopify/scripts/data/tk135/audit-grid.png shopify/scripts/data/tk135/audit-thumbs/ shopify/scripts/data/tk135/bakeoff-grid.png shopify/scripts/data/tk135/bakeoff-thumbs/ shopify/scripts/data/tk135/material-sample200-unmatched.tsv
---
shopify/scripts/data/tk135/audit-grid.png | Bin 0 -> 883857 bytes
.../data/tk135/audit-thumbs/1495138402416.jpg | Bin 0 -> 112645 bytes
.../data/tk135/audit-thumbs/4509315170355.jpg | Bin 0 -> 17706 bytes
.../data/tk135/audit-thumbs/7375645245491.jpg | Bin 0 -> 15434 bytes
.../data/tk135/audit-thumbs/7422637310003.jpg | Bin 0 -> 21950 bytes
.../data/tk135/audit-thumbs/7866927120435.jpg | Bin 0 -> 23908 bytes
.../data/tk135/audit-thumbs/7878155206707.jpg | Bin 0 -> 25580 bytes
shopify/scripts/data/tk135/bakeoff-grid.png | Bin 0 -> 866139 bytes
.../data/tk135/bakeoff-thumbs/1495150952560.jpg | Bin 0 -> 78286 bytes
.../data/tk135/bakeoff-thumbs/1497253183600.jpg | Bin 0 -> 6065 bytes
.../data/tk135/bakeoff-thumbs/6829062881331.jpg | Bin 0 -> 7465 bytes
.../data/tk135/bakeoff-thumbs/7584977715251.jpg | Bin 0 -> 5155 bytes
.../data/tk135/bakeoff-thumbs/7855831384115.jpg | Bin 0 -> 9429 bytes
.../data/tk135/bakeoff-thumbs/7855840002099.jpg | Bin 0 -> 7753 bytes
.../data/tk135/bakeoff-thumbs/7882757308467.jpg | Bin 0 -> 5100 bytes
.../data/tk135/bakeoff-thumbs/7882828120115.jpg | Bin 0 -> 15627 bytes
.../data/tk135/bakeoff-thumbs/7896279056435.jpg | Bin 0 -> 17003 bytes
.../data/tk135/bakeoff-thumbs/7896475795507.jpg | Bin 0 -> 15128 bytes
.../data/tk135/material-sample200-unmatched.tsv | 105 ++++++++
shopify/scripts/data/tk135/material-sample200.tsv | 95 +++++++
shopify/scripts/data/tk135/vision-bakeoff-10.tsv | 10 +
shopify/scripts/data/tk17/batchA-full-run.json | 24 ++
.../scripts/tk135-material-classifier-dryrun.js | 294 +++++++++++++++++++++
23 files changed, 528 insertions(+)
diff --git a/shopify/scripts/data/tk135/audit-grid.png b/shopify/scripts/data/tk135/audit-grid.png
new file mode 100644
index 00000000..8d0bc1f2
Binary files /dev/null and b/shopify/scripts/data/tk135/audit-grid.png differ
diff --git a/shopify/scripts/data/tk135/audit-thumbs/1495138402416.jpg b/shopify/scripts/data/tk135/audit-thumbs/1495138402416.jpg
new file mode 100644
index 00000000..600eaddc
Binary files /dev/null and b/shopify/scripts/data/tk135/audit-thumbs/1495138402416.jpg differ
diff --git a/shopify/scripts/data/tk135/audit-thumbs/4509315170355.jpg b/shopify/scripts/data/tk135/audit-thumbs/4509315170355.jpg
new file mode 100644
index 00000000..6ad28236
Binary files /dev/null and b/shopify/scripts/data/tk135/audit-thumbs/4509315170355.jpg differ
diff --git a/shopify/scripts/data/tk135/audit-thumbs/7375645245491.jpg b/shopify/scripts/data/tk135/audit-thumbs/7375645245491.jpg
new file mode 100644
index 00000000..019d8396
Binary files /dev/null and b/shopify/scripts/data/tk135/audit-thumbs/7375645245491.jpg differ
diff --git a/shopify/scripts/data/tk135/audit-thumbs/7422637310003.jpg b/shopify/scripts/data/tk135/audit-thumbs/7422637310003.jpg
new file mode 100644
index 00000000..02f13ac3
Binary files /dev/null and b/shopify/scripts/data/tk135/audit-thumbs/7422637310003.jpg differ
diff --git a/shopify/scripts/data/tk135/audit-thumbs/7866927120435.jpg b/shopify/scripts/data/tk135/audit-thumbs/7866927120435.jpg
new file mode 100644
index 00000000..f9534538
Binary files /dev/null and b/shopify/scripts/data/tk135/audit-thumbs/7866927120435.jpg differ
diff --git a/shopify/scripts/data/tk135/audit-thumbs/7878155206707.jpg b/shopify/scripts/data/tk135/audit-thumbs/7878155206707.jpg
new file mode 100644
index 00000000..4e83d896
Binary files /dev/null and b/shopify/scripts/data/tk135/audit-thumbs/7878155206707.jpg differ
diff --git a/shopify/scripts/data/tk135/bakeoff-grid.png b/shopify/scripts/data/tk135/bakeoff-grid.png
new file mode 100644
index 00000000..30312807
Binary files /dev/null and b/shopify/scripts/data/tk135/bakeoff-grid.png differ
diff --git a/shopify/scripts/data/tk135/bakeoff-thumbs/1495150952560.jpg b/shopify/scripts/data/tk135/bakeoff-thumbs/1495150952560.jpg
new file mode 100644
index 00000000..66a7a45c
Binary files /dev/null and b/shopify/scripts/data/tk135/bakeoff-thumbs/1495150952560.jpg differ
diff --git a/shopify/scripts/data/tk135/bakeoff-thumbs/1497253183600.jpg b/shopify/scripts/data/tk135/bakeoff-thumbs/1497253183600.jpg
new file mode 100644
index 00000000..348b461e
Binary files /dev/null and b/shopify/scripts/data/tk135/bakeoff-thumbs/1497253183600.jpg differ
diff --git a/shopify/scripts/data/tk135/bakeoff-thumbs/6829062881331.jpg b/shopify/scripts/data/tk135/bakeoff-thumbs/6829062881331.jpg
new file mode 100644
index 00000000..372713ae
Binary files /dev/null and b/shopify/scripts/data/tk135/bakeoff-thumbs/6829062881331.jpg differ
diff --git a/shopify/scripts/data/tk135/bakeoff-thumbs/7584977715251.jpg b/shopify/scripts/data/tk135/bakeoff-thumbs/7584977715251.jpg
new file mode 100644
index 00000000..a64d1c75
Binary files /dev/null and b/shopify/scripts/data/tk135/bakeoff-thumbs/7584977715251.jpg differ
diff --git a/shopify/scripts/data/tk135/bakeoff-thumbs/7855831384115.jpg b/shopify/scripts/data/tk135/bakeoff-thumbs/7855831384115.jpg
new file mode 100644
index 00000000..641d00db
Binary files /dev/null and b/shopify/scripts/data/tk135/bakeoff-thumbs/7855831384115.jpg differ
diff --git a/shopify/scripts/data/tk135/bakeoff-thumbs/7855840002099.jpg b/shopify/scripts/data/tk135/bakeoff-thumbs/7855840002099.jpg
new file mode 100644
index 00000000..a3827dfe
Binary files /dev/null and b/shopify/scripts/data/tk135/bakeoff-thumbs/7855840002099.jpg differ
diff --git a/shopify/scripts/data/tk135/bakeoff-thumbs/7882757308467.jpg b/shopify/scripts/data/tk135/bakeoff-thumbs/7882757308467.jpg
new file mode 100644
index 00000000..4c676fde
Binary files /dev/null and b/shopify/scripts/data/tk135/bakeoff-thumbs/7882757308467.jpg differ
diff --git a/shopify/scripts/data/tk135/bakeoff-thumbs/7882828120115.jpg b/shopify/scripts/data/tk135/bakeoff-thumbs/7882828120115.jpg
new file mode 100644
index 00000000..c32ecacf
Binary files /dev/null and b/shopify/scripts/data/tk135/bakeoff-thumbs/7882828120115.jpg differ
diff --git a/shopify/scripts/data/tk135/bakeoff-thumbs/7896279056435.jpg b/shopify/scripts/data/tk135/bakeoff-thumbs/7896279056435.jpg
new file mode 100644
index 00000000..c4fbd169
Binary files /dev/null and b/shopify/scripts/data/tk135/bakeoff-thumbs/7896279056435.jpg differ
diff --git a/shopify/scripts/data/tk135/bakeoff-thumbs/7896475795507.jpg b/shopify/scripts/data/tk135/bakeoff-thumbs/7896475795507.jpg
new file mode 100644
index 00000000..d94a4518
Binary files /dev/null and b/shopify/scripts/data/tk135/bakeoff-thumbs/7896475795507.jpg differ
diff --git a/shopify/scripts/data/tk135/material-sample200-unmatched.tsv b/shopify/scripts/data/tk135/material-sample200-unmatched.tsv
new file mode 100644
index 00000000..23b7698a
--- /dev/null
+++ b/shopify/scripts/data/tk135/material-sample200-unmatched.tsv
@@ -0,0 +1,105 @@
+gid://shopify/Product/7416208261171 Clarke And Clarke Latour - Taupe By Clarke And Clarke | Clarke & Clarke Latour | Multipurpose Weave
+gid://shopify/Product/7874381742131 Suncloth Multi Blues Classic | Suncloth
+gid://shopify/Product/7810558853171 Los Angeles Fabrics Trellis - Artisan | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/6606477918259 Designer Wallcoverings Helen's Houndstooth Check White Table Runner on Lilly
+gid://shopify/Product/7416831246387 Clarke And Clarke Miami - Cream Ivory By Clarke And Clarke | Clarke & Clarke Miami | Solid Drapery Velvet
+gid://shopify/Product/7882832576563 Phillipe Romano Islamorada-Pewter Wallcovering | Phillipe Romano
+gid://shopify/Product/7810579562547 Los Angeles Fabrics Soaring - Filigree | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/7878419054643 Pierre Frey Brissac Celadon | Pierre Frey
+gid://shopify/Product/7876562059315 Thibaut Night Garden, Spa Blue Wallcoverings | Thibaut
+gid://shopify/Product/7880946155571 Elitis Madagascar À Peine Éclose ! | Elitis
+gid://shopify/Product/1498301923440 Phillipe Romano Italiano Textile | Phillipe Romano
+gid://shopify/Product/1499205337200 Phillipe Romano Uxbridge Specialty Wallcovering
+gid://shopify/Product/7422312546355 Brunschwig & Fils Coeur Bullion-L - Ecru White By Brunschwig & Fils | Le Coeur Passementerie | Trim Bullion
+gid://shopify/Product/7422317887539 Brunschwig & Fils Coeur Tassel - Coral Orange By Brunschwig & Fils | Le Coeur Passementerie | Trim Tassel / Tieback
+gid://shopify/Product/7867618033715 Thibaut Balin Ikat, Beige Wallcoverings | Thibaut
+gid://shopify/Product/7422933303347 Lee Jofa Dame - Straw/Ebony Beige By Lee Jofa Modern | Kelly Wearstler Leather Collection |Animal Skins Upholstery Leather/Suede
+gid://shopify/Product/7810456223795 Los Angeles Fabrics Dolphin - Gardenia | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/7421915529267 GP & J Baker Baker House Fr Velvet - Indigo Blue By G P & J Baker | Baker House Fr Velvet |Solid Upholstery Velvet
+gid://shopify/Product/7882770153523 Hollywood Wallcoverings Beam 250 Timber 9H x 108L Harvest Tan | Hollywood Wallcoverings
+gid://shopify/Product/7416228347955 Clarke And Clarke Bw1023 - Black/White By Clarke And Clarke | Clarke & Clarke Black + White | Multipurpose Weave
+gid://shopify/Product/7416185520179 Clarke And Clarke Casanova - Antique By Clarke And Clarke | Clarke & Clarke Casanova |Solid Texture Multipurpose Chenille
+gid://shopify/Product/7810450325555 Los Angeles Fabrics Flamingo - Horseradish | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/1495149903984 PR Faux Leather Glaze�� - Faux Vintage Leather - Bordeaux
+gid://shopify/Product/7416219500595 Clarke And Clarke Highlander - Moss By Clarke And Clarke | Clarke & Clarke Highlander 2 |Solid Texture Multipurpose
+gid://shopify/Product/7864389632051 Los Angeles Fabrics Infatuation - Tinsel | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/7416163008563 Clarke And Clarke Linoso - Pesto By Clarke And Clarke | Clarke & Clarke Linoso Ii |Solid Texture Multipurpose
+gid://shopify/Product/7416315871283 Clarke And Clarke Martello - Charcoal By Clarke And Clarke | Clarke & Clarke Martello | Multipurpose Velvet
+gid://shopify/Product/1495121363056 PR Faux Leather Milano�� Classic Faux Leather - Brandy
+gid://shopify/Product/7810568028211 Los Angeles Fabrics Nectar - Macaw | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/4693301067827 Nina Campbell Nina Campbell Fabric - Chartreuse Green Wallcovering | Nina Campbell
+gid://shopify/Product/4693305524275 Nina Campbell Nina Campbell Fabric - Oatmeal Wallcovering | Nina Campbell
+gid://shopify/Product/4693303328819 Nina Campbell Nina Campbell Fabric - Teal Blue Wallcovering | Nina Campbell
+gid://shopify/Product/7821430325299 Novasuede Novasuede™ Fabric & Wallcovering - Verdigris
+gid://shopify/Product/7416690212915 Clarke And Clarke Puro - Chalk By Clarke And Clarke | Clarke & Clarke Lusso Sheers |Solid Drapery Weave
+gid://shopify/Product/7796281475123 Los Angeles Fabrics Sandbar - Ironwood Faux Leather | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/7810445279283 Los Angeles Fabrics Shorescape - Plateau | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/7876656922675 Suncloth Tashkent, Pale Griege on White | Suncloth
+gid://shopify/Product/7099513143347 Hollywood Acoustical Yettington Acoustical Wallcovering
+gid://shopify/Product/7875514990643 Kravet Kravet Basics, Seafoam Green Wallcoverings | Kravet
+gid://shopify/Product/7866117095475 Thibaut Palampore Leaf, Blue and White Wallcoverings | Thibaut
+gid://shopify/Product/7552688947251 Anna French Woodland Blue Wallcovering
+gid://shopify/Product/1497511362672 Phillipe Romano GlamFab - Pleated Knit Backed Fabric for Walls
+gid://shopify/Product/7880018493491 Hollywood Wallcoverings South Salmon Silhouette | Hollywood Wallcoverings
+gid://shopify/Product/7896373329971 Carnegie Carnegie Xorel Prism
+gid://shopify/Product/7817253322803 AS Creation Michalsky 6 Gray Wallcovering | AS Creation
+gid://shopify/Product/7864807096371 Wolf Gordon Divine Frosted | Wolf Gordon Wallcoverings
+gid://shopify/Product/1502346805360 Phillipe Romano Merana | Phillipe Romano
+gid://shopify/Product/7882827694131 Phillipe Romano Edgartown-Putty Wallcovering | Phillipe Romano
+gid://shopify/Product/7297436713011 PS Removable Wallpaper Malibu Ps Wood Panel Rustic Wood - Alabaster | Peel and Stick Removable Wallcovering
+gid://shopify/Product/1498005569648 Phillipe Romano Alaminos Arrowroot | Phillipe Romano
+gid://shopify/Product/4396410699827 Phillipe Romano Luxuria Beige | Phillipe Romano
+gid://shopify/Product/7896398856243 Coordonné Rolling-Stripes Sage | Coordonné
+gid://shopify/Product/7384904826931 Maya Romanoff Grand Scale Ajiro Coffers - Chestnut | Maya Romanoff
+gid://shopify/Product/7898462978099 CMO Paris Bois Marbré Ecaille Zinc | CMO Paris
+gid://shopify/Product/7877387911219 Kravet On the Horizon, Off-White Wallcoverings | Kravet
+gid://shopify/Product/7866952253491 Thibaut Gibson, Navy Wallcoverings | Thibaut
+gid://shopify/Product/7882842767411 Phillipe Romano Osterville-Harbor Mist Wallcovering | Phillipe Romano
+gid://shopify/Product/7896290459699 Anthology Anthology - Nisiros Bronze / Basalt Wallcovering | Anthology
+gid://shopify/Product/7882831462451 Phillipe Romano Jupiter-Flint Wallcovering | Phillipe Romano
+gid://shopify/Product/1499742109808 Phillipe Romano Boynton Stain Repellent Real Suede | Phillipe Romano
+gid://shopify/Product/7876147511347 Kravet Kravet Basics, Forest Green Wallcoverings | Kravet
+gid://shopify/Product/7865301827635 Thibaut Westmont, Blush Wallcoverings | Thibaut
+gid://shopify/Product/7794234720307 Zoffany Artisan Palampore - Primrose wallcovering | Zoffany
+gid://shopify/Product/1495881711728 Designer Wallcoverings Et Cie The Huntington Wall Mural Panel #6
+gid://shopify/Product/7876473913395 Thibaut Virginia, Cream and Aqua Wallcoverings | Thibaut
+gid://shopify/Product/7880948285491 Elitis Volute Y Faire Son Miel | Elitis
+gid://shopify/Product/6944664682547 Thibaut Indies Ikat Lavender and French Blue - Lavender and French Blue Wallcovering | Thibaut
+gid://shopify/Product/7388488826931 Phillipe Romano La Calabria Mint Natural | Phillipe Romano
+gid://shopify/Product/7793953275955 Zoffany Emperors Musician - Indigo wallcovering | Zoffany
+gid://shopify/Product/7880948678707 Elitis Moshi Moshi Donner Du Sens | Elitis
+gid://shopify/Product/7817251586099 AS Creation Daniel Hechter 7 Dark Purple Wallcovering | AS Creation
+gid://shopify/Product/7878157664307 Pierre Frey Les ombrelles rayure Bleu | Pierre Frey
+gid://shopify/Product/7897178800179 Vahallan Liana Wallcovering | Vahallan
+gid://shopify/Product/7692850462771 Novasuede Novasuede™ - Buff Luxury Suede
+gid://shopify/Product/7817254404147 AS Creation A.s. Creation Design Panel Anna D Andrea Green Wallcovering | AS Creation
+gid://shopify/Product/7692852035635 Novasuede Novasuede™ - Light Amethyst Luxury Suede
+gid://shopify/Product/7817258303539 AS Creation Walls By Patel Beige Wallcovering | AS Creation
+gid://shopify/Product/1499597570160 Phillipe Romano Fulton Stain Repellent Real Textile | Phillipe Romano
+gid://shopify/Product/7880940945459 Elitis Cesteria Les Fibres Du Plaisir | Elitis
+gid://shopify/Product/7810544566323 Los Angeles Fabrics Aloha - Summit | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/7832785813555 Scalamandre Backyard Bengal Outdoor Pillow Lumbar 14X22 Ivy | Scalamandre
+gid://shopify/Product/7801633701939 Thibaut Bree Tape Tapes & Trims – Paprika and Soft Gold Fabric | Thibaut
+gid://shopify/Product/7896369725491 Carnegie Carnegie Pigment
+gid://shopify/Product/7896367464499 Carnegie Carnegie Xorel Strie
+gid://shopify/Product/7810432663603 Los Angeles Fabrics Coralia - Sorghum | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/7422349705267 Gaston Y Daniela Kf Gyd:: - Yellow By Gaston Y Daniela | Gaston Africalia |Solid Texture Upholstery Indoor / Outdoor
+gid://shopify/Product/7416207671347 Clarke And Clarke Latour - Citrus By Clarke And Clarke | Clarke & Clarke Latour | Multipurpose Weave
+gid://shopify/Product/7413740437555 Brunschwig & Fils Loriyan Tape - Multi Multi By Brunschwig & Fils | Treillis Passementerie | Trim Braid / Tape
+gid://shopify/Product/7810573697075 Los Angeles Fabrics Seafarer - Waterfront | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/7810545483827 Los Angeles Fabrics Steward - Rainbow | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/7810559115315 Los Angeles Fabrics Trellis - Poinsettia | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/4466673811507 Innovations USA Zion | Innovations USA
+gid://shopify/Product/7832779587635 Scalamandre Backyard Bengal Outdoor Pillow Square 22X22 Ivy | Scalamandre
+gid://shopify/Product/7422134059059 Lee Jofa Avignon Tape - Grey White By Lee Jofa | Suzanne Kasler Collection Ii | Trim Braid / Tape
+gid://shopify/Product/7799402823731 Atomic 50 Ceilings AT50-04 Unfinished | Atomic 50
+gid://shopify/Product/7832789516339 Scalamandre Corbet Pillow Square 22X22 Blue | Scalamandre
+gid://shopify/Product/7864374263859 Los Angeles Fabrics Hampton - Key Lime | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/7810441248819 Los Angeles Fabrics Iguana - Cay | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/7419648114739 Gaston Y Daniela Kurt - Lino Beige By Gaston Y Daniela | Lorenzo Castillo Vi | Texture Upholstery Indoor / Outdoor
+gid://shopify/Product/7810541912115 Los Angeles Fabrics Liana - Tangerine | Commercial Fabric | Los Angeles Fabrics
+gid://shopify/Product/7416909266995 Clarke And Clarke Majorelle - Outdoor Ivory By Clarke And Clarke | Clarke & Clarke Alfresco |Botanical & Floral Tropical Multipurpose Indoor / Outdoor
+gid://shopify/Product/7874108293171 Plains Mink | Plains
+gid://shopify/Product/7422386503731 Gaston Y Daniela Olmo - Crudo White By Gaston Y Daniela | Gaston Libreria |Solid Texture Upholstery
+gid://shopify/Product/7832786239539 Scalamandre Pomfret Pillow Square 22X22 Lapis | Scalamandre
+gid://shopify/Product/4466669846579 Innovations USA Spalt | Innovations USA
diff --git a/shopify/scripts/data/tk135/material-sample200.tsv b/shopify/scripts/data/tk135/material-sample200.tsv
new file mode 100644
index 00000000..fbbc4e03
--- /dev/null
+++ b/shopify/scripts/data/tk135/material-sample200.tsv
@@ -0,0 +1,95 @@
+gid://shopify/Product/7899330707507 Sisal
+gid://shopify/Product/7822756511795 Silk
+gid://shopify/Product/7896254119987 Silk
+gid://shopify/Product/7896255496243 Vinyl
+gid://shopify/Product/7865241239603 Vinyl
+gid://shopify/Product/7896256970803 Vinyl
+gid://shopify/Product/7865526976563 Vinyl
+gid://shopify/Product/7896220762163 Paper
+gid://shopify/Product/7896225185843 Silk
+gid://shopify/Product/7878818988083 Wool
+gid://shopify/Product/7832788926515 Linen
+gid://shopify/Product/7878808240179 Wool
+gid://shopify/Product/7897507299379 Vinyl
+gid://shopify/Product/7421293789235 Cotton
+gid://shopify/Product/6948078157875 Cotton
+gid://shopify/Product/7416184537139 Cotton
+gid://shopify/Product/7416245289011 Cotton
+gid://shopify/Product/7416881217587 Silk
+gid://shopify/Product/7419530805299 Wool
+gid://shopify/Product/7422104469555 Cotton
+gid://shopify/Product/7864792743987 Mylar
+gid://shopify/Product/7297457520691 Vinyl
+gid://shopify/Product/7896995594291 Wool
+gid://shopify/Product/7297527218227 Vinyl
+gid://shopify/Product/7297400504371 Vinyl
+gid://shopify/Product/7297531740211 Vinyl
+gid://shopify/Product/7896462557235 Wool
+gid://shopify/Product/7896451612723 Wool
+gid://shopify/Product/7896461344819 Wool
+gid://shopify/Product/7896372314163 Wool
+gid://shopify/Product/7422417567795 Wool
+gid://shopify/Product/7898836762675 Silk
+gid://shopify/Product/4396398936115 Silk
+gid://shopify/Product/4396416925747 Silk
+gid://shopify/Product/6948076847155 Grasscloth
+gid://shopify/Product/7882836279347 Vinyl
+gid://shopify/Product/7882822385715 Non-woven
+gid://shopify/Product/7297460568115 Paper-weave
+gid://shopify/Product/7297412759603 Paper-weave
+gid://shopify/Product/7297376911411 Paper-weave
+gid://shopify/Product/7297533575219 Paper-weave
+gid://shopify/Product/6941805346867 Wool
+gid://shopify/Product/7421296410675 Silk
+gid://shopify/Product/7882825662515 Grasscloth
+gid://shopify/Product/7896295637043 Vinyl
+gid://shopify/Product/7876903043123 Vinyl
+gid://shopify/Product/7865526747187 Paper-weave
+gid://shopify/Product/7896263458867 Non-woven
+gid://shopify/Product/7692851052595 Vinyl
+gid://shopify/Product/4348479078451 Non-woven
+gid://shopify/Product/7896288493619 Silk
+gid://shopify/Product/7814464831539 Cork
+gid://shopify/Product/7864373280819 Vinyl
+gid://shopify/Product/1501217030256 Vinyl
+gid://shopify/Product/7882811310131 Grasscloth
+gid://shopify/Product/7887507390515 Linen
+gid://shopify/Product/7876465164339 Vinyl
+gid://shopify/Product/7870482776115 Vinyl
+gid://shopify/Product/7882810851379 Paper-weave
+gid://shopify/Product/7876774920243 Vinyl
+gid://shopify/Product/7817263415347 Non-woven
+gid://shopify/Product/7876147576883 Vinyl
+gid://shopify/Product/7870604345395 Vinyl
+gid://shopify/Product/7877196021811 Vinyl
+gid://shopify/Product/7870021107763 Vinyl
+gid://shopify/Product/1497504776304 Paper-weave
+gid://shopify/Product/7882812162099 Paper-weave
+gid://shopify/Product/7421293461555 Silk
+gid://shopify/Product/7870218895411 Wool
+gid://shopify/Product/7419637661747 Silk
+gid://shopify/Product/7416866275379 Silk
+gid://shopify/Product/7417272369203 Silk
+gid://shopify/Product/7885998293043 Paper
+gid://shopify/Product/7880944975923 Silk
+gid://shopify/Product/6948084482099 Vinyl
+gid://shopify/Product/7794228133939 Vinyl
+gid://shopify/Product/7876062838835 Vinyl
+gid://shopify/Product/7793954488371 Vinyl
+gid://shopify/Product/7864796119091 Vinyl
+gid://shopify/Product/7880940388403 Silk
+gid://shopify/Product/7873963458611 Vinyl
+gid://shopify/Product/7880947466291 Silk
+gid://shopify/Product/7817262956595 Vinyl
+gid://shopify/Product/1495880990832 Vinyl
+gid://shopify/Product/7878391529523 Cotton
+gid://shopify/Product/7413738602547 Cotton
+gid://shopify/Product/7832781193267 Wool
+gid://shopify/Product/7416185421875 Silk
+gid://shopify/Product/7422348099635 Wool
+gid://shopify/Product/7413668413491 Linen
+gid://shopify/Product/7413642133555 Cotton
+gid://shopify/Product/7422865571891 Wool
+gid://shopify/Product/7878412304435 Silk
+gid://shopify/Product/7878384910387 Silk
+gid://shopify/Product/7885749846067 Vinyl
diff --git a/shopify/scripts/data/tk135/vision-bakeoff-10.tsv b/shopify/scripts/data/tk135/vision-bakeoff-10.tsv
new file mode 100644
index 00000000..e8d6171f
--- /dev/null
+++ b/shopify/scripts/data/tk135/vision-bakeoff-10.tsv
@@ -0,0 +1,10 @@
+gid://shopify/Product/7896279056435 https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GWP-3727.355.0.jpg?v=1784734742 UNMATCHED:Roulade Paper Navy/Teal | Groundworks
+gid://shopify/Product/6829062881331 https://cdn.shopify.com/s/files/1/0015/4117/7456/files/prw-920571-mks-012.jpg?v=1781716164 UNMATCHED:Roseland Heights Type 2 | Phillipe Romano
+gid://shopify/Product/7882757308467 https://cdn.shopify.com/s/files/1/0015/4117/7456/files/0148968_crossroad-wallpaper-whitewash_abfafda2-c68d-4cfe-922e-c7a2956b99f2.jpg?v=1783866063 UNMATCHED:Crossroad Whitewash | Jeffrey Stevens
+gid://shopify/Product/7882828120115 https://cdn.shopify.com/s/files/1/0015/4117/7456/files/3b0d60193d283c498b57bec9778fd493.jpg?v=1783880854 UNMATCHED:Vineyard Haven-Oak Buff Wallcovering | Phillipe Romano
+gid://shopify/Product/7584977715251 https://cdn.shopify.com/s/files/1/0015/4117/7456/files/MARMORINO_TERRA_7321-12_new_f812593d-a513-495a-a72e-10915d4ead1c.jpg?v=1751949555 UNMATCHED:Marmorino Terra - Burnt Sienna Commercial Wallcovering | Kor
+gid://shopify/Product/7855831384115 https://cdn.shopify.com/s/files/1/0015/4117/7456/files/R19712_interior1.jpg?v=1781029646 UNMATCHED:Colorful Sunset - Golden Orange | Rebel Walls
+gid://shopify/Product/1495150952560 https://cdn.shopify.com/s/files/1/0015/4117/7456/products/3953d719bb51792fda1ddd6b0f90e2a6.png?v=1572308967 UNMATCHED:Glaze�� - Faux Vintage Leather - Walnut
+gid://shopify/Product/1497253183600 https://cdn.shopify.com/s/files/1/0015/4117/7456/products/2f256cebc7289705a473d9153b37eeef.jpg?v=1572309624 UNMATCHED:Palerma with Surface Stick - Faux Wood Grain Self Adhesive
+gid://shopify/Product/7855840002099 https://cdn.shopify.com/s/files/1/0015/4117/7456/files/R19047_interior1.jpg?v=1781030117 UNMATCHED:Downhill - Cool Gray | Rebel Walls
+gid://shopify/Product/7896475795507 https://cdn.shopify.com/s/files/1/0015/4117/7456/files/BBSU04.jpg?v=1784741564 UNMATCHED:London Big Sur Coast Road Wallcovering | Phillipe Romano
diff --git a/shopify/scripts/data/tk17/batchA-full-run.json b/shopify/scripts/data/tk17/batchA-full-run.json
new file mode 100644
index 00000000..aba4a200
--- /dev/null
+++ b/shopify/scripts/data/tk17/batchA-full-run.json
@@ -0,0 +1,24 @@
+{
+ "ticket": "TK-17",
+ "batch": "A",
+ "started": "2026-07-28T00:52:37.239Z",
+ "apply": true,
+ "worklist": "/Users/macstudio3/Projects/consulting-designerwallcoverings-com/data/work-orders/execution/batchA-quotes-tag-worklist.tsv",
+ "tag": "quotes",
+ "tagged": 9684,
+ "errors": [],
+ "byVendor": {
+ "Alan Campbell": 434,
+ "Architectural Fabrics": 328,
+ "China Seas": 1776,
+ "Donghia": 154,
+ "Home Couture": 229,
+ "Koroseal": 2454,
+ "Maya Romanoff": 624,
+ "Newmor Wallcoverings": 512,
+ "Phillip Jeffries": 2461,
+ "Quadrille": 443,
+ "Wolf Gordon": 269
+ },
+ "finished": "2026-07-28T03:11:17.502Z"
+}
\ No newline at end of file
diff --git a/shopify/scripts/tk135-material-classifier-dryrun.js b/shopify/scripts/tk135-material-classifier-dryrun.js
new file mode 100644
index 00000000..a5d75504
--- /dev/null
+++ b/shopify/scripts/tk135-material-classifier-dryrun.js
@@ -0,0 +1,294 @@
+#!/usr/bin/env node
+/**
+ * TK-00135 — MATERIAL descriptor backfill DRY-RUN (free/local, NO WRITES, NO paid API).
+ *
+ * HARD CONSTRAINTS (Steve):
+ * - local models only -> $0 (local)
+ * - NO LIVE WRITES to Shopify / PostgreSQL — this only emits a proposed TSV,
+ * gated for Steve.
+ * - Output tags are BARE VALUES, NO label prefix: "Linen", "Grasscloth",
+ * "Vinyl" — NEVER "material:Linen".
+ *
+ * Classifies every ACTIVE product that is MISSING a material tag into one of the
+ * 15 buckets, resolving by SOURCE PRIORITY (deterministic first, qwen2.5 only
+ * for the ambiguous remainder):
+ * 1. specs / specifications metafield (specs.material / .composition / .content
+ * / specifications.material_type)
+ * 2. existing composition tag ("Cotton - 90%;Linen - 10%" etc.)
+ * 3. TITLE keywords
+ * 4. vendor conventions (vendors that are ~all one material)
+ * 5. qwen2.5:latest (ambiguous remainder, local, $0)
+ *
+ * Buckets (BARE output values):
+ * Cotton Linen Vinyl Grasscloth Silk Paper Paper-weave Mylar Cork Wool
+ * Jute Sisal Mica Metallic Non-woven
+ *
+ * Inputs (produced by the SQL pulls documented in the ticket log):
+ * --active TSV: gid \t title \t vendor \t product_type \t specs_material
+ * \t specs_composition \t specs_content \t spec_material_type
+ * --tags TSV: gid \t comma-joined-tags (to find composition tags + the
+ * set already-having-material, which we SKIP)
+ * --vendorconv JSON: { "<vendor>": "<BareMaterial>" } (data-derived conventions)
+ *
+ * Usage:
+ * node tk135-material-classifier-dryrun.js # full dry-run
+ * node tk135-material-classifier-dryrun.js --sample 200 # 200-product validation
+ * node tk135-material-classifier-dryrun.js --no-llm # deterministic only
+ * node tk135-material-classifier-dryrun.js --llm-batch 15 # qwen batch size
+ *
+ * NOTHING here writes to Shopify or Postgres. Output is a proposal TSV only.
+ */
+const fs = require('fs');
+const path = require('path');
+const { execSync } = require('child_process');
+
+const args = process.argv.slice(2);
+const arg = (k, d) => { const i = args.indexOf(k); return i >= 0 ? args[i + 1] : d; };
+const has = (k) => args.includes(k);
+
+const ACTIVE = arg('--active', '/tmp/tk135-active-full.tsv');
+const TAGS = arg('--tags', '/tmp/tk135-mat-active-tags.tsv');
+const VCONV = arg('--vendorconv', '/tmp/tk135-vendor-conv.json');
+const OUT = arg('--out', path.join(__dirname, 'data/tk135/material-proposed.tsv'));
+const SAMPLE = parseInt(arg('--sample', '0'), 10); // 0 = full run
+const NO_LLM = has('--no-llm');
+const LLM_BATCH = parseInt(arg('--llm-batch', '15'), 10);
+const LLM_MODEL = arg('--llm-model', 'qwen2.5:latest');
+
+// ---- the 15 buckets, ordered most-specific -> most-generic ----------------
+// Each bucket: BARE output value + keyword list. Order matters: "Paper-weave"
+// must be tested before "Paper"; "Grasscloth"/"Non-woven" before fibre words.
+const BUCKETS = [
+ ['Paper-weave', ['paper weave', 'paper-weave', 'paperweave']],
+ ['Grasscloth', ['grasscloth', 'grass cloth', 'grass and natural', 'grass - 100', 'hemp grasscloth']],
+ ['Non-woven', ['non-woven', 'non woven', 'nonwoven']],
+ ['Vinyl', ['vinyl', 'pvc', 'poly vinyl chloride', 'polyvinyl chloride']],
+ ['Cotton', ['cotton']],
+ ['Linen', ['linen']],
+ ['Silk', ['silk']],
+ ['Wool', ['wool', 'mohair']],
+ ['Jute', ['jute']],
+ ['Sisal', ['sisal']],
+ ['Mica', ['mica']],
+ ['Cork', ['cork']],
+ ['Mylar', ['mylar']],
+ ['Metallic', ['metallic']],
+ ['Paper', ['paper']],
+];
+const VALID = new Set(BUCKETS.map((b) => b[0]));
+
+// keyword -> bucket for the LLM output normalizer
+const KW2BUCKET = {};
+for (const [val, kws] of BUCKETS) for (const kw of kws) KW2BUCKET[kw] = val;
+
+// Whole-tag / composition-tag classifier (strong): tag == kw or "kw - N%..."
+function fromTagList(tagsLower, strongOnly) {
+ const joined = ' , ' + tagsLower.join(' , ') + ' , ';
+ for (const [val, kws] of BUCKETS) {
+ for (const kw of kws) {
+ for (const t of tagsLower) {
+ if (t === kw || t.startsWith(kw + ' - ') || t.startsWith(kw + ' on ')) return val;
+ }
+ }
+ }
+ if (strongOnly) return null;
+ for (const [val, kws] of BUCKETS) {
+ for (const kw of kws) if (joined.includes(' ' + kw) || joined.includes(kw)) return val;
+ }
+ return null;
+}
+
+// Free-text classifier for a metafield string ("Silk - 85%, Polyester - 15%",
+// "Type II 20oz Vinyl", "Paulownia Veneer", ...). Uses the FIRST/dominant
+// component so a Silk-dominant blend classifies Silk, not the polyester filler.
+function fromText(text) {
+ if (!text) return null;
+ const s = String(text).toLowerCase();
+ // dominant component = first listed (compositions list primary fibre first)
+ for (const [val, kws] of BUCKETS) {
+ for (const kw of kws) {
+ const i = s.indexOf(kw);
+ if (i >= 0) return val;
+ }
+ }
+ return null;
+}
+
+// Title-keyword classifier: word-boundary so "paperweave" motifs don't
+// false-hit; require the keyword to appear as a real token.
+function fromTitle(title) {
+ if (!title) return null;
+ const s = title.toLowerCase();
+ for (const [val, kws] of BUCKETS) {
+ for (const kw of kws) {
+ const re = new RegExp('(^|[^a-z])' + kw.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '($|[^a-z])', 'i');
+ if (re.test(s)) return val;
+ }
+ }
+ return null;
+}
+
+// ---- load inputs ----------------------------------------------------------
+const tagsByGid = new Map(); // gid -> lowercased tag array
+const hasMaterialGid = new Set(); // gids that already carry a material (SKIP)
+for (const line of fs.readFileSync(TAGS, 'utf8').split('\n')) {
+ if (!line) continue;
+ const i = line.indexOf('\t');
+ if (i < 0) continue;
+ const gid = line.slice(0, i);
+ const tagsLower = line.slice(i + 1).split(',').map((t) => t.trim().toLowerCase());
+ tagsByGid.set(gid, tagsLower);
+ if (fromTagList(tagsLower, false)) hasMaterialGid.add(gid);
+}
+
+let vendorConv = {};
+try { vendorConv = JSON.parse(fs.readFileSync(VCONV, 'utf8')); } catch { vendorConv = {}; }
+// normalize vendor keys to lower for match
+const vendorConvLC = {};
+for (const [k, v] of Object.entries(vendorConv)) vendorConvLC[k.toLowerCase()] = v;
+
+// active rows
+const active = [];
+for (const line of fs.readFileSync(ACTIVE, 'utf8').split('\n')) {
+ if (!line) continue;
+ const p = line.split('\t');
+ active.push({
+ gid: p[0], title: p[1] || '', vendor: p[2] || '', ptype: p[3] || '',
+ m_material: p[4] || '', m_comp: p[5] || '', m_content: p[6] || '', m_mtype: p[7] || '',
+ });
+}
+
+// ---- the missing set (active AND not already having material) -------------
+let missing = active.filter((r) => tagsByGid.has(r.gid) && !hasMaterialGid.has(r.gid));
+if (SAMPLE > 0) {
+ // deterministic sample: every Nth so it spans vendors, capped at SAMPLE
+ const step = Math.max(1, Math.floor(missing.length / SAMPLE));
+ missing = missing.filter((_, i) => i % step === 0).slice(0, SAMPLE);
+}
+
+// ---- deterministic pass ---------------------------------------------------
+const proposed = []; // { gid, material, source, title, vendor }
+const forLLM = [];
+const srcCount = {};
+function record(r, material, source) {
+ proposed.push({ gid: r.gid, material, source, title: r.title, vendor: r.vendor });
+ srcCount[source] = (srcCount[source] || 0) + 1;
+}
+for (const r of missing) {
+ // 1. specs / specifications metafield
+ let v = fromText(r.m_material) || fromText(r.m_comp) || fromText(r.m_content) || fromText(r.m_mtype);
+ if (v) { record(r, v, 'specs-metafield'); continue; }
+ // 2. existing composition tag (strong whole-tag / "X - N%")
+ v = fromTagList(tagsByGid.get(r.gid) || [], true);
+ if (v) { record(r, v, 'composition-tag'); continue; }
+ // 3. TITLE keywords
+ v = fromTitle(r.title);
+ if (v) { record(r, v, 'title-keyword'); continue; }
+ // 4. vendor convention
+ v = vendorConvLC[r.vendor.toLowerCase()];
+ if (v && VALID.has(v)) { record(r, v, 'vendor-convention'); continue; }
+ // 5. remainder -> qwen2.5 (or unmatched if --no-llm)
+ forLLM.push(r);
+}
+
+// ---- type-plausibility guard ----------------------------------------------
+// A textile product cannot be a hard-surface wallcovering material. This rejects
+// qwen's hallucinated "fabric -> Cork/Mylar/Mica/..." picks -> route to unmatched
+// (honest: better unlabeled than wrong).
+const FABRIC_TYPE = /fabric|pillow|drapery|upholst|trim|tassel|cushion|throw|textile|runner|sheer/i;
+// materials that make sense for a textile
+const FABRIC_OK = new Set(['Cotton', 'Linen', 'Silk', 'Wool', 'Jute', 'Sisal', 'Metallic']);
+function plausible(material, ptype, title) {
+ if (FABRIC_TYPE.test(ptype) || (!ptype && FABRIC_TYPE.test(title))) {
+ return FABRIC_OK.has(material);
+ }
+ return true; // wallcovering: any bucket allowed
+}
+
+// ---- qwen2.5 pass (local, $0) for the ambiguous remainder -----------------
+const unmatched = [];
+function askQwen(batch) {
+ const list = batch.map((r, i) =>
+ `${i + 1}. ${r.title.replace(/\s+/g, ' ').slice(0, 110)} | ${r.vendor} | ${r.ptype}`
+ ).join('\n');
+ const prompt =
+`Classify each numbered wallcovering/fabric product into ONE material.
+Choose from EXACTLY: Cotton, Linen, Vinyl, Grasscloth, Silk, Paper, Paper-weave, Mylar, Cork, Wool, Jute, Sisal, Mica, Metallic, Non-woven, Unknown.
+Guidance: velvet/chenille/upholstery fabric with no stated fiber = Cotton; sheer/drapery fabric = Linen; contract/commercial wallcovering = Vinyl; if genuinely unclear = Unknown.
+Output ONE line per item, format exactly: <number>. <Material>
+Do not explain.
+
+${list}`;
+ const tmp = `/tmp/tk135-mat-qwen-${process.pid}.txt`;
+ fs.writeFileSync(tmp, prompt);
+ let out = '';
+ try {
+ out = execSync(`ollama run ${LLM_MODEL} < ${tmp}`, { encoding: 'utf8', timeout: 180000, maxBuffer: 1 << 22 });
+ } catch (e) { out = (e.stdout || '').toString(); }
+ try { fs.unlinkSync(tmp); } catch {}
+ const map = {};
+ for (const m of out.matchAll(/^\s*(\d+)\s*[=:.\)]\s*([A-Za-z][A-Za-z\- ]*)/gm)) {
+ map[+m[1]] = m[2].trim();
+ }
+ return map;
+}
+function normalizeLLM(raw) {
+ if (!raw) return null;
+ const s = raw.trim().toLowerCase();
+ for (const val of VALID) if (s === val.toLowerCase()) return val;
+ // keyword contains
+ for (const kw in KW2BUCKET) if (s.includes(kw)) return KW2BUCKET[kw];
+ return null;
+}
+
+if (!NO_LLM && forLLM.length) {
+ for (let i = 0; i < forLLM.length; i += LLM_BATCH) {
+ const batch = forLLM.slice(i, i + LLM_BATCH);
+ const map = askQwen(batch);
+ batch.forEach((r, j) => {
+ const val = normalizeLLM(map[j + 1]);
+ if (val && plausible(val, r.ptype, r.title)) record(r, val, 'qwen2.5');
+ else unmatched.push(r);
+ });
+ if ((i / LLM_BATCH) % 10 === 0) {
+ process.stderr.write(` qwen ${Math.min(i + LLM_BATCH, forLLM.length)}/${forLLM.length}\r`);
+ }
+ }
+ process.stderr.write('\n');
+} else {
+ for (const r of forLLM) unmatched.push(r);
+}
+
+// ---- write proposal (BARE values) + unmatched -----------------------------
+fs.mkdirSync(path.dirname(OUT), { recursive: true });
+fs.writeFileSync(OUT, proposed.map((p) => `${p.gid}\t${p.material}`).join('\n') + (proposed.length ? '\n' : ''));
+const UNM = OUT.replace(/\.tsv$/, '-unmatched.tsv');
+fs.writeFileSync(UNM, unmatched.map((u) => `${u.gid}\t${u.vendor}\t${u.title.replace(/\t/g, ' ')}`).join('\n') + (unmatched.length ? '\n' : ''));
+
+// ---- report ---------------------------------------------------------------
+const dist = {};
+for (const p of proposed) dist[p.material] = (dist[p.material] || 0) + 1;
+const N = missing.length;
+console.log(`TK-135 MATERIAL DRY-RUN — NO WRITES · cost: $0 (local)`);
+console.log(` mode: ${SAMPLE > 0 ? `SAMPLE (${SAMPLE})` : 'FULL'}${NO_LLM ? ' [--no-llm]' : ''}`);
+console.log(` active total (in tags file): ${tagsByGid.size}`);
+console.log(` already have material (skipped): ${hasMaterialGid.size}`);
+console.log(` MISSING material (input): ${N}`);
+console.log(` classified: ${proposed.length} (${(100 * proposed.length / N).toFixed(1)}%) unmatched: ${unmatched.length} (${(100 * unmatched.length / N).toFixed(1)}%)`);
+console.log(`\n === source breakdown ===`);
+for (const [k, v] of Object.entries(srcCount).sort((a, b) => b[1] - a[1])) {
+ console.log(` ${String(v).padStart(6)} (${(100 * v / N).toFixed(1)}%) ${k}`);
+}
+console.log(`\n === material distribution (BARE values) ===`);
+for (const [k, v] of Object.entries(dist).sort((a, b) => b[1] - a[1])) {
+ console.log(` ${String(v).padStart(6)} ${k}`);
+}
+console.log(`\n === 10 sample classifications (gid · source · title -> BARE) ===`);
+proposed.slice(0, 10).forEach((p) => {
+ console.log(` [${p.source.padEnd(16)}] ${p.title.slice(0, 44).padEnd(44)} -> ${p.material}`);
+});
+console.log(`\n === 8 sample UNMATCHED ===`);
+unmatched.slice(0, 8).forEach((u) => console.log(` ${u.vendor.slice(0, 18).padEnd(18)} | ${u.title.slice(0, 46)}`));
+console.log(`\n proposed TSV -> ${OUT} (${proposed.length} rows, format: <gid>\\t<BareMaterialValue>)`);
+console.log(` unmatched TSV -> ${UNM} (${unmatched.length} rows)`);
+console.log(`\n NO Shopify / PostgreSQL writes performed. Proposal is gated for Steve.`);
← 16012764 TK-135: stamp custom.color_normalized_at per SKU (durable de
·
back to Designer Wallcoverings
·
TK-135: material classifier — 24,581 bare primary-material t fcb3debd →