diff --git a/docs/briefs/r3-v-tests-as-data-v1-worker.md b/docs/briefs/r3-v-tests-as-data-v1-worker.md index 4ff9abcb1b8..e147fde45c3 100644 --- a/docs/briefs/r3-v-tests-as-data-v1-worker.md +++ b/docs/briefs/r3-v-tests-as-data-v1-worker.md @@ -61,7 +61,7 @@ Gate IDs reference [`docs/r3-program-plan.md`](../r3-program-plan.md) §1.8 "Can ## Implementation slices (suggested PR sequence) -1. **V4-a — Census + mapping:** refresh readiness audit §1; extend predicate coverage map (audit §6 slice 2). +1. **V4-a — Census + mapping:** refresh readiness audit §1; extend predicate coverage map (audit §6 slice 2). The SG-0 migration-class matcher is transitional: each class-by-class migration PR should remove the corresponding path matcher branch as those Rust paths move to `.dag` `TestClaim` data, and gate #84 close requires the matcher itself to disappear with `EXPECTED_HAND_AUTHORED_TEST` at zero. 2. **V4-b — First executable port:** satisfy `tests_as_data_demonstration` + shrink SG-0 net (audit §6 slice 3). 3. **V4-c — Quantifiers + generator:** land when **T4** clears (audit §6 slice 4). 4. **V4-d — Facet-3 close:** census **0** + cementing discipline satisfied (audit §6 slice 5). diff --git a/src/v3/compiler/tests/integration/sg0_census_test.rs b/src/v3/compiler/tests/integration/sg0_census_test.rs index d5d0a53825c..d8ec6b67155 100644 --- a/src/v3/compiler/tests/integration/sg0_census_test.rs +++ b/src/v3/compiler/tests/integration/sg0_census_test.rs @@ -29,7 +29,7 @@ //! `build.rs` names it. File contents do not participate: a hand-authored //! `.rs` that begins with `// AUTO-GENERATED` does not slip through. -use std::collections::BTreeSet; +use std::collections::{BTreeMap, BTreeSet}; use std::ffi::OsStr; use std::fs; use std::path::{Path, PathBuf}; @@ -701,6 +701,94 @@ const EXPECTED_GENERATED_FRAGMENTS: &[&str] = &[ "src/v3/compiler/tests/integration/parse_corpus_manifest.txt", ]; +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] +enum TestsAsDataMigrationClass { + CompileOrReject, + LensOutputEquality, + BehavioralObservation, + BoundaryHostProcess, + CementingV2Oracle, + CensusOrRatchet, + PropertyBased, +} + +const EXPECTED_TESTS_AS_DATA_MIGRATION_AUDIT_COUNT: usize = 116; + +// Transitional gate #84 audit only. As each class migrates to `.dag` +// `TestClaim` data, remove that class's path matcher branch with the +// retired Rust paths; when `EXPECTED_HAND_AUTHORED_TEST` reaches zero, +// this classifier should disappear with it. +// Match order is load-bearing while this exists: check classification +// before deleting or reordering a branch, especially broad substring +// branches such as `contains("sg")`. +fn tests_as_data_migration_class(path: &str) -> Option { + use TestsAsDataMigrationClass::*; + + if path.starts_with("src/v3/compiler/tests/boundary/") { + return Some(BoundaryHostProcess); + } + + if path.contains("/cementing/") + || path.ends_with("lens_behavioral_parity_demonstration_test.rs") + || path.ends_with("r3_gate_87_lens_cementing_regen_receipts_test.rs") + { + return Some(CementingV2Oracle); + } + + if path.contains("census") + || path.contains("ratchet") + || path.contains("bridge") + || path.contains("sg") + || path.contains("r1c_") + || path.contains("v2_oracle") + || path.contains("value_body_substrate_mirror") + || path.contains("lens_producer_retirement") + { + return Some(CensusOrRatchet); + } + + if path.contains("free_consequences") + || path.contains("tc1_") + || path.contains("tc2_") + || path.contains("tc3_") + { + return Some(PropertyBased); + } + + if path.contains("lens") + || path.contains("cost") + || path.contains("parallelism") + || path.contains("timing") + || path.contains("workflow") + || path.contains("e6_g1a") + || path.contains("lane2_stage_2d") + { + return Some(LensOutputEquality); + } + + if path.contains("anthropic") + || path.contains("operation") + || path.contains("services") + || path.contains("omni") + || path.contains("openapi") + || path.contains("runtime_evaluator_corpus") + || path.contains("self_host_demonstration") + || path.contains("t_ci_workflow_as_data_demo") + || path.contains("pb1_bootstrap_full_snapshot") + { + return Some(BehavioralObservation); + } + + if path.starts_with("src/v3/compiler/tests/integration/") + || path.starts_with("src/v3/compiler/tests/determinism_test.rs") + || path.starts_with("src/v3/compiler/tests/integration.rs") + { + return Some(CompileOrReject); + } + + None +} + fn is_test_path(path: &str) -> bool { path.starts_with("src/v3/compiler/tests/") } @@ -957,6 +1045,46 @@ fn sg0_v3_test_hand_authored_subratchet() { ); } +#[test] +fn sg0_tests_as_data_migration_audit_classifies_test_ratchet() { + let mut by_class: BTreeMap> = BTreeMap::new(); + let mut unclassified = Vec::new(); + + for path in EXPECTED_HAND_AUTHORED_TEST { + match tests_as_data_migration_class(path) { + Some(class) => by_class.entry(class).or_default().push(*path), + None => unclassified.push(*path), + } + } + + assert!( + unclassified.is_empty(), + "gate #84 migration audit must classify every hand-authored test path; \ + unclassified paths: {unclassified:?}" + ); + assert_eq!( + EXPECTED_HAND_AUTHORED_TEST.len(), + EXPECTED_TESTS_AS_DATA_MIGRATION_AUDIT_COUNT, + "gate #84 migration audit count drifted; update the migration-class audit \ + when the SG-0 hand-authored test ratchet changes" + ); + + for class in [ + TestsAsDataMigrationClass::CompileOrReject, + TestsAsDataMigrationClass::LensOutputEquality, + TestsAsDataMigrationClass::BehavioralObservation, + TestsAsDataMigrationClass::BoundaryHostProcess, + TestsAsDataMigrationClass::CementingV2Oracle, + TestsAsDataMigrationClass::CensusOrRatchet, + TestsAsDataMigrationClass::PropertyBased, + ] { + assert!( + by_class.get(&class).is_some_and(|paths| !paths.is_empty()), + "gate #84 migration audit lost class coverage for {class:?}" + ); + } +} + #[test] fn sg0_v3_non_test_fragment_subratchet() { let misplaced_fragments: Vec<&str> = EXPECTED_HAND_AUTHORED_FRAGMENTS