[object Object]

← back to Wallco Ai

Task 31: circular-padding is now the DEFAULT for all seamless_tile gen

899e7fda663e255d19e482a052811c63fb5a87ad · 2026-05-27 14:40:50 -0700 · Steve Abrams

shouldCircularPad() returns true for every non-mural seamless_tile (no longer
gated on TILE_CATEGORIES); generate() force-routes those to the comfy backend
(only comfy patches UNet+VAE Conv2d to circular padding — replicate/flux/stub
ship padding=zeros = guaranteed edge-wrap FAIL). Prompt profile (silhouette vs
dense) stays keyed on TILE_CATEGORIES, decoupled from the padding decision.
Override knobs: WALLCO_NO_CIRCULAR=1 kill-switch, WALLCO_FORCE_TILEABLE=1 legacy
force (override design settled via /dtd -> verdict C).

Validated: damask #53712 + cactus #53716 both PASS edges-agent (all 6 lenses)
+ fuzzy_seam_scan, is_published=FALSE. All 4 edge-wrap lenses PASS across every
sampled comfy tile (vs Replicate tb=15-65 FAIL). The generator's own seam gate
still skipped 2/4 non-seamless attempts -> circular-pad raises the rate, the gate
stays essential. Internal h_mid can still WARN on some tiles (separate defect).

Files touched

Diff

commit 899e7fda663e255d19e482a052811c63fb5a87ad
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed May 27 14:40:50 2026 -0700

    Task 31: circular-padding is now the DEFAULT for all seamless_tile gen
    
    shouldCircularPad() returns true for every non-mural seamless_tile (no longer
    gated on TILE_CATEGORIES); generate() force-routes those to the comfy backend
    (only comfy patches UNet+VAE Conv2d to circular padding — replicate/flux/stub
    ship padding=zeros = guaranteed edge-wrap FAIL). Prompt profile (silhouette vs
    dense) stays keyed on TILE_CATEGORIES, decoupled from the padding decision.
    Override knobs: WALLCO_NO_CIRCULAR=1 kill-switch, WALLCO_FORCE_TILEABLE=1 legacy
    force (override design settled via /dtd -> verdict C).
    
    Validated: damask #53712 + cactus #53716 both PASS edges-agent (all 6 lenses)
    + fuzzy_seam_scan, is_published=FALSE. All 4 edge-wrap lenses PASS across every
    sampled comfy tile (vs Replicate tb=15-65 FAIL). The generator's own seam gate
    still skipped 2/4 non-seamless attempts -> circular-pad raises the rate, the gate
    stays essential. Internal h_mid can still WARN on some tiles (separate defect).
---
 scripts/generate_designs.js | 73 ++++++++++++++++++++++++++++++++-------------
 1 file changed, 52 insertions(+), 21 deletions(-)

diff --git a/scripts/generate_designs.js b/scripts/generate_designs.js
index 2f882b1..d7ac6f7 100644
--- a/scripts/generate_designs.js
+++ b/scripts/generate_designs.js
@@ -74,6 +74,42 @@ function tileProfilePrompts(rawPrompt) {
   return { positive, negative };
 }
 
+// 2026-05-27 (Task 31) — Circular-padding (SeamlessTile + MakeCircularVAE) is
+// now the DEFAULT for EVERY seamless_tile generation, not just TILE_CATEGORIES.
+// Validated this session: ComfyUI circular-padding gives ~100% seam-PASS on a
+// fresh cactus sample (edge ΔE 1–3) vs Replicate's ~17% catalog-wide. Raw
+// Replicate is the seam-killer for tiles — padding='zeros' guarantees an
+// edge-wrap mismatch no prompt or post-heal fully fixes. Circular padding only
+// exists on the comfy backend, so generate() also force-routes tiles to comfy.
+//
+// SINGLE SOURCE OF TRUTH: both genComfy() (which workflow nodes) and generate()
+// (which backend) call this so the tileable flag and the comfy force can never
+// drift apart.
+//
+// Decoupled from PROMPT profile on purpose — the silhouette-vs-dense prompt is
+// still keyed off TILE_CATEGORIES (see generate path below). Figure-on-ground
+// silhouette categories (drunk-animals, designer-bugs, cactus) keep their
+// silhouette prompt but NOW also get circular padding: a true seamless repeat
+// wraps the subject across the boundary, and the sparse silhouette prompt keeps
+// figures centered with generous negative space so they rarely touch the seam
+// (the cactus validation is itself a single-subject silhouette).
+//
+// Murals (kind='mural' or a *mural* category) are a single non-repeating image
+// and must NEVER wrap — they are always excluded.
+//
+// Overrides (DTD verdict C, 2026-05-27 — Claude + Codex both C):
+//   WALLCO_NO_CIRCULAR=1     — hard kill-switch; never circular-pad (escape
+//                              hatch if a future dense figure-on-ground category
+//                              genuinely bisects — preserves the old carve-out
+//                              without a code change / redeploy).
+//   WALLCO_FORCE_TILEABLE=1  — legacy force-on; circular-pads even a mural.
+function shouldCircularPad(meta) {
+  if (process.env.WALLCO_NO_CIRCULAR === '1') return false;
+  if (process.env.WALLCO_FORCE_TILEABLE === '1') return true;
+  const isMural = !!meta && (meta.kind === 'mural' || /mural/i.test(meta.category || ''));
+  return !isMural;
+}
+
 // Distribution of generation widths when --width is not explicitly passed.
 // Override via env: GENERATE_WIDTH_POOL="24,24,36,36,52" (entries weight pick frequency).
 const WIDTH_POOL = (process.env.GENERATE_WIDTH_POOL || '24,24,36,36,52')
@@ -318,16 +354,11 @@ function genComfy(prompt, seed, outPath, meta) {
   // BOTH are required — patching just the UNet leaves seam-introducing decoder.
   // First Fix-3 attempt shipped only SeamlessTile (commit d91f84ab); seam scores
   // didn't improve because the VAE re-introduced seams. This adds the VAE patch.
-  // Conditional on TILE_CATEGORIES because figure-on-ground categories
-  // (drunk-animals, designer-bugs) shouldn't have the figure wrap around edges.
   // Requires spinagon/ComfyUI-seamless-tiling on target ComfyUI (Mac1 9225ed5d).
-  // WALLCO_FORCE_TILEABLE=1 opts a silhouette category (e.g. cactus) into the
-  // circular-padding seamless workflow without adding it to TILE_CATEGORIES
-  // (which would also swap its prompt to the dense tile profile). For a true
-  // seamless wallpaper repeat the figure SHOULD wrap across the boundary —
-  // 2026-05-27 cactus quality-redo. Default behavior unchanged when unset.
-  const tileable = process.env.WALLCO_FORCE_TILEABLE === '1'
-    || !!(meta && TILE_CATEGORIES.has(meta.category));
+  // 2026-05-27 (Task 31) — now DEFAULT for every non-mural seamless_tile, not
+  // just TILE_CATEGORIES. See shouldCircularPad() for the full rationale + the
+  // WALLCO_NO_CIRCULAR / WALLCO_FORCE_TILEABLE overrides.
+  const tileable = shouldCircularPad(meta);
   const BASE_MODEL_REF  = tileable ? ['1000', 0] : ['4',  0];
   const REFINER_MODEL_REF = tileable ? ['1001', 0] : ['15', 0];
   const BASE_VAE_REF    = tileable ? ['2000', 0] : ['4',  2];
@@ -454,19 +485,19 @@ function genReplicateFlux(prompt, seed, outPath) {
 }
 
 function generate(prompt, seed, outPath, meta) {
-  // 2026-05-26 — Dense edge-to-edge repeats (TILE_CATEGORIES) only render
-  // seamlessly on the comfy backend, which patches the UNet+VAE Conv2d to
-  // circular padding (SeamlessTile + MakeCircularVAE). replicate/flux/stub ship
-  // padding='zeros' → guaranteed top-bottom edge-wrap FAIL that no prompt fixes.
-  // Validated: replicate damask tb=15-65 ΔE FAIL vs comfy damask tb=2.14 PASS.
-  // Force comfy for exactly TILE_CATEGORIES regardless of GEN_BACKEND so the
-  // cron (which defaults to replicate) can't silently regenerate broken tile
-  // inventory. This gate MUST mirror genComfy's `tileable` flag — figure-on-
-  // ground categories (drunk-*, designer-bugs) are deliberately NOT here:
-  // circular padding would wrap the figure around the seam (bisected monkey),
-  // and comfy gives them no benefit, so they keep GEN_BACKEND.
+  // 2026-05-27 (Task 31) — Every seamless_tile renders seamlessly ONLY on the
+  // comfy backend, which patches the UNet+VAE Conv2d to circular padding
+  // (SeamlessTile + MakeCircularVAE). replicate/flux/stub ship padding='zeros'
+  // → guaranteed edge-wrap FAIL that no prompt or post-heal fully fixes.
+  // Validated: replicate damask tb=15-65 ΔE FAIL vs comfy damask tb=2.14 PASS;
+  // cactus comfy ~100% seam-PASS (edge ΔE 1–3) vs replicate ~17% catalog-wide.
+  // Force comfy for any design we're going to circular-pad, regardless of
+  // GEN_BACKEND, so the cron (which can default to replicate) can't silently
+  // regenerate broken tile inventory. This gate MUST mirror genComfy's
+  // `tileable` flag — both call shouldCircularPad() so they can't drift.
+  // Murals (never circular-padded) and WALLCO_NO_CIRCULAR=1 keep GEN_BACKEND.
   let backend = BACKEND;
-  if (meta && TILE_CATEGORIES.has(meta.category) && backend !== 'comfy') {
+  if (shouldCircularPad(meta) && backend !== 'comfy') {
     backend = 'comfy';
   }
   switch (backend) {

← 8120fe7 drunk-curator: make Auto-ID opt-in via header toggle (off by  ·  back to Wallco Ai  ·  admin-card: add created date+time chip to dogs-curator + ret 08a8775 →