# Choose or make a lens

> A lens decides what is pulled out of each passage. Use a built-in one, or make your own from it.

A lens says what is pulled out of each passage and what gets compared.

## The built-in lenses

| Lens | Its cards |
|---|---|
| **nonfiction** | Concepts, claims, cases and practices |
| **fiction** | Motifs, characters, places and objects |
| **notes** | Ideas, claims, decisions and open questions |

A collection names its lens in its note, in the `reader` property.

## The notes lens

The notes lens reads your own notes as notes. A long note is read a section at a time, and the prompt names the note and the section.

It pulls out four kinds of card:

- **idea**: something worth trying or developing.
- **claim**: a position the note takes, with what supports it.
- **decision**: what was chosen, why, and what was ruled out.
- **question**: something still open, and why it is open.

Each card carries a **basis** that says where the point comes from, not what it is about: `own` for your own thinking, `source` for something you read or watched, `experience` for something you lived or did, and `discussion` for a conversation or meeting. Search can narrow by it, so you can tell your own thinking from what you copied in.

The lens also reads three of each note’s properties into every prompt: `tags`, `status` and `created`. A note without one is read as `unknown` for it. To read more properties, such as `project`, list them in the collection note’s `fields` (see [Make a collection](collections.md)), or tick them in a [survey](survey.md).

A new collection made from a folder, a tag or a Base starts on the notes lens. A collection you made earlier keeps its lens.

### Switch an older collection to notes

A collection of notes or Base rows that is read by the nonfiction or fiction lens shows a **Read as notes** row in its dialog (**Settings → Topic Map → Collections**, then select the collection). The row gives the cost of switching, worked out without calling a model. Select **Switch to notes** to change the note’s `reader` to `notes`.

- Switching starts a new index, so every section is read again. The old index stays where it is until you remove it.
- The switch is logged like any other run. **Undo a run** (or the panel’s **Runs** tab) puts the lens back.

## Make your own

1. Open **Settings → Topic Map → Lenses** and select **Customize…** beside a built-in lens. Or run **Customize this lens…** (the panel’s Setup menu).
2. Topic Map shows what it will write, then makes a folder in Model Hub's skills folder.
3. Add your changes to its `reader.yml`.
4. In Model Hub, reload the skills. Your lens then shows under **Yours** on the Lenses tab.
5. Name it in a collection note's `reader` property.

Your lens **extends** the built-in one: it holds only what you change, so you keep the built-in's later improvements.

A facet can set **group_by** to the name of one of its fields. That field names a card, and cards of that facet with the same name and meaning are shown as one. The built-in lenses group concepts by term, ideas by idea and motifs by motif. A lens that extends a built-in one keeps this; set `group_by: null` on a facet to turn it off.

A lens is a Model Hub skill: a folder with `SKILL.md`, `reader.yml` and a `prompts` folder. Model Hub needs a skills folder set in its settings.

## Domain libraries

A domain library defines kinds of card once, so several lenses can share them. It is a Model Hub skill with a `domains.yml`, which holds:

- **domains**: kinds of card read together with the passage.
- **addons**: kinds of card read in a later pass.
- **unit_fields**: passage fields that a lens using its domains also gets.

Each domain has a two-letter `key`, a `count`, an `about` and its `fields`.

A lens uses a library with these keys in its `reader.yml`:

| Key | What it does |
|---|---|
| `facets_from` | The library skill's name. |
| `domains` | The library's domains read with the passage, besides the lens's own facets: `[motifs, helpers]`. |
| `addons` | Later passes, each a list of the library's domains (`[[craft]]`), or a mapping that also picks which passages it reads (`[{domains: [craft], select: craft}]`). See [Add-on passes](#add-on-passes). |
| `domain_notes` | Rewords a domain's `about` or a field's description for this lens. It can't add or remove a field. |
| `max_tokens` | The longest reply allowed for a passage, from 256 to 32000. A lens with many domains needs more than the default. |

A lens with `addons` needs an add-on prompt: `prompts/extract-addon.md` in the lens, or `extract-addon.md` in the library.

### Add-on passes

An index run reads each passage once for the lens's own facets and its `domains` (pass 0). Then it runs each add-on pass, in order, on the passages pass 0 let through the lens's `gate`. A passage pass 0 gated out never reaches an add-on. A passage whose pass 0 failed, or isn't read yet, waits for it.

Each add-on pass is one more call per passage, and asks only for that pass's domains. Write a pass as a list of domains, or as a mapping with `select`:

```yaml
addons:
  - {domains: [craft], select: craft}   # pass 1: only the passages the craft screen picks
  - [voice]                             # pass 2: every passage pass 0 let through
```

`select: craft` reads the passage field `craft_notable`, a whole number from 0 to 3 that pass 0 gives each passage. Put it in the lens's `unit_fields` or in the library's. In each book the pass takes:

- every passage scored 3;
- passages scored 2, spread evenly through the book, up to 5% of the book's passages;
- the book's first and last passage that pass 0 let through.

The pick is the same every time for the same scores.

What an add-on reads is kept under its own key, which includes the pass, its domains and the add-on prompt. So:

- adding an add-on pass, or changing one, never reads pass 0 again;
- rewording `extract-addon.md` reads that pass again, but not pass 0;
- a run stopped part way through a pass carries on from what it kept, and nothing kept is paid for twice.

The dry run counts each pass's reads in its passages to read, and prices them. It also says how many passages each pass is waiting on: those need pass 0 first, so a new collection's add-on reads are known only once pass 0 has run. **Undo a run** takes back what the run's add-on passes read, with their cards.

Topic Map refuses a lens that names a domain its library lacks, lists a domain in two passes, or rewords a field the domain doesn't have. Each refusal names the line at fault. A worked example, a library and a lens that uses it, is in the repository's `docs/examples/lens-domains`.

## Check your lenses

Run **Check my lenses** (the panel’s Setup menu), or use the check button on the Lenses tab. It lists any problem in plain words, with the line at fault. Topic Map also checks on its own after an update.

A lens in an older format still works, and the check offers to rewrite it in the current one. The rewrite happens only when you select **Rewrite**, and it has no undo.

## What a lens changes later

Changing a lens changes what is sent for each passage, so the next index run reads the affected passages again. The dry run shows how many.

## Related

- [Make a collection](collections.md)
- [Survey a collection](survey.md)
