[object Object]

← back to Dw Yolo Loop

fence-strip APPLY (c53): 60/60 code-fence leaks stripped (Steve-authorized)

f488a4e3267320041517e32c4bad58f1dc6d8171 · 2026-06-16 22:39:00 -0700 · Steve Abrams

Applied the officer-CONFIRMED fix: 60 ACTIVE products (Kravet 49/Scalamandre 8/
Graduate 2/Thibaut 1) had a leaked leading markdown code-fence in body_html. Per
product: re-fetched fresh, re-ran guards (leading-fence present, unwrap changes it,
non-empty + no banned word), set descriptionHtml=cleaned + seo.description=regen.
60 stripped, 0 skipped, 0 failed. Rollback (60 old bodies) saved to
yolo-queue/fence-strip-ROLLBACK-2026-06-16.json. Verified live: herb-garden +
all-over-leopard now fence-free w/ clean body + seo. $0 (Shopify Admin API).

Files touched

Diff

commit f488a4e3267320041517e32c4bad58f1dc6d8171
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Jun 16 22:39:00 2026 -0700

    fence-strip APPLY (c53): 60/60 code-fence leaks stripped (Steve-authorized)
    
    Applied the officer-CONFIRMED fix: 60 ACTIVE products (Kravet 49/Scalamandre 8/
    Graduate 2/Thibaut 1) had a leaked leading markdown code-fence in body_html. Per
    product: re-fetched fresh, re-ran guards (leading-fence present, unwrap changes it,
    non-empty + no banned word), set descriptionHtml=cleaned + seo.description=regen.
    60 stripped, 0 skipped, 0 failed. Rollback (60 old bodies) saved to
    yolo-queue/fence-strip-ROLLBACK-2026-06-16.json. Verified live: herb-garden +
    all-over-leopard now fence-free w/ clean body + seo. $0 (Shopify Admin API).
---
 scripts/fence-strip/fence-strip-apply.mjs | 35 +++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/scripts/fence-strip/fence-strip-apply.mjs b/scripts/fence-strip/fence-strip-apply.mjs
new file mode 100644
index 0000000..24a1841
--- /dev/null
+++ b/scripts/fence-strip/fence-strip-apply.mjs
@@ -0,0 +1,35 @@
+// fence-strip-apply (c53) — APPLY the officer-CONFIRMED code-fence-strip to the 60
+// leading-fence-leak products (Steve-authorized 2026-06-16). Per product: re-fetch
+// fresh body, re-run guards (leading fence present, unwrap changes it, post-strip
+// non-empty + no banned word), SAVE old body to rollback, then
+// productUpdate(descriptionHtml=cleaned, seo.description=regen from cleaned).
+import fs from 'fs';
+const T=(fs.readFileSync(process.env.HOME+'/Projects/secrets-manager/.env','utf8').match(/^SHOPIFY_ADMIN_TOKEN=(.+)$/m)||[])[1];
+const API='https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10/graphql.json';
+const sleep=ms=>new Promise(r=>setTimeout(r,ms));
+async function gql(q,v){for(let a=0;a<6;a++){const r=await fetch(API,{method:'POST',headers:{'X-Shopify-Access-Token':T,'Content-Type':'application/json'},body:JSON.stringify({query:q,variables:v||{}})});if(r.status===429){await sleep(2500);continue;}const j=await r.json();if(j.errors&&JSON.stringify(j.errors).match(/THROTTLED/)){await sleep(2500);continue;}return j;}throw new Error('throttled');}
+function unwrap(b){let body=b;body=body.replace(/^\s*```[a-z]*\s*\n?/i,'');body=body.replace(/\n?\s*```\s*$/,'');body=body.replace(/```[a-z]*\s*([\s\S]*?)\s*```/gi,'$1');body=body.replace(/^\s*<code>([\s\S]*?)<\/code>\s*$/i,'$1');return body.trim();}
+const txt=h=>(h||'').replace(/<[^>]+>/g,'').replace(/&[a-z]+;/g,' ').replace(/\s+/g,' ').trim();
+const work=JSON.parse(fs.readFileSync(process.env.HOME+'/.claude/yolo-queue/fence-strip-dryrun-worklist.json','utf8')).filter(i=>i.changed);
+console.log(`apply targets (changed, leading-fence): ${work.length}`);
+const M=`mutation($id:ID!,$html:String!,$seo:String!){productUpdate(input:{id:$id,descriptionHtml:$html,seo:{description:$seo}}){userErrors{message}}}`;
+const rollback=[]; let ok=0,skip=0,fail=0;
+for(const it of work){
+  try{
+    const j=await gql(`{products(first:1,query:"handle:${it.handle}"){nodes{id descriptionHtml}}}`);
+    const p=j.data?.products?.nodes?.[0]; if(!p){skip++;console.log(`  skip(not found): ${it.handle}`);continue;}
+    const old=p.descriptionHtml||'';
+    if(!/^\s*(```|<code>)/i.test(old)){skip++;console.log(`  skip(no leading fence now): ${it.handle}`);continue;}
+    const cleaned=unwrap(old);
+    if(cleaned===old || txt(cleaned).length<3){skip++;console.log(`  skip(no-op/empty): ${it.handle}`);continue;}
+    if(/\bwallpaper\b/i.test(txt(cleaned))){skip++;console.log(`  skip(banned-word surfaced): ${it.handle}`);continue;}
+    const seo=txt(cleaned).slice(0,300);
+    rollback.push({id:p.id,handle:it.handle,old_descriptionHtml:old});
+    const r=await gql(M,{id:p.id,html:cleaned,seo}); const ue=r.data?.productUpdate?.userErrors;
+    if(ue&&ue.length)throw new Error(ue[0].message);
+    ok++; if(ok%15===0)console.log(`  ${ok}...`);
+  }catch(e){fail++;console.log(`  ✗ ${it.handle}: ${e.message.slice(0,70)}`);}
+  await sleep(300);
+}
+fs.writeFileSync(process.env.HOME+'/.claude/yolo-queue/fence-strip-ROLLBACK-2026-06-16.json',JSON.stringify(rollback,null,2));
+console.log(`\nDONE: ${ok} stripped, ${skip} skipped(guard), ${fail} failed. Rollback saved: ${rollback.length}.`);

← 6c53615 fence-strip dry-run: tighten to leading-fence-only per offic  ·  back to Dw Yolo Loop  ·  no-image scan (c54): 50 of 74,441 ACTIVE have no image (0.07 b9c390f →