Project a timed-out partial success from Petri's UnderlyingFailure

Petri's PartialSuccess now carries Option<UnderlyingFailure>, which is
Failure(FailureInfo) or TimedOut, so a partial success converted from a
timeout keeps the timeout (lithoscomputer/petri#51). The projection's
failure message reads the new shape: the info's message for a failure,
"the step timed out" for a timeout, as for the plain statuses.

Lock the Petri crates at the PR head ded1df4, which also moves Petri's
run format to 8; the attach snapshot records it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-09-26 16:59:22 -04:00
parent 8ab3c7c63c
commit 4ad3d2b793
No known key found for this signature in database
3 changed files with 50 additions and 19 deletions

30
Cargo.lock generated
View file

@ -5162,7 +5162,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "petri-attractor-steps"
version = "0.1.0"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#62483bad9fbaaa8b6261fc54f6a67b7df57a3212"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#ded1df4f2ad80fa790d807fe4abed89887399392"
dependencies = [
"async-trait",
"globset",
@ -5193,7 +5193,7 @@ dependencies = [
[[package]]
name = "petri-driver"
version = "0.1.0"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#62483bad9fbaaa8b6261fc54f6a67b7df57a3212"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#ded1df4f2ad80fa790d807fe4abed89887399392"
dependencies = [
"async-trait",
"getrandom 0.3.4",
@ -5213,7 +5213,7 @@ dependencies = [
[[package]]
name = "petri-engine"
version = "0.1.0"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#62483bad9fbaaa8b6261fc54f6a67b7df57a3212"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#ded1df4f2ad80fa790d807fe4abed89887399392"
dependencies = [
"petri-ir",
"serde",
@ -5225,7 +5225,7 @@ dependencies = [
[[package]]
name = "petri-execution"
version = "0.1.0"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#62483bad9fbaaa8b6261fc54f6a67b7df57a3212"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#ded1df4f2ad80fa790d807fe4abed89887399392"
dependencies = [
"async-trait",
"petri-driver",
@ -5249,7 +5249,7 @@ dependencies = [
[[package]]
name = "petri-executor"
version = "0.1.0"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#62483bad9fbaaa8b6261fc54f6a67b7df57a3212"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#ded1df4f2ad80fa790d807fe4abed89887399392"
dependencies = [
"async-trait",
"libc",
@ -5264,7 +5264,7 @@ dependencies = [
[[package]]
name = "petri-executor-sandbox"
version = "0.1.0"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#62483bad9fbaaa8b6261fc54f6a67b7df57a3212"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#ded1df4f2ad80fa790d807fe4abed89887399392"
dependencies = [
"async-trait",
"petri-executor",
@ -5286,7 +5286,7 @@ dependencies = [
[[package]]
name = "petri-frontend"
version = "0.1.0"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#62483bad9fbaaa8b6261fc54f6a67b7df57a3212"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#ded1df4f2ad80fa790d807fe4abed89887399392"
dependencies = [
"marked-yaml",
"petri-ir",
@ -5300,7 +5300,7 @@ dependencies = [
[[package]]
name = "petri-frontend-attractor"
version = "0.1.0"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#62483bad9fbaaa8b6261fc54f6a67b7df57a3212"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#ded1df4f2ad80fa790d807fe4abed89887399392"
dependencies = [
"minijinja",
"petri-frontend",
@ -5317,7 +5317,7 @@ dependencies = [
[[package]]
name = "petri-frontend-fabro"
version = "0.1.0"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#62483bad9fbaaa8b6261fc54f6a67b7df57a3212"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#ded1df4f2ad80fa790d807fe4abed89887399392"
dependencies = [
"petri-frontend",
"petri-frontend-attractor",
@ -5333,7 +5333,7 @@ dependencies = [
[[package]]
name = "petri-frontend-native"
version = "0.1.0"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#62483bad9fbaaa8b6261fc54f6a67b7df57a3212"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#ded1df4f2ad80fa790d807fe4abed89887399392"
dependencies = [
"petri-frontend",
"petri-ir",
@ -5344,7 +5344,7 @@ dependencies = [
[[package]]
name = "petri-ir"
version = "0.1.0"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#62483bad9fbaaa8b6261fc54f6a67b7df57a3212"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#ded1df4f2ad80fa790d807fe4abed89887399392"
dependencies = [
"regex",
"serde",
@ -5357,7 +5357,7 @@ dependencies = [
[[package]]
name = "petri-runtime"
version = "0.1.0"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#62483bad9fbaaa8b6261fc54f6a67b7df57a3212"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#ded1df4f2ad80fa790d807fe4abed89887399392"
dependencies = [
"async-trait",
"petri-driver",
@ -5378,7 +5378,7 @@ dependencies = [
[[package]]
name = "petri-steps"
version = "0.1.0"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#62483bad9fbaaa8b6261fc54f6a67b7df57a3212"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#ded1df4f2ad80fa790d807fe4abed89887399392"
dependencies = [
"async-trait",
"petri-executor",
@ -5394,7 +5394,7 @@ dependencies = [
[[package]]
name = "petri-store"
version = "0.1.0"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#62483bad9fbaaa8b6261fc54f6a67b7df57a3212"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#ded1df4f2ad80fa790d807fe4abed89887399392"
dependencies = [
"async-trait",
"getrandom 0.3.4",
@ -5409,7 +5409,7 @@ dependencies = [
[[package]]
name = "petri-testkit"
version = "0.1.0"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#62483bad9fbaaa8b6261fc54f6a67b7df57a3212"
source = "git+https://github.com/lithoscomputer/petri.git?branch=main#ded1df4f2ad80fa790d807fe4abed89887399392"
dependencies = [
"async-trait",
"petri-driver",

View file

@ -904,7 +904,7 @@ fn attach_json_errors_without_prompting_for_human_input() {
"recorded_at": "[EPOCH_MS]",
"body": {
"event": "run.started",
"format_version": 7,
"format_version": 8,
"key": "[ULID]",
"root": 0,
"middleware_chain": [

View file

@ -13,7 +13,7 @@ use fabro_types::{
use petri_execution::events::{Derived, RunEvent, Subject, ViewEvent, WaitState};
use petri_execution::{ExecutionId, InvocationId};
use petri_runtime::engine::{Admission, Event};
use petri_runtime::ir::{Metrics, Status};
use petri_runtime::ir::{Metrics, Status, UnderlyingFailure};
use serde_json::Value;
use tracing::debug;
@ -382,9 +382,12 @@ pub(super) fn failure_message(status: &Status) -> Option<String> {
match status {
Status::Failure(info)
| Status::PartialSuccess {
underlying: Some(info),
underlying: Some(UnderlyingFailure::Failure(info)),
} => Some(info.message.clone()),
Status::TimedOut => Some("the step timed out".to_string()),
Status::TimedOut
| Status::PartialSuccess {
underlying: Some(UnderlyingFailure::TimedOut),
} => Some("the step timed out".to_string()),
Status::Cancelled => Some("the step was cancelled".to_string()),
Status::Success | Status::PartialSuccess { underlying: None } | Status::Skipped => None,
}
@ -451,3 +454,31 @@ fn apply_metrics(stage: &mut StageProjection, metrics: &Metrics) {
}
}
}
#[cfg(test)]
mod tests {
use petri_runtime::ir::FailureInfo;
use super::*;
/// A partial success reports the failure it was converted from, a
/// timeout included, and its outcome stays a partial success.
#[test]
fn a_partial_success_reports_the_failure_it_came_from() {
let failed = Status::partial(FailureInfo::new("tests failed"));
let timed_out = Status::PartialSuccess {
underlying: Some(UnderlyingFailure::TimedOut),
};
let unexplained = Status::PartialSuccess { underlying: None };
assert_eq!(failure_message(&failed).as_deref(), Some("tests failed"));
assert_eq!(
failure_message(&timed_out).as_deref(),
Some("the step timed out")
);
assert_eq!(failure_message(&unexplained), None);
for status in [&failed, &timed_out, &unexplained] {
assert_eq!(stage_outcome(status), StageOutcome::PartiallySucceeded);
}
}
}