# `Agentic.ModelRouter.Selector`

Scores and ranks catalog models based on an `Analyzer.analysis()` result
and a user `Preference`.

Returns an ordered list of `{model, score}` tuples (lowest score first).
Models with missing required capabilities receive heavy penalties so they
sink to the bottom but remain available as fallbacks.

# `ranked_model`

```elixir
@type ranked_model() :: {Agentic.LLM.Model.t(), float()}
```

# `rank`

```elixir
@spec rank(
  Agentic.ModelRouter.Analyzer.analysis(),
  Agentic.ModelRouter.Preference.preference(),
  keyword()
) :: [ranked_model()]
```

Rank all candidate models for a given analysis and preference.

Returns a list of `{model, score}` tuples sorted by score ascending.

# `select`

```elixir
@spec select(String.t(), Agentic.ModelRouter.Preference.preference(), keyword()) ::
  {:ok, {Agentic.LLM.Model.t(), Agentic.ModelRouter.Analyzer.analysis()}}
  | {:error, term()}
```

Analyze a request and return ranked models for the given preference.

This is the main entry point combining analysis + ranking.
When `llm_chat` is provided, uses LLM-based analysis; otherwise
falls back to heuristic analysis.

# `select_all`

Like `select/3` but returns all ranked models (not just the best),
so the caller can walk the full list on failure.

# `top`

```elixir
@spec top(
  Agentic.ModelRouter.Analyzer.analysis(),
  Agentic.ModelRouter.Preference.preference(),
  pos_integer(),
  keyword()
) :: [ranked_model()]
```

Get the top N ranked models.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
