> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fensu.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# fensu map

> Render a deterministic downstream call tree for a function, with clickable locations.

`fensu map` renders a function's call lineage as a deterministic terminal tree. It
is the read-and-explore counterpart to [`fensu check`](/cli/check)'s enforcement:
where `check` imposes the repository's structure, `map` lets you see it. It is
useful for recovering the mental map of a large codebase on demand, without paying
a model to rediscover it each time.

```bash theme={null}
fensu map SYMBOL [--root ROOT ...] [--depth N] [--paths MODE] [--color MODE]
                  [--cache | --no-cache] [--cache-stats]
```

<Note>
  `fensu map` does **not** require Fensu configuration or rule adoption. It
  resolves import roots on its own, so you can run it on any Python repository.
</Note>

## Usage

Point it at a function to get its downstream call tree:

```bash theme={null}
fensu map run_check --root src
```

```text theme={null}
run_check(...)  src/fensu/cli/main/check.py:23
├── _parser(...)  src/fensu/cli/main/check.py:49
├── load_config(...)  src/fensu/config/main/load_config.py:15
│   ├── locate_config(...)  src/fensu/config/_helpers/discovery.py:13  (depth limit)
│   ├── parse_config_source(...)  src/fensu/config/_helpers/parse.py:14  (depth limit)
│   ├── validate_config(...)  src/fensu/config/_helpers/validate.py:19  (depth limit)
│   └── build_config(...)  src/fensu/config/_helpers/defaults.py:20  (depth limit)
├── discover_files(...)  src/fensu/discovery/main/discover_files.py:11
├── build_ruleset(...)  src/fensu/rules/catalog/main/build_ruleset.py:10
├── evaluate(...)  src/fensu/evaluation/main/evaluate.py:16
└── render(...)  src/fensu/reporting/main/render.py:12
```

Each node is one resolved call, shown with its function name and a `path:line`
location. Calls are listed in source order, and locations are repository-relative by
default so editors can make them clickable.

## Selecting a symbol

The symbol argument accepts function and method selectors:

| Form                 | Example                                                     | Use                                  |
| -------------------- | ----------------------------------------------------------- | ------------------------------------ |
| Bare name            | `run_check`                                                 | A uniquely named top-level function. |
| Dotted name          | `config.main.load_config`                                   | A module-qualified function.         |
| `path::function`     | `src/fensu/cli/main/check.py::run_check`                    | An exact file and function.          |
| `Class.method`       | `FunctionDefinition.build_key`                              | A uniquely named class and method.   |
| Full dotted method   | `fensu.mapping.models.FunctionDefinition.build_key`         | An exact module, class, and method.  |
| `path::Class.method` | `src/fensu/mapping/models.py::FunctionDefinition.build_key` | An exact file, class, and method.    |

If a bare name or `Class.method` is ambiguous across the resolved roots, Fensu
lists full dotted keys and asks you to qualify the selector rather than guessing.

## Import roots

`--root` names a Python import root and may be repeated to map across several
independent package trees:

```bash theme={null}
fensu map service.run --root services --root libraries
```

When you do not pass `--root`, `fensu map` uses your configured Fensu roots if a
configuration is present, otherwise it infers `src/`, and otherwise falls back to
the repository root.

## Options

| Option                   | Values                                    | Default      | Purpose                                                  |
| ------------------------ | ----------------------------------------- | ------------ | -------------------------------------------------------- |
| `--root`                 | path (repeatable)                         | inferred     | Python import roots to map.                              |
| `--depth`                | non-negative integer                      | `3`          | Maximum call depth before truncation.                    |
| `--paths`                | `relative`, `absolute`, `compact`, `none` | `relative`   | How locations are displayed.                             |
| `--color`                | `auto`, `always`, `never`                 | `auto`       | ANSI color behavior.                                     |
| `--direction`            | `downstream`                              | `downstream` | Direction of the walk.                                   |
| `--cache` / `--no-cache` | flag                                      | configured   | Enable or disable the persistent map index for this run. |
| `--cache-stats`          | flag                                      | off          | Write map cache operation counts to stderr.              |

Path display modes trade detail for readability. `compact` keeps a leading segment
and the filename, which stays legible in deeply layered repositories:

```bash theme={null}
fensu map run_check --root src --depth 2 --paths compact
```

```text theme={null}
run_check(...)  src/fensu/…/main/check.py:23
├── _parser(...)  src/fensu/…/main/check.py:49
├── load_config(...)  src/fensu/…/main/load_config.py:15
│   ├── locate_config(...)  src/fensu/…/_helpers/discovery.py:13  (depth limit)
│   └── ...
└── render(...)  src/fensu/…/main/render.py:12
```

Color is automatic for terminals, can be forced with `--color`, and respects the
`NO_COLOR` environment variable.

Map index caching follows the configured `[cache].enabled` value when configuration
is available and defaults to enabled otherwise. It shares Fensu's persistent cache
storage but remains separate from cached check results.

## What the walk resolves

The current provider is a conservative pure-Python analysis of project functions
and methods. It resolves:

* same-module calls,
* absolute and relative direct imports,
* module aliases,
* namespace packages,
* calls across multiple import roots,
* concrete method calls through constructors, imports, annotations, and `self` or
  `cls` dispatch.

It does not guess dynamic dispatch. Calls made through a function parameter are
shown as **unresolved seams** rather than invented targets. Protocol and dynamic
method calls remain unresolved rather than guessed. This keeps the map trustworthy:
what it draws, it can stand behind.

## Markers

The tree marks three deterministic conditions so the output is stable and
unambiguous:

* **depth limit**: the branch was truncated at `--depth`.
* **cycle**: a function reachable from itself; only the looping branch stops, and
  siblings continue normally.
* **unresolved**: a dynamic call the provider will not guess.

## Exit codes

| Code | Meaning                                                                      |
| ---- | ---------------------------------------------------------------------------- |
| `0`  | The tree was rendered.                                                       |
| `2`  | The symbol could not be found, was ambiguous, or a file could not be parsed. |

An unknown symbol reports a clear error:

```text theme={null}
Unknown project function: does_not_exist
```

## Not yet available

`fensu map` is deliberately conservative today. The following are planned and not
part of current behavior: upstream (incoming-call) mapping, protocol dispatch
resolution, JSON output, helper collapsing and layered rendering, and docstring
captions. This page documents only what the command does now.
