← back to Tk10640 Redirect Prune
TK-10653: applied 495-row reversible canary batch (195 repoint + 300 prune), count 100k->99.7k, 0 errors
a94744d3f792ca8c0515dee388c69ada1663ee76 · 2026-08-20 00:09:04 -0700 · Steve Abrams
Files touched
M apply-remediation.mjsA rebuild-done-from-live.mjs
Diff
commit a94744d3f792ca8c0515dee388c69ada1663ee76
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Aug 20 00:09:04 2026 -0700
TK-10653: applied 495-row reversible canary batch (195 repoint + 300 prune), count 100k->99.7k, 0 errors
---
apply-remediation.mjs | 3 ++-
rebuild-done-from-live.mjs | 29 +++++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/apply-remediation.mjs b/apply-remediation.mjs
index 707a3fa..9563d6e 100644
--- a/apply-remediation.mjs
+++ b/apply-remediation.mjs
@@ -36,7 +36,8 @@ const PBH=`query($h:String!){ productByHandle(handle:$h){ status onlineStoreUrl
const handleOf=t=>(t||'').replace(/^\/products\//,'').split('?')[0].split('#')[0];
async function liveTarget(id){ const d=await gql(REDIR,{id}); return d.urlRedirect? d.urlRedirect.target : null; }
async function isLiveProduct(target){ if(!/^\/products\//.test(target||'')) return false; const d=await gql(PBH,{h:handleOf(target)}); const p=d.productByHandle; return !!(p && p.status==='ACTIVE' && p.onlineStoreUrl); }
-const rows=readFileSync(`${HOME}/Projects/tk10640-redirect-prune/data/full-scan/remediation-map.jsonl`,'utf8').trim().split('\n').filter(Boolean).map(JSON.parse)
+const MAP=(process.argv.find(a=>a.startsWith('--map='))||'').split('=')[1]||`${HOME}/Projects/tk10640-redirect-prune/data/full-scan/remediation-map.jsonl`;
+const rows=readFileSync(MAP,'utf8').trim().split('\n').filter(Boolean).map(JSON.parse)
.filter(r=> ONLY? r.action===ONLY : true);
let scanned=0,repointed=0,pruned=0,skipped_live=0,skipped_stale=0,err=0,writes=0;
for(const r of rows){
diff --git a/rebuild-done-from-live.mjs b/rebuild-done-from-live.mjs
new file mode 100644
index 0000000..dbd2448
--- /dev/null
+++ b/rebuild-done-from-live.mjs
@@ -0,0 +1,29 @@
+// TK-10653 — RECOVERY: rebuild done-remediation.jsonl from LIVE Shopify truth.
+// For every REPOINT row in remediation-map, read the redirect's current live target by id.
+// If it already equals new_target -> it was applied; write a {repointed} done-line.
+// This reconstructs the authoritative applied-set after the local done-log was corrupted.
+// READ-ONLY on Shopify (only urlRedirect(id) reads); rewrites the LOCAL done-log.
+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 rows=readFileSync(`${HOME}/Projects/tk10640-redirect-prune/data/full-scan/remediation-map.jsonl`,'utf8').trim().split('\n').filter(Boolean).map(JSON.parse);
+const reps=rows.filter(r=>r.action==='REPOINT');
+const out=[]; let applied=0, notyet=0, i=0;
+for(const r of reps){
+ const d=await gql(`query($id:ID!){ urlRedirect(id:$id){ target } }`,{id:r.id});
+ const cur=d.urlRedirect? d.urlRedirect.target : null;
+ if(cur===r.new_target){ out.push(JSON.stringify({id:r.id,path:r.path,repointed:r.new_target})); applied++; }
+ else notyet++;
+ if(++i%500===0) process.stderr.write(` ${i}/${reps.length} applied=${applied} notyet=${notyet}\n`);
+}
+writeFileSync(`${HOME}/Projects/tk10640-redirect-prune/data/full-scan/done-remediation.jsonl`, out.join('\n')+(out.length?'\n':''));
+console.log(JSON.stringify({repoint_rows:reps.length, live_applied_repoints:applied, not_applied:notyet},null,2));
← 3b7f6f2 TK-10653: write-time freshness guard on apply + read-only fr
·
back to Tk10640 Redirect Prune
·
TK-10653: demote 193 low-confidence repoints to prune; rebui 96720ac →