# `Dsxir.Trace`

Process-local trace accumulator for `Dsxir.with_trace/1`.

Owns a single process-dict slot. When the slot is `nil`, `record/1` is a
no-op. Inference paths (no `with_trace`) pay one `Process.get/1` per
`Dsxir.Module.Runtime.call/4` and allocate nothing.

The slot does not cross process boundaries. `Dsxir.Predictor.Parallel`,
`Dsxir.Evaluate`, and any user-spawned task run with their own `nil` slot.
Bootstrap optimization is single-process by design.

Entries are pushed on the head (`[entry | acc]`) and reversed on `stop/1`,
so callers see them in forward order.

# `entry`

```elixir
@type entry() ::
  {atom(), map(), Dsxir.Prediction.t(), [Dsxir.Demo.t() | Dsxir.Example.t()]}
```

# `active?`

```elixir
@spec active?() :: boolean()
```

True iff a `with_trace` block is currently open in this process.

# `record`

```elixir
@spec record(entry()) :: :ok
```

Append an entry. No-op when no `with_trace` is active.

# `start`

```elixir
@spec start() :: nil | [entry()]
```

Open a fresh accumulator. Returns the prior slot value for `stop/1`.

# `stop`

```elixir
@spec stop(nil | [entry()]) :: [entry()]
```

Close the accumulator, restore the prior slot, and return the trace.

---

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