Skip to content

Generic fallback: a country-code TLD corroborates the page's stated venue country - #752

Merged
missingbulb merged 3 commits into
mainfrom
claude/fallback-coverage/2026-07-26-cctld-locale
Jul 26, 2026
Merged

Generic fallback: a country-code TLD corroborates the page's stated venue country#752
missingbulb merged 3 commits into
mainfrom
claude/fallback-coverage/2026-07-26-cctld-locale

Conversation

@missingbulb

Copy link
Copy Markdown
Owner

Weekly gcec/fallback-extractor-improvements run (dispatch #741). Refs #366.

Hypothesis

helpers/derive-timezone.js names a zone only when two independent page-declared hints agree. Scanning the column of the fallback-coverage matrix, ctz was the largest gap (20 of 32 gradeable cases missing), and one shape recurred: a page that does state its venue country in JSON-LD (location.address.addressCountry) but whose <html lang> is a country-less "en" — so the country stood alone and nothing was derived, even though the site is published under a country's own TLD.

visit.tel-aviv.gov.il is the exemplar: addressCountry: "Israel", floating times, <html lang="en">.

The change

localeCountry() gains a last-resort signal: the host's country-code TLD (.co.il → IL, .co.uk → GB via the one ISO/TLD divergence worth encoding).

Two properties keep it inside the existing contract rather than weakening it:

  • It is a locale-kind hint, never a country one. A ccTLD describes the site, exactly like <html lang> — a Tel Aviv cinema's .co.il says nothing about where any particular screening happens. So it can only corroborate a venue country the page itself stated, never name one. That is also what bounds a ccTLD in vanity use (.co, .io, .fm): since the country always comes from the page's own address, a bogus TLD→country mapping can never point at a wrong country — at worst it agrees with a country the page already claimed, which is the residual risk the country+locale rule already documents and accepts.
  • It is the weakest locale signal, consulted only when <html lang>/og:locale named no country at all — so a vanity ccTLD can never contradict or override a locale the page actually declared.

Every refusal rule is untouched: still no zone without a stated venue country, still nothing for a multi-zone country on locale agreement alone, still nothing when the country is ambiguous across a page's events.

Why it's generic (which unseen sites it helps)

The pattern "regional/municipal/venue site on its country's ccTLD, JSON-LD venue address, English-language chrome" is everywhere outside the tested corpus — tourism boards, city event calendars, national theatres and museums, regional ticketing on .co.uk / .fr / .de / .jp / .au / .nz / .ie. Nothing here keys off a host, a path, or a per-site DOM shape; the two files that carry site knowledge (custom/*.js) are untouched.

How the jsdom trap was ruled out

No value passed through the body-text scan — there is nothing to submit to the postcondition's jsdom check. The two inputs are document.querySelectorAll('script[type="application/ld+json"]') content (a Chrome-readable attribute/JSON signal, already how venueCountry() works) and location.hostname. document.body.textContent is not involved, no scan-window cap was touched, and no new text matching was added, so the "matched a <script> blob Chrome's innerText never exposes" failure mode cannot arise. postconditions.sh exits 0.

Before → after

Metric Before After
Critical fields (title + start + location) 75.2% 75.2%
All fields 55.9% 56.9%
ctz field 12/32 (37.5%) 14/32 (43.8%)

Non-regressing: no gated % moved down, no exemplar cell moved from ✓. The two cells that flipped are visit-tel-aviv and visit-tel-aviv-timed, ctz ✗ → ✓.

Deliberate-empty cases verified still empty, per the routine's rule: stubhub (venue country Israel, but en-US locale wins over the .com non-hint), seetickets (GB venues, Z-serialized times, .com), and — the sharpest guard — livenation.de, a real ccTLD page: its de-DE lang already names DE so the TLD is never consulted, and its JSON-LD spans several countries so venueCountry() refuses anyway. All three still derive "", and their starts are unchanged.

Also unchanged: the cinema.co.il / thinkdrink.co.il / ticketmaster.co.il / barby.co.il cases. They sit on .il but state no venue country anywhere, and a locale hint alone must never pick a zone — so they correctly stay empty rather than being guessed at.

The covering test

Added to extension-test/event-extractors/extraction.test.js (the end-to-end home the helper's own unit tests point at for "events actually gaining a ctz"), red before green. One test, three assertions:

  1. .co.il host + JSON-LD addressCountry + country-less lang="en"Asia/Jerusalem, times placed by it.
  2. The same page served from a .com host → "" (pins that the ccTLD is what did the work, and that a generic TLD mints nothing).
  3. The same page on .co.il with lang="en-US""" (pins that a declared locale outranks the ccTLD).

npm test is green (468 passed / 8 skipped).


Heads-up for review: an unmerged sibling branch claude/fallback-coverage/2026-07-26 (a 00:00–23:59 all-day-range change) also edits derive-timezone.js; whichever lands second may need a trivial rebase.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AHCptFbq5GK4HpnK8PR5jA


Generated by Claude Code

claude added 3 commits July 26, 2026 04:22
…enue country

The ctz derivation refuses to name a zone unless two independent page-declared
hints agree. A very common shape cleared every bar but one: a local/municipal
site that publishes its venue address in JSON-LD (addressCountry) but whose
<html lang> is a country-less "en" — one hint, so nothing was derived.

Read the host's country-code TLD as the weakest LOCALE-kind hint (.co.il -> IL,
.co.uk -> GB), consulted only when <html lang>/og:locale named no country. It is
deliberately not a country hint: a ccTLD describes the site, not the venue, so
it can only corroborate a venue country the page itself stated — which is also
what bounds a ccTLD in vanity use (.co/.io/.fm), since the country always comes
from the page's own address.

Fallback coverage: allFieldsPct 55.9 -> 56.9 (ctz 12/32 -> 14/32);
criticalFieldsPct unchanged. livenation.de, stubhub and seetickets — whose
dedicated sources deliberately set no ctz — still come out empty.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AHCptFbq5GK4HpnK8PR5jA
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants