/**
 * Diagnosis runner — engine entry point (D0048).
 *
 * Phase 5 implements the factory body; Phase 1 shipped `diagnosisVersion` only.
 * `GeneratorContext.judgmentAttributions` is sourced once per `.run({...})` via
 * `deps.loadAttributions(runId)` reading Phase 4's
 * `runs/{runId}/attribution/{entryKey}.json` per-entry artifacts (RESEARCH
 * Landmine 11).
 *
 * @see docs/decisions/D0048-engine-homes-for-cli-api-parity.md
 * @see .planning/phases/01-foundation-contracts-cross-cutting-schemas/01-CONTEXT.md (D-02)
 * @see .planning/phases/05-diagnosis-engine-cli-llm-cards/05-RESEARCH.md (Landmine 11)
 * @see .planning/phases/05-diagnosis-engine-cli-llm-cards/05-CONTEXT.md (D-02, D-06, D-10)
 */
import type { LLMClient, ModelId } from "../ports/llm-client.js";
import type { Logger } from "../ports/logger.js";
import type { ProgressReporter } from "../ports/progress-reporter.js";
import type { JudgmentAttribution } from "../types/attribution.js";
import type { CardType, Diagnosis, DiagnosisCard, VersionedInputs } from "../types/diagnosis.js";
import type { Report } from "../types/index.js";
/**
 * Bumped when the runner's selection logic, prompt orchestration, or
 * card-set composition changes in a way that should invalidate cached
 * Diagnoses (VER-01 / D-02). Co-located here so the cache-invalidation
 * contract test reads the canonical value.
 *
 * `export const` (never `export let`) — module-scope mutables leak
 * across vitest workers (cross-cutting hazard #2).
 */
export declare const diagnosisVersion = "0.1.0";
/**
 * Per-invocation context threaded into every card generator.
 *
 * `judgmentAttributions` is the Landmine-11 addition — Phase 4 emits
 * per-judgment attribution as per-entry GCS artifacts at
 * `runs/{runId}/attribution/{entryKey}.json`. The runner loads them once
 * per `.run({...})` via `deps.loadAttributions(runId)` and threads the
 * result here. Cards that need attribution inspect this field and return
 * `status: "missing"` when it is `undefined` or empty.
 */
export interface GeneratorContext {
    readonly llm: LLMClient | undefined;
    readonly model: ModelId;
    readonly logger: Logger;
    readonly progress: ProgressReporter;
    readonly versions: VersionedInputs;
    readonly runId: string;
    readonly reportId: string;
    readonly baseline?: Report;
    /** Phase-4 attribution array, loaded once per run (Landmine 11). */
    readonly judgmentAttributions?: JudgmentAttribution[];
}
/**
 * Per-card generator function. Pure async function; the runner wraps
 * each invocation in try/catch so generators MUST NOT suppress their
 * own errors — throw freely; the runner owns error translation.
 */
export type CardGenerator = (report: Report, ctx: GeneratorContext) => Promise<DiagnosisCard>;
/**
 * Flat registry of all 8 card types → generator functions. Lives here
 * (NOT in `services/diagnosis/registry.ts`) per CONTEXT D-06 — the
 * Phase-1 `cardRegistry` placeholder stays empty to keep the contract
 * test green; the composition root builds a `CardRegistry` literal and
 * passes it into `createDiagnosisRunner(deps)`.
 *
 * `Readonly<Record<CardType, CardGenerator>>` — TypeScript exhaustiveness
 * ensures all 8 literal `CardType` strings appear in any registry literal
 * (no rogue keys, no silently missing keys).
 */
export type CardRegistry = Readonly<Record<CardType, CardGenerator>>;
/**
 * Dependencies for the diagnosis runner factory.
 *
 * D-02 delta vs. AI-SPEC §3: `cache: CacheStore` is replaced by two
 * narrow callback deps so the engine uses the artifact store directly
 * without needing a `CacheStore.get/set` API that doesn't exist.
 *
 * Landmine-11 addition: `loadAttributions` lets the composition root bind
 * a reader over `ARTIFACT_REGISTRY.perEntryAttribution` without widening
 * the `CacheStore` port.
 */
export interface DiagnosisRunnerDeps {
    /**
     * Cache-lookup hook. Receives the artifact path built from the
     * 4-version + model cache key. Plan 06's composition root supplies a
     * reader that parses cached bytes through the Diagnosis Zod schema
     * (T-05-04-01 mitigation). Tests supply a simple fake.
     *
     * Returns `null` on miss; returns the cached `Diagnosis` on hit.
     */
    readonly diagnosisReader: (path: string) => Promise<Diagnosis | null>;
    /**
     * Cache-write hook. Receives the same path as `diagnosisReader` plus
     * the freshly-built `Diagnosis`. Called unconditionally after every
     * successful run (including `refresh: true` — a refreshed call
     * replaces the cached Diagnosis per AI-SPEC §3).
     */
    readonly diagnosisWriter: (path: string, diagnosis: Diagnosis) => Promise<void>;
    /**
     * Attribution loader — invoked once per `.run({...})` with
     * `report.provenance.runId`. Rejection is caught by the runner; the
     * resolved value (including `[]`) is threaded into every
     * `GeneratorContext.judgmentAttributions` (Landmine 11).
     */
    readonly loadAttributions: (runId: string) => Promise<JudgmentAttribution[]>;
    readonly llm: LLMClient | undefined;
    readonly model: ModelId;
    readonly logger: Logger;
    readonly progress: ProgressReporter;
    readonly registry: CardRegistry;
}
/**
 * Arguments for a single diagnosis run.
 */
export interface DiagnosisRunnerRunArgs {
    readonly report: Report;
    readonly versions: VersionedInputs;
    readonly baseline?: Report;
    /** When `true`, bypasses the cache lookup (but still writes on completion). */
    readonly refresh?: boolean;
}
/**
 * The diagnosis runner interface. A single `.run()` method returns a
 * fully-assembled `Diagnosis` (or a partial one if some cards degraded).
 */
export interface DiagnosisRunner {
    run(args: DiagnosisRunnerRunArgs): Promise<Diagnosis>;
}
/**
 * Build a `DiagnosisRunner` whose `.run({report, versions, baseline?, refresh?})`
 * produces a `Diagnosis` with cards in registry-order.
 *
 * No module-scope `let` — all state lives in the `deps` closure and per-run
 * local variables (AI-SPEC §3 Pitfall 1).
 */
export declare function createDiagnosisRunner(deps: DiagnosisRunnerDeps): DiagnosisRunner;
