use crate::api::{
EvidenceLevel, FailureClassification, ScenarioOutcome, restart_requery_schema_id,
};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct WorkloadIdentity<'a> {
pub workload_id: &'a str,
pub dataset_family: &'a str,
pub query_profile: &'a str,
pub embedding_profile: &'a str,
}
impl<'a> WorkloadIdentity<'a> {
#[must_use]
pub const fn new(
workload_id: &'a str,
dataset_family: &'a str,
query_profile: &'a str,
embedding_profile: &'a str,
) -> Self {
Self {
workload_id,
dataset_family,
query_profile,
embedding_profile,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ReplayBundle<'a> {
pub scenario_id: &'a str,
pub dataset_family: &'a str,
pub commit_or_version: &'a str,
pub maturity_tier: &'a str,
}
impl<'a> ReplayBundle<'a> {
#[must_use]
pub const fn new(
scenario_id: &'a str,
dataset_family: &'a str,
commit_or_version: &'a str,
maturity_tier: &'a str,
) -> Self {
Self {
scenario_id,
dataset_family,
commit_or_version,
maturity_tier,
}
}
#[must_use]
pub fn artifact_name(&self) -> String {
format!(
"alloy-assurance-{}-{}-bundle-{}",
self.commit_or_version, self.maturity_tier, self.scenario_id
)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct AssertionRecord<'a> {
pub assertion_id: &'a str,
pub description: &'a str,
pub outcome: ScenarioOutcome,
pub expected: &'a str,
pub actual: &'a str,
}
impl<'a> AssertionRecord<'a> {
#[must_use]
pub const fn new(
assertion_id: &'a str,
description: &'a str,
outcome: ScenarioOutcome,
expected: &'a str,
actual: &'a str,
) -> Self {
Self {
assertion_id,
description,
outcome,
expected,
actual,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct AttachedArtifact<'a> {
pub artifact_role: &'a str,
pub artifact_ref: &'a str,
pub media_type: &'a str,
}
impl<'a> AttachedArtifact<'a> {
#[must_use]
pub const fn new(artifact_role: &'a str, artifact_ref: &'a str, media_type: &'a str) -> Self {
Self {
artifact_role,
artifact_ref,
media_type,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ReplayPayload<'a> {
pub scenario_id: &'a str,
pub bundle: ReplayBundle<'a>,
pub reproduction_entrypoint: &'a str,
pub runner: &'a str,
}
impl<'a> ReplayPayload<'a> {
#[must_use]
pub const fn new(
scenario_id: &'a str,
bundle: ReplayBundle<'a>,
reproduction_entrypoint: &'a str,
runner: &'a str,
) -> Self {
Self {
scenario_id,
bundle,
reproduction_entrypoint,
runner,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ScenarioManifest<'a> {
pub scenario_id: &'a str,
pub scenario_family: &'a str,
pub tags: &'a [&'a str],
}
impl<'a> ScenarioManifest<'a> {
#[must_use]
pub const fn new(scenario_id: &'a str, scenario_family: &'a str, tags: &'a [&'a str]) -> Self {
Self {
scenario_id,
scenario_family,
tags,
}
}
#[must_use]
pub fn summary_line(&self) -> String {
format!(
"{} [{}] tags={}",
self.scenario_id,
self.scenario_family,
self.tags.join(",")
)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct EvidenceEnvelope<'a> {
pub artifact_id: &'a str,
pub dataset_family: &'a str,
pub commit_or_version: &'a str,
pub maturity_tier: &'a str,
pub level: EvidenceLevel,
pub outcome: ScenarioOutcome,
pub failure: FailureClassification,
}
impl<'a> EvidenceEnvelope<'a> {
#[must_use]
pub const fn new(
artifact_id: &'a str,
dataset_family: &'a str,
commit_or_version: &'a str,
maturity_tier: &'a str,
level: EvidenceLevel,
) -> Self {
Self {
artifact_id,
dataset_family,
commit_or_version,
maturity_tier,
level,
outcome: ScenarioOutcome::Pass,
failure: FailureClassification::None,
}
}
pub fn record_outcome(
&mut self,
outcome: ScenarioOutcome,
failure: FailureClassification,
) -> &mut Self {
self.outcome = outcome;
self.failure = failure;
self
}
#[must_use]
pub const fn permits_release(&self) -> bool {
match self.level {
EvidenceLevel::ReleaseBlocking => matches!(self.outcome, ScenarioOutcome::Pass),
EvidenceLevel::Informational | EvidenceLevel::RegressionProtecting => true,
}
}
#[must_use]
pub fn artifact_name(&self) -> String {
format!(
"alloy-assurance-{}-{}-report-{}",
self.commit_or_version, self.maturity_tier, self.artifact_id
)
}
#[must_use]
pub fn report_line(&self) -> String {
format!(
"{} outcome={:?} failure={}",
self.artifact_id,
self.outcome,
self.failure.as_str()
)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RestartRequeryEvidence<'a> {
pub schema_id: &'static str,
pub workload: WorkloadIdentity<'a>,
pub envelope: EvidenceEnvelope<'a>,
pub assertions: Vec<AssertionRecord<'a>>,
pub artifacts: Vec<AttachedArtifact<'a>>,
pub replay: ReplayPayload<'a>,
}
impl<'a> RestartRequeryEvidence<'a> {
#[must_use]
pub fn new(
workload: WorkloadIdentity<'a>,
mut envelope: EvidenceEnvelope<'a>,
assertions: Vec<AssertionRecord<'a>>,
artifacts: Vec<AttachedArtifact<'a>>,
replay: ReplayPayload<'a>,
) -> Self {
envelope.record_outcome(
aggregate_outcome(&assertions),
aggregate_failure(&assertions),
);
Self {
schema_id: restart_requery_schema_id(),
workload,
envelope,
assertions,
artifacts,
replay,
}
}
#[must_use]
pub fn is_replay_ready(&self) -> bool {
!self.assertions.is_empty()
&& self
.artifacts
.iter()
.any(|artifact| artifact.artifact_role == "replay-bundle")
&& !self.replay.reproduction_entrypoint.is_empty()
&& !self.replay.runner.is_empty()
}
}
fn aggregate_outcome(assertions: &[AssertionRecord<'_>]) -> ScenarioOutcome {
if assertions
.iter()
.all(|assertion| assertion.outcome == ScenarioOutcome::Pass)
{
ScenarioOutcome::Pass
} else if assertions
.iter()
.all(|assertion| assertion.outcome == ScenarioOutcome::Fail)
{
ScenarioOutcome::Fail
} else {
ScenarioOutcome::Mixed
}
}
fn aggregate_failure(assertions: &[AssertionRecord<'_>]) -> FailureClassification {
if assertions
.iter()
.any(|assertion| assertion.outcome != ScenarioOutcome::Pass)
{
FailureClassification::RestartConsistency
} else {
FailureClassification::None
}
}