Skip to main content

chio_conformance/
model.rs

1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
6#[serde(rename_all = "kebab-case")]
7pub enum ScenarioCategory {
8    McpCore,
9    McpExperimental,
10    ChioExtension,
11    Infra,
12}
13
14impl ScenarioCategory {
15    pub fn heading(self) -> &'static str {
16        match self {
17            Self::McpCore => "MCP Core",
18            Self::McpExperimental => "MCP Experimental",
19            Self::ChioExtension => "Chio Extensions",
20            Self::Infra => "Infrastructure",
21        }
22    }
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
26#[serde(rename_all = "kebab-case")]
27pub enum Transport {
28    Stdio,
29    StreamableHttp,
30}
31
32impl Transport {
33    pub fn label(self) -> &'static str {
34        match self {
35            Self::Stdio => "stdio",
36            Self::StreamableHttp => "streamable-http",
37        }
38    }
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
42#[serde(rename_all = "snake_case")]
43pub enum PeerRole {
44    ClientToChioServer,
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
48#[serde(rename_all = "snake_case")]
49pub enum DeploymentMode {
50    WrappedStdio,
51    NativeStdio,
52    RemoteHttp,
53}
54
55impl DeploymentMode {
56    pub fn label(self) -> &'static str {
57        match self {
58            Self::WrappedStdio => "wrapped-stdio",
59            Self::NativeStdio => "native-stdio",
60            Self::RemoteHttp => "remote-http",
61        }
62    }
63}
64
65#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
66#[serde(rename_all = "camelCase")]
67pub struct RequiredCapabilities {
68    #[serde(default)]
69    pub server: Vec<String>,
70    #[serde(default)]
71    pub client: Vec<String>,
72}
73
74#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
75#[serde(rename_all = "camelCase")]
76pub struct ScenarioDescriptor {
77    pub id: String,
78    pub title: String,
79    pub area: String,
80    pub category: ScenarioCategory,
81    pub spec_versions: Vec<String>,
82    #[serde(default)]
83    pub transport: Vec<Transport>,
84    #[serde(default)]
85    pub peer_roles: Vec<PeerRole>,
86    #[serde(default)]
87    pub deployment_modes: Vec<DeploymentMode>,
88    #[serde(default)]
89    pub required_capabilities: RequiredCapabilities,
90    #[serde(default)]
91    pub tags: Vec<String>,
92    pub expected: ResultStatus,
93    #[serde(default)]
94    pub timeout_ms: Option<u64>,
95    #[serde(default)]
96    pub notes: Option<String>,
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
100#[serde(rename_all = "kebab-case")]
101pub enum ResultStatus {
102    Pass,
103    Fail,
104    Unsupported,
105    Skipped,
106    Xfail,
107}
108
109impl ResultStatus {
110    pub fn label(self) -> &'static str {
111        match self {
112            Self::Pass => "pass",
113            Self::Fail => "fail",
114            Self::Unsupported => "unsupported",
115            Self::Skipped => "skipped",
116            Self::Xfail => "xfail",
117        }
118    }
119}
120
121#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
122#[serde(rename_all = "kebab-case")]
123pub enum AssertionOutcome {
124    Pass,
125    Fail,
126}
127
128#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
129#[serde(rename_all = "camelCase")]
130pub struct AssertionResult {
131    pub name: String,
132    pub status: AssertionOutcome,
133    #[serde(default)]
134    pub message: Option<String>,
135}
136
137#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
138#[serde(rename_all = "camelCase")]
139pub struct ScenarioResult {
140    pub scenario_id: String,
141    pub peer: String,
142    pub peer_role: PeerRole,
143    pub deployment_mode: DeploymentMode,
144    pub transport: Transport,
145    pub spec_version: String,
146    pub category: ScenarioCategory,
147    pub status: ResultStatus,
148    pub duration_ms: u64,
149    #[serde(default)]
150    pub assertions: Vec<AssertionResult>,
151    #[serde(default)]
152    pub notes: Option<String>,
153    #[serde(default)]
154    pub artifacts: BTreeMap<String, String>,
155    #[serde(default)]
156    pub failure_kind: Option<String>,
157    #[serde(default)]
158    pub failure_message: Option<String>,
159    #[serde(default)]
160    pub expected_failure: Option<bool>,
161}
162
163#[derive(Debug, Clone, PartialEq, Eq, Default)]
164pub struct CompatibilityReport {
165    pub scenarios: Vec<ScenarioDescriptor>,
166    pub results: Vec<ScenarioResult>,
167}