From ed5be0bef028d2d1861854567cdf5d6b469f8253 Mon Sep 17 00:00:00 2001 From: Lucas Winther Date: Wed, 19 Aug 2026 04:25:34 +0200 Subject: [PATCH] docs: sweep thirteen Game8 hubs, of which two carry a schedule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two are worth building. MementoMori's current-events page parses today with no parser change at all — seven events out of a seven-row table, six of them live. Fire Emblem Heroes has the freshest page found anywhere here and states both boundaries in their own columns, which is a shape the parser cannot read: not two header words, but a title with a separate start and end, where the existing Start/End reader wants the rowspan pair. It also publishes one real seven-month banner, which the 180-day rule rejects as a misread year — a decision to make before the fixture is written, because the fixture is the test. The other eleven fail in three ways worth telling apart. Seven wikis are abandoned, newest page between 2021 and 2025: they parse perfectly and publish history, which is the failure a stale source hides behind. Gundam prints ends with no starts, so no event ID exists to mint. Pokemon UNITE is current and still refused, because its template fails canParse — the structural check doing exactly its job rather than emptying a lane quietly. Two method notes, both of which cost time. A hub's navigation is not an index of its pages: four of these games have a schedule page linked from nowhere in the nav, found only by searching. And "Last updated on:" separates a live wiki from a dead one in a single grep, which is the check that was missing when Infinity Nikki went a year stale. Co-Authored-By: Claude Opus 5 (1M context) --- docs/SOURCES.md | 204 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 198 insertions(+), 6 deletions(-) diff --git a/docs/SOURCES.md b/docs/SOURCES.md index 85b1bbf..5a111ce 100644 --- a/docs/SOURCES.md +++ b/docs/SOURCES.md @@ -426,6 +426,199 @@ Two shapes the parser handles, both of which would otherwise lose or corrupt a r Asking the wiki's editors to state the zone on the Duration column would upgrade this source to exact instants, and remains the cheapest improvement available to it. +## 12. Thirteen Game8 hubs, swept on 2026-08-19 — two are worth building, eleven are not + +Not a P1 game between them: this section answers a direct request to check a list of Game8 game +hubs for a schedule page we could add. All thirteen hubs exist and returned `200` (unlike the +2026-08-18 probe, where eight of the games looked at had no Game8 hub at all), so the question was +never whether the wiki exists — it was whether the wiki is *alive* and whether its schedule is in a +table. + +**Two things about the method, both of which cost time here.** + +- **A hub's navigation is not an index of its pages.** Reading only the links on + `game8.co/games/` found no schedule page for Pokémon UNITE, Pokémon Champions, Gundam UC + Engage or Black Beacon. All four have one. They were found by web search instead, and one of them + — UNITE's — is among the freshest pages in this sweep. Do not conclude "no such page" from the hub + alone. +- **`Last updated on:` is the cheapest check there is**, and it separated the two live candidates + from the ones still publishing last year's schedule in a single grep. It is the check that was missing when Infinity Nikki went + a year stale behind a source that parsed perfectly (§ 11). Run it before parsing anything. + +| Game | Best page found | Last updated | `game8` parser today | Verdict | +|---|---|---|---|---| +| **MementoMori** | `/MementoMori/archives/436644` | **2026-08-13** | **7 events from 7 rows** | **Build.** Zero parser work — the cheapest adapter since Chaos Zero Nightmare | +| **Fire Emblem Heroes** | `/fire-emblem-heroes/archives/272468` | **2026-08-18** | 0 (shape unsupported) | **Build second.** Best data in the sweep, but a new column shape and one rule collision — see below | +| Pokémon UNITE | `/Pokemon-UNITE/archives/337574` | 2026-08-16 | `canParse` **false** | Decline — fresh page, two dated rows, and a template the parser refuses by design | +| Gundam UC Engage | `/gundam-uce/archives/521684` | 2026-07-13 | 0 | Decline — ends without starts | +| Pokémon Champions | `/Pokemon-Champions/archives/596103` | 2026-04-22 | 0 | Decline — a tournament calendar, four months stale | +| Mongil: Star Dive | `/Mongil-Star-Dive/archives/595311` | 2026-05-27 | 0 | Decline — image grid, and the wiki stopped in June | +| Destiny: Rising | `/Destiny-Rising/archives/546191` | 2025-10-09 | 5 events, newest ended 2025-11-06 | Decline — parses cleanly to nothing live | +| Black Beacon | `/Black-Beacon/archives/515801` | 2025-05-14 | 1 event, from May 2025 | Decline — the Infinity Nikki failure mode | +| Tower of Fantasy | `/Tower-of-Fantasy/archives/384442` | 2022-11-01 | 0 | Decline — both pages are four years old | +| Epic Seven | — | 2022-01 | — | Decline — hub's newest content is January 2022 | +| Diablo Immortal | — | 2022-09 | — | Decline — abandoned, and zone events are a daily rotation, not a calendar | +| Brawl Stars | — | 2021-11 | — | Decline — abandoned five years ago | +| Fire Emblem Shadows | — | — | — | Decline — the whole wiki is fourteen pages and none is a schedule | +| Chaos Zero Nightmare | — | — | — | Already built, 2026-08-19 — see § 4 | + +**One cost applies to both builds and should be in the commit message, not discovered later.** Both +candidates are game8.co, which does not answer the Actions runner (`AGENTS.md` § Scraping conduct). +Nine of the nineteen sources are game8 pages today, now that Infinity Nikki has moved to Fandom +(§ 11); these would make ten and eleven. Each is a lane fixture-backed in CI from day one and only +ever as fresh as someone's last manual `bun run refresh`, and one more request to a single host every +cycle — the per-host arithmetic § Scraping conduct already calls uncomfortable. + +### 12a. MementoMori — the whole adapter is a `SOURCES` entry + +**Source:** `https://game8.co/games/MementoMori/archives/436644` ("List of All Current Events"), +last updated 13 August 2026. + +The existing parser reads it as-is. Run offline against the fetched bytes: + +``` +parser game8 canParse: true +events: 7 + - NijiSanji x MementoMori Special Collaboration 2026-07-28 → 2026-08-24 + - NijiSanji x MementoMori Special Title Screen 2026-07-28 → 2026-08-24 + - NijiSanji x MementoMori: Invocation of the Lucky Draw 2026-07-28 → 2026-08-24 + - NijiSanji x MementoMori In-Game MV 2026-07-28 → 2026-08-24 + - NijiSanji x MementoMori X Repost Campaign 2026-07-28 → 2026-08-10 + - Invite a Friend Campaign 2026-07-28 → 2026-08-24 + - Twilight Florence Celebration Missons Event 2026-08-13 → (unknown) +``` + +Seven events out of a seven-row table under `List of Current Limited-Time Events`, headed +`Current Events | Duration` — the count check `AGENTS.md` § Silent drops asks for, with nothing +dropped. Six are live today. The seventh states `Part 1 Start Date: August 13, 2026 Part 2 Start +Date: August 31, 2026` and no end, so it lands `endsAt: null`, which is the correct reading of a cell +that names two starts and no finish. `List of Upcoming Events` currently holds one sentence saying +there are none, and `List of Past Events` is fenced off by its heading. + +**Two latent hazards, and they are about this page more than most.** + +- **`Recurring Events Schedule` is an *included* section here.** It is an `

` and it matches + `/recurring events/i` in `INCLUDED_SECTIONS`. Its table is `Event List | Latest Dates` and its rows + are months stale — `Guild Missions … April 27, 2026 4:00 - May 17, 2026 3:59 (UTC+1)`. Nothing + fences it off; the only thing keeping those rows off the calendar is that `COL_TITLE` does not + know the words `Event List` and `COL_RANGE` does not know `Latest Dates`. That is column + vocabulary standing in for a section rule, which is exactly the arrangement the Umamusume commit + warned about. +- **The gacha page's back catalogue is not excluded by anything.** `archives/436056` heads its + 168-row history `List of Previous Invocation (Gacha) Banners`, and `EXCLUDED_SECTIONS` matches + `previous banners` — which that string does not contain. So **do not** add the gacha page as a + second source, and treat any future widening of `game8.ts`'s vocabulary as dangerous for this game + specifically. Its current banners are unusable anyway: the dates sit inside an + `Info and Duration` prose cell (`Rarity Banner Duration: August …`), not a column. + +**No `resetOffsets`.** The current-events table names no timezone, which is honest day precision and +what `clockFor` exists to resolve. The rest of the page is worse than silent — it is *inconsistent*: +recurring rows carry `(UTC+1)`, others carry `(UTC-7)`, on the same page. Nothing there evidences one +clock for the game, so this is the Blue Archive call — no offset, and say why in `games.ts`. + +**Work:** a `mmori` `GameId`, a `GAMES` entry, one `SOURCES` entry, a fixture and a test. No parser +change. `canParse` already asserts the Game8 structural markers; the test should additionally pin +the `Current Events | Duration` header, so a redesign fails the source rather than emptying the lane. + +### 12b. Fire Emblem Heroes — the best data here, and it costs a ninth Game8 shape + +**Source:** `https://game8.co/games/fire-emblem-heroes/archives/272468` ("FEH Calendar & Banner +Schedule"), **last updated 18 August 2026** — yesterday, and the freshest page found anywhere in this +sweep. A nine-year-old article ID that has been maintained the whole time, which is the stable-URL +property Umamusume's monthly pages lack (§ 5). + +Three tables under `List of Current and Upcoming Events`, all one shape: + +``` +Event Name | Availability | End +Binding Worlds | 08/12/2026 | 08/21/2026 +Hall of Forms (Revival) | 08/14/2026 | 08/20/2026 +CYL 10: Grand Festival | 08/17/2026 | 09/18/2026 +A Blissful Soak | 08/07/2026 | 09/06/2026 +Weekly Revival | Weekly | +Free Summon | Date of Installation | +``` + +Eight datable rows today (two events, six summons), plus four rows reading `Daily`, `Weekly`, +`Monthly` or `Date of Installation`, which are genuinely undatable and skipped — the rule working, +not a silent drop. Both boundaries carry a year. No timezone anywhere on the page, so day precision +on both sides, resolved on the reader's server by `clockFor`; no `resetOffsets` claim to make. + +**The parser returns zero, and the reason is a shape, not two header words.** + +- `COL_TITLE` is `/^(.*\b)?(events?|banners?)$/i`, so `Event Name` misses. +- There is no range column at all. `Availability` holds a *start*, and the end is its own column. + `readStartEndTable` looks like the answer and is not: it wants headers matching `^start$` and + `^end$` and reads the rowspan shape where each event spans two rows, one boundary each. This is + one row per event with two date columns — a ninth Game8 shape, and the one shape that is trivial + everywhere else. +- `dates.ts` has no reader for a single `MM/DD/YYYY` boundary. `parseShortSlashRange` wants both + halves in one cell; `parseMonthDayYear` wants `August 12, 2026`. One small function, and it should + refuse a two-digit year rather than guess a century. + +**One row breaks a rule this repository holds on purpose, and it is not a parse error.** + +``` +Summer Celebration: Guaranteed 4★SHSR | 08/02/2026 | 03/01/2027 +``` + +That is 211 days. `AGENTS.md` § Domain rules says any event over 180 days is a parse error, and +`test/adapters/game8.test.ts` asserts it across every fixture — a rule that exists because a span +that long is normally a misread year. Here it is real: FEH runs a seven-month new-player banner. So +building this source means choosing, **before the fixture is written, because the fixture is the +test**: drop rows over 180 days at the adapter and lose a real banner while the guard keeps its +meaning, or carve a stated exception and weaken the guard for the eight sources that share it. The +first is the safer default and the second needs an argument. + +**And the widening is the Umamusume question again.** `COL_TITLE` is shared by every live game8 +source. Teaching it `Event Name` may start matching tables on pages it currently ignores, so parse +every pinned fixture *and* every live snapshot before and after and diff the output. That measurement +is what distinguished a safe widening from a silent one last time, and it costs one script. + +### 12c. The eleven declines, grouped by how they fail + +**Abandoned wikis** — the Infinity Nikki failure mode (§ 11), where a source parses perfectly and +publishes last year. Each of these would put a lane on the calendar that is history or empty: + +| Game | Evidence | +|---|---| +| Black Beacon | Three pages checked — `500805` News & Events (15 May 2025), `515801` Events Schedule and Calendar (14 May 2025), `500801` banners (5 May 2025). The events page parses **one** event, 5–29 May 2025 | +| Destiny: Rising | `546191` (9 Oct 2025) parses five events whose newest ended 6 November 2025; `546176` banners (14 Oct 2025) parses none. The hub's newest article is dated November 2025. `bluearchive.fandom.com` verbatim | +| Mongil: Star Dive | `595311` (27 May 2026) is the image-grid shape — an `

` per event and no date in any table. `592077` banners (6 May 2026) hides `Availability: Apr. 29 - May 26, 2026` inside a `Details` cell, and every banner listed as current ended three months ago | +| Tower of Fantasy | Both pages last updated 1 November 2022. A search summary also reports Game8 saying it stopped covering the game at Update 2.0 — second-hand, and the two `Last updated on:` stamps are the first-hand evidence | +| Epic Seven | Hub's newest content is January 2022. A search summary reports a Game8 notice ending coverage; not read on a page fetched here, and not needed — the stamps say it | +| Brawl Stars | Newest content October–November 2021 | +| Diablo Immortal | Newest content September 2022. Its "events" are zone rotations on a time of day — `Ancient Arena … Tuesday, Thursday, Saturday and Sunday at 9:30 PM server time` — which is a daily chore, not a dated event | + +**Alive, but the schedule is not in a datable table:** + +- **Gundam UC Engage** is the frustrating one. The wiki is *very* active — a weekly + ` Update Details and Summary` article, newest dated 18 August 2026. But the calendar + page `521684` was last updated 13 July 2026 and prints **ends without starts**: + `2.5th Anniv. Login Bonus Until October 28, 2026`, two events per cell, no header row. No start + means no event ID, so the whole page yields nothing by the rule rather than by accident. The banner + page `443747` (28 May 2026) does the same — `Period: Until June 3, 2026`. The dates that *are* + current live in the weekly update articles, whose URL changes every week, which a static `SOURCES` + registry cannot follow — the Umamusume monthly-page problem, one cadence faster. +- **Pokémon Champions** (`596103`, 22 April 2026) lists two in-game events, one of them + `April 8, 2026 - TBD`, and otherwise schedules online competitions and regional championships. A + tournament calendar for a competitive title, not a gacha schedule. +- **Fire Emblem Shadows** has fourteen article links in its entire hub — `Disciples` and + `Season Passes` are the only two structured pages. There is nothing to parse yet. Worth one look + again if the game gets a content cadence. + +**And one that is fresh, and still no**: **Pokémon UNITE** (`337574`, 16 August 2026). Two findings +worth keeping: + +- **`game8.canParse` returns `false` on it** — the page carries 25 `a-table` matches and **zero** + `a-header--3`. That is the structural check doing precisely its job: a Game8 page in a different + template refuses the source rather than silently returning nothing. Pointing a `SOURCES` entry at + it would fail the run, which is the correct outcome and the reason not to. +- The data is thin regardless. `Current Seasons` fuses the name and the range into one cell — + `Ranked Season 38 8/1/2026 - 9/1/2026` — under a header reading `Event Name / Duration | Rewards`, + and only two rows are dated at all; everything else is recurring or permanent. The back catalogue + under `List of Past Events` is the rowspan Start/End shape and is correctly fenced by its heading. + ## What every one of these costs, beyond the source Adding a game is never only a `SOURCES` entry: @@ -443,15 +636,14 @@ Adding a game is never only a `SOURCES` entry: ## Recommended order Steps 1 through 5 were done on 2026-08-19, and step 6's declines are now written into `AGENTS.md` -§ Scraping conduct. What is left is one decision and two builds: +§ Scraping conduct. Every game assessed in the § P1 pass is now built or declined with its reasoning +recorded, and the two decisions it raised — Nikke's permission and Infinity Nikki's timezone — have +both been made. What is queued is the two live finds of the § 12 sweep: -Nothing is queued. Every game assessed in this file is now built or declined with its reasoning -recorded, and the two decisions this pass raised — Nikke's permission and Infinity Nikki's timezone — -have both been made. -2. **MementoMori** (§ 12a) — the cheapest adapter available today: a `GameId`, a `GAMES` entry, one +1. **MementoMori** (§ 12a) — the cheapest adapter available today: a `GameId`, a `GAMES` entry, one `SOURCES` entry, a fixture and a test, with no parser change. Seven events parse out of a seven-row table and six of them are live. -3. **Fire Emblem Heroes** (§ 12b) — better data and a real cost: a ninth Game8 column shape, a +2. **Fire Emblem Heroes** (§ 12b) — better data and a real cost: a ninth Game8 column shape, a single-date `MM/DD/YYYY` reader, and a decision about the 180-day rule, which one legitimate seven-month banner breaks. Two commits, parser then source, with the vocabulary widening diffed across every fixture and snapshot as Umamusume's was.