Decorator presenter that tees every event to a JSON-lines file.
Purpose
-------
Wraps any concrete :class:`~oc_ui.presenter_base.Presenter` and emits
one JSON object per call to *<path>*. The wrapped presenter still
renders normally — :class:`LoggingPresenter` is a strict pass-through
that just records.
Use cases:
* **Replay** — drive a different presenter through a recorded session
to compare rendering changes without re-running the model.
* **CI diffing** — capture the event stream for ``ConsolePresenter``
and ``RichPresenter`` against the same scripted input and assert
they emit the same logical events.
* **Debugging** — when a user reports a UI glitch, asking them to
re-run with ``--log-events sessions/<name>/events.jsonl`` produces
a reproducible trace.
The format is intentionally minimal — one ``{event, args, ts}``
object per line, using :func:`json.dumps` with ``ensure_ascii=False``.
The file is opened in append mode so multiple turns concatenate into
the same log; ``flush=True`` after each event keeps the log usable
from ``tail -f`` for live monitoring.
Responsibilities
----------------
- :class:`LoggingPresenter` — implement every :class:`Presenter` hook
by writing a JSON line to the configured path *and* delegating to
the wrapped presenter.
- Provide a ``close`` method so callers can flush the log
deterministically at session shutdown.
Diagnostics
-----------
Domain: OC_UI.TERMINAL
Levels:
L2 — lifecycle events
L3 — semantic details
L4 — deep tracing
Contracts
---------
- The decorator is *strict pass-through*: every event reaches the
inner presenter, in order, with unmodified arguments.
- Each line is a complete JSON object terminated by ``\\n``; partial
writes are not permitted.
- The log file is append-mode — never truncated.
- Failures while writing the log are surfaced as exceptions; the
decorator does not silently drop events.
Dependencies
------------
- oc_diagnostics (structured debug logging via _dbg)
- oc_ui.presenter_base (Presenter ABC contract)
- oc_chat.core.iteration_stat (lazy; show_iteration_stat imports its JSON and human-line formatters, currently unused)
- oc_chat.core.session (lazy; ChatSession type hint for show_welcome and bind_session)
- oc_ui.terminal.statusline (lazy; StatusBarState type hint for bind_status)