← back to Designerwallcoverings
Stroheim onboard: read-only price/coverage canary (auto-resume signal on price-landing); DTD 3/2, launchd install deferred (gated)
eb3b88765727bfef8481a8560e780d71987c5a9a · 2026-07-26 16:48:38 -0700 · Steve Abrams
Files touched
M .gitignoreA scripts/stroheim-onboard/price-canary.mjs
Diff
commit eb3b88765727bfef8481a8560e780d71987c5a9a
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sun Jul 26 16:48:38 2026 -0700
Stroheim onboard: read-only price/coverage canary (auto-resume signal on price-landing); DTD 3/2, launchd install deferred (gated)
---
.gitignore | 1 +
scripts/stroheim-onboard/price-canary.mjs | 56 +++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+)
diff --git a/.gitignore b/.gitignore
index ecfab95..d2fe66c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@ dist/
build/
.next/
uploads/
+scripts/stroheim-onboard/data/
diff --git a/scripts/stroheim-onboard/price-canary.mjs b/scripts/stroheim-onboard/price-canary.mjs
new file mode 100644
index 0000000..f7b19af
--- /dev/null
+++ b/scripts/stroheim-onboard/price-canary.mjs
@@ -0,0 +1,56 @@
+#!/usr/bin/env node
+/**
+ * Stroheim price/coverage canary — READ-ONLY. (DTD 3/2, yolo-plus 2026-07-26.)
+ *
+ * The onboard is complete but HELD on price (price_retail 100% NULL). This canary turns that
+ * indefinite external block into an auto-resume signal:
+ * • detects the NULL→non-NULL transition on price_retail (price has LANDED → onboard can fire)
+ * • reports coverage: staged · priced · minted (DWST) · drafts-on-Shopify
+ * • classifies BLOCKED_NO_PRICE / READY_TO_ONBOARD / ONBOARDING / DONE
+ * Writes data/latest.json each run (heartbeat + prior state for transition detection).
+ *
+ * Pure reads against the local dw_unified mirror — no writes, no network, $0 (local).
+ * NOTE: this only runs when invoked (or by resume.sh); wiring a launchd schedule + CNCP/George
+ * alert is a SEPARATE gated step (scheduled-job install) — drafted, not installed here.
+ *
+ * node price-canary.mjs # print verdict + coverage, update data/latest.json
+ */
+import fs from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+import { execFileSync } from 'node:child_process';
+
+const HERE = path.dirname(fileURLToPath(import.meta.url));
+const DATA = path.join(HERE, 'data');
+fs.mkdirSync(DATA, { recursive: true });
+const LATEST = path.join(DATA, 'latest.json');
+const PSQL = '/opt/homebrew/opt/postgresql@14/bin/psql';
+const PGENV = { ...process.env, PGHOST: '/tmp', PGDATABASE: 'dw_unified' };
+const q = sql => execFileSync(PSQL, ['-d', 'dw_unified', '-tAc', sql], { env: PGENV, encoding: 'utf8' }).trim();
+
+const stats = JSON.parse(q(`SELECT json_build_object(
+ 'staged', count(*),
+ 'priced', count(*) FILTER (WHERE price_retail IS NOT NULL AND price_retail > 0),
+ 'minted', count(*) FILTER (WHERE proposed_dw_sku IS NOT NULL),
+ 'on_shopify', count(*) FILTER (WHERE on_shopify IS TRUE),
+ 'net_new', count(*) FILTER (WHERE dedup_status = 'net_new')
+)::text FROM stroheim_catalog`));
+
+let verdict;
+if (stats.priced === 0) verdict = 'BLOCKED_NO_PRICE';
+else if (stats.on_shopify === 0) verdict = 'READY_TO_ONBOARD';
+else if (stats.on_shopify < stats.priced) verdict = 'ONBOARDING';
+else verdict = 'DONE';
+
+const prior = fs.existsSync(LATEST) ? JSON.parse(fs.readFileSync(LATEST, 'utf8')) : null;
+const priceLanded = prior && prior.priced === 0 && stats.priced > 0; // NULL→non-NULL transition
+
+const rec = { checked_at: new Date().toISOString(), verdict, ...stats,
+ coverage_pct: stats.priced ? Math.round((stats.on_shopify / stats.priced) * 100) : 0,
+ price_landed_transition: !!priceLanded };
+fs.writeFileSync(LATEST, JSON.stringify(rec, null, 2));
+
+const bar = { BLOCKED_NO_PRICE: '⛔', READY_TO_ONBOARD: '🟢', ONBOARDING: '🔄', DONE: '✅' }[verdict];
+console.log(`${bar} Stroheim ${verdict} · staged ${stats.staged} · priced ${stats.priced} · minted ${stats.minted} · on-Shopify ${stats.on_shopify} (${rec.coverage_pct}%)`);
+if (priceLanded) console.log(` 🔔 PRICE LANDED (was NULL) — run resume.sh to fire the onboard (mint → build → gate → create-drafts).`);
+if (verdict === 'BLOCKED_NO_PRICE') console.log(` waiting on Steve: populate stroheim_catalog.price_retail (trade-login scrape or cost-map).`);
← 07f745c Stroheim onboard: add settlement-gate + go-live (Steve-gated
·
back to Designerwallcoverings
·
stout-onboard: fix stale docs — double-roll (not single), Ge 16717b2 →