cortexkit_usage_steps/open_set.rs
1//! String value sets that a newer provider may extend.
2//!
3//! Each set decodes a value it does not know as `Other`, keeping the exact
4//! string, so an older reader never fails on a newer provider's value and
5//! re-encodes it unchanged.
6
7use serde::{Deserialize, Deserializer, Serialize, Serializer};
8
9macro_rules! open_set {
10 (
11 $(#[$meta:meta])*
12 pub enum $name:ident {
13 $( $(#[$vmeta:meta])* $variant:ident => $wire:literal, )+
14 }
15 ) => {
16 $(#[$meta])*
17 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
18 #[non_exhaustive]
19 pub enum $name {
20 $( $(#[$vmeta])* $variant, )+
21 /// A value this version of the contract does not know, kept
22 /// exactly as received. Build values from strings with
23 /// `from_wire`, so a known string never lands here.
24 Other(String),
25 }
26
27 impl $name {
28 /// Every value this version knows, as sent on the wire.
29 pub const KNOWN: &'static [&'static str] = &[$($wire),+];
30
31 /// Decodes a wire string; an unknown string becomes `Other`.
32 pub fn from_wire(value: &str) -> Self {
33 match value {
34 $( $wire => Self::$variant, )+
35 other => Self::Other(other.to_owned()),
36 }
37 }
38
39 /// The wire string.
40 pub fn as_str(&self) -> &str {
41 match self {
42 $( Self::$variant => $wire, )+
43 Self::Other(other) => other,
44 }
45 }
46
47 /// Whether this version of the contract knows the value.
48 pub fn is_known(&self) -> bool {
49 !matches!(self, Self::Other(_))
50 }
51 }
52
53 impl Serialize for $name {
54 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
55 serializer.serialize_str(self.as_str())
56 }
57 }
58
59 impl<'de> Deserialize<'de> for $name {
60 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
61 let value = String::deserialize(deserializer)?;
62 Ok(Self::from_wire(&value))
63 }
64 }
65 };
66}
67
68open_set! {
69 /// A step's prompt-cache verdict. The rules that choose it are in
70 /// `CONTRACT.md` and are computed over the step's whole session in time
71 /// order.
72 ///
73 /// `Unknown` is a real verdict: the cache's health cannot be judged for
74 /// this step. `Other` is a value this version does not know (a newer
75 /// verdict); show it as received rather than treating it as `Unknown`.
76 pub enum Verdict {
77 /// The session's first step.
78 ColdStart => "cold_start",
79 /// Retention of at least 0.95, or no usable earlier step to compare.
80 Stable => "stable",
81 /// Retention of at least 0.80 and below 0.95.
82 Warning => "warning",
83 /// Retention below 0.80 with a positive cache read.
84 Bust => "bust",
85 /// A cache read of zero.
86 FullBust => "full_bust",
87 /// The cache's health cannot be judged for this step.
88 Unknown => "unknown",
89 }
90}
91
92open_set! {
93 /// Where the provider learned of a step.
94 pub enum StepSource {
95 /// Read from a harness store or a runner's durable log.
96 File => "file",
97 /// Known so far only from a runner's bus event.
98 Runner => "runner",
99 }
100}
101
102open_set! {
103 /// On a prompt drop, whether the request body shrank compared with the
104 /// earlier step.
105 pub enum RequestSize {
106 /// The current request body is shorter than the earlier step's.
107 Smaller => "smaller",
108 /// The current request body is not shorter.
109 NotSmaller => "not_smaller",
110 }
111}