/**
 * Shared RunViewModel — unified state interpretation for HUD and Parallel UI.
 */
import type { RunCapabilityAssignment, RunState } from "../contracts/orchestration.js";
import type { TelemetryEvent } from "./events-logger.js";
export type RunHealth = "ok" | "warn" | "blocked" | "failed";
export interface RunViewModelWorker {
    id: string;
    label: string;
    state: "idle" | "running" | "done" | "failed" | "blocked" | "skipped";
    liveStatus?: "running-active" | "running-silent" | "waiting-input" | "stalled" | "orphaned" | "done" | "failed" | "blocked" | "skipped" | "idle";
    elapsedMs: number;
    retryCount: number;
    currentNode?: string;
    lastEvidence?: {
        gate: string;
        passed: boolean;
        message?: string;
    };
    /** Latest thinking text from the worker (live activity). */
    thinking?: string;
    /** High-level phase description (e.g. "reading src/foo.ts"). */
    phase?: string;
    /** Milliseconds since last meaningful activity (thinking/node event). */
    lastActivityAgeMs?: number;
    /** Milliseconds since latest heartbeat event/state update. */
    lastHeartbeatAgeMs?: number;
    assignment?: RunCapabilityAssignment;
}
export interface RunViewModelBlocker {
    nodeId: string;
    reason: string;
    nextAction: string;
    evidenceMessage?: string;
    recoverable: boolean;
    retryCount: number;
    maxRetries: number;
    logHint?: string;
}
export interface RunViewModelActiveNode {
    id: string;
    name: string;
    role: string;
    thinking?: string;
}
export interface RunViewModelProgress {
    percent: number;
    done: number;
    total: number;
    running: number;
    failed: number;
    blocked: number;
    skipped: number;
    /** Number of nodes that are terminal (done + skipped + failed + blocked). */
    settled: number;
}
export interface RunViewModelProviderRouting {
    attempts: number;
    fallbackCount: number;
    byProvider: Record<string, number>;
}
export interface RunViewModelBlockerItem {
    nodeId: string;
    reason: string;
    status: "blocked" | "failed" | "skipped";
}
export interface RunViewModel {
    health: RunHealth;
    goalTitle: string | null;
    goalScore: number | null;
    activeNode: RunViewModelActiveNode | null;
    blocker: RunViewModelBlocker | null;
    blockers?: RunViewModelBlockerItem[];
    nextAction: string | null;
    progress: RunViewModelProgress;
    eta: string | null;
    changedFiles: string[];
    stateError: "ok" | "missing" | "invalid" | "corrupt" | "oldSchema";
    runId: string | null;
    workers: RunViewModelWorker[];
    /** Lifecycle nodes (bootstrap, root-coordinator, review-merge) exposed separately from workers. */
    lifecycleNodes?: RunViewModelWorker[];
    /** ISO timestamp when the run started. */
    startedAt?: string;
    /** ISO timestamp of last meaningful activity. */
    lastActivityAt?: string;
    iterationCount?: number;
    maxIterations?: number;
    /** Confidence level of the ETA estimate. */
    etaConfidence?: "low" | "medium" | "high";
    /** Provider route/fallback metrics collected from node attempts. */
    providerRouting: RunViewModelProviderRouting;
    routeDecision?: RunState["routeDecision"];
    /** Team/tmux runtime snapshot when the run was created by `omk team`. */
    teamRuntime?: RunState["teamRuntime"];
}
export interface BuildRunViewModelOptions {
    goalTitle?: string | null;
    changedFiles?: string[];
    workerLabels?: Record<string, string>;
    telemetry?: TelemetryEvent[];
}
export declare function sanitizeForDisplay(text: string): string;
export declare function parseRunStateResult(content: string): {
    state: RunState | null;
    error: RunViewModel["stateError"];
};
export declare function getRunStateRecoveryHint(error: RunViewModel["stateError"], runId?: string): string;
export declare function formatEtaMs(ms: number | undefined): string;
export declare function renderRunSummary(vm: RunViewModel): string;
export declare function buildRunViewModel(state: RunState | null, options?: BuildRunViewModelOptions): RunViewModel;
