/** * Prose projection of a plan — the review surface an operator reads at the approval gate, and the * re-consumption surface a model reads for a plan it did not author. * * @module @nhtio/adk/batteries/orchestration/render * * @remarks * There is NO dry run in this design. This prose IS the review surface, and that is what makes the * operator view load-bearing rather than cosmetic: an operator who approves a plan they cannot * fully see is the failure this replaces. So for `audience: 'operator'` with `view: 'as_planned'`, * brevity is NOT a virtue — every side effect with its tool and arguments, every authority claim, * every condition with its exact predicate, in traversal order, with branch structure legible. * * Arguments at approval time are STAGED, NOT RESOLVED, and the renderer says which. A `NodeRef` * resolves from the `OutputTable`, which only exists during a run; approval happens before any run * and there is no dry run to populate it. So a literal argument renders as its value, and a * `NodeRef` renders as its PROVENANCE — never as a fabricated value, never silently as though it * were known. The operator is approving what the plan will do with whatever its sources produce, * and the AUTHORITY CLAIM is the bound on that — which IS fully known at approval time. The * `as_executed` view is where arguments appear resolved, because by then they are. * * The operator view is a SEPARATE DISPLAY PROJECTION, not the execution payload: no model-written * free text rendered as if it were fact, no raw machine identifiers where a human-readable label * exists. The model view (`audience: 'model'`) is the inverse: exact identifiers, the same surface * forms a model would cite back, so a model can re-consume a plan it did not author without a * paraphrase hop. * * Properties: * - **DETERMINISTIC.** Same plan + same options ⇒ byte-identical output. The traversal order is * fixed (entry-first, then graph order, with branch structure rendered by handle), value * formatting is total, and nothing reads a clock, a store, or a global. * - **TOTAL.** Every node kind renders. The node-kind switch is exhaustiveness-checked with * `const exhaustive: never = kind`, so a new node kind cannot silently render as nothing. * * It is NOT reversible — there is no prose parser, and `render(parse(s)) === s` is not promised, * because `parse` does not exist. The renderer is a one-way display projection. */ import type { RawPlanView, RunProjection } from "./types"; /** * The audience a render targets. * - `'operator'` — the approval-gate human: prose, trust framing, side effects legible, a total * authority summary. * - `'model'` — a model re-consuming a plan it did not author: exact identifiers and surface * forms, minimal paraphrase. */ type Audience = 'operator' | 'model'; /** * Options for {@link renderPlan}. * * @remarks * The union encodes the two real read modes: `as_planned` carries no run (it is the approval-gate * view, before any execution), and `as_executed` requires a `RunProjection` so arguments can be * resolved from its `outputs` and node states can be annotated. */ export type RenderPlanOptions = { audience: Audience; view: 'as_planned'; } | { audience: Audience; view: 'as_executed'; run: RunProjection; }; /** * Render a plan as prose — the review surface an operator reads at the approval gate, or the * re-consumption surface a model reads for a plan it did not author. * * @remarks * A PURE function of its arguments — no store access, no I/O, no clock. That is what keeps it * testable and deterministic: the same plan plus the same options yields byte-identical output, * and a snapshot test is a complete regression contract. It reads no `PlanStore`, resolves no * live values, and registers nothing. * * The `as_planned` view renders staged arguments as their provenance (a `NodeRef` names the node * and selection it reads, never a fabricated value); the `as_executed` view resolves them against * `run.outputs`. The operator view renders every side effect with its tool and arguments, every * authority claim, every condition with its exact predicate, and ends with a deduplicated * total-authority summary grouped by capability; the model view renders exact identifiers. * * DETERMINISTIC and TOTAL — see the module doc. Not reversible. * * @param plan - the {@link RawPlanView} to render. * @param options - audience, view, and (for `as_executed`) the {@link RunProjection} to resolve * against. * @returns the prose projection, as a single string. */ export declare function renderPlan(plan: RawPlanView, options: RenderPlanOptions): string; export {};