/**
 * # render — the renderer (Renderings of a Frame)
 *
 * Charter: the renderer is a **pure function of the Frame; it invents no value** — it
 * chooses only glyphs, layout, and token spend. A Rendering has two parameters: a
 * **format** (`ascii | unicode | md | json | html`) and the **tokenizer** its token
 * costs are measured under (which glyphs are cheap is an empirical, per-model fact). The
 * agent's token-efficient ASCII screen and the human's HTML chart are two Renderings of
 * one Frame — same numbers, same moment. This is what makes the screen a trainable
 * curriculum and satisfies the perception-parity requirement: the agent sees exactly
 * what the human sees.
 *
 * ## The render tokenizer contract — single source of truth (kestrel-2fab)
 * A Rendering's **tokenizer** is HOW its token cost is measured; the canonical contract lives
 * HERE so the frame renderer ({@link ../frame/render.ts}) and the pane-budget guard
 * ({@link ../frame/pane-catalog.ts}) measure under ONE type that cannot drift. It is the render
 * surface's first concrete export; the full renderer still materializes under `src/frame/render.ts`
 * against this contract (Phase 1: the rest of the surface lands in a later milestone).
 *
 * This is deliberately the LIGHTWEIGHT budget tokenizer (`count(text): number`) — NOT the per-model
 * token-count ORACLE in {@link ./tokens.ts} (`TokenCounter`, which returns a LABELLED `TokenCount`
 * distinguishing precise BPE from a documented estimate). The oracle is a benchmark/efficiency leaf
 * module kept OFF this barrel so the library surface stays dependency-free (js-tiktoken is reached
 * only through a lazy import there); the two are separate contracts on purpose.
 */

/**
 * A Rendering's **tokenizer** (CONTEXT: Rendering) — how a rendered string's token cost is measured
 * (which glyphs are cheap is an empirical, per-model fact). Carries its own `id` so a measurement is
 * HONEST about which tokenizer produced it (never an unlabelled estimate). Pure + deterministic.
 */
export interface Tokenizer {
  readonly id: string;
  count(text: string): number;
}

/** The default tokenizer — a documented chars/4 estimate, LABELLED as an estimate (never claimed to
 * be a real BPE). A caller measuring under a model's own tokenizer supplies one via `RenderOptions`. */
export const DEFAULT_TOKENIZER: Tokenizer = {
  id: "chars/4-estimate",
  count: (text: string): number => Math.ceil(text.length / 4),
};
