import type { CompiledRule, CompilerOutput, NonCompilableReasonCode, RegexValidation } from './compiler-schema.js';
import type { RuleTestResult } from './rule-tester.js';
import type { Stage4VerificationResult } from './stage4-verifier.js';
export interface LessonInput {
    index: number;
    heading: string;
    body: string;
    hash: string;
}
/**
 * Machine-readable skip reasons. Threaded through `CompileLessonResult` so
 * downstream consumers (totem doctor, Layer 4 fallthrough reporting per ADR-088)
 * can distinguish why a lesson produced no rule without string-matching
 * human-readable messages.
 *
 * mmnto-ai/totem#1481 aligned this internal type 1:1 with the persisted
 * `NonCompilableReasonCode` enum so ledger writers can pass the code through
 * without a mapping table. `'non-compilable'` renamed to `'out-of-scope'`,
 * `'security-verify-rejected'` renamed to `'security-rule-rejected'`, and
 * four producer-facing codes joined: `'no-pattern-generated'`,
 * `'pattern-syntax-invalid'`, `'pattern-zero-match'`, `'no-pattern-found'`.
 * Fresh compile runs MUST NOT emit `'legacy-unknown'`; that sentinel exists
 * solely for migrating pre-#1481 2-tuples.
 */
export type CompileLessonReasonCode = Exclude<NonCompilableReasonCode, 'legacy-unknown'>;
/**
 * Single event inside a lesson's compile pipeline. Appended to a per-lesson
 * `trace` array on every pipeline step (generate / verify / retry / result)
 * and surfaced via `CompileLessonResult.trace` for the CLI `--verbose`
 * renderer (mmnto-ai/totem#1482).
 *
 * `layer` numbers align with the ADR-088 staging (1 = manual, 2 = example-
 * based, 3 = Layer 3 LLM with verify-retry). Consumers MUST tolerate unknown
 * layer numbers so a future ADR-088 phase (dedicated Layer 1 / Layer 2
 * telemetry) can emit without breaking the renderer.
 *
 * `patternHash` is a stable 16-character sha256 prefix of the emitted
 * pattern, included only on `generate` events. Callers use it to correlate
 * retries ("this retry produced the same pattern") without forwarding the
 * pattern string itself.
 *
 * `reasonCode` is only set on the terminal `result` event when the lesson
 * skipped. A compiled or failed lesson omits the field.
 */
export interface LayerTraceEvent {
    layer: number;
    action: 'generate' | 'verify' | 'retry' | 'result';
    outcome: string;
    patternHash?: string;
    reasonCode?: Exclude<NonCompilableReasonCode, 'legacy-unknown'>;
}
export type CompileLessonResult = {
    status: 'compiled';
    rule: CompiledRule;
    trace?: LayerTraceEvent[];
} | {
    status: 'skipped';
    hash: string;
    reason?: string;
    reasonCode: CompileLessonReasonCode;
    trace?: LayerTraceEvent[];
} | {
    status: 'failed';
    trace?: LayerTraceEvent[];
} | {
    status: 'noop';
    trace?: LayerTraceEvent[];
};
export interface CompileLessonCallbacks {
    onWarn?: (heading: string, message: string) => void;
    onDim?: (heading: string, message: string) => void;
    /**
     * Fires when the declared-severity override (mmnto-ai/totem#1656) actually
     * changed the emitted severity. CLI callers use this to write telemetry
     * records tagged `type: 'severity-override'` for prompt-tuning feedback —
     * frequent fires mean the prompt directive is drifting. Absent = core runs
     * without telemetry plumbing.
     */
    onSeverityOverride?: (lesson: {
        heading: string;
        hash: string;
    }, event: {
        from: 'error' | 'warning' | undefined;
        to: 'error' | 'warning';
    }) => void;
    /**
     * Fires when the declared-scope override (mmnto-ai/totem#1665) actually
     * changed the emitted `fileGlobs`. CLI callers use this to write telemetry
     * records tagged `type: 'scope-override'` for prompt-tuning feedback —
     * frequent fires mean the LLM is drifting on Scope preservation. Absent =
     * core runs without telemetry plumbing. Mirrors `onSeverityOverride`
     * shape and discipline from #1656.
     */
    onScopeOverride?: (lesson: {
        heading: string;
        hash: string;
    }, event: {
        from: string[] | undefined;
        to: string[];
    }) => void;
    /**
     * Fires after Stage 4 verification returns a result (mmnto-ai/totem#1682).
     * CLI callers use this to write telemetry records tagged
     * `type: 'stage4-verify'` to `.totem/temp/telemetry.jsonl`. Absent = core
     * runs without telemetry plumbing. The result mirrors the discriminated
     * union returned by `verifyAgainstCodebase`; see ADR-091 §"Stage 4" for
     * the four-outcome contract. Telemetry path-redaction (per
     * mmnto-ai/totem#1644 precedent) is the caller's responsibility — the
     * verifier returns repo-relative paths, but the telemetry writer must
     * apply the `<extern:<sha256-12>>` redaction for any path outside the
     * repo root.
     */
    onStage4Outcome?: (lesson: {
        heading: string;
        hash: string;
    }, result: Stage4VerificationResult) => void;
}
export interface CompileLessonDeps {
    parseCompilerResponse: (response: string) => CompilerOutput | null;
    /**
     * Invoke the LLM. The optional second parameter `systemPrompt` carries the
     * persistent compiler template separately from the per-lesson user prompt
     * so the orchestrator can mark it as a cache target (mmnto/totem#1291
     * Phase 3). When the wrapper threads systemPrompt through to a caching-
     * capable provider (Anthropic), repeat calls within the TTL window read
     * from prompt cache instead of paying full input-token cost.
     *
     * Backward compatible: callers that ignore the second parameter and
     * receive a wrapper-prepended single string still work — just without
     * the cache benefit.
     */
    runOrchestrator: (prompt: string, systemPrompt?: string) => Promise<string | undefined>;
    existingByHash: Map<string, CompiledRule>;
    callbacks?: CompileLessonCallbacks;
    /** Optional: specialized system prompt for Pipeline 3 (Bad/Good example-based compilation). */
    pipeline3Prompt?: string;
    /**
     * Optional telemetry-driven directive prepended to the Pipeline 2 USER prompt
     * (not the system prompt). Used by `totem compile --upgrade <hash>`
     * (mmnto/totem#1131) to nudge Sonnet toward an ast-grep structural pattern
     * when the existing rule is firing in non-code contexts. Has no effect on
     * Pipeline 1 (manual) or Pipeline 3 (example-based) compilation.
     *
     * Note: this lives in the user prompt rather than the system prompt because
     * it's per-lesson (specific to one rule's telemetry). Putting it in the
     * system prompt would invalidate the cache on every --upgrade call.
     */
    telemetryPrefix?: string;
    /**
     * Assert that this compile is producing a security rule. Per ADR-088
     * Decision 3 (Layer 3 zero-tolerance), security rules that fail the smoke
     * gate are rejected outright with no retry. Reserved for callers that know
     * the source pack context (e.g., compiling lessons from a pack scoped
     * `@mmnto/pack-agent-security` or any pack whose manifest carries an
     * immutable severity contract). Today's `totem lesson compile` at repo
     * level does not set this; a future pack-build command will. Defaults to
     * false; security zero-tolerance is gated on an affirmative caller assertion.
     */
    securityContext?: boolean;
    /**
     * ADR-091 Stage 4 Verify-Against-Codebase verifier (mmnto-ai/totem#1682).
     * When provided, runs after Layer 3 verify-retry produces a compiled rule
     * (Pipeline 2 / Pipeline 3 only — Pipeline 1 manual rules bypass Stage 4
     * because they are human-authored). The callback returns a discriminated
     * `Stage4VerificationResult` and `compileLesson` mutates the rule in-place
     * per the four-outcome contract:
     *
     *   - `'no-matches'`           → `status: 'untested-against-codebase'`
     *   - `'out-of-scope'`         → `status: 'archived'`, `archivedReason`
     *                                cites the offending paths, archive
     *                                timestamp set
     *   - `'in-scope-bad-example'` → `confidence: 'high'` (status remains
     *                                unset / 'active')
     *   - `'candidate-debt'`       → force `severity: 'warning'`, log the
     *                                candidate-debt sites via `onWarn`
     *
     * Absent (undefined) means Stage 4 does not run. The compiled rule keeps
     * its Layer 3 zero-trust shape (`unverified: true`, status absent =
     * active). Callers that don't have filesystem access (cloud compile
     * worker, packs without consumer codebase) leave this absent; consumer-
     * side `totem lint` runs the verifier later via the
     * `pending-verification` flow shipped in T3 (mmnto-ai/totem#1684).
     */
    verifyStage4?: (rule: CompiledRule) => Promise<Stage4VerificationResult>;
}
/**
 * Compile-time validation for ast-grep patterns (#1062, #1339).
 *
 * Two layers:
 *   1. Heuristic fast-path — reject empty patterns, multi-root string
 *      patterns (statement boundaries outside braces/parens), and
 *      compound object patterns missing the required `rule` key.
 *      Gives fast, human-readable error messages for the common cases.
 *   2. Parser-based check (#1339, #1654) — actually invoke ast-grep's rule
 *      compiler via `parse(lang, '').root().findAll(pattern)` for every
 *      Lang resolved from the rule's `fileGlobs`. The pattern is accepted
 *      if it parses under any of those Langs; rejected with the last
 *      Lang's error message if all of them fail. This catches single-line
 *      patterns that look balanced but fail semantic validation — e.g.
 *      `.option("--no-$FLAG", $$$REST)` (floating member call with no
 *      receiver) or `catch($E) { $$$ }` (bare catch clause that can only
 *      exist inside a try statement) — and equally importantly, surfaces
 *      grammar-mismatch failures when a pattern would parse under TSX
 *      but not under the rule's actual target grammar (e.g. a Rust
 *      `ResMut<TacticalState>` pattern that TSX accepts as a JSX element
 *      but Rust rejects as a malformed type expression).
 *
 * Language choice: when `fileGlobs` resolves to one or more registered
 * languages (e.g., `**\/*.rs` → Rust, `**\/*.ts` → TypeScript), the pattern
 * is validated under every such grammar and accepted if any one accepts
 * it. When `fileGlobs` is absent or no glob carries a registered
 * extension, falls back to `Lang.Tsx` — the most permissive parser
 * available (superset of TypeScript plus JSX) — so unscoped pre-1.16
 * rules retain their legacy validation behavior. Empty source (`''`)
 * keeps the call cheap — ast-grep compiles the pattern into a rule
 * before iterating any AST, so we see the rule-compile error even though
 * there's nothing to match against.
 *
 * Lite-build safety: this function is only called from compile flows
 * (buildCompiledRule / buildManualRule), which require an orchestrator
 * and therefore never run in the Lite binary. The esbuild alias swaps
 * `@ast-grep/napi` for the WASM shim in Lite builds, but since this
 * function is dead code there, the shim's `ensureInit()` requirement
 * is never triggered. The parser call is additionally wrapped in
 * try/catch so any surprise error (uninitialized engine, native-binding
 * failure) degrades conservatively to `valid: false` rather than
 * crashing the compile command.
 */
export declare function validateAstGrepPattern(pattern: string | Record<string, unknown>, fileGlobs?: readonly string[]): RegexValidation;
/**
 * Options controlling how `buildCompiledRule` validates its input before
 * emitting a `CompiledRule`. The smoke gate is opt-in so Pipeline 1 (manual)
 * callers and ad-hoc test callers keep their existing behaviour unchanged;
 * Pipeline 2 (LLM) and Pipeline 3 (example-based) opt in explicitly in the
 * compileLesson flow.
 */
export interface BuildCompiledRuleOptions {
    /**
     * When true, the smoke gate runs after validation and before rule emission.
     * Missing badExample or zero-match badExample both reject the rule with a
     * rejectReason that names the gate. When false (default), the gate is
     * skipped entirely - backward compatible.
     */
    enforceSmokeGate?: boolean;
    /**
     * Optional badExample override. When supplied, takes precedence over
     * `parsed.badExample`. Pipeline 3 uses this to reuse its Bad snippet as the
     * smoke-gate target without relying on the LLM to echo the snippet back in
     * the structured output.
     */
    badExampleOverride?: string;
    /**
     * Optional goodExample override (mmnto-ai/totem#1580). When supplied,
     * takes precedence over `parsed.goodExample`. Pipeline 3 uses this to
     * reuse its Good snippet as the over-matching check target without
     * relying on the LLM to echo the snippet back.
     */
    goodExampleOverride?: string;
    /**
     * Optional declared-severity override (mmnto-ai/totem#1656). When
     * supplied, takes precedence over `parsed.severity` regardless of
     * LLM emission. Sourced from the lesson body's `**Severity:** error`
     * / `Severity: warning` prose convention. `buildCompiledRule`
     * reports the override event in `BuildRuleResult.severityOverride`
     * when the override actually changes the emitted severity, so CLI
     * callers can record telemetry for prompt-tuning feedback.
     */
    declaredSeverityOverride?: 'error' | 'warning';
    /**
     * Optional lesson body for declared-scope override (mmnto-ai/totem#1665).
     * When supplied AND the body declares a `**Scope:**` line, the parsed
     * source-Scope glob list takes precedence over `parsed.fileGlobs`
     * regardless of LLM emission. Author-declared intent always wins; #1626's
     * test-contract auto-include heuristic only applies when source omits Scope.
     * `buildCompiledRule` reports the override event in
     * `BuildRuleResult.scopeOverride` when the override actually changes the
     * emitted globs, so CLI callers can record telemetry for prompt-tuning
     * feedback (mirrors `declaredSeverityOverride` from #1656).
     */
    lessonBody?: string;
}
/**
 * Build a CompiledRule from parsed compiler output.
 * Returns { rule, rejectReason } so callers can report why a rule was rejected.
 */
export declare function buildCompiledRule(parsed: CompilerOutput, lesson: {
    hash: string;
    heading: string;
}, existingByHash: Map<string, CompiledRule>, options?: BuildCompiledRuleOptions): BuildRuleResult;
export interface BuildRuleResult {
    rule: CompiledRule | null;
    rejectReason?: string;
    /**
     * Populated when `declaredSeverityOverride` actually changed the emitted
     * severity (mmnto-ai/totem#1656). Absent when no override was supplied, or
     * when the override matched the LLM's emission. CLI callers use this as a
     * telemetry signal for prompt-tuning feedback — frequent overrides mean
     * the prompt directive is drifting and the LLM needs a stronger signal.
     */
    severityOverride?: {
        from: 'error' | 'warning' | undefined;
        to: 'error' | 'warning';
    };
    /**
     * Populated when source-declared `**Scope:**` actually changed the emitted
     * `fileGlobs` (mmnto-ai/totem#1665). Absent when no `lessonBody` was
     * supplied, when the body declared no Scope, or when the LLM emission
     * already matched the source declaration. CLI callers use this as a
     * telemetry signal for prompt-tuning feedback — frequent overrides mean
     * the LLM is dropping or hallucinating Scope entries.
     */
    scopeOverride?: {
        from: string[] | undefined;
        to: string[];
    };
}
/**
 * Derive a virtual file path that satisfies a rule's fileGlobs.
 * Used to construct test fixtures where glob matching is active.
 */
export declare function deriveVirtualFilePath(rule: CompiledRule): string;
/**
 * Verify a compiled rule against inline Example Hit/Miss lines.
 * Returns null if no examples exist or engine is `'ast'` (Tree-sitter).
 * Tree-sitter rules are skipped because `testRule`'s non-`ast-grep` branch
 * runs the regex pipeline (`applyRulesToAdditions`), which does not handle
 * S-expression queries. Regex and ast-grep rules both flow through to
 * `testRule`. mmnto-ai/totem#1699.
 * Returns RuleTestResult if verification was run.
 */
export declare function verifyRuleExamples(rule: CompiledRule, body: string): RuleTestResult | null;
export declare function formatExampleFailure(result: RuleTestResult): string;
/**
 * Build a CompiledRule from a lesson's manually specified pattern.
 * Returns { rule, rejectReason } so callers can report why a pattern was rejected.
 */
export declare function buildManualRule(lesson: LessonInput, existingByHash: Map<string, CompiledRule>): BuildRuleResult;
/**
 * Security-context signal for the missing-Example-Hit check. Either the
 * compile orchestrator asserts the pack is security-scoped
 * (`deps.securityContext === true`) OR the rule under construction already
 * carries `immutable: true` (set by the pack manifest, ADR-089). Both
 * paths trigger the zero-tolerance reject per ADR-088 Decision 3.
 *
 * The LLM-emitted `CompilerOutput` does not currently carry an `immutable`
 * field (packs set it at pack-merge time), so the second signal only
 * engages on the Pipeline 1 manual-rule path where `buildManualRule`
 * could synthesize an immutable rule directly. A future change that
 * threads `immutable` through `CompilerOutput` can wire Pipeline 2/3
 * into this helper without touching the call sites.
 */
export declare function isSecurityContext(deps: CompileLessonDeps, rule?: {
    immutable?: boolean;
} | null): boolean;
/**
 * Compile a single lesson into a rule.
 * Handles both manual patterns (zero LLM) and LLM-compiled patterns.
 * Pure business logic — no UI, no I/O, no process.exit.
 */
export declare function compileLesson(lesson: LessonInput, compilerPrompt: string, deps: CompileLessonDeps): Promise<CompileLessonResult>;
//# sourceMappingURL=compile-lesson.d.ts.map