# The machine faces

Everything a machine needs from this origin is a first-class document
on this origin. Nothing is scraped, inferred, or maintained by hand:
every machine face renders from the same source module as the human
page it mirrors, inside the same build, behind the same lint — so the
face and the page cannot disagree.

## The documents

| document | what it is |
|---|---|
| [`/llms.txt`](/llms.txt) | the summariser contract: what this property is, the ledger line, the doors, the rules for restating claims |
| [`/.well-known/agents.json`](/.well-known/agents.json) | agent discovery: the live doors, the MCP door, the waitlist action — ledger first |
| [`/icp.json`](/icp.json) | the derivation contract: which agent classes arrive here and the hint → face → fallback classification ladder |
| [`/agent-classes.json`](/agent-classes.json) | the single frozen enumeration of agent classes that `/icp.json` selects from |
| [`/flow.json`](/flow.json) | the onboarding flow as typed steps, with the one sanctioned provisioning promise |
| `node_modules/epcis.dev/AGENTS.md` | the in-tarball operating manual — the CLI/MCP contract, greppable where your code already is |

Both JSON identity faces are built from one frozen enumeration — the
same module a runtime selector must read — so the published contract
and the runtime selection cannot drift. The same law binds
the [reference pages](/docs/reference/cli/) and the in-tarball
`AGENTS.md`: one typed catalog is the source, and a drift between any
two faces fails the site build.

## Every page is its own markdown twin

Core pages serve a `text/markdown` twin **on the same route**, selected
by the `Accept` header — no `/api/`, no `.md` suffix, no second URL to
go stale. Cut live:

```
$ curl -sI https://epcis.dev/translate/ \
    -H 'Accept: text/markdown' | grep -i \
    'HTTP/\|content-type\|vary\|x-client-type'
HTTP/2 200
content-type: text/markdown; charset=utf-8
vary: accept
x-client-type: md
```

The body opens as markdown, proof artifacts intact:

```
# Translate — ten years of vendor XML, translated

A decade of EPCIS 1.1 and 1.2 XML becomes EPCIS 2.0 JSON-LD,
deterministically, with a per-job round-trip fidelity report…
```

`Vary: Accept` keeps caches honest; `X-Client-Type: md|html` tells you
which face you got. The twins render from the same constants and
frontmatter as the HTML and pass the same brand lint.

## agents.json leads with the ledger

The discovery document's first line is the claims floor, not a pitch —
verbatim from the live origin:

```json
{
  "$comment": "Agent discovery for epcis.dev. Ledger first:
    live on this origin, no key — POST /translate,
    POST /validate, POST /hash. No conformance attestation
    has ever been issued. The dated launch ledger at
    /what-ships-today/ is authoritative for everything else;
    treat its open column as open, not live.",
  "doors": {
    "translate": "POST /translate — EPCIS 1.1/1.2/2.0 XML in,
      2.0 JSON-LD + FidelityReport out; no key",
    "validate": "POST /validate — document/event in, verdict +
      per-path errors against the pinned schema; no key",
    "hash": "POST /hash — event(s) in, CBV 2.0 §8.9 ni URIs
      out; no key"
  }
}
```

(Excerpt; strings wrapped for width. The full document adds the MCP
block, the surfaces map, and the waitlist action.)

Read the faces in this order when you arrive cold: `agents.json` for
the doors, `llms.txt` for the claim rules, `icp.json` to classify
yourself, then [the quickstart that fits](/docs/quickstart/mcp/).

---

**Proof, not adjectives.** This build could not verify the gateway's test suite green, so no sentence on this page claims a passing run — the last verified run is recorded in the repository's own CI, not here. Live on this origin, no key: POST /translate, /validate, /hash. No conformance attestation has ever been issued. The dated ledger is /what-ships-today/.
