← back to Norma Platform
Norma IG cadence: fresh-source via Boost API (fixes clean-product pool exhaustion)
43de9ea5386433546ec13523423f8572e31f7819 · 2026-08-15 08:00:57 -0700 · Steve Abrams
Root cause: findProduct sourced only 10 candidates/keyword from suggest.json;
as everPosted grew, narrow-keyword pools exhausted -> 'no clean product … all reused'.
Fix pages the Boost SF-filter search API (50/page, thousands available) for the SAME
keyword, applying the IDENTICAL leak/no-image guard to every candidate + suggest.json
fallback. Widens the guard-gated pool WITHOUT loosening the private-label guard.
DTD 7/9 Option C, Cody-scoped. TK-10588.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M agents/instagram-agent/daily-cadence.js
Diff
commit 43de9ea5386433546ec13523423f8572e31f7819
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sat Aug 15 08:00:57 2026 -0700
Norma IG cadence: fresh-source via Boost API (fixes clean-product pool exhaustion)
Root cause: findProduct sourced only 10 candidates/keyword from suggest.json;
as everPosted grew, narrow-keyword pools exhausted -> 'no clean product … all reused'.
Fix pages the Boost SF-filter search API (50/page, thousands available) for the SAME
keyword, applying the IDENTICAL leak/no-image guard to every candidate + suggest.json
fallback. Widens the guard-gated pool WITHOUT loosening the private-label guard.
DTD 7/9 Option C, Cody-scoped. TK-10588.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
agents/instagram-agent/daily-cadence.js | 37 +++++++++++++++++++++++++++------
1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/agents/instagram-agent/daily-cadence.js b/agents/instagram-agent/daily-cadence.js
index 5c23afd..9a082e7 100644
--- a/agents/instagram-agent/daily-cadence.js
+++ b/agents/instagram-agent/daily-cadence.js
@@ -66,14 +66,19 @@ function themeFor(h) {
return { keyword, sensitive: !!o.sensitive };
}
-async function findProduct(keyword) {
- const u = `${STORE}/search/suggest.json?q=${encodeURIComponent(keyword)}&resources%5Btype%5D=product&resources%5Blimit%5D=10`;
- let list = [];
- try { const j = await (await fetch(u)).json(); list = (j.resources?.results?.products) || []; } catch { return null; }
+// Fresh-sourcing fix (TK-10588, DTD 7/9 C + Cody-scoped 2026-08-15): the old source was
+// suggest.json capped at 10 candidates/keyword, so narrow-keyword pools exhausted as everPosted
+// grew ("no clean product … all reused"). We now page the Boost SF-filter search API (50/keyword/page,
+// thousands available) for the SAME keyword. Every candidate STILL passes the identical leak/no-image
+// guard below — this WIDENS the guard-gated pool, it does NOT loosen the private-label guard.
+const BOOST_SHOP = 'designer-laboratory-sandbox.myshopify.com';
+const CANDIDATE_PAGES = 3; // up to 150 guard-gated candidates before giving up
+
+async function tryCandidates(list) {
for (const p of list) {
- if (everPosted.has(p.handle)) continue; // don't repost a product
+ if (!p.handle || everPosted.has(p.handle)) continue; // don't repost a product
try {
- const r = await content.resolveProduct(p.handle); // throws on leak/no-image (guard)
+ const r = await content.resolveProduct(p.handle); // throws on leak/no-image (guard) — UNCHANGED
if (everPostedImg.has(imgKey(r.image_url))) continue; // same image already posted — skip (no dup)
return { handle: p.handle, title: r.title, image_url: r.image_url };
} catch { /* leak or imageless — next */ }
@@ -81,6 +86,26 @@ async function findProduct(keyword) {
return null;
}
+async function findProduct(keyword) {
+ for (let page = 1; page <= CANDIDATE_PAGES; page++) {
+ let list = [];
+ try {
+ const u = `https://services.mybcapps.com/bc-sf-filter/search?q=${encodeURIComponent(keyword)}&shop=${BOOST_SHOP}&limit=50&page=${page}`;
+ const j = await (await fetch(u)).json();
+ list = j.products || [];
+ } catch { break; }
+ if (!list.length) break;
+ const hit = await tryCandidates(list);
+ if (hit) return hit;
+ }
+ // Fallback: original 10-capped suggest.json if the Boost API is unreachable.
+ try {
+ const u = `${STORE}/search/suggest.json?q=${encodeURIComponent(keyword)}&resources%5Btype%5D=product&resources%5Blimit%5D=10`;
+ const j = await (await fetch(u)).json();
+ return await tryCandidates((j.resources?.results?.products) || []);
+ } catch { return null; }
+}
+
(async () => {
if (isRestDay) { console.log('REST DAY (Sunday) — no posting today.'); return; }
const hour = now.getHours();
← 191eee1 IG cadence: dedup by IMAGE filename (not just product handle
·
back to Norma Platform
·
IG cadence: close carousel room-image dedup gap (Cody gate) 4b58e97 →