/**
 * Canonical Markdown Renderer Family
 *
 * Deterministic, schema-ordered markdown (and compact text) renderers for the
 * first-class Neotoma data objects: entities, relationships, sources,
 * timeline-day logs, and schemas.
 *
 * Used by:
 *   - The filesystem mirror subsystem (src/services/canonical_mirror.ts)
 *   - MCP `retrieve_entity_snapshot` text output (via buildTextResponse)
 *   - Inspector markdown preview (GET /entities/:id/markdown)
 *   - `neotoma memory-export`
 *
 * Determinism invariants:
 *   - Field ordering: schema field order first, then alphabetically sorted for
 *     unknown/extra keys. Nested object keys are alphabetically sorted in
 *     serialization (via canonicalStringify).
 *   - No Date.now() / Math.random() — all timestamps come from input data.
 *   - Every call with the same input produces byte-identical output.
 *
 * These invariants back the public KV-cache stability claim for Neotoma text
 * output to LLMs.
 */
import { type EntityDisplayInput } from "../shared/entity_display_name.js";
export interface RenderEntityInput {
    entity_id: string;
    entity_type: string;
    schema_version: string;
    snapshot: Record<string, unknown>;
    computed_at?: string | null;
    observation_count?: number | null;
    last_observation_at?: string | null;
    /** Field → observation_id. Only used when opts.includeProvenance is true. */
    provenance?: Record<string, string>;
}
export interface RenderSchemaFieldDef {
    type: "string" | "number" | "date" | "boolean" | "array" | "object";
    required?: boolean;
    description?: string;
}
export interface RenderSchemaInput {
    entity_type: string;
    schema_version: string;
    schema_definition: {
        fields: Record<string, RenderSchemaFieldDef>;
    };
    active?: boolean;
    created_at?: string;
    metadata?: {
        label?: string;
        description?: string;
        category?: string;
    };
}
export interface RenderRelationshipInput {
    relationship_key: string;
    relationship_type: string;
    source_entity_id: string;
    target_entity_id: string;
    schema_version?: string;
    snapshot: Record<string, unknown>;
    computed_at?: string | null;
    observation_count?: number | null;
    last_observation_at?: string | null;
    provenance?: Record<string, string>;
}
export interface RenderSourceInput {
    id: string;
    content_hash: string;
    mime_type: string;
    file_name?: string | null;
    original_filename?: string | null;
    byte_size?: number | null;
    source_type: string;
    source_agent_id?: string | null;
    source_metadata?: Record<string, unknown> | null;
    created_at?: string | null;
    storage_status?: string | null;
}
export interface RenderTimelineEventInput {
    id: string;
    event_type: string;
    event_timestamp: string;
    source_id?: string | null;
    source_field?: string | null;
    entity_ids?: string[] | null;
    metadata?: Record<string, unknown> | null;
}
/**
 * Render options shared across kinds. None trigger nondeterminism.
 */
export interface RenderOpts {
    /** Include the per-field provenance footer (entities and relationships). */
    includeProvenance?: boolean;
    /** Resolve entity ids to display labels when rendering relationships / timeline. */
    resolveEntityDisplay?: (entityId: string) => EntityDisplayInput | null;
    /** Absolute URL base used when rendering "view raw source" links for sources. */
    apiBase?: string;
    /** Include the "do not edit" header notice (default true). */
    includeDoNotEditHeader?: boolean;
    /**
     * Optional hard cap on the character length of a single formatted field
     * value in compact text rendering. When set and a value exceeds the cap,
     * the value is truncated with a deterministic suffix
     * `… (<N> chars truncated)` so downstream diffs and KV prefixes remain
     * stable across reruns. Leave unset for the full-fidelity MCP output; the
     * memory-export flow sets this so long bodies (posts, notes, transcripts)
     * do not blow a MEMORY.md line budget.
     */
    maxFieldChars?: number;
}
/** JSON stringify with alphabetically sorted object keys (deterministic). */
export declare function canonicalStringify(value: unknown, indent?: 0 | 2): string;
/**
 * Order the keys of a snapshot-like record deterministically.
 *
 * Priority:
 *   1. Conceptual first keys (title, name, canonical_name, description, summary)
 *      that actually appear.
 *   2. Schema-declared field order (when schema is provided).
 *   3. Any remaining keys, alphabetically sorted.
 *
 * Keys in EXCLUDED_SNAPSHOT_KEYS are dropped (they live in the header instead).
 * Keys whose value is the `_deleted` sentinel are also dropped.
 */
export declare function orderedSnapshotKeys(snapshot: Record<string, unknown>, schemaFieldOrder?: string[]): string[];
export declare function renderEntityMarkdown(entity: RenderEntityInput, schemaFieldOrder: string[] | undefined, opts?: RenderOpts): string;
/**
 * Compact text variant for MCP `retrieve_entity_snapshot` text output.
 *
 * Dense, single section per field, no markdown code fences for nested values
 * (they are canonical JSON). Deterministic across reruns so LLM KV caches
 * remain stable.
 */
export declare function renderEntityCompactText(entity: RenderEntityInput, schemaFieldOrder: string[] | undefined, opts?: RenderOpts): string;
export declare function renderRelationshipMarkdown(rel: RenderRelationshipInput, opts?: RenderOpts): string;
export declare function renderSourceMarkdown(source: RenderSourceInput, opts?: RenderOpts): string;
export declare function renderTimelineDayMarkdown(date: string, events: RenderTimelineEventInput[], opts?: RenderOpts): string;
export declare function renderSchemaMarkdown(schema: RenderSchemaInput, opts?: RenderOpts): string;
export interface ProfileRenderMeta {
    entity_id: string;
    entity_type: string;
    schema_version: string;
    computed_at: string | null | undefined;
    last_observation_at: string | null | undefined;
    observation_count: number | null | undefined;
}
export interface ProfileRenderOpts {
    render_mode: "frontmatter_content" | "content_only";
    /** Fields to include in YAML frontmatter (frontmatter_content only). Defaults to all non-content fields. */
    frontmatter_fields?: string[];
    /** Snapshot field whose value is used as the markdown body. Defaults to "body". */
    content_field?: string;
}
/**
 * Renders a plan (or other profile entity) with a human-readable document
 * structure instead of the generic "one ## section per field" entity format.
 *
 * render_mode "frontmatter_content":
 *   YAML frontmatter with selected metadata fields, followed by the value of
 *   `content_field` (default "body") as the document body. If no content field
 *   is present, falls back to rendering all remaining fields as ## sections.
 *
 * render_mode "content_only":
 *   Just the content field value, no frontmatter. Falls back to empty string
 *   when the field is absent.
 */
export declare function renderProfileEntity(snapshot: Record<string, unknown>, meta: ProfileRenderMeta, opts: ProfileRenderOpts): string;
export declare function renderIndexMarkdown(title: string, entries: Array<{
    label: string;
    href: string;
    summary?: string;
}>, opts?: RenderOpts): string;
//# sourceMappingURL=canonical_markdown.d.ts.map