package com.correx.core.kernel.orchestration

import com.correx.core.events.events.RecoveryProposal

/**
 * The recorded facts handed to the one-shot post-failure diagnostic (design task #294). Assembled
 * by the kernel from the event log only — no fresh workspace observation (acceptance #2) — so the
 * diagnostic reasons over the same evidence replay will see.
 */
data class DiagnosisInput(
    val intent: String,
    val gate: String,
    val reason: String,
    val fingerprint: String,
    val retryHistory: List<String>,
    val attemptedActions: List<String>,
    val recoveryAvailable: Boolean,
)

/**
 * Seam for the one-shot post-failure diagnostic (design task #294). When a run is about to become
 * terminal, the kernel consults this once per terminal-failure fingerprint to get an untrusted
 * [RecoveryProposal] for a materially different recovery route. Like the other inference seams
 * ([SalvageJudge], [SemanticReviewer]), the implementation is injected so the deterministic core
 * never runs inference itself; the call is tool-free and must not alter model temperature.
 *
 * The proposal is nondeterministic (LLM-backed), so invariant #9 requires the caller to record it —
 * and the kernel's validation decision — as a
 * [com.correx.core.events.events.PostFailureDiagnosedEvent]; replay reads that back and never
 * re-invokes the diagnoser. When none is wired (`null` in [OrchestratorEngines]), the run fails
 * terminally as before, so the feature degrades safely without inference.
 */
fun interface PostFailureDiagnoser {
    suspend fun diagnose(input: DiagnosisInput): RecoveryProposal?
}
