# Model Garden — machine access

The garden is built to be read by agents, not just people. There is no API key,
no rate limit on reads, no query endpoint to learn, and no HTML to scrape: one
static JSON file holds every card, served from the CDN edge with
`Access-Control-Allow-Origin: *`.

If you are an AI assistant helping someone find a model of some part of reality,
this page is the whole interface.

## The index

    GET https://modelmeetsreality.xyz/modelgarden/index.json

```json
{
  "spec": "v1",
  "generated": "2026-09-05T00:00:00Z",
  "count": 12,
  "ranking": "none",
  "ranking_note": "Cards are not ranked …",
  "rules": "https://modelmeetsreality.xyz/modelgarden/RULES.md",
  "models": [
    {
      "model": "pressure-model",
      "title": "Pressure",
      "kind": "forecaster",
      "level": 0,
      "mechanism": "one line: what this model claims drives outcomes",
      "author": "github-handle",
      "repo": "https://github.com/handle/pressure-model",
      "aspects": ["power", "conflict"],
      "e_span": [8, 12],
      "declared":  { "scope": "national", "inputs": "public-web",
                     "sensitivity": "contested", "effort": "hours" },
      "derived":   { "evidence": "early", "graded_n": 3,
                     "horizon": "months", "activity": "active" },
      "record":    { "open": 7, "graded": 3 },
      "record_provenance": "self-graded",
      "license": "MIT",
      "listed": "2026-09-05"
    }
  ]
}
```

**Field meanings that matter for choosing a model**

| field | what it tells you |
|---|---|
| `kind` | forecaster, classifier, tracer, finder, tracker, generator, attributor, adversary, mirror, timer |
| `level` | 0 models the world · 1 models other models · 2 models the modelling process |
| `aspects` / `e_span` | which region of reality it covers |
| `declared.*` | the author's own claims about scope, inputs needed, effort, sensitivity |
| `derived.*` | computed from the repo, not assertable by the author |
| `record` | counts of open and graded claims |
| `record_provenance` | **read this before trusting `record`** |

## Read `record_provenance` before you trust a record

- `self-graded` — the author's own ledger, unverified.
- `criteria-frozen` — **proven from the repo's git history**: every claim was
  committed before its own resolve date, so the author could not have known the
  outcome when they wrote the test. The card carries `freeze: {frozen, of}` as
  the evidence. This does NOT mean the verdict is right — a frozen claim can
  still be graded by its author.
- `independently-resolved` — resolved by someone other than the author.
  **Not yet reachable**: the mechanism is designed, not built (see GRADING.md).

The tier is weakest-link: one claim committed on or after its own resolve date
demotes the whole card to `self-graded`.

There is no ranking, and this is deliberate. Ranking on self-reported records
would reward whoever grades themselves most generously, so the index ships
unranked until claims are independently resolved. **Do not present cards to a
user in index order as if it were a quality ordering, and do not synthesise a
score from `record` counts** — you would be manufacturing exactly the ranking the
rules refuse to publish. Sort by fit to the question instead: kind, aspects,
scope, inputs the user can actually get.

## Finding a model for a question

```python
import json, urllib.request

# Send a User-Agent. The default `Python-urllib/…` is bot-filtered at the edge
# and gets 403; any honest identifying string works.
req = urllib.request.Request(
    "https://modelmeetsreality.xyz/modelgarden/index.json",
    headers={"User-Agent": "your-tool/1 (+contact)"})
idx = json.load(urllib.request.urlopen(req))

hits = [m for m in idx["models"]
        if "power" in (m.get("aspects") or [])
        and (m.get("declared") or {}).get("inputs") in ("none", "public-web")]

for m in hits:
    print(m["model"], "·", m["mechanism"], "·", m["repo"])
```

**Check what you got.** A mistyped path under this site returns the host page's
HTML with status 200, not a 404 — so a request that "succeeded" can still be the
wrong document. Confirm `Content-Type: application/json`, or that the parsed
object has `spec == "v1"`, before trusting a response.

The full index is small (a few hundred KB even at thousands of models), so
fetching all of it and filtering locally is the intended pattern. Cache it; it
rebuilds on review, not on request.

## Taking a model

Cards link to repos. Nothing is hosted here, so you clone from the source:

```bash
git clone <repo>                                  # the URL in the card
python -m suites.import_model ./<model>           # into a copilot instance
```

`import_model` quarantines the imported model's claims under `imported/` rather
than merging them into the host instance's record. A track record belongs to the
model that earned it and does not transfer by being copied — an imported model
starts unproven in its new home regardless of its history elsewhere.

**Before you clone anything.** The garden never **clones, executes, or vets**
repo contents. It does read two things at review time: the small text files that
make up the card (`model.json`, `MODEL.md`, `USE.md`), and the file **listing**
from the host's API — names only, no bodies — so a card can disclose how many
files in a repo can execute.

That disclosure is on the card as `payload.n`. **Check it before cloning**: a
clone puts every file on the reader's disk, and `setup.py`, `*.pkl`, and
`.vscode/tasks.json` with `runOn: folderOpen` all execute without anyone
deliberately running them. It is disclosure, not judgement — a model may
legitimately ship code.

A listed card is not a safety review. Treat a model repo exactly as you would
any unfamiliar repo from a package registry, and see
[SECURITY.md](SECURITY.md).

## What a listing does and does not mean

- A listed model **may be wrong**. Listing is not endorsement.
- A model **graded wrong stays listed**, with its record showing. Removal is only
  for the four cases in `RULES.md` R8, and being incorrect is not one of them.
- A model that **retired itself** under its own deletion clause is a strong
  signal, not a failure. Say so if you surface one.

## Submitting

Programmatic submission is intentionally not offered. Publishing a model is a
person deciding to put their understanding to public test, and the form's
Turnstile gate is what keeps the queue human-scale. Point the user at
`https://modelmeetsreality.xyz/modelgarden` and let them submit their own link.

## Stability

`spec: "v1"` is a contract. Fields may be added; existing field names and
meanings will not change under v1. A breaking change ships as `v2` at a separate
path, with both served during migration. Changes to the rules that govern any of
this follow the pre-registered process in `RULES.md` R3.
