Check criteria reference - scanner v1.15.0

Versioned HonestClaw scanner check criteria. Source of truth is the Acc-generated check-reference markdown for this scanner version.

Markdown source

Criteria

# Check criteria reference — scanner v1.15.0

- scanner_version: 1.15.0
- Provenance: regenerated and diff-verified against the code in this commit by the contract test; see this file's git history.

Generated by `scripts/generate-check-reference.ts` from the check registry (`src/scanner/checks`). Do not edit by hand; regenerate after any rungs change. Content changes require a SCANNER_VERSION bump (A1 invariant).

## State points

A check contributes `STATE_POINTS[state] / 100 × maxPoints` (`src/scanner/types.ts`):

| State | Points (of 100) |
|---|---|
| unknown | 0 |
| not_detected | 0 |
| detected | 10 |
| parseable | 35 |
| useful | 70 |
| high_confidence | 100 |

## Global negative-rung semantics (applies to every check)

A check's positive rungs (`detected` and above) are earned by its own grading
code, summarized per check below. When no clean positive signal is found, the
shared classifier (`src/scanner/classify-state.ts`) resolves the state from
the most informative HTTP outcome across the paths the check probed:

| Winning outcome | Resolved state |
|---|---|
| 2xx without the check's signal | `not_detected` |
| 401 / 403 (gated) | `detected` for existence-kind checks (the gate proves something is there); `unknown` for content-kind checks (the content cannot be assessed) |
| 404 / 410 | `not_detected` |
| 429 / 5xx / other reached status | `unknown` |
| status 0 (timeout / network / SSRF) | `unknown` |
| nothing probed / reachable | `unknown` |

**Honest-exhaustion rule**: a `not_detected` conclusion requires complete
evidence. When the scan's fetch/render budget latched before the check
resolved, a would-be `not_detected` resolves `unknown` instead (out of the
score denominator, lowers confidence). Positive evidence always stands.

**Orchestration overlays** (`src/scanner/scoring.ts`) can additionally force
two states onto ANY check after it returns, beyond its declared rungs:

- `not_detected` — a robots.txt `'*'`-baseline block on a surface the check
  needed forces a conclusive `not_detected` (`stampRobots`); a compliant
  generic agent is locked out, so the surface is a real gap.
- `unknown` — the runtime-budget truncation demotion, the no-work-item
  fallback, and the fail-open error catch all resolve `unknown`.

These two states form the globally assignable envelope
(`GLOBALLY_ASSIGNABLE_STATES` in `classify-state.ts`).

## Checks by dimension

"Reachable states" are the check's declared `rungs` keys — every state its own grading code can resolve to (the global envelope above can additionally force `not_detected`/`unknown`). "Cap" is the highest declared state; "effective max" is `maxPoints × STATE_POINTS[cap] / 100`, the most the check can actually contribute.

### discoverability

| Check | Max pts | Scored | Reachable states | Cap | Effective max | Description |
|---|---|---|---|---|---|---|
| api-existence | 5 | yes | unknown, not_detected, detected, parseable | parseable | 1.75 | Checks whether the domain exposes an API endpoint. |
| api-versioning | 5 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 5 | Checks whether the API uses versioned endpoints. |
| api-catalog | 3 | yes | unknown, not_detected, detected | detected | 0.3 | Checks whether the domain publishes an RFC 9727 API Catalog at /.well-known/api-catalog. |
| robots-txt | 3 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 3 | Checks whether the site publishes a valid robots.txt that declares a sitemap. |
| sitemap-xml | 3 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 3 | Checks whether the site publishes a valid, machine-readable XML sitemap. |
| canonical-domain | 2 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 2 | Checks whether the site resolves to one canonical origin (root/www convergence, canonical tag). |
| subdomain-sweep | 3 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 3 | Checks whether agent-relevant surfaces live at conventional subdomains (api.*, docs.*). |

Dimension totals (scored checks): maxPoints 24, effective max 18.05.

### content_accessibility

| Check | Max pts | Scored | Reachable states | Cap | Effective max | Description |
|---|---|---|---|---|---|---|
| llms-txt | 5 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 5 | Checks whether the domain publishes an llms.txt file for LLM consumption. |
| llms-full-txt | 3 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 3 | Checks whether the domain publishes an llms-full.txt file with comprehensive inline LLM-readable content. |
| markdown-twin | 3 | yes | unknown, not_detected, detected, parseable | parseable | 1.05 | Checks whether a markdown twin (.md) is published alongside docs HTML pages (V1 detection only). |
| ai-txt | 2 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 2 | Checks whether the domain publishes an ai.txt file declaring AI crawler policy. |
| raw-content-extractability | 8 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 8 | Checks whether meaningful content is extractable from raw HTML without JavaScript (not behind a JS shell, with usable main content). |
| freshness-signals | 3 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 3 | Checks whether the site publishes freshness signals (Last-Modified, ETag, sitemap lastmod) for content. |
| crawl-cost-estimate | 2 | no (informational) | unknown | unknown | 0 | Estimates crawl cost legibility from sitemap URL count and robots.txt Crawl-delay directives (informational — discoverability checks own sitemap/Crawl-delay scoring). |

Dimension totals (scored checks): maxPoints 24, effective max 22.05.

### bot_access_control

| Check | Max pts | Scored | Reachable states | Cap | Effective max | Description |
|---|---|---|---|---|---|---|
| ai-bot-rules | 5 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 5 | Checks whether robots.txt declares access rules specifically for AI bots (a declared AI-crawler preference). |
| content-signals | 2 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 2 | Checks whether robots.txt declares Cloudflare Content Signals (search/ai-input/ai-train preferences). |
| tdmrep | 2 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 2 | Checks whether the domain declares a TDM Reservation Protocol policy at /.well-known/tdmrep.json (a declared text-and-data-mining preference). |
| rsl | 3 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 3 | Checks whether robots.txt declares an RSL (Really Simple Licensing) License directive and, if so, how completely the linked license states its terms. |

Dimension totals (scored checks): maxPoints 12, effective max 12.

### protocol_and_capability_discovery

| Check | Max pts | Scored | Reachable states | Cap | Effective max | Description |
|---|---|---|---|---|---|---|
| link-headers | 2 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 2 | Checks whether the API advertises related resources via RFC 8288 Link headers. |
| well-known-index | 2 | yes | unknown, not_detected, detected, parseable | parseable | 0.7 | Checks whether the site publishes machine-readable /.well-known/ descriptors. |
| openapi-spec | 5 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 5 | Checks whether an OpenAPI/Swagger specification is published. |
| sdk-availability | 5 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 5 | Checks whether official SDKs or client libraries are available. |
| mcp-server | 5 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 5 | Checks whether the domain advertises an MCP server descriptor. |
| mcp-server-card | 3 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 3 | Checks whether the domain publishes an MCP Server Card for pre-connection discovery. |
| a2a-agent-card | 3 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 3 | Checks whether the domain publishes an A2A Agent Card for agent-to-agent discovery. |
| webmcp | 3 | no (informational) | unknown | unknown | 0 | Checks whether the site exposes WebMCP tools via navigator.modelContext at page load. |
| graphql-surface | 3 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 3 | Checks whether the domain advertises a GraphQL transport surface (static GET only — no introspection POST). |
| dns-aid | 3 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 3 | Checks whether the domain publishes a DNS-AID agent index at _index._agents.{domain}. |
| rate-limit-docs | 5 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 5 | Checks whether rate limiting is documented. |
| auth-discovery | 5 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 5 | Checks whether the site publishes a standardized, machine-readable authentication-discovery surface (OAuth 2.0 AS metadata / OpenID Connect Discovery / RFC 9728 Protected Resource Metadata) an agent can use to authenticate. |

Dimension totals (scored checks): maxPoints 41, effective max 39.7.

### authentication_and_credentials

| Check | Max pts | Scored | Reachable states | Cap | Effective max | Description |
|---|---|---|---|---|---|---|
| auth-documentation | 5 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 5 | Checks whether authentication documentation exists. |
| programmatic-auth-flow | 5 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 5 | Checks whether a programmatic (non-interactive) authentication flow is documented. |
| credential-management | 4 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 4 | Checks whether credential management (rotation, revocation, scoping) is documented. |
| sandbox-environment | 5 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 5 | Checks whether a sandbox or test environment is available. |

Dimension totals (scored checks): maxPoints 19, effective max 19.

### documentation_quality

| Check | Max pts | Scored | Reachable states | Cap | Effective max | Description |
|---|---|---|---|---|---|---|
| api-reference-depth | 5 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 5 | Checks whether API reference documentation has meaningful depth. |
| changelog-presence | 5 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 5 | Checks whether a changelog or release notes page exists. |

Dimension totals (scored checks): maxPoints 10, effective max 10.

### structured_data_io

| Check | Max pts | Scored | Reachable states | Cap | Effective max | Description |
|---|---|---|---|---|---|---|
| structured-data-io | 8 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 8 | Checks whether the API publishes a typed, consistent structured-data contract (OpenAPI response schemas). |
| data-export-api | 4 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 4 | Checks whether the API supports data export or bulk retrieval. |
| machine-readable-pricing | 1 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 1 | Checks whether pricing information is available via a machine-readable endpoint (JSON API). |

Dimension totals (scored checks): maxPoints 13, effective max 13.

### observable_state_and_reliability

| Check | Max pts | Scored | Reachable states | Cap | Effective max | Description |
|---|---|---|---|---|---|---|
| status-and-health | 2 | yes | unknown, not_detected, detected | detected | 0.2 | Checks whether the API exposes health or status endpoints. |
| webhook-documentation | 5 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 5 | Checks whether webhook or event notification documentation exists. |
| error-documentation | 5 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 5 | Checks whether error codes and error handling are documented. |
| retry-and-idempotency | 3 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 3 | Checks whether retry behavior and idempotency are documented. |
| x402-or-mpp-support | 1 | no (informational) | unknown, detected, parseable, useful | useful | 0.7 | Checks whether the API advertises machine-payable access (x402 / MPP): an HTTP 402 response, a payment-required response header, or a published /.well-known/x402.json manifest. |

Dimension totals (scored checks): maxPoints 15, effective max 13.2.

### agent_safety_and_trust

| Check | Max pts | Scored | Reachable states | Cap | Effective max | Description |
|---|---|---|---|---|---|---|
| security-txt | 3 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 3 | Checks whether the site publishes a valid security.txt for vulnerability disclosure. |
| legal-pages | 2 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 2 | Checks whether terms of service, privacy, and data-use policies are discoverable. |
| org-identity | 3 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 3 | Checks whether the site exposes org identity signals (legal name, address, support email, socials). |
| metadata-consistency | 3 | yes | unknown, not_detected, detected, parseable, useful, high_confidence | high_confidence | 3 | Checks whether homepage metadata is internally consistent (canonical, Open Graph, schema, pricing). |

Dimension totals (scored checks): maxPoints 11, effective max 11.

## Grand totals (scored checks)

- maxPoints: 169
- effective max contribution: 158 — checks whose declared cap sits below `high_confidence` cannot earn their full maxPoints, so a site that maxes every check scores 93/100, not 100.