guides/code-facts.md

# Code Facts

Exograph stores normalized code facts alongside AST fragments. These facts make
common code-intelligence queries fast and composable.

## Stored facts

Exograph extracts and persists:

- source files
- fragments
- comments
- definitions
- references
- graph nodes
- call edges

Facts include package/version/file scope so the same database can hold multiple
projects or package releases.

## Text and code-fact search

Literal source search uses ParadeDB when available, falling back to
Postgres-backed candidate retrieval plus source verification. Regex search is
verified against fragment source.

```elixir
Exograph.search_text(index, "/users/:id")
Exograph.search_text(index, ~r/Repo\.get!\(/)
Exograph.search_comments(index, "streaming chunks")
Exograph.search_definitions(index, "parse_resp")
Exograph.search_references(index, "Repo.transaction")
```

These return typed hit structs:

- `%Exograph.TextHit{}`
- `%Exograph.CommentHit{}`
- `%Exograph.DefinitionHit{}`
- `%Exograph.ReferenceHit{}`
- `%Exograph.CallEdgeHit{}`

## Definitions

Definitions include function/module kind, module/name/arity, qualified name,
source location, and scope IDs.

```elixir
import Exograph.DSL

query =
  from(d in Definition,
    where: d.kind == :defp,
    where: prefix_search(d.name, "parse")
  )

{:ok, definitions} = Exograph.all(index, query)
```

## References

References include local calls, remote calls, aliases, module attributes, and
MFA-style fields when available.

```elixir
from(r in Reference,
  where: r.qualified_name == "Repo.transaction/1"
)
```

## When to use facts vs structural search

Use code facts when you know the symbolic property you want:

- function name prefix
- qualified reference name
- definition kind
- call edge caller/callee

Use structural search when the AST shape matters:

- a function with a specific body pattern
- a pipeline shape
- a `case` or `with` form
- absence/presence of nested expressions

Use the DSL when you need both.