Skip to content

feat(stepfunctions): add execution lifecycle with Pass/Succeed/Fail interpreter#241

Merged
vieiralucas merged 1 commit intomainfrom
worktree-batch-2-execution-lifecycle
Apr 11, 2026
Merged

feat(stepfunctions): add execution lifecycle with Pass/Succeed/Fail interpreter#241
vieiralucas merged 1 commit intomainfrom
worktree-batch-2-execution-lifecycle

Conversation

@vieiralucas
Copy link
Copy Markdown
Member

@vieiralucas vieiralucas commented Apr 11, 2026

Summary

  • 6 new operations: StartExecution, StopExecution, DescribeExecution, ListExecutions, GetExecutionHistory, DescribeStateMachineForExecution
  • ASL interpreter executing Pass, Succeed, and Fail state types with InputPath/ResultPath/OutputPath processing
  • Async execution via tokio::spawn — StartExecution returns immediately, interpreter runs in background
  • Execution history events recorded for each state transition

Test plan

  • 25 E2E tests (12 new) covering execution lifecycle, Pass chains, ResultPath, Succeed/Fail states
  • 14 conformance tests (6 new) with Smithy model checksums
  • 15 unit tests for interpreter and I/O processing
  • cargo clippy --workspace --all-targets -- -D warnings clean

Summary by cubic

Adds a Step Functions execution lifecycle with an async interpreter for Pass, Succeed, and Fail states, including path processing and execution history. Exposes execution APIs so state machines can run end to end.

  • New Features

    • New APIs: StartExecution, StopExecution, DescribeExecution, ListExecutions, GetExecutionHistory, DescribeStateMachineForExecution
    • Async execution via tokio::spawn; StartExecution returns immediately
    • ASL interpreter for Pass/Succeed/Fail with InputPath/ResultPath/OutputPath (simple JSONPath)
    • Execution history recorded with event details; ListExecutions supports status filtering and pagination
  • Dependencies

    • Add tokio to crates/fakecloud-stepfunctions

Written for commit f9982f1. Summary will update on new commits.

…nterpreter

- StartExecution, StopExecution, DescribeExecution, ListExecutions,
  GetExecutionHistory, DescribeStateMachineForExecution
- ASL interpreter with Pass, Succeed, and Fail state types
- InputPath/ResultPath/OutputPath processing with simple JsonPath
- Async execution via tokio::spawn with history event recording
- 12 new E2E tests (25 total), 6 new conformance tests (14 total)
- 15 unit tests for interpreter and I/O processing
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 issues found across 8 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="crates/fakecloud-stepfunctions/src/service.rs">

<violation number="1" location="crates/fakecloud-stepfunctions/src/service.rs:395">
P1: Stopped executions can be overwritten by the background interpreter and end up SUCCEEDED/FAILED instead of ABORTED.</violation>
</file>

<file name="crates/fakecloud-stepfunctions/src/io_processing.rs">

<violation number="1" location="crates/fakecloud-stepfunctions/src/io_processing.rs:88">
P1: Avoid unwrapping `get_mut` in path traversal; non-object intermediates can cause a panic.</violation>

<violation number="2" location="crates/fakecloud-stepfunctions/src/io_processing.rs:105">
P1: Guard bracket parsing before slicing to prevent panics on malformed path segments.</violation>
</file>

<file name="crates/fakecloud-stepfunctions/src/interpreter.rs">

<violation number="1" location="crates/fakecloud-stepfunctions/src/interpreter.rs:248">
P1: JSON `null` paths (e.g. `"InputPath": null`) are never detected. `Value::Null.as_str()` returns `None`, so `== Some("null")` never matches. This silently breaks `ResultPath: null` (result replaces input instead of being discarded) and `InputPath/OutputPath: null` (input passes through instead of becoming `{}`).

Check for JSON null on the `Value` directly before extracting the string:</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

}

let now = Utc::now();
exec.status = ExecutionStatus::Aborted;
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Stopped executions can be overwritten by the background interpreter and end up SUCCEEDED/FAILED instead of ABORTED.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At crates/fakecloud-stepfunctions/src/service.rs, line 395:

<comment>Stopped executions can be overwritten by the background interpreter and end up SUCCEEDED/FAILED instead of ABORTED.</comment>

<file context>
@@ -261,6 +277,276 @@ impl StepFunctionsService {
+        }
+
+        let now = Utc::now();
+        exec.status = ExecutionStatus::Aborted;
+        exec.stop_date = Some(now);
+        exec.error = error;
</file context>
Fix with Cubic

for part in path.split('.') {
if let Some(bracket_pos) = part.find('[') {
let name = &part[..bracket_pos];
let idx_str = &part[bracket_pos + 1..part.len() - 1];
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Guard bracket parsing before slicing to prevent panics on malformed path segments.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At crates/fakecloud-stepfunctions/src/io_processing.rs, line 105:

<comment>Guard bracket parsing before slicing to prevent panics on malformed path segments.</comment>

<file context>
@@ -0,0 +1,193 @@
+    for part in path.split('.') {
+        if let Some(bracket_pos) = part.find('[') {
+            let name = &part[..bracket_pos];
+            let idx_str = &part[bracket_pos + 1..part.len() - 1];
+            if let Ok(idx) = idx_str.parse::<usize>() {
+                segments.push(PathSegment::Index(name, idx));
</file context>
Fix with Cubic

obj.insert(segment.to_string(), serde_json::json!({}));
}
}
current = current.get_mut(*segment).unwrap();
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Avoid unwrapping get_mut in path traversal; non-object intermediates can cause a panic.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At crates/fakecloud-stepfunctions/src/io_processing.rs, line 88:

<comment>Avoid unwrapping `get_mut` in path traversal; non-object intermediates can cause a panic.</comment>

<file context>
@@ -0,0 +1,193 @@
+                    obj.insert(segment.to_string(), serde_json::json!({}));
+                }
+            }
+            current = current.get_mut(*segment).unwrap();
+        }
+    }
</file context>
Suggested change
current = current.get_mut(*segment).unwrap();
current = match current.get_mut(*segment) {
Some(v) => v,
None => return result,
};
Fix with Cubic

let output_path = state_def["OutputPath"].as_str();

// Step 1: Apply InputPath
let effective_input = if input_path == Some("null") {
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: JSON null paths (e.g. "InputPath": null) are never detected. Value::Null.as_str() returns None, so == Some("null") never matches. This silently breaks ResultPath: null (result replaces input instead of being discarded) and InputPath/OutputPath: null (input passes through instead of becoming {}).

Check for JSON null on the Value directly before extracting the string:

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At crates/fakecloud-stepfunctions/src/interpreter.rs, line 248:

<comment>JSON `null` paths (e.g. `"InputPath": null`) are never detected. `Value::Null.as_str()` returns `None`, so `== Some("null")` never matches. This silently breaks `ResultPath: null` (result replaces input instead of being discarded) and `InputPath/OutputPath: null` (input passes through instead of becoming `{}`).

Check for JSON null on the `Value` directly before extracting the string:</comment>

<file context>
@@ -0,0 +1,561 @@
+    let output_path = state_def["OutputPath"].as_str();
+
+    // Step 1: Apply InputPath
+    let effective_input = if input_path == Some("null") {
+        json!({})
+    } else {
</file context>
Fix with Cubic

@vieiralucas vieiralucas merged commit f4bcfdf into main Apr 11, 2026
22 checks passed
@vieiralucas vieiralucas deleted the worktree-batch-2-execution-lifecycle branch April 11, 2026 05:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant