[object Object]

← back to Sanderson Onboard

TK-10873 cycle6: batch-1 US-retail harvest for 14 of the 51 held rows (8 firm PROPOSE, e.g. Ajanta $342/French Marble $382 — confirms zc was GBP-as-USD low; 3 per-metre POR held; 1 unit-review; 1 low-conf). DATA FLAG: Desert Flower II ZAQF322696 is a FABRIC (per-yard $133), misclassified as wallpaper -> RECLASSIFY. Proposals only, nothing promoted. +7 tests

a72761f3576aaebdb6a33a05994fbdc8ef7de141 · 2026-08-30 22:20:37 -0700 · Steve Abrams

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit a72761f3576aaebdb6a33a05994fbdc8ef7de141
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sun Aug 30 22:20:37 2026 -0700

    TK-10873 cycle6: batch-1 US-retail harvest for 14 of the 51 held rows (8 firm PROPOSE, e.g. Ajanta $342/French Marble $382 — confirms zc was GBP-as-USD low; 3 per-metre POR held; 1 unit-review; 1 low-conf). DATA FLAG: Desert Flower II ZAQF322696 is a FABRIC (per-yard $133), misclassified as wallpaper -> RECLASSIFY. Proposals only, nothing promoted. +7 tests
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 tk10873/build_harvest_proposals.mjs |  69 +++++++++++
 tk10873/harvest_batch1.json         |  22 ++++
 tk10873/held_price_proposals.json   | 239 ++++++++++++++++++++++++++++++++++++
 tk10873/held_price_proposals.md     |  24 ++++
 tk10873/test_proposals.mjs          |  16 +++
 5 files changed, 370 insertions(+)

diff --git a/tk10873/build_harvest_proposals.mjs b/tk10873/build_harvest_proposals.mjs
new file mode 100644
index 0000000..69474b5
--- /dev/null
+++ b/tk10873/build_harvest_proposals.mjs
@@ -0,0 +1,69 @@
+#!/usr/bin/env node
+// build_harvest_proposals.mjs — TK-10873 cycle 6+. Merge the harvest_batch*.json US-retail
+// findings into a single proposals artifact for the HELD_UNVERIFIED rows. PROPOSALS ONLY —
+// nothing is promoted to REPRICE here (per the cycle-5 Cody lesson: web-confirm per SKU;
+// promotion to reprice-eligible is a later gated step once a batch is confirmed + reviewed).
+//
+// READ-ONLY. NO Shopify/dw_unified writes. Reads harvest_batch*.json + v3, writes local files.
+import fs from 'node:fs';
+
+const DIR = new URL('.', import.meta.url).pathname;
+const V3_IN = `${DIR}zoffany_optionA_draft_v3.json`;
+const OUT = `${DIR}held_price_proposals.json`;
+const MD_OUT = `${DIR}held_price_proposals.md`;
+const SAMPLE = 4.25;
+
+// Pure: classify one harvest row into a disposition. Testable.
+export function dispositionOf(row) {
+  if (row.status === 'FABRIC_MISCLASS') return 'RECLASSIFY_FABRIC';         // wrong product type — not a wallpaper roll
+  if (row.status === 'NOT_FOUND' || row.us_retail == null) return 'HOLD_NO_US_PRICE';
+  const p = Number(row.us_retail);
+  if (!(p > SAMPLE)) return 'HOLD_BAD_PRICE';
+  if (row.status === 'PROPOSED_UNIT_FLAG') return 'PROPOSE_UNIT_REVIEW';    // per-metre/double-roll — unit needs review
+  if (row.status === 'PROPOSED_SIBLING_EST') return 'PROPOSE_LOW_CONF';     // sibling-estimated, med conf
+  return 'PROPOSE';                                                          // firm US price
+}
+
+function main() {
+  const v3 = JSON.parse(fs.readFileSync(V3_IN, 'utf8'));
+  const heldSet = new Set(v3.filter(r => r.action === 'HELD_UNVERIFIED').map(r => r.mfr_sku));
+  const batches = fs.readdirSync(DIR).filter(f => /^harvest_batch\d+\.json$/.test(f)).sort();
+  const proposals = [];
+  for (const b of batches) {
+    const data = JSON.parse(fs.readFileSync(DIR + b, 'utf8'));
+    for (const row of data.rows) {
+      const inHeld = heldSet.has(row.mfr_sku);
+      proposals.push({ ...row, batch: data.batch, in_held_set: inHeld, disposition: dispositionOf(row) });
+    }
+  }
+  const byDisp = {};
+  for (const p of proposals) byDisp[p.disposition] = (byDisp[p.disposition] || 0) + 1;
+  const harvested = proposals.map(p => p.mfr_sku);
+  const remaining = [...heldSet].filter(m => !harvested.includes(m));
+
+  const out = {
+    ticket: 'TK-10873', generated_at: new Date().toISOString(), read_only: true,
+    held_total: heldSet.size, harvested: proposals.length, remaining_to_harvest: remaining.length,
+    dispositions: byDisp,
+    note: 'PROPOSALS ONLY — no REPRICE promotion here. PROPOSE rows have a firm US retail; UNIT_REVIEW/LOW_CONF need a human look; RECLASSIFY_FABRIC is a data-type bug; HOLD_* stay held. Live reprice + any promotion stays Steve-gated.',
+    proposals,
+    remaining_mfr_skus: remaining,
+  };
+  fs.writeFileSync(OUT, JSON.stringify(out, null, 2));
+
+  const md = [`# TK-10873 — HELD_UNVERIFIED US-retail harvest proposals`, '',
+    `- Held total: ${heldSet.size} · harvested: ${proposals.length} · remaining: ${remaining.length}`,
+    `- Dispositions: ${JSON.stringify(byDisp)}`, '',
+    `| mfr_sku | pattern | zc | proposed US | disposition | conf | source |`,
+    `|---|---|---|---|---|---|---|`,
+    ...proposals.map(p => `| ${p.mfr_sku} | ${p.pattern} | $${p.zc_price} | ${p.us_retail == null ? '—' : '$' + p.us_retail} | ${p.disposition} | ${p.confidence} | ${p.source} |`),
+    '', `_PROPOSALS ONLY — Steve/pricing-owner reviews before any promotion; live reprice gated._`, ''];
+  fs.writeFileSync(MD_OUT, md.join('\n') + '\n');
+
+  console.log('=== held-price harvest proposals (READ-ONLY) ===');
+  console.log(`held=${heldSet.size} harvested=${proposals.length} remaining=${remaining.length}`);
+  console.log(`dispositions=${JSON.stringify(byDisp)}`);
+  console.log(`artifacts:\n  ${OUT}\n  ${MD_OUT}`);
+}
+
+if (import.meta.url === `file://${process.argv[1]}`) main();
diff --git a/tk10873/harvest_batch1.json b/tk10873/harvest_batch1.json
new file mode 100644
index 0000000..69e4b9a
--- /dev/null
+++ b/tk10873/harvest_batch1.json
@@ -0,0 +1,22 @@
+{
+  "batch": 1,
+  "ticket": "TK-10873",
+  "cycle": 6,
+  "note": "US per-roll retail harvested via free web search (web-researcher subagent), per representative colorway. Proposals only — NOT auto-promoted to REPRICE (per cycle-5 Cody lesson: web-confirm per SKU). Zoffany US 'roll' = 11-yd extra-wide double-roll-equivalent unless flagged.",
+  "rows": [
+    { "mfr_sku": "ZOW0091-01", "pattern": "Ajanta", "zc_price": 122, "us_retail": 342.00, "unit": "11yd-roll", "confidence": "high", "source": "decoratorsbest.com", "status": "PROPOSED" },
+    { "mfr_sku": "ZIND313111", "pattern": "Artisan Palampore", "zc_price": 136, "us_retail": 350.00, "unit": "per-metre-double-roll", "confidence": "high", "source": "wallpaperdirect.com/us", "status": "PROPOSED_UNIT_FLAG" },
+    { "mfr_sku": "ZDAR312884", "pattern": "Darnley", "zc_price": 176, "us_retail": 390.00, "unit": "11yd-roll", "confidence": "med", "source": "morriswallpaper.com", "status": "PROPOSED" },
+    { "mfr_sku": "ZAQF322696", "pattern": "Desert Flower II", "zc_price": 132, "us_retail": 133.00, "unit": "per-yard-FABRIC", "confidence": "high", "source": "zoffany.sandersondesigngroup.com", "status": "FABRIC_MISCLASS" },
+    { "mfr_sku": "ZEND313098", "pattern": "Domino Paper", "zc_price": 148, "us_retail": 264.00, "unit": "double-roll", "confidence": "high", "source": "selectedwallpapers.com", "status": "PROPOSED" },
+    { "mfr_sku": "ZDAR312865", "pattern": "Ebru II", "zc_price": 122, "us_retail": 230.00, "unit": "11yd-roll", "confidence": "high", "source": "morriswallpaper.com", "status": "PROPOSED" },
+    { "mfr_sku": "ZCOT313026", "pattern": "French Marble", "zc_price": 148, "us_retail": 382.00, "unit": "11yd-roll", "confidence": "high", "source": "decoratorsbest.com", "status": "PROPOSED" },
+    { "mfr_sku": "ZDAR312861", "pattern": "Highclere", "zc_price": 148, "us_retail": null, "unit": "11yd-roll", "confidence": "low", "source": "selectedwallpapers.com", "status": "NOT_FOUND" },
+    { "mfr_sku": "ZDAR312864", "pattern": "Mitford Damask", "zc_price": 148, "us_retail": 230.00, "unit": "11yd-roll", "confidence": "med", "source": "studio198.com", "status": "PROPOSED" },
+    { "mfr_sku": "ZDAR312873", "pattern": "Ormonde", "zc_price": 122, "us_retail": 342.00, "unit": "11yd-roll", "confidence": "high", "source": "decoratorsbest.com", "status": "PROPOSED" },
+    { "mfr_sku": "ZCOT313015", "pattern": "Pompadour Print", "zc_price": 210, "us_retail": null, "unit": "per-metre-grasscloth", "confidence": "low", "source": "selectedwallpapers.com", "status": "NOT_FOUND" },
+    { "mfr_sku": "ZDAR312857", "pattern": "Richmond Park", "zc_price": 164, "us_retail": 416.00, "unit": "11yd-roll", "confidence": "high", "source": "morriswallpaper.com", "status": "PROPOSED" },
+    { "mfr_sku": "ZAMW310430", "pattern": "Verdure", "zc_price": 200, "us_retail": null, "unit": "per-metre", "confidence": "low", "source": "decoratorsbest.com", "status": "NOT_FOUND" },
+    { "mfr_sku": "ZDAR312869", "pattern": "Wallis", "zc_price": 122, "us_retail": 342.00, "unit": "11yd-roll", "confidence": "med", "source": "morriswallpaper.com", "status": "PROPOSED_SIBLING_EST" }
+  ]
+}
diff --git a/tk10873/held_price_proposals.json b/tk10873/held_price_proposals.json
new file mode 100644
index 0000000..3d407a0
--- /dev/null
+++ b/tk10873/held_price_proposals.json
@@ -0,0 +1,239 @@
+{
+  "ticket": "TK-10873",
+  "generated_at": "2026-08-31T05:19:47.152Z",
+  "read_only": true,
+  "held_total": 51,
+  "harvested": 14,
+  "remaining_to_harvest": 37,
+  "dispositions": {
+    "PROPOSE": 8,
+    "PROPOSE_UNIT_REVIEW": 1,
+    "RECLASSIFY_FABRIC": 1,
+    "HOLD_NO_US_PRICE": 3,
+    "PROPOSE_LOW_CONF": 1
+  },
+  "note": "PROPOSALS ONLY — no REPRICE promotion here. PROPOSE rows have a firm US retail; UNIT_REVIEW/LOW_CONF need a human look; RECLASSIFY_FABRIC is a data-type bug; HOLD_* stay held. Live reprice + any promotion stays Steve-gated.",
+  "proposals": [
+    {
+      "mfr_sku": "ZOW0091-01",
+      "pattern": "Ajanta",
+      "zc_price": 122,
+      "us_retail": 342,
+      "unit": "11yd-roll",
+      "confidence": "high",
+      "source": "decoratorsbest.com",
+      "status": "PROPOSED",
+      "batch": 1,
+      "in_held_set": true,
+      "disposition": "PROPOSE"
+    },
+    {
+      "mfr_sku": "ZIND313111",
+      "pattern": "Artisan Palampore",
+      "zc_price": 136,
+      "us_retail": 350,
+      "unit": "per-metre-double-roll",
+      "confidence": "high",
+      "source": "wallpaperdirect.com/us",
+      "status": "PROPOSED_UNIT_FLAG",
+      "batch": 1,
+      "in_held_set": true,
+      "disposition": "PROPOSE_UNIT_REVIEW"
+    },
+    {
+      "mfr_sku": "ZDAR312884",
+      "pattern": "Darnley",
+      "zc_price": 176,
+      "us_retail": 390,
+      "unit": "11yd-roll",
+      "confidence": "med",
+      "source": "morriswallpaper.com",
+      "status": "PROPOSED",
+      "batch": 1,
+      "in_held_set": true,
+      "disposition": "PROPOSE"
+    },
+    {
+      "mfr_sku": "ZAQF322696",
+      "pattern": "Desert Flower II",
+      "zc_price": 132,
+      "us_retail": 133,
+      "unit": "per-yard-FABRIC",
+      "confidence": "high",
+      "source": "zoffany.sandersondesigngroup.com",
+      "status": "FABRIC_MISCLASS",
+      "batch": 1,
+      "in_held_set": true,
+      "disposition": "RECLASSIFY_FABRIC"
+    },
+    {
+      "mfr_sku": "ZEND313098",
+      "pattern": "Domino Paper",
+      "zc_price": 148,
+      "us_retail": 264,
+      "unit": "double-roll",
+      "confidence": "high",
+      "source": "selectedwallpapers.com",
+      "status": "PROPOSED",
+      "batch": 1,
+      "in_held_set": true,
+      "disposition": "PROPOSE"
+    },
+    {
+      "mfr_sku": "ZDAR312865",
+      "pattern": "Ebru II",
+      "zc_price": 122,
+      "us_retail": 230,
+      "unit": "11yd-roll",
+      "confidence": "high",
+      "source": "morriswallpaper.com",
+      "status": "PROPOSED",
+      "batch": 1,
+      "in_held_set": true,
+      "disposition": "PROPOSE"
+    },
+    {
+      "mfr_sku": "ZCOT313026",
+      "pattern": "French Marble",
+      "zc_price": 148,
+      "us_retail": 382,
+      "unit": "11yd-roll",
+      "confidence": "high",
+      "source": "decoratorsbest.com",
+      "status": "PROPOSED",
+      "batch": 1,
+      "in_held_set": true,
+      "disposition": "PROPOSE"
+    },
+    {
+      "mfr_sku": "ZDAR312861",
+      "pattern": "Highclere",
+      "zc_price": 148,
+      "us_retail": null,
+      "unit": "11yd-roll",
+      "confidence": "low",
+      "source": "selectedwallpapers.com",
+      "status": "NOT_FOUND",
+      "batch": 1,
+      "in_held_set": true,
+      "disposition": "HOLD_NO_US_PRICE"
+    },
+    {
+      "mfr_sku": "ZDAR312864",
+      "pattern": "Mitford Damask",
+      "zc_price": 148,
+      "us_retail": 230,
+      "unit": "11yd-roll",
+      "confidence": "med",
+      "source": "studio198.com",
+      "status": "PROPOSED",
+      "batch": 1,
+      "in_held_set": true,
+      "disposition": "PROPOSE"
+    },
+    {
+      "mfr_sku": "ZDAR312873",
+      "pattern": "Ormonde",
+      "zc_price": 122,
+      "us_retail": 342,
+      "unit": "11yd-roll",
+      "confidence": "high",
+      "source": "decoratorsbest.com",
+      "status": "PROPOSED",
+      "batch": 1,
+      "in_held_set": true,
+      "disposition": "PROPOSE"
+    },
+    {
+      "mfr_sku": "ZCOT313015",
+      "pattern": "Pompadour Print",
+      "zc_price": 210,
+      "us_retail": null,
+      "unit": "per-metre-grasscloth",
+      "confidence": "low",
+      "source": "selectedwallpapers.com",
+      "status": "NOT_FOUND",
+      "batch": 1,
+      "in_held_set": true,
+      "disposition": "HOLD_NO_US_PRICE"
+    },
+    {
+      "mfr_sku": "ZDAR312857",
+      "pattern": "Richmond Park",
+      "zc_price": 164,
+      "us_retail": 416,
+      "unit": "11yd-roll",
+      "confidence": "high",
+      "source": "morriswallpaper.com",
+      "status": "PROPOSED",
+      "batch": 1,
+      "in_held_set": true,
+      "disposition": "PROPOSE"
+    },
+    {
+      "mfr_sku": "ZAMW310430",
+      "pattern": "Verdure",
+      "zc_price": 200,
+      "us_retail": null,
+      "unit": "per-metre",
+      "confidence": "low",
+      "source": "decoratorsbest.com",
+      "status": "NOT_FOUND",
+      "batch": 1,
+      "in_held_set": true,
+      "disposition": "HOLD_NO_US_PRICE"
+    },
+    {
+      "mfr_sku": "ZDAR312869",
+      "pattern": "Wallis",
+      "zc_price": 122,
+      "us_retail": 342,
+      "unit": "11yd-roll",
+      "confidence": "med",
+      "source": "morriswallpaper.com",
+      "status": "PROPOSED_SIBLING_EST",
+      "batch": 1,
+      "in_held_set": true,
+      "disposition": "PROPOSE_LOW_CONF"
+    }
+  ],
+  "remaining_mfr_skus": [
+    "ZAMW310431",
+    "ZOW0091-02",
+    "ZOW0091-03",
+    "ZOW0092-01",
+    "ZOW0092-03",
+    "ZOW0092-04",
+    "ZOW0092-05",
+    "ZOW0093-02",
+    "ZOW0093-03",
+    "ZOW0093-05",
+    "ZOW0093-07",
+    "ZOW0094-01",
+    "ZOW0094-03",
+    "ZOW0094-06",
+    "ZOW0095-01",
+    "ZOW0095-02",
+    "ZOW0095-03",
+    "ZOW0095-05",
+    "ZOW0096-01",
+    "ZOW0096-02",
+    "ZOW0096-03",
+    "ZOW0097-01",
+    "ZOW0098-01",
+    "ZOW0098-02",
+    "ZOW0098-03",
+    "ZOW0100-01",
+    "ZOW0100-02",
+    "ZOW0100-03",
+    "ZOW0101-01",
+    "ZOW0101-02",
+    "ZOW0102-01",
+    "ZOW0102-02",
+    "ZOW0102-03",
+    "ZOW0103-01",
+    "ZOW0103-02",
+    "ZOW0103-03",
+    "ZPHA312622"
+  ]
+}
\ No newline at end of file
diff --git a/tk10873/held_price_proposals.md b/tk10873/held_price_proposals.md
new file mode 100644
index 0000000..36cb778
--- /dev/null
+++ b/tk10873/held_price_proposals.md
@@ -0,0 +1,24 @@
+# TK-10873 — HELD_UNVERIFIED US-retail harvest proposals
+
+- Held total: 51 · harvested: 14 · remaining: 37
+- Dispositions: {"PROPOSE":8,"PROPOSE_UNIT_REVIEW":1,"RECLASSIFY_FABRIC":1,"HOLD_NO_US_PRICE":3,"PROPOSE_LOW_CONF":1}
+
+| mfr_sku | pattern | zc | proposed US | disposition | conf | source |
+|---|---|---|---|---|---|---|
+| ZOW0091-01 | Ajanta | $122 | $342 | PROPOSE | high | decoratorsbest.com |
+| ZIND313111 | Artisan Palampore | $136 | $350 | PROPOSE_UNIT_REVIEW | high | wallpaperdirect.com/us |
+| ZDAR312884 | Darnley | $176 | $390 | PROPOSE | med | morriswallpaper.com |
+| ZAQF322696 | Desert Flower II | $132 | $133 | RECLASSIFY_FABRIC | high | zoffany.sandersondesigngroup.com |
+| ZEND313098 | Domino Paper | $148 | $264 | PROPOSE | high | selectedwallpapers.com |
+| ZDAR312865 | Ebru II | $122 | $230 | PROPOSE | high | morriswallpaper.com |
+| ZCOT313026 | French Marble | $148 | $382 | PROPOSE | high | decoratorsbest.com |
+| ZDAR312861 | Highclere | $148 | — | HOLD_NO_US_PRICE | low | selectedwallpapers.com |
+| ZDAR312864 | Mitford Damask | $148 | $230 | PROPOSE | med | studio198.com |
+| ZDAR312873 | Ormonde | $122 | $342 | PROPOSE | high | decoratorsbest.com |
+| ZCOT313015 | Pompadour Print | $210 | — | HOLD_NO_US_PRICE | low | selectedwallpapers.com |
+| ZDAR312857 | Richmond Park | $164 | $416 | PROPOSE | high | morriswallpaper.com |
+| ZAMW310430 | Verdure | $200 | — | HOLD_NO_US_PRICE | low | decoratorsbest.com |
+| ZDAR312869 | Wallis | $122 | $342 | PROPOSE_LOW_CONF | med | morriswallpaper.com |
+
+_PROPOSALS ONLY — Steve/pricing-owner reviews before any promotion; live reprice gated._
+
diff --git a/tk10873/test_proposals.mjs b/tk10873/test_proposals.mjs
new file mode 100644
index 0000000..777c91b
--- /dev/null
+++ b/tk10873/test_proposals.mjs
@@ -0,0 +1,16 @@
+#!/usr/bin/env node
+// test_proposals.mjs — unit tests for dispositionOf (pure).
+import { dispositionOf } from './build_harvest_proposals.mjs';
+let pass = 0, fail = 0;
+const ok = (c, m) => { if (c) pass++; else { fail++; console.error(`FAIL: ${m}`); } };
+
+ok(dispositionOf({ status: 'PROPOSED', us_retail: 342 }) === 'PROPOSE', 'firm price -> PROPOSE');
+ok(dispositionOf({ status: 'FABRIC_MISCLASS', us_retail: 133 }) === 'RECLASSIFY_FABRIC', 'fabric -> RECLASSIFY_FABRIC');
+ok(dispositionOf({ status: 'NOT_FOUND', us_retail: null }) === 'HOLD_NO_US_PRICE', 'not found -> HOLD_NO_US_PRICE');
+ok(dispositionOf({ status: 'PROPOSED', us_retail: null }) === 'HOLD_NO_US_PRICE', 'null price -> HOLD_NO_US_PRICE');
+ok(dispositionOf({ status: 'PROPOSED', us_retail: 2 }) === 'HOLD_BAD_PRICE', 'below sample -> HOLD_BAD_PRICE');
+ok(dispositionOf({ status: 'PROPOSED_UNIT_FLAG', us_retail: 350 }) === 'PROPOSE_UNIT_REVIEW', 'unit flag -> PROPOSE_UNIT_REVIEW');
+ok(dispositionOf({ status: 'PROPOSED_SIBLING_EST', us_retail: 342 }) === 'PROPOSE_LOW_CONF', 'sibling est -> PROPOSE_LOW_CONF');
+
+console.log(`\ntest_proposals: ${pass} passed, ${fail} failed`);
+process.exit(fail === 0 ? 0 : 1);

← 2d6980f TK-10873 cycle5 Cody-fix: web spot-check clears the circular  ·  back to Sanderson Onboard  ·  TK-10873 cycle7: batch-2 US-retail harvest (15 Folio-collect b80844e →