/**
 * E2 prediction first-class object (v0.31 / docs/plans/2026-05-26-e2-prediction-object.md).
 *
 * Canonical store for ex-ante claims that can be closed against ex-post
 * outcomes. The `predictions` table holds every field (including
 * `claim_text`); a memory row mirrors the claim for recall/inspect surfaces
 * but is NOT the source of truth — ON DELETE SET NULL on memory_id means
 * memory deletion gracefully orphans the prediction without losing data.
 *
 * Tenant scoping: every helper requires tenantId. The schema's BEFORE INSERT
 * + BEFORE UPDATE triggers (`trg_predictions_tenant_match_*`) enforce that
 * `predictions.tenant_id` matches the referenced memory's tenant_id when
 * `memory_id IS NOT NULL`. Cross-tenant references are unrepresentable at
 * the schema level.
 *
 * Dual-write atomicity: `savePrediction` writes the memory + predictions
 * row inside `writeEntry`'s SAVEPOINT 'write_entry' (store.ts:1196). The
 * afterWrite hook (store.ts:1199-1201) runs inside the same SAVEPOINT, so
 * a failure in either step rolls back both. Pattern matches supersede
 * (api.ts:1486) and the Slack/GitHub connectors.
 *
 * J3 (reference-class / planning-fallacy detector) reads from
 * `loadPredictionsByClass` to compute per-class base rates from
 * (estimate_value, actual_value) at query time. J3 is a follow-up episode;
 * this module ships the data layer.
 */
export type ClosureState = 'open' | 'closed' | 'closed-unknown';
export declare const VALID_CLOSURE_STATES: ReadonlySet<ClosureState>;
export interface Prediction {
    id: number;
    /** Nullable: ON DELETE SET NULL allows memory deletion (forget /
     *  consolidate / archive) without breaking the prediction row. */
    memoryId: string | null;
    tenantId: string;
    classTag: string;
    claimText: string;
    estimateValue: number | null;
    estimateUnit: string | null;
    targetDate: string | null;
    actualValue: number | null;
    closureState: ClosureState;
    closedAt: string | null;
    closureNote: string | null;
    createdAt: string;
}
export interface SavePredictionOpts {
    classTag: string;
    claimText: string;
    estimateValue?: number;
    estimateUnit?: string;
    targetDate?: string;
}
export interface ClosePredictionOpts {
    closureState: ClosureState;
    actualValue?: number;
    closureNote?: string;
}
export interface ListPredictionsOpts {
    closureState?: ClosureState;
    limit?: number;
}
/**
 * Create a new prediction. Writes a memory mirror + a predictions table
 * row atomically inside `writeEntry`'s SAVEPOINT 'write_entry'. On any
 * failure (audit write, predictions INSERT, trigger ABORT), the SAVEPOINT
 * rolls back — neither the memory row nor the predictions row lands.
 *
 * The memory is tagged `['prediction', classTag]` with `source='prediction'`
 * and `kind='distilled'`. It surfaces in `hippo recall` so the agent can
 * see open predictions naturally; the predictions table is the canonical
 * structured store used by J3.
 */
export declare function savePrediction(hippoRoot: string, tenantId: string, opts: SavePredictionOpts, actor?: string): Prediction;
/**
 * Close an existing open prediction. Updates the predictions row only;
 * the memory mirror is NOT mutated in v1 (predictions table is canonical).
 * J3 computes accuracy (clean vs regressed) from (estimateValue,
 * actualValue) at query time.
 */
export declare function closePrediction(hippoRoot: string, tenantId: string, id: number, opts: ClosePredictionOpts, actor?: string): Prediction;
export declare function loadPredictionById(hippoRoot: string, tenantId: string, id: number): Prediction | null;
export declare function loadPredictionsByClass(hippoRoot: string, tenantId: string, classTag: string, opts?: ListPredictionsOpts): Prediction[];
export interface PredictionBaserate {
    classTag: string;
    /** Count of closed predictions with a numeric actual_value (excludes
     *  open + closed-unknown). The denominator for MAE. */
    nClosed: number;
    /** Count of closed rows where estimate_value > 0 (i.e. ratio is defined).
     *  Subset of nClosed used for meanRatio + p50Ratio. */
    nRatioEligible: number;
    meanEstimate: number | null;
    meanActual: number | null;
    /** mean(actual / estimate) over the nRatioEligible subset. Null when
     *  nRatioEligible = 0 (e.g. all closed predictions had estimate=0). */
    meanRatio: number | null;
    /** Median ratio over the nRatioEligible subset. */
    p50Ratio: number | null;
    /** Mean absolute error = mean(|actual - estimate|) over the nClosed set. */
    mae: number | null;
    /** Human-readable summary string for direct surface in CLI / MCP / HTTP.
     *  Empty when nClosed = 0. */
    summary: string;
}
/**
 * Compute base-rate stats for closed predictions in a class. Used by J3
 * reference-class / planning-fallacy detector. Direct application of
 * Lovallo-Kahneman (2003) inside-vs-outside view.
 *
 * Filter: closure_state='closed' AND estimate_value IS NOT NULL AND
 * actual_value IS NOT NULL. Excludes closed-unknown (no actual to
 * compare against) and open (not yet resolved).
 *
 * Audit-emit is BUILT IN here (single source of truth, no caller-site
 * drift risk). Plan-eng-critic round 1 HIGH recommendation: emit inside
 * helper, not at 3 call sites.
 */
export declare function computePredictionBaserate(hippoRoot: string, tenantId: string, classTag: string, actor?: string, 
/** v0.32 / J3.2 — when false, skip the predict_baserate audit emit. The
 *  J3.2 orchestrator (computePlanningFallacyHint, below) calls this with
 *  emitAudit=false and emits its own `recall_autodebias_hint` audit row
 *  instead, so the predict_baserate channel stays scoped to deliberate
 *  CLI / HTTP / MCP predict-baserate calls and does NOT pollute on every
 *  recall containing a forward-claim phrase. Default true preserves the
 *  v1.13.0 J3 audit semantics for the 3 direct callers (cmdPredict
 *  baserate, /v1/predictions/stats route, hippo_predict_baserate MCP
 *  handler) — none of them pass this argument. */
emitAudit?: boolean): PredictionBaserate;
export declare function loadOpenPredictions(hippoRoot: string, tenantId: string, opts?: {
    classTag?: string;
    limit?: number;
}): Prediction[];
/**
 * J3.2 surface delivered on `RecallResult.planningFallacyHint` when an
 * agent's recall query carries a forward-prediction phrase AND the closest
 * matching prediction class has closed historical data.
 *
 * The agent sees its track record at the moment of forecasting, anchoring
 * on the outside view (Lovallo-Kahneman 2003) rather than the inside-view
 * inside the planning fallacy.
 *
 * Plan: docs/plans/2026-05-26-j32-auto-injection.md.
 */
export interface PlanningFallacyHint {
    classTag: string;
    /** Verbatim PredictionBaserate.summary, e.g.
     *  "Last 5 estimates in class migration-effort averaged 2.10x actual (MAE 1.40)." */
    baserateSummary: string;
    /** Discriminator vs hypothetical future manual-override hints. */
    source: 'j3.2-auto';
    /** The regex match snippet that triggered detection. Lets the agent
     *  see WHY the hint appeared and self-correct if detection misfires
     *  (e.g. "I wasn't predicting; ignore"). */
    detectedPhrase: string;
    nClosed: number;
    /** Null only when every closed-row had estimate_value=0 (ratio undefined). */
    meanRatio: number | null;
}
/**
 * v1.13.4 / J3.2 follow-up — "watching" variant emitted when the
 * forward-claim regex matched but no PlanningFallacyHint baserate was
 * returned. Dogfood diary (docs/dogfood/2026-05-27-track-j-warnings.md)
 * Trial 2a confirmed the pre-v1.13.4 silent paths were the most common
 * real-world J3.2 failure mode: a natural-language query carries a
 * forward-claim phrase but its non-stopword tokens don't overlap with
 * any prediction class tag, so hippo silently emitted nothing despite
 * the regex match. The watching variant surfaces the detection event
 * + a one-line suggestion so the agent can either re-tag the prediction
 * or pass the suggestion through to the user.
 */
export interface PlanningFallacyWatching {
    /** The forward-claim phrase the detector matched (verbatim regex match snippet). */
    detectedPhrase: string;
    /** Why hippo couldn't produce a baserate hint despite the match.
     *  - 'no_class_match': no class scored >=1 on token overlap.
     *  - 'tiebreak': >=2 classes tied at the same best score (silent on ambiguity). */
    reason: 'no_class_match' | 'tiebreak';
    /** One-line agent-facing suggestion for how the user can give hippo
     *  enough signal to produce a baserate next time. */
    suggestion: string;
}
/**
 * v1.13.4 / J3.2 follow-up — richer return type for
 * `computePlanningFallacyOutput`. Carries EITHER `hint` (baserate
 * available) OR `watching` (regex fired, no baserate), or NEITHER (mode=off,
 * no queryText, no regex match, or nClosed=0 silent path). Never both.
 *
 * Existing `computePlanningFallacyHint` (preserved as a backward-compat
 * wrapper) returns only the hint variant; new code should call
 * `computePlanningFallacyOutput` directly to surface the watching variant.
 */
export interface PlanningFallacyOutput {
    hint?: PlanningFallacyHint;
    watching?: PlanningFallacyWatching;
}
export type AutodebiasMode = 'off' | 'regex';
export interface ComputePlanningFallacyHintOpts {
    /** Override env. When undefined, reads process.env.HIPPO_AUTODEBIAS at
     *  call time (per-call to allow test-time env toggling without module
     *  reload). 'off' short-circuits to null BEFORE the regex gate so the
     *  AUTODEBIAS=off path pays zero work. */
    mode?: AutodebiasMode;
    /** Actor for any audit emissions. Defaults to 'recall' (caller didn't
     *  specify). MUST thread through to the inner computePredictionBaserate
     *  call (passed as its `actor` arg) so MCP/HTTP-originated auto-hints
     *  carry the right attribution instead of the 'cli' default. */
    actor?: string;
}
/**
 * J3.2 orchestrator (v1.13.4: richer return type — see computePlanningFallacyHint
 * below for the backward-compat wrapper that returns only the hint variant).
 *
 * Composes the forward-claim detector + class resolver + baserate compute,
 * with telemetry-grade audit emission at every decision point (success,
 * no-class-match, tiebreak).
 *
 * Returns `{}` (neither hint nor watching) on:
 *   - mode === 'off' (env-disabled; pays only the env read, skips regex)
 *   - empty queryText
 *   - no forward-claim regex match
 *   - resolved class has nClosed=0 (no historical data yet; silent)
 *
 * Returns `{ watching: ... }` on (v1.13.4 NEW — was silent null pre-1.13.4):
 *   - resolver returns no class (no overlap ≥ 1; emits no_class_match audit)
 *   - resolver returns tiebreak (≥2 classes tied at best; emits tiebreak audit)
 *
 * Returns `{ hint: ... }` on success: calls computePredictionBaserate(...,
 * emitAudit=false) so the predict_baserate audit channel stays scoped to
 * deliberate predict-baserate calls (the orchestrator's own recall_autodebias_hint
 * audit carries n_closed + mean_ratio in metadata so no telemetry is lost),
 * then emits recall_autodebias_hint audit + returns the hint.
 *
 * Latency budget (plan §Latency): ~50us regex-only on miss; ~750-850us
 * on full match+resolve+baserate path. Well under 50ms target.
 */
export declare function computePlanningFallacyOutput(hippoRoot: string, tenantId: string, queryText: string, opts?: ComputePlanningFallacyHintOpts): PlanningFallacyOutput;
/**
 * v1.13.4 backward-compat wrapper: thin shim around
 * computePlanningFallacyOutput that returns only the hint variant.
 * Existing callers (api.recall, cmdRecall, MCP handler) that don't yet
 * consume the watching variant continue to work unchanged.
 *
 * New callers that want to surface the silent no-class-match / tiebreak
 * paths to users should call computePlanningFallacyOutput directly.
 */
export declare function computePlanningFallacyHint(hippoRoot: string, tenantId: string, queryText: string, opts?: ComputePlanningFallacyHintOpts): PlanningFallacyHint | null;
//# sourceMappingURL=predictions.d.ts.map