# Reading completeness

Every query result says whether the index fully answered. Three fields carry it,
and they are the difference between "nothing was written" and "part of the index
did not answer".

| Field | Value | What happened | What to do |
|---|---|---|---|
| `partial` | `true` | Some of the index could not answer. | Say so. Never report absence. |
| `coverage` | `complete` | Everything in range was read. | Nothing. |
| | `timed_out` | The query ran out of time. | Retry, or narrow the range. |
| | `range_too_wide` | The range spans more than one request may read. | Narrow it; retrying will not help. |
| | `recent_unavailable` | The newest data in range is still loading. | Retry shortly. |
| | `field_unavailable` | A filter needs a field part of the index was built without. | The results are right but may be incomplete; narrow to rebuilt months or retry after the rebuild. |
| `from_clamped` | `true` | `from` was moved forward to the plan's archive boundary. | Say which window was searched. |

A complete answer is:

```
const complete = !r.partial && r.coverage === "complete" && !r.from_clamped;
```

## Why absence is the dangerous conclusion

A `503` means no part of the index answered, and every client treats it as an
error. A `200` with `partial: true` means some parts answered, and looks like a
normal result. An empty page from half the index reads exactly like an empty
page from all of it, which is why the fields exist and why an agent must read
them before saying something did not happen.

## What these fields are not

`total_relation` and a facet's `approximate` are about counting: whether a total
or a count was exact or estimated. They do not say whether the index answered.
An `approximate` total can still be `complete`.

## Over MCP

Tool results carry the same fields in `structuredContent`. Every search-shaped
tool description repeats the rule: never conclude that something does not exist
when `partial` is true, `coverage` is not `complete`, or `from_clamped` is true.
