# `SuperPi.Discovery`
[🔗](https://github.com/oleksandr/super-pi-beam/blob/v0.1.0/lib/super_pi/discovery.ex#L1)

Multi-Tier Customization Discovery Engine (`23 - Deprecating AGY and Unifying Workspace Plugins and CLI.md`).

Discovers and resolves **Rules** (`AGENTS.md`, `GEMINI.md`, `.agents/rules/*.md`),
**Skills** (`skills/<name>/SKILL.md`, `skills.json`),
and **Hooks** (`hooks.json`) in strict precedence order:
1. Workspace `.agents/` (or `.agent/`, `_agents/`, `_agent/`) walking up from `cwd` to the `.git` root.
2. Declared workspace JSON manifests (`skills.json`, `plugins.json` with `entries`, `inherits`, `include_only`, `exclude`).
3. Global configuration directory (see "Paths").
4. Built-in application skills (`<app data dir>/builtin/skills/`).
5. Global declared JSON manifests (`skills.json`).

## Paths

No path is hardcoded. Each directory resolves in this order:

| Directory | Option or app env | Environment variable | Default |
|---|---|---|---|
| Global config | `:global_config_dir` | `SUPER_PI_CONFIG_DIR` | `:filename.basedir(:user_config, "super-pi")` |
| App data | `:app_data_dir` | `SUPER_PI_DATA_DIR` | `:filename.basedir(:user_data, "super-pi")` |
| Extra global roots | `:discovery_roots` | `SUPER_PI_DISCOVERY_ROOTS` (path-separated) | none |

The defaults follow each operating system: XDG on Linux, `~/Library/Application Support` on
macOS, and `%APPDATA%` on Windows. Extra roots are scanned like the global config directory,
after it. Use them to read a directory that another tool owns.

# `ancestor_chain`

Walks up from `start_dir` to the repository root (directory containing `.git`).
If no `.git` boundary exists in any parent, returns `[start_dir]`.
Returns all ancestor directories from highest priority (`start_dir`) to lowest (`repo_root`).

# `default_app_data_dir`

Application data directory (transcripts, built-in skills). See the module doc.

# `default_global_config_dir`

Global configuration directory. See the module doc for how it resolves.

# `default_knowledge_paths`

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

Roots of a knowledge base: `config :super_pi, :knowledge_paths`, else `default_workspace_paths/0`.

# `default_workspace_paths`

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

Workspace roots for a conversation that names none: `config :super_pi, :workspace_paths`, else the
current working directory. This is the only place the server reads the working directory for it.

# `discover_hooks_files`

Discovers all `hooks.json` files across workspace `.agents/hooks.json`, active plugins, and `<global config>/hooks.json`.

# `discover_rule_files`

Discovers all active rule files (`GEMINI.md`, `AGENTS.md`, `.agents/rules/*.md`) for `workspace_dirs`,
deduplicating by canonical resolved path (`File.read_link` / `Path.expand`) so a rule file is never
injected more than once.

# `discover_skills`

Discovers all skills across the 5 priority tiers. Higher-priority skills override lower-priority
skills with the same `name`.
Returns `[%{name: String.t(), description: String.t(), path: String.t(), tier: atom()}]`.

# `extra_roots`

Extra global roots that are scanned like the global config directory.

# `parse_skill_md`

Parses YAML frontmatter (`name` and `description`) from a `SKILL.md` file.

# `resolve_json_manifest`

Resolves a `skills.json` or `plugins.json` manifest recursively (`inherits` + `entries`),
applying `include_only` and `exclude` regex/glob filters.

---

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