{"slug":"abrams-report","total":34,"limit":100,"offset":0,"since":null,"commits":[{"hash":"6e271f4","date":"2026-08-30 19:45:43 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-30T19:40:35 (1 data files) — data/headlines.db","body":""},{"hash":"be42851","date":"2026-08-30 07:20:29 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-30T07:15:22 (1 data files) — data/headlines.db","body":""},{"hash":"40e75c5","date":"2026-08-29 07:20:47 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-29T07:15:37 (1 data files) — data/headlines.db","body":""},{"hash":"4572c46","date":"2026-08-28 13:26:20 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-28T13:21:26 (1 data files) — data/headlines.db","body":""},{"hash":"181c9a2","date":"2026-08-27 19:29:42 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-27T19:24:37 (1 data files) — data/headlines.db","body":""},{"hash":"6b0790d","date":"2026-08-27 07:47:30 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-27T07:42:31 (1 data files) — data/headlines.db","body":""},{"hash":"17dce3e","date":"2026-08-26 13:30:56 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-26T13:25:11 (1 data files) — data/headlines.db","body":""},{"hash":"e701050","date":"2026-08-25 19:34:45 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-25T19:29:44 (1 data files) — data/headlines.db","body":""},{"hash":"9ce77bc","date":"2026-08-25 07:44:33 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-25T07:39:06 (1 data files) — data/headlines.db","body":""},{"hash":"fd60f49","date":"2026-08-24 13:29:22 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-24T13:25:50 (1 data files) — data/headlines.db","body":""},{"hash":"02eac81","date":"2026-08-23 13:21:58 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-23T13:21:43 (1 data files) — data/headlines.db","body":""},{"hash":"6d5d044","date":"2026-08-22 19:18:27 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-22T19:18:13 (1 data files) — data/headlines.db","body":""},{"hash":"b8a2d67","date":"2026-08-22 07:37:00 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-22T07:36:43 (1 data files) — data/headlines.db","body":""},{"hash":"f82e973","date":"2026-08-21 07:42:21 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-21T07:42:04 (1 data files) — data/headlines.db","body":""},{"hash":"2ab3935","date":"2026-08-20 13:35:01 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-20T13:34:43 (1 data files) — data/headlines.db","body":""},{"hash":"285efec","date":"2026-08-19 23:18:02 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-19T23:16:54 (1 data files) — data/headlines.db","body":""},{"hash":"64f926f","date":"2026-08-19 13:28:09 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-19T13:27:48 (1 data files) — data/headlines.db","body":""},{"hash":"cd8475f","date":"2026-08-18 19:20:11 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-18T19:20:00 (1 data files) — data/headlines.db","body":""},{"hash":"a58d942","date":"2026-08-18 12:21:23 -0700","author":"Steve Abrams","subject":"abrams-report: add scheduled scrape cron (3x/day, local $0)","body":"TK-10655 (Steve: 'run on cron to keep current'). abrams-report had no scheduler\n(hadn't scraped since May). Adds scripts/run-scrape.sh + LaunchAgent\ncom.steve.abrams-report-scrape (07:15/13:15/19:15 daily, headless, ProcessType\nBackground). RSS + all HTML + Schumacher refresh at $0 via local Chrome; Wallquest\n(CF-hard) needs a headed manual 'npm run scrape' — documented in the wrapper.\nPlist mirrored under deploy/launchd/ for reinstall. Scrape logs gitignored.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"4127e9b","date":"2026-08-18 12:03:14 -0700","author":"Steve Abrams","subject":"abrams-report: rescrape — refresh headlines (300 new, all-local $0)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"e85230b","date":"2026-08-18 12:03:13 -0700","author":"Steve Abrams","subject":"abrams-report: bump better-sqlite3 9.4.3 -> 13.0.3 for node v26 support","body":"The pinned ^9.4.3 had no prebuilt binary for node v26 (ABI 147) and its source\nwon't compile against node 26's V8 API — so the DB write step was broken (app\nhadn't scraped since May). 13.0.3 ships a node-26 prebuilt; loads instantly,\nsame Database API (no app-code change). Full scrape now runs end-to-end: 300\nheadlines written, $0 (local Chrome for the 2 anti-bot sources). Completes the\nTK-10655 reroute (fetch path was already proven; this unblocks the write path).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"4c1bd95","date":"2026-08-18 11:41:33 -0700","author":"Steve Abrams","subject":"abrams-report: reroute anti-bot scrapes off Browserbase to local real Chrome ($0)","body":"TK-10655 (Steve-approved): the 2 Cloudflare-protected sources (Schumacher blog,\nWallquest sitemap) went through paid Browserbase (~$46.80 all-time, the #1 spend\nline). Replace with scrapers/fetch-local-browser.js — Playwright driving the\ninstalled Google Chrome via a persistent profile (residential IP + real-Chrome\nfingerprint clears CF's managed challenge where headless/datacenter is bounced).\nRaw XML captured from page.goto().text() before Chrome's viewer transforms it.\nVerified live: Schumacher -> 13 blog links, Wallquest -> 394 sitemap URLs, $0.\nDeleted fetch-browserbase.js + dropped @browserbasehq/sdk dep (now unused).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"4cc35d4","date":"2026-07-30 15:49:24 -0700","author":"Steve Abrams","subject":"auto-save: 2026-07-30T15:49:17 (1 files) — data/headlines.db","body":""},{"hash":"5fc761c","date":"2026-05-31 16:32:22 -0700","author":"Steve Abrams","subject":"Add per-site favicon (kills /favicon.ico 404)","body":""},{"hash":"a0688b4","date":"2026-05-19 17:21:23 -0700","author":"Steve Abrams","subject":"chore(refactor): broaden .gitignore for snapshot files + add .bak/.pre 404 guard middleware","body":"- .gitignore now excludes *.bak, *.bak.*, *.pre-*, *.orig, *.rej, *~, .next/\n  so accidental snapshot files never enter the tree.\n- New Express middleware (before express.static) returns 404 for any path\n  matching .bak / .pre- / .orig / .rej / trailing-tilde patterns, so even if\n  a snapshot file slips into public/ it can't serve.\n\nNo behavior change for normal traffic.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"},{"hash":"92af6d6","date":"2026-05-19 11:35:43 -0700","author":"Steve","subject":"snapshot — gitify backup 2026-05-19","body":""},{"hash":"a92bf0f","date":"2026-05-13 12:14:24 -0700","author":"Steve Abrams","subject":"snapshot: backup uncommitted work (1 files)","body":""},{"hash":"712af18","date":"2026-05-13 08:57:45 -0700","author":"Steve","subject":"snapshot: 1 file(s) changed, ~1 modified","body":""},{"hash":"782921d","date":"2026-05-12 16:46:24 -0700","author":"Steve","subject":"fetch-browserbase: log session-minutes to cost-tracker via shared helper","body":""},{"hash":"7257efe","date":"2026-05-11 20:52:16 -0700","author":"Steve Abrams","subject":"fix(schumacher): route through Browserbase","body":"CloudFront 403s data-center IPs (Kamatera prod) but allows residential\n(Mac2). Force Browserbase so the scheduled scrape works on Kamatera."},{"hash":"2e118fb","date":"2026-05-11 20:49:02 -0700","author":"Steve Abrams","subject":"fix(fetch-browserbase): prefer project-local .env over home-dir paths","body":"abrams-report's own .env (written by secrets-manager) is the canonical\nlocation on both Mac2 and Kamatera. Move it to the front of the\ncandidate list so a per-project key rotation propagates immediately\ninstead of being shadowed by an older skill .env on Mac2 or /root/.env\non Kamatera."},{"hash":"20113db","date":"2026-05-11 20:41:02 -0700","author":"Steve Abrams","subject":"deps(wallpaper): add @browserbasehq/sdk + playwright-core for Wallquest scrape","body":"Wallquest is behind Cloudflare bot protection; only path to scrape its\nsitemap is via Browserbase's residential-IP Chromium cluster. Adding\nthe SDK + playwright-core as direct deps so 'npm install --omit=dev'\non Kamatera pulls them in. fetch-browserbase.js falls back to loading\nfrom ~/.claude/skills/browserbase/node_modules on Mac2 when these are\nabsent, so this dep addition is additive, not a hard requirement on\nthe dev box."},{"hash":"42ab728","date":"2026-05-11 20:38:16 -0700","author":"Steve Abrams","subject":"fix(wallpaper-watch): rewrite all 10 wallpaper-house scrapers","body":"Each source now yields 3-6 real headlines per run. Changes:\n\n- Schumacher: switched fschumacher.com/search to schumacher.com/blog\n  (parent brand publishes a real editorial blog; selector 'h3 a').\n- Thibaut: news/blog paths all 404, switched to /sitemaps/collections.xml\n  with sitemap parser (lastmod = newest collection drop).\n- Phillip Jeffries: /news redirects to /shop; switched to blog subdomain\n  blog.phillipjeffries.com with 'h2 a' selector.\n- Scalamandre: /news page literally says 'No news!'; switched to flat\n  sitemap.xml filtered to /brands/.+/.+\\.html collection pages, sorted\n  by lastmod (newest collection updates).\n- Maya Romanoff: kept /news/ URL but tightened selector to 'h2 a' and\n  link filter to /news/<slug>/ (was matching every nav link).\n- Arte International: switched from /en/collections to /en/stories with\n  selector a[href*=/stories/] and slug filter (rejects ?category= nav).\n- Brewster: /new-arrivals 404s; switched to /blog with 'h3 a' selector\n  and a host-anchored slug filter.\n- York: tightened to a[href*=/blog/] + excludeFilter for tag/month/rss\n  (was matching navigation tag clouds).\n- Wallquest: blocked by Cloudflare bot challenge AND publishes nothing\n  to /news or /blog. Routed through Browserbase, fetching sitemap.xml\n  via the same-origin fetch (page.evaluate) to bypass Chrome's XML\n  pretty-print wrapper; filtered slugs to human-readable collection\n  names (≥1 dash, no SKU codes).\n- Cole & Son: /en/news redirects to homepage; switched to\n  sitemap_blogs_1.xml, parse <image:title> as headline.\n\nInfrastructure:\n- New scrapers/fetch-browserbase.js for cloud-Chromium fetches; loads\n  creds from ~/.claude/skills/browserbase/.env, /root/.env, or process.\n  When URL contains 'sitemap' or '.xml', uses page.evaluate(fetch) to\n  return raw XML (not Chrome's wrapper HTML).\n- scrape-html.js: real Chrome UA (was scraper bot UA — many sites\n  403/404 a bot), redirect: 'follow', new parsers for 'sitemap' and\n  'sitemap-index', new 'excludeFilter' for rejecting category/tag/etc,\n  cap of 6 headlines per source (per copyright-safety brief)."},{"hash":"035396a","date":"2026-05-11 15:59:44 -0700","author":"Steve Abrams","subject":"initial scaffold: Drudge-style design industry news aggregator","body":""}]}