{"slug":"CelebritySignatures","total":229,"limit":100,"offset":0,"since":null,"commits":[{"hash":"fbffb50","date":"2026-09-13 14:58:46 -0700","author":"Steve","subject":"gitignore: exclude campaign image-gen candidates + QA artifacts","body":"Rejected Lincoln generation variants and verification screenshots from the\nSep-9 campaign session — regenerable, not referenced by any tracked code.\nThe chosen hero (campaign-lincoln-seated.jpg) stays tracked.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"8272a62","date":"2026-09-13 14:51:52 -0700","author":"Steve","subject":"campaign: lead the homepage hero with the full seated Signature Edit","body":"Swap the campaign hero from the tee-only shot to campaign-lincoln-seated.jpg\n(Lincoln seated in the full Signature Edit — bucket hat, tee, socks) and\nreword the copy + rendering disclaimer to match.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01VAzDMrVAjLD4umvnMMStjD"},{"hash":"d72fd54","date":"2026-09-13 11:51:43 -0700","author":"Steve","subject":"wear: fix \"See on garment\" not hiding the editorial worn shot + modernize gallery E2E","body":"- wear.html: #lifestyleShot had display:block with no [hidden] guard, so\n  setLifeView(\"garment\") (.hidden=true) never actually hid the seated\n  Signature Edit portrait — for all 50+ mapped signers, \"See on garment\"\n  left the worn shot covering the garment mockup/3D view. Add\n  #lifestyleShot[hidden]{display:none}.\n- gallery-shopping.e2e.cjs: port the retired murals journey to the shipped\n  /wallpaper studio (commit 3d9677d), expect all 9 garments, correct the\n  sale state (dad/trucker/bucket/socks are for sale; the two AOP shirts are\n  the coming-soon holds), cover the worn-shot -> garment toggle, screenshot\n  the always-visible .preview instead of the now-hidden #stage.\n- 5x/ink-gate.mjs: supplementary CDP E2E for the modal ink control (PASS).\n\nBoth viewports PASS, zero page errors.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01VAzDMrVAjLD4umvnMMStjD"},{"hash":"a310a07","date":"2026-09-09 22:52:37 -0700","author":"Steve","subject":"wear: enable Dad Cap (29) + Trucker Cap (33) for sale, cost/placement verified (TK-10286, Steve-approved)","body":""},{"hash":"52b0f48","date":"2026-09-09 22:50:25 -0700","author":"Steve","subject":"printify-cost-check: add dad-cap + trucker-cap candidates (cost/placement verified)","body":""},{"hash":"1d53030","date":"2026-09-09 22:31:55 -0700","author":"Steve","subject":"wear: raise Bucket Hat 32 to 38 to restore margin floor (TK-10286, Steve-approved)","body":""},{"hash":"15e7499","date":"2026-09-09 22:30:46 -0700","author":"Steve","subject":"wear: add Signature Edit lookbook promo banner (discoverability)","body":"Slim green-accented callout below the header linking /wear → /signature-edit,\nso shoppers find the 53-icon worn-shot lookbook.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"7bce96c","date":"2026-09-09 22:27:10 -0700","author":"Steve","subject":"signature-edit: expand The Signature Edit lookbook from 10 → 53 icons","body":"All top-50 famous signers now have their seated editorial 'worn' card in the SEO\nlookbook (was just the original 10). Generated from the ranked list + live feed\ndata (name, qid, death year, signature, license), matched to the campaign slugs.\nEach card + lightbox links to its /wear product page. Headline/meta updated.\nVerified 53 cards render, 0 JS errors.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"8322ca0","date":"2026-09-09 20:16:44 -0700","author":"Steve","subject":"wear: fix stale ink-color fallback in reconcile-wear-orders.mjs + its test","body":"test/wear-artwork-flow.test.mjs (committed 07:58 today) asserted the old\nfixed #f5f3ee recolor tint. Commit 18cca456 (16:13 today) deliberately\nchanged server.js's dark-cloth fallback to #ffffff to match the on-shirt\npreview's inkHexFor() exactly — but the test was never updated, so it was\nfailing on HEAD (verified via git blame: the two commits are unrelated,\nthe test simply predates the ink-choice feature).\n\nRoot-caused by reading both implementations rather than guessing:\nserver.js's #ffffff is correct/intentional (matches public/wear.html's\ninkHexFor, \"dark cloth, no pick → white\"); the old #f5f3ee was pre-feature\nscaffolding. So the fix is NOT touching server.js — it's:\n\n1. scripts/reconcile-wear-orders.mjs: renamed recolorSignatureToLight() ->\n   recolorSignatureInk(imageUrl, hex) and added safeInkHex(), mirroring\n   server.js's current signature/cache-key/fallback exactly (was still on\n   the pre-buyer-choice, fixed-#f5f3ee version — the two producers had\n   drifted out of parity since the ink-color feature landed).\n2. test/wear-artwork-flow.test.mjs: updated the two stale pixel assertions\n   from #F5F3EE(FF/00) to #FFFFFF(FF/00) to match current intended\n   behavior.\n\nVerified: both producer subtests (success + reconciler) now pass; node\n--check clean. Did not touch server.js, public/index.html, or the\nunrelated wear-accessories.test.mjs failures (separate, pre-existing,\nin another session's active hat/accessory work).\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>"},{"hash":"71f5347","date":"2026-09-09 20:14:03 -0700","author":"Steve","subject":"wear: surface the Signature Edit — ✦ badge + 'Signature Edit first' sort","body":"The 52 signers with a seated editorial 'worn' shot were buried among 2,955 in the\ngrid. Now a subtle ✦ star + green outline marks them, and a new sort option\nbrings them to the top so shoppers can find the premium lookbook content. Keyed\noff the same exact worn-shot map (no false badges). 0 errors, verified.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"cb3ba6f","date":"2026-09-09 18:43:31 -0700","author":"Steve","subject":"wear: map Michelangelo Buonarroti → campaign-michelangelo.jpg (same-person dup record)","body":"The catalog has two Michelangelo records ('Michelangelo' + 'Michelangelo\nBuonarroti'); both are the same artist so both should show the worn shot. Added\nthe name variant. (Napoleon III / Rembrandt Peale / Dumas fils / the George\nWashington-named people are DIFFERENT people and stay correctly excluded.)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"ced4cca","date":"2026-09-09 17:15:27 -0700","author":"Steve","subject":"wear: map worn-shot by EXACT signer name, not surname — kills wrong-celebrity collisions","body":"Surname auto-detect would show campaign-adams.jpg (John Quincy Adams) on all 10\nother Adams pages (John/Samuel/Abigail...), Napoleon's shot on Napoleon III,\nHugo's on Hugo Grotius, Louis XIV's on France Prešeren, etc. — the WRONG person's\neditorial photo. Replaced with an exact full-name→slug map of the definitive\ntop-50 (+ existing); anyone not listed shows the normal garment mockup. Still\nprobes the file (may not be generated yet) and self-surfaces as shots land.\nVerified: Darwin/Napoleon show, Abigail Adams/Napoleon III show nothing, 0 errors.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"a0253a8","date":"2026-09-09 17:10:15 -0700","author":"Steve","subject":"wear: 43 worn editorial campaign shots for top-signer roster (TK-10286)","body":"Each historical signer seated editorial in our white bucket hat + tee + crew\nsocks, garments carrying a cursive signature — matches the Einstein bar.\nflux-kontext text-to-image with front-loaded per-figure features. Assets only;\nwear.html auto-detects campaign-<slug>.jpg. Likeness approximate for non-iconic\nfigures (text-to-image ceiling). Cost $1.72 (43 imgs)."},{"hash":"22b0eba","date":"2026-09-09 17:00:03 -0700","author":"Steve","subject":"wear: accent-fold worn-shot slug candidates (Velázquez→velazquez, Molière→moliere)","body":"The auto-detect stripped accents to nothing (velázquez→velzquez), so accented-name\nshots would never surface. Normalize NFD + strip diacritics first, matching the\npipeline's transliterated campaign-<slug>.jpg filenames. Verified across the\naccented top-50 names. Display-only, reversible.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"d8381ce","date":"2026-09-09 16:50:29 -0700","author":"Steve","subject":"wear: auto-detect campaign-<slug>.jpg for the 'worn' shot instead of a hardcoded map","body":"Per peer coordination (celebritysignatures-e9 owns generation + naming): derive\nslug candidates from the signer's name (surname / joined last-two / full / first,\n+ overrides for vangogh & frida) and probe which campaign-<slug>.jpg exists, so\nevery shot the pipeline generates (Shakespeare, da Vinci, Goethe, … the top 50)\nsurfaces on its product page automatically with no code change. Fixes Lincoln to\nuse campaign-lincoln.jpg (was pointing at -seated). Verified Darwin/Lincoln worn,\nShakespeare no-shot, 0 errors. Local only, not deployed. Reverse: git revert HEAD.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"523cb04","date":"2026-09-09 16:44:58 -0700","author":"Steve","subject":"wear: 'See it worn' — feature each celebrity's seated editorial shot on their product page","body":"For signers who have an AI 'seated in the full Signature Edit' campaign photo\n(currently Darwin, Franklin, Lincoln, Michelangelo, Napoleon, Van Gogh among the\nwear-eligible), the /wear product modal now leads with that editorial 'worn' shot\n(the person in the signed hat + tee + socks) with a 'See on garment' toggle back\nto the interactive mockup. Signers without a shot are unchanged (flat mockup, no\ntoggle) — verified both paths, 0 console errors. Display-only, reversible; NOT\ndeployed (overnight gate). Reverse: git revert this commit.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"ba96456","date":"2026-09-09 16:27:02 -0700","author":"Steve","subject":"printify-cost-check: support bucket-hat + crew-socks + --yes non-interactive flag","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"7489d97","date":"2026-09-09 16:21:00 -0700","author":"Steve","subject":"signatures: serve the full-resolution original (vector SVG / native raster), not a downsampled thumb","body":"Steve: 'high res'. resolveSource returned Wikimedia's 1200px PNG thumbnail — which\nalso rasterizes SVGs, throwing away vector sharpness. Now prefer info.url (the\noriginal file): SVGs render as VECTOR (crisp at any size), rasters at full native\nresolution. Signature files are small so full-res is cheap; thumb stays a fallback.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"6adf104","date":"2026-09-09 16:16:47 -0700","author":"Steve","subject":"wear: raise crew-socks price $22 → $28 to clear cost/markup floor (TK-10286)","body":"Crew Socks was priced $22, which at reference blank cost ~$11-16 fell below\nSteve's cost/0.65/0.85 markup floor (only ~1.4-1.7x). $28 clears it comfortably.\nBucket Hat left at $32 (healthy ~2x vs ~$13-17 reference cost). Exact Printify\ncost unverified — Printify does not expose blank cost read-only; run\nscripts/printify-cost-check.mjs for precision.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"18cca45","date":"2026-09-09 16:13:19 -0700","author":"Steve","subject":"signatures: show TRUE source colors, crisp — drop the invented per-signer recoloring","body":"Steve: 'make all signatures original colors, not all diff colors on index page'\n(+ a green box on the shirt, + blurry). Root causes & fixes:\n\n- Gallery/detail (signature-preview): render the ORIGINAL resolved image directly\n  instead of the canvas-normalized copy. SVGs stay vector (crisp at any size) and\n  every signature keeps its true source colors — no more raster blur, no rainbow.\n- Shirt (wear canvas): DEFAULT is now the original art (multiply drops the white\n  ground, shows true colors) — no recolor. The green box was recolorInk's source-in\n  fill painting every opaque pixel of a white-bg source; recolorInk now thresholds\n  (ink→color, background→transparent) so a buyer's chosen color / white-on-dark\n  colors only the strokes. 3D decal uses a matching knockoutWhite for the original.\n- Print (server): recolor only when the buyer picked a color or the cloth is dark;\n  otherwise keep the original art.\n- Ink control default is now 'Original' (the signature's own colors); presets +\n  Custom remain for buyers who want a specific color.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"68dd99d","date":"2026-09-09 16:02:58 -0700","author":"Steve","subject":"wear: full Signature Edit campaign hero — Lincoln seated in hat+tee+socks","body":"Replaced the bust campaign hero with the full-edit seated shot: real O-77 portrait\nface composited in Photoshop onto a generated seated body (kontext, $0.12 total\nthis thread), craggy AI face removed; our exact 1862 signature composited onto the\nbucket hat, tee chest, and both socks; garbled AI text blurred out. Campaign copy\nupdated to 'the full Signature Edit'. (index.html swap on disk; ships on deploy.)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"47a6363","date":"2026-09-09 15:59:34 -0700","author":"Steve","subject":"wear: make Bucket Hat ($32) + Crew Socks ($22) sellable — Lincoln campaign look (TK-10286)","body":"Bucket Hat (bp1698/provider99, Bone/One size 116655) and Crew Socks\n(bp2941/provider29, White/One size 155679) were Printify-mapped but held\n(saleEnabled:false, priceUsd:null). Set saleEnabled:true + priceUsd. Socks\nprintPositions (left_leg/right_leg) were already set by codex-run-10286;\nhat printPosition (front) already set. Prices are category defaults — NOT\ncost-verified (Printify exposes blank cost only on a created product, which\nis gated). Classic/Pocket/Polo + Dad/Trucker caps + AOP shirts untouched.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"ec820c7","date":"2026-09-09 15:55:10 -0700","author":"Steve","subject":"5x sweep 1: record M3 false-negative (ink control is modal-gated; verified working)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"08f3529","date":"2026-09-09 15:33:35 -0700","author":"Steve","subject":"wear: buyer-adjustable signature ink + Node-ported color for the printed art","body":"UI: a SIGNATURE INK control on the /wear product — Auto (the signer's own color,\nwhite on dark cloth) + 7 curated inks + a Custom… full picker. The pick drives\nthe live shirt preview (inkHexFor honors the override) and rides the cart →\ncheckout → order item (validated server-side).\n\nPrint: ported inkColorForHue to server.js (identical FNV+HSL+WCAG-3:1 output,\nverified against the client), generalized recolorSignatureToLight →\nrecolorSignatureInk(url, hex), and the POD draft now bakes the resolved ink into\nthe printed art — buyer's pick, else white on dark / signer color on light —\nmatching the preview. Client ink is strictly validated (#rrggbb) before it can\nreach ImageMagick -fill.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"b5ebc16","date":"2026-09-09 15:25:13 -0700","author":"Steve","subject":"signature-size: make the mobile grid slider actually resize signatures","body":"The mobile @media block hardcoded .sig height:96px, overriding the --sig-h\nvar, so the \"Signature size\" slider (reachable via the ☰ drawer on phones)\nsaved the pref but never changed tile size. Use var(--sig-h,96px) so mobile\nmatches desktop. Verified headless: mobile grid 96px -> 172px.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"5acdc48","date":"2026-09-09 15:22:54 -0700","author":"Steve","subject":"wear: on-shirt signature uses the signer's color on light cloth, white on dark","body":"Extend the distinct per-signer color to the garment mockup (2D canvas, AOP tile,\nand 3D decal): recolor the ink to the signer's own color on light colorways\n(composited via multiply so fabric shading still reads), and to pure white on\ndark colorways (source-over) where a dark color would be invisible. Generalizes\nrecolorToLight(img) -> recolorInk(img,hex); a small module bridge exposes the\nshared inkColorFor() to the classic canvas script so shirt and swatch match.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"a272fad","date":"2026-09-09 15:10:05 -0700","author":"Steve","subject":"wear: Lincoln-in-exact-tee campaign hero (kontext-fit, real product preserved)","body":"Photoshop-placed our real Signature Tee on Lincoln's public-domain O-77 portrait,\ncontent-aware-filled the suit remnants, then one flux-kontext image-EDIT ($0.04,\nlogged) added his neck/shoulders so he genuinely wears it — his face + our exact\ntee + chest signature preserved (edit, not recreate). Campaign section now points\nat /assets/campaign-lincoln-tee.jpg with an honest 'digitally composed, not a\nphotograph' line. (index.html campaign swap is on disk; ships on deploy.)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"3a772dc","date":"2026-09-09 15:09:02 -0700","author":"Steve","subject":"signatures: render each signer in a distinct, WCAG-legible color on clean white","body":"Route every signature swatch (gallery, /wear, murals rosters, games, detail +\nevolution panels) through the shared signature-preview component so the ink is\npainted in a stable per-signer color on a clean white ground instead of black\nink on cream. Color keyed on qid (unique per signer) with a name fallback.\n\nnormalizeInk() takes an optional ink triple; inkColorForHue() guarantees every\nhue clears WCAG 3:1 non-text contrast on white by darkening lightness only as\nmuch as needed (fixes the ~10% olive/yellow dead zone). Fallback path (CORS-\ndenied source, ~0.06% of the feed) instrumented via window.signatureRenderStats.\nTests: 360-hue WCAG sweep + color-path assertions (7/7).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"6a759ce","date":"2026-09-09 14:46:17 -0700","author":"Steve","subject":"game/murals/wear: render cleaned colored-ink signatures via shared preview","body":"Wire the signature-preview.css + signature-preview.js component into the game,\nmurals, and wear pages so their signatures get the same white-ground / colored-\nink cleanup as the gallery. Depends on the signature-ink.js crash fix.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_014ikfY9DhpMDXkpNRpb5ufG"},{"hash":"5499131","date":"2026-09-09 14:44:41 -0700","author":"Steve","subject":"signatures: permanently exclude Q352 (brand safety) from every surface","body":"Filters the QID from mergedSignatures() so it never appears in feed, grid,\nwear, or sitemap.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_014ikfY9DhpMDXkpNRpb5ufG"},{"hash":"abc8f51","date":"2026-09-09 14:44:41 -0700","author":"Steve","subject":"signature-viewer: fix ink-collision crash + add user-adjustable signature size","body":"- signature-ink.js: rename the pixel counter (was `let ink` shadowing the\n  `ink` color param) → hard SyntaxError that broke the whole preview module.\n  The broken build had shipped to prod; unit test now 5/5, module chain parses.\n- New size controls (both surfaces): a \"Signature size\" slider resizes gallery\n  tile signatures (--sig-h); a −/＋/Reset stepper resizes the popup preview\n  (--ap-sig-h). Both persist in localStorage prefs; null keeps the responsive\n  default. Verified headless on desktop + mobile.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_014ikfY9DhpMDXkpNRpb5ufG"},{"hash":"6140aaa","date":"2026-09-09 13:59:26 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-09T13:56:45 (1 data files) — verification/signature-viewer-decision.md","body":""},{"hash":"d2c9573","date":"2026-09-09 13:24:38 -0700","author":"Steve","subject":"signature-edit: click any icon opens a lightbox of the full in-outfit look","body":"Clicking a card image or name opens a modal showing the full campaign image\n(person in the signature outfit) + their real signature + shop/source links.\nKeeps the crawlable /a/Q link for SEO (JS intercepts the click).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01U2uvgXWs4FjLd6eDBDNUxP"},{"hash":"936d27e","date":"2026-09-09 13:08:06 -0700","author":"Steve","subject":"signature-edit: regenerate the 9 figures with distinct poses + backdrops","body":"Each icon now has a unique pose (leaning, standing, arms-crossed, contemplative,\netc.) and a different studio backdrop shade, so the lookbook no longer reads as\none shot repeated. Products + real signatures + likeness unchanged. Lincoln kept\nas-is (its composition drives the home-page text overlay).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01U2uvgXWs4FjLd6eDBDNUxP"},{"hash":"3d9677d","date":"2026-09-09 12:59:20 -0700","author":"Steve","subject":"Fix Lincoln shop links and launch custom signature wallpaper studio","body":""},{"hash":"19dfb15","date":"2026-09-09 12:56:41 -0700","author":"Steve","subject":"signature-edit: new SEO lookbook page — 10 icons in the Signature Edit","body":"New /signature-edit page (route + sitemap in server.js): 10 famous public-domain\nfigures (Lincoln, Einstein, Van Gogh, Picasso, Frida Kahlo, Napoleon, Franklin,\nTwain, Darwin, Michelangelo) each seated in the signature products, with their\nREAL Wikimedia signature + attribution + /a/Q link. Person ItemList JSON-LD,\ncanonical, OG. Front-page 'Shop the Lincoln edit' now links here.\nOnly deceased/public-domain figures used (likeness + never-invent rules).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01U2uvgXWs4FjLd6eDBDNUxP"},{"hash":"1b058a3","date":"2026-09-09 12:53:40 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-09T12:49:50 (3 data files) — public/assets/campaign-lincoln-products-v2.png verification/e2e-proof.json verification/wallpaper-release.json","body":""},{"hash":"bc4838a","date":"2026-09-09 12:19:21 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-09T12:16:55 (2 data files) — verification/wallpaper-decision.md verification/wallpaper-release.json","body":""},{"hash":"dc24bda","date":"2026-09-09 12:14:58 -0700","author":"Steve","subject":"campaign: regenerate Lincoln image — natural eyes/expression (was distorted)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01U2uvgXWs4FjLd6eDBDNUxP"},{"hash":"01e407c","date":"2026-09-09 12:14:36 -0700","author":"Steve","subject":"wear: fix Lincoln sock signature — flat/horizontal at the cuff, not rotated up the shin","body":"Steve flagged the live front-page \"Signature Socks\" card: the signature was\nrotated ~90° and ran vertically up the shin. Recomposited from the clean base\n(crew-socks-white.jpg) with the signature flat and horizontal, small, at the\nsock's cuff/ankle — matching how it sits on the tee's chest. Same source\nasset (Wikimedia 1862 signature), no re-generation, $0 local. Reversible.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01Scv6ymMnvxhwETzTMdobqJ"},{"hash":"0355907","date":"2026-09-09 12:05:39 -0700","author":"Steve","subject":"campaign: overlay text on the photo's open area + signature on all products","body":"- Text (Signed, Mr. Lincoln + copy) now overlays the left negative space of\n  the image with a soft ivory scrim (dark ink); mobile falls back to a dark band.\n- Regenerated campaign-lincoln.jpg so the hat, tee, and socks all carry the\n  signature (were blank).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01U2uvgXWs4FjLd6eDBDNUxP"},{"hash":"f757861","date":"2026-09-09 12:00:06 -0700","author":"Steve","subject":"front page: flip sections — campaign (seated Lincoln) leads, hero follows","body":"Per Steve: swap section order so the full-width seated-Lincoln campaign image\nis the first thing under the masthead, with the 'Wear a piece of history'\neditorial hero below it.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01U2uvgXWs4FjLd6eDBDNUxP"},{"hash":"62fab0c","date":"2026-09-09 11:41:43 -0700","author":"Steve","subject":"front page: stack the campaign section — image on top, text below","body":"Per Steve: campaign band goes from side-by-side (image left/text right) to\nstacked full-width image on top of the dark text band. Local build; deploying.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01U2uvgXWs4FjLd6eDBDNUxP"},{"hash":"1e946e3","date":"2026-09-09 11:12:34 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-09T11:09:48 (1 data files) — verification/lincoln-campaign-prompts.json","body":""},{"hash":"2a4de6d","date":"2026-09-09 11:06:17 -0700","author":"Steve","subject":"wear: put Abraham Lincoln's signature on the ACTUAL product images (Signature Edit)","body":"The front-page Signature Edit trio showed blank products while the copy said the\nautograph 'runs through every thread'. Composited Lincoln's real 1862 signature\n(public-domain, Wikimedia) onto the actual product photos — tee/polo/pocket at the\nchest, dad/trucker/bucket caps centered front, socks up the leg, and the two AOP\nshirts all-over — producing real signed product images (<garment>-lincoln.jpg).\nSwapped the front-page edit-trio (tee/hat/socks) to the signed versions. $0 local\ncompositing, no image-gen spend. Reversible.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_013oMdD46CVyPsuM6JUoiea7"},{"hash":"f4f8745","date":"2026-09-09 11:01:55 -0700","author":"Steve","subject":"front page: Gucci-style Signature Edit hero — No. 001 Abraham Lincoln","body":"Redesign public/index.html hero into an editorial 'Signature Edit': real\npublic-domain Lincoln signature (Wikimedia, attributed, links to /a/Q91) +\nthe 3 real wear blanks (tee/hat/socks) + softened hero-bg. Adds a clearly\nlabeled AI 'campaign' accent (Lincoln dressed in the products; not a photo).\nPreserves all existing hooks (burger/drawer/grid/sort/artistPop/api fetch).\nHonors the project's never-invent-a-signature rule. Local only; not deployed.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01U2uvgXWs4FjLd6eDBDNUxP"},{"hash":"3693ec3","date":"2026-09-09 10:52:09 -0700","author":"Steve","subject":"wear: add all-over-print signature shirts (camp button-up + long-sleeve) — TK-10286","body":"Steve's reference was a button-up covered edge-to-edge in tone-on-tone signature\nscript; add it as product options. POD reality: Printify AOP cut-and-sew,\nsublimation (printed tone-on-tone, not woven jacquard). Two blueprints:\n - Signature Camp Shirt  = #1533 (MWW On Demand), short-sleeve button-up\n - Signature Long-Sleeve = #1261 (Miami Sublimation), pullover\nNew AOP render path in wear.html (paintAllover): tiles the selected signature\nedge-to-edge, staggered + tone-on-tone, clipped to the garment silhouette via a\nbackground-keyed mask (threshold 80 + 3px erode = no off-fabric bleed). Bases are\nthe official blank flat-lay front mockups. saleEnabled:false / priceUsd:null until\nPrintify config + go-live (TK-10286 Steve gate); real variant IDs recorded.\nVerified live in-browser (verification/live-aop-*.jpg), zero console errors.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_013oMdD46CVyPsuM6JUoiea7"},{"hash":"a70566c","date":"2026-09-09 10:20:46 -0700","author":"Steve","subject":"wear: add typeahead search across the top of the signature picker","body":"Full-width search bar above the grid that (a) live-filters the 2,955-signature\ngrid as you type (name + category) with the count + empty-state updating, and\n(b) drops an autocomplete list of the top ranked matches (word-start > substring,\nmatch highlighted, thumbnail + category) that you can click or arrow-key +Enter\nto jump straight to the product. Escape/blur closes it; × clears. Pure client-side\naddition to wear.html, no server change.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_013oMdD46CVyPsuM6JUoiea7"},{"hash":"6ccdfb9","date":"2026-09-09 10:18:57 -0700","author":"Steve Abrams","subject":"Clear the bucket hat eyelets and update verified preview handoff","body":""},{"hash":"c4e6752","date":"2026-09-09 10:13:18 -0700","author":"Steve Abrams","subject":"Match the bucket hat preview selection to the supported Bone variant","body":""},{"hash":"ac773c5","date":"2026-09-09 10:11:38 -0700","author":"Steve Abrams","subject":"wear: front-facing hats + centered signature; remove YOUR DESIGN placeholder (TK-10286)","body":"Dad Cap / Trucker Cap / Bucket Hat previews were rendering on ANGLED on-model\nlifestyle photos, so a centered front decal was geometrically impossible (the\nearlier curve/rotation overlay hacks were compensating for that). Rebased each\nhat on a true front-facing Printify view; inpainted the 'YOUR DESIGN(/HERE)'\nplaceholder off the dad+trucker front panels; used the clean blank front bucket.\nReset overlayBox to a centered front print box (center x=1024=image center) and\nremoved curve+rotation. Bucket colorway Army->White to match the only\nfront-facing asset (preview-only; saleEnabled stays false). Proofs in verification/.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_013oMdD46CVyPsuM6JUoiea7"},{"hash":"703013b","date":"2026-09-09 10:07:12 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-09T10:04:38 (1 data files) — data/wear-templates.json","body":""},{"hash":"178086a","date":"2026-09-09 09:52:21 -0700","author":"Steve Abrams","subject":"wear: curve-warp hat signature overlays + fix dad-cap/bucket-hat placement (TK-10286)","body":"Per /dtd (4/4 unanimous B): graphic-designer review flagged flat\nrectangle overlays on curved cap crowns read as pasted stickers rather\nthan real DTF/embroidery prints. paintSignatures() now optionally\nslices the signature into thin vertical strips and bends each along a\nparabola (ob.curve, px) when a garment box declares one — cheap,\ncanvas-only, no 3D pipeline. Applied per-hat (trucker:6, dad-cap:14,\nbucket-hat:18, matched to each crown's actual curvature).\n\nAlso fixed the two placement issues the same review caught: dad-cap\noverlayBox was too close to the bill seam (y:705->640, h:150->130);\nbucket-hat's right edge landed on the crown's ventilation grommet\n(x:860->780). Verified via Playwright screenshots against local pm2 —\nall three hats now centered, curved, and clear of seams/hardware.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"a15a0cd","date":"2026-09-09 09:36:24 -0700","author":"Steve Abrams","subject":"wear: re-center trucker-cap signature overlay (TK-10286)","body":"Steve flagged live that the signature sat low, overlapping the mesh\nside seam instead of centered on the solid front panel. Pixel-verified\nagainst the actual on-model photo (overlaid a debug rectangle, compared\nbefore/after) rather than guessing: x:765,y:560,w:570,h:160 ->\nx:955,y:500,w:450,h:140. Checked dad-cap and bucket-hat the same way —\nboth already reasonably centered, left unchanged.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"7648991","date":"2026-09-09 09:18:51 -0700","author":"Steve Abrams","subject":"wear: hover-to-zoom 3x lens on the signature only (TK-10286)","body":"Only activates over the printed signature (not the whole garment), and\nrepaints fresh from the source photo + signature images at the zoomed\nresolution instead of CSS-scaling the already-rendered canvas (which\njust stretched existing pixels and looked blurry). Zoom level adapts\nper garment box so wide signatures never clip out of the lens.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"e546ddf","date":"2026-09-09 09:00:15 -0700","author":"Steve Abrams","subject":"Center the product preview text and options","body":""},{"hash":"f44f65b","date":"2026-09-09 08:51:11 -0700","author":"Steve Abrams","subject":"Add three hat previews and socks with guarded purchase and fulfillment paths","body":""},{"hash":"f19730e","date":"2026-09-09 08:24:58 -0700","author":"Steve Abrams","subject":"homepage: tighten gallery card UI + wire real mural/clothing purchase links (TK-10286)","body":"Two coordinated changes landed together (claude-run-10286 + codex-run-10286,\nsame session, real-time a2a via the ticket system after a genuine file-write\nrace on public/index.html — reconciled rather than reverted):\n\n1. Card UI tightening (Steve's direct ask, screenshot-driven): grid gap\n   18px->10px, .sig image area 120px->88px, .meta padding 11px/13px->6px/8px,\n   .name forced single-line (white-space:nowrap + ellipsis, was wrapping to\n   2 lines for longer names like \"Mustafa Kemal Atatürk\"). Verified via a\n   real Playwright screenshot at /?cat=Politics — names fit one row, padding\n   visibly tighter.\n\n2. Real mural/clothing purchase links, wired end-to-end (Steve separately\n   steered codex-run-10286: the Politics homepage had no visible /wear links\n   and mural CTAs were buried in a modal): new signatureShopLinks() helper\n   generates qid-carrying links to /murals?qid=...#finder and /wear?qid=...,\n   rendered as a .shop-actions button pair on every card, in the artist\n   detail popup (.ap-shop), the masthead nav, hero CTAs, and the drawer.\n   public/wear.html and public/murals.html got matching boot-time hooks that\n   read ?qid=/?name= and either open that signature's configurator directly\n   (wear: only if it passes the same wearEligible() gate server.js enforces\n   — shows a graceful \"not available on clothing\" notice otherwise) or\n   preselect it in the mural finder/roster.\n\nAn earlier icon-based approach (🖼️/👕 badges + a client-side\nwearEligibleClient() mirror) was built independently by claude-run-10286\nfor the same \"signal what's purchasable\" goal, then removed once\nsignatureShopLinks()'s real deep-linking buttons landed — redundant with,\nand less functional than, working links.\n\nVerified: all 3 files' inline script blocks parse clean. codex-run-10286\nran desktop+mobile Playwright E2E (verification/gallery-shopping.e2e.cjs,\nverification/e2e-proof.json) covering the full click-through journey.\nclaude-run-10286 verified the card tightening visually via a fresh\nscreenshot. Not deployed — held for explicit Steve go per the standing\ndeploy gate.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"2dd7c66","date":"2026-09-09 08:08:17 -0700","author":"Steve Abrams","subject":"wear: persist sort selection to localStorage, matching density (TK-10286)","body":"Caught by codex-run-10286 (a2a, also active on this ticket) — density\nalready persisted (wear_cols) but sort never did, missing the standing\nsort+density rule's persistence requirement. Added wear_sort localStorage\nkey, saved on change, restored on boot alongside the existing density\nrestore. Verified via Playwright: select a sort, reload, value persists.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"c90a83c","date":"2026-09-09 07:58:22 -0700","author":"Steve Abrams","subject":"Verify recolored wear artwork through both fulfillment draft paths","body":""},{"hash":"c9d72f3","date":"2026-09-09 07:41:40 -0700","author":"Steve Abrams","subject":"wear: fix recolored signature URL being relative, not absolute (TK-10286)","body":"Real bug caught via a2a by codex-run-10286 (also actively on this ticket) —\nrecolorSignatureToLight() returned a RELATIVE path\n(/assets/recolored-signatures/<hash>.png), set directly as\ndraft.design_image_url. That flows straight into\nsubmit-pod-draft-printify.mjs's buildPayload() as images[0].src, which\nPrintify fetches from the public internet — a relative path would have\nfailed there (or worse, resolved against whatever base the fetcher assumes).\nBoth the cache-hit AND cache-miss return paths had the bug.\n\nFixed in both places that build this URL (server.js, and the duplicate in\nreconcile-wear-orders.mjs — same reasoning already applied to\nextraPrintAreas' imageUrl in submit-pod-draft-printify.mjs, which already\nprefixes with the site origin): added WEAR_SITE_ORIGIN and prefixed both\nreturn points. Verified the function now returns a proper\nhttps://celebsignatures.com/... URL.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"c2a79ec","date":"2026-09-09 07:39:25 -0700","author":"Steve Abrams","subject":"wear: independent Stripe live switch — allows one test order before real money (TK-10286)","body":"Steve wants a real test order through /wear before it charges real cards.\nCritical finding that made this necessary: Kamatera's .env already has\nSTRIPE_LIVE_ENABLED=1 set (murals/downloads use it) with a real live key\npresent. /wear's checkout previously shared STRIPE_MURAL_KEY, so the moment\nWEAR_SALES_LIVE=1 landed, it would have charged REAL cards immediately —\nzero chance to place a test order first.\n\nAdded WEAR_STRIPE_LIVE_ENABLED as wear's own independent live switch,\ncompletely separate from STRIPE_LIVE_ENABLED. New WEAR_STRIPE_KEY /\nWEAR_STRIPE_MODE resolvers (same shape as the existing STRIPE_MURAL_KEY /\nSTRIPE_DOWNLOAD_KEY per-flow pattern already in this file for exactly this\nkind of reason — downloads stay pinned to test until a payout mechanism\nexists). Swapped both /api/wear-checkout and /wear-success off\nSTRIPE_MURAL_KEY/STRIPE_MODE onto the new wear-specific ones. Applied the\nsame fix to reconcile-wear-orders.mjs's resolveStripeKey().\n\nThis means Steve can now set WEAR_SALES_LIVE=1 + WEAR_POD_PROVIDER=printify +\nPRINTIFY_SHOP_ID + PRINTIFY_MANUAL_APPROVAL_CONFIRMED=1 — making checkout,\nPrintify, and the cart fully functional — while WEAR_STRIPE_LIVE_ENABLED\nstays unset, so it still charges the TEST key. Place one real test order\nend-to-end, then flip WEAR_STRIPE_LIVE_ENABLED=1 as the final, deliberate\nstep to real money.\n\nVerified by faking the exact production condition locally (STRIPE_LIVE_\nENABLED=1 + WEAR_SALES_LIVE=1, WEAR_STRIPE_LIVE_ENABLED unset): checkout\ncorrectly returned a cs_test_ session despite the shared flag being live,\nwith the startup log clearly showing the split (\"STRIPE LIVE MODE — murals\ncharge REAL cards\" vs \"Wear apparel: Stripe test mode, independent of the\nmurals live flag\"). Also verified WEAR_STRIPE_LIVE_ENABLED=1 correctly flips\nwear to live mode on its own. Test order cleaned from the gitignored\nwear-orders.json afterward. Real (unfaked) local environment re-confirmed\nstill fully gated off.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"f2976c0","date":"2026-09-09 07:30:23 -0700","author":"Steve Abrams","subject":"wear: use 'convert' not 'magick' — prod box only has ImageMagick 6 (TK-10286)","body":"Caught right after deploying 9f1ba52: SSH'd into Kamatera to verify the\nblack-print recolor fix would actually work there, and 'which magick' came\nback empty — only 'convert' (ImageMagick 6) is installed. My local dev\nmachine has IMv7's 'magick' unified CLI, which made the gap invisible until\nchecked. Would have failed open (the try/catch falls back to the original\nunrecolored image) rather than crash anything, but the actual fix wouldn't\nhave worked in production — worth catching before it needed a real dark-\ngarment order to surface.\n\nSwitched both call sites (server.js, reconcile-wear-orders.mjs) to spawn\n'convert' instead — verified present and working with identical output on\nboth this Mac and Kamatera (same recolor command, same result, 'convert' is\njust deprecated-but-functional under IMv7 too, only a stderr warning).\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"452cc4c","date":"2026-09-08 17:06:19 -0700","author":"Steve Abrams","subject":"wear: update stale KNOWN ISSUE notes now that the black-print fix landed (TK-10286)","body":"Documentation-only follow-up to 9f1ba52.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"9f1ba52","date":"2026-09-08 17:05:42 -0700","author":"Steve Abrams","subject":"wear: fix the black-garment print contrast bug for real (TK-10286)","body":"Resumes the standing KNOWN ISSUE noted in wear-templates.json since the\n2026-09-08 verification session: Printify prints a design's own pixel colors\nas-is (no auto-recolor for dark garments), so the black polo's dark-ink\nsignature printed as low-contrast dark-gray-on-black on the REAL product —\nconfirmed visually earlier this session, never fixed until now.\n\nAdded recolorSignatureToLight() in server.js (and the same logic duplicated\nin scripts/reconcile-wear-orders.mjs, which has its own independent draft-\ncreation path) — shells out to ImageMagick (already on this box) via stdin/\nstdout piping, no temp files: `magick -background none - -channel RGB -fill\n#f5f3ee -colorize 100% png:-`. This recolors every opaque pixel to a light\nink while preserving the alpha channel exactly (mirrors the client-side\ncanvas recolorToLight() used in the on-site preview and the 3D decal).\nHandles both PNG and SVG signature sources (needed -background none — without\nit, ImageMagick's default SVG rasterization fills a white background instead\nof preserving transparency, verified by testing both formats). Cached by a\nhash of the source URL under public/assets/recolored-signatures/ (gitignored\n— regenerable, not something to track) so a re-ordered signature isn't\nreprocessed. Fails open: any error (magick missing, fetch failure, an 8s\ntimeout) falls back to the original image rather than blocking order/draft\ncreation — a low-contrast print is a quality issue, not a reason to lose the\ncustomer's order record.\n\nWired into both draft-creation paths (/wear-success and\nreconcile-wear-orders.mjs): for each cart line item, look up its garment+\ncolor's hex from wear-templates.json, and if luminance < 0.4 (dark), recolor\nbefore setting design_image_url on the draft.\n\nVerified the actual fix, not just the mechanism: recolored a real signature,\nuploaded it to Printify, and rendered a real throwaway draft product on the\nblack polo — the signature is now clearly legible (light ink) instead of the\nlow-contrast dark-gray from the original verification. Deleted immediately\nafter. Also verified the recolor pipeline handles SVG-sourced signatures\ncorrectly (transparency preserved) and that reconcile-wear-orders.mjs still\nruns clean against the existing test order. Local E2E re-confirmed sales\nstill fully gated off (comingSoon:true) afterward.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"bda7296","date":"2026-09-08 15:46:14 -0700","author":"Steve Abrams","subject":"wear: real rotatable 3D viewer for the classic tee (Three.js) — TK-10286","body":"Steve: \"show each shirt with blender and three.js\". Blender isn't installed\nand there's no from-scratch 3D garment model — building one with correct\ncloth draping + UV-mapped print area is genuine 3D-artist work, not a script.\nUsed the practical path instead: a free, MIT-licensed, pre-made crew-neck\ntee model (Starklord17/threejs-t-shirt on GitHub — itself the well-known\n\"JS Mastery 3D T-shirt customizer\" tutorial asset by Anderson Mancini + Paul\nHenschel), loaded in Three.js with real rotation, live garment-color swap,\nand the signature applied as a DecalGeometry projected onto the mesh at the\nmodel's own standard chest-decal placement.\n\nScoped to classic-tee ONLY — it's a generic crew-neck shape, wrong for the\npolo (no collar) and pocket-tee (no pocket), and no matching free model was\nfound for those. Showing the wrong silhouette would be worse than no 3D view,\nso the \"View in 3D\" toggle only appears for classic-tee; switching to another\ngarment while in 3D mode falls back to the real photo automatically.\n\nHit and fixed 2 real integration bugs during verification:\n1. The addon modules (GLTFLoader/OrbitControls/DecalGeometry) do bare\n   `import ... from 'three'` internally, which a plain dynamic import() of a\n   CDN URL can't resolve — added an <script type=\"importmap\"> mapping\n   \"three\" and \"three/addons/\" to the CDN, verified via Playwright that this\n   is what actually made the modules load (the error before the fix was\n   caught, not silent).\n2. Drawing the (cross-origin, Wikimedia-hosted) signature image onto the\n   decal's offscreen canvas tainted it, throwing a WebGL SecurityError on\n   texSubImage2D — verified Wikimedia serves permissive CORS\n   (access-control-allow-origin: *) and set sigImg.crossOrigin='anonymous'\n   to fix it. Only affects the new 3D path; the existing 2D canvas never\n   reads pixels back so it needed no CORS handling.\n\nVerified end-to-end via Playwright: 3D toggle appears for classic-tee, loads\nand renders the real 3D model with the signature decal visible on the chest,\ndrag-to-rotate works, switching colors while in 3D mode updates the garment\ncolor live, and switching to polo correctly hides the toggle and falls back\nto the 2D photo — 0 console errors throughout (after both fixes). Checkout\nre-verified still fully gated off (comingSoon:true) afterward.\n\nThe shirt_baked.glb model itself (1.0MB, MIT-licensed) was already captured\nby this repo's auto-data-snapshot automation before this commit.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"8b345a4","date":"2026-09-08 15:44:04 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-08T15:35:04 (1 data files) — public/assets/models/shirt_baked.glb","body":""},{"hash":"108381c","date":"2026-09-08 14:15:27 -0700","author":"Steve Abrams","subject":"wear: drop the cap, real Printify product photos instead of flat SVG (TK-10286)","body":"Steve: \"I DONT LIKE THE HATS AND THE TSHIRTS NEED TO LOK REAL FROM PRINTERS\nTEMPLATES\". Still fully gated off (WEAR_SALES_LIVE unset, checkout returns\ncomingSoon).\n\n1. Removed the cap/Classic Dad Cap garment entirely (data + the SVG geometry\n   that only existed for it).\n\n2. Replaced the hand-drawn flat-vector garment illustration (Path2D body\n   shape + accent paths) with REAL Printify product photography. Captured 7\n   real blank product photos (one per garment x color: tee white/heather/\n   sand/sky, polo white/black, pocket-tee white) via a throwaway draft\n   product with an invisible 1x1-pixel transparent print (so the photo comes\n   back completely blank), fetched the real mockup image, deleted the\n   product — same proven create/fetch/delete/verify-404 pattern used all\n   session. Saved to public/assets/garments/*.jpg (1200x1200, real Printify\n   photography).\n\n3. New wear-templates.json fields per garment: photoWidth/photoHeight (1200)\n   and overlayBox (the pixel rectangle where the client composites the\n   signature onto the real photo) — measured directly against a real\n   Printify mockup WITH an actual signature printed at that garment's own\n   printify.printPosition, so the on-site preview and the real order use the\n   same position. pocket-tee's overlayBox was measured straight off the\n   blank photo itself (the real stitched pocket is visible with no print at\n   all). Each color object now carries its own `photo` path instead of just\n   a flat `hex` (hex/ink kept — still used to decide the multiply-vs-recolor\n   blend mode).\n\n4. public/wear.html draw() rewritten: loads and caches the current color's\n   real photo, draws it as the canvas background, then composites the\n   signature into the measured overlayBox with the same contain-fit +\n   multiply/recolor-to-light logic as before (unchanged math, real photo\n   underneath instead of a flat color fill). Removed the now-dead shade()\n   helper and all Path2D/accent/pocketAccent/pocketHem drawing code.\n\n5. FOUND AND FIXED a real bug while visually verifying: switching garments\n   via the chip only re-resolved state.color when the color id was NOT found\n   on the new garment — when both garments shared a color id (e.g. \"white\"),\n   it silently kept the OLD garment's color object, which under the old\n   flat-hex rendering was invisible (same hex value) but under real photos\n   showed the WRONG garment's photo entirely. Fixed by always re-resolving\n   to the new garment's own matching color object.\n\nVerified: node --check clean, JSON valid, local E2E shows 3 garments\n(cap gone), checkout still comingSoon:true. Playwright screenshots of the\nreal on-site canvas (tee white/heather, polo white/black, pocket-tee) all\nshow real photographic garments with the signature correctly composited —\n0 console errors.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"4173af9","date":"2026-09-08 13:54:37 -0700","author":"Steve Abrams","subject":"wear: real multi-item shopping cart (own cart, not Shopify's) — TK-10286","body":"Steve: \"create our own shopping cart for this build.\" Replaces the old\nimmediate single-item \"Add to cart -> Stripe redirect\" with an actual cart:\nadd multiple signatures/garments to a localStorage-backed cart, review/edit\nin a cart panel, one Stripe Checkout session for everything at once.\n\n1. public/wear.html: cart badge in the header, localStorage-backed cart\n   (add/remove, persists across reloads), a cart panel (thumbnail + garment/\n   color/size + price per line, remove button, running total, single email\n   field). \"Add to cart\" no longer redirects immediately — it adds the\n   current selection and lets the shopper keep browsing. The old per-item\n   email field only shows in the NOT-live \"notify me\" state, unchanged from\n   before; live sales use the cart's one email field instead.\n\n2. server.js: POST /api/wear-checkout now accepts `items: [...]` (an array)\n   instead of one flat item — validates every item (eligibility, garment/\n   color/size), builds ONE Stripe Checkout Session with one line_item per\n   cart item, stores the order as `items: [...]`. Kept a back-compat shim\n   (a bare single-item body still works) so nothing else calling this\n   endpoint breaks. Added WEAR_CART_MAX_ITEMS=20 (abuse guard, not a real\n   limit concern).\n\n3. New wearOrderItems(order) helper normalizes EITHER order shape (the new\n   items[] array, or the old flat qid/garment/color/size fields from orders\n   placed before 2026-09-08) into one array — /wear-success and\n   reconcile-wear-orders.mjs both use it so old and new orders process\n   identically. /wear-success now drafts ONE POD entry per cart line item,\n   each with its own composite id (\"<orderId>.<itemIndex>\") so the existing\n   per-draft idempotency/dedupe logic in the POD senders needs no changes —\n   a multi-item order becomes N independent Printify orders to the same\n   shipping address, which was the simplest correct architecture (no changes\n   needed to submit-pod-draft-printify.mjs's per-draft submission logic).\n\nVerified end-to-end with a real (throwaway, local-only) Playwright run:\nfaked WEAR_SALES_LIVE=1 + printify-provider env vars in a local process only\n(never touched .env or real Stripe) to add 2 different items (tee + polo,\ndifferent signatures/colors/sizes) to the cart, confirmed badge count and\nrunning total ($78.00 = $34+$44, correct), removed an item, re-added, and\ncompleted checkout — got a REAL Stripe TEST session URL back, confirming the\nmulti-line-item session builds correctly. Verified the resulting order\nrecorded with the new items[] shape, and that the pre-existing single-item\ntest order (2026-08-10) still normalizes correctly through the same helper.\nTest order removed from the gitignored data/wear-orders.json afterward.\nZero console errors throughout. Real environment re-verified afterward:\nstill gated off (comingSoon:true), all 4 garments present.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"adf1313","date":"2026-09-08 13:03:59 -0700","author":"Steve Abrams","subject":"wear: polo left_chest placeholder, add cap garment, collar fabric tag (TK-10286)","body":"Still fully gated off (WEAR_SALES_LIVE unset, checkout returns comingSoon).\n\n1. Polo: switched from the manually-tuned 'front' full-torso print area to\n   Printify's own DEDICATED 'left_chest' placeholder for this blueprint. The\n   'front' area kept sitting too low no matter how high y went (y:0.0 still\n   overlapped the placket) — the dedicated placeholder is a properly-scoped\n   small print area that lands at the correct height automatically. Verified\n   via a real throwaway draft product + mockup.\n\n2. New 4th garment: Classic Dad Cap (Yupoong 6245CM, blueprint 1447, provider\n   99 Printify Choice), DTF print (not embroidery — a cursive signature's\n   thin strokes would blob out in embroidery) on the front_dtf placeholder,\n   x:0.5/y:0.5/scale:0.7. White/Stone/Khaki/Light Blue (light-only, same\n   conservative default as the original tee palette). One-size. Cost $16.12\n   at verification. New SVG geometry in wear-templates.json (dome + brim) and\n   public/wear.html renders it via the existing generic accent/pocketAccent\n   hooks — no cap-specific branch needed. Verified with real Playwright\n   screenshots (0 console errors) plus a real Printify draft-product mockup.\n\n3. 'Celebrity Signatures' fabric tag at the back collar (Steve's request) —\n   Printify's dedicated 'neck' placeholder, only available on the tee's\n   blueprint (checked: polo/pocket-tee/cap blueprints have none). Rendered\n   the tag as a real PNG (Playfair Display italic, matching the site's own\n   wordmark) via a local Playwright screenshot, saved to\n   public/assets/wear-tag-celebrity-signatures.png. Iterated position against\n   4 real throwaway draft products: y:0.5 (centered, too low) -> y:0.15 ->\n   y:0.0 (clips into the collar-binding curve, distorts the text) -> the\n   final y:0.08, the highest clean/legible position.\n\n   New data model: garment.printify.extraPrintAreas[] — static (not\n   per-order) image print areas layered onto every order for that garment.\n   scripts/submit-pod-draft-printify.mjs's buildPayload() now merges these\n   into the order's print_areas object alongside the per-order signature\n   design, referencing the tag by its live site URL\n   (https://celebsignatures.com/assets/...) the same way the existing code\n   already references design_image_url — no image upload/ID plumbing needed,\n   since Printify's Orders API (unlike the Products API used for mockup\n   verification) accepts a fetchable src URL directly.\n\nVerified: node --check clean, JSON valid, dry-run sender unchanged (0\npending, nothing submitted), local E2E shows all 4 garments + correct\nvariant maps, checkout still comingSoon:true, Playwright screenshots of the\nreal on-site canvas confirm all 4 garments render without JS errors.\n\nKnown gap (not fixed here): the on-site canvas preview doesn't render the\ncollar tag (only the real Printify mockup does) — a completeness gap, not a\ncorrectness bug, left for a follow-up pass.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"06e1b9d","date":"2026-09-08 12:05:01 -0700","author":"Steve Abrams","subject":"wear: dial print size back down to standard small left-chest logo (TK-10286)","body":"Steve: bigger (0.14->0.22) was too big — wanted it smaller again, sitting\njust above where a pocket top would be, standard logo size. Verified 2 more\nthrowaway draft products (tee + polo) against real mockups, landed on\nx:0.7, y:0.1, scale:0.16 — a standard small left-chest logo size, positioned\njust above pocket-top height. Updated both garments; fixed the stale\nprintPosition _note text left over from the two prior iterations (0.25 wrong\ndead-center -> 0.14 -> 0.22 too big -> this).\n\nStill fully gated off. Verified: JSON valid, node --check clean, local E2E\nshows printPosition x:0.7/y:0.1/scale:0.16, checkout still comingSoon:true.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"e887506","date":"2026-09-08 11:13:58 -0700","author":"Steve Abrams","subject":"wear: bigger/higher placement, add pocket-tee, fix preview left/right mismatch (TK-10286)","body":"Still fully gated off (WEAR_SALES_LIVE unset, checkout returns comingSoon).\n\n1. Bigger + higher (Steve's call, 2026-09-08): iterated 2 more throwaway\n   draft products (tee + polo) against real Printify mockups to land on\n   x:0.7, y:0.13, scale:0.22 — the signature now sits at pocket-top height\n   and is legibly sized, not the smaller/lower size from the prior commit.\n\n2. New garment: pocket-tee (Bella+Canvas 3021 Unisex Pocket Tee, blueprint\n   1358, provider 99 Printify Choice). Prints the signature directly ON the\n   physical pocket via Printify's dedicated 'pocket' placeholder (not\n   'front') — verified with a real throwaway draft product + mockup, deleted\n   + confirmed gone via 404. White-only, S/M/L/2XL (Printify's own catalog\n   has no White/XL or Deep-Heather/L+ for this blueprint's pocket-DTG combo\n   on either available provider — a real catalog gap, not an oversight).\n   public/wear.html now draws an actual patch-pocket shape (fill + hem line)\n   for garments with a real pocket, instead of the generic dashed hint.\n\n3. FOUND AND FIXED a real preview/product mismatch: the on-site canvas\n   preview placed the signature at viewer-LEFT (pocketBox x:128 of a 400-wide\n   canvas), but the real Printify print — verified via mockups this session —\n   lands at viewer-RIGHT (wearer's left chest, industry-standard placement).\n   Customers were previously shown a preview that didn't match what they'd\n   actually receive. Mirrored pocketBox for classic-tee and polo to match.\n\nVerified: node --check clean, JSON valid, local E2E shows 3 garments\n(classic-tee/polo/pocket-tee), pocket-tee has 4 mapped variants, checkout\nstill comingSoon:true. Playwright screenshots of the actual on-site canvas\nconfirm correct mirrored placement + working pocket-tee rendering + the\nblack-polo light-recolor fix still holds at the new position.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"dcec53c","date":"2026-09-08 11:07:36 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-09-08T10:58:37 (1 data files) — data/wear-templates.json","body":""},{"hash":"97b050d","date":"2026-09-08 09:42:55 -0700","author":"Steve Abrams","subject":"wear: verify + fix left-chest print position against real Printify mockups (TK-10286)","body":"Fixed printify-cost-check.mjs's upload (Printify rejected url-fetch upload,\nHTTP 400 code 10300 — switched to base64 'contents', which worked), added\nCLI overrides for x/y/scale/garment so placement could be iterated without\nediting the script each time, then actually ran it against the live account\n(3 throwaway draft products: tee, polo, polo-black — each created, mockup\nimage fetched and inspected, deleted, delete verified via 404).\n\nReal cost data from the run: tee cost $13.82 (retail $34, margin $20.18/59%),\npolo cost $18.67 (retail $44, margin $25.33/58%). Healthy margins on both.\n\nThe old printPosition (x:0.32, y:0.3, scale:0.25) was WRONG — it rendered the\nsignature dead-center on the torso, not at the left chest. Iterated against\nreal mockups to x:0.7, y:0.15, scale:0.14, which renders correctly at the\nleft chest on both garments. Updated wear-templates.json for both.\n\nFound a genuine open issue while verifying the black polo: Printify prints\nthe source signature art's own pixel colors as-is (no auto-recolor for dark\ngarments), so the black colorway prints as low-contrast dark-gray-on-black —\nthis is a REAL PRINT problem, not just the website-preview issue fixed in\nba30f90 (which only fixed the on-site mockup, not what actually gets sent to\nPrintify). Documented in wear-templates.json's printify._note; needs either a\nserver-side light-ink recolor of design_image_url before order submission for\ndark colors, or dropping the black colorway — flagged to Steve, not decided\nhere since it's a product-scope/engineering-investment call.\n\nSales remain fully gated off throughout — verified via local E2E after commit.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"2e8f61b","date":"2026-09-08 09:36:05 -0700","author":"Steve Abrams","subject":"wear: extend printify-cost-check.mjs to also verify left-chest placement (TK-10286)","body":"Combines the cost check with a real placement verification in one run: uploads\na real signature PNG (Samuel Adams — already wear-eligible), creates each\ndraft product with print_areas at the SAME x/y/scale wear-templates.json\ncarries, fetches back any auto-generated mockup image URLs to eyeball, then\ndeletes + verifies + logs exactly as before. Pauses for a manual dashboard\ncheck if mockups aren't generated yet by the time it fetches, rather than\ndeleting blind. Still not run — blocked from autonomous execution by the\nharness's classifier (external account write); Steve runs it directly.\n\nnode --check clean. Untested against the live Printify API (can't run it from\nhere) — flagged to Steve as such.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"ba30f90","date":"2026-09-08 09:32:15 -0700","author":"Steve Abrams","subject":"wear: fix dark-garment preview + map Printify blueprints/variants (TK-10286)","body":"Still fully gated off (WEAR_SALES_LIVE unset, checkout returns comingSoon).\n\n1. public/wear.html: the left-chest signature preview used canvas 'multiply'\n   blend unconditionally — correct for light garments (dark ink darkens light\n   cloth) but multiply can only ever darken, so a dark garment rendered the\n   signature completely invisible. Added a luminance check: dark colorways now\n   recolor the signature to a light ink and composite normally instead.\n2. data/wear-templates.json: polo colorways restricted to white/black (Steve's\n   call, 2026-09-08) — the mapped JERZEES 443M Piqué Polo blueprint only offers\n   6 colors, no sand/sky equivalent; black needed fix #1 above to render.\n3. Filled in real Printify blueprint/print-provider/variant mappings for both\n   garments via read-only catalog GETs (no account write): tee = Bella+Canvas\n   3001 (blueprint 12), polo = JERZEES 443M Piqué (blueprint 1402), both DTG\n   via print provider 99 (Printify Choice). Shop id 496929 confirmed by Steve\n   (Designer Wallcoverings and Fabrics — the new products.write-scoped token\n   resolves to a different shop id than the old token's discovery, corrected).\n4. New scripts/printify-cost-check.mjs (not yet run) — creates one throwaway\n   unpublished draft product per garment to read real per-unit cost, deletes\n   it immediately, verifies the delete with a follow-up GET. Blocked from\n   autonomous execution by the harness's own safety classifier (external\n   account write); handed to Steve to run directly.\n\nVerified: node --check clean, wear-templates.json valid JSON, local E2E shows\n2955 signatures, polo colors=[white,black], tee/polo variant maps populated\n(20 + 10 entries), checkout still returns comingSoon:true for every request.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"f197cfc","date":"2026-09-08 06:47:25 -0700","author":"Steve Abrams","subject":"wear/POD: fix 4 correctness bugs from codex's 2026-09-04 review (TK-10286)","body":"All still gated OFF (WEAR_SALES_LIVE unset, no variant mappings) — these are\nhardening fixes for whenever go-live happens, not activation.\n\n1. Pin POD provider on the order at checkout time instead of re-reading\n   WEAR_POD_PROVIDER at /wear-success, so an env change between checkout and\n   success can never route a paid order to the wrong provider's sender.\n2. wearPodReady() (checkout readiness) now also requires PRINTIFY_SHOP_ID +\n   PRINTIFY_MANUAL_APPROVAL_CONFIRMED=1 for the printify path, matching the\n   5-gate check submit-pod-draft-printify.mjs already enforces — a paid order\n   can no longer sit forever as a DRAFT_UNSENT the sender will never touch.\n3. Idempotent draft-append guard in /wear-success (checks the drafts log for\n   an existing orderId before appending) + orderId-dedupe defense-in-depth in\n   both submit-pod-draft*.mjs senders, so a crash/retry window can never\n   produce two DRAFT_UNSENT lines for one order and double-submit it.\n4. Dry-run payload previews (the default mode) now redact recipient PII\n   (name/email/address/zip) by default; --show-pii opts back in for real\n   debugging. Previously a dry-run printed full customer addresses to stdout.\n\nNew: scripts/reconcile-wear-orders.mjs — closes the \"customer paid but never\nreached /wear-success\" gap (browser closed, redirect never lands) by\nre-checking pending_payment orders with a stripeSession against Stripe\n(read-only GET) and running the same draft logic on anything Stripe reports\npaid. Dry-run by default; --apply persists. No webhook, no new config.\n\nVerified: node --check clean on all 4 files; local E2E (throwaway port) shows\n2955 signatures, purchasable:false, checkout still returns comingSoon:true,\nhome/wear both 200; all three POD scripts dry-run to zero-fire.\n\nCo-authored with a concurrent claude-run-10286 session (celebritysignatures-50)\nthat independently landed items 1-4; this commit also adds the printify-sender\ndedupe (item 3b) it hadn't covered and merges both sessions' work.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AmxcNKtFg77wP47uZq5Zsm"},{"hash":"919eed1","date":"2026-09-04 08:53:23 -0700","author":"Steve Abrams","subject":"Celebrity Signatures: correct a FALSE 'Data Not Collected' privacy instruction (TK-10387)","body":"The repo's own store-listing file instructed filing 'Data Not Collected.' That is false\nagainst the shipped binary, and it is the file someone would naturally work from when\nfilling in App Store Connect — so it would have produced a filed misrepresentation on an\naccount already carrying seven rejections.\n\nVerified in source rather than inferred:\n  api.ts:119  login(email, password)\n  api.ts:121  signup(email, password, name)\n  api.ts:18   appleSignIn()\n  api.ts:113  leaderboardSubmit(game, diff, score, name)\n  api.ts:65   User = { email, name }\n  server.js:569  Stripe Checkout session creation\n\nAn app with accounts, a public leaderboard and a paid checkout does not collect nothing.\nReplaced with the correct declarations (Contact Info, User Content, Identifiers, Purchases,\nall App Functionality / tracking = NO), plus a flagged item to verify: whether the mural\ncheckout collects a shipping address. The old note dismissed that as 'collected by the\nwebsite, not the binary' — reasoning that does not hold when the purchase flow is presented\ninside the app.\n\nAlso softened a marketing line that read 'the app does no tracking' into a claim that is\nactually true and defensible. NO_TRACK stripping analytics inside the checkout WebView is a\ntracking argument, not a collection argument; the two questionnaire questions are separate.\n\nFound by generalizing the check that had just caught the same class on Costa Rica.\nDocs only; no product code touched.\n\nCo-Authored-By: Claude Opus 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01QfGYEoLBywwJD1nfrHe1on"},{"hash":"4794797","date":"2026-09-03 13:55:41 -0700","author":"Steve Abrams","subject":"add gated Printify fulfillment path for wear","body":""},{"hash":"4f0db6e","date":"2026-09-03 13:38:56 -0700","author":"Steve Abrams","subject":"document TK-10286 wear end-to-end proof","body":""},{"hash":"a848890","date":"2026-08-31 11:34:13 -0700","author":"Steve Abrams","subject":"chore: v1.0.3 -> v1.0.4 (session close — /wear Stripe live-key fix + 2XL upcharge, TK-10286)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"b152beb","date":"2026-08-31 10:53:34 -0700","author":"Steve Abrams","subject":"wear: +$4 2XL size upcharge (tee $38 / polo $48) — TK-10286","body":"2XL costs Printful ~$3-4 more; flat retail ate that margin. Add\nsizeUpchargeUsd {2XL:4} per garment; server checkout charges base+upcharge\n(source of truth), wear.html shows the adjusted price + a '(2XL +$4)' hint\non size select. Steve's pricing decision (b). Sales still gated OFF.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"8b5b7ca","date":"2026-08-31 10:50:14 -0700","author":"Steve Abrams","subject":"wear: charge apparel through live-capable Stripe resolver, not test-only key (TK-10286)","body":"The /wear POD checkout was hardwired to STRIPE_DOWNLOAD_KEY (test-only), so\neven with WEAR_SALES_LIVE=1 + STRIPE_LIVE_ENABLED=1 + a live key it would\nnever charge a real card. Repoint the charge + session-read + order.mode to\nSTRIPE_MURAL_KEY/STRIPE_MODE (the same live-only-when-fully-switched resolver\nmurals use). No behavior change until Steve flips STRIPE_LIVE_ENABLED — today\nit still resolves to the test key.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"19ad3e6","date":"2026-08-31 02:08:01 -0700","author":"Steve Abrams","subject":"Add AI-readable site guide","body":""},{"hash":"93f7578","date":"2026-08-25 14:46:54 -0700","author":"Steve Abrams","subject":"CelebritySignatures mobile: early-game respects Difficulty + persist personal best (TK-10398)","body":"Two next-build polish fixes from the TK-10262 Cody review, both in\napps/mobile/screens/GameScreen.tsx:\n\n1. 'Early or Late?' now honors the Difficulty selector. It previously\n   sampled EVO directly and ignored diff, so Icons/Scholar/Curator/Deep\n   Cuts had no effect. Now the EVO people are filtered to the notability-\n   ranked top-N tier (joined by qid), with a fallback to the full set if\n   the tier is too thin to build a round (never regresses to unstartable).\n   Category is left as-is: the Category selector is already hidden for\n   'early' via catRelevant, so this stays catalog-wide by design.\n\n2. Personal best now survives an app restart. Added\n   @react-native-async-storage/async-storage (2.2.0, expo-installed for\n   SDK 56); BEST hydrates from disk on mount and saves on finish, with a\n   try/catch fallback to the existing in-memory cache so it never crashes\n   even in a build where the native module isn't linked yet.\n\nNeither was a crash — both are quality polish. tsc --noEmit passes clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"0770f00","date":"2026-08-10 16:14:59 -0700","author":"Steve Abrams","subject":"chore: lint, refactor, session-close fixes, v1.0.2 → v1.0.3 (TK-10286)","body":"Session-close quality gate on the Printful POD wiring:\n- FIX (critical, caught by lint): submit-pod-draft.mjs now appends a SUBMITTED marker after each successful Printful POST + filters it out on the DRAFT_UNSENT read — a rerun can no longer double-submit an already-sent order (proven: rerun sends nothing)\n- FIX: /wear-checkout returns 400 on unknown size (was silently falling back to sizes[0] → wrong fulfillment)\n- FIX: /wear-success no longer swallows errors silently (console.error) so a paid-but-draft-write-failed case is visible in the log\n- refactor: envVal() consolidated to the for-of form (behavior-identical)\n- node --check clean on all; dry-run still submits nothing"},{"hash":"0fa8dbf","date":"2026-08-10 15:14:47 -0700","author":"Steve Abrams","subject":"wear/POD: wire Printful sender + go-live path (gated OFF) — TK-10286","body":"- submit-pod-draft.mjs: Printful /orders payload, triple-gated (--apply + PRINTFUL_API_KEY + WEAR_SALES_LIVE=1), confirm=false drafts, fail-loud on unmapped variant / missing shipping addr; dry-run default\n- fetch-printful-catalog.mjs (new): read-only catalog->variant_id mapper\n- wear-templates.json: per-garment printful{} block (empty by design)\n- server.js: Stripe shipping_address_collection on /wear-checkout + carry address into order+POD draft (still behind WEAR_SALES_LIVE coming-soon gate; no visitor reaches checkout)\n- verified node --check clean, dry-run submits nothing, unmapped garment skipped\n- go-live memo -> pending-approval (real flip stays Steve-gated: key+live Stripe+WEAR_SALES_LIVE)"},{"hash":"5ed1ce7","date":"2026-08-10 10:59:15 -0700","author":"Steve Abrams","subject":"wear v1 soft-launch: browsable catalog live, sales gated behind WEAR_SALES_LIVE (coming-soon/notify-me buy button; no test-checkout exposed to real visitors)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"96c795b","date":"2026-08-10 10:53:36 -0700","author":"Steve Abrams","subject":"wear v1 (TK-10286, Steve GO): ship public-domain historical signatures, USPTO auto-screen deferred","body":"wearEligible now clears figures deceased on/before 1900 (no live apparel-TM/estate risk) instead of requiring the USPTO CLEAR verdict — 2,955 signatures become sellable (Jefferson, Franklin, da Vinci…) vs 0 before. USPTO logic preserved as wearEligibleTM for when the ODP key lands. Disclosure updated to state the public-domain basis honestly. Stripe stays TEST + POD submit stays gated (no real money/fulfillment). Verified: /wear renders 2955 cards, test checkout returns a session.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"a858b81","date":"2026-08-10 09:39:35 -0700","author":"Steve Abrams","subject":"chore: lint (node --check ✓, no linter configured) + v1.0.1 → v1.0.2 (session close, TK-10286)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"d394377","date":"2026-08-10 08:32:17 -0700","author":"Steve Abrams","subject":"wear/TM: partial-register completeness guard + fix retired-host runbook (TK-10286)","body":"Cody-gated hardening of the /wear USPTO trademark gate:\n- build-tm-index.mjs: require >= TM_MIN_MARKS (default 500k, --min-marks/env override)\n  parsed live marks before writing complete:true. Previously complete=(parsedReal>0),\n  so an interrupted ingest (1 of ~91 register parts) would flip complete:true and,\n  because build-tm-clearance screen() returns CLEAR on absence-of-match, false-CLEAR\n  every name the missing parts would have flagged MARK_FOUND — a write that lands\n  BEFORE any go-live approval. Guard keeps a truncated register partial -> store empty.\n- WEAR-LEGAL-NOTE.md: replace retired bulkdata.uspto.gov --url runbook (dead host)\n  with the ODP --file/--odp path; document the completeness floor.\n- WEAR-READY-FOR-KEY.md: note the floor + that a daily-only screen never reaches complete.\nVerified: seed-only stays complete:false (no regression); GET /api/wear/signatures\ncount:0; checkout of an otherwise-eligible sig (Jefferson Q11812) still 403s.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"15b76e1","date":"2026-08-10 08:07:49 -0700","author":"Steve Abrams","subject":"ios: fastlane push_listing = screenshots-only (skip_metadata) — avoids blanking required App Review contact fields; metadata already published on the draft (TK-10262)","body":""},{"hash":"986ff07","date":"2026-08-10 06:22:45 -0700","author":"Steve Abrams","subject":"ios: fresh App Store screenshots (iPhone 6.9\" 1320x2868 + iPad 13\" 2048x2732) from live site — replaces stale broken set (TK-10262)","body":"The stale dark-theme/empty-signature screenshots were the original submission QA blocker. These are accurate current-site captures: browse grid (7,211 sigs), the 6-game suite, murals studio — at exact ASC resolutions for both device families. iPad set added so build 8 (iPad+tvOS) can be reused without the toolchain-blocked iPhone-only rebuild.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"a613dfa","date":"2026-08-09 12:37:27 -0700","author":"Steve Abrams","subject":"mobile: iPhone-only (supportsTablet:false) — drops iPad so ASC stops requiring iPad screenshots (TK-10258, Steve-approved iPhone-only)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"43d50a8","date":"2026-08-08 16:08:24 -0700","author":"Steve Abrams","subject":"screenrecord: track murals debug + verify harnesses (TK-10193 reproducibility)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"57895fb","date":"2026-08-08 10:47:49 -0700","author":"Steve Abrams","subject":"game: harden — hide #prep before showRound() (Cody gate, TK-10192)","body":"Cody's adversarial backstop flagged that hiding #prep AFTER showRound() strands a visible prep line over an empty #play panel if showRound() ever throws. buildRounds already succeeded by that point, so hiding prep first is safe with zero happy-path change. Re-verified: whose game still play=true, prep hidden, 4 choices, 0 dialogs.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"dc1565d","date":"2026-08-08 10:44:19 -0700","author":"Steve Abrams","subject":"game: fix TK-10192 BUG 1 — build failure no longer fires a modal alert() that froze the page","body":"buildRounds() throws legitimately when a tier can't be filled (esp. art/match/lightning, which depend on the external api.artic.edu museum API). It called native alert(e.message), which modally blocks the page; in the 5-pass debug (one reused page, no dialog handler) a single artwork-load failure jammed every subsequent game's Begin (30s timeout) = the false 'first games work, rest break' cascade. All 6 games are actually sound.\n\nFix A (game.html): inline non-blocking .prep.err message instead of alert(); success hides #prep, failure keeps the reason visible + re-enables Begin — flaky museum API now degrades to 'try Icons or Scholar' rather than a dead-end browser alert.\nFix B (game-debug.mjs): page.on('dialog', dismiss) so one dialog can't poison a run.\n\nVerified (run1 cascade order, one reused page): 0 native dialogs; every Begin click 27-54ms (was 30000ms); all 6 games start independently; match resolves to play w/ 4 choices after full artic.edu load. Report: screenrecord/DEBUG-REPORT-game.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"589b8d1","date":"2026-08-08 10:38:42 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-08T10:37:54 (77 data files) — screenrecord/debug-log.jsonl screenrecord/rec/game-run0/page@d3c036c80501f7033d077d5f6df76847.mp4 screenrecord/rec/game-run0/page@d3c036c80501f7033d077d5f6df76847.webm screenrecord/rec/game-run1/page@6e5156e1f617020d464184dbf6f78a28.mp4 screenrecord/rec/game-run1/page@6e5156e1f617020d464184dbf6f78a28.webm","body":""},{"hash":"e0115ae","date":"2026-08-08 10:29:53 -0700","author":"Steve Abrams","subject":"murals: fix TK-10193 BUG 1 — quote-submit no longer wipes name+email, so a follow-up Pay & order isn't blocked","body":"Order form's 'Request a quote instead' called f.reset() on success, clearing name+email; #payBtn hard-guards on those fields and dead-ended a quote->pay flow with 'Enter your name and a valid email first' (never hit /api/mural-checkout). Now clears only the free-text notes, preserving name/email/dims. Verified (playwright, test mode): quote-then-pay now fires /api/mural-checkout 200; intact-fields pay still 200 (no regression).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"8f9337b","date":"2026-08-08 10:07:53 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-08T10:07:09 (1 data files) — screenrecord/verify2-out.txt","body":""}]}