[object Object]

← back to Designerwallcoverings

TK-11574: --offline mode so the headline count is reproducible + negative-tested

8e95060e9239982dd4c15765a3c8266138d7ffdf · 2026-09-13 16:41:35 -0700 · Steve Abrams

Cody's sharpest hole was that the shipped script could not reproduce the ticket's own
central number: it hardcoded the assumed window, so re-running it gave 60,165 while the
memo claimed 70,359 (the 70,359 came from an ad-hoc re-filter that was never shipped).

--offline <raw.jsonl> re-runs the identical derivation + extraction path over a saved
export with no Shopify call, so anyone can reproduce the number.

Both directions tested:
  positive  offline re-run over the saved export -> derived burst 23:17..23:27, 70,359. Matches.
  negative  forcing the ticket's assumed window [23:20:00,23:26:59] -> WINDOW DRIFT, exit 2.

The negative test is the point: a window that would undercount the job now refuses to
report rather than quietly returning a smaller number.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Eu4qMc5WBStSPq2FSnEcAG

Files touched

Diff

commit 8e95060e9239982dd4c15765a3c8266138d7ffdf
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sun Sep 13 16:41:35 2026 -0700

    TK-11574: --offline mode so the headline count is reproducible + negative-tested
    
    Cody's sharpest hole was that the shipped script could not reproduce the ticket's own
    central number: it hardcoded the assumed window, so re-running it gave 60,165 while the
    memo claimed 70,359 (the 70,359 came from an ad-hoc re-filter that was never shipped).
    
    --offline <raw.jsonl> re-runs the identical derivation + extraction path over a saved
    export with no Shopify call, so anyone can reproduce the number.
    
    Both directions tested:
      positive  offline re-run over the saved export -> derived burst 23:17..23:27, 70,359. Matches.
      negative  forcing the ticket's assumed window [23:20:00,23:26:59] -> WINDOW DRIFT, exit 2.
    
    The negative test is the point: a window that would undercount the job now refuses to
    report rather than quietly returning a smaller number.
    
    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01Eu4qMc5WBStSPq2FSnEcAG
---
 scripts/tk11574-titletag-backstop.mjs | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/scripts/tk11574-titletag-backstop.mjs b/scripts/tk11574-titletag-backstop.mjs
index afb9092..de5369d 100644
--- a/scripts/tk11574-titletag-backstop.mjs
+++ b/scripts/tk11574-titletag-backstop.mjs
@@ -65,15 +65,26 @@ async function poll(myId) {
 }
 
 const t0 = Date.now();
+
+// --offline <raw.jsonl> re-runs the window derivation + extraction over a PREVIOUSLY downloaded
+// export, with no Shopify call. This is what makes the headline count reproducible and testable:
+// the same code path that produces the number can be re-run by anyone against the saved raw file.
+const offIdx = process.argv.indexOf('--offline');
+let jsonl, done = { objectCount: 'offline' };
+if (offIdx !== -1) {
+  const src = process.argv[offIdx + 1];
+  console.error(`TK-11574 backstop: OFFLINE re-run over ${src} (no Shopify call)`);
+  jsonl = fs.readFileSync(src, 'utf8');
+} else {
 console.error('TK-11574 backstop: starting full-catalog bulk export (products + global.title_tag)...');
 const myId = await startBulk();
-const done = await poll(myId);
+done = await poll(myId);
 if (!done.url) { console.error('no results url (0 objects)'); process.exit(1); }
-
 console.error(`downloading ${done.objectCount} objects ...`);
 const res = await fetch(done.url);
-const jsonl = await res.text();
+jsonl = await res.text();
 fs.writeFileSync(RAW, jsonl);
+}
 const lines = jsonl.split('\n').filter(Boolean);
 
 // ---- derive the job burst empirically from every title_tag updatedAt in the catalog ----

← 7aa2e4e TK-11574: fix classifier substring bug + make the job window  ·  back to Designerwallcoverings  ·  TK-11076: Oxford-comma guard — stop the parser truncating fu 50b34e7 →