# `PtcRunner.Lisp.Discovery`
[🔗](https://github.com/andreasronge/ptc_runner/blob/main/lib/ptc_runner/lisp/discovery.ex#L1)

Local REPL-style discovery for executable PTC-Lisp capabilities.

This module is deliberately pure and registry-backed: it exposes only
implemented PTC/Clojure builtins and curated Java interop entries. It does
not reflect over the JVM or discover arbitrary Java members.

# `all_ns`

```elixir
@spec all_ns(PtcRunner.Lisp.Prelude.t() | nil) :: {:ok, [String.t()]}
```

Sorted list of curated Lisp-facing namespace-name strings (plan §8), with the
attached prelude's declared namespaces merged in. Never leaks BEAM internals,
Java classes, or implementation-only namespaces.

# `apropos`

```elixir
@spec apropos(term(), map()) :: {:ok, [String.t()]} | {:programmer_fault, String.t()}
```

Returns rendered local apropos lines.

# `apropos_matches`

```elixir
@spec apropos_matches(String.t(), map()) :: [map()]
```

Returns structured local apropos matches for unified MCP/local ordering.

# `curated_namespaces`

```elixir
@spec curated_namespaces() :: [String.t()]
```

Curated Lisp-facing namespace-name strings exposed by `(all-ns)` without an
attached prelude.

# `dir`

```elixir
@spec dir(term(), map()) ::
  {:ok, [String.t()]} | :unknown | {:programmer_fault, String.t()}
```

Lists members for a known local namespace or curated Java class.

# `doc`

```elixir
@spec doc(term()) :: {:ok, String.t()} | :unknown | {:programmer_fault, String.t()}
```

Returns human-readable docs for a known local function or Java interop ref.

# `local_ref?`

```elixir
@spec local_ref?(term()) :: boolean()
```

# `meta`

```elixir
@spec meta(term()) :: {:ok, map()} | :unknown | {:programmer_fault, String.t()}
```

Returns compact metadata for a known local function or Java interop ref.

# `ns_name`

```elixir
@spec ns_name(PtcRunner.Lisp.Prelude.t() | nil, term()) ::
  {:ok, String.t()} | :unknown | {:programmer_fault, String.t()}
```

Returns the namespace-name string for a known namespace ref (a curated
Lisp-facing namespace or a prelude-declared namespace), or `:unknown`.

# `ns_publics`

```elixir
@spec ns_publics(term()) :: {:ok, map()} | :unknown | {:programmer_fault, String.t()}
```

Returns public vars for local Clojure/PTC namespaces only.

# `parse_apropos_opts`

```elixir
@spec parse_apropos_opts(term()) :: {:ok, map()} | {:programmer_fault, String.t()}
```

# `parse_dir_opts`

```elixir
@spec parse_dir_opts(term()) :: {:ok, map()} | {:programmer_fault, String.t()}
```

# `prelude_apropos_matches`

```elixir
@spec prelude_apropos_matches(PtcRunner.Lisp.Prelude.t() | nil, String.t()) :: [map()]
```

Structured prelude apropos matches (`@prelude_source_rank`) for unified
ordering. Scored over each public export's ref/symbol/doc/namespace.

# `prelude_dir`

```elixir
@spec prelude_dir(PtcRunner.Lisp.Prelude.t() | nil, term(), map()) ::
  {:ok, [String.t()]} | :unknown | {:programmer_fault, String.t()}
```

`dir`-style member lines for a prelude namespace, or `:unknown` when `ref`
is not a declared prelude namespace. Honors the same `:limit`/`:offset`
pagination opts as the local/MCP `dir` paths.

# `prelude_doc`

```elixir
@spec prelude_doc(PtcRunner.Lisp.Prelude.t() | nil, term()) ::
  {:ok, String.t()} | :unknown | {:programmer_fault, String.t()}
```

Human-readable docs for an exact prelude export ref (e.g. `"crm/get-user"`),
or `:unknown` when there is no such public export.

# `prelude_meta`

```elixir
@spec prelude_meta(PtcRunner.Lisp.Prelude.t() | nil, term()) ::
  {:ok, map()} | :unknown | {:programmer_fault, String.t()}
```

Compact metadata map for an exact prelude export ref, or `:unknown`.

# `prelude_ns_publics`

```elixir
@spec prelude_ns_publics(PtcRunner.Lisp.Prelude.t() | nil, term()) ::
  {:ok, map()} | :unknown | {:programmer_fault, String.t()}
```

Public exports of a prelude namespace as a `{symbol-string => meta}` map, or
`:unknown` when `ref` is not a declared prelude namespace.

# `prelude_source`

```elixir
@spec prelude_source(PtcRunner.Lisp.Prelude.t() | nil, term()) ::
  {:ok, String.t()} | :unknown | {:programmer_fault, String.t()}
```

Rendered defining-form source for an exact prelude ref (e.g.
`"crm/get-user"`), or `:unknown` when the ref is not in the prelude's
`source_index`.

Resolves ONLY against the attached prelude — unlike `prelude_doc`/`prelude_meta`
there is no local/MCP fallthrough (plan D2). The index covers public exports
plus the private helpers transitively reachable from a public export, so a
reachable `defn-` helper is `source`-visible even though it has no `%Export{}`
(and so stays invisible to `doc`/`meta`/`ns-publics`/`apropos`).

# `render_matches`

```elixir
@spec render_matches([map()]) :: [String.t()]
```

# `reserved_namespace_names`

```elixir
@spec reserved_namespace_names() :: [String.t()]
```

Namespace-like names reserved by local discovery.

Prelude stores use this to reject candidate ids that would collide with
built-in Clojure/JSON namespaces or curated Java interop aliases, including
names that are intentionally omitted from `(all-ns)`.

# `score_tokens`

```elixir
@spec score_tokens([String.t()], [String.t()], integer()) :: integer()
```

Shared lexical token scoring. Exact matches outrank prefixes; prefixes
outrank substrings. No regex matching is used for search.

# `sort_matches`

```elixir
@spec sort_matches([map()]) :: [map()]
```

Sorts unified discovery matches.

# `tokenize`

```elixir
@spec tokenize(term()) :: [String.t()]
```

---

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