← back to Wallco Ai
restore-verified-drunk-animals: per-image gemma3 re-verify + single-row republish of Gemini-cap false-unpublishes
dc1fa177a377be61aca24ecfac80421441148303 · 2026-06-09 14:52:14 -0700 · Steve
Files touched
A scripts/restore-verified-drunk-animals.js
Diff
commit dc1fa177a377be61aca24ecfac80421441148303
Author: Steve <steve@designerwallcoverings.com>
Date: Tue Jun 9 14:52:14 2026 -0700
restore-verified-drunk-animals: per-image gemma3 re-verify + single-row republish of Gemini-cap false-unpublishes
---
scripts/restore-verified-drunk-animals.js | 79 +++++++++++++++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/scripts/restore-verified-drunk-animals.js b/scripts/restore-verified-drunk-animals.js
new file mode 100644
index 0000000..9c100c3
--- /dev/null
+++ b/scripts/restore-verified-drunk-animals.js
@@ -0,0 +1,79 @@
+#!/usr/bin/env node
+// Restore the drunk-animals that the Gemini-cap fail-closed cascade unpublished —
+// but ONLY after re-verifying each image via the (now-live) local gemma3 vision
+// fallback. Each republish is single-row and backed by that design's own vision
+// verdict — no blanket verdict overwrite. Gemini is capped, so verdicts come from
+// gemma3 (clamped: OK or NEEDS REVIEW, never a destructive BLOCK from a local model).
+//
+// node scripts/restore-verified-drunk-animals.js # dry run (verify only)
+// node scripts/restore-verified-drunk-animals.js --apply # verify + republish
+'use strict';
+const { execSync, execFileSync } = require('child_process');
+const fs = require('fs');
+const path = require('path');
+
+const ROOT = path.join(__dirname, '..');
+const PSQL = '/opt/homebrew/opt/postgresql@14/bin/psql';
+const APPLY = process.argv.includes('--apply');
+const LOG = path.join(ROOT, 'data/logs/restore-verified-drunk-animals.log');
+const log = (m) => { const line = `${new Date().toISOString()} ${m}`; console.log(line); try { fs.appendFileSync(LOG, line + '\n'); } catch {} };
+
+function psql(sql) {
+ return execFileSync(PSQL, ['-U', 'stevestudio2', '-d', 'dw_unified', '-tA', '-F', '|', '-c', sql], { encoding: 'utf8' });
+}
+
+// the cohort: unpublished drunk-animals carrying the sweep-trigger verdict
+const rows = psql(`
+ SELECT id, COALESCE(local_path,'')
+ FROM all_designs
+ WHERE category='drunk-animals' AND COALESCE(is_published,false)=false AND COALESCE(user_removed,false)=false
+ AND (settlement_verdict LIKE 'REVIEW-VISION-ERROR%' OR settlement_verdict='BLOCK' OR settlement_verdict IS NULL)
+ ORDER BY id;`).trim().split('\n').filter(Boolean).map(l => {
+ const [id, lp] = l.split('|'); return { id: +id, lp, title: 'drunk animal wallpaper' };
+});
+
+log(`cohort: ${rows.length} designs to re-verify (apply=${APPLY})`);
+let pub = 0, review = 0, blocked = 0, nofile = 0, gateskip = 0, i = 0;
+
+const MAX = +process.env.MAX || 0; // 0 = all; >0 = test cap
+for (const d of rows) {
+ i++;
+ if (MAX && i > MAX) { log(`stopping at MAX=${MAX}`); break; }
+ // resolve image path
+ let img = d.lp && fs.existsSync(d.lp) ? d.lp : path.join(ROOT, 'data/generated', path.basename(d.lp || ''));
+ if (!d.lp || !fs.existsSync(img)) { nofile++; log(`[${i}/${rows.length}] #${d.id} SKIP — image not on disk`); continue; }
+
+ // re-verify via the vision check (Gemini capped → gemma3 fallback)
+ let verdict = 'ERROR';
+ try {
+ const out = execFileSync('node', [path.join(ROOT, 'scripts/settlement_postgen_vision_check.js'), img, d.title],
+ { cwd: ROOT, encoding: 'utf8', timeout: 120000, env: process.env });
+ const m = out.match(/VERDICT:\s*(BLOCK|NEEDS REVIEW|OK)/);
+ verdict = m ? m[1] : 'ERROR';
+ } catch (e) {
+ // exit code 2 = BLOCK; otherwise capture
+ const out = `${e.stdout || ''}${e.stderr || ''}`;
+ const m = out.match(/VERDICT:\s*(BLOCK|NEEDS REVIEW|OK)/);
+ verdict = m ? m[1] : 'ERROR';
+ }
+
+ if (verdict === 'BLOCK') { blocked++; log(`[${i}/${rows.length}] #${d.id} BLOCK — left unpublished`); continue; }
+ if (verdict === 'ERROR') { blocked++; log(`[${i}/${rows.length}] #${d.id} vision ERROR — left unpublished`); continue; }
+
+ const norm = verdict === 'OK' ? 'OK' : 'NEEDS_REVIEW';
+ if (!APPLY) { (norm === 'OK' ? pub++ : review++); log(`[${i}/${rows.length}] #${d.id} ${verdict} (dry-run, would republish)`); continue; }
+
+ // single-row republish, backed by THIS design's verdict; SQL publish-gate still adjudicates the prompt
+ try {
+ execFileSync(PSQL, ['-U', 'stevestudio2', '-d', 'dw_unified', '-v', 'ON_ERROR_STOP=1', '-c',
+ `UPDATE all_designs SET is_published=true, settlement_verdict='${norm}', ` +
+ `notes=COALESCE(notes,'') || ' | RESTORED 2026-06-09 after gemma3 re-verify=${verdict}; was Gemini-cap false-unpublish' ` +
+ `WHERE id=${d.id};`], { encoding: 'utf8' });
+ (norm === 'OK' ? pub++ : review++);
+ log(`[${i}/${rows.length}] #${d.id} ${verdict} → republished`);
+ } catch (e) {
+ gateskip++; log(`[${i}/${rows.length}] #${d.id} ${verdict} but SQL publish-gate blocked (real prompt violation) — left down`);
+ }
+}
+
+log(`DONE — republished(OK):${pub} republished(NEEDS_REVIEW):${review} left-blocked:${blocked} sql-gate-skip:${gateskip} no-file:${nofile}`);
← a259466 geometric pilot: 19/20 generated (57711-57750), settlement O
·
back to Wallco Ai
·
cactus scale-sample: 28 gens, seam-PASS 76-90% per window vs e3ccb0e →