/**
 * localizeContextBug — the contextual-bug LOCALIZER, "git bisect for
 * context" (RFC-003 Part B, block D8).
 *
 * The five-stage pipeline (each stage is a shipped piece — this file only
 * ASSEMBLES):
 *
 *   1. TRIGGER     — an explicit `atStep`, a custom trigger strategy, or
 *                    the QualityRecorder's lowest-scoring step.
 *   2. SLICE       — footprintjs `causalChain` over the commit log, WITH
 *                    control-dependence edges (D3) and honesty markers
 *                    (A2/A4) when the artifacts carry them.
 *   3. WEIGH       — D7's `llmEdgeWeigher` stamps influence weights on
 *                    every LLM-call parent edge (two-pass: prime, re-slice).
 *   4. RANK        — suspects = slice nodes classified into ablatable
 *                    context sources (tool / injection / memory / arg),
 *                    scored by max-product path weight × per-item semantic
 *                    refinement. CORRELATIONAL tier — and marked so.
 *   5. ABLATE      — optional: the consumer's `AblationRunner` re-runs the
 *                    scenario without each top suspect, N seeded times.
 *                    Verdicts (the ONLY causal claims, §B2) + variance.
 *
 * Without a runner the report stops at stage 4 with
 * `mode: 'correlational'` — explicitly a ranking of proxies, no causal
 * claim anywhere.
 *
 * Every `source` / `step` id in the report is a plain runtimeStageId —
 * drill any of them with the trace-toolpack tools (`trace_node`,
 * `trace_slice`, `get_value`) over the same artifacts bag.
 */
import type { CausalNode, ValueBasis } from 'foottrace';
import { type Embedder, type InfluenceScorer, type InfluenceStrategy } from '../influence-core/index.js';
import type { LoopRecallShortlist } from './loop-recall.js';
import { type ContextUnit } from './missingContext.js';
import { type RestorationRerun } from './restoration.js';
import type { AblationRerun, ContextBugArtifacts, ContextBugReport, Suspect, SuspectDetail, SuspectKind } from './types.js';
/**
 * Extract LLM-call step ids from captured typed events: the
 * `meta.runtimeStageId` of every `agentfootprint.stream.llm_start`
 * envelope, deduplicated in event order. Collect events with
 * `agent.on('*', (e) => events.push(e))`.
 */
export declare function llmCallIdsFromEvents(events: readonly {
    readonly type: string;
    readonly meta: {
        readonly runtimeStageId: string;
    };
}[]): string[];
/** A classified-but-unscored suspect produced by a classifier. */
export interface SuspectSeed {
    readonly kind: SuspectKind;
    readonly detail?: SuspectDetail;
}
/** What a classifier sees for one slice node. */
export interface ClassifyContext {
    readonly node: CausalNode;
    /** Keys this node committed. */
    readonly keysWritten: readonly string[];
    /** Verb-aware value of a key as of this node's last commit. */
    readonly valueOf: (key: string) => unknown;
    /**
     * Why `valueOf(key)` is not exact, when it is not — footprintjs's
     * `commitValueAtWithBasis` codes for the same fold (`HONESTY_CODES` on
     * `foottrace` has each sentence). `[]` = exact. ABSENT = unknown (a hand-built
     * context): no `valueBasis` is attached.
     */
    readonly basisOf?: (key: string) => readonly ValueBasis[];
}
/**
 * Pluggable classifier: map one slice node to its ablatable context
 * sources. Return `undefined` to fall through to the default (which
 * understands the agent chart's committed shapes); return `[]` to
 * suppress the node entirely.
 */
export type SuspectClassifier = (ctx: ClassifyContext) => readonly SuspectSeed[] | undefined;
/**
 * The default classifier — reads the node's COMMITTED values (already
 * redaction-scrubbed) and recognizes the agent chart's shapes:
 *
 * - `systemPromptInjections` / `messagesInjections` / `toolsInjections`
 *   records with an engineered source → one suspect per `Injection.id`
 *   (kind `'memory'` for source `'memory'`, else `'injection'`).
 * - `lastToolResult` → a `'tool'` suspect for the tool that ran.
 * - footprintjs A2 honesty marker `args` → an `'arg'` suspect (the
 *   consumer's runner must override the input — nothing to filter).
 * - anything else → the honest `'stage'` fallback (no ablation spec).
 */
export declare function defaultSuspectClassifier(ctx: ClassifyContext): readonly SuspectSeed[];
export interface LocalizeContextBugOptions {
    readonly artifacts: ContextBugArtifacts;
    /** Injected embedder (D6) — wrap in `embeddingCache(...)`. */
    readonly embedder: Embedder;
    /** Explicit trigger step (runtimeStageId). Wins over everything. */
    readonly atStep?: string;
    /** Custom trigger strategy — consulted when `atStep` is absent. */
    readonly trigger?: (artifacts: ContextBugArtifacts) => string | undefined;
    /**
     * The counterfactual tier: supply a runner (+ the original output) and
     * top suspects get ablation verdicts. Absent → the report stops at the
     * ranking, marked `mode: 'correlational'`.
     */
    readonly rerun?: AblationRerun;
    /**
     * Interface #3 — the MISSING-context tier. Supply what was `available` for
     * the turn and what was `sent` to the model; the report's `dropped` lists the
     * units that never reached the model (`available − sent`). Add a `rerun` and
     * each dropped candidate gets a RESTORATION verdict (the mirror of ablation:
     * restoring it flips the outcome → causal). Absent → no `dropped` section.
     */
    readonly missingContext?: {
        readonly available: readonly ContextUnit[];
        readonly sent: readonly ContextUnit[];
        readonly rerun?: RestorationRerun;
    };
    /** Slice depth budget. Default 12. */
    readonly maxDepth?: number;
    /** Slice node budget. Default 80. */
    readonly maxNodes?: number;
    /** Ranked suspects kept on the report. Default 12. */
    readonly maxSuspects?: number;
    /** Override / extend the suspect classifier. */
    readonly classify?: SuspectClassifier;
    /**
     * The RANK stage's pluggable influence scorer (the suspect-ordering
     * extension point). Default `scoreInfluence` — the FDL four-signal
     * composite. Bring your own `InfluenceScorer` — e.g.
     * `scoreContrastiveInfluence` wrapped with a `referenceText`, or a
     * scorer of your own — to change the ranking ORDER, never causality:
     * a scorer only changes how FAST §B2 ablation confirms a culprit;
     * ablation alone makes the causal claim.
     *
     * Or pass a named `InfluenceStrategy` (`semanticAlignmentStrategy` /
     * `lexicalOverlapStrategy` / your own) — the report's `rankedBy` echoes
     * its name.
     */
    readonly scorer?: InfluenceScorer | InfluenceStrategy;
    /**
     * L3 narrowing (proposal 006): a per-loop recall shortlist from `shortlistEarlyCulprits`.
     * When supplied, suspects are REORDERED (never filtered) so high-recall candidates float to the
     * top and survive the `maxSuspects` slice → ablation targets them first. Joined on the suspect
     * identity (`detail.injectionId`/`detail.toolName`). Default off (back-compat).
     */
    readonly shortlist?: LoopRecallShortlist;
}
/**
 * Localize a contextual bug: trigger → causal slice → influence-weighted
 * ranking → (optional) counterfactual ablation. See module docs for the
 * pipeline and the §B2 claim tiers.
 *
 * @beta Beta feature — the API may change before GA.
 *
 * @throws when no trigger can be resolved (no `atStep`, no custom
 *         strategy hit, no `artifacts.quality`), or when the trigger step
 *         is not in the commit log.
 */
export declare function localizeContextBug(options: LocalizeContextBugOptions): Promise<ContextBugReport>;
export declare function suspectLabel(suspect: Suspect): string;
/**
 * Human-readable report. The claim tiers are spelled out in the output
 * itself (§B2): scores are proxies; verdict lines are the only causal
 * claims; every ⚠ honesty flag prints.
 */
export declare function formatContextBugReport(report: ContextBugReport): string;
