/** * The canonical IR contract for structured content. * * Every source (live agent stream, DB reload, Python-preprocessed results, * notes, any future surface) is normalized into these shapes exactly once. * Anything already carrying this IR passes through downstream layers by * reference — see `core/normalize.ts` for the idempotence law. * * This file is pure types + path helpers. No React, no Redux, no IO. */ /** Path of a value inside a parsed region (object keys + array indices). */ type IrPath = Array; /** * How a node's kind was (or wasn't) established. * * 🚨 `unverified` IS NOT `raw`, AND THE DIFFERENCE IS LOAD-BEARING (Arman's * ruling, 2026-08-29). "We checked it and it is wrong" and "we had nothing to * check it with" are opposite facts about a payload, and collapsing them cost * ~221 live kinds their component overnight: a kind whose schema never loaded * degraded to `raw`, the render route read `raw` as "broken instance", and * perfectly valid payloads were dumped as key/value lists instead of reaching * the component the user built. A consumer that treats `unverified` as a * failure is reintroducing that outage — the data is intact and MAY be * entirely valid; all that is missing is the schema that would prove it. */ type IrKindState = "resolved" | "speculative" | "pending_kind" | "pending_schema" | "unverified" | "raw"; /** * System-level zero-data-loss channel. Unknown keys are NEVER merged into a * node's `value` (they'd be indistinguishable from schema fields); they are * carried here verbatim — Protobuf unknown-fields discipline. Distinct from * any domain-level `additionalDetails` field, which is an ordinary schema * field inside `value`. */ interface IrResidue { /** Keys present in the source object but absent from the kind schema. */ extra: Record | null; /** Optional schema fields the source never provided. */ optionalMissing: string[] | null; /** Structured warnings attached during parsing (speculation backtracks, truncation, …). */ notices: Array<{ code: string; message: string; at?: number; }> | null; } /** Which wire syntax carried the kind discriminator for a node. */ type IrDiscriminator = { format: "json"; key: "__kind"; } | { format: "xml"; tag: string; } | { format: "fence"; language: string; }; /** A schema-shaped structured node. Children live inside `value` (and carry their own metadata via `nodeIndex`). */ interface IrStructuredNode { role: "structured"; /** Canonical kind slug. Empty string while pending. */ kind: string; kindState: IrKindState; discriminator: IrDiscriminator; /** Region-relative path ([] = region root). */ path: IrPath; status: "streaming" | "complete" | "error"; /** Compliant snapshot: schema fields + __kind ONLY. Unknown keys → residue. */ value: Record; residue: IrResidue | null; } /** Envelope version. Bump = migration point for persisted envelopes. */ declare const IR_VERSION: 1; /** Reserved key carrying the envelope inside RenderBlockPayload.data. */ declare const IR_ENVELOPE_KEY: "__ir"; /** * One parsed region's canonical form. Serializable (plain JSON), carried on * render blocks (`data.__ir`), persisted on artifacts and message metadata, * and — with `engine: "py-block-detector"` — accepted pre-built from Python. */ interface CanonicalBlockIR { v: typeof IR_VERSION; /** Provenance: which implementation produced this envelope. */ engine: "fe-kind-parser" | "py-block-detector"; /** Stable hash of the region source text — the idempotence / cache key. */ fingerprint: string; root: IrStructuredNode; /** * pathKey → node metadata for per-path readers (child kinds under root). * Carries each child node's residue — child snapshot values inside * `root.value` hold schema fields only, so WITHOUT this the envelope would * silently drop nested unknown keys (zero-data-loss violation). */ nodeIndex?: Record & { residue?: IrResidue | null; }>; } /** Normalizer output segment: prose stays raw text; structured regions carry IR. */ type CanonicalSegment = { role: "text"; content: string; } | { role: "block"; blockType: string; content: string; ir: CanonicalBlockIR | null; }; interface CanonicalContent { v: typeof IR_VERSION; segments: CanonicalSegment[]; } declare function irPathKey(path: IrPath): string; declare function irPathsEqual(left: IrPath, right: IrPath): boolean; declare function irPathIsUnderOrEqual(path: IrPath, prefix: IrPath): boolean; /** Human label for a path ("root", "cards[2].front"). */ declare function irPathLabel(path: IrPath): string; /** True when every residue channel is empty — normalize to null instead. */ declare function isEmptyResidue(residue: IrResidue): boolean; export { IR_ENVELOPE_KEY as I, IR_VERSION as c, irPathIsUnderOrEqual as i, irPathKey as j, irPathLabel as k, irPathsEqual as l, isEmptyResidue as m }; export type { CanonicalBlockIR as C, CanonicalContent as a, CanonicalSegment as b, IrDiscriminator as d, IrKindState as e, IrPath as f, IrResidue as g, IrStructuredNode as h };