Skip to main content

omena_lawvere/
lib.rs

1//! Transform-pass catalog and reorderability metadata scaffold.
2//!
3//! This crate is intentionally contract-first. It records the 40-pass catalog,
4//! rank clusters, reorderability evidence, and a scaffolded parallel plan
5//! without changing the existing transform executor.
6//!
7//! claim_level: feature-gated differential commutativity witness, not a global
8//! transform-catalog theorem or default product mechanism.
9
10use std::collections::BTreeMap;
11
12use omena_evidence_graph::ObligationFamilyIdV0;
13use omena_transform_cst::{
14    TRANSFORM_PASS_CATALOG_LEN, TransformDagEdgeV0, TransformPassKind, all_transform_pass_kinds,
15    cascade_safe_obligation, default_transform_dag_edges,
16};
17use serde::Serialize;
18
19mod independence;
20
21pub use independence::{
22    TransformCatalogDescriptorEdgeJustificationV0, TransformCatalogIndependenceDataV0,
23    TransformCatalogIndependenceDispositionV0, TransformCatalogIndependenceEntryV0,
24    TransformCatalogIndependenceErrorV0, TransformCatalogIndependenceJustificationV0,
25    TransformCatalogIndependenceObservationRowV0, TransformCatalogObservationProfileDataV0,
26    TransformCatalogScheduleEquivalenceV0, canonicalize_transform_catalog_schedule_v0,
27    default_transform_catalog_independence_data_v0, transform_catalog_independence_layers_v0,
28    transform_catalog_passes_are_independent_v0, transform_catalog_schedules_equivalent_v0,
29    validate_transform_catalog_independence_data_v0,
30};
31use independence::{
32    adjacent_schedule_pair_term_v0, checked_adjacent_swap_token_v0,
33    transform_catalog_independence_layers_from_data_v0,
34};
35
36pub const TRANSFORM_CATALOG_SCHEMA_VERSION_V0: &str = "css-transform-catalog-v0";
37pub const TRANSFORM_CATALOG_MECHANISM_SCOPE_V0: &str = "featureGatedDifferentialWitnessSubstrate";
38pub const TRANSFORM_CATALOG_PRODUCT_PATH_EVIDENCE_READY_V0: bool = false;
39pub const TRANSFORM_CATALOG_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0: bool = false;
40pub const TRANSFORM_CATALOG_PLAN_NON_CONSUMPTION_REASON_V0: &str =
41    "executorKeepsValidatedSerialDagUntilParallelApplicationSemanticsLand";
42
43#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize)]
44#[serde(rename_all = "camelCase")]
45pub enum AbstractDomainTagV0 {
46    SyntaxTrivia,
47    TokenValue,
48    SelectorShape,
49    CascadeStructural,
50    SemanticGraph,
51    TerminalEmission,
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize)]
55#[serde(rename_all = "camelCase")]
56pub enum TransformCatalogRoleV0 {
57    Generator,
58    TerminalForgetfulFunctor,
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize)]
62#[serde(rename_all = "camelCase")]
63pub enum SaturationBudgetTierV0 {
64    Full,
65    Half,
66    Minimal,
67}
68
69impl SaturationBudgetTierV0 {
70    pub const fn fixture_count(self) -> usize {
71        match self {
72            Self::Minimal => 10,
73            Self::Half => 50,
74            Self::Full => 200,
75        }
76    }
77
78    pub const fn label(self) -> &'static str {
79        match self {
80            Self::Minimal => "Dev",
81            Self::Half => "CI",
82            Self::Full => "Nightly",
83        }
84    }
85}
86
87#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
88#[serde(rename_all = "camelCase")]
89pub struct TransformCatalogGeneratorMetadataV0 {
90    pub schema_version: &'static str,
91    pub product: &'static str,
92    pub layer_marker: &'static str,
93    pub feature_gate: &'static str,
94    pub theory_version: &'static str,
95    pub pass_id: &'static str,
96    pub ordinal: u8,
97    pub title: &'static str,
98    pub catalog_role: TransformCatalogRoleV0,
99    pub abstract_domain_tag: AbstractDomainTagV0,
100    pub execution_rank_hint: u32,
101    pub terminal_forgetful_functor: bool,
102    pub reads_fixed_point: bool,
103}
104
105#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
106#[serde(rename_all = "camelCase")]
107pub struct TransformCatalogEquationClusterV0 {
108    pub schema_version: &'static str,
109    pub product: &'static str,
110    pub layer_marker: &'static str,
111    pub feature_gate: &'static str,
112    pub execution_rank_hint: u32,
113    pub pass_ids: Vec<&'static str>,
114    pub generator_count: usize,
115    pub saturation_budget_tier: SaturationBudgetTierV0,
116    pub theory_version: &'static str,
117}
118
119#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
120#[serde(rename_all = "camelCase")]
121pub struct TransformCatalogDifferentialCorpusTierV0 {
122    pub schema_version: &'static str,
123    pub product: &'static str,
124    pub layer_marker: &'static str,
125    pub feature_gate: &'static str,
126    pub theory_version: &'static str,
127    pub tier: SaturationBudgetTierV0,
128    pub tier_label: &'static str,
129    pub fixture_count: usize,
130    pub required_pass_rate_percent: u8,
131}
132
133#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
134#[serde(rename_all = "camelCase")]
135pub struct ReorderabilityCertificateV0 {
136    pub schema_version: &'static str,
137    pub product: &'static str,
138    pub layer_marker: &'static str,
139    pub feature_gate: &'static str,
140    pub mechanism_scope: &'static str,
141    pub product_path_evidence_ready: bool,
142    pub global_transform_theorem_claimed: bool,
143    pub left_pass_id: &'static str,
144    pub right_pass_id: &'static str,
145    pub theory_version: &'static str,
146    pub differential_tier: SaturationBudgetTierV0,
147    pub commute_witness: &'static str,
148    pub differential_fixture_count: usize,
149    pub differential_equal_fixture_count: usize,
150    pub differential_mismatch_count: usize,
151    pub specificity_preserved: bool,
152    #[serde(skip_serializing)]
153    obligation_family: ObligationFamilyIdV0,
154    #[serde(skip_serializing)]
155    issuance_token: Option<omena_cascade_proof::RewriteIssuanceTokenV0>,
156    pub computed_value_preserved: bool,
157    pub provenance_preserved: bool,
158    pub cascade_safe_witness: String,
159    pub accepted: bool,
160}
161
162impl ReorderabilityCertificateV0 {
163    pub fn has_checked_issuance_token_v0(&self) -> bool {
164        self.issuance_token.is_some()
165    }
166
167    pub fn issuance_token_matches_pair_v0(
168        &self,
169        left: TransformPassKind,
170        right: TransformPassKind,
171    ) -> bool {
172        let before = adjacent_schedule_pair_term_v0(left, right);
173        let after = adjacent_schedule_pair_term_v0(right, left);
174        let trusted_catalog = independence::adjacent_schedule_swap_catalog_v0();
175        self.issuance_token.as_ref().is_some_and(|token| {
176            token.matches_endpoints_v0(&before, &after)
177                && token.matches_catalog_v0(&trusted_catalog)
178        })
179    }
180}
181
182#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
183#[serde(rename_all = "camelCase")]
184pub struct TransformCatalogDifferentialCommutativityCaseV0 {
185    pub label: String,
186    pub input_css: String,
187    pub left_then_right_css: String,
188    pub right_then_left_css: String,
189    pub left_then_right_mutation_count: usize,
190    pub right_then_left_mutation_count: usize,
191    pub equal_output: bool,
192}
193
194#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
195#[serde(rename_all = "camelCase")]
196pub struct TransformCatalogDifferentialCommutativityWitnessV0 {
197    pub schema_version: &'static str,
198    pub product: &'static str,
199    pub layer_marker: &'static str,
200    pub feature_gate: &'static str,
201    pub mechanism_scope: &'static str,
202    pub product_path_evidence_ready: bool,
203    pub global_transform_theorem_claimed: bool,
204    pub theory_version: &'static str,
205    pub left_pass_id: &'static str,
206    pub right_pass_id: &'static str,
207    pub fixture_count: usize,
208    pub equal_fixture_count: usize,
209    pub mismatch_count: usize,
210    pub cases: Vec<TransformCatalogDifferentialCommutativityCaseV0>,
211    pub accepted: bool,
212}
213
214#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
215#[serde(rename_all = "camelCase")]
216pub struct TransformCatalogTransformPassParallelPlanV0 {
217    pub schema_version: &'static str,
218    pub product: &'static str,
219    pub layer_marker: &'static str,
220    pub feature_gate: &'static str,
221    pub mechanism_scope: &'static str,
222    pub product_path_evidence_ready: bool,
223    pub global_transform_theorem_claimed: bool,
224    pub scheduler_status: &'static str,
225    pub requested_pass_ids: Vec<&'static str>,
226    pub terminal_pass_ids: Vec<&'static str>,
227    pub rank_clusters: Vec<TransformCatalogEquationClusterV0>,
228    pub executor_consumes_plan: bool,
229}
230
231#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
232#[serde(rename_all = "camelCase")]
233pub struct TransformCatalogModelTraceV0 {
234    pub schema_version: &'static str,
235    pub product: &'static str,
236    pub layer_marker: &'static str,
237    pub feature_gate: &'static str,
238    pub mechanism_scope: &'static str,
239    pub product_path_evidence_ready: bool,
240    pub global_transform_theorem_claimed: bool,
241    pub theory_version: &'static str,
242    pub input_pass_ids: Vec<&'static str>,
243    pub ordered_pass_ids: Vec<&'static str>,
244    pub terminal_pass_ids: Vec<&'static str>,
245    pub rank_clusters: Vec<TransformCatalogEquationClusterV0>,
246    pub preserves_existing_executor_signature: bool,
247}
248
249#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
250#[serde(rename_all = "camelCase")]
251pub struct TransformCatalogSaturationExecutionV0 {
252    pub schema_version: &'static str,
253    pub product: &'static str,
254    pub layer_marker: &'static str,
255    pub feature_gate: &'static str,
256    pub mechanism_scope: &'static str,
257    pub product_path_evidence_ready: bool,
258    pub global_transform_theorem_claimed: bool,
259    pub theory_version: &'static str,
260    pub pass_id: &'static str,
261    pub analysis_slot: &'static str,
262    pub original_unit_analysis_path_preserved: bool,
263    pub differential_tier: SaturationBudgetTierV0,
264    pub differential_fixture_count: usize,
265    pub iteration_limit: usize,
266    pub iteration_count: usize,
267    pub eclass_count: usize,
268    pub enode_count: usize,
269    pub accepted: bool,
270    pub extracted_matches_candidate: bool,
271}
272
273#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
274#[serde(rename_all = "camelCase")]
275pub struct TransformCatalogMetadataSummaryV0 {
276    pub schema_version: &'static str,
277    pub product: &'static str,
278    pub layer_marker: &'static str,
279    pub feature_gate: &'static str,
280    pub theory_version: &'static str,
281    pub catalog_pass_count: usize,
282    pub catalog_entry_count: usize,
283    /// Compatibility field owned by `omena-lawvere` maintainers. Remove not
284    /// before 1.0, after downstream migration and zero audited non-compat uses.
285    #[deprecated(
286        since = "0.4.0",
287        note = "use transform_catalog_generator_count(); removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
288    )]
289    pub lawvere_generator_count: usize,
290    pub terminal_forgetful_functor_count: usize,
291    pub execution_rank_cluster_count: usize,
292    pub equation_clusters: Vec<TransformCatalogEquationClusterV0>,
293    pub generators: Vec<TransformCatalogGeneratorMetadataV0>,
294    pub dag_edges: Vec<TransformDagEdgeV0>,
295    pub saturation_budget_tiers: Vec<SaturationBudgetTierV0>,
296    pub differential_corpus_tiers: Vec<TransformCatalogDifferentialCorpusTierV0>,
297    /// Compatibility field owned by `omena-lawvere` maintainers. Remove not
298    /// before 1.0, after downstream migration and zero audited non-compat uses.
299    #[deprecated(
300        since = "0.4.0",
301        note = "use transform_catalog_saturation_feature_enabled_by_default(); removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
302    )]
303    pub lawvere_saturation_feature_enabled_by_default: bool,
304    pub product_path_evidence_ready: bool,
305    pub mechanism_scope: &'static str,
306    pub omena_categorical_dependency_forbidden: bool,
307}
308
309impl TransformCatalogMetadataSummaryV0 {
310    #[allow(deprecated)]
311    pub fn transform_catalog_generator_count(&self) -> usize {
312        transform_catalog_generator_count_from_legacy_field_v0(self)
313    }
314
315    #[allow(deprecated)]
316    pub fn transform_catalog_saturation_feature_enabled_by_default(&self) -> bool {
317        transform_catalog_saturation_default_from_legacy_field_v0(self)
318    }
319}
320
321#[deprecated(
322    since = "0.4.0",
323    note = "compatibility field adapter owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
324)]
325#[allow(deprecated)]
326fn transform_catalog_generator_count_from_legacy_field_v0(
327    summary: &TransformCatalogMetadataSummaryV0,
328) -> usize {
329    summary.lawvere_generator_count
330}
331
332#[deprecated(
333    since = "0.4.0",
334    note = "compatibility field adapter owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
335)]
336#[allow(deprecated)]
337fn transform_catalog_saturation_default_from_legacy_field_v0(
338    summary: &TransformCatalogMetadataSummaryV0,
339) -> bool {
340    summary.lawvere_saturation_feature_enabled_by_default
341}
342
343#[allow(deprecated)]
344pub fn summarize_transform_catalog_metadata_v0() -> TransformCatalogMetadataSummaryV0 {
345    let generators = transform_catalog_generator_metadata_catalog_v0();
346    let terminal_forgetful_functor_count = generators
347        .iter()
348        .filter(|generator| generator.terminal_forgetful_functor)
349        .count();
350    let equation_clusters = transform_catalog_equation_clusters_v0(
351        generators
352            .iter()
353            .map(|generator| generator.pass_id)
354            .collect::<Vec<_>>()
355            .as_slice(),
356    );
357
358    build_transform_catalog_metadata_summary_v0(
359        generators,
360        terminal_forgetful_functor_count,
361        equation_clusters,
362    )
363}
364
365#[deprecated(
366    since = "0.4.0",
367    note = "constructs retained serialized fields; owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
368)]
369#[allow(deprecated)]
370fn build_transform_catalog_metadata_summary_v0(
371    generators: Vec<TransformCatalogGeneratorMetadataV0>,
372    terminal_forgetful_functor_count: usize,
373    equation_clusters: Vec<TransformCatalogEquationClusterV0>,
374) -> TransformCatalogMetadataSummaryV0 {
375    TransformCatalogMetadataSummaryV0 {
376        schema_version: "0",
377        product: "omena-lawvere.theory-summary",
378        layer_marker: "enriched-algebraic",
379        feature_gate: "transform-catalog-saturation",
380        theory_version: TRANSFORM_CATALOG_SCHEMA_VERSION_V0,
381        catalog_pass_count: TRANSFORM_PASS_CATALOG_LEN,
382        catalog_entry_count: generators.len(),
383        lawvere_generator_count: transform_catalog_generator_count_v0(&generators),
384        terminal_forgetful_functor_count,
385        execution_rank_cluster_count: equation_clusters.len(),
386        equation_clusters,
387        generators,
388        dag_edges: default_transform_dag_edges(),
389        saturation_budget_tiers: vec![
390            SaturationBudgetTierV0::Minimal,
391            SaturationBudgetTierV0::Half,
392            SaturationBudgetTierV0::Full,
393        ],
394        differential_corpus_tiers: transform_catalog_differential_corpus_tiers_v0(),
395        lawvere_saturation_feature_enabled_by_default: false,
396        product_path_evidence_ready: TRANSFORM_CATALOG_PRODUCT_PATH_EVIDENCE_READY_V0,
397        mechanism_scope: TRANSFORM_CATALOG_MECHANISM_SCOPE_V0,
398        omena_categorical_dependency_forbidden: true,
399    }
400}
401
402pub fn transform_catalog_generator_metadata_catalog_v0() -> Vec<TransformCatalogGeneratorMetadataV0>
403{
404    all_transform_pass_kinds()
405        .into_iter()
406        .map(transform_catalog_generator_metadata_v0)
407        .collect()
408}
409
410pub fn transform_catalog_generator_metadata_v0(
411    kind: TransformPassKind,
412) -> TransformCatalogGeneratorMetadataV0 {
413    let terminal_forgetful_functor = kind == TransformPassKind::PrintCss;
414    TransformCatalogGeneratorMetadataV0 {
415        schema_version: "0",
416        product: "omena-lawvere.generator-metadata",
417        layer_marker: "enriched-algebraic",
418        feature_gate: "transform-catalog-saturation",
419        theory_version: TRANSFORM_CATALOG_SCHEMA_VERSION_V0,
420        pass_id: kind.id(),
421        ordinal: kind.ordinal(),
422        title: kind.title(),
423        catalog_role: if terminal_forgetful_functor {
424            TransformCatalogRoleV0::TerminalForgetfulFunctor
425        } else {
426            TransformCatalogRoleV0::Generator
427        },
428        abstract_domain_tag: abstract_domain_tag_for_pass(kind),
429        execution_rank_hint: u32::from(transform_catalog_execution_rank_hint(kind)),
430        terminal_forgetful_functor,
431        reads_fixed_point: matches!(
432            kind,
433            TransformPassKind::StaticVarSubstitution
434                | TransformPassKind::TreeShakeCustomProperty
435                | TransformPassKind::DesignTokenRouting
436        ),
437    }
438}
439
440pub fn transform_catalog_equation_clusters_v0(
441    pass_ids: &[&'static str],
442) -> Vec<TransformCatalogEquationClusterV0> {
443    let mut clusters = BTreeMap::<u32, Vec<&'static str>>::new();
444    for kind in all_transform_pass_kinds() {
445        if pass_ids.contains(&kind.id())
446            && transform_catalog_catalog_role_v0(kind) == TransformCatalogRoleV0::Generator
447        {
448            clusters
449                .entry(u32::from(transform_catalog_execution_rank_hint(kind)))
450                .or_default()
451                .push(kind.id());
452        }
453    }
454    clusters
455        .into_iter()
456        .map(|(execution_rank_hint, mut pass_ids)| {
457            pass_ids.sort();
458            let generator_count = pass_ids.len();
459            TransformCatalogEquationClusterV0 {
460                schema_version: "0",
461                product: "omena-lawvere.equation-cluster",
462                layer_marker: "enriched-algebraic",
463                feature_gate: "transform-catalog-saturation",
464                execution_rank_hint,
465                pass_ids,
466                generator_count,
467                saturation_budget_tier: budget_tier_for_cluster_size(generator_count),
468                theory_version: TRANSFORM_CATALOG_SCHEMA_VERSION_V0,
469            }
470        })
471        .collect()
472}
473
474fn transform_catalog_independence_clusters_v0(
475    requested: &[TransformPassKind],
476) -> Vec<TransformCatalogEquationClusterV0> {
477    let generators = requested
478        .iter()
479        .copied()
480        .filter(|kind| {
481            transform_catalog_catalog_role_v0(*kind) == TransformCatalogRoleV0::Generator
482        })
483        .collect::<Vec<_>>();
484    let layers = default_transform_catalog_independence_data_v0().map_or_else(
485        |_| generators.iter().copied().map(|kind| vec![kind]).collect(),
486        |data| transform_catalog_independence_layers_from_data_v0(&generators, &data),
487    );
488    layers
489        .into_iter()
490        .enumerate()
491        .map(|(layer_index, layer)| {
492            let pass_ids = layer.iter().map(|kind| kind.id()).collect::<Vec<_>>();
493            let generator_count = pass_ids.len();
494            TransformCatalogEquationClusterV0 {
495                schema_version: "0",
496                product: "omena-lawvere.independence-layer",
497                layer_marker: "enriched-algebraic",
498                feature_gate: "transform-catalog-saturation",
499                execution_rank_hint: u32::try_from(layer_index).unwrap_or(u32::MAX),
500                pass_ids,
501                generator_count,
502                saturation_budget_tier: budget_tier_for_cluster_size(generator_count),
503                theory_version: TRANSFORM_CATALOG_SCHEMA_VERSION_V0,
504            }
505        })
506        .collect()
507}
508
509fn transform_catalog_independence_clusters_from_pass_ids_v0(
510    pass_ids: &[&'static str],
511) -> Vec<TransformCatalogEquationClusterV0> {
512    let requested = pass_ids
513        .iter()
514        .filter_map(|pass_id| {
515            all_transform_pass_kinds()
516                .into_iter()
517                .find(|kind| kind.id() == *pass_id)
518        })
519        .collect::<Vec<_>>();
520    transform_catalog_independence_clusters_v0(&requested)
521}
522
523fn legacy_plan_transform_catalog_parallel_layers_v0(
524    requested: &[TransformPassKind],
525) -> TransformCatalogTransformPassParallelPlanV0 {
526    let requested_pass_ids = requested.iter().map(|kind| kind.id()).collect::<Vec<_>>();
527    TransformCatalogTransformPassParallelPlanV0 {
528        schema_version: "0",
529        product: "omena-lawvere.transform-pass-parallel-plan",
530        layer_marker: "enriched-algebraic",
531        feature_gate: "transform-catalog-saturation",
532        mechanism_scope: TRANSFORM_CATALOG_MECHANISM_SCOPE_V0,
533        product_path_evidence_ready: TRANSFORM_CATALOG_PRODUCT_PATH_EVIDENCE_READY_V0,
534        global_transform_theorem_claimed: TRANSFORM_CATALOG_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0,
535        scheduler_status: "scaffoldOnly",
536        requested_pass_ids: requested_pass_ids.clone(),
537        terminal_pass_ids: terminal_pass_ids_from_pass_kinds(requested),
538        rank_clusters: transform_catalog_equation_clusters_v0(requested_pass_ids.as_slice()),
539        executor_consumes_plan: false,
540    }
541}
542
543fn legacy_trace_transform_catalog_model_v0(
544    requested: &[TransformPassKind],
545    ordered_pass_ids: Vec<&'static str>,
546) -> TransformCatalogModelTraceV0 {
547    let input_pass_ids = requested.iter().map(|kind| kind.id()).collect::<Vec<_>>();
548    TransformCatalogModelTraceV0 {
549        schema_version: "0",
550        product: "omena-lawvere.model-trace",
551        layer_marker: "enriched-algebraic",
552        feature_gate: "transform-catalog-saturation",
553        mechanism_scope: TRANSFORM_CATALOG_MECHANISM_SCOPE_V0,
554        product_path_evidence_ready: TRANSFORM_CATALOG_PRODUCT_PATH_EVIDENCE_READY_V0,
555        global_transform_theorem_claimed: TRANSFORM_CATALOG_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0,
556        theory_version: TRANSFORM_CATALOG_SCHEMA_VERSION_V0,
557        rank_clusters: transform_catalog_equation_clusters_v0(ordered_pass_ids.as_slice()),
558        input_pass_ids,
559        terminal_pass_ids: terminal_pass_ids_from_pass_ids(ordered_pass_ids.as_slice()),
560        ordered_pass_ids,
561        preserves_existing_executor_signature: true,
562    }
563}
564
565pub fn plan_transform_catalog_parallel_layers_v0(
566    requested: &[TransformPassKind],
567) -> TransformCatalogTransformPassParallelPlanV0 {
568    let requested_pass_ids = requested.iter().map(|kind| kind.id()).collect::<Vec<_>>();
569    TransformCatalogTransformPassParallelPlanV0 {
570        schema_version: "0",
571        product: "omena-lawvere.transform-pass-parallel-plan",
572        layer_marker: "enriched-algebraic",
573        feature_gate: "transform-catalog-saturation",
574        mechanism_scope: TRANSFORM_CATALOG_MECHANISM_SCOPE_V0,
575        product_path_evidence_ready: TRANSFORM_CATALOG_PRODUCT_PATH_EVIDENCE_READY_V0,
576        global_transform_theorem_claimed: TRANSFORM_CATALOG_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0,
577        scheduler_status: "independenceDataReady",
578        requested_pass_ids: requested_pass_ids.clone(),
579        terminal_pass_ids: terminal_pass_ids_from_pass_kinds(requested),
580        rank_clusters: transform_catalog_independence_clusters_v0(requested),
581        executor_consumes_plan: false,
582    }
583}
584
585pub fn trace_transform_catalog_model_v0(
586    requested: &[TransformPassKind],
587    ordered_pass_ids: Vec<&'static str>,
588) -> TransformCatalogModelTraceV0 {
589    let input_pass_ids = requested.iter().map(|kind| kind.id()).collect::<Vec<_>>();
590    TransformCatalogModelTraceV0 {
591        schema_version: "0",
592        product: "omena-lawvere.model-trace",
593        layer_marker: "enriched-algebraic",
594        feature_gate: "transform-catalog-saturation",
595        mechanism_scope: TRANSFORM_CATALOG_MECHANISM_SCOPE_V0,
596        product_path_evidence_ready: TRANSFORM_CATALOG_PRODUCT_PATH_EVIDENCE_READY_V0,
597        global_transform_theorem_claimed: TRANSFORM_CATALOG_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0,
598        theory_version: TRANSFORM_CATALOG_SCHEMA_VERSION_V0,
599        rank_clusters: transform_catalog_independence_clusters_from_pass_ids_v0(
600            ordered_pass_ids.as_slice(),
601        ),
602        input_pass_ids,
603        terminal_pass_ids: terminal_pass_ids_from_pass_ids(ordered_pass_ids.as_slice()),
604        ordered_pass_ids,
605        preserves_existing_executor_signature: true,
606    }
607}
608
609pub fn transform_catalog_reorderability_certificate_v0(
610    left: TransformPassKind,
611    right: TransformPassKind,
612) -> ReorderabilityCertificateV0 {
613    let issuance_token = default_transform_catalog_independence_data_v0()
614        .ok()
615        .and_then(|data| checked_adjacent_swap_token_v0(left, right, &data).ok());
616    let accepted = issuance_token.is_some();
617    ReorderabilityCertificateV0 {
618        schema_version: "0",
619        product: "omena-lawvere.reorderability-certificate",
620        layer_marker: "enriched-algebraic",
621        feature_gate: "transform-catalog-saturation",
622        mechanism_scope: TRANSFORM_CATALOG_MECHANISM_SCOPE_V0,
623        product_path_evidence_ready: TRANSFORM_CATALOG_PRODUCT_PATH_EVIDENCE_READY_V0,
624        global_transform_theorem_claimed: TRANSFORM_CATALOG_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0,
625        left_pass_id: left.id(),
626        right_pass_id: right.id(),
627        theory_version: TRANSFORM_CATALOG_SCHEMA_VERSION_V0,
628        differential_tier: budget_tier_for_cluster_size(2),
629        commute_witness: if accepted {
630            "checkedRewriteCertificate"
631        } else {
632            "requiresCheckedIndependenceCertificate"
633        },
634        differential_fixture_count: 0,
635        differential_equal_fixture_count: 0,
636        differential_mismatch_count: 0,
637        specificity_preserved: accepted,
638        obligation_family: ObligationFamilyIdV0::from_computed_value_preservation(accepted),
639        issuance_token,
640        computed_value_preserved: accepted,
641        provenance_preserved: accepted,
642        cascade_safe_witness: format!(
643            "{}:{}",
644            cascade_safe_obligation(left),
645            cascade_safe_obligation(right)
646        ),
647        accepted,
648    }
649}
650
651pub fn transform_catalog_differential_commutativity_witness_v0(
652    left: TransformPassKind,
653    right: TransformPassKind,
654    cases: Vec<TransformCatalogDifferentialCommutativityCaseV0>,
655) -> TransformCatalogDifferentialCommutativityWitnessV0 {
656    let fixture_count = cases.len();
657    let equal_fixture_count = cases.iter().filter(|case| case.equal_output).count();
658    let mismatch_count = fixture_count.saturating_sub(equal_fixture_count);
659
660    TransformCatalogDifferentialCommutativityWitnessV0 {
661        schema_version: "0",
662        product: "omena-lawvere.differential-commutativity-witness",
663        layer_marker: "enriched-algebraic",
664        feature_gate: "transform-catalog-saturation",
665        mechanism_scope: TRANSFORM_CATALOG_MECHANISM_SCOPE_V0,
666        product_path_evidence_ready: TRANSFORM_CATALOG_PRODUCT_PATH_EVIDENCE_READY_V0,
667        global_transform_theorem_claimed: TRANSFORM_CATALOG_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0,
668        theory_version: TRANSFORM_CATALOG_SCHEMA_VERSION_V0,
669        left_pass_id: left.id(),
670        right_pass_id: right.id(),
671        fixture_count,
672        equal_fixture_count,
673        mismatch_count,
674        cases,
675        accepted: fixture_count > 0 && mismatch_count == 0,
676    }
677}
678
679pub fn transform_catalog_reorderability_certificate_from_differential_v0(
680    left: TransformPassKind,
681    right: TransformPassKind,
682    witness: &TransformCatalogDifferentialCommutativityWitnessV0,
683) -> ReorderabilityCertificateV0 {
684    let mut certificate = transform_catalog_reorderability_certificate_v0(left, right);
685    certificate.commute_witness = if certificate.accepted {
686        "checkedRewriteCertificateWithDifferentialSearch"
687    } else {
688        "requiresCheckedIndependenceCertificate"
689    };
690    certificate.differential_fixture_count = witness.fixture_count;
691    certificate.differential_equal_fixture_count = witness.equal_fixture_count;
692    certificate.differential_mismatch_count = witness.mismatch_count;
693    certificate.accepted &= witness.accepted;
694    certificate.specificity_preserved = certificate.accepted;
695    certificate.obligation_family =
696        ObligationFamilyIdV0::from_computed_value_preservation(certificate.accepted);
697    certificate.computed_value_preserved = certificate.obligation_family.preserves_computed_value();
698    certificate.provenance_preserved = certificate.accepted;
699    certificate
700}
701
702fn legacy_transform_catalog_reorderability_certificate_v0(
703    left: TransformPassKind,
704    right: TransformPassKind,
705) -> ReorderabilityCertificateV0 {
706    ReorderabilityCertificateV0 {
707        schema_version: "0",
708        product: "omena-lawvere.reorderability-certificate",
709        layer_marker: "enriched-algebraic",
710        feature_gate: "transform-catalog-saturation",
711        mechanism_scope: TRANSFORM_CATALOG_MECHANISM_SCOPE_V0,
712        product_path_evidence_ready: TRANSFORM_CATALOG_PRODUCT_PATH_EVIDENCE_READY_V0,
713        global_transform_theorem_claimed: TRANSFORM_CATALOG_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0,
714        left_pass_id: left.id(),
715        right_pass_id: right.id(),
716        theory_version: TRANSFORM_CATALOG_SCHEMA_VERSION_V0,
717        differential_tier: budget_tier_for_cluster_size(2),
718        commute_witness: "requiresDifferentialCommutativityWitness",
719        differential_fixture_count: 0,
720        differential_equal_fixture_count: 0,
721        differential_mismatch_count: 0,
722        specificity_preserved: false,
723        obligation_family: ObligationFamilyIdV0::CascadeSafetyFloor,
724        issuance_token: None,
725        computed_value_preserved: ObligationFamilyIdV0::CascadeSafetyFloor
726            .preserves_computed_value(),
727        provenance_preserved: false,
728        cascade_safe_witness: format!(
729            "{}:{}",
730            cascade_safe_obligation(left),
731            cascade_safe_obligation(right)
732        ),
733        accepted: false,
734    }
735}
736
737fn legacy_transform_catalog_reorderability_certificate_from_differential_v0(
738    left: TransformPassKind,
739    right: TransformPassKind,
740    witness: &TransformCatalogDifferentialCommutativityWitnessV0,
741) -> ReorderabilityCertificateV0 {
742    let mut certificate = legacy_transform_catalog_reorderability_certificate_v0(left, right);
743    certificate.commute_witness = "differentialCommutativityCorpus";
744    certificate.differential_fixture_count = witness.fixture_count;
745    certificate.differential_equal_fixture_count = witness.equal_fixture_count;
746    certificate.differential_mismatch_count = witness.mismatch_count;
747    certificate.specificity_preserved = witness.accepted;
748    certificate.obligation_family =
749        ObligationFamilyIdV0::from_computed_value_preservation(witness.accepted);
750    certificate.computed_value_preserved = certificate.obligation_family.preserves_computed_value();
751    certificate.provenance_preserved = witness.accepted;
752    certificate.accepted = witness.accepted;
753    certificate
754}
755
756pub fn transform_catalog_differential_corpus_tiers_v0()
757-> Vec<TransformCatalogDifferentialCorpusTierV0> {
758    [
759        SaturationBudgetTierV0::Minimal,
760        SaturationBudgetTierV0::Half,
761        SaturationBudgetTierV0::Full,
762    ]
763    .into_iter()
764    .map(|tier| TransformCatalogDifferentialCorpusTierV0 {
765        schema_version: "0",
766        product: "omena-lawvere.differential-corpus-tier",
767        layer_marker: "enriched-algebraic",
768        feature_gate: "transform-catalog-saturation",
769        theory_version: TRANSFORM_CATALOG_SCHEMA_VERSION_V0,
770        tier,
771        tier_label: tier.label(),
772        fixture_count: tier.fixture_count(),
773        required_pass_rate_percent: 100,
774    })
775    .collect()
776}
777
778pub fn summarize_transform_catalog_saturation_execution_v0(
779    pass_id: &'static str,
780    iteration_limit: usize,
781    iteration_count: usize,
782    eclass_count: usize,
783    enode_count: usize,
784    extracted_matches_candidate: bool,
785) -> TransformCatalogSaturationExecutionV0 {
786    TransformCatalogSaturationExecutionV0 {
787        schema_version: "0",
788        product: "omena-lawvere.saturation-execution",
789        layer_marker: "enriched-algebraic",
790        feature_gate: "transform-catalog-saturation",
791        mechanism_scope: TRANSFORM_CATALOG_MECHANISM_SCOPE_V0,
792        product_path_evidence_ready: TRANSFORM_CATALOG_PRODUCT_PATH_EVIDENCE_READY_V0,
793        global_transform_theorem_claimed: TRANSFORM_CATALOG_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0,
794        theory_version: TRANSFORM_CATALOG_SCHEMA_VERSION_V0,
795        pass_id,
796        analysis_slot: "TransformCatalogAnalysis",
797        original_unit_analysis_path_preserved: true,
798        differential_tier: SaturationBudgetTierV0::Minimal,
799        differential_fixture_count: SaturationBudgetTierV0::Minimal.fixture_count(),
800        iteration_limit,
801        iteration_count,
802        eclass_count,
803        enode_count,
804        accepted: extracted_matches_candidate,
805        extracted_matches_candidate,
806    }
807}
808
809pub const fn transform_catalog_execution_rank_hint(kind: TransformPassKind) -> u8 {
810    // Mirrors the planner promote pattern (omena-transform-passes runtime::planner
811    // execution_rank), keyed by catalog ordinal: target-lowering + static-eval
812    // (14..=25) plus the appended relative-color/@container passes (42/43) cluster
813    // together; print-css (41) is the terminal emission rank.
814    match kind.ordinal() {
815        27..=29 => 10,
816        30..=40 => 20,
817        14..=25 | 42 | 43 => 30,
818        8..=13 | 26 => 40,
819        1..=7 => 50,
820        41 => 60,
821        _ => 70,
822    }
823}
824
825pub const fn transform_catalog_catalog_role_v0(kind: TransformPassKind) -> TransformCatalogRoleV0 {
826    match kind {
827        TransformPassKind::PrintCss => TransformCatalogRoleV0::TerminalForgetfulFunctor,
828        _ => TransformCatalogRoleV0::Generator,
829    }
830}
831
832fn transform_catalog_generator_count_v0(
833    generators: &[TransformCatalogGeneratorMetadataV0],
834) -> usize {
835    generators
836        .iter()
837        .filter(|generator| generator.catalog_role == TransformCatalogRoleV0::Generator)
838        .count()
839}
840
841fn terminal_pass_ids_from_pass_kinds(requested: &[TransformPassKind]) -> Vec<&'static str> {
842    requested
843        .iter()
844        .filter(|kind| {
845            transform_catalog_catalog_role_v0(**kind)
846                == TransformCatalogRoleV0::TerminalForgetfulFunctor
847        })
848        .map(|kind| kind.id())
849        .collect()
850}
851
852fn terminal_pass_ids_from_pass_ids(pass_ids: &[&'static str]) -> Vec<&'static str> {
853    all_transform_pass_kinds()
854        .into_iter()
855        .filter(|kind| {
856            transform_catalog_catalog_role_v0(*kind)
857                == TransformCatalogRoleV0::TerminalForgetfulFunctor
858        })
859        .map(|kind| kind.id())
860        .filter(|pass_id| pass_ids.contains(pass_id))
861        .collect()
862}
863
864const fn abstract_domain_tag_for_pass(kind: TransformPassKind) -> AbstractDomainTagV0 {
865    match kind.ordinal() {
866        1..=7 => AbstractDomainTagV0::TokenValue,
867        8..=13 | 25 => AbstractDomainTagV0::SelectorShape,
868        14..=24 => AbstractDomainTagV0::CascadeStructural,
869        26..=39 => AbstractDomainTagV0::SemanticGraph,
870        40 => AbstractDomainTagV0::TerminalEmission,
871        _ => AbstractDomainTagV0::SyntaxTrivia,
872    }
873}
874
875const fn budget_tier_for_cluster_size(size: usize) -> SaturationBudgetTierV0 {
876    if size >= 10 {
877        SaturationBudgetTierV0::Full
878    } else if size >= 4 {
879        SaturationBudgetTierV0::Half
880    } else {
881        SaturationBudgetTierV0::Minimal
882    }
883}
884
885/// Legacy wire values retained only for deprecated pre-1.0 adapters.
886/// Owner: `omena-lawvere` maintainers. Removal is not before 1.0 and requires
887/// downstream migration plus zero audited non-compatibility uses.
888#[deprecated(
889    since = "0.4.0",
890    note = "legacy schema byte; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
891)]
892const LEGACY_TRANSFORM_CATALOG_SCHEMA_VERSION_V0: &str = "lawvere-css-transform-catalog-v0";
893
894#[deprecated(
895    since = "0.4.0",
896    note = "legacy feature byte; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
897)]
898const LEGACY_TRANSFORM_CATALOG_FEATURE_GATE_V0: &str = "lawvere-saturation";
899
900#[deprecated(
901    since = "0.4.0",
902    note = "legacy analysis-slot byte; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
903)]
904const LEGACY_TRANSFORM_CATALOG_ANALYSIS_SLOT_V0: &str = "LawvereAnalysis";
905
906#[allow(deprecated)]
907fn restore_legacy_generator_metadata_v0(
908    mut metadata: TransformCatalogGeneratorMetadataV0,
909) -> TransformCatalogGeneratorMetadataV0 {
910    metadata.feature_gate = LEGACY_TRANSFORM_CATALOG_FEATURE_GATE_V0;
911    metadata.theory_version = LEGACY_TRANSFORM_CATALOG_SCHEMA_VERSION_V0;
912    metadata
913}
914
915#[allow(deprecated)]
916fn restore_legacy_equation_cluster_v0(
917    mut cluster: TransformCatalogEquationClusterV0,
918) -> TransformCatalogEquationClusterV0 {
919    cluster.feature_gate = LEGACY_TRANSFORM_CATALOG_FEATURE_GATE_V0;
920    cluster.theory_version = LEGACY_TRANSFORM_CATALOG_SCHEMA_VERSION_V0;
921    cluster
922}
923
924#[allow(deprecated)]
925fn restore_legacy_differential_tier_v0(
926    mut tier: TransformCatalogDifferentialCorpusTierV0,
927) -> TransformCatalogDifferentialCorpusTierV0 {
928    tier.feature_gate = LEGACY_TRANSFORM_CATALOG_FEATURE_GATE_V0;
929    tier.theory_version = LEGACY_TRANSFORM_CATALOG_SCHEMA_VERSION_V0;
930    tier
931}
932
933#[allow(deprecated)]
934fn restore_legacy_metadata_summary_v0(
935    mut summary: TransformCatalogMetadataSummaryV0,
936) -> TransformCatalogMetadataSummaryV0 {
937    summary.feature_gate = LEGACY_TRANSFORM_CATALOG_FEATURE_GATE_V0;
938    summary.theory_version = LEGACY_TRANSFORM_CATALOG_SCHEMA_VERSION_V0;
939    summary.generators = summary
940        .generators
941        .into_iter()
942        .map(restore_legacy_generator_metadata_v0)
943        .collect();
944    summary.equation_clusters = summary
945        .equation_clusters
946        .into_iter()
947        .map(restore_legacy_equation_cluster_v0)
948        .collect();
949    summary.differential_corpus_tiers = summary
950        .differential_corpus_tiers
951        .into_iter()
952        .map(restore_legacy_differential_tier_v0)
953        .collect();
954    summary
955}
956
957#[allow(deprecated)]
958fn restore_legacy_parallel_plan_v0(
959    mut plan: TransformCatalogTransformPassParallelPlanV0,
960) -> TransformCatalogTransformPassParallelPlanV0 {
961    plan.feature_gate = LEGACY_TRANSFORM_CATALOG_FEATURE_GATE_V0;
962    plan.rank_clusters = plan
963        .rank_clusters
964        .into_iter()
965        .map(restore_legacy_equation_cluster_v0)
966        .collect();
967    plan
968}
969
970#[allow(deprecated)]
971fn restore_legacy_model_trace_v0(
972    mut trace: TransformCatalogModelTraceV0,
973) -> TransformCatalogModelTraceV0 {
974    trace.feature_gate = LEGACY_TRANSFORM_CATALOG_FEATURE_GATE_V0;
975    trace.theory_version = LEGACY_TRANSFORM_CATALOG_SCHEMA_VERSION_V0;
976    trace.rank_clusters = trace
977        .rank_clusters
978        .into_iter()
979        .map(restore_legacy_equation_cluster_v0)
980        .collect();
981    trace
982}
983
984#[allow(deprecated)]
985fn restore_legacy_reorderability_certificate_v0(
986    mut certificate: ReorderabilityCertificateV0,
987) -> ReorderabilityCertificateV0 {
988    certificate.feature_gate = LEGACY_TRANSFORM_CATALOG_FEATURE_GATE_V0;
989    certificate.theory_version = LEGACY_TRANSFORM_CATALOG_SCHEMA_VERSION_V0;
990    certificate
991}
992
993#[allow(deprecated)]
994fn restore_legacy_differential_witness_v0(
995    mut witness: TransformCatalogDifferentialCommutativityWitnessV0,
996) -> TransformCatalogDifferentialCommutativityWitnessV0 {
997    witness.feature_gate = LEGACY_TRANSFORM_CATALOG_FEATURE_GATE_V0;
998    witness.theory_version = LEGACY_TRANSFORM_CATALOG_SCHEMA_VERSION_V0;
999    witness
1000}
1001
1002#[allow(deprecated)]
1003fn restore_legacy_saturation_execution_v0(
1004    mut execution: TransformCatalogSaturationExecutionV0,
1005) -> TransformCatalogSaturationExecutionV0 {
1006    execution.feature_gate = LEGACY_TRANSFORM_CATALOG_FEATURE_GATE_V0;
1007    execution.theory_version = LEGACY_TRANSFORM_CATALOG_SCHEMA_VERSION_V0;
1008    execution.analysis_slot = LEGACY_TRANSFORM_CATALOG_ANALYSIS_SLOT_V0;
1009    execution
1010}
1011
1012/// Pre-1.0 nominal compatibility role.
1013/// Owner: `omena-lawvere` maintainers. Removal condition: not before 1.0,
1014/// after downstream migration and zero audited in-repo non-compatibility uses.
1015#[deprecated(
1016    since = "0.4.0",
1017    note = "use TransformCatalogRoleV0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1018)]
1019#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize)]
1020#[serde(rename_all = "camelCase")]
1021pub enum LawvereCatalogRoleV0 {
1022    Generator,
1023    TerminalForgetfulFunctor,
1024}
1025
1026#[deprecated(
1027    since = "0.4.0",
1028    note = "use TransformCatalogGeneratorMetadataV0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1029)]
1030#[allow(deprecated)]
1031#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1032#[serde(rename_all = "camelCase")]
1033pub struct LawvereGeneratorMetadataV0 {
1034    pub schema_version: &'static str,
1035    pub product: &'static str,
1036    pub layer_marker: &'static str,
1037    pub feature_gate: &'static str,
1038    pub theory_version: &'static str,
1039    pub pass_id: &'static str,
1040    pub ordinal: u8,
1041    pub title: &'static str,
1042    pub catalog_role: LawvereCatalogRoleV0,
1043    pub abstract_domain_tag: AbstractDomainTagV0,
1044    pub execution_rank_hint: u32,
1045    pub terminal_forgetful_functor: bool,
1046    pub reads_fixed_point: bool,
1047}
1048
1049#[deprecated(
1050    since = "0.4.0",
1051    note = "use TransformCatalogEquationClusterV0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1052)]
1053#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1054#[serde(rename_all = "camelCase")]
1055pub struct LawvereEquationClusterV0 {
1056    pub schema_version: &'static str,
1057    pub product: &'static str,
1058    pub layer_marker: &'static str,
1059    pub feature_gate: &'static str,
1060    pub execution_rank_hint: u32,
1061    pub pass_ids: Vec<&'static str>,
1062    pub generator_count: usize,
1063    pub saturation_budget_tier: SaturationBudgetTierV0,
1064    pub theory_version: &'static str,
1065}
1066
1067#[deprecated(
1068    since = "0.4.0",
1069    note = "use TransformCatalogDifferentialCorpusTierV0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1070)]
1071#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1072#[serde(rename_all = "camelCase")]
1073pub struct LawvereDifferentialCorpusTierV0 {
1074    pub schema_version: &'static str,
1075    pub product: &'static str,
1076    pub layer_marker: &'static str,
1077    pub feature_gate: &'static str,
1078    pub theory_version: &'static str,
1079    pub tier: SaturationBudgetTierV0,
1080    pub tier_label: &'static str,
1081    pub fixture_count: usize,
1082    pub required_pass_rate_percent: u8,
1083}
1084
1085#[deprecated(
1086    since = "0.4.0",
1087    note = "use TransformCatalogDifferentialCommutativityCaseV0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1088)]
1089#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1090#[serde(rename_all = "camelCase")]
1091pub struct LawvereDifferentialCommutativityCaseV0 {
1092    pub label: String,
1093    pub input_css: String,
1094    pub left_then_right_css: String,
1095    pub right_then_left_css: String,
1096    pub left_then_right_mutation_count: usize,
1097    pub right_then_left_mutation_count: usize,
1098    pub equal_output: bool,
1099}
1100
1101#[deprecated(
1102    since = "0.4.0",
1103    note = "use TransformCatalogDifferentialCommutativityWitnessV0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1104)]
1105#[allow(deprecated)]
1106#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1107#[serde(rename_all = "camelCase")]
1108pub struct LawvereDifferentialCommutativityWitnessV0 {
1109    pub schema_version: &'static str,
1110    pub product: &'static str,
1111    pub layer_marker: &'static str,
1112    pub feature_gate: &'static str,
1113    pub mechanism_scope: &'static str,
1114    pub product_path_evidence_ready: bool,
1115    pub global_transform_theorem_claimed: bool,
1116    pub theory_version: &'static str,
1117    pub left_pass_id: &'static str,
1118    pub right_pass_id: &'static str,
1119    pub fixture_count: usize,
1120    pub equal_fixture_count: usize,
1121    pub mismatch_count: usize,
1122    pub cases: Vec<LawvereDifferentialCommutativityCaseV0>,
1123    pub accepted: bool,
1124}
1125
1126#[deprecated(
1127    since = "0.4.0",
1128    note = "use TransformCatalogTransformPassParallelPlanV0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1129)]
1130#[allow(deprecated)]
1131#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1132#[serde(rename_all = "camelCase")]
1133pub struct TransformPassParallelPlanV0 {
1134    pub schema_version: &'static str,
1135    pub product: &'static str,
1136    pub layer_marker: &'static str,
1137    pub feature_gate: &'static str,
1138    pub mechanism_scope: &'static str,
1139    pub product_path_evidence_ready: bool,
1140    pub global_transform_theorem_claimed: bool,
1141    pub scheduler_status: &'static str,
1142    pub requested_pass_ids: Vec<&'static str>,
1143    pub terminal_pass_ids: Vec<&'static str>,
1144    pub rank_clusters: Vec<LawvereEquationClusterV0>,
1145    pub executor_consumes_plan: bool,
1146}
1147
1148#[deprecated(
1149    since = "0.4.0",
1150    note = "use TransformCatalogModelTraceV0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1151)]
1152#[allow(deprecated)]
1153#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1154#[serde(rename_all = "camelCase")]
1155pub struct LawvereModelTraceV0 {
1156    pub schema_version: &'static str,
1157    pub product: &'static str,
1158    pub layer_marker: &'static str,
1159    pub feature_gate: &'static str,
1160    pub mechanism_scope: &'static str,
1161    pub product_path_evidence_ready: bool,
1162    pub global_transform_theorem_claimed: bool,
1163    pub theory_version: &'static str,
1164    pub input_pass_ids: Vec<&'static str>,
1165    pub ordered_pass_ids: Vec<&'static str>,
1166    pub terminal_pass_ids: Vec<&'static str>,
1167    pub rank_clusters: Vec<LawvereEquationClusterV0>,
1168    pub preserves_existing_executor_signature: bool,
1169}
1170
1171#[deprecated(
1172    since = "0.4.0",
1173    note = "use TransformCatalogSaturationExecutionV0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1174)]
1175#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1176#[serde(rename_all = "camelCase")]
1177pub struct LawvereSaturationExecutionV0 {
1178    pub schema_version: &'static str,
1179    pub product: &'static str,
1180    pub layer_marker: &'static str,
1181    pub feature_gate: &'static str,
1182    pub mechanism_scope: &'static str,
1183    pub product_path_evidence_ready: bool,
1184    pub global_transform_theorem_claimed: bool,
1185    pub theory_version: &'static str,
1186    pub pass_id: &'static str,
1187    pub analysis_slot: &'static str,
1188    pub original_unit_analysis_path_preserved: bool,
1189    pub differential_tier: SaturationBudgetTierV0,
1190    pub differential_fixture_count: usize,
1191    pub iteration_limit: usize,
1192    pub iteration_count: usize,
1193    pub eclass_count: usize,
1194    pub enode_count: usize,
1195    pub accepted: bool,
1196    pub extracted_matches_candidate: bool,
1197}
1198
1199#[deprecated(
1200    since = "0.4.0",
1201    note = "use TransformCatalogMetadataSummaryV0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1202)]
1203#[allow(deprecated)]
1204#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
1205#[serde(rename_all = "camelCase")]
1206pub struct LawvereTheorySummaryV0 {
1207    pub schema_version: &'static str,
1208    pub product: &'static str,
1209    pub layer_marker: &'static str,
1210    pub feature_gate: &'static str,
1211    pub theory_version: &'static str,
1212    pub catalog_pass_count: usize,
1213    pub catalog_entry_count: usize,
1214    pub lawvere_generator_count: usize,
1215    pub terminal_forgetful_functor_count: usize,
1216    pub execution_rank_cluster_count: usize,
1217    pub equation_clusters: Vec<LawvereEquationClusterV0>,
1218    pub generators: Vec<LawvereGeneratorMetadataV0>,
1219    pub dag_edges: Vec<TransformDagEdgeV0>,
1220    pub saturation_budget_tiers: Vec<SaturationBudgetTierV0>,
1221    pub differential_corpus_tiers: Vec<LawvereDifferentialCorpusTierV0>,
1222    pub lawvere_saturation_feature_enabled_by_default: bool,
1223    pub product_path_evidence_ready: bool,
1224    pub mechanism_scope: &'static str,
1225    pub omena_categorical_dependency_forbidden: bool,
1226}
1227
1228#[deprecated(
1229    since = "0.4.0",
1230    note = "use TRANSFORM_CATALOG_MECHANISM_SCOPE_V0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1231)]
1232pub const LAWVERE_MECHANISM_SCOPE_V0: &str = "featureGatedDifferentialWitnessSubstrate";
1233#[deprecated(
1234    since = "0.4.0",
1235    note = "use TRANSFORM_CATALOG_PRODUCT_PATH_EVIDENCE_READY_V0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1236)]
1237pub const LAWVERE_PRODUCT_PATH_EVIDENCE_READY_V0: bool = false;
1238#[deprecated(
1239    since = "0.4.0",
1240    note = "use TRANSFORM_CATALOG_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1241)]
1242pub const LAWVERE_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0: bool = false;
1243
1244#[allow(deprecated)]
1245#[deprecated(
1246    since = "0.4.0",
1247    note = "nominal compatibility conversion owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1248)]
1249const fn into_lawvere_catalog_role_v0(role: TransformCatalogRoleV0) -> LawvereCatalogRoleV0 {
1250    match role {
1251        TransformCatalogRoleV0::Generator => LawvereCatalogRoleV0::Generator,
1252        TransformCatalogRoleV0::TerminalForgetfulFunctor => {
1253            LawvereCatalogRoleV0::TerminalForgetfulFunctor
1254        }
1255    }
1256}
1257
1258#[allow(deprecated)]
1259#[deprecated(
1260    since = "0.4.0",
1261    note = "nominal compatibility conversion owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1262)]
1263fn into_lawvere_generator_metadata_v0(
1264    metadata: TransformCatalogGeneratorMetadataV0,
1265) -> LawvereGeneratorMetadataV0 {
1266    LawvereGeneratorMetadataV0 {
1267        schema_version: metadata.schema_version,
1268        product: metadata.product,
1269        layer_marker: metadata.layer_marker,
1270        feature_gate: metadata.feature_gate,
1271        theory_version: metadata.theory_version,
1272        pass_id: metadata.pass_id,
1273        ordinal: metadata.ordinal,
1274        title: metadata.title,
1275        catalog_role: into_lawvere_catalog_role_v0(metadata.catalog_role),
1276        abstract_domain_tag: metadata.abstract_domain_tag,
1277        execution_rank_hint: metadata.execution_rank_hint,
1278        terminal_forgetful_functor: metadata.terminal_forgetful_functor,
1279        reads_fixed_point: metadata.reads_fixed_point,
1280    }
1281}
1282
1283#[allow(deprecated)]
1284#[deprecated(
1285    since = "0.4.0",
1286    note = "nominal compatibility conversion owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1287)]
1288fn into_lawvere_equation_cluster_v0(
1289    cluster: TransformCatalogEquationClusterV0,
1290) -> LawvereEquationClusterV0 {
1291    LawvereEquationClusterV0 {
1292        schema_version: cluster.schema_version,
1293        product: cluster.product,
1294        layer_marker: cluster.layer_marker,
1295        feature_gate: cluster.feature_gate,
1296        execution_rank_hint: cluster.execution_rank_hint,
1297        pass_ids: cluster.pass_ids,
1298        generator_count: cluster.generator_count,
1299        saturation_budget_tier: cluster.saturation_budget_tier,
1300        theory_version: cluster.theory_version,
1301    }
1302}
1303
1304#[allow(deprecated)]
1305#[deprecated(
1306    since = "0.4.0",
1307    note = "nominal compatibility conversion owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1308)]
1309fn into_lawvere_differential_tier_v0(
1310    tier: TransformCatalogDifferentialCorpusTierV0,
1311) -> LawvereDifferentialCorpusTierV0 {
1312    LawvereDifferentialCorpusTierV0 {
1313        schema_version: tier.schema_version,
1314        product: tier.product,
1315        layer_marker: tier.layer_marker,
1316        feature_gate: tier.feature_gate,
1317        theory_version: tier.theory_version,
1318        tier: tier.tier,
1319        tier_label: tier.tier_label,
1320        fixture_count: tier.fixture_count,
1321        required_pass_rate_percent: tier.required_pass_rate_percent,
1322    }
1323}
1324
1325#[allow(deprecated)]
1326#[deprecated(
1327    since = "0.4.0",
1328    note = "nominal compatibility conversion owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1329)]
1330fn into_lawvere_case_v0(
1331    case: TransformCatalogDifferentialCommutativityCaseV0,
1332) -> LawvereDifferentialCommutativityCaseV0 {
1333    LawvereDifferentialCommutativityCaseV0 {
1334        label: case.label,
1335        input_css: case.input_css,
1336        left_then_right_css: case.left_then_right_css,
1337        right_then_left_css: case.right_then_left_css,
1338        left_then_right_mutation_count: case.left_then_right_mutation_count,
1339        right_then_left_mutation_count: case.right_then_left_mutation_count,
1340        equal_output: case.equal_output,
1341    }
1342}
1343
1344#[allow(deprecated)]
1345#[deprecated(
1346    since = "0.4.0",
1347    note = "nominal compatibility conversion owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1348)]
1349fn from_lawvere_case_v0(
1350    case: LawvereDifferentialCommutativityCaseV0,
1351) -> TransformCatalogDifferentialCommutativityCaseV0 {
1352    TransformCatalogDifferentialCommutativityCaseV0 {
1353        label: case.label,
1354        input_css: case.input_css,
1355        left_then_right_css: case.left_then_right_css,
1356        right_then_left_css: case.right_then_left_css,
1357        left_then_right_mutation_count: case.left_then_right_mutation_count,
1358        right_then_left_mutation_count: case.right_then_left_mutation_count,
1359        equal_output: case.equal_output,
1360    }
1361}
1362
1363#[allow(deprecated)]
1364#[deprecated(
1365    since = "0.4.0",
1366    note = "nominal compatibility conversion owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1367)]
1368fn into_lawvere_witness_v0(
1369    witness: TransformCatalogDifferentialCommutativityWitnessV0,
1370) -> LawvereDifferentialCommutativityWitnessV0 {
1371    LawvereDifferentialCommutativityWitnessV0 {
1372        schema_version: witness.schema_version,
1373        product: witness.product,
1374        layer_marker: witness.layer_marker,
1375        feature_gate: witness.feature_gate,
1376        mechanism_scope: witness.mechanism_scope,
1377        product_path_evidence_ready: witness.product_path_evidence_ready,
1378        global_transform_theorem_claimed: witness.global_transform_theorem_claimed,
1379        theory_version: witness.theory_version,
1380        left_pass_id: witness.left_pass_id,
1381        right_pass_id: witness.right_pass_id,
1382        fixture_count: witness.fixture_count,
1383        equal_fixture_count: witness.equal_fixture_count,
1384        mismatch_count: witness.mismatch_count,
1385        cases: witness
1386            .cases
1387            .into_iter()
1388            .map(into_lawvere_case_v0)
1389            .collect(),
1390        accepted: witness.accepted,
1391    }
1392}
1393
1394#[allow(deprecated)]
1395#[deprecated(
1396    since = "0.4.0",
1397    note = "nominal compatibility conversion owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1398)]
1399fn from_lawvere_witness_v0(
1400    witness: LawvereDifferentialCommutativityWitnessV0,
1401) -> TransformCatalogDifferentialCommutativityWitnessV0 {
1402    TransformCatalogDifferentialCommutativityWitnessV0 {
1403        schema_version: witness.schema_version,
1404        product: witness.product,
1405        layer_marker: witness.layer_marker,
1406        feature_gate: witness.feature_gate,
1407        mechanism_scope: witness.mechanism_scope,
1408        product_path_evidence_ready: witness.product_path_evidence_ready,
1409        global_transform_theorem_claimed: witness.global_transform_theorem_claimed,
1410        theory_version: witness.theory_version,
1411        left_pass_id: witness.left_pass_id,
1412        right_pass_id: witness.right_pass_id,
1413        fixture_count: witness.fixture_count,
1414        equal_fixture_count: witness.equal_fixture_count,
1415        mismatch_count: witness.mismatch_count,
1416        cases: witness
1417            .cases
1418            .into_iter()
1419            .map(from_lawvere_case_v0)
1420            .collect(),
1421        accepted: witness.accepted,
1422    }
1423}
1424
1425#[allow(deprecated)]
1426#[deprecated(
1427    since = "0.4.0",
1428    note = "nominal compatibility conversion owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1429)]
1430fn into_transform_pass_parallel_plan_v0(
1431    plan: TransformCatalogTransformPassParallelPlanV0,
1432) -> TransformPassParallelPlanV0 {
1433    TransformPassParallelPlanV0 {
1434        schema_version: plan.schema_version,
1435        product: plan.product,
1436        layer_marker: plan.layer_marker,
1437        feature_gate: plan.feature_gate,
1438        mechanism_scope: plan.mechanism_scope,
1439        product_path_evidence_ready: plan.product_path_evidence_ready,
1440        global_transform_theorem_claimed: plan.global_transform_theorem_claimed,
1441        scheduler_status: plan.scheduler_status,
1442        requested_pass_ids: plan.requested_pass_ids,
1443        terminal_pass_ids: plan.terminal_pass_ids,
1444        rank_clusters: plan
1445            .rank_clusters
1446            .into_iter()
1447            .map(into_lawvere_equation_cluster_v0)
1448            .collect(),
1449        executor_consumes_plan: plan.executor_consumes_plan,
1450    }
1451}
1452
1453#[allow(deprecated)]
1454#[deprecated(
1455    since = "0.4.0",
1456    note = "nominal compatibility conversion owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1457)]
1458fn into_lawvere_model_trace_v0(trace: TransformCatalogModelTraceV0) -> LawvereModelTraceV0 {
1459    LawvereModelTraceV0 {
1460        schema_version: trace.schema_version,
1461        product: trace.product,
1462        layer_marker: trace.layer_marker,
1463        feature_gate: trace.feature_gate,
1464        mechanism_scope: trace.mechanism_scope,
1465        product_path_evidence_ready: trace.product_path_evidence_ready,
1466        global_transform_theorem_claimed: trace.global_transform_theorem_claimed,
1467        theory_version: trace.theory_version,
1468        input_pass_ids: trace.input_pass_ids,
1469        ordered_pass_ids: trace.ordered_pass_ids,
1470        terminal_pass_ids: trace.terminal_pass_ids,
1471        rank_clusters: trace
1472            .rank_clusters
1473            .into_iter()
1474            .map(into_lawvere_equation_cluster_v0)
1475            .collect(),
1476        preserves_existing_executor_signature: trace.preserves_existing_executor_signature,
1477    }
1478}
1479
1480#[allow(deprecated)]
1481#[deprecated(
1482    since = "0.4.0",
1483    note = "nominal compatibility conversion owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1484)]
1485fn into_lawvere_saturation_execution_v0(
1486    execution: TransformCatalogSaturationExecutionV0,
1487) -> LawvereSaturationExecutionV0 {
1488    LawvereSaturationExecutionV0 {
1489        schema_version: execution.schema_version,
1490        product: execution.product,
1491        layer_marker: execution.layer_marker,
1492        feature_gate: execution.feature_gate,
1493        mechanism_scope: execution.mechanism_scope,
1494        product_path_evidence_ready: execution.product_path_evidence_ready,
1495        global_transform_theorem_claimed: execution.global_transform_theorem_claimed,
1496        theory_version: execution.theory_version,
1497        pass_id: execution.pass_id,
1498        analysis_slot: execution.analysis_slot,
1499        original_unit_analysis_path_preserved: execution.original_unit_analysis_path_preserved,
1500        differential_tier: execution.differential_tier,
1501        differential_fixture_count: execution.differential_fixture_count,
1502        iteration_limit: execution.iteration_limit,
1503        iteration_count: execution.iteration_count,
1504        eclass_count: execution.eclass_count,
1505        enode_count: execution.enode_count,
1506        accepted: execution.accepted,
1507        extracted_matches_candidate: execution.extracted_matches_candidate,
1508    }
1509}
1510
1511#[allow(deprecated)]
1512#[deprecated(
1513    since = "0.4.0",
1514    note = "nominal compatibility conversion owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1515)]
1516fn into_lawvere_theory_summary_v0(
1517    summary: TransformCatalogMetadataSummaryV0,
1518) -> LawvereTheorySummaryV0 {
1519    LawvereTheorySummaryV0 {
1520        schema_version: summary.schema_version,
1521        product: summary.product,
1522        layer_marker: summary.layer_marker,
1523        feature_gate: summary.feature_gate,
1524        theory_version: summary.theory_version,
1525        catalog_pass_count: summary.catalog_pass_count,
1526        catalog_entry_count: summary.catalog_entry_count,
1527        lawvere_generator_count: summary.lawvere_generator_count,
1528        terminal_forgetful_functor_count: summary.terminal_forgetful_functor_count,
1529        execution_rank_cluster_count: summary.execution_rank_cluster_count,
1530        equation_clusters: summary
1531            .equation_clusters
1532            .into_iter()
1533            .map(into_lawvere_equation_cluster_v0)
1534            .collect(),
1535        generators: summary
1536            .generators
1537            .into_iter()
1538            .map(into_lawvere_generator_metadata_v0)
1539            .collect(),
1540        dag_edges: summary.dag_edges,
1541        saturation_budget_tiers: summary.saturation_budget_tiers,
1542        differential_corpus_tiers: summary
1543            .differential_corpus_tiers
1544            .into_iter()
1545            .map(into_lawvere_differential_tier_v0)
1546            .collect(),
1547        lawvere_saturation_feature_enabled_by_default: summary
1548            .lawvere_saturation_feature_enabled_by_default,
1549        product_path_evidence_ready: summary.product_path_evidence_ready,
1550        mechanism_scope: summary.mechanism_scope,
1551        omena_categorical_dependency_forbidden: summary.omena_categorical_dependency_forbidden,
1552    }
1553}
1554
1555#[deprecated(
1556    since = "0.4.0",
1557    note = "use TRANSFORM_CATALOG_SCHEMA_VERSION_V0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1558)]
1559#[allow(deprecated)]
1560pub const LAWVERE_THEORY_VERSION_V0: &str = LEGACY_TRANSFORM_CATALOG_SCHEMA_VERSION_V0;
1561
1562#[allow(deprecated)]
1563#[deprecated(
1564    since = "0.4.0",
1565    note = "use summarize_transform_catalog_metadata_v0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1566)]
1567pub fn summarize_lawvere_theory_v0() -> LawvereTheorySummaryV0 {
1568    into_lawvere_theory_summary_v0(restore_legacy_metadata_summary_v0(
1569        summarize_transform_catalog_metadata_v0(),
1570    ))
1571}
1572
1573#[allow(deprecated)]
1574#[deprecated(
1575    since = "0.4.0",
1576    note = "use transform_catalog_generator_metadata_catalog_v0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1577)]
1578pub fn lawvere_generator_metadata_catalog_v0() -> Vec<LawvereGeneratorMetadataV0> {
1579    transform_catalog_generator_metadata_catalog_v0()
1580        .into_iter()
1581        .map(restore_legacy_generator_metadata_v0)
1582        .map(into_lawvere_generator_metadata_v0)
1583        .collect()
1584}
1585
1586#[allow(deprecated)]
1587#[deprecated(
1588    since = "0.4.0",
1589    note = "use transform_catalog_generator_metadata_v0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1590)]
1591pub fn lawvere_generator_metadata_v0(kind: TransformPassKind) -> LawvereGeneratorMetadataV0 {
1592    into_lawvere_generator_metadata_v0(restore_legacy_generator_metadata_v0(
1593        transform_catalog_generator_metadata_v0(kind),
1594    ))
1595}
1596
1597#[allow(deprecated)]
1598#[deprecated(
1599    since = "0.4.0",
1600    note = "use transform_catalog_equation_clusters_v0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1601)]
1602pub fn lawvere_equation_clusters_v0(pass_ids: &[&'static str]) -> Vec<LawvereEquationClusterV0> {
1603    transform_catalog_equation_clusters_v0(pass_ids)
1604        .into_iter()
1605        .map(restore_legacy_equation_cluster_v0)
1606        .map(into_lawvere_equation_cluster_v0)
1607        .collect()
1608}
1609
1610#[allow(deprecated)]
1611#[deprecated(
1612    since = "0.4.0",
1613    note = "use plan_transform_catalog_parallel_layers_v0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1614)]
1615pub fn plan_transform_pass_parallel_layers_v0(
1616    requested: &[TransformPassKind],
1617) -> TransformPassParallelPlanV0 {
1618    into_transform_pass_parallel_plan_v0(restore_legacy_parallel_plan_v0(
1619        legacy_plan_transform_catalog_parallel_layers_v0(requested),
1620    ))
1621}
1622
1623#[allow(deprecated)]
1624#[deprecated(
1625    since = "0.4.0",
1626    note = "use trace_transform_catalog_model_v0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1627)]
1628pub fn trace_lawvere_model_v0(
1629    requested: &[TransformPassKind],
1630    ordered_pass_ids: Vec<&'static str>,
1631) -> LawvereModelTraceV0 {
1632    into_lawvere_model_trace_v0(restore_legacy_model_trace_v0(
1633        legacy_trace_transform_catalog_model_v0(requested, ordered_pass_ids),
1634    ))
1635}
1636
1637#[allow(deprecated)]
1638#[deprecated(
1639    since = "0.4.0",
1640    note = "use transform_catalog_reorderability_certificate_v0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1641)]
1642pub fn reorderability_certificate_v0(
1643    left: TransformPassKind,
1644    right: TransformPassKind,
1645) -> ReorderabilityCertificateV0 {
1646    restore_legacy_reorderability_certificate_v0(
1647        legacy_transform_catalog_reorderability_certificate_v0(left, right),
1648    )
1649}
1650
1651#[allow(deprecated)]
1652#[deprecated(
1653    since = "0.4.0",
1654    note = "use transform_catalog_differential_commutativity_witness_v0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1655)]
1656pub fn lawvere_differential_commutativity_witness_v0(
1657    left: TransformPassKind,
1658    right: TransformPassKind,
1659    cases: Vec<LawvereDifferentialCommutativityCaseV0>,
1660) -> LawvereDifferentialCommutativityWitnessV0 {
1661    into_lawvere_witness_v0(restore_legacy_differential_witness_v0(
1662        transform_catalog_differential_commutativity_witness_v0(
1663            left,
1664            right,
1665            cases.into_iter().map(from_lawvere_case_v0).collect(),
1666        ),
1667    ))
1668}
1669
1670#[allow(deprecated)]
1671#[deprecated(
1672    since = "0.4.0",
1673    note = "use transform_catalog_reorderability_certificate_from_differential_v0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1674)]
1675pub fn reorderability_certificate_from_differential_v0(
1676    left: TransformPassKind,
1677    right: TransformPassKind,
1678    witness: &LawvereDifferentialCommutativityWitnessV0,
1679) -> ReorderabilityCertificateV0 {
1680    let canonical_witness = from_lawvere_witness_v0(witness.clone());
1681    restore_legacy_reorderability_certificate_v0(
1682        legacy_transform_catalog_reorderability_certificate_from_differential_v0(
1683            left,
1684            right,
1685            &canonical_witness,
1686        ),
1687    )
1688}
1689
1690#[allow(deprecated)]
1691#[deprecated(
1692    since = "0.4.0",
1693    note = "use transform_catalog_differential_corpus_tiers_v0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1694)]
1695pub fn lawvere_differential_corpus_tiers_v0() -> Vec<LawvereDifferentialCorpusTierV0> {
1696    transform_catalog_differential_corpus_tiers_v0()
1697        .into_iter()
1698        .map(restore_legacy_differential_tier_v0)
1699        .map(into_lawvere_differential_tier_v0)
1700        .collect()
1701}
1702
1703#[allow(deprecated)]
1704#[deprecated(
1705    since = "0.4.0",
1706    note = "use summarize_transform_catalog_saturation_execution_v0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1707)]
1708pub fn summarize_lawvere_saturation_execution_v0(
1709    pass_id: &'static str,
1710    iteration_limit: usize,
1711    iteration_count: usize,
1712    eclass_count: usize,
1713    enode_count: usize,
1714    extracted_matches_candidate: bool,
1715) -> LawvereSaturationExecutionV0 {
1716    into_lawvere_saturation_execution_v0(restore_legacy_saturation_execution_v0(
1717        summarize_transform_catalog_saturation_execution_v0(
1718            pass_id,
1719            iteration_limit,
1720            iteration_count,
1721            eclass_count,
1722            enode_count,
1723            extracted_matches_candidate,
1724        ),
1725    ))
1726}
1727
1728#[deprecated(
1729    since = "0.4.0",
1730    note = "use transform_catalog_execution_rank_hint; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1731)]
1732pub const fn lawvere_execution_rank_hint(kind: TransformPassKind) -> u8 {
1733    transform_catalog_execution_rank_hint(kind)
1734}
1735
1736#[deprecated(
1737    since = "0.4.0",
1738    note = "use transform_catalog_catalog_role_v0; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1739)]
1740#[allow(deprecated)]
1741pub const fn lawvere_catalog_role_v0(kind: TransformPassKind) -> LawvereCatalogRoleV0 {
1742    into_lawvere_catalog_role_v0(transform_catalog_catalog_role_v0(kind))
1743}
1744
1745#[cfg(test)]
1746#[deprecated(
1747    since = "0.4.0",
1748    note = "legacy metadata wire fixture owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1749)]
1750const COMPATIBILITY_TRANSFORM_CATALOG_METADATA_EXPECTED_WIRE_V0: &str = r#"{"product":"omena-lawvere.theory-summary","featureGate":"lawvere-saturation","theoryVersion":"lawvere-css-transform-catalog-v0","firstGeneratorFeatureGate":"lawvere-saturation","firstGeneratorTheoryVersion":"lawvere-css-transform-catalog-v0"}"#;
1751
1752#[cfg(test)]
1753#[allow(deprecated)]
1754#[deprecated(
1755    since = "0.4.0",
1756    note = "legacy metadata wire fixture adapter owned by omena-lawvere maintainers; removal is not before 1.0 and requires downstream migration plus zero audited non-compatibility uses"
1757)]
1758fn compatibility_transform_catalog_metadata_serialized_projection_v0()
1759-> Result<String, serde_json::Error> {
1760    let summary = summarize_lawvere_theory_v0();
1761    serde_json::to_string(&serde_json::json!({
1762        "product": summary.product,
1763        "featureGate": summary.feature_gate,
1764        "theoryVersion": summary.theory_version,
1765        "firstGeneratorFeatureGate": summary.generators[0].feature_gate,
1766        "firstGeneratorTheoryVersion": summary.generators[0].theory_version,
1767    }))
1768}
1769
1770#[cfg(test)]
1771mod tests {
1772    use super::*;
1773
1774    #[test]
1775    fn summarizes_forty_pass_transform_catalog_catalog_with_schema_zero() {
1776        let summary = summarize_transform_catalog_metadata_v0();
1777
1778        assert_eq!(summary.schema_version, "0");
1779        assert_eq!(summary.layer_marker, "enriched-algebraic");
1780        assert_eq!(summary.feature_gate, "transform-catalog-saturation");
1781        assert_eq!(summary.catalog_pass_count, TRANSFORM_PASS_CATALOG_LEN);
1782        assert_eq!(summary.catalog_entry_count, TRANSFORM_PASS_CATALOG_LEN);
1783        assert_eq!(
1784            summary.transform_catalog_generator_count(),
1785            TRANSFORM_PASS_CATALOG_LEN - 1
1786        );
1787        assert_eq!(summary.terminal_forgetful_functor_count, 1);
1788        assert_eq!(summary.differential_corpus_tiers.len(), 3);
1789        assert!(summary.differential_corpus_tiers.iter().any(|tier| {
1790            tier.tier == SaturationBudgetTierV0::Minimal && tier.fixture_count == 10
1791        }));
1792        assert!(
1793            summary.differential_corpus_tiers.iter().any(|tier| {
1794                tier.tier == SaturationBudgetTierV0::Half && tier.fixture_count == 50
1795            })
1796        );
1797        assert!(summary.differential_corpus_tiers.iter().any(|tier| {
1798            tier.tier == SaturationBudgetTierV0::Full && tier.fixture_count == 200
1799        }));
1800        assert!(!summary.transform_catalog_saturation_feature_enabled_by_default());
1801        assert_eq!(
1802            summary.product_path_evidence_ready,
1803            TRANSFORM_CATALOG_PRODUCT_PATH_EVIDENCE_READY_V0
1804        );
1805        assert_eq!(
1806            summary.mechanism_scope,
1807            TRANSFORM_CATALOG_MECHANISM_SCOPE_V0
1808        );
1809        assert!(summary.omena_categorical_dependency_forbidden);
1810    }
1811
1812    #[test]
1813    #[allow(deprecated)]
1814    fn compatibility_and_canonical_metadata_keep_distinct_exact_wire_projections()
1815    -> Result<(), serde_json::Error> {
1816        let compatibility = compatibility_transform_catalog_metadata_serialized_projection_v0()?;
1817        assert_eq!(
1818            compatibility,
1819            COMPATIBILITY_TRANSFORM_CATALOG_METADATA_EXPECTED_WIRE_V0
1820        );
1821
1822        let summary = summarize_transform_catalog_metadata_v0();
1823        let canonical = serde_json::to_string(&serde_json::json!({
1824            "product": summary.product,
1825            "featureGate": summary.feature_gate,
1826            "theoryVersion": summary.theory_version,
1827            "firstGeneratorFeatureGate": summary.generators[0].feature_gate,
1828            "firstGeneratorTheoryVersion": summary.generators[0].theory_version,
1829        }))?;
1830        assert_eq!(
1831            canonical,
1832            r#"{"product":"omena-lawvere.theory-summary","featureGate":"transform-catalog-saturation","theoryVersion":"css-transform-catalog-v0","firstGeneratorFeatureGate":"transform-catalog-saturation","firstGeneratorTheoryVersion":"css-transform-catalog-v0"}"#
1833        );
1834        Ok(())
1835    }
1836
1837    #[test]
1838    fn execution_rank_hint_clusters_match_planner_promote_pattern() {
1839        let metadata = transform_catalog_generator_metadata_catalog_v0();
1840
1841        assert_eq!(metadata.len(), TRANSFORM_PASS_CATALOG_LEN);
1842        assert!(metadata.iter().any(|generator| {
1843            generator.pass_id == "css-modules-class-hashing" && generator.execution_rank_hint == 20
1844        }));
1845        assert!(metadata.iter().any(|generator| {
1846            generator.pass_id == "print-css"
1847                && generator.catalog_role == TransformCatalogRoleV0::TerminalForgetfulFunctor
1848                && generator.terminal_forgetful_functor
1849                && generator.execution_rank_hint == 60
1850        }));
1851    }
1852
1853    #[test]
1854    fn parallel_plan_uses_independence_data_and_declares_non_consumption() {
1855        let plan = plan_transform_catalog_parallel_layers_v0(&[
1856            TransformPassKind::ColorCompression,
1857            TransformPassKind::NumberCompression,
1858            TransformPassKind::PrintCss,
1859        ]);
1860
1861        assert_eq!(plan.schema_version, "0");
1862        assert_eq!(plan.scheduler_status, "independenceDataReady");
1863        assert!(!plan.executor_consumes_plan);
1864        assert_eq!(
1865            TRANSFORM_CATALOG_PLAN_NON_CONSUMPTION_REASON_V0,
1866            "executorKeepsValidatedSerialDagUntilParallelApplicationSemanticsLand"
1867        );
1868        assert_eq!(plan.mechanism_scope, TRANSFORM_CATALOG_MECHANISM_SCOPE_V0);
1869        assert_eq!(
1870            plan.product_path_evidence_ready,
1871            TRANSFORM_CATALOG_PRODUCT_PATH_EVIDENCE_READY_V0
1872        );
1873        assert_eq!(
1874            plan.global_transform_theorem_claimed,
1875            TRANSFORM_CATALOG_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0
1876        );
1877        assert_eq!(plan.terminal_pass_ids, vec!["print-css"]);
1878        assert_eq!(plan.rank_clusters.len(), 1);
1879    }
1880
1881    #[test]
1882    #[allow(deprecated)]
1883    fn legacy_plan_and_reorderability_keep_pre_04_runtime_contract() {
1884        let legacy_plan = plan_transform_pass_parallel_layers_v0(&[
1885            TransformPassKind::ColorCompression,
1886            TransformPassKind::NumberCompression,
1887            TransformPassKind::PrintCss,
1888        ]);
1889        assert_eq!(legacy_plan.scheduler_status, "scaffoldOnly");
1890        assert!(!legacy_plan.executor_consumes_plan);
1891        assert_eq!(legacy_plan.rank_clusters.len(), 1);
1892
1893        let legacy_certificate = reorderability_certificate_v0(
1894            TransformPassKind::NumberCompression,
1895            TransformPassKind::ColorCompression,
1896        );
1897        assert_eq!(
1898            legacy_certificate.commute_witness,
1899            "requiresDifferentialCommutativityWitness"
1900        );
1901        assert!(!legacy_certificate.accepted);
1902        assert!(!legacy_certificate.has_checked_issuance_token_v0());
1903    }
1904
1905    #[test]
1906    fn saturation_execution_contract_records_transform_catalog_analysis_slot() {
1907        let execution = summarize_transform_catalog_saturation_execution_v0(
1908            TransformPassKind::CalcReduction.id(),
1909            8,
1910            2,
1911            5,
1912            9,
1913            true,
1914        );
1915
1916        assert_eq!(execution.schema_version, "0");
1917        assert_eq!(execution.layer_marker, "enriched-algebraic");
1918        assert_eq!(execution.feature_gate, "transform-catalog-saturation");
1919        assert_eq!(execution.analysis_slot, "TransformCatalogAnalysis");
1920        assert_eq!(execution.differential_fixture_count, 10);
1921        assert!(execution.original_unit_analysis_path_preserved);
1922        assert_eq!(
1923            execution.mechanism_scope,
1924            TRANSFORM_CATALOG_MECHANISM_SCOPE_V0
1925        );
1926        assert_eq!(
1927            execution.product_path_evidence_ready,
1928            TRANSFORM_CATALOG_PRODUCT_PATH_EVIDENCE_READY_V0
1929        );
1930        assert_eq!(
1931            execution.global_transform_theorem_claimed,
1932            TRANSFORM_CATALOG_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0
1933        );
1934        assert!(execution.accepted);
1935    }
1936
1937    #[test]
1938    fn committed_independent_pair_receives_checked_reorder_token() {
1939        let certificate = transform_catalog_reorderability_certificate_v0(
1940            TransformPassKind::NumberCompression,
1941            TransformPassKind::ColorCompression,
1942        );
1943
1944        assert_eq!(certificate.commute_witness, "checkedRewriteCertificate");
1945        assert_eq!(
1946            certificate.mechanism_scope,
1947            TRANSFORM_CATALOG_MECHANISM_SCOPE_V0
1948        );
1949        assert_eq!(
1950            certificate.product_path_evidence_ready,
1951            TRANSFORM_CATALOG_PRODUCT_PATH_EVIDENCE_READY_V0
1952        );
1953        assert_eq!(
1954            certificate.global_transform_theorem_claimed,
1955            TRANSFORM_CATALOG_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0
1956        );
1957        assert_eq!(certificate.differential_fixture_count, 0);
1958        assert!(certificate.accepted);
1959        assert!(certificate.has_checked_issuance_token_v0());
1960        assert!(certificate.issuance_token_matches_pair_v0(
1961            TransformPassKind::NumberCompression,
1962            TransformPassKind::ColorCompression,
1963        ));
1964    }
1965
1966    #[test]
1967    fn reorderability_certificate_family_derivation_preserves_legacy_json_contract()
1968    -> Result<(), serde_json::Error> {
1969        let rank_only = transform_catalog_reorderability_certificate_v0(
1970            TransformPassKind::NumberCompression,
1971            TransformPassKind::ColorCompression,
1972        );
1973        let rank_only_json = serde_json::to_value(&rank_only)?;
1974        assert_eq!(rank_only_json["computedValuePreserved"], true);
1975        assert!(rank_only_json.get("obligationFamily").is_none());
1976        assert!(rank_only_json.get("issuanceToken").is_none());
1977
1978        let witness = transform_catalog_differential_commutativity_witness_v0(
1979            TransformPassKind::NumberCompression,
1980            TransformPassKind::ColorCompression,
1981            vec![TransformCatalogDifferentialCommutativityCaseV0 {
1982                label: "comment-whitespace".to_string(),
1983                input_css: ".a { color : red ; /* x */ }".to_string(),
1984                left_then_right_css: ".a{color:red}".to_string(),
1985                right_then_left_css: ".a{color:red}".to_string(),
1986                left_then_right_mutation_count: 2,
1987                right_then_left_mutation_count: 2,
1988                equal_output: true,
1989            }],
1990        );
1991        let accepted = transform_catalog_reorderability_certificate_from_differential_v0(
1992            TransformPassKind::NumberCompression,
1993            TransformPassKind::ColorCompression,
1994            &witness,
1995        );
1996        let accepted_json = serde_json::to_value(&accepted)?;
1997
1998        assert_eq!(accepted_json["computedValuePreserved"], true);
1999        assert!(accepted_json.get("obligationFamily").is_none());
2000        assert_eq!(
2001            accepted_json["commuteWitness"],
2002            "checkedRewriteCertificateWithDifferentialSearch"
2003        );
2004
2005        Ok(())
2006    }
2007
2008    #[test]
2009    fn differential_reorderability_certificate_accepts_only_equal_output_corpus() {
2010        let witness = transform_catalog_differential_commutativity_witness_v0(
2011            TransformPassKind::NumberCompression,
2012            TransformPassKind::ColorCompression,
2013            vec![TransformCatalogDifferentialCommutativityCaseV0 {
2014                label: "comment-whitespace".to_string(),
2015                input_css: ".a { color : red ; /* x */ }".to_string(),
2016                left_then_right_css: ".a{color:red}".to_string(),
2017                right_then_left_css: ".a{color:red}".to_string(),
2018                left_then_right_mutation_count: 2,
2019                right_then_left_mutation_count: 2,
2020                equal_output: true,
2021            }],
2022        );
2023        let certificate = transform_catalog_reorderability_certificate_from_differential_v0(
2024            TransformPassKind::NumberCompression,
2025            TransformPassKind::ColorCompression,
2026            &witness,
2027        );
2028
2029        assert!(witness.accepted);
2030        assert_eq!(
2031            certificate.commute_witness,
2032            "checkedRewriteCertificateWithDifferentialSearch"
2033        );
2034        assert_eq!(
2035            witness.mechanism_scope,
2036            TRANSFORM_CATALOG_MECHANISM_SCOPE_V0
2037        );
2038        assert_eq!(
2039            certificate.mechanism_scope,
2040            TRANSFORM_CATALOG_MECHANISM_SCOPE_V0
2041        );
2042        assert_eq!(
2043            witness.global_transform_theorem_claimed,
2044            TRANSFORM_CATALOG_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0
2045        );
2046        assert_eq!(
2047            certificate.global_transform_theorem_claimed,
2048            TRANSFORM_CATALOG_GLOBAL_TRANSFORM_THEOREM_CLAIMED_V0
2049        );
2050        assert_eq!(certificate.differential_fixture_count, 1);
2051        assert_eq!(certificate.differential_mismatch_count, 0);
2052        assert!(certificate.accepted);
2053    }
2054}