← back to Wallco Ai
mid-heal-preview: $0 SDXL grid-leak fix sample preview
e30db7df604a247e267b6d65b1bab45807e3b64b · 2026-05-26 08:17:33 -0700 · Steve Abrams
20-design experiment with PIL Gaussian-band-blur (BAND_PX=12, SIGMA=4.0)
applied to the H/2 and V/2 midlines of mids-only FAILs from the edges
sweep. Result: 20/20 improved, 9/20 → PASS, 11/20 → WARN, 0 stayed FAIL.
Avg mids ΔE 17.10 → 3.44 (80% reduction). No design got worse.
This is a free replacement for the planned $293 Gemini-edit run on the
7,333 SDXL grid-leak cohort. New admin surface lets Steve eyeball-verify
the 24-px blur band isn't visually obtrusive before scaling.
/admin/mid-heal-preview — side-by-side gallery
/api/admin/mid-heal-preview/sample — JSON from /tmp/seam-heal-experiment.json
Heal-band overlay toggle highlights the red regions where the blur was
applied — everything outside is untouched. Composition preserved.
Production batch tool ships once Steve approves the visual quality.
Standing rule "round-1 outputs are sacred" — the batch tool will
backup originals as __preseam.png and INSERT new spoon_all_designs rows
with generator='pil-mid-heal' + parent_design_id=source, mirroring the
fix-seam pattern.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Files touched
A public/admin/mid-heal-preview.htmlM server.js
Diff
commit e30db7df604a247e267b6d65b1bab45807e3b64b
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue May 26 08:17:33 2026 -0700
mid-heal-preview: $0 SDXL grid-leak fix sample preview
20-design experiment with PIL Gaussian-band-blur (BAND_PX=12, SIGMA=4.0)
applied to the H/2 and V/2 midlines of mids-only FAILs from the edges
sweep. Result: 20/20 improved, 9/20 → PASS, 11/20 → WARN, 0 stayed FAIL.
Avg mids ΔE 17.10 → 3.44 (80% reduction). No design got worse.
This is a free replacement for the planned $293 Gemini-edit run on the
7,333 SDXL grid-leak cohort. New admin surface lets Steve eyeball-verify
the 24-px blur band isn't visually obtrusive before scaling.
/admin/mid-heal-preview — side-by-side gallery
/api/admin/mid-heal-preview/sample — JSON from /tmp/seam-heal-experiment.json
Heal-band overlay toggle highlights the red regions where the blur was
applied — everything outside is untouched. Composition preserved.
Production batch tool ships once Steve approves the visual quality.
Standing rule "round-1 outputs are sacred" — the batch tool will
backup originals as __preseam.png and INSERT new spoon_all_designs rows
with generator='pil-mid-heal' + parent_design_id=source, mirroring the
fix-seam pattern.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
public/admin/mid-heal-preview.html | 214 +++++++++++++++++++++++++++++++++++++
server.js | 37 +++++++
2 files changed, 251 insertions(+)
diff --git a/public/admin/mid-heal-preview.html b/public/admin/mid-heal-preview.html
new file mode 100644
index 0000000..f7eb322
--- /dev/null
+++ b/public/admin/mid-heal-preview.html
@@ -0,0 +1,214 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="robots" content="noindex,nofollow">
+<title>Mid-Seam-Heal Preview — wallco.ai admin</title>
+<style>
+ :root {
+ --ink:#1f1808; --line:#d8d0c0; --gold:#c9a14b;
+ --bg:#fbf8f1; --card:#fff; --faint:#7a6e5a;
+ --green:#1f6a2c; --red:#b3261e; --orange:#c0660b;
+ --sans:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
+ --serif:'Playfair Display','Didot',Georgia,serif;
+ }
+ * { box-sizing:border-box; }
+ body { margin:0; background:var(--bg); color:var(--ink); font:14px var(--sans); }
+ header {
+ padding:14px 24px; border-bottom:1px solid var(--line); background:#fff;
+ display:flex; gap:16px; align-items:baseline; position:sticky; top:0; z-index:5;
+ }
+ header h1 { font:400 22px/1.2 var(--serif); margin:0; }
+ header .meta { color:var(--faint); font-size:12px; }
+ header .summary { margin-left:auto; font:600 12px ui-monospace,Menlo,monospace; color:var(--ink); }
+ header .summary .pass { color:var(--green); }
+ header .summary .warn { color:var(--orange); }
+ header .summary .fail { color:var(--red); }
+ main { max-width:1400px; margin:0 auto; padding:18px; }
+
+ .controls {
+ display:flex; gap:14px; align-items:center; padding:11px 14px;
+ background:#fff; border:1px solid var(--line); border-radius:8px;
+ margin-bottom:14px; font-size:12px;
+ }
+ .controls label { font:600 10.5px var(--sans); letter-spacing:.16em;
+ text-transform:uppercase; color:var(--faint); }
+ .controls .toggle { display:flex; align-items:center; gap:6px; cursor:pointer; }
+ .controls .toggle input { margin:0; }
+
+ .pair {
+ background:#fff; border:1px solid var(--line); border-radius:8px;
+ margin-bottom:18px; padding:14px;
+ }
+ .pair-header {
+ display:flex; justify-content:space-between; align-items:baseline;
+ margin-bottom:10px;
+ }
+ .pair-id {
+ font:700 14px ui-monospace,Menlo,monospace; color:var(--ink);
+ }
+ .pair-stats {
+ font:600 12px ui-monospace,Menlo,monospace; color:var(--faint);
+ }
+ .pair-stats .v-before { color:var(--red); }
+ .pair-stats .v-after.pass { color:var(--green); }
+ .pair-stats .v-after.warn { color:var(--orange); }
+ .pair-stats .v-after.fail { color:var(--red); }
+
+ .duo {
+ display:grid; grid-template-columns:1fr 1fr; gap:12px;
+ }
+ .duo .panel { position:relative; }
+ .duo .panel img {
+ width:100%; aspect-ratio:1; object-fit:cover;
+ border:1px solid var(--line); border-radius:6px;
+ background:#f3eee2;
+ }
+ .duo .panel.show-bands img {
+ /* highlight the heal band */
+ }
+ .duo .panel.show-bands::after {
+ content:''; position:absolute; inset:0;
+ background:
+ linear-gradient(transparent calc(50% - 12px), rgba(255,52,52,.18) calc(50% - 12px), rgba(255,52,52,.18) calc(50% + 12px), transparent calc(50% + 12px)),
+ linear-gradient(90deg, transparent calc(50% - 12px), rgba(255,52,52,.18) calc(50% - 12px), rgba(255,52,52,.18) calc(50% + 12px), transparent calc(50% + 12px));
+ border-radius:6px;
+ pointer-events:none;
+ }
+ .duo .panel-label {
+ position:absolute; top:8px; left:8px;
+ background:rgba(0,0,0,.7); color:#fff;
+ font:700 9px var(--sans); letter-spacing:.12em; text-transform:uppercase;
+ padding:3px 7px; border-radius:3px;
+ }
+ .duo .panel-de {
+ position:absolute; bottom:8px; right:8px;
+ background:rgba(0,0,0,.65); color:#fff;
+ font:700 10px ui-monospace,Menlo,monospace;
+ padding:3px 7px; border-radius:3px;
+ }
+ .duo .panel.before .panel-de { background:rgba(179,38,30,.85); }
+ .duo .panel.after .panel-de { background:rgba(31,106,44,.85); }
+
+ .verdict-pill {
+ display:inline-block;
+ font:700 9.5px var(--sans); letter-spacing:.14em; text-transform:uppercase;
+ padding:3px 8px; border-radius:3px;
+ color:#fff;
+ }
+ .verdict-pill.PASS { background:var(--green); }
+ .verdict-pill.WARN { background:var(--orange); }
+ .verdict-pill.FAIL { background:var(--red); }
+
+ .loading { text-align:center; padding:40px; color:var(--faint); }
+
+ .decision {
+ background:var(--ink); color:#fff;
+ padding:16px 24px; border-radius:8px;
+ margin-top:20px; text-align:center;
+ }
+ .decision h3 { margin:0 0 8px; font:400 18px var(--serif); }
+ .decision p { margin:0 0 12px; color:#dcd0bb; font-size:13px; }
+ .decision .btn {
+ background:var(--gold); color:#fff; border:0; padding:10px 22px;
+ border-radius:4px; cursor:pointer; margin:0 6px;
+ font:600 11.5px var(--sans); letter-spacing:.12em; text-transform:uppercase;
+ }
+ .decision .btn.no { background:#555; }
+</style>
+</head>
+<body>
+<header>
+ <h1>Mid-Seam-Heal Preview</h1>
+ <span class="meta">20-sample · BAND=12px · SIGMA=4.0 · before vs after</span>
+ <div class="summary" id="summary">loading…</div>
+</header>
+
+<main>
+ <div class="controls">
+ <label class="toggle">
+ <input type="checkbox" id="show-bands">
+ Highlight heal bands (red overlay at H/2 and V/2)
+ </label>
+ <span style="margin-left:auto; color:var(--faint); font-size:11px;">
+ The red bands show the 24px region (12px each side of the midline) where
+ Gaussian blur σ=4 was applied. Everything outside the bands is untouched.
+ </span>
+ </div>
+
+ <div id="pairs"><div class="loading">loading sample…</div></div>
+
+ <div class="decision">
+ <h3>Eyeball check — does the blur band look acceptable?</h3>
+ <p>If yes, scale to all 7,333 mids-only FAILs for $0 (new spoon_all_designs rows,
+ round-1 originals preserved as __preseam.png backup).</p>
+ <p style="font-size:11.5px; color:var(--gold)">
+ This page is read-only. Tell Claude in chat to scale or to retune
+ (e.g. "tighter band" / "less blur" / "different sigma").
+ </p>
+ </div>
+</main>
+
+<script>
+fetch('/api/admin/mid-heal-preview/sample')
+ .then(r => r.json())
+ .then(data => {
+ if (!data.ok) {
+ document.getElementById('pairs').innerHTML =
+ `<div class="loading">error: ${data.error || 'unknown'}</div>`;
+ return;
+ }
+ const rows = data.items || [];
+ const passN = rows.filter(r => r.post_v === 'PASS').length;
+ const warnN = rows.filter(r => r.post_v === 'WARN').length;
+ const failN = rows.filter(r => r.post_v === 'FAIL').length;
+ document.getElementById('summary').innerHTML =
+ `n=${rows.length} ` +
+ `<span class="fail">${rows.length} FAIL</span> → ` +
+ `<span class="pass">${passN} PASS</span> + ` +
+ `<span class="warn">${warnN} WARN</span> + ` +
+ `<span class="fail">${failN} still FAIL</span>`;
+
+ document.getElementById('pairs').innerHTML = rows.map(r => `
+ <div class="pair">
+ <div class="pair-header">
+ <span class="pair-id">#${r.id}</span>
+ <span class="pair-stats">
+ mids ${r.pre_mids.toFixed(1)} → ${r.post_mids.toFixed(1)} ·
+ max ${r.pre_max.toFixed(1)} → ${r.post_max.toFixed(1)} ·
+ <span class="verdict-pill ${r.pre_v}">${r.pre_v}</span>
+ →
+ <span class="verdict-pill ${r.post_v}">${r.post_v}</span>
+ </span>
+ </div>
+ <div class="duo">
+ <div class="panel before">
+ <span class="panel-label">Before (source)</span>
+ <img src="${r.before_url}" loading="lazy" alt="before #${r.id}">
+ <span class="panel-de">ΔE ${r.pre_max.toFixed(1)}</span>
+ </div>
+ <div class="panel after">
+ <span class="panel-label">After (heal)</span>
+ <img src="${r.after_url}" loading="lazy" alt="after #${r.id}">
+ <span class="panel-de">ΔE ${r.post_max.toFixed(1)}</span>
+ </div>
+ </div>
+ </div>
+ `).join('');
+
+ const cb = document.getElementById('show-bands');
+ function applyBands() {
+ document.querySelectorAll('.duo .panel').forEach(p => {
+ p.classList.toggle('show-bands', cb.checked);
+ });
+ }
+ cb.addEventListener('change', applyBands);
+ })
+ .catch(err => {
+ document.getElementById('pairs').innerHTML =
+ `<div class="loading">fetch failed: ${err.message}</div>`;
+ });
+</script>
+</body>
+</html>
diff --git a/server.js b/server.js
index 8eeddba..909ba06 100644
--- a/server.js
+++ b/server.js
@@ -1080,6 +1080,43 @@ app.get('/admin/elements', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'admin', 'elements.html'));
});
+// ── /admin/mid-heal-preview — side-by-side before/after for the 20-design
+// SDXL grid-leak repair experiment. Gates the decision to scale the
+// PIL-only $0 mid-seam-blend to all 7,333 mids-only FAILs.
+app.get('/admin/mid-heal-preview', (req, res) => {
+ if (!isAdmin(req)) return res.status(404).type('html').send('<h1>404</h1>');
+ res.sendFile(path.join(__dirname, 'public', 'admin', 'mid-heal-preview.html'));
+});
+
+app.get('/api/admin/mid-heal-preview/sample', (req, res) => {
+ if (!isAdmin(req)) return res.status(404).json({ error: 'not found' });
+ try {
+ const ledgerPath = '/tmp/seam-heal-experiment.json';
+ if (!fs.existsSync(ledgerPath)) {
+ return res.json({ ok: false, error: 'ledger missing — run seam_heal_experiment.py first' });
+ }
+ const rows = JSON.parse(fs.readFileSync(ledgerPath, 'utf8'));
+ const items = rows.map(r => {
+ const fp = r.fixed_path || '';
+ // fixed_path is data/generated/<name>.__midheal.png — serve via /designs/img/<basename>
+ const after_url = fp ? '/designs/img/' + path.basename(fp) : null;
+ // before_url = source served by-id (route handles missing-from-cache)
+ const before_url = `/designs/img/by-id/${r.id}`;
+ return {
+ id: r.id,
+ pre_mids: r.pre_mids, post_mids: r.post_mids,
+ pre_edges: r.pre_edges, post_edges: r.post_edges,
+ pre_max: r.pre_max, post_max: r.post_max,
+ pre_v: r.pre_v, post_v: r.post_v,
+ before_url, after_url,
+ };
+ });
+ res.json({ ok: true, items });
+ } catch (err) {
+ res.status(500).json({ ok: false, error: err.message });
+ }
+});
+
// Serve baked element derivatives. These live outside the public
// /designs/img/ tree so they can be cleared without touching source tiles.
app.use('/elements/img', express.static(
← 50890a3 elements skill: /admin/elements browse UI + bake-at-ingest p
·
back to Wallco Ai
·
gitignore: exclude data/elements (6GB), data/rooms (141MB), 3190409 →