← back to Wallco Ai
scripts/drunk_monkeys_birds_subdued_batch.js
73 lines
#!/usr/bin/env node
/**
* Fire N drunk-monkey/bird/botanical-subdued designs through generate_designs.js.
* Uses the focused prompt builder at drunk_monkeys_birds_subdued_prompts.js.
* Settlement-gate filtered, errors-tolerant (single bad design ≠ batch kill).
*
* Usage: node scripts/drunk_monkeys_birds_subdued_batch.js [N] (default 100)
*
* Output rows land in dw_unified.spoon_all_designs with
* kind='seamless_tile', category='drunk-monkeys-birds-subdued'
* so this batch is separable from the existing 2,687 'drunk-animals' rows.
*/
const { spawnSync } = require('child_process');
const path = require('path');
const fs = require('fs');
const { buildN } = require('./drunk_monkeys_birds_subdued_prompts');
const { checkPrompt } = require('./settlement-gate');
const N = parseInt(process.argv[2] || '100', 10);
const ROOT = path.join(__dirname, '..');
const CATEGORY = 'drunk-monkeys-birds-subdued';
const LOG = `/tmp/dmbs-batch-${new Date().toISOString().replace(/[:.]/g, '-')}.log`;
const t0 = Date.now();
function L(msg) {
const line = `[${new Date().toISOString()}] ${msg}`;
console.log(line);
fs.appendFileSync(LOG, line + '\n');
}
L(`=== drunk-monkeys-birds-subdued batch: firing ${N} designs ===`);
L(`log file: ${LOG}`);
L(`category: ${CATEGORY}`);
const items = buildN(N);
let ok = 0, fail = 0, skipped = 0;
for (let i = 0; i < items.length; i++) {
const item = items[i];
const gate = checkPrompt(item.prompt);
if (gate.verdict !== 'OK') {
L(`[${i+1}/${N}] SKIP (settlement ${gate.verdict}) — ${(gate.reason||'').slice(0,100)}`);
skipped++;
continue;
}
L(`[${i+1}/${N}] palette=${item.palette} animal=${item.animal_summary}`);
const r = spawnSync('node', [
path.join(ROOT, 'scripts', 'generate_designs.js'),
'--n', '1',
'--kind', 'seamless_tile',
'--category', CATEGORY,
'--prompts', item.prompt,
], { cwd: ROOT, encoding: 'utf8', timeout: 240_000 });
if (r.status === 0) {
ok++;
L(` ✓ ok (running: ${ok} ok, ${fail} fail, ${skipped} skip — ${((Date.now()-t0)/60000).toFixed(1)}min elapsed)`);
} else {
fail++;
L(` ✗ FAIL status=${r.status} stderr=${(r.stderr||'').slice(0,140)}`);
}
}
L(`=== batch done: ${ok} ok / ${fail} fail / ${skipped} skipped (${((Date.now()-t0)/60000).toFixed(1)} min) ===`);
// Refresh designs.json + tell wallco-ai server to reload its in-memory grid
L('refreshing designs.json snapshot…');
spawnSync('python3', [path.join(ROOT, 'scripts', 'refresh_designs_snapshot.py')],
{ stdio: 'inherit', cwd: ROOT, timeout: 180_000 });
L('hot-reloading wallco-ai server (local + remote if reachable)…');
spawnSync('curl', ['-sf', '-m', '5', '-X', 'POST', 'http://127.0.0.1:9878/admin/reload-designs'], { stdio: 'inherit', timeout: 10_000 });
process.exit(fail === 0 ? 0 : (ok > 0 ? 0 : 1));