# `Raxol.AgentClientProtocol.Session.Emitter.Journal`
[🔗](https://github.com/DROOdotFOO/raxol-agent/blob/raxol_agent_client_protocol-v0.1.0/packages/raxol_agent_client_protocol/lib/raxol/agent_client_protocol/session.ex#L1112)

The durable emitter — reroutes updates and turn boundaries through the
single-publisher Writer (`Ext.Journal.Writer`) so the session's durable,
offset-addressed journal is FILLED by live turns, and every attached
reattacher replays it.

## What lands durably

  * `emit/2` → `Writer.append("session_update", SessionUpdate.to_json(update),
    taint)`. The Writer publishes the stamped record to every subscriber
    (reattachers). Taint is stamped here and NEVER filters delivery.
  * `turn_started/3` → `Writer.append("turn_started", %{turnId, prompt}, "user")`
    — acquires the Writer's cross-connection turn latch.
  * `turn_completed/3` → `Writer.append("turn_completed", payload, "system")`
    — clears the latch atomically. Built from the single render value, so
    a reattacher's `turn_completed` frame equals the live prompt response.

## Delivery and edge cases

  * **Origin delivery is append-then-notify (two call sites).** `emit/2`
    durably appends the update, then delivers it to the origin connection
    with a direct `Connection.notify` (the same FIFO lane as the prompt
    reply). Reattachers on OTHER connections get the identical stamped stream
    via the Writer subscription. Every delivered update is durable and
    reattachers see the same stream; append order is the single-publisher
    Writer's arrival order, so ordering is guaranteed for the Writer's
    sequence, NOT for interleaved live delivery from concurrent turn tasks.
  * **No Writer ⇒ degrade to notify-only.** If the session has no live Writer
    (`Writer.whereis == nil`), `emit/2` still notifies (never crashes a turn);
    the update is simply non-durable. Turn boundaries no-op.
  * **Born-cancelled turns** append neither `turn_started` nor
    `turn_completed`: that path resolves in the Session without reaching the
    emitter.
  * **`prompt` is recorded as `[]`.** `turn_started` records `turnId` (the
    turn-totality key) with an empty prompt-block list.

---

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