/**
 * llmEdgeWeigher — influence-scored `EdgeWeigher` for LLM-call slice edges
 * (RFC-003 Part B, block D7).
 *
 * The gap this fills: footprintjs's causal slice treats every parent of an
 * LLM call equally — a 12-parent hairball (system prompt, history, tool
 * results, cache markers, counters …) gives a debugger 12 equally-plausible
 * leads. D7 turns the hairball into a RANKED shortlist by weighing each
 * parent edge with influence-core's composite (D6): the parent's WRITTEN
 * content vs the LLM call's OUTPUT.
 *
 * Pattern: two-pass adapter over footprintjs's synchronous `EdgeWeigher`
 *          hook (A3). Embedding is async, the hook is sync — so the handle
 *          PRIMES first (walk an unweighted slice, embed every needed text
 *          in deduplicated batches, memoize composites), and `weigh` then
 *          answers synchronously from the primed map. `localizeContextBug`
 *          drives the two passes; standalone consumers call
 *          `prime(dag)` themselves and re-run `causalChain({ weigh })`.
 * Role:    `src/context-bisect/` leaf. The engine stays zero-dep — the
 *          weigher is consumer-injected exactly as A3 intended.
 *
 * ## Honest claim (§B2)
 *
 * Weights are CORRELATIONAL proxies: deterministic embedding geometry
 * between texts the run already committed — never model internals, never
 * causal attribution (ablation is the causal tier). A weight of 0.93 means
 * "this parent's content is semantically close to what the LLM produced",
 * not "the LLM used it".
 *
 * ## Determinism
 *
 * Same artifacts + same (deterministic) embedder → same weights and same
 * ranking, run after run: texts are built from the commit log in commit
 * order, embedded via influence-core's deduplicated batch, and ties in
 * `rankedParents` keep first-seen (slice BFS) order. Wrap the embedder in
 * `embeddingCache(...)` to also make repeat localizations embed nothing.
 *
 * ## What is weighed
 *
 * DATA edges whose CHILD is an LLM call (`llmCallIds`). Everything else —
 * non-LLM children, control edges (a routing decision's influence is not a
 * semantic-content question) — returns `undefined`, which footprintjs
 * stamps as the default 1.0.
 *
 * ## Redaction posture
 *
 * Texts come exclusively from the COMMIT LOG, which footprintjs scrubs at
 * commit time — a redacted key's committed value IS the placeholder, so
 * the embedder never sees the raw secret.
 */
import type { CausalNode, CommitBundle, EdgeWeigher } from 'foottrace';
import { type Embedder, type InfluenceWeights } from '../influence-core/index.js';
export interface LlmEdgeWeigherOptions {
    /**
     * Injected embedder (D6 contract). Wrap in `embeddingCache(...)` so the
     * weigher, the suspect refinement, and any margin/lint consumer share
     * one embedding spend.
     */
    readonly embedder: Embedder;
    /**
     * runtimeStageIds of LLM-call executions — the children whose parent
     * edges get weighed. Provide explicitly, or extract from captured
     * events with `llmCallIdsFromEvents` (the `stream.llm_start` ids).
     */
    readonly llmCallIds: Iterable<string>;
    /** The run's commit log — where edge texts are read from. */
    readonly commitLog: readonly CommitBundle[];
    /** Char cap per embedded text. Default 2000. */
    readonly maxTextChars?: number;
    /** Composite weights forwarded to influence-core. Default: paper priors. */
    readonly weights?: InfluenceWeights;
    /**
     * Override the CHILD text (the LLM call's output). Default: the values
     * the child committed, serialized `key=value` in trace order, capped.
     */
    readonly childTextOf?: (runtimeStageId: string) => string | undefined;
    /**
     * Override the PARENT text for one edge. Default: the value the parent
     * committed for the edge's key, serialized + capped.
     */
    readonly parentTextOf?: (runtimeStageId: string, key: string) => string | undefined;
}
/** One ranked parent edge of an LLM call (descending weight). */
export interface RankedParentEdge {
    readonly parentId: string;
    readonly stageName: string;
    readonly key: string;
    /** Influence composite clamped to [0, 1] — a correlational proxy (§B2). */
    readonly weight: number;
}
export interface LlmEdgeWeigherHandle {
    /**
     * Pass 1 — walk an (unweighted) causal DAG, embed every LLM-edge text in
     * one deduplicated batch, and memoize composite weights. Idempotent;
     * call again with a different DAG to extend the map.
     */
    prime(root: CausalNode): Promise<void>;
    /**
     * Pass 2 — the synchronous footprintjs `EdgeWeigher`. Returns the primed
     * weight for (LLM child, parent, data key); `undefined` (→ engine
     * default 1.0) for control edges, non-LLM children, and unprimed pairs.
     */
    readonly weigh: EdgeWeigher;
    /**
     * The D7 acceptance view: an LLM call's parents ranked by weight,
     * descending; ties keep first-seen (slice BFS) order. Empty until
     * `prime` ran over a DAG containing the call.
     */
    rankedParents(llmCallId: string): readonly RankedParentEdge[];
    /** Texts the embedder was given — exposed for security audits/tests. */
    embeddedTexts(): readonly string[];
}
/**
 * Default child text: everything the step committed, `key=value` in trace
 * order. For an agent's LLM call this carries the assistant content +
 * tool-call intents — the step's observable OUTPUT.
 *
 * WITH ONE EXCLUSION (9.88.0). The receipt an LLM call commits is a
 * FINGERPRINT of the request, not something the step said: run-salted hex
 * digests, which are by construction semantically empty. Left in, they are
 * hundreds of characters of noise inside a `maxChars` budget that then has
 * less room for the assistant's actual words — measured, that alone reordered
 * the localizer's suspects and demoted a planted fact below a tool. A text
 * corpus scored by an embedder must contain only text somebody wrote.
 */
export declare function stepOutputText(commitLog: readonly CommitBundle[], lastIdxOf: Map<string, number>, runtimeStageId: string, maxChars: number): string | undefined;
/**
 * Build the D7 weigher. See module docs for the two-pass contract, the
 * determinism guarantee, and the §B2 honest claim (weights = proxies).
 */
export declare function llmEdgeWeigher(options: LlmEdgeWeigherOptions): LlmEdgeWeigherHandle;
