# `Minga.Project.Detector`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga/project/detector.ex#L1)

Detects the project root by walking up from a file path and looking for
root marker files or directories.

This is the shared detection logic used by both `Minga.Project` (editor-wide
project awareness) and `Minga.LSP.RootDetector` (per-language-server roots).

Pure functions, no process state.

## Detection order

Walks up from the file's parent directory. The first directory containing
any marker wins. Markers are checked in the order given, but since we stop
at the nearest directory, the marker list order only matters when multiple
markers exist in the same directory.

## Default markers

`default_markers/0` returns a broad set covering common project types:
`.git`, `mix.exs`, `Cargo.toml`, `package.json`, `go.mod`, `pyproject.toml`,
`.minga` (sentinel file users can drop into any directory to mark a project root).

# `project_type`

```elixir
@type project_type() :: atom()
```

Project type inferred from the marker that matched.

# `result`

```elixir
@type result() :: {:ok, root :: String.t(), project_type()} | :none
```

Detection result.

# `default_markers`

```elixir
@spec default_markers() :: [{String.t(), project_type()}]
```

Returns the default marker list as `{filename, project_type}` tuples.

Combines sentinel markers (`.git`, `.minga`) with root markers from
all registered languages. Pass a custom list to `detect/2` if you
need different markers.

# `detect`

```elixir
@spec detect(String.t()) :: result()
```

Detects the project root for a file using the default marker list.

Returns `{:ok, root_path, project_type}` or `:none`.

## Examples

    iex> {:ok, root, _type} = Minga.Project.Detector.detect("lib/minga/editor.ex")
    iex> File.exists?(Path.join(root, "mix.exs"))
    true

# `detect`

```elixir
@spec detect(String.t(), [{String.t(), project_type()}]) :: result()
```

Detects the project root for a file using a custom marker list.

Each marker is a `{filename, project_type}` tuple. The walk stops at the
first directory containing any marker file.

Returns `{:ok, root_path, project_type}` or `:none`.

# `find_root`

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

Finds the project root for a file given a flat list of marker filenames.

This is the compatibility API used by `Minga.LSP.RootDetector`. It returns
just the root path (no project type), falling back to `File.cwd!/0` when
no marker is found.

---

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