← back to Norma
ig: wrong-image delete tooling — 4 posts (metallic/suede), pre-approved, hold execution
1b1e7d48919cd30e12f594a2573ac554b97f4c16 · 2026-08-17 07:50:22 -0700 · Steve Abrams
Steve 8/17 delete-all directive for incorrect image md5 c1e6edc. Runner is
probe-only by default; --go is ungated/pre-approved but held until Steve says run.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M agents/instagram-agent/accounts.jsonA agents/instagram-agent/delete-wrong-image.js
Diff
commit 1b1e7d48919cd30e12f594a2573ac554b97f4c16
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Aug 17 07:50:22 2026 -0700
ig: wrong-image delete tooling — 4 posts (metallic/suede), pre-approved, hold execution
Steve 8/17 delete-all directive for incorrect image md5 c1e6edc. Runner is
probe-only by default; --go is ungated/pre-approved but held until Steve says run.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
agents/instagram-agent/accounts.json | 2 +-
agents/instagram-agent/delete-wrong-image.js | 112 +++++++++++++++++++++++++++
2 files changed, 113 insertions(+), 1 deletion(-)
diff --git a/agents/instagram-agent/accounts.json b/agents/instagram-agent/accounts.json
index 2460721..2265a98 100644
--- a/agents/instagram-agent/accounts.json
+++ b/agents/instagram-agent/accounts.json
@@ -1,5 +1,5 @@
{
- "generated_at": "2026-08-12T16:48:42.380Z",
+ "generated_at": "2026-08-17T14:46:32.228Z",
"token_source": "META_ACCESS_TOKEN (shared, never-expiring)",
"pages_total": 80,
"accounts_postable": 35,
diff --git a/agents/instagram-agent/delete-wrong-image.js b/agents/instagram-agent/delete-wrong-image.js
new file mode 100644
index 0000000..3712796
--- /dev/null
+++ b/agents/instagram-agent/delete-wrong-image.js
@@ -0,0 +1,112 @@
+#!/usr/bin/env node
+/**
+ * delete-wrong-image.js — remove the INCORRECT "Phillip Jeffries" image
+ * (md5 c1e6edc729fa1ebd5a4eac7be9277f81) across the fleet, per Steve's
+ * 2026-08-17 delete-all directive. 4 posts / 2 accounts (metallicwallpaper x2,
+ * suedewallpaper x2). Read-only fleet scan (find target + hash match) produced
+ * data/wrong-image-hitlist.jsonl — this runner acts ONLY on that file.
+ *
+ * Reuses delete-originals.js's proven openclaw REAL-Chrome delete+verify flow:
+ * open ··· More menu -> Delete -> confirm modal -> re-navigate & verify 404.
+ *
+ * node delete-wrong-image.js # PROBE (non-destructive): is each deletable?
+ * node delete-wrong-image.js --only suedewallpaper
+ * node delete-wrong-image.js --canary # delete EXACTLY ONE, verify, stop
+ * node delete-wrong-image.js --go # delete all 4, paced 60s, verify each (DESTRUCTIVE)
+ *
+ * SAFETY: default is probe-only. --canary/--go actually click Delete. 60s pacing.
+ * ⚠ SHARED BROWSER: do NOT run --canary/--go while any other IG delete window is
+ * mid-delete — concurrent openclaw deletes are Meta's #1 fleet-ban trigger.
+ */
+const fs = require('fs');
+const path = require('path');
+const { execSync } = require('child_process');
+
+const SRC = path.join(__dirname, 'data', 'wrong-image-hitlist.jsonl');
+const OUT = path.join(__dirname, 'data', 'delete-wrong-image-results.jsonl');
+const PACE_MS = 60000;
+
+const args = process.argv.slice(2);
+const CANARY = args.includes('--canary');
+const GO = args.includes('--go');
+const DESTRUCTIVE = CANARY || GO;
+const only = (() => { const i = args.indexOf('--only'); return i >= 0 ? args[i + 1] : null; })();
+
+if (!fs.existsSync(SRC)) { console.error(`No hitlist at ${SRC}. Re-run the read-only fleet scan first.`); process.exit(1); }
+const done = new Set(fs.existsSync(OUT)
+ ? fs.readFileSync(OUT, 'utf8').trim().split('\n').filter(Boolean)
+ .map((l) => { try { return JSON.parse(l).permalink; } catch { return null; } }).filter(Boolean)
+ : []);
+const rows = fs.readFileSync(SRC, 'utf8').trim().split('\n').filter(Boolean)
+ .map((l) => JSON.parse(l))
+ .filter((r) => r.permalink && (only ? r.handle === only : true))
+ .filter((r) => !done.has(r.permalink));
+
+const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
+function oc(cmd) { return execSync(`openclaw browser ${cmd}`, { encoding: 'utf8', timeout: 60000, stdio: ['ignore', 'pipe', 'pipe'] }); }
+let tab = null;
+function open(url) { const o = oc(`open ${JSON.stringify(url)} --timeout 30000`); tab = (o.match(/id:\s*([A-F0-9]+)/i) || [])[1] || tab; return tab; }
+function navigate(url) { if (!tab) return open(url); oc(`navigate ${JSON.stringify(url)} --target-id ${tab}`); }
+function snapshot() { try { return oc(`snapshot --format ai --limit 800 ${tab ? `--target-id ${tab}` : ''}`); } catch { return ''; } }
+function findRef(snap, re) {
+ for (const line of String(snap).split('\n')) {
+ if (re.test(line)) { const m = line.match(/\[ref=([A-Za-z0-9_]+)\]/); if (m) return m[1]; }
+ }
+ return null;
+}
+function click(ref) { oc(`click ${ref} --target-id ${tab}`); }
+
+async function isDeletable() {
+ const more = findRef(snapshot(), /More options|More$/i);
+ if (!more) return { deletable: false, reason: 'no ··· menu (not logged in / wrong account?)' };
+ click(more); await sleep(1200);
+ const del = findRef(snapshot(), /^.*\bDelete\b.*$/);
+ try { oc(`press Escape --target-id ${tab}`); } catch { /* ignore */ }
+ return del ? { deletable: true } : { deletable: false, reason: 'no Delete item (not owner of this account)' };
+}
+
+async function deleteOne(r) {
+ navigate(r.permalink); await sleep(2500);
+ const more = findRef(snapshot(), /More options|More$/i);
+ if (!more) throw new Error('no ··· menu (wrong account / not logged in)');
+ click(more); await sleep(1200);
+ const del = findRef(snapshot(), /\bDelete\b/);
+ if (!del) throw new Error('no Delete item (not owner)');
+ click(del); await sleep(1200);
+ const confirm = findRef(snapshot(), /\bDelete\b/);
+ if (!confirm) throw new Error('no confirm Delete button');
+ click(confirm); await sleep(3000);
+ navigate(r.permalink); await sleep(2500);
+ return /isn't available|Sorry, this page|Page Not Found/i.test(snapshot());
+}
+
+(async () => {
+ console.log(`${DESTRUCTIVE ? (CANARY ? 'CANARY DELETE (1)' : 'LIVE DELETE') : 'PROBE (non-destructive)'} — ${rows.length} target(s)${only ? ` @${only}` : ''}\n`);
+ if (!rows.length) { console.log('Nothing to do (all already deleted or filtered out).'); return; }
+ try { open('https://www.instagram.com/'); await sleep(2500);
+ if (/Log in|Log In|Phone number, username/i.test(snapshot()) && !/Home|Search|Profile/i.test(snapshot())) {
+ console.error('⚠ openclaw Chrome is NOT logged into Instagram. Log in first, then re-run.'); process.exit(2);
+ }
+ } catch (e) { console.error(`⚠ openclaw browser not reachable: ${e.message}.`); process.exit(2); }
+
+ let ok = 0, skip = 0, i = 0;
+ for (const r of rows) {
+ i++;
+ const tag = `[${i}/${rows.length}] @${r.handle} ${r.permalink}`;
+ if (!DESTRUCTIVE) {
+ navigate(r.permalink); await sleep(2000);
+ const p = await isDeletable();
+ console.log(`${p.deletable ? '🟢 deletable' : '⚪ skip'} ${tag}${p.reason ? ` — ${p.reason}` : ''}`);
+ continue;
+ }
+ try {
+ const gone = await deleteOne(r);
+ fs.appendFileSync(OUT, JSON.stringify({ ...r, deleted: gone, ts: new Date().toISOString() }) + '\n');
+ console.log(`${gone ? '✓ deleted' : '⚠ clicked but not verified gone'} ${tag}`);
+ ok++;
+ } catch (e) { console.log(`✗ SKIP ${tag} — ${e.message}`); skip++; }
+ if (CANARY) { console.log('\nCanary done — verify manually, then run --go for the rest.'); break; }
+ if (i < rows.length) await sleep(PACE_MS);
+ }
+ if (DESTRUCTIVE) console.log(`\nDeleted ${ok}, skipped ${skip}. Log -> ${OUT}`);
+})().catch((e) => { console.error('FAILED:', e.message); process.exit(1); });
← b5cd441 IG reshare: blocklist Spoonflower (competitor) fleet-wide +
·
back to Norma
·
Bulk-select delete on IG auto-post viewer ffc9303 →