PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m2s
PR Checks / Backend Smoke (pull_request) Successful in 8s
PR Checks / Build Backend (no push) (pull_request) Successful in 11s
PR Checks / Build Frontend (no push) (pull_request) Successful in 44s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 41s
The staging gate was red on three journeys. All three were faults in the tests; the site was behaving correctly in each case. Next normalises canonical URLs against trailingSlash:false, so the homepage ships "https://www.schoolcompare.co.uk" with no slash while every other route keeps its path. Both address the same document. The test hardcoded the slash and so failed only on the root — /rankings and /admissions passed throughout, which is what made it look like a homepage bug rather than a test bug. Compared with trailing slashes stripped from both sides. The robots.txt assertion matched "Disallow: /" anywhere in the file and tripped over the AI-crawler groups Cloudflare injects — ClaudeBot, GPTBot, Amazonbot and six others all carry a blanket disallow, deliberately, and none of them is Googlebot. It now parses the file into user-agent groups and checks only the "*" group, which is also the thing the test was always trying to say: Google may crawl the page, so it can see the noindex header. Both were the same mistake as the doubled brand: asserting a naive string rather than the semantics, and asserting against what the code assembles rather than what the page renders. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015mWQnpye9F299NVRCCSRvj