← back to Wallco Ai
Add seam-warn recovery + animal-forward filter helpers (DTD-C bounded WARN slice)
41f6dfc030450192a7b263ce26ac6c4b88d953d1 · 2026-06-11 19:34:45 -0700 · Steve Abrams
seam-warn-list.py re-derives the 793 distinct WARN roots (the original
seam-fail-scan.py persisted only FAILs). seam-warn-animal-filter.py runs the
FREE local-llava dominance gate over them in id order, CAP=100, dropping
glassware-dominant / pastoral-toile / animal-minority roots. Both read-only
against the DB; neither appends to the manifest, flips is_published, or deploys.
Files touched
A scripts/seam-warn-animal-filter.pyA scripts/seam-warn-list.py
Diff
commit 41f6dfc030450192a7b263ce26ac6c4b88d953d1
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Jun 11 19:34:45 2026 -0700
Add seam-warn recovery + animal-forward filter helpers (DTD-C bounded WARN slice)
seam-warn-list.py re-derives the 793 distinct WARN roots (the original
seam-fail-scan.py persisted only FAILs). seam-warn-animal-filter.py runs the
FREE local-llava dominance gate over them in id order, CAP=100, dropping
glassware-dominant / pastoral-toile / animal-minority roots. Both read-only
against the DB; neither appends to the manifest, flips is_published, or deploys.
---
scripts/seam-warn-animal-filter.py | 113 +++++++++++++++++++++++++++++++++++++
scripts/seam-warn-list.py | 82 +++++++++++++++++++++++++++
2 files changed, 195 insertions(+)
diff --git a/scripts/seam-warn-animal-filter.py b/scripts/seam-warn-animal-filter.py
new file mode 100644
index 0000000..3786fd7
--- /dev/null
+++ b/scripts/seam-warn-animal-filter.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python3
+"""seam-warn-animal-filter.py — FREE local-llava animal-forward filter over the
+recovered WARN roots (data/seam-warn-roots.txt), for the DTD-C bounded slice.
+
+For each WARN root IN ID ORDER: resolve its on-disk PNG, ask the free local
+llava gate (scripts/vision-contains-local.py question form) whether a SINGLE
+ANIMAL is the largest / most dominant element. KEEP yes; DROP glassware-
+dominant / pastoral-toile / animal-minority. STOP once CAP (=100) roots are
+kept — hard cap, does not classify the rest.
+
+Writes the kept ids to data/seam-warn-animal-kept.txt (one per line) and a
+per-root decision log to stderr. Read-only against the DB (single batched
+read of local_paths). Never appends to the manifest, never flips is_published,
+no deploy. The append step is done separately by the operator.
+
+Env: CAP (default 100), OLLAMA_URL, OLLAMA_VISION_MODEL (llava:latest).
+Usage: python3 scripts/seam-warn-animal-filter.py
+"""
+import base64, json, os, sys, urllib.request
+from pathlib import Path
+
+ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+WARN = os.path.join(ROOT, 'data', 'seam-warn-roots.txt')
+OUT = os.path.join(ROOT, 'data', 'seam-warn-animal-kept.txt')
+CAP = int(os.environ.get('CAP', '100'))
+OLLAMA = os.environ.get('OLLAMA_URL', 'http://127.0.0.1:11434')
+MODEL = os.environ.get('OLLAMA_VISION_MODEL', 'llava:latest')
+
+QUESTION = ("Is a single animal the largest and most dominant element in this "
+ "image, taking up more visual space than any glassware, drinks, "
+ "plants, foliage, or background scenery?")
+
+sys.path.insert(0, os.path.join(ROOT, 'scripts'))
+from importlib import import_module
+scan = import_module('seam-fail-scan')
+sfv = import_module('seam-fix-variants')
+
+
+def llava_yes(png):
+ try:
+ img_b64 = base64.b64encode(open(png, 'rb').read()).decode()
+ except Exception:
+ return None
+ body = {'model': MODEL,
+ 'prompt': QUESTION + ' Answer with exactly one word: yes or no.',
+ 'images': [img_b64], 'stream': False,
+ 'options': {'temperature': 0}}
+ req = urllib.request.Request(f'{OLLAMA}/api/generate',
+ data=json.dumps(body).encode(),
+ headers={'Content-Type': 'application/json'})
+ try:
+ with urllib.request.urlopen(req, timeout=120) as r:
+ j = json.load(r)
+ txt = (j.get('response') or '').strip().lower()
+ return txt.startswith('yes')
+ except Exception as e:
+ print(f' llava error: {e}', file=sys.stderr)
+ return None
+
+
+def load_paths(ids):
+ """Single batched read: id -> local_path for all WARN roots."""
+ idlist = ','.join(str(i) for i in ids)
+ out = sfv.psql(f"SELECT id, COALESCE(local_path,'') FROM all_designs "
+ f"WHERE id IN ({idlist}) AND parent_design_id IS NULL;")
+ m = {}
+ for line in out.splitlines():
+ if '|' not in line:
+ continue
+ sid, lp = line.split('|', 1)
+ try:
+ m[int(sid)] = lp
+ except ValueError:
+ continue
+ return m
+
+
+def main():
+ ids = [int(x) for x in open(WARN) if x.strip().isdigit()]
+ paths = load_paths(ids)
+ kept, dropped, missing, errored = [], 0, 0, 0
+ for n, rid in enumerate(ids, 1):
+ if len(kept) >= CAP:
+ print(f"-- CAP {CAP} reached after classifying {n-1} roots; stopping.",
+ file=sys.stderr)
+ break
+ png = scan.resolve(paths.get(rid, ''))
+ if not png:
+ missing += 1
+ print(f"[{n}] {rid} MISSING-png", file=sys.stderr)
+ continue
+ ans = llava_yes(png)
+ if ans is None:
+ errored += 1
+ print(f"[{n}] {rid} ERROR (fail-closed: drop)", file=sys.stderr)
+ continue
+ if ans:
+ kept.append(rid)
+ print(f"[{n}] {rid} KEEP ({len(kept)}/{CAP})", file=sys.stderr)
+ else:
+ dropped += 1
+ print(f"[{n}] {rid} drop", file=sys.stderr)
+
+ with open(OUT, 'w') as f:
+ f.write('\n'.join(str(r) for r in kept) + ('\n' if kept else ''))
+ print(json.dumps({'kept': len(kept), 'dropped': dropped,
+ 'missing': missing, 'errored': errored,
+ 'classified': n if ids else 0, 'cap': CAP,
+ 'out': OUT}, indent=2))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/seam-warn-list.py b/scripts/seam-warn-list.py
new file mode 100644
index 0000000..af34f03
--- /dev/null
+++ b/scripts/seam-warn-list.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python3
+"""seam-warn-list.py — read-only re-derivation of the WARN root universe.
+
+seam-fail-scan.py persists only the FAIL rows; the 1586 WARN ids it tallied
+were never written out. This helper reproduces that scan EXACTLY — same
+eligible query, same queue+exclude skip set, same canonical both-axes gate
+(verify-edge-seamless.verify_path) — and emits ONLY the WARN root ids, one
+per line, to data/seam-warn-roots.txt (and the count to stdout).
+
+DOES NOT touch the DB beyond a single read. Never flips is_published. No
+deploy. Never appends to the live manifest. This is the recovery step for the
+DTD-C bounded WARN slice; the animal-forward pre-filter + manifest append are
+separate steps run by the operator.
+
+Usage: python3 scripts/seam-warn-list.py
+"""
+import json, os, sys
+from pathlib import Path
+
+ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+OUT = os.path.join(ROOT, 'data', 'seam-warn-roots.txt')
+
+sys.path.insert(0, os.path.join(ROOT, 'scripts'))
+from importlib import import_module
+scan = import_module('seam-fail-scan') # reuse resolve/queue_roots/excluded_roots
+sfv = import_module('seam-fix-variants')
+edgeverify = import_module('verify-edge-seamless')
+
+
+def main():
+ skip = scan.queue_roots() | scan.excluded_roots()
+ out = sfv.psql('''
+SELECT id, COALESCE(local_path,'')
+FROM all_designs
+WHERE is_published=true
+ AND COALESCE(user_removed,false)=false
+ AND parent_design_id IS NULL
+ AND needs_fixing_at IS NULL
+ AND category='drunk-animals'
+ AND local_path IS NOT NULL AND local_path<>''
+ORDER BY id;
+''')
+ rows = []
+ for line in out.splitlines():
+ if '|' not in line:
+ continue
+ sid, lp = line.split('|', 1)
+ try:
+ rid = int(sid)
+ except ValueError:
+ continue
+ if rid in skip:
+ continue
+ rows.append((rid, lp))
+
+ tally = {'PASS': 0, 'WARN': 0, 'FAIL': 0, 'MISSING': 0, 'ERROR': 0}
+ warns = []
+ total = len(rows)
+ for i, (rid, lp) in enumerate(rows):
+ path = scan.resolve(lp)
+ if not path:
+ tally['MISSING'] += 1
+ continue
+ try:
+ ev = edgeverify.verify_path(Path(path))
+ except Exception:
+ tally['ERROR'] += 1
+ continue
+ v = ev.get('verdict', 'ERROR')
+ tally[v] = tally.get(v, 0) + 1
+ if v == 'WARN':
+ warns.append(rid)
+ if (i + 1) % 100 == 0:
+ print(f" scanned {i+1}/{total} tally={tally} warns={len(warns)}", file=sys.stderr)
+
+ with open(OUT, 'w') as f:
+ f.write('\n'.join(str(r) for r in warns) + ('\n' if warns else ''))
+ print(json.dumps({'tally': tally, 'warn_count': len(warns), 'out': OUT}, indent=2))
+
+
+if __name__ == '__main__':
+ main()
← 61d91dd TODO: log overnight seam-fix runner launch (3-root manifest,
·
back to Wallco Ai
·
seam-wave Wave 1: 1/3 roots cleared (55272 elephant -> 10000 4992ea4 →