← back to Gmc Titlefix
TK-11448: archive 33 vendor-discontinued products (Shopify + FileMaker), verified
e42e577d2e54388be8196e3fe969292bbe47e043 · 2026-09-11 12:17:38 -0700 · Steve
Steve approved in-session: 'if not on mfr website. archive it', scope
Shopify + FileMaker discontinued.
Executed, canary-first, with independent verification at every step:
- Shopify: 33 ACTIVE -> ARCHIVED. Canary 3 verified by re-read before the
remaining 30. Exhaustive re-read: 33/33 ARCHIVED. 33 undo rows ledgered.
- FileMaker: 105 WALLPAPER rows stamped Date Discontinued=09/11/2026 on rows
where it was blank; rows already dated are skipped, never overwritten.
Live canary verified against an UNWRITTEN control that stayed blank, proving
the write was targeted. Exhaustive re-read: 105/105 dated, 0 blank,
0 unreadable. 105 undo rows ledgered.
- WRITE-2 (close open sample order) was a measured no-op: 0 open orders.
Caught in my own code first: the FM survey defaulted an unreadable client
response to [] and reported 0 rows for all 33 — a false zero indistinguishable
from 'nothing to do'. Replaced with a hard shape assertion that throws.
The client returns {records,dataInfo}, not {response:{data}}.
Fix plan reduced 19 -> 17: Sandberg Oscar grey and Kimono green are gone from
the vendor too and were archived instead of repaired.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JwXCqw4PdXfTY729wX8BFw
Files touched
M data/tk11448-remediation-plan.jsonA tk11448-apply-fm-disco.mjsA tk11448-fm-survey.mjs
Diff
commit e42e577d2e54388be8196e3fe969292bbe47e043
Author: Steve <steve@designerwallcoverings.com>
Date: Fri Sep 11 12:17:38 2026 -0700
TK-11448: archive 33 vendor-discontinued products (Shopify + FileMaker), verified
Steve approved in-session: 'if not on mfr website. archive it', scope
Shopify + FileMaker discontinued.
Executed, canary-first, with independent verification at every step:
- Shopify: 33 ACTIVE -> ARCHIVED. Canary 3 verified by re-read before the
remaining 30. Exhaustive re-read: 33/33 ARCHIVED. 33 undo rows ledgered.
- FileMaker: 105 WALLPAPER rows stamped Date Discontinued=09/11/2026 on rows
where it was blank; rows already dated are skipped, never overwritten.
Live canary verified against an UNWRITTEN control that stayed blank, proving
the write was targeted. Exhaustive re-read: 105/105 dated, 0 blank,
0 unreadable. 105 undo rows ledgered.
- WRITE-2 (close open sample order) was a measured no-op: 0 open orders.
Caught in my own code first: the FM survey defaulted an unreadable client
response to [] and reported 0 rows for all 33 — a false zero indistinguishable
from 'nothing to do'. Replaced with a hard shape assertion that throws.
The client returns {records,dataInfo}, not {response:{data}}.
Fix plan reduced 19 -> 17: Sandberg Oscar grey and Kimono green are gone from
the vendor too and were archived instead of repaired.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JwXCqw4PdXfTY729wX8BFw
---
data/tk11448-remediation-plan.json | 31 ++++---------------------
tk11448-apply-fm-disco.mjs | 47 ++++++++++++++++++++++++++++++++++++++
tk11448-fm-survey.mjs | 46 +++++++++++++++++++++++++++++++++++++
3 files changed, 97 insertions(+), 27 deletions(-)
diff --git a/data/tk11448-remediation-plan.json b/data/tk11448-remediation-plan.json
index c5833e9..9f9f3b8 100644
--- a/data/tk11448-remediation-plan.json
+++ b/data/tk11448-remediation-plan.json
@@ -1,10 +1,10 @@
{
"ticket": "TK-11448",
"built_at": "2026-09-11T18:29:12.922Z",
- "blast_radius": 19,
+ "blast_radius": 17,
"tally": {
"ADD_REAL_IMAGE_AND_FEATURE": 11,
- "REORDER_FEATURED": 8
+ "REORDER_FEATURED": 6
},
"gated": true,
"fired": false,
@@ -174,30 +174,6 @@
"undo": "delete the created media id (recorded per row) — restores the prior featured image",
"spend": "$0 — Shopify-hosted upload from an existing vendor CDN URL"
},
- {
- "handle": "dwss-71022",
- "vendor": "Sandberg",
- "title": "Oscar grey Wallcovering | Sandberg",
- "action": "REORDER_FEATURED",
- "before_featured": "https://cdn.shopify.com/s/files/1/0015/4117/7456/products/221-21_image2.png?v=1646099675",
- "after_featured": "https://cdn.shopify.com/s/files/1/0015/4117/7456/products/221-21_image1.jpg?v=1646099675",
- "after_px": "800x800",
- "shopify_op": "productReorderMedia (promote existing media to position 1)",
- "undo": "productReorderMedia back to the recorded prior order",
- "spend": "$0 — no upload, image already on the product"
- },
- {
- "handle": "dwss-71076",
- "vendor": "Sandberg",
- "title": "Kimono green Wallcovering | Sandberg",
- "action": "REORDER_FEATURED",
- "before_featured": "https://cdn.shopify.com/s/files/1/0015/4117/7456/products/238-38_image2.png?v=1646100218",
- "after_featured": "https://cdn.shopify.com/s/files/1/0015/4117/7456/products/238-38_image1.jpg?v=1646100218",
- "after_px": "800x800",
- "shopify_op": "productReorderMedia (promote existing media to position 1)",
- "undo": "productReorderMedia back to the recorded prior order",
- "spend": "$0 — no upload, image already on the product"
- },
{
"handle": "dwss-71269",
"vendor": "Sandberg",
@@ -270,5 +246,6 @@
"undo": "productReorderMedia back to the recorded prior order",
"spend": "$0 — no upload, image already on the product"
}
- ]
+ ],
+ "note": "2026-09-11: dwss-71022 (Oscar grey) and dwss-71076 (Kimono green) REMOVED from the fix set — both confirmed absent from sandbergwallpaper.com and archived instead under TK-11448 archive plan."
}
\ No newline at end of file
diff --git a/tk11448-apply-fm-disco.mjs b/tk11448-apply-fm-disco.mjs
new file mode 100644
index 0000000..63ffcac
--- /dev/null
+++ b/tk11448-apply-fm-disco.mjs
@@ -0,0 +1,47 @@
+#!/usr/bin/env node
+/** TK-11448 — stamp `Date Discontinued` on the FileMaker WALLPAPER rows for the 33 archived
+ * products (Steve approved Shopify + FileMaker, 2026-09-11).
+ * Follows the discontinued-agent contract: WRITE-1 only (Date Discontinued = today MM/DD/YYYY)
+ * on rows where it is currently BLANK; rows already dated are skipped, never overwritten.
+ * WRITE-2 (close open sample order) is a no-op here — the survey measured 0 open orders.
+ * DRY-RUN BY DEFAULT (the fm client itself defaults dryRun:true). --apply commits.
+ * Every row's prior value is ledgered BEFORE the write; undo = set the field back to ''. */
+import {findRecords,updateRecord} from '/Users/macstudio3/Projects/filemaker-mcp/src/fm-client.js';
+import fs from 'fs';
+const DB='WALLPAPER', LAY='REPORT ON SAMPLES ORDERED';
+const APPLY=process.argv.includes('--apply');
+const CAN=(()=>{const i=process.argv.indexOf('--canary');return i>0?+process.argv[i+1]:0;})();
+const d=new Date(); const TODAY=`${String(d.getMonth()+1).padStart(2,'0')}/${String(d.getDate()).padStart(2,'0')}/${d.getFullYear()}`;
+const survey=JSON.parse(fs.readFileSync('data/tk11448-fm-survey.json','utf8'));
+let subjects=survey.rows.filter(r=>r.blank_disco>0);
+if(CAN) subjects=subjects.slice(0,CAN);
+console.log(`${APPLY?'APPLY':'DRY-RUN'} | Date Discontinued = ${TODAY} | products ${subjects.length}`);
+const led=APPLY?fs.createWriteStream('data/tk11448-fm-ledger.jsonl',{flags:'a'}):null;
+let wrote=0,skipped=0,failed=0,notMeasured=0;
+for(const s of subjects){
+ let recs;
+ try{
+ const r=await findRecords(DB,LAY,[{'combo sku':`==${s.combo}`}],{limit:200});
+ if(!r||!Array.isArray(r.records)) throw new Error('UNEXPECTED_SHAPE');
+ recs=r.records;
+ }catch(e){ console.log(' NOT_MEASURED',s.handle,String(e).slice(0,80)); notMeasured++; continue; }
+ for(const rec of recs){
+ const prior=String(rec.fieldData['Date Discontinued']||'').trim();
+ if(prior){ skipped++; continue; } // never overwrite an existing date
+ try{
+ const res=await updateRecord(DB,LAY,rec.recordId,{'Date Discontinued':TODAY},{dryRun:!APPLY});
+ if(APPLY){
+ led.write(JSON.stringify({ts:new Date().toISOString(),handle:s.handle,combo:s.combo,
+ recordId:rec.recordId,field:'Date Discontinued',prior_value:'',new_value:TODAY,
+ undo:`updateRecord(WALLPAPER,'${LAY}',${rec.recordId},{'Date Discontinued':''})`})+'\n');
+ }
+ wrote++;
+ }catch(e){ console.log(' ERR',s.handle,rec.recordId,String(e).slice(0,90)); failed++; }
+ await new Promise(z=>setTimeout(z,200));
+ }
+ console.log(` ${APPLY?'stamped':'would stamp'} ${s.handle} (${s.combo}) rows=${recs.length}`);
+}
+if(led) led.end();
+console.log(`\n${APPLY?'WROTE':'WOULD WRITE'} ${wrote} | skipped(already dated) ${skipped} | failed ${failed} | NOT_MEASURED ${notMeasured}`);
+if(!APPLY) console.log('DRY-RUN ONLY — nothing committed. Re-run with --apply.');
+else console.log('ledger -> data/tk11448-fm-ledger.jsonl');
diff --git a/tk11448-fm-survey.mjs b/tk11448-fm-survey.mjs
new file mode 100644
index 0000000..6d04a61
--- /dev/null
+++ b/tk11448-fm-survey.mjs
@@ -0,0 +1,46 @@
+#!/usr/bin/env node
+/** TK-11448 READ-ONLY FileMaker survey for the 33 archive products.
+ * Joins on `combo sku` (exact: handle dwrw-75513 -> DWRW75513), NOT the `Mfr Pattern` word-match,
+ * which can over-match a neighbouring SKU. Reports per product: rows found, how many already have
+ * Date Discontinued, how many are blank (the WRITE-1 set), and how many are OPEN sample orders
+ * (the WRITE-2 set per the discontinued-agent contract). Writes nothing. */
+import {findRecords} from '/Users/macstudio3/Projects/filemaker-mcp/src/fm-client.js';
+import fs from 'fs';
+const DB='WALLPAPER', LAY='REPORT ON SAMPLES ORDERED';
+const plan=JSON.parse(fs.readFileSync('data/tk11448-archive-plan.json','utf8')).rows.filter(r=>r.verdict==='ARCHIVE');
+const out=[]; let totRows=0,totBlank=0,totDated=0,totOpen=0,notMeasured=0;
+for(const p of plan){
+ const combo=p.handle.replace(/-/g,'').toUpperCase();
+ const rec={handle:p.handle,combo,mfr_sku:p.mfr_sku,title:p.title};
+ try{
+ const r=await findRecords(DB,LAY,[{'combo sku':`==${combo}`}],{limit:200});
+ // HARD SHAPE ASSERTION — never default an unreadable response to []. A silent [] is
+ // indistinguishable from "no rows" and is exactly how a false zero gets reported as done.
+ if(!r || !Array.isArray(r.records)) throw new Error('UNEXPECTED_SHAPE keys='+Object.keys(r||{}).join(','));
+ const rows=r.records;
+ rec.rows=rows.length;
+ rec.blank_disco=rows.filter(x=>!String(x.fieldData['Date Discontinued']||'').trim()).length;
+ rec.already_disco=rows.length-rec.blank_disco;
+ rec.open_orders=rows.filter(x=>{const f=x.fieldData;
+ return (String(f['account']||'').trim()||String(f['Clients::Company']||'').trim())
+ && String(f['Date Sample Request printed for vendor']||'').trim()
+ && !String(f['Date WP Sample Sent']||'').trim();}).length;
+ rec.recordIds=rows.map(x=>x.recordId);
+ rec.vid=[...new Set(rows.map(x=>x.fieldData['vid']))].join(',');
+ totRows+=rec.rows; totBlank+=rec.blank_disco; totDated+=rec.already_disco; totOpen+=rec.open_orders;
+ }catch(e){
+ const msg=String(e).slice(0,90);
+ if(/401|no records|not found|404/i.test(msg)){ rec.rows=0; rec.blank_disco=0; rec.already_disco=0; rec.open_orders=0; rec.note='no FM rows'; }
+ else { rec.status='NOT_MEASURED'; rec.err=msg; notMeasured++; }
+ }
+ out.push(rec);
+ console.log(' ',(rec.status||'ok').padEnd(13),p.handle,combo.padEnd(11),'rows='+String(rec.rows??'?').padStart(3),
+ 'blank='+String(rec.blank_disco??'?').padStart(3),'dated='+String(rec.already_disco??'?').padStart(3),
+ 'open='+String(rec.open_orders??'?').padStart(2),'|',p.title.slice(0,28));
+ await new Promise(z=>setTimeout(z,250));
+}
+console.log(`\n=== population ${plan.length} | NOT_MEASURED ${notMeasured} ===`);
+console.log(`FM rows total ${totRows} | WRITE-1 set (blank Date Discontinued) ${totBlank} | already dated ${totDated} | WRITE-2 open sample orders ${totOpen}`);
+fs.writeFileSync('data/tk11448-fm-survey.json',JSON.stringify({ticket:'TK-11448',checked_at:new Date().toISOString(),
+ population:plan.length,not_measured:notMeasured,total_rows:totRows,write1_blank:totBlank,already_dated:totDated,write2_open:totOpen,rows:out},null,2));
+console.log('-> data/tk11448-fm-survey.json');
← 3e98b29 auto-data-snapshot: 2026-09-11T12:03:30 (3 data files) — dat
·
back to Gmc Titlefix
·
5x sweep 1: fix the storefront probe — redirect:follow measu c0bbc10 →