use std::collections::HashSet;
pub const AC_MONO_INCR_COMPILE_REGRESSION_FACTOR: f64 = 3.0;
pub const AC_MONO_INCR_COMPILE_BASELINE_S: f64 = 5.0;
pub const AC_MONO_CI_TIME_BUDGET_S: u32 = 600;
pub const AC_MONO_MERGE_CONFLICT_THRESHOLD_PER_WEEK: u32 = 2;
pub const AC_MONO_PUBLISH_TIME_BUDGET_S: u32 = 300;
pub const AC_MONO_BROKEN_PUBLISH_BUDGET: u32 = 2;
pub const AC_MONO_CLONE_TIME_BUDGET_S: u32 = 30;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MonoIncrCompileVerdict {
Pass,
Fail,
}
#[must_use]
pub fn verdict_from_mono_incr_compile(measured_seconds: f64) -> MonoIncrCompileVerdict {
if !measured_seconds.is_finite() || measured_seconds < 0.0 {
return MonoIncrCompileVerdict::Fail;
}
let budget = AC_MONO_INCR_COMPILE_BASELINE_S * AC_MONO_INCR_COMPILE_REGRESSION_FACTOR;
if measured_seconds <= budget {
MonoIncrCompileVerdict::Pass
} else {
MonoIncrCompileVerdict::Fail
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MonoCiTimeVerdict { Pass, Fail }
#[must_use]
pub fn verdict_from_mono_ci_time(seconds: u32) -> MonoCiTimeVerdict {
if seconds <= AC_MONO_CI_TIME_BUDGET_S { MonoCiTimeVerdict::Pass } else { MonoCiTimeVerdict::Fail }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MonoMergeConflictVerdict { Pass, Fail }
#[must_use]
pub fn verdict_from_mono_merge_conflict(conflicts_per_week: u32) -> MonoMergeConflictVerdict {
if conflicts_per_week <= AC_MONO_MERGE_CONFLICT_THRESHOLD_PER_WEEK {
MonoMergeConflictVerdict::Pass
} else {
MonoMergeConflictVerdict::Fail
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MonoPublishTimeVerdict { Pass, Fail }
#[must_use]
pub fn verdict_from_mono_publish_time(seconds: u32) -> MonoPublishTimeVerdict {
if seconds <= AC_MONO_PUBLISH_TIME_BUDGET_S {
MonoPublishTimeVerdict::Pass
} else {
MonoPublishTimeVerdict::Fail
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MonoBrokenPublishVerdict { Pass, Fail }
#[must_use]
pub fn verdict_from_mono_broken_publish(incidents_in_90d: u32) -> MonoBrokenPublishVerdict {
if incidents_in_90d <= AC_MONO_BROKEN_PUBLISH_BUDGET {
MonoBrokenPublishVerdict::Pass
} else {
MonoBrokenPublishVerdict::Fail
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MonoCloneTimeVerdict { Pass, Fail }
#[must_use]
pub fn verdict_from_mono_clone_time(seconds: u32) -> MonoCloneTimeVerdict {
if seconds <= AC_MONO_CLONE_TIME_BUDGET_S {
MonoCloneTimeVerdict::Pass
} else {
MonoCloneTimeVerdict::Fail
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MonoHistoryVerdict { Pass, Fail }
#[must_use]
pub fn verdict_from_mono_history(commits_from_original_repo: u32) -> MonoHistoryVerdict {
if commits_from_original_repo > 0 {
MonoHistoryVerdict::Pass
} else {
MonoHistoryVerdict::Fail
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MonoShimReexportVerdict { Pass, Fail }
#[must_use]
pub fn verdict_from_mono_shim_reexport(
shim_compiles: bool,
test_results_match_legacy: bool,
) -> MonoShimReexportVerdict {
if shim_compiles && test_results_match_legacy {
MonoShimReexportVerdict::Pass
} else {
MonoShimReexportVerdict::Fail
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MonoVersionBumpVerdict { Pass, Fail }
#[must_use]
pub fn verdict_from_mono_version_bump(
is_major_bump: bool,
breaking_api_changes: u32,
) -> MonoVersionBumpVerdict {
if breaking_api_changes == 0 {
return MonoVersionBumpVerdict::Pass;
}
if is_major_bump {
MonoVersionBumpVerdict::Pass
} else {
MonoVersionBumpVerdict::Fail
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MonoRegistryComplianceVerdict { Pass, Fail }
#[must_use]
pub fn verdict_from_mono_registry_compliance(
workspace_names: &[&str],
registered_names: &[&str],
) -> MonoRegistryComplianceVerdict {
if workspace_names.is_empty() {
return MonoRegistryComplianceVerdict::Fail;
}
let registry: HashSet<&&str> = registered_names.iter().collect();
for name in workspace_names {
if !registry.contains(name) {
return MonoRegistryComplianceVerdict::Fail;
}
}
MonoRegistryComplianceVerdict::Pass
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MonoSingleBinaryVerdict { Pass, Fail }
pub const AC_MONO_BIN_ALLOWED: [&str; 2] = ["apr-cli", "aprender-contracts-cli"];
#[must_use]
pub fn verdict_from_mono_single_binary(crates_with_bins: &[&str]) -> MonoSingleBinaryVerdict {
for c in crates_with_bins {
if !AC_MONO_BIN_ALLOWED.contains(c) {
return MonoSingleBinaryVerdict::Fail;
}
}
MonoSingleBinaryVerdict::Pass
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MonoFlatLayoutVerdict { Pass, Fail }
#[must_use]
pub fn verdict_from_mono_flat_layout(member_paths: &[&str]) -> MonoFlatLayoutVerdict {
if member_paths.is_empty() {
return MonoFlatLayoutVerdict::Fail;
}
for path in member_paths {
if !path.starts_with("crates/") {
return MonoFlatLayoutVerdict::Fail;
}
let suffix = &path["crates/".len()..];
if suffix.contains('/') {
return MonoFlatLayoutVerdict::Fail;
}
if suffix.is_empty() {
return MonoFlatLayoutVerdict::Fail;
}
}
MonoFlatLayoutVerdict::Pass
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MonoSubcommandContractVerdict { Pass, Fail }
#[must_use]
pub fn verdict_from_mono_subcommand_contract(
subcommands: &[&str],
contract_names: &[&str],
) -> MonoSubcommandContractVerdict {
if subcommands.is_empty() {
return MonoSubcommandContractVerdict::Fail;
}
let contracts: HashSet<&&str> = contract_names.iter().collect();
for cmd in subcommands {
if !contracts.contains(cmd) {
return MonoSubcommandContractVerdict::Fail;
}
}
MonoSubcommandContractVerdict::Pass
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn provenance_incr_factor_3() {
assert!((AC_MONO_INCR_COMPILE_REGRESSION_FACTOR - 3.0).abs() < f64::EPSILON);
}
#[test]
fn provenance_ci_budget_600s() {
assert_eq!(AC_MONO_CI_TIME_BUDGET_S, 600);
}
#[test]
fn provenance_publish_budget_300s() {
assert_eq!(AC_MONO_PUBLISH_TIME_BUDGET_S, 300);
}
#[test]
fn provenance_clone_budget_30s() {
assert_eq!(AC_MONO_CLONE_TIME_BUDGET_S, 30);
}
#[test]
fn provenance_bin_allowed_2() {
assert_eq!(AC_MONO_BIN_ALLOWED.len(), 2);
}
#[test]
fn fm001_pass_under_budget() {
assert_eq!(verdict_from_mono_incr_compile(10.0), MonoIncrCompileVerdict::Pass);
}
#[test]
fn fm001_pass_at_budget() {
assert_eq!(verdict_from_mono_incr_compile(15.0), MonoIncrCompileVerdict::Pass);
}
#[test]
fn fm001_fail_over_budget() {
assert_eq!(verdict_from_mono_incr_compile(20.0), MonoIncrCompileVerdict::Fail);
}
#[test]
fn fm001_fail_nan() {
assert_eq!(verdict_from_mono_incr_compile(f64::NAN), MonoIncrCompileVerdict::Fail);
}
#[test]
fn fm002_pass_under_ci_budget() {
assert_eq!(verdict_from_mono_ci_time(180), MonoCiTimeVerdict::Pass);
}
#[test]
fn fm002_fail_over_ci_budget() {
assert_eq!(verdict_from_mono_ci_time(700), MonoCiTimeVerdict::Fail);
}
#[test]
fn fm003_pass_low_conflicts() {
assert_eq!(verdict_from_mono_merge_conflict(1), MonoMergeConflictVerdict::Pass);
}
#[test]
fn fm003_fail_high_conflicts() {
assert_eq!(verdict_from_mono_merge_conflict(5), MonoMergeConflictVerdict::Fail);
}
#[test]
fn fm004_pass_fast_publish() {
assert_eq!(verdict_from_mono_publish_time(120), MonoPublishTimeVerdict::Pass);
}
#[test]
fn fm004_fail_slow_publish() {
assert_eq!(verdict_from_mono_publish_time(600), MonoPublishTimeVerdict::Fail);
}
#[test]
fn fm005_pass_zero_incidents() {
assert_eq!(verdict_from_mono_broken_publish(0), MonoBrokenPublishVerdict::Pass);
}
#[test]
fn fm005_fail_many_incidents() {
assert_eq!(verdict_from_mono_broken_publish(5), MonoBrokenPublishVerdict::Fail);
}
#[test]
fn fm006_pass_fast_clone() {
assert_eq!(verdict_from_mono_clone_time(15), MonoCloneTimeVerdict::Pass);
}
#[test]
fn fm006_fail_slow_clone() {
assert_eq!(verdict_from_mono_clone_time(60), MonoCloneTimeVerdict::Fail);
}
#[test]
fn fm007_pass_history_preserved() {
assert_eq!(verdict_from_mono_history(100), MonoHistoryVerdict::Pass);
}
#[test]
fn fm007_fail_no_history() {
assert_eq!(verdict_from_mono_history(0), MonoHistoryVerdict::Fail);
}
#[test]
fn fm008_pass_shim_works() {
assert_eq!(
verdict_from_mono_shim_reexport(true, true),
MonoShimReexportVerdict::Pass
);
}
#[test]
fn fm008_fail_shim_compile_error() {
assert_eq!(
verdict_from_mono_shim_reexport(false, true),
MonoShimReexportVerdict::Fail
);
}
#[test]
fn fm008_fail_results_diverge() {
assert_eq!(
verdict_from_mono_shim_reexport(true, false),
MonoShimReexportVerdict::Fail
);
}
#[test]
fn fm009_pass_no_breaking_changes() {
assert_eq!(
verdict_from_mono_version_bump(false, 0),
MonoVersionBumpVerdict::Pass
);
}
#[test]
fn fm009_pass_breaking_in_major_bump() {
assert_eq!(
verdict_from_mono_version_bump(true, 5),
MonoVersionBumpVerdict::Pass
);
}
#[test]
fn fm009_fail_breaking_in_minor_bump() {
assert_eq!(
verdict_from_mono_version_bump(false, 1),
MonoVersionBumpVerdict::Fail
);
}
#[test]
fn fm010_pass_all_registered() {
let workspace = ["aprender-core", "aprender-train"];
let registry = ["aprender-core", "aprender-train", "aprender-extra"];
assert_eq!(
verdict_from_mono_registry_compliance(&workspace, ®istry),
MonoRegistryComplianceVerdict::Pass
);
}
#[test]
fn fm010_fail_unregistered() {
let workspace = ["aprender-core", "rogue-crate"];
let registry = ["aprender-core"];
assert_eq!(
verdict_from_mono_registry_compliance(&workspace, ®istry),
MonoRegistryComplianceVerdict::Fail
);
}
#[test]
fn fm010_fail_empty_workspace() {
let registry = ["aprender-core"];
assert_eq!(
verdict_from_mono_registry_compliance(&[], ®istry),
MonoRegistryComplianceVerdict::Fail
);
}
#[test]
fn fm011_pass_only_apr_cli_has_bin() {
let bins = ["apr-cli"];
assert_eq!(
verdict_from_mono_single_binary(&bins),
MonoSingleBinaryVerdict::Pass
);
}
#[test]
fn fm011_pass_apr_cli_plus_contracts_tooling() {
let bins = ["apr-cli", "aprender-contracts-cli"];
assert_eq!(
verdict_from_mono_single_binary(&bins),
MonoSingleBinaryVerdict::Pass
);
}
#[test]
fn fm011_fail_unauthorized_binary() {
let bins = ["apr-cli", "rogue-bin"];
assert_eq!(
verdict_from_mono_single_binary(&bins),
MonoSingleBinaryVerdict::Fail
);
}
#[test]
fn fm012_pass_flat() {
let p = ["crates/aprender-core", "crates/aprender-train"];
assert_eq!(verdict_from_mono_flat_layout(&p), MonoFlatLayoutVerdict::Pass);
}
#[test]
fn fm012_fail_nested() {
let p = ["crates/aprender-core", "crates/parent/child"];
assert_eq!(verdict_from_mono_flat_layout(&p), MonoFlatLayoutVerdict::Fail);
}
#[test]
fn fm012_fail_outside_crates() {
let p = ["src/lib"];
assert_eq!(verdict_from_mono_flat_layout(&p), MonoFlatLayoutVerdict::Fail);
}
#[test]
fn fm013_pass_all_contracts_present() {
let cmds = ["run", "serve", "chat"];
let contracts = ["run", "serve", "chat", "extra"];
assert_eq!(
verdict_from_mono_subcommand_contract(&cmds, &contracts),
MonoSubcommandContractVerdict::Pass
);
}
#[test]
fn fm013_fail_missing_contract() {
let cmds = ["run", "new-cmd"];
let contracts = ["run"];
assert_eq!(
verdict_from_mono_subcommand_contract(&cmds, &contracts),
MonoSubcommandContractVerdict::Fail
);
}
#[test]
fn fm013_fail_empty_subcommands() {
let contracts = ["run"];
assert_eq!(
verdict_from_mono_subcommand_contract(&[], &contracts),
MonoSubcommandContractVerdict::Fail
);
}
#[test]
fn realistic_healthy_migration_passes_all_13() {
assert_eq!(verdict_from_mono_incr_compile(8.0), MonoIncrCompileVerdict::Pass);
assert_eq!(verdict_from_mono_ci_time(240), MonoCiTimeVerdict::Pass);
assert_eq!(verdict_from_mono_merge_conflict(1), MonoMergeConflictVerdict::Pass);
assert_eq!(verdict_from_mono_publish_time(150), MonoPublishTimeVerdict::Pass);
assert_eq!(verdict_from_mono_broken_publish(0), MonoBrokenPublishVerdict::Pass);
assert_eq!(verdict_from_mono_clone_time(20), MonoCloneTimeVerdict::Pass);
assert_eq!(verdict_from_mono_history(50), MonoHistoryVerdict::Pass);
assert_eq!(
verdict_from_mono_shim_reexport(true, true),
MonoShimReexportVerdict::Pass
);
assert_eq!(
verdict_from_mono_version_bump(false, 0),
MonoVersionBumpVerdict::Pass
);
let workspace = ["aprender-core"];
let registry = ["aprender-core", "aprender-train"];
assert_eq!(
verdict_from_mono_registry_compliance(&workspace, ®istry),
MonoRegistryComplianceVerdict::Pass
);
assert_eq!(
verdict_from_mono_single_binary(&["apr-cli"]),
MonoSingleBinaryVerdict::Pass
);
let p = ["crates/aprender-core"];
assert_eq!(verdict_from_mono_flat_layout(&p), MonoFlatLayoutVerdict::Pass);
assert_eq!(
verdict_from_mono_subcommand_contract(&["run"], &["run", "serve"]),
MonoSubcommandContractVerdict::Pass
);
}
#[test]
fn realistic_pre_fix_all_13_failures() {
assert_eq!(verdict_from_mono_incr_compile(60.0), MonoIncrCompileVerdict::Fail);
assert_eq!(verdict_from_mono_ci_time(900), MonoCiTimeVerdict::Fail);
assert_eq!(verdict_from_mono_merge_conflict(10), MonoMergeConflictVerdict::Fail);
assert_eq!(verdict_from_mono_publish_time(600), MonoPublishTimeVerdict::Fail);
assert_eq!(verdict_from_mono_broken_publish(20), MonoBrokenPublishVerdict::Fail);
assert_eq!(verdict_from_mono_clone_time(120), MonoCloneTimeVerdict::Fail);
assert_eq!(verdict_from_mono_history(0), MonoHistoryVerdict::Fail);
assert_eq!(
verdict_from_mono_shim_reexport(false, false),
MonoShimReexportVerdict::Fail
);
assert_eq!(
verdict_from_mono_version_bump(false, 5),
MonoVersionBumpVerdict::Fail
);
assert_eq!(
verdict_from_mono_registry_compliance(&["rogue"], &["aprender-core"]),
MonoRegistryComplianceVerdict::Fail
);
assert_eq!(
verdict_from_mono_single_binary(&["rogue-bin"]),
MonoSingleBinaryVerdict::Fail
);
assert_eq!(
verdict_from_mono_flat_layout(&["crates/parent/child"]),
MonoFlatLayoutVerdict::Fail
);
assert_eq!(
verdict_from_mono_subcommand_contract(&["new-cmd"], &["run"]),
MonoSubcommandContractVerdict::Fail
);
}
}