Creative ideas + design notes
Commits with substantial prose (≥120 chars) — the rationale behind each move.
cfd73e8 · 2026-09-24 · TK-12136: drop 8 fake-hires P2 rows (native 400px via pad=true); P2-final map = 3 real + 32 P2b
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FdQNVBL3doxmMXmnn6kSAZ
700132b · 2026-09-24 · TK-12136 P2b: deeper re-resolve of 128 kravet slug-misses
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FdQNVBL3doxmMXmnn6kSAZ
c181cc4 · 2026-09-24 · TK-12136 P2 remainder map: 11 unapplied rows, live-verified still 400px
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FdQNVBL3doxmMXmnn6kSAZ
1278615 · 2026-09-24 · Add dupe-media cleanup for TK-12097 concurrent Batch-A run
Two apply runs processed Batch A at once; each uploaded its own copy of
the same hi-res image, leaving 249 products with a redundant duplicate.
The tool picks which copy to remove from a live per-product read rather
than from ledger order, refuses when the featured media is not one of the
two uploaded copies, and refuses when the low-res rollback anchor is
missing. Dry-run by default; deletions are ledgered with a re-upload undo.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY
5489959 · 2026-09-24 · Add live Shopify verifier for TK-12097 hi-res swap ledgers
Re-probes a random sample of ledger rows against the live store and
confirms the product's current featured media is the ledger's new
media and that it is larger than the retained low-res anchor.
Distinguishes NOT-MEASURED (API unreachable) from PASS so a dead
token cannot read as a clean run.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY
c176a22 · 2026-09-24 · TK-12097 P2+P3: 20 slug-reresolve recoveries + Hollywood momentum re-scrape spec (TK-12134)
P2: 150 kravet.com slug-misses -> 20 recovered (naive_slug never converted spaces; fixed slug
resolves name-alias redirects), all 2048px colorway-safe .auto; 128 genuinely off-kravet, 2
wrong-colorway dropped. P3: 434 Hollywood no-source = 100% absent from stale momentum snapshot
(Meilisearch 20k cap); ~405 recoverable via refresh.mjs; spec + ticket TK-12134.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAz5GCSg6DiHMufykgedet
011ebf6 · 2026-09-24 · TK-12097: no-source re-scrape lane (763 A/C/D) characterized + 44 immediate recoveries
Buckets: 44 recoverable_now (.auto hero, phase-2 .jpg-forcing bug — 30/30 sampled confirmed >=800px,
built to batchD-plus map, colorway-verified, dry-run clean); 434 Hollywood no-momentum-mapping
(needs live re-scrape); 150 kravet.com slug-miss (re-resolve via product_url/search); 129 vendor-capped
<=400px (recheck quarterly); 6 placeholder/discontinued. 179 discontinued patterns flagged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAz5GCSg6DiHMufykgedet
1a1afae · 2026-09-24 · TK-12090 Fix 2: apply-hires.mjs — orphan-media ledgering + throttle backoff
2a — a throw AFTER productCreateMedia succeeded (poll/reorder/ledger-write)
left the new media live on the product with no ledger row, so --rollback
(ledger-driven) was blind to it. newMediaId is now tracked outside the
try block; the catch path writes an `orphaned: true` row (old_media_id,
orphaned_media_id, the error) to both the per-run ledger and the fleet
exec-ledger instead of attempting a best-effort delete that could itself
throw on the same fault that caused the orphan. --rollback now splits
completed swaps (reorder back to old_media_id) from orphan rows (delete
the orphan media outright, since nothing was ever displaced) so an
orphan is never mistaken for an applied swap.
2b — shopify() threw immediately on THROTTLED/429 with no retry, and this
script shares one SHOPIFY_ADMIN_TOKEN rate bucket with T4
(shopify-room-mockup.py). Added bounded exponential backoff + jitter
(--max-retries, default 6), honoring Shopify's own throttleStatus hint
or a Retry-After header when present, with every backoff logged so a
throttled run is visibly slow rather than silently stalled. Concurrency
is unchanged (batches stay sequential).
Negative tests (scripted global.fetch mock, zero live Shopify calls):
post-create throw -> orphan row + rollback dry-run/live correctly
delete-not-reorder it; THROTTLED -> retry+recover with an honored wait;
always-THROTTLED -> bounded retries (exhausts, reports failed, never
hangs or falsely applies). All 6 checks pass; real fleet ledgers
(project apply-ledger.jsonl + ~/.claude/.../executed-reversible/ledger.jsonl)
confirmed untouched by the test run.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY
fe1692c · 2026-09-24 · TK-12097 Batch A: verify 99 tier-2 cross-ref rows vs kravet.com (99/99 colorway-correct) -> fold 98 (>=800) in; Batch A now 550 rows
Every tier-2 row (legacy B&F/Lee Jofa cross-ref codes, e.g. 8013149<->33127) resolved to the
requested product's own kravet.com page, isMain hero matches recorded URL, color present.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAz5GCSg6DiHMufykgedet
dae45e5 · 2026-09-24 · TK-12097 Batch D: Gaston Y Daniela dry-run map (436 colorway-safe @ >=1200px)
520 low-res(<=500px); staging (165 rows) contributed 0 (doesn't cover active GDT/LCT fabrics);
436 via phase-2 kravet.com Brandfolder hero, all filename-verified colorway-safe, all >=1200px;
84 no-source. Dry-run 0 writes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAz5GCSg6DiHMufykgedet
1a8a6f5 · 2026-09-24 · TK-12097 Batch B+C: dry-run maps (measured, colorway-safe)
Batch B Jeffrey Stevens: 851 low-res(<=500px) but jeffrey_stevens_catalog is a MIRROR of the
live store (memo 600-1800px yorkwall claim FALSE) -> only 1 genuine upgrade (ext Schumacher S3
1200px). Batch C Hollywood: 741 low-res, 307 colorway-safe upgrades via momentum_colorways
Cloudinary TRUE-NATIVE (c_scale,w_2000 upscales=fake; used transform-removed original); dw_sku
join dead (fabricated DWHD-*), used unique mfr-code join. Both dry-run 0 writes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAz5GCSg6DiHMufykgedet
1cf9573 · 2026-09-23 · TK-12097 Batch A: build colorway-safe hi-res swap map (452 rows @ >=800px) + dry-run clean
814 live-measured low-res(<=400px) Kravet-family ACTIVE products; hi-res resolved from vendor
_catalog Brandfolder (colorway-exact) + kravet.com Brandfolder hero (phase-2, filename-verified
colorway). 470 colorway-safe upgrades, 452 at >=800px floor. 99 held (color matches, pattern
base differs -> unverified). 245 no bigger vendor asset. Dry-run: 452 rows, 3 batches, 0 writes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAz5GCSg6DiHMufykgedet
8ab5855 · 2026-09-23 · TK-12090: parameterize low-res width threshold (--max-width, default 400) to fix Batch B false-green skip risk
Batch B (Jeffrey Stevens ~665 products) targets <500px low-res, but the hardcoded 400px threshold at L171 was skipping ALL of them as 'already moved'. Added --max-width parameter (defaults to 400 for Batch A Kravet compatibility) so each batch can specify its own threshold: Batch A=400, Batch B=500, Batch C=640, Batch D=650 (per memo targets). Also fixed the skip message to show the actual limit being applied, not the hardcoded 400.
1ee7e73 · 2026-09-15 · apply-hires: rollback self-scopes by --ticket (shared-ledger over-revert fix)
data/apply-ledger.jsonl accumulates every phase's swaps (TK-11658 1546 +
TK-11740 84 + TK-11742 28 = 1658), so the old undo reverted ALL of them.
rollback() now reverses only TICKET's entries by default; --all-tickets restores
the whole-ledger behavior explicitly; baked-in undo_cmd now carries --ticket so
each run's recorded undo self-scopes. Guards exit 2 on an unknown ticket.
Verified dry-run: TK-11740->84, TK-11742->28, --all-tickets->1658, all of 1658.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HgXb7b5SZbb9MNZwNZW94q
0c1deb7 · 2026-09-15 · TK-11740: post-apply review — scoped rollback ledger (84) + live verify PASS 84/84 hi-res held
Scoped rollback data/rollback-tk11740.jsonl reverses exactly TK-11740's 84
(vs baked-in undo_cmd targeting the shared 1658-entry apply-ledger.jsonl).
verify-tk11740.mjs is read-only; confirms 84/84 featured==new hi-res media live.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HgXb7b5SZbb9MNZwNZW94q
8c73060 · 2026-09-15 · TK-11740: apply-ledger — 84/84 fixable oversized-source variants swapped to hi-res
Steve-approved live apply complete over 3 runs (resize param iterated: fit=bound -> +quality=90
for JPEG -> bound=3000 for PNG). Final: 84/84 fixable = hi-res, 0 failed, old 400px kept per
product as rollback anchor. 28 broken-source variants tracked separately in TK-11742.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R9NqWUYGborGRqS4NMyA13
087fb5e · 2026-09-14 · TK-11658 cycle3: pre-flight Phase-1 621 swappable rows + measure live state
- preflight-phase1.py: MEASURE all 621 (ranged GET+PIL), cap oversized w/ TK-11740
per-format Brandfolder param, RE-MEASURE capped. 495 pass as-is, 84 pass-after-cap,
42 flagged (14 kravet placeholder-thumb, 1 dead 404, 27 unprocessable 422 PNGs).
- live-featured-check.mjs (read-only): ground truth = 529/621 ALREADY hi-res live.
- normalized-map.json (579 clean, idempotent-safe) + remaining-map.json (50 real delta)
+ clean/flagged split. Pre-flight only; no --live.
80f62c8 · 2026-09-14 · TK-11740: PNG dim-cap (bound=3000) + longer processing poll — fixes final 8
Second live run: 76/84 landed; 8 self-healed. Root causes: (a) 6 .CAC PNG sources stay ~20MB
even resized because Brandfolder ignores &quality/&format on PNG (lossless) -> cap PNG dims to
3000px (~11-15MB); (b) 2 valid JPEGs false-healed on the 45s processing poll -> bump poll to 75s.
JPEG sources keep quality=90@4472. Already-live products race-skip on re-run.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R9NqWUYGborGRqS4NMyA13
0e5f574 · 2026-09-14 · TK-11740: add &quality=90 to resize param — fixes 53/84 that failed Shopify 20MB byte limit
First live run: fit=bound kept dims at 4472px (<=20MP) but the JPEG came back ~24MB, over
Shopify's 20MB BYTE limit -> productCreateMedia processing FAILED for 53/84 (all self-healed
to old 400px, no breakage). &quality=90 compresses to ~6MB worst-case, full 4472px retained.
The 31 that already succeeded are race-skipped on re-run.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R9NqWUYGborGRqS4NMyA13
11e8962 · 2026-09-14 · TK-11658 Phase-2 + TK-11742: recover Kravet-family hi-res via vendor gallery re-scrape
- phase2-recover.py: feed-first brandfolder gallery-hero extractor ($0, 12-way parallel, resumable)
- 1,621 targets processed: 806 recovered(>1200px) / 568 below-threshold(401-1200px) / 247 absent
- TK-11742: 28/28 broken-source residuals recovered (gallery hero != broken direct URL)
- TK-11658 Phase-2: 778 recovered + 568 below-1200 upgrades + 247 genuinely-absent
- staging maps built (apply-hires.mjs-compatible, rollback_url per row): phase2 / phase2b-below1200 / tk11742
- data/phase2-absent.json: 247 for ACTIVE->DRAFT/Needs-Image follow-up
- both maps dry-run clean (0 writes, $0)
f64f457 · 2026-09-14 · TK-11740: apply-hires.mjs — additive --ticket override (default TK-11658)
Lets subset re-runs tag their ledger rows correctly (e.g. --ticket TK-11740).
No behavior change unless passed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R9NqWUYGborGRqS4NMyA13
ecf0161 · 2026-09-14 · TK-11740: oversized-source residual subset — 84 resize-fixable + 28 broken-source split
Brandfolder CDN supports aspect-preserving resize (?width=4472&height=4472&fit=bound,
verified <=4472px/<=20MP, under Shopify's ~20MP limit; parent's accepted swaps topped 4480px).
84 of 112 residuals resize cleanly (source 200); 28 have broken sources (1x404 dead jpg,
27x422 unprocessable PNGs) that resizing cannot fix -> need re-scrape (data/hires-broken-source.txt).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R9NqWUYGborGRqS4NMyA13
d057cdc · 2026-09-14 · TK-11658: Kravet-family hi-res image audit + reversible swap map (2214 <=400px verified)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RePUgpi4TWMrHo68U8ckpT