use runx_contracts::schema::NonEmptyString;
use runx_contracts::{
ActForm, Closure, ClosureDisposition, CriterionBinding, CriterionStatus, Intent, ReceiptAct,
SuccessCriterion,
};
use crate::execution::output_projection::StepOutputRefs;
pub(crate) struct ActOutcome<'a> {
pub(crate) disposition: ClosureDisposition,
pub(crate) succeeded: bool,
pub(crate) summary: String,
pub(crate) performed_at: &'a str,
pub(crate) refs: &'a StepOutputRefs,
}
pub(crate) struct RuntimeAct {
id: NonEmptyString,
form: ActForm,
intent: Intent,
summary: NonEmptyString,
criterion_id: NonEmptyString,
reason_code: NonEmptyString,
}
impl RuntimeAct {
pub(crate) fn observation(step_id: &str) -> Self {
Self {
id: format!("act_{step_id}").into(),
form: ActForm::Observation,
intent: Intent {
purpose: format!("Run graph step {step_id}").into(),
legitimacy: "Runtime graph execution was admitted by the local harness".into(),
success_criteria: vec![SuccessCriterion {
criterion_id: "process_exit".into(),
statement: "cli-tool exits successfully".into(),
required: true,
}],
constraints: Vec::new(),
derived_from: Vec::new(),
},
summary: format!("Executed graph step {step_id}").into(),
criterion_id: "process_exit".into(),
reason_code: "process_exit".into(),
}
}
pub(crate) fn close(self, outcome: ActOutcome<'_>) -> ReceiptAct {
let mut artifact_refs = outcome.refs.artifact_refs.clone();
artifact_refs.extend(outcome.refs.surface_refs.iter().cloned());
ReceiptAct {
id: self.id,
form: self.form,
intent: self.intent,
summary: self.summary,
criterion_bindings: vec![CriterionBinding {
criterion_id: self.criterion_id,
status: if outcome.succeeded {
CriterionStatus::Verified
} else {
CriterionStatus::Failed
},
evidence_refs: outcome.refs.evidence_refs.clone(),
verification_refs: outcome.refs.verification_refs.clone(),
summary: Some(outcome.summary.clone().into()),
}],
by: None,
source_refs: outcome.refs.source_refs.clone(),
target_refs: Vec::new(),
artifact_refs,
context_ref: None,
closure: Closure {
disposition: outcome.disposition,
reason_code: self.reason_code,
summary: outcome.summary.into(),
closed_at: outcome.performed_at.into(),
},
revision: None,
verification: None,
}
}
}