← back to Designerwallcoverings
Restore and verify Sanderson Breeze Blue hero for TK-11453
ece3b73cc64a88a54837567f77256e1942f8c05f · 2026-09-11 08:24:09 -0700 · Steve Abrams
Files touched
A verification/TK-11453/after.jsonA verification/TK-11453/e2e-proof.jsonA verification/TK-11453/fleet-canary.jsonA verification/TK-11453/intent.jsonA verification/TK-11453/preflight.jsonA verification/TK-11453/recheck.jsonA verification/TK-11453/restore.mjsA verification/TK-11453/result.jsonA verification/TK-11453/source.jpgA verification/TK-11453/storefront.png
Diff
commit ece3b73cc64a88a54837567f77256e1942f8c05f
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Sep 11 08:24:09 2026 -0700
Restore and verify Sanderson Breeze Blue hero for TK-11453
---
verification/TK-11453/after.json | 26 +++++++++++
verification/TK-11453/e2e-proof.json | 69 +++++++++++++++++++++++++++
verification/TK-11453/fleet-canary.json | 80 ++++++++++++++++++++++++++++++++
verification/TK-11453/intent.json | 43 +++++++++++++++++
verification/TK-11453/preflight.json | 42 +++++++++++++++++
verification/TK-11453/recheck.json | 27 +++++++++++
verification/TK-11453/restore.mjs | 73 +++++++++++++++++++++++++++++
verification/TK-11453/result.json | 26 +++++++++++
verification/TK-11453/source.jpg | Bin 0 -> 217366 bytes
verification/TK-11453/storefront.png | Bin 0 -> 474314 bytes
10 files changed, 386 insertions(+)
diff --git a/verification/TK-11453/after.json b/verification/TK-11453/after.json
new file mode 100644
index 0000000..d29e748
--- /dev/null
+++ b/verification/TK-11453/after.json
@@ -0,0 +1,26 @@
+{
+ "ts": "2026-09-11T15:19:46.811Z",
+ "verdict": "PASS",
+ "product": {
+ "id": 7899582201907,
+ "title": "101 Dalmatians Breeze Blue | Sanderson",
+ "vendor": "Sanderson",
+ "handle": "101-dalmatians-breeze-blue-sanderson",
+ "status": "active",
+ "images": [
+ {
+ "id": 38069312749619,
+ "alt": "101 Dalmatians Breeze Blue wallpaper — Sanderson",
+ "position": 1,
+ "product_id": 7899582201907,
+ "created_at": "2026-09-11T08:19:46-07:00",
+ "updated_at": "2026-09-11T08:19:46-07:00",
+ "admin_graphql_api_id": "gid://shopify/MediaImage/28904884338739",
+ "width": 1366,
+ "height": 1366,
+ "src": "https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DDIW217290_b307.jpg?v=1789139986",
+ "variant_ids": []
+ }
+ ]
+ }
+}
diff --git a/verification/TK-11453/e2e-proof.json b/verification/TK-11453/e2e-proof.json
new file mode 100644
index 0000000..c5d729b
--- /dev/null
+++ b/verification/TK-11453/e2e-proof.json
@@ -0,0 +1,69 @@
+{
+ "ticket": "TK-11453",
+ "intent": "Restore exact SAW0189-02 Breeze Blue hero to one imageless active product",
+ "risk_tier": "R4 authorized single product write",
+ "timestamp": "2026-09-11T15:19:46.811Z",
+ "authorization": "User go following gated single-product restoration recap",
+ "baseline": {
+ "product_id": 7899582201907,
+ "images": []
+ },
+ "verdict": "PASS",
+ "checks": [
+ {
+ "name": "Exact manufacturer SKU/name/image JSON-LD and visual confirmation",
+ "verdict": "PASS"
+ },
+ {
+ "name": "Single created image38069312749619 persisted; active status preserved",
+ "verdict": "PASS"
+ },
+ {
+ "name": "Independent reviewer Shopify GET",
+ "verdict": "PASS",
+ "timestamp": "2026-09-11T15:20:57.789Z"
+ },
+ {
+ "name": "Chromium live storefront image decoded and visible576x576",
+ "verdict": "PASS",
+ "evidence": "storefront.png"
+ },
+ {
+ "name": "Repeat preflight returns no-op, zero duplicate writes",
+ "verdict": "PASS"
+ }
+ ],
+ "commands": [
+ "node verification/TK-11453/restore.mjs",
+ "node verification/TK-11453/restore.mjs --apply",
+ "Chromium Playwright live product-page screenshot and naturalWidth assertion",
+ "node ~/.claude/skills/dw-image-identity-canary/canary.mjs"
+ ],
+ "rollback": {
+ "artifact": "result.json",
+ "status": "Recorded scoped delete of only created image; not executed because restoration succeeded"
+ },
+ "negative_checks": "Existing matching image exercised as no-op; identity/changed-gallery guards reviewed independently. No intentional live failure or rollback of correct image.",
+ "artifacts": [
+ "preflight.json",
+ "intent.json",
+ "result.json",
+ "after.json",
+ "recheck.json",
+ "source.jpg",
+ "storefront.png"
+ ],
+ "code_sha256": "53fb14642c5cdb715bdcdff36ee2a2665cb6e40dee4977448248078781be45aa",
+ "separate_fleet_regression": {
+ "status": "FAIL",
+ "timestamp": "2026-09-11T15:20:55.053Z",
+ "totals": {
+ "active": 1003,
+ "gallery_imgs": 125,
+ "foreign_imgs": 54,
+ "foreign_products": 34
+ },
+ "note": "Other gallery-image defects; this product retains exactly one image so is outside gallery check. No broader mutation authorized."
+ },
+ "cleanup": "Browser closed; correct image retained; no canonical DB write or external messages."
+}
diff --git a/verification/TK-11453/fleet-canary.json b/verification/TK-11453/fleet-canary.json
new file mode 100644
index 0000000..e1578e5
--- /dev/null
+++ b/verification/TK-11453/fleet-canary.json
@@ -0,0 +1,80 @@
+{
+ "skill": "dw-image-identity-canary",
+ "verdict": "FAIL",
+ "status": "FAIL",
+ "ts": "2026-09-11T15:20:55.053Z",
+ "vendors": [
+ "Sanderson"
+ ],
+ "totals": {
+ "active": 1003,
+ "gallery_imgs": 125,
+ "foreign_imgs": 54,
+ "foreign_products": 34
+ },
+ "baseline": {
+ "foreign_products": 6,
+ "foreign_imgs": 6,
+ "ts": "2026-09-03T18:40:47.111Z",
+ "note": "first-run baseline"
+ },
+ "perVendor": {
+ "Sanderson": {
+ "active": 1003,
+ "gallery_imgs": 125,
+ "foreign_imgs": 54,
+ "foreign_products": 34,
+ "examples": [
+ {
+ "handle": "anaar-lionsmane-sanderson",
+ "mfr_sku": "SAW0237-01",
+ "img": "DBOW217451_eb34.jpg",
+ "cls": "foreign_pattern"
+ },
+ {
+ "handle": "anaar-lionsmane-sanderson",
+ "mfr_sku": "SAW0237-01",
+ "img": "DBOW217450_f936.jpg",
+ "cls": "foreign_pattern"
+ },
+ {
+ "handle": "anaar-lionsmane-sanderson",
+ "mfr_sku": "SAW0237-01",
+ "img": "DBOW217453_96d5_f6f5024c-f677-40e7-84b6-e053c93c0292.jpg",
+ "cls": "foreign_pattern"
+ },
+ {
+ "handle": "andromeda-s-cup-putty-sanderson",
+ "mfr_sku": "SAW0203-02",
+ "img": "DGDW217306_74ac_831110c4-903a-4b88-8c25-6c5a613f546f.jpg",
+ "cls": "foreign_pattern"
+ },
+ {
+ "handle": "aperigon-parade-bone-sanderson",
+ "mfr_sku": "SAW0204-03",
+ "img": "DGDW217306_74ac_36d0e594-7e4c-4925-ab33-8adeadce96b4.jpg",
+ "cls": "foreign_pattern"
+ },
+ {
+ "handle": "calathea-olive-sanderson",
+ "mfr_sku": "SAW0127-02",
+ "img": "DGLW216659_045c.jpg",
+ "cls": "foreign_pattern"
+ },
+ {
+ "handle": "dabu-namak-sanderson",
+ "mfr_sku": "SAW0238-02",
+ "img": "DBOW217459_a43e.jpg",
+ "cls": "foreign_pattern"
+ },
+ {
+ "handle": "dabu-namak-sanderson",
+ "mfr_sku": "SAW0238-02",
+ "img": "DBOW217455_3f44_a8936af7-357a-473d-9dfa-42bac90152de.jpg",
+ "cls": "foreign_pattern"
+ }
+ ]
+ }
+ },
+ "note": "contamination GREW: 34 products vs baseline 6 \u2014 a re-import likely re-introduced foreign gallery images"
+}
diff --git a/verification/TK-11453/intent.json b/verification/TK-11453/intent.json
new file mode 100644
index 0000000..c6d315d
--- /dev/null
+++ b/verification/TK-11453/intent.json
@@ -0,0 +1,43 @@
+{
+ "ts": "2026-09-11T15:19:44.380Z",
+ "ticket": "TK-11453",
+ "approval": "Steve: go, following gated single-product restoration recap",
+ "product_id": 7899582201907,
+ "sku": "SAW0189-02",
+ "source": "https://www.sanderson.design/static/media/catalog/product/D/D/DDIW217290_b307.jpg",
+ "vendorUrl": "https://www.sanderson.design/wallpaper/101-dalmatians-breeze-blue-saw0189-02",
+ "manufacturer": {
+ "@context": "http://schema.org",
+ "@type": "Product",
+ "@id": "SAW0189-02",
+ "name": "101 Dalmatians Breeze Blue",
+ "sku": "SAW0189-02",
+ "url": "https://www.sanderson.design/wallpaper/101-dalmatians-breeze-blue-saw0189-02",
+ "image": [
+ "https://www.sanderson.design/static/media/catalog/product/D/D/DDIW217290_b307.jpg"
+ ],
+ "offers": {
+ "@type": "Offer",
+ "priceCurrency": "GBP",
+ "price": "126",
+ "itemCondition": "https://schema.org/NewCondition",
+ "availability": "https://schema.org/PreOrder",
+ "seller": {
+ "@context": "http://schema.org",
+ "@type": "Organization",
+ "name": "",
+ "url": "https://www.sanderson.design/"
+ }
+ }
+ },
+ "source_sha256": "7343f2ba285eae1388796baf98de5a277998b510f575aeda9b5fe7383b96c23c",
+ "before": {
+ "id": 7899582201907,
+ "title": "101 Dalmatians Breeze Blue | Sanderson",
+ "vendor": "Sanderson",
+ "handle": "101-dalmatians-breeze-blue-sanderson",
+ "status": "active",
+ "images": []
+ },
+ "rollback": "Restore prior empty gallery by deleting ONLY the created image ID recorded in result.json after identity recheck; never replace the whole product."
+}
diff --git a/verification/TK-11453/preflight.json b/verification/TK-11453/preflight.json
new file mode 100644
index 0000000..f15729f
--- /dev/null
+++ b/verification/TK-11453/preflight.json
@@ -0,0 +1,42 @@
+{
+ "ts": "2026-09-11T15:19:44.380Z",
+ "ticket": "TK-11453",
+ "approval": "Steve: go, following gated single-product restoration recap",
+ "product_id": 7899582201907,
+ "sku": "SAW0189-02",
+ "source": "https://www.sanderson.design/static/media/catalog/product/D/D/DDIW217290_b307.jpg",
+ "vendorUrl": "https://www.sanderson.design/wallpaper/101-dalmatians-breeze-blue-saw0189-02",
+ "manufacturer": {
+ "@context": "http://schema.org",
+ "@type": "Product",
+ "@id": "SAW0189-02",
+ "name": "101 Dalmatians Breeze Blue",
+ "sku": "SAW0189-02",
+ "url": "https://www.sanderson.design/wallpaper/101-dalmatians-breeze-blue-saw0189-02",
+ "image": [
+ "https://www.sanderson.design/static/media/catalog/product/D/D/DDIW217290_b307.jpg"
+ ],
+ "offers": {
+ "@type": "Offer",
+ "priceCurrency": "GBP",
+ "price": "126",
+ "itemCondition": "https://schema.org/NewCondition",
+ "availability": "https://schema.org/PreOrder",
+ "seller": {
+ "@context": "http://schema.org",
+ "@type": "Organization",
+ "name": "",
+ "url": "https://www.sanderson.design/"
+ }
+ }
+ },
+ "source_sha256": "7343f2ba285eae1388796baf98de5a277998b510f575aeda9b5fe7383b96c23c",
+ "before": {
+ "id": 7899582201907,
+ "title": "101 Dalmatians Breeze Blue | Sanderson",
+ "vendor": "Sanderson",
+ "handle": "101-dalmatians-breeze-blue-sanderson",
+ "status": "active",
+ "images": []
+ }
+}
diff --git a/verification/TK-11453/recheck.json b/verification/TK-11453/recheck.json
new file mode 100644
index 0000000..d758e93
--- /dev/null
+++ b/verification/TK-11453/recheck.json
@@ -0,0 +1,27 @@
+{
+ "ts": "2026-09-11T15:20:48.743Z",
+ "verdict": "PASS",
+ "action": "already restored; no write",
+ "product": {
+ "id": 7899582201907,
+ "title": "101 Dalmatians Breeze Blue | Sanderson",
+ "vendor": "Sanderson",
+ "handle": "101-dalmatians-breeze-blue-sanderson",
+ "status": "active",
+ "images": [
+ {
+ "id": 38069312749619,
+ "alt": "101 Dalmatians Breeze Blue wallpaper — Sanderson",
+ "position": 1,
+ "product_id": 7899582201907,
+ "created_at": "2026-09-11T08:19:46-07:00",
+ "updated_at": "2026-09-11T08:19:46-07:00",
+ "admin_graphql_api_id": "gid://shopify/MediaImage/28904884338739",
+ "width": 1366,
+ "height": 1366,
+ "src": "https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DDIW217290_b307.jpg?v=1789139986",
+ "variant_ids": []
+ }
+ ]
+ }
+}
diff --git a/verification/TK-11453/restore.mjs b/verification/TK-11453/restore.mjs
new file mode 100644
index 0000000..ec2148c
--- /dev/null
+++ b/verification/TK-11453/restore.mjs
@@ -0,0 +1,73 @@
+// TK-11453: one approved image attachment; default is read-only preflight.
+import fs from 'node:fs';
+import assert from 'node:assert/strict';
+import {createHash} from 'node:crypto';
+const id = 7899582201907;
+const sku = 'SAW0189-02';
+const handle = '101-dalmatians-breeze-blue-sanderson';
+const source = 'https://www.sanderson.design/static/media/catalog/product/D/D/DDIW217290_b307.jpg';
+const vendorUrl = 'https://www.sanderson.design/wallpaper/101-dalmatians-breeze-blue-saw0189-02';
+const base = `https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10/products/${id}`;
+const dir = new URL('./', import.meta.url);
+const save = (name, obj) => fs.writeFileSync(new URL(name, dir), JSON.stringify(obj,null,2)+'\n');
+const apply = process.argv.includes('--apply');
+const env = fs.readFileSync(process.env.HOME+'/Projects/secrets-manager/.env','utf8');
+const credential = name => env.match(new RegExp('^'+name+'=(.+)$','m'))?.[1].trim().replace(/^["']|["']$/g,'');
+const token = credential(apply?'SHOPIFY_FULL_ACCESS_TOKEN':'SHOPIFY_ADMIN_TOKEN');
+assert(token, 'Missing credential');
+async function api(suffix, method='GET', body) {
+ const response = await fetch(base+suffix,{method,headers:{'X-Shopify-Access-Token':token,'Content-Type':'application/json'},body:body?JSON.stringify(body):undefined,signal:AbortSignal.timeout(30000)});
+ if(!response.ok) throw Error(`${method} failed HTTP ${response.status}; no automatic write retry`);
+ return response.json();
+}
+const get = async () => (await api('.json?fields=id,title,vendor,handle,status,images')).product;
+function validate(p, fields) {
+ assert.equal(p.id,id); assert.equal(p.vendor,'Sanderson'); assert.equal(p.handle,handle); assert.equal(p.status,'active');
+ assert(Array.isArray(p.images));
+ for(const namespace of ['custom','dwc']) assert.equal(fields.find(m=>m.namespace===namespace&&m.key==='manufacturer_sku')?.value,sku);
+ assert.equal(fields.find(m=>m.namespace==='custom'&&m.key==='real_color_name')?.value,'Breeze Blue');
+}
+const matches = image => /\/DDIW217290_b307(?:_[0-9a-f-]+)?\.jpg(?:\?|$)/i.test(image.src);
+const p = await get();
+const fields = (await api('/metafields.json')).metafields;
+validate(p,fields);
+if(p.images.length) {
+ assert.equal(p.images.length,1,'Product changed: stop, do not replace existing gallery');
+ assert(matches(p.images[0]),'Existing image differs: stop for inspection');
+ save('recheck.json',{ts:new Date().toISOString(),verdict:'PASS',action:'already restored; no write',product:p});
+ console.log('PASS: correct image already present; zero writes');
+ process.exit(0);
+}
+const response = await fetch(vendorUrl,{signal:AbortSignal.timeout(30000)});
+assert(response.ok,'Manufacturer page unavailable');
+const html = await response.text();
+const schemas = [...html.matchAll(/<script[^>]*type=["']application\/ld\+json["'][^>]*>([\s\S]*?)<\/script>/gi)].flatMap(m=>{try{return [JSON.parse(m[1])]}catch{return []}});
+const product = schemas.find(s=>s['@type']==='Product'&&s.sku===sku);
+assert.equal(product?.name,'101 Dalmatians Breeze Blue');
+assert(product.image.includes(source),'Exact manufacturer SKU must explicitly name candidate image');
+const imageResponse = await fetch(source,{signal:AbortSignal.timeout(30000)});
+assert(imageResponse.ok && imageResponse.headers.get('content-type')?.startsWith('image/'));
+const bytes = Buffer.from(await imageResponse.arrayBuffer());
+assert(bytes.length>10000,'Source image suspiciously small');
+const proof = {ts:new Date().toISOString(),ticket:'TK-11453',approval:'Steve: go, following gated single-product restoration recap',product_id:id,sku,source,vendorUrl,manufacturer:product,source_sha256:createHash('sha256').update(bytes).digest('hex'),before:p};
+save('preflight.json',proof);
+fs.writeFileSync(new URL('source.jpg',dir),bytes);
+if(!apply){console.log('PASS: preflight; zero writes');process.exit(0);}
+// Immutable intent written before any mutation. An ambiguous POST must be reconciled by GET, never blindly retried.
+const intent = new URL('intent.json',dir);
+assert(!fs.existsSync(intent),'Previous mutation intent exists: reconcile it before any retry');
+const current = await get(); validate(current,fields); assert.equal(current.images.length,0,'Product gained images: stop');
+fs.writeFileSync(intent,JSON.stringify({...proof,rollback:'Restore prior empty gallery by deleting ONLY the created image ID recorded in result.json after identity recheck; never replace the whole product.'},null,2)+'\n',{flag:'wx'});
+const created = (await api('/images.json','POST',{image:{src:source,position:1,alt:'101 Dalmatians Breeze Blue wallpaper — Sanderson'}})).image;
+assert(created?.id,'Image attachment response missing id');
+save('result.json',{ts:new Date().toISOString(),image:created,rollback:{method:'DELETE',url:base+`/images/${created.id}.json`,preconditions:{product_id:id,image_id:created.id,source_pattern:'DDIW217290_b307',prior_images:[]}}});
+let after;
+for(let attempt=0;attempt<6;attempt++) {
+ after=await get();
+ if(after.images.some(im=>im.id===created.id))break;
+ await new Promise(r=>setTimeout(r,2000));
+}
+validate(after,fields);
+assert.equal(after.images.length,1); assert.equal(after.images[0].id,created.id); assert(matches(after.images[0]));
+save('after.json',{ts:new Date().toISOString(),verdict:'PASS',product:after});
+console.log(JSON.stringify({verdict:'PASS',product_id:id,image_id:created.id,images:after.images.length,src:created.src}));
diff --git a/verification/TK-11453/result.json b/verification/TK-11453/result.json
new file mode 100644
index 0000000..95a76dc
--- /dev/null
+++ b/verification/TK-11453/result.json
@@ -0,0 +1,26 @@
+{
+ "ts": "2026-09-11T15:19:46.620Z",
+ "image": {
+ "id": 38069312749619,
+ "alt": "101 Dalmatians Breeze Blue wallpaper — Sanderson",
+ "position": 1,
+ "product_id": 7899582201907,
+ "created_at": "2026-09-11T08:19:46-07:00",
+ "updated_at": "2026-09-11T08:19:46-07:00",
+ "admin_graphql_api_id": "gid://shopify/MediaImage/28904884338739",
+ "width": 1366,
+ "height": 1366,
+ "src": "https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DDIW217290_b307.jpg?v=1789139986",
+ "variant_ids": []
+ },
+ "rollback": {
+ "method": "DELETE",
+ "url": "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10/products/7899582201907/images/38069312749619.json",
+ "preconditions": {
+ "product_id": 7899582201907,
+ "image_id": 38069312749619,
+ "source_pattern": "DDIW217290_b307",
+ "prior_images": []
+ }
+ }
+}
diff --git a/verification/TK-11453/source.jpg b/verification/TK-11453/source.jpg
new file mode 100644
index 0000000..84f663e
Binary files /dev/null and b/verification/TK-11453/source.jpg differ
diff --git a/verification/TK-11453/storefront.png b/verification/TK-11453/storefront.png
new file mode 100644
index 0000000..c4d4e44
Binary files /dev/null and b/verification/TK-11453/storefront.png differ
← 04658ec auto-data-snapshot: 2026-09-11T08:16:47 (5 data files) — scr
·
back to Designerwallcoverings
·
auto-data-snapshot: 2026-09-11T08:57:34 (1 data files) — ver af2c060 →