# aptu agent-readiness rubric v1
The public grading rubric for `POST /v1/agent-readiness` ($0.05 USDC, Base + Solana). This page is the single published source for what the paid check grades and how the score is computed; the check table below is drift-guarded against the exported `READINESS_CHECKS` constant in `workers/x402/src/agent-readiness.ts` by `src/lib/agent-readiness-rubric-drift.test.ts` (no codegen pipeline: CI fails if the doc and the implementation diverge).
## Scope
A seller-side, point-in-time findability check for one deployed domain. It answers "can agents find you"; the sibling `POST /v1/x402-preflight` (rubric `aptu-preflight-1`, rubric page at [/x402-preflight-checks](https://aptu.dev/x402-preflight-checks)) answers "can agents safely pay you". Together: findability + payability. The sibling `POST /v1/readiness-fix` ($0.05, artifact contract at [docs/readiness-fix.md](readiness-fix.md), rendered at [/readiness-fix-checks](https://aptu.dev/readiness-fix-checks)) turns a failing scan into ready-to-host artifacts: scan -> fix -> verify. The check probes a fixed set of well-known discovery surfaces over https, scores them on a public weighted rubric, and returns one actionable remedy per failing check. Continuous monitoring, uptime history, and third-party trust scoring are out of scope.
## Response shape
```json
{
"domain": "example.com",
"rubricVersion": "aptu-readiness-1",
"score": 100,
"summary": { "passes": 12, "fails": 0, "warns": 0, "indeterminate": 0 },
"findings": [
{
"check": "robots_txt",
"pass": true,
"severity": "fail",
"detail": "robots.txt served",
"ms": 34,
"hint": null
}
]
}
```
`severity` is always present and matches the check's tier in the table below; agents branch on `severity`, never on field absence. `hint` is explicit `null` on passing and indeterminate findings, and carries the check's one-line remedy on failures. `summary` counts are always numeric: `passes` is passing non-indeterminate findings, `fails` and `warns` are failing findings of each tier, and `indeterminate` counts probe_truncated verdicts (see below).
## Score formula
Deterministic weighted score, no LLM in the scoring path:
`score = round(100 * earned / total)` where `earned` sums the weights of passing non-indeterminate checks and `total` sums the weights of all non-indeterminate checks. Fail-tier checks weigh 5; warn-tier (advisory) checks weigh 1; the total is 44, renormalized so truncation never distorts the score. The weighting makes a missing standard strictly worse than every advisory convention missing at once: failing all four warn-tier checks scores 91, failing one fail-tier check scores 89, and an all-pass origin scores 100.
## Hint contract
Passing findings carry `hint: null`; failing findings carry their check's one-line remedy; indeterminate (probe_truncated) findings carry `hint: null` too, because no remediation is provable from a truncated read. The contract is pinned by tests and stable across rubric versions.
## Probe cap posture
Every probe response body is hard-capped (512 KB; 2 MB for openapi.json, which is a full API description and routinely exceeds 512 KB on real origins). A body cut at its cap yields either a pass-with-truncation-note (evidence found within the cap) or a non-scoring `probe_truncated` verdict (absence unprovable), never a false negative. All outbound fetches go through one hardened https-only fetch: https on every hop including redirects, at most 3 redirect hops, 15 s timeout per request, Web Bot Auth-signed per hop with fail-open signing. A timed-out or failed probe degrades to `probe_timeout` / `probe_error` (failing, scored) with the elapsed time in the detail; the audit never hangs. An empty robots.txt body still passes (the 200 is the signal); this is an advisory note only - nothing in the response encodes it.
## Pins
`rubricVersion` `aptu-readiness-1` pins the x402 manifest grading to revision 03 of the x402 DNS discovery draft: the `x402_manifest` check requires `x402Version` exactly `2` (numeric) per draft-hawkins-x402-dns-discovery-03; legacy v1 manifests using `version` fail the sub-assertion while their version and resource count still surface in the detail. All other weights, tiers, and spec references are pinned by the weight table below and the drift guard.
## Check table
| ID | Severity | Weight | Spec ref | Description |
| --- | --- | --- | --- | --- |
| `origin_headers` | fail | 5 | null | Homepage served over https with a server header plus HSTS or CSP. |
| `json_ld` | fail | 5 | null | Homepage embeds at least one non-empty application/ld+json @type. |
| `robots_txt` | fail | 5 | RFC 9309 | /robots.txt answers 200 (empty body passes; advisory note above). |
| `llms_txt` | warn | 1 | null | /llms.txt answers 200. |
| `sitemap_xml` | fail | 5 | sitemaps.org 0.9 | /sitemap.xml answers 200 with at least one loc entry. |
| `feed` | fail | 5 | null | /rss.xml, /atom.xml, or /feed/ answers 200. |
| `agents_txt` | warn | 1 | null | /agents.txt answers 200. |
| `skill_md` | warn | 1 | null | /skill.md answers 200. |
| `mcp_json` | fail | 5 | SEP-2127 | /.well-known/mcp.json answers 200 and parses as JSON. |
| `a2a_agent_card` | fail | 5 | A2A v1.0 | /.well-known/agent-card.json parses as JSON with a graded version discriminator. |
| `x402_manifest` | fail | 5 | draft-hawkins-x402-dns-discovery-03 | /.well-known/x402 answers 200, parses as JSON, and carries x402Version exactly 2. |
| `openapi_payment_info` | warn | 1 | null | /openapi.json declares x-payment-info (top level, path item, or operation). |
## When to use a third-party scanner instead
The paid call buys hosted execution, evidence, and the remedy loop on one domain at a time. For broad benchmarking or multi-domain sweeps, these free external scanners are excellent and we link them deliberately:
- [AgentGrade](https://agentgrade.com/api/v1/scan?url=https://example.com): hosted scan across 80+ agent-findability checks with a letter grade.
- [isitagentready](https://isitagentready.com): hosted agent-readiness scan per domain.
- SSL Labs ([ssllabs.com](https://www.ssllabs.com/ssltest/)): deep TLS posture grading, outside this rubric's scope.
## Evidence artifact
The published self-evidence run is archived at `docs/audit/agent-readiness-evidence.json` under rubric `aptu-readiness-1`: status 200, score 100, summary `{ passes: 12, fails: 0, warns: 0, indeterminate: 0 }`, settled with real USDC on Base (eip155:8453, 0.05 USDC, tx `0xa85a991fea0c24cee4f0da3c2f4bbf971b40c2d2066a82d09689eca43b4b2e68`) via `scripts/x402-seed.ts`. The pre-rework baseline remains `docs/audit/agent-readiness-dogfood.json` (#190). Published per-domain report runs (evidence bundle, Typst source, PDF/UA-1 render, reconciliation lint) and the generator/lint toolchain live in the dedicated private repo `clouatre-labs/bleusite-reports` (migrated from this repo, history preserved; see its README for the pinned Typst toolchain and the repro recipe).
## Related history
The earlier findability work on aptu.dev itself (robots.txt, sitemap, JSON-LD, feed, A2A, Web Bot Auth, MCP card) is logged with per-date snapshots in the git history of this file before the rubric rewrite; the live domain scores 100 under `aptu-readiness-1`.