1use crate::types::{BudgetClass, CanonicalCaseClass, LawfulStepKind};
7use serde::{Deserialize, Serialize};
8use stack_ids::ClaimVersionId;
9use verification_control::VerificationCaseClass;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
13#[serde(rename_all = "snake_case")]
14pub enum TargetPriority {
15 ActiveSyndrome = 0,
16 FragileNode = 1,
17 ThinExport = 2,
18 UnverifiedClaimVersion = 3,
19 RefutationGap = 4,
20 SupersessionVerification = 5,
21 ComparabilityDrift = 6,
22 CalibrationCaveat = 7,
23 ScopeStale = 8,
24}
25
26#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
31#[serde(rename_all = "snake_case")]
32pub enum TargetKind {
33 FragileNode {
34 node_id: String,
35 belief_micros: u64,
36 },
37 ActiveSyndrome {
38 signature: String,
39 },
40 ThinExport {
41 marker: String,
42 },
43 UnverifiedClaimVersion {
44 claim_version_id: ClaimVersionId,
45 },
46 RefutationGap {
47 target_node_id: String,
48 claim_version_id: Option<ClaimVersionId>,
49 },
50 SupersessionVerification {
51 claim_version_id: ClaimVersionId,
52 supersedes_claim_version_id: ClaimVersionId,
53 },
54 ComparabilityDrift {
55 detail: String,
56 },
57 CalibrationCaveat {
58 marker: String,
59 },
60 ScopeStale {
61 last_import_at: Option<String>,
62 },
63}
64
65impl TargetKind {
66 pub fn canonical_case_class(&self) -> CanonicalCaseClass {
68 match self {
69 Self::ActiveSyndrome { .. } => CanonicalCaseClass::ContradictionInvestigation,
70 Self::FragileNode { .. } => CanonicalCaseClass::PromotionCandidate,
71 Self::ThinExport { .. } => CanonicalCaseClass::ThinExportGap,
72 Self::UnverifiedClaimVersion { .. } => CanonicalCaseClass::PromotionCandidate,
73 Self::RefutationGap { .. } => CanonicalCaseClass::PromotionCandidate,
74 Self::SupersessionVerification { .. } => CanonicalCaseClass::SupersessionVerification,
75 Self::ComparabilityDrift { .. } => CanonicalCaseClass::ComparabilityDrift,
76 Self::CalibrationCaveat { .. } => CanonicalCaseClass::CalibrationCaveat,
77 Self::ScopeStale { .. } => CanonicalCaseClass::ScopeFreshness,
78 }
79 }
80
81 pub fn case_class(&self) -> VerificationCaseClass {
83 match self {
84 Self::FragileNode { .. } => VerificationCaseClass::FragileNode,
85 Self::ActiveSyndrome { .. } => VerificationCaseClass::ActiveSyndrome,
86 Self::ThinExport { .. } => VerificationCaseClass::ThinExport,
87 Self::UnverifiedClaimVersion { .. } => VerificationCaseClass::UnverifiedClaimVersion,
88 Self::RefutationGap { .. } => VerificationCaseClass::RefutationGap,
89 Self::SupersessionVerification { .. } => {
90 VerificationCaseClass::SupersessionVerification
91 }
92 Self::ComparabilityDrift { .. } => VerificationCaseClass::ComparabilityDrift,
93 Self::CalibrationCaveat { .. } => VerificationCaseClass::CalibrationCaveat,
94 Self::ScopeStale { .. } => VerificationCaseClass::ScopeStale,
95 }
96 }
97
98 pub fn primary_claim_version_id(&self) -> Option<ClaimVersionId> {
100 match self {
101 Self::UnverifiedClaimVersion { claim_version_id }
102 | Self::RefutationGap {
103 claim_version_id: Some(claim_version_id),
104 ..
105 }
106 | Self::SupersessionVerification {
107 claim_version_id, ..
108 } => Some(claim_version_id.clone()),
109 _ => None,
110 }
111 }
112
113 pub fn stable_key(&self) -> String {
115 match self {
116 Self::FragileNode { node_id, .. } => format!("fragile:{node_id}"),
117 Self::ActiveSyndrome { signature } => format!("syndrome:{signature}"),
118 Self::ThinExport { marker } => format!("thin_export:{marker}"),
119 Self::UnverifiedClaimVersion { claim_version_id } => {
120 format!("unverified:{}", claim_version_id.as_str())
121 }
122 Self::RefutationGap {
123 target_node_id,
124 claim_version_id,
125 } => format!(
126 "refutation_gap:{target_node_id}:{}",
127 claim_version_id
128 .as_ref()
129 .map(|id| id.as_str())
130 .unwrap_or("none")
131 ),
132 Self::SupersessionVerification {
133 claim_version_id,
134 supersedes_claim_version_id,
135 } => format!(
136 "supersession:{}:{}",
137 claim_version_id.as_str(),
138 supersedes_claim_version_id.as_str()
139 ),
140 Self::ComparabilityDrift { detail } => format!("comparability:{detail}"),
141 Self::CalibrationCaveat { marker } => format!("calibration:{marker}"),
142 Self::ScopeStale { last_import_at } => {
143 format!(
144 "scope_stale:{}",
145 last_import_at.as_deref().unwrap_or("none")
146 )
147 }
148 }
149 }
150
151 pub fn priority(&self) -> TargetPriority {
153 match self {
154 Self::ActiveSyndrome { .. } => TargetPriority::ActiveSyndrome,
155 Self::FragileNode { .. } => TargetPriority::FragileNode,
156 Self::ThinExport { .. } => TargetPriority::ThinExport,
157 Self::UnverifiedClaimVersion { .. } => TargetPriority::UnverifiedClaimVersion,
158 Self::RefutationGap { .. } => TargetPriority::RefutationGap,
159 Self::SupersessionVerification { .. } => TargetPriority::SupersessionVerification,
160 Self::ComparabilityDrift { .. } => TargetPriority::ComparabilityDrift,
161 Self::CalibrationCaveat { .. } => TargetPriority::CalibrationCaveat,
162 Self::ScopeStale { .. } => TargetPriority::ScopeStale,
163 }
164 }
165
166 pub fn budget_class(&self) -> BudgetClass {
168 match self {
169 Self::ThinExport { .. } | Self::ScopeStale { .. } => BudgetClass::Micro,
170 Self::ActiveSyndrome { .. }
171 | Self::FragileNode { .. }
172 | Self::UnverifiedClaimVersion { .. }
173 | Self::RefutationGap { .. }
174 | Self::SupersessionVerification { .. }
175 | Self::ComparabilityDrift { .. }
176 | Self::CalibrationCaveat { .. } => BudgetClass::Standard,
177 }
178 }
179
180 pub fn required_artifact_families(&self) -> Vec<String> {
182 let mut families = vec![
183 "ExecutionContextV1".into(),
184 "RuntimeQueryProvenanceV1".into(),
185 ];
186 match self {
187 Self::ThinExport { .. } => {}
188 Self::ComparabilityDrift { .. } => families.push("ComparableWitnessSet".into()),
189 Self::SupersessionVerification { .. } => families.push("ReplayArtifact".into()),
190 Self::RefutationGap { .. } => families.push("FalsifierWitness".into()),
191 _ => families.push("VerificationPlanV1".into()),
192 }
193 families
194 }
195
196 pub fn lawful_step_ladder(&self) -> Vec<LawfulStepKind> {
198 match self {
199 Self::ActiveSyndrome { .. } => vec![
200 LawfulStepKind::ExactOracleSlice,
201 LawfulStepKind::ExactReplay,
202 LawfulStepKind::MinimalPerturbationRefuter,
203 LawfulStepKind::HumanReviewRequest,
204 ],
205 Self::FragileNode { .. } => vec![
206 LawfulStepKind::ContractSchemaCheck,
207 LawfulStepKind::ProvenanceReceiptAudit,
208 LawfulStepKind::MinimalPerturbationRefuter,
209 LawfulStepKind::HumanReviewRequest,
210 ],
211 Self::ThinExport { .. } => vec![
212 LawfulStepKind::ContractSchemaCheck,
213 LawfulStepKind::ProvenanceReceiptAudit,
214 LawfulStepKind::HumanReviewRequest,
215 ],
216 Self::UnverifiedClaimVersion { .. } => vec![
217 LawfulStepKind::ContractSchemaCheck,
218 LawfulStepKind::ProvenanceReceiptAudit,
219 LawfulStepKind::TemporalConsistencyCheck,
220 LawfulStepKind::ExactOracleSlice,
221 LawfulStepKind::ConservativeOracleSlice,
222 LawfulStepKind::HumanReviewRequest,
223 ],
224 Self::RefutationGap { .. } => vec![
225 LawfulStepKind::MinimalPerturbationRefuter,
226 LawfulStepKind::ExactOracleSlice,
227 LawfulStepKind::HumanReviewRequest,
228 ],
229 Self::SupersessionVerification { .. } => vec![
230 LawfulStepKind::TemporalConsistencyCheck,
231 LawfulStepKind::ExactReplay,
232 LawfulStepKind::HumanReviewRequest,
233 ],
234 Self::ComparabilityDrift { .. } => vec![
235 LawfulStepKind::NuisanceComparabilityAudit,
236 LawfulStepKind::PairedComparativeCheck,
237 LawfulStepKind::HumanReviewRequest,
238 ],
239 Self::CalibrationCaveat { .. } => vec![
240 LawfulStepKind::ProvenanceReceiptAudit,
241 LawfulStepKind::ConservativeOracleSlice,
242 LawfulStepKind::HumanReviewRequest,
243 ],
244 Self::ScopeStale { .. } => vec![
245 LawfulStepKind::TemporalConsistencyCheck,
246 LawfulStepKind::CanonicalExportRequest,
247 LawfulStepKind::CanonicalImportRequest,
248 LawfulStepKind::HumanReviewRequest,
249 ],
250 }
251 }
252}