/** * Per-turn RenderContext runtime for the phrase pipeline (ADR-192 §6, W2). * * The Assembler realizes a phrase tree against a `RenderContext`: a read-only * world, the bound params, locale settings, and the declared seams * (`reference` / `textState` / `contribute` + `slotContributions`). This module * supplies the engine's runtime for that contract — a thin adapter over the world * model, the live turn-scoped slot store (ADR-195), and the live persistent * `textState` store (ADR-196). The engine owns this per turn. The ONE sanctioned * mutation is the `textState` capability write (ADR-196 §4 — the declared exception * ADR-192 §7 reserved for deterministic `Choice` variation); entity and spatial * state are never touched here. * * Public interface: `createRenderWorld`, `createRenderContextFactory`, * `WorldTextStateStore`, `WorldModelLike`. The factory binds the per-turn * invariants (world, settings, seams) once and yields a per-message * `RenderContext` by adding that message's params. * * Owner context: `@sharpee/engine` — internal prose pipeline. * * @see ADR-192 §6 (report pipeline / render context) * @see ADR-195 (contribute seam) / ADR-196 (textState seam) / ADR-197 (reference seam) */ import type { EntityId, IEntity } from '@sharpee/core'; import type { LocaleSettings, NarrativeAgreement, RenderContext, RenderWorld, TextStateStore } from '@sharpee/if-domain'; /** * The minimal world surface the render world adapter needs. The engine's * `WorldModel` satisfies this structurally; declaring only the methods the * pipeline reads keeps it honest. The pipeline never mutates entity/spatial * state — the one sanctioned write is the `textState` capability (ADR-196 §4), * exposed through the OPTIONAL capability accessors below. They are optional * (the ADR-195 optional-seam precedent) so test mocks that wire only the read * methods keep compiling; a world without them degrades to an empty text-state * store (no persistence, `Choice` starts at counter 0 — AC-9). */ export interface WorldModelLike { getEntity(id: EntityId): IEntity | undefined; getContents(containerId: EntityId): IEntity[]; getContainingRoom(entityId: EntityId): IEntity | undefined; /** The player entity, for narrative verb-person agreement (ADR-199 §4 B). */ getPlayer(): IEntity | undefined; /** Read a capability's data map (ADR-196 text-state read). */ getCapability?(name: string): Record | undefined; /** Merge into a capability's data map (ADR-196 text-state write — the one sanctioned mutation). */ updateCapability?(name: string, updates: Record): void; /** Whether a capability is registered (guards the defensive self-register). */ hasCapability?(name: string): boolean; /** Register a capability if absent (defensive — the engine normally registers `textState` at setup). */ registerCapability?(name: string, registration?: { initialData?: Record; }): void; } /** * Wrap a world model as the read-only `RenderWorld` the Assembler consumes. * * Supplies the entity→`NounPhrase` bridge (`nounPhraseFor`, ADR-194) by delegating * to stdlib's producer — the engine may depend on stdlib, lang-en-us may not, so the * bridge crosses here rather than in the Assembler. * * @param world the live world model (read-only access only) * @returns a `RenderWorld` delegating to the model's lookup methods */ export declare function createRenderWorld(world: WorldModelLike): RenderWorld; /** * The persistent per-`(entityId, messageKey)` text-state store (ADR-196 §4). * * Backed by the `textState` world capability, which serializes with the world — * so a `Choice`'s cycle index / trigger count / sticky pick survives turns and * save/restore (S13–S14). The engine registers the capability at setup * (`game-engine.ts`); this store also self-registers defensively so it works in * tests and standalone render contexts. * * A world that does not expose the optional capability accessors degrades to the * empty-store behavior (no persistence) — AC-9. */ export declare class WorldTextStateStore implements TextStateStore { private readonly world; constructor(world: WorldModelLike); get(entityId: EntityId, messageKey: string): number | undefined; set(entityId: EntityId, messageKey: string, value: number): void; } /** * A per-message render-context builder bound to a turn's invariants. * * @param params the message's parameter/producer bindings * @returns a `RenderContext` carrying those params plus the bound world, * settings, and per-turn seams */ export type RenderContextFactory = (params: Record) => RenderContext; /** * Build the per-turn render-context factory. * * World, locale settings, and the seams are the turn's invariants and are * captured once; only `params` vary per message, so the returned factory is * called once per rendered message. The `contribute` / `slotContributions` pair * shares one turn-scoped {@link TurnSlotStore} across every message context, so a * slot contribution staged while building one message is visible when another * message's `{slot:key}` realizes (ADR-195 §2). * * @param world the read-only render world (see {@link createRenderWorld}) * @param settings the locale realization settings for this turn * @param narrative the player id + narrative person for verb agreement (ADR-199 §4 B) * @param textState the persistent text-state store backing `Choice` (ADR-196 §4); * defaults to the empty store for world-less / string-path callers * @returns a factory that yields a `RenderContext` for a message's params */ export declare function createRenderContextFactory(world: RenderWorld, settings: LocaleSettings, narrative: NarrativeAgreement, textState?: TextStateStore): RenderContextFactory; //# sourceMappingURL=render-context.d.ts.map