.impeccable/design.json was a derived copy of docs/DESIGN.md and the CSS,
read only by Impeccable's live panel, which this project does not use. It
had drifted two weeks behind while DESIGN.md stayed current, so DESIGN.md
is now the only design reference; /impeccable document regenerates the
sidecar if it is ever wanted.
The layout block's "1,099 tests" was 285 behind; it now names the suite
without a number, which only goes stale.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It records only this machine's consent to the design hook, so it has no
business in the shared history; the design sidecar beside it does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every snapshot is written to a sibling `.tmp-*` and renamed into place, so a
run killed mid-write leaves one behind. `refresh.yml` commits the whole
snapshots/ directory, which would pin that truncated page in git forever — and
the point of the atomic write was that a crash leaves nothing a reader can
mistake for a page.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The feed was generated from checked-in fixtures and only moved when
somebody captured a page by hand. This fetches.
bun run refresh caches each page raw under snapshots/ and rebuilds the
feed from what it cached; build-feed prefers a snapshot and falls back to
the fixture, so a clean checkout and the container build stay offline and
reproducible. The workflow runs it twice a day and commits only when a
page's bytes actually changed — a 304, an identical body or a rejected
parse all leave the tree clean — then dispatches ci.yml, which already
knows how to test, build and deploy.
Scraping conduct is enforced in code rather than left to good
intentions: one request per source per cycle, a six-hour floor checked
per source, conditional requests, a User-Agent with a contact URL, and
robots.txt honoured — failing closed, because a permission we could not
read is not a permission we have. No retries; a retry is a second
request.
A body that yields zero events is rejected and the previous snapshot
kept, so a redesigned wiki shows up as a stale timestamp rather than an
emptied calendar. One source down is a warning; all of them down fails
the run, so a cycle that learned nothing is never committed.
Tested entirely offline against an injected fetch and clock — no request
has ever been made to a live wiki from this code.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Emits exactly the shape GET /api/events.json will serve, so the client can
be developed against real parsed data before the server and database land.
Reads fixtures only, never the network.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bun is the runtime, bundler, test runner and SQLite driver, so zod is the
only dependency. Strict TS with noUncheckedIndexedAccess.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>