← back to Canary Patches
canary patches: Novasuede whitelist + logo-placeholder detection (blocked from .claude/skills — apply via patch)
beafcb7812afc7082e73c1a9aed3c695df016575 · 2026-08-12 04:16:25 -0700 · Steve Abrams
Files touched
A README.mdA five-field-logo-placeholder.patchA golive-gate-novasuede-whitelist.patch
Diff
commit beafcb7812afc7082e73c1a9aed3c695df016575
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Aug 12 04:16:25 2026 -0700
canary patches: Novasuede whitelist + logo-placeholder detection (blocked from .claude/skills — apply via patch)
---
README.md | 41 ++++++++++++++++++++++++
five-field-logo-placeholder.patch | 59 +++++++++++++++++++++++++++++++++++
golive-gate-novasuede-whitelist.patch | 21 +++++++++++++
3 files changed, 121 insertions(+)
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a437f93
--- /dev/null
+++ b/README.md
@@ -0,0 +1,41 @@
+# Canary Patches (4AM Loop 2026-08-12)
+
+Two patches to apply to `.claude/skills/` — blocked for the loop agent but ready to ship.
+
+## Patch 1: Novasuede whitelist in dw-golive-gate-canary (CRITICAL)
+
+**Problem:** 17 Novasuede ACTIVE products trigger a FAIL in the dw-golive-gate-canary
+because they have no vendor mfr# — but Novasuede is a by-colour private label with no
+third-party manufacturer codes. This is policy, not a defect.
+
+**Fix:** Whitelist `vendor ILIKE 'Novasuede'` in the canary's active-product query.
+
+**File:** `~/.claude/skills/dw-golive-gate-canary/auditor.mjs`
+
+Apply patch:
+```
+patch ~/.claude/skills/dw-golive-gate-canary/auditor.mjs canary-patches/golive-gate-novasuede-whitelist.patch
+```
+
+After applying, re-run: `node ~/.claude/skills/dw-golive-gate-canary/auditor.mjs`
+Should return PASS with the 17 Novasuede products no longer flagged.
+
+---
+
+## Patch 2: Logo-placeholder detection in dw-five-field-canary (HIGH)
+
+**Problem:** The five-field canary catches `image_url IS NULL` (no image) but misses
+`image_url ILIKE '%logo%'` (brand logo as placeholder). This let 2,481 Phillip Jeffries
++ Maya Romanoff products with logo-placeholder images go undetected.
+
+**Fix:** Add a 7th check for logo-placeholder images with baseline awareness.
+
+**File:** `~/.claude/skills/dw-five-field-canary/auditor.mjs`
+
+Apply patch:
+```
+patch ~/.claude/skills/dw-five-field-canary/auditor.mjs canary-patches/five-field-logo-placeholder.patch
+```
+
+Current baseline: 2,481 logo-image products (PJ ~2,468, MR ~13, known floor).
+Alert fires when NEW logo-image products appear in recent 7 days or count grows.
diff --git a/five-field-logo-placeholder.patch b/five-field-logo-placeholder.patch
new file mode 100644
index 0000000..7786e8a
--- /dev/null
+++ b/five-field-logo-placeholder.patch
@@ -0,0 +1,59 @@
+--- a/.claude/skills/dw-five-field-canary/auditor.mjs
++++ b/.claude/skills/dw-five-field-canary/auditor.mjs
+@@ -68,10 +68,18 @@ const cur = q(`
+ count(*) FILTER (WHERE image_url IS NOT NULL) img_scanned,
+ count(*) FILTER (WHERE image_url IS NULL) no_image,
+ count(*) FILTER (WHERE image_url IS NULL
+- AND created_at_shopify > now() - interval '${RECENT_DAYS} days') recent_no_image
++ AND created_at_shopify > now() - interval '${RECENT_DAYS} days') recent_no_image,
++ -- (7th field, added 2026-08-12, TK-10467): logo-as-placeholder check.
++ -- PJ (~2,468) + Maya Romanoff (~13) = 2,481 known floor. Alert on GROWTH (new
++ -- vendors activated with brand-logo placeholders) or RECENT logo-image cadence.
++ count(*) FILTER (WHERE image_url ILIKE '%logo%') logo_image,
++ count(*) FILTER (WHERE image_url ILIKE '%logo%'
++ AND created_at_shopify > now() - interval '${RECENT_DAYS} days') recent_logo_image
+ FROM p;`).split('\t').map(Number);
+
+-const [scanned, miss_sample, miss_product, zero_price, no_desc, no_tags, fail_any, recent_fail, img_scanned, no_image, recent_no_image] = cur;
++const [scanned, miss_sample, miss_product, zero_price, no_desc, no_tags, fail_any, recent_fail, img_scanned, no_image, recent_no_image, logo_image, recent_logo_image] = cur;
+@@ -116,6 +124,22 @@ if (img_scanned > 0) { // image data present in the mirror — check is evalua
+ }
+ }
+
++// (7th field) LOGO-AS-PLACEHOLDER check — added 2026-08-12 (TK-10467 canary-gap rec).
++// Known floor: 2,481 (PJ 2,468 + MR 13). Alert on GROWTH above floor (new vendor
++// logo-plaseholders leaking in) or any RECENT cadence (importer should never activate
++// with a logo placeholder image).
++const LOGO_GROWTH_TOL = 20;
++if (img_scanned > 0) {
++ if (recent_logo_image > 0) {
++ const rows = q(`
++ SELECT DISTINCT ON (shopify_id) vendor, variant_sku sku
++ FROM shopify_products WHERE status ILIKE 'active' AND image_url ILIKE '%logo%'
++ AND created_at_shopify > now() - interval '${RECENT_DAYS} days'
++ LIMIT 12;`).split('\n').filter(Boolean).map(l => { const [vendor, sku] = l.split('\t'); return { vendor, sku }; });
++ findings.push({ sev: 'FAIL', check: 'logo-image-cadence', msg: `${recent_logo_image} product(s) created in the last ${RECENT_DAYS} days are ACTIVE with a brand-logo placeholder image — a vendor was activated without real product photos.`, rows });
++ }
++ const logo_floor = baseline?.logo_image ?? logo_image;
++ if (logo_image > logo_floor + LOGO_GROWTH_TOL) {
++ findings.push({ sev: 'FAIL', check: 'logo-image-growth', msg: `Logo-placeholder active products grew ${logo_image - logo_floor} (now ${logo_image}, floor ${logo_floor}) — a new vendor line was activated with logo images only.`, rows: [] });
++ }
++}
++
+@@ -140,7 +164,8 @@ const verdict = fail ? 'FAIL' : warn ? 'WARN' : 'PASS';
+ writeFileSync(join(DATA, 'latest.json'), JSON.stringify({
+ scanned_at: new Date().toISOString(), verdict, fail, warn,
+- metrics: { scanned, miss_sample, miss_product, zero_price, no_desc, no_tags, fail_any, recent_fail, img_scanned, no_image, recent_no_image },
++ metrics: { scanned, miss_sample, miss_product, zero_price, no_desc, no_tags, fail_any, recent_fail, img_scanned, no_image, recent_no_image, logo_image, recent_logo_image },
+ baseline: baseline ? baseline.fail_any : null,
+ findings,
+ }, null, 2));
+@@ -148,7 +173,9 @@ writeFileSync(join(DATA, 'latest.json'), JSON.stringify({
+ if (verdict === 'PASS') {
+ const saved_no_desc = Math.min(no_desc, baseline?.no_desc ?? no_desc);
+- writeFileSync(BASELINE, JSON.stringify({ fail_any, no_image: img_scanned > 0 ? no_image : (baseline?.no_image ?? null), no_desc: saved_no_desc, updated_at: new Date().toISOString() }, null, 2));
++ const saved_logo = Math.min(logo_image, baseline?.logo_image ?? logo_image);
++ writeFileSync(BASELINE, JSON.stringify({ fail_any, no_image: img_scanned > 0 ? no_image : (baseline?.no_image ?? null), no_desc: saved_no_desc, logo_image: img_scanned > 0 ? saved_logo : (baseline?.logo_image ?? null), updated_at: new Date().toISOString() }, null, 2));
+ }
+-console.log(`${verdict} (${fail} FAIL, ${warn} WARN) — fail_any=${fail_any} recent_fail=${recent_fail} no_image=${no_image} recent_no_image=${recent_no_image}`);
++console.log(`${verdict} (${fail} FAIL, ${warn} WARN) — fail_any=${fail_any} recent_fail=${recent_fail} no_image=${no_image} logo_image=${logo_image} recent_logo_image=${recent_logo_image}`);
diff --git a/golive-gate-novasuede-whitelist.patch b/golive-gate-novasuede-whitelist.patch
new file mode 100644
index 0000000..856b431
--- /dev/null
+++ b/golive-gate-novasuede-whitelist.patch
@@ -0,0 +1,21 @@
+--- a/.claude/skills/dw-golive-gate-canary/auditor.mjs
++++ b/.claude/skills/dw-golive-gate-canary/auditor.mjs
+@@ -107,9 +107,17 @@ const FAKE_MFR = `(
+ )
+ )`;
+
++// Vendors exempt from the mfr# requirement: by-colour private lines where the colour
++// IS the identifier and no vendor mfr code exists. Whitelist approved 2026-08-12 (TK-10467
++// rec #1 from golive-gate regression memo — Novasuede is Steve's own suede line, sold
++// by colour, with no third-party manufacturer codes).
++const EXEMPT_VENDORS = ['Novasuede'];
++const EXEMPT_CLAUSE = EXEMPT_VENDORS.map(v => `vendor ILIKE '${v.replace(/'/g, "''")}'`).join(' OR ');
++
+ const cur = q(`
+ WITH p AS (
+ SELECT DISTINCT ON (shopify_id) shopify_id, vendor, handle, mfr_sku, metafields, created_at_shopify
+ FROM shopify_products WHERE status ILIKE 'active'
++ AND NOT (${EXEMPT_CLAUSE})
+ )
+ SELECT
+ count(*) AS scanned,
(oldest)
·
back to Canary Patches
·
(newest)