[object Object]

← back to Designer Wallcoverings

merge-staging: fold DTD-A fallback titles into merged set (title 37->100%); gate-readiness: word-boundary fix for BAD_TITLE_TOKENS (LW1404 '404' false-match). Gates untouched: cost 0, activation_ready 0.

151d386df1b87e9f7c2db3c56d065abc3c583791 · 2026-07-01 15:05:54 -0700 · Steve

Files touched

Diff

commit 151d386df1b87e9f7c2db3c56d065abc3c583791
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed Jul 1 15:05:54 2026 -0700

    merge-staging: fold DTD-A fallback titles into merged set (title 37->100%); gate-readiness: word-boundary fix for BAD_TITLE_TOKENS (LW1404 '404' false-match). Gates untouched: cost 0, activation_ready 0.
---
 .../sangetsu-lilycolor/scripts/gate-readiness.py   | 10 +++++--
 .../sangetsu-lilycolor/scripts/merge-staging.py    | 35 ++++++++++++++++++++--
 2 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/onboarding/sangetsu-lilycolor/scripts/gate-readiness.py b/onboarding/sangetsu-lilycolor/scripts/gate-readiness.py
index 1e1d7c41..61b2df86 100644
--- a/onboarding/sangetsu-lilycolor/scripts/gate-readiness.py
+++ b/onboarding/sangetsu-lilycolor/scripts/gate-readiness.py
@@ -58,10 +58,14 @@ def title_guard_ok(d):
     if BANNED in t.lower():          # "wallpaper" is banned ANYWHERE in the title
         return False
     # Error tokens (unknown/404/not found/…) are only meaningful in the PATTERN-NAME
-    # segment (before the first pipe). Checking the whole title false-matched "404"
-    # inside SKU ranges like LL6404 / LV2404.
+    # segment (before the first pipe), AND only as WHOLE words — a substring check
+    # false-matched "404" inside SKU codes like LL6404 / LV2404 / LW1404 (the
+    # MFR-SKU-fallback titles are legitimately just the SKU code).
     pattern_seg = re.split(r"[||]", t)[0].strip().lower()
-    return not any(tok in pattern_seg for tok in BAD_TITLE_TOKENS)
+    for tok in BAD_TITLE_TOKENS:
+        if re.search(r"(?<![0-9a-z])" + re.escape(tok) + r"(?![0-9a-z])", pattern_seg):
+            return False
+    return True
 
 
 def has_description(d):
diff --git a/onboarding/sangetsu-lilycolor/scripts/merge-staging.py b/onboarding/sangetsu-lilycolor/scripts/merge-staging.py
index 484b9753..b912a264 100644
--- a/onboarding/sangetsu-lilycolor/scripts/merge-staging.py
+++ b/onboarding/sangetsu-lilycolor/scripts/merge-staging.py
@@ -6,6 +6,10 @@ OFFLINE / non-gated prep. Left-joins onto the 2,543 unified-staging records
 (the publishable universe, keyed by mfr_sku):
   - design enrichment  (enrichment-full-063026A.jsonl,   key: sku)
   - EN titles          (lilycolor-titles-en-063026A.jsonl, key: sku)
+  - FALLBACK titles     (lilycolor-titles-fallback-063026A.jsonl, key: sku)
+      DTD-A synthesized titles for the 1,580 title-less SKUs (title_ja null).
+      Only applied when the record still has NO title after the JA/EN join —
+      so a real scraped/translated title always wins over the fallback.
 
 Preserves every gating flag exactly as-is (cost_confirmed, activation_ready,
 status) — this script NEVER flips a gate. It only co-locates the staged data
@@ -31,6 +35,7 @@ ENRICH = os.path.join(STAGING, "enrichment-full-063026A.final.jsonl")
 if not os.path.exists(ENRICH):
     ENRICH = os.path.join(STAGING, "enrichment-full-063026A.jsonl")
 TITLES = os.path.join(STAGING, "lilycolor-titles-en-063026A.jsonl")
+FALLBACK = os.path.join(STAGING, "lilycolor-titles-fallback-063026A.jsonl")
 
 OUT = os.path.join(STAGING, "lilycolor-merged-063026A.jsonl")
 ORPHANS = os.path.join(STAGING, "lilycolor-merge-orphans-063026A.json")
@@ -68,13 +73,16 @@ def load_by_key(path, key):
 def main():
     enrich = load_by_key(ENRICH, "sku")
     titles = load_by_key(TITLES, "sku")
+    fallback = load_by_key(FALLBACK, "sku")
 
     n_out = 0
     n_enriched = 0
     n_titled = 0
     n_both = 0
+    n_fallback = 0
     used_enrich = set()
     used_titles = set()
+    used_fallback = set()
 
     with open(UNIFIED) as fin, open(OUT, "w") as fout:
         for line in fin:
@@ -109,6 +117,28 @@ def main():
             else:
                 rec["_titled_en"] = False
 
+            # FALLBACK titles (DTD-A) — only when the record STILL has no title
+            # after the JA/EN join. A real title always wins over a synthesized
+            # one; gates are untouched (this only fills title_en so publish has a
+            # non-empty, compliant, guard-passing title for every SKU).
+            has_real_title = bool((rec.get("title_ja") or rec.get("title_en") or "").strip())
+            if not has_real_title:
+                fb = fallback.get(sku)
+                if fb and fb.get("title_en"):
+                    used_fallback.add(sku)
+                    rec["title_en"] = fb["title_en"]
+                    rec["pattern_en"] = fb.get("pattern_en")
+                    rec["_titled_fallback"] = True
+                    rec["needs_pattern_name"] = True   # synthesized — reviewable
+                    if fb.get("settlement_required"):
+                        # LIS Morris & Co birds/foliage — GATE before publish.
+                        rec["settlement_required"] = True
+                    n_fallback += 1
+                else:
+                    rec["_titled_fallback"] = False
+            else:
+                rec["_titled_fallback"] = False
+
             if e and t:
                 n_both += 1
 
@@ -129,8 +159,9 @@ def main():
 
     print(f"merged records written : {n_out}  -> {os.path.relpath(OUT, HERE)}")
     print(f"  with design enrichment: {n_enriched}  ({100*n_enriched//n_out}%)")
-    print(f"  with EN title         : {n_titled}  ({100*n_titled//n_out}%)")
-    print(f"  with BOTH             : {n_both}")
+    print(f"  with EN title (join)  : {n_titled}  ({100*n_titled//n_out}%)")
+    print(f"  with FALLBACK title   : {n_fallback}  (DTD-A, title-less SKUs; needs_pattern_name)")
+    print(f"  with BOTH enrich+title: {n_both}")
     print(f"orphans (enrich/title)  : {len(enrich_orphans)}/{len(title_orphans)}"
           f"  -> {os.path.relpath(ORPHANS, HERE)}")
     # sanity: gates must all still be closed at this staging phase

← f1960768 title-fallback.py: synthesize compliant titles for 1580 titl  ·  back to Designer Wallcoverings  ·  auto-save: 2026-07-01T15:07:02 (7 files) — DW-Programming/Im 8da7b499 →