# `Sigra.Install.Report`
[🔗](https://github.com/sztheory/sigra/blob/v1.20.0/lib/sigra/install/report.ex#L1)

Record-as-you-go accumulator for installer decisions, rendered as
a 4-column post-install summary (GEN-05).

The walker threads a `Report` through every `run_feature/3` call
and every file write, injection, and skip flows through one of the
`record_*` functions. At the end of the walk,
`render_summary/1` emits a stable 4-column table.

This replaces the ad-hoc `Mix.shell().info([:yellow, "* skipping ", ...])`
inline prints scattered through `lib/mix/tasks/sigra.install.ex`.

# `skipped_entry`

```elixir
@type skipped_entry() :: %{path: Path.t(), reason: String.t()}
```

# `t`

```elixir
@type t() :: %Sigra.Install.Report{
  generated: [Path.t()],
  manual_actions: [String.t()],
  modified: [Path.t()],
  skipped: [skipped_entry()]
}
```

# `new`

```elixir
@spec new() :: t()
```

# `record_generated`

```elixir
@spec record_generated(t(), Path.t()) :: t()
```

# `record_manual_action`

```elixir
@spec record_manual_action(t(), String.t()) :: t()
```

# `record_modified`

```elixir
@spec record_modified(t(), Path.t()) :: t()
```

# `record_skipped`

```elixir
@spec record_skipped(t(), Path.t(), String.t()) :: t()
```

# `render_summary`

```elixir
@spec render_summary(t()) :: iodata()
```

Renders the 4-column summary table as iodata. Column order is
`Generated | Modified | Skipped | Manual Action`. Entries within a
column are sorted alphabetically so snapshot tests are stable.

Column widths are padded to the maximum of (header width, longest
entry in that column) so long paths don't break alignment. An empty
report still emits a valid header row.

---

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