Dw Photo Capture

repo: ~/Projects/dw-photo-capture · 493 commits · 9 in last 24h, 112 in last 7d · ▃▂▂▃█▄▂

Search the build

493 commits indexed

  1. 6286a2f 2026-09-26 Swipe picker: Pick this one opens the theme full screen (Back / Esc / Go to the app), Open-your-pick button reopens it; fix filter wiring catching the pick button (TK-12343)
  2. 28a1391 2026-09-26 Swipe picker: one trackpad swipe/wheel flick = one theme (Safari skipped two); app chooser shows once per tab, not on every load (TK-12343)
  3. 24bc0c3 2026-09-26 Front screen: one-at-a-time swipe theme picker (Figma v1-v25 + Photoshop Kid-Simple v7-v16); capture app moves to /app (TK-12343)
  4. 6e2c3f2 2026-09-26 Onload chooser: Adobe Spectrum themes (Light/Dark/Darkest/Auto) + accents, smart Suggested action, full UX (TK-12346)
  5. 4ace5d4 2026-09-26 Add /kid-simple/ review page: Kid-Simple mockups v1-v16 + Photoshop board, behind basic-auth (TK-12344)
  6. ac13489 2026-09-26 Untrack runtime build counter data/build.json and gitignore it
  7. 6e16998 2026-09-26 TK-12090: add verify-only prod vision check paste script
  8. 436c44b 2026-09-26 auto-data-snapshot: 2026-09-26T04:44:27 (1 data files) — data/color-dots.json
  9. d7887da 2026-09-26 auto-data-snapshot: 2026-09-26T03:43:38 (1 data files) — data/color-dots.json
  10. 655426a 2026-09-25 TK-12268: add creds-in-URL fetch guard (fleet pattern) to gated page
  11. 9b15829 2026-09-25 TK-12268: add creds-in-URL fetch guard (fleet pattern) to gated page
  12. 7aecde5 2026-09-25 Editor fits iPhone width: narrow-screen layout (wheel above sliders, Use Photo full-width, Crop/Reset/Cancel row)
  13. 69d5016 2026-09-25 Front/Back tiles: tap a taken photo to adjust it in the Enhance/Crop editor; Adjust + Retake buttons below each tile (TK-12256)
  14. a2e8198 2026-09-25 5x sweep 5: report — sweeps converge at cap, 3 app defects fixed, env SIGTERM open
  15. 0e8aa0e 2026-09-25 5x sweep 4: history evidence screenshot viewport-only (Firefox 32767px full-page limit)
  16. bf95f56 2026-09-25 5x sweep 3: hung-camera e2e mode (all engines), WebKit stub fix, sweep aborts if server dies
  17. 4fd7dee 2026-09-25 5x sweep 2: camera-timeout retry tap now opens the snap camera (as the toast promises)
  18. b49fdf9 2026-09-25 deploy: exclude tracked schu-publish-audit.jsonl (identical on remote) from rsync to stop delete-guard false positive
  19. 15beb44 2026-09-25 5x sweep 1: favicon on captures/batch/cam, consistent missing-side rule, 3-engine e2e + lazy-img scroll
  20. d1a0b78 2026-09-25 TK-12228: every captured photo, front and back, displays in the app
  21. e82585f 2026-09-25 deploy: exclude .claude/ from rsync so agent worktree logs on remote aren't deleted
  22. 126f917 2026-09-25 Fix grainy Shopify product photos: raise server-side JPEG normalize cap+quality
  23. afa2777 2026-09-25 auto-data-snapshot: 2026-09-25T04:38:13 (1 data files) — data/color-dots.json
  24. 14a6623 2026-09-25 auto-data-snapshot: 2026-09-25T03:37:11 (1 data files) — data/color-dots.json
  25. 8cceebc 2026-09-24 TK-12205: untrack agent worktree gitlink auto-snapshotted into main; ignore .claude/worktrees/
  26. 05c1b61 2026-09-24 auto-data-snapshot: 2026-09-24T23:32:41 (1 data files) — .claude/worktrees/agent-a841f65dcd871d6ac
  27. d47866f 2026-09-24 auto-data-snapshot: 2026-09-24T23:02:07 (1 data files) — .claude/worktrees/agent-a841f65dcd871d6ac
  28. 99b4c9a 2026-09-24 auto-data-snapshot: 2026-09-24T21:00:07 (1 data files) — .claude/worktrees/agent-a841f65dcd871d6ac
  29. e99e554 2026-09-24 auto-data-snapshot: 2026-09-24T20:29:39 (2 data files) — .claude/worktrees/agent-a841f65dcd871d6ac data/build.json
  30. 67566bd 2026-09-24 TK-12162: mint checks vendor catalog reservations + confirms the number is free LIVE (FileMaker + Shopify)
  31. 2bc55d4 2026-09-24 TK-12162: 582 FileMaker masters created for live Tres Tintas products (DWTS); 10 Thibaut records mis-moved earlier restored to DWTT
  32. 30fe09a 2026-09-24 TK-12162: fix my collision - 7 Tres Tintas sq-ft listings DWTS-900000..006 -> DWTS-901507..513 (900001-006 reserved in tres_tintas_catalog)
  33. b1582b8 2026-09-24 TK-12162: 1168 Tres Tintas Shopify variant SKUs DWTB- -> DWTS- (undo log)
  34. 825c8b2 2026-09-24 auto-data-snapshot: 2026-09-24T16:24:12 (2 data files) — ops/tres-tintas-dwts-2026-09-24/__pycache__/shop-tb.cpython-314.pyc ops/tres-tintas-dwts-2026-09-24/shop-tb-restore.jsonl
  35. d6f19b5 2026-09-24 Henry sync: treat not-yet-created server archive as OK 0, not FAIL (TK-12162)
  36. 2653995 2026-09-24 Nightly additive rsync of vendor photo archive to Henry + launchd plist (TK-12162)
  37. 0260eb6 2026-09-24 Save every uploaded photo by vendor: photos/vendors/<Vendor>/ archive + index + /vendor-photos gallery + one-time backfill (TK-12162)
  38. 07b7e8c 2026-09-24 deploy: exclude ops/ (Tres Tintas restore maps/scripts are local-only, not server runtime) (TK-12162)
  39. d5ea198 2026-09-24 TK-12162: DWTB-10050 Tres Tintas master -> DWTS, duplicate tagged DUPE-DELETE (restore map)
  40. 83caea3 2026-09-24 Add 'Other apps' links (4 simplified capture concepts) to home screen + bottom of upload grid (TK-12162)
  41. 450f953 2026-09-24 TK-12162: script to move 584 Tres Tintas Shopify products DWTB- -> DWTS- (Steve-run; classifier-gated)
  42. 34ac646 2026-09-24 TK-12162: Tres Tintas DWTT/DWRW -> DWTS restore maps + delete list
  43. a99636b 2026-09-24 TK-12162: show a dw_unified save-status line on all 4 capture pages, independent of the Shopify draft result
  44. e7a5066 2026-09-24 TK-12162: auto-save only for registry vendors; case-insensitive vendor lookup; Minimal sends pattern name
  45. 360da78 2026-09-24 TK-12162: await + retry the dw_unified new_items_staging write on every item create and report its result (dw_unified field) instead of fire-and-forget
  46. 7e1353c 2026-09-24 TK-12090: verify script resolves dwphoto by name, not stale pm2 id 226
  47. 1a2c398 2026-09-24 TK-12162: pre-shot 11-slider adjust panel + auto-save on all simple-* pages
  48. 4d1311b 2026-09-24 TK-12162: full-res native-camera capture on all simple-* pages
  49. 14e3194 2026-09-24 TK-12162: capture at high res on all simple-* pages + route minimal/wizard/probooth
  50. 2b1d006 2026-09-24 Consolidate SKU field cleanup into shared field-clean.js helper
  51. 10d3e40 2026-09-24 TK-12162: guided wizard never strands a guest on an unexpected finishCapture error
  52. 03f509f 2026-09-24 TK-12090/TK-12162: fix numeric-SKU .trim() crash + de-obfuscate deploy verifier
  53. a7bae5f 2026-09-24 auto-data-snapshot: 2026-09-24T13:20:22 (1 data files) — data/build.json
  54. a262d3e 2026-09-24 TK-12162 Instant Film concept: simple-instant.html (Polaroid-style single-photo capture, animation decoupled from real /api/extract upload)
  55. 247c9f9 2026-09-24 TK-12090: report provider=null when the vision call fails
  56. dc3cc71 2026-09-24 TK-12162 Pro Booth concept: simple-probooth.html (3-slider capture, bake-once + speculative extract, single-commit save) + staged Figma build script
  57. 8452fcc 2026-09-24 TK-12090: decouple exo VLM ring from HAS_MACVISION, make it the reasoning-path default
  58. 8364615 2026-09-24 TK-12126: never report Gemini OCR cost for a call that errored
  59. d9c9612 2026-09-24 TK-12126: add camera commit:true round-trip proof script (mock-tested, live path gated)
  60. a1b8ee3 2026-09-24 Extract shared acquireCamera() helper, adopt across 5 unbounded surfaces (TK-12127)
  61. 0e42baf 2026-09-24 Wire ended + mute listeners on _tsTrack, scoped by generation (TK-12128)
  62. b2bd893 2026-09-24 Add persistent "applies at capture, not preview" hint on the Sharpness slider (TK-12125)
  63. 9f4d2c2 2026-09-24 Fix 3 Cody-found holes in the getUserMedia timeout fix (TK-12124 follow-up)
  64. ca60ce9 2026-09-24 Fix: bound getUserMedia() with an 8s timeout so a hung camera prompt can't brick the shutter (TK-12124)
  65. 1d04e3f 2026-09-24 auto-data-snapshot: 2026-09-24T04:27:32 (1 data files) — data/color-dots.json
  66. 12011d5 2026-09-24 auto-data-snapshot: 2026-09-24T03:56:09 (1 data files) — data/color-dots.json
  67. 2a2801e 2026-09-23 batch.html: adopt shared capture-pipeline engine, full Photoshop set on top of gray-card calibration (TK-12090)
  68. 880e4d8 2026-09-23 cam.html + desk.html: full pre-capture photoshop camera (zero→full parity) (TK-12090)
  69. af5702a 2026-09-23 index.html two-shot: adopt shared capture-pipeline + full adjust panel + presets + histogram (TK-12090)
  70. fdff137 2026-09-23 add shared capture-pipeline.js engine (full pre-capture photoshop set, manual canvas pixel math)
  71. 94c8d60 2026-09-23 server.js: bounded /js/ static route to serve the shared capture-pipeline module (TK-12090)
  72. 63b4de0 2026-09-23 auto-data-snapshot: 2026-09-23T15:21:10 (2 data files) — visual-search/__pycache__/pattern_siblings.cpython-312.pyc visual-search/__pycache__/search_service.cpython-312.pyc
  73. 409e338 2026-09-23 deploy.conf: exclude visual-search venv + CLIP weights + test dirs from rsync (1.3GB, TK-12090 Lane P follow-up)
  74. 95babfe 2026-09-23 visual-search: optional pattern-sibling stage (PATTERN_SIBLINGS=1 + body siblings:true) using dw-pairs-well colour-invariant dHash + WS-1 pattern_id, vendor+pattern_name fallback (TK-12090 Lane P)
  75. 6a07319 2026-09-23 visual-search: product_image_fingerprints PG table + disk-guarded idempotent loader + flagged SQL-filtered PG search path (PG_FINGERPRINTS=1, default off) (TK-12090 Lane P)
  76. b1c94e3 2026-09-23 auto-data-snapshot: 2026-09-23T14:48:42 (1 data files) — visual-search/sql/product_image_fingerprints.sql
  77. d5f6c4a 2026-09-23 visual-search nightly embed: env-first DB user (PGUSER or running OS user, drop retired stevestudio2), launchd PATH for psql, fail-loud connect precheck (TK-12090 Lane P)
  78. 5b591d9 2026-09-23 repoint dead Ollama macvision + Q&A paths to shared exo-vision lib (ring primary, Gemini fallback, honest not_measured) (TK-12090 Lane P)
  79. 2284bdb 2026-09-23 auto-data-snapshot: 2026-09-23T04:15:24 (1 data files) — data/color-dots.json
  80. a7f6dc5 2026-09-23 auto-data-snapshot: 2026-09-23T03:44:04 (1 data files) — data/color-dots.json
  81. 4d1ee36 2026-09-22 harden pid interpolation in staging insert (independent-review follow-up)
  82. 060357d 2026-09-22 fix SQL injection in create-item staging insert (dollar-quote escape defeated by $$$)
  83. 0d34d1b 2026-09-22 gitignore 5x/out/ screen-capture test artifacts
  84. 2bc0f06 2026-09-22 harden all-dw cache write: atomic tmp+rename, refresh disk-cache sig
  85. 77ae6ab 2026-09-21 harden(TK-11962): catalog-cache guard survives corrupt/unreadable cache (Kimi review)
  86. 39cda0e 2026-09-21 fix(perf): guard redundant disk-cache reparse in buildCatalog (TK-11962)
  87. b272ac4 2026-09-21 auto-data-snapshot: 2026-09-21T17:27:28 (2 data files) — 5x/twoshot-result.json data/build.json
  88. 5e89bec 2026-09-21 fix(lint): drop redundant \/ escape in COLOR/NAME label regexes (TK-11962)
  89. 10fd713 2026-09-21 auto-data-snapshot: 2026-09-21T10:59:35 (1 data files) — data/build.json
  90. c5ee50a 2026-09-21 photo-capture #8 harden (TK-11962 DTD): TTL-guard stale restore + surface quota failure
  91. fc87163 2026-09-21 auto-data-snapshot: 2026-09-21T06:39:23 (1 data files) — data/build.json
  92. c87b661 2026-09-21 harden (TK-11962 review #7/#8/#9): server.on('error') + unconditional create gate + persist in-progress capture
  93. 3af4c92 2026-09-21 auto-data-snapshot: 2026-09-21T04:28:28 (1 data files) — data/color-dots.json
  94. 9342c10 2026-09-21 auto-data-snapshot: 2026-09-21T03:55:17 (1 data files) — data/color-dots.json
  95. ec70808 2026-09-20 auto-data-snapshot: 2026-09-20T18:59:45 (1 data files) — 5x/out/features-sweep9.json
  96. 71c8d21 2026-09-20 auto-data-snapshot: 2026-09-20T18:25:19 (3 data files) — 5x/out/s9-dryrun-9890.json 5x/out/s9-dryrun-9899-FM.json data/build.json
  97. 9a8a272 2026-09-20 harden: process-level error safety net + string-validate dataUrl (fixes 1-request DoS)
  98. 39c872f 2026-09-20 auto-data-snapshot: 2026-09-20T12:15:15 (2 data files) — data/build.json data/scan-log.jsonl
  99. 7d98690 2026-09-20 5x REPORT: TK-11947 capture rebuild — 51/51, Cody SHIP IT, deploy gated
  100. 635c96e 2026-09-20 Cody re-gate #2 hardening: conditional shutter-arm + flip double-tap guard + injected-failure negative test
  101. 1878910 2026-09-20 5x fix sweep: guard camera race + fail-safe liveness + cap capture res + lock lens on BACK (Cody FIX FIRST)
  102. 480017e 2026-09-20 photo-capture: live pre-shutter colour + ordered two-photo ghost capture (#twoShotCam)
  103. fc97695 2026-09-20 auto-data-snapshot: 2026-09-20T11:40:52 (1 data files) — data/build.json
  104. ad2e176 2026-09-20 auto-data-snapshot: 2026-09-20T09:27:07 (1 data files) — data/scan-log.jsonl
  105. 5e0422e 2026-09-20 auto-data-snapshot: 2026-09-20T08:54:11 (1 data files) — data/build.json
  106. fe8bd65 2026-09-20 photo-capture: plain 12-yr-old wording + large simple buttons across index/batch/cam
  107. 3b53e0e 2026-09-20 auto-data-snapshot: 2026-09-20T04:26:57 (1 data files) — data/color-dots.json
  108. c11515c 2026-09-20 fix threading race in _get_model(): add _MODEL_LOCK + double-checked locking pattern
  109. 618d031 2026-09-20 auto-data-snapshot: 2026-09-20T03:53:01 (1 data files) — data/color-dots.json
  110. 08460f7 2026-09-19 auto-data-snapshot: 2026-09-19T18:59:45 (2 data files) — data/build.json data/scan-log.jsonl
  111. 131d2a5 2026-09-19 photo-capture: raise UI scale to 1.35x + extend to batch-shoot + remote-cam
  112. 3b83a72 2026-09-19 photo-capture: global 1.2x UI scale on editor (--ui-scale dial) — 'make all larger'
  113. 313e6c7 2026-09-19 auto-data-snapshot: 2026-09-19T13:09:57 (2 data files) — data/scan-log.jsonl data/vendor_profiles.json
  114. 767d07c 2026-09-19 auto-data-snapshot: 2026-09-19T11:34:41 (7 data files) — 5x/out/features-sweep6.json 5x/out/features-sweep7.json 5x/out/features-sweep8.json 5x/out/s8-dryrun-9890.json 5x/out/s8-dryrun-9899-FM.json
  115. 725a545 2026-09-19 Add-modal: session counter survived only until the modal opened — addTitle.textContent wiped the #sessCount child span, so 'N this session' could never render. Title text now lives in #addTitleTxt. F7.0-F7.2 pass (sweep 7)
  116. 4084d07 2026-09-19 Add-modal: scrollable overlay (flex-start + overflow-y:auto, card margin:auto) — iPhone 390x844 close/vendor/Preview were unreachable; the sweep-1 fix was logged but never committed. F2m + F1/F6/F9/F12 pass locally (sweep 6)
  117. 237a9ab 2026-09-19 auto-data-snapshot: 2026-09-19T11:03:02 (4 data files) — 5x/out/features-sweep5.json 5x/out/features-sweep6.json 5x/out/s5-dryrun-9890.json 5x/out/s5-dryrun-9899-FM.json
  118. f121f54 2026-09-19 5x: archive stale July-7 sweep notes so they cannot be mistaken for current evidence (Cody #3)
  119. 1855b9b 2026-09-19 5x: sweep-1 evidence screenshots (iPad chips, iPad/iPhone add-modal)
  120. ed3e909 2026-09-19 auto-data-snapshot: 2026-09-19T10:31:17 (3 data files) — 5x/out/features-sweep2.json 5x/out/features-sweep3.json 5x/out/features-sweep4.json
  121. 26941e3 2026-09-19 chore: lint, refactor, v1.6.1 (session close) — 5x batch harness: track() closure, dead cal/increment removed, eslint browser-globals for harness
  122. 97b0233 2026-09-19 5x: batch UI calibrates via real #cSave (no synthetic cal seed); B7.10 resume-cal + B7.11 fall-through — 33/33 vs 5f0e9fc
  123. 5f0e9fc 2026-09-19 Batch shoot: Resume now restores calibration (was shooting with cal=null)
  124. 7100b30 2026-09-19 DEVICE-TEST: batch — panel position persistence + WYSIWYG master-vs-original verify step
  125. 1d4b604 2026-09-19 5x: add Batch Shoot Mode (/batch) coverage — side-named batch-shot, gate, toolpanel
  126. 243f267 2026-09-19 Batch shoot: live WYSIWYG colour tools + PSku/Info two-shot flow + TWIL vendor
  127. 7a758b5 2026-09-19 auto-data-snapshot: 2026-09-19T09:59:20 (4 data files) — data/batch-sessions/smoke-test.jsonl data/batch-sessions/smoke3.jsonl data/build.json data/scan-log.jsonl
  128. 243f75a 2026-09-19 DEVICE-TEST: batch checklist for PSku→Info two-shot flow, side-named files, WYSIWYG sliders, toolpanel
  129. 23bf804 2026-09-19 Batch capture: harden against camera death + low-confidence SKU
  130. 721a8a6 2026-09-19 auto-data-snapshot: 2026-09-19T08:55:30 (2 data files) — data/scan-log.jsonl data/vendor_profiles.json
  131. 036345c 2026-09-19 auto-data-snapshot: 2026-09-19T04:40:20 (1 data files) — data/color-dots.json
  132. 1c505d9 2026-09-19 auto-data-snapshot: 2026-09-19T03:36:55 (1 data files) — data/color-dots.json
  133. caccd25 2026-09-18 auto-data-snapshot: 2026-09-18T15:26:25 (6 data files) — 5x/fixtures/warm-cast.y4m 5x/out/features-sweep1.json 5x/out/s1-dryrun-9890.json 5x/out/s1-dryrun-9899-FM.json data/build.json
  134. ac3ec66 2026-09-18 Batch UI: redo as a simple 1-2-3 wizard with plain-English explanations
  135. 40f89a1 2026-09-18 auto-data-snapshot: 2026-09-18T14:54:24 (2 data files) — data/build.json data/scan-log.jsonl
  136. 14ba745 2026-09-18 Photo capture: linear 2-photo flow, Measure Depth, White Balance, colour hue, continue-able batch, mic-every-field
  137. a138b39 2026-09-18 Batch OCR: load GEMINI_API_KEY from secrets + default to gemini engine
  138. bad2f48 2026-09-18 auto-data-snapshot: 2026-09-18T14:19:46 (2 data files) — data/build.json data/scan-log.jsonl
  139. b99e4d9 2026-09-18 Photo capture: installable PWA — DW-branded home-screen icon (iPad/iPhone)
  140. 4cbb39e 2026-09-18 Photo capture: two-photo capture + mfr# identity gate (front-OCR/back-OCR/manual)
  141. c03988d 2026-09-18 Photo capture: post each metafield with its store-defined type (fix 422)
  142. 37a2682 2026-09-18 auto-data-snapshot: 2026-09-18T13:45:34 (2 data files) — data/build.json data/scan-log.jsonl
  143. e74d7de 2026-09-18 batch mode: vendor is now a dropdown (catalog vendor list) instead of free text
  144. 0c8c48f 2026-09-18 Photo capture: vendor picker → sticky overlay bar on the live camera
  145. 0a65a03 2026-09-18 Photo capture: vendor-first new-SKU creation across Shopify + dw_unified + FileMaker
  146. 70ed167 2026-09-18 batch mode: OCR falls back to manual after a timeout (no more 30s hang)
  147. e43af57 2026-09-18 auto-data-snapshot: 2026-09-18T11:01:55 (1 data files) — data/batch-sessions/TESTSESSION-smoke.jsonl
  148. 39ffa6e 2026-09-18 batch mode: draw the light-reference band live during shooting too
  149. 02ce83c 2026-09-18 batch mode: fix gate + queue bugs from contrarian review
  150. 374d995 2026-09-18 auto-data-snapshot: 2026-09-18T10:30:02 (1 data files) — data/build.json
  151. acf1bf8 2026-09-18 batch: add Batch Shoot Mode (production-line capture for 400+ samples)
  152. 84755d9 2026-09-18 auto-data-snapshot: 2026-09-18T04:37:40 (1 data files) — data/color-dots.json
  153. 8b77105 2026-09-18 auto-data-snapshot: 2026-09-18T03:33:53 (1 data files) — data/color-dots.json
  154. 05bcfcd 2026-09-17 auto-data-snapshot: 2026-09-17T04:30:36 (1 data files) — data/color-dots.json
  155. 77c2810 2026-09-17 auto-data-snapshot: 2026-09-17T03:58:38 (1 data files) — data/color-dots.json
  156. 690f742 2026-09-16 auto-data-snapshot: 2026-09-16T04:39:34 (1 data files) — data/color-dots.json
  157. 1a17ae2 2026-09-16 auto-data-snapshot: 2026-09-16T03:35:57 (1 data files) — data/color-dots.json
  158. 42047ed 2026-09-15 chore: commit code deployed in 2026-09-15 fleet push
  159. b0d1b1e 2026-09-15 auto-data-snapshot: 2026-09-15T04:27:49 (1 data files) — data/color-dots.json
  160. 75cca4c 2026-09-15 auto-data-snapshot: 2026-09-15T03:56:10 (1 data files) — data/color-dots.json
  161. 2d472c1 2026-09-14 auto-data-snapshot: 2026-09-14T04:37:30 (1 data files) — data/color-dots.json
  162. 825ecfa 2026-09-14 auto-data-snapshot: 2026-09-14T03:34:24 (1 data files) — data/color-dots.json
  163. ffdc98e 2026-09-13 auto-data-snapshot: 2026-09-13T04:15:01 (1 data files) — data/color-dots.json
  164. 3bee7ae 2026-09-13 auto-data-snapshot: 2026-09-13T03:42:21 (1 data files) — data/color-dots.json
  165. 4f9634d 2026-09-12 auto-data-snapshot: 2026-09-12T04:26:59 (1 data files) — data/color-dots.json
  166. 9ae1360 2026-09-12 auto-data-snapshot: 2026-09-12T03:53:49 (1 data files) — data/color-dots.json
  167. b56600e 2026-09-11 auto-data-snapshot: 2026-09-11T04:24:06 (1 data files) — data/color-dots.json
  168. 96b8c8d 2026-09-11 auto-data-snapshot: 2026-09-11T03:51:39 (1 data files) — data/color-dots.json
  169. b8aa768 2026-09-10 guard TK-11357 Fix D: create_22_new.py minted price-LESS rolls already stocked at 2026
  170. 625721e 2026-09-10 auto-data-snapshot: 2026-09-10T04:15:51 (1 data files) — data/color-dots.json
  171. eff7edc 2026-09-10 auto-data-snapshot: 2026-09-10T03:43:17 (1 data files) — data/color-dots.json
  172. 5f0be7e 2026-09-09 auto-data-snapshot: 2026-09-09T04:40:57 (1 data files) — data/color-dots.json
  173. 5d67be1 2026-09-09 auto-data-snapshot: 2026-09-09T03:37:19 (1 data files) — data/color-dots.json
  174. 30367f1 2026-09-08 auto-data-snapshot: 2026-09-08T04:33:12 (1 data files) — data/color-dots.json
  175. 4fc4f06 2026-09-08 auto-data-snapshot: 2026-09-08T03:55:22 (1 data files) — data/color-dots.json
  176. 646369e 2026-09-07 auto-data-snapshot: 2026-09-07T04:15:57 (1 data files) — data/color-dots.json
  177. c47ea8d 2026-09-07 auto-data-snapshot: 2026-09-07T03:37:33 (1 data files) — data/color-dots.json
  178. d17fdf7 2026-09-06 auto-data-snapshot: 2026-09-06T04:34:41 (1 data files) — data/color-dots.json
  179. c61c7f4 2026-09-06 auto-data-snapshot: 2026-09-06T03:56:22 (1 data files) — data/color-dots.json
  180. 424dcfa 2026-09-05 auto-data-snapshot: 2026-09-05T04:17:39 (1 data files) — data/color-dots.json
  181. 1af0607 2026-09-05 auto-data-snapshot: 2026-09-05T03:39:28 (1 data files) — data/color-dots.json
  182. 02b92ea 2026-09-04 auto-data-snapshot: 2026-09-04T04:33:28 (1 data files) — data/color-dots.json
  183. f090659 2026-09-04 auto-data-snapshot: 2026-09-04T03:52:16 (1 data files) — data/color-dots.json
  184. 50f78c5 2026-09-03 auto-data-snapshot: 2026-09-03T04:44:57 (1 data files) — data/color-dots.json
  185. d64e7f1 2026-09-03 auto-data-snapshot: 2026-09-03T04:07:16 (1 data files) — data/color-dots.json
  186. 488f4ab 2026-09-02 repair autonomous color index rebuild
  187. 731dcfa 2026-09-02 auto-data-snapshot: 2026-09-02T04:39:22 (1 data files) — data/color-dots.json
  188. d854b02 2026-09-01 auto-data-snapshot: 2026-09-01T04:43:03 (1 data files) — data/color-dots.json
  189. e89cb1a 2026-08-31 auto-data-snapshot: 2026-08-31T04:30:23 (1 data files) — data/color-dots.json
  190. ac43121 2026-08-30 deploy-safety: exclude data/ from rsync (TK-10984)
  191. 1407ed7 2026-08-30 add creds-in-URL fetch guard to gated pages (TK-10984)
  192. e27fa61 2026-08-30 auto-data-snapshot: 2026-08-30T04:46:23 (1 data files) — data/color-dots.json
  193. ac2ed26 2026-08-30 auto-data-snapshot: 2026-08-30T03:31:23 (1 data files) — data/color-dots.json
  194. 3ad7902 2026-08-29 auto-data-snapshot: 2026-08-29T04:46:12 (1 data files) — data/color-dots.json
  195. 7e6c278 2026-08-29 auto-data-snapshot: 2026-08-29T03:31:35 (1 data files) — data/color-dots.json
  196. ab4806e 2026-08-28 auto-data-snapshot: 2026-08-28T04:38:35 (1 data files) — data/color-dots.json
  197. 76dc410 2026-08-28 auto-data-snapshot: 2026-08-28T04:01:51 (1 data files) — data/color-dots.json
  198. 0e3b7c4 2026-08-27 auto-data-snapshot: 2026-08-27T04:38:11 (1 data files) — data/color-dots.json
  199. 0e65730 2026-08-27 auto-data-snapshot: 2026-08-27T04:01:50 (1 data files) — data/color-dots.json
  200. 539e67e 2026-08-26 auto-data-snapshot: 2026-08-26T04:39:06 (1 data files) — data/color-dots.json
  201. 412b7ce 2026-08-26 auto-data-snapshot: 2026-08-26T04:02:16 (1 data files) — data/color-dots.json
  202. bdc246b 2026-08-25 creds-safe fetch guard: resolve relative fetch vs credential-free location (creds-in-URL trap)
  203. 87ae2c5 2026-08-25 auto-data-snapshot: 2026-08-25T04:35:37 (1 data files) — data/color-dots.json
  204. cf6bcc9 2026-08-25 auto-data-snapshot: 2026-08-25T03:58:57 (1 data files) — data/color-dots.json
  205. 38a39ec 2026-08-24 auto-data-snapshot: 2026-08-24T04:45:01 (1 data files) — data/color-dots.json
  206. ff4610e 2026-08-24 auto-data-snapshot: 2026-08-24T03:41:17 (1 data files) — data/color-dots.json
  207. eb531a7 2026-08-23 auto-data-snapshot: 2026-08-23T04:19:03 (1 data files) — data/color-dots.json
  208. 7cb4772 2026-08-23 auto-data-snapshot: 2026-08-23T03:47:15 (1 data files) — data/color-dots.json
  209. 8b50b57 2026-08-22 auto-data-snapshot: 2026-08-22T04:22:57 (1 data files) — data/color-dots.json
  210. 0d2a33e 2026-08-22 auto-data-snapshot: 2026-08-22T03:51:11 (1 data files) — data/color-dots.json
  211. 833f180 2026-08-21 auto-data-snapshot: 2026-08-21T04:29:08 (1 data files) — data/color-dots.json
  212. d7bda18 2026-08-21 auto-data-snapshot: 2026-08-21T03:57:28 (1 data files) — data/color-dots.json
  213. 8cadf1f 2026-08-20 auto-data-snapshot: 2026-08-20T04:44:35 (1 data files) — data/color-dots.json
  214. 32bb501 2026-08-20 auto-data-snapshot: 2026-08-20T03:38:46 (1 data files) — data/color-dots.json
  215. 80558a8 2026-08-19 auto-data-snapshot: 2026-08-19T04:17:42 (1 data files) — data/color-dots.json
  216. f94162f 2026-08-19 auto-data-snapshot: 2026-08-19T03:46:07 (1 data files) — data/color-dots.json
  217. aed2273 2026-08-18 auto-data-snapshot: 2026-08-18T04:37:55 (1 data files) — data/color-dots.json
  218. d0fe135 2026-08-18 auto-data-snapshot: 2026-08-18T03:37:22 (1 data files) — data/color-dots.json
  219. 7575b38 2026-08-17 snapshot before restart: preserve in-flight work (auto-saved by /restart pre-reboot)
  220. 8fc972d 2026-08-17 auto-data-snapshot: 2026-08-17T04:29:37 (1 data files) — data/color-dots.json
  221. d62c63f 2026-08-17 auto-data-snapshot: 2026-08-17T03:59:16 (1 data files) — data/color-dots.json
  222. 029ddeb 2026-08-16 auto-data-snapshot: 2026-08-16T04:20:17 (1 data files) — data/color-dots.json
  223. e99b674 2026-08-16 auto-data-snapshot: 2026-08-16T03:49:55 (1 data files) — data/color-dots.json
  224. 0cb4ba7 2026-08-15 auto-data-snapshot: 2026-08-15T04:38:51 (1 data files) — data/color-dots.json
  225. 70c224f 2026-08-15 auto-data-snapshot: 2026-08-15T03:38:01 (1 data files) — data/color-dots.json
  226. 0934636 2026-08-14 auto-data-snapshot: 2026-08-14T04:16:15 (1 data files) — data/color-dots.json
  227. 36acc48 2026-08-14 auto-data-snapshot: 2026-08-14T03:45:50 (1 data files) — data/color-dots.json
  228. cbb7144 2026-08-13 auto-data-snapshot: 2026-08-13T15:04:38 (4 data files) — visual-search/train/.gitignore visual-search/train/HANDOFF.md visual-search/train/__pycache__/finetune.cpython-312.pyc visual-search/train/__pycache__/finetune_aug.cpython-312.pyc
  229. fe6cef3 2026-08-13 auto-data-snapshot: 2026-08-13T04:16:27 (1 data files) — data/color-dots.json
  230. dfdac89 2026-08-13 auto-data-snapshot: 2026-08-13T03:45:50 (1 data files) — data/color-dots.json
  231. e1301ca 2026-08-12 auto-data-snapshot: 2026-08-12T04:15:31 (1 data files) — data/color-dots.json
  232. ea93077 2026-08-12 auto-data-snapshot: 2026-08-12T03:44:41 (1 data files) — data/color-dots.json
  233. 2e3fe5b 2026-08-11 auto-data-snapshot: 2026-08-11T04:29:53 (1 data files) — data/color-dots.json
  234. e847757 2026-08-11 auto-data-snapshot: 2026-08-11T03:59:02 (1 data files) — data/color-dots.json
  235. 3cb011d 2026-08-10 auto-data-snapshot: 2026-08-10T04:16:24 (1 data files) — data/color-dots.json
  236. 1235d6a 2026-08-10 auto-data-snapshot: 2026-08-10T03:45:26 (1 data files) — data/color-dots.json
  237. a2a39ee 2026-08-09 auto-data-snapshot: 2026-08-09T04:37:25 (1 data files) — data/color-dots.json
  238. 1af553b 2026-08-09 auto-data-snapshot: 2026-08-09T03:35:42 (1 data files) — data/color-dots.json
  239. 98ee7ea 2026-08-07 auto-data-snapshot: 2026-08-07T04:23:46 (1 data files) — data/color-dots.json
  240. 662c672 2026-08-07 auto-data-snapshot: 2026-08-07T03:53:01 (1 data files) — data/color-dots.json
  241. baec7aa 2026-08-06 auto-save: 2026-08-06T04:18:20 (1 files) — data/color-dots.json
  242. 39c9259 2026-08-06 auto-save: 2026-08-06T03:48:10 (1 files) — data/color-dots.json
  243. 1565c16 2026-08-05 auto-save: 2026-08-05T04:39:04 (1 files) — data/color-dots.json
  244. deec734 2026-08-05 auto-save: 2026-08-05T03:38:44 (1 files) — data/color-dots.json
  245. 98368f6 2026-08-04 auto-save: 2026-08-04T04:29:46 (1 files) — data/color-dots.json
  246. 80c5a95 2026-08-04 auto-save: 2026-08-04T03:59:36 (1 files) — data/color-dots.json
  247. d85c504 2026-08-03 auto-save: 2026-08-03T04:20:12 (1 files) — data/color-dots.json
  248. 318f2b0 2026-08-03 auto-save: 2026-08-03T03:50:03 (1 files) — data/color-dots.json
  249. e3beb54 2026-08-02 auto-save: 2026-08-02T04:42:12 (1 files) — data/color-dots.json
  250. e7d4158 2026-08-02 auto-save: 2026-08-02T03:41:50 (1 files) — data/color-dots.json
  251. d2c1d79 2026-08-01 auto-save: 2026-08-01T04:33:25 (1 files) — data/color-dots.json
  252. 1ae3d54 2026-08-01 auto-save: 2026-08-01T03:33:03 (1 files) — data/color-dots.json
  253. bd29311 2026-07-31 auto-save: 2026-07-31T09:26:15 (1 files) — server.js
  254. b890acb 2026-07-31 auto-save: 2026-07-31T04:23:41 (1 files) — data/color-dots.json
  255. 7ab6ab0 2026-07-31 auto-save: 2026-07-31T03:53:30 (1 files) — data/color-dots.json
  256. 9551f9b 2026-07-30 auto-save: 2026-07-30T04:44:39 (1 files) — data/color-dots.json
  257. 2c82b3c 2026-07-30 auto-save: 2026-07-30T03:44:22 (1 files) — data/color-dots.json
  258. f58ad8d 2026-07-29 auto-save: 2026-07-29T20:42:08 (1 files) — package-lock.json
  259. 3116235 2026-07-29 chore: v1.6.0 — public /marketing static route for email assets (session close)
  260. ba0e274 2026-07-29 Add bounded public /marketing/ static route (images only, traversal-safe) + color-coordinate demo GIF for email hosting
  261. d204283 2026-07-29 auto-save: 2026-07-29T04:35:46 (1 files) — data/color-dots.json
  262. f9dbf0d 2026-07-29 auto-save: 2026-07-29T03:35:26 (1 files) — data/color-dots.json
  263. e944832 2026-07-28 auto-save: 2026-07-28T04:27:17 (1 files) — data/color-dots.json
  264. 2085685 2026-07-28 auto-save: 2026-07-28T03:57:08 (1 files) — data/color-dots.json
  265. 7f05d6c 2026-07-27 auto-save: 2026-07-27T04:17:53 (1 files) — data/color-dots.json
  266. d407efc 2026-07-27 auto-save: 2026-07-27T03:47:45 (1 files) — data/color-dots.json
  267. 210a279 2026-07-26 auto-save: 2026-07-26T04:40:35 (1 files) — data/color-dots.json
  268. 8038793 2026-07-26 auto-save: 2026-07-26T03:40:20 (1 files) — data/color-dots.json
  269. 89699fd 2026-07-25 auto-save: 2026-07-25T04:33:37 (1 files) — data/color-dots.json
  270. 77c6b64 2026-07-25 auto-save: 2026-07-25T03:33:15 (1 files) — data/color-dots.json
  271. d7be4c6 2026-07-24 auto-save: 2026-07-24T04:25:19 (1 files) — data/color-dots.json
  272. 98b67d2 2026-07-24 auto-save: 2026-07-24T03:55:12 (1 files) — data/color-dots.json
  273. d17f80f 2026-07-23 auto-save: 2026-07-23T04:18:33 (1 files) — data/color-dots.json
  274. c643cf0 2026-07-23 auto-save: 2026-07-23T03:48:26 (1 files) — data/color-dots.json
  275. 214f7fb 2026-07-22 auto-save: 2026-07-22T04:41:22 (1 files) — data/color-dots.json
  276. 22fe1cb 2026-07-22 auto-save: 2026-07-22T03:41:10 (1 files) — data/color-dots.json
  277. 52d98a4 2026-07-21 chore: lint (drop unused HSL l), refactor (familyOf hue comment, hexToRgb param), v1.5.1 (session close)
  278. f733796 2026-07-21 auto-save: 2026-07-21T04:35:41 (1 files) — data/color-dots.json
  279. 904218b 2026-07-21 auto-save: 2026-07-21T03:35:30 (1 files) — data/color-dots.json
  280. d684bcb 2026-07-20 auto-save: 2026-07-20T04:29:52 (1 files) — data/color-dots.json
  281. 2a2122c 2026-07-20 auto-save: 2026-07-20T03:59:45 (1 files) — data/color-dots.json
  282. e002054 2026-07-19 shop-by-color: data-driven ΔE-collapsed color dots (real DB hexes, ≥20 patterns, qty-ordered)
  283. a9c6a11 2026-07-19 chore: version-up v1.5.0 (session close — shop-by-color product_type)
  284. 8112eaf 2026-07-17 color-index: carry product_type through builder + both /apps/color-index and /apps/color-widen results (shop-by-color type checkboxes)
  285. 0d6c355 2026-07-16 color-widen: add min param — guarantee >=N results via nearest-neighbor fallback when the band is thin
  286. e2c9e01 2026-07-16 add /apps/color-widen route: tunable ΔE band (default 15%) for the Shop-by-Color wheel at /pages/colors
  287. 5d305fe 2026-07-15 color-index: exclude sample-only ($4.25) products — require has_product_variant so shop-by-color never links to a sample-only PDP (harm-reduction until vendor costs are sourced)
  288. 4214868 2026-07-15 add nightly color-index refresh script + launchd plist (DRAFT — install gated): build from live shopify_products, rsync json to Kamatera (endpoint hot-reloads)
  289. 91ce171 2026-07-15 deps: add pg so build-color-index runs standalone (needed for scheduled rebuild)
  290. 61eee41 2026-07-15 color-index: build from live shopify_products (active + online_store_published) — drop archived/unpublished handles so PDP color grid never links to 404s or dead images
  291. dd6e416 2026-07-13 chore: session close snapshot (visual-search)
  292. 2212c21 2026-07-13 nightly embed top-up script + plist draft (coverage anti-decay: both embedders resumable + index hot-reload)
  293. bdba9e2 2026-07-13 visual-search: path-(a) Kamatera self-host bundle (lite venv, no torch; pm2 unit reading local dw_unified) — verified 71MB footprint
  294. fcb1edb 2026-07-13 visual-search: bind VS_HOST=0.0.0.0 so Kamatera pairs-well can reach the CLIP index over the tailnet (100.82.17.107:9914)
  295. 95931a9 2026-07-13 auto-save: 2026-07-13T00:51:43 (2 files) — visual-search/__pycache__/search_service.cpython-312.pyc visual-search/search_service.py
  296. a0e586b 2026-07-13 visual-search: make bind host configurable via VS_HOST (default 127.0.0.1, unchanged); enables opt-in tailnet exposure for remote consumers
  297. 2890b8f 2026-07-12 auto-save: 2026-07-12T23:51:20 (5 files) — visual-search/search_service.py visual-search/__pycache__/embed_shopify_gap.cpython-312.pyc visual-search/__pycache__/search_service.cpython-312.pyc visual-search/com.steve.visual-search.plist visual-search/embed_shopify_gap.py
  298. ca63a1e 2026-07-12 auto-save: 2026-07-12T23:21:12 (1 files) — visual-search/.gitignore
  299. c913d7d 2026-07-09 auto-save: 2026-07-09T22:42:31 (5 files) — screenrecord/debug-log.jsonl screenrecord/rec/run3/page@ea8fb1218f5b7b345af268e4e545b083.mp4 screenrecord/rec/run3/page@ea8fb1218f5b7b345af268e4e545b083.webm screenrecord/rec/run4/page@96324b4cfafc83a80afe7cd203ccecb3.mp4 screenrecord/rec/run4/page@96324b4cfafc83a80afe7cd203ccecb3.webm
  300. 7c5ada1 2026-07-09 auto-save: 2026-07-09T22:12:24 (1 files) — package-lock.json
  301. bb7bf3e 2026-07-09 chore: v1.4.0 (session close) — GCV+Gemini OCR fusion, WALLPAPER FileMaker lookup (dash-agnostic + partial search), save-every-scan, iOS freeze fixes (decode-free photo pipeline + 250x memory cut)
  302. 6aa4a18 2026-07-09 auto-save: 2026-07-09T19:41:55 (8 files) — screenrecord/debug-log.jsonl screenrecord/DEBUG-REPORT.md screenrecord/rec/run0_v103/ screenrecord/rec/run1_v103/ screenrecord/rec/run2_v103/
  303. 30757b5 2026-07-09 auto-save: 2026-07-09T16:41:19 (5 files) — schu-candidates.tsv schu-publish.mjs schu-apply-out.json schu-publish-audit.jsonl schu-settlement-hold.json
  304. d52d765 2026-07-09 auto-save: 2026-07-09T16:11:12 (2 files) — schu-candidates.tsv schu-publish.mjs
  305. 8ef6e5f 2026-07-09 auto-save: 2026-07-09T09:09:49 (1 files) — visual-search/__pycache__/
  306. 602bb7f 2026-07-09 PDP color-dot color-index: /apps/color-index endpoint + generator (catalog-wide 10% CIELAB tolerance)
  307. 41d871a 2026-07-09 CLIP /similar: DW-safe guard — only return storefront products w/ handle + DW-hosted image; drop wallquest.com hotlinks (broken imgs + private-label leak) + handleless entries; backfill to keep strip full
  308. 0bd9187 2026-07-09 iOS OOM-freeze root cause (found via mobile screenrecord 5x): app fetched /api/twil = 36MB/88,319 items on EVERY page load (default filter=twil) and render() built a DOM card for all 88k → browser hit 13GB and crashed the tab, starving the device so photo capture froze. Fix: RENDER_CAP=500 cards max + 'narrow your search' note; defer the 36MB loadTwil() off page-load (lazy on skip/TWIL-chip)
  309. 036d130 2026-07-09 auto-save: 2026-07-09T08:39:40 (2 files) — public/index.html screenrecord/
  310. ab7c20f 2026-07-08 Scan upload-progress (final DTD FIX-THEN-SHIP): identify-multi POST via XHR shows '⬆ Uploading photo… n%' then '🔎 Identifying…' — kills the dead-looking wait on a big raw-photo cellular upload that a user would misread as a freeze
  311. dd49fa4 2026-07-08 iOS freeze — close the contrarian gap: ALL photo flows now decode-free. downscale() itself = FileReader raw (fixes Add New SKU / Update SKU / gallery-batch, which still froze via createImageBitmap that v99 proved unsafe). Server normalizes at every ingest: create-item + /api/photo + /api/photos via normB64 (HEIC→JPEG for Shopify; box IM has libheif). Scan regression green
  312. 71b8574 2026-07-08 iOS freeze — eliminate ALL client-side image decode (DTD verdict B): fbRead uses FileReader.readAsDataURL (raw file, zero decode/canvas/bitmap), server normalizeImage() (ImageMagick: any format→auto-orient→≤1600px JPEG) handles it before OCR + visual. decodeQR capped at 1000px (a full-12MP getImageData is a ~48MB array that froze iOS). Verified: raw 3000px photo → resolves CHC217203. /5x 10/10
  313. d5ff7da 2026-07-08 iOS photo-processing freeze fix: downscale() now uses createImageBitmap (off-main-thread, low-memory decode) instead of <img>+canvas.toDataURL which OOM-hangs iOS on a 12MP camera photo; cap 1200px + q0.82. fbRead shows '📷 Processing photo…' immediately + guards a null (undecodable) read
  314. ef6656d 2026-07-08 Fix iOS camera freeze on Look Up SKU: stop auto-clicking the BACK capture input after the front photo — iOS Safari LOCKS UP when a capture-input .click() fires from a change-event (no fresh user gesture). Now highlights the Back tile + prompts a tap; front-only Identify also enabled
  315. 6eb9013 2026-07-08 FM lookup dash-agnostic + printed-code-first: wallpaper-details tries raw+dashless forms on both combo-sku and Mfr-Pattern (CHC-217203 ⇄ CHC217203 auto), and the scan keys the FM lookup off the PRINTED OCR code first (the model# on the label) plus the resolved dw_sku
  316. c473b21 2026-07-08 dwphoto: add SSRF-guarded CORS-scoped /apps/similar proxy route → loopback CLIP :9914 (shipped GATED-STEP-1)
  317. 06f5839 2026-07-08 visual-search /similar: also return storefront handle (LEFT JOIN shopify_products) so PDP cards link to real product pages
  318. 3e6d84f 2026-07-08 Save EVERY scan (Steve): identify-multi now persists the raw photo(s) + OCR candidates + engines + resolved identity to data/scan-log.jsonl (append-only, async best-effort — never breaks a scan). New /api/scans (newest-first, filter=unresolved) + /scans review page: photo ⇄ what OCR read ⇄ resolved SKU, so mis-reads are visible and the corpus improves the app. Verified: scan saved, image served, GCV+Gemini fusion recorded
  319. 51cf188 2026-07-08 OCR: multi-engine fusion for the back label — backOcrFused() runs every available engine (GCV→Gemini→macVision) and unions candidate codes so the catalog partial-search has more shots on goal; literal-transcriber engines lead. GCV is now plug-and-play (set GCV_API_KEY → auto-fuses). Scan read-line shows which engine(s) ran + per-scan cost
  320. c68081a 2026-07-08 visual-search: add POST /similar (SKU->CLIP visual neighbors, color+style soft re-rank, lazy CLIP load)
  321. a7f6374 2026-07-08 Scan lookup driven by the OCR'd label code: a VISUAL-only identify no longer beats the printed model# — the wallpaper-file lookup now prefers the OCR'd code (so 217500 gets searched even when identify 'found' a visual match), and every scan shows '📄 read: <codes>' so mis-reads are visible on-device. No-code-read state guides toward a clearer label photo
  322. 5cea2c8 2026-07-08 Scan fixes: (1) scrub DW's OWN header from identification — our phone 888-373-4564 (+ fragments/phone-shaped tokens) never becomes a candidate code, and 'Designer Wallcoverings' never read as the pattern name; model# is what runs down the SKU. (2) partial search now fires AUTOMATICALLY when a scan doesn't confidently match (uses the OCR'd code via back_read). (3) live search-as-you-type (debounced 300ms + race-guard) in the manual search box
  323. 8837b5f 2026-07-08 Scan: partial/fuzzy wallpaper-file lookup — new /api/wallpaper-search substring-matches any part of combo sku / Mfr Pattern / JS Pattern / Internal Description (FileMaker *q* OR-across-fields), with OCR trailing-char trim tolerance (217500→21750→CHC-21750-style), grouped+coalesced per SKU. Manual search box in the scan modal + auto partial-fallback when exact identify misses; tap a candidate → full detail card
  324. c3d8429 2026-07-08 Scan → show WALLPAPER FileMaker details: new /api/wallpaper-details (queries 'Basic List of Fields' by combo sku→Mfr Pattern, coalesces non-empty specs across the mega-table's multiple rows, portal:[] so no stall) + loadWallpaperDetails() renders a spec card (Mfr#/Collection/Width/Repeat/Retail/Net/Cost/Roll/Min/Border/Price-code/Line/SKU) under every scan result. 58k+ SKUs carry rich FM specs; sparse scraped lines show what FM has
  325. d4db33e 2026-07-08 doc: cross-reference the shared Date WP Sample Sent writer (mark-received + print-sticker both close the open-sample request via this field) — surfaced by contrarian gate during /5x
  326. b56afa1 2026-07-08 auto-save: 2026-07-08T11:35:28 (1 files) — package-lock.json
  327. 66895a7 2026-07-08 chore: v1.2.0 → v1.3.0 (session close — feed + discontinued-successor features)
  328. 5f86fc5 2026-07-08 auto-save: 2026-07-08T11:05:21 (1 files) — data/build.json
  329. ba63786 2026-07-08 Add discontinued-SKU resolver → red card → live successor link (local only)
  330. 140c994 2026-07-08 gitignore the runtime all-dw feed cache (data/all-catalog.json)
  331. a4417e3 2026-07-08 browse whole dw_unified catalog via all-dw feed (was Fentucci-only); disk-cache + Fentucci fallbacks
  332. 62ce2a4 2026-07-08 Incoming queue: best-effort image enrichment — pass 2 in the background refresh resolves CATALOG-miss samples via identifyUnified (full 267k crossref + 173k shopify_products), concurrency-bounded (6 workers), serve-stale-while-enriching. 0/40 -> 16/40 (40%) thumbnails + real pattern names; also populates dw_sku/mfr_sku so scan-match highlights more incoming cards
  333. 999db25 2026-07-08 Check Sample In: 'Received' button stamps Date WP Sample Sent=today (Steve's receive-stamp field) via POST /api/mark-received (fmSet), drops the card from the incoming queue; scan-match surfaces a one-tap 'Check in — received today'. Input-guarded (400 on missing recordId/bad json), no live write on my tests
  334. 427db51 2026-07-07 Check Sample In: incoming-queue panel — shows vendor-ordered+not-sent samples (recent 120d) with spec info, cached server-side + 8-min background refresh (FM find is a ~30s whole-file scan, so cache→instant 0.15s). Scan flags the matching incoming card. Images best-effort from active catalog
  335. 2d627ac 2026-07-07 Check Sample In → incoming queue: /api/incoming-samples finds vendor-ordered+not-sent samples in FileMaker (the arriving ones), enriched with catalog image+spec. fmFind gains portal:[] to suppress heavy portalData (fixed the FM timeout)
  336. 17b5c68 2026-07-07 Local aug-model deploy pipeline (mac_deploy_embed): embed full catalog with dw_clip_ft_aug on Mac MPS → Postgres COPY file for Kamatera local ingest (gate-respecting: no Mac→prod tunnel). Reuses 90k cache, 3-state load (ok/dead-404/transient-retry) so rate-limits never false-mark images dead. Resumable
  337. 2acc59c 2026-07-07 auto-save: 2026-07-07T13:30:45 (1 files) — visual-search/train/__pycache__/finetune_aug.cpython-312.pyc
  338. e56063d 2026-07-07 Look Up SKU pill: camera-first pure-identify flow — shoot FRONT pattern → auto-prompts/opens BACK label (the text/SKU) → runs identify-multi (visual+OCR+code fusion) and shows the SKU. Skips the sample check-in (that's the separate Check Sample In pill)
  339. 27b572c 2026-07-07 Fix aug-training crash (cannot write empty image): guard augment against tiny/empty crops + wrap JPEG recompress + AugSet falls back to a neighbor on a corrupt cache image (never crashes the run)
  340. a376a2d 2026-07-07 DEVICE-TEST: multi-photo tip — take 2-3 pattern shots for visual-ID (app fuses views; single shot ~28% top-1, multi-view is the reliable path)
  341. de2aca3 2026-07-07 robustness_fusion: note CDN rate-limiting makes the A/B unreliable; fusion verified directly (3-view demo promotes the corroborated match)
  342. 6cdd9d9 2026-07-07 Multi-photo visual-ID fusion: identify-multi now fuses up to 5 views (fronts[]) — a product matching across multiple photos gets a corroboration boost and outranks spurious single-view matches; Add/Update flows send all captured photos. Independent lever on the 28% single-shot problem (complements the augmentation retrain)
  343. 724673e 2026-07-07 auto-save: 2026-07-07T13:00:27 (1 files) — visual-search/train/__pycache__/finetune_aug.cpython-312.pyc
  344. 33641ca 2026-07-07 eval_aug: A/B degraded→clean image retrieval (base vs current FT vs augmented) → recommend deploy only if the aug model beats current top-1
  345. 54e085f 2026-07-07 Augmentation re-fine-tune: warm-start from dw_clip_ft.pt + heavy handheld-photo augmentation (rotate/crop/blur/glare/JPEG) on the image side → teach degraded→clean matching (targets the 28% real-photo top-1)
  346. 6a137d9 2026-07-07 5x contrarian gate: honest re-scope — FT visual-ID validated on the REAL task (degraded phone-like image→image) = only 28% top-1 (n=40), thresholds overlap; clean-image self-match hid this. App still safe (label-OCR primary + confidence+2nd-push gates). Real fix = augmentation re-train (surfaced, gated). Camera/iOS-Safari still untested (headless can't reach getUserMedia)
  347. 8694d87 2026-07-07 5x: 2 consecutive clean sweeps (0 app defects) post FT-model + dedup — six-way + endpoints + flow + dedup + calibrate all green; sole non-green is the M3 no-auth harness artifact (authed load 0.24s)
  348. 828996f 2026-07-07 Contrarian gate fix (dedup): add _addSession guard before every DOM write (no stale warning/switch into a reopened modal) + require a non-null product_id before offering 'Update instead' (was binding null pid → wrong-product write)
  349. cf2ea4a 2026-07-07 Add-mode visual dedup: new-SKU pattern photo → fine-tuned visual-ID; if it confidently matches an existing catalog pattern, warn (non-blocking) + offer one-tap 'Update it instead' (resolves via mfr then dw_sku). Prevents duplicate SKUs
  350. 7d4ccb6 2026-07-07 Device-test checklist for the iPhone-Safari real-device pass (camera-first, specs, mics, 10/6 gallery, calibrate-once measure, live Update + 2nd-push confirm, video transcode)
  351. ec02bd7 2026-07-07 Wire in fine-tuned DW CLIP: sanity-check picks best epoch (ep4, 52.9% held-out recall@1 vs 23.0% base — 2.3x, no overfit); load dw_clip_ft.pt in search_service + embed_catalog (both sides); catalog re-embedding on FT model (311k, snapshot saved for rollback)
  352. 5673cad 2026-07-06 Contrarian gate fix: _updateNeedsConfirm invariant — ANY ambiguous visual bind (background OR mid-Push) requires a 2nd Push before a LIVE write; label OCR + chip-tap are explicit (no gate). Plus session checks after resolve/visual awaits in addExtract
  353. 1570feb 2026-07-06 yolo hardening (8 fixes from adversarial review): C1 visual bind requires confirm before live push · C2 no auto-bind on low-confidence · W1 escape all $$ fields in staging SQL · W2 downscale onerror+timeout (no HEIC hang) · W3 create-item/photo/photos drain+413 · W4 session token guards stale async rebind · S1 calibration viewport check · S2 poll waits for all expected videos
  354. a2500f8 2026-07-06 Calibrate-once measurement: card sizes px/in for the device once → stored in localStorage → every later scan just needs the goods box, no card. Zoom locked so focal length stays constant. Recalibrate button to re-anchor.
  355. 8cff6c4 2026-07-06 Camera-unavailable UX: detect Chrome/3rd-party iOS browsers (no getUserMedia) and tell user to open in Safari, instead of a cryptic error
  356. b0a3ecc 2026-07-06 Handoff doc: how to wire the fine-tuned DW CLIP weights into visual search (sanity-check, re-embed both sides, gate the reindex, rollback)
  357. da94b6f 2026-07-06 Card-free measurement groundwork: lock camera zoom + /caps capability probe (reports focusDistance/zoom/motion support per device) to pick the right no-reference scale method
  358. b87d402 2026-07-06 Visual pattern-ID in capture flow (front photo → identify-multi → bind SKU by design, even with unreadable label; tappable candidate chips) + live on-camera dimension readout (credit-card scale reference → real W×L overlaid live, writes to specs)
  359. 5126f02 2026-07-06 Overnight DW CLIP fine-tune pipeline (MPS): build_manifest + resumable 256px downloader + open_clip contrastive fine-tune + overnight orchestrator
  360. 942ce16 2026-07-06 5x: 2 consecutive clean sweeps (0 app defects) — six-way + functional + headless-flow all green; 2 caught items proven harness artifacts
  361. aa3a6ce 2026-07-06 Video transcode poll: /api/media-status reads Shopify video processing state; client polls after upload until every clip is READY (or fails), updating the note in-place
  362. 4a51d5b 2026-07-06 Camera-first capture flow + 10-photo/6-video gallery: pill→camera→details-after-scan; Add mode creates draft, Update mode resolves existing SKU (shopifySearch fallback) and pushes photos+videos LIVE to Shopify; /api/resolve-product endpoint
  363. 29237c6 2026-07-06 Sticker loop web side LIVE: web_print_request field placed + FM_PRINT_FLAG_FIELD configured on Kamatera; dryRun-verified Print writes sent-date + sku/address flag
  364. c0cf2c5 2026-07-06 Add 3 photo slots to Add-item (Front·pattern / Back·label / Detail): label photo drives spec extraction, all 3 attach as ordered Shopify product images (front primary)
  365. eae81b8 2026-07-06 Add per-field 🎤 mic buttons on every Add-item field (dictate straight into Mfr#/Vendor/VID/Color/Name/Price) + prominent Voice-fill button
  366. 2857339 2026-07-06 FileMaker sticker setup: STEP 1 now requires placing web_print_request on the target layout (Data API can only write layout-present fields)
  367. d548ec8 2026-07-06 Generalize spec capture to any spec sheet or sample: read product material (Wallcovering/Fabric/Trim/…), drive Shopify product_type + metafield off it, persist full spec set to new_items_staging.specs jsonb
  368. 3fcbec5 2026-07-06 Capture full wallcovering spec set on scan (repeat/width/roll length/match/substrate/how-sold/collection/price code) → metafields + read-only specs panel in add-item
  369. 264f5cc 2026-07-06 feat: max-info extract on scan + voice-only-as-needed. /api/extract: Gemini pulls EVERY label field (vendor, mfr, pattern, colorway, collection, width, length, repeat, content, price) + fuzzy-maps vendor. Add-item photo auto-prefills all fields. Then voice ONLY as needed: if a required field (mfr/vendor) is still blank, the app SPEAKS the prompt (‘Enter vendor name’) via TTS + listens, while the dropdown stays usable + the field is highlighted. Verified extract: WDW2310/Winfield/Compass Clay.
  370. 496dc6c 2026-07-06 chore: embed-daemon.sh — resumable batch loop (20k chunks + auto-reload vsearch index), run via nohup + @reboot cron on Kamatera for reboot-resume. Replaces bare nohup embed. (pm2 wouldn't register the bash daemon reliably.)
  371. 2e4814d 2026-07-06 feat: onload chooser — 3 white-on-black pills (Add New SKU / Update SKU / Check Sample In), centered 3 rows. Routes: Add→new-item modal, Update→live scan, Check→front/back identify. ⌂ home button reopens; skip→ goes to catalog. Verified on mobile viewport, 0 pageerrors.
  372. 94d5ee9 2026-07-06 5x: app clean across 2 sweeps — M1/M2/B4 pass, 85 tests, both new modals open, 163-vendor dropdown, 0 console errors, all new endpoints live. M3 flake = harness no-auth + batch load (networkidle settles 1.24s with auth). WebKit skip = install tooling. No app fixes needed.
  373. 9a59376 2026-07-06 feat: add new SKU to dw_unified + Shopify (draft) with vendor/vid dropdown
  374. ac1d6d0 2026-07-06 feat: front+back identify UI + QR/vendor clues. #fbModal captures back label + front pattern; client jsQR decodes QR silently (extracts SKU token, never navigates); server fuses code+QR+vendor+visual. QR token filter requires a digit (skips domain words). Vendor name off the label used to weight visual + fill primary. Verified: QR URL→TR2581→RHT264/Seabrook.
  375. 023d1b2 2026-07-06 feat: CLIP visual search + multi-photo front/back fusion identify
  376. 873541c 2026-07-06 feat: visual identify — Gemini compares the ACTUAL user photo against candidate catalog IMAGES (not typed attributes) and floats the true pixel-match to the front, or honestly reports no-match. Adds fetchImageB64 + geminiVisualMatch; /api/recognize returns a visual{} block. ~$0.0036/recognize (6 imgs). Correctly rejected 5 non-matching grasscloths in test.
  377. 11691f4 2026-07-06 feat: Option B — Mac-side sticker watcher (use both). sticker-watcher.js polls FileMaker for web_print_request-flagged records, fires the existing print script via AppleScript do-script (combo-sku param), clears the flag; reuses fm-client.js, loads FM creds from filemaker-mcp/.env. launchd plist staged (not started — needs field + real print-script names). Doc: arm ONLY ONE of A/B (double-print race); DTD favored A, B built as the no-FileMaker-window option.
  378. 8d68c8e 2026-07-06 docs: precise 2-step FileMaker setup (create web_print_request field + Web Sticker Poller script) — Data API can't create schema/scripts; server pre-staged to activate on field creation. Includes Mac-side AppleScript-watcher alternative.
  379. 5e67458 2026-07-06 5x: report — desktop + mobile Chrome PASS (0 console errors), lazy-thumb fix (414→4 reqs), M3=harness auth artifact. WebKit engine install broken on this box (tooling, not app).
  380. 060b63d 2026-07-06 5x sweep: lazy-load grid thumbnails (IntersectionObserver) — grid used CSS background-images (can't use loading=lazy) so a big filter loaded 100s of images at once. Now bg applies only on-visible: +414 requests after load → +4. Big mobile win; networkidle settles 2.3s. No console errors.
  381. 7754221 2026-07-06 fix: print-sticker no longer hangs + go-live hardening
  382. 1f9cc3b 2026-07-06 docs: FileMaker sticker setup — flag field + OnTimer poller (reuse existing print/stamp scripts) + FM_WRITE gate. Deployed read-only FM creds to Kamatera; sample-request lookup live (Maya50162→Haley McKinley w/ image), print-sticker dry-run until flag field designated.
  383. 7f00ab4 2026-07-06 feat: sample-request sticker popup + scan cost throttle
  384. 31dbd12 2026-07-06 feat: FileMaker sample-request lookup + print-sticker handoff
  385. a985673 2026-07-06 feat: best-ID identify-first against unified catalog — identifyUnified(code) resolves a scanned code via dw_sku_crossref (267k, shares FileMaker's Mfr Pattern/combo sku vocabulary) to canonical {internal_sku, mfr_sku, vendor} + best-effort image/title from shopify_products. New GET /api/identify-unified. Verified: TR2581→RHT264/Seabrook, 83615→VIC261B w/ image.
  386. 5483a67 2026-07-06 feat: hone in on the text — OCR now reads a centered, upscaled ROI (guide-box region, 5:2, up to 2x) instead of the whole frame, so small printed SKUs read sharper; full frame retained for logo/pattern match
  387. 9277da4 2026-07-06 fix: dw_unified 'match design' works on Kamatera — drop non-existent min_variant_price column from unifiedSimilar (Kamatera schema differs from mac2); app now returns similar products. DW_UNIFIED_DB accepts a full postgres:// URI (app runs as root, no PG role). Verified: grasscloth swatch → 48 products live.
  388. 1ffca17 2026-07-06 feat: structured field auto-detect (sku#/model#/name/color) + live green highlight + per-vendor spec learning
  389. 761b356 2026-07-06 feat: front side auto-matches the design — hold steady on the pattern face → auto-fires /api/recognize (reuses the match path) instead of only prompting a flip; resets on code/open/close
  390. 9192328 2026-07-06 feat: auto front/back side detection on scan — analyzeOcr classifies label(back) vs pattern-face(front) from OCR density ($0, per-frame); live scanner shows '🎨 flip to the label' on the pattern side. +5 tests (79 total)
  391. b7eee40 2026-07-06 chore: photocapture LIVE on Kamatera at photo.designerwallcoverings.com (pm2 dwphoto :9912, gemini engine, CF-proxied + LE cert); retire Mac tunnel
  392. d3b12d1 2026-07-06 chore: Kamatera deploy artifacts — .deploy.conf (gemini engine, /healthz smoke), .env.example, DEPLOY.md runbook
  393. 75c75e3 2026-07-06 feat: pluggable vision engines (macvision|gemini|gcv), runtime-selectable + engine=all — enables Linux/Kamatera hosting
  394. 7bb6521 2026-07-06 docs: expose photocapture publicly via Cloudflare Tunnel at photo.designerwallcoverings.com (Mac-bound; CF edge TLS for camera)
  395. ea390e5 2026-07-03 chore: macstudio3 migration — reconcile from mac2 + repoint paths (stevestudio2→macstudio3, node/npm/npx→/opt/homebrew)
  396. 70f9dc0 2026-06-26 auto-save: 2026-06-26T10:45:01 (2 files) — OVERNIGHT_LEDGER.md package-lock.json
  397. fbc4b68 2026-06-26 chore: lint clean, refactor (none needed), v1.1.0 (session close)
  398. 06f58bc 2026-06-26 chore: v1.1.0 — 🎨 Recognize Pattern feature (session close)
  399. 6407d11 2026-06-26 test: lock parseOcrRows barcode branches + overnight wind-down note (cycle 23)
  400. 25e9532 2026-06-26 test: cover nmfr + brandRe normalizers (cycle 22)
  401. 2e6d31c 2026-06-26 test: cover mfrToHouseSku resolver (cycle 21)
  402. 93cd3e4 2026-06-26 auto-save: 2026-06-26T08:43:59 (1 files) — data/build.json
  403. eb1e546 2026-06-26 test: reject O/0 OCR fallback (real collisions) + lock verbatim-code contract (cycle 20)
  404. e3483ef 2026-06-26 observability: add /api/stats; backlog O/0 OCR fallback with evidence (cycle 19)
  405. c3b1b21 2026-06-26 auto-save: 2026-06-26T08:13:39 (2 files) — data/build.json data/vendor_profiles.json
  406. 4d8fe6d 2026-06-26 robustness: atomic saveJSON so a crash/ENOSPC can't corrupt persisted data (cycle 18)
  407. d9df0cb 2026-06-26 test: lock candidate-order contract scanResolve relies on (cycle 17 audit)
  408. 5980db1 2026-06-26 auto-save: 2026-06-26T07:13:19 (2 files) — data/build.json data/vendor_profiles.json
  409. 830b25f 2026-06-26 fuzzy: ambiguity guard so a partial read can't bind the wrong vendor (cycle 16)
  410. f35ef39 2026-06-26 security: fix /api/learn prototype-pollution DoS (cycle 15)
  411. bf76d61 2026-06-26 auto-save: 2026-06-26T06:43:07 (1 files) — data/build.json
  412. a3b00cc 2026-06-26 harden: prefix support gate so one bad scan can't corrupt learned prefixes (cycle 14)
  413. 3eaa90d 2026-06-26 auto-save: 2026-06-26T06:12:56 (1 files) — data/build.json
  414. ad48b18 2026-06-26 Recognize Pattern: strip -SAMPLE suffix from result SKUs (2,900 sample-variant rows showed sample SKU on card)
  415. f050ab3 2026-06-26 test: fuzzyVendor edge guards + disk-full debug note (cycle 13)
  416. 0801a44 2026-06-26 test: fingerprintVendor edge cases + reject OCR-confidence-threshold (cycle 12)
  417. 8f32cd4 2026-06-26 auto-save: 2026-06-26T05:12:44 (1 files) — data/build.json
  418. bfd8249 2026-06-26 scan UX: tentative 'hold steady' cue + reject Swift low-light pre-pass (cycle 11)
  419. 367d125 2026-06-26 auto-save: 2026-06-26T02:08:48 (2 files) — data/build.json data/vendor_profiles.json
  420. 2c6e052 2026-06-26 test: harden analyzeOcr against adversarial OCR inputs (cycle 10, brainstorm)
  421. f6b8dec 2026-06-26 review: fix 3 findings from session code-review (cycle 9)
  422. a412dce 2026-06-26 auto-save: 2026-06-26T01:38:39 (1 files) — data/build.json
  423. 64ab508 2026-06-26 scan: background logo-ID when a code locks but OCR names no vendor (cycle 8)
  424. d76cc5a 2026-06-26 identify: per-request model toggle (moondream fast path) + API.md (cycle 7)
  425. 934a758 2026-06-26 auto-save: 2026-06-26T00:38:23 (2 files) — data/build.json data/recents.json
  426. bf7279e 2026-06-26 test: analyzeOcr/vendor unit tests (overnight cycle 6)
  427. 6264e28 2026-06-26 Recognize Pattern refactor: dedupe SQL term-match, single-trigger visual rerank, shared image-pipe helper, reuse one fingerprint canvas
  428. 94dce12 2026-06-25 ledger: switch overnight loop to NEVER-STOP idea-adding mode (Steve)
  429. 2a4ae14 2026-06-25 identify: logo-fingerprint tiebreaker (DTD 3/3 verdict A)
  430. edd68a9 2026-06-25 Add 🎨 Recognize Pattern: VLM reads a swatch, finds this + visually-similar items across the whole unified DB
  431. 39a065c 2026-06-25 learn: surface logo fingerprint + flag rejected logos (overnight cycle 4)
  432. dfefc4a 2026-06-25 Scan UX: distinct BARCODE lock label (overnight cycle 3)
  433. b10f11c 2026-06-25 Overnight cycle 1-2: selfcheck pass + draft gated weekly vendor-refresh launchd
  434. 3c0bcb1 2026-06-25 Logos: tighten matcher + validate fingerprints (DTD-A verdict)
  435. 33731b6 2026-06-25 auto-save: 2026-06-25T23:37:59 (8 files) — build_logo_fingerprints.py build_vendor_logos.py data/build.json data/logos/fabricut.jpg data/vendor_logos.json
  436. 85dccb3 2026-06-25 Harvest vendor logos from Shopify Files → ground logo recognition
  437. d30783b 2026-06-25 Scan: recognize barcodes (exact SKU) + logos/typeface (local VLM)
  438. 8fae114 2026-06-25 auto-save: 2026-06-25T23:07:50 (4 files) — bin/ocr bin/ocr.swift data/build.json server.js
  439. 5ebe4e6 2026-06-25 Learn how each vendor labels their samples (180 vendor profiles)
  440. 47a5ecf 2026-06-25 Ask-the-SKU: voice Q&A about a product via local Ollama ($0)
  441. fc5196a 2026-06-25 auto-save: 2026-06-25T18:36:37 (1 files) — data/recents.json
  442. 3948d6a 2026-06-25 Voice search: mic button → speak vendor/SKU/what-to-look-for → search
  443. 610fc30 2026-06-25 Scan audio: outcome-based — yoo-hoo on resolve, 'uh-oh' on no-match
  444. a045b5f 2026-06-25 Scan: brand-aware fast-lock + RED locked-in state
  445. 89ca632 2026-06-25 Scan: audible 'yoo-hoo' cue on code lock-in (v41)
  446. b974240 2026-06-25 Auto-refresh mfr# index: hourly incremental (8-18) + nightly full rebuild
  447. dcb3fda 2026-06-25 auto-save: 2026-06-25T17:36:07 (2 files) — build_mfr_index.py refresh_mfr_index.py
  448. 47fbc5a 2026-06-25 Add manufacturer-SKU resolver: scanned vendor codes resolve to DW house SKUs
  449. 8ddb73e 2026-06-25 Scan: code numbers ONLY — drop name/prose candidates
  450. 3046f62 2026-06-25 Scan ranks by font size first (largest letters), WD/Winfield Thybony prefix
  451. e48f07d 2026-06-25 auto-save: 2026-06-25T16:05:06 (2 files) — data/build.json photo-app-qr.png
  452. 9a72bcb 2026-06-25 Add dev-only ESLint static gate + remove dead tcase helper
  453. 4ba1fb1 2026-06-25 Fix front-camera scan: mirror-retry (ocrSmart) recovers backwards-text reads on iOS selfie cam; wired into live + snap scan
  454. 3355c70 2026-06-25 Camera chooser: back/front toggle (header + live-scan flip), persisted, drives scanner + all capture inputs; fix getLS->LS init crash
  455. f482ee7 2026-06-25 Multi-pass OCR scan: try every candidate (DW SKU + mfr# + name) across TWIL then all-Shopify
  456. 7a11139 2026-06-25 Video uploads: 🎥 Video in gallery → /api/video runs the Shopify staged-upload + productCreateMedia(VIDEO) pipeline (multipart to GCS), 150MB cap. Verified end-to-end + cleaned test
  457. 3832493 2026-06-25 Crop tool: add aspect-ratio presets (Free / 1:1 / 4:3 / 3:4 / 16:9) — ratio-locked, anchor-based corner resize
  458. f97337a 2026-06-25 Add ✂️ Crop tool to photo editor (drag corners/move, dim outside, bakes into final) + default landing = 🧵 All TWIL + Any-SKU auto-falls-back to all-Shopify (mfr#/DW SKU) when not in TWIL index
  459. a2e7b32 2026-06-25 Add 🧵 All TWIL chip (every Fentucci/grasscloth item, not just photos-needed) via /api/twil; confirm 🌐 All Shopify gives access to every vendor's SKUs. GRS-27080 = numbering gap (never assigned)
  460. ae60fb4 2026-06-25 auto-save: 2026-06-25T09:33:15 (1 files) — server.js
  461. ae3352b 2026-06-25 Live SKU scanner: HTTPS listener (:9891, self-signed cert) enables getUserMedia; 🔢 Scan streams the camera, OCRs each frame, LOCKS IN when a SKU repeats 2x -> auto-lookup. Falls back to tap-snap over HTTP
  462. 5047a83 2026-06-25 App starts collapsed (clean landing until filter/search/scan) + re-crawl spreadsheet -> 203 GRS items (DWNAT->GRS col-W backfill)
  463. 54495aa 2026-06-25 auto-save: 2026-06-25T09:03:03 (1 files) — data/build.json
  464. b34052e 2026-06-25 Camera SKU scan: 🔢 Scan button → macOS Vision OCR (/api/ocr, local/free) reads a printed mfr#/SKU off a sample book, extracts the SKU token, and jumps to that product in Any-SKU search. bin/ocr Swift binary
  465. f61b633 2026-06-25 Desktop-controlled remote shutter (DTD-C): /desk control page + /cam phone live-camera page, paired via SSE+POST over the tailnet. Desktop SHOOT -> SSE shoot event -> phone captures native-res frame from getUserMedia -> uploads via existing /api/photo -> desktop previews. iOS-hardened (playsinline/muted, 3-tier facingMode, auto-reconnect). No new Shopify auto-write; attach stays operator-triggered.
  466. 8ca15e9 2026-06-25 auto-save: 2026-06-25T08:32:54 (1 files) — server.js
  467. 8cdab9b 2026-06-25 Add /selfcheck self-check: server-side health report (catalog/index/queue/token/data) + auto-cleans stale photo refs (kills the dead-link class); HTML report; version pill links to it. selfcheck.sh runs server + deep Playwright UI crawl
  468. f90170b 2026-06-25 Make PWA icon + manifest public (no auth) so iOS Add-to-Home-Screen fetches them; app routes stay gated
  469. 989aa83 2026-06-25 Installable PWA: app icon (gold DW/camera) + web manifest + apple-touch-icon + standalone meta — Add to Home Screen now gives a real app icon + fullscreen
  470. 4e6ec3f 2026-06-25 Multi-photo add: ➕ Multiple in the Photos gallery batch-appends several shots at once (keeps featured + existing images); /api/photos endpoint, never-upscale each, 12/batch cap
  471. a4af440 2026-06-25 All GRS- sold PER YARD: flipped 133 products (variant Roll->Per Yard, unit_of_measure->Priced Per Yard, dwc.order_unit->Yard); now 174/174 uniform. createFromSheet defaults to per-yard for future creates. Price unchanged (already per-yard)
  472. 3c7d0a2 2026-06-25 Add ⭐ Favorites + 🕘 Recent views: star any card to pin SKUs you update often; recents auto-log on every upload (server-stored, shared across phone+office)
  473. 3cbfbc0 2026-06-24 All-Shopify search covers collections too: parallel product + collection-products query, merged/deduped, across every vendor; results carry their collections
  474. 418e972 2026-06-24 Add collections to search: each product carries its Shopify collection titles; lookup matches collection name + cards show 📚 collection chips
  475. 087b386 2026-06-24 Create 22 net-new GRS drafts (full sheet info, photo->live) + per-SKU photo gallery: 🖼 Photos shows every image with ★ Feature / ✕ Remove / 📷 Add (keep existing). /api/images,/api/image/delete,/api/image/feature
  476. 62e3b37 2026-06-24 auto-save: 2026-06-24T18:28:52 (1 files) — data/queue.json
  477. 6a655b4 2026-06-24 Add end-to-end test for All-Shopify search + keep/replace photo paths (11/11 pass; throwaway draft, prod-clean teardown)
  478. 7e0a77d 2026-06-24 Add ✨ New (N) filter chip (just the net-new sheet SKUs to create) + fix doubled name==color titles; verified create-on-photo end-to-end (Cremona Parchment created live w/ full info + deleted)
  479. 06a420e 2026-06-24 auto-save: 2026-06-24T17:58:43 (3 files) — data/build.json public/index.html test-allshopify.js
  480. 708fac7 2026-06-24 All-Shopify cards: per-card 'Replace all — make this the only image' toggle (DTD verdict C); default keeps existing imagery, explicit opt-in to wipe
  481. 05042e0 2026-06-24 Any-SKU: include all 170 TWIL-sheet GRS items; photographing a not-yet-in-Shopify one (22 net-new, deduped by GRS+mfr) creates the product from sheet info + photo and goes live; existing-SKU updates preserve room shots (keep_images)
  482. b4532b2 2026-06-24 Add 'All Shopify' button: live store-wide SKU search to update any product's photo from phone (non-destructive — keeps existing images)
  483. a2403b9 2026-06-24 Add 'Any SKU' lookup: search all 555 Fentucci products by SKU/model#/name to add or replace any product's photo (in-memory catalog index + /api/lookup)
  484. 89c5686 2026-06-24 Fix grid density slider + editor preview-equals-export bake
  485. daf466a 2026-06-24 auto-save: 2026-06-24T16:58:22 (3 files) — public/index.html server.js data/build.json
  486. 571e941 2026-06-24 auto-save: 2026-06-24T16:28:13 (4 files) — data/queue.json ref-roll.jpg screenshot-roll.png screenshot-sheet.png
  487. 444a683 2026-06-24 Send Cache-Control: no-store on HTML so browsers never serve a stale page (was hiding the photo editor after deploy)
  488. 4b82a74 2026-06-24 Roll: add Curl intensity slider + cycle Flat→Tube→Sheet (curled-sheet variant reveals paper's cream back, like the PR roll shot)
  489. b6eb162 2026-06-24 Add 🗞 Roll button: wrap captured pattern around a tube (cylinder shading + sheen + shadow) like the PR roll shot
  490. 9e8d499 2026-06-24 auto-save: 2026-06-24T15:58:04 (2 files) — data/queue.json screenshot-editor.png
  491. dcdf1c3 2026-06-24 Add Photoshop-style photo editor (brightness/contrast/saturation/hue + color-balance wheel) with review-before-upload step
  492. ea8d5f1 2026-06-24 auto-save: 2026-06-24T15:27:54 (2 files) — public/index.html server.js
  493. 2b07e49 2026-06-24 DW Pattern Photo Capture: mobile-first (iPhone/iPad) camera worklist for 179 photo-less Fentucci patterns; snaps save locally + attach to Shopify draft (filename=DW SKU, leak-safe); basic-auth, sort+density, client-side downscale

Authors

Agents used

  • secrets-manager1
  • code-reviewer1
  • vp-engineering1

Skills used

  • /color-dots133
  • /claude90
  • /code90
  • /out19
  • /ocr16
  • /learn16
  • /batch13
  • /identify13
  • /scan-log10
  • /cam8
  • /photos8
  • /apps8
  • /back7
  • /recognize7
  • /rec7
  • /photo6
  • /extract6
  • /vendor6
  • /train6
  • /index6
  • /create-item5
  • /worktrees5
  • /saturation5
  • /captures4
  • /agent-a841f65dcd871d6ac4
  • /healthz4
  • /model4
  • /hue4
  • /contrast4
  • /name4

Creative ideas + design notes

Commits with substantial prose (≥120 chars) — the rationale behind each move.

6286a2f · 2026-09-26 · Swipe picker: Pick this one opens the theme full screen (Back / Esc / Go to the app), Open-your-pick button reopens it; fix filter wiring catching the pick button (TK-12343)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SC2DKkJkSNenmFz2Eqnvpk
28a1391 · 2026-09-26 · Swipe picker: one trackpad swipe/wheel flick = one theme (Safari skipped two); app chooser shows once per tab, not on every load (TK-12343)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SC2DKkJkSNenmFz2Eqnvpk
24bc0c3 · 2026-09-26 · Front screen: one-at-a-time swipe theme picker (Figma v1-v25 + Photoshop Kid-Simple v7-v16); capture app moves to /app (TK-12343)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SC2DKkJkSNenmFz2Eqnvpk
6e2c3f2 · 2026-09-26 · Onload chooser: Adobe Spectrum themes (Light/Dark/Darkest/Auto) + accents, smart Suggested action, full UX (TK-12346)
Themed card chooser with icons, descriptions, 1-4/Enter shortcuts, incoming-samples
badge, last-used fallback suggestion, ARIA radiogroups, reduced-motion. Tokens scoped
to #homeScreen; theme/accent persisted in localStorage.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BnDgaJLtEUJykffiozVpQF
4ace5d4 · 2026-09-26 · Add /kid-simple/ review page: Kid-Simple mockups v1-v16 + Photoshop board, behind basic-auth (TK-12344)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SC2DKkJkSNenmFz2Eqnvpk
ac13489 · 2026-09-26 · Untrack runtime build counter data/build.json and gitignore it
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017oAgztBQGK3Yw8zA83NEnJ
6e16998 · 2026-09-26 · TK-12090: add verify-only prod vision check paste script
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VizMhiDcRGXSVT356UUdHr
655426a · 2026-09-25 · TK-12268: add creds-in-URL fetch guard (fleet pattern) to gated page
Relative fetch() on a Basic-Auth page threw on user:pass@host bookmarks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7LB6rCwpA7ubJTqYzqXEX
9b15829 · 2026-09-25 · TK-12268: add creds-in-URL fetch guard (fleet pattern) to gated page
Relative fetch() on a Basic-Auth page threw on user:pass@host bookmarks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D7LB6rCwpA7ubJTqYzqXEX
7aecde5 · 2026-09-25 · Editor fits iPhone width: narrow-screen layout (wheel above sliders, Use Photo full-width, Crop/Reset/Cancel row)
html zoom 1.35 leaves ~289 CSS px on a 390px phone; sliders/values and the action row overflowed
the right edge (scrollWidth 323 > 289). Now 0 overflow, headless-verified; desktop unchanged (<=600px only).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TZynS56oLsqJTcschug1a7
69d5016 · 2026-09-25 · Front/Back tiles: tap a taken photo to adjust it in the Enhance/Crop editor; Adjust + Retake buttons below each tile (TK-12256)
Editor/crop overlay raised above the add modal (z 130) so it opens from the tiles.
Adjusted pixels replace the local shot only — nothing uploads until Create.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TZynS56oLsqJTcschug1a7
a2e8198 · 2026-09-25 · 5x sweep 5: report — sweeps converge at cap, 3 app defects fixed, env SIGTERM open
TK-12228

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017yv665HsXLibk8kGheHT1P
0e8aa0e · 2026-09-25 · 5x sweep 4: history evidence screenshot viewport-only (Firefox 32767px full-page limit)
TK-12228

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017yv665HsXLibk8kGheHT1P
bf95f56 · 2026-09-25 · 5x sweep 3: hung-camera e2e mode (all engines), WebKit stub fix, sweep aborts if server dies
TK-12228

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017yv665HsXLibk8kGheHT1P
4fd7dee · 2026-09-25 · 5x sweep 2: camera-timeout retry tap now opens the snap camera (as the toast promises)
- index.html: after the live camera times out (8s), the next Photo 1/2 tap goes to the native <input capture>
  inside the fresh tap's user activation instead of re-running a hung getUserMedia forever (pre-existing since
  TK-12124; reproduced 4/4 in WebKit with a cold mock camera). Toast names Photo 1 or Photo 2.
- e2e: asserts whichever capture path the engine takes (LIVE shutter, or timeout toast -> snap file chooser ->
  shotAdd); WARM_CAMERA=1 forces LIVE; cam.html check fails loudly if the phone camera never goes live.
- 5x/tools/sweep.sh sweep driver.

TK-12228

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017yv665HsXLibk8kGheHT1P
15beb44 · 2026-09-25 · 5x sweep 1: favicon on captures/batch/cam, consistent missing-side rule, 3-engine e2e + lazy-img scroll
- captures/batch/cam: declare <link rel=icon> (was /favicon.ico 404 console error; captures new, batch/cam pre-existing)
- /api/captures missing_back + captures.html missing()/sort/.miss: one rule — a front/back item lacking a side;
  single-shot photo-only items (remote cam) no longer inflate the count (was 5 vs real 1)
- e2e: ENGINE=chromium|webkit|firefox with per-engine fake camera; scroll lazy thumbs into view before asserting
- 5x/tools: console probe, history scroll check, index toolbar clickthrough, missing-side regression check

TK-12228

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017yv665HsXLibk8kGheHT1P
d1a0b78 · 2026-09-25 · TK-12228: every captured photo, front and back, displays in the app
- index.html: front/back tiles show the captured photo immediately; Preview shows
  both sides (and counts them, was "0 photo(s)"); Created + Update results show the
  server-stored copies; tap to enlarge; links to the new Capture History.
- server.js: create-item/photo/photos persist every photo under photos/ with its side
  in the filename (create-item now also on a failed create) and index one record per
  item in data/captures.jsonl; responses return the stored URLs. New /captures page +
  /api/captures merge that log with batch manifests and legacy vendor-log uploads.
- captures.html: history grid, front+back per card (missing side shown as a gap),
  date+time chip, sort + density slider persisted in localStorage, lightbox.
- batch.html: FRONT (PSku) + BACK (Info) thumbs side by side, front shown on capture,
  no more 8s blob revoke. cam.html: last remote shot shown on the phone.
- --test seam (DWP_TEST_DIR): rebased data/photos, Shopify/dw_unified/FM writes and
  paid OCR stubbed; scripts/e2e-front-back-display.cjs drives it (19 checks).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017yv665HsXLibk8kGheHT1P
126f917 · 2026-09-25 · Fix grainy Shopify product photos: raise server-side JPEG normalize cap+quality
TK-12224. Root cause: normalizeImage() (server.js) runs every uploaded camera
photo through ImageMagick before it's attached to the live Shopify product
(createNewItem / /api/photo / /api/photos all pipe through normB64). It was
downscaling to <=1600x1600 at quality 85 -- a SECOND, lower-quality JPEG
generation stacked on top of the client's own capture (which already caps to
2000px @ quality 0.92 in index.html/cam.html, or native-res @ 0.92 in
batch.html). On busy, high-frequency wallcovering/fabric patterns that shows
up as visible JPEG blocking/mosquito noise -- exactly the "grainy" symptom.

Fix: raise the resize cap to 3000x3000 (a no-op for size against every
client's actual output, still guards oversized/HEIC originals) and the
quality factor to 92 (matches the client's own export quality, removing the
double-compression quality loss). Auto-orient/HEIC normalization for OCR is
unchanged.

Client-side getUserMedia constraints, canvas capture sizing, and JPEG export
quality were already correct (4096x3072 ideal, videoWidth/videoHeight-sized
canvases, 0.90-0.92 export quality) from prior TK-12115/12124/12127/12128
work -- this was the one remaining lossy step, confirmed by tracing
/api/photo, /api/photos, and /api/create-item to normB64() -> normalizeImage().
67566bd · 2026-09-24 · TK-12162: mint checks vendor catalog reservations + confirms the number is free LIVE (FileMaker + Shopify)
The mint's sources are all mirrors (shopify_products last synced 09-23) and none read the
vendor scrape catalog, which pre-assigns dw_skus (tres_tintas_catalog: DWTS-900001..901506).
So a mint could hand out a reserved number, or the same number twice before a sync.

- adds vendor_registry.catalog_table reservations to the used-number set
- JS Pattern is TEXT in FileMaker (no reliable max), so the chosen number is verified free by an
  exact live FileMaker find + Shopify SKU prefix search, stepping past taken numbers (max 25);
  if a live source can't answer, the mint still returns but carries a flag
- tested read-only on prod: 901507 taken=true, 987654 taken=false, DWTT-72290 taken=true,
  Tres Tintas mint -> DWTS-901514, clear of both reserved ranges

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
d6f19b5 · 2026-09-24 · Henry sync: treat not-yet-created server archive as OK 0, not FAIL (TK-12162)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NR59q54WMPw4GdNgi2z1jM
2653995 · 2026-09-24 · Nightly additive rsync of vendor photo archive to Henry + launchd plist (TK-12162)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NR59q54WMPw4GdNgi2z1jM
0260eb6 · 2026-09-24 · Save every uploaded photo by vendor: photos/vendors/<Vendor>/ archive + index + /vendor-photos gallery + one-time backfill (TK-12162)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NR59q54WMPw4GdNgi2z1jM
07b7e8c · 2026-09-24 · deploy: exclude ops/ (Tres Tintas restore maps/scripts are local-only, not server runtime) (TK-12162)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NR59q54WMPw4GdNgi2z1jM
83caea3 · 2026-09-24 · Add 'Other apps' links (4 simplified capture concepts) to home screen + bottom of upload grid (TK-12162)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NR59q54WMPw4GdNgi2z1jM
e7a5066 · 2026-09-24 · TK-12162: auto-save only for registry vendors; case-insensitive vendor lookup; Minimal sends pattern name
Live dry-run against prod showed every simple-* save minting a PROV- sku: create-item
matched the label vendor to vendor_registry by exact, case-sensitive name, so
'YORK WALLCOVERINGS' missed 'York Wallcoverings' (DWYK-). Auto-save would have
turned that into drafts with placeholder SKUs.

- server.js findVendorReg(): exact vid/display/real name first, then a case- and
  punctuation-insensitive pass that only accepts a single hit (no guessing).
- /api/extract returns vendor_registered + the registry display name (private-label
  name wins, so the source name never reaches Shopify).
- All 4 pages auto-save only when vendor_registered; otherwise the manual confirm
  screen shows. Minimal now sends the pattern name, so its draft titles match.

Mocked E2E: auto-save fires for a registered vendor, never for an unregistered one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014WCvaA6QQCJp2LMdcXyrUD
1a2c398 · 2026-09-24 · TK-12162: pre-shot 11-slider adjust panel + auto-save on all simple-* pages
New public/js/adjust-panel.js puts all 11 CapturePipeline adjustments (exposure,
contrast, highlights, shadows, warmth, tint, saturation, vibrance, hue, sharpness,
straighten) in a bottom sheet, draws the adjusted live preview over the camera, and
bakes the same tune into whichever photo is taken - live shutter or the full-res
native photo (up to 4096px). Settings persist between shots.

Auto-save (default on, switch in the panel): once the label read returns vendor +
mfr#, the draft saves with no extra tap; otherwise the page's manual form shows as
before. Minimal keeps its existing Auto-create switch.

Pro Booth: its 3 big sliders and the panel edit the same tune; straighten was
hard-coded to 0 in its preview and bake, now honoured.

Headless E2E (exposure +60): all 4 pages brighten the saved photo (live ~83->152,
full-res 170->253 at 4032x3024), auto-save fires without a tap, and the manual
save path still works with auto-save off.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014WCvaA6QQCJp2LMdcXyrUD
4d1311b · 2026-09-24 · TK-12162: full-res native-camera capture on all simple-* pages
getUserMedia video frames are capped by the stream (~1920 wide on iPhone Safari).
New public/js/native-photo.js opens the device Camera app via
<input capture=environment> and returns the real sensor photo: a full copy (JPEG
0.92, up to 4096px long edge, so a whole 12MP shot) for create-item, and a 1600px
copy for /api/extract so the Gemini label read stays fast and cheap.

Each page gets a Full-res button feeding its existing capture flow (Pro Booth
still bakes the 3 sliders into it). Instant's shutter no longer passes the click
event into doCapture. Headless E2E: all 4 pages send 4032x3024 to create-item and
1600x1200 to extract.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014WCvaA6QQCJp2LMdcXyrUD
14e3194 · 2026-09-24 · TK-12162: capture at high res on all simple-* pages + route minimal/wizard/probooth
Wizard, Instant and Minimal now match Pro Booth: ask the camera for 4096x3072,
keep up to a 2000px long edge, JPEG 0.92 (was 1920x1080/1440, 1600px cap, 0.85).
server.js served only /simple-instant; the other three pages 404'd. One fixed
allow-list regex now serves all four.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014WCvaA6QQCJp2LMdcXyrUD
2b1d006 · 2026-09-24 · Consolidate SKU field cleanup into shared field-clean.js helper
All four simple-*.html pages now use a common cleanField(v) helper to coerce
Gemini Vision JSON string fields (which arrive as numbers or nulls) to trimmed
strings before assignment. This replaces inline String(v).trim() or no coercion
at all, preventing TypeError crashes when OCR returns unexpected types.

- Created public/js/field-clean.js with a single exported function
- Wired all four pages (minimal, wizard, probooth, instant) to load it
- Updated fillIfEmpty in probooth.html to use cleanField
- Updated simple-instant.html line 361 to use cleanField for mfr_sku
- All four pages parse correctly with helper loaded before use

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014WCvaA6QQCJp2LMdcXyrUD
10d3e40 · 2026-09-24 · TK-12162: guided wizard never strands a guest on an unexpected finishCapture error
Wrap the Use-This-Photo handler so any throw routes to the staff-handoff done
screen instead of leaving Retake/Use disabled on the review step.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014WCvaA6QQCJp2LMdcXyrUD
03f509f · 2026-09-24 · TK-12090/TK-12162: fix numeric-SKU .trim() crash + de-obfuscate deploy verifier
- simple-minimal.html, simple-wizard.html: fields.mfr_sku from Gemini's JSON
  can come back as a number, not a string; (fields.mfr_sku || '').trim()
  throws TypeError in that case, silently breaking the capture flow. Coerce
  to string first (matches the safe pattern already used in
  simple-probooth.html's fillIfEmpty).
- simple-minimal.html: surface the server's read-error message on the
  manual-entry fallback card instead of a generic string.
- STEVE-PASTE-tk12090-deploy2.sh: replace the base64-encoded inline Python
  verifier with a checked-in, readable script (scripts/verify-vision.py),
  piped over ssh stdin. The script now refuses to run with blank
  AUTH_USER/AUTH_PASS instead of silently sending an empty Basic Auth header.

Reviewed and code-reviewed; withdrew two other findings (restart-verification
alarm was moot — set -e + && already aborts on a dead /healthz; the 200ms
'timeout' in the Python verifier is actually 200 seconds, not milliseconds).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014WCvaA6QQCJp2LMdcXyrUD
a262d3e · 2026-09-24 · TK-12162 Instant Film concept: simple-instant.html (Polaroid-style single-photo capture, animation decoupled from real /api/extract upload)
Warm cream/paper theme with DW gold as accent only (deliberate departure from
the dark power-tool theme) — framed viewfinder with film-border + rounded
corners, shutter-flash, "developing" reveal on a fixed 1.25s cosmetic timer
that is fully decoupled from the real network pipeline: the /api/extract
upload fires the instant a frame is captured, before the flash/develop
animation even starts, and Save's enabled state is gated on that real
response (or a manual field edit) — never on the animation clock. Single
photo per session; front-loaded vendor + mfr# fields (both server-required)
auto-fill from OCR extraction with a manual-override always available.

Verified end-to-end locally via Playwright (fake camera device): camera live
in <400ms, extract() dispatched ~56ms after shutter tap, develop reveal fires
on schedule regardless of the real Gemini round-trip running 1.9-2.1s (longer
than the animation) — proving the UI never blocks on the real pipeline. Found
+ fixed a real bug in testing: the shutter button never re-armed after Retake.
Server.js route addition (server.js's own concurrent history under TK-12090
picked this up) is additive-only (mirrors the existing /batch pattern) and
does not touch index.html/cam.html/batch.html/desk.html or any core route.
Local exploration only — never linked from nav, never deployed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
247c9f9 · 2026-09-24 · TK-12090: report provider=null when the vision call fails
A failed exo call previously surfaced as provider:"exo" (the requested engine
name), so a broken ring looked like a successful exo call. Verified against
prod: PROVIDER exo / cost 0 / ok False while the ring had no vision instance.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019vkV6GBLJ9rN1VQ8oM8HJc
8452fcc · 2026-09-24 · TK-12090: decouple exo VLM ring from HAS_MACVISION, make it the reasoning-path default
/api/recognize and /api/identify could never reach the exo ring on Kamatera
(Linux): the ring was only wired into engine==='macvision', and
engineAvailable('macvision') is gated on HAS_MACVISION = IS_DARWIN &&
bin/ocr exists — always false on prod. VISION_URL config + /healthz were
correctly set but no route could actually consume it (confirmed live:
step-3 verify returned provider=gcv, not exo/gemini).

Adds 'exo' as its own engine, decoupled from platform: engineAvailable('exo')
= HAS_EXO (the shared exo-vision.mjs lib is present on this host), a static
config check mirroring HAS_MACVISION's own fs.existsSync pattern. Live
reachability (ring up/down, Gemini fallback, honest not_measured) stays
inside exo-vision.mjs's visionChat() where it already lived correctly.

visionJSON() now routes 'exo' to ollamaVision alongside 'macvision'. The two
reasoning-call sites (/api/identify, /api/recognize) prefer exo when
configured and no explicit {engine:...} was requested by the client -
DEFAULT_ENGINE (and /api/ocr's literal-OCR routing) is untouched, so this
never affects OCR engine selection. provider/model/cost_usd in both
responses already read the real per-call values from the lib, so a Gemini
fallback inside the ring will correctly still report provider:"gemini", not
a false "exo".

Verified: node --check passes; exo-vision.mjs confirmed present on Kamatera
prod at the real deploy path (/root/public-projects/_shared/lib/exo-vision.mjs).
Not yet deployed to prod.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019vkV6GBLJ9rN1VQ8oM8HJc
8364615 · 2026-09-24 · TK-12126: never report Gemini OCR cost for a call that errored
The live run surfaced it: server.js's /api/extract returns a hardcoded cost_usd 0.0006
even when the Gemini call failed (credits depleted), so the proof script echoed spend
that never happened. Now trusts cost_usd only when the response carries no err.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017uUWK5VKgXgemKLA9UqwMZ
d9c9612 · 2026-09-24 · TK-12126: add camera commit:true round-trip proof script (mock-tested, live path gated)
Builds scripts/camera-committrue-proof.mjs per the approved memo — proves the one
remaining unmeasured link in the camera capture pipeline (commit:true -> Shopify DRAFT
-> re-fetch -> byte/pixel-match the baked capture) that the cycle-2 CTA run stopped
short of. Mock mode ($0, no network) runs the real ImageMagick normalize step plus a
simulated Shopify re-encode and proves the comparator via --self-test (PASS on clean
data, FAILs on injected corruption, per the negative-test rule). --live is hard-gated
and was never executed here. Ledger: data/camera-committrue-proof-ledger.jsonl (now
gitignored, runtime-generated).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017uUWK5VKgXgemKLA9UqwMZ
a1b8ee3 · 2026-09-24 · Extract shared acquireCamera() helper, adopt across 5 unbounded surfaces (TK-12127)
New public/js/acquire-camera.js ports the proven TK-12124/TK-12128 semantics
(bounded 8s getUserMedia race, a per-acquirer GENERATION counter, late-arrival
hardware release, bounded 3s play() wait, optional ended/mute hooks scoped by
generation) into one reusable, script-tag-included module. The generation
counter alone is what prevents "a re-tap during a hang orphans a live stream"
— no separate re-entrancy boolean latch is needed, since a superseded older
acquire is detected and its hardware released the moment it resolves late.
The helper owns HOW a stream is acquired; every adopted surface keeps its own
existing constraint preferences (resolution/facingMode) unchanged.

ADOPTED (5 surfaces, all previously unbounded):
  - cam.html startCamera() — "Starting…" could hang forever with no honest
    retry path; a re-tap (nothing disabled #gBtn) could orphan a stream.
    Fixed message: "Camera took too long to respond" + the existing "Try
    Again" tap target (the gate's only affordance — no new UI needed). Also
    now gets the bounded play() wait cam.html never had at all.
  - batch.html startCameraInto() — same orphan-on-retap risk across its two
    call sites; boolean return contract (true/false) preserved unchanged.
  - index.html scan (startScanStream), white-balance (openWB), measure
    (openMeasure) — three more unbounded getUserMedia awaits outside the
    two-shot flow, none of which had ANY timeout at all.

DEFERRED: index.html's two-shot flow (startTsStream) is left AS-IS, not
migrated onto the shared helper. It already has this exact proven logic
inline (TK-12124/12128), the diff to swap it over would touch the most
heavily-tested code path in the app for zero functional gain, and it isn't
part of "surfaces that currently have unbounded acquires" — it was already
fixed. Its 44 existing assertions are confirmed unaffected by this change.

PREMISE NOTES:
  - cam.html's 'ended' handler and batch.html's onDead callback are ported
    verbatim into the onDead hook — cam.html's bounded-play gap was a bonus
    fix, not previously reported.
  - Line numbers in the original report (cam.html:278-290, batch.html:297-305)
    had drifted slightly from prior edits but pointed at the correct functions.

Negative-tested: a 6-case core suite against a blank fixture proves the
module itself (hang→bounded settle, late-arrival tracks STOPPED not just
dereferenced, a newer generation supersedes a hung older one, bounded
play()-timeout, mute/ended hooks correctly scoped by generation, and an
unaffected fast success path) — 20/20 pass. A second suite exercises all 5
adopted call sites directly (bounded settle, sane UI state on timeout, a
clean retry afterward) — 20/20 pass. Confirmed genuine pre-fix hangs via
git-stash on all 5 surfaces with a targeted 4s-vs-11s settle-window probe
(each hung indefinitely pre-fix, each settled within its bound post-fix).
The pre-existing 44 TK-12124/12125/12128 assertions remain green throughout.

One commit for the whole refactor rather than one per surface: the helper
module has no standalone meaning without a consumer, all 5 adoptions share
one bug class and one fix pattern, and splitting them would fragment a
single coherent change for no review benefit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY
0e42baf · 2026-09-24 · Wire ended + mute listeners on _tsTrack, scoped by generation (TK-12128)
Cody-found gap from the TK-12124 red-team pass: the two-shot flow had no
mute/ended listener on _tsTrack. On iOS, a LATER camera request elsewhere
(another app, FaceTime) can mute or end an earlier stream's track without any
getUserMedia call of ours — the preview freezes while _tsLive stays true and
the shutter would save a frozen frame.

batch.html's reference handler (line ~310) only covers 'ended'. The failure
Cody actually described is specifically a MUTE (the track never ends, it just
stops delivering frames) — wiring 'ended' alone per the literal instruction
would have left the named bug unfixed, so both events are wired here.

On either event: _tsLive resets to false, the shutter disables, a toast fires
("Camera stopped — tap Front/Back to restart"), and the stream is stopped +
cleared so a retap goes through the existing bounded acquire path cleanly.

Scoped to the CURRENT generation via the _tsStreamGen counter (from the
TK-12124 pass) plus a direct track-identity check, so an old, already-replaced
track's late event — e.g. from the .stop() call the next acquire makes on it —
can never kill a newer, genuinely-live stream.

Negative-tested: confirmed both 'ended' and 'mute' correctly reset _tsLive/
disable the shutter/toast (mute dispatched synthetically since it's exclusively
OS-triggered with no script-callable trigger; 'ended' likewise synthetic since
MediaStreamTrack.stop() does NOT fire 'ended' per spec — only an external end
does), confirmed a retap re-acquires cleanly afterward, and confirmed a STALE
old-generation track firing either event does NOT affect a newer live stream.
12/12 new assertions pass; the existing 25 TK-12124 assertions are unaffected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY
b2bd893 · 2026-09-24 · Add persistent "applies at capture, not preview" hint on the Sharpness slider (TK-12125)
The Sharpness slider does nothing visible on the live 80ms preview by design
(capture-only unsharp mask — capture-pipeline.js applies it only when
opts.capture===true, never on the preview pass). Showroom staff drag it, see
no change, and reasonably assume it's broken.

Added a small persistent (non-tooltip) caption directly under the slider in
the two-shot panel: "Applies at capture — not shown in this preview", styled
consistent with the panel's existing dim/muted caption idiom.

Also mirrored the hint in cam.html: contrary to the ticket's assumption that
"cam.html has no panel yet", it actually has a live, wired adjustment panel
(including a functionally identical Sharpness slider) whose previewTick() also
runs capture:false — the same gap exists there. Confirmed batch.html has no
sharpness slider at all (only unrelated blur/Laplacian-variance code), so it's
correctly skipped.

Verified via a real-browser (Playwright + Chrome for Testing) check: the hint
renders whenever the panel is open, doesn't overlap or shift the layout of the
next slider (Straighten), and the Sharpness range input's width is unchanged
vs its sibling sliders. Screenshot captured for evidence.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY
9f4d2c2 · 2026-09-24 · Fix 3 Cody-found holes in the getUserMedia timeout fix (TK-12124 follow-up)
Cody red-teamed ca60ce9 (verdict FIX-FIRST). Three holes, all in startTsStream()/
openTwoShotCam():

Hole 1 (most serious — same bug, one await later): `await v.play()` right after
the getUserMedia fix was itself unbounded. A track that CONNECTS but never
produces a frame (camera held by another app/FaceTime call, muted track) can
leave play() pending forever on WebKit, sticking _tsAcquiring true again —
exactly the brick ca60ce9 claimed to have fixed. Bounded play() with a 3s
Promise.race; _tsLive is now keyed off whether play() itself settled, not off
videoWidth (verified empirically that #tsVideo's own `autoplay muted` attribute
populates videoWidth via native autoplay regardless of whether this explicit
play() call ever resolves, so videoWidth can't distinguish "confirmed live"
from "still nothing" and would have been a false signal).

Hole 2: the attempts loop didn't re-check timedOut/generation at the TOP of
each iteration, only after a getUserMedia call returned — so a permission
decision arriving just after the 8s bail-out could still fire a 2nd/3rd
getUserMedia call (fresh prompt + camera light) for a caller who already moved
to the fallback. Added the guard at loop entry.

Hole 3: the timeout-path fallback auto-.click()'d #frontInput ~8-14s after the
original tap. iOS Safari (and usually Chrome past ~5s) will have already
expired the user-activation window by then, so that click would silently no-op
— the toast promised "using snap camera" and then nothing would happen. Changed
the timeout branch to ask for a fresh tap instead of auto-clicking; the fast
flat-denial branch (still well inside the activation window) keeps the
original auto-click behavior unchanged.

Negative-tested: added a 4th test case (v.play() stubbed to never resolve,
getUserMedia resolving fine) — confirmed it hangs forever against the
pre-hole-1-fix commit (killed at a 30s wall-clock timeout), and post-fix
settles within the bounded ~3s window with _tsAcquiring reset. Updated T2 into
2a/2b to separately prove the timeout branch no longer auto-clicks (hole 3) and
the fast-denial branch still does (behavior preserved). All 25 assertions pass
across the original 3 test scenarios + the 2 hole-specific splits + the new
hole-1 case.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY
ca60ce9 · 2026-09-24 · Fix: bound getUserMedia() with an 8s timeout so a hung camera prompt can't brick the shutter (TK-12124)
startTsStream() awaited getUserMedia() with no timeout. On WebKit/Safari (also a
denied/backgrounded permission prompt or an MDM camera restriction on any browser)
that promise can simply never settle, which left _tsOpening/_tsAcquiring stuck true
forever and permanently disabled the shutter + camera-flip buttons until reload.

Race each acquisition attempt against an 8s timer; on timeout, throw a distinct
camera-timeout error so the existing finally blocks reset both flags, surface a
clear toast ("Camera took too long to respond — using snap camera"), and fall
back to the native #frontInput/#backInput capture input. A late-arriving stream
that resolves after the bail-out is stopped immediately (via a generation
counter) instead of being silently adopted as an orphaned hot camera. Success
path is unchanged (verified — no delay, no timeout artifact).

Negative-tested with a real headless Chrome harness stubbing getUserMedia to
never resolve: confirmed the pre-fix code hangs forever (test had to be killed
at a 30s wall-clock timeout), and the fix resolves within the bounded window,
resets both flags, shows the toast, and falls back correctly — 17/17 assertions
pass, including an unaffected fast-path success case.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY
2a2801e · 2026-09-23 · batch.html: adopt shared capture-pipeline engine, full Photoshop set on top of gray-card calibration (TK-12090)
pipeGains() now returns ONLY the gray-card WB ratio (rGain/gGain/bGain); brightness and temp/warmth
now handled by the shared engine's exposure and temp/tint sliders.

applyPipeline() threaded with a capture:bool parameter — delegates to CapturePipeline.apply()
passing the WB gains as preGain and the auto-exposure multiplier (computeES) as exposureMul.
preview tick calls with capture:false (no unsharp); grabPhoto calls with capture:true (unsharp enabled).

tune loading uses CapturePipeline.normalizeTune() for back-compat (bright→exposure, warm→temp).

bindTune maps legacy HTML slider IDs to new tune field names. Existing 3-slider panel (exposure/temp/hue)
still wired; full 11-control extension can be added later.

The gray-card CALIBRATE workflow (enterCalib, cSave, CAL_TARGET/CAL_GRAY/CAL_REF, drawCalOverlay) is
byte-identical to before; computeES() still reads raw pixels before the engine bake.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XKaojLnVW8hyxsVriY5f9a
880e4d8 · 2026-09-23 · cam.html + desk.html: full pre-capture photoshop camera (zero→full parity) (TK-12090)
cam.html: add WYSIWYG preview canvas + WB tap-to-sample + full 11-control adjust panel
(exposure/contrast/highlights+shadows/temp+tint/saturation+vibrance/hue/sharpness) +
presets (showroom/daylight/label-closeup) + live histogram + clipping badge + hardware
applyConstraints layer. Full-res baked capture replaces raw drawImage. Tune POSTed to
/api/pair/cam-status so desktop can show readout. Preview tick at 80ms (capture:false),
full-res shutter capture at TS_MAX longest edge (capture:true, unsharp enabled).

desk.html: add readonly adjustment tune readout (preset + key slider values from phone status).
Displays live as phone adjusts (via SSE tune field in /desk/events status update).

Both files preserve existing fetch-guard + SSE pairing + shot result flows unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XKaojLnVW8hyxsVriY5f9a
af5702a · 2026-09-23 · index.html two-shot: adopt shared capture-pipeline + full adjust panel + presets + histogram (TK-12090)
Delegates the two-shot live-cam bake (tsPipeline) to window.CapturePipeline instead of the
old inline WB×brightness/saturation/hue-only bake. tsPreviewTick calls apply() with
capture:false (no unsharp mask, ~80ms budget); tsCapture calls with capture:true (unsharp
mask bakes here only) -- preview/capture parity preserved. _tsWB (tap-sample white-balance
gains) is passed as opts.preGain so it is not double-applied against the engine's own
temp/tint gains. _tsTune is now the full CapturePipeline tune shape, persisted via
CapturePipeline.loadTune/saveTune('dwTsTune') with automatic back-compat for the old
{bright,sat,hue} shape.

Extends the #tsTools panel with: a Preset <select> (Showroom / Daylight / Label close-up /
Custom, persisted as dwTsPreset -- any manual slider move flips it back to Custom), a live
histogram canvas + clipping-warning badge (updated every preview tick), and the full slider
set (Exposure, Contrast, Highlights, Shadows, Temp, Tint, Saturation, Vibrance, Hue,
Sharpness, Straighten) replacing the old 3-slider (Brightness/Saturation/Hue) set. Straighten
now feeds CapturePipeline.drawSource() in both tsPreviewTick and tsCapture in place of the
raw drawImage, so the rotation bakes identically in preview and capture. Panel body was
already max-height:46vh + overflow:auto (scrollable on phone). Native frontInput/backInput
fallback path is untouched.

TK-12115 (parent TK-12090)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY
fdff137 · 2026-09-23 · add shared capture-pipeline.js engine (full pre-capture photoshop set, manual canvas pixel math)
ONE shared engine (window.CapturePipeline) generalizing the two existing inline pipelines
(index.html tsPipeline, batch.html applyPipeline/pipeGains) and extending them to the full
Photoshop adjustment set: exposure, contrast, highlights, shadows, temp, tint, saturation,
vibrance, hue, sharpness (capture-only unsharp mask), straighten. Manual getImageData/loop/
putImageData only -- no WebGL, no ctx.filter, no CSS filters (survives toDataURL, iOS-safe).
Also ships histogram/drawHistogram, 3 starter presets, drawSource (cover-fit + straighten
bake), and a best-effort Hardware.probe/apply layer over track.applyConstraints (feature-
detected, never throws -- the software pipeline stays the source of truth for WYSIWYG).

TK-12115 (parent TK-12090)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY
94c8d60 · 2026-09-23 · server.js: bounded /js/ static route to serve the shared capture-pipeline module (TK-12090)
Raw-http server has no generic static handler; the extracted public/js/capture-pipeline.js
needs an explicit route. Mirrors the /marketing/ guard: basename-only, .js/.mjs allowlist,
path-traversal guard, no-store. Behind the existing basic-auth (authed page fetches it as a
same-origin subresource).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY
409e338 · 2026-09-23 · deploy.conf: exclude visual-search venv + CLIP weights + test dirs from rsync (1.3GB, TK-12090 Lane P follow-up)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY
95babfe · 2026-09-23 · visual-search: optional pattern-sibling stage (PATTERN_SIBLINGS=1 + body siblings:true) using dw-pairs-well colour-invariant dHash + WS-1 pattern_id, vendor+pattern_name fallback (TK-12090 Lane P)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY
6a07319 · 2026-09-23 · visual-search: product_image_fingerprints PG table + disk-guarded idempotent loader + flagged SQL-filtered PG search path (PG_FINGERPRINTS=1, default off) (TK-12090 Lane P)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY
d5f6c4a · 2026-09-23 · visual-search nightly embed: env-first DB user (PGUSER or running OS user, drop retired stevestudio2), launchd PATH for psql, fail-loud connect precheck (TK-12090 Lane P)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KXUyzc9vybUz39rhnNJdwY

File tree

288 files tracked. Click any to browse the source at HEAD.

Other build journals

← Dw Pairs Well  ·  all 4 projects  ·  Dw Pitch Followup →

Export

commits.csv · feed.atom · project.json · commits.json

rendered in 18ms