# Search

Four retrieval strategies, fused by rank, with an explanation attached to every hit.

## Four ways of being wrong, combined

| Strategy | Finds |
| --- | --- |
| Lexical | the words that are actually in the document |
| Dense | the meaning, when your words and the note’s words differ |
| Graph | what is attached to what the first two found |
| Recency | the version you were working on this week |

Results are fused by position, not by score. Each strategy returns a number on its own scale, and normalizing three incomparable scales into one is a tuning exercise that has to be redone every time any of them changes; combining ranks is scale-free.

Weights are tuned per kind of query — a quoted phrase leans lexical, a sentence leans dense, a name leans graph — and the classifier is a deterministic rule, never a model. A model on the retrieval path costs a round trip and gets the weighting wrong in a way nobody can reproduce.

## What gets indexed

Notes are indexed in block-aligned chunks: sibling blocks under the same heading, packed to a target size, with one block of overlap so a fact stated across a boundary survives in one piece. A code block or a table row is never split — half a function does not compile and half a row is not a fact, and both would retrieve confidently.

Each chunk is prefixed with where it lives — note title, heading path, type, linked entities, date — before being embedded. A notes app knows that structurally, which is why the prefix costs nothing and is not generated by a model.

Text is searchable the instant it is saved. Semantic search catches up asynchronously; without an embedding provider configured, search runs on the other three strategies rather than returning nothing.

## Why did I get this result?

Every hit carries its own explanation: which strategies contributed, what they scored, which terms matched, the path through the graph that reached it, and any ranking penalty applied.

If a note has been superseded by another, the result says so and names the successor. Agents follow the chain rather than citing the stale note.

## What search will not return

- Archived notes, unless explicitly asked for.
- Notes outside the caller’s resolved scope.
- Content an agent wrote that nobody reviewed — unless the caller lowers the trust floor.
- Anything reached only by an edge an agent asserted and no person confirmed.

That last one is a security rule rather than a quality one. Asserting a link is a cheap write, so if an inferred edge were walkable, an agent could pull arbitrary content into the next agent’s context just by claiming a connection to it.

## Asking a question

`fp ask` and `POST /v1/ask` return a grounded answer with block-level citations. Citations are identifiers drawn from what was actually retrieved — the model chooses which to cite and cannot invent one.

This is the one path that sends note text to a third party. Everything sent is scoped to what you can read, redacted for secrets by deterministic rules, and fenced as data so a note reading “ignore your instructions” is quoted rather than obeyed. A deployment with no model provider configured refuses the route outright rather than pretending.

Each answer is a paid model call, so questions are limited to 20 a minute per person. The allowance is shared across your session and every CLI token you hold, so logging in again does not buy a second one. A token with a spending cap is held to that cap as well.
