/** * explainRecord — translate an AuditRecord into a human-readable explanation. * * Operator-console and support-tool surfaces render this. Adopters override * templates per-locale or per-Pack; the default English registry ships with * the kernel and covers the core categories (state, auth, taint, ledger, * schema, validation, kill, deadline, confirmation, business). * * Template substitution is intentionally minimal: `{fieldName}` → looked up * in the basis `detail` map. A missing field stays as the literal `{x}` so * misconfigured registries surface visibly in the console rather than * silently swallowing data. * * The registry is data, not code — adopters can ship locales by extending * `templates`. `headlines` is optional; when omitted, a sensible default is * derived from the Decision kind. */ import type { AuditRecord } from "./audit.js"; import type { Decision } from "./decision.js"; export interface DecisionExplanation { readonly intentHash: string; readonly headline: string; readonly bullets: readonly string[]; readonly locale: string; /** * Supersession-chain narration (AuditRecord v3+). Present when the * record carries `supersedes` — describes what this record continues * from in human-readable form ("Continues a prior REQUEST_CONFIRMATION * resolved at 2026-01-15T10:32:08Z"). Operators viewing a single * record can follow the chain back without joining tables. */ readonly supersession?: string; } export interface ExplanationRegistry { readonly locale: string; /** * Map of `"category:code"` → template string. The basis emits these as * `{category, code, detail}`; this template renders them as a bullet. The * `{fieldName}` syntax looks up `detail[fieldName]`. Missing keys remain * as literal `{fieldName}` to surface mis-templated rows during dev. */ readonly templates: Readonly>; /** * Optional decision-kind-specific headline producers. When a kind has no * entry, `defaultHeadline(record)` is used. Producers receive the full * record so they can pull amount/principal/etc. out of the envelope. */ readonly headlines?: Readonly string>>>; } export declare function explainRecord(record: AuditRecord, registry: ExplanationRegistry): DecisionExplanation; /** * Merge multiple `ExplanationRegistry` objects into one. Later registries * override earlier ones at the key level — this is what Pack authors do * when extending the framework's `DEFAULT_EXPLANATION_REGISTRY` with * their domain-specific basis codes. Locale must agree across all * inputs (else the merge throws); pass distinct locales by building * separate merged registries. * * The merge is shallow at the template level and shallow at the * `headlines` map level. Adopters who need deeper composition (e.g., * conditional templates) wrap the merged registry themselves. */ export declare function mergeExplanationRegistries(...registries: ReadonlyArray): ExplanationRegistry; /** * Default English registry. Built from the BASIS_CODES vocabulary; adopters * extend this when they introduce new basis codes via module augmentation. * * The map keys are intentionally `"category:code"` strings (not nested) so * a Pack author copying-and-pasting a registry into a translations file can * see every line on one line of grep output. */ export declare const DEFAULT_EXPLANATION_REGISTRY: ExplanationRegistry; //# sourceMappingURL=explain.d.ts.map