← back to Designerwallcoverings
TK-11515: archive 1,281 dead-404 DWPP duplicate products (Option 1, reversible)
299aff0d2ce9c27888a83bbda9312f02ea043dcd · 2026-09-13 09:23:27 -0700 · Steve Abrams
Root cause: duplicate products where the FULL per-yard twin was left ACTIVE-but-
unpublished (published_at=null) while a sample-only twin got published → 1,281
'ACTIVE 404's. Guarded executor (active + published_at=null only) archives them;
storefront went 404 → 302-home (benign). Fully reversible via --rollback + undo map.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DyhN9EFxZP1ietHceDCTVE
Files touched
M scripts/tk11515-archive-dead404.mjs
Diff
commit 299aff0d2ce9c27888a83bbda9312f02ea043dcd
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sun Sep 13 09:23:27 2026 -0700
TK-11515: archive 1,281 dead-404 DWPP duplicate products (Option 1, reversible)
Root cause: duplicate products where the FULL per-yard twin was left ACTIVE-but-
unpublished (published_at=null) while a sample-only twin got published → 1,281
'ACTIVE 404's. Guarded executor (active + published_at=null only) archives them;
storefront went 404 → 302-home (benign). Fully reversible via --rollback + undo map.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DyhN9EFxZP1ietHceDCTVE
---
scripts/tk11515-archive-dead404.mjs | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/scripts/tk11515-archive-dead404.mjs b/scripts/tk11515-archive-dead404.mjs
index dd6a577..94c60a2 100644
--- a/scripts/tk11515-archive-dead404.mjs
+++ b/scripts/tk11515-archive-dead404.mjs
@@ -33,6 +33,8 @@ const APPLY = process.argv.includes('--apply');
const ROLLBACK = process.argv.includes('--rollback');
const canIdx = process.argv.indexOf('--canary');
const CANARY = canIdx >= 0 ? parseInt(process.argv[canIdx + 1], 10) : 0;
+const batIdx = process.argv.indexOf('--batch');
+const BATCH = batIdx >= 0 ? parseInt(process.argv[batIdx + 1], 10) : 0;
const sleep = ms => new Promise(r => setTimeout(r, ms));
@@ -110,13 +112,14 @@ if (!APPLY) {
process.exit(0);
}
-// APPLY path
-let targets = plan.filter(p => p.verdict === 'ARCHIVE_OK' && p.product_id);
-if (CANARY > 0) targets = targets.slice(0, CANARY);
-console.log(`APPLY: archiving ${targets.length} products${CANARY ? ` (CANARY ${CANARY})` : ''}…`);
-
+// APPLY path — load undo first so we can skip already-archived (resumable batches)
const undo = existsSync(UNDO) ? JSON.parse(readFileSync(UNDO, 'utf8')) : [];
const undoSeen = new Set(undo.map(u => u.product_id));
+let targets = plan.filter(p => p.verdict === 'ARCHIVE_OK' && p.product_id && !undoSeen.has(p.product_id));
+const remaining = targets.length;
+if (BATCH > 0) targets = targets.slice(0, BATCH);
+else if (CANARY > 0) targets = targets.slice(0, CANARY);
+console.log(`APPLY: ${remaining} remaining un-archived; this run = ${targets.length}${BATCH ? ` (BATCH ${BATCH})` : CANARY ? ` (CANARY ${CANARY})` : ' (ALL)'}…`);
let archived = 0, failed = 0;
for (const t of targets) {
const r = await rest(`/products/${t.product_id}.json`, { method: 'PUT', body: { product: { id: t.product_id, status: 'archived' } } });
← d189a70 auto-data-snapshot: 2026-09-13T09:13:35 (3 data files) — scr
·
back to Designerwallcoverings
·
TK-11076: Hollywood colorway retag allow-list (282 clean) + 0c45db2 →