/**
 * Inline Source Attribution Protocol (issue #369)
 *
 * Extracted facts carry provenance inline inside the fact body, so the
 * citation survives prompt injection, copy/paste, and LLM quoting. This
 * complements — never replaces — the YAML frontmatter provenance stored on
 * disk.
 *
 * Default format (matches issue #369 proposal):
 *
 *   The foo service uses Redis for rate limiting. [Source: agent=planner, session=abc123, ts=2026-04-10T14:25:07Z]
 *
 * Key properties:
 *   - Inline (part of the body, not metadata).
 *   - Compact (typically <80 chars of overhead per fact).
 *   - Machine-parseable by a single regex.
 *   - Opt-in via `inlineSourceAttributionEnabled` config flag (default off
 *     for backwards compatibility with existing downstream consumers).
 *   - Legacy facts without a citation remain fully readable.
 *
 * The format template is configurable via `inlineSourceAttributionFormat`
 * with supported placeholders:
 *
 *   {agent}     — principal / agent identifier
 *   {session}   — full session key (colon-delimited)
 *   {sessionId} — short stable session id (trailing component)
 *   {ts}        — extraction timestamp (ISO 8601)
 *   {date}      — extraction date (YYYY-MM-DD)
 *
 * Any privacy-sensitive identifiers should be normalized before being passed
 * to `formatCitation` — the helper treats them as opaque strings.
 */
/** Default citation format template (matches issue #369). */
declare const DEFAULT_CITATION_FORMAT = "[Source: agent={agent}, session={sessionId}, ts={ts}]";
/** Sentinel value used when a provenance field is missing. */
declare const CITATION_UNKNOWN = "unknown";
interface CitationContext {
    /** Principal / agent identifier (e.g. resolved via resolvePrincipal). */
    agent?: string;
    /** Full session key (e.g. "agent:planner:main"). */
    session?: string;
    /**
     * Opaque short session id. Derived from the trailing component of the
     * session key when not provided explicitly. Use this for compact formats
     * that do not need the full colon-delimited session key.
     */
    sessionId?: string;
    /** Extraction timestamp as an ISO 8601 string. */
    ts?: string;
}
interface ParsedCitation {
    /** Agent identifier parsed from the citation (never crashes on malformed input). */
    agent?: string;
    /** Session identifier parsed from the citation. */
    session?: string;
    /** Extraction timestamp parsed from the citation. */
    ts?: string;
    /** The full matched citation substring. */
    raw: string;
}
/**
 * Derive a short session id from a full session key.
 * Falls back to the raw session string if no colon is present.
 */
declare function deriveSessionId(session: string | undefined): string | undefined;
/**
 * Format an inline citation tag using the provided template.
 *
 * Missing context fields fall back to {@link CITATION_UNKNOWN} — the caller
 * should always get a non-empty, parseable tag.
 *
 * Uses a single-pass substitution so that values which themselves contain
 * placeholder syntax (e.g. an agent literally named `"{ts}"`) cannot be
 * re-interpreted by subsequent replacement steps. Each placeholder slot
 * receives exactly one lookup and the substituted value is treated as
 * terminal text, not template source.
 */
declare function formatCitation(ctx: CitationContext, template?: string): string;
/**
 * Returns true if the text already carries at least one citation marker.
 * Safe to call on any string — never throws.
 */
declare function hasCitation(text: string): boolean;
/**
 * Returns true if `text` already carries a citation produced by `template`
 * **or** by the default `[Source: ...]` format (for facts that were tagged
 * before a config change).
 *
 * Use this instead of {@link hasCitation} whenever the caller has access to
 * the configured `inlineSourceAttributionFormat`.
 *
 * All-placeholder templates such as `{agent}{sessionId}` have no literal
 * content to anchor on and therefore cannot be reliably detected without
 * dedicated sentinel markers. In that case the function returns `false` —
 * callers that need idempotent dedup for such templates should either adopt
 * a template with literal delimiters (recommended) or rely on the default
 * `[Source: ...]` marker detection which is always available via
 * {@link hasCitation}.
 */
declare function hasCitationForTemplate(text: string, template: string): boolean;
/**
 * Attach an inline citation to fact text.
 *
 * If the text already has a citation — either the default `[Source: ...]`
 * marker or one produced by the configured template — it is returned unchanged.
 * Existing provenance is respected and never overwritten. Otherwise the
 * citation is appended to the trimmed text with a single space separator,
 * which keeps the marker visually adjacent to the fact body.
 */
declare function attachCitation(text: string, ctx: CitationContext, template?: string): string;
/**
 * Parse a single inline citation from a piece of text. Returns the first
 * citation encountered or `null` when none is present. Malformed citations
 * do not throw — fields that cannot be parsed simply remain `undefined`.
 */
declare function parseCitation(text: string): ParsedCitation | null;
/**
 * Parse every citation embedded in the text. Always returns an array; empty
 * when none are present.
 */
declare function parseAllCitations(text: string): ParsedCitation[];
/**
 * Remove all inline citations from a piece of text.
 *
 * Callers that want the raw fact body (for dedup hashing, display, or
 * comparison) should use this helper instead of hand-rolled regexes so the
 * whole codebase agrees on the citation syntax.
 *
 * Finding 2 fix: when the input contains no citation marker, the input is
 * returned byte-for-byte unchanged. When a citation IS removed, whitespace
 * normalization is applied only at each join seam (the single space between
 * the preceding text and where the citation was), rather than across the
 * entire string. This preserves markdown hard-break spacing, aligned text,
 * and code-like snippets in fact bodies that happen to carry a citation.
 *
 * Implementation: each citation match is replaced by its "seam fix" — the
 * content before the match has its trailing whitespace trimmed and then a
 * single space is appended if any text remains, collapsing only the gap
 * left by the removed marker. Whitespace elsewhere in the body is untouched.
 */
declare function stripCitation(text: string): string;
/**
 * Strip an inline citation from text using a specific template regex.
 *
 * This is the template-aware counterpart to {@link stripCitation}. When the
 * caller holds the configured `inlineSourceAttributionFormat`, use this
 * function to strip citations produced by that template — including custom
 * templates that differ from the default `[Source: ...]` pattern.
 *
 * Behaviour:
 *  - If the text has a **default-format** citation, delegates to
 *    {@link stripCitation} (always safe).
 *  - If the text has a **custom-template** citation detected by
 *    `hasCitationForTemplate`, builds the template regex and removes every
 *    occurrence (citations are appended at the end of the fact body by
 *    {@link attachCitation}).
 *  - All-placeholder templates (no literal prefix/suffix/separator) cannot
 *    produce a reliable matcher. `hasCitationForTemplate` already returns
 *    `false` for such templates, so this function never attempts to strip an
 *    undetectable citation. The text is returned unchanged when no citation
 *    is detected.
 *  - If no citation is detected for the given template, returns the text
 *    unchanged.
 *
 * @returns The stripped text (or the original text when no citation is found).
 */
declare function stripCitationForTemplate(text: string, template: string): string;

export { CITATION_UNKNOWN, type CitationContext, DEFAULT_CITATION_FORMAT, type ParsedCitation, attachCitation, deriveSessionId, formatCitation, hasCitation, hasCitationForTemplate, parseAllCitations, parseCitation, stripCitation, stripCitationForTemplate };
