{"slug":"dw-pairs-well","total":76,"limit":100,"offset":0,"since":null,"commits":[{"hash":"2fc0641","date":"2026-07-13 12:25:58 -0700","author":"Steve Abrams","subject":"chore: lint, refactor (DRY sourceArchived + null-status guard), vpatch (session close)","body":"Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>"},{"hash":"2fd335e","date":"2026-07-13 12:25:00 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-13T12:24:56 (1 files) — server.js","body":""},{"hash":"73d4393","date":"2026-07-13 12:18:40 -0700","author":"Steve Abrams","subject":"pipe-title-backfill: apply 2 genuine-name draft rows (Dig-540050/053) + WM ghost reconcile investigation (all 4 -> ARCHIVE, 0 live candidates)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"5c2a34e","date":"2026-07-13 12:17:42 -0700","author":"Steve Abrams","subject":"similar: flag archived/non-live source with 'archived' + reason instead of a silent empty strip","body":"An empty similar strip only occurs for ARCHIVED/unpublished source SKUs (no live\nproduct page). Surfacing source.status !== ACTIVE as archived:true + a reason makes\nthat self-explaining and prevents future 'is the site broken?' scares. Purely\nadditive — active-product responses gain only archived:false, no behavior change."},{"hash":"f89ae0b","date":"2026-07-13 10:57:35 -0700","author":"Steve Abrams","subject":"add reload-visual-search.sh: resolve :9914 owner by listening port, not name substring","body":"block2's resolver matched paint-visualizer-agent (substring 'visual' in visualizer)\ninstead of the real :9914 service, so the rsynced search_service.py (new /pairwise +\nACTIVE+published load() join) was never loaded. This resolves by the bound port.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>"},{"hash":"fbc4aba","date":"2026-07-13 10:54:33 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-13T10:54:28 (1 files) — scripts/pipe-title-backfill/fm-cli.mjs","body":""},{"hash":"1f6151b","date":"2026-07-13 10:30:32 -0700","author":"Steve Abrams","subject":"fix: OSP Kamatera sync survives prevent_dw_prefix_mfr_sku guard trigger (v2 wraps UPDATE in txn w/ DISABLE TRIGGER USER; v1 left column all-NULL -> empty suggestions)","body":"Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>"},{"hash":"ae252a3","date":"2026-07-13 10:23:31 -0700","author":"Steve Abrams","subject":"pipe-title-backfill: APPLIED 23 CLEAN rows result log (PG 23/23, Shopify 19/23; 4 WM live-deleted)","body":""},{"hash":"e438fe4","date":"2026-07-13 10:15:35 -0700","author":"Steve Abrams","subject":"pipe-title-backfill: apply script for the 23 CLEAN rows (PG-first, Shopify title+mfr-metafield, 95s batch cadence)","body":""},{"hash":"da590e8","date":"2026-07-13 09:40:58 -0700","author":"Steve Abrams","subject":"chore: lint (W3/W4 script fixes), refactor (shared paint helpers, test dedup), v0.1.1 (session close)","body":""},{"hash":"6103fe5","date":"2026-07-13 08:53:52 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-13T08:53:46 (2 files) — 5x/live-sweep-2.md 5x/live-sweep-3.md","body":""},{"hash":"779cabe","date":"2026-07-13 08:23:43 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-13T08:23:39 (1 files) — 5x/live-sweep-1.md","body":""},{"hash":"bd214fc","date":"2026-07-13 02:01:55 -0700","author":"Steve Abrams","subject":"yolo contrarian fixes: freshness+rowcount+live-spot gates in fix-osp-kamatera.sh; export-osp-flags.sh writes provenance .meta; block2-clip-flip.sh with hard PASS/ABORT prompt, link-check precondition, validated pm2 target (no guessing); 12/12 empirical flag-vs-live verification OK","body":""},{"hash":"73efede","date":"2026-07-13 01:56:05 -0700","author":"Steve Abrams","subject":"deps: bump qs to 6.15.3 via npm audit fix (GHSA-q8mj-m7cp-5q26 moderate DoS)","body":"Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>"},{"hash":"6145281","date":"2026-07-13 01:36:28 -0700","author":"Steve Abrams","subject":"deploy/fix-osp-kamatera.sh — sync online_store_published flags Mac2→Kamatera (closes the last live leak class: ACTIVE-but-unpublished suggestions); flags TSV gitignored","body":""},{"hash":"82d7d3a","date":"2026-07-13 01:29:32 -0700","author":"Steve Abrams","subject":"SIMILAR_CLIP_DEFAULT one-switch flag; KAMATERA-GOLIVE.md paste bundle (discovery: Kamatera already hosts visual-search in dwphoto — no tailnet needed)","body":""},{"hash":"2805347","date":"2026-07-13 01:25:12 -0700","author":"Steve Abrams","subject":"5x: final report — sweep 5 clean at cap","body":""},{"hash":"0d36db3","date":"2026-07-13 01:24:06 -0700","author":"Steve Abrams","subject":"5x sweep 5: color+texture lock in clipSimilarTop (CLIP cosine × hex ΔE gate, cosine+color re-rank, backfill never blanks); PUB_SQL boot probe so a mirror without online_store_published degrades loudly instead of 500ing; clickthrough re-expand + designed-404 tolerance","body":""},{"hash":"f2f2ae6","date":"2026-07-13 01:20:05 -0700","author":"Steve Abrams","subject":"5x sweep 4 (contrarian FIX FIRST): no-store on all product-link-carrying responses — link guarantee now enforced at serve time; clickthrough gains real terminal assertions + unknown-SKU error-state coverage","body":""},{"hash":"5a3ae69","date":"2026-07-13 01:17:04 -0700","author":"Steve Abrams","subject":"5x sweeps 2-3 clean (2 consecutive) — REPORT.md; stop condition met","body":""},{"hash":"8b2123a","date":"2026-07-13 01:15:32 -0700","author":"Steve Abrams","subject":"5x sweep 1: pairs-well-specific clickthrough (shared 3x clickthrough is hardcoded for the curator UI); sweep-1 ledger","body":""},{"hash":"263b80d","date":"2026-07-13 01:05:32 -0700","author":"Steve Abrams","subject":"audit: pipe-title backfill generator for malformed '| Vendor' ACTIVE titles (54 found, 23 clean / 31 draft) — draft only, no live writes","body":""},{"hash":"7fcb7a9","date":"2026-07-13 00:52:49 -0700","author":"Steve Abrams","subject":"CLIP-3: hard link guarantee — every suggested SKU must be ACTIVE + online_store_published (all 5 suggestion queries + clipSimilarTop verified-row gate, 2x over-fetch); tools/live-link-check.sh audits suggested links against the live store","body":""},{"hash":"79e1c62","date":"2026-07-13 00:51:47 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-13T00:51:43 (1 files) — tools/live-link-check.sh","body":""},{"hash":"b2207f5","date":"2026-07-13 00:04:18 -0700","author":"Steve Abrams","subject":"pairs: trip CLIP circuit-breaker on 5xx (service alive but erroring), not just on timeout/refused; 404 stays a per-sku miss","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"ce3fda2","date":"2026-07-13 00:00:40 -0700","author":"Steve Abrams","subject":"pairs: PAIRS_CLIP_DEFAULT env flag (default OFF) blends CLIP for all callers; add circuit-breaker + 1.5s timeout on visual-search so an unreachable service never hangs customer requests","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"f189739","date":"2026-07-12 23:51:28 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-12T23:51:20 (1 files) — server.js","body":""},{"hash":"399cce5","date":"2026-07-12 23:21:16 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-12T23:21:12 (1 files) — server.js","body":""},{"hash":"52301ea","date":"2026-07-12 23:05:46 -0700","author":"Steve Abrams","subject":"CLIP-1: /api/similar?engine=clip — image-embedding nearest-neighbour via visual-search service, graceful fallback to tag engine (opt-in, non-breaking)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"76a8e98","date":"2026-07-12 23:03:12 -0700","author":"Steve Abrams","subject":"Design Coordinate: guard degenerate pattern labels (no more '| Vendor' tiles)","body":"Products with malformed titles ('| Osborne & Little Europe', '| DW Bespoke\nStudios') rendered the VENDOR as the pattern name on grouped tiles + colorways.\nbestPatternLabel() detects empty/pipe-led/vendor-only labels and falls back to\nhumanized handle -> mfr_root -> dw_sku, recovering real names from descriptive\nhandles. Display-only; group keys unchanged. Healthy titles pass through as-is.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"d53de9e","date":"2026-07-07 08:56:39 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-07T08:56:34 (1 files) — tools/pattern-id-write.jsonl","body":""},{"hash":"e22bffc","date":"2026-06-27 11:04:05 -0700","author":"Steve Abrams","subject":"Design Coordinate: loadSource falls back dw_sku -> handle (fix theme MFR-sku-as-dw_sku breakage)","body":""},{"hash":"13c4dfe","date":"2026-06-26 13:03:37 -0700","author":"Steve Abrams","subject":"auto-save: 2026-06-26T13:03:32 (3 files) — tools/ci-hash-build.py tools/_active-for-ci.tsv tools/_multi-images.tsv","body":""},{"hash":"671721d","date":"2026-06-26 12:47:32 -0700","author":"Steve","subject":"WS-1: server.js AUTH_PID prefers title-first pattern_id map (fallback to old mfr-first)","body":""},{"hash":"6476f17","date":"2026-06-26 12:46:35 -0700","author":"Steve","subject":"WS-1: set pattern_id image-confirm threshold to 30 (Yakatore+La Corka fully merge, over-merge flat 42); point write.js at title-first map","body":""},{"hash":"11cab42","date":"2026-06-26 11:50:39 -0700","author":"Steve","subject":"WS-1: title-first + color-invariant image-confirm pattern_id derivation (dry-run + hasher + analyzer)","body":"Per /dtd 3/3 verdict A: derive grouping key title-first (normalized title primary,\nmfr-root fallback), image-confirm within title groups via color-invariant dHash+inverse\nso same-pattern-diff-color colorways merge and different designs sharing a title split.\nDry-run shows over-merge 1250->41, under-merge halved. server.js groupKeyForRow now\nconsults the authoritative per-dwsku map first. Re-backfill stays gated."},{"hash":"84cafc2","date":"2026-06-26 11:45:32 -0700","author":"Steve Abrams","subject":"auto-save: 2026-06-26T11:45:25 (1 files) — tools/pattern-id-titlefirst-dryrun.py","body":""},{"hash":"e22b966","date":"2026-06-26 11:15:19 -0700","author":"Steve Abrams","subject":"auto-save: 2026-06-26T11:15:12 (1 files) — server.js","body":""},{"hash":"fc5135e","date":"2026-06-26 10:53:18 -0700","author":"Steve","subject":"collection-grouped feed: emit color/style facets (only populated filter values) so the grid UI never shows a dead filter tab","body":""},{"hash":"2d70921","date":"2026-06-26 10:31:57 -0700","author":"Steve","subject":"Design Coordinate v7: 6+6 cards, rename AI→Auto Generated (no AI wording), compact CTA/headings; fix /api/ai-coordinates to honor ?limit","body":""},{"hash":"adf33a8","date":"2026-06-26 10:14:55 -0700","author":"Steve Abrams","subject":"auto-save: 2026-06-26T10:14:48 (5 files) — tools/pattern-id-backfill-report.json tools/pattern-id-backfill.js tools/pattern-id-by-dwsku.json tools/pattern-id-write.js tools/pattern-id-write.jsonl","body":""},{"hash":"0802d86","date":"2026-06-26 09:44:39 -0700","author":"Steve Abrams","subject":"auto-save: 2026-06-26T09:44:31 (1 files) — tools/pattern-id-backfill.js","body":""},{"hash":"9454dbf","date":"2026-06-26 09:14:23 -0700","author":"Steve Abrams","subject":"auto-save: 2026-06-26T09:14:14 (4 files) — tools/pattern-id-backfill-report.json tools/mfr-by-dwsku.json tools/mfr-by-handle.json tools/mfr-map.jsonl","body":""},{"hash":"12d6677","date":"2026-06-26 09:12:47 -0700","author":"Steve","subject":"WS-1: junk-root denylist (SANCAR/INNOVATIONS/TRUE/placeholders → title fallback) + bulk mfr_sku pull tool","body":""},{"hash":"de4b0bc","date":"2026-06-26 08:13:51 -0700","author":"Steve Abrams","subject":"auto-save: 2026-06-26T08:13:39 (3 files) — server.js tools/grouped-chips-view.png tools/pattern-page-fixed.png","body":""},{"hash":"0fa1972","date":"2026-06-26 07:43:34 -0700","author":"Steve Abrams","subject":"auto-save: 2026-06-26T07:43:29 (2 files) — tools/grouped-preview-designers-guild.png tools/pattern-page-preview.png","body":""},{"hash":"af1d385","date":"2026-06-26 07:29:54 -0700","author":"Steve","subject":"collection-grouped feed: vendor-FAMILY scope (catches all brand spellings) + collection_handle param","body":""},{"hash":"99f1752","date":"2026-06-26 07:24:30 -0700","author":"Steve","subject":"collection-grouped: real sort (hue/style/colorways/az) in feed + show toolbar on load + Hue/Style options","body":""},{"hash":"901bbdd","date":"2026-06-26 00:13:54 -0700","author":"Steve Abrams","subject":"WS-3: /api/colorways + /api/collection-grouped (interim T2 grouping key, prod pattern_id ready)","body":""},{"hash":"90dbcaf","date":"2026-06-25 23:58:33 -0700","author":"Steve Abrams","subject":"Add pattern-id-backfill dry-run (Option-A hybrid) + texture-vision stub","body":"- tools/pattern-id-backfill.js: DRY-RUN-ONLY pattern_id computer.\n  mfr_root primary (input map or --use-mirror-mfr) -> T2 title fallback ->\n  pattern_name last resort. Texture-aware bucketing: skip image gate only for\n  texture+mfr_root non-huge groups; texture T2/huge -> local-vision; non-texture\n  -> dHash. --apply is a GATED no-op stub (writes nothing).\n- tools/pattern-texture-vision-stub.py: design-only Ollama qwen2.5vl helper ($0).\n- Finding: mirror mfr_sku column is polluted (SANCAR/TRUE junk roots) -> validates\n  DTD that the authoritative source is the gated custom.manufacturer_sku metafield."},{"hash":"c76eef6","date":"2026-06-25 23:38:08 -0700","author":"Steve Abrams","subject":"auto-save: 2026-06-25T23:37:59 (1 files) — tools/","body":""},{"hash":"5e32b37","date":"2026-06-25 23:29:11 -0700","author":"Steve","subject":"Add /api/similar (visually-similar designs) + similar-designs.liquid","body":"Forks the pairs-well scorer with inverted motif sign (reward sameness): new\nscoreSimilar() in lib/classify.js (+5 motif, +3 material/era/color, hard-excludes\nsame pattern). New loadSimilarCandidates() anchors the pool on the source's own\nmotif/material tags; pickSimilar() dedupes by pattern (no colorway floods). New\nGET /api/similar?dw_sku|handle endpoint. Frontend similar-designs.liquid mirrors\ndesign-coordinate with its own namespace + density slider.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"ffc4b86","date":"2026-06-15 07:57:56 -0700","author":"Steve Abrams","subject":"Add idempotent fleet-wide fix-all-stale dw_admin password repair script (dry-run default, tests candidate pw before any write/restart)","body":""},{"hash":"6d446b9","date":"2026-05-31 16:32:30 -0700","author":"Steve Abrams","subject":"Add per-site favicon (kills /favicon.ico 404)","body":""},{"hash":"95606ac","date":"2026-05-30 23:53:12 -0700","author":"Steve Abrams","subject":"harden .gitignore: add backup/temp file patterns to prevent source leaks in public/","body":"Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>"},{"hash":"fbbb236","date":"2026-05-20 01:21:31 -0700","author":"Steve Abrams","subject":"dw-pairs-well: scrub real-looking DB password from tracked .env.example","body":"DATABASE_URL had a credential 'DW2024SecurePass' baked into the tracked\n.env.example — this is the shared DW dev-DB credential used fleet-wide\n(per security punch-list Tier 2 #11). Replaced literal with CHANGE_ME\nplaceholder so the tracked file no longer broadcasts the password to\nanyone who clones the repo.\n\nReal .env (untracked, gitignored) on Mac2 + Kamatera keeps the working\nvalue. If this password is still actively used in prod, rotate it as\npart of the broader DW DB credential rotation tracked in\n~/Projects/_yolo-security-punchlist-2026-05-20.md."},{"hash":"5f8d1eb","date":"2026-05-18 20:26:31 -0700","author":"Steve Abrams","subject":"gitignore: exclude logs/ directory (server logs, watcher logs, debug pngs)","body":""},{"hash":"cd6aed7","date":"2026-05-18 20:26:31 -0700","author":"Steve Abrams","subject":"package.json: dev script uses correct port 9813 (was 9799)","body":""},{"hash":"386eea8","date":"2026-05-13 15:46:17 -0700","author":"Steve","subject":"preview.html: surface attempted key in fetch-failure UI + esc innerHTML","body":""},{"hash":"56de022","date":"2026-05-13 13:35:33 -0700","author":"Steve Abrams","subject":"ai-coordinates: rebuild generator — 24 real seamless patterns (3 width tiers × multiple styles + plaids), lightest+darkest required, ?tile_in slider, /render endpoint for editor","body":""},{"hash":"c7d0bfc","date":"2026-05-13 12:43:42 -0700","author":"Steve Abrams","subject":"CORS_ORIGIN: add wallco.ai (+ www variants, local dev) — wallco.ai design-detail page calls pairs.designerwallcoverings.com with ?palette=#hex,..., but allowlist only included designerwallcoverings.com so the browser blocked the response and the catch handler rendered 'Could not load coordinates right now.' / 'AI generator not ready.' for both panels","body":""},{"hash":"fb9ee05","date":"2026-05-13 12:17:14 -0700","author":"Steve","subject":"preview.html: gate default DWRW-74991 init on window.__deepLinkLoaded — fixes race where ?handle=izara… deep-link loaded correctly then got clobbered by the trailing default loadSource (caught via chrome-devtools MCP repro 2026-05-13; verified by reload showing only 2 fetches both for the Izara handle, color story renders SW/DE/BM/F&B paint matches)","body":""},{"hash":"d7926be","date":"2026-05-13 12:04:30 -0700","author":"Steve Abrams","subject":"pairs/coordinate: accept ?palette=#hex,#hex,... for external sources (wallco.ai design pages)","body":""},{"hash":"c54aef9","date":"2026-05-13 11:14:51 -0700","author":"Steve","subject":"preview.html: accept handle (auto-detect vs dw_sku), deep-link via ?handle=/?sku=/?key=, surface real .catch errors, add Izara repro buttons — dev surface to diagnose the 2026-05-13 Shopify-side render failure without touching the live theme","body":""},{"hash":"a19993c","date":"2026-05-13 10:55:48 -0700","author":"Steve","subject":"design-coordinate: surface real error in .catch (was 'Could not load' / 'AI not ready' blackbox; now shows error.message inline + console.error with attempted URL — diagnostic for the Izara render failure on prod 2026-05-13)","body":""},{"hash":"c323508","date":"2026-05-13 10:12:34 -0700","author":"Steve Abrams","subject":"server: GET / redirects to /preview.html","body":""},{"hash":"675669d","date":"2026-05-13 10:08:07 -0700","author":"Steve Abrams","subject":"preview: relative API paths so prod-served page can fetch (was hardcoded localhost:9813)","body":""},{"hash":"c417ba8","date":"2026-05-13 10:07:06 -0700","author":"Steve Abrams","subject":"preview + snippet: hide raw hex codes (color story = paint names only)","body":""},{"hash":"567375b","date":"2026-05-13 09:54:15 -0700","author":"Steve Abrams","subject":"v6 paste-in snippet refreshed to match Liquid block","body":""},{"hash":"1d2c3f3","date":"2026-05-13 09:43:46 -0700","author":"Steve Abrams","subject":"v6: all 7 paint brands + paste-in snippet for Shopify theme","body":"- /api/pairs response now includes sw, de, bm, behr, ppg, fb, ral matches per hex\n- preview.html: vendor-picker chips (default SW+DE+BM+F&B), localStorage persist, re-renders grid + source-palette table on toggle\n- color_reference query batches all 7 brands in one call\n- deploy/shopify/design-coordinate.liquid: standalone paste-in snippet\n- deploy/shopify/PASTE-INTO-THEME.md: 3-min manual install guide (current token lacks write_themes scope, same gap as existing read_customers)"},{"hash":"a3a416a","date":"2026-05-13 09:34:02 -0700","author":"Steve Abrams","subject":"Design Coordinate v5: graceful fallback for sources without Gemini palette","body":"Test results — 6/6 source SKUs return 24 coordinates (was 5/6).\nDWKK-101067 (Brunschwig, no hex data) now produces 'Coordinating stripe • Shared color: green' matches via the tag classifier instead of zeroing out.\n\nBehavior unchanged for sources with palette data (4 SKUs tested with palette → palette-based 'Picks up: black, white, ochre, brown' chips); the fallback only activates when the source has no hex enrichment (~9% of catalog)."},{"hash":"d2062b0","date":"2026-05-13 09:17:06 -0700","author":"Steve Abrams","subject":"Design Coordinate v4: density slider 3-12 (default 8), 24 catalog + 24 AI","body":"- /api/pairs returns up to 24 cards (capped), enforces palette overlap ≥ 1 picked-up color\n- /api/ai-coordinates returns 24 stripe/plaid posters built from source palette (SVG data-URLs, ready to swap for wallco-ai PNG urls)\n- preview.html: density slider 3-12 default 8 with localStorage persist per section\n- separate Catalog vs AI sections, each with its own slider\n- vendor cap 6/24, motif cap 16/24 so plaids still surface"},{"hash":"95a5934","date":"2026-05-13 09:11:09 -0700","author":"Steve Abrams","subject":"Design Coordinate v3: stripe/plaid/check filter + palette-vs-palette ΔE scoring","body":"- Hard motif filter on candidates (stripe/plaid/check/tartan/gingham/ticking)\n- For each source palette color, find best ΔE2000 in candidate palette\n- 'Picks up: ochre, navy, cream' explanation per card\n- Vendor cap 2/6, motif cap 4/6 so plaids + stripes both surface"},{"hash":"72fbd05","date":"2026-05-13 09:07:22 -0700","author":"Steve Abrams","subject":"Design Coordinate v2: palette + SW/DE paint match per product+pair","body":""},{"hash":"776b365","date":"2026-05-13 08:36:15 -0700","author":"Steve Abrams","subject":"deploy bundle: kamatera-bootstrap.sh + .deploy.conf + README","body":""},{"hash":"1d3d2f3","date":"2026-05-13 08:27:15 -0700","author":"Steve Abrams","subject":"initial scaffold: Pairs Well With This Design service (Express :9813 + algorithm + skill)","body":""}]}