Evidence (verified on production 2026-06-12)
Sitemap (src/lib/feeds/sitemap.ts): prod https://ogsfrompoly.com/sitemap.xml contains only the two statement URLs. Missing: / (homepage), /statements, /methodology — the three highest-value pages for search. The footer links to this sitemap; the Cloudflare-managed robots.txt carries no Sitemap: directive either (CF content-signals preamble only; CF prepends to an origin robots.txt if one exists — the repo ships none, public/ has only favicon.svg).
RSS (src/lib/feeds/rss.ts): channel has no <atom:link rel="self">, no <lastBuildDate>, no <language> — the W3C feed validator flags the missing self-link; some readers use lastBuildDate for change detection. Also note pubDate is period_end at 00:00 GMT, which predates the actual publish moment (Tue 14:00 UTC cadence) — fine if intentional, but document the choice in the module.
TDD plan (failing tests first)
All three generators are pure with snapshot tests (src/lib/feeds/*.test.ts, determinism.test.ts) — extend tests first, then implement:
sitemap.test.ts: generateSitemap output must include <loc> for siteUrl root, /statements, /methodology (likely a new staticPages: ReadonlyArray<{path, lastmod?}> field on FeedInput populated in collect.ts — keeps the generator collection-agnostic). Decide lastmod for static pages (latest entry date is a reasonable proxy for / and /statements; omit for /methodology).
rss.test.ts: assert xmlns:atom namespace, <atom:link href=".../rss.xml" rel="self" type="application/rss+xml"/>, <language>en</language>, <lastBuildDate> equal to the newest entry's pubDate (deterministic — do NOT use build time; determinism snapshots are the gate).
- Add
public/robots.txt with Sitemap: https://ogsfrompoly.com/sitemap.xml (CF content-signals get prepended automatically).
- Update inline snapshots in
determinism.test.ts.
Acceptance criteria
| AC |
Test |
| Static pages present in sitemap |
unit + snapshot |
| RSS validates clean (self-link, language, lastBuildDate) |
unit + W3C validator pass after deploy |
| Output remains byte-deterministic |
existing determinism tests |
| robots.txt served with Sitemap directive |
curl after deploy |
Evidence (verified on production 2026-06-12)
Sitemap (
src/lib/feeds/sitemap.ts): prod https://ogsfrompoly.com/sitemap.xml contains only the two statement URLs. Missing:/(homepage),/statements,/methodology— the three highest-value pages for search. The footer links to this sitemap; the Cloudflare-managed robots.txt carries noSitemap:directive either (CF content-signals preamble only; CF prepends to an origin robots.txt if one exists — the repo ships none,public/has onlyfavicon.svg).RSS (
src/lib/feeds/rss.ts): channel has no<atom:link rel="self">, no<lastBuildDate>, no<language>— the W3C feed validator flags the missing self-link; some readers use lastBuildDate for change detection. Also notepubDateisperiod_endat 00:00 GMT, which predates the actual publish moment (Tue 14:00 UTC cadence) — fine if intentional, but document the choice in the module.TDD plan (failing tests first)
All three generators are pure with snapshot tests (
src/lib/feeds/*.test.ts,determinism.test.ts) — extend tests first, then implement:sitemap.test.ts:generateSitemapoutput must include<loc>for siteUrl root,/statements,/methodology(likely a newstaticPages: ReadonlyArray<{path, lastmod?}>field onFeedInputpopulated incollect.ts— keeps the generator collection-agnostic). Decidelastmodfor static pages (latest entry date is a reasonable proxy for/and/statements; omit for/methodology).rss.test.ts: assertxmlns:atomnamespace,<atom:link href=".../rss.xml" rel="self" type="application/rss+xml"/>,<language>en</language>,<lastBuildDate>equal to the newest entry's pubDate (deterministic — do NOT use build time; determinism snapshots are the gate).public/robots.txtwithSitemap: https://ogsfrompoly.com/sitemap.xml(CF content-signals get prepended automatically).determinism.test.ts.Acceptance criteria