{"schema":"1.0.0","version":"2026.11.0","status":"active","sha":"fd2d0686690660ae60ecfe9d4e7ac2ac689ef4c935e45b49fae782b9e2587349","publishedAt":"2026-08-19","lastUpdatedAt":"2026-08-19","gradeBandVersion":"1","gradeBands":[{"grade":"A","min":90},{"grade":"B","min":80},{"grade":"C","min":70},{"grade":"D","min":60},{"grade":"F","min":0}],"subScoreWeights":{"discoverability":0.22,"readability":0.22,"structured_data":0.13,"actionability":0.28,"performance":0.15},"categories":[{"key":"actionability","label":"Actionability","checkCount":8,"weightSharePct":28},{"key":"discoverability","label":"Discoverability","checkCount":11,"weightSharePct":22},{"key":"readability","label":"Readability","checkCount":9,"weightSharePct":22},{"key":"performance","label":"Performance","checkCount":3,"weightSharePct":15},{"key":"structured_data","label":"Structured data","checkCount":5,"weightSharePct":13}],"changelog":[{"date":"2026-08-19","summary":"Adds actionability.commerce_protocols (weight 1, emerging): does the site declare an agentic-commerce discovery manifest — x402 (/.well-known/x402.json), UCP (/.well-known/ucp), or ACP (/.well-known/acp.json)? One check that passes on any of the three, because a site adopts one standard and the capability, not the spelling, is the subject. Nothing else changes: no thresholds move, no check is removed or reweighted."},{"date":"2026-07-30","summary":"The text-density finding now reports where a document's bytes actually went. It gave a percentage and then blamed \"heavy ad or navigation markup\", which is wrong for most framework-rendered pages, where the weight is serialized hydration state inside script tags. Measured across 20 live sites, script and style are a median 34% of a homepage. Thresholds are unchanged: on the same 20 sites the existing bands separate document-first sites from application shells, with 30% passing."},{"date":"2026-07-30","summary":"One page now yields one text reading. Three implementations of \"the text an agent sees\" had drifted apart over what to do with template elements, the document title and inline SVG labels, so the same page scored differently depending on which path scanned it. Verdicts move slightly downward on template-heavy pages scanned through the public path."},{"date":"2026-07-30","summary":"performance.payload_kb can fail again. It fails above 3 MB, but the public scan refuses to download more than 3 MB, so the heaviest documents on the web were recorded as \"not measured\" and scored 100. A document too large to fetch is now graded as too large rather than as a missing measurement."},{"date":"2026-07-30","summary":"A scan no longer describes a document the origin never served. When the landing page returns a non-2xx status, every check whose subject is that document reports no measurement; robots.txt, sitemap.xml and the /.well-known surface still report, because they are separate fetches, and reachability.status still fails, because the status code is its subject. Found in the corpus: the three highest text-ratio scores across 43 scans were a 404 and two 403s, at 90.0%, 77.6% and 40.2%, all PASS, while every site that served us a real page failed the same check."},{"date":"2026-07-30","summary":"content.text_ratio requires a document of at least 2,048 bytes. Below that there is no markup weight to crowd out text, so the ratio measures rounding. Threshold set from the corpus, where every document under 16 KB passed and the smallest to return anything else was 33,794 bytes."},{"date":"2026-07-30","summary":"A refused probe is no longer read as an absent resource. The /.well-known checks scored any unsuccessful probe as \"not published\", so a site blocking our user-agent was told to publish six files it may already serve. HTTP 401, 403, 407, 408, 429 and 5xx now report no measurement; 404, 410, a 200 with an invalid body, and 406 for Accept: text/markdown still fail, because each of those answers the question asked."},{"date":"2026-07-28","summary":"New check family: operability (2 checks). Every check before this one graded what a page SAYS. None graded whether its controls can be worked by an agent driving the DOM, which is where agents actually fail. Published measurement, not assumption: on 300 tasks across 136 live sites the strongest agent succeeded 61.3% of the time, and filter and sorting errors caused 57.7% of its failures (arXiv:2504.01382); in a controlled experiment a call to action baked into an image was clicked 0/10 by every model tested versus 7/10 for the same action as a real element (arXiv:2507.12844)."},{"date":"2026-07-28","summary":"operability.primary_action_in_dom (actionability, weight 2, deterministic): a page that asks for an action must express it as a real clickable element. PASSes on the first link, button, or input carrying action language; SKIPs when the page asks for nothing; FAILs only when the words appear in image alt text or on a plain element and nothing clickable carries them. operability.filters_addressable (actionability, weight 2, deterministic): when a page offers to filter or sort a list, at least one filtered view must be reachable by URL, through a link with a query parameter or a GET form. WARNs when controls exist but produce no URL, FAILs when no operable control is served at all, SKIPs on pages with no facets. The check set grows from 34 to 36 (35 scored)."},{"date":"2026-07-28","summary":"No claim is made that operability changes citation or conversion rates. The cited research measures agent task success on other sites, not revenue on yours. These checks state something per-site and factual: the control is operable, or it is not."},{"date":"2026-07-27","summary":"New check family: coherence (3 checks). The rubric so far verified each machine channel EXISTS - JSON-LD present, lang declared - but nothing verified the channels AGREE with each other or with what humans see. Disagreement is worse than absence: an absent price makes an agent hedge, a divergent one makes it quote the wrong number with confidence. Cross-channel agreement is also structurally un-gameable - the only way to game a consistency check is to become consistent."},{"date":"2026-07-27","summary":"coherence.jsonld_price_matches_visible (structured_data, weight 2, deterministic): a price declared in JSON-LD must appear among the visible prices, compared by numeric value. FAILs only when ZERO declared prices are visible. Both price lists are recorded as evidence. coherence.jsonld_name_matches_visible (structured_data, weight 1, deterministic): a declared Product/Organization/Store name must appear in the title or visible text. coherence.language_declared_matches_content (readability, weight 1, heuristic): <html lang> compared against a conservative stopword/script language profile of the content; WARNs, never FAILs, and stays silent when unsure. The check set grows from 31 to 34 (33 scored)."},{"date":"2026-07-27","summary":"No claim is made that coherence affects AI citation rates - that measurement has not been done. What these checks demonstrate is per-site and factual: when the machine and human channels disagree, an agent trusting the machine channel quotes numbers and names the visible page does not show."}],"changesFromPrevious":{"from":"2026.10.4","checkChanges":[{"key":"actionability.commerce_protocols","kind":"added","before":null,"after":"actionability, weight 1, deterministic"}],"subScoreWeightChanges":[],"gradeBandsChanged":false,"instrumentUnchanged":false},"counts":{"total":37,"scored":36,"reported":1,"retired":0},"checks":[{"id":"robots_txt.present","title":"robots.txt present","category":"discoverability","categoryLabel":"Discoverability","weight":1,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"established","specUrl":"https://datatracker.ietf.org/doc/html/rfc9309","description":"A reachable robots.txt exists at the site root.","remediation":"Add a `/robots.txt` file at the site root. Even an allow-all file signals intent to agents.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":5,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/robots_txt.present"},{"id":"robots_txt.allows_known_agents","title":"robots.txt allows AI agents","category":"discoverability","categoryLabel":"Discoverability","weight":2,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"established","specUrl":"https://datatracker.ietf.org/doc/html/rfc9309","description":"robots.txt does not disallow answer-time AI access agents (ChatGPT-User, OAI-SearchBot, Claude-User, Claude-SearchBot, PerplexityBot, Perplexity-User, YouBot, Amazonbot). Training-data crawler blocks (GPTBot, CCBot, Google-Extended, …) are reported as informational and never fail the check.","remediation":"If you want your content in AI answers, explicitly allow the access agents in robots.txt — blocking them keeps assistants from reading or citing your site at answer time. Blocking training-data crawlers (GPTBot, CCBot, Google-Extended) is a separate licensing choice and does not affect this check.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":3,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/robots_txt.allows_known_agents"},{"id":"robots_txt.content_signals","title":"Content-Signal directives","category":"discoverability","categoryLabel":"Discoverability","weight":1,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"emerging","specUrl":"https://contentsignals.org","description":"robots.txt advertises Content-Signal directives (e.g. `Content-Signal: ai-train=no, ai-summarize=yes`) that let agents respect granular usage preferences.","remediation":"Add `Content-Signal:` directives to your robots.txt. This is the emerging standard (Cloudflare-driven) for declaring fine-grained AI usage policy beyond a binary allow/disallow.","introducedIn":"2026.04.2","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":2,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/robots_txt.content_signals"},{"id":"llms_txt.present","title":"llms.txt present","category":"discoverability","categoryLabel":"Discoverability","weight":2,"state":"reported","scored":false,"determinism":"deterministic","heuristicParam":null,"maturity":"unproven","specUrl":"https://llmstxt.org","description":"An llms.txt file at the site root. Reported for completeness and NOT scored: no measurement has connected it to AI citations. Google states Search does not use it; a ~300k-domain study found no correlation with citations; a 137k-domain crawl found 97% of these files received zero requests. Most traffic they do get is from SEO audit tools checking whether the file exists.","remediation":"No action needed for AI visibility. `/llms.txt` is cheap to publish and harmless, but the evidence does not support it changing whether assistants cite you — so we do not score it and you should not prioritise it. Spend the effort on being fetchable (robots.txt access agents), readable without JavaScript, and structured.","introducedIn":"2026.04.1","deprecatedIn":"2026.08.0","calibration":{"state":"not_in_corpus","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":0,"precision":null,"recall":null,"falsePositives":null,"falseNegatives":null,"reason":"Not covered by calibration corpus v1."},"url":"https://agentspeed.com/rubric/check/llms_txt.present"},{"id":"sitemap.present","title":"Sitemap present","category":"discoverability","categoryLabel":"Discoverability","weight":2,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"established","specUrl":"https://www.sitemaps.org/protocol.html","description":"A sitemap.xml is reachable and referenced from robots.txt.","remediation":"Publish a sitemap.xml and add `Sitemap: https://your-domain/sitemap.xml` to robots.txt.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":3,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/sitemap.present"},{"id":"discoverability.link_headers","title":"Link response headers","category":"discoverability","categoryLabel":"Discoverability","weight":1,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"established","specUrl":"https://datatracker.ietf.org/doc/html/rfc8288","description":"HTTP `Link:` response headers carry useful relations (canonical, alternate, describedby) that agents consume without parsing HTML.","remediation":"Emit `Link:` headers for canonical, alternate-language, and describedby relations. Agents that fetch HEAD-only or stream-render rely on these.","introducedIn":"2026.04.2","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":2,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/discoverability.link_headers"},{"id":"markup.canonical","title":"Canonical URL","category":"discoverability","categoryLabel":"Discoverability","weight":2,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"established","specUrl":"https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls","description":"A canonical URL is declared and resolves to the same page.","remediation":"Add `<link rel=\"canonical\" href=\"...\">` to your primary pages. Agents use this to dedupe and cite.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":6,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 2 flagged cases (30 needed to publish), 2 defective cases (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/markup.canonical"},{"id":"discoverability.mcp_server_card","title":"MCP server card","category":"discoverability","categoryLabel":"Discoverability","weight":1,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"emerging","specUrl":"https://modelcontextprotocol.io","description":"An MCP Server Card is reachable at `/.well-known/mcp/server-card.json` (or referenced from a Link header) and validates against the Model Context Protocol spec.","remediation":"Publish an MCP Server Card describing the tools your site exposes. Agents discover capabilities via `/.well-known/mcp/server-card.json`. See modelcontextprotocol.io for the schema.","introducedIn":"2026.04.2","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":5,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 2 flagged cases (30 needed to publish), 2 defective cases (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/discoverability.mcp_server_card"},{"id":"discoverability.oauth_authorization_server","title":"OAuth authorization metadata","category":"discoverability","categoryLabel":"Discoverability","weight":1,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"emerging","specUrl":"https://datatracker.ietf.org/doc/html/rfc8414","description":"`/.well-known/oauth-authorization-server` is reachable and conforms to RFC 8414, letting agents discover authorization endpoints without out-of-band setup.","remediation":"Expose OAuth metadata at `/.well-known/oauth-authorization-server` per RFC 8414. Required for agents that need to perform user-authorized actions on your site.","introducedIn":"2026.04.2","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":5,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 2 flagged cases (30 needed to publish), 2 defective cases (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/discoverability.oauth_authorization_server"},{"id":"discoverability.oauth_protected_resource","title":"OAuth resource metadata","category":"discoverability","categoryLabel":"Discoverability","weight":1,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"emerging","specUrl":"https://datatracker.ietf.org/doc/html/rfc9728","description":"`/.well-known/oauth-protected-resource` is published per RFC 9728 so agents can discover required scopes and authorization servers programmatically.","remediation":"Publish OAuth resource metadata at `/.well-known/oauth-protected-resource` per RFC 9728. Required for agents that act on behalf of authenticated users without hand-coded credentials.","introducedIn":"2026.04.2","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":3,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/discoverability.oauth_protected_resource"},{"id":"discoverability.api_catalog","title":"API catalog / OpenAPI","category":"discoverability","categoryLabel":"Discoverability","weight":1,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"emerging","specUrl":"https://datatracker.ietf.org/doc/html/rfc9727","description":"An API catalog is published at `/.well-known/api-catalog` (RFC 9727) or an OpenAPI document is reachable at `/openapi.json` or `/openapi.yaml`.","remediation":"Publish either an `/.well-known/api-catalog` (RFC 9727) referencing your OpenAPI documents, or expose `/openapi.json` directly. Agents that integrate with APIs use these to plan calls.","introducedIn":"2026.04.2","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":4,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 2 flagged cases (30 needed to publish), 2 defective cases (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/discoverability.api_catalog"},{"id":"discoverability.web_bot_auth","title":"Web Bot Auth","category":"discoverability","categoryLabel":"Discoverability","weight":1,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"emerging","specUrl":"https://datatracker.ietf.org/doc/draft-meunier-web-bot-auth-architecture/","description":"The site signals support for the Web Bot Auth IETF draft (HTTP Message Signatures over a known JWKS) so well-behaved agents can prove identity.","remediation":"Publish a JWKS at `/.well-known/http-message-signatures-directory.json` and accept signed requests per the Web Bot Auth draft. Lets you allow trusted agents while keeping a default-deny posture for the rest.","introducedIn":"2026.04.2","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":3,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/discoverability.web_bot_auth"},{"id":"readability.markdown_negotiation","title":"Markdown negotiation","category":"readability","categoryLabel":"Readability","weight":1,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"emerging","specUrl":"https://www.rfc-editor.org/rfc/rfc7763.html","description":"Requests with `Accept: text/markdown` return a markdown representation of the page (Markdown content negotiation).","remediation":"Serve a markdown variant of your primary content when the request `Accept` header includes `text/markdown`. Agents prefer markdown over HTML for summarization and citation.","introducedIn":"2026.04.2","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":2,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/readability.markdown_negotiation"},{"id":"content.text_ratio","title":"Text-to-markup ratio","category":"readability","categoryLabel":"Readability","weight":1,"state":"scored","scored":true,"determinism":"heuristic","heuristicParam":{"label":"min text ratio","value":"15%"},"maturity":"established","specUrl":null,"description":"Visible text makes up at least 15% of the rendered DOM weight.","remediation":"Your report says which of these applies. If the weight is markup, the usual cause is deeply nested wrappers, repeated navigation and ad slots: flatten the structure and move presentation into stylesheets. If the weight is inline script, it is almost always serialized state your framework embeds so the browser can hydrate, and on many pages that is a second copy of the text already in the HTML. Ship less of it: send only the props a component cannot recompute, and prefer static rendering for pages that do not need to hydrate at all. Either way the target is the same, visible text above 15% of the document.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":2,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/content.text_ratio"},{"id":"content.js_required_for_primary_content","title":"Content without JavaScript","category":"readability","categoryLabel":"Readability","weight":2,"state":"scored","scored":true,"determinism":"heuristic","heuristicParam":{"label":"detector","value":"no-JS visibility heuristic"},"maturity":"established","specUrl":null,"description":"Primary content is visible without JavaScript.","remediation":"Render your primary headings, body copy, and calls-to-action in server HTML. Many agents fetch without executing JS. If you must hydrate, include the core content in the initial HTML response.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":2,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/content.js_required_for_primary_content"},{"id":"content.headings_hierarchy","title":"Heading hierarchy","category":"readability","categoryLabel":"Readability","weight":1,"state":"scored","scored":true,"determinism":"heuristic","heuristicParam":{"label":"rule","value":"single H1, no skipped levels"},"maturity":"established","specUrl":"https://www.w3.org/WAI/tutorials/page-structure/headings/","description":"Heading hierarchy is well-formed (one H1, no skipped levels).","remediation":"Use a single H1 and avoid skipping heading levels (H1 → H3).","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":5,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/content.headings_hierarchy"},{"id":"auth.cookie_consent_blocks_content","title":"Cookie wall blocks content","category":"readability","categoryLabel":"Readability","weight":2,"state":"scored","scored":true,"determinism":"heuristic","heuristicParam":{"label":"detector","value":"consent overlay heuristic"},"maturity":"established","specUrl":null,"description":"A cookie-consent modal does not cover or block the primary content on first load.","remediation":"Defer cookie consent overlay until after content is visible, or render behind the primary content. Agents without JS or with ad-blocking profiles see a blank page otherwise.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":2,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/auth.cookie_consent_blocks_content"},{"id":"markup.language","title":"Declared language","category":"readability","categoryLabel":"Readability","weight":1,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"established","specUrl":null,"description":"The document declares its language: <html lang> is present and a well-formed BCP 47 tag, and any hreflang alternates carry well-formed values. Self-referencing and reciprocity are not checked — both require fetching the alternates, and a wrong warning there would be the scanner's limit charged to the site.","remediation":"Add `lang` to your `<html>` element (`<html lang=\"en\">`, `<html lang=\"de-DE\">`). If you publish translations, declare them with `<link rel=\"alternate\" hreflang=\"...\" href=\"...\">` using BCP 47 tags — language[-Script][-REGION], hyphens not underscores.","introducedIn":"2026.08.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":6,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/markup.language"},{"id":"markup.title","title":"Page title","category":"readability","categoryLabel":"Readability","weight":2,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"established","specUrl":"https://developer.mozilla.org/docs/Web/HTML/Element/title","description":"A non-empty <title> is present and under 70 characters.","remediation":"Add a concise <title> tag. Agents often cite it verbatim.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":8,"precision":null,"recall":null,"falsePositives":1,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 2 flagged cases (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/markup.title"},{"id":"markup.meta_description","title":"Meta description","category":"readability","categoryLabel":"Readability","weight":2,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"established","specUrl":"https://developers.google.com/search/docs/appearance/snippet","description":"A meta description is present and between 50 and 200 characters.","remediation":"Add `<meta name=\"description\" content=\"...\">` to your primary pages. Agents frequently use it as a summary.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":8,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 2 flagged cases (30 needed to publish), 2 defective cases (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/markup.meta_description"},{"id":"coherence.language_declared_matches_content","title":"Declared language matches the content","category":"readability","categoryLabel":"Readability","weight":1,"state":"scored","scored":true,"determinism":"heuristic","heuristicParam":{"label":"detector","value":"stopword/script profile, >=40 words, WARN-only"},"maturity":"emerging","specUrl":null,"description":"<html lang> matches the language the visible content is actually written in, per a conservative deterministic language profile. The classic failure is a template default nobody edited: a German shop declaring lang=\"en\". A mismatch WARNs, never fails - the detector is probabilistic and stays silent when unsure.","remediation":"Set `<html lang>` to the language the page is actually written in. Agents pick tokenizers, target markets, and which variant to quote from this attribute; a wrong declaration routes the wrong readers to the page.","introducedIn":"2026.09.0","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":2,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/coherence.language_declared_matches_content"},{"id":"structured_data.jsonld_present","title":"JSON-LD present","category":"structured_data","categoryLabel":"Structured data","weight":2,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"established","specUrl":"https://schema.org","description":"At least one valid JSON-LD block is present.","remediation":"Emit JSON-LD for the page type (Product, Article, FAQPage, Organization). Use schema.org types.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":8,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 2 flagged cases (30 needed to publish), 2 defective cases (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/structured_data.jsonld_present"},{"id":"structured_data.validates","title":"Structured data validates","category":"structured_data","categoryLabel":"Structured data","weight":2,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"established","specUrl":"https://schema.org","description":"JSON-LD validates against the declared schema.org type.","remediation":"Validate your JSON-LD with Google Rich Results test. Fix missing required properties.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":4,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/structured_data.validates"},{"id":"structured_data.type_coverage","title":"Schema type coverage","category":"structured_data","categoryLabel":"Structured data","weight":1,"state":"scored","scored":true,"determinism":"heuristic","heuristicParam":{"label":"match","value":"type-to-purpose inference"},"maturity":"established","specUrl":null,"description":"Declared JSON-LD types cover the apparent page purpose (e.g. a product page has Product, a blog post has Article).","remediation":"Align JSON-LD type to page purpose. Product pages without Product markup are skipped by agent shopping flows.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":2,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/structured_data.type_coverage"},{"id":"coherence.jsonld_price_matches_visible","title":"JSON-LD price matches the visible price","category":"structured_data","categoryLabel":"Structured data","weight":2,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"emerging","specUrl":"https://schema.org/Offer","description":"A price declared in JSON-LD appears among the prices visible on the served page, compared by numeric value (\"79.00\" matches \"$79\"). Fails only when NO declared price is visible - a page whose machine channel and human channel disagree makes agents quote a number customers never see. Both price lists are recorded as evidence.","remediation":"Keep JSON-LD offers in the same template pass as the visible price so they cannot drift apart. If the visible price only renders via JavaScript, put it in the served HTML - agents that do not execute scripts currently see your structured-data price and nothing on the page to confirm it.","introducedIn":"2026.09.0","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":2,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/coherence.jsonld_price_matches_visible"},{"id":"coherence.jsonld_name_matches_visible","title":"JSON-LD name appears on the page","category":"structured_data","categoryLabel":"Structured data","weight":1,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"emerging","specUrl":"https://schema.org/name","description":"A Product/Organization/Store name declared in JSON-LD appears in the page title or visible text (case-insensitive). A declared name that appears nowhere is stale structured data or machine-only content - either way agents identify an entity visitors never see.","remediation":"Generate the JSON-LD `name` from the same source as the visible heading. After a rename, update structured data in the same release - agents read it first.","introducedIn":"2026.09.0","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":3,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/coherence.jsonld_name_matches_visible"},{"id":"auth.paywall_or_login_wall_on_landing","title":"Paywall / login wall","category":"actionability","categoryLabel":"Actionability","weight":2,"state":"scored","scored":true,"determinism":"heuristic","heuristicParam":{"label":"detector","value":"paywall/login-wall heuristic"},"maturity":"established","specUrl":null,"description":"Landing URL is not gated by a login or paywall.","remediation":"Render a meaningful preview or marketing view of gated content for unauthenticated requests. Agents cannot authenticate on your behalf.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":3,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/auth.paywall_or_login_wall_on_landing"},{"id":"journey.primary_probe","title":"Primary action reachable","category":"actionability","categoryLabel":"Actionability","weight":2,"state":"scored","scored":true,"determinism":"llm_assisted","heuristicParam":null,"maturity":"established","specUrl":null,"description":"A read-only LLM-driven probe can identify the primary offering and either its price or its primary call-to-action.","remediation":"If agents cannot identify what you sell within 3 steps, your primary-offer page is under-structured. Add a visible headline, price (or \"contact us\"), and canonical CTA.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"uncovered","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":0,"precision":null,"recall":null,"falsePositives":null,"falseNegatives":null,"reason":"llm_assisted: the runner returns SKIP unless ANTHROPIC_API_KEY is set, so an offline fixture can only observe the disabled path. Calibrating it requires the recorded-provider harness in packages/ai, tracked separately from this corpus."},"url":"https://agentspeed.com/rubric/check/journey.primary_probe"},{"id":"reachability.status","title":"Reachability","category":"actionability","categoryLabel":"Actionability","weight":2,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"established","specUrl":"https://datatracker.ietf.org/doc/html/rfc9110#name-redirection-3xx","description":"Landing URL returns a 2xx after at most one redirect.","remediation":"An agent gets whatever this URL returns, and nothing else. Serve a 2xx at the address you publish: a 403 or 404 means the agent reads an error page instead of your site, and if the block is aimed at bots, decide deliberately which agents it should apply to. Reach it in at most one redirect, since chained redirects break some agent crawlers.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":3,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/reachability.status"},{"id":"operability.primary_action_in_dom","title":"Primary action is clickable","category":"actionability","categoryLabel":"Actionability","weight":2,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"emerging","specUrl":null,"description":"The page expresses its primary action as a real clickable element - a link with an href, a button, or a submit input - rather than as text painted into an image or onto a plain element. Passes as soon as one clickable element carries action language. Skips when the page asks the reader to do nothing. Fails only when the page clearly asks for an action and nothing clickable carries it.","remediation":"Express the call to action as a real `<a href>` or `<button>` carrying the words as text (or as an `aria-label`). An agent driving the page acts on the DOM: a call to action baked into an image is invisible to it, and `alt` text does not make an image clickable.","introducedIn":"2026.10.0","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":2,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/operability.primary_action_in_dom"},{"id":"operability.filters_addressable","title":"Filters reachable by URL","category":"actionability","categoryLabel":"Actionability","weight":2,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"emerging","specUrl":null,"description":"When the page offers to filter or sort a list, at least one filtered view is reachable by URL - a link carrying a filter query parameter, or a GET form around the controls. Warns when controls are served but no filtered view has its own URL. Fails when the page offers filtering and serves no operable control at all. Skips on pages that offer no filtering.","remediation":"Make filtered and sorted views addressable: put the facet state in the query string and link to it, or wrap the controls in a `<form method=\"get\">`. An agent can request `?sort=price_asc` on the first try; a script-only widget it has to operate blind is the single largest published cause of agent failure on real sites.","introducedIn":"2026.10.0","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":2,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/operability.filters_addressable"},{"id":"actionability.agent_skills","title":"Agent Skills manifest","category":"actionability","categoryLabel":"Actionability","weight":1,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"emerging","specUrl":null,"description":"An Agent Skills manifest is reachable (e.g. `/.well-known/agent-skills.json`) describing discrete tasks an agent can perform on the site.","remediation":"Publish an Agent Skills manifest enumerating the tasks agents can perform (search, add-to-cart, contact-support). Agents that support skills will pick the right one without HTML scraping.","introducedIn":"2026.04.2","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":5,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 2 flagged cases (30 needed to publish), 2 defective cases (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/actionability.agent_skills"},{"id":"actionability.web_mcp","title":"WebMCP actions","category":"actionability","categoryLabel":"Actionability","weight":1,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"emerging","specUrl":null,"description":"The page exposes WebMCP (in-browser Model Context Protocol) so on-page agents can invoke tools without leaving the tab.","remediation":"Embed a WebMCP server on pages that have first-class actions (cart, support form, account settings). Agents in browser sessions invoke these directly without DOM scraping.","introducedIn":"2026.04.2","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":2,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/actionability.web_mcp"},{"id":"performance.ttfb_ms","title":"Time to first byte","category":"performance","categoryLabel":"Performance","weight":1,"state":"scored","scored":true,"determinism":"heuristic","heuristicParam":{"label":"threshold","value":"800ms"},"maturity":"established","specUrl":"https://web.dev/articles/ttfb","description":"Time-to-first-byte is under 800ms from a US-East origin. Measured as a single sample of total fetch time from one location, so treat it as directional.","remediation":"Agents time out aggressively. Use edge caching for anonymous requests to cut TTFB below 800ms.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":4,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/performance.ttfb_ms"},{"id":"performance.full_render_ms","title":"Full render time","category":"performance","categoryLabel":"Performance","weight":1,"state":"scored","scored":true,"determinism":"heuristic","heuristicParam":{"label":"threshold","value":"4s"},"maturity":"established","specUrl":null,"description":"Full render (network idle) completes under 4 seconds.","remediation":"Defer non-critical scripts. Agents configured with short timeouts may abandon the page before content is visible.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":4,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/performance.full_render_ms"},{"id":"performance.payload_kb","title":"Page weight","category":"performance","categoryLabel":"Performance","weight":1,"state":"scored","scored":true,"determinism":"heuristic","heuristicParam":{"label":"threshold","value":"3MB"},"maturity":"established","specUrl":null,"description":"Total page weight is under 3 MB, and the document can be fetched at all.","remediation":"Compress images, code-split JavaScript, and remove unused third-party scripts. Agents route via slow proxies more often than humans, and one working to a context budget will stop reading a document this large rather than pay for it.","introducedIn":"2026.04.1","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":3,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/performance.payload_kb"},{"id":"actionability.commerce_protocols","title":"Commerce protocol manifest","category":"actionability","categoryLabel":"Actionability","weight":1,"state":"scored","scored":true,"determinism":"deterministic","heuristicParam":null,"maturity":"emerging","specUrl":null,"description":"The site declares an agentic-commerce discovery manifest (x402, UCP, or ACP), so a buying agent can learn how to transact from the domain alone.","remediation":"If you sell to agents, publish the discovery manifest for the commerce protocol you support: `/.well-known/x402.json` (x402), `/.well-known/ucp` (UCP), or `/.well-known/acp.json` (ACP). Any one of the three passes — agents pre-flight these before attempting a transaction.","introducedIn":"2026.11.0","deprecatedIn":null,"calibration":{"state":"withheld","corpusVersion":"v1","measuredUnderRubric":"2026.11.0","cases":2,"precision":null,"recall":null,"falsePositives":0,"falseNegatives":0,"reason":"Too few labelled cases to publish a rate: 1 flagged case (30 needed to publish), 1 defective case (30 needed to publish). The counts are the honest answer here."},"url":"https://agentspeed.com/rubric/check/actionability.commerce_protocols"}],"versions":[{"version":"2026.11.0","status":"active","publishedAt":"2026-08-19","url":"https://agentspeed.com/rubric.json?version=2026.11.0"},{"version":"2026.10.4","status":"deprecated","publishedAt":"2026-07-30","url":"https://agentspeed.com/rubric.json?version=2026.10.4"},{"version":"2026.10.3","status":"deprecated","publishedAt":"2026-07-30","url":"https://agentspeed.com/rubric.json?version=2026.10.3"},{"version":"2026.10.2","status":"deprecated","publishedAt":"2026-07-30","url":"https://agentspeed.com/rubric.json?version=2026.10.2"},{"version":"2026.10.1","status":"deprecated","publishedAt":"2026-07-30","url":"https://agentspeed.com/rubric.json?version=2026.10.1"},{"version":"2026.10.0","status":"deprecated","publishedAt":"2026-07-28","url":"https://agentspeed.com/rubric.json?version=2026.10.0"},{"version":"2026.09.0","status":"deprecated","publishedAt":"2026-07-27","url":"https://agentspeed.com/rubric.json?version=2026.09.0"},{"version":"2026.08.1","status":"deprecated","publishedAt":"2026-07-26","url":"https://agentspeed.com/rubric.json?version=2026.08.1"},{"version":"2026.08.0","status":"deprecated","publishedAt":"2026-07-26","url":"https://agentspeed.com/rubric.json?version=2026.08.0"},{"version":"2026.07.4","status":"deprecated","publishedAt":"2026-07-25","url":"https://agentspeed.com/rubric.json?version=2026.07.4"},{"version":"2026.07.3","status":"deprecated","publishedAt":"2026-07-25","url":"https://agentspeed.com/rubric.json?version=2026.07.3"},{"version":"2026.07.2","status":"deprecated","publishedAt":"2026-07-23","url":"https://agentspeed.com/rubric.json?version=2026.07.2"},{"version":"2026.07.1","status":"deprecated","publishedAt":"2026-07-20","url":"https://agentspeed.com/rubric.json?version=2026.07.1"},{"version":"2026.04.2","status":"deprecated","publishedAt":"2026-04-27","url":"https://agentspeed.com/rubric.json?version=2026.04.2"},{"version":"2026.04.1","status":"deprecated","publishedAt":"2026-04-01","url":"https://agentspeed.com/rubric.json?version=2026.04.1"}],"calibration":{"corpusVersion":"v1","measuredUnderRubric":"2026.11.0","observations":127,"falsePositives":1,"falseNegatives":0,"caveat":"These cases are adversarial by construction: each one was written to defeat a specific rule. The results are a stress test, not a sample of the web, so they describe how the rules behave when someone is trying to fool them and not how often a score is right about a random site.","url":"https://agentspeed.com/rubric/accuracy"},"license":"The rubric content in this document may be freely read, quoted and implemented against, with attribution to AgentSpeed and the rubric version. The scanner implementation is not covered. Scores and certifications are issued only by AgentSpeed.","url":"https://agentspeed.com/rubric.json?version=2026.11.0"}