The key rotated on every server restart, stranding every phone that
held the previous cookie — during active development that guaranteed a
wall of refusals from stale polling tabs after each restart. The key
now lives in data/.lan_key (gitignored, 0600 — the Playwright-state
treatment for credential-adjacent files) and is reused across
restarts; delete the file to rotate. A keyless browser navigation now
gets a one-line HTML page saying what to do instead of raw JSON.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016jXZFSTZQKzAC8fqpWSz9g
Per-photo raw results cached under data/extract_raw/ (gitignored) so
re-runs are free, --only re-extracts a single photo, and titles.json is
rebuilt with dedupe that keeps conflicting-edition sightings separate.
HEIC converts via pillow-heif; images downscale to <=1568px long edge;
model JSON parsed defensively (code fences, surrounding prose). Vision
callable is injectable — tests use a local fake; the real one uses the
anthropic SDK (approved) with the model from config.toml.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Design spec for the bggpipe shelf-to-BGG pipeline, CLAUDE.md and
bgg-api skill capturing BGG API constraints, ruff format-on-edit
hook, README, LICENSE, and .gitignore.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>