← back to Tk10640 Redirect Prune
TK-10653: demote 193 low-confidence repoints to prune; rebuild done-log from live truth (610 applied: 558 repoint+52 prune); re-prune 50 died-after-scan + 2 wrong-product; freshness/target guards; final verify 30/30 -> 200
96720acaa239c946a4c7edf5e4b9ee1d77e34887 · 2026-08-20 00:33:12 -0700 · Steve Abrams
Files touched
A verify-applied-targets.mjs
Diff
commit 96720acaa239c946a4c7edf5e4b9ee1d77e34887
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Aug 20 00:33:12 2026 -0700
TK-10653: demote 193 low-confidence repoints to prune; rebuild done-log from live truth (610 applied: 558 repoint+52 prune); re-prune 50 died-after-scan + 2 wrong-product; freshness/target guards; final verify 30/30 -> 200
---
verify-applied-targets.mjs | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/verify-applied-targets.mjs b/verify-applied-targets.mjs
new file mode 100644
index 0000000..4cea8f1
--- /dev/null
+++ b/verify-applied-targets.mjs
@@ -0,0 +1,28 @@
+// TK-10653 — verify every APPLIED repoint's target is STILL a live ACTIVE+published product.
+// Catalog churn between scan and apply can leave a repoint pointing at a now-dead product
+// (301 fires -> target 404). For each done repoint, re-check productByHandle liveness.
+// Emits data/full-scan/applied-dead-targets.json (rows to re-prune). READ-ONLY.
+import { readFileSync, writeFileSync } from 'node:fs';
+const HOME=process.env.HOME;
+const txt=readFileSync(`${HOME}/Projects/secrets-manager/.env`,'utf8');
+const env={}; for(const l of txt.split('\n')){const m=l.match(/^([A-Z0-9_]+)=(.*)$/); if(m) env[m[1]]=m[2].replace(/^["']|["']$/g,'');}
+const STORE=env.SHOPIFY_STORE_DOMAIN||'designer-laboratory-sandbox.myshopify.com', TOKEN=env.SHOPIFY_FULL_ACCESS_TOKEN, API='2024-10';
+const sleep=ms=>new Promise(r=>setTimeout(r,ms));
+async function gql(q,v={}){for(let a=0;a<12;a++){try{
+ const res=await fetch(`https://${STORE}/admin/api/${API}/graphql.json`,{method:'POST',headers:{'Content-Type':'application/json','X-Shopify-Access-Token':TOKEN},body:JSON.stringify({query:q,variables:v})});
+ const tx=await res.text();let j;try{j=JSON.parse(tx);}catch{await sleep(1200*(a+1));continue;}
+ if(j.errors){if(/THROTTLED/i.test(JSON.stringify(j.errors))){await sleep(1200*(a+1));continue;}throw new Error(JSON.stringify(j.errors));}
+ return j.data;
+}catch(e){if(a<11){await sleep(1200*(a+1));continue;}throw e;}}}
+const applied=readFileSync(`${HOME}/Projects/tk10640-redirect-prune/data/full-scan/done-remediation.jsonl`,'utf8').trim().split('\n').filter(Boolean).map(JSON.parse).filter(x=>x.repointed);
+const dead=[]; let live=0,i=0;
+for(const a of applied){
+ const h=a.repointed.replace('/products/','').split('?')[0].split('#')[0];
+ const d=await gql(`query($h:String!){productByHandle(handle:$h){status onlineStoreUrl}}`,{h});
+ const p=d.productByHandle;
+ if(p&&p.status==='ACTIVE'&&p.onlineStoreUrl) live++;
+ else dead.push({id:a.id,path:a.path,repointed:a.repointed});
+ if(++i%200===0) process.stderr.write(` ${i}/${applied.length} live=${live} dead=${dead.length}\n`);
+}
+writeFileSync(`${HOME}/Projects/tk10640-redirect-prune/data/full-scan/applied-dead-targets.json`, JSON.stringify(dead,null,1));
+console.log(JSON.stringify({applied_repoints:applied.length, target_still_live:live, target_now_dead_reprune:dead.length},null,2));
← a94744d TK-10653: applied 495-row reversible canary batch (195 repoi
·
back to Tk10640 Redirect Prune
·
(newest)