This is an automated email from the ASF dual-hosted git repository.

luigidemasi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-kit.git

commit d449ffde636fe34009dd057eded2d3e1feb441ae
Author: Jinal Sarvaiya <[email protected]>
AuthorDate: Sun Nov 1 23:35:42 2026 +0000

    fix #100: exercise production coordinator submit and guard Pi against 
backend injection
---
 .../camel/kit/command/ship/ShipCommandTest.java    | 43 +++++++++++++++++++---
 .../kit/generator/ShippedAssetStructureTest.java   |  4 +-
 2 files changed, 40 insertions(+), 7 deletions(-)

diff --git 
a/kit/camel-kit-core/src/test/java/org/apache/camel/kit/command/ship/ShipCommandTest.java
 
b/kit/camel-kit-core/src/test/java/org/apache/camel/kit/command/ship/ShipCommandTest.java
index d4771ea3..a45dd0b4 100644
--- 
a/kit/camel-kit-core/src/test/java/org/apache/camel/kit/command/ship/ShipCommandTest.java
+++ 
b/kit/camel-kit-core/src/test/java/org/apache/camel/kit/command/ship/ShipCommandTest.java
@@ -14,11 +14,13 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Objects;
 
+import org.apache.camel.kit.config.DistributionConfig;
 import org.apache.camel.kit.ship.ShipDigest;
 import org.apache.camel.kit.ship.context.ShipContext;
 import org.apache.camel.kit.ship.context.ShipContext.Kind;
 import org.apache.camel.kit.ship.controller.ShipController;
 import org.apache.camel.kit.ship.controller.ShipControllerTestSupport;
+import org.apache.camel.kit.ship.controller.ShipCoordinator;
 import org.apache.camel.kit.ship.controller.ShipRun;
 
 import org.junit.jupiter.api.Assumptions;
@@ -222,15 +224,46 @@ class ShipCommandTest {
         assertEquals(1, mismatchClaude.exitCode());
         assertTrue(mismatchClaude.error().contains("execution-mode-mismatch"), 
mismatchClaude.error());
 
+        Assumptions.assumeTrue(
+                Files.getFileStore(tempDir).supportsFileAttributeView("posix"),
+                "Pi coordinator requires POSIX executable files");
+        Path fakePi = writeExecutable(tempDir.resolve("fake-pi"), 
"#!/bin/sh\nexit 1\n");
+        Path fakeNode = writeExecutable(tempDir.resolve("fake-node"), 
"#!/bin/sh\nexit 1\n");
+        ShipCoordinator coordinator = new ShipCoordinator(
+                tempDir.resolve("state"), fakePi, fakeNode,
+                tempDir.resolve("repo"),
+                DistributionConfig.loadBundled(),
+                Duration.ofMinutes(10), false);
+        ShipCommand.WorkflowLauncher coordinatorLauncher = settings -> new 
ShipCommand.Workflow() {
+            @Override
+            public ShipRun run(String runId) throws IOException, 
InterruptedException {
+                return coordinator.run(runId);
+            }
+
+            @Override
+            public ShipRun resume(String runId, List<? extends 
ShipContext.Input> additions)
+                    throws IOException, InterruptedException {
+                return coordinator.resume(runId, additions);
+            }
+
+            @Override
+            public ShipRun submit(String runId, Path resultFile) throws 
IOException, InterruptedException {
+                return coordinator.submit(runId, resultFile);
+            }
+        };
+
         Path fakeResult = Files.writeString(tempDir.resolve("fake.json"), 
"{}");
-        RunResult submitted = run(controller, 
RecordingLauncher.passThrough(controller),
+        RunResult submitted = run(controller, coordinatorLauncher,
                 "--project-dir", project.toString(),
                 "--submit", id, "--result", fakeResult.toString());
         assertEquals(1, submitted.exitCode());
-        assertTrue(submitted.error().contains("execution-mode-mismatch")
-                || submitted.error().contains("no-pending-task")
-                || submitted.error().contains("requires a native backend"),
-                "Pi run must reject --submit: " + submitted.error());
+        assertTrue(submitted.error().contains("requires a native Ship run"),
+                "Pi run must reject --submit through the production 
coordinator: " + submitted.error());
+        ShipRun afterSubmit = controller.status(id);
+        assertEquals(ShipRun.ExecutionMode.PI, afterSubmit.executionMode(),
+                "Run state must be unchanged after rejected submit");
+        assertEquals(ShipRun.RunStatus.RUNNING, afterSubmit.status(),
+                "Run status must be unchanged after rejected submit");
     }
 
     @Test
diff --git 
a/kit/camel-kit-core/src/test/java/org/apache/camel/kit/generator/ShippedAssetStructureTest.java
 
b/kit/camel-kit-core/src/test/java/org/apache/camel/kit/generator/ShippedAssetStructureTest.java
index facde7a0..ae47f4c5 100644
--- 
a/kit/camel-kit-core/src/test/java/org/apache/camel/kit/generator/ShippedAssetStructureTest.java
+++ 
b/kit/camel-kit-core/src/test/java/org/apache/camel/kit/generator/ShippedAssetStructureTest.java
@@ -887,8 +887,8 @@ class ShippedAssetStructureTest {
                     agentName + " Ship skill must not reference retired guide 
" + guide);
         }
         if ("pi".equals(agentName)) {
-            assertFalse(skillContent.contains("--backend pi-native"),
-                    "Pi Ship skill must not reference a pi-native backend");
+            assertFalse(skillContent.contains("--backend"),
+                    "Pi Ship skill must not select any backend");
             assertFalse(skillContent.contains("spawn_subagent"),
                     "Pi Ship skill must not dispatch native subagents");
             assertFalse(skillContent.contains("invoke_subagent"),

Reply via email to