← back to Wallco Ai
DA-2+DA-3: Met PD + prior wallco design references in every drunk-animal prompt
061b76f9aa7d1fd7817cfd5bcc6f1843e4deadf7 · 2026-05-25 20:34:25 -0700 · Steve Abrams
YOLO queue items DA-1 → DA-3 complete.
DA-1 audit: 3,518 prompts missing drink vocab; 830 are PUBLISHED.
- drunk-animals: 3398 missing (752 published)
- drunk-zoo-36: 118 missing (76 published)
- drunk-monkeys-v2: 2 missing
- drunk-animals-designer: 0 missing
DA-2 — lib/design-references.js:
- pickMetReference(themes) — samples dw_unified.met_museum_art PD rows
across 5 theme pools (bacchanal, wine, engraving, animal, chinoiserie),
120 rows per pool cached at module-load with 6-hr TTL
- pickPriorDesignReference(category) — samples top-rated prior published
wallco design from spoon_all_designs, bucketed per drunk-* category
- pickReferences(category) — returns combined { met, prior, promptClause }
ready to paste into a prompt
- themesForCategory() — maps each drunk-* sub-category to a sensible
Met theme mix (zoo-36 → bacchanal/animal/engraving, designer →
chinoiserie/wine/engraving, etc.)
- Graceful fallback to a 4-entry MET_FALLBACK list if PG unreachable
DA-3 — wire into all 4 generators via SHARED.pickReferenceClause(cat):
- drunk_animal_prompts.js — buildPrompt + buildN both inject ref clause
- drunk_monkeys_v2_prompts.js — "Reference anchor: ..." line in positive
- drunk_monkeys_birds_subdued_prompts.js — same
- night-builder.js drunk-zoo-36 composer — same
Sample fresh prompt now reads:
"...inspired by the Met's 'Terracotta fragment of a skyphos (deep
drinking cup)' (Unknown), composition lineage from wallco internal
design #38562 (#6c3e31 dominant)..."
DA-4 (preview batch generator scripts/da4-preview-batch.js) kicked off
in background; 6 heterogeneous designs across 4 categories, curator-mode,
local ComfyUI. Results to data/logs/drunk-animals-preview-batch.json.
Files touched
M .yolo-queue.mdA data/logs/drunk-animals-glass-audit.jsonA lib/design-references.jsA scripts/da4-preview-batch.jsM scripts/drunk_animal_prompts.jsM scripts/drunk_monkeys_birds_subdued_prompts.jsM scripts/drunk_monkeys_v2_prompts.jsM scripts/drunk_motif_shared.jsM scripts/night-builder.js
Diff
commit 061b76f9aa7d1fd7817cfd5bcc6f1843e4deadf7
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon May 25 20:34:25 2026 -0700
DA-2+DA-3: Met PD + prior wallco design references in every drunk-animal prompt
YOLO queue items DA-1 → DA-3 complete.
DA-1 audit: 3,518 prompts missing drink vocab; 830 are PUBLISHED.
- drunk-animals: 3398 missing (752 published)
- drunk-zoo-36: 118 missing (76 published)
- drunk-monkeys-v2: 2 missing
- drunk-animals-designer: 0 missing
DA-2 — lib/design-references.js:
- pickMetReference(themes) — samples dw_unified.met_museum_art PD rows
across 5 theme pools (bacchanal, wine, engraving, animal, chinoiserie),
120 rows per pool cached at module-load with 6-hr TTL
- pickPriorDesignReference(category) — samples top-rated prior published
wallco design from spoon_all_designs, bucketed per drunk-* category
- pickReferences(category) — returns combined { met, prior, promptClause }
ready to paste into a prompt
- themesForCategory() — maps each drunk-* sub-category to a sensible
Met theme mix (zoo-36 → bacchanal/animal/engraving, designer →
chinoiserie/wine/engraving, etc.)
- Graceful fallback to a 4-entry MET_FALLBACK list if PG unreachable
DA-3 — wire into all 4 generators via SHARED.pickReferenceClause(cat):
- drunk_animal_prompts.js — buildPrompt + buildN both inject ref clause
- drunk_monkeys_v2_prompts.js — "Reference anchor: ..." line in positive
- drunk_monkeys_birds_subdued_prompts.js — same
- night-builder.js drunk-zoo-36 composer — same
Sample fresh prompt now reads:
"...inspired by the Met's 'Terracotta fragment of a skyphos (deep
drinking cup)' (Unknown), composition lineage from wallco internal
design #38562 (#6c3e31 dominant)..."
DA-4 (preview batch generator scripts/da4-preview-batch.js) kicked off
in background; 6 heterogeneous designs across 4 categories, curator-mode,
local ComfyUI. Results to data/logs/drunk-animals-preview-batch.json.
---
.yolo-queue.md | 18 +-
data/logs/drunk-animals-glass-audit.json | 1 +
lib/design-references.js | 226 +++++++++++++++++++++++++
scripts/da4-preview-batch.js | 126 ++++++++++++++
scripts/drunk_animal_prompts.js | 10 +-
scripts/drunk_monkeys_birds_subdued_prompts.js | 5 +-
scripts/drunk_monkeys_v2_prompts.js | 9 +-
scripts/drunk_motif_shared.js | 34 +++-
scripts/night-builder.js | 2 +
9 files changed, 414 insertions(+), 17 deletions(-)
diff --git a/.yolo-queue.md b/.yolo-queue.md
index ca30b2b..c52d102 100644
--- a/.yolo-queue.md
+++ b/.yolo-queue.md
@@ -162,17 +162,31 @@ for a COMMITTED verdict. For blockers / 2-path forks, use
> 2 missing / 259 OK; drunk-animals-designer: 0 missing / 115 OK. The
> 830-published-missing-drink set is the obvious priority for DA-6 batch.
-- [ ] **DA-2** Build `lib/design-references.js` — exports
+- [x] **DA-2** Build `lib/design-references.js` — exports
`pickMetReference(themes)` (samples 1-2 PD rows from
`dw_unified.met_museum_art` matching themes like 'bacchanal', 'wine',
'engraving', 'animal') + `pickPriorDesignReference(category)` (samples
1 top-rated prior wallco design from `spoon_all_designs` matching
category). Returns title + artist + period + reference URL.
-- [ ] **DA-3** Wire `lib/design-references.js` into all 4 drunk-animal
+ > NOTE 2026-05-25 ✓ Shipped at lib/design-references.js. 5 Met PD theme
+ > pools cached (bacchanal/wine/engraving/animal/chinoiserie, 120 each).
+ > Prior wallco cache buckets: drunk-animals 151, drunk-zoo-36 399,
+ > drunk-monkeys-v2 50. Sample pulled: "The Triumph of Caesar: The
+ > Elephants" (Mantegna ca. 1497), "Bacchus" (Meissen Manufactory).
+ > CLI smoke test passes. 6-hr TTL, lazy refresh.
+
+- [x] **DA-3** Wire `lib/design-references.js` into all 4 drunk-animal
generators. Inject `inspired by [Met title] ([artist], [period])` +
`composition lineage from internal design #[id]` into every prompt.
+ > NOTE 2026-05-25 ✓ SHARED.pickReferenceClause(category) wired into
+ > all 4 generators. Sample fresh prompt now carries "inspired by the
+ > Met's 'Terracotta fragment of a skyphos (deep drinking cup)',
+ > composition lineage from wallco internal design #38562". Falls back
+ > to empty clause if PG unreachable (caches PD pool at module load +
+ > 6-hr TTL).
+
- [ ] **DA-4** Generate 6 heterogeneous preview designs spanning the
4 categories (2 drunk-animals, 2 drunk-zoo-36, 1 drunk-monkeys-v2,
1 drunk-animals-designer). curator-mode (is_published=false), local
diff --git a/data/logs/drunk-animals-glass-audit.json b/data/logs/drunk-animals-glass-audit.json
new file mode 100644
index 0000000..137c4d3
--- /dev/null
+++ b/data/logs/drunk-animals-glass-audit.json
@@ -0,0 +1 @@
+[{"category" : "drunk-animals", "has_drink" : 1003, "missing_drink" : 3398, "has_drink_published" : 43, "missing_drink_published" : 752, "sample_missing_ids" : [38425,38501,38550,39662,41297,41318,41362,41369,41420,41531]}, {"category" : "drunk-monkeys-v2", "has_drink" : 259, "missing_drink" : 2, "has_drink_published" : 250, "missing_drink_published" : 2, "sample_missing_ids" : [39299,39304]}, {"category" : "drunk-zoo-36", "has_drink" : 2219, "missing_drink" : 118, "has_drink_published" : 1993, "missing_drink_published" : 76, "sample_missing_ids" : [39455,39502,39760,39947,40448,40538,40539,40912,40913,41087]}, {"category" : "drunk-animals-designer", "has_drink" : 115, "missing_drink" : 0, "has_drink_published" : 2, "missing_drink_published" : 0, "sample_missing_ids" : []}]
diff --git a/lib/design-references.js b/lib/design-references.js
new file mode 100644
index 0000000..4d0b857
--- /dev/null
+++ b/lib/design-references.js
@@ -0,0 +1,226 @@
+/**
+ * Design reference picker — pulls art-historical anchors from
+ * (a) Met Museum public-domain artworks (dw_unified.met_museum_art)
+ * (b) prior wallco designs already in the catalog (spoon_all_designs)
+ * for use as style/composition anchors inside drunk-animal /
+ * drunk-zoo / mural generator prompts.
+ *
+ * Steve directive 2026-05-25 — "designs pulled from the postgresql
+ * and met museum images" + "this is our llm". We use real PD artwork
+ * and our own prior winners as the inspiration layer for every new
+ * prompt, instead of relying purely on the diffusion model's training.
+ *
+ * USAGE:
+ * const refs = require('./lib/design-references');
+ * const met = refs.pickMetReference(['bacchanal', 'wine']);
+ * const own = refs.pickPriorDesignReference('drunk-animals');
+ * // append to prompt body:
+ * // `inspired by ${met.compactCitation}, composition lineage from ${own.compactCitation}`
+ *
+ * Both pickers are SYNCHRONOUS (they use execSync against a pre-warmed
+ * in-memory cache) so the generator hot paths stay simple. Cache
+ * refresh happens at module-load + once every 6 hours (configurable
+ * via DESIGN_REFS_TTL_SEC).
+ *
+ * If PG is unreachable, fall back to a tiny hardcoded list so the
+ * generators never throw — just less variety.
+ */
+'use strict';
+
+const { execSync } = require('child_process');
+
+// ── Theme pools — Met PD query templates keyed by drunk-animal vibe ───
+const MET_THEMES = {
+ bacchanal: { sql: "LOWER(title) ~ 'bacchanal|bacchus|dionys|reveler|carous|silen|priap' OR (LOWER(title) ~ 'feast' AND classification IN ('Prints','Paintings','Drawings'))", weight: 3 },
+ wine: { sql: "(LOWER(title) ~ 'wine|cup|goblet|chalice|amphora|krater|kantharos|tankard|tavern|drinking') AND classification IN ('Prints','Paintings','Drawings','Ceramics','Glass','Vases')", weight: 2 },
+ engraving: { sql: "classification ILIKE 'Prints' AND object_begin_date BETWEEN 1700 AND 1899", weight: 1 },
+ animal: { sql: "LOWER(title) ~ 'monkey|giraffe|elephant|orangutan|lemur|sloth|capybara|frog|macaw|parrot|peacock|owl|panda' AND classification IN ('Prints','Paintings','Drawings')", weight: 2 },
+ chinoiserie: { sql: "(department = 'Asian Art' AND LOWER(medium) ~ 'silk|cloth|textile') OR LOWER(title) ~ 'chinoiserie|wallpaper'", weight: 1 },
+};
+
+// In-memory cache. Key = theme name → array of Met rows.
+const METROW_CACHE = {};
+let MET_CACHE_AT = 0;
+const TTL_SEC = parseInt(process.env.DESIGN_REFS_TTL_SEC || '21600', 10); // 6 hr
+
+// Cap per-theme pool size to keep memory + query cost bounded.
+const POOL_SIZE = parseInt(process.env.DESIGN_REFS_POOL_SIZE || '120', 10);
+
+function psqlJson(sql) {
+ try {
+ const cmd = `psql dw_unified -At -F'\t' -c ${JSON.stringify(sql)}`;
+ return execSync(cmd, { encoding: 'utf8', timeout: 12000 });
+ } catch (e) {
+ return '';
+ }
+}
+
+function refreshMetCache() {
+ const now = Date.now();
+ if (now - MET_CACHE_AT < TTL_SEC * 1000 && Object.keys(METROW_CACHE).length) return;
+ for (const [theme, cfg] of Object.entries(MET_THEMES)) {
+ const sql =
+ `SELECT object_id, title, COALESCE(artist,'Unknown') AS artist, ` +
+ `COALESCE(NULLIF(date_display,''), object_date, 'date unknown') AS date_display, ` +
+ `COALESCE(NULLIF(classification,''), 'Artwork') AS classification, ` +
+ `COALESCE(NULLIF(met_url,''), 'https://www.metmuseum.org/art/collection/search/' || object_id) AS met_url, ` +
+ `COALESCE(NULLIF(primary_image_small,''), NULLIF(image_url,''), NULLIF(primary_image,'')) AS image ` +
+ `FROM met_museum_art ` +
+ `WHERE is_public_domain AND active AND (${cfg.sql}) ` +
+ `ORDER BY random() LIMIT ${POOL_SIZE};`;
+ const raw = psqlJson(sql);
+ const rows = raw.split('\n').filter(Boolean).map(line => {
+ const [object_id, title, artist, date_display, classification, met_url, image] = line.split('\t');
+ return {
+ source: 'met',
+ theme,
+ object_id,
+ title: (title || '').slice(0, 120),
+ artist: (artist || 'Unknown').split('|')[0].slice(0, 80),
+ date_display: (date_display || '').slice(0, 40),
+ classification: classification || '',
+ met_url, image,
+ };
+ });
+ METROW_CACHE[theme] = rows;
+ }
+ MET_CACHE_AT = now;
+}
+
+// Fallback list — used only when PG is unreachable.
+const MET_FALLBACK = [
+ { source: 'met', theme: 'bacchanal', object_id: '345721', title: 'A Bacchanal (Silenus & bacchants)', artist: 'Marcantonio Raimondi', date_display: 'ca. 1510–13', classification: 'Prints' },
+ { source: 'met', theme: 'wine', object_id: '436106', title: 'Still Life with Wine Bottle and Apples', artist: 'Henri Fantin-Latour', date_display: '1876', classification: 'Paintings' },
+ { source: 'met', theme: 'engraving', object_id: '720507', title: 'Autumn (Wine Harvest)', artist: 'Aignan Thomas Desfriches', date_display: '1768', classification: 'Prints' },
+ { source: 'met', theme: 'animal', object_id: '435716', title: 'Studies of Monkeys', artist: 'Antoine Watteau', date_display: 'ca. 1714–16', classification: 'Drawings' },
+];
+
+function pickRand(arr) { return arr[Math.floor(Math.random() * arr.length)]; }
+
+function compactCitation(row) {
+ if (!row) return null;
+ const yr = row.date_display ? `, ${row.date_display}` : '';
+ return `the Met's "${row.title}" (${row.artist}${yr})`;
+}
+
+/**
+ * Pick a Met Museum PD reference matching one or more themes.
+ * @param {string[]} themes e.g. ['bacchanal', 'wine']. Defaults to all.
+ * @returns {object} { theme, title, artist, date_display, met_url, compactCitation }
+ */
+function pickMetReference(themes) {
+ refreshMetCache();
+ const pool = [];
+ const want = (themes && themes.length) ? themes : Object.keys(MET_THEMES);
+ for (const t of want) {
+ const rows = METROW_CACHE[t] || [];
+ const weight = (MET_THEMES[t] && MET_THEMES[t].weight) || 1;
+ for (let i = 0; i < weight; i++) pool.push(...rows);
+ }
+ const row = pool.length ? pickRand(pool) : pickRand(MET_FALLBACK);
+ return { ...row, compactCitation: compactCitation(row) };
+}
+
+// ── Prior wallco designs from PG (composition reference) ──────────────
+const PRIOR_CACHE = {};
+let PRIOR_CACHE_AT = 0;
+
+function refreshPriorCache() {
+ const now = Date.now();
+ if (now - PRIOR_CACHE_AT < TTL_SEC * 1000 && Object.keys(PRIOR_CACHE).length) return;
+ // Pull the top-rated published prior designs per category (stars desc),
+ // then random within ties.
+ const sql =
+ `SELECT id, ` +
+ `CASE WHEN category LIKE 'drunk-zoo-36%' THEN 'drunk-zoo-36' ELSE category END AS bucket, ` +
+ `COALESCE(LEFT(prompt, 160), '') AS prompt_head, ` +
+ `COALESCE(user_stars, 0) AS stars, ` +
+ `COALESCE(dominant_hex, '#888888') AS dominant_hex ` +
+ `FROM spoon_all_designs ` +
+ `WHERE is_published AND (category IN ('drunk-animals','drunk-monkeys-v2','drunk-animals-designer') ` +
+ `OR category LIKE 'drunk-zoo-36%') ` +
+ `ORDER BY stars DESC NULLS LAST, random() LIMIT 600;`;
+ const raw = psqlJson(sql);
+ const buckets = {};
+ for (const line of raw.split('\n').filter(Boolean)) {
+ const [id, bucket, prompt_head, stars, dominant_hex] = line.split('\t');
+ if (!buckets[bucket]) buckets[bucket] = [];
+ buckets[bucket].push({
+ source: 'prior',
+ id: parseInt(id, 10),
+ category: bucket,
+ prompt_head: (prompt_head || '').slice(0, 160),
+ stars: parseInt(stars, 10) || 0,
+ dominant_hex,
+ });
+ }
+ Object.assign(PRIOR_CACHE, buckets);
+ PRIOR_CACHE_AT = now;
+}
+
+function pickPriorDesignReference(category) {
+ refreshPriorCache();
+ const bucket =
+ (category && category.startsWith('drunk-zoo-36')) ? 'drunk-zoo-36' :
+ category || 'drunk-animals';
+ const rows = PRIOR_CACHE[bucket] || PRIOR_CACHE['drunk-animals'] || [];
+ if (!rows.length) return null;
+ const row = pickRand(rows);
+ return {
+ ...row,
+ compactCitation: `composition lineage from wallco internal design #${row.id} (${row.dominant_hex} dominant)`,
+ };
+}
+
+// ── Combined helper — return both refs ready-to-paste into a prompt ──
+function pickReferences(category) {
+ const m = pickMetReference(themesForCategory(category));
+ const p = pickPriorDesignReference(category);
+ return {
+ met: m,
+ prior: p,
+ promptClause: [
+ m && `inspired by ${m.compactCitation}`,
+ p && p.compactCitation,
+ ].filter(Boolean).join(', '),
+ };
+}
+
+function themesForCategory(category) {
+ // Map each drunk-animal sub-category to a sensible Met theme mix.
+ if (!category) return ['bacchanal', 'wine', 'animal'];
+ if (category.startsWith('drunk-zoo-36')) return ['bacchanal', 'animal', 'engraving'];
+ if (category === 'drunk-monkeys-v2') return ['animal', 'bacchanal'];
+ if (category === 'drunk-animals-designer') return ['chinoiserie', 'wine', 'engraving'];
+ return ['bacchanal', 'wine', 'animal'];
+}
+
+module.exports = {
+ pickMetReference,
+ pickPriorDesignReference,
+ pickReferences,
+ themesForCategory,
+ MET_THEMES,
+};
+
+// CLI smoke-test
+if (require.main === module) {
+ console.log('Met cache warming...');
+ refreshMetCache();
+ for (const t of Object.keys(MET_THEMES)) {
+ console.log(` ${t}: ${(METROW_CACHE[t]||[]).length} rows`);
+ }
+ console.log('\nPrior cache warming...');
+ refreshPriorCache();
+ for (const b of Object.keys(PRIOR_CACHE)) {
+ console.log(` ${b}: ${PRIOR_CACHE[b].length} rows`);
+ }
+ console.log('\nSample reference pairs:');
+ for (const cat of ['drunk-animals', 'drunk-zoo-36', 'drunk-monkeys-v2', 'drunk-animals-designer']) {
+ const r = pickReferences(cat);
+ console.log(`\n [${cat}]`);
+ console.log(` met: ${r.met && r.met.compactCitation}`);
+ console.log(` prior: ${r.prior && r.prior.compactCitation}`);
+ console.log(` clause: ${r.promptClause}`);
+ }
+}
diff --git a/scripts/da4-preview-batch.js b/scripts/da4-preview-batch.js
new file mode 100644
index 0000000..c002279
--- /dev/null
+++ b/scripts/da4-preview-batch.js
@@ -0,0 +1,126 @@
+#!/usr/bin/env node
+/**
+ * DA-4: heterogeneous preview batch for the drunk-animals refresh.
+ * Generates 6 designs spanning 4 categories, curator-mode (is_published=
+ * false because generate_designs.js inserts FALSE by default), local
+ * ComfyUI backend ($0). Writes data/logs/drunk-animals-preview-batch.json.
+ *
+ * Settlement-gate runs inline via scripts/settlement_tick_guard.js, so
+ * BLOCK / NEEDS_REVIEW will skip that prompt and try another.
+ */
+'use strict';
+const path = require('path');
+const fs = require('fs');
+const { spawnSync, execSync } = require('child_process');
+
+const ROOT = path.join(__dirname, '..');
+const OUT_JSON = path.join(ROOT, 'data', 'logs', 'drunk-animals-preview-batch.json');
+
+const { buildN: buildDA } = require('./drunk_animal_prompts');
+const { buildN: buildV2 } = require('./drunk_monkeys_v2_prompts');
+const { buildN: buildSub } = require('./drunk_monkeys_birds_subdued_prompts');
+const SHARED = require('./drunk_motif_shared');
+
+// Build a drunk-zoo-36 prompt by lifting ZOO_VIGNETTES from night-builder
+// (it's not exported there) and SHARED + composing it here.
+const NB = fs.readFileSync(path.join(ROOT, 'scripts', 'night-builder.js'), 'utf8');
+const VIGS_MATCH = NB.match(/const ZOO_VIGNETTES = \[([\s\S]*?)\];/);
+const VIGS = VIGS_MATCH[1].split(/'\s*,\s*\n\s*'/).map(s => s.replace(/^[\s']*|['\s,]*$/g, ''));
+const ARTDIR_MATCH = NB.match(/const SHARED_ARTDIR = ([\s\S]*?);\s*\n/);
+const SHARED_ARTDIR = ARTDIR_MATCH ? eval(ARTDIR_MATCH[1]) : '';
+
+const ZOO_CWS = [
+ { name: 'Bordeaux Velvet', tone: 'deep burgundy', hex: '#5a1818' },
+ { name: 'Forest Loden', tone: 'dark gallery green', hex: '#22443a' },
+];
+
+function composeDrunkZoo36(cw) {
+ const vig = VIGS[Math.floor(Math.random() * VIGS.length)];
+ const tex = SHARED.TEXTURE_GROUNDS[Math.floor(Math.random() * SHARED.TEXTURE_GROUNDS.length)];
+ const bb = SHARED.BOTTLE_BACKDROPS[Math.floor(Math.random() * SHARED.BOTTLE_BACKDROPS.length)];
+ const ref = SHARED.pickReferenceClause('drunk-zoo-36');
+ return (
+ `Drunk Zoo 36" repeat wallpaper — ${cw.name} colorway. ` +
+ `Substrate: real ${tex.slug} (${tex.voice.replace(/^rendered on /, '')}). ` +
+ `Ground: solid ${cw.tone} (${cw.hex}) tinted over the natural-fiber substrate so the texture grain still reads through. ` +
+ `Figure: bone-ivory (#F2EADB) single-ink. ` +
+ `Vignette: ${vig}. Renders at wall-scale 36-inch seamless tile — motifs are LARGE, anchored on the central vertical axis of symmetry, generous breathing room of clean ground around each motif. ` +
+ (ref ? `Reference anchor: ${ref}. ` : '') +
+ `Secondary detail in negative space: ${bb} (rendered as a tiny bone-ivory ink silhouette at the very back, smaller scale than the main pair, not competing). ` +
+ `MANDATORY motifs visible in EVERY vignette: (1) alcohol being consumed, (2) a lit handrolled cannabis joint with a visible curl of smoke, (3) the animal(s) swinging from something. ` +
+ `Each animal is one FLAT STENCIL SILHOUETTE in bone-ivory ink — no interior shading. The joint and smoke wisp are tiny silhouette props inside the bone-ivory ink layer. NO cannabis leaf, NO marijuana leaf, NO foliage. ` +
+ `Whimsical playful joyful tone. Lean toward BOTANICALS over leaves. ` +
+ SHARED_ARTDIR
+ );
+}
+
+// Compose the 6 prompts
+const batch = [
+ { cat: 'drunk-animals', prompt: buildDA(1)[0] },
+ { cat: 'drunk-animals', prompt: buildDA(1)[0] },
+ { cat: 'drunk-zoo-36', prompt: composeDrunkZoo36(ZOO_CWS[0]) },
+ { cat: 'drunk-zoo-36', prompt: composeDrunkZoo36(ZOO_CWS[1]) },
+ { cat: 'drunk-monkeys-v2', prompt: buildV2(1)[0].prompt },
+ { cat: 'drunk-animals-designer', prompt: buildSub(1)[0].prompt },
+];
+
+function psqlMaxId() {
+ try {
+ return parseInt(execSync(`psql dw_unified -At -c "SELECT COALESCE(max(id),0) FROM spoon_all_designs;"`, { encoding: 'utf8' }).trim(), 10) || 0;
+ } catch { return 0; }
+}
+
+const results = [];
+const startedAt = new Date().toISOString();
+
+for (let i = 0; i < batch.length; i++) {
+ const { cat, prompt } = batch[i];
+ console.log(`\n[${i+1}/${batch.length}] cat=${cat} — kicking off generate_designs.js`);
+ const maxBefore = psqlMaxId();
+ const t0 = Date.now();
+ const r = spawnSync('node', [
+ path.join(ROOT, 'scripts', 'generate_designs.js'),
+ '--n', '1',
+ '--kind', 'seamless_tile',
+ '--category', cat,
+ '--prompts', prompt,
+ ], { stdio: 'inherit', cwd: ROOT, timeout: 5 * 60_000 });
+
+ const elapsedSec = ((Date.now() - t0) / 1000).toFixed(1);
+ let newId = null;
+ try {
+ const raw = execSync(
+ `psql dw_unified -At -c "SELECT id FROM spoon_all_designs WHERE category='${cat.replace(/'/g, "''")}' AND id > ${maxBefore} ORDER BY id DESC LIMIT 1;"`,
+ { encoding: 'utf8' }).trim();
+ newId = raw ? parseInt(raw, 10) : null;
+ } catch {}
+
+ results.push({
+ idx: i + 1,
+ category: cat,
+ new_design_id: newId,
+ elapsed_sec: parseFloat(elapsedSec),
+ exit_status: r.status,
+ view_url: newId ? `http://127.0.0.1:9792/design/${newId}` : null,
+ image_url: newId ? `http://127.0.0.1:9792/designs/img/by-id/${newId}` : null,
+ prompt_head: prompt.slice(0, 200),
+ });
+
+ console.log(` → ${newId ? `id=${newId} (${elapsedSec}s)` : 'NO NEW DESIGN'}`);
+}
+
+const out = {
+ generated_at: startedAt,
+ finished_at: new Date().toISOString(),
+ total_designs: results.length,
+ successful: results.filter(r => r.new_design_id).length,
+ results,
+};
+
+fs.mkdirSync(path.dirname(OUT_JSON), { recursive: true });
+fs.writeFileSync(OUT_JSON, JSON.stringify(out, null, 2));
+console.log(`\n✓ wrote ${OUT_JSON}`);
+console.log(` ${out.successful} / ${out.total_designs} generated successfully`);
+for (const r of results) {
+ console.log(` ${r.category}\tid=${r.new_design_id}\t${r.view_url || '(none)'}`);
+}
diff --git a/scripts/drunk_animal_prompts.js b/scripts/drunk_animal_prompts.js
index a22b249..e45f7b9 100644
--- a/scripts/drunk_animal_prompts.js
+++ b/scripts/drunk_animal_prompts.js
@@ -319,6 +319,7 @@ function buildPrompt(seed = null) {
TONE_ON_TONE_SUFFIX
].join(', ');
}
+ const refClause = SHARED.pickReferenceClause('drunk-animals');
return [
pickRand(ANIMALS), pickRand(TABLEAUX),
// Mandatory motifs — Steve 2026-05-25
@@ -326,12 +327,13 @@ function buildPrompt(seed = null) {
pickRand(SWINGS),
pickRand(BOTTLE_BACKDROPS),
pickTextureGroundVoice(),
+ refClause && `${refClause}`,
`set among ${pickRand(BOTANICALS)}`,
`palette: ${pickRand(pickPaletteSource())}`,
pickRand(STYLES),
pickRand(COMPOSITIONS),
SHARED.DRUNK_NEGATIVE_SUFFIX
- ].join(', ');
+ ].filter(Boolean).join(', ');
}
function buildN(n) {
@@ -344,17 +346,19 @@ function buildN(n) {
if (usedStyles.size >= STYLES.length - 1) usedStyles.clear();
const animal = pickRand(ANIMALS, usedAnimals); usedAnimals.add(animal);
const style = pickRand(STYLES, usedStyles); usedStyles.add(style);
+ const refClause = SHARED.pickReferenceClause('drunk-animals');
const parts = [
animal,
pickRand(TABLEAUX),
// Mandatory motifs — Steve 2026-05-25 — every drunk-animal must show
// alcohol-in-hand + lit joint + swinging + wild-bottle backdrop +
// rendered on a natural-fiber texture ground (grasscloth/sisal/raffia/
- // Madagascar etc.).
+ // Madagascar etc.) + Met PD + prior wallco design reference clause.
pickRand(JOINTS),
pickRand(SWINGS),
pickRand(BOTTLE_BACKDROPS),
pickTextureGroundVoice(),
+ refClause,
`set among ${pickRand(BOTANICALS)}`,
`palette: ${pickRand(pickPaletteSource())}`,
style,
@@ -362,7 +366,7 @@ function buildN(n) {
SHARED.DRUNK_NEGATIVE_SUFFIX,
// Aesthetic gate — Steve 2026-05-19: empirical professional palette from dw_unified
TONE_ON_TONE_SUFFIX
- ];
+ ].filter(Boolean);
out.push(parts.join(', '));
}
return out;
diff --git a/scripts/drunk_monkeys_birds_subdued_prompts.js b/scripts/drunk_monkeys_birds_subdued_prompts.js
index 21450b3..c8809e2 100644
--- a/scripts/drunk_monkeys_birds_subdued_prompts.js
+++ b/scripts/drunk_monkeys_birds_subdued_prompts.js
@@ -174,14 +174,17 @@ function buildOne(i) {
? { name: 'deep-tone-on-tone', voice: pick(SHARED.DEFAULT_PALETTES), hex: [] }
: pick(PALETTES);
+ const refClause = SHARED.pickReferenceClause('drunk-animals-designer');
+
// Build the prompt — clearly SUBDUED, clearly REPEAT-FRIENDLY, clearly
// settlement-safe (no directional/tropical foliage, controlled multicolor).
// Steve 2026-05-25 — mandatory drink + joint + swinging + bottle-backdrop
- // + natural-fiber texture in every prompt.
+ // + natural-fiber texture + Met-PD reference in every prompt.
const positive =
`Editorial wallpaper design — ${animal}, ${tableau}, also holding ${joint}, ${swing}, ` +
`${bottleBackdrop}, ` +
`${texture.voice}, ` +
+ (refClause ? `reference anchor: ${refClause}, ` : '') +
`set on a subdued botanical ground of ${botanical}. ` +
`Composition: ${composition}. ` +
`Palette: ${palette.voice}${palette.hex && palette.hex.length ? '; palette hex anchors: ' + palette.hex.join(', ') : ''}. ` +
diff --git a/scripts/drunk_monkeys_v2_prompts.js b/scripts/drunk_monkeys_v2_prompts.js
index bb6214e..53e864b 100644
--- a/scripts/drunk_monkeys_v2_prompts.js
+++ b/scripts/drunk_monkeys_v2_prompts.js
@@ -158,13 +158,16 @@ function buildOne(i) {
? { name: 'deep-tone-on-tone', voice: pick(SHARED.DEFAULT_PALETTES) }
: pick(PALETTES);
- // SUBJECT FIRST — that's the key v2 fix. ~250 char prompt total.
- // Steve 2026-05-25 — mandatory joint + swinging + bottle-backdrop +
- // natural-fiber texture in every prompt.
+ const refClause = SHARED.pickReferenceClause('drunk-monkeys-v2');
+
+ // SUBJECT FIRST — that's the key v2 fix. Steve 2026-05-25 — mandatory
+ // joint + swinging + bottle-backdrop + natural-fiber texture + Met-PD
+ // reference clause in every prompt.
const positive =
`${subject}, ${action}, also ${joint}, ${swing}. ` +
`${bottleBackdrop}. ` +
`${texture.voice}. ` +
+ (refClause ? `Reference anchor: ${refClause}. ` : '') +
`${backdrop}. ` +
`Hand-painted gouache wallpaper illustration, ${composition}, ${palette.voice}, ` +
`restrained tone-on-tone, museum-archival print quality. ` +
diff --git a/scripts/drunk_motif_shared.js b/scripts/drunk_motif_shared.js
index 7d5672e..c4baf04 100644
--- a/scripts/drunk_motif_shared.js
+++ b/scripts/drunk_motif_shared.js
@@ -23,6 +23,23 @@
const path = require('path');
const fs = require('fs');
+// Met PD + prior wallco design reference picker — lib/design-references.js
+// is loaded lazily so this module stays cheap to require() in cron paths.
+let _refs = null;
+function getRefs() {
+ if (_refs === null) {
+ try { _refs = require('../lib/design-references'); }
+ catch { _refs = { pickReferences: () => ({ promptClause: '', met: null, prior: null }) }; }
+ }
+ return _refs;
+}
+function pickReferenceClause(category) {
+ try {
+ const r = getRefs().pickReferences(category);
+ return r && r.promptClause ? r.promptClause : '';
+ } catch { return ''; }
+}
+
// ── JOINTS — lit handrolled cannabis joints w/ smoke trail ─────────────
// Small silhouette prop, NEVER a cannabis leaf. The negative prompt
// explicitly bans "cannabis leaf / marijuana leaf" so the joint stays
@@ -252,14 +269,15 @@ function pickRand(arr, exclude) {
// One-line mandatory motif block — drop-in for any prompt generator that
// wants the guaranteed alcohol+joint+swing+bottle-backdrop+texture clause.
-function buildMandatoryMotifs() {
+function buildMandatoryMotifs(category) {
return {
- drink: pickRand(TABLEAUX),
- joint: pickRand(JOINTS),
- swing: pickRand(SWINGS),
- bottleBackdrop: pickRand(BOTTLE_BACKDROPS),
- texture: pickRand(TEXTURE_GROUNDS),
- palette: pickRand(DEFAULT_PALETTES),
+ drink: pickRand(TABLEAUX),
+ joint: pickRand(JOINTS),
+ swing: pickRand(SWINGS),
+ bottleBackdrop: pickRand(BOTTLE_BACKDROPS),
+ texture: pickRand(TEXTURE_GROUNDS),
+ palette: pickRand(DEFAULT_PALETTES),
+ referenceClause: pickReferenceClause(category),
};
}
@@ -277,7 +295,7 @@ const DRUNK_NEGATIVE_SUFFIX =
module.exports = {
JOINTS, SWINGS, TABLEAUX, BOTTLE_BACKDROPS, TEXTURE_GROUNDS,
FASHION_PALETTES, TONE_ON_TONE_DEEP_PALETTES, DEFAULT_PALETTES,
- pickRand, buildMandatoryMotifs,
+ pickRand, pickReferenceClause, buildMandatoryMotifs,
DRUNK_NEGATIVE_SUFFIX,
};
diff --git a/scripts/night-builder.js b/scripts/night-builder.js
index 2633d47..cca050c 100755
--- a/scripts/night-builder.js
+++ b/scripts/night-builder.js
@@ -403,12 +403,14 @@ function composeDrunkZoo36Prompt(cw) {
// negative space, in the same bone-ivory ink as the main silhouettes.
const tex = SHARED.TEXTURE_GROUNDS[Math.floor(Math.random() * SHARED.TEXTURE_GROUNDS.length)];
const bottleBackdrop = SHARED.BOTTLE_BACKDROPS[Math.floor(Math.random() * SHARED.BOTTLE_BACKDROPS.length)];
+ const refClause = SHARED.pickReferenceClause('drunk-zoo-36');
return (
`Drunk Zoo 36" repeat wallpaper — ${cw.name} colorway. ` +
`Substrate: real ${tex.slug} (${tex.voice.replace(/^rendered on /, '')}). ` +
`Ground: solid ${cw.tone} (${cw.hex}) tinted over the natural-fiber substrate so the texture grain still reads through. ` +
`Figure: bone-ivory (#F2EADB) single-ink. ` +
`Vignette: ${vig}. Renders at wall-scale 36-inch seamless tile — motifs are LARGE, anchored on the central vertical axis of symmetry, generous breathing room of clean ground around each motif. ` +
+ (refClause ? `Reference anchor: ${refClause}. ` : '') +
`Secondary detail in negative space: ${bottleBackdrop} (rendered as a tiny bone-ivory ink silhouette at the very back, smaller scale than the main pair, not competing). ` +
`MANDATORY motifs visible in EVERY vignette: (1) alcohol being consumed (drink glass or bottle held to mouth/in paw), (2) a lit handrolled cannabis joint with a visible curl of smoke, (3) the animal(s) swinging from something — vine, branch, chandelier, rope, or porch swing — mid-swing arc visible. ` +
`Each animal is one FLAT STENCIL SILHOUETTE in bone-ivory ink — no interior shading, no anatomical line-detail, no spots, no stripes, no fur texture. Spots/stripes appear ONLY as cut-out negative shapes in the silhouette (revealing ground tone), never as a second ink color. The joint and smoke wisp are tiny silhouette props inside the bone-ivory ink layer (joint = small rolled-paper cylinder with a glowing tip; smoke = a thin curling line). NO cannabis leaf, NO marijuana leaf, NO foliage of any kind. ` +
← 5f63e2d remove mural pan HUD (5 arrows ↑↓←→⟲) + drag-to-pan on /desi
·
back to Wallco Ai
·
design-coordinate cards: image-only grid, hover overlay reve 0e37522 →