Make it mine's copying was inline in App and untested; it is now a pure
function with a test, so a change to either store can't make the copy
silently arrive empty. The question's buttons now say what they answer
when heard out of context. The prefs block and the spec now match what
shipped.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A reload can be served the browser's cached feed for minutes. The button
beside the data's age asks the server past that copy, swaps in a newer
feed without reloading, and says honestly what came back. Newer is
judged on events and sources, never the build stamp. The age now says
"just now" rather than "ended ago" when a fresh feed is a moment ahead
of the page's clock.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The switch sits beside the daily chores and answers the strip's question
too. Built-ins are listed with a link to their dated source. Make it mine
copies one into the reader's tasks, numbers and ticks included, and hides
the original while the copy exists. It's additive, so deleting the copy
brings the original back as it was.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The strip asks once, in one line, about a game on screen that has
built-ins. Yes puts them beside its dailies, drawn and counted like the
reader's own tasks, with a tooltip giving the source's date.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Both prefs are absent unless the reader answers, so built-ins are opt-in
for every install, old ones included. The question is asked only about a
game on screen, and only once. A built-in the reader made their own
stays hidden while the copy exists.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Ridu Weekly (1,300 points) and the Weekly Routine (10 points), each with
the page that states it and that page's own date, so a figure from an
old guide shows its age. Routines share the task shape, so they draw and
count like a reader's own.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review found that import and edit rebuilt a task from this build's parse.
That stripped any field it didn't know, and import dropped a newer
version's task entirely. Both now keep the record as stored and validate
only to display it.
An event whose goal is points can't be ticked, so it no longer counts as
waiting today: it counts with its week. The month-day field reset
itself to 1 when emptied; it now keeps a draft.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
They live in Your own, beside the reader's games and events. Every field
has a default the reader can accept unread (weekly, from Monday, ticked
off once) except the target, which nobody can guess for them. Save is
offered only when the store would accept what was typed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Some events want a number of points rather than a number of days. The
goal control gains Days and Points. Switching period keeps the measure
and the number, and the sheet keeps this period's number editable in
place. A target is capped where the schema reads it back, so a huge
number can't silently become no goal.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Tasks sit at the end of their game's group and are counted by their own
period, so a chore due Sunday is not "waiting on you today" every
morning. A number chip opens an editor under the strip instead of
ticking, since a chip is one target. Catch up offers last period's
number the way it offers yesterday's tick.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
They exist on this device and nowhere else, so an export without them is
a lossy backup. Both are additive keys, as custom games were: older files
lack them and still import. Tasks travel as stored, including any this
build cannot read.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Both stores keep what is on disk and validate where they read, unlike the
custom-event store. Filtering on load would let the next write delete a
newer version's records. Import merges by id, or by item and period for
amounts, and the later edit wins, so a restored backup cannot roll a
week back.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A task is a period that rolls on the game's reset and a measure that
fills it: days ticked, or a number against a target. Its status is the
goal status shape, so the dailies strip treats it like any other item.
Its ids get their own reserved space, as do the built-ins to come.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Weekly chores like 2,100 activity points are a number, not a count of
days, and monthly ones need a month. The status shape now carries its
measure and period start, so tasks can reuse it whole.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review found three ordinary actions that deleted a goal this build could
not read: "It repeats daily", pressing an already-pressed Off, and "not
daily" without saying so. Only "not daily" clears a goal now, and its
warning keys off what is stored, not what parses.
The count field was bound straight to the goal, so emptying it snapped
the old number back and typing appended to it. It now keeps a draft.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The goal sits under the checklist, where its count shows. With a goal
set, the caption counts against it instead of calling unticked days
missed. Reaching an event-wide goal offers Mark event done but never
takes it. Saying "not daily" says up front that it removes the goal.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
An event wanting five days of seven stays in the strip all week with its
count on the chip. Once the week is met it reads as done this week, and
it counts toward the header without a tick being invented. The burst
now watches today's ticks, so meeting a week by backfilling stays quiet.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Goals ride the existing record, so export and the later-edit-wins import
merge carry them with no new key. Setting one clears a contradicting
"not daily"; saying "not daily" clears the goal, so no conflict hides
in storage.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Some events want five days out of seven, not every day. The goal is the
reader's input, recomputed from the day log on every read, so backfills
and week rollovers need no bookkeeping. An unreadable stored goal reads
as none instead of being stripped, so a newer shape survives an older
bundle.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Check-in goals and weekly tasks both need a period longer than a day.
Working in game-day keys rather than instants means a week rolls exactly
where the game's own day does, per region, with no second clock.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Every server's reset hour and offset was checked against it, so it is
credited beside the schedules' sources.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Game-Time-Master gives the reset as 05:00 JST (20:00 UTC). The previous
04:00 was read off a single mission ending at 3:59AM JST.
Re-labels the game-day of some already-logged ticks.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Reverse: 1999 has an Asia server on UTC+8 alongside Global on UTC-5, both
resetting at 05:00. Asia readers were on Global's 10:00 UTC; theirs rolls
at 21:00 UTC. Source: Game-Time-Master.
Re-labels the game-day of some already-logged ticks for Asia readers.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Haoplay Asia resets at 05:00 UTC+8 and Haoplay Global at 21:00 UTC-8; the
app used the regional default at 04:00. Asia readers take the Asia server,
America and Europe take Global. Source: Game-Time-Master.
Re-labels the game-day of some already-logged ticks.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
NTE resets at 05:00 server time, not 04:00, and its America server runs
UTC-4. Asia and Europe rolled an hour early; America lands on the same
09:00 UTC instant and day key as before. Source: Game-Time-Master.
Re-labels the game-day of some already-logged ticks in Asia and Europe.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
One worldwide server on a fixed UTC-7 resetting at 13:00 (20:00 UTC); the
app used the regional default. Source: Game-Time-Master, which lists the
zone as fixed rather than Pacific.
Re-labels the game-day of some already-logged ticks.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The Global server resets at 05:00 UTC; the app used the regional default.
Source: Game-Time-Master.
Re-labels the game-day of some already-logged ticks.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The English/Japanese server resets once worldwide at 20:00 UTC; the app
used the regional default. Source: Game-Time-Master.
Re-labels the game-day of some already-logged ticks.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
One worldwide server resetting at 18:00 UTC; the app used the regional
default. Source: Game-Time-Master, corroborated by GameWith.
Re-labels the game-day of some already-logged ticks.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Umamusume Global resets once worldwide at 15:00 UTC (midnight JST); the app
used the regional default. Kept on the UTC calendar because the source's
dates are headed Availability (UTC). Source: Game-Time-Master.
Re-labels the game-day of some already-logged ticks.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Blue Archive Global is one worldwide server resetting at 19:00 UTC, but the
app used the regional default (20:00 / 09:00 / 03:00 UTC). Source:
Game-Time-Master, corroborated by two guides.
Re-labels the game-day of some already-logged ticks.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Infinity Nikki resets at 04:00 on America UTC-7 and Europe UTC+2, not the
regional default, so the app rolled the day 2h early for American readers
and 1h late for European ones. Source: Game-Time-Master.
Re-labels the game-day of some already-logged ticks for those readers.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A game's servers need not agree on the reset hour any more than on the
offset. Reverse: 1999 and Nikke spell their 05:00 out for all three
regions, so no reader's day key moves.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
readableHue returned every dark hue untouched on the claim that all of
them already cleared 4.5:1 there. Five did not, and Fate's navy was
1.8:1, so its name under the headline deadline was nearly invisible.
Those five are now lifted in lightness only, keeping hue and saturation;
the fifteen that pass are unchanged. The owner approved relaxing the
"dark theme does not move" rule to this, and AGENTS.md and PRD F15 say so.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Record lastConfirmedAt in snapshot metadata when a source is confirmed (200 or 304). This ensures git-committed snapshot metadata reflects when sources like wiki.gg were successfully pulled even when page HTML did not change, avoiding false pull overdue notices on downstream builds like GitHub Pages.
Document the forge responsibilities across AGENTS.md, README.md, ARCHITECTURE.md, INGESTION.md, and the CI workflow headers: GitHub Actions only builds and serves (Pages deployment) without fetching data sources, while Gitea Actions exclusively runs the scheduled refresh and publishes the container image.
When sources return 304, no git commit is created, but the cache holds updated confirmation timestamps. Publish the refreshed feed unconditionally on non-dry runs so CI rebuilds events.v1.json with fresh confirmation dates.
Derive source pull date from confirmation and recent content updates, preventing recently updated sources from displaying as pulled never or pull overdue.
The Blue Archive Wiki (bluearchive.wiki/wiki/Events) redesigned its
schedule, replacing the per-version MediaWiki tabber with a unified
#eventtable displaying JP and Global periods side-by-side.
- Parse #eventtable resolving GL Period, event titles, and article links
from .event-region-gl, with fallback to .event-region-jp.
- Maintain backwards compatibility with legacy tabber schedule format.
- Add pinned fixture fixtures/ba/bawiki-events-2026-09-17 and tests.
- Update snapshot, AGENTS.md, ARCHITECTURE.md, and INGESTION.md.
Move the scheduled refresh and container-registry CI workflows into
.gitea/workflows/ so Gitea Actions runs them natively. Update
.github/workflows/ci.yml to build with BASE_PATH and deploy to GitHub
Pages upon push from the mirror sync, removing the Gitea-specific
container registry step. Update Dockerfile, .dockerignore, and test
harness to test and copy workflows from .gitea/.
The pipeline change made a set of sentences false, and they are the only
record of why things are the way they are, so they move with it: the CI
section and deploy target in README, the cron and BASE_PATH notes in
ARCHITECTURE, the documented User-Agent in INGESTION, and the contact
URL in SOURCES.
Two comments in source were false in the same way and are fixed here
rather than left for the next reader. `serve.ts` said compression was
"the whole difference between the Docker image and the deployed site" —
the image *is* the deployed site now, so that negotiation is the only
compression any reader gets. `robots.ts` justified product-token
matching with "our contact URL contains the string StereotypicalCat",
which it no longer does; the hazard is the arbitrary substring, not that
one, so the comment now says so and the regression test keeps the URL
that actually caused it.
What is deliberately NOT rewritten: game8.co's refusal stays in the past
tense with the Gitea result marked unverified, in AGENTS.md, README,
SOURCES and FEEDBACK alike. A new runner address is the variable that
failure turns on, so it may well be served — but "may well be" is not
evidence, and the four places that would have to change are named
together so they change together once a cycle has actually run.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Add karendar.com as the event source for Punishing: Gray Raven (PGR).
Karendar publishes a dedicated Global event calendar with exact UTC
timestamps in clean server-rendered HTML.
- Register 'pgr' in GameId and GAMES registry (#CC292B, Kuro Games).
- Add parseWeekdayDayMonthYearUtc in src/ingest/dates.ts with unit tests.
- Implement karendarParser in src/ingest/parsers/karendar.ts reading
'week', 'ongoing', and 'upcoming' sections, mapping indefinite/permanent
ends to endsAt: null, and categorizing tags to EventType.
- Register pgr-karendar-events in src/ingest/adapters/index.ts.
- Add pinned fixture, expected output, and comprehensive test suites.
- Update documentation in AGENTS.md, README.md, docs/INGESTION.md,
and docs/SOURCES.md.
Add genshin-impact.fandom.com as a second source for Genshin Impact,
which has been fixture-backed in CI because Game8 CloudFront-blocks the
Actions runner with 202s.
- Add fifth Fandom template parser in src/ingest/parsers/fandom.ts
extracting titles from caption display text, stripping dated subpage
suffixes, and checking currency via latestBoundaryMs.
- Register genshin-fandom-events in src/ingest/adapters/index.ts and
set genshin-game8-events priority: 10 so existing event IDs survive
near-match ties, preventing localStorage completion marks from
orphaning.
- Explicitly sort adapter groups by priority descending in
scripts/build-feed.ts to align with parseGame.
- Pin fixtures and add test coverage in test/adapters/game8.test.ts.
- Update AGENTS.md, README.md, docs/INGESTION.md, and docs/SOURCES.md.
Patch cycles are ~6 weeks, so a span over 180 days previously indicated
a misread year. However, real year-long events exist in this domain:
Genshin's anniversary 5-star selection runs 336 days (2025-10-22 to
2026-09-23), correctly dated on its wiki, and Fire Emblem Heroes runs a
seven-month new-player banner (docs/SOURCES.md § 12b).
Widening the ceiling to 365 days admits genuinely year-long events while
still catching misread years, which place the end 12 months out (span +
~365, or 405+ days for a 6-week event).
Update test/adapters/game8.test.ts duration test, AGENTS.md domain rules,
and docs/INGESTION.md sanity checks.