Presenter contract — the abstract interface every presenter must satisfy.
Purpose
-------
A *presenter* is everything OC Chat knows about how to render the
chat to a human. The contract is intentionally minimal and procedural
so that:
- :class:`~oc_ui.terminal.presenter.ConsolePresenter` (plain ANSI)
can satisfy it with simple ``print`` calls.
- A future ``RichPresenter`` (Phase 1) can satisfy the same interface
using ``rich.live.Live`` to render token-by-token streaming inside
a borderless region without scrolling history off screen.
- A future ``TextualPresenter`` (Phase 3) can satisfy it via async
widgets.
The single non-trivial method is :meth:`Presenter.turn`: it returns
a context manager wrapping a chat turn so streaming presenters have
an unambiguous place to open and close their live region.
``ConsolePresenter`` implements it as a no-op contextmanager.
See ``oc_chat/docs/Terminal_and_UI_design (Synthesis).md`` for the
full rationale and ``oc_chat/docs/Terminal_and_UI_design
(Implementation Plan).md`` for the multi-phase rollout this contract
enables.
Responsibilities
----------------
- :class:`Presenter` — abstract base with the per-turn lifecycle
hooks (``start_turn`` / ``turn`` contextmanager / ``end_turn``)
and event hooks (``show_reasoning``, ``show_content``,
``show_tool_call``, ``show_tool_result``, ``show_usage``,
``show_turn_summary``, ``show_compressed``, ``show_welcome``,
etc.).
- Document the streaming-event contract so subclasses don't have to
guess about ordering or completion.
Diagnostics
-----------
Domain: OC_UI.TERMINAL
Levels:
L2 — lifecycle events
L3 — semantic details
L4 — deep tracing
Contracts
---------
- All hooks are ``@abstractmethod`` — subclasses must implement them.
- Implementations must be safe to call from a single thread; any
presenter that wants to support background streaming must
serialise internally.
- ``turn()`` always returns a context manager, even if it's a no-op.
- ``show_content`` / ``show_reasoning`` chunks are append-only — the
presenter never sees a "rewind" event.
Dependencies
------------
- oc_diagnostics (structured debug logging via _dbg)
- oc_chat.core.session (lazy; ChatSession, for type checking the show_welcome session argument)
- oc_ui.terminal.statusline (lazy; StatusBarState, for type checking the bind_status provider)
See Also
--------
oc_chat/docs/conventions/CONTRACTS.md §2.3 Presenter — owner of the 19-method
presenter ABC pinned by tests/unit/test_presenter_contract.py.