lean_ctx/core/context_quality/tier.rs
1// SPDX-License-Identifier: Apache-2.0
2//! Evidence tiers: what a quality result is allowed to claim.
3//!
4//! A tier describes *how* evidence was produced, not whether it was positive. The
5//! ordering is by claim strength: a Tier A result shows that the evaluation pipeline
6//! works and must never back a Tier D statement such as "LeanCTX keeps answer quality".
7
8use serde::{Deserialize, Serialize};
9
10/// Kind of evidence behind a quality result, ordered from weakest to strongest claim.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
12#[serde(rename_all = "snake_case")]
13pub enum EvidenceTier {
14 /// Tier A — fixture answers; proves the evaluation pipeline runs end to end.
15 Mechanism,
16 /// Tier B — deterministic invariants (fidelity, retention, recovery, security).
17 DeterministicQuality,
18 /// Tier C — replay of a previously captured real-model run; detects drift
19 /// relative to that run.
20 RecordedRegression,
21 /// Tier D — live baseline/treatment run against a real model. Only a powered
22 /// run of this tier supports an empirical non-inferiority claim.
23 LiveTaskEvaluation,
24 /// Tier E — outcomes observed in a real deployment (holdouts).
25 ProductionOutcome,
26}
27
28impl EvidenceTier {
29 pub fn code(self) -> &'static str {
30 match self {
31 Self::Mechanism => "A",
32 Self::DeterministicQuality => "B",
33 Self::RecordedRegression => "C",
34 Self::LiveTaskEvaluation => "D",
35 Self::ProductionOutcome => "E",
36 }
37 }
38
39 pub fn label(self) -> &'static str {
40 match self {
41 Self::Mechanism => "mechanism",
42 Self::DeterministicQuality => "deterministic quality",
43 Self::RecordedRegression => "recorded regression",
44 Self::LiveTaskEvaluation => "live task evaluation",
45 Self::ProductionOutcome => "production outcome",
46 }
47 }
48
49 /// Whether a non-regressing result of this tier says anything about task
50 /// quality on a real model. Mechanism and deterministic tiers do not.
51 pub fn supports_task_quality_claim(self) -> bool {
52 self >= Self::RecordedRegression
53 }
54}