# Per-item questions

Ask a question once for each item in a list, in the same call.

## When to use one

Some judgments apply to every item in a list: does each tender match the search, is each line of an
order allowed, which category does each message belong to. Instead of numbered copies of a question
(`match_1`, `match_2`…), add `each` to one question. It is asked once for every element of the list,
in the same call as the rest of the Decision, and answers with one native answer per element.

## Writing one

```yaml
format: 3
model: jev-1.13.0
state_schema:
  type: object
  required: [search, tenders]
  additionalProperties: false
  properties:
    search: { type: string }
    tenders:
      type: array
      maxItems: 25
      items:
        type: object
        required: [ref, summary]
        additionalProperties: false
        properties:
          ref: { type: string }
          summary: { type: string }
questions:
  match:
    type: noul
    each: input.tenders
    instructions: Would a supplier searching with `input.search` want to bid for `item`?
```

- `each` names a list in the input (`input.tenders`) or in the context (`context.categories`), as a
  plain dotted path.
- An input list must declare the shape of its `items` and a `maxItems` between 1 and 100. Between 10
  and 25 suits most lists. A list in the context is bounded by its own length, up to 100.
- In the instructions, `` `item` `` stands for the element being judged, and `` `item.summary` `` for
  one of its fields. Each copy of the question is told exactly which element it is about.
  `` `item` `` means nothing outside an `each` question, so it is refused there.

Any kind of question can be asked per item: `noul`, `choice` or `score`.

## The answer

The answer is a list of native answers in the same order as the elements:

```json
"match": [
  { "type": "noul", "noul": 0.93 },
  { "type": "noul", "noul": 0.03 }
]
```

An empty list answers `[]`. When every question is per item and every list is empty, the Decision
answers straight away and the run records no tokens.

In the SDK, `perItem(items, answers)` pairs each answer with the item it belongs to.

## Examples and Test cases

An expected answer for a per-item question is a list too, one entry per element. Use `null` for an
element you have no expectation about. Evaluations compare per-item answers item by item.

## Limits

The whole Decision can expand to at most 500 questions, and it must still fit the model's input size
when every list is at its `maxItems`. If it doesn't, the error names a `maxItems` that would fit.

Publishing always asks each copy with its own element. Test runs of a draft can also try the
`shared` expansion, which sends the list once and asks every copy against it; that option is in the
CLI (`typefuse evaluate --expansion shared`) and MCP, not in the web app yet.

The [Definition assistant](https://typefuse.dev/guides/definition-assistant) spots numbered copies of a question and
offers to turn them into one `each` question.
