# AI extras

A sale listing from the passport, search across a car's documents and services, translation of a foreign document beside its original, and a maintenance plan read from the owner's manual.

## What it does [#what-it-does]

The extras of the AI features spec (§5) sit behind one flag, `ai.extras`, off by default, and each needs its model in the registry ([ADR-0017](/docs/adr/0017-ai-model-registry-and-quotas)). A model writes text or reads a document; it never computes a figure the app shows (RN03), and what it returns stays a draft until the person keeps it (RN10).

| Extra                | Where (board)                               | Model call (registry row)            | Quota       |
| -------------------- | ------------------------------------------- | ------------------------------------ | ----------- |
| Sale listing         | M-Vender ⋯ → `Extra-Listing`                | `listing` (text)                     | structuring |
| Search the documents | M-Documentos ⋯ → `Extra-Search`             | `embedding`                          | none        |
| Translation          | a document's sheet → `Extra-Translate`      | `translation` (text)                 | structuring |
| Plan from the manual | M-Manutencao, Plan segment → `Extra-Manual` | `manualPlan` (document: reads a PDF) | structuring |

The monthly summary named in §5 is the insights feed's ([Insights](/docs/features/insights)).

## Grounding [#grounding]

`@autofolio/domain/grounding` holds the rules, with tests:

- `figuresIn` reads the figures a text writes with their separators dropped ("15.000 km" and "15,000 mi" both write `15000`; a date's parts are figures of their own).
- `groundLines` keeps only a model's lines whose figures all appear in what it was given; the listing drops the others and says how many.
- `groundTranslation` pairs each read line with its translation by number; a line left out, or whose figures changed, shows the original and asks for a check.
- `groundPlanItem` keeps a manual's interval only when the quoted words print it, and turns miles into km and years into months.

## Sale listing [#sale-listing]

`passport.listing { vehicleId, sections, language, distanceUnit, platform }` (owner role) writes from `snapshotOf`, the same field-by-field snapshot a passport link stores, limited to services, receipts and specs: photos, costs and the estimate never reach it, and neither can a plate, VIN or address (RN09). Distances are in the reader's unit. The phone keeps one answer per language for the session; nothing is stored. The owner edits the title and text, then copies or shares them.

## Search across documents [#search-across-documents]

`vehicleDocument.search { vehicleId, query, platform }` embeds the question with the car's newest 100 services (title, shop, items, note) and 100 documents (title, the text the phone read, a kept translation), ranks them by cosine similarity and answers up to five hits, each a service or a document with its own date and reading. Nothing is generated. Row-level security leaves out the documents a Member may not see. The phone reads a photo filed with **Add document** while `ai.extras` is on, so its text is searchable (`vehicle_document.text`).

## Translation [#translation]

The phone reads the document's stored photo, or new photos of a PDF's pages (it reads pictures only), and sends the lines to `vehicleDocument.translate { id, lines, locale, platform }`; they reach the model scrubbed. The draft shows each translation above its original. **Keep translation** calls `vehicleDocument.keepTranslation`, which stores the lines in `vehicle_document.translation` and the read text in `vehicle_document.text`; the file itself never changes. `vehicleDocument.translation { id }` reads the kept one.

## Plan from the owner's manual [#plan-from-the-owners-manual]

The owner picks a PDF among the car's documents, or one from Files (filed as "Owner's manual"). `reminder.manualPlan { vehicleId, documentId, locale, platform }` (editor with documents) reads a PDF of up to 20 MB from private storage and sends it to the model as a document part; it is the one unscrubbed input, since a manufacturer's manual holds no owner's data. Each suggestion keeps the manual's page and words. **Add** creates the owner's own reminder with the interval (or opens the reminder form when a first due date is needed); tapping a suggestion opens the form to edit first. A suggestion is never presented as the manufacturer's data without its source.

| Procedure                   | Failures                                                                       |
| --------------------------- | ------------------------------------------------------------------------------ |
| `passport.listing`          | `NOT_FOUND` (car, or `ai.extras` off), `CONFLICT` (not in the garage), `QUOTA` |
| `vehicleDocument.search`    | `NOT_FOUND`, `TOO_MANY_REQUESTS`                                               |
| `vehicleDocument.translate` | `NOT_FOUND`, `QUOTA`, `INPUT_VALIDATION` (over 400 lines or 12,000 characters) |
| `reminder.manualPlan`       | `NOT_FOUND`, `BAD_REQUEST` (no PDF, or over 20 MB), `QUOTA`                    |

## Dev boards [#dev-boards]

`autofolio://dev/Extra-Listing`, `Extra-Search`, `Extra-Translate` and `Extra-Manual` open on the seeded M3. The seed turns `ai.extras` on and keeps a translation of the M3's purchase invoice, read in German (in Italian on the German board). Writing, searching and reading a manual still need a configured model on the server.

## Tests [#tests]

- [`grounding.test.ts`](https://github.com/CarlosZiegler/autofolio/blob/main/packages/domain/src/grounding.test.ts)
- [`passport.listing.test.ts`](https://github.com/CarlosZiegler/autofolio/blob/main/packages/api/src/features/passport/passport.listing.test.ts), [`vehicle-document.extras.test.ts`](https://github.com/CarlosZiegler/autofolio/blob/main/packages/api/src/features/vehicle-document/vehicle-document.extras.test.ts), [`reminder.manual.test.ts`](https://github.com/CarlosZiegler/autofolio/blob/main/packages/api/src/features/reminder/reminder.manual.test.ts): fake adapters, what left the server, quotas and other households.

