/**
 * MessagingToneGate — Haiku-powered gate for outbound agent-to-user messages.
 *
 * Catches CLI commands, file paths, config keys, and other technical leakage
 * in messages the agent is about to send to a user. Invoked by the server's
 * messaging routes (/telegram/reply, /slack/reply, /whatsapp/send, etc.).
 *
 * Uses an IntelligenceProvider — works with either:
 *   - Claude CLI subscription (default, zero extra cost)
 *   - Anthropic API key (explicit opt-in)
 *
 * Fail-open on any error (LLM timeout, parse failure, unavailable provider).
 * The goal is high signal, not correctness under adversarial conditions —
 * a legitimate message getting blocked by a parse error is worse than a
 * leaked CLI command slipping through under degraded conditions.
 *
 * The agent's own memory discipline is the first line of defense; this gate
 * is the structural backup that catches lapses.
 */
import type { IntelligenceProvider } from './types.js';
export interface ToneReviewResult {
    pass: boolean;
    /**
     * Rule id applied — must be one of the enumerated B1..B18 ids defined in
     * the prompt when pass=false, or empty string when pass=true. Any other
     * value is treated as a reasoning-discipline violation (the LLM invented
     * a rule not in its ruleset) and fails-open with failedOpen=true.
     */
    rule: string;
    /** Short description of what leaked — empty when pass=true */
    issue: string;
    /** Guidance for revising the message — empty when pass=true */
    suggestion: string;
    /** Milliseconds spent in the review (for observability) */
    latencyMs: number;
    /** True if the LLM call failed and we fail-opened */
    failedOpen?: boolean;
    /** True if the LLM's rule citation was invalid (not in B1..B18) — gate failed open. */
    invalidRule?: boolean;
    /**
     * True if the gate review exceeded the outbound route's hard budget and the
     * route failed it open without waiting for the verdict. Distinguishes a
     * budget-cap fail-open (gate too slow under load) from an error fail-open
     * (`failedOpen`) in the latency/over-block audit. Set by the route seam, not
     * by `review()` itself.
     */
    budgetExceeded?: boolean;
}
export interface ToneReviewContextMessage {
    role: 'user' | 'agent';
    text: string;
}
/**
 * Structured signals from upstream deterministic detectors.
 *
 * These are evidence, not verdicts. The tone gate (this class) is the
 * single authority that combines signals with conversational context to
 * make the block/allow decision. Detectors upstream (junk-payload matcher,
 * outbound dedup gate, etc.) must NOT block on their own — they populate
 * these fields and let the authority decide.
 *
 * See docs/signal-vs-authority.md for the principle.
 */
/**
 * What kind of message is this? Single-sourced union — widened with
 * 'automated' (background-job / scheduled-task sends, stamped structurally
 * by the scheduler env, never declared by the model). Spec:
 * docs/specs/outbound-jargon-filepath-gap.md §2.1.
 */
export type MessageKind = 'reply' | 'health-alert' | 'unknown' | 'automated';
export interface ToneReviewSignals {
    /** Junk-payload detector: does the candidate look like a debug/sanity-check token? */
    junk?: {
        detected: boolean;
        /** Reason text from the detector — e.g., "matches known debug token 'test'". */
        reason?: string;
    };
    /** Outbound-dedup detector: is the candidate near-duplicate of a recent outbound message? */
    duplicate?: {
        detected: boolean;
        /** Jaccard-like similarity score [0, 1] — populated when detected OR when a close-but-below-threshold match was the best prior. */
        similarity?: number;
        /** Short excerpt of the matched prior message for context (truncated to 200 chars). */
        matchedText?: string;
    };
    /**
     * Paraphrase cross-check (Integrated-Being v1).
     *
     * This is SIGNAL ONLY. It fires when an outbound message closely paraphrases
     * an entry in the shared-state ledger whose counterparty differs from the
     * current outbound target. It NEVER blocks on its own — the MessagingToneGate
     * is the single authority for block/allow, and the existing rule-id system
     * (B1-B9) is unchanged. A new rule-id B10_PARAPHRASE_FLAGGED is reserved
     * for observability so the gate may *cite* B10 in reasoning for dashboard
     * telemetry, but the gate's default behavior is to PASS on this signal
     * alone. See docs/signal-vs-authority.md.
     */
    paraphrase?: {
        detected: boolean;
        /** Similarity score (Jaccard / cosine over bag-of-words) [0, 1]. */
        similarityScore?: number;
        /** ID of the matched ledger entry. */
        matchedEntryId?: string;
        /** Counterparty of the matched entry (differs from current outbound). */
        counterparty?: {
            type: string;
            name: string;
        };
    };
    /**
     * Jargon-detector signal (see src/core/JargonDetector.ts).
     *
     * SIGNAL ONLY. The detector produces a list of jargon terms found in the
     * candidate. The authority decides whether the presence of those terms,
     * combined with the messageKind and conversational context, constitutes
     * a block. Pure prose discussion of internals between agent and user is
     * not a block; an outbound health alert that leaks the same terms is.
     */
    jargon?: {
        detected: boolean;
        terms?: string[];
        score?: number;
    };
    /**
     * Topic-Intent ArcCheck verdict (Layer 3 of the Topic Intent Layer).
     *
     * SIGNAL ONLY. ArcCheck classifies the outbound draft against the topic's
     * tracked refs and emits a verdict when the draft contradicts a settled
     * item, drifts from the active task frame, or acts on an unconfirmed
     * tentative item. The classifier itself never blocks — the tone gate
     * consumes the signal and may fold the suggested rewrite hint into its
     * rewrite plan. Spec: docs/specs/topic-intent-arccheck-wiring.md.
     */
    arcCheck?: {
        /** Did ArcCheck identify a draft-vs-tracked-ref engagement worth flagging? */
        fire: boolean;
        /** Verdict kind when fire=true. */
        kind?: 'acting-on-tentative' | 'contradicts-settled' | 'contradicts-frame';
        /** Short excerpt of the tracked-ref text the draft engaged with. */
        refText?: string;
        /** Natural-language rewrite hint the gate may include in its review prompt. */
        suggestedRewriteHint?: string;
    };
    /**
     * Self-heal-first signal (see DegradationReporter).
     *
     * SIGNAL ONLY. Producers of internal-health alerts must attempt at least
     * one self-heal action before escalating to the user. The result of that
     * attempt is reported here. The authority uses this signal to suppress
     * the user message when the heal succeeded (rule B13).
     */
    selfHeal?: {
        /** Was at least one self-heal attempt made? */
        attempted: boolean;
        /** Did the heal verify successful? null if no attempt was made. */
        succeeded: boolean | null;
        /** Number of attempts made (0 if attempted=false). */
        attempts: number;
    };
    /**
     * Raw-file-path detector signal (see src/core/raw-file-path.ts).
     *
     * SIGNAL ONLY. Anchors the existing B2_FILE_PATH judgment with the exact
     * deterministic match — a legitimate "I edited src/foo.ts" stays the
     * authority's call. No new rule, no floor. Spec:
     * docs/specs/outbound-jargon-filepath-gap.md §2.3.
     */
    filePath?: {
        detected: boolean;
        /** First offending path, bounded to 120 chars by the detector. */
        match?: string;
    };
    /**
     * Parked-on-user detector signal (C1+C2 §4.3, B-PARK; src/core/parked-on-user.ts).
     * SIGNAL ONLY — flags outbound text that defers an action onto the user. The
     * authority decides whether the deferral is illegitimate (an action the agent
     * could own → reframe to agent-owned) vs. a genuine value/taste/spend decision
     * that is legitimately the user's (→ pass). Fail toward sending.
     */
    parkedOnUser?: {
        parked: boolean;
        phrase?: string;
    };
    /**
     * Internal-ID leak detector signal (C1+C2 §4.3, B-IDLEAK; src/core/internal-id-leak.ts).
     * SIGNAL ONLY, jargon-class — flags raw internal plumbing tokens (CMT-\d+,
     * dryRun, sentinel/gate names, endpoints) in unsolicited agent-initiated text.
     * Does NOT replace redactSecrets / guardProxyOutput. A direct answer to a user
     * who explicitly asked for an identifier should pass.
     */
    internalIdLeak?: {
        leaked: boolean;
        terms?: string[];
    };
}
export interface ToneReviewContext {
    channel: string;
    /** Recent conversation history for context-aware judgment (last ~6 messages). */
    recentMessages?: ToneReviewContextMessage[];
    /** Structured signals from upstream detectors. See ToneReviewSignals. */
    signals?: ToneReviewSignals;
    /**
     * Free-text description of how outbound messages should be written for this
     * agent's user — e.g. "ELI10, short sentences, plain words". Sourced from
     * `InstarConfig.messagingStyle`. When undefined/empty, the style rule
     * (B11_STYLE_MISMATCH) does not apply. Other agents set a different string
     * to fit their user's preferences without changing any code.
     */
    targetStyle?: string;
    /**
     * What kind of message is this? Health-alert-specific rules (B12, B13, B14)
     * only apply when this is 'health-alert'. Default is 'reply' — the
     * standard agent-to-user reply path. 'automated' marks background-job /
     * scheduled-task sends (stamped by the scheduler env, not the model).
     */
    messageKind?: MessageKind;
}
export declare class MessagingToneGate {
    private provider;
    constructor(provider: IntelligenceProvider);
    review(text: string, context: ToneReviewContext): Promise<ToneReviewResult>;
    private buildPrompt;
    private renderMessageKind;
    private renderSignals;
    private renderTargetStyle;
    private renderRecentMessages;
    private parseResponse;
}
//# sourceMappingURL=MessagingToneGate.d.ts.map