Commit Graph
99 Commits
Author SHA1 Message Date
Lucas WintherandClaude Opus 5.5 23924db4b8 chore(changelog): note built-ins for seven games, per-item tracking and standard pulls (612e0a2..9d5b473)
CI / Typecheck, test, feed (push) Successful in 16s
CI / Build site (push) Successful in 8s
CI / Container image (push) Successful in 34s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:01:59 +02:00
Lucas WintherandClaude Opus 5.5 9d5b473218 fix(games): roll NTE's Europe day at 05:00 UTC+2, as the game does
Game-Time-Master lists NTE Europe on UTC+1, but the game disagrees: on
2026-10-16 two in-game timers ran out at 03:00 UTC — one on 26 Oct, after the
clocks change — and Realm of Greed says "resets every Monday at 5:00". Only a
fixed UTC+2 fits all three.

Re-labels the hour 03:00-04:00 UTC of every European reader's NTE day.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:00:58 +02:00
Lucas WintherandClaude Opus 5.5 af2ad942cd feat(routines): let a reader add standard-banner pulls beside the premium ones
Most shops sell both banners' pulls. A shop's premium line is offered like any
built-in; its standard line (Acquaint Fates, Star Rail Pass, Master Tapes,
Resonite Crystals) only when the reader switches on Include standard-banner
pulls under the built-ins switch. A new pref, standardPulls, absent meaning
off, so no install gains anything until it asks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:00:52 +02:00
Lucas WintherandClaude Opus 5.5 9cf7649cc2 feat(routines): Infinity Nikki's weekly and monthly built-ins
Mira Journey's weekly EXP cap and the Resonance Store's Revelation Crystals on
the 1st, confirmed in game, and Realm of Breakthrough from the wiki, which the
owner could not check yet (TODO.md). The wiki answers again after refusing
every request with HTTP 402.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:00:48 +02:00
Lucas WintherandClaude Opus 5.5 88c850416f feat(routines): NTE's weekly built-ins
Anomaly Pilgrimage (3 claims in total, settling a source conflict), City
Stamina (700), Realm of Greed and the Special City Commission, beside the
Season Pass weekly EXP cap — all confirmed in game by the owner.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:00:45 +02:00
Lucas WintherandClaude Opus 5.5 d635780c72 feat(routines): Wuthering Waves' weekly built-ins
Weekly Challenge, Pioneer Podcast weekly EXP and Weekly Activities, confirmed
in game. The Podcast cap is 12,000 — the wiki's newest season page (v3.1)
still says 10,000.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:00:42 +02:00
Lucas WintherandClaude Opus 5.5 39e04c6139 feat(routines): Endfield's Focus Commissions
Etchspace Salvage: Focus Commissions, 3 a week, from the wiki; the owner could
not check it in game yet (TODO.md). The Weekly Routine and Endfield's EU reset
hour are confirmed in game.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:00:38 +02:00
Lucas WintherandClaude Opus 5.5 6d6db9c11c feat(routines): more of ZZZ's weekly and monthly built-ins
Bounty Commissions (one 8,000-point cap shared by Lost Void and Enigma of the
Labyrinth), Notorious Hunt, the New Eridu City Fund's weekly EXP cap, and the
Signal Shop's Encrypted Master Tapes and Boopons on the 1st — all confirmed in
game by the owner.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:00:35 +02:00
Lucas WintherandClaude Opus 5.5 387fc1d2e4 fix(routines): Ridu Weekly tops out at 2,100 points, not 1,300
The wiki recorded 2,100 on 2026-01-05 and the owner confirmed it in game;
Game8's page still says 1,300. Same id, so logged numbers are kept — a week
logged at 1,300 now reads 1,300 of 2,100.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:00:31 +02:00
Lucas WintherandClaude Opus 5.5 cd52641d88 feat(routines): Star Rail's weekly and monthly built-ins
Nameless Honor's weekly EXP cap (8,000, which no page states; confirmed in
game) and the Embers Exchange's Star Rail Special Passes on the 1st, beside
Echo of War, now confirmed in game. The EU reset hour is confirmed too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:00:28 +02:00
Lucas WintherandClaude Opus 5.5 af6a02cb34 feat(routines): Genshin's weekly and monthly built-ins
Weekly Bosses, Battle Pass weekly EXP, Reputation Bounties and Requests, the
Realm Depot, Paimon's Bargains (Intertwined Fates), Spiral Abyss and
Imaginarium Theater, each from a dated wiki page and confirmed in game by the
owner. Records the one exception to "a page states it": a figure the owner
confirmed in game says so in its note, with the day, and a test holds it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:00:25 +02:00
Lucas WintherandClaude Opus 5.5 f322061c88 feat(routines): say "weekly and monthly" for built-ins
Built-ins now include monthly items, so the strip's question, Settings and Your
own say "weekly and monthly". The per-game tooltip quotes the oldest source
date when a game has several.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:00:21 +02:00
Lucas WintherandClaude Opus 5.5 612e0a23e4 feat(routines): let a reader stop tracking one built-in
A new pref, routinesHidden, lists built-ins stopped one at a time by id. It
narrows the game's answer and never widens it, so stopping one changes nothing
else, and a built-in shipped later still arrives. Tracking one of a game that
is off turns the game on with that item alone (trackRoutinePatch).

Absent means none; ticks and numbers stay under the id.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:00:15 +02:00
Lucas WintherandClaude Opus 5.5 653195fce6 chore(changelog): note Genshin listed once, not twice (7c8fa7f..16c277b)
CI / Typecheck, test, feed (push) Successful in 14s
CI / Build site (push) Successful in 7s
CI / Container image (push) Successful in 31s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:50:19 +02:00
Lucas WintherandClaude Opus 5.5 2924605bd4 feat(feed): name the ids merge absorbed, and carry marks off them
When merge fuses two sources' copies, the loser's id leaves the calendar, and it may already hold a reader's ticks from a day it was published alone. Until now that needed a hand-edited RETIRED_IDS entry per fusion.

The survivor now lists what it absorbed in an optional mergedIds field. When a feed arrives the client turns those into carry-forward pairs, skipping any id the feed still publishes, and an import takes the same table. Optional, so an older cached feed still validates and an older bundle drops it unread. RETIRED_IDS stays for parser changes, whose old ids no feed will name again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:48:15 +02:00
Lucas WintherandClaude Opus 5.5 b174295e48 chore(changelog): note examples to start from in the add forms (6c66b81)
CI / Typecheck, test, feed (push) Canceled after 0s
CI / Build site (push) Canceled after 0s
CI / Container image (push) Canceled after 0s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 03:12:19 +02:00
Lucas WintherandClaude Opus 5.5 6c66b812b1 feat(forms): start an event or a task from an example, and say what Save needs
Readers who knew what they wanted could not see which answers in Add an
event or Add a task produced it. Both add forms now open with a row of
examples (templates.ts) that set the form's shape only: kind, how often,
how it repeats, how it is measured. Never a name, date, target or game,
and no date is guessed, so nothing an example set can be saved unread.

Both forms also had a pass: plain words and pills for how often and
repeat, the name asked first and the kind after the dates, each message
beside its field, and a "Still needed" line read from the same check that
disables Save. The event form's derived state is now one pure function,
eventFormState, so the examples are proved to complete into a saveable
event without a click.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 03:10:15 +02:00
Lucas WintherandClaude Opus 5.5 3d32ab8d21 chore(changelog): note per-game switches for chores and built-ins (a39c6a8)
CI / Typecheck, test, feed (push) Successful in 14s
CI / Build site (push) Successful in 8s
CI / Container image (push) Successful in 32s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 02:21:19 +02:00
Lucas WintherandClaude Opus 5.5 47c395379b feat(prefs): switch chores and built-in tasks per game, on one rule
Chores had one global switch and built-ins only a per-game opt-in, so the
two answered the same question two different ways. perGame.ts is now the
one rule for both: a global answer, then the games that differ.

Nothing is migrated. routineGames keeps its meaning as the built-ins'
on-list and an absent showRoutines still reads as off, so every reader's
answers, and an older cached tab, see what they saw before. The strip
stops asking about one game once the reader has answered for all.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 02:20:18 +02:00
Lucas WintherandClaude Opus 5.5 7a68613f3e chore(changelog): note editing the dailies strip in place (9477ac5)
CI / Typecheck, test, feed (push) Successful in 14s
CI / Build site (push) Successful in 7s
CI / Container image (push) Successful in 33s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:41:59 +02:00
Lucas WintherandClaude Opus 5.5 9477ac54b6 feat(dailies): edit the strip in place, and give weekly and monthly tasks their own row
Giving Genshin's "To Temper Thyself and Journey Far" its five-of-seven goal
meant finding it in the list, opening its sheet, saying it repeats and only
then setting the goal. The strip now has an Edit mode beside Catch up that
lists its events by game with their goals, opens the sheet's goal control in
place, and adds any running event a game at a time. It calls the same
setDaily/setGoal the sheet does, so it can store nothing the sheet would not.

Weekly and monthly tasks are not due tonight, so they move to a row under the
dailies, and each period can be switched off (showWeeklyTasks,
showMonthlyTasks; default on, so nothing disappears on upgrade).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:41:37 +02:00
Lucas WintherandClaude Opus 5.5 e467582350 chore(changelog): note upcoming events shown to new readers
CI / Typecheck, test, feed (push) Successful in 13s
CI / Build site (push) Successful in 8s
CI / Container image (push) Successful in 31s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:42:17 +02:00
Lucas WintherandClaude Opus 5.5 ab3173adf0 fix(refresh): don't call a stored copy "nothing newer", and point an entry at its feature
CI / Typecheck, test, feed (push) Successful in 15s
CI / Build site (push) Successful in 8s
CI / Container image (push) Failing after 29s
When the network failed behind the service worker, it answered from its
own store. Check for new data then said nothing newer was published when
the server was never reached. The worker now marks that copy, and a fresh
check treats it as unreachable; ordinary loads still use it offline.

The built-in tasks entry linked to a follow-up fix instead of the
feature, and the changelog spec's details now match what shipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:31:04 +02:00
Lucas WintherandClaude Opus 5.5 1fc47e2864 chore(changelog): announce the changelog, and make entries a convention
The changelog's own entry names the commit before this one, since a
commit cannot contain its own hash. AGENTS.md now asks every
reader-visible change for an entry, and every multi-commit feature for a
note, so the record keeps up. PRD F18 and the storage and design records
describe what shipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:27:25 +02:00
Lucas WintherandClaude Opus 5.5 238d21686a feat(changelog): write down what changed, tied to git
Forty-four reader-facing entries and ten release notes, backfilled from
the history and the specs, each naming the commit or range it describes.
Tests pin the shape; a script checks the refs exist, since CI's shallow
checkout can't.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:23:01 +02:00
Lucas WintherandClaude Opus 5.5 1c7df637a4 fix(routines): test the copy, name what Yes agrees to, and true up the docs
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 <noreply@anthropic.com>
2026-10-13 14:19:16 +02:00
Lucas WintherandClaude Opus 5.5 624c725cbf feat(settings): switch built-in weekly tasks per game, and make one your own
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 <noreply@anthropic.com>
2026-10-13 14:10:58 +02:00
Lucas WintherandClaude Opus 5.5 228ce9132d feat(dailies): offer a game's built-in weekly tasks, and show them once on
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 <noreply@anthropic.com>
2026-10-13 14:09:25 +02:00
Lucas WintherandClaude Opus 5.5 bfd79c295e feat(routines): record which games' built-ins are on, and who was asked
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 <noreply@anthropic.com>
2026-10-13 14:07:31 +02:00
Lucas WintherandClaude Opus 5.5 8aa820e2c0 feat(routines): ship sourced weekly tasks for ZZZ and Endfield
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 <noreply@anthropic.com>
2026-10-13 14:06:34 +02:00
Lucas WintherandClaude Opus 5.5 9c2d63b73b feat(task): model the reader's own weekly and monthly tasks
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 <noreply@anthropic.com>
2026-10-13 13:32:13 +02:00
Lucas WintherandClaude Opus 5.5 e7ee43f92d feat(goal): let a goal be a number against a target, and a period a month
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 <noreply@anthropic.com>
2026-10-13 13:30:47 +02:00
Lucas WintherandClaude Opus 5.5 9e826f22e4 feat(goal): count check-ins against a weekly or event-wide target
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 <noreply@anthropic.com>
2026-10-13 13:05:36 +02:00
Lucas WintherandClaude Opus 5.5 664cdbe0db feat(period): cut weeks and months on each game's reset clock
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 <noreply@anthropic.com>
2026-10-13 13:04:36 +02:00
Lucas WintherandClaude Opus 5.5 be5089fca6 docs: record per-server reset clocks and Game-Time-Master as their source
Rewrites the reset table for every corrected game, records the rule that a
game's offset must make its day key name the source's calendar day, and
names Game-Time-Master as the evidence for server clocks a source does not
state (transcribed, never vendored: it is GPL-3.0).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 12:43:14 +02:00
Lucas WintherandClaude Opus 5.5 6c870b23d2 fix(games): roll hololive Dreams' day at 05:00 JST, not 04:00
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 <noreply@anthropic.com>
2026-10-13 12:42:05 +02:00
Lucas WintherandClaude Opus 5.5 ad159c5306 fix(games): give Reverse: 1999's Asia readers the Asia server's clock
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 <noreply@anthropic.com>
2026-10-13 12:41:51 +02:00
Lucas WintherandClaude Opus 5.5 aadd57126f fix(games): put Girls' Frontline 2 on its Asia and Global server clocks
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 <noreply@anthropic.com>
2026-10-13 12:41:27 +02:00
Lucas WintherandClaude Opus 5.5 ccc4eb667c fix(games): roll Neverness to Everness's day at 05:00, America on UTC-4
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 <noreply@anthropic.com>
2026-10-13 12:41:13 +02:00
Lucas WintherandClaude Opus 5.5 93bde74973 fix(games): roll Stella Sora's day at 13:00 UTC-7 for every region
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 <noreply@anthropic.com>
2026-10-13 12:40:41 +02:00
Lucas WintherandClaude Opus 5.5 d1029f606c fix(games): roll Punishing: Gray Raven's day at 05:00 UTC for every region
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 <noreply@anthropic.com>
2026-10-13 12:40:27 +02:00
Lucas WintherandClaude Opus 5.5 faa5a166ff fix(games): roll P5X's day at 20:00 UTC for every region
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 <noreply@anthropic.com>
2026-10-13 12:40:13 +02:00
Lucas WintherandClaude Opus 5.5 54aed5617b fix(games): roll Chaos Zero Nightmare's day at 18:00 UTC for every region
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 <noreply@anthropic.com>
2026-10-13 12:39:57 +02:00
Lucas WintherandClaude Opus 5.5 f23d01a110 fix(games): roll Umamusume's day at 15:00 UTC for every region
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 <noreply@anthropic.com>
2026-10-13 12:39:36 +02:00
Lucas WintherandClaude Opus 5.5 eb96b70122 fix(games): roll Blue Archive's day at 04:00 JST for every region
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 <noreply@anthropic.com>
2026-10-13 12:38:54 +02:00
Lucas WintherandClaude Opus 5.5 32e252e381 fix(games): put Infinity Nikki's America and Europe servers on their own clocks
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 <noreply@anthropic.com>
2026-10-13 12:38:29 +02:00
Lucas WintherandClaude Opus 5.5 72fe6b618b refactor(time): make resetHourLocal a per-region map
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 <noreply@anthropic.com>
2026-10-13 12:37:10 +02:00
Lucas WintherandClaude Opus 5.5 f5c8d52686 fix(ui): keep a formatted time on one line
CI / Typecheck, test, feed (push) Successful in 15s
CI / Build site (push) Successful in 8s
CI / Container image (push) Successful in 32s
The detail sheet wrapped "09:00 AM" and left "AM" on a line of its own.
The time's spaces are now non-breaking, which also covers the footer's
"last refreshed" time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 04:18:45 +02:00
Lucas Winther 157b9fe20c fix(feed): reflect content updates in source health confirmation and freshness
Ensure lastConfirmedAt never precedes contentChangedAt for fetched snapshots and calculate game-level lastConfirmedAt using effective pull times.
2026-09-18 09:30:31 +02:00
Lucas Winther 6c09accc20 feat(feed): record crawler check and content update timestamps in SourceHealth
Add lastConfirmedAt and contentChangedAt to SourceHealth and enrich freshness() to track per-source check and content update times.
2026-09-18 08:55:10 +02:00