2026-W42

2026-10-14

2026-10-14

  • /score/[domain] pages and score-0 sitemap (GEO P1). Any audited domain now has an English-only score page (title "Is {domain} agent ready? w2agent Score {grade} ({score}/100)", answer sentence, category scores, check results, protocol panel, score history, CTA to /audit). The latest attempt decides what shows: a failed latest attempt renders a status page with no score. Pages are indexable only when the latest attempt is ok and under 60 days old (otherwise noindex, follow) and listed in /sitemap/score-0.xml. The route is dynamic; the DB read sits in a tagged unstable_cache (1-day TTL), and an uncached newest-row-id check on every request bypasses the cache when it is stale, so a page never shows a score a newer attempt has superseded. Audit writes also invalidate the tag. New POST /api/revalidate/score (bearer SCORE_REVALIDATE_SECRET) lets bulk writers invalidate domains.

  • /leaderboard/[domain] now 301s to /score/[domain] (GEO P1). middleware.ts answers /leaderboard/<domain> and /zh/leaderboard/<domain> with a 301 straight to /score/<canonical domain> (non-canonical /score spellings get a 301 too; query dropped). The leaderboard detail page is deleted; the leaderboard list and the May 2026 blog post link to /score/; the core sitemap no longer lists leaderboard domains (score-0 does) and no longer needs the leaderboard edition. During next build, a DB error in the score-0 child is reported to Sentry and the child is emitted empty, so a DB blip cannot fail a deploy; at runtime it still throws so ISR keeps the previous sitemap.

  • /llms.txt fixed and /llms.txt + /llms-full.txt refreshed (GEO S1). /llms.txt was returning 404 because the i18n middleware matched it; both files are now excluded from the matcher. Both are generated from one shared module (lib/llms-txt-content.ts) listing only routes that exist (product pages, four blog posts, methodology, leaderboard, directory, adoption, API docs, MCP/A2A endpoints incl. agent.w2agent.dev). /llms-full.txt now returns 200 with prose, scoring and MCP tool details instead of a deliberate 404. A route test checks every listed path maps to a real route.

  • Canonical + hreflang fixed for zh pages (GEO S2). Pages that set their own alternates (learn, platforms, blog, pricing, connect, home, directory, leaderboard, audit, sites, docs/api) overrode the layout, so /zh/... canonicalised to English with no hreflang. Page-level alternates are removed (guarded by tests/page-alternates.test.ts); the [locale] layout now emits a locale-correct canonical plus en/zh/x-default hreflang from lib/seo.ts. English-only prefixes (EN_ONLY_PREFIXES: /score, /checks, /guides, /state-of-ai-readiness, /tools, /compare) get the English canonical, en/x-default hreflang only, and noindex,follow on /zh/....

  • Sitemap split into families with real lastModified (GEO S3). /sitemap.xml is now a sitemap index over /sitemap/core.xml (static pages, blog index + 4 posts, ranked /leaderboard/[domain] pages) and /sitemap/sites.xml (directory-eligible sites only), robots.txt points at the index. (Superseded by P1: leaderboard domains moved out of core; /leaderboard/[domain] now 301s to /score.) Static pages no longer carry a build-time lastModified; blog posts use their date, leaderboard domains auditedAt, sites updatedAt. Unmeasured leaderboard entries are excluded. Middleware matcher now excludes /sitemap/. Non-eligible /sites/[slug] pages serve noindex, follow (same isSitemapIndexable predicate as the sitemap).

  • /leaderboard/[domain] returns a real 404 for unknown domains (GEO S3). A domain that is neither ranked nor unmeasured used to render an empty page with status 200 (soft-404); it now calls notFound(). When the latest edition cannot be loaded (DB down or empty) the page throws instead, so a DB outage answers 5xx (which crawlers treat as temporary) rather than a 404 that gets the URL dropped. (Superseded by P1: /leaderboard/[domain] now 301s to /score; the same 5xx-not-404 rule applies to /score.) The page is dynamic (the locale layout reads headers()), so there is no ISR stale page. The sitemap families now fail loudly on a DB error (or a missing edition when a DB is configured), so ISR keeps the previous sitemap instead of caching an incomplete one for 24h.

  • /score hub and grade / A-Z browse pages (GEO P2). /score lists the count of measured websites, a card per grade and an A-Z grid; /score/grade/<g>[/<n>] and /score/a-z/<letter>[/<n>] list domains 100 per page with real /score/<domain> links (English only, path-based pagination, /1 permanently redirects (308) to the base path, bad pages 404). Backed by one cached score index (score-index tag, 1-day TTL, also refreshed by POST /api/revalidate/score; the 60-day freshness filter runs after the cache). /leaderboard and /learn/ai-readiness-audit link to the hub.

  • Related websites and score breadcrumbs on /score/[domain] (GEO P2). Up to 8 related domains (same platform first, then closest score) from the cached score index; the section is skipped on any index failure. Breadcrumb now Home > Score > domain.

  • Score sitemap chunks and /score index pages in the sitemap (GEO P2). score-<k> children are generated from SCORE_SITEMAP_CHUNKS at 45,000 URLs each (overflow is reported to Sentry), and core now lists /score plus the non-empty grade and A-Z pages, English only with real lastModified. Submit https://w2agent.dev/sitemap.xml in Search Console after deploy (docs/launch/QA-CHECKLIST.md 2.23).

  • GEO P2 fix round. Sitemap score chunks and the core /score pages now read the DB uncached at regeneration (a failed latest attempt drops out immediately; a DB error reaches the build/runtime guard). Web audit writes also refresh the hub index tag. The cached index SQL filters latest-ok rows under 61 days in an outer query and warns in Sentry past 1.5 MB. /score/grade and /score/a-z redirect to /score.

  • Monthly rescan of measured domains (GEO R1). scripts/rescan-measured.ts re-audits every measured domain in sorted batches of 20 (resumable with --cursor, plus --dry-run, --limit, --domains), writes through recordDomainAudit, calls POST /api/revalidate/score once per batch and retries non-ok domains once. It runs by hand from the owner's machine (pnpm rescan:prod); .github/workflows/rescan-measured.yml is a manual-dispatch fallback with no schedule, to save Actions minutes. First production run 2026-10-14 (~4 hours for ~1.3k domains).

  • "Changed since last check" on /score/[domain] (GEO R1). Under the same rubric version the page shows the score change with the previous check's date, fixed and regressed checks, and files added or removed (robots.txt, sitemap.xml, llms.txt, agent card and similar). Under a different rubric version it shows only "Rescored under rubric v{N}" with no numbers. Nothing is shown without a previous check.

  • llms.txt validator at /tools/llms-txt-validator (GEO K1). A free validator that checks a site's /llms.txt by URL (?url= prefills) or pasted text, backed by POST /api/tools/llms-txt-validate, which runs core's llms-txt-exists, llms-txt-valid and llms-txt-links-resolve checks (URL mode re-roots to <origin>/llms.txt, SSRF-guarded, link checks capped at 10 links and 30 s; paste mode runs only the validity check; 5/min per IP on its own limiter key). English only and listed in the core sitemap. Linked from /learn/llms-txt, the llms.txt rows of audit reports and the llms.txt row of the /score/[domain] protocol panel.

  • /audit is now the website AI readiness checker (GEO K3). The page has the title and H1 "Website AI Readiness Checker" (zh: 网站 AI 就绪度检测) and a below-tool explainer in en and zh: the categories from core CATEGORY_CONFIG, links to /methodology, /tools/llms-txt-validator and /score (English only, so on /zh/audit the hrefs are the unprefixed English paths that crawlers follow; a zh-cookie visitor is still redirected by next-intl middleware to the noindexed /zh/ copy), a short "website AI readiness vs. an AI readiness assessment" note and a visible six-question FAQ. No FAQPage JSON-LD. Counts come from core.

  • By-platform browse pages (GEO P3). /score/platform/<p>[/<n>] lists the measured websites on one platform (100 per page, score desc, then domain; same paging, /1 redirect and 404 rules as grade pages). The /score hub has a "By platform" list, the platform on /score/[domain] links to its page, and /score/platform redirects to /score. The pages are in the core sitemap.

  • Percentile and platform stats on score pages (GEO P3). /score/[domain] shows "Better than X% of measured sites" and, for a known platform, "vs other {Platform} sites" with the platform median; /score/platform/<p> shows a summary card (site count, median, file adoption). Stats come from the latest ok audit per domain under the current rubric, need at least 20 sites in the cohort, are hidden for rows scored under an older rubric, and are cached for a day. A stats error never fails the page.

  • State of AI Readiness monthly editions (GEO R2). pnpm edition:prod --month=YYYY-MM (scripts/build-edition.ts) snapshots the month's latest successful audit per website into a new editions table (migration 0033). /state-of-ai-readiness lists the editions and /state-of-ai-readiness/<YYYY-MM> shows the median score, grade distribution, llms.txt / agent card / MCP / OAuth adoption, platform medians, month-over-month change (when at least 20 websites were measured in both months) and notable movers. English only, in the editions sitemap family, linked from /score once an edition exists. Stats over fewer than 20 websites are hidden.

  • Public changelog at /changelog (GEO R2). /changelog lists the weekly docs/changelog files newest first and /changelog/<YYYY-Www> renders one (English only, /zh is noindex; unknown week is a 404). The pages are in the core sitemap, the footer and llms.txt. While OSS_PUBLISHED is false, sections, list items and paragraphs that name unpublished packages or commands are left out of the rendered pages (the files are not edited). The markdown styles moved from the methodology page to components/markdown-components.tsx.

  • Agent readiness checkers compared (GEO K4). /compare/agent-readiness-checkers compares eight checkers (Cloudflare, Fern, GEO Toolbox, chatthing.ai, Backlinko, Frase, an Apify listing and w2agent) with a signal matrix and per-tool sections, each fact linked to the page it came from and dated 2026-10-14. English only, in the core sitemap, linked from /score, the llms.txt validator, the /audit explainer (en and zh) and /llms.txt.

Changelog — 2026-W42 | w2agent