/**
 * Readers for a decision model's answer map.
 *
 * Every reader validates at runtime and returns `undefined` for a missing id
 * **or** a type mismatch, so no call site needs a type assertion (CLAUDE.md
 * rule 14) and "no opinion" stays distinguishable from "an opinion of 0".
 *
 * @module utils/decisionAnswers
 */
import type { DecisionAnswerMap, DecisionBooleanGate, DecisionChoiceReading, DecisionQuestion, DecisionResult, DecisionScoreReading, ProviderDescriptor } from "../types/index.js";
/**
 * Read a yes/no answer as a probability.
 *
 * Returns undefined when the id is absent or the answer was a different
 * type — a caller can therefore tell "not answered" from "answered 0".
 */
export declare function readDecisionBoolean(answers: DecisionAnswerMap, id: string): number | undefined;
/**
 * Read a choice answer, including the full ranking.
 *
 * `ranked` is the distribution sorted highest-first. This is what makes one
 * choice question over N options a ranking of all N — the basis for picking
 * from a large catalogue in a single request.
 */
export declare function readDecisionChoice(answers: DecisionAnswerMap, id: string): DecisionChoiceReading | undefined;
export declare function readDecisionScore(answers: DecisionAnswerMap, id: string): DecisionScoreReading | undefined;
/**
 * A yes/no answer carries no confidence of its own, so certainty has to be
 * inferred from how far the probability sits from a coin flip. 0.5 → 0, and
 * 0 or 1 → 1.
 */
export declare function decisionBooleanConfidence(probability: number): number;
/** Whether a descriptor declares support for a given inference type. */
export declare function servesInferenceKind(descriptor: Pick<ProviderDescriptor, "inferenceKinds">, kind: "generate" | "stream" | "decide"): boolean;
/**
 * Read a yes/no answer as an actionable decision, or `undefined` when there
 * is not enough signal to act.
 *
 * Three outcomes, and keeping them distinct is the whole point: `true` (a
 * confident yes), `false` (a confident no), and `undefined` (unanswered, the
 * wrong type, or too close to a coin flip). Every consumer of the `decide`
 * inference type needs exactly this, so the bars live here rather than being
 * re-invented — inconsistently — at each call site.
 */
export declare function gateDecisionBoolean(answers: DecisionAnswerMap, id: string, gate?: DecisionBooleanGate): boolean | undefined;
/**
 * Build a question id that survives a round trip.
 *
 * Question ids are the only thing tying an answer back to what it was asked
 * about, and a batch mixes heterogeneous questions (one per server, one per
 * message, plus gates), so the namespace prefix is what demultiplexes them.
 * The index — not the subject's own name — is the key, because ids from the
 * wild (server ids, model ids, file paths) are not guaranteed to be distinct
 * after any normalisation the wire might apply.
 */
export declare function decisionKey(namespace: string, index: number): string;
/** Namespace for questions a host adds through `decisionHooks.extendQuestions`. */
export declare const HOST_DECISION_NAMESPACE = "host";
/** Whether a wire id is one the funnel gave a host's question (`host__N`). */
export declare function isHostDecisionKey(id: string): boolean;
/**
 * A validated copy of a question a host handed back from `extendQuestions`,
 * or undefined when it is malformed or cannot be copied. The wire carries
 * the copy, never the host's object: a getter, a proxy or a later edit on
 * the host's side can then reach neither the request nor the answers keyed
 * on it. A value `structuredClone` refuses (a proxy, a function-valued
 * field, a throwing getter) is treated as malformed.
 */
export declare function snapshotDecisionQuestion(value: unknown): DecisionQuestion | undefined;
/**
 * `result` without the answers to a host's namespaced questions — what a
 * consumer is handed when the funnel's host-facing steps failed after the
 * wire call had already returned. A null-prototype map, so an own id such
 * as `__proto__` survives the copy.
 */
export declare function stripHostAnswers(result: DecisionResult, hostIdByWireId: ReadonlyMap<string, string>): DecisionResult;
/**
 * Runtime check that a value from outside the type system — a host's
 * `extendQuestions` hook — is a well-formed question, so a malformed one
 * is dropped on its own rather than failing the whole request that
 * NeuroLink's own routing depends on.
 *
 * A `choice` needs at least two options and a `score` at least two levels;
 * fewer carries no information, and the servers refuse it anyway.
 */
export declare function isDecisionQuestion(value: unknown): value is DecisionQuestion;
