diff --git a/test/integration/Elsa.Activities.IntegrationTests/Composition/Activities/InnerComposite.cs b/test/integration/Elsa.Activities.IntegrationTests/Composition/Activities/InnerComposite.cs
new file mode 100644
index 000000000..3f3e737df
--- /dev/null
+++ b/test/integration/Elsa.Activities.IntegrationTests/Composition/Activities/InnerComposite.cs
@@ -0,0 +1,32 @@
+using Elsa.Workflows;
+using Elsa.Workflows.Activities;
+
+namespace Elsa.Activities.IntegrationTests.Composition.Activities;
+
+///
+/// Inner composite activity that uses Complete.
+///
+public class InnerComposite : Composite
+{
+ private readonly WriteLine _completedMessage = new("Inner composite completed");
+
+ public InnerComposite()
+ {
+ Root = new Sequence
+ {
+ Activities =
+ {
+ new WriteLine("Inner composite started"),
+ new Complete(),
+ new WriteLine("This should not execute in inner"),
+ _completedMessage
+ }
+ };
+ }
+
+ protected override async ValueTask OnCompletedAsync(ActivityCompletedContext context)
+ {
+ // Schedule the completion message
+ await context.TargetContext.ScheduleActivityAsync(_completedMessage);
+ }
+}
\ No newline at end of file
diff --git a/test/integration/Elsa.Activities.IntegrationTests/Composition/Activities/OuterComposite.cs b/test/integration/Elsa.Activities.IntegrationTests/Composition/Activities/OuterComposite.cs
new file mode 100644
index 000000000..9de2de220
--- /dev/null
+++ b/test/integration/Elsa.Activities.IntegrationTests/Composition/Activities/OuterComposite.cs
@@ -0,0 +1,21 @@
+using Elsa.Workflows.Activities;
+
+namespace Elsa.Activities.IntegrationTests.Composition.Activities;
+
+///
+/// Outer composite activity for nested composite testing.
+///
+public class OuterComposite : Composite
+{
+ public OuterComposite()
+ {
+ Root = new Sequence
+ {
+ Activities =
+ {
+ new InnerComposite(),
+ new WriteLine("After inner composite")
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/test/integration/Elsa.Activities.IntegrationTests/Composition/Activities/SimpleComposite.cs b/test/integration/Elsa.Activities.IntegrationTests/Composition/Activities/SimpleComposite.cs
new file mode 100644
index 000000000..22f2be050
--- /dev/null
+++ b/test/integration/Elsa.Activities.IntegrationTests/Composition/Activities/SimpleComposite.cs
@@ -0,0 +1,22 @@
+using Elsa.Workflows.Activities;
+
+namespace Elsa.Activities.IntegrationTests.Composition.Activities;
+
+///
+/// Simple composite activity that uses Complete to terminate early.
+///
+public class SimpleComposite : Composite
+{
+ public SimpleComposite()
+ {
+ Root = new Sequence
+ {
+ Activities =
+ {
+ new WriteLine("Before Complete"),
+ new Complete(),
+ new WriteLine("This should not execute")
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/test/integration/Elsa.Activities.IntegrationTests/Composition/CompleteTests.cs b/test/integration/Elsa.Activities.IntegrationTests/Composition/CompleteTests.cs
new file mode 100644
index 000000000..b0ea0651a
--- /dev/null
+++ b/test/integration/Elsa.Activities.IntegrationTests/Composition/CompleteTests.cs
@@ -0,0 +1,47 @@
+using Elsa.Activities.IntegrationTests.Composition.Workflows;
+using Elsa.Testing.Shared;
+using Elsa.Workflows;
+using Elsa.Workflows.Activities;
+using Xunit.Abstractions;
+
+namespace Elsa.Activities.IntegrationTests.Composition;
+
+///
+/// Integration tests for the activity.
+///
+public class CompleteTests(ITestOutputHelper testOutputHelper)
+{
+ private readonly WorkflowTestFixture _fixture = new WorkflowTestFixture(testOutputHelper)
+ .AddWorkflow()
+ .AddWorkflow();
+
+ [Fact(DisplayName = "Complete terminates composite execution immediately")]
+ public async Task Complete_TerminatesCompositeExecutionImmediately()
+ {
+ // Act
+ var workflowState = await _fixture.RunWorkflowAsync(CompleteTerminatesCompositeWorkflow.DefinitionId);
+
+ // Assert
+ Assert.Equal(WorkflowStatus.Finished, workflowState.Status);
+ var lines = _fixture.CapturingTextWriter.Lines.ToList();
+ Assert.Contains("Before Complete", lines);
+ Assert.DoesNotContain("This should not execute", lines);
+ Assert.Contains("After composite", lines);
+ }
+
+ [Fact(DisplayName = "Complete in nested composite completes immediate parent only")]
+ public async Task Complete_InNestedComposite_CompletesImmediateParentOnly()
+ {
+ // Act
+ var workflowState = await _fixture.RunWorkflowAsync(CompleteInNestedCompositeWorkflow.DefinitionId);
+
+ // Assert
+ Assert.Equal(WorkflowStatus.Finished, workflowState.Status);
+ var lines = _fixture.CapturingTextWriter.Lines.ToList();
+ Assert.Contains("Outer composite started", lines);
+ Assert.Contains("Inner composite started", lines);
+ Assert.Contains("Inner composite completed", lines);
+ Assert.Contains("Outer composite completed", lines);
+ Assert.DoesNotContain("This should not execute in inner", lines);
+ }
+}
\ No newline at end of file
diff --git a/test/integration/Elsa.Activities.IntegrationTests/Composition/Workflows/CompleteInNestedCompositeWorkflow.cs b/test/integration/Elsa.Activities.IntegrationTests/Composition/Workflows/CompleteInNestedCompositeWorkflow.cs
new file mode 100644
index 000000000..5f84b5e62
--- /dev/null
+++ b/test/integration/Elsa.Activities.IntegrationTests/Composition/Workflows/CompleteInNestedCompositeWorkflow.cs
@@ -0,0 +1,27 @@
+using Elsa.Activities.IntegrationTests.Composition.Activities;
+using Elsa.Workflows;
+using Elsa.Workflows.Activities;
+
+namespace Elsa.Activities.IntegrationTests.Composition.Workflows;
+
+///
+/// Workflow with nested composite activities to verify Complete only affects immediate parent.
+///
+public class CompleteInNestedCompositeWorkflow : WorkflowBase
+{
+ public static readonly string DefinitionId = Guid.NewGuid().ToString();
+
+ protected override void Build(IWorkflowBuilder workflow)
+ {
+ workflow.WithDefinitionId(DefinitionId);
+ workflow.Root = new Sequence
+ {
+ Activities =
+ {
+ new WriteLine("Outer composite started"),
+ new OuterComposite(),
+ new WriteLine("Outer composite completed")
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/test/integration/Elsa.Activities.IntegrationTests/Composition/Workflows/CompleteTerminatesCompositeWorkflow.cs b/test/integration/Elsa.Activities.IntegrationTests/Composition/Workflows/CompleteTerminatesCompositeWorkflow.cs
new file mode 100644
index 000000000..af589932b
--- /dev/null
+++ b/test/integration/Elsa.Activities.IntegrationTests/Composition/Workflows/CompleteTerminatesCompositeWorkflow.cs
@@ -0,0 +1,26 @@
+using Elsa.Activities.IntegrationTests.Composition.Activities;
+using Elsa.Workflows;
+using Elsa.Workflows.Activities;
+
+namespace Elsa.Activities.IntegrationTests.Composition.Workflows;
+
+///
+/// Workflow demonstrating that Complete terminates composite execution immediately.
+///
+public class CompleteTerminatesCompositeWorkflow : WorkflowBase
+{
+ public static readonly string DefinitionId = Guid.NewGuid().ToString();
+
+ protected override void Build(IWorkflowBuilder workflow)
+ {
+ workflow.WithDefinitionId(DefinitionId);
+ workflow.Root = new Sequence
+ {
+ Activities =
+ {
+ new SimpleComposite(),
+ new WriteLine("After composite")
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/test/unit/Elsa.Activities.UnitTests/Composition/CompleteTests.cs b/test/unit/Elsa.Activities.UnitTests/Composition/CompleteTests.cs
new file mode 100644
index 000000000..843e7fa65
--- /dev/null
+++ b/test/unit/Elsa.Activities.UnitTests/Composition/CompleteTests.cs
@@ -0,0 +1,34 @@
+using Elsa.Testing.Shared;
+using Elsa.Workflows;
+
+namespace Elsa.Activities.UnitTests.Composition;
+
+///
+/// Unit tests for the activity.
+///
+public class CompleteTests
+{
+ [Fact(DisplayName = "Complete implements ITerminalNode interface")]
+ public void Complete_ImplementsITerminalNode()
+ {
+ // Arrange
+ var completeActivity = new Complete();
+
+ // Assert
+ Assert.IsAssignableFrom(completeActivity);
+ }
+
+ [Fact(DisplayName = "Complete completes execution")]
+ public async Task Complete_CompletesExecution()
+ {
+ // Arrange
+ var completeActivity = new Complete();
+ var fixture = new ActivityTestFixture(completeActivity);
+
+ // Act
+ var context = await fixture.ExecuteAsync();
+
+ // Assert
+ Assert.Equal(ActivityStatus.Completed, context.Status);
+ }
+}