Skip to content
AF

The gates: what this site refuses to ship

Updated 2026-09-04

Before any change to this site is committed, the build runs 110 automated refusals over the rendered output. Each one names a specific way a page can be wrong — a link to nothing, a title that will be truncated, a dataset whose CSV disagrees with its JSON, a link to the company that funds this site with no disclosure beside it. A failed gate is not a warning: the suite exits non-zero and the site does not deploy until the underlying problem is fixed. Weakening a gate to make a change pass is not allowed, which is the only reason a list like this is worth publishing.

The gates are one half of how this site is checked. The other half — primary sources, adversarial review, and what happens when we cannot verify something — is in methodology. When something gets through anyway, it goes in corrections, alongside the errors these gates caught before publish.

Content integrity (10)

CodeWhat the build refuses to ship
DUP-FAQThe same question answered in the FAQ data of two pages, where the two entries would compete in one rich result.
MATRIX-INCOMPLETEThe HealthKit-to-Health-Connect type table with any row missing its Apple or its Android identifier.
APIS-COUNTAn API directory with a different number of product pages than there are products in the cost model.
APIS-MISSINGA build in which a product named by the cost model has no directory page.
APIS-NO-COVERAGEA directory page that lists no pages covering its product, which is a thin page pretending to be an entity.
TOOLSA build where an interactive tool page has dropped out, which nothing else would notice because the tools have no data file behind them.
GATE-UNDESCRIBEDA gate that exists in the build but is described nowhere on this page, which would make the published list an understatement.
GATE-STALEA row on this page describing a gate the build no longer runs.
GATE-PAGE-MISSINGA build where this page did not render its table of gates at all.
GATE-PAGE-ROWSA rendered gates table holding a different number of rows than there are described gates.

Links and anchors (11)

CodeWhat the build refuses to ship
PHANTOM-LINKA page carrying an internal link to a URL that no built page answers.
LINK-TO-404A site that links to a route which builds a file but renders notFound() to the reader.
ORPHANA published page that no other page on the site links to.
QUESTIONS-HUBSA build where a cluster stops generating its /questions index and a whole topic disappears from the list.
QUESTIONS-DEAD-ANCHORA question-index deep link whose FAQ anchor no longer exists on the page it points into.
FACTS-NO-ANSWERSA build with no answers.json to resolve published fact citations against.
FACTS-ANSWERS-INVALIDAn answers.json that does not parse when the citation anchors are checked.
FACTS-MISSINGAn answers.json with no facts section, so the citable fragment URLs are not published at all.
FACTS-NO-FRAGMENTA published fact whose id has no fragment, leaving nothing precise for a machine reader to cite.
FACTS-NO-PAGEA published fact pointing at a page that is not in the build output.
FACTS-DEAD-ANCHORA published fact whose fragment does not resolve on the page it points into, which would break every citation already made to it.

Metadata (6)

CodeWhat the build refuses to ship
TITLE-*A page whose rendered title tag is longer than 60 characters and would be truncated in results.
DESC-*A page whose meta description is longer than 155 characters.
NO-CANONICALA page with no rel=canonical link telling crawlers which URL is the real one.
NO-OG-IMAGEA page with no og:image, which would share as a blank card everywhere it is linked.
DUP-TITLETwo pages shipping the identical title tag, so neither can be told apart in a result list.
DUP-DESCTwo pages shipping the identical meta description.

Structured data / GEO (17)

CodeWhat the build refuses to ship
BAD-JSON-LDA page carrying a JSON-LD block that does not parse as JSON.
MULTI-BREADCRUMBA page emitting more than one BreadcrumbList, which makes its breadcrumb trail ambiguous.
APIS-NO-ENTITYA directory page with no SoftwareApplication node identifying the product it describes.
GEO-NO-ROBOTSA build with no robots.txt in its output.
GEO-ROBOTSA robots.txt that does not explicitly allow each named AI crawler.
GEO-ROBOTS-SURFACEA robots.txt that does not point crawlers at llms.txt, answers.json and the changes feed.
GEO-NO-ANSWERSA build with no answers.json in its output.
GEO-ANSWERS-INVALIDAn answers.json that does not parse as JSON.
GEO-ANSWERS-COUNTAn answers.json holding a different number of records than there are cluster spokes.
GEO-ANSWERS-FIELDSAn answers.json record missing its question, answer, URL, markdown mirror or last-reviewed date.
GEO-NO-MD-ALTA hub or spoke with no rel=alternate link advertising its markdown mirror.
GEO-NO-DESCRIBEDBYA hub or spoke with no rel=describedby link to its structured description.
GEO-NO-COLLECTIONPAGEA cluster hub with no CollectionPage or ItemList describing what it collects.
GEO-NO-FAQPAGEA spoke page with no FAQPage data, unless it is a post that explicitly opted out.
GEO-NO-SPEAKABLEA spoke page that names no speakable section for voice and assistant surfaces.
GEO-NO-TECHARTICLEA spoke page with no TechArticle node identifying it as documentation.
GEO-NO-FAQ-ANCHORA page publishing FAQ data whose answers carry no per-answer anchor, so an assistant cannot deep link the one it quoted.

Feeds and mirrors (30)

CodeWhat the build refuses to ship
GEO-NO-MD-MIRRORSA build with no /md markdown mirrors at all, leaving machine readers nothing clean to fetch.
GEO-MIRROR-COUNTA build where the number of markdown spoke mirrors does not match the number of spoke pages.
GEO-HUB-MIRRORSA build missing a markdown index for a cluster, or the site index mirror.
GEO-MD-FRONTMATTERA markdown mirror that does not open with the YAML front matter a parser reads instead of prose.
GEO-MD-CANONICALA markdown mirror whose front matter does not name the canonical URL of the page it mirrors.
GEO-MD-REWRITEA cluster missing from the rewrite list, which would make its conventional /cluster/slug.md addresses 404.
GEO-NO-LLMSA build with no llms.txt in its output.
GEO-LLMS-MISSINGA spoke page that llms.txt does not list, so a model reading the index never learns it exists.
GEO-LLMS-SURFACEAn llms.txt that fails to advertise the answers, changes and full-text surfaces.
GEO-NO-CHANGES-FEEDA build with no changes.xml in its output.
GEO-CHANGES-FEED-EMPTYA changes feed that contains no items.
ICS-MISSINGA build with no changes calendar in its output.
ICS-EMPTYA changes calendar containing no events.
ICS-PARITYA changes calendar holding a different number of events than the changes feed holds items.
ICS-UNTERMINATEDA calendar file with no END:VCALENDAR, which a strict client will reject outright.
ICS-FOLDA calendar file with lines over the 75-octet limit the format allows.
ICS-LINE-ENDINGSA calendar file that is not CRLF-terminated as the format requires.
FEED-COUNTA build with a different number of per-cluster RSS feeds than there are populated clusters.
FEED-EMPTYA cluster feed that contains no items.
FEED-NO-SELFA cluster feed with no self link, so readers cannot tell where it lives.
FEED-UNESCAPED-AMPA feed containing a raw ampersand outside CDATA, which breaks strict readers.
FEED-NO-JSONA build with no feed.json in its output.
FEED-JSON-VERSIONA feed.json that declares no JSON Feed version, so conforming clients will not read it.
FEED-JSON-ITEMSA feed.json with no items array.
FEED-JSON-INVALIDA feed.json that does not parse.
NO-OPENSEARCHA build with no OpenSearch descriptor in its output.
OPENSEARCH-TARGETAn OpenSearch descriptor that does not point at the site's own results page.
NO-MANIFESTA build with no web app manifest in its output.
MANIFEST-FIELDSA web app manifest missing its name, start URL or icons.
MANIFEST-INVALIDA web app manifest that does not parse as JSON.

Datasets and artifacts (12)

CodeWhat the build refuses to ship
DATASET-UNGATEDA dataset published under /datasets that no check in the QA suite covers.
DATASET-MISSINGA build where a dataset the site advertises has no JSON or no CSV file on disk.
DATASET-EMPTYA dataset file whose items array is empty, which a generator can produce silently.
DATASET-NO-LICENCEA dataset published without the licence field that tells a reuser what they may do with it.
DATASET-CSV-ROWSA dataset whose CSV export carries a different number of rows than its JSON.
DATASET-INVALIDA dataset JSON file that does not parse.
KIT-MISSINGA build where a file in the downloadable decision kit is absent.
KIT-EMPTYA kit file that exists but is zero bytes.
KIT-UNGATEDA file published under /kit that no check in the QA suite covers.
DATASET-NO-MANIFESTDatasets published without the manifest that records their hashes and row counts.
DATASET-UNMANIFESTEDA dataset the manifest does not cover, so its changes never show up in the published diff.
DATASET-MANIFEST-STALEA manifest whose recorded byte sizes disagree with the dataset files actually on disk.

Disclosure (3)

CodeWhat the build refuses to ship
KINESTEX-NOTEA build where the disclosed first-party link renders on a different number of pages than the map declares.
KINESTEX-UNDISCLOSEDA page linking to the site's funder without the funding disclosure beside it.
FIRSTPARTYA page whose prose features the site's funder three or more times with no funding disclosure anywhere on it.

Blog (14)

CodeWhat the build refuses to ship
POST-FRONTMATTERA post file with no YAML front matter.
POST-NO-TITLEA post whose front matter declares no title.
POST-TITLE-*A post title over 45 characters, which overflows the tab once the site suffix is appended.
POST-NO-DESCA post whose front matter declares no description.
POST-DESC-*A post description longer than 155 characters.
POST-NO-DATEA post with no publication date in its front matter.
POST-NO-UPDATEDA post with no last-updated stamp in its front matter.
POST-NOT-BUILTA live post that silently stopped building and would be invisible rather than broken.
POST-FAQ-RENDERA build where the number of posts rendering their FAQ block does not match the number that declare FAQs.
POST-PLACE-PARSEA build in which the blog placement map cannot be read out of the component source, so neither half of the placement check can run.
POST-PLACE-SLUGA placement pointing at a post slug that is not a live post.
POST-PLACE-PATHA placement that would surface a post on a page which does not exist.
POST-LINKSA build where the blog link block renders on a different set of pages than the placement map declares.
POST-EXEMPT-CREEPMore than two posts opting out of the FAQ requirement, which would turn an announcement exemption into the default.

Derived blocks (7)

CodeWhat the build refuses to ship
REFERENCE-CALLOUTA build where the reference callout renders on a different number of guides than the map declares, which is how a renamed slug drops it.
APP-STACKA build where the derived type-and-API stack block is missing from any /build guide that should carry it.
HK-GROUP-COVERAGEA set of HealthKit group pages that does not carry every identifier in the dataset exactly once.
HK-GROUP-PARTIALA build where only some of the HealthKit group pages were generated.
METRIC-FACTSA /data guide that quietly lost its derived HealthKit facts block because the join behind it stopped matching.
ARCH-DIAGRAMAn /architecture page publishing without its hand-drawn mechanism figure.
ARCH-DIAGRAM-LEAKThe architecture diagram marker appearing on any page outside the /architecture cluster.

What the gates cannot do

Every check above tests form, not truth. A rate limit copied wrong from a vendor page, a benchmark recalled from memory, a deprecation date off by a quarter — each of those is a well-formed sentence on a well-formed page, and it would pass all 110 of these gates without a murmur. Nothing automated catches a claim that is simply false. That is what the verification rules in methodology are for: primary sources fetched at write time, unverifiable claims marked rather than filled in, and dated review stamps you can hold us to. The gates make the mechanical failures impossible. They do not make us right.