← back to Wallco Ai
mid_seam_heal.py — $0 production fix for SDXL latent-grid leak
02f91e6f44d8923383a0a1210ef1829d16e77e04 · 2026-05-26 08:23:37 -0700 · Steve Abrams
Replaces the planned $293 Gemini-edit run on the 7,333 mids-only FAIL
cohort. PIL Gaussian-band-blur (BAND=12px, SIGMA=4.0) at H/2 and V/2
midlines collapses the 4x4 latent-block stitch discontinuity while
preserving composition everywhere else.
Validated on 20-sample experiment (committed e30db7df):
20/20 improved · 9 → PASS · 11 → WARN · 0 stayed FAIL
avg mids ΔE: 17.10 → 3.44 (80% reduction)
avg max ΔE: 17.10 → 5.22
Round-1-sacred pattern:
- Source PNG NEVER modified
- Healed PNG → data/generated/midheal_<src>_<ts>.png
- INSERT new all_designs row:
generator='pil-mid-heal'
parent_design_id=<src>
is_published=TRUE
kind='seamless_tile' (or whatever source had)
notes='mid_heal of #<src>: PIL band-blur BAND=12 SIGMA=4.0'
- Source notes appended: ' | MID_HEALED_BY: <new_id>'
- Idempotent — skips already-healed sources via MID_HEALED_BY: tag
Reversible via POST /api/fix-decision/<new_id> verdict='reject'.
3-design smoke test passed before scaling: ids 24/4593/4594 healed,
new ids 43236/43237/43238 inserted with correct lineage, source notes
got MID_HEALED_BY append. Batch run on remaining 7,326 designs is in
flight at ~78 designs/s.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Files touched
A scripts/mid_seam_heal.py
Diff
commit 02f91e6f44d8923383a0a1210ef1829d16e77e04
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue May 26 08:23:37 2026 -0700
mid_seam_heal.py — $0 production fix for SDXL latent-grid leak
Replaces the planned $293 Gemini-edit run on the 7,333 mids-only FAIL
cohort. PIL Gaussian-band-blur (BAND=12px, SIGMA=4.0) at H/2 and V/2
midlines collapses the 4x4 latent-block stitch discontinuity while
preserving composition everywhere else.
Validated on 20-sample experiment (committed e30db7df):
20/20 improved · 9 → PASS · 11 → WARN · 0 stayed FAIL
avg mids ΔE: 17.10 → 3.44 (80% reduction)
avg max ΔE: 17.10 → 5.22
Round-1-sacred pattern:
- Source PNG NEVER modified
- Healed PNG → data/generated/midheal_<src>_<ts>.png
- INSERT new all_designs row:
generator='pil-mid-heal'
parent_design_id=<src>
is_published=TRUE
kind='seamless_tile' (or whatever source had)
notes='mid_heal of #<src>: PIL band-blur BAND=12 SIGMA=4.0'
- Source notes appended: ' | MID_HEALED_BY: <new_id>'
- Idempotent — skips already-healed sources via MID_HEALED_BY: tag
Reversible via POST /api/fix-decision/<new_id> verdict='reject'.
3-design smoke test passed before scaling: ids 24/4593/4594 healed,
new ids 43236/43237/43238 inserted with correct lineage, source notes
got MID_HEALED_BY append. Batch run on remaining 7,326 designs is in
flight at ~78 designs/s.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
scripts/mid_seam_heal.py | 325 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 325 insertions(+)
diff --git a/scripts/mid_seam_heal.py b/scripts/mid_seam_heal.py
new file mode 100755
index 0000000..afbc48e
--- /dev/null
+++ b/scripts/mid_seam_heal.py
@@ -0,0 +1,325 @@
+#!/usr/bin/env python3
+"""mid_seam_heal — production batch tool for the SDXL latent-grid leak.
+
+Defect: pixel discontinuity at row H/2 and col W/2 (the 4x4 latent-block
+stitch line). The 6-lens edges-agent flags this as `grid=mids_only` or
+`grid=both`. Average mids ΔE in flagged designs: 17.10.
+
+Fix: PIL Gaussian-blur of a 24-px band (12px each side) at H/2 and V/2.
+Composition preserved everywhere else. Validated on 20-design sample —
+20/20 improved, 0/20 stayed FAIL, 9/20 reached PASS, 11/20 reached WARN.
+Avg mids ΔE dropped 17.10 → 3.44 (80% reduction).
+
+Round-1-sacred pattern (per feedback_round_one_outputs_are_sacred):
+ - Source PNG NEVER modified or deleted
+ - Healed PNG written to data/generated/midheal_<src_id>_<ts>.png
+ - New spoon_all_designs row INSERTed:
+ generator='pil-mid-heal'
+ parent_design_id=<src_id>
+ is_published=TRUE
+ notes='mid_heal of #<src_id>: PIL band-blur BAND=12 SIGMA=4.0'
+ - Source kept is_published=FALSE (it already was, from the edges sweep)
+ - Source gets notes append: ' | MID_HEALED_BY: <new_id>'
+
+Reversible via POST /api/fix-decision/<new_id> with verdict='reject' —
+that flips new is_published=FALSE + restores source is_published=TRUE.
+
+Usage:
+ python3 mid_seam_heal.py --id 40689 # one design
+ python3 mid_seam_heal.py --all # every mids-only FAIL
+ python3 mid_seam_heal.py --all --workers 8 # parallel
+ python3 mid_seam_heal.py --grid both # also heal 'both' cohort
+ python3 mid_seam_heal.py --limit 50 # cap for smoke test
+ python3 mid_seam_heal.py --dry-run # plan only, no writes
+"""
+import argparse
+import json
+import multiprocessing as mp
+import os
+import subprocess
+import sys
+import tempfile
+import time
+from pathlib import Path
+
+WALLCO_ROOT = Path.home() / 'Projects' / 'wallco-ai'
+OUT_DIR = WALLCO_ROOT / 'data' / 'generated'
+BAND_PX = 12
+SIGMA = 4.0
+
+
+def fetch_targets(grid: str, limit: int | None, ids: list[int] | None):
+ """Return list of (id, local_path, dominant_hex, category, kind, palette_json)
+ rows for designs that match the mid-heal target.
+
+ grid=mids_only → notes LIKE '%EDGES_FAIL: %grid=mids_only%'
+ grid=both → both 'mids_only' AND 'both'
+ grid=any → any EDGES_FAIL row (for diagnostic re-heal)
+ """
+ where = []
+ if ids:
+ where = [f"id IN ({','.join(str(int(i)) for i in ids)})"]
+ else:
+ # Skip rows that have already been mid-healed (avoid duplicate work)
+ where.append("(notes IS NULL OR notes NOT LIKE '%MID_HEALED_BY:%')")
+ # Skip user-removed
+ where.append("(user_removed IS NULL OR user_removed = FALSE)")
+ where.append("local_path IS NOT NULL")
+ if grid == 'mids_only':
+ where.append("notes LIKE '%EDGES_FAIL:%grid=mids_only%'")
+ elif grid == 'both':
+ where.append("(notes LIKE '%EDGES_FAIL:%grid=mids_only%' "
+ "OR notes LIKE '%EDGES_FAIL:%grid=both%')")
+ elif grid == 'any':
+ where.append("notes LIKE '%EDGES_FAIL:%'")
+ else:
+ raise ValueError(f'bad --grid {grid}')
+
+ sql = (
+ "SELECT id, local_path, dominant_hex, category, kind, "
+ "COALESCE(palette::text, 'null') AS palette_json, "
+ "width_in, height_in, panels "
+ "FROM all_designs WHERE " + ' AND '.join(where)
+ + " ORDER BY id"
+ )
+ if limit:
+ sql += f' LIMIT {int(limit)}'
+ sql += ';'
+
+ r = subprocess.run(
+ ['psql', 'dw_unified', '-At', '-F', chr(31), '-c', sql],
+ check=True, capture_output=True, text=True,
+ )
+ rows = []
+ for line in r.stdout.splitlines():
+ if not line.strip():
+ continue
+ parts = line.split(chr(31))
+ if len(parts) < 9:
+ continue
+ try:
+ rows.append({
+ 'id': int(parts[0]),
+ 'local_path': parts[1],
+ 'dominant_hex': parts[2] if parts[2] != '' else None,
+ 'category': parts[3] or 'mixed',
+ 'kind': parts[4] or 'seamless_tile',
+ 'palette_json': parts[5] if parts[5] not in ('', 'null') else 'null',
+ 'width_in': parts[6] if parts[6] != '' else None,
+ 'height_in': parts[7] if parts[7] != '' else None,
+ 'panels': parts[8] if parts[8] != '' else None,
+ })
+ except ValueError:
+ continue
+ return rows
+
+
+def heal_image(src_path: Path, out_path: Path):
+ from PIL import Image, ImageFilter
+ import numpy as np
+ img = Image.open(src_path).convert('RGB')
+ W, H = img.size
+ arr = np.asarray(img).copy()
+
+ blurred = img.filter(ImageFilter.GaussianBlur(radius=SIGMA))
+ blur_arr = np.asarray(blurred)
+
+ hm = H // 2
+ arr[hm - BAND_PX:hm + BAND_PX, :, :] = blur_arr[hm - BAND_PX:hm + BAND_PX, :, :]
+
+ wm = W // 2
+ arr[:, wm - BAND_PX:wm + BAND_PX, :] = blur_arr[:, wm - BAND_PX:wm + BAND_PX, :]
+
+ Image.fromarray(arr).save(out_path, 'PNG', optimize=True)
+ return out_path.stat().st_size
+
+
+def worker(row: dict):
+ """Heal one design. Returns dict with success metadata."""
+ src_id = row['id']
+ try:
+ src_path = Path(row['local_path'])
+ if not src_path.exists():
+ return {'id': src_id, 'ok': False, 'error': 'file_missing'}
+
+ ts = int(time.time() * 1000)
+ out_filename = f'midheal_{src_id}_{ts}.png'
+ out_path = OUT_DIR / out_filename
+
+ bytes_written = heal_image(src_path, out_path)
+
+ return {
+ 'id': src_id,
+ 'ok': True,
+ 'out_path': str(out_path),
+ 'out_filename': out_filename,
+ 'bytes': bytes_written,
+ 'category': row['category'],
+ 'kind': row['kind'],
+ 'dominant_hex': row['dominant_hex'],
+ 'palette_json': row['palette_json'],
+ 'width_in': row['width_in'],
+ 'height_in': row['height_in'],
+ 'panels': row['panels'],
+ }
+ except Exception as exc:
+ return {'id': src_id, 'ok': False, 'error': f'heal_exception: {exc}'}
+
+
+def sql_escape(s: str) -> str:
+ return s.replace("'", "''")
+
+
+def persist(results: list[dict]):
+ """Batched PG transaction:
+ INSERT new spoon_all_designs rows + UPDATE source notes for each success."""
+ ok = [r for r in results if r.get('ok')]
+ if not ok:
+ return 0
+
+ sql_parts = ['BEGIN;']
+ # Build the insert statements one at a time so we capture each new id.
+ # We use a CTE per row to also append to the source's notes column in
+ # the same batch. To keep this simple + atomic, we'll INSERT all rows
+ # via a TEMP TABLE join, then UPDATE sources.
+ sql_parts.append(
+ 'CREATE TEMP TABLE _heal_in (src_id BIGINT PRIMARY KEY, '
+ 'kind TEXT, category TEXT, dominant_hex TEXT, palette JSONB, '
+ 'width_in INTEGER, height_in INTEGER, panels INTEGER, '
+ 'local_path TEXT, image_url TEXT, prompt TEXT, seed BIGINT, '
+ 'notes TEXT) ON COMMIT DROP;'
+ )
+
+ seed_base = int(time.time())
+ rows_for_sql = []
+ for i, r in enumerate(ok):
+ seed = (seed_base + i) & 0x7fffffff
+ kind = sql_escape(r['kind'])
+ cat = sql_escape(r['category'])
+ dh = "NULL" if not r['dominant_hex'] else f"'{sql_escape(r['dominant_hex'])}'"
+ pal_json = r.get('palette_json') or 'null'
+ if pal_json in ('', 'None'):
+ pal_json = 'null'
+ pal = f"'{sql_escape(pal_json)}'::jsonb"
+ wi = r['width_in'] if r['width_in'] not in (None, '') else 'NULL'
+ hi = r['height_in'] if r['height_in'] not in (None, '') else 'NULL'
+ pn = r['panels'] if r['panels'] not in (None, '') else 'NULL'
+ local_path = sql_escape(r['out_path'])
+ img_url = sql_escape(f"/designs/img/{r['out_filename']}")
+ prompt = sql_escape(f"mid_heal of #{r['id']}: PIL band-blur BAND={BAND_PX} SIGMA={SIGMA}")
+ notes = sql_escape(f"mid_heal of #{r['id']}: PIL band-blur BAND={BAND_PX} SIGMA={SIGMA}")
+ rows_for_sql.append(
+ f"({r['id']}, '{kind}', '{cat}', {dh}, {pal}, {wi}, {hi}, {pn}, "
+ f"'{local_path}', '{img_url}', '{prompt}', {seed}, '{notes}')"
+ )
+
+ CHUNK = 200
+ for i in range(0, len(rows_for_sql), CHUNK):
+ batch = rows_for_sql[i:i + CHUNK]
+ sql_parts.append(
+ 'INSERT INTO _heal_in (src_id, kind, category, dominant_hex, palette, '
+ 'width_in, height_in, panels, local_path, image_url, prompt, seed, notes) VALUES '
+ + ','.join(batch) + ';'
+ )
+
+ # Insert new rows + capture (src_id, new_id) for the source-notes update.
+ sql_parts.append("""
+WITH ins AS (
+ INSERT INTO all_designs
+ (kind, brand, width_in, height_in, panels, generator, prompt, seed,
+ image_url, local_path, dominant_hex, palette, category,
+ is_published, parent_design_id, notes)
+ SELECT
+ h.kind, 'wallco.ai', h.width_in, h.height_in, h.panels, 'pil-mid-heal',
+ h.prompt, h.seed, h.image_url, h.local_path, h.dominant_hex, h.palette,
+ h.category, TRUE, h.src_id, h.notes
+ FROM _heal_in h
+ RETURNING id AS new_id, parent_design_id AS src_id
+)
+UPDATE all_designs ad
+SET notes = CASE
+ WHEN ad.notes IS NULL OR ad.notes = '' THEN ' | MID_HEALED_BY: ' || ins.new_id::text
+ ELSE ad.notes || ' | MID_HEALED_BY: ' || ins.new_id::text
+END
+FROM ins
+WHERE ad.id = ins.src_id;
+""")
+
+ sql_parts.append('SELECT count(*) FROM _heal_in;')
+ sql_parts.append('COMMIT;')
+
+ full_sql = '\n'.join(sql_parts)
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.sql', delete=False) as tf:
+ tf.write(full_sql)
+ sql_path = tf.name
+
+ r = subprocess.run(
+ ['psql', 'dw_unified', '-At', '-q', '-v', 'ON_ERROR_STOP=1', '-f', sql_path],
+ capture_output=True, text=True,
+ )
+ if r.returncode != 0:
+ print(f'PSQL FAILED:\n stdout: {r.stdout[:500]}\n stderr: {r.stderr[:500]}',
+ file=sys.stderr)
+ return 0
+ return len(ok)
+
+
+def main():
+ ap = argparse.ArgumentParser()
+ ap.add_argument('--id', type=int, action='append', help='Specific id (repeatable)')
+ ap.add_argument('--all', action='store_true', help='Every matching design')
+ ap.add_argument('--grid', choices=['mids_only', 'both', 'any'], default='mids_only')
+ ap.add_argument('--limit', type=int, default=None)
+ ap.add_argument('--workers', type=int, default=8)
+ ap.add_argument('--dry-run', action='store_true', help='List targets, no writes')
+ args = ap.parse_args()
+
+ if not (args.id or args.all or args.limit):
+ ap.error('Pass --id, --all, or --limit')
+
+ targets = fetch_targets(args.grid, args.limit, args.id)
+ print(f'targets: {len(targets)} ({args.grid} cohort)', flush=True)
+ if not targets:
+ print('nothing to do', flush=True)
+ return
+
+ if args.dry_run:
+ print('--dry-run — first 10 ids:', [t['id'] for t in targets[:10]])
+ return
+
+ OUT_DIR.mkdir(parents=True, exist_ok=True)
+ t0 = time.time()
+ results = []
+ counts = {'ok': 0, 'err': 0}
+
+ with mp.Pool(args.workers) as pool:
+ for i, res in enumerate(pool.imap_unordered(worker, targets, chunksize=4), 1):
+ results.append(res)
+ if res.get('ok'):
+ counts['ok'] += 1
+ else:
+ counts['err'] += 1
+ if i % 250 == 0 or i == len(targets):
+ rate = i / max(0.001, time.time() - t0)
+ eta = (len(targets) - i) / max(0.001, rate)
+ print(
+ f' [{i:>5}/{len(targets)}] ok={counts["ok"]} err={counts["err"]} '
+ f'rate={rate:.1f}/s eta={eta:.0f}s',
+ flush=True,
+ )
+
+ pg_written = persist(results)
+ elapsed = time.time() - t0
+ print('', flush=True)
+ print(f'heal done in {elapsed:.1f}s — '
+ f'baked={counts["ok"]} err={counts["err"]} pg_inserted={pg_written}',
+ flush=True)
+
+ # Sample a few healed rows
+ sample = [r for r in results if r.get('ok')][:5]
+ for r in sample:
+ print(f" id={r['id']:>6} → {r['out_filename']} {r['bytes']//1024}KB", flush=True)
+
+
+if __name__ == '__main__':
+ main()
← 3190409 gitignore: exclude data/elements (6GB), data/rooms (141MB),
·
back to Wallco Ai
·
gitignore: exclude data/edges-scan-report-*.md (regeneratabl e69a345 →