Skip to main content

lexicon_spec/
common.rs

1use serde::{Deserialize, Serialize};
2
3/// Status of a contract in its lifecycle.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5#[serde(rename_all = "snake_case")]
6pub enum ContractStatus {
7    /// Contract is being drafted, not yet enforced.
8    Draft,
9    /// Contract is active and enforced.
10    Active,
11    /// Contract is deprecated, still enforced but expected to be replaced.
12    Deprecated,
13    /// Contract is retired, no longer enforced.
14    Retired,
15}
16
17impl Default for ContractStatus {
18    fn default() -> Self {
19        Self::Draft
20    }
21}
22
23/// Stability level of a contract or artifact.
24#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
25#[serde(rename_all = "snake_case")]
26pub enum Stability {
27    /// Experimental: may change or be removed at any time.
28    Experimental,
29    /// Unstable: expected to stabilize but may still change.
30    Unstable,
31    /// Stable: changes require versioned migration.
32    Stable,
33    /// Frozen: must not change without extraordinary justification.
34    Frozen,
35}
36
37impl Default for Stability {
38    fn default() -> Self {
39        Self::Experimental
40    }
41}
42
43/// Severity level for invariants and checks.
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
45#[serde(rename_all = "snake_case")]
46pub enum Severity {
47    /// Must pass. Failure blocks verification.
48    Required,
49    /// Should pass. Contributes to score but does not block.
50    Advisory,
51}
52
53impl Default for Severity {
54    fn default() -> Self {
55        Self::Required
56    }
57}
58
59/// Type of repository being managed.
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
61#[serde(rename_all = "snake_case")]
62pub enum RepoType {
63    Library,
64    Binary,
65    Workspace,
66}
67
68impl Default for RepoType {
69    fn default() -> Self {
70        Self::Library
71    }
72}
73
74/// Naming convention preference for generated artifacts.
75#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
76#[serde(rename_all = "snake_case")]
77pub enum NamingConvention {
78    SnakeCase,
79    KebabCase,
80}
81
82impl Default for NamingConvention {
83    fn default() -> Self {
84        Self::KebabCase
85    }
86}
87
88/// Style of conformance testing to generate.
89#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
90#[serde(rename_all = "snake_case")]
91pub enum ConformanceStyle {
92    /// Uses trait-based test harnesses.
93    TraitBased,
94    /// Uses factory functions to create test instances.
95    FactoryBased,
96}
97
98impl Default for ConformanceStyle {
99    fn default() -> Self {
100        Self::TraitBased
101    }
102}
103
104/// Category for scoring dimensions and gates.
105#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
106#[serde(rename_all = "snake_case")]
107pub enum DimensionCategory {
108    /// Must pass. Failure blocks the overall gate.
109    Required,
110    /// Contributes to the numeric score.
111    Scored,
112    /// Informational only. Does not affect pass/fail.
113    Advisory,
114}
115
116impl Default for DimensionCategory {
117    fn default() -> Self {
118        Self::Scored
119    }
120}
121
122/// Source of a score dimension value.
123#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
124#[serde(rename_all = "snake_case")]
125pub enum ScoreSource {
126    Gate,
127    TestSuite,
128    Coverage,
129    Manual,
130}
131
132/// Actor that performed an action.
133#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
134#[serde(rename_all = "snake_case")]
135pub enum Actor {
136    User,
137    Ai,
138    System,
139}
140
141/// Kind of conversation workflow.
142#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
143#[serde(rename_all = "snake_case")]
144pub enum WorkflowKind {
145    Init,
146    ContractNew,
147    ContractEdit,
148    ConformanceAdd,
149    BehaviorAdd,
150    ScoreInit,
151    GateInit,
152    Improve,
153    Coach,
154    Chat,
155}
156
157/// Status of a conversation session.
158#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
159#[serde(rename_all = "snake_case")]
160pub enum SessionStatus {
161    Active,
162    Completed,
163    Abandoned,
164}
165
166/// Type of step in a conversation workflow.
167#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
168#[serde(rename_all = "snake_case")]
169pub enum StepType {
170    Question,
171    UserInput,
172    Proposal,
173    Refinement,
174    Validation,
175    Write,
176    Info,
177}
178
179/// Type of auditable action.
180#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
181#[serde(rename_all = "snake_case")]
182pub enum AuditAction {
183    RepoInit,
184    ContractCreate,
185    ContractUpdate,
186    ContractStatusChange,
187    ConformanceCreate,
188    ConformanceUpdate,
189    BehaviorCreate,
190    BehaviorUpdate,
191    ScoreModelChange,
192    GateModelChange,
193    GateWeakeningAttempt,
194    AiImprove,
195    AiImproveRejected,
196    VerifyRun,
197    ClaudeSyncRun,
198    TestDeletion,
199    ThresholdChange,
200    ApiScan,
201    ApiDiff,
202    CoverageReport,
203    PropertyTestCreate,
204    FuzzCreate,
205    EdgeCaseCreate,
206    ContractInfer,
207    PromptGenerate,
208    PromptRegenerate,
209    CoachAccept,
210    CoachReject,
211}
212
213#[cfg(test)]
214mod tests {
215    use super::*;
216
217    #[test]
218    fn test_contract_status_serde() {
219        let s = ContractStatus::Active;
220        let json = serde_json::to_string(&s).unwrap();
221        assert_eq!(json, "\"active\"");
222        let parsed: ContractStatus = serde_json::from_str(&json).unwrap();
223        assert_eq!(s, parsed);
224    }
225
226    #[test]
227    fn test_stability_ordering() {
228        assert!(Stability::Experimental < Stability::Unstable);
229        assert!(Stability::Unstable < Stability::Stable);
230        assert!(Stability::Stable < Stability::Frozen);
231    }
232
233    #[test]
234    fn test_all_enums_roundtrip_json() {
235        macro_rules! roundtrip {
236            ($t:ty, $val:expr) => {
237                let json = serde_json::to_string(&$val).unwrap();
238                let parsed: $t = serde_json::from_str(&json).unwrap();
239                assert_eq!($val, parsed);
240            };
241        }
242
243        roundtrip!(ContractStatus, ContractStatus::Draft);
244        roundtrip!(Stability, Stability::Frozen);
245        roundtrip!(Severity, Severity::Advisory);
246        roundtrip!(RepoType, RepoType::Workspace);
247        roundtrip!(NamingConvention, NamingConvention::SnakeCase);
248        roundtrip!(ConformanceStyle, ConformanceStyle::FactoryBased);
249        roundtrip!(DimensionCategory, DimensionCategory::Required);
250        roundtrip!(ScoreSource, ScoreSource::Gate);
251        roundtrip!(Actor, Actor::Ai);
252        roundtrip!(WorkflowKind, WorkflowKind::ContractNew);
253        roundtrip!(SessionStatus, SessionStatus::Abandoned);
254        roundtrip!(StepType, StepType::Proposal);
255        roundtrip!(AuditAction, AuditAction::AiImprove);
256    }
257}