[object Object]

← back to Designer Wallcoverings

recover: single supervised local-cache Lily enrichment (Henry chokes under sustained I/O)

8beec0f681f00ffc1e3c1811428809cfcd6cb34e · 2026-07-01 14:47:24 -0700 · Steve Abrams

Files touched

Diff

commit 8beec0f681f00ffc1e3c1811428809cfcd6cb34e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Jul 1 14:47:24 2026 -0700

    recover: single supervised local-cache Lily enrichment (Henry chokes under sustained I/O)
---
 .../scripts/enrich-local-supervised.sh             | 80 ++++++++++++++++++++++
 1 file changed, 80 insertions(+)

diff --git a/onboarding/sangetsu-lilycolor/scripts/enrich-local-supervised.sh b/onboarding/sangetsu-lilycolor/scripts/enrich-local-supervised.sh
new file mode 100755
index 00000000..7cbfe5bb
--- /dev/null
+++ b/onboarding/sangetsu-lilycolor/scripts/enrich-local-supervised.sh
@@ -0,0 +1,80 @@
+#!/usr/bin/env bash
+# enrich-local-supervised.sh — THE single canonical Lily recovery runner.
+#
+# Combines: (1) supervise.sh's jetsam-survival respawn loop, and (2) the local
+# cache + good-seed + remerge logic. Reads images from the STABLE local SSD
+# cache (.image-cache/lily), NOT flaky /Volumes/Henry — so image_not_found under
+# sustained I/O can't happen. Resumable, $0 local, JSONL-only (reversible).
+#
+# Completion = a clean enrich pass (rc==0) that produced NO new rows.
+set -u
+PROJ="$HOME/Projects/Designer-Wallcoverings/onboarding/sangetsu-lilycolor"
+cd "$PROJ" || exit 1
+ST="$PROJ/staging"; CACHE="$PROJ/.image-cache/lily"
+FINAL="$ST/enrichment-full-063026A.final.jsonl"
+GOOD="$ST/enrichment-full-063026A.good-seed2.jsonl"
+REC="$ST/enrichment-full-063026A.local-recovery.jsonl"
+LOG="$ST/enrich-localsup.log"
+log(){ echo "[localsup $(date '+%H:%M:%S')] $*" >> "$LOG"; }
+
+[ -d "$CACHE" ] || { log "FATAL cache missing $CACHE"; exit 1; }
+NC=$(find "$CACHE" -type f 2>/dev/null | wc -l | tr -d ' ')
+log "START local-supervised recovery. cache files=$NC"
+
+# good-seed2 = current final rows WITHOUT error and not usable:false
+python3 - "$FINAL" "$GOOD" <<'PY' 2>> "$LOG"
+import json,sys
+src,good=sys.argv[1],sys.argv[2]; bad=0; ok=0
+with open(good,"w") as g:
+    for line in open(src):
+        line=line.strip()
+        if not line: continue
+        try:o=json.loads(line)
+        except:continue
+        if o.get("error") or o.get("usable") is False: bad+=1; continue
+        ok+=1; g.write(json.dumps(o)+"\n")
+print(f"[seed] good={ok} to-redo={bad}")
+PY
+
+count(){ wc -l < "$REC" 2>/dev/null | tr -d ' ' || echo 0; }
+# supervise loop: relaunch on any jetsam/non-clean exit; stop on clean+no-new
+while true; do
+  before="$(count)"
+  ENRICH_HENRY_DIR="$CACHE" ENRICH_SHARD_COUNT=1 ENRICH_OLLAMA_URL=http://127.0.0.1:11434 \
+    ENRICH_DONE_SEEDS="$GOOD" python3 -u scripts/enrich-full.py "$REC" >> "$LOG" 2>&1
+  rc=$?; after="$(count)"
+  if [ "$rc" -eq 0 ] && [ "$before" = "$after" ]; then
+    log "COMPLETE (clean exit, no new rows at ${after})"; break
+  fi
+  log "pass rc=$rc rows ${before}->${after} — relaunch in 5s"; sleep 5
+done
+
+# Remerge ALL enrichment sources (last-wins) into final so nothing is lost.
+python3 - "$FINAL" <<'PY' 2>> "$LOG"
+import json,sys,glob,os
+ST=os.path.dirname(sys.argv[1]); final=sys.argv[1]
+srcs=[final, os.path.join(ST,"enrichment-full-063026A.good-seed2.jsonl"),
+      os.path.join(ST,"enrichment-full-063026A.local-recovery.jsonl"),
+      os.path.join(ST,"enrichment-full-063026A.local-recover.jsonl"),
+      os.path.join(ST,"enrichment-full-063026A.jsonl")]
+by={}
+def better(new,old):
+    # prefer a real enrichment row over an error/unusable one
+    def score(o): return 0 if (o.get("error") or o.get("usable") is False) else 1
+    return score(new) >= score(old)
+for p in srcs:
+    if not os.path.exists(p): continue
+    for line in open(p):
+        line=line.strip()
+        if not line: continue
+        try:o=json.loads(line)
+        except:continue
+        s=o.get("sku")
+        if not s: continue
+        if s not in by or better(o,by[s]): by[s]=o
+ok=sum(1 for o in by.values() if not o.get("error") and o.get("usable") is not False)
+with open(final,"w") as f:
+    for s in sorted(by): f.write(json.dumps(by[s])+"\n")
+print(f"[remerge] final={len(by)} ok={ok} err={len(by)-ok}")
+PY
+log "REMERGE done. final=$(wc -l < "$FINAL") rows"; touch "$ST/LOCALRE-DONE"; log "ALL DONE"

← d76076d1 gate-readiness.py: check error-tokens only in pattern-name s  ·  back to Designer Wallcoverings  ·  enrich-full.py: lock-guard exits 75 (busy) not 0, so supervi e830c243 →