# Ratings

> Caliber grades every question from AAA to C on how likely it is to resolve cleanly. Read ratings over GraphQL, REST or as an embeddable badge.

Every question gets a quality rating from Caliber, Somnia Oracle's rating engine: a **band** from `AAA` to `C`, a **score** from 0 to 100, and a breakdown by criterion. A rating measures how well the question is defined: whether its sources are reachable and relevant, whether they agree, and whether the question text is precise. It predicts how cleanly the question will resolve, not what the answer will be.

Ratings are advisory. They never block or change resolution. Venues and apps use them to decide which questions to list or trust.

## Bands

| Band | Score | Meaning |
| --- | --- | --- |
| `AAA` | 90 to 100 | Exceptional definition quality; highly reliable and unambiguous. |
| `AA` | 80 to 89 | Very strong; minor weaknesses. |
| `A` | 70 to 79 | Strong; some limitations. |
| `BBB` | 60 to 69 | Adequate; moderate ambiguity or risk. |
| `BB` | 50 to 59 | Speculative; notable weaknesses. |
| `B` | 35 to 49 | Weak; high risk of poor resolution. |
| `CCC` | 20 to 34 | Very weak; high likelihood of problematic resolution. |
| `CC` | 10 to 19 | Highly unreliable; severe structural issues. |
| `C` | 0 to 9 | Structurally broken or guaranteed to fail resolution. |

## Criteria

Two criteria are **gates**. If either fails, the score is 0, whatever else is true:

- **Source reachability:** can an agent reach every source?
- **Source blocklisted:** is any source on a blocklist?

The rest are **scored** and weighted into the final score:

| Criterion | Weight | Question it asks |
| --- | --- | --- |
| Source count | 23.33% | Are there enough sources to resolve fairly? One source scores 20%; five or more score 100%. |
| Source agreement | 23.33% | Do enough of the sources agree? |
| Source relevancy | 23.34% | Are the sources likely to contain the information the question asks for? |
| Source history | 10% | Have these sources been used in earlier questions that resolved successfully? |
| Prompt subjectivity | 10% | How precise, specific and unambiguous is the question text? |
| Temporal soundness | 10% | For a time-based question, does the source encode the moment being asked about? |

Each criterion in a rating carries a status, a one-line summary and the evidence behind it, such as which URLs were checked and what they returned. The quickest ways to a higher grade are more independent sources, sources with the timestamp in the URL, and question text that names the exact instant, unit and thing being measured. See [Asking questions](./asking-questions).

## When ratings appear

New questions are rated shortly after they are indexed, usually within seconds to a couple of minutes. Until then the rating is `null`: show it as "unrated", not as an error.

A rating is fixed for a given algorithm version (`rating_version`). When the algorithm changes, questions are re-rated under the new version. Treat `(question_id, rating_version)` as the cache key and `rated_at` as freshness.

## Reading ratings

Ratings are public; no key is needed. The origins are:

| Network | Origin |
| --- | --- |
| Mainnet | `https://prd.oracle.somnia.host` |
| Testnet | `https://dev.oracle.somnia.host` |

### GraphQL

`POST {origin}/v1/graphql`. The rating is a nested field on a question:

```graphql
{
  Question_by_pk(id: "72000") {
    displayName
    rating {
      rating          # band, e.g. "AA"
      final_score     # e.g. "82.00"
      rating_version
      criteria        # [{ key, name, status, summary, evidence, ... }]
      rated_at
    }
  }
}
```

You can't filter, sort or subscribe through the nested `rating` field. For lists, query the ratings table directly and join on `question_id`:

```graphql
{
  caliber_question_rating(where: { rating: { _eq: "AAA" } }, order_by: { rated_at: desc }, limit: 20) {
    question_id
    rating
    final_score
    rating_version
    rated_at
  }
}
```

### REST

| Endpoint | Returns |
| --- | --- |
| `GET {origin}/api/caliber/{questionId}` | The band, score, definition and criteria, with badge and detail URLs |
| `GET {origin}/api/caliber/{questionId}/badge` | An SVG badge you can embed with `<img src>` |
| `GET {origin}/api/caliber/latest` | The most recent ratings with their questions, paginated with `limit` and `cursor` |

```bash
curl https://prd.oracle.somnia.host/api/caliber/72000
# {"status":"ok","result":{"id":"72000","rating":"AAA","score":100,...}}
```

An unrated question returns a status other than `ok`.

## In the Somnia Explorer

The [Somnia Explorer](./explorer) shows each question's band on its card in the question list and on its detail page.

---

Every page is also Markdown: append `.md` to its URL, or ask for `text/markdown`. Found something wrong, missing or confusing in these docs? Tell us: `POST /api/feedback` on this site with JSON `{"message": "…", "context": "what you were doing and what happened", "page": "…"}`, or a plain-text body. `GET /api/feedback` gives the JSON Schema. The team reads every one.
