pub mod catalog;
mod composition;
pub mod identity;
mod machine;
mod seam;
pub mod types;
pub use identity::{
NamedTypeBinding, RustTypeAtom, TypePathEnumPayloadAtom, TypePathEnumPayloadField,
TypePathEnumStructuralVariant, TypePathStructField, TypePathStructFieldAtom,
};
pub use types::{CommsRuntimeId, McpServerId, MobId, PeerCorrelationId};
pub use catalog::{
CompositionCoverageManifest, CoverageAnchor, CoverageClaims, CoverageSchemaTarget,
MachineCoverageManifest, MachineProductionOwnerRelation, ScenarioCoverage,
SemanticCoverageEntry, SymbolRef, canonical_composition_coverage_manifests,
canonical_composition_schemas, canonical_machine_coverage_manifests,
canonical_machine_production_owner_relations, canonical_machine_schemas,
meerkat_mob_seam_composition, scheduler_rule_coverage_name,
};
pub use composition::{
ActorKind, ActorPriority, ActorSchema, ClosurePolicy, CommsTrustAuthorityOperation,
CommsTrustAuthorityProtocol, CommsTrustAuthoritySourceKind, CompositionDriver,
CompositionDriverRustBinding, CompositionInvariant, CompositionInvariantKind,
CompositionSchema, CompositionSchemaError, CompositionStateLimits, CompositionTransactionPlan,
CompositionWitness, CompositionWitnessField, CompositionWitnessInput, CompositionWitnessState,
CompositionWitnessTransition, CompositionWitnessTransitionOrder, DriverDispatchRoute,
DurableMarkerFieldBinding, DurableMarkerProtocol, DurableMarkerRelationProtocol,
EffectHandoffProtocol, EffectTeardownClass, EntryInput, FeedbackFieldBinding,
FeedbackFieldSource, FeedbackInputRef, HandleBridgeFeedbackBinding, MachineInstance,
ProtocolGenerationMode, ProtocolHelperReturnShape, ProtocolRustBinding, Route,
RouteBindingSource, RouteDelivery, RouteFieldBinding, RouteTarget, RouteTargetKind,
RouteTargetSelector, RouteVariantId, SchedulerRule, TeardownObligationClass, WatchedEffect,
};
pub use machine::{
CommandPlanSchema, EffectClosureSchema, EffectDisposition, EffectDispositionRule, EffectEmit,
EnumSchema, Expr, FieldInit, FieldSchema, FieldType, Guard, HelperSchema, InitSchema,
InputMatch, InvariantSchema, MachineSchema, MachineSchemaError, Quantifier, RustBinding,
StateSchema, TransitionSchema, TriggerKind, TriggerMatch, TypeRef, Update, VariantSchema,
};
pub use seam::SeamClassification;
#[cfg(test)]
mod tests {
use super::{Update, canonical_machine_coverage_manifests, canonical_machine_schemas};
use crate::catalog::dsl::dsl_schedule_lifecycle_machine as schedule_lifecycle_machine;
#[test]
fn schedule_and_occurrence_machines_are_registered_in_canonical_catalog() {
let machine_names: Vec<_> = canonical_machine_schemas()
.into_iter()
.map(|schema| schema.machine)
.collect();
let coverage_names: Vec<_> = canonical_machine_coverage_manifests()
.into_iter()
.map(|manifest| manifest.machine)
.collect();
assert!(
machine_names
.iter()
.any(|name| name.as_str() == "ScheduleLifecycleMachine"),
"schedule lifecycle machine must be a canonical schema"
);
assert!(
machine_names
.iter()
.any(|name| name.as_str() == "OccurrenceLifecycleMachine"),
"occurrence lifecycle machine must be a canonical schema"
);
assert!(
coverage_names
.iter()
.any(|name| name.as_str() == "ScheduleLifecycleMachine"),
"schedule lifecycle machine must have coverage metadata"
);
assert!(
coverage_names
.iter()
.any(|name| name.as_str() == "OccurrenceLifecycleMachine"),
"occurrence lifecycle machine must have coverage metadata"
);
}
#[test]
fn schedule_delete_transitions_bump_revision_and_supersede_pending_occurrences() {
let machine = schedule_lifecycle_machine();
for transition_name in ["DeleteActive", "DeletePaused"] {
let transition = machine
.transitions
.iter()
.find(|transition| transition.name.as_str() == transition_name);
assert!(transition.is_some(), "missing {transition_name} transition");
let Some(transition) = transition else {
return;
};
assert!(
transition.updates.iter().any(|update| matches!(
update,
Update::Increment { field, amount } if field.as_str() == "revision" && *amount == 1
)),
"{transition_name} should advance the revision"
);
assert!(
transition
.emit
.iter()
.any(|effect| effect.variant.as_str() == "SupersedePendingOccurrences"),
"{transition_name} should supersede older pending occurrences"
);
}
}
#[test]
fn canonical_registry_excludes_absorbed_flow_machine_schemas() {
let machine_names: Vec<_> = canonical_machine_schemas()
.into_iter()
.map(|schema| schema.machine)
.collect();
for compat_name in ["FlowRunMachine", "FlowFrameMachine", "LoopIterationMachine"] {
assert!(
!machine_names
.iter()
.any(|name| name.as_str() == compat_name),
"{compat_name} should be absorbed into MobMachine, not canonical"
);
}
}
}