{"$schema":"https://ejfox.com/schema/page-twin@1.json","kind":"github","url":"https://ejfox.com/github/devtools","json_url":"https://ejfox.com/github/devtools.json","generator":"ejfox.com/json-twin@1","data":{"stats":{"totalRepos":213,"totalContributions":1214,"followers":127,"following":58},"contributions":[],"dates":[],"detail":{"commits":[{"repository":{"name":"website2","url":"https://github.com/ejfox/website2"},"message":"Merge pull request #92 from ejfox/feat/verify-page\n\n/verify: identity proofs and accounts in one place","occurredAt":"2026-10-12T06:30:43Z","url":"https://github.com/ejfox/website2/commit/440a59a80a499b9769d4a43f8f82d4f3736d9b96","type":"other"},{"repository":{"name":"website2","url":"https://github.com/ejfox/website2"},"message":"Merge pull request #95 from ejfox/feat/markdown-twins\n\nMarkdown copies of posts at /blog/<slug>.md","occurredAt":"2026-10-12T06:11:25Z","url":"https://github.com/ejfox/website2/commit/1741f3411a78515403a92b8213d6afe115b93c73","type":"other"},{"repository":{"name":"website2","url":"https://github.com/ejfox/website2"},"message":"Merge remote-tracking branch 'origin/main' into feat/markdown-twins\n\n# Conflicts:\n#\tpages/blog/[...slug].vue","occurredAt":"2026-10-12T06:05:43Z","url":"https://github.com/ejfox/website2/commit/9d1adc330d7ec1938533771b48271f0612d1c25f","type":"other"},{"repository":{"name":"website2","url":"https://github.com/ejfox/website2"},"message":"Merge pull request #94 from ejfox/feat/belief-changelog\n\nPredictions: belief changelog timeline","occurredAt":"2026-10-12T06:01:45Z","url":"https://github.com/ejfox/website2/commit/930248b9a611af23143ac19ab5f43f3a97678a8b","type":"other"},{"repository":{"name":"website2","url":"https://github.com/ejfox/website2"},"message":"Belief timeline: 30-char labels so the Apple row clears its percentage\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-12T05:56:52Z","url":"https://github.com/ejfox/website2/commit/62c2ca7224309cc8fb96ae8aa54fa49ff4d38619","type":"other"},{"repository":{"name":"website2","url":"https://github.com/ejfox/website2"},"message":"Markdown copies: dated posts only, and advertise on the crowned page\n\nLimit .md to <year>/<slug>, the shape isValidPost calls a blog post, so\nweek notes, robots and other processed JSON get no copy. The page link\nchecks the same shape. The Peter Todd crowned page replaces the generic\npost page, so it now advertises its own copy.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-12T05:53:10Z","url":"https://github.com/ejfox/website2/commit/635c14339a6f204c960d7334f788941a4d12dcdc","type":"other"},{"repository":{"name":"website2","url":"https://github.com/ejfox/website2"},"message":"Changelog: fit the content column, shorter row labels\n\nAt 900px the chart clipped past 2029 inside the ~768px column.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-12T05:50:44Z","url":"https://github.com/ejfox/website2/commit/f87d21a2d7b138222ac23628c8eceb2952cd9567","type":"other"},{"repository":{"name":"website2","url":"https://github.com/ejfox/website2"},"message":"Merge pull request #93 from ejfox/feat/standard-site\n\nStandard.site: verify publication + documents; Content-Signal","occurredAt":"2026-10-12T05:48:53Z","url":"https://github.com/ejfox/website2/commit/479bacd7b7cc5892114628d397ae7bff729c5f1a","type":"other"},{"repository":{"name":"website2","url":"https://github.com/ejfox/website2"},"message":"Merge pull request #91 from ejfox/feat/scraps-feed\n\nScraps: RSS feed at /scraps-rss.xml","occurredAt":"2026-10-12T05:43:54Z","url":"https://github.com/ejfox/website2/commit/c65d87c4f06607275f2b6c5cee3624c933dc5070","type":"other"},{"repository":{"name":"website2","url":"https://github.com/ejfox/website2"},"message":"Markdown copies of posts at /blog/<slug>.md\n\nAI tools cite more accurately from markdown than from rendered HTML.\n/blog/<year>/<slug>.md serves the post as markdown, converted from the\nprocessed HTML (rehype-remark), never from content/blog source. The\nfrontmatter is a four-key whitelist: title, date, tags, canonical.\n\nThe gate is stricter than the HTML page's: it reuses isHiddenFromListings\nand isScheduled, so draft, hidden, unlisted, password, passwordHash,\nsealed and scheduled posts all 404, in dev too. private/ slugs 404 before\nany lookup. Post pages advertise the copy with rel=alternate\ntype=text/markdown, but only when it would serve.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-12T05:42:59Z","url":"https://github.com/ejfox/website2/commit/c232e1ebfa038abc6112da89118befeab261d616","type":"other"},{"repository":{"name":"website2","url":"https://github.com/ejfox/website2"},"message":"Predictions: belief changelog timeline\n\nOne row per prediction, signed → deadline, with each logged confidence\nupdate (◆ 25→80 / held 80) and the resolution (✓/✗). The number at left\nis the confidence when signed — updates[0].confidenceBefore — so the\nMamdani row reads 25%, not the 80% it was moved to.\n\nPlain computed SVG; row logic in utils/beliefTimeline.ts with tests.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-12T05:41:41Z","url":"https://github.com/ejfox/website2/commit/02975634d3568fdd2a981c6575aef5d216afb9c5","type":"other"},{"repository":{"name":"website2","url":"https://github.com/ejfox/website2"},"message":"Standard.site: verify publication + documents; Content-Signal\n\nServe /.well-known/site.standard.publication (bare AT-URI, text/plain) and\nput <link rel=\"site.standard.document\" href=\"at://...\"> on every mirrored\npost, gated by the mirror's own eligibility predicate. PUB_RKEY moves into\nutils/atprotoRkey.mjs (value unchanged; the mirror's dry run is\nbyte-identical before and after). robots.txt gains a Content-Signal line.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-12T05:39:25Z","url":"https://github.com/ejfox/website2/commit/e396cc376f7b831cdf99f1b5fa204a579d5b479e","type":"other"},{"repository":{"name":"website2","url":"https://github.com/ejfox/website2"},"message":"/verify: identity proofs and accounts in one place\n\nPGP fingerprint + key dates, key sources (pgp.txt, WKD, keys.openpgp.org),\nrel=\"me\" accounts (GitHub, Mastodon, Bluesky with DID, Keybase, email) and\nthe domain's proof files. Sidebar PGP line now links here; footer and\nsitemap list it next to /tips.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-12T05:38:32Z","url":"https://github.com/ejfox/website2/commit/082a6788fe5bdc439ee09b5d3ccb60a2cb772c3f","type":"other"},{"repository":{"name":"website2","url":"https://github.com/ejfox/website2"},"message":"Scraps: RSS feed at /scraps-rss.xml\n\nLatest 100 shared scraps, newest first. Reads /api/scraps so the feed\nexposes exactly what /scraps shows and rides its 1h cache (no extra\nSupabase egress). Untitled bookmarks fall back to the URL hostname;\nguid is the scrap id. Discoverable via <link rel=alternate> on /scraps,\nan rss link in its header, /sitemap and llms.txt.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-12T05:37:41Z","url":"https://github.com/ejfox/website2/commit/9ca2d16c098638b1e178bbdeba4a7f7a98287763","type":"other"},{"repository":{"name":"website2","url":"https://github.com/ejfox/website2"},"message":"Merge pull request #90 from ejfox/fix/umami-prod-only\n\nUmami: count only ejfox.com, never the bookmarklet popup","occurredAt":"2026-10-12T05:03:36Z","url":"https://github.com/ejfox/website2/commit/2e31bd355992917112a483493a3183dba7f27af9","type":"other"},{"repository":{"name":"dotfiles","url":"https://github.com/ejfox/dotfiles"},"message":"fix(computah): respect paperize GPU leases; self-heal FLUX otherwise\n\n- sd-server start refuses while ~/code/paperize/gpulease holds the card (leases <6h;\n  --force overrides). Covers every revive path: ask's restore, game-over, self-heal.\n  EJ: paperize/CRT renders beat the image wall.\n- muse-loop idles while leased (like blender-only) instead of a hiccup per cell\n- muse-loop restarts sd-server (2 min backoff) when it's down and FLUX is meant to run\n  (it crashed mid-request and stayed dead ~45 min)\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T19:11:11Z","url":"https://github.com/ejfox/dotfiles/commit/65da7f7756d130d37970b1413d8e365ac5171b7a","type":"fix"},{"repository":{"name":"dotfiles","url":"https://github.com/ejfox/dotfiles"},"message":"feat(muse): FLUX steering experiment arms (refs, best-of-N, FK particles) with random-pick controls\n\nbin/muse-steer rolls three independent factors per wall cell and logs them under\nthe trace's \"arms\": 0-2 reference images from EJ's stars (klein multi-ref via\nsd-server extra_images), best-of-N (extra seeds after the normal render) and\nFK-style particles (K x0 predictions at ~25% of the cell's own sigma schedule,\nwinner continued by img2img + custom_sigmas tail). Each picker is the judge\n(taste-judge, else probe-v0, else placeholder) or a same-compute random control.\nimagine gains IMAGINE_REF_LOCALS + IMAGINE_SDCPP_EXTRA. MUSE_EXP_OFF=1 restores\nthe old behavior incl. the legacy ref roll. computah/exp-report.py joins arms with\nstars/downs/pairs/inspects (Wilson CIs, power note, GPU cost); taste-export.py\nwrites a LoRA/DPO-ready dataset on the PC.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T18:18:48Z","url":"https://github.com/ejfox/dotfiles/commit/c35eff53c7f1699abcf578c8d5db77f6dabf6dea","type":"feat"},{"repository":{"name":"dotfiles","url":"https://github.com/ejfox/dotfiles"},"message":"preview-server: un-star also removes the piece from 417am.party (Unpost-417)\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T18:11:29Z","url":"https://github.com/ejfox/dotfiles/commit/b5b9f31eb5e333ae5a08a0c49425c044e1242459","type":"other"},{"repository":{"name":"dotfiles","url":"https://github.com/ejfox/dotfiles"},"message":"feat(computah): log-only early-preview scoring for wall cells\n\nimagine watches its own sd-server progress (seed-matched in sd-server.log via\n:7861), grabs the TAE preview.png at ~25% of sampled steps (min 4), and scores\nearly + final frames (contrast, edge density, occupancy, EJ-taste v1, early->final\ncomposition corr). muse-loop folds it into the cell trace under \"early\" plus\np_like_early/p_like_final (null until a taste-judge exists) and archives\nmuse-<id>-early.png. Changes nothing about which image wins; the multi-seed\nbranching plan (2-phase POST, no sd-server kill) lives in the code comment.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T18:09:36Z","url":"https://github.com/ejfox/dotfiles/commit/55f58e5676e114fab946dd1d28bfcb79a6243f7a","type":"feat"},{"repository":{"name":"dotfiles","url":"https://github.com/ejfox/dotfiles"},"message":"feat(taste): taste judge (validated preference model + score CLI) and why-note rubric scaffold\n\n- taste_judge.py: labels (stars, downs, pairs, inspects), seen-exposure background,\n  out-of-fold eval (random, by-day, temporal forward) vs baselines, reproduces the\n  existing probe's LOO; ships judge-vN.npz with metrics and a ready gate\n  (min(by-day, temporal) AUC >= 0.65). judge-v1: by-day 0.74, temporal 0.60, not ready.\n- score CLI / Judge import: p_like, pct, logit, maxsim_to_wall, pick (diversity penalty)\n- taste-embed.py: embed-studio mode (Blender pieces), generic resumable embed, utf-8 stdout\n- taste-rubric.py: ViPer-style why-note -> liked/disliked attribute rubric (claude -p or\n  already-running Qwen), fixture-guarded; fixtures/why-notes-example.jsonl is fabricated\n- taste-judge-train.sh: pull inputs, retrain, ship to computah\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T18:06:54Z","url":"https://github.com/ejfox/dotfiles/commit/3278a6c5804270d9673674856255132bb5da5921","type":"feat"},{"repository":{"name":"dotfiles","url":"https://github.com/ejfox/dotfiles"},"message":"feat(wall): ~10 pair picks a day incl. studio, say-why, studio taste events\n\n- Pair picks: server-paced (pairstate/pairmark → taste/pair-state.json), one offer\n  every 60-90 min, max 12/day, shared by every open wall; skip backs off\n  1.5h/3h/6h/12h, a pick resets it. Only while EJ is present (Mac HID idle < 10 min\n  via taste/sys.json, or pointer moved on the page), page visible, nothing open;\n  unanswered after 8 min it goes away. Sides can be FLUX cells or studio pieces\n  (flux-flux / mixed / studio-studio); the pair follows a studio piece when new\n  pieces shift the slots. Marker = black frame + white dashes (the old white\n  dashed outline vanished on white 1-bit pieces).\n- pair event keeps win/lose, adds win_kind, lose_kind, ms (offer → pick).\n- Say-why: optional one-line field after a star, down or pair pick; Enter saves,\n  Esc drops it, left alone it closes itself (keeps typed text). type=why with\n  id, kind, verdict (star|down|pair), text (+ lose, lose_kind for pairs).\n  Text is decoded as UTF-8 from the raw URL.\n- Studio pieces: inspect, fav (alongside studiofav) and a new not-for-me all log\n  events with kind=studio; downs copy to renders\\downvotes\\studio; studiodownlist.\n- kind=flux added to flux inspect/down events.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T17:51:21Z","url":"https://github.com/ejfox/dotfiles/commit/7670bc99b128045be6382ea4168e4da195e33de5","type":"feat"},{"repository":{"name":"dotfiles","url":"https://github.com/ejfox/dotfiles"},"message":"feat(computah): computah screenshot grabs the real Windows desktop to ~/screenshots/computah + clipboard\n\nSaved in a subfolder so the Cloudinary watcher on ~/screenshots doesn't publish it;\n--up opts into the upload.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T17:40:40Z","url":"https://github.com/ejfox/dotfiles/commit/c6ea7916abea1b13c3f184a24ff1008f7a272810","type":"feat"},{"repository":{"name":"dotfiles","url":"https://github.com/ejfox/dotfiles"},"message":"fix(computah): studio-seed strength 0.60-0.78 (0.58 echoed the dither, >=0.8 ignored the seed)\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T17:26:28Z","url":"https://github.com/ejfox/dotfiles/commit/6a39eaafb3cb9b547befdaf5fff9f9a0bbda9157","type":"fix"},{"repository":{"name":"dotfiles","url":"https://github.com/ejfox/dotfiles"},"message":"feat(computah): obs start/rec/stop/status; studio pieces seed 60% of FLUX cells\n\n- computah obs drives C:\\dev\\computah\\bin\\obs-ctl.ps1; OBS is off by default\n  (idling at ~35% GPU 3D it tripped the wall's game guard for ~2 days)\n- MUSE_STUDIO_PCT 10 -> 60, MUSE_STUDIO_FAV_PCT 25 from studio favorites,\n  newest-weighted picks, full-res seed, strength 0.55-0.85, trace studio_piece\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T17:12:00Z","url":"https://github.com/ejfox/dotfiles/commit/08f493d17f26b386a8b3ae2352c1bbb0b094470b","type":"feat"},{"repository":{"name":"dotfiles","url":"https://github.com/ejfox/dotfiles"},"message":"feat(wall): 1:1 pixel view, close buttons, no scrollbars, motion pass\n\n- click the inspect image (or shift-click a cell) for a true 1:1 view:\n  natural size / devicePixelRatio, drag to pan, esc peels one layer\n- x close on the card and the 1:1 view; scrollbars hidden except in 1:1\n- card sizes to the image instead of 44% of 1120px; studio raw+evidence side by side\n- View Transitions morph cell -> card -> 1:1 and back, staggered meta rise,\n  FLIP glide on reshuffles, crossfade on new renders; off under reduced motion\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T17:11:59Z","url":"https://github.com/ejfox/dotfiles/commit/1c85c9a359aadc75d5f444da18fb86980be0a0be","type":"feat"},{"repository":{"name":"dotfiles","url":"https://github.com/ejfox/dotfiles"},"message":"feat(bin): owner-login opens owner-gated VPS apps with the 1-year cookie\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-05T19:49:46Z","url":"https://github.com/ejfox/dotfiles/commit/55caf2d5d9804aa02b3b995a5185e17dfdfc25f0","type":"feat"},{"repository":{"name":"dotfiles","url":"https://github.com/ejfox/dotfiles"},"message":"feat(canary): canary CLI for honeypot document beacons + cheatsheet\n\ncanary new/list/hits/mute/retire/docx. Mints unguessable tokens in\nvps:/smallweb-db/honeypot/canary.db over ssh (parameterized, script on stdin);\nopening a planted file trips honeypot /c/<id> → critical anomalywatch alert.\nCheatsheet also gains the owner-login section from the same session.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-05T19:48:49Z","url":"https://github.com/ejfox/dotfiles/commit/717701fd21d5c47540873f46bcb15dd855280fc9","type":"feat"},{"repository":{"name":"dotfiles","url":"https://github.com/ejfox/dotfiles"},"message":"feat(wall): show each studio piece's raw (pre-dither) render in the inspect card\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-05T18:59:15Z","url":"https://github.com/ejfox/dotfiles/commit/90215aedc1e19f56c438890b54bdf2750c1473af","type":"feat"},{"repository":{"name":"dotfiles","url":"https://github.com/ejfox/dotfiles"},"message":"feat: studio-turntable (360 turntable video of any studio piece, rendered on computah)\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-05T17:50:55Z","url":"https://github.com/ejfox/dotfiles/commit/27453870ebb4855bd8197f8989be4b3de78d3bc4","type":"feat"},{"repository":{"name":"dotfiles","url":"https://github.com/ejfox/dotfiles"},"message":"feat(bin): kuma-push heartbeats for things-bridge, cipher-daily, mac-backup\n\nkuma-push <token> [up|down] [msg] reports to Uptime Kuma push monitors at\nstatus.tools.ejfox.com; never fails the caller. Each job pings only after\nreal success, so a silent failure shows up as a missed heartbeat.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-05T17:50:00Z","url":"https://github.com/ejfox/dotfiles/commit/b8f097d570a904ceb9ae21fa1cd3678d7ea32fef","type":"feat"},{"repository":{"name":"room302studio","url":"https://github.com/room302studio/room302studio"},"message":"Merge pull request #53 from room302studio/feat/umami-replay\n\nUmami 3.4: session replay + heatmaps, Web Vitals, behavior events","occurredAt":"2026-10-06T21:15:27Z","url":"https://github.com/room302studio/room302studio/commit/f3ccd42ce8af81d68aa9df2ebe3a865e072ae9ec","type":"other"},{"repository":{"name":"room302studio","url":"https://github.com/room302studio/room302studio"},"message":"Umami 3.4: session replay + heatmaps, Web Vitals, umami-plus behavior events\n\n- recorder.js: heatmaps + session replay, STRICT masking (all text and inputs hidden;\n  forms, email and password fields blocked); sampling configured inside Umami\n- tracker pinned to ?v=3.4.0 (Cloudflare edge still caches the pre-3.4 script, which\n  lacks data-performance/getSession) + data-performance (Web Vitals)\n- umami-plus: scroll depth, engaged time, copy length, 404s; outbound + mailto stay\n  with plugins/umami-funnel.client.ts so nothing double-counts\n- CSP: allow https://umami-plus.tools.ejfox.com in script-src\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T18:38:55Z","url":"https://github.com/room302studio/room302studio/commit/80ae8ef02c249388ef88670d97d9e4e209293094","type":"other"},{"repository":{"name":"room302studio","url":"https://github.com/room302studio/room302studio"},"message":"Merge pull request #52 from room302studio/fix/contact-worker-hardening\n\nContact worker: bot-bypass fix + first test suite","occurredAt":"2026-10-06T17:25:18Z","url":"https://github.com/room302studio/room302studio/commit/a4404735c68d9daff9f7eb09f55a6baa1113ca22","type":"other"},{"repository":{"name":"room302studio","url":"https://github.com/room302studio/room302studio"},"message":"Contact worker: close the no-timer bot bypass, 400 on non-object JSON, add tests\n\nA post without elapsed_ms skipped the too-fast check (NaN < 3000 is false);\nthe site's form always sends it, so only bots posting directly are affected.\nA JSON body of null crashed with a 500. New local test suite (wrangler dev\n--local, throwaway D1, simulated mail to a .invalid address): 10 tests,\nwhich fail on the old code exactly where these bugs were.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T17:25:13Z","url":"https://github.com/room302studio/room302studio/commit/49f43a1904c73531c252b8da55b4724ba13a8201","type":"other"},{"repository":{"name":"room302studio","url":"https://github.com/room302studio/room302studio"},"message":"Merge pull request #51 from room302studio/fix-light-mode-grey\n\nFix light mode: whole page was faded to 18% opacity","occurredAt":"2026-10-05T17:11:44Z","url":"https://github.com/room302studio/room302studio/commit/c5d7c9577b7201c27b69452f70765d11eec0750f","type":"other"},{"repository":{"name":"room302studio","url":"https://github.com/room302studio/room302studio"},"message":"Fix light mode: the whole page was faded to 18% opacity\n\n`:global(:root.light) .hero-bg video { opacity: .18 }` in scoped CSS:\nVue drops everything after a :global(...), so it compiled to\n`:root.light { opacity: .18 }` and greyed out the entire site for anyone\nin light mode. Put the whole selector inside :global(), and invert the\nclip in light mode so it reads as a pale texture instead of a grey smudge.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-05T17:11:32Z","url":"https://github.com/room302studio/room302studio/commit/85dd3ef60f3eaa254114b08953ede078fbc6e402","type":"other"},{"repository":{"name":"room302studio","url":"https://github.com/room302studio/room302studio"},"message":"Merge pull request #50 from room302studio/lead-fallback-room302\n\nContact leads: fall back to ejfox@room302.studio","occurredAt":"2026-10-05T16:40:45Z","url":"https://github.com/room302studio/room302studio/commit/cedb21fc32fe0d17eafa51bd69b76589f60733d5","type":"other"},{"repository":{"name":"room302studio","url":"https://github.com/room302studio/room302studio"},"message":"Contact leads: fall back to ejfox@room302.studio until studio@ verifies\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-05T16:40:34Z","url":"https://github.com/room302studio/room302studio/commit/728c36d94c376b0a509583aafc1a1089778160e2","type":"other"},{"repository":{"name":"room302studio","url":"https://github.com/room302studio/room302studio"},"message":"Merge pull request #49 from room302studio/lead-recipients\n\nContact leads → studio@room302.studio","occurredAt":"2026-10-05T16:37:02Z","url":"https://github.com/room302studio/room302studio/commit/cc3519f2396ced8f4b4eaecac6c64c147fa65784","type":"other"},{"repository":{"name":"room302studio","url":"https://github.com/room302studio/room302studio"},"message":"Contact leads go to studio@ (Google group); ejfox+artie is a fallback\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-05T16:36:51Z","url":"https://github.com/room302studio/room302studio/commit/f255b61f1d8e5b6a7edb3b4527be5f066f97906b","type":"other"},{"repository":{"name":"room302studio","url":"https://github.com/room302studio/room302studio"},"message":"Merge pull request #48 from room302studio/contact-from-room302\n\nContact email: send from contact@mail.room302.studio","occurredAt":"2026-10-05T16:33:30Z","url":"https://github.com/room302studio/room302studio/commit/73e9a96cd897779d72ab23fa14bf4718dda630fd","type":"other"},{"repository":{"name":"room302studio","url":"https://github.com/room302studio/room302studio"},"message":"Contact email: send from contact@mail.room302.studio\n\nEmail Routing is now enabled on the mail.room302.studio subdomain only;\nthe apex MX stays on Google Workspace.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-05T16:33:20Z","url":"https://github.com/room302studio/room302studio/commit/acef8043169e8bf92878c4ce62e21f47a629a7f5","type":"other"},{"repository":{"name":"room302studio","url":"https://github.com/room302studio/room302studio"},"message":"Merge pull request #47 from room302studio/contact-form\n\nContact form backed by a Worker + D1","occurredAt":"2026-10-05T16:28:20Z","url":"https://github.com/room302studio/room302studio/commit/c088ff271c981e393c1862316d42ad4012fae2ca","type":"other"},{"repository":{"name":"room302studio","url":"https://github.com/room302studio/room302studio"},"message":"Contact email: send as \"Room 302 Studio\", subject \"New inquiry: <name>\"\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-05T16:27:56Z","url":"https://github.com/room302studio/room302studio/commit/db6531f6225de7c3de64a021c95a3f902f4b7de5","type":"other"},{"repository":{"name":"room302studio","url":"https://github.com/room302studio/room302studio"},"message":"Add a contact form backed by a Worker + D1\n\nThe site's only conversion was a mailto: link, which does nothing for\nwebmail users and tells us nothing about who reached out or why.\n\n- pages/contact.vue: name / email / \"What are you working on?\" / \"How did\n  you hear about us?\" form; the email address stays as a fallback.\n  Fires a form-submit Umami event on success.\n- contact-worker/: room302-contact Worker. Saves every lead to D1 first,\n  then emails LEAD_EMAILS via Email Routing with Reply-To set to the\n  sender. Honeypot, 3s minimum fill time, 5/hour per (hashed) IP, CORS\n  locked to room302.studio.\n- umami-funnel plugin: records the visit's first page (with utm_ params)\n  and referrer in sessionStorage so each lead carries its source.\n- CSP: allow the Worker origin in connect-src.\n\nSends from room302@vestibulequarterly.com for now: room302.studio's\napex MX is Google Workspace, so Email Routing can't be enabled there.\nSwitch FROM_ADDRESS once a subdomain (e.g. notify.room302.studio) has it.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-05T16:22:32Z","url":"https://github.com/room302studio/room302studio/commit/6315c5c514dec25c06fad910eabecf9b2c9dfe5d","type":"other"},{"repository":{"name":"vestibule-quarterly","url":"https://github.com/ejfox/vestibule-quarterly"},"message":"umami: self-hosted cookieless stats on both pages\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-03T18:38:44Z","url":"https://github.com/ejfox/vestibule-quarterly/commit/fbd4c7dbe5ff3676626ba5d2533fd5349eb70919","type":"other"},{"repository":{"name":"vestibule-quarterly","url":"https://github.com/ejfox/vestibule-quarterly"},"message":"Hotline: only publish messages with audio in R2; constant-time sig check; bodyless POSTs get 403 not 500\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-02T04:18:22Z","url":"https://github.com/ejfox/vestibule-quarterly/commit/b499734bbc3b03409fe343e306b806abb506c07a","type":"other"},{"repository":{"name":"vestibule-quarterly","url":"https://github.com/ejfox/vestibule-quarterly"},"message":"Hotline README: archive, approve links, R2, dead-letter alerts\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-02T04:09:40Z","url":"https://github.com/ejfox/vestibule-quarterly/commit/43331a45b29cb73c7588d34351a109a578f203e9","type":"other"},{"repository":{"name":"vestibule-quarterly","url":"https://github.com/ejfox/vestibule-quarterly"},"message":"Hotline: secret phone archive (*777), editor approve links, R2 copy, failure alerts\n\n- greeting listens for ARCHIVE_CODE; approved messages play newest first\n- each email links a signed approve page (POST to publish, so scanners can't)\n- every recording copied to R2; audio served only once approved\n- dead-letter queue emails the editors when a message fails every retry\n- email failures now retry (they were swallowed); whisper vad_filter\n- greeting fades out, twilio's beep follows\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-02T04:09:22Z","url":"https://github.com/ejfox/vestibule-quarterly/commit/0b1157870a4f0092dd1fa9140b5f02ef4a7475b3","type":"other"},{"repository":{"name":"vestibule-quarterly","url":"https://github.com/ejfox/vestibule-quarterly"},"message":"Hotline: 30s silence timeout (twilio's 5s default hung up on people)\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-02T02:16:06Z","url":"https://github.com/ejfox/vestibule-quarterly/commit/7791afe311c5ca86beb4b45b0accf7d32e5007fd","type":"other"},{"repository":{"name":"vestibule-quarterly","url":"https://github.com/ejfox/vestibule-quarterly"},"message":"Footer: add the hotline number\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-02T02:15:13Z","url":"https://github.com/ejfox/vestibule-quarterly/commit/ad630762b95c031415991f239093b2a55910ede5","type":"other"},{"repository":{"name":"vestibule-quarterly","url":"https://github.com/ejfox/vestibule-quarterly"},"message":"Hotline: drop the url key; only mail recordings fetched from our own account\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-02T01:45:23Z","url":"https://github.com/ejfox/vestibule-quarterly/commit/26f429e50e9d59ddfcd0dd7222a4abfb55815968","type":"other"},{"repository":{"name":"vestibule-quarterly","url":"https://github.com/ejfox/vestibule-quarterly"},"message":"Hotline: api-key auth via url key, Puck greeting that trips out into the beep\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-02T01:26:07Z","url":"https://github.com/ejfox/vestibule-quarterly/commit/88067fa2a2812740ad1b4d3c5d11125b91fb699a","type":"other"},{"repository":{"name":"vestibule-quarterly","url":"https://github.com/ejfox/vestibule-quarterly"},"message":"Add the hotline: Twilio voicemail → Worker → email (+ optional Discord)\n\nTwilio-signed webhooks, queue consumer downloads the mp3, Whisper\ntranscribes, Email Routing mails it with the audio attached, D1 logs it.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-01T19:38:34Z","url":"https://github.com/ejfox/vestibule-quarterly/commit/16ee74349808c317e538d30250ad340da3a1e6d1","type":"other"},{"repository":{"name":"vestibule-quarterly","url":"https://github.com/ejfox/vestibule-quarterly"},"message":"Add agent handoff notes (AGENTS.md, CLAUDE.md imports it)\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-25T04:29:11Z","url":"https://github.com/ejfox/vestibule-quarterly/commit/fce6d3bc6aa73c5bb481a55946555c6d0b1b0c08","type":"other"},{"repository":{"name":"vestibule-quarterly","url":"https://github.com/ejfox/vestibule-quarterly"},"message":"README: match the site as it is (D1 forms, art, deploy + cache gotchas)\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-25T04:26:21Z","url":"https://github.com/ejfox/vestibule-quarterly/commit/f0660d55f5d56eb875d0b6c19e0c94477a280f4d","type":"other"},{"repository":{"name":"vestibule-quarterly","url":"https://github.com/ejfox/vestibule-quarterly"},"message":"Chains are curated by us, not a submitter mechanic\n\n- drop the Respond button + its preselect JS, the Chain form option,\n  and the 'responding to another piece?' placeholder\n- chains blurb: you send your piece, we do the stitching\n- 'Open chain № 001' → 'A prompt, if you want one'; tickers say Prompt:\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-25T04:17:55Z","url":"https://github.com/ejfox/vestibule-quarterly/commit/d19a4f2842d146f8921e4c0661057a3c309945e5","type":"other"},{"repository":{"name":"vestibule-quarterly","url":"https://github.com/ejfox/vestibule-quarterly"},"message":"Open chain № 001: LLMs and writing code\n\n- Issue One gets an \"open chain\" ticket: \"Who's holding the pen?\" with a\n  Respond link that preselects Chain in the form and seeds the pitch\n- chains blurb names talking heads / screen recordings / terminals;\n  a 60-second short counts toward length\n- ticker on both pages advertises the open chain\n- bump ?v= on style.css and submit-form.js\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-25T04:16:23Z","url":"https://github.com/ejfox/vestibule-quarterly/commit/2f8632bf0fea3ee1b5da5f7e5597ce9546043349","type":"other"},{"repository":{"name":"vestibule-quarterly","url":"https://github.com/ejfox/vestibule-quarterly"},"message":"Make video + chains of responses explicit on both pages\n\nFrom community feedback (text/video discourse that builds on itself):\n- submissions: fifth kind \"Chains\" (Grandville engraving, Met CC0\n  DP887660, cleaned to ink-on-white at 240/384/576), a \"written, filmed,\n  or both\" note under What we publish, video in Form + Length particulars,\n  \"Chain\" form option, video in the link label, \"responding to another\n  piece? say which\" in the pitch placeholder, ticker + og descriptions\n- home: lede names video and chains; ticker adds \"Text or video\"\n- bump style.css ?v= (zone Browser Cache TTL still overrides _headers)\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-25T04:06:14Z","url":"https://github.com/ejfox/vestibule-quarterly/commit/3c87f607a0286fc41c4ca96e57f816af28bfe1e7","type":"other"},{"repository":{"name":"vestibule-quarterly","url":"https://github.com/ejfox/vestibule-quarterly"},"message":"Stop serving stale CSS: no-cache CSS/JS, version-stamp the stylesheet\n\nPages' default max-age=14400 let browsers pair fresh HTML with a\n4-hour-old style.css after a deploy.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-25T03:55:59Z","url":"https://github.com/ejfox/vestibule-quarterly/commit/66d7ec1e0d54204b0984a74bddb03a0f3a71e07d","type":"other"},{"repository":{"name":"coachartie2","url":"https://github.com/room302studio/coachartie2"},"message":"Read Supabase service key from env, not a hardcoded literal (#103)\n\nscripts/migrate-from-supabase.ts carried a service_role JWT for the old\nSupabase project in a public repo. The project's keys are being rotated;\nthis removes the literal from HEAD (history still has it).\n\nCo-authored-by: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-07T18:13:57Z","url":"https://github.com/room302studio/coachartie2/commit/3b8414451715004be3437b2bdce124e39b9399de","type":"other"},{"repository":{"name":"coachartie2","url":"https://github.com/room302studio/coachartie2"},"message":"Merge pull request #101 from room302studio/fix-brokey-commands\n\nFix /memory, /models and /debug capabilities (dead BRAIN_URL)","occurredAt":"2026-09-30T00:31:06Z","url":"https://github.com/room302studio/coachartie2/commit/cf048fc09e056849120db647ab42e5c69a3dadaa","type":"other"},{"repository":{"name":"coachartie2","url":"https://github.com/room302studio/coachartie2"},"message":"Fix /memory, /models and /debug capabilities (dead BRAIN_URL)\n\nAll three called BRAIN_URL, whose default (localhost:18239) never had a listener, so\nthey failed for everyone.\n\n- /memory reads the caller's own rows straight from the shared DB\n  (services/user-memories.ts). Every query filters user_id in SQL, so no path can return\n  someone else's memory. Search is FTS5 (quoted terms, so injection-safe) with a LIKE\n  fallback. Stats now parse tags as the JSON arrays they are (were split on commas).\n- /models points at capabilities /api/models, the shape it always expected.\n- /debug capabilities checks capabilities /capabilities (free: up + registry size).\n  It used to POST a \"2+2\" chat, which once pointed anywhere real would have run a paid\n  model reply on every /debug.\n\nTests: user isolation (a matching memory of another user is never returned), FTS\nsyntax in queries, recent ordering, stats with JSON tags.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-30T00:31:00Z","url":"https://github.com/room302studio/coachartie2/commit/c3a67636c02290866840ac90fac705435621dd6f","type":"other"},{"repository":{"name":"coachartie2","url":"https://github.com/room302studio/coachartie2"},"message":"Merge pull request #100 from room302studio/privacy-slash-commands\n\nSlash command privacy: no cross-server or public-repo forum sync, own errors only","occurredAt":"2026-09-30T00:23:05Z","url":"https://github.com/room302studio/coachartie2/commit/86e20ba5782a83f2865b4c3604b013fefdb9000e","type":"other"},{"repository":{"name":"coachartie2","url":"https://github.com/room302studio/coachartie2"},"message":"Slash command privacy: no cross-server or public-repo forum sync, own errors only\n\nAudit of every global slash command for memory/PII exposure (EJ, 2026-09-29).\n\n- /sync-discussions copies forum threads (Discord usernames + full message text) into\n  GitHub issues:\n  - The forum must be in the server the command runs in. Any channel id was accepted,\n    so one server's managers could copy the other server's forum out.\n  - The target repo must be private. A public repo publishes people's messages to the\n    internet.\n- /debug errors: only the caller's own events. System events with no user attached\n  can carry other people's content or raw provider error bodies.\n\nChecked and fine as-is: /memory, /status, /usage (caller's own data, private replies;\nthe brain memory API also requires auth), /bot-status, /models (aggregates only),\n/quiz (cards from the public flashcard deck), /pairing (owner only, private),\n/watch-repo, /unwatch-repo, /list-watches (repo names only).\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-30T00:23:00Z","url":"https://github.com/room302studio/coachartie2/commit/10341bd621fadf76c164a4afd096407729f916a4","type":"other"},{"repository":{"name":"coachartie2","url":"https://github.com/room302studio/coachartie2"},"message":"register-commands: exit explicitly (imported commands keep DB handles open)\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-29T23:43:36Z","url":"https://github.com/room302studio/coachartie2/commit/11aefe06f19bdde670b689ca94d412ba5f579a8c","type":"other"},{"repository":{"name":"coachartie2","url":"https://github.com/room302studio/coachartie2"},"message":"Merge pull request #99 from room302studio/fix-slash-commands\n\nFix slash commands: one registry, working GitHub watch management, /pairing","occurredAt":"2026-09-29T23:41:38Z","url":"https://github.com/room302studio/coachartie2/commit/fbf1735b2b78a3b1d082ffb764f993b4b28ec779","type":"other"},{"repository":{"name":"coachartie2","url":"https://github.com/room302studio/coachartie2"},"message":"Fix slash commands: one registry, working GitHub watch management, /pairing\n\nThe live global command set had drifted from the code. Discord offered /link-phone,\n/verify-phone and /unlink-phone, whose handlers were gone, while /quiz, /watch-repo,\n/unwatch-repo and /list-watches worked but were never registered.\n\n- commands/registry.ts is the single list: the interaction handler routes from it and\n  register-commands.ts publishes it. The script prints the diff against Discord first\n  and supports --dry-run.\n- GitHub watches (services/github-watches.ts, direct DB instead of the poller instance):\n  - /unwatch-repo pauses (is_active = 0) instead of deleting. Deleted org repos were\n    silently re-added by the org watcher on its next sync.\n  - Watches are matched per repo per server, not only in the channel you run the\n    command from (unwatching from anywhere but #robot did nothing).\n  - No more reporting success when nothing changed: the poller-not-initialized path\n    swallowed the error.\n  - /watch-repo creates, or updates in place: change events, move channel, resume.\n    It now accepts every event the poller supports (issues and push were rejected).\n  - Repo autocomplete on watch/unwatch; the handler now routes autocomplete.\n  - /list-watches shows active vs paused, target channel and events. Channel mentions\n    in embed field names never rendered.\n- /pairing (owner only, works in DMs with Artie): list / approve / deny / allow /\n  revoke for the DM gate. The phone alert for a new request now points at it\n  instead of a chat line that runs a full model turn.\n- /sync-discussions now requires Manage Server. It files real GitHub issues with\n  Artie's token and was open to anyone in either server.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-29T23:41:28Z","url":"https://github.com/room302studio/coachartie2/commit/d7ba7fb67198b84ed31f1014016e57b5dd5b52a6","type":"other"},{"repository":{"name":"coachartie2","url":"https://github.com/room302studio/coachartie2"},"message":"DM pairing requests page EJ via anomalywatch\n\nA new pairing request (unverified user DMs Artie) now reports to anomalywatch with its\nown alert_type, dm_pairing_request, which anomalywatch scores at 7.5: phone when awake,\ndigest when asleep. It is not sent as a critical 'system' alert, because those count as\ninfra and page through sleep. One report per requester per ET day. The message carries\nthe username, first words and the exact `pairing approve <code>` line; the link opens\ntheir Discord profile.\n\nreportToAnomalywatch gains alertType / deepLink options, passed to alert.sh as\nALERT_TYPE / ALERT_DEEPLINK.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-29T19:55:26Z","url":"https://github.com/room302studio/coachartie2/commit/a6fe153aa8f0681fbb3c2f6ca6eaaf44d4f73cc1","type":"other"},{"repository":{"name":"coachartie2","url":"https://github.com/room302studio/coachartie2"},"message":"DM gate: log every access decision, gate DM slash commands\n\nEJ: only people he verifies may DM Artie, thoroughly logged and on his dashboards.\n\n- logDMGate(): one structured line per decision (owner / allowed / open /\n  blocked_pairing / blocked_closed / blocked_command / approved / denied / revoked /\n  added / policy_changed) with a dmGate field for Loki. Blocked attempts log at warn so\n  they also reach pm2 stdout; they previously logged at info and never reached the\n  job=coach_artie dashboard at all. Allowed DMs previously logged nothing.\n- Slash commands, buttons and menus in DMs now require the same verification as DM\n  messages. They bypassed the pairing gate entirely (the /quiz AI judge was paid).\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-29T19:26:04Z","url":"https://github.com/room302studio/coachartie2/commit/cd078179c94209ef8debcb3b732907590febe1dc","type":"other"},{"repository":{"name":"coachartie2","url":"https://github.com/room302studio/coachartie2"},"message":"docs: GitHub feed channel + mention rules in CLAUDE.md (old sb-robot channel is gone)\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-29T19:15:45Z","url":"https://github.com/room302studio/coachartie2/commit/78766ced08843212105bf875f03d5291a0c60271","type":"docs"},{"repository":{"name":"coachartie2","url":"https://github.com/room302studio/coachartie2"},"message":"Sticky per-conversation model rotation for reflections\n\nReflection (fact extraction into memory) rode the global round-robin, which advances\nafter every call, so consecutive reflections in one conversation alternated models and\nnever hit their prompt cache. generateFromMessageChain(Streaming) now takes an optional\nrotationKey: when set, the starting model is FNV-1a(key) % rotation, so a conversation\nstays on one model while different conversations still spread across the rotation.\nFallback-on-error order is unchanged.\n\nReflection keeps its full context and passes the conversation (thread, else channel,\nelse user) as the key, and is tagged stepType 'reflection' for cost attribution.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-29T19:09:09Z","url":"https://github.com/room302studio/coachartie2/commit/91184237806a4abedc6c2c485669a51ac32215f9","type":"other"},{"repository":{"name":"coachartie2","url":"https://github.com/room302studio/coachartie2"},"message":"fix: no reasoning on low/medium auto routes; failed calls book their real cost\n\nLive on first start: BACKGROUND_MODEL=auto:low picked a reasoning model for the\nSteam-review summary, which spent max_tokens thinking and returned no text — paid\nand useless — and the failure row booked it at $0. Auto-routed low/medium calls\nnow send reasoning {effort: \"none\"} (openrouter.ts, speak gate, quiz judge;\nauto:high keeps reasoning for planning). Empty completions keep OpenRouter's\nusage + reported cost for the failure row instead of zeros.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-29T18:59:21Z","url":"https://github.com/room302studio/coachartie2/commit/f864ae7c6e13584e7c87593d525e41eacf284bad","type":"fix"},{"repository":{"name":"coachartie2","url":"https://github.com/room302studio/coachartie2"},"message":"fix(quiz): LLM judge goes through the same guards as every paid call\n\nPR #84's judge was a direct fetch that bypassed the kill switch, the daily budget\nmute and the per-guild share, and recorded no usage (invisible spend). It now\nreturns null (falls back to exact-match) when muted or over the guild share,\ntakes QUIZ_JUDGE_MODEL as a concrete id or an auto:<tier> spec, requests usage\naccounting and writes a model_usage_stats row (step_type quiz_judge, guild_id,\nreported cost). Default endpoint follows OPENROUTER_BASE_URL like the speak gate\n(QUIZ_JUDGE_URL overrides).\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-29T18:52:37Z","url":"https://github.com/room302studio/coachartie2/commit/693b15ea4afa85fdb82dc4bc0fb726de10775e91","type":"fix"},{"repository":{"name":"coachartie2","url":"https://github.com/room302studio/coachartie2"},"message":"Merge PR #84: quiz streak competition + optional LLM judge","occurredAt":"2026-09-29T18:51:26Z","url":"https://github.com/room302studio/coachartie2/commit/182f032c8de628ecaff93c811803ae360a41c1cb","type":"other"},{"repository":{"name":"errand-joy-bot","url":"https://github.com/ejfox/errand-joy-bot"},"message":"Windows: mock-vendor test purchases don't count against real vendors' caps\n\nThe live mock approval test ($80.40) blocked a real $20 joy pick on the $100/day cap.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-12T00:17:20Z","url":"https://github.com/ejfox/errand-joy-bot/commit/734fd26544cfe229bf6cb658ba5fd2a94002c3db","type":"other"},{"repository":{"name":"errand-joy-bot","url":"https://github.com/ejfox/errand-joy-bot"},"message":"Zinc quote: small-order shipping floor under the $35 free-shipping threshold\n\nThe first live joy pick (~$14) failed with max_price_exceeded: offers reported $0\nshipping but Amazon charges shipping under $35, pushing the real total past the\n10% max_price headroom. Quote now assumes $6.99 shipping under the threshold\n(ZINC_FREE_SHIPPING_THRESHOLD_CENTS / ZINC_SMALL_ORDER_SHIPPING_CENTS; 0 disables).\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-12T00:13:38Z","url":"https://github.com/ejfox/errand-joy-bot/commit/df10121cc3b93db3965e65ed02f22d7e9b0eb1cd","type":"other"},{"repository":{"name":"errand-joy-bot","url":"https://github.com/ejfox/errand-joy-bot"},"message":"Merge CJdropshipping adapter (off by default; sandbox first)\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T23:59:25Z","url":"https://github.com/ejfox/errand-joy-bot/commit/025aa8e82729395bd250443d5e0ed1af93623488","type":"other"},{"repository":{"name":"errand-joy-bot","url":"https://github.com/ejfox/errand-joy-bot"},"message":"cj adapter: CJdropshipping, DDP-only, prepaid wallet, sandbox by default\n\nquote(): variant price + freightCalculate to the owner ZIP; only lines with a\nCJ-collected US taxesFee (cj_not_ddp otherwise); CJ duties under half of a\n40%+$3 estimate refuse as cj_duty_suspicious. place(): createOrderV2 with\npayType 3 (no payment), re-read total vs hard cap and quoted duties, wallet\ncheck, then pay the whole order from balance and confirm it is paid.\norderNumber = the gate idempotency key. listCharges from paid orders by\npaymentDate. cjSourcingRequest() is an exported research errand, not wired\ninto purchases. Built from CJ's REST docs only; CJ's MCP is not used.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T23:58:46Z","url":"https://github.com/ejfox/errand-joy-bot/commit/9d21d51125e67002d2fdec0805477a460b560a1a","type":"other"},{"repository":{"name":"errand-joy-bot","url":"https://github.com/ejfox/errand-joy-bot"},"message":"docs: generic host in Lob key example\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T23:47:18Z","url":"https://github.com/ejfox/errand-joy-bot/commit/5fb33e701faea15052e1866bcbc511dc09ff8f57","type":"docs"},{"repository":{"name":"errand-joy-bot","url":"https://github.com/ejfox/errand-joy-bot"},"message":"Merge Lob credit check + send_date\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T23:46:19Z","url":"https://github.com/ejfox/errand-joy-bot/commit/6a5f3eeff80c92b064ae58443f1e42200c0d1c21","type":"other"},{"repository":{"name":"errand-joy-bot","url":"https://github.com/ejfox/errand-joy-bot"},"message":"Merge OSH Park PCB handoff adapter\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T23:46:19Z","url":"https://github.com/ejfox/errand-joy-bot/commit/9e7931544d503b81f947255652d5fb121de81bd5","type":"other"},{"repository":{"name":"errand-joy-bot","url":"https://github.com/ejfox/errand-joy-bot"},"message":"Lob: refuse on short Lob Credits; send_date window for cancel\n\nLob holds postcards when credits run out and mails the backlog on top-up, so place() now reads\nthe credits balance (GET /accounts/credits_balance, /accounts fallback) and refuses\nlob_insufficient_credit unless it covers this piece plus our unsent pieces; an unreadable\nbalance refuses lob_balance_unavailable unless LOB_ALLOW_UNCHECKED_BALANCE=1. Test keys skip it.\nEvery postcard gets send_date = now + LOB_SEND_DELAY_MINUTES (default 60) so cancel() works.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T23:45:53Z","url":"https://github.com/ejfox/errand-joy-bot/commit/fc9aaccb7dd2e276cd1aee0b0cc3f3288cd038b5","type":"other"},{"repository":{"name":"errand-joy-bot","url":"https://github.com/ejfox/errand-joy-bot"},"message":"Merge Lob postcard adapter\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T23:45:26Z","url":"https://github.com/ejfox/errand-joy-bot/commit/cdb00d43959d774ab7480c3980faa81ed08efc81","type":"other"},{"repository":{"name":"errand-joy-bot","url":"https://github.com/ejfox/errand-joy-bot"},"message":"OSH Park handoff adapter + tools/pcb Gerber bbox pipeline\n\nquote() prices locally from the published per-sq-in table (verified 2026-10-11) using the\noutline bbox read from the Gerber zip (stdlib zip reader, X2 Profile / Edge_Cuts / GKO / GM1,\narcs included). place() uploads to the documented anonymous import endpoint and records $0:\nthe owner checks out on oshpark.com. status() open until a marker file; listCharges() [].\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T23:42:56Z","url":"https://github.com/ejfox/errand-joy-bot/commit/3f0d4ccc486b874557d4c84e33f3ed7cd977eb25","type":"other"},{"repository":{"name":"errand-joy-bot","url":"https://github.com/ejfox/errand-joy-bot"},"message":"Lob postcard adapter (id \"lob\")\n\nOne US First Class postcard per request: front = item.url (pdf/png/jpg), back = item.message\nor item.title, escaped into a left-column HTML layout. quote() is offline from Lob's published\nall-in per-piece table (4x6 91c, 6x9 103c, Developer plan) + 3% card fee; no tax, no separate\npostage. place() sends an Idempotency-Key and metadata ejb_cents so listCharges() matches;\nstatus() maps tracking events (Returned to Sender stays shipped: it is billed). Owner-home\nreuses zinc's OWNER_SHIP_TO_JSON parser; any other recipient is reach \"others\". Opt-in\nLOB_LIVE=1 test makes one free test-mode postcard and refuses live_ keys.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T23:42:41Z","url":"https://github.com/ejfox/errand-joy-bot/commit/632c90d365ca946040db51c2a5a86eb76b54c3bd","type":"other"},{"repository":{"name":"errand-joy-bot","url":"https://github.com/ejfox/errand-joy-bot"},"message":"Slant upload host in allow-net map; verified Lulu package ids\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T23:42:37Z","url":"https://github.com/ejfox/errand-joy-bot/commit/a76dc6bb78ded049a77d65b7d0294a1b7c1f2e0f","type":"other"},{"repository":{"name":"errand-joy-bot","url":"https://github.com/ejfox/errand-joy-bot"},"message":"docs: generic host name in key-name examples\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T23:39:43Z","url":"https://github.com/ejfox/errand-joy-bot/commit/81f91a91fd04719a65b1d4be53fffb96ff750e1d","type":"docs"},{"repository":{"name":"errand-joy-bot","url":"https://github.com/ejfox/errand-joy-bot"},"message":"deno task check covers gate/vendor_hosts.ts (install.sh runs it)\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T23:38:55Z","url":"https://github.com/ejfox/errand-joy-bot/commit/33d30e6bd346b9489f5b3b99c4015abc6acec86b","type":"other"},{"repository":{"name":"errand-joy-bot","url":"https://github.com/ejfox/errand-joy-bot"},"message":"install.sh derives vendor --allow-net hosts; vendors table, env vars, MCP item fields\n\n- VENDOR_HOSTS + vendorHosts() in registry.ts (test: covers exactly the\n  registered vendors); gate/vendor_hosts.ts prints them for a config.\n  install.sh adds the enabled vendors' hosts (example config on a first\n  install), keeps --allow-net additions, dedupes, and dies on a bad config.\n  install.sh's test step now matches `deno task test` (tools too).\n- docs/vendors.md: one table of all vendors (reach, payment, cap, env\n  vars, key name), the new Item fields, links / needs-action, the\n  hard-cap reconcile rule; per-vendor item docs updated; stale gaps out.\n- README roadmap, runbook, threat model; .env.example lists every\n  vendor env var (commented, empty).\n- MCP request_purchase item schema: message, files, pageCount, sizing,\n  attributes, aoi.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T23:35:38Z","url":"https://github.com/ejfox/errand-joy-bot/commit/416aaedef5c9dd13804ee35e10c6ce4db1af0276","type":"other"},{"repository":{"name":"website-dispatch","url":"https://github.com/ejfox/website-dispatch"},"message":"Merge pull request #9 from ejfox/release/dispatch-fixes\n\nPublishing actually works, waits for the deploy, can't leak week notes; native macOS fixes","occurredAt":"2026-10-11T20:48:07Z","url":"https://github.com/ejfox/website-dispatch/commit/c09064103ed056c17e779b6a441fa5dffd739fb7","type":"other"},{"repository":{"name":"website-dispatch","url":"https://github.com/ejfox/website-dispatch"},"message":"v0.8.0\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T20:47:49Z","url":"https://github.com/ejfox/website-dispatch/commit/1703363219c39912e6c645b3ac7aaefa2b8be742","type":"other"},{"repository":{"name":"website-dispatch","url":"https://github.com/ejfox/website-dispatch"},"message":"Keep the shell plugin; help overlay says ⌘1–5\n\nFollow-up to the Gear removal. GearPanel was the only JS importer of\n@tauri-apps/plugin-shell, but the Rust plugin also injects a script that\nopens <a target=\"_blank\"> http(s)/mailto links in the system browser\n(StatusBanner, ActionToolbar, WebmentionStatus, rendered preview links...).\nRestore tauri_plugin_shell::init(), the crate, and shell:allow-open /\nshell:default. The npm package and the git/yarn shell:allow-execute scope\nstay removed. With Gear gone there are five tabs, so the help row reads 1–5.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T20:35:54Z","url":"https://github.com/ejfox/website-dispatch/commit/5dffa2250f58d3d12bed22509eb04d80c777ca78","type":"other"},{"repository":{"name":"website-dispatch","url":"https://github.com/ejfox/website-dispatch"},"message":"Remove the companion web server\n\ncompanion.rs bound 0.0.0.0:6420 at every launch and exposed a PIN-protected\npublish/schedule API to the whole LAN. Deletes it, its HTML UI, the\nget_companion_info command, the boot spawn, the status-bar item and its\ncontext menu, and the deps only it used (axum, tower-http,\nlocal-ip-address, rand).\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T20:29:36Z","url":"https://github.com/ejfox/website-dispatch/commit/2f641718bc6fd489083260aa2ff967d27a96443f","type":"other"},{"repository":{"name":"website-dispatch","url":"https://github.com/ejfox/website-dispatch"},"message":"Remove publishing streaks, stats, milestones, nudges and vault pulse\n\nKeeps the journal's event log (record_event, recent entries, heatmap,\nbackfill) that ActivityFeed and the Journal tab's heatmap + recent-activity\nlist read. Deletes journal.rs's stats/WeirdStats/streak/milestone/nudge code,\nvault_pulse.rs, sketchybar_cache.rs and its calls (publish, unpublish, deploy,\nvault watcher, boot), the get_journal_stats/get_journal_nudge/get_vault_pulse\ncommands, and their UI: the Journal tab's streak header, nudge, stat cards,\nmonthly/rhythm charts, vault-pulse lists and milestones; the status bar's\nk/mo; the publish modal's \"publish #N · streak\" line; and the milestone toast.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T20:27:52Z","url":"https://github.com/ejfox/website-dispatch/commit/72df9e598dcd29d53bfaeeb29e33ddc5826be9e6","type":"other"},{"repository":{"name":"website-dispatch","url":"https://github.com/ejfox/website-dispatch"},"message":"Remove the Gear panel\n\nA CSV inventory editor has no overlap with publishing. Deletes gear.rs,\nGearPanel.vue, its 7 commands, the Gear tab/menu item/palette entry/home-tab\noption, the csv crate, and the shell plugin (Rust + npm + capability\npermissions) whose only user was GearPanel. A stored 'gear' home tab falls\nback to the Desk.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T20:26:03Z","url":"https://github.com/ejfox/website-dispatch/commit/df4532fb94ad78f72851501125edd09e450ce915","type":"other"},{"repository":{"name":"website-dispatch","url":"https://github.com/ejfox/website-dispatch"},"message":"Merge fix/native\n\nAlso fixes the deploy-state key: the publish fix removed getSlug() from the\npublish-flow options and the deploy tracker still used it (vue-tsc errors\nsince the fix/deploycheck merge). Deploys are now keyed by file path.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T20:21:15Z","url":"https://github.com/ejfox/website-dispatch/commit/f42472811ed7356864a65bb77a67dbb68b4b76f8","type":"other"},{"repository":{"name":"website-dispatch","url":"https://github.com/ejfox/website-dispatch"},"message":"Merge fix/deploycheck\n\n# Conflicts:\n#\tsrc-tauri/src/lib.rs","occurredAt":"2026-10-11T20:20:19Z","url":"https://github.com/ejfox/website-dispatch/commit/93d00ed8000c462d215b539be24f382eda569be6","type":"other"},{"repository":{"name":"website-dispatch","url":"https://github.com/ejfox/website-dispatch"},"message":"Merge fix/weeknotes\n\n# Conflicts:\n#\tsrc-tauri/src/publish.rs","occurredAt":"2026-10-11T20:19:36Z","url":"https://github.com/ejfox/website-dispatch/commit/4180a7c9a740173d30ef43e70f926cc1504aa53b","type":"other"},{"repository":{"name":"website-dispatch","url":"https://github.com/ejfox/website-dispatch"},"message":"Merge fix/publishfix","occurredAt":"2026-10-11T20:19:17Z","url":"https://github.com/ejfox/website-dispatch/commit/7a2618a9ce3ddba1fd69a13d88c3cf0c26cc4eaf","type":"other"},{"repository":{"name":"website-dispatch","url":"https://github.com/ejfox/website-dispatch"},"message":"Deploy check: skip the URL probe for password posts\n\nwebsite2 404s password-protected posts at their own URL in production\n(isProtectedContent), so probing them would report every protected\npublish as not live. The matching healthcheck SHA is the confirmation.\nUntitled posts now notify with their slug instead of \"Your post\".\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T20:18:12Z","url":"https://github.com/ejfox/website-dispatch/commit/e814379ebce79bd6275f5f0d2599a1407ce87f3f","type":"other"},{"repository":{"name":"website-dispatch","url":"https://github.com/ejfox/website-dispatch"},"message":"Window minimum size and macOS bundle metadata\n\nminWidth/minHeight 560x420 so the layout can't be crushed; bundle\nminimumSystemVersion 13.0 (the CSS needs color-mix/AccentColor and\nvibrancy), Productivity category and a copyright line.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T20:17:54Z","url":"https://github.com/ejfox/website-dispatch/commit/9780d1c284e5af17c98ee07d0d0c36c735518ffa","type":"other"},{"repository":{"name":"website-dispatch","url":"https://github.com/ejfox/website-dispatch"},"message":"Dock badge: grant set-badge-count so the modified count shows\n\nApp.vue already set the Dock badge to the modified-since-publish count,\nbut core:default only grants read-only window commands, so the call was\ndenied and the empty catch hid it. Allow core:window:allow-set-badge-count\nand log failures instead of swallowing them.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T20:17:54Z","url":"https://github.com/ejfox/website-dispatch/commit/2bc314a4f4c47d461dc644da7e0fb750753db305","type":"other"},{"repository":{"name":"website-dispatch","url":"https://github.com/ejfox/website-dispatch"},"message":"Add Settings… ⌘, to the app menu\n\nThe shortcut only existed as a JS keydown, so it was invisible in the\nmenu bar and Help search. The menu item now owns ⌘, (showing the window\nif it was hidden); the duplicate keydown handler is removed.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T20:17:54Z","url":"https://github.com/ejfox/website-dispatch/commit/55a50743c5cc1af2382c3f96fef8529ffc989507","type":"other"},{"repository":{"name":"website-dispatch","url":"https://github.com/ejfox/website-dispatch"},"message":"publish UI: send the vault path, not a hand-built year/slug\n\nThe backend now derives the destination from the source path, so the\n\"2026/x\" slug that caused the doubled-year path is no longer passed to\npublish_file. The year/slug computed stays for OG and display.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T20:17:35Z","url":"https://github.com/ejfox/website-dispatch/commit/3c2bd23c6f8e977111d42fa49d8fc2e2240e2a0a","type":"other"},{"repository":{"name":"election-helpers","url":"https://github.com/ejfox/election-helpers"},"message":"chore(release): 0.3.0 changelog — tally, raceMargin fix, party buckets\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-01T00:16:22Z","url":"https://github.com/ejfox/election-helpers/commit/9f893750d1951b4f322457fe9b69aeec971f6702","type":"chore"},{"repository":{"name":"election-helpers","url":"https://github.com/ejfox/election-helpers"},"message":"Merge pull request #8 from ejfox/fix/unopposed-margin\n\nraceMargin: unopposed seat is a 100% margin even with 0 votes","occurredAt":"2026-09-30T19:38:08Z","url":"https://github.com/ejfox/election-helpers/commit/4bbbd767490d0a3d81392d64d7d39a7ce28009a5","type":"other"},{"repository":{"name":"election-helpers","url":"https://github.com/ejfox/election-helpers"},"message":"fix(raceMargin): an unopposed seat is a 100% margin even with 0 votes\n\nSeats left off the ballot (FL, LA) report the lone candidate with 0 votes;\nmarginPct fell back to 0 and electology painted them as tossups.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-30T19:35:01Z","url":"https://github.com/ejfox/election-helpers/commit/5dd5c97ad79dbcafbb6f2ca5a7c4cbc34ee7e754","type":"fix"},{"repository":{"name":"election-helpers","url":"https://github.com/ejfox/election-helpers"},"message":"Merge pull request #7 from ejfox/feat/tally\n\nfeat(tally): vote-mode aware candidate totals + race margins","occurredAt":"2026-09-29T16:50:58Z","url":"https://github.com/ejfox/election-helpers/commit/7e45d99fc99cb6b28ad99f71aa432aa908311f6c","type":"other"},{"repository":{"name":"election-helpers","url":"https://github.com/ejfox/election-helpers"},"message":"style: prettier on tally export + fixture\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-29T16:50:50Z","url":"https://github.com/ejfox/election-helpers/commit/e5698b1182c68f0e842e8202cfbd85564ec4a231","type":"style"},{"repository":{"name":"election-helpers","url":"https://github.com/ejfox/election-helpers"},"message":"feat(tally): vote-mode aware candidate totals + race margins\n\ntallyByCandidate / tallyByUnit / raceMargin / isTotalMode. Results arrive\nTOTAL-only, TOTAL + per-mode, or per-mode only (e.g. GA 2020). Per candidate:\nTOTAL rows if it has any, else the sum of its mode rows; multiple TOTAL lines\nare summed; modes that disagree with the TOTAL are flagged (modes-mismatch).\n\nFixtures are real 2020 presidential rows (Fulton GA, Rich + Salt Lake UT,\n53069, GA/MD state rows, all GA counties) with a county→state sum invariant.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-09-29T16:21:17Z","url":"https://github.com/ejfox/election-helpers/commit/25f3a2336272bc88b0923864276cecce1bd834c9","type":"feat"},{"repository":{"name":"election-helpers","url":"https://github.com/ejfox/election-helpers"},"message":"boundariesAvailableForRaceType: senate is statewide → add 'state'\n\nSenate returned only ['county'], so isBoundaryAvailableForRaceType('senate',\n'state') was false and a senate choropleth couldn't render at the state level —\nyet state IS the natural senate boundary (senate races are statewide). Now\n['state', 'county']. Updated the two tests that had codified the old behavior;\nadded a positive senate/state assertion. Suite green (177).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>","occurredAt":"2026-09-23T22:37:20Z","url":"https://github.com/ejfox/election-helpers/commit/419f5236dbbc3f24197016991570ac4660b14371","type":"other"},{"repository":{"name":"election-helpers","url":"https://github.com/ejfox/election-helpers"},"message":"partyBucket: bucket MN DFL and ND DNL as 'dem' (were falling through to 'other')\n\nMinnesota's Democratic-Farmer-Labor party and North Dakota's Democratic-\nNonpartisan League ARE the state Democratic parties (their members caucus as\nDemocrats and analysts treat them as Democratic for two-party views). partyBucket\nnormalized them to codes DFL/DNL but only mapped D→dem, so every DFL/DNL result\nbucketed 'other' — e.g. a Minnesota senate map rendered grey for Klobuchar,\nFranken, Wellstone, Dayton. Now DFL/DNL → 'dem'. Added a regression test.\n\nFull suite green (176 tests).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>","occurredAt":"2026-09-23T20:29:25Z","url":"https://github.com/ejfox/election-helpers/commit/1756704780d1f1473c2ffdf2157802bcfe179e89","type":"other"},{"repository":{"name":"election-helpers","url":"https://github.com/ejfox/election-helpers"},"message":"Merge pull request #5 from ejfox/feat/intl-and-textfit\n\nfeat: international standards (ISO 3166-2, apportionment) + name-fitting math","occurredAt":"2026-09-22T22:41:17Z","url":"https://github.com/ejfox/election-helpers/commit/c1c41d6b7afa7ae523b354b0d51ba42d3173f81b","type":"other"},{"repository":{"name":"election-helpers","url":"https://github.com/ejfox/election-helpers"},"message":"chore(release): finish 0.3.0 — version bump, docs, CHANGELOG\n\nReady PR #5 for review/publish:\n- Bump 0.2.0 -> 0.3.0 (additive, backward-compatible: ISO 3166-2 helpers,\n  seat apportionment, text-fit name-fitting math).\n- README: \"What's new in 0.3.0\" + API Reference sections for the ISO 3166-2\n  codes, seat apportionment, and text-fit modules.\n- CHANGELOG: 0.3.0 entry.\n- Formatting: prettier-fix the hand-written text-fit source + its tests;\n  prettier-ignore the generated src/tables/oswald.js (JSON.stringify output,\n  regenerated via `npm run gen:oswald`, not hand-formatted).\n\n`npm run check` is green: format ✓, lint ✓ (0 errors), 175 tests pass.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>","occurredAt":"2026-09-22T15:22:47Z","url":"https://github.com/ejfox/election-helpers/commit/89f0b74799eefb28f8663e83fdbda8c48dc04a41","type":"chore"},{"repository":{"name":"election-helpers","url":"https://github.com/ejfox/election-helpers"},"message":"chore(text-fit): reproducible Oswald table via scripts/gen-oswald.mjs\n\nMove the width-table generator into the repo and dogfood the public\nbuildWidthTable() API to regenerate src/tables/oswald.js from the font\n(scripts/fonts/Oswald.ttf, OFL). Adds opentype.js as a devDep and a\n'npm run gen:oswald' script; regenerated output is byte-identical to the\ncommitted table. scripts/ is outside the files allowlist, so none of this\nships to npm. eslint: node-globals override for scripts/**/*.mjs.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>","occurredAt":"2026-09-21T17:30:19Z","url":"https://github.com/ejfox/election-helpers/commit/c0e8a37ecfddeff30699ec34a0cbcce88635a9c8","type":"chore"},{"repository":{"name":"election-helpers","url":"https://github.com/ejfox/election-helpers"},"message":"feat(text-fit): precomputed width tables + name-fitting math\n\nThe 'make every candidate name fill the same column, no gaps' problem, solved\nwith pure local math (no DOM, no runtime font dep):\n\n- buildWidthTable(measure): black-box pairwise builder — adj[ab] = measure(ab) -\n  a - b captures kerning + 2-glyph ligatures from ANY measurer (canvas =>\n  browser-accurate, opentype => metrics-accurate). Build-time only.\n- measureWithTable / measureOswald: size * Σ table[char] + Σ adj[pair]. Best-\n  effort (never null): combining marks => 0 width, unknown chars => fallback.\n  Benchmarked exact vs its source measurer, ~14-230x faster than per-call libs.\n- OSWALD_WIDTHS: prebuilt table for Oswald 400 (electology's chyron face), ~24KB.\n- fitFontSize / justifyLetterSpacing / fitTextToWidth: fit to an exact width by\n  scaling size then justifying slack as letter-spacing.\n\nEmpirically chosen (bench: opentype vs fontkit vs satori vs @napi-rs/canvas —\nall agree to 0.01%; table+kern reproduces them at 0.000%). 20 tests. No bump.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>","occurredAt":"2026-09-21T17:28:06Z","url":"https://github.com/ejfox/election-helpers/commit/1c99ea258352111005ddfcaeaa9f88ee15e0b52a","type":"feat"},{"repository":{"name":"election-helpers","url":"https://github.com/ejfox/election-helpers"},"message":"feat(apportionment): highest-averages seat allocation (D'Hondt, Sainte-Laguë, Huntington-Hill)\n\nNew country-agnostic module: allocateSeats(votes, seats, { method }) plus named\nwrappers dHondt / sainteLague / huntingtonHill. One divisor algorithm, pluggable\nsequence:\n- dhondt (1,2,3…), sainte-lague (1,3,5…), modified-sainte-lague (1.4,3,5…)\n- huntington-hill (√(s(s+1))) — the method the US uses to apportion the 435\n  House seats among states, so this works for the US too (each party seeded 1)\n\nPlain object in/out (Turf-shaped), deterministic tie-break by votes, full input\nvalidation. 18 tests vs known vectors (Wikipedia D'Hondt/Sainte-Laguë). No bump.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>","occurredAt":"2026-09-21T16:49:49Z","url":"https://github.com/ejfox/election-helpers/commit/e49014d41bca1ceb575de7062d7a4ab006a7358f","type":"feat"},{"repository":{"name":"election-helpers","url":"https://github.com/ejfox/election-helpers"},"message":"feat(geo): ISO 3166-2 subdivision helpers (US-CA etc.)\n\nAdd stateAbbrToIso / isoToStateAbbr / stateFipsToIso / isoToStateFips, derived\nfrom US_STATES (the US already conforms to ISO 3166-2: US-<USPS abbr>). This is\nthe international standard for country subdivisions and the join key to GADM /\nNatural Earth / Eurostat / Wikidata — a step toward helpers that also work\noutside the US, at zero cost to US callers.\n\nFM/MH/PW intentionally return undefined: their 2-letter codes are ISO 3166-1\n*country* codes (Freely Associated States), not US subdivisions, so US-FM would\nbe wrong. Rule: only fips-bearing US_STATES entries get an ISO 3166-2 code.\n\n137 tests pass (7 new), lint clean. No version bump — batch with a later publish.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>","occurredAt":"2026-09-21T16:39:25Z","url":"https://github.com/ejfox/election-helpers/commit/d743895adce644dd180618ca9983ebbb5873e464","type":"feat"},{"repository":{"name":"election-helpers","url":"https://github.com/ejfox/election-helpers"},"message":"chore: add files allowlist to slim published tarball\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>","occurredAt":"2026-09-21T15:52:46Z","url":"https://github.com/ejfox/election-helpers/commit/97903100b0ec2a8e418dacbde6745d4c21fe1216","type":"chore"},{"repository":{"name":"417am-site","url":"https://github.com/ejfox/417am-site"},"message":"Video entries: mp4/webm with metadata stripped, poster frame, feeds\n\n- /api/post (field \"video\") and /upload accept H.264 mp4 or VP8/VP9 webm, sniffed from\n  magic bytes and forced on ffprobe/ffmpeg; caps 90 MB, 180 s, 4096 px\n- re-mux drops all container/stream/chapter metadata, extra tracks, encoder tags,\n  creation times and H.264 SEI; AAC/Vorbis audio re-encoded bitexact\n- poster = first non-black frame as a stripped PNG\n- <video> muted loop playsinline controls preload=metadata, caption mark ▶︎ video\n- RSS enclosure + media:content, JSON Feed attachments, og:video\n- Umami video-play (once per video) and video-open\n- MEDIA_DIR dev mode stores files locally for end-to-end tests\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-11T22:42:56Z","url":"https://github.com/ejfox/417am-site/commit/c8a7add7976ad44b922ba16281383efde40cb01e","type":"other"},{"repository":{"name":"417am-site","url":"https://github.com/ejfox/417am-site"},"message":"Umami 3.4: versioned tracker + Web Vitals, umami-plus helper, recorder (heatmaps/replay)\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T18:28:51Z","url":"https://github.com/ejfox/417am-site/commit/5917293a6b86982ec2f072e75aaaa9c3836b0c1f","type":"other"},{"repository":{"name":"417am-site","url":"https://github.com/ejfox/417am-site"},"message":"Feed items: drop inline style (W3C validator warning)\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T18:08:21Z","url":"https://github.com/ejfox/417am-site/commit/97edd808eb0598585da04ac767dcf8342e6eee46","type":"other"},{"repository":{"name":"417am-site","url":"https://github.com/ejfox/417am-site"},"message":"Umami hooks: UMAMI_WEBSITE_ID env (no script when unset) + event attributes\n\nEvents: rss-click, feed-json-click, permalink-open, image-open, outbound,\narchive-divider-view (once, IntersectionObserver on the bot-era break).\nPermalink image links to the full-size original.\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T18:06:00Z","url":"https://github.com/ejfox/417am-site/commit/416ec33abda31277d326c8e644e04c7478ff5c4c","type":"other"},{"repository":{"name":"417am-site","url":"https://github.com/ejfox/417am-site"},"message":"One record, two eras: new work (2026-) above the @417am1975 archive\n\n- live manifest moves out of git (LIVE_MANIFEST, VPS /data2/417am-data/now.json) so\n  deploys (git reset --hard) can never wipe posts; data/art.json stays a read-only seed\n- posting API: POST/DELETE/PATCH /api/post, GET /api/schedule (Bearer POST_TOKEN,\n  fail closed), idempotent on id, publish_at drip scheduling, PNG metadata stripped\n- public pages show image, number, kind and date only; private ids never rendered,\n  permalinks use random slugs (/p/:slug with og:image)\n- RSS 2.0 (/rss.xml) + JSON Feed 1.1 (/feed.json), new work only, live entries only\n- brutalist-academic redesign: one monospace size, flat colors, 1px rules, numbered\n  entries, crisp pixelated 1-bit pieces\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-06T18:03:15Z","url":"https://github.com/ejfox/417am-site/commit/f8622fe3d72a2077a7b0790fd094893fdd8000a2","type":"other"},{"repository":{"name":"417am-site","url":"https://github.com/ejfox/417am-site"},"message":"Fill era gaps: Oct/Nov 2017, Feb-Mar 2018, Jul 2018 (27 pieces)\n\nSystematic month-by-month X search sweep of @417am1975's full\n2017-2019 lifespan to surface visual eras missing from the gallery.\nConfirmed Nov 2018 and Mar-May 2019 are genuinely empty (no posts).\n3 pieces flagged as having had likes/favorites.\n\nManifest: 118 -> 145 entries.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>","occurredAt":"2026-10-02T17:09:57Z","url":"https://github.com/ejfox/417am-site/commit/cfeef1ceb580dabb9b1f53909b3fba1b8523ae0a","type":"other"},{"repository":{"name":"417am-site","url":"https://github.com/ejfox/417am-site"},"message":"Add 38 more pieces from the X timeline: engagement + era sampling\n\n17 pieces with confirmed likes/retweets (May 2018 - Sep 2019), plus\nera-sampled pieces covering the bot's debut (Aug 2017 debug builds,\nparams visible in captions), late 2017, and April 2018 - filling gaps\nbetween the previously-recovered Imgur album and Nov 2019 letterform\nburst. Manifest: 80 -> 118.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>","occurredAt":"2026-10-02T16:57:28Z","url":"https://github.com/ejfox/417am-site/commit/5f52dab7b7ca649ee18c5031ba8bb61a25652cb1","type":"other"},{"repository":{"name":"417am-site","url":"https://github.com/ejfox/417am-site"},"message":"Add 20 pieces recovered directly from the @417am1975 X timeline\n\nFirst excavation pass of the live account (21.5K posts, 2017-2019+)\nbeyond the Imgur-era archive already on site. This batch is an hourly\nburst of a word/letterform-collage series posted Nov 18-19, 2019.\nTotal gallery: 80 pieces.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>","occurredAt":"2026-10-02T16:45:57Z","url":"https://github.com/ejfox/417am-site/commit/83f0fb55f5c3de07214585279f52cfdad5d558a7","type":"other"},{"repository":{"name":"417am-site","url":"https://github.com/ejfox/417am-site"},"message":"Link to @417am1975 instead of /upload, add posting how-to\n\nNo public link to /upload — it's bookmark-only now. HOWTO-POST.md\nhas the login/posting instructions for EJ.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>","occurredAt":"2026-10-02T16:20:10Z","url":"https://github.com/ejfox/417am-site/commit/e857a2fe4e22b8f0fafffff1e8450538e0c6df1c","type":"other"},{"repository":{"name":"417am-site","url":"https://github.com/ejfox/417am-site"},"message":"Expand gallery to 60 pieces + add GitHub Actions deploy\n\nRecovered 51 more pieces from the full imgur archive (0nlIRIo album,\nthe 7 artscript-named images linked in twitter-artbot/four-seventeen\nREADMEs) plus 15 splinescroller images committed in the original 417am\nrepo. Excluded 2 blank/broken frames.\n\nAdds .github/workflows/deploy.yml: push to main -> ssh to VPS ->\ngit reset --hard -> pm2 restart -> health check.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>","occurredAt":"2026-10-02T15:34:08Z","url":"https://github.com/ejfox/417am-site/commit/84d86aeec84c63150742e1c50997c3d4a0dd26ef","type":"other"},{"repository":{"name":"417am-site","url":"https://github.com/ejfox/417am-site"},"message":"Initial scaffold: gallery + Tumblr-simple upload for 417am.party\n\nSingle-file Deno + Hono app. Gallery shows all art newest-first;\npassword-gated /upload signs a Cloudinary upload and appends to a\nJSON manifest. Seeded with 9 pieces recovered from the original\n@417am1975 generative-art bot (2017).\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>","occurredAt":"2026-10-02T15:31:33Z","url":"https://github.com/ejfox/417am-site/commit/9f33d5754fe8cdee89d46e2d6dc32e45fc2c8fa0","type":"other"},{"repository":{"name":"vulpes-theme-lab","url":"https://github.com/ejfox/vulpes-theme-lab"},"message":"Merge remote-tracking branch 'origin/main'","occurredAt":"2026-09-14T13:52:22Z","url":"https://github.com/ejfox/vulpes-theme-lab/commit/b539073a1957c511e50774c13857013521f51512","type":"other"},{"repository":{"name":"vulpes-theme-lab","url":"https://github.com/ejfox/vulpes-theme-lab"},"message":"chore(release): v0.4.0\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_015gU6rjTCZufwbtEHJiGTSr","occurredAt":"2026-09-14T13:50:55Z","url":"https://github.com/ejfox/vulpes-theme-lab/commit/90c68ba1512303b689b9499aa3d813c559dd357f","type":"chore"},{"repository":{"name":"vulpes-theme-lab","url":"https://github.com/ejfox/vulpes-theme-lab"},"message":"perf: cut per-drag work so sliders stay responsive\n\nProfiling a live hue drag showed the cost was elsewhere than the color\nmath. Remove the biggest per-tick offenders:\n\n- Delete the URL-sync watcher that rewrote ~120 query params through the\n  history API on every state change (inbound deep-linking still works).\n- CodePreview: stop destroying/rebuilding the CodeMirror editor each tick;\n  swap the theme via a Compartment and debounce it off the drag path\n  (its DOM re-measure was the dominant cost).\n- MapPreview: lazy-init maplibre via IntersectionObserver and debounce\n  restyles so its full style-diff never runs mid-drag; drop the redundant\n  double JSON.parse.\n- useTheme: reuse the computed dark/light variant instead of generating a\n  third palette for `colors`.\n\nMain-thread blocking during a hue sweep drops ~3.4x.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_015gU6rjTCZufwbtEHJiGTSr","occurredAt":"2026-09-14T13:49:26Z","url":"https://github.com/ejfox/vulpes-theme-lab/commit/39ab95b81144bf410ae32e9cdb5d2776834d249e","type":"perf"},{"repository":{"name":"vulpes-theme-lab","url":"https://github.com/ejfox/vulpes-theme-lab"},"message":"feat: flatten sidebar/preview nesting and redesign sliders\n\nReduce the \"boxes within boxes\" to a single layer: strip nested\nborders/fills from the sidebar controls, swatch cards, month tiles and\npreview panels so each element reads as one surface.\n\nRedesign both slider systems (sidebar + in-swatch) into an Apple-style,\ndata-vizzy control: thin pill tracks, a precise round white knob with a\nrealistic layered shadow, and signed fills that originate from a center\nzero-tick on bipolar (hue-offset) sliders. Fix the base-hue gradient that\nwas being overridden by the track background.\n\nAdd a plain-language description under every control slider and rename the\ncryptic \"offset ±\" to \"hue spread\" so it's clear what each one does.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_015gU6rjTCZufwbtEHJiGTSr","occurredAt":"2026-09-14T13:49:18Z","url":"https://github.com/ejfox/vulpes-theme-lab/commit/2ef49133638e5c6f839fd86414aab2a4cbf0c915","type":"feat"},{"repository":{"name":"vulpes-theme-lab","url":"https://github.com/ejfox/vulpes-theme-lab"},"message":"fix: pin nuxt to 4.1.3 to resolve vue-router RouterView crash\n\nNuxt 4.5 pulls in vue-router 5, whose RouterView leaves the page vnode's\ncomponent.ref.i null, throwing \"null is not an object (evaluating\n'instance.__vrv_devtools = info')\" and blanking the SPA. Pin nuxt to the\nknown-good 4.1.3 (vue-router 4.6.x) and drop the stray yarn.lock so npm's\nlockfile is authoritative.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_015gU6rjTCZufwbtEHJiGTSr","occurredAt":"2026-09-14T13:49:10Z","url":"https://github.com/ejfox/vulpes-theme-lab/commit/3c3e254f92403187bc68a066ec6fa3dedc6bb4de","type":"fix"},{"repository":{"name":"vulpes-theme-lab","url":"https://github.com/ejfox/vulpes-theme-lab"},"message":"feat: standalone MapLibre basemap editor at /map\n\nFull-screen interactive map editor for designers with:\n- useMapTheme composable wrapping useTheme for map-specific state\n- Interactive MapLibre map with pan/zoom/rotate and camera readout\n- Color engine: base hue, hue spread, saturation, contrast sliders\n- Per-feature color controls: water, parks, roads, buildings, POIs\n  with clickable swatches opening hue+saturation+hex popover\n- 20 extended color overrides (roads, infrastructure, landuse, POIs, labels)\n  each with native color picker and hex paste input\n- Geometry controls: building height, road width, water outline, boundary width\n- Typography: font family, size scale, halo width/opacity, label density\n- Layer visibility toggles with per-group opacity sliders\n- View angle presets (top-down, 3D, street level)\n- Location presets (10 cities)\n- Export (download JSON, copy JSON, share URL)\n- Fix: hue offset fields now actually work in mapColorAt()\n- Fix: buildings use single flat color instead of random hue spread\n- Vite optimizeDeps.include for maplibre-gl, chroma-js, @vueuse/core\n\nv0.4.0\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>","occurredAt":"2026-04-15T03:28:32Z","url":"https://github.com/ejfox/vulpes-theme-lab/commit/1b2b178419cc88c34341277f1c62f0b2dda29cd8","type":"feat"},{"repository":{"name":"vulpes-theme-lab","url":"https://github.com/ejfox/vulpes-theme-lab"},"message":"fix: remove problematic colors.value refs in Obsidian preview\n\nUse colors directly from template context instead of colors.value\nwhich can be undefined during SSR\n\n🤖 Generated with Claude Code\n\nCo-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-03T19:30:27Z","url":"https://github.com/ejfox/vulpes-theme-lab/commit/e737487d3c50acacc424b9f92b911ca01ca72147","type":"fix"},{"repository":{"name":"vulpes-theme-lab","url":"https://github.com/ejfox/vulpes-theme-lab"},"message":"fix: ObsidianPreview undefined colors.value.property\n\nUse colors.value.variable instead which is guaranteed to exist\n\n🤖 Generated with Claude Code\n\nCo-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-03T19:25:43Z","url":"https://github.com/ejfox/vulpes-theme-lab/commit/c119f6bbb2a165bad38a048f3b4b1b346c0d6f8e","type":"fix"},{"repository":{"name":"vulpes-theme-lab","url":"https://github.com/ejfox/vulpes-theme-lab"},"message":"feat: add Obsidian theme exporter and preview component\n\n- Export themes to Obsidian CSS format with semantic color mappings\n- Create preview component showing how theme renders in Obsidian vault UI\n- Includes file explorer, editor with syntax highlighting, and properties sidebar\n- Maps palette colors to Obsidian's standard CSS custom properties for consistency\n\n🤖 Generated with Claude Code\n\nCo-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-03T18:09:07Z","url":"https://github.com/ejfox/vulpes-theme-lab/commit/d117169f88deab2e2f7bdc0caf7f7463c4ed02be","type":"feat"},{"repository":{"name":"vulpes-theme-lab","url":"https://github.com/ejfox/vulpes-theme-lab"},"message":"feat: add Tailwind CSS exporter\n\nExports theme as CSS custom properties with tailwind.config.js extend snippet and usage examples.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2025-12-30T05:23:11Z","url":"https://github.com/ejfox/vulpes-theme-lab/commit/7cc38f8914cdfd182bd636ce4b38684b4273bb64","type":"feat"},{"repository":{"name":"vulpes-theme-lab","url":"https://github.com/ejfox/vulpes-theme-lab"},"message":"Update README with live demo and project details\n\nAdded a screenshot and updated project description.","occurredAt":"2025-12-28T22:48:57Z","url":"https://github.com/ejfox/vulpes-theme-lab/commit/5d3372b1ccbd07c64e8b97cbd4a2c19cf76a7334","type":"other"},{"repository":{"name":"vulpes-theme-lab","url":"https://github.com/ejfox/vulpes-theme-lab"},"message":"feat: showcase page overhaul with hero examples, presets grid, and Monaspace fonts\n\n- Add PresetShowcase component displaying all 12 monthly presets\n- Create evocative \"chromatic alchemy\" code samples for hero section\n- Implement Monaspace font family (Krypton, Argon, Neon, Xenon, Radon)\n- Fix light mode contrast for AAA accessibility (25-35% lightness)\n- Add subtle hue tint to light mode backgrounds\n- Throttle MapLibre style updates to prevent performance issues\n- Extract showcase animation logic to useShowcaseAnimation composable\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2025-12-28T01:55:55Z","url":"https://github.com/ejfox/vulpes-theme-lab/commit/904c4feaafd76069a4a2331d7ef35a404540fbd2","type":"feat"},{"repository":{"name":"vulpes-theme-lab","url":"https://github.com/ejfox/vulpes-theme-lab"},"message":"feat: make base, fg, and bg colors editable\n\n- Add base, fg, bg to editableSwatches set\n- These now have full controls (offset, lightness, link/unlink)\n- State properties already existed, just weren't exposed in UI\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2025-12-24T21:49:10Z","url":"https://github.com/ejfox/vulpes-theme-lab/commit/49e61119992595954c6e84b425ba3f6343df7ba0","type":"feat"},{"repository":{"name":"vulpes-theme-lab","url":"https://github.com/ejfox/vulpes-theme-lab"},"message":"fix: proper grid layouts for color swatches and presets\n\n- Use auto-fill grid for swatches to wrap into rows naturally\n- Change swatches from position:absolute to sticky for better flow\n- Use minmax(0, 1fr) pattern to allow grid items to shrink properly\n- Fix preset selector with proper grid and text sizing\n- Remove overflow:hidden band-aids in favor of real layout fixes\n- Responsive breakpoints updated for dynamic grid\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2025-12-24T21:45:09Z","url":"https://github.com/ejfox/vulpes-theme-lab/commit/328b48bab909f8bd10b895dca536b7a765d276d2","type":"fix"},{"repository":{"name":"vulpes-theme-lab","url":"https://github.com/ejfox/vulpes-theme-lab"},"message":"feat: add real SVG logos to export formats grid\n\n- Use official Simple Icons for Neovim, Alacritty, Git (Lazygit), Bash (ZSH)\n- Add VT323 pixelated font from Google Fonts for tools without icons\n- Show emoji/text for Ghostty (👻), Wezterm (WEZ), Bat (BAT), Yazi (🦆)\n- Faster animations (1.3x speed boost)\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2025-12-24T21:44:59Z","url":"https://github.com/ejfox/vulpes-theme-lab/commit/ad721985a52afa161fba6a70b2d149fd54a3cfe0","type":"feat"},{"repository":{"name":"electology-visual-diffs","url":"https://github.com/ejfox/electology-visual-diffs"},"message":"add essay-toolkit PR media","occurredAt":"2026-09-22T17:11:38Z","url":"https://github.com/ejfox/electology-visual-diffs/commit/e1e7177ccaa158e70eba83081f2a332e421f1e46","type":"other"},{"repository":{"name":"electology-visual-diffs","url":"https://github.com/ejfox/electology-visual-diffs"},"message":"add PR media for electology #69 loading bar","occurredAt":"2026-09-22T16:36:12Z","url":"https://github.com/ejfox/electology-visual-diffs/commit/afa96d0590a5bc4132d49554af05d2d607789d16","type":"other"},{"repository":{"name":"electology-visual-diffs","url":"https://github.com/ejfox/electology-visual-diffs"},"message":"Initial commit","occurredAt":"2026-09-17T17:06:07Z","url":"https://github.com/ejfox/electology-visual-diffs/commit/3c17864d24534dd9f1d235f0303803d0f27c29f5","type":"other"},{"repository":{"name":"vulpino","url":"https://github.com/ejfox/vulpino"},"message":"Merge pull request #1 from ejfox/fix/build-from-clean-clone","occurredAt":"2026-09-23T19:39:01Z","url":"https://github.com/ejfox/vulpino/commit/a46bdc9b5cdfeb2d690e7769f86d75cca1eb873f","type":"other"},{"repository":{"name":"vulpino","url":"https://github.com/ejfox/vulpino"},"message":"fix(widget): migrate to App Intents; fix Color.quaternary type error\n\n- SelectWidgetIntent is a modern App Intents WidgetConfigurationIntent, but\n  the provider used the legacy SiriKit IntentTimelineProvider + IntentConfiguration\n  (which require an INIntent). Migrated to AppIntentTimelineProvider (async\n  snapshot/timeline) + AppIntentConfiguration, and .widgetConfig?.identifier\n  -> .id (AppEntity id).\n- JSONTreeView: a ternary mixed Color (.blue) with hierarchical ShapeStyles\n  (.secondary/.quaternary), which don't share a type; wrapped each in\n  AnyShapeStyle so foregroundStyle unifies. Preserves the exact intent.\n\nBuilds clean for the iOS 26 simulator (app + widget); installs and launches.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>","occurredAt":"2026-09-21T03:55:47Z","url":"https://github.com/ejfox/vulpino/commit/946a0b1f6170bcd71ca6b783f2cc3046af2afa13","type":"fix"},{"repository":{"name":"vulpino","url":"https://github.com/ejfox/vulpino"},"message":"fix(project): repair Xcode project so it builds from a clean clone\n\nThree project-file defects (edits made outside Xcode that never landed in\nproject.pbxproj) meant a fresh clone did not build:\n\n- App entry file mis-pathed: referenced as VulpinoApp/VulpinoApp.swift but it\n  lives in VulpinoApp/Sources/. Fixed the PBXFileReference path.\n- Six sources existed on disk but were in NO target, so anything referencing\n  them failed to compile: OnboardingView, SettingsView, WidgetCreatedView,\n  AppIconView, HapticService (app), and shared Formatters (app + widget).\n- Widget-dependency proxy pointed remoteGlobalIDString at the app's own\n  product (Vulpino.app) instead of the widget TARGET (AC000005). xcodebuild\n  crashed with an internal 'unrecognized selector' walking dependencies, and\n  the widget never built.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>","occurredAt":"2026-09-21T03:55:47Z","url":"https://github.com/ejfox/vulpino/commit/76763a2da46e459cdfad46affab2c676367fc3ee","type":"fix"},{"repository":{"name":"vulpino","url":"https://github.com/ejfox/vulpino"},"message":"Add SwiftLint configuration\n\nConfigures SwiftLint for Xcode with sensible defaults:\n- Relaxed line length and body length rules\n- Enabled useful opt-in rules for better code quality\n- Excluded build directories\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-10T23:57:07Z","url":"https://github.com/ejfox/vulpino/commit/42b49f25dd02a307a3e73768ba99a0bfbec6e67d","type":"other"},{"repository":{"name":"vulpino","url":"https://github.com/ejfox/vulpino"},"message":"Add search and auto-expand for deeply nested JSON\n\n- Search bar filters by key names, values, and paths\n- Matching nodes highlighted in yellow\n- First 2 levels auto-expand on load\n- Expand All / Collapse All buttons\n- Auto-expands parent nodes when searching\n\nMakes navigating complex nested APIs much easier.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-10T23:50:22Z","url":"https://github.com/ejfox/vulpino/commit/0073aaf60b3d5c39782fe6169073d549005e133a","type":"other"},{"repository":{"name":"vulpino","url":"https://github.com/ejfox/vulpino"},"message":"Add final polish: accessibility, dark mode, launch screen, App Store copy\n\n- Full VoiceOver accessibility for all 7 widget templates\n- Semantic colors for proper light/dark mode adaptation\n- Launch screen configuration with branded background\n- Asset catalog with accent and launch colors\n- App Store description and metadata\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-10T23:44:41Z","url":"https://github.com/ejfox/vulpino/commit/c2aefc5823b2684d883e793456de5696fa0a8f73","type":"other"},{"repository":{"name":"vulpino","url":"https://github.com/ejfox/vulpino"},"message":"Add privacy policy and terms of service\n\nLegal pages in both Markdown and HTML formats:\n- legal/privacy.md + legal/privacy.html\n- legal/terms.md + legal/terms.html\n\nKey points covered:\n\nPrivacy Policy:\n- All data stored locally on device\n- No analytics, tracking, or data collection\n- API keys stored in secure Keychain\n- Network requests go directly to user-configured endpoints\n- Clear data deletion instructions\n\nTerms of Service:\n- User responsible for URLs they connect to\n- User responsible for API key security\n- No warranty on third-party data accuracy\n- Don't rely on app for critical decisions\n- Standard limitation of liability\n\nHTML pages styled in Vignelli tradition:\n- Georgia serif body text\n- Helvetica headings\n- Classic blue links\n- Clean, readable layout\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-10T23:37:25Z","url":"https://github.com/ejfox/vulpino/commit/2370fffb86f80cdbbafc0d78afe1634930143183","type":"other"},{"repository":{"name":"vulpino","url":"https://github.com/ejfox/vulpino"},"message":"App Store readiness: privacy, accessibility, safety\n\nPrivacy & Legal:\n- Add PrivacyInfo.xcprivacy manifests for app and widget\n- Declare UserDefaults and FileTimestamp API usage with reasons\n- Add Settings screen with privacy policy and terms links\n- Add data management screen with delete all option\n- Link to GitHub for documentation and issue reporting\n\nSafety:\n- Add 1MB response size limit to prevent memory issues\n- Add per-host rate limiting (1 request/second minimum)\n- Add User-Agent header for responsible API usage\n- Add responseTooLarge and rateLimited error cases\n\nAccessibility:\n- Add VoiceOver labels to MonoStatView template\n- Combine elements for better screen reader experience\n\nSettings:\n- Gear icon in navigation bar opens settings\n- Show onboarding option for re-viewing intro\n- Version number display\n- Credits section with \"Vulpino dice no\" tagline\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-10T23:19:02Z","url":"https://github.com/ejfox/vulpino/commit/7b556c0f51def1d092ba2209d3843a1668340e4a","type":"other"},{"repository":{"name":"vulpino","url":"https://github.com/ejfox/vulpino"},"message":"Polish and refine the Vulpino experience\n\nUX Improvements:\n- Add 4-page onboarding flow introducing key concepts\n- Add success screen after widget creation with home screen instructions\n- Add example endpoints sheet (GitHub Status, CoinGecko, etc.)\n- Add URL validation with real-time feedback\n- Add test endpoint button showing latency\n- Use SecureField for API key/header values\n\nHaptics:\n- Add HapticService for consistent tactile feedback\n- Tap feedback on selections and navigation\n- Success/error feedback on API tests and saves\n\nFormatting:\n- Add Formatters utility with smart number formatting (K/M/B suffixes)\n- Add percentage, currency, duration formatters\n- Add relative time formatting (\"2h ago\", \"just now\")\n- Add \"as of\" time formatting for timestamp template\n\nDeep Linking:\n- Register vulpino:// URL scheme\n- Widget taps open custom URL or deep link to editor\n- Handle vulpino://widget/{id} to open specific widget\n\nVisual:\n- Add geometric fox app icon view (SwiftUI-based)\n- Improve empty state with tagline\n- Better error state styling\n- Content margins disabled on widgets for edge-to-edge display\n\nDocumentation:\n- Add comprehensive README with architecture overview\n- Document all templates and their use cases\n- Include example endpoints for testing\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-10T20:46:10Z","url":"https://github.com/ejfox/vulpino/commit/3c529895e57f53a588c12c2a8fa79dde168b1860","type":"other"},{"repository":{"name":"vulpino","url":"https://github.com/ejfox/vulpino"},"message":"Implement full Vulpino iOS app\n\nComplete implementation of the JSON-to-widget iOS app:\n\nCore Features:\n- Paste any JSON URL, auto-parse structure\n- Select data fields via interactive tree view\n- 7 opinionated typographic templates:\n  - Mono Stat (single large number)\n  - Dual Stat (two numbers side by side)\n  - Stat Stack (3-5 key-value pairs)\n  - Headline (large text)\n  - List (bulleted items)\n  - Grid (2x2 or 3x2 stats)\n  - Timestamp (value with time)\n- Support for all iOS widget sizes (small/medium/large)\n- Custom label editing for JSON keys\n- Configurable refresh intervals\n\nArchitecture:\n- SwiftUI + WidgetKit\n- App Group for data sharing between app and widget\n- Keychain storage for API keys/auth headers\n- Offline-first with cached data and stale indicators\n- App Intents for widget configuration\n\n\"Vulpino dice no\" to customization theater.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-10T20:37:39Z","url":"https://github.com/ejfox/vulpino/commit/63da09f43d7861d21246e3315f4eb9902c8d64d4","type":"other"},{"repository":{"name":"vulpino","url":"https://github.com/ejfox/vulpino"},"message":"Add Vulpino reverse etymology\n\nThe little fox that says no to customization theater.\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-10T20:26:51Z","url":"https://github.com/ejfox/vulpino/commit/2bbffc014dfbd3def0495052361cae0532b0a0ab","type":"other"},{"repository":{"name":"vulpino","url":"https://github.com/ejfox/vulpino"},"message":"Initial commit: Vulpino iOS app scaffold\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-10T20:25:19Z","url":"https://github.com/ejfox/vulpino/commit/9c58c683d5ceb2c2bb045177d957727c08cf3c5e","type":"other"},{"repository":{"name":"tmux-link-grab","url":"https://github.com/ejfox/tmux-link-grab"},"message":"fix: Unicode punctuation no longer swallowed into URLs\n\nhttps://ejfox.com—great, https://ejfox.com’s, CJK 。， and similar\nnow end the URL. A split_punct pre-pass turns Unicode punctuation and\nTUI borders into spaces before matching, which also makes smart quotes\nand full-width brackets valid delimiters before bare hosts\n(“ejfox.com”) and splits comma-glued URLs. Replaces the old trailing\ndecoration list. 25 new regression tests (228 total).\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-04T15:35:40Z","url":"https://github.com/ejfox/tmux-link-grab/commit/8734e0086c37376d130688d4007da331cf17ccf3","type":"fix"},{"repository":{"name":"tmux-link-grab","url":"https://github.com/ejfox/tmux-link-grab"},"message":"feat: smarter URL detection — bare domains, git remotes, GFM trimming (v3.2.0)\n\nDetection is now two-stage: a greedy candidate grep, then a clean_urls\nawk pass that trims edges GFM-autolink style (trailing punctuation,\nunbalanced brackets, TUI box-drawing) and validates hosts.\n\n- Bare domains (github.com/x) via a curated TLD list from W3Techs'\n  top ~100; file-extension/English-word TLDs need a lowercase host and\n  a /path; known platform hosts (*.vercel.app, *.pages.dev) count bare\n- Rejects code-shaped text: method calls, email local parts,\n  mixed-case TLDs (import.meta.env.DEV), reverse-DNS IDs\n- IPv4/IPv6/IDN/single-label hosts, uppercase schemes, userinfo\n- git@, ssh://, git+ssh:// and \"To host:owner/repo.git\" → https\n- Test suite 28 → 203 cases\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-04T15:10:23Z","url":"https://github.com/ejfox/tmux-link-grab/commit/10f93ca39e23580a0ef33e77ec851503b7af0c6b","type":"feat"},{"repository":{"name":"tmux-link-grab","url":"https://github.com/ejfox/tmux-link-grab"},"message":"fix: fzf popup follows terminal ANSI palette (v3.1.1)\n\nReplace hardcoded `pointer:red` with a full --color spec using\npalette indexes (-1 default, 0-15 ANSI) so the picker renders\ncorrectly in both light and dark terminal themes without any\nconfiguration.","occurredAt":"2026-04-24T15:41:49Z","url":"https://github.com/ejfox/tmux-link-grab/commit/ec5f729ad53f9ec5f759b509970caffa67a55f76","type":"fix"},{"repository":{"name":"tmux-link-grab","url":"https://github.com/ejfox/tmux-link-grab"},"message":"docs: add demo GIF to README\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>","occurredAt":"2026-04-20T14:26:55Z","url":"https://github.com/ejfox/tmux-link-grab/commit/18fe2e623a968d0efdb5a9e49fb95cf7937b7c34","type":"docs"},{"repository":{"name":"tmux-link-grab","url":"https://github.com/ejfox/tmux-link-grab"},"message":"docs: add CHANGELOG entry for v3.1.0\n\nCovers the four commits landing today: shellcheck cleanup +\n-J consistency fix, testability guard, test suite, and CI.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>","occurredAt":"2026-04-18T13:26:33Z","url":"https://github.com/ejfox/tmux-link-grab/commit/6afa9f21fb44161448ecd0889b8cfe7854efa358","type":"docs"},{"repository":{"name":"tmux-link-grab","url":"https://github.com/ejfox/tmux-link-grab"},"message":"ci: add shellcheck + bash-syntax + test workflow\n\n.github/workflows/ci.yml runs on every push to main and every PR:\n- shellcheck on grab-links.sh, plugin.tmux, and tests/run.sh\n- bash -n syntax check on all three\n- full tests/run.sh suite\n\nTests source grab-links.sh to exercise the URL regex and helpers\nwithout needing tmux installed in the runner — the tmux show-option\ncalls at parse time fail gracefully to defaults, which is itself a\nuseful property being verified.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>","occurredAt":"2026-04-18T13:25:54Z","url":"https://github.com/ejfox/tmux-link-grab/commit/527b14bcb4c0369fa5ab3ae24b84bd2f4fd595aa","type":"ci"},{"repository":{"name":"tmux-link-grab","url":"https://github.com/ejfox/tmux-link-grab"},"message":"test: add URL regex + helper function test suite\n\nAdds tests/run.sh, a self-contained bash test harness that sources\ngrab-links.sh to exercise its URL regex and helpers directly (no\ntmux or fzf involved).\n\n28 cases covering:\n- Happy-path HTTP/HTTPS matching with paths, queries, fragments,\n  subdomains, and URL encoding\n- Localhost special case (bare and with port)\n- Terminator characters that should NOT be captured into the URL\n  (closing parens, angle brackets, quotes, backticks)\n- Multiple URLs on one line (count assertions)\n- Non-matches: ftp://, bare IPs, file://, mailto:, plain text\n- reverse_lines portability (tac/tail -r/awk fallback)\n- Label-strip parameter expansion used in the main block\n\nAlso shellcheck-clean (one SC2016 suppressed with a comment\nexplaining the literal backticks in test input).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>","occurredAt":"2026-04-18T13:25:21Z","url":"https://github.com/ejfox/tmux-link-grab/commit/d7b80973ed729ed29f60f14581b82e95aecd8472","type":"test"},{"repository":{"name":"tmux-link-grab","url":"https://github.com/ejfox/tmux-link-grab"},"message":"refactor: guard main execution for testability\n\nWrap the main block in an if [[ BASH_SOURCE == $0 ]] check so\ntests (and future ad-hoc tooling) can source grab-links.sh to\naccess its functions without triggering the fzf popup and tmux\nside effects.\n\nCURRENT_PANE is now initialized to empty via : \"\\${CURRENT_PANE:=}\"\nat the top-level so sourced callers can override it or leave it\nempty for non-tmux contexts. The main block reassigns it from\ntmux display-message when the script is run directly.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>","occurredAt":"2026-04-18T13:24:13Z","url":"https://github.com/ejfox/tmux-link-grab/commit/66f7a4ff0fe49fd80d04b6e7d06bcd807e6c236f","type":"refactor"},{"repository":{"name":"tmux-link-grab","url":"https://github.com/ejfox/tmux-link-grab"},"message":"fix: shellcheck clean + strict mode + capture-pane -J consistency\n\n- Add `set -uo pipefail` (not -e: grep returns 1 on empty matches,\n  which is a normal case when the scrollback has no URLs)\n- Fix all 5 shellcheck warnings:\n  - 5× SC2155 (separate local declaration from assignment so\n    return values aren't masked)\n  - 1× SC2001 (replace sed-based label strip with parameter\n    expansion: ${SELECTED#\\[*\\] })\n- Add -J to extract_urls' capture-pane call so window/session\n  scopes correctly join wrapped-across-width URLs, matching\n  the behavior of the pane-scope fallback branch\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>","occurredAt":"2026-04-18T13:23:10Z","url":"https://github.com/ejfox/tmux-link-grab/commit/0ade0626186e46320542aa546e786d1e87135274","type":"fix"},{"repository":{"name":"tmux-link-grab","url":"https://github.com/ejfox/tmux-link-grab"},"message":"fix: replace tac with portable reverse_lines for macOS compatibility\n\nmacOS doesn't ship GNU tac. Without coreutils installed, tac silently\nfails and eats all piped input, causing the plugin to report \"No URLs\nfound\" even when URLs are present.\n\nAdded reverse_lines() helper that tries tac (GNU), then tail -r\n(macOS built-in), then awk as a last resort.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>","occurredAt":"2026-03-05T18:59:06Z","url":"https://github.com/ejfox/tmux-link-grab/commit/04bb666ab2fb2ef20464bd05508ab8d6c2246ef1","type":"fix"},{"repository":{"name":"tmux-link-grab","url":"https://github.com/ejfox/tmux-link-grab"},"message":"fix: exclude backticks from URL pattern\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-16T20:18:32Z","url":"https://github.com/ejfox/tmux-link-grab/commit/3bc8975745f6f1a0224f6ece81716b15c204bb39","type":"fix"},{"repository":{"name":"tmux-link-grab","url":"https://github.com/ejfox/tmux-link-grab"},"message":"fix: enable filtering, add header hint, pre-select first URL\n\n- Remove --disabled so typing filters the list\n- Add header showing keybinds\n- First URL (most recent from current pane) is pre-selected\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-16T20:17:15Z","url":"https://github.com/ejfox/tmux-link-grab/commit/0145177fabd8d11c6a82b3e847a0fd58b4b606ca","type":"fix"},{"repository":{"name":"tmux-link-grab","url":"https://github.com/ejfox/tmux-link-grab"},"message":"feat!: proper tmux citizen with native options\n\nBREAKING CHANGE: config now via tmux options, not script variables\n\n- Configure with `set -g @link-grab-*` in tmux.conf\n- Auto keybinding via plugin.tmux\n- New 'buffer' action for tmux paste buffer\n- Status line feedback on actions\n- Respects user's copy-command setting\n- @link-grab-key to customize keybinding\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-16T20:12:49Z","url":"https://github.com/ejfox/tmux-link-grab/commit/d312c0cc366819e4da358b6e9e91927c957f240d","type":"other"},{"repository":{"name":"tmux-link-grab","url":"https://github.com/ejfox/tmux-link-grab"},"message":"feat: add pane labels and persistent URL history\n\n- URLs from other panes show [command] prefix\n- Opened/copied URLs saved to ~/.tmux-link-history\n- New SCOPE=\"history\" to browse past URLs\n- SHOW_LABELS, HISTORY_FILE, HISTORY_MAX config options\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-16T20:05:59Z","url":"https://github.com/ejfox/tmux-link-grab/commit/52a5b3b503a5f605dae3c601b84b1dda6ff21e4c","type":"feat"},{"repository":{"name":"tmux-link-grab","url":"https://github.com/ejfox/tmux-link-grab"},"message":"feat: add session scope for searching all panes across entire session\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-16T19:55:48Z","url":"https://github.com/ejfox/tmux-link-grab/commit/2bc85506593e29d4168b391116a10210a79e36d6","type":"feat"},{"repository":{"name":"weddings","url":"https://github.com/ejfox/weddings"},"message":"Remove client-side AI keys from public runtimeConfig (#1)\n\nruntimeConfig.public is serialized into every rendered HTML page, so any\nOPENROUTER_API_KEY/OPENAI_API_KEY set at build time would ship to every\nvisitor. This exact pattern leaked an OpenRouter key from spacepunk-logi\nfor 9 months (2026-10). Both values are empty in production today and the\nuseOpenRouter composable has no callers, so this removes it outright.\n\nCo-authored-by: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-07T17:44:15Z","url":"https://github.com/ejfox/weddings/commit/be407288295c0ad962527da544a55243b6403b78","type":"other"},{"repository":{"name":"weddings","url":"https://github.com/ejfox/weddings"},"message":"update nuxt config and homepage layout\n\n- modernize nuxt configuration settings\n- update package dependencies\n- refine homepage design and content\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>","occurredAt":"2025-07-24T14:50:13Z","url":"https://github.com/ejfox/weddings/commit/d63baca4c84fd42cd9a8699524e9400e1f99e5b5","type":"other"},{"repository":{"name":"weddings","url":"https://github.com/ejfox/weddings"},"message":"docs: comprehensive devlog documenting luxury wedding site transformation\n\nDocument complete development process from basic portfolio to $8,500 conversion powerhouse:\n\n• Phase-by-phase development breakdown\n• 2025 conversion optimization research and implementation\n• Technical architecture and design philosophy\n• Expected performance metrics based on data\n• Deployment process and live site details\n\nChronicles transformation using data-driven UX, multi-step forms, social proof,\nurgency psychology, and Vue.js interactivity for premium Hudson Valley positioning.\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>","occurredAt":"2025-06-13T20:17:38Z","url":"https://github.com/ejfox/weddings/commit/eec426109c55600203ff7c85804304bf1cce81ce","type":"docs"},{"repository":{"name":"weddings","url":"https://github.com/ejfox/weddings"},"message":"feat: transform into luxury wedding photography conversion powerhouse\n\nImplement 2025 conversion optimization best practices with data-backed improvements:\n\n• Multi-step booking form (300% conversion boost potential)\n• Dynamic urgency messaging and scarcity psychology\n• Social proof with testimonials and trust indicators\n• Enhanced CTA strategy with floating sticky button\n• Gallery with scroll animations and staggered reveals\n• Performance optimizations with lazy loading\n• Luxury positioning at $8,500 with estate branding\n• Mobile-responsive design throughout\n• SEO optimization with structured data\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>","occurredAt":"2025-06-13T20:07:40Z","url":"https://github.com/ejfox/weddings/commit/fd702e354ea3aabbafe9f789a812c9c05e7620dc","type":"feat"},{"repository":{"name":"weddings","url":"https://github.com/ejfox/weddings"},"message":"feat: begin project 🪴","occurredAt":"2025-06-13T16:21:43Z","url":"https://github.com/ejfox/weddings/commit/ba0b33c45cfc8bc37157e6a589dbf48427c8e371","type":"feat"},{"repository":{"name":"paramilitary-leaks-frontend","url":"https://github.com/ejfox/paramilitary-leaks-frontend"},"message":"Remove client-side AI keys from public runtimeConfig (#1)\n\nruntimeConfig.public is serialized into every rendered HTML page, so any\nOPENROUTER_API_KEY/OPENAI_API_KEY set at build time would ship to every\nvisitor. This exact pattern leaked an OpenRouter key from spacepunk-logi\nfor 9 months (2026-10). Both values are empty in production today and the\nuseOpenRouter composable has no callers, so this removes it outright.\n\nCo-authored-by: Claude Opus 5.5 <noreply@anthropic.com>","occurredAt":"2026-10-07T17:44:24Z","url":"https://github.com/ejfox/paramilitary-leaks-frontend/commit/0fa4b8fd9e3d4efc55903794e6f2c6340d5f012f","type":"other"},{"repository":{"name":"paramilitary-leaks-frontend","url":"https://github.com/ejfox/paramilitary-leaks-frontend"},"message":"feat(narrative): improve video playback with autoplay and poster images","occurredAt":"2025-04-06T15:19:26Z","url":"https://github.com/ejfox/paramilitary-leaks-frontend/commit/6838557518d541ed0983b21623aafdcdbf17a7b9","type":"feat"},{"repository":{"name":"paramilitary-leaks-frontend","url":"https://github.com/ejfox/paramilitary-leaks-frontend"},"message":"feat: Add autoplay, loop, and muted attributes to narrative page videos","occurredAt":"2025-04-06T15:09:54Z","url":"https://github.com/ejfox/paramilitary-leaks-frontend/commit/36c3ab5d33de9b8bb57d4fd0d440fe1ae9725a98","type":"feat"},{"repository":{"name":"paramilitary-leaks-frontend","url":"https://github.com/ejfox/paramilitary-leaks-frontend"},"message":"feat: Add poster images and hover effects for narrative videos","occurredAt":"2025-04-06T15:09:30Z","url":"https://github.com/ejfox/paramilitary-leaks-frontend/commit/228d1a265da190aa2b8e4a000e0e6a1cdd24c6b4","type":"feat"},{"repository":{"name":"paramilitary-leaks-frontend","url":"https://github.com/ejfox/paramilitary-leaks-frontend"},"message":"refactor: Simplify video implementation with direct Cloudinary URLs and native controls","occurredAt":"2025-04-06T15:08:35Z","url":"https://github.com/ejfox/paramilitary-leaks-frontend/commit/a6203c75871cf63b77889fb84cf7f82698a7a3d6","type":"refactor"},{"repository":{"name":"paramilitary-leaks-frontend","url":"https://github.com/ejfox/paramilitary-leaks-frontend"},"message":"feat: Improve video loading and error handling in narrative page","occurredAt":"2025-04-06T15:05:59Z","url":"https://github.com/ejfox/paramilitary-leaks-frontend/commit/2ca99419a0ebdc343fc81e1d2752940c02e5ab5d","type":"feat"},{"repository":{"name":"paramilitary-leaks-frontend","url":"https://github.com/ejfox/paramilitary-leaks-frontend"},"message":"refactor: Simplify narrative page layout and update demo video content","occurredAt":"2025-04-06T15:05:57Z","url":"https://github.com/ejfox/paramilitary-leaks-frontend/commit/8ae8e67a9f526ec5ce39f2b1cf31700ab706016b","type":"refactor"},{"repository":{"name":"paramilitary-leaks-frontend","url":"https://github.com/ejfox/paramilitary-leaks-frontend"},"message":"chore: bump version to 0.0.5 and update changelog","occurredAt":"2025-04-05T16:33:17Z","url":"https://github.com/ejfox/paramilitary-leaks-frontend/commit/bc88c8087e6179d20d8ec028308b3895894e0561","type":"chore"},{"repository":{"name":"paramilitary-leaks-frontend","url":"https://github.com/ejfox/paramilitary-leaks-frontend"},"message":"chore: update changelog to include recent enhancements in TopBar component and user experience improvements","occurredAt":"2025-04-05T16:31:11Z","url":"https://github.com/ejfox/paramilitary-leaks-frontend/commit/f56e4a186ff44e21c63267063535c4c1260a499d","type":"chore"},{"repository":{"name":"paramilitary-leaks-frontend","url":"https://github.com/ejfox/paramilitary-leaks-frontend"},"message":"feat: enhance StreamGraph and ScrollStreamGraph components with new default layout prop, improved top 5 senders display, and optimized video handling for better user experience","occurredAt":"2025-04-05T01:51:36Z","url":"https://github.com/ejfox/paramilitary-leaks-frontend/commit/8b495bcb30793170661ba87dcbfbcd07a34ec03a","type":"feat"},{"repository":{"name":"paramilitary-leaks-frontend","url":"https://github.com/ejfox/paramilitary-leaks-frontend"},"message":"feat: simplify scroll progress handling and improve performance with a new ultra simple scroll handler for enhanced user experience","occurredAt":"2025-04-05T00:28:53Z","url":"https://github.com/ejfox/paramilitary-leaks-frontend/commit/d426d5d5396a3caa461b4c0251d96ae9c7c64a84","type":"feat"},{"repository":{"name":"paramilitary-leaks-frontend","url":"https://github.com/ejfox/paramilitary-leaks-frontend"},"message":"feat: enhance narrative components with new visual elements, improved animations, and responsive design adjustments for better user experience","occurredAt":"2025-04-05T00:15:47Z","url":"https://github.com/ejfox/paramilitary-leaks-frontend/commit/33348ccb06994a0838a85ee0113f33e6535b8c0e","type":"feat"},{"repository":{"name":"paramilitary-leaks-frontend","url":"https://github.com/ejfox/paramilitary-leaks-frontend"},"message":"chore: update changelog to reflect recent feature additions and improvements in user experience components","occurredAt":"2025-03-29T20:35:55Z","url":"https://github.com/ejfox/paramilitary-leaks-frontend/commit/d68f4e8d718935429e9d80c1086cc36eb9047bc3","type":"chore"},{"repository":{"name":"paramilitary-leaks-frontend","url":"https://github.com/ejfox/paramilitary-leaks-frontend"},"message":"feat: implement page transitions and loading indicators with new components for enhanced user experience","occurredAt":"2025-03-28T18:46:07Z","url":"https://github.com/ejfox/paramilitary-leaks-frontend/commit/ed56ec82270d4ee9378d664f15b469389aba623f","type":"feat"},{"repository":{"name":"paramilitary-leaks-frontend","url":"https://github.com/ejfox/paramilitary-leaks-frontend"},"message":"chore: bump version to 0.0.4 and update changelog","occurredAt":"2025-03-26T20:29:29Z","url":"https://github.com/ejfox/paramilitary-leaks-frontend/commit/a81b720da837ec84d5a58f899035e04b9e8c20a1","type":"chore"},{"repository":{"name":"ejfox","url":"https://github.com/ejfox/ejfox"},"message":"Update README with new badges\n\nUpdated social media badges and added Paperclip badge.","occurredAt":"2026-10-06T22:39:48Z","url":"https://github.com/ejfox/ejfox/commit/b26b7b2474b1bbd5204de88347edb7b4f73eb040","type":"other"},{"repository":{"name":"ejfox","url":"https://github.com/ejfox/ejfox"},"message":"Enable GitHub Sponsors\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>","occurredAt":"2026-01-17T18:25:49Z","url":"https://github.com/ejfox/ejfox/commit/84fbbe39823537f54ca54a4dcb46ad2e002ac5c5","type":"other"},{"repository":{"name":"ejfox","url":"https://github.com/ejfox/ejfox"},"message":"nvm","occurredAt":"2024-05-28T01:57:55Z","url":"https://github.com/ejfox/ejfox/commit/21a7931581076cb92fde7a91a53f8361b80f1217","type":"other"},{"repository":{"name":"ejfox","url":"https://github.com/ejfox/ejfox"},"message":"Update README.md with GitHub sponsorship","occurredAt":"2024-05-28T01:57:46Z","url":"https://github.com/ejfox/ejfox/commit/270d3df29fcd0cd0edd737dd45442abb8fe75634","type":"other"},{"repository":{"name":"ejfox","url":"https://github.com/ejfox/ejfox"},"message":"Update README.md","occurredAt":"2023-11-09T22:30:30Z","url":"https://github.com/ejfox/ejfox/commit/545b3f677115a04a05b8ac43c4f6911384bee3f7","type":"other"},{"repository":{"name":"ejfox","url":"https://github.com/ejfox/ejfox"},"message":"rip twitter","occurredAt":"2023-08-28T15:49:08Z","url":"https://github.com/ejfox/ejfox/commit/40cb6696121525e8aeb45a769cb3e8f73fecae5a","type":"other"},{"repository":{"name":"ejfox","url":"https://github.com/ejfox/ejfox"},"message":"Update README.md","occurredAt":"2022-11-09T14:22:33Z","url":"https://github.com/ejfox/ejfox/commit/6e183eea351926f29df1d5d0fbf4487864c9bb53","type":"other"},{"repository":{"name":"ejfox","url":"https://github.com/ejfox/ejfox"},"message":"add social media badges and website section","occurredAt":"2022-06-21T02:30:09Z","url":"https://github.com/ejfox/ejfox/commit/402e83343c0035d06f089441e6c8c9c6e28ffbd4","type":"other"},{"repository":{"name":"ejfox","url":"https://github.com/ejfox/ejfox"},"message":"Update README.md","occurredAt":"2022-06-20T22:54:27Z","url":"https://github.com/ejfox/ejfox/commit/6fb25c4d7039ee41361fdb8d1fd2386453ad0623","type":"other"},{"repository":{"name":"ejfox","url":"https://github.com/ejfox/ejfox"},"message":"Update README.md","occurredAt":"2022-06-20T22:53:26Z","url":"https://github.com/ejfox/ejfox/commit/8a7a6294d88007c3809fde320396f008aba96d30","type":"other"},{"repository":{"name":"ejfox","url":"https://github.com/ejfox/ejfox"},"message":"Initial commit","occurredAt":"2022-06-20T22:49:22Z","url":"https://github.com/ejfox/ejfox/commit/61f30ecd84588f5ecc8e77a2ddff9d6ef2ba32ff","type":"other"},{"repository":{"name":"code-network-gen","url":"https://github.com/ejfox/code-network-gen"},"message":"Modernize analyzer and clean project layout","occurredAt":"2026-10-04T18:58:56Z","url":"https://github.com/ejfox/code-network-gen/commit/2d0b1285fb54034298c38a34f019072c14872c9b","type":"other"},{"repository":{"name":"code-network-gen","url":"https://github.com/ejfox/code-network-gen"},"message":"Merge pull request #1 from ejfox/copilot/update-codebase-for-2026","occurredAt":"2026-01-11T04:18:56Z","url":"https://github.com/ejfox/code-network-gen/commit/f9a2d1a9705ed88e5cdd9b32da4eb1e75d6ac1fb","type":"other"},{"repository":{"name":"code-network-gen","url":"https://github.com/ejfox/code-network-gen"},"message":"Fix linting warning in catch block\n\nCo-authored-by: ejfox <530073+ejfox@users.noreply.github.com>","occurredAt":"2026-01-11T03:10:12Z","url":"https://github.com/ejfox/code-network-gen/commit/49cd1238e9a1a68d93b4c9ecb31da89b5d870324","type":"other"},{"repository":{"name":"code-network-gen","url":"https://github.com/ejfox/code-network-gen"},"message":"Final updates: sync package-lock.json version and complete 2026 upgrade\n\nCo-authored-by: ejfox <530073+ejfox@users.noreply.github.com>","occurredAt":"2026-01-11T03:09:18Z","url":"https://github.com/ejfox/code-network-gen/commit/32e8df102c65e60d6852a5299f41af36dc74c1d1","type":"other"},{"repository":{"name":"code-network-gen","url":"https://github.com/ejfox/code-network-gen"},"message":"Update index.js\n\nCo-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>","occurredAt":"2026-01-11T03:08:40Z","url":"https://github.com/ejfox/code-network-gen/commit/5e6ff8533a6ac2de69ad22df5eb42447e3bc0a12","type":"other"},{"repository":{"name":"code-network-gen","url":"https://github.com/ejfox/code-network-gen"},"message":"Upgrade dependencies and fix all linting errors for 2026\n\nCo-authored-by: ejfox <530073+ejfox@users.noreply.github.com>","occurredAt":"2026-01-11T03:04:39Z","url":"https://github.com/ejfox/code-network-gen/commit/07c858221f18a80c126363ff705bfde2b42b0ba4","type":"other"},{"repository":{"name":"code-network-gen","url":"https://github.com/ejfox/code-network-gen"},"message":"Initial assessment - preparing upgrade plan for 2026\n\nCo-authored-by: ejfox <530073+ejfox@users.noreply.github.com>","occurredAt":"2026-01-11T02:59:41Z","url":"https://github.com/ejfox/code-network-gen/commit/21f06bdbb2791a7d5002b0d82ecfa5567d3d457d","type":"other"},{"repository":{"name":"code-network-gen","url":"https://github.com/ejfox/code-network-gen"},"message":"Initial plan","occurredAt":"2026-01-11T02:56:08Z","url":"https://github.com/ejfox/code-network-gen/commit/733098386beaa1c1f2b7f4d09a70883e5494f165","type":"other"},{"repository":{"name":"code-network-gen","url":"https://github.com/ejfox/code-network-gen"},"message":"docs: update README to reflect real import/require tracking\n\n- Clarified that --include-deps parses actual import statements\n- Updated example to show real edge format: data.js:global -> package.json:axios (imports)\n- Removed misleading 'adds all dependencies' language\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>","occurredAt":"2025-07-24T22:41:25Z","url":"https://github.com/ejfox/code-network-gen/commit/b51aff503dffe7608ec4fcbe5cdbcba7cddf0a0a","type":"docs"},{"repository":{"name":"code-network-gen","url":"https://github.com/ejfox/code-network-gen"},"message":"feat: parse actual import/require statements for real dependency tracking\n\n- Parse ES6 imports and require() calls from AST during code analysis\n- Show real file-to-dependency relationships instead of fake package.json globals\n- Example: data.js:global -> package.json:@supabase/supabase-js (imports)\n- Super efficient: only tracks dependencies that exist in package.json\n- Works with both import statements and require() calls\n\nNow --include-deps shows actual code-to-dependency usage patterns\\!\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>","occurredAt":"2025-07-24T22:38:11Z","url":"https://github.com/ejfox/code-network-gen/commit/503666ad7a26a1087c2db91f46334cdc59bf1f26","type":"feat"},{"repository":{"name":"code-network-gen","url":"https://github.com/ejfox/code-network-gen"},"message":"feat: add --include-deps flag for package.json dependency analysis\n\n- New --include-deps flag includes all dependencies and devDependencies\n- Dependencies shown as orange nodes with 'requires' edge type\n- Added dependency styling to mermaid diagrams with amber colors\n- Updated CLI help and README documentation\n- Package.json dependencies integrated seamlessly with code structure\n\nPerfect for understanding full project ecosystem including external deps.\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>","occurredAt":"2025-07-24T22:34:47Z","url":"https://github.com/ejfox/code-network-gen/commit/d0b24a8da2b406dbd8a23a11e6f61b04045af691","type":"feat"},{"repository":{"name":"code-network-gen","url":"https://github.com/ejfox/code-network-gen"},"message":"docs: add mermaid diagram to README example\n\n- Added interactive mermaid flowchart that renders on GitHub\n- Shows visual architecture of the example CLI app\n- Demonstrates color-coded function types and module boundaries\n- Perfect for showcasing the tool's visual output capabilities\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>","occurredAt":"2025-07-24T22:32:35Z","url":"https://github.com/ejfox/code-network-gen/commit/c8162c23c1a0e3928b02b05e10ef4925c4e94b55","type":"docs"},{"repository":{"name":"code-network-gen","url":"https://github.com/ejfox/code-network-gen"},"message":"docs: add concrete example output to README\n\n- Added real-world example showing nodes.csv and edges.csv output\n- Shows analysis of CLI app with 12 functions across 4 files\n- Demonstrates clear architectural patterns (data/ui/main separation)\n- Makes the tool's output more tangible for new users\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>","occurredAt":"2025-07-24T22:31:23Z","url":"https://github.com/ejfox/code-network-gen/commit/f03f2d65cb0aa295161bd3f9d32043880fca9ea0","type":"docs"},{"repository":{"name":"code-network-gen","url":"https://github.com/ejfox/code-network-gen"},"message":"docs: update README with npx usage and version bump to 0.0.3\n\n- Updated all command examples to use npx code-network-gen\n- Added fallback node index.js usage for local development\n- Bumped version from 0.0.2 to 0.0.3\n- Verified all export formats working correctly\n- Comprehensive testing completed on multiple codebases\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>","occurredAt":"2025-07-24T22:24:43Z","url":"https://github.com/ejfox/code-network-gen/commit/50459d1e2c3c7cdeab1efefc31f21904967275c2","type":"docs"},{"repository":{"name":"code-network-gen","url":"https://github.com/ejfox/code-network-gen"},"message":"test: comprehensive testing across multiple codebases\n\nSuccessfully tested delete-driven development version on:\n- anime-beta: 400+ nodes, complex animation library\n- obsidian-analysis: 35 nodes, 53 edges, data analysis tools\n- connectology2: 226 nodes, 282 edges, full-stack Nuxt app\n- zackgaydos: 35 nodes, 36 edges, personal site\n- ARCHIVE: 544 nodes, 2044 edges, massive multi-project archive\n\nAll export formats working: CSV, GEXF, GraphML, DOT, Mermaid\nMinified file filtering working correctly\nTypeScript parsing gracefully handled\nTool scales from tiny to massive codebases\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>","occurredAt":"2025-07-24T22:21:31Z","url":"https://github.com/ejfox/code-network-gen/commit/bd304278c15f1d8f4db85a40120aad443b70484a","type":"test"}],"commitTypes":[{"type":"other","count":140,"percentage":63.06306306306306},{"type":"feat","count":38,"percentage":17.117117117117118},{"type":"fix","count":17,"percentage":7.657657657657657},{"type":"docs","count":10,"percentage":4.504504504504505},{"type":"chore","count":9,"percentage":4.054054054054054},{"type":"refactor","count":3,"percentage":1.3513513513513513},{"type":"test","count":2,"percentage":0.9009009009009009},{"type":"style","count":1,"percentage":0.45045045045045046},{"type":"perf","count":1,"percentage":0.45045045045045046},{"type":"ci","count":1,"percentage":0.45045045045045046}]}},"_links":{"self":"https://ejfox.com/github/devtools.json","html":"https://ejfox.com/github/devtools","gists":"/gists.json"}}