4 Commits
Author SHA1 Message Date
Lucas WintherandClaude Opus 5 1156c358a7 fix: stop failing the build on a page that says it has no events
Infinity Nikki's wiki prints "There are no Events in this category"
between versions, and the refresh runner has honoured that since
2026-09-03 — it stores the empty parse as the source's real answer
rather than letting a quiet lane reach the broken tier. The feed build
never asked, so the same page arrived at CI as parsedCount 0,
indistinguishable from a parser that has stopped reading a redesigned
page, and brokenSources failed every build while every refresh stayed
green.

The runner's verdict cannot travel on its own: only a parser has seen
the page, and by the time brokenSources runs there is nothing left but
the feed. So the fact rides on SourceHealth, defaulted so an older feed
the service worker cached keeps validating and reads as the strict
answer.

Both ends now ask it the same way — of an empty parse only, from the
page's own words only — because a redesign yields zero rows too, and
excusing that is the silently emptied calendar the gate exists for.

The rule sits in a module rather than in build-feed.ts, which writes
public/ and so runs a build if a test imports it. That is how the two
ends drifted apart with nothing to catch it.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-06 18:02:16 +02:00
Lucas WintherandClaude Opus 5 ef109f224b Tell a broken source apart from a stale one
CI failed on Infinity Nikki yielding no events, and was wrong to. Its
snapshot parses to six events; every one of them had ended by the morning
the build ran. The parser is fine — `--now 2026-08-14` gives six, today
gives none — and the page simply has nothing current left on it.

eventCount is counted after expired events are dropped, so "this parser has
stopped reading a redesigned page" and "this page's events have all
finished" arrived as the same zero. Only the first means our code is wrong,
and only the first should redden a build. So the feed now records what each
document yields parsed as of its own capture date, before expiry, and the
check fails on that instead.

Nikki cannot refresh itself out of this, either: docs/SOURCES.md records
that Fandom refuses the Actions runner. A lane with an empty calendar is a
real problem, but it is a refresh problem, so it is reported on the build
log and left visible rather than thrown.

parsedCount is nullable and defaulted, never required: the client validates
the whole feed with safeParse and the service worker serves the last feed it
downloaded, so a required field would have made every cached feed fail
validation and taken the offline promise with it. Null also covers a source
whose bytes were never confirmed live — there is no date to parse "as of",
and a build is not failed on missing information.

The rule moved to shared/feed.ts. A test did pin the old one, by grepping
the workflow for the string — which proved the check existed, never that it
was right.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-28 05:54:17 +02:00
Lucas WintherandClaude Opus 5 09716054f4 fix(test): let the README link check stand down where there is no README
The check I added for `?template=` links read README.md unconditionally, and the
image build is the one place that runs this suite without it: `.dockerignore`
omits the README along with docs/ and AGENTS.md, so that editing a doc does not
invalidate the layer that installs, typechecks, tests and builds. `.github/` is
copied in for the opposite reason, which is why every other check in the file
ran there fine.

So this failed in a way CI could not see — the check job has the whole
repository and stayed green, while the container build went red on a file that
context leaves out on purpose. Skipping it there keeps the gate honest about
what it can actually inspect; the assertion still runs in CI and locally, which
is where a README link is edited in the first place.

Verified by running the suite inside the build stage: 516 pass, 1 skip, 0 fail,
against 517 pass and no skips in the full tree.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-17 23:31:12 +02:00
Lucas WintherandClaude Opus 5 02dd7b3ed4 feat(github): give readers two issue forms and link to them
Nothing a reader marks, types or ticks ever leaves their browser, so there is no
account and no server-side record to look anything up in after a report arrives.
Whatever the form captured is all there will ever be — which is the argument for
structured forms over a blank box, and for the bug form carrying the footer's
"event data last refreshed" line as a prefill. A stale calendar and a genuinely
wrong parse are indistinguishable from outside, eight sources cannot be fetched
from CI at all, and that line is the only thing that separates the two cases.

The feature form states the three constraints up front, because "sync across my
devices" and "have a model read the page" both have settled answers and a reader
deserves them before typing rather than after. It also points source requests at
the assessed-and-declined table: the loudest feedback on the first release was
that the game list is too short, so that is the request that arrives most, and a
wiki that forbids automated access or only archives finished events cannot be
used no matter how often it is asked for.

Blank issues stay enabled. A form that turns someone away loses the report, not
the noise.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-17 23:19:47 +02:00