[object Object]

← back to Designerwallcoverings

chore: lint, refactor, v0.1.1 (session close) — execFileSync + negative-limit guards + set -e + error log on stroheim-onboard

6bae8c2655bed67ffbf7770ceb9962bdbbeee7ba · 2026-07-26 19:57:41 -0700 · Steve Abrams

Files touched

Diff

commit 6bae8c2655bed67ffbf7770ceb9962bdbbeee7ba
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sun Jul 26 19:57:41 2026 -0700

    chore: lint, refactor, v0.1.1 (session close) — execFileSync + negative-limit guards + set -e + error log on stroheim-onboard
---
 package.json                                 |  6 ++++--
 scripts/stroheim-onboard/build-payloads.mjs  | 10 ++++++----
 scripts/stroheim-onboard/create-drafts.mjs   |  4 ++--
 scripts/stroheim-onboard/go-live.mjs         |  2 +-
 scripts/stroheim-onboard/resume.sh           |  2 +-
 scripts/stroheim-onboard/settlement-gate.mjs |  2 +-
 6 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/package.json b/package.json
index 533ed9e..64c9e07 100644
--- a/package.json
+++ b/package.json
@@ -1,13 +1,15 @@
 {
   "name": "designerwallcoverings-ai",
-  "version": "0.1.0",
+  "version": "0.1.1",
   "private": true,
   "description": "designerwallcoverings.ai — AI room-render landing. Upload a room photo, get matching wallcoverings.",
   "main": "server.js",
   "scripts": {
     "start": "node server.js"
   },
-  "engines": { "node": ">=20" },
+  "engines": {
+    "node": ">=20"
+  },
   "dependencies": {
     "express": "^4.19.2",
     "multer": "^2.0.1"
diff --git a/scripts/stroheim-onboard/build-payloads.mjs b/scripts/stroheim-onboard/build-payloads.mjs
index 97435bd..6734004 100644
--- a/scripts/stroheim-onboard/build-payloads.mjs
+++ b/scripts/stroheim-onboard/build-payloads.mjs
@@ -21,11 +21,12 @@
 import fs from 'node:fs';
 import path from 'node:path';
 import { fileURLToPath } from 'node:url';
-import { execSync } from 'node:child_process';
+import { execFileSync } from 'node:child_process';
 
 const HERE = path.dirname(fileURLToPath(import.meta.url));
 const OUT = path.join(HERE, 'out');
-const DB = 'postgresql:///dw_unified?host=/tmp';
+const PSQL = '/opt/homebrew/opt/postgresql@14/bin/psql';
+const PGENV = { ...process.env, PGHOST: '/tmp', PGDATABASE: 'dw_unified' };
 const BRAND = 'Stroheim';
 const SAMPLE_PRICE = '4.25';
 
@@ -36,13 +37,14 @@ const clean = s => (s || '').replace(/wall\s*paper/ig, 'Wallcovering').replace(/
 const isBadWord = s => !s || /unknown/i.test(s);
 
 function rows() {
-  const json = execSync(`psql "${DB}" -tAc "select coalesce(json_agg(row_to_json(t))::text,'[]') from (
+  const SQL = `select coalesce(json_agg(row_to_json(t))::text,'[]') from (
     select mfr_sku, proposed_dw_sku as dw_sku, pattern_name, color_name, collection, product_type,
            width, repeat_v, repeat_h, material, book,
            price_retail, dedup_status, image_url, thumb_url, product_url, shopify_product_id
     from stroheim_catalog
     where mfr_sku is not null
-    order by mfr_sku) t"`, { encoding: 'utf8', maxBuffer: 256 * 1024 * 1024 });
+    order by mfr_sku) t`;
+  const json = execFileSync(PSQL, ['-d', 'dw_unified', '-tAc', SQL], { env: PGENV, encoding: 'utf8', maxBuffer: 256 * 1024 * 1024 });
   return JSON.parse(json.trim());
 }
 
diff --git a/scripts/stroheim-onboard/create-drafts.mjs b/scripts/stroheim-onboard/create-drafts.mjs
index c1f56bf..e6916b7 100644
--- a/scripts/stroheim-onboard/create-drafts.mjs
+++ b/scripts/stroheim-onboard/create-drafts.mjs
@@ -72,7 +72,7 @@ async function liveStroheimSkus() {
     const s = new Set();
     for (const p of prods) for (const v of (p.variants || [])) if (v.sku) s.add(v.sku.toUpperCase());
     return s;
-  } catch { return new Set(); }
+  } catch (e) { console.error('  ⚠ liveStroheimSkus() failed:', String(e).slice(0, 120), '— live-SKU dedup disabled this run'); return new Set(); }
 }
 
 async function main() {
@@ -86,7 +86,7 @@ async function main() {
   const blocked = payloads.filter(p => verdict.get(p.sku.toUpperCase()) === 'BLOCK').length;
   const ungated = payloads.filter(p => !verdict.has(p.sku.toUpperCase())).length;
   let todo = gatedOk.filter(p => !liveSkus.has(p.sku.toUpperCase()) && !createdSku.has(p.sku.toUpperCase()));
-  if (LIMIT) todo = todo.slice(0, LIMIT);
+  if (LIMIT > 0) todo = todo.slice(0, LIMIT);
 
   const headroom = budget.remaining(BUDGET_CAT);
   console.log(`Store ${SHOP} · token …${TOKEN.slice(-4)} · payloads ${payloads.length} · settlement OK ${gatedOk.length} / BLOCK ${blocked} / ungated ${ungated} · live ${liveSkus.size} · to create ${todo.length} · '${BUDGET_CAT}' headroom ${headroom} variants (~${Math.floor(headroom/2)} products) · ${APPLY ? 'APPLY' : 'DRY-RUN'}`);
diff --git a/scripts/stroheim-onboard/go-live.mjs b/scripts/stroheim-onboard/go-live.mjs
index 8a76d3e..8aea4fb 100644
--- a/scripts/stroheim-onboard/go-live.mjs
+++ b/scripts/stroheim-onboard/go-live.mjs
@@ -117,7 +117,7 @@ async function goLive(pid, sku, mfrSku) {
   const verdict = new Map(loadJsonl('settlement-verdicts.jsonl').map(r => [r.sku.toUpperCase(), r.verdict]));
   const payload = new Map(loadJsonl('payloads.jsonl').map(o => [o.sku.toUpperCase(), o]));
   let todo = loadJsonl('created.jsonl').filter(r => !done.has(r.sku));
-  if (LIMIT) todo = todo.slice(0, LIMIT);
+  if (LIMIT > 0) todo = todo.slice(0, LIMIT);
   console.log(`go-live: ${todo.length} drafts · loc ${LOCATION_ID} · qty ${TARGET_QTY} · ${PUBLICATIONS.length} channels (Google excluded) · ${APPLY ? 'APPLY' : 'DRY-RUN'}`);
   if (!APPLY) { console.log('first 3:', todo.slice(0, 3).map(r => r.sku).join(', ')); console.log('DRY-RUN. --apply to execute (Steve-gated activation).'); return; }
 
diff --git a/scripts/stroheim-onboard/resume.sh b/scripts/stroheim-onboard/resume.sh
index 2900caf..ecb55f9 100755
--- a/scripts/stroheim-onboard/resume.sh
+++ b/scripts/stroheim-onboard/resume.sh
@@ -13,7 +13,7 @@
 #
 # HARD BLOCK: while price_retail is NULL, steps 1-4 no-op cleanly (build emits 0). This script
 # is NOT scheduled in launchd (scheduled-job install is itself gated) — run it by hand.
-set -uo pipefail
+set -euo pipefail
 cd "$(dirname "$0")" || exit 1
 export PATH="/opt/homebrew/bin:/opt/homebrew/opt/postgresql@14/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH"
 NODE="$(command -v node)"
diff --git a/scripts/stroheim-onboard/settlement-gate.mjs b/scripts/stroheim-onboard/settlement-gate.mjs
index 9ba2950..9263e37 100644
--- a/scripts/stroheim-onboard/settlement-gate.mjs
+++ b/scripts/stroheim-onboard/settlement-gate.mjs
@@ -87,7 +87,7 @@ async function main() {
   const done = new Map(loadJsonl('settlement-verdicts.jsonl').map(r => [r.sku.toUpperCase(), r]));
   let todo = payloads.filter(p => !done.has(p.sku.toUpperCase()));
   if (ONLY_SET) todo = todo.filter(p => ONLY_SET.has(p.sku.toUpperCase()));
-  if (LIMIT) todo = todo.slice(0, LIMIT);
+  if (LIMIT > 0) todo = todo.slice(0, LIMIT);
 
   console.log(`settlement-gate · model ${MODEL} · payloads ${payloads.length} · already-gated ${done.size} · to gate ${todo.length} · est $${(todo.length * COST_PER_IMG).toFixed(4)} · ${APPLY ? 'APPLY' : 'DRY-RUN'}`);
   if (payloads.length === 0) { console.log('  ℹ 0 payloads (price not yet sourced) — nothing to gate. $0.'); return; }

← 999aac3 recover wiped scripts/ tree: restore 325 untracked source fi  ·  back to Designerwallcoverings  ·  maharam-onboard: dedicated daily drip runner + launchd plist 18333b8 →