# `PtcRunner.TraceLog.MemorySink`
[🔗](https://github.com/andreasronge/ptc_runner/blob/main/lib/ptc_runner/trace_log/memory_sink.ex#L1)

In-memory ring-buffer sink for turn-log events, alongside the JSONL file
sink (`PtcRunner.TraceLog.Collector`).

A `GenServer` holding recent events in memory under a total byte budget. When
appending an event would push the buffer over `:max_bytes`, the oldest events
are evicted until it fits (the newest event is always retained). This makes
"analyze my last session" work with no filesystem setup — `mix ptc.repl`
enables a sink by default, and the same `PtcRunner.TraceLog.Analyzer` queries
read its events.

The byte cost of each event is its JSON-encoded size (the same encoding the
file sink writes), so the budget bounds real serialized retention. Retention
and redaction are host policy (plan D2): the default budget is conservative
but host-configurable via `:max_bytes`.

Records are accepted as already-built event maps (see
`PtcRunner.TraceLog.TurnEvent`). Like the file sink, the in-memory sink
assigns a monotonic `seq` and stamps `timestamp` when absent, so events stay
orderable independent of wall-clock skew.

# `t`

```elixir
@type t() :: %PtcRunner.TraceLog.MemorySink{
  bytes: non_neg_integer(),
  events: [{non_neg_integer(), map()}],
  max_bytes: pos_integer(),
  seq: non_neg_integer()
}
```

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `clear`

```elixir
@spec clear(GenServer.server()) :: :ok
```

Drops all retained events.

# `count`

```elixir
@spec count(GenServer.server()) :: non_neg_integer()
```

Returns the number of retained events.

# `events`

```elixir
@spec events(GenServer.server()) :: [map()]
```

Returns all retained events in chronological (oldest-first) order.

# `query`

```elixir
@spec query(GenServer.server(), ([map()] -&gt; term())) :: term()
```

Runs `fun` over the retained events (chronological order) INSIDE the sink
process and returns its result.

Host-side projection support (P2 of `docs/plans/sandbox-heap-rebaseline.md`):
a caller running under a heap budget — the PTC-Lisp sandbox holding a
`log/` introspection grant — pays only for the projected result crossing
back, never for a copy of the full buffer. `fun` must be host-trusted code;
if it raises, the error is re-raised in the caller and the sink survives.

# `record`

```elixir
@spec record(GenServer.server(), map()) :: :ok
```

Records an event map into the sink (async). Never raises.

# `start_link`

```elixir
@spec start_link(keyword()) :: GenServer.on_start()
```

Starts an in-memory sink.

## Options

  * `:max_bytes` - total JSON-encoded byte budget (default: 8388608)
  * `:name` - optional registered name for the GenServer

---

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