/**
 * Pure, framework-free view-model derivations for the Predictive Studio dashboard.
 *
 * Everything in this module is a deterministic function over plain data shapes (NOT BaseEntity
 * instances) so it can be unit-tested with zero DB / Angular / metadata-provider setup. The Angular
 * panels (Registry / Experiments / Home / Compare) thread their cached engine rows through narrow
 * row interfaces declared here, keeping the parsing + grouping + leaderboard logic out of the
 * components and under test.
 *
 * Design rules honored throughout:
 * - **100% entity-agnostic.** Nothing references members / renewals / any specific business entity —
 *   model/metric names come straight from the data. The single domain assumption is the ML metric
 *   vocabulary (AUC / F1 / precision / recall …), which is universal to predictive modeling.
 * - **Tolerant of missing/partial/garbage JSON.** Every parser returns `null` / `[]` rather than
 *   throwing, so a half-populated environment renders gracefully instead of erroring.
 * - **Only surface what's present.** Metric maps omit absent keys; the UI shows just the numbers the
 *   model actually recorded, never fabricated zeros.
 */
import { PSFeatureBar, PSIterationCard, PSLeaderboardEntry } from './predictive-studio.types';
/** Minimal model slice consumed by the registry/home/compare derivations. */
export interface PSModelRow {
    ID: string;
    Version: number;
    Status: string;
    AlgorithmID: string | null;
    PipelineID: string | null;
    Metrics: string | null;
    HoldoutMetrics: string | null;
    FeatureImportance: string | null;
    TargetVariable: string | null;
    ProblemType: string | null;
    TrainingDurationSec?: number | null;
}
/** Minimal experiment-session-iteration slice consumed by the experiments/compare derivations. */
export interface PSIterationRow {
    ID: string;
    ExperimentSessionID: string;
    Sequence: number;
    Label: string | null;
    Status: string;
    Score: number | null;
    ComputeCost: number | null;
    TokensUsed: number | null;
    Rationale: string | null;
    AlgorithmName?: string;
}
/** Minimal process-run slice consumed by the home activity/KPI derivations. */
export interface PSProcessRunRow {
    ID: string;
    Status: string;
    StartTime: Date | null;
    CreatedAt: Date | null;
    SuccessCount: number;
    TotalItemCount?: number | null;
    ProcessName: string | null;
    EntityName: string | null;
    DryRun: boolean;
}
/** Canonical metric keys we know how to surface, in display order. */
export declare const PS_KNOWN_METRIC_KEYS: readonly ["AUC", "Accuracy", "Precision", "Recall", "F1", "LogLoss", "Brier", "RMSE", "MAE", "R2"];
export type PSMetricKey = (typeof PS_KNOWN_METRIC_KEYS)[number];
/**
 * A parsed metric map — canonical key → numeric value. Only keys actually present (and numeric) in
 * the source JSON appear; everything else is omitted so the UI shows just real numbers.
 */
export type PSMetricMap = Partial<Record<PSMetricKey, number>>;
/**
 * Parse a metrics JSON string (e.g. `model.Metrics` / `model.HoldoutMetrics`) into a canonical
 * {@link PSMetricMap}. Accepts both canonical (`AUC`) and common alias (`auc`, `f1_score`) keys,
 * keeps only finite numeric values, and never throws — invalid/empty input yields `{}`.
 *
 * @param json The raw JSON string, or null/undefined.
 * @returns A metric map containing only the recognized, numeric metrics present in the source.
 */
export declare function parseMetrics(json: string | null | undefined): PSMetricMap;
/** Resolve a raw metric key to its canonical form (exact match first, then alias), or null. */
export declare function canonicalMetricKey(rawKey: string): PSMetricKey | null;
/** The primary AUC/score of a model: holdout AUC preferred, else training AUC, else null. */
export declare function primaryAuc(model: Pick<PSModelRow, 'Metrics' | 'HoldoutMetrics'>): number | null;
/** A labeled metric ready for display (value formatted to a sensible precision). */
export interface PSMetricDisplay {
    key: PSMetricKey;
    label: string;
    value: string;
}
/**
 * Turn a metric map into an ordered, formatted display list (canonical order, only present keys).
 * AUC is excluded by default since the panels surface it as a hero number separately.
 *
 * @param metrics The parsed metric map.
 * @param options.excludeAuc When true (default), omit AUC from the secondary stat list.
 */
export declare function metricsToDisplay(metrics: PSMetricMap, options?: {
    excludeAuc?: boolean;
}): PSMetricDisplay[];
/** Format a metric value: 3 decimals for ratio metrics, 2 for the rest. */
export declare function formatMetricValue(key: PSMetricKey, value: number): string;
/**
 * The train-vs-holdout overfit gap (train AUC − holdout AUC), or null when either is missing.
 * Positive means the model does better in-sample than out-of-sample (the expected direction).
 */
export declare function overfitGap(model: Pick<PSModelRow, 'Metrics' | 'HoldoutMetrics'>): number | null;
/** The dominance threshold above which a single feature's share triggers the leakage guard. */
export declare const PS_FEATURE_DOMINANCE_THRESHOLD = 0.6;
/**
 * Parse a `FeatureImportance` JSON string (a `Record<string, number>`) into sorted importance bars.
 * Sorts by absolute value (descending), normalizes the bar widths against the largest |value| so the
 * top bar fills the track, flags any bar at/above {@link PS_FEATURE_DOMINANCE_THRESHOLD}, and returns
 * at most `topN`. Never throws — invalid/empty input yields `[]`.
 *
 * Also accepts an array-of-`{ name|feature, importance|value }` shape (some sidecars emit that),
 * making the parser robust to both common serializations.
 *
 * @param json The raw feature-importance JSON, or null/undefined.
 * @param topN Maximum bars to return (default 6).
 */
export declare function parseFeatureImportance(json: string | null | undefined, topN?: number): PSFeatureBar[];
/** The single largest absolute feature importance (the dominance number), or null. */
export declare function maxFeatureImportance(json: string | null | undefined): number | null;
/** Algorithm chip styling (icon + categorical color), keyed by a normalized algorithm name. */
interface AlgoStyle {
    icon: string;
    color: string;
}
/** Resolve an algorithm display name to its icon + categorical color. */
export declare function algoStyle(name: string | null | undefined): AlgoStyle;
/** The three kanban buckets an iteration set is grouped into. */
export interface PSKanbanColumns {
    running: PSIterationCard[];
    completed: PSIterationCard[];
    pruned: PSIterationCard[];
}
/**
 * Group a session's iterations into the Running / Completed / Pruned kanban columns, mapping each to
 * a {@link PSIterationCard}. The single best-scoring Completed iteration is badged `Best`; `Pending`
 * iterations are treated as Running (they're queued/in-flight); `Failed` iterations join Pruned (a
 * terminal non-success outcome). Completed/pruned cards carry the holdout score + Δ-from-best; running
 * cards carry an indeterminate progress hint.
 *
 * @param iterations The session's iterations (any order — sorted by Sequence internally).
 * @returns The three populated kanban columns.
 */
export declare function groupIterationsToKanban(iterations: PSIterationRow[]): PSKanbanColumns;
/** The highest Completed-iteration score in a set (the leaderboard top), or null. */
export declare function bestIterationScore(iterations: PSIterationRow[]): number | null;
/**
 * Derive the leaderboard (rank-ordered pills) from a session's iterations: every iteration with a
 * score, sorted by score descending, ranked 1..N. The top entry is flagged `best`; pruned/failed
 * iterations are flagged `pruned`. Iterations without a score are omitted.
 *
 * @param iterations The session's iterations.
 * @param topN Maximum leaderboard entries (default 6).
 */
export declare function deriveLeaderboard(iterations: PSIterationRow[], topN?: number): PSLeaderboardEntry[];
/** A derived Home KPI strip — all entity-agnostic counts/metrics. */
export interface PSHomeKpis {
    publishedCount: number;
    activeExperiments: number;
    /** Best holdout AUC across published models, formatted, or '—' when none. */
    bestHoldout: string;
    /** Sum of SuccessCount across recent non-dry-run ML scoring runs this week. */
    scoredThisWeek: string;
    /** Total training runs (experiment iterations) recorded. */
    experimentRuns: number;
}
/**
 * Compute the Home KPI strip from the cached engine rows. `bestHoldout` is the max holdout AUC across
 * **published** models (the production-quality number); `scoredThisWeek` sums successful records
 * across the supplied recent scoring runs (already filtered to ML-scoring, non-dry-run, last 7 days
 * by the caller). Everything degrades gracefully to '—' / 0 when data is absent.
 */
export declare function computeHomeKpis(models: PSModelRow[], runningSessionCount: number, recentScoringRuns: PSProcessRunRow[], experimentRunCount: number): PSHomeKpis;
/** A vertical activity-feed item, with the icon/kind chosen by {@link buildActivityFeed}. */
export interface PSActivityFeedItem {
    kind: 'promote' | 'run' | 'warn' | 'archive';
    icon: string;
    title: string;
    detail: string;
    when: string;
    /** Sort key (epoch ms) — most recent first. Not rendered. */
    sortMs: number;
}
/**
 * Build the Home recent-activity feed by merging recent ML scoring runs and recent model promotions
 * into one reverse-chronological list. Scoring runs become `run` (or `warn` when failed) items;
 * published models become `promote` items; archived models become `archive` items. Capped at `limit`.
 *
 * @param scoringRuns Recent ML scoring process runs (any order).
 * @param models All cached models (used to surface recent promotions/archives by UpdatedAt-derived time).
 * @param now Reference time for the relative "when" strings.
 * @param limit Max feed items (default 6).
 */
export declare function buildActivityFeed(scoringRuns: PSProcessRunRow[], modelEvents: PSModelEvent[], now: Date, limit?: number): PSActivityFeedItem[];
/** A model lifecycle event (promotion / archive) feeding the activity timeline. */
export interface PSModelEvent {
    kind: 'promote' | 'archive';
    name: string;
    status: string;
    algorithm: string | null;
    auc: number | null;
    when: Date;
}
/**
 * Project recent non-Draft models into lifecycle activity events (Published → promote, Archived →
 * archive), ordered by `when` (their last-updated time) descending. Validated models are treated as
 * promotions too (a meaningful lifecycle advance).
 *
 * @param models Model rows extended with a display name + last-updated time.
 * @param limit Max events (default 8).
 */
export declare function deriveModelEvents(models: PSModelEventSource[], limit?: number): PSModelEvent[];
/** Source row for {@link deriveModelEvents} — a model plus its resolved display name + timestamp. */
export interface PSModelEventSource extends Pick<PSModelRow, 'Metrics' | 'HoldoutMetrics' | 'Status'> {
    Name: string;
    Algorithm: string | null;
    UpdatedAt: Date;
}
/**
 * A compact relative-time string ("just now", "22 minutes ago", "3 hours ago", "Yesterday",
 * "2 days ago", or a date for older). Deterministic given `now` — testable.
 */
/** Coerce a possibly-null / string / Date value to a valid Date, or `null` when there isn't one. */
export declare function toDate(value: Date | string | null | undefined): Date | null;
export declare function relativeTime(when: Date, now: Date): string;
/** A single run column in the Compare panel, derived from a scored iteration. */
export interface PSCompareColumn {
    key: string;
    label: string;
    algorithm: string;
    descriptor: string;
    color: string;
    holdoutAuc: number | null;
    computeCost: number | null;
    status: string;
    isBest: boolean;
}
/**
 * Derive Compare-panel run columns from a session's iterations: the scored iterations ranked by score
 * descending, capped at `maxRuns`, each carrying its holdout score, compute cost, and algorithm chip.
 * The top scorer is flagged `isBest`. Returns `[]` when nothing scored — the panel shows its prompt
 * state.
 *
 * @param iterations The session's iterations.
 * @param maxRuns Maximum run columns to compare (default 3).
 */
export declare function deriveCompareColumns(iterations: PSIterationRow[], maxRuns?: number): PSCompareColumn[];
/** A compare metric row (label + per-run formatted values + which column is best). */
export interface PSCompareMetricRow {
    label: string;
    qualifier: string;
    values: string[];
    bestIndex: number;
}
/**
 * Build the side-by-side metric rows for a set of compare columns. Currently surfaces Holdout AUC
 * (higher is better) and Compute Cost (lower is better) — the two universally-available iteration
 * metrics — formatting absent values as '—' and marking the best column per row.
 */
export declare function buildCompareMetricRows(columns: PSCompareColumn[]): PSCompareMetricRow[];
/** Coerce an unknown value to a finite number, or null. Accepts numeric strings. */
export declare function coerceFiniteNumber(value: unknown): number | null;
export {};
//# sourceMappingURL=predictive-studio.view-models.d.ts.map