# ADR-0011 — Renderer Layer Contract **Status:** Accepted **Date:** 2026-05-13 --- ## Context The architecture pipeline terminates at `generate/stream.py`, which produces a sequence of versor-nearest tokens. Those tokens are internal field entities — they have CGA coordinates, provenance, and algebraic identity. Before reaching any surface (terminal, API response, UI, audio), they must be realized into a modality-specific form. In `core-ai`, this became `core_logos` — a full subsystem with deterministic readback, surface realization, public trace metadata, and its own authority boundary. That was over-engineering: it solved operational concerns (auditability, proof artifacts, API stability) before the underlying generation was correct. In `core`, the renderer is deliberately thin. It is not a subsystem. It is a single contract. --- ## Decision The renderer layer is defined by one interface: ```python class Renderer(Protocol): """Convert a generated token sequence into surface output. Contract: - Input: Iterable[VocabEntry] — the ordered token stream from generate/stream.py - Output: str | bytes — modality-specific surface realization - Stateless: the renderer holds no field state and modifies nothing - Deterministic: identical token sequences produce identical surface output """ def render(self, tokens: Iterable["VocabEntry"]) -> str | bytes: ... ``` The default implementation (`generate/render.py`) is a plain text renderer: tokens → their `.surface` strings joined by the language-appropriate separator. Modality-specific renderers (markdown, Hebrew RTL, Koine Greek polytonic, audio phoneme stream) are implementations of this same protocol, registered externally. The engine never selects a renderer — the caller provides one. --- ## Rationale **Why thin?** The field knows what it means. The renderer only knows how to write it down. These are fundamentally different concerns. Mixing them (as `core_logos` did) creates a subsystem that must understand both the algebra and the output format — a dual responsibility that violates Semantic Rigor. **Why caller-provided?** The engine has no concept of "deployment context." Whether it renders to a terminal, an API, a mobile UI, or an audio stream is not the engine's concern. Injecting a renderer at the call site keeps the engine's contract pure and keeps the engine testable in isolation. **Why stateless?** Propagation-over-mutation. The renderer receives a completed token stream. It does not accumulate, buffer, or modify field state. If continuity across renders is needed, that is a session-level concern, not a renderer concern. **Why deterministic?** Third Door: the renderer is a pure function of the token stream. Non-determinism (formatting decisions, adaptive punctuation, "natural" variation in surface form) is a property of language models that apply stochastic transforms at output time. CORE does not do that. The field determines meaning; the renderer transcribes it exactly. --- ## Hebrew and Koine Greek Rendering These are not localizations — they are depth languages with structurally different rendering requirements: - **Hebrew:** RTL script, prefix/suffix morphology carried as field metadata, nikud (vowel points) rendered only when the VocabEntry carries them explicitly - **Koine Greek:** polytonic diacritics, breathing marks, iota subscript — all carried in the VocabEntry's `.surface` field; the renderer writes them as-is Neither requires a special renderer *subsystem*. Both require only that the VocabEntry's `.surface` field is correctly populated upstream (in `vocab/`), and that the text renderer respects Unicode directionality. That is all. --- ## Consequences - `generate/render.py` is added as the default `TextRenderer` implementation - `generate/stream.py` does not call any renderer — it yields tokens - No `core_logos` equivalent will be introduced - Future modality renderers (audio, structured data) implement `Renderer` and are provided by the caller - The renderer is the last thing that happens before output leaves the system - Nothing after the renderer touches the field