[object Object]

← back to Wallco Ai

Add live variant-curator for Wave-1 drunk-animal composition variants

96285b02c92521db4b8f1db78fc568970876cd08 · 2026-06-12 08:20:47 -0700 · Steve Abrams

New /admin/variant-curator (admin-gated) + /api/variant-curator + pick endpoint.
One row per root: root thumb + up-to-10 unpublished variant children, auto-poll
every 5s so new variants appear live as variants-9roots.py lands them. Multi-keep
toggle for variety. Each card shows the 🕓 created date+time chip (standing rule).

KEEP is durable via a local sidecar wallco_variant_picks (PK-backed → UPDATE-able)
rather than UPDATE-ing all_designs, which is INSERT-only on Mac2 (no replica
identity in FOR-ALL-TABLES publication dw_unified_pub). Roots never touched; real
is_published flip to live stays a Steve-gated Kamatera export. DTD verdict A
(unanimous). Nav link added to the admin hub.

Files touched

Diff

commit 96285b02c92521db4b8f1db78fc568970876cd08
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Fri Jun 12 08:20:47 2026 -0700

    Add live variant-curator for Wave-1 drunk-animal composition variants
    
    New /admin/variant-curator (admin-gated) + /api/variant-curator + pick endpoint.
    One row per root: root thumb + up-to-10 unpublished variant children, auto-poll
    every 5s so new variants appear live as variants-9roots.py lands them. Multi-keep
    toggle for variety. Each card shows the 🕓 created date+time chip (standing rule).
    
    KEEP is durable via a local sidecar wallco_variant_picks (PK-backed → UPDATE-able)
    rather than UPDATE-ing all_designs, which is INSERT-only on Mac2 (no replica
    identity in FOR-ALL-TABLES publication dw_unified_pub). Roots never touched; real
    is_published flip to live stays a Steve-gated Kamatera export. DTD verdict A
    (unanimous). Nav link added to the admin hub.
---
 data/cactus-decisions.jsonl     |   4 +
 data/fliepaper-bugs             |   1 +
 data/logs/gate-rejections.jsonl |   5 +
 data/seam-fix-queue.jsonl       |  10 +
 data/seam-warn-animal-kept.txt  | 100 +++++
 data/seam-warn-roots.txt        | 793 ++++++++++++++++++++++++++++++++++++++++
 data/variants-9roots.jsonl      |   6 +
 public/variant-curator.html     | 164 +++++++++
 server.js                       | 139 +++++++
 9 files changed, 1222 insertions(+)

diff --git a/data/cactus-decisions.jsonl b/data/cactus-decisions.jsonl
index 3787859..4b49148 100644
--- a/data/cactus-decisions.jsonl
+++ b/data/cactus-decisions.jsonl
@@ -11469,3 +11469,7 @@
 {"ts":"2026-06-09T19:22:20.555Z","id":41519,"action":"bad"}
 {"ts":"2026-06-09T19:22:28.153Z","id":38413,"action":"bad"}
 {"ts":"2026-06-09T19:23:26.733Z","id":53676,"action":"bad"}
+{"ts":"2026-06-09T21:58:20.075Z","id":53661,"action":"live"}
+{"ts":"2026-06-09T22:36:31.416Z","id":10550,"action":"bad"}
+{"ts":"2026-06-09T22:36:35.704Z","id":11498,"action":"bad"}
+{"ts":"2026-06-09T22:37:44.222Z","id":10549,"action":"bad"}
diff --git a/data/fliepaper-bugs b/data/fliepaper-bugs
new file mode 120000
index 0000000..1f4ec28
--- /dev/null
+++ b/data/fliepaper-bugs
@@ -0,0 +1 @@
+../public/data/fliepaper-bugs
\ No newline at end of file
diff --git a/data/logs/gate-rejections.jsonl b/data/logs/gate-rejections.jsonl
new file mode 100644
index 0000000..6f672cb
--- /dev/null
+++ b/data/logs/gate-rejections.jsonl
@@ -0,0 +1,5 @@
+{"ts":"2026-06-09T21:09:02.918Z","seed":"1277645893","file":"1781038906053_1277645893.png","gate":"seamless-tile","reason":"SEAMLESS_FAIL_LR tb=6.94 lr=26.21","category":"geometric-block-leaves","kind":"seamless_tile"}
+{"ts":"2026-06-09T21:14:08.646Z","seed":"208527289","file":"1781039211902_208527289.png","gate":"seamless-tile","reason":"SEAMLESS_FAIL_LR tb=8.28 lr=12.02","category":"cactus","kind":"seamless_tile"}
+{"ts":"2026-06-09T21:44:55.553Z","seed":"1030954561","file":"1781041191437_1030954561.png","gate":"seamless-tile","reason":"SEAMLESS_FAIL_LR tb=4.85 lr=13.6","category":"cactus","kind":"seamless_tile"}
+{"ts":"2026-06-09T22:32:11.963Z","seed":"988865451","file":"1781044096310_988865451.png","gate":"seamless-tile","reason":"SEAMLESS_FAIL_LR tb=4.75 lr=12.94","category":"drunk-animals","kind":"seamless_tile"}
+{"ts":"2026-06-12T02:09:14.740Z","seed":"1085770820","file":"1781229719778_1085770820.png","gate":"seamless-tile","reason":"SEAMLESS_FAIL_LR tb=7.03 lr=18.06","category":"drunk-animals","kind":"seamless_tile"}
diff --git a/data/seam-fix-queue.jsonl b/data/seam-fix-queue.jsonl
index 4393101..05491c3 100644
--- a/data/seam-fix-queue.jsonl
+++ b/data/seam-fix-queue.jsonl
@@ -188,3 +188,13 @@
 {"ts": "2026-06-11T23:45:41.880222Z", "root_id": 54076, "variant": "controlnet-anchored-reroll-2", "generator": "controlnet-anchored-reroll-2", "category": "drunk-animals", "subject": "shaggy orange orangutan clutching a banana cocktail, painkiller cocktail in a wide rocks glass with grated nutmeg dusting on top", "animal": "orangutan", "ground": "natural linen", "seed": 1385132858, "base_hex": "#c09060", "cn_strength": 0.37, "cn_end": 0.45, "crop_box": [272, 96, 266], "coverage_pct": 17.3, "attempts_used": 2, "attempts": [{"attempt": 1, "seed": 971004480, "cn_strength": 0.4, "motif_edge": "WARN", "h": "WARN", "v": "WARN", "h_tiled": 24.05, "v_tiled": 17.85, "coverage_pct": 20.8, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781221290763_971004480_reroll2_motif.png"}, {"attempt": 2, "seed": 1385132858, "cn_strength": 0.37, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 5.82, "v_tiled": 0.22, "coverage_pct": 17.3, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781221418498_1385132858_reroll2_motif.png"}], "technique": "canny-SDXL-CN-anchored native-seamless txt2img (SeamlessTile+MakeCircularVAE, denoise 1.0, tighter focal canny crop) + SEAM-RETRY-until-motif-PASS-both-axes + deterministic real-fibre composite \u2014 NO smear", "edge_verdict": "PASS", "edge_seamless": true, "edge_axes": {"h": {"verdict": "PASS", "line_diff": 1.96, "line_diff_halfdrop": 23.05, "best": 1.96, "tiled_cross_seam_max": 5.34, "edges": "column[0] vs column[W-1]"}, "v": {"verdict": "PASS", "line_diff": 0.0, "line_diff_halfdrop": 13.82, "best": 0.0, "tiled_cross_seam_max": 0.26, "edges": "row[0] vs row[H-1]"}}, "motif_edge_verdict": "PASS", "new_id": 10000016, "hint": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781221290750_54076_reroll2_hint.png", "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781221418498_1385132858_reroll2_motif.png", "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781221418498_1385132858_reroll2.png", "ok": true}
 {"ts": "2026-06-11T23:49:35.469877Z", "root_id": 54266, "variant": "controlnet-anchored-reroll-2", "generator": "controlnet-anchored-reroll-2", "category": "drunk-animals", "subject": "wide-eyed Amazonian tree frog, pyramid-tower of stacked champagne coupes", "animal": "tree frog", "ground": "raffia", "seed": 1102319585, "base_hex": "#909080", "cn_strength": 0.38, "cn_end": 0.42, "crop_box": [420, 195, 245], "coverage_pct": 28.7, "attempts_used": 1, "attempts": [{"attempt": 1, "seed": 1102319585, "cn_strength": 0.38, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 9.84, "v_tiled": 8.51, "coverage_pct": 28.7, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781221542078_1102319585_reroll2_motif.png"}], "technique": "canny-SDXL-CN-anchored native-seamless txt2img (SeamlessTile+MakeCircularVAE, denoise 1.0, tighter focal canny crop) + SEAM-RETRY-until-motif-PASS-both-axes + deterministic real-fibre composite \u2014 NO smear", "edge_verdict": "PASS", "edge_seamless": true, "edge_axes": {"h": {"verdict": "PASS", "line_diff": 2.79, "line_diff_halfdrop": 50.79, "best": 2.79, "tiled_cross_seam_max": 9.7, "edges": "column[0] vs column[W-1]"}, "v": {"verdict": "PASS", "line_diff": 4.95, "line_diff_halfdrop": 64.52, "best": 4.95, "tiled_cross_seam_max": 10.04, "edges": "row[0] vs row[H-1]"}}, "motif_edge_verdict": "PASS", "new_id": 10000017, "hint": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781221542069_54266_reroll2_hint.png", "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781221542078_1102319585_reroll2_motif.png", "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781221542078_1102319585_reroll2.png", "ok": true}
 {"ts": "2026-06-12T02:54:30.357259Z", "root_id": 55272, "variant": "controlnet-anchored-reroll-2", "generator": "controlnet-anchored-reroll", "category": "drunk-animals", "subject": "wobbly pink champagne elephant, zombie cocktail in a tall chimney glass \u2014 three-color sunset gradient", "animal": "elephant", "ground": "natural linen", "seed": 856748299, "base_hex": "#e090a0", "cn_strength": 0.44, "cn_end": 0.55, "mode": "canny", "subject_recovered": true, "crop_box": [380, 304, 307], "coverage_pct": 12.7, "attempts_used": 3, "attempts": [{"attempt": 1, "seed": 724087732, "mode": "canny", "cn_strength": 0.5, "motif_edge": "WARN", "h": "WARN", "v": "WARN", "h_tiled": 13.88, "v_tiled": 30.93, "coverage_pct": 21.3, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781232363781_724087732_reroll2_motif.png"}, {"attempt": 2, "seed": 1000621086, "mode": "canny", "cn_strength": 0.47, "motif_edge": "WARN", "h": "WARN", "v": "PASS", "h_tiled": 13.49, "v_tiled": 6.04, "coverage_pct": 49.5, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781232601010_1000621086_reroll2_motif.png"}, {"attempt": 3, "seed": 856748299, "mode": "canny", "cn_strength": 0.44, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 0.33, "v_tiled": 6.04, "coverage_pct": 12.7, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781232729214_856748299_reroll2_motif.png", "subject_recovered": true}], "technique": "canny-SDXL-CN-anchored native-seamless txt2img (tighter focal crop) + SEAM-RETRY-until-motif-PASS-both-axes + Gemini subject-recovery gate + deterministic real-fibre composite \u2014 NO smear", "edge_verdict": "PASS", "edge_seamless": true, "edge_axes": {"h": {"verdict": "PASS", "line_diff": 0.0, "line_diff_halfdrop": 16.79, "best": 0.0, "tiled_cross_seam_max": 0.29, "edges": "column[0] vs column[W-1]"}, "v": {"verdict": "PASS", "line_diff": 1.34, "line_diff_halfdrop": 21.93, "best": 1.34, "tiled_cross_seam_max": 4.35, "edges": "row[0] vs row[H-1]"}}, "motif_edge_verdict": "PASS", "new_id": 10000018, "hint": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781232363768_55272_reroll2_hint.png", "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781232729214_856748299_reroll2_motif.png", "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781232729214_856748299_reroll2.png", "ok": true}
+{"ts": "2026-06-12T03:23:25.410236Z", "root_id": 2656, "variant": "controlnet-anchored-reroll-2", "generator": "controlnet-anchored-reroll", "category": "drunk-animals", "subject": "plastered red panda, gripping a pale-gold pilsner glass in one paw", "animal": "red panda", "ground": "raffia", "seed": 1011370191, "base_hex": "#f0f0f0", "cn_strength": 0.35, "cn_end": 0.55, "mode": "canny", "subject_recovered": true, "crop_box": [0, 361, 307], "coverage_pct": 26.8, "attempts_used": 6, "attempts": [{"attempt": 1, "seed": 555215139, "mode": "canny", "cn_strength": 0.5, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 2.79, "v_tiled": 0.06, "coverage_pct": 12.5, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781233725865_555215139_reroll2_motif.png", "subject_recovered": false}, {"attempt": 2, "seed": 1204731116, "mode": "canny", "cn_strength": 0.47, "motif_edge": "WARN", "h": "PASS", "v": "WARN", "h_tiled": 7.71, "v_tiled": 15.69, "coverage_pct": 13.8, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781233863022_1204731116_reroll2_motif.png"}, {"attempt": 3, "seed": 514194282, "mode": "canny", "cn_strength": 0.44, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 8.49, "v_tiled": 10.35, "coverage_pct": 51.3, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781233989645_514194282_reroll2_motif.png"}, {"attempt": 4, "seed": 1101879628, "mode": "canny", "cn_strength": 0.41, "motif_edge": "WARN", "h": "PASS", "v": "WARN", "h_tiled": 0.06, "v_tiled": 15.54, "coverage_pct": 40.7, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781234114350_1101879628_reroll2_motif.png"}, {"attempt": 5, "seed": 920562721, "mode": "canny", "cn_strength": 0.38, "motif_edge": "WARN", "h": "WARN", "v": "WARN", "h_tiled": 24.82, "v_tiled": 15.53, "coverage_pct": 17.4, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781234346612_920562721_reroll2_motif.png"}, {"attempt": 6, "seed": 1011370191, "mode": "canny", "cn_strength": 0.35, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 0.05, "v_tiled": 0.01, "coverage_pct": 26.8, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781234472439_1011370191_reroll2_motif.png", "subject_recovered": true}], "technique": "canny-SDXL-CN-anchored native-seamless txt2img (tighter focal crop) + SEAM-RETRY-until-motif-PASS-both-axes + Gemini subject-recovery gate + deterministic real-fibre composite \u2014 NO smear", "edge_verdict": "PASS", "edge_seamless": true, "edge_axes": {"h": {"verdict": "PASS", "line_diff": 0.02, "line_diff_halfdrop": 71.0, "best": 0.02, "tiled_cross_seam_max": 0.32, "edges": "column[0] vs column[W-1]"}, "v": {"verdict": "PASS", "line_diff": 0.0, "line_diff_halfdrop": 39.3, "best": 0.0, "tiled_cross_seam_max": 0.54, "edges": "row[0] vs row[H-1]"}}, "motif_edge_verdict": "PASS", "new_id": 10000019, "hint": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781233725851_2656_reroll2_hint.png", "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781234472439_1011370191_reroll2_motif.png", "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781234472439_1011370191_reroll2.png", "ok": true}
+{"ts": "2026-06-12T03:31:56.983809Z", "root_id": 2766, "variant": "controlnet-anchored-reroll-2", "generator": "controlnet-anchored-reroll", "category": "drunk-animals", "subject": "wide-eyed Amazonian tree frog, mid-toast with a champagne flute", "animal": "tree frog", "ground": "natural linen", "seed": 983323966, "base_hex": "#d0c0b0", "cn_strength": 0.41, "cn_end": 0.55, "mode": "canny", "subject_recovered": true, "crop_box": [551, 361, 307], "coverage_pct": 30.7, "attempts_used": 4, "attempts": [{"attempt": 1, "seed": 310503841, "mode": "canny", "cn_strength": 0.5, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 0.08, "v_tiled": 0.13, "coverage_pct": 9.4, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781234605638_310503841_reroll2_motif.png", "subject_recovered": false}, {"attempt": 2, "seed": 135646735, "mode": "canny", "cn_strength": 0.47, "motif_edge": "WARN", "h": "WARN", "v": "PASS", "h_tiled": 27.99, "v_tiled": 1.96, "coverage_pct": 28.4, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781234733125_135646735_reroll2_motif.png"}, {"attempt": 3, "seed": 933022117, "mode": "canny", "cn_strength": 0.44, "motif_edge": "WARN", "h": "WARN", "v": "PASS", "h_tiled": 22.17, "v_tiled": 0.28, "coverage_pct": 49.1, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781234858989_933022117_reroll2_motif.png"}, {"attempt": 4, "seed": 983323966, "mode": "canny", "cn_strength": 0.41, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 2.88, "v_tiled": 0.1, "coverage_pct": 30.7, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781234983025_983323966_reroll2_motif.png", "subject_recovered": true}], "technique": "canny-SDXL-CN-anchored native-seamless txt2img (tighter focal crop) + SEAM-RETRY-until-motif-PASS-both-axes + Gemini subject-recovery gate + deterministic real-fibre composite \u2014 NO smear", "edge_verdict": "PASS", "edge_seamless": true, "edge_axes": {"h": {"verdict": "PASS", "line_diff": 0.31, "line_diff_halfdrop": 50.62, "best": 0.31, "tiled_cross_seam_max": 3.11, "edges": "column[0] vs column[W-1]"}, "v": {"verdict": "PASS", "line_diff": 0.0, "line_diff_halfdrop": 19.3, "best": 0.0, "tiled_cross_seam_max": 0.36, "edges": "row[0] vs row[H-1]"}}, "motif_edge_verdict": "PASS", "new_id": 10000020, "hint": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781234605628_2766_reroll2_hint.png", "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781234983025_983323966_reroll2_motif.png", "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781234983025_983323966_reroll2.png", "ok": true}
+{"ts": "2026-06-12T03:35:55.042161Z", "root_id": 3391, "variant": "controlnet-anchored-reroll-2", "generator": "controlnet-anchored-reroll", "category": "drunk-animals", "subject": "jolly grey African elephant calf, two paws on a hand-blown wine bottle", "animal": "elephant", "ground": "sisal", "seed": 1810887479, "base_hex": "#e0e0e0", "cn_strength": 0.5, "cn_end": 0.55, "mode": "canny", "subject_recovered": true, "crop_box": [418, 703, 307], "coverage_pct": 32.2, "attempts_used": 1, "attempts": [{"attempt": 1, "seed": 1810887479, "mode": "canny", "cn_strength": 0.5, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 4.3, "v_tiled": 0.01, "coverage_pct": 32.2, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781235117206_1810887479_reroll2_motif.png", "subject_recovered": true}], "technique": "canny-SDXL-CN-anchored native-seamless txt2img (tighter focal crop) + SEAM-RETRY-until-motif-PASS-both-axes + Gemini subject-recovery gate + deterministic real-fibre composite \u2014 NO smear", "edge_verdict": "PASS", "edge_seamless": true, "edge_axes": {"h": {"verdict": "PASS", "line_diff": 0.31, "line_diff_halfdrop": 55.86, "best": 0.31, "tiled_cross_seam_max": 4.41, "edges": "column[0] vs column[W-1]"}, "v": {"verdict": "PASS", "line_diff": 0.0, "line_diff_halfdrop": 25.75, "best": 0.0, "tiled_cross_seam_max": 0.46, "edges": "row[0] vs row[H-1]"}}, "motif_edge_verdict": "PASS", "new_id": 10000021, "hint": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781235117195_3391_reroll2_hint.png", "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781235117206_1810887479_reroll2_motif.png", "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781235117206_1810887479_reroll2.png", "ok": true}
+{"ts": "2026-06-12T04:11:50.494284Z", "root_id": 53999, "variant": "controlnet-anchored-reroll-2", "generator": "controlnet-anchored-reroll", "category": "drunk-animals", "subject": "pink-cheeked drunken bullfrog, red-star amber-lager bottle gripped tight", "animal": "frog", "ground": "grasscloth", "seed": 1607144552, "base_hex": "#f0f0e0", "cn_strength": 0.32, "cn_end": 0.55, "mode": "canny", "subject_recovered": true, "crop_box": [608, 133, 307], "coverage_pct": 35.3, "attempts_used": 7, "attempts": [{"attempt": 1, "seed": 1618320389, "mode": "canny", "cn_strength": 0.5, "motif_edge": "FAIL", "h": "WARN", "v": "FAIL", "h_tiled": 37.95, "v_tiled": 58.61, "coverage_pct": 29.7, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781236502701_1618320389_reroll2_motif.png"}, {"attempt": 2, "seed": 2004843499, "mode": "canny", "cn_strength": 0.47, "motif_edge": "FAIL", "h": "WARN", "v": "FAIL", "h_tiled": 28.09, "v_tiled": 38.23, "coverage_pct": 30.0, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781236627212_2004843499_reroll2_motif.png"}, {"attempt": 3, "seed": 314974783, "mode": "canny", "cn_strength": 0.44, "motif_edge": "WARN", "h": "WARN", "v": "WARN", "h_tiled": 43.76, "v_tiled": 16.32, "coverage_pct": 44.6, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781236749652_314974783_reroll2_motif.png"}, {"attempt": 4, "seed": 611925982, "mode": "canny", "cn_strength": 0.41, "motif_edge": "WARN", "h": "WARN", "v": "WARN", "h_tiled": 34.3, "v_tiled": 28.68, "coverage_pct": 52.6, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781236874923_611925982_reroll2_motif.png"}, {"attempt": 5, "seed": 2076377898, "mode": "canny", "cn_strength": 0.38, "motif_edge": "WARN", "h": "PASS", "v": "WARN", "h_tiled": 2.23, "v_tiled": 15.19, "coverage_pct": 18.4, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781237111879_2076377898_reroll2_motif.png"}, {"attempt": 6, "seed": 225034007, "mode": "canny", "cn_strength": 0.35, "motif_edge": "WARN", "h": "WARN", "v": "WARN", "h_tiled": 21.33, "v_tiled": 41.59, "coverage_pct": 52.0, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781237240415_225034007_reroll2_motif.png"}, {"attempt": 7, "seed": 1607144552, "mode": "canny", "cn_strength": 0.32, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 0.12, "v_tiled": 0.12, "coverage_pct": 35.3, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781237368957_1607144552_reroll2_motif.png", "subject_recovered": true}], "technique": "canny-SDXL-CN-anchored native-seamless txt2img (tighter focal crop) + SEAM-RETRY-until-motif-PASS-both-axes + Gemini subject-recovery gate + deterministic real-fibre composite \u2014 NO smear", "edge_verdict": "PASS", "edge_seamless": true, "edge_axes": {"h": {"verdict": "PASS", "line_diff": 0.02, "line_diff_halfdrop": 36.88, "best": 0.02, "tiled_cross_seam_max": 0.44, "edges": "column[0] vs column[W-1]"}, "v": {"verdict": "PASS", "line_diff": 0.05, "line_diff_halfdrop": 55.8, "best": 0.05, "tiled_cross_seam_max": 0.23, "edges": "row[0] vs row[H-1]"}}, "motif_edge_verdict": "PASS", "new_id": 10000022, "hint": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781236502686_53999_reroll2_hint.png", "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781237368957_1607144552_reroll2_motif.png", "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781237368957_1607144552_reroll2.png", "ok": true}
+{"ts": "2026-06-12T04:14:00.836947Z", "root_id": 54002, "variant": "controlnet-anchored-reroll-2", "generator": "controlnet-anchored-reroll", "category": "drunk-animals", "subject": "jolly grey African elephant calf, jeroboam champagne bottle taller than the animal itself", "animal": "elephant", "ground": "raffia", "seed": 1993398038, "base_hex": "#f0f0e0", "cn_strength": 0.5, "cn_end": 0.55, "mode": "canny", "subject_recovered": true, "crop_box": [418, 190, 307], "coverage_pct": 20.3, "attempts_used": 1, "attempts": [{"attempt": 1, "seed": 1993398038, "mode": "canny", "cn_strength": 0.5, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 9.44, "v_tiled": 0.14, "coverage_pct": 20.3, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781237510780_1993398038_reroll2_motif.png", "subject_recovered": true}], "technique": "canny-SDXL-CN-anchored native-seamless txt2img (tighter focal crop) + SEAM-RETRY-until-motif-PASS-both-axes + Gemini subject-recovery gate + deterministic real-fibre composite \u2014 NO smear", "edge_verdict": "PASS", "edge_seamless": true, "edge_axes": {"h": {"verdict": "PASS", "line_diff": 0.35, "line_diff_halfdrop": 34.37, "best": 0.35, "tiled_cross_seam_max": 9.15, "edges": "column[0] vs column[W-1]"}, "v": {"verdict": "PASS", "line_diff": 0.0, "line_diff_halfdrop": 38.63, "best": 0.0, "tiled_cross_seam_max": 0.6, "edges": "row[0] vs row[H-1]"}}, "motif_edge_verdict": "PASS", "new_id": 10000023, "hint": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781237510767_54002_reroll2_hint.png", "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781237510780_1993398038_reroll2_motif.png", "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781237510780_1993398038_reroll2.png", "ok": true}
+{"ts": "2026-06-12T04:41:12.212647Z", "root_id": 54092, "variant": "controlnet-anchored-reroll-2", "generator": "controlnet-anchored-reroll", "category": "drunk-animals", "subject": "sloshed scarlet macaw, champagne saber poised \u2014 vintage cavalry-style sabre about to slice the bottle neck off", "animal": "animal", "ground": "sisal", "seed": 671030467, "base_hex": "#e0d0c0", "cn_strength": 0.47, "cn_end": 0.55, "mode": "canny", "subject_recovered": true, "crop_box": [304, 0, 307], "coverage_pct": 10.1, "attempts_used": 2, "attempts": [{"attempt": 1, "seed": 262362179, "mode": "canny", "cn_strength": 0.5, "motif_edge": "WARN", "h": "WARN", "v": "PASS", "h_tiled": 33.46, "v_tiled": 2.98, "coverage_pct": 24.7, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781239002221_262362179_reroll2_motif.png"}, {"attempt": 2, "seed": 671030467, "mode": "canny", "cn_strength": 0.47, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 0.3, "v_tiled": 0.17, "coverage_pct": 10.1, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781239133674_671030467_reroll2_motif.png", "subject_recovered": true}], "technique": "canny-SDXL-CN-anchored native-seamless txt2img (tighter focal crop) + SEAM-RETRY-until-motif-PASS-both-axes + Gemini subject-recovery gate + deterministic real-fibre composite \u2014 NO smear", "edge_verdict": "PASS", "edge_seamless": true, "edge_axes": {"h": {"verdict": "PASS", "line_diff": 0.02, "line_diff_halfdrop": 31.75, "best": 0.02, "tiled_cross_seam_max": 0.8, "edges": "column[0] vs column[W-1]"}, "v": {"verdict": "PASS", "line_diff": 0.0, "line_diff_halfdrop": 23.97, "best": 0.0, "tiled_cross_seam_max": 0.44, "edges": "row[0] vs row[H-1]"}}, "motif_edge_verdict": "PASS", "new_id": 10000024, "hint": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781239002210_54092_reroll2_hint.png", "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781239133674_671030467_reroll2_motif.png", "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781239133674_671030467_reroll2.png", "ok": true}
+{"ts": "2026-06-12T04:59:54.858174Z", "root_id": 54110, "variant": "controlnet-anchored-reroll-2", "generator": "controlnet-anchored-reroll", "category": "drunk-animals", "subject": "shaggy orange orangutan clutching a banana cocktail, one paw around a jet-black stout pint", "animal": "orangutan", "ground": "paperweave", "seed": 1280313471, "base_hex": "#e0d0c0", "cn_strength": 0.3, "cn_end": 0.55, "mode": "canny", "subject_recovered": true, "crop_box": [703, 209, 307], "coverage_pct": 33.4, "attempts_used": 8, "attempts": [{"attempt": 1, "seed": 652518521, "mode": "canny", "cn_strength": 0.5, "motif_edge": "WARN", "h": "WARN", "v": "PASS", "h_tiled": 15.99, "v_tiled": 8.17, "coverage_pct": 42.4, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781239272445_652518521_reroll2_motif.png"}, {"attempt": 2, "seed": 637132867, "mode": "canny", "cn_strength": 0.47, "motif_edge": "WARN", "h": "PASS", "v": "WARN", "h_tiled": 1.75, "v_tiled": 28.23, "coverage_pct": 48.0, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781239399686_637132867_reroll2_motif.png"}, {"attempt": 3, "seed": 1530898661, "mode": "canny", "cn_strength": 0.44, "motif_edge": "FAIL", "h": "FAIL", "v": "FAIL", "h_tiled": 0.15, "v_tiled": 0.21, "coverage_pct": 34.3, "cov_ok": true, "isolated_motif": true, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781239522421_1530898661_reroll2_motif.png"}, {"attempt": 4, "seed": 671122951, "mode": "canny", "cn_strength": 0.41, "motif_edge": "WARN", "h": "WARN", "v": "WARN", "h_tiled": 21.07, "v_tiled": 13.98, "coverage_pct": 34.5, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781239767499_671122951_reroll2_motif.png"}, {"attempt": 5, "seed": 1129290253, "mode": "canny", "cn_strength": 0.38, "motif_edge": "WARN", "h": "WARN", "v": "WARN", "h_tiled": 17.38, "v_tiled": 28.02, "coverage_pct": 64.9, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781239889865_1129290253_reroll2_motif.png"}, {"attempt": 6, "seed": 1706906133, "mode": "canny", "cn_strength": 0.35, "motif_edge": "FAIL", "h": "FAIL", "v": "WARN", "h_tiled": 126.72, "v_tiled": 19.03, "coverage_pct": 33.8, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781240017501_1706906133_reroll2_motif.png"}, {"attempt": 7, "seed": 1059048280, "mode": "canny", "cn_strength": 0.32, "motif_edge": "WARN", "h": "WARN", "v": "WARN", "h_tiled": 57.01, "v_tiled": 44.79, "coverage_pct": 64.7, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781240140328_1059048280_reroll2_motif.png"}, {"attempt": 8, "seed": 1280313471, "mode": "canny", "cn_strength": 0.3, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 0.14, "v_tiled": 8.47, "coverage_pct": 33.4, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781240263142_1280313471_reroll2_motif.png", "subject_recovered": true}], "technique": "canny-SDXL-CN-anchored native-seamless txt2img (tighter focal crop) + SEAM-RETRY-until-motif-PASS-both-axes + Gemini subject-recovery gate + deterministic real-fibre composite \u2014 NO smear", "edge_verdict": "PASS", "edge_seamless": true, "edge_axes": {"h": {"verdict": "PASS", "line_diff": 0.0, "line_diff_halfdrop": 19.93, "best": 0.0, "tiled_cross_seam_max": 0.35, "edges": "column[0] vs column[W-1]"}, "v": {"verdict": "PASS", "line_diff": 1.04, "line_diff_halfdrop": 77.92, "best": 1.04, "tiled_cross_seam_max": 7.84, "edges": "row[0] vs row[H-1]"}}, "motif_edge_verdict": "PASS", "new_id": 10000025, "hint": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781239272434_54110_reroll2_hint.png", "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781240263142_1280313471_reroll2_motif.png", "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781240263142_1280313471_reroll2.png", "ok": true}
+{"ts": "2026-06-12T05:02:04.964038Z", "root_id": 54112, "variant": "controlnet-anchored-reroll-2", "generator": "controlnet-anchored-reroll", "category": "drunk-animals", "subject": "jolly grey African elephant calf, tiki ceramic mug shaped like a hula dancer", "animal": "elephant", "ground": "grasscloth", "seed": 855636312, "base_hex": "#b0a0a0", "cn_strength": 0.5, "cn_end": 0.55, "mode": "canny", "subject_recovered": true, "crop_box": [171, 703, 307], "coverage_pct": 10.7, "attempts_used": 1, "attempts": [{"attempt": 1, "seed": 855636312, "mode": "canny", "cn_strength": 0.5, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 10.95, "v_tiled": 0.21, "coverage_pct": 10.7, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781240395159_855636312_reroll2_motif.png", "subject_recovered": true}], "technique": "canny-SDXL-CN-anchored native-seamless txt2img (tighter focal crop) + SEAM-RETRY-until-motif-PASS-both-axes + Gemini subject-recovery gate + deterministic real-fibre composite \u2014 NO smear", "edge_verdict": "PASS", "edge_seamless": true, "edge_axes": {"h": {"verdict": "PASS", "line_diff": 2.08, "line_diff_halfdrop": 55.59, "best": 2.08, "tiled_cross_seam_max": 9.64, "edges": "column[0] vs column[W-1]"}, "v": {"verdict": "PASS", "line_diff": 0.0, "line_diff_halfdrop": 21.38, "best": 0.0, "tiled_cross_seam_max": 0.3, "edges": "row[0] vs row[H-1]"}}, "motif_edge_verdict": "PASS", "new_id": 10000026, "hint": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781240395145_54112_reroll2_hint.png", "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781240395159_855636312_reroll2_motif.png", "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781240395159_855636312_reroll2.png", "ok": true}
+{"ts": "2026-06-12T06:09:04.246121Z", "root_id": 54290, "variant": "controlnet-anchored-reroll-2", "generator": "controlnet-anchored-reroll", "category": "drunk-animals", "subject": "shaggy orange orangutan clutching a banana cocktail, clutching a long-stemmed red wine glass", "animal": "orangutan", "ground": "paperweave", "seed": 1180017874, "base_hex": "#e0e0d0", "cn_strength": 0.41, "cn_end": 0.55, "mode": "canny", "subject_recovered": true, "crop_box": [0, 608, 307], "coverage_pct": 23.6, "attempts_used": 4, "attempts": [{"attempt": 1, "seed": 1856411779, "mode": "canny", "cn_strength": 0.5, "motif_edge": "WARN", "h": "PASS", "v": "WARN", "h_tiled": 5.39, "v_tiled": 26.58, "coverage_pct": 30.3, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781244023062_1856411779_reroll2_motif.png"}, {"attempt": 2, "seed": 524654614, "mode": "canny", "cn_strength": 0.47, "motif_edge": "WARN", "h": "WARN", "v": "WARN", "h_tiled": 21.59, "v_tiled": 16.74, "coverage_pct": 25.7, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781244159140_524654614_reroll2_motif.png"}, {"attempt": 3, "seed": 982910357, "mode": "canny", "cn_strength": 0.44, "motif_edge": "WARN", "h": "WARN", "v": "WARN", "h_tiled": 44.85, "v_tiled": 13.13, "coverage_pct": 46.9, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781244283954_982910357_reroll2_motif.png"}, {"attempt": 4, "seed": 1180017874, "mode": "canny", "cn_strength": 0.41, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 10.74, "v_tiled": 0.03, "coverage_pct": 23.6, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781244411136_1180017874_reroll2_motif.png", "subject_recovered": true}], "technique": "canny-SDXL-CN-anchored native-seamless txt2img (tighter focal crop) + SEAM-RETRY-until-motif-PASS-both-axes + Gemini subject-recovery gate + deterministic real-fibre composite \u2014 NO smear", "edge_verdict": "PASS", "edge_seamless": true, "edge_axes": {"h": {"verdict": "PASS", "line_diff": 0.64, "line_diff_halfdrop": 113.5, "best": 0.64, "tiled_cross_seam_max": 9.71, "edges": "column[0] vs column[W-1]"}, "v": {"verdict": "PASS", "line_diff": 0.0, "line_diff_halfdrop": 21.52, "best": 0.0, "tiled_cross_seam_max": 0.27, "edges": "row[0] vs row[H-1]"}}, "motif_edge_verdict": "PASS", "new_id": 10000027, "hint": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781244023028_54290_reroll2_hint.png", "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781244411136_1180017874_reroll2_motif.png", "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781244411136_1180017874_reroll2.png", "ok": true}
+{"ts": "2026-06-12T06:35:07.004969Z", "root_id": 54303, "variant": "controlnet-anchored-reroll-2", "generator": "controlnet-anchored-reroll", "category": "drunk-animals", "subject": "jolly grey African elephant calf, one paw around a jet-black stout pint", "animal": "elephant", "ground": "grasscloth", "seed": 1747039360, "base_hex": "#d0d0c0", "cn_strength": 0.32, "cn_end": 0.55, "mode": "canny", "subject_recovered": true, "crop_box": [228, 437, 307], "coverage_pct": 34.1, "attempts_used": 7, "attempts": [{"attempt": 1, "seed": 2010705802, "mode": "canny", "cn_strength": 0.5, "motif_edge": "WARN", "h": "WARN", "v": "WARN", "h_tiled": 54.8, "v_tiled": 18.13, "coverage_pct": 39.6, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781245026170_2010705802_reroll2_motif.png"}, {"attempt": 2, "seed": 811005274, "mode": "canny", "cn_strength": 0.47, "motif_edge": "WARN", "h": "WARN", "v": "PASS", "h_tiled": 12.58, "v_tiled": 0.17, "coverage_pct": 48.0, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781245194041_811005274_reroll2_motif.png"}, {"attempt": 3, "seed": 2135433976, "mode": "canny", "cn_strength": 0.44, "motif_edge": "FAIL", "h": "WARN", "v": "FAIL", "h_tiled": 12.74, "v_tiled": 43.06, "coverage_pct": 50.7, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781245371986_2135433976_reroll2_motif.png"}, {"attempt": 4, "seed": 1508731039, "mode": "canny", "cn_strength": 0.41, "motif_edge": "WARN", "h": "WARN", "v": "WARN", "h_tiled": 50.15, "v_tiled": 35.88, "coverage_pct": 38.7, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781245493967_1508731039_reroll2_motif.png"}, {"attempt": 5, "seed": 75462656, "mode": "canny", "cn_strength": 0.38, "motif_edge": "WARN", "h": "WARN", "v": "WARN", "h_tiled": 40.71, "v_tiled": 39.6, "coverage_pct": 34.0, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781245617942_75462656_reroll2_motif.png"}, {"attempt": 6, "seed": 983054970, "mode": "canny", "cn_strength": 0.35, "motif_edge": "WARN", "h": "WARN", "v": "PASS", "h_tiled": 15.19, "v_tiled": 0.27, "coverage_pct": 22.8, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781245740174_983054970_reroll2_motif.png"}, {"attempt": 7, "seed": 1747039360, "mode": "canny", "cn_strength": 0.32, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 5.18, "v_tiled": 0.19, "coverage_pct": 34.1, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781245866357_1747039360_reroll2_motif.png", "subject_recovered": true}], "technique": "canny-SDXL-CN-anchored native-seamless txt2img (tighter focal crop) + SEAM-RETRY-until-motif-PASS-both-axes + Gemini subject-recovery gate + deterministic real-fibre composite \u2014 NO smear", "edge_verdict": "PASS", "edge_seamless": true, "edge_axes": {"h": {"verdict": "PASS", "line_diff": 0.53, "line_diff_halfdrop": 123.87, "best": 0.53, "tiled_cross_seam_max": 4.85, "edges": "column[0] vs column[W-1]"}, "v": {"verdict": "PASS", "line_diff": 0.0, "line_diff_halfdrop": 26.19, "best": 0.0, "tiled_cross_seam_max": 0.39, "edges": "row[0] vs row[H-1]"}}, "motif_edge_verdict": "PASS", "new_id": 10000028, "hint": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781245026154_54303_reroll2_hint.png", "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781245866357_1747039360_reroll2_motif.png", "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781245866357_1747039360_reroll2.png", "ok": true}
diff --git a/data/seam-warn-animal-kept.txt b/data/seam-warn-animal-kept.txt
new file mode 100644
index 0000000..c58f515
--- /dev/null
+++ b/data/seam-warn-animal-kept.txt
@@ -0,0 +1,100 @@
+2656
+2766
+3391
+53927
+53999
+54002
+54018
+54092
+54110
+54112
+54193
+54207
+54209
+54214
+54241
+54249
+54270
+54273
+54290
+54303
+54314
+54328
+54339
+54340
+54362
+54373
+54375
+54394
+54460
+54461
+54482
+54487
+54493
+54504
+54514
+54515
+54537
+54555
+54586
+54594
+54597
+54598
+54603
+54614
+54621
+54623
+54631
+54641
+54643
+54656
+54660
+54664
+54681
+54689
+54694
+54710
+54741
+54766
+54768
+54770
+54774
+54780
+54781
+54786
+54797
+54803
+54807
+54812
+54818
+54827
+54848
+54850
+54855
+54857
+54860
+54885
+54888
+54889
+54895
+54899
+54916
+54977
+55038
+55043
+55052
+55062
+55089
+55094
+55106
+55113
+55207
+55219
+55228
+55234
+55273
+55286
+55294
+55306
+55317
+55327
diff --git a/data/seam-warn-roots.txt b/data/seam-warn-roots.txt
new file mode 100644
index 0000000..981ae0f
--- /dev/null
+++ b/data/seam-warn-roots.txt
@@ -0,0 +1,793 @@
+2656
+2760
+2766
+2829
+3391
+53686
+53704
+53865
+53867
+53872
+53885
+53901
+53903
+53927
+53929
+53973
+53977
+53984
+53988
+53990
+53999
+54000
+54002
+54004
+54006
+54008
+54010
+54013
+54018
+54020
+54023
+54024
+54032
+54035
+54038
+54042
+54046
+54056
+54059
+54080
+54092
+54094
+54102
+54110
+54112
+54113
+54119
+54180
+54181
+54186
+54188
+54189
+54191
+54193
+54194
+54199
+54200
+54206
+54207
+54209
+54212
+54214
+54219
+54220
+54223
+54224
+54227
+54230
+54231
+54232
+54235
+54239
+54241
+54242
+54243
+54244
+54246
+54247
+54248
+54249
+54256
+54257
+54258
+54259
+54262
+54264
+54265
+54267
+54269
+54270
+54272
+54273
+54275
+54276
+54277
+54278
+54280
+54282
+54283
+54284
+54288
+54289
+54290
+54292
+54294
+54295
+54296
+54297
+54301
+54303
+54306
+54307
+54308
+54309
+54310
+54312
+54314
+54315
+54316
+54320
+54322
+54323
+54324
+54325
+54328
+54332
+54333
+54339
+54340
+54345
+54346
+54347
+54349
+54351
+54352
+54354
+54355
+54356
+54358
+54360
+54361
+54362
+54363
+54364
+54365
+54366
+54367
+54368
+54370
+54372
+54373
+54374
+54375
+54376
+54377
+54380
+54381
+54383
+54384
+54386
+54388
+54389
+54390
+54391
+54392
+54393
+54394
+54395
+54396
+54437
+54438
+54439
+54442
+54443
+54444
+54446
+54448
+54449
+54450
+54452
+54453
+54454
+54457
+54460
+54461
+54462
+54465
+54467
+54472
+54473
+54474
+54475
+54476
+54477
+54479
+54480
+54481
+54482
+54485
+54486
+54487
+54488
+54489
+54490
+54491
+54493
+54494
+54495
+54497
+54499
+54500
+54504
+54506
+54512
+54514
+54515
+54524
+54526
+54532
+54537
+54542
+54555
+54557
+54558
+54559
+54561
+54565
+54571
+54576
+54578
+54584
+54585
+54586
+54587
+54588
+54593
+54594
+54597
+54598
+54599
+54600
+54601
+54602
+54603
+54604
+54605
+54607
+54608
+54611
+54613
+54614
+54617
+54621
+54622
+54623
+54624
+54625
+54626
+54629
+54631
+54632
+54633
+54635
+54637
+54639
+54641
+54642
+54643
+54645
+54646
+54647
+54648
+54649
+54650
+54651
+54653
+54654
+54655
+54656
+54657
+54660
+54661
+54662
+54663
+54664
+54665
+54666
+54668
+54670
+54671
+54672
+54673
+54675
+54677
+54678
+54679
+54681
+54684
+54689
+54691
+54692
+54694
+54698
+54701
+54706
+54710
+54713
+54717
+54719
+54720
+54721
+54722
+54723
+54724
+54728
+54731
+54732
+54739
+54740
+54741
+54745
+54748
+54749
+54750
+54752
+54754
+54755
+54763
+54764
+54766
+54767
+54768
+54769
+54770
+54772
+54773
+54774
+54775
+54776
+54779
+54780
+54781
+54782
+54784
+54786
+54787
+54790
+54792
+54797
+54799
+54803
+54804
+54807
+54808
+54809
+54810
+54811
+54812
+54814
+54817
+54818
+54819
+54820
+54821
+54822
+54823
+54826
+54827
+54831
+54832
+54836
+54841
+54842
+54848
+54850
+54852
+54853
+54855
+54857
+54860
+54862
+54868
+54869
+54872
+54875
+54876
+54883
+54885
+54886
+54888
+54889
+54890
+54891
+54892
+54894
+54895
+54897
+54899
+54901
+54902
+54905
+54906
+54914
+54916
+54917
+54920
+54921
+54962
+54963
+54976
+54977
+54993
+54999
+55002
+55030
+55036
+55038
+55040
+55041
+55043
+55048
+55049
+55052
+55053
+55054
+55055
+55056
+55058
+55059
+55060
+55062
+55066
+55067
+55069
+55071
+55073
+55077
+55078
+55082
+55083
+55085
+55086
+55089
+55093
+55094
+55097
+55099
+55100
+55101
+55103
+55106
+55110
+55112
+55113
+55114
+55116
+55119
+55124
+55149
+55161
+55207
+55208
+55211
+55212
+55216
+55217
+55218
+55219
+55220
+55221
+55222
+55225
+55227
+55228
+55233
+55234
+55235
+55236
+55273
+55275
+55277
+55279
+55285
+55286
+55287
+55288
+55292
+55293
+55294
+55300
+55301
+55302
+55304
+55305
+55306
+55307
+55308
+55309
+55311
+55314
+55315
+55316
+55317
+55318
+55320
+55321
+55323
+55324
+55326
+55327
+55328
+55329
+55330
+55331
+55332
+55335
+55336
+55339
+55342
+55343
+55345
+55348
+55352
+55355
+55360
+55364
+55367
+55385
+55389
+55399
+55406
+55409
+55414
+55423
+55427
+55428
+55431
+55435
+55438
+55440
+55444
+55452
+55468
+55472
+55483
+55488
+55494
+55499
+55523
+55527
+55541
+55551
+55556
+55565
+55589
+55598
+55627
+55631
+55640
+55645
+55662
+55670
+55675
+55679
+55687
+55691
+55706
+55717
+55727
+55751
+55771
+55784
+55789
+55797
+55818
+55823
+55830
+55840
+55844
+55849
+55853
+55856
+55861
+55874
+55887
+55897
+55905
+55910
+55924
+55954
+55973
+55986
+56013
+56022
+56025
+56034
+56038
+56044
+56049
+56054
+56061
+56080
+56088
+56096
+56100
+56121
+56131
+56135
+56154
+56163
+56171
+56185
+56195
+56200
+56207
+56210
+56216
+56223
+56229
+56235
+56253
+56258
+56262
+56273
+56281
+56286
+56293
+56297
+56304
+56308
+56312
+56330
+56333
+56341
+56346
+56351
+56368
+56373
+56389
+56393
+56416
+56419
+56424
+56439
+56443
+56460
+56464
+56473
+56480
+56484
+56493
+56517
+56522
+56526
+56529
+56533
+56537
+56545
+56548
+56564
+56580
+56590
+56609
+56615
+56619
+56622
+56650
+56663
+56682
+56691
+56694
+56699
+56702
+56720
+56725
+56732
+56737
+56748
+56759
+56778
+56781
+56809
+56824
+56837
+56844
+56850
+56854
+56858
+56867
+56874
+56886
+56890
+56895
+56898
+56903
+56915
+56926
+56940
+56951
+56966
+56973
+56984
+56988
+56992
+56995
+57006
+57012
+57016
+57020
+57029
+57034
+57050
+57055
+57059
+57084
+57087
+57098
+57112
+57118
+57125
+57135
+57142
+57155
+57170
+57175
+57188
+57192
+57201
+57218
+57221
+57230
+57233
+57240
+57245
+57251
+57253
+57254
+57256
+57257
+57259
+57260
+57263
+57265
+57266
+57268
+57269
+57271
+57272
+57273
+57276
+57279
+57310
+57311
+57312
+57361
+57391
+57401
+57412
+57438
+57466
+57494
+57509
+57522
+57533
+57538
+57552
+57571
+57591
+57592
+57594
+57595
+57596
+57597
+57598
+57599
+57600
+57602
+57604
+57605
+57606
+57609
+57610
+57611
+57612
+57613
+57614
+57616
+57617
+57618
+57619
+57686
+57688
+57710
diff --git a/data/variants-9roots.jsonl b/data/variants-9roots.jsonl
new file mode 100644
index 0000000..725f4cb
--- /dev/null
+++ b/data/variants-9roots.jsonl
@@ -0,0 +1,6 @@
+{"root_id": 2656, "ok": false, "mode": "canny", "error": "no motif cleared all gates (edge PASS-both-axes + coverage 14.0-40.0% + Gemini subject-recovery) in 3 retries", "ground": "raffia", "attempts": [{"attempt": 1, "seed": 465955999, "mode": "canny", "cn_strength": 0.52, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 8.02, "v_tiled": 0.49, "coverage_pct": 37.4, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781274923771_465955999_reroll2_motif.png", "subject_recovered": false}, {"attempt": 2, "seed": 174299714, "mode": "canny", "cn_strength": 0.49, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 0.18, "v_tiled": 11.47, "coverage_pct": 45.4, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781275117082_174299714_reroll2_motif.png"}, {"attempt": 3, "seed": 729019688, "mode": "canny", "cn_strength": 0.46, "motif_edge": "FAIL", "h": "FAIL", "v": "FAIL", "h_tiled": 0.12, "v_tiled": 0.16, "coverage_pct": 15.6, "cov_ok": true, "isolated_motif": true, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781275242460_729019688_reroll2_motif.png"}], "variant_n": 1, "variant_cfg": {"motif_px": 120, "cov_lo": 14.0, "cov_hi": 40.0, "crop_frac": 0.22}, "generator": "variants-9roots", "variant": "comp-v1"}
+{"root_id": 2656, "ok": false, "mode": "canny", "error": "no motif cleared all gates (edge PASS-both-axes + coverage 14.0-40.0% + Gemini subject-recovery) in 3 retries", "ground": "raffia", "attempts": [{"attempt": 1, "seed": 1922301935, "mode": "canny", "cn_strength": 0.51, "motif_edge": "FAIL", "h": "FAIL", "v": "FAIL", "h_tiled": 0.11, "v_tiled": 0.11, "coverage_pct": 25.3, "cov_ok": true, "isolated_motif": true, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781275366102_1922301935_reroll2_motif.png"}, {"attempt": 2, "seed": 1985608211, "mode": "canny", "cn_strength": 0.48, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 7.49, "v_tiled": 0.25, "coverage_pct": 64.1, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781275491405_1985608211_reroll2_motif.png"}, {"attempt": 3, "seed": 1338193351, "mode": "canny", "cn_strength": 0.45, "motif_edge": "WARN", "h": "WARN", "v": "PASS", "h_tiled": 13.65, "v_tiled": 9.85, "coverage_pct": 22.4, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781275614790_1338193351_reroll2_motif.png"}], "variant_n": 2, "variant_cfg": {"motif_px": 130, "cov_lo": 14.0, "cov_hi": 40.0, "crop_frac": 0.233}, "generator": "variants-9roots", "variant": "comp-v2"}
+{"root_id": 2656, "ok": false, "mode": "canny", "error": "no motif cleared all gates (edge PASS-both-axes + coverage 14.0-40.0% + Gemini subject-recovery) in 3 retries", "ground": "raffia", "attempts": [{"attempt": 1, "seed": 1068871874, "mode": "canny", "cn_strength": 0.5, "motif_edge": "FAIL", "h": "FAIL", "v": "FAIL", "h_tiled": 0.1, "v_tiled": 0.2, "coverage_pct": 28.3, "cov_ok": true, "isolated_motif": true, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781275906876_1068871874_reroll2_motif.png"}, {"attempt": 2, "seed": 1476981108, "mode": "canny", "cn_strength": 0.47, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 1.47, "v_tiled": 0.43, "coverage_pct": 52.2, "cov_ok": false, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781276030506_1476981108_reroll2_motif.png"}, {"attempt": 3, "seed": 1669917402, "mode": "canny", "cn_strength": 0.44, "motif_edge": "WARN", "h": "PASS", "v": "WARN", "h_tiled": 0.08, "v_tiled": 15.49, "coverage_pct": 32.8, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781276153796_1669917402_reroll2_motif.png"}], "variant_n": 3, "variant_cfg": {"motif_px": 140, "cov_lo": 14.0, "cov_hi": 40.0, "crop_frac": 0.246}, "generator": "variants-9roots", "variant": "comp-v3"}
+{"ts": "2026-06-12T15:02:11.772122Z", "root_id": 2656, "variant": "comp-v4", "generator": "variants-9roots", "category": "drunk-animals", "subject": "plastered red panda, gripping a pale-gold pilsner glass in one paw", "animal": "red panda", "ground": "raffia", "seed": 382426020, "base_hex": "#d0b0a0", "cn_strength": 0.46, "cn_end": 0.55, "mode": "canny", "subject_recovered": true, "crop_box": [0, 384, 265], "coverage_pct": 22.7, "attempts_used": 2, "attempts": [{"attempt": 1, "seed": 2093612182, "mode": "canny", "cn_strength": 0.49, "motif_edge": "FAIL", "h": "FAIL", "v": "WARN", "h_tiled": 35.54, "v_tiled": 15.28, "coverage_pct": 36.7, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781276277463_2093612182_reroll2_motif.png"}, {"attempt": 2, "seed": 382426020, "mode": "canny", "cn_strength": 0.46, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 7.95, "v_tiled": 0.2, "coverage_pct": 22.7, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781276400700_382426020_reroll2_motif.png", "subject_recovered": true}], "technique": "canny-SDXL-CN-anchored native-seamless txt2img (tighter focal crop) + SEAM-RETRY-until-motif-PASS-both-axes + Gemini subject-recovery gate + deterministic real-fibre composite \u2014 NO smear", "edge_verdict": "PASS", "edge_seamless": true, "edge_axes": {"h": {"verdict": "PASS", "line_diff": 0.9, "line_diff_halfdrop": 72.09, "best": 0.9, "tiled_cross_seam_max": 7.94, "edges": "column[0] vs column[W-1]"}, "v": {"verdict": "PASS", "line_diff": 0.03, "line_diff_halfdrop": 34.11, "best": 0.03, "tiled_cross_seam_max": 0.64, "edges": "row[0] vs row[H-1]"}}, "motif_edge_verdict": "PASS", "new_id": 10000029, "hint": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781276277453_2656_reroll2_hint.png", "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781276400700_382426020_reroll2_motif.png", "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781276400700_382426020_reroll2.png", "ok": true, "variant_n": 4, "variant_cfg": {"motif_px": 150, "cov_lo": 14.0, "cov_hi": 40.0, "crop_frac": 0.259}}
+{"ts": "2026-06-12T15:08:12.152505Z", "root_id": 2656, "variant": "comp-v5", "generator": "variants-9roots", "category": "drunk-animals", "subject": "plastered red panda, gripping a pale-gold pilsner glass in one paw", "animal": "red panda", "ground": "raffia", "seed": 611069176, "base_hex": "#b0a080", "cn_strength": 0.45, "cn_end": 0.55, "mode": "canny", "subject_recovered": true, "crop_box": [0, 374, 278], "coverage_pct": 22.1, "attempts_used": 2, "attempts": [{"attempt": 1, "seed": 1608931834, "mode": "canny", "cn_strength": 0.48, "motif_edge": "FAIL", "h": "PASS", "v": "FAIL", "h_tiled": 5.84, "v_tiled": 36.44, "coverage_pct": 24.9, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781276532021_1608931834_reroll2_motif.png"}, {"attempt": 2, "seed": 611069176, "mode": "canny", "cn_strength": 0.45, "motif_edge": "PASS", "h": "PASS", "v": "PASS", "h_tiled": 0.04, "v_tiled": 1.03, "coverage_pct": 22.1, "cov_ok": true, "isolated_motif": false, "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781276761299_611069176_reroll2_motif.png", "subject_recovered": true}], "technique": "canny-SDXL-CN-anchored native-seamless txt2img (tighter focal crop) + SEAM-RETRY-until-motif-PASS-both-axes + Gemini subject-recovery gate + deterministic real-fibre composite \u2014 NO smear", "edge_verdict": "PASS", "edge_seamless": true, "edge_axes": {"h": {"verdict": "PASS", "line_diff": 0.0, "line_diff_halfdrop": 26.0, "best": 0.0, "tiled_cross_seam_max": 0.38, "edges": "column[0] vs column[W-1]"}, "v": {"verdict": "PASS", "line_diff": 0.12, "line_diff_halfdrop": 37.67, "best": 0.12, "tiled_cross_seam_max": 1.42, "edges": "row[0] vs row[H-1]"}}, "motif_edge_verdict": "PASS", "new_id": 10000030, "hint": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781276532009_2656_reroll2_hint.png", "motif": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781276761299_611069176_reroll2_motif.png", "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781276761299_611069176_reroll2.png", "ok": true, "variant_n": 5, "variant_cfg": {"motif_px": 160, "cov_lo": 14.0, "cov_hi": 40.0, "crop_frac": 0.272}}
+{"ts": "2026-06-12T15:18:37.954378Z", "root_id": 2656, "animal": "red panda", "ground": "raffia", "seed": 689577113, "base_hex": "#c0a090", "coverage_pct": 13.0, "cn_strength": 0.52, "attempts_used": 1, "edge_verdict": "PASS", "new_id": 10000031, "out": "/Users/stevestudio2/Projects/wallco-ai/data/generated/1781277213352_689577113_var.png", "ok": true, "variant_n": 1, "variant_cfg": {"motif_px": 120, "crop_frac": 0.22}, "generator": "variants-9roots", "variant": "comp-v1"}
diff --git a/public/variant-curator.html b/public/variant-curator.html
new file mode 100644
index 0000000..21b4d42
--- /dev/null
+++ b/public/variant-curator.html
@@ -0,0 +1,164 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>Variant Curator — Wave-1 Drunk Animals</title>
+<style>
+  :root { --bg:#12100e; --panel:#1c1813; --line:#33291f; --ink:#f3ece1; --muted:#a08f78;
+          --gold:#caa45a; --keep:#3fa34d; --keepbg:#15301a; }
+  * { box-sizing: border-box; }
+  body { margin:0; background:var(--bg); color:var(--ink);
+         font:14px/1.45 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif; }
+  header { position:sticky; top:0; z-index:5; background:linear-gradient(180deg,#1c1813,#1c1813ee);
+           border-bottom:1px solid var(--line); padding:14px 20px; display:flex; align-items:center; gap:16px; }
+  header h1 { font-size:17px; margin:0; letter-spacing:.3px; font-weight:600; }
+  header .sub { color:var(--muted); font-size:12px; }
+  .live { display:inline-flex; align-items:center; gap:6px; font-size:12px; color:var(--muted); }
+  .dot { width:8px; height:8px; border-radius:50%; background:var(--keep); box-shadow:0 0 8px var(--keep);
+         animation:pulse 1.6s infinite; }
+  @keyframes pulse { 0%,100%{opacity:1} 50%{opacity:.3} }
+  .wrap { padding:18px 20px 60px; max-width:1500px; margin:0 auto; }
+  .row { display:flex; gap:14px; align-items:flex-start; padding:14px 0; border-bottom:1px solid var(--line); }
+  .root { flex:0 0 190px; }
+  .root .rthumb { width:190px; height:190px; border-radius:8px; object-fit:cover;
+                  border:2px solid var(--gold); background:#000; display:block; }
+  .root .rmeta { margin-top:6px; }
+  .root .rid { font-weight:600; color:var(--gold); font-size:13px; }
+  .root .rcat { color:var(--muted); font-size:11px; }
+  .root .rprompt { color:#cdbfa8; font-size:11px; margin-top:3px; max-height:46px; overflow:hidden; }
+  .count { font-size:12px; color:var(--muted); margin-top:6px; }
+  .count b { color:var(--ink); }
+  .variants { flex:1; display:flex; flex-wrap:wrap; gap:12px; align-content:flex-start; }
+  .empty { color:var(--muted); font-style:italic; padding:30px 6px; font-size:13px; }
+  .card { width:150px; border:1px solid var(--line); border-radius:8px; overflow:hidden;
+          background:var(--panel); display:flex; flex-direction:column; transition:border-color .15s; }
+  .card.kept { border-color:var(--keep); box-shadow:0 0 0 2px var(--keep) inset; }
+  .card img { width:150px; height:150px; object-fit:cover; background:#000; cursor:zoom-in; display:block; }
+  .card .meta { padding:6px 8px; font-size:11px; }
+  .vid { color:var(--muted); }
+  .cov { color:#cdbfa8; }
+  .when { color:var(--muted); display:block; margin-top:2px; font-size:10px; }
+  .pickbtn { border:0; cursor:pointer; padding:7px 8px; font-size:12px; font-weight:600;
+             color:#1a140c; background:var(--gold); text-align:center; }
+  .pickbtn.kept { background:var(--keep); color:#fff; }
+  .pickbtn:disabled { opacity:.5; cursor:wait; }
+  .new { animation:flash 1.4s ease-out; }
+  @keyframes flash { 0%{box-shadow:0 0 0 3px var(--gold)} 100%{box-shadow:0 0 0 0 transparent} }
+  #lightbox { position:fixed; inset:0; background:#000d; display:none; align-items:center;
+              justify-content:center; z-index:20; cursor:zoom-out; }
+  #lightbox img { max-width:92vw; max-height:92vh; border-radius:6px; }
+  .err { color:#e07a5f; font-size:12px; }
+</style>
+</head>
+<body>
+<header>
+  <h1>🥃 Variant Curator</h1>
+  <span class="sub">Wave-1 drunk-animal composition variants · multi-keep for variety · click <b>KEEP</b> to publish that variant</span>
+  <span class="live" id="live"><span class="dot"></span> live · <span id="ts">—</span></span>
+  <span class="err" id="err"></span>
+</header>
+<div class="wrap" id="wrap"><div class="empty">Loading…</div></div>
+<div id="lightbox" onclick="this.style.display='none'"><img id="lbimg" alt=""></div>
+
+<script>
+const ROOT_THUMB = id => '/designs/img/by-id/' + id;
+const seen = new Set();          // child ids already rendered (for "new" flash)
+let firstPaint = true;
+
+function fmtDate(iso){
+  if(!iso) return '—';
+  try{
+    return new Date(iso).toLocaleString(undefined,
+      { year:'numeric', month:'short', day:'numeric', hour:'numeric', minute:'2-digit' });
+  }catch(e){ return iso; }
+}
+
+function lightbox(src){
+  document.getElementById('lbimg').src = src;
+  document.getElementById('lightbox').style.display = 'flex';
+}
+
+async function pick(btn, rootId, designId, keep){
+  btn.disabled = true;
+  try{
+    const r = await fetch('/api/variant-curator/pick', {
+      method:'POST', headers:{'Content-Type':'application/json'},
+      body: JSON.stringify({ root_id:rootId, design_id:designId, keep })
+    });
+    const j = await r.json();
+    if(!j.ok) throw new Error(j.error || 'pick failed');
+    const card = btn.closest('.card');
+    const kept = j.kept === true;
+    card.classList.toggle('kept', kept);
+    btn.classList.toggle('kept', kept);
+    btn.textContent = kept ? '✓ KEPT' : 'KEEP';
+    btn.onclick = () => pick(btn, rootId, designId, !kept);
+  }catch(e){
+    document.getElementById('err').textContent = 'pick error: ' + e.message;
+  }finally{ btn.disabled = false; }
+}
+
+function render(data){
+  const wrap = document.getElementById('wrap');
+  document.getElementById('ts').textContent = fmtDate(data.generated_at);
+  document.getElementById('err').textContent = '';
+  const cap = data.cap || 10;
+  wrap.innerHTML = '';
+  for(const root of data.roots){
+    const row = document.createElement('div'); row.className = 'row';
+
+    const rootDiv = document.createElement('div'); rootDiv.className = 'root';
+    rootDiv.innerHTML =
+      '<img class="rthumb" src="'+ROOT_THUMB(root.root_id)+'" alt="root '+root.root_id+'" '+
+        'onclick="lightbox(this.src)" style="cursor:zoom-in">'+
+      '<div class="rmeta">'+
+        '<span class="rid">root #'+root.root_id+'</span> '+
+        '<span class="rcat">'+(root.category||'')+'</span>'+
+        '<div class="rprompt" title="'+(root.prompt||'').replace(/"/g,'&quot;')+'">'+(root.prompt||'')+'</div>'+
+        '<div class="count">(<b>'+root.variant_count+'</b>/'+cap+') variants</div>'+
+      '</div>';
+    row.appendChild(rootDiv);
+
+    const vbox = document.createElement('div'); vbox.className = 'variants';
+    if(!root.variants.length){
+      vbox.innerHTML = '<div class="empty">no variants yet — generating…</div>';
+    } else {
+      for(const v of root.variants){
+        const card = document.createElement('div');
+        card.className = 'card' + (v.kept ? ' kept' : '') + ((!firstPaint && !seen.has(v.id)) ? ' new' : '');
+        seen.add(v.id);
+        const cov = (v.coverage_pct != null) ? (v.coverage_pct.toFixed ? v.coverage_pct.toFixed(1) : v.coverage_pct) + '% cov' : '';
+        card.innerHTML =
+          '<img src="'+v.image_url+'" alt="variant '+v.id+'" onclick="lightbox(this.src)">'+
+          '<div class="meta">'+
+            '<span class="vid">#'+v.id+'</span>'+(cov? ' · <span class="cov">'+cov+'</span>':'')+
+            '<span class="when" title="'+(v.created_at||'')+'">🕓 '+fmtDate(v.created_at)+'</span>'+
+          '</div>';
+        const btn = document.createElement('button');
+        btn.className = 'pickbtn' + (v.kept ? ' kept' : '');
+        btn.textContent = v.kept ? '✓ KEPT' : 'KEEP';
+        btn.onclick = () => pick(btn, root.root_id, v.id, !v.kept);
+        card.appendChild(btn);
+        vbox.appendChild(card);
+      }
+    }
+    row.appendChild(vbox);
+    wrap.appendChild(row);
+  }
+  firstPaint = false;
+}
+
+async function poll(){
+  try{
+    const r = await fetch('/api/variant-curator', { cache:'no-store' });
+    const j = await r.json();
+    if(j.ok) render(j);
+    else document.getElementById('err').textContent = j.error || 'load failed';
+  }catch(e){ document.getElementById('err').textContent = 'poll error: ' + e.message; }
+}
+poll();
+setInterval(poll, 5000);
+</script>
+</body>
+</html>
diff --git a/server.js b/server.js
index b1ed008..1210308 100644
--- a/server.js
+++ b/server.js
@@ -2722,6 +2722,144 @@ app.post('/api/admin/drunk/extract', express.json({ limit: '2kb' }), (req, res)
   } catch (e) { res.status(500).json({ ok: false, error: e.message }); }
 });
 
+// ── /admin/variant-curator — LIVE picker for the Wave-1 drunk-animal
+// composition variants (scripts/variants-9roots.py). One ROW per root: root
+// thumb + its up-to-10 unpublished variant CHILDREN. The page auto-polls
+// /api/variant-curator every ~5s so new variants appear live as the generator
+// lands them. PICK is MULTI-KEEP (Steve curates for variety): a click toggles
+// is_published on just that one child — never the root. Roots are sacred; this
+// surface ONLY ever flips is_published on the CHILD variant rows.
+//
+// The variant children are inserted by cnar.insert_child(), which stamps
+// generator='controlnet-anchored-redo' (NOT 'variants-9roots' — that string is
+// ledger-only) + a 'redo-sample-from-<root>' tag. We scope to exactly those:
+// parent_design_id IN (the 9 Wave-1 roots) AND generator='controlnet-anchored-redo'
+// AND is_published=FALSE AND user_removed not set.
+const VARIANT_CURATOR_ROOTS = [2656, 2766, 3391, 53999, 54002, 54092, 54110, 54112, 54290];
+
+app.get('/admin/variant-curator', (req, res) => {
+  if (!isAdmin(req)) return res.status(404).type('html').send('<h1>404</h1>');
+  res.sendFile(path.join(__dirname, 'public', 'variant-curator.html'));
+});
+
+app.get('/api/variant-curator', (req, res) => {
+  if (!isAdmin(req)) return res.status(404).json({ error: 'not found' });
+  const roots = VARIANT_CURATOR_ROOTS;
+  const rootsCsv = roots.join(',');
+  try {
+    // Root meta. all_designs has duplicate root rows (snapshot import dupes), so
+    // DISTINCT ON (id) ... ORDER BY id, ctid takes exactly one per root.
+    const rootJson = psqlQuery(
+      "SELECT COALESCE(json_agg(t ORDER BY array_position(ARRAY[" + rootsCsv + "]::bigint[], t.id::bigint)), '[]'::json) FROM (" +
+        "SELECT DISTINCT ON (id) id, category, left(prompt, 200) AS prompt, created_at " +
+        `FROM all_designs WHERE id IN (${rootsCsv}) ORDER BY id, ctid` +
+      ") t;"
+    );
+    // Variant children for ALL 9 roots in one query, newest first, capped to 10
+    // per root via a window. KEPT-STATE comes from the local sidecar
+    // wallco_variant_picks (NOT all_designs.is_published) — on Mac2 all_designs
+    // is INSERT-only (no replica identity in the FOR-ALL-TABLES publication), so
+    // we never UPDATE it. The sidecar carries the durable local KEEP flag; the
+    // real is_published flip to the live storefront stays a Steve-gated Kamatera
+    // export (DTD verdict A, 2026-06-12, unanimous).
+    const childJson = psqlQuery(
+      "SELECT COALESCE(json_agg(t ORDER BY t.parent_design_id, t.created_at DESC, t.id DESC), '[]'::json) FROM (" +
+        "SELECT * FROM (" +
+          "SELECT d.id, d.parent_design_id, d.is_published, d.created_at, d.dominant_hex, " +
+                 "COALESCE(p.kept, FALSE) AS kept, " +
+                 "NULLIF(substring(d.notes from 'coverage_pct=([0-9.]+)'),'')::float AS coverage_pct, " +
+                 "row_number() OVER (PARTITION BY d.parent_design_id ORDER BY d.created_at DESC, d.id DESC) AS rn " +
+          `FROM all_designs d ` +
+          "LEFT JOIN wallco_variant_picks p ON p.design_id = d.id " +
+          `WHERE d.parent_design_id IN (${rootsCsv}) ` +
+          "AND d.generator='controlnet-anchored-redo' " +
+          "AND (d.user_removed IS NULL OR d.user_removed=FALSE) " +
+          "AND d.local_path IS NOT NULL " +
+          "AND EXISTS (SELECT 1 FROM unnest(d.tags) tg WHERE tg LIKE 'redo-sample-from-%') " +
+        ") s WHERE s.rn <= 10" +
+      ") t;"
+    );
+    const rootRows = JSON.parse(rootJson || '[]');
+    const childRows = JSON.parse(childJson || '[]');
+    const byParent = new Map();
+    for (const c of childRows) {
+      const arr = byParent.get(c.parent_design_id) || [];
+      arr.push({
+        id: c.id,
+        image_url: '/designs/img/by-id/' + c.id,
+        coverage_pct: (c.coverage_pct != null ? c.coverage_pct : null),
+        dominant_hex: c.dominant_hex || null,
+        created_at: c.created_at || null,
+        kept: c.kept === true,
+        live_published: c.is_published === true,
+      });
+      byParent.set(c.parent_design_id, arr);
+    }
+    const rootById = new Map(rootRows.map(r => [r.id, r]));
+    const out = roots.map(rid => {
+      const r = rootById.get(rid) || { id: rid, category: null, prompt: null, created_at: null };
+      const variants = byParent.get(rid) || [];
+      return {
+        root_id: rid,
+        category: r.category || null,
+        prompt: r.prompt || null,
+        created_at: r.created_at || null,
+        image_url: '/designs/img/by-id/' + rid,
+        variant_count: variants.length,
+        variants,
+      };
+    });
+    res.json({ ok: true, roots: out, cap: 10, generated_at: new Date().toISOString() });
+  } catch (e) { res.status(500).json({ ok: false, error: e.message }); }
+});
+
+// POST /api/variant-curator/pick  body:{root_id, design_id, keep}
+// MULTI-KEEP toggle on a single CHILD variant. keep=true marks it kept,
+// keep=false un-keeps it. NEVER touches the root, NEVER UPDATEs all_designs.
+//
+// On Mac2 all_designs is INSERT-only — it has no primary key / replica identity
+// inside the FOR-ALL-TABLES publication dw_unified_pub, so Postgres REJECTS
+// every UPDATE (the drunk-curator's is_published UPDATE has the same latent
+// failure here). DTD verdict A (2026-06-12, unanimous Claude/Codex/Qwen): the
+// KEEP flag is persisted to a SEPARATE local sidecar (wallco_variant_picks, a
+// PK-backed table → fully UPDATE-able even under the same publication). The real
+// is_published flip to the live storefront stays a later Steve-gated Kamatera
+// export. design_id MUST be a child variant of root_id (guarded) so the curator
+// can only ever flag these specific variant rows.
+app.post('/api/variant-curator/pick', express.json({ limit: '2kb' }), (req, res) => {
+  if (!isAdmin(req)) return res.status(404).json({ error: 'not found' });
+  const rootId = parseInt(req.body && req.body.root_id, 10);
+  const designId = parseInt(req.body && req.body.design_id, 10);
+  const keep = !(req.body && req.body.keep === false); // default keep=true
+  if (!Number.isFinite(rootId) || !Number.isFinite(designId)) {
+    return res.status(400).json({ ok: false, error: 'bad root_id/design_id' });
+  }
+  if (!VARIANT_CURATOR_ROOTS.includes(rootId)) {
+    return res.status(400).json({ ok: false, error: 'root_id not in Wave-1 set' });
+  }
+  try {
+    // Guard: design_id must be a CHILD variant of root_id (this run's family).
+    const okRow = (psqlQuery(
+      `SELECT count(*) FROM all_designs WHERE id=${designId} AND parent_design_id=${rootId} ` +
+      "AND generator='controlnet-anchored-redo' " +
+      "AND EXISTS (SELECT 1 FROM unnest(tags) tg WHERE tg LIKE 'redo-sample-from-%');"
+    ) || '0').trim();
+    if (parseInt(okRow, 10) < 1) {
+      return res.status(400).json({ ok: false, error: 'design_id is not a variant child of root_id' });
+    }
+    // Upsert the durable KEEP flag into the local sidecar. PK = design_id, so
+    // ON CONFLICT DO UPDATE works (unlike all_designs which has no replica id).
+    psqlExecLocal(
+      `INSERT INTO wallco_variant_picks (design_id, root_id, kept, updated_at) ` +
+      `VALUES (${designId}, ${rootId}, ${keep ? 'TRUE' : 'FALSE'}, now()) ` +
+      `ON CONFLICT (design_id) DO UPDATE SET kept=EXCLUDED.kept, root_id=EXCLUDED.root_id, updated_at=now();`
+    );
+    // Canary: read the flag straight back so the API never lies about durability.
+    const stored = (psqlQuery(`SELECT kept FROM wallco_variant_picks WHERE design_id=${designId} LIMIT 1;`) || '').trim();
+    return res.json({ ok: true, root_id: rootId, design_id: designId, kept: stored === 't', published: false });
+  } catch (e) { res.status(500).json({ ok: false, error: e.message }); }
+});
+
 app.get('/api/admin/defect-registry/list', (req, res) => {
   if (!isAdmin(req)) return res.status(404).json({ error: 'not found' });
   const limit  = Math.min(Math.max(parseInt(req.query.limit  || '600', 10), 1), 8000);
@@ -6713,6 +6851,7 @@ function htmlHeader(active) {
     <a href="/admin/prompt-vs-image" class="${active === '/admin/prompt-vs-image' ? 'active' : ''}">◧ Prompt vs Image</a>
     <a href="/admin/bleed-review"   class="${active === '/admin/bleed-review'   ? 'active' : ''}">🩸 Bleed Review</a>
     <a href="/admin/drunk-curator"  class="${active === '/admin/drunk-curator'  ? 'active' : ''}">🥃 Hot-or-Not + Wall Viewer</a>
+    <a href="/admin/variant-curator" class="${active === '/admin/variant-curator' ? 'active' : ''}">🎛 Variant Curator (live)</a>
     <a href="/admin/rooms"          class="${active === '/admin/rooms'          ? 'active' : ''}">🛋 Room Renders Gallery</a>
     <a href="/admin/theme-gallery"  class="${active === '/admin/theme-gallery'  ? 'active' : ''}">🎨 Theme Gallery</a>
     <a href="/admin/elements"       class="${active === '/admin/elements'       ? 'active' : ''}">✂️ Elements Library</a>

← 8f035f5 variants-9roots: edge-seamless is the only hard gate (Steve  ·  back to Wallco Ai  ·  Add gated variant-pick export: dry-run by default, publishes 78491e9 →