1use serde::Serialize;
2
3#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
5#[serde(rename_all = "camelCase")]
6pub struct OmenaTestkitSnapshotGovernancePolicyV0 {
7 pub fixture_grammar: &'static str,
9 pub snapshot_manifest_schema: &'static str,
11 pub known_failure_schema: &'static str,
13 pub allow_global_disable: bool,
15 pub update_requires_review: bool,
17 pub unreferenced_action: &'static str,
19 pub hot_snapshot_max_age_days: u32,
21 pub known_failure_review_period_days: u32,
23}
24
25#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
27#[serde(rename_all = "camelCase")]
28pub struct OmenaTestkitKnownFailureRecordV0 {
29 pub rationale: &'static str,
31 pub owner: &'static str,
33 pub age_days: u32,
35 pub has_expiry_or_review_policy: bool,
37}
38
39#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
41#[serde(rename_all = "camelCase")]
42pub struct OmenaTestkitSnapshotGovernanceSeedV0 {
43 pub snapshot_id: &'static str,
45 pub fixture_id: &'static str,
47 pub snapshot_path: &'static str,
49 pub referenced_by_fixture: bool,
51 pub hot_snapshot: bool,
53 pub age_days: u32,
55 pub known_failure: Option<OmenaTestkitKnownFailureRecordV0>,
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
61#[serde(rename_all = "camelCase")]
62pub struct OmenaTestkitSnapshotGovernanceVerdictV0 {
63 pub snapshot_id: &'static str,
65 pub fixture_id: &'static str,
67 pub rejected_unreferenced: bool,
69 pub hot_snapshot_review_required: bool,
71 pub known_failure_review_required: bool,
73 pub known_failure_policy_complete: bool,
75 pub action: &'static str,
77}
78
79#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
81#[serde(rename_all = "camelCase")]
82pub struct OmenaTestkitSnapshotGovernanceReportV0 {
83 pub schema_version: &'static str,
85 pub product: &'static str,
87 pub fixture_grammar: &'static str,
89 pub policy: OmenaTestkitSnapshotGovernancePolicyV0,
91 pub seed_count: usize,
93 pub global_disable_rejected: bool,
95 pub unreferenced_reject_ready: bool,
97 pub hot_snapshot_age_audit_ready: bool,
99 pub known_failure_policy_ready: bool,
101 pub rejected_unreferenced_count: usize,
103 pub hot_snapshot_review_required_count: usize,
105 pub known_failure_count: usize,
107 pub known_failure_review_required_count: usize,
109 pub verdicts: Vec<OmenaTestkitSnapshotGovernanceVerdictV0>,
111}
112
113const SNAPSHOT_POLICY: OmenaTestkitSnapshotGovernancePolicyV0 =
114 OmenaTestkitSnapshotGovernancePolicyV0 {
115 fixture_grammar: "omena-fixture-v0",
116 snapshot_manifest_schema: "omena-testkit-snapshot-manifest-v0",
117 known_failure_schema: "omena-testkit-known-failures-v0",
118 allow_global_disable: false,
119 update_requires_review: true,
120 unreferenced_action: "reject",
121 hot_snapshot_max_age_days: 14,
122 known_failure_review_period_days: 30,
123 };
124
125const SNAPSHOT_GOVERNANCE_SEEDS: &[OmenaTestkitSnapshotGovernanceSeedV0] = &[
126 OmenaTestkitSnapshotGovernanceSeedV0 {
127 snapshot_id: "style-facts-current",
128 fixture_id: "shared-style-fixture",
129 snapshot_path: "snapshots/shared-style-fixture/style-facts.snap.json",
130 referenced_by_fixture: true,
131 hot_snapshot: false,
132 age_days: 3,
133 known_failure: None,
134 },
135 OmenaTestkitSnapshotGovernanceSeedV0 {
136 snapshot_id: "orphan-style-facts",
137 fixture_id: "removed-fixture",
138 snapshot_path: "snapshots/removed-fixture/style-facts.snap.json",
139 referenced_by_fixture: false,
140 hot_snapshot: false,
141 age_days: 2,
142 known_failure: None,
143 },
144 OmenaTestkitSnapshotGovernanceSeedV0 {
145 snapshot_id: "hot-lsp-hover",
146 fixture_id: "lsp-hover-scenario",
147 snapshot_path: "snapshots/lsp-hover-scenario/hover.snap.json",
148 referenced_by_fixture: true,
149 hot_snapshot: true,
150 age_days: 21,
151 known_failure: None,
152 },
153 OmenaTestkitSnapshotGovernanceSeedV0 {
154 snapshot_id: "known-failure-source-rename",
155 fixture_id: "dynamic-source-rename-scenario",
156 snapshot_path: "snapshots/dynamic-source-rename-scenario/rename.snap.json",
157 referenced_by_fixture: true,
158 hot_snapshot: true,
159 age_days: 5,
160 known_failure: Some(OmenaTestkitKnownFailureRecordV0 {
161 rationale: "issue-38 dynamic identifier rename path is tracked as an M4 gate",
162 owner: "m4-axis-a-testkit",
163 age_days: 31,
164 has_expiry_or_review_policy: true,
165 }),
166 },
167];
168
169pub fn summarize_omena_testkit_snapshot_governance_report() -> OmenaTestkitSnapshotGovernanceReportV0
171{
172 let verdicts = SNAPSHOT_GOVERNANCE_SEEDS
173 .iter()
174 .map(snapshot_governance_verdict)
175 .collect::<Vec<_>>();
176 let rejected_unreferenced_count = verdicts
177 .iter()
178 .filter(|verdict| verdict.rejected_unreferenced)
179 .count();
180 let hot_snapshot_review_required_count = verdicts
181 .iter()
182 .filter(|verdict| verdict.hot_snapshot_review_required)
183 .count();
184 let known_failure_count = SNAPSHOT_GOVERNANCE_SEEDS
185 .iter()
186 .filter(|seed| seed.known_failure.is_some())
187 .count();
188 let known_failure_review_required_count = verdicts
189 .iter()
190 .filter(|verdict| verdict.known_failure_review_required)
191 .count();
192 let known_failure_policy_ready = SNAPSHOT_GOVERNANCE_SEEDS
193 .iter()
194 .filter_map(|seed| seed.known_failure.as_ref())
195 .all(|known_failure| {
196 !known_failure.rationale.trim().is_empty()
197 && !known_failure.owner.trim().is_empty()
198 && known_failure.has_expiry_or_review_policy
199 });
200
201 OmenaTestkitSnapshotGovernanceReportV0 {
202 schema_version: "0",
203 product: "omena-testkit.snapshot-governance",
204 fixture_grammar: SNAPSHOT_POLICY.fixture_grammar,
205 policy: SNAPSHOT_POLICY,
206 seed_count: SNAPSHOT_GOVERNANCE_SEEDS.len(),
207 global_disable_rejected: !SNAPSHOT_POLICY.allow_global_disable,
208 unreferenced_reject_ready: rejected_unreferenced_count > 0
209 && SNAPSHOT_POLICY.unreferenced_action == "reject",
210 hot_snapshot_age_audit_ready: hot_snapshot_review_required_count > 0,
211 known_failure_policy_ready,
212 rejected_unreferenced_count,
213 hot_snapshot_review_required_count,
214 known_failure_count,
215 known_failure_review_required_count,
216 verdicts,
217 }
218}
219
220fn snapshot_governance_verdict(
221 seed: &OmenaTestkitSnapshotGovernanceSeedV0,
222) -> OmenaTestkitSnapshotGovernanceVerdictV0 {
223 let rejected_unreferenced =
224 !seed.referenced_by_fixture && SNAPSHOT_POLICY.unreferenced_action == "reject";
225 let hot_snapshot_review_required =
226 seed.hot_snapshot && seed.age_days > SNAPSHOT_POLICY.hot_snapshot_max_age_days;
227 let known_failure_review_required = seed.known_failure.as_ref().is_some_and(|known_failure| {
228 known_failure.age_days > SNAPSHOT_POLICY.known_failure_review_period_days
229 });
230 let known_failure_policy_complete = seed.known_failure.as_ref().is_none_or(|known_failure| {
231 !known_failure.rationale.trim().is_empty()
232 && !known_failure.owner.trim().is_empty()
233 && known_failure.has_expiry_or_review_policy
234 });
235 let action = if rejected_unreferenced {
236 "reject"
237 } else if hot_snapshot_review_required || known_failure_review_required {
238 "review"
239 } else {
240 "accept"
241 };
242
243 OmenaTestkitSnapshotGovernanceVerdictV0 {
244 snapshot_id: seed.snapshot_id,
245 fixture_id: seed.fixture_id,
246 rejected_unreferenced,
247 hot_snapshot_review_required,
248 known_failure_review_required,
249 known_failure_policy_complete,
250 action,
251 }
252}
253
254#[cfg(test)]
255mod tests {
256 use super::*;
257
258 #[test]
259 fn snapshot_governance_rejects_unreferenced_snapshots() {
260 let report = summarize_omena_testkit_snapshot_governance_report();
261
262 assert_eq!(report.product, "omena-testkit.snapshot-governance");
263 assert_eq!(report.fixture_grammar, "omena-fixture-v0");
264 assert!(report.global_disable_rejected);
265 assert!(report.policy.update_requires_review);
266 assert!(report.unreferenced_reject_ready);
267 assert_eq!(report.rejected_unreferenced_count, 1);
268 assert!(
269 report
270 .verdicts
271 .iter()
272 .any(|verdict| verdict.snapshot_id == "orphan-style-facts"
273 && verdict.rejected_unreferenced
274 && verdict.action == "reject")
275 );
276 }
277
278 #[test]
279 fn snapshot_governance_audits_hot_snapshots_and_known_failures() {
280 let report = summarize_omena_testkit_snapshot_governance_report();
281
282 assert!(report.hot_snapshot_age_audit_ready);
283 assert_eq!(report.hot_snapshot_review_required_count, 1);
284 assert!(report.known_failure_policy_ready);
285 assert_eq!(report.known_failure_count, 1);
286 assert_eq!(report.known_failure_review_required_count, 1);
287 assert!(report.verdicts.iter().any(|verdict| verdict.snapshot_id
288 == "known-failure-source-rename"
289 && verdict.known_failure_review_required
290 && verdict.known_failure_policy_complete
291 && verdict.action == "review"));
292 }
293}