[object Object]

← back to Wallco Ai

la-toile: add palm vision-gate + tighten panel gate (negative prompt alone wasn't beating SDXL toile-palm prior; #56222 band leaked through old PANEL_Q)

b62bf3af24056c93502ed0d53cdced54fd073bed · 2026-06-02 08:55:47 -0700 · Steve Abrams

Files touched

Diff

commit b62bf3af24056c93502ed0d53cdced54fd073bed
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Jun 2 08:55:47 2026 -0700

    la-toile: add palm vision-gate + tighten panel gate (negative prompt alone wasn't beating SDXL toile-palm prior; #56222 band leaked through old PANEL_Q)
---
 scripts/build-la-toile-gallery.js  | 104 +++++++++++++++++++++++++++++++++++++
 scripts/generate-la-toile-clean.js |  16 +++++-
 2 files changed, 119 insertions(+), 1 deletion(-)

diff --git a/scripts/build-la-toile-gallery.js b/scripts/build-la-toile-gallery.js
new file mode 100644
index 0000000..2558fbb
--- /dev/null
+++ b/scripts/build-la-toile-gallery.js
@@ -0,0 +1,104 @@
+// Build a before/after LA Toile gallery from pass snapshots.
+// AFTER = pass-2 (first complete post-fix run, DENSITY_MAX=0.58 + palm removal + BH palette).
+// BEFORE = pass-1 (pre-fix: TONE_ON_TONE monochrome + palms + over-tight density).
+const fs = require('fs');
+
+const SCENES = [
+  'Hollywood Sign + Griffith Observatory domes',
+  'Venice Beach boardwalk, pier, surf',
+  'Downtown LA skyline + City Hall',
+  'Jacaranda-lined Sunset Boulevard',
+  'Beverly Hills Spanish-revival bungalows',
+  'Santa Monica Pier Ferris wheel',
+  'Chinatown paifang gate + lanterns',
+  'Echo Park Lake paddle boats + lotus',
+  'Mid-century Case Study glass houses',
+  '1960s convertibles on Mulholland Drive',
+  'Watts Towers mosaic spires',
+  'LA Aqueduct cascade + San Gabriels',
+  'Olvera Street market stalls',
+  'Griffith Park oak trails + mule deer',
+  'Malibu coastline + surfers + lighthouse',
+  'Art-Deco movie palaces + marquees',
+  'Old-LA citrus groves + packing sheds',
+  'Union Station + streamliner train',
+  'Golden-age studio backlot',
+  'Pasadena Rose Parade floats',
+  'Angels Flight funicular railway',
+  'La Brea Tar Pits + mammoths',
+  'Bradbury Building atrium stairs',
+  'Mulholland overlook + coyote at dusk',
+  'Silver Lake reservoir + modernist homes',
+  'Original Farmers Market clock tower',
+  'Topanga Canyon cabins + oaks',
+  'Googie LAX Theme Building arches',
+  'Dodger Stadium grandstands',
+  'Jacaranda residential streets in bloom',
+];
+
+const before = JSON.parse(fs.readFileSync('/tmp/la-toile-pass-1.json', 'utf8'));
+const after = JSON.parse(fs.readFileSync('/tmp/la-toile-pass-2.json', 'utf8'));
+const BASE = 'http://127.0.0.1:9905/designs/img/by-id/';
+
+const rows = SCENES.map((label, i) => {
+  const slug = 'la-toile-' + String(i + 1).padStart(2, '0');
+  return { slug, label, before: before[slug] || null, after: after[slug] || null };
+}).filter(r => r.after); // show scenes that have a post-fix winner
+
+const cells = rows.map(r => `
+  <div class="card">
+    <div class="lbl"><b>${r.slug}</b> · ${r.label}</div>
+    <div class="pair">
+      <figure>
+        <div class="tag tag-b">BEFORE · pre-fix</div>
+        ${r.before
+          ? `<a href="${BASE}${r.before}" target="_blank"><img loading="lazy" src="${BASE}${r.before}"></a><figcaption>#${r.before} · monochrome / palmy / sparse</figcaption>`
+          : `<div class="missing">no pre-fix winner<br>(scene failed gates in pass 1)</div>`}
+      </figure>
+      <figure>
+        <div class="tag tag-a">AFTER · fixed</div>
+        <a href="${BASE}${r.after}" target="_blank"><img loading="lazy" src="${BASE}${r.after}"></a>
+        <figcaption>#${r.after} · BH multi-color · palm-free · density 0.58</figcaption>
+      </figure>
+    </div>
+  </div>`).join('\n');
+
+const html = `<!doctype html><html><head><meta charset="utf-8">
+<title>LA Toile de Jouy — before / after (pass 2, post-fix)</title>
+<style>
+  :root{--ink:#1a1713;--line:#e2dcd0;--bg:#f6f2ea}
+  *{box-sizing:border-box}
+  body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.5 -apple-system,Georgia,serif;padding:28px 32px}
+  h1{font:600 26px/1.2 Georgia,serif;margin:0 0 4px}
+  .sub{color:#6b6357;margin:0 0 24px;font-size:14px}
+  .sub b{color:var(--ink)}
+  .grid{display:grid;grid-template-columns:1fr;gap:22px;max-width:1180px}
+  .card{background:#fff;border:1px solid var(--line);border-radius:12px;padding:14px 16px;box-shadow:0 1px 3px rgba(0,0,0,.04)}
+  .lbl{font-size:14px;margin-bottom:10px;color:#3a342b}
+  .lbl b{font-size:13px;letter-spacing:.02em;color:#8a7f6c;font-variant:all-small-caps}
+  .pair{display:grid;grid-template-columns:1fr 1fr;gap:14px}
+  figure{margin:0;position:relative}
+  img{width:100%;aspect-ratio:1/1;object-fit:cover;border-radius:8px;display:block;background:#eee}
+  .missing{width:100%;aspect-ratio:1/1;border-radius:8px;display:flex;align-items:center;justify-content:center;text-align:center;color:#a99;background:#faf6f3;border:1px dashed #e2c9c9;font-size:13px}
+  figcaption{font-size:12px;color:#6b6357;margin-top:6px}
+  .tag{position:absolute;top:8px;left:8px;font:600 10px/1 -apple-system;letter-spacing:.06em;padding:5px 8px;border-radius:5px;z-index:2;color:#fff}
+  .tag-b{background:#9a6b63}.tag-a{background:#3f6b4e}
+  .legend{display:flex;gap:18px;margin-bottom:20px;font-size:13px;flex-wrap:wrap}
+  .legend span{display:inline-flex;align-items:center;gap:6px}
+  .dot{width:10px;height:10px;border-radius:3px;display:inline-block}
+</style></head><body>
+<h1>LA Toile de Jouy — before / after</h1>
+<p class="sub">Pass&nbsp;2 (first complete post-fix run) vs pass&nbsp;1 (pre-fix). Fixes: <b>BH multi-color palette wins</b> (removed conflicting tone-on-tone monochrome suffix) · <b>palms removed</b> from positive prompt · <b>density 0.52→0.58</b>. ${rows.length} scenes with a post-fix winner.</p>
+<div class="legend">
+  <span><i class="dot" style="background:#9a6b63"></i> BEFORE — pale monochrome, palms everywhere, over-rejected breathing room</span>
+  <span><i class="dot" style="background:#3f6b4e"></i> AFTER — full BH colorway, no palms, classic toile density</span>
+</div>
+<div class="grid">
+${cells}
+</div>
+</body></html>`;
+
+fs.writeFileSync('/tmp/la-toile-gallery-after.html', html);
+console.log('wrote /tmp/la-toile-gallery-after.html — ' + rows.length + ' scenes (' +
+  rows.filter(r => r.before).length + ' with before/after pair, ' +
+  rows.filter(r => !r.before).length + ' after-only)');
diff --git a/scripts/generate-la-toile-clean.js b/scripts/generate-la-toile-clean.js
index 3511663..de24f4c 100644
--- a/scripts/generate-la-toile-clean.js
+++ b/scripts/generate-la-toile-clean.js
@@ -33,6 +33,16 @@ const CONCEPT_Q = process.env.CONCEPT_Q ||
 // This gate now blocks ONLY Part-B elements; that is the sole settlement guard, so keep it strict.
 const SETTLEMENT_Q = process.env.SETTLEMENT_Q ||
   "Does this image contain any bird, butterfly, banana, banana plant or leaf, or bunch of grapes? Answer yes only if one of those is clearly visible.";
+// Anti-panel gate (Steve 2026-06-02) — reject blocky abstract blocks, register-band
+// rows, and horizontal-bar/shelf artifacts; keep only continuous all-over scenes.
+const PANEL_Q = process.env.PANEL_Q ||
+  "Look for a horizontal strip, bar, or band running across the image that is noticeably emptier (mostly blank ground color) than the scenery above and below it, OR a flat rectangular block/panel of solid color, OR a collage of separate boxed-off panes. Answer yes if ANY such empty band, blank block, or boxed panel is present — even a single horizontal empty strip cutting across counts. Answer no only if the illustrated scene reads as continuous edge to edge with no empty band slicing through it.";
+// Anti-palm gate (Steve 2026-06-02) — the prompt depicts LA's cypress/oak/jacaranda/
+// olive/eucalyptus, NEVER palms. Negative conditioning alone doesn't beat SDXL's
+// strong toile-palm prior, so reject any roll showing palms at the gate (this is an
+// AESTHETIC gate, separate from SETTLEMENT_Q which treats a lone palm as non-violation).
+const PALM_Q = process.env.PALM_Q ||
+  "Does this image contain any palm tree, palm frond, or palm-like tree with a tall bare trunk topped by a fan or feather of fronds (date palm, fan palm, coconut palm, or any palm silhouette)? Answer yes if any palm is visible anywhere in the scene, even a small one in the background.";
 
 // Beverly Hills style-guide colorways (see ~/Projects/dw-style-guides/index.html).
 // Each toile is MONOCHROME single-ink (settlement A3=false → bulletproof). The ink
@@ -159,8 +169,12 @@ function evalRoll(id) {
   // MANDATORY settlement Part-B gate: any bird/butterfly/banana/grape => violation => reject.
   const partB = visionAsk(lp, SETTLEMENT_Q);
   if (partB === 'yes') return { aesthetic: false, om: null, why: 'SETTLEMENT: part-B element present' };
+  const panels = visionAsk(lp, PANEL_Q);
+  if (panels === 'yes') return { aesthetic: false, om: null, why: 'panels/bands (not continuous)' };
+  const palms = visionAsk(lp, PALM_Q);
+  if (palms === 'yes') return { aesthetic: false, om: null, why: 'palm tree present (LA toile uses cypress/oak, not palms)' };
   const om = seamOf(id);
-  return { aesthetic: true, om, why: `colors ${major} concept yes settlement OK seam ${om}` };
+  return { aesthetic: true, om, why: `colors ${major} concept yes settlement OK panels no palms no seam ${om}` };
 }
 // Heal the seam boxes of a concept-clean roll → new healed id + post-heal seam.
 function healSeam(id) {

← 7b073e5 pilot-build-tifs.py: --all batch mode (published ids, disk g  ·  back to Wallco Ai  ·  hires: cache TIF-lookup HITS only, never misses bc1d6d8 →