{"slug":"rebel-walls-push","total":41,"limit":100,"offset":0,"since":null,"commits":[{"hash":"f46edb3","date":"2026-09-22 17:52:43 -0700","author":"Steve Abrams","subject":"Fix: replace hardcoded-path shim with portable resolution (TK-11786)","body":"The inventory-stamp-guard.mjs shim now resolves via DW_SHARED_GUARDS env or\nhome-dir fallback instead of hardcoded /Users/macstudio3 path. This enables\nthe guard to work on Kamatera (/root), Mac1, and any other machine.\n\nESM consumers (import) work correctly. CJS consumers (require) fail safely\nwith ERR_REQUIRE_ASYNC_MODULE, preventing silent bad defaults on inventory\nstamps. CJS call sites should use dynamic import() instead.\n\nOriginal vendored copy preserved as inventory-stamp-guard.mjs.pre-shared-lift.\nThe $0-orderable guard (TK-11357) now has ONE source of truth at\n~/Projects/_shared/dw-guards/.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01WoD95uATtwJXUZvQ7PNPsB"},{"hash":"960314b","date":"2026-09-22 11:44:34 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-22T11:43:24 (1 data files) — scripts/lib/inventory-stamp-guard.mjs.pre-shared-lift","body":""},{"hash":"68b2721","date":"2026-09-10 09:44:20 -0700","author":"Steve","subject":"guard TK-11357 Fix D: rebel-walls push.js — refuse to MINT a $0 mural, and never CONTINUE it","body":"SCHEDULED: reached from run-cadence-hourly.sh:117 via cadence-daily-step.sh behind an $RW_MARK\nmarker, i.e. effectively daily. Behind a multi-hop .sh chain, which is why plist greps missed it.\n\nPRE-EXISTING GUARD STATE (whole path read, not assumed): NO price gate anywhere. fetchRows()\nfilters only on `(shopify_product_id IS NULL OR = '') AND dedup_skip IS NOT TRUE`; there is no\nprice_retail condition in the SQL and none in JS. buildInput() then prices the main mural variant\n`String(row.price_retail)` with inventoryPolicy CONTINUE and tracked:true.\n\nWhy CONTINUE is the dangerous part: CONTINUE (oversell) makes a variant orderable at ANY quantity\nINCLUDING ZERO. So a $0 variant minted here is orderable AND the established qty->0 stopgap for\nthis defect class is a NO-OP against it. Guarding only the quantity would have been decorative.\n\nTHREE fixes:\n  (a) pushRow() refuses to create when !(Number(row.price_retail) > 0). Safe + idempotent: this is\n      a create-only MINTING path (hard-coded VENDOR 'Rebel Walls'), it cannot revert an existing\n      cohort, and the row keeps shopify_product_id NULL so it is re-picked when a real price lands.\n      The caller reports it as HELD, not FAILED, and logs it to the progress log.\n  (b) inventoryPolicy comes from the guard: CONTINUE only for a genuinely priced mural, 'deny'\n      otherwise (uppercased for the productSet enum). Priced murals keep CONTINUE unchanged.\n  (c) publishAndStock()'s flat QTY_2026 stamp is guarded too. HONEST NOTE: that path is currently\n      unreachable for new rows — buildInput() mints DRAFT/ARCHIVED and the call is gated on\n      status === 'ACTIVE' despite the comment above it claiming ACTIVE. Guarded anyway so flipping\n      that decision back cannot silently reopen the hole. The mutation already returned each\n      variant's price; it now returns `title` too, for guard accuracy.\n\nShared guard vendored to scripts/lib/. Proven by the Designer-Wallcoverings harness:\n4/4 required + 3/3 regression + P8 policy 2/2 ($0->deny, priced->continue).\nSOURCE-ONLY: nothing run, no Shopify write. Reversible: git revert.\n\nCo-Authored-By: Claude Opus 5 <noreply@anthropic.com>"},{"hash":"359cbbf","date":"2026-09-04 23:59:00 -0700","author":"Steve Abrams","subject":"TK-10405 full-fix EXECUTED: reordered Mural(per m²)->pos1 + Sample->pos2, DELETED the 2 Default-Title orphans on dwrw-76016 + dwrw-76264","body":"Supersedes the A' mitigation. End state verified live (Admin API + storefront):\nboth PDPs now read offers[0]=$117.47, Default-Title absent. Reversible via\nscripts/TK-10405-fullfix-undo.mjs (recreates orphan from captured pre-state).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"d6494a0","date":"2026-09-04 14:54:24 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-04T14:52:10 (1 data files) — data/TK-10405-restore-map.json","body":""},{"hash":"89338f9","date":"2026-09-04 13:25:31 -0700","author":"Steve Abrams","subject":"TK-10405: A' mitigation executor + undo for the 2 held RW pos-1 orphans (append -DUP + inventory 0)","body":""},{"hash":"8debf6b","date":"2026-09-04 12:23:34 -0700","author":"Steve Abrams","subject":"TK-11248 EXECUTED: Aries title fixed live; guard held 2 position-1 RW products; 10 deletes done concurrently","body":"- TK-11238: productUpdate fired -> 'Aries - Akoya Type II Vinyl Wallcovering | Hollywood Wallcoverings' (verified live ACTIVE, ledgered, undo=TK-11238-restore.json).\n- TK-10405: hardened executor with DTD-verdict guard (position-1/default-served + dw_unified mirror id-reference). Guard correctly HELD 2 position-1 products (6679729078323 $80.48 anomaly, 6679739629619 A Priori) for A' follow-up. The other 10 (position-3) were deleted by a concurrent batch agent; this run detected drift (dt=0) and refused to double-write. Live verify: 10/10 deleted-clean (Mural+Sample), 2/2 held intact, 0 anomalies.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01HzpfrKkjFqGRUrMEQGhFFW"},{"hash":"ff9dbfb","date":"2026-09-04 12:16:12 -0700","author":"Steve Abrams","subject":"TK-11248 action G: read-only revalidation confirms 6 cleared descriptions already live (no write needed)","body":"All 6 settlement-CLEARED Rebel Walls murals carry authorized descriptionHtml,\nall DRAFT, 0 activated. 4 from TK-11192 (9/3); 2 refreshed in the 9/4 18:26 wave\n(word-identical, curly-vs-straight apostrophe only). Holds intact: R20805 blocked,\n5 counsel untouched (len=0). Stopped on the (benign) drift per instruction — no\ncustomer-facing write fired.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01RFJimFhUJowuXnXtjNTLEC"},{"hash":"3fbf2ca","date":"2026-09-04 12:14:39 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-04T12:10:54 (2 data files) — data/TK11248-descG-revalidation-2026-09-04T19-13-18-778Z.json scripts/descG-copy.json","body":""},{"hash":"3111ca5","date":"2026-09-04 11:00:57 -0700","author":"Steve Abrams","subject":"TK-11248 prep: revalidate + gated executor + rollback for TK-11238 (Aries title) + TK-10405 (12 RW Default-Title deletes)","body":"Read-only revalidation confirms both live targets exactly match characterization\n(Aries ACTIVE, old title verbatim; 12 products each 3 variants -> 1 Default-Title\n+ distinct Mural + Sample survivors). Executor is DRY-RUN by default and hard-gated:\n--apply requires --approval=TK-11248 + a sentinel token file written only after\nSteve's explicit approval on TK-11248 (proven: premature --apply exits 3, no write).\nRestore maps written for one-command rollback. NO Shopify writes fired.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01HzpfrKkjFqGRUrMEQGhFFW"},{"hash":"5b92c13","date":"2026-09-03 14:31:39 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-03T14:29:24 (1 data files) — data/relabel-2flagged-rollback-2026-09-03T20-58-23-544Z.json","body":""},{"hash":"5688941","date":"2026-09-03 14:01:00 -0700","author":"Steve Abrams","subject":"Relabel 2 mural-typed Rebel Walls products Single Roll -> Mural (per m²) (TK-10029, Steve-approved); rollback map committed","body":""},{"hash":"3fda4bb","date":"2026-09-03 13:56:13 -0700","author":"Steve Abrams","subject":"Add read-only confirm for soft roll/bolt cohort (TK-10029 DTD verdict C): flags mural-typed products hiding under a Single Roll label","body":""},{"hash":"d710728","date":"2026-09-03 13:47:31 -0700","author":"Steve Abrams","subject":"Add read-only roll/bolt audit (TK-10029): group the 280 held products by unit label","body":""},{"hash":"2b3cea0","date":"2026-09-03 12:33:45 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-03T12:32:21 (1 data files) — data/TK-11192-rebel6-desc-restore-2026-09-03T19-01-48-717Z.jsonl","body":""},{"hash":"12856c3","date":"2026-09-03 12:28:25 -0700","author":"Steve Abrams","subject":"TK-10029: runnable Scope-B rollback (reverse 1220 relabels from durable map)","body":"Reads the committed B rollback map and renames each touched option value from\n'Mural (per m²)' back to its recorded old_value. Dry-run default; --apply reverts.\nIdempotent; never touches the 280 held roll/bolt or originally-canonical products.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"c93997d","date":"2026-09-03 12:09:07 -0700","author":"Steve Abrams","subject":"TK-10029: retry gql() on transient Shopify upstream errors (backoff)","body":"A non-JSON 'upstream connect error' gateway blip was crashing long --apply\nruns mid-flight (JSON.parse throw, no retry). Split into gqlOnce + a 6-attempt\nexponential-backoff gql wrapper. Transport-only; rename set/hold logic unchanged.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"dd06ad8","date":"2026-09-03 11:17:31 -0700","author":"Steve Abrams","subject":"TK-10029: durable scope-B rollback map (1220 rows) + generator","body":"Captures old->new for exactly the 1220 per-m² FIX rows the\n--apply --hold-rollbolt run touches (1144 Sold Per Square Meter +\n76 Complete Mural, zero held roll/bolt). Deterministic non-destructive\nreverse documented in the map.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01PZBUFotX5YXv7nUtTtAa2r"},{"hash":"72b8edd","date":"2026-09-03 11:09:51 -0700","author":"Steve Abrams","subject":"TK-10029: one-command rollback executor (reads durable ledger, reverts canonical->old_value)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01VA9ekkiMa6vAC2RaDP11zU"},{"hash":"789f983","date":"2026-09-03 11:07:45 -0700","author":"Steve Abrams","subject":"TK-10029: fresh complete pre-apply rollback ledger (1500 renames + 12 orphans, current live state)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01VA9ekkiMa6vAC2RaDP11zU"},{"hash":"080e96f","date":"2026-09-03 11:07:12 -0700","author":"Steve Abrams","subject":"TK-10029: add --hold-rollbolt flag (scope B) to relabel-units.js","body":"Subtractive flag that excises the roll/bolt unit-of-sale cohort\n(roll / single roll / sold per roll / sold per bolt (20.5in x 33ft))\nfrom the wrong-label set entirely, so those variants are neither FIXed\nnor REVIEWed. Scope-A behavior unchanged when the flag is absent.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01PZBUFotX5YXv7nUtTtAa2r"},{"hash":"59a6e8f","date":"2026-08-31 10:59:34 -0700","author":"Steve Abrams","subject":"route relabel-units to SHOPIFY_FULL_ACCESS_TOKEN (TK-10979 DTD-A bridge)","body":""},{"hash":"6880860","date":"2026-08-27 09:22:35 -0700","author":"Steve Abrams","subject":"TK-10029: durable pre-apply rollback ledger (1467 renames + 12 review orphans, from live)","body":""},{"hash":"be208a1","date":"2026-08-10 09:44:52 -0700","author":"Steve Abrams","subject":"TK-10029: retarget relabel to canonical 'Mural (per m²)' (DTD Option A, 7/7)","body":"- CORRECT_LABEL now 'Mural (per m²)' — the label the live importer push.js already mints\n- converge legacy roll/bolt/complete-mural + interim 'Sold Per Square Meter' + mojibake onto it\n- robust matcher isWrongMuralLabel() catches corrupted 'Mural (per m<?>)'\n- NON-DESTRUCTIVE: renames only, never deletes a variant, never creates a duplicate canonical\n- collision/orphan cases (canonical already present + Default Title) FLAGGED for manual review, not auto-modified\n- dry-run: 1467 renames, 0 deletes, 12 review; still --apply-gated (live customer-facing write)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"09027cf","date":"2026-07-30 04:06:22 -0700","author":"Steve Abrams","subject":"relabel-units: skip sample products from Roll→SqMeter relabel","body":"84 'Memo Sample' products were wrongly included in the fix set because\n'Default Title' matched WRONG_MURAL_LABELS. Added isSampleProduct() guard\nthat checks title for 'memo sample' / ' sample' / ends-with 'sample'.\nDry-run now shows 370 true mural products needing relabel (was 454).\n\nCo-author: steve@designerwallcoverings.com"},{"hash":"5f49d70","date":"2026-07-29 04:20:48 -0700","author":"steve@designerwallcoverings.com","subject":"TK-10029: add relabel-units.js — dry-run verified, 454 products need unit relabel","body":""},{"hash":"2f475a9","date":"2026-07-21 13:37:51 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-21T13:37:45 (1 files) — scripts/push.js.bak-20260721-131041","body":""},{"hash":"fa667c7","date":"2026-07-21 13:11:11 -0700","author":"Steve Abrams","subject":"push: create DRAFT not ACTIVE so Rebel Walls flows through the unified rotation","body":""},{"hash":"e6677f9","date":"2026-07-08 15:56:09 -0700","author":"Steve Abrams","subject":"GMC re-gate: exclude Google & YouTube publication (29646651457) from push + activate","body":"Both run on a daily cron and re-leaked the $4.25 sample price to the Google channel.\nFilter Google out of loadPublications() in each. Google is fed by the controlled TSV\nfeed only. Inline + reversible.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"2f4dc48","date":"2026-07-03 08:08:15 -0700","author":"Steve","subject":"chore: macstudio3 migration — reconcile from mac2 + repoint paths (stevestudio2→macstudio3, node/npm/npx→/opt/homebrew)","body":""},{"hash":"a3c8752","date":"2026-06-30 15:22:47 -0700","author":"Steve Abrams","subject":"Add RW cadence daily step — 5 murals/day, budget-coordinated, DRY by default","body":"Steve 2026-06-30: '5 new SKUs a day, focusing on murals' (RW is 100% murals). Budget-coordinated\nvia the shared variant ledger (take 'rebel' N) so it never races the hourly uploader. DRY by default;\n--commit creates live. NOTE: push.js dry flag is --dry-run (an initial --dry typo created 5 live\nproducts DWRW-361150..361154 = today's authorized batch; flag corrected, true-dry now verified 0 writes)."},{"hash":"d7447f1","date":"2026-06-22 09:25:46 -0700","author":"Steve Abrams","subject":"secret-strip: remove hardcoded dw_admin password from PG config (env-first, no rotation/deploy)","body":""},{"hash":"e01aadd","date":"2026-06-09 13:00:38 -0700","author":"SteveStudio2","subject":"launchd plist for daily staggered push (Steve pastes the load command)","body":"Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>"},{"hash":"d3719d0","date":"2026-06-09 12:59:50 -0700","author":"SteveStudio2","subject":"daily-push.sh: capped daily slice wrapper for the staggered push","body":"Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>"},{"hash":"1e70258","date":"2026-06-09 11:16:11 -0700","author":"SteveStudio2","subject":"dedup-guard push: skip 759 patterns already live under older Rebel Walls SKUs (DTD verdict A)","body":"- dedup-flag.js: tightened pattern+exact-color match vs older live cohort (DWRW-72201..451820);\n  flags 759 true dups, leaves 2,874 net-new pushable via reversible dedup_skip column\n- push.js fetchRows: AND dedup_skip IS NOT TRUE (null-safe) so resume pushes only net-new\n- verify-live.js / reconcile-from-shopify.js: read-only Shopify count + sku->id helpers"},{"hash":"c54afd5","date":"2026-06-04 08:29:40 -0700","author":"SteveStudio2","subject":"Rebel Walls: bake live-on-create (ACTIVE + all channels + inventory 2026) into pusher; add activation pass for already-pushed products","body":"push.js now creates non-discontinued products as ACTIVE with tracked variants,\npublishes to all 13 publications, and sets available=2026 on both variants after\neach productSet. New activate.js does the same for the ~500 already-pushed DRAFT\nproducts (idempotent, resumable via activated_at checkpoint). _shop.js shared\nGraphQL/psql helper with 429/throttle backoff.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"6401830","date":"2026-06-04 08:01:29 -0700","author":"SteveStudio2","subject":"add retitle.js: title-only bulk update inserting \" Wallcoverings\", resumable, idempotent","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"de60df5","date":"2026-06-04 08:00:09 -0700","author":"SteveStudio2","subject":"rebel walls title: insert \" Wallcoverings\" before \" | Rebel Walls\" suffix","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"f6de296","date":"2026-06-04 00:14:36 -0700","author":"Steve","subject":"align metafield types to store defs; canary 5 verified clean in Shopify","body":""},{"hash":"87b7133","date":"2026-06-04 00:12:39 -0700","author":"Steve","subject":"title-caser preserves 3D/ABC/acronym tokens","body":""},{"hash":"3dcaf20","date":"2026-06-04 00:11:47 -0700","author":"Steve","subject":"rebel walls -> shopify pusher (productSet, draft, sample variant, resumable)","body":""}]}