Back to feed

sledtools/pika branch #98

pika-cloud-local-guest-results

Pin local guest result contracts

Target branch: master

Merge Commit: eaba719d79405f6270e6f21429b8be16f6d67a30

branch: merged tutorial: ready ci: success
Open CI Details

Continuous Integration

CI: success

Compact status on the review page, with full logs on the CI page.

Open CI Details

Latest run #124 success

6 passed

head 398bb6866275eac6c9fc908490f7704d149cc201 · queued 2026-03-26 01:47:21 · 6 lane(s)

queued 14s · ran 28s

check-notifications · success check-agent-contracts · success check-pikachat · success check-pikachat-typescript · success check-pikachat-openclaw-e2e · success check-fixture · success

Summary

This branch pins the local guest result contract by replacing the hard-coded schema version literal in the Incus guest script with a shared LIFECYCLE_SCHEMA_VERSION constant imported from pika_cloud, and adds comprehensive assertion-based tests to ensure both the Tart (macOS) and local Linux guest scripts emit the exact same terminal-result JSON vocabulary. A new helper reads the Linux guest Nix module source at compile time so the test suite can verify its result contract in lockstep with the rest of the codebase.

Tutorial Steps

Import the shared LIFECYCLE_SCHEMA_VERSION constant

Intent: Replace the implicit, hard-coded schema version with an authoritative constant so every guest script references a single source of truth for the result-contract version.

Affected files: crates/pikaci/src/executor.rs

Evidence
@@ -11,9 +11,10 @@ use anyhow::{Context, anyhow, bail};
 use pika_cloud::{
-    CLOUD_GUEST_LOG_PATH, EVENTS_PATH, GUEST_REQUEST_PATH, IncusGuestRunRequest, RESULT_PATH,
-    RuntimeResultStatus, RuntimeTerminalResult, STATUS_PATH, encode_runtime_terminal_result_pretty,
-    load_runtime_terminal_result, runtime_terminal_result_for_exit_code,
+    CLOUD_GUEST_LOG_PATH, EVENTS_PATH, GUEST_REQUEST_PATH, IncusGuestRunRequest,
+    LIFECYCLE_SCHEMA_VERSION, RESULT_PATH, RuntimeResultStatus, RuntimeTerminalResult, STATUS_PATH,
+    encode_runtime_terminal_result_pretty, load_runtime_terminal_result,
+    runtime_terminal_result_for_exit_code,

The production use block in executor.rs now imports LIFECYCLE_SCHEMA_VERSION from the pika_cloud crate alongside the other cloud constants. This is the constant that will replace every literal 1 previously embedded in the guest script template.

Substitute the constant into the Incus guest script template

Intent: Ensure the generated Incus guest script's `result.json` always carries the version declared by the shared constant rather than a manually maintained literal.

Affected files: crates/pikaci/src/executor.rs

Evidence
@@ -1647,7 +1648,7 @@ cat > "{artifacts_mount}/result.json" <<EOF
 {{
-  "schema_version": 1,
+  "schema_version": {LIFECYCLE_SCHEMA_VERSION},

Inside the heredoc that writes result.json from the Incus guest script, the hard-coded 1 is replaced with the Rust format-string interpolation {LIFECYCLE_SCHEMA_VERSION}. Because the template is built with format!, the constant is expanded at compile time into the script string, keeping the generated shell script correct while removing the duplication.

Import the constant into the test module

Intent: Make `LIFECYCLE_SCHEMA_VERSION` available inside `mod tests` so assertions can reference the same constant the production code uses.

Affected files: crates/pikaci/src/executor.rs

Evidence
@@ -2440,7 +2441,7 @@ mod tests {
     use pika_cloud::{
         CLOUD_GUEST_LOG_PATH, EVENTS_PATH, GUEST_REQUEST_PATH,
-        INCUS_GUEST_RUN_REQUEST_SCHEMA_VERSION, RESULT_PATH, STATUS_PATH,
+        INCUS_GUEST_RUN_REQUEST_SCHEMA_VERSION, LIFECYCLE_SCHEMA_VERSION, RESULT_PATH, STATUS_PATH,

The test module's own use pika_cloud import is extended with LIFECYCLE_SCHEMA_VERSION so that every test assertion about schema version compares against the canonical constant instead of a magic number.

Add a compile-time include for the local Linux guest Nix module

Intent: Give the test suite read access to the Nix module that defines the local Linux guest so its result-contract output can be verified without running Nix.

Affected files: crates/pikaci/src/executor.rs

Evidence
@@ -2479,6 +2480,10 @@ mod tests {
+    fn local_linux_guest_module_source() -> &'static str {
+        include_str!("../../../nix/pikaci/guest-module.nix")
+    }

A new test helper, local_linux_guest_module_source(), uses include_str! to embed the contents of nix/pikaci/guest-module.nix at compile time. This mirrors the existing incus_guest_image_source() pattern already used for the Incus image Nix file, keeping the approach consistent.

Strengthen the Tart guest script assertions

Intent: Replace the sparse three-line assertions with a comprehensive check that the Tart script emits every field of the terminal-result JSON contract, and add negative assertions to reject stale vocabulary.

Affected files: crates/pikaci/src/executor.rs

Evidence
@@ -2635,9 +2640,42 @@ fn tart_guest_script_writes_shared_terminal_result_vocabulary() {
-        assert!(script.contains("status=\"completed\""));
-        assert!(script.contains("\"schema_version\": 1"));
-        assert!(script.contains("\"status\": \"$status\""));
+        assert_contains_all(
+            &script,
+            &[
+                "status=\"completed\"",
+                "status=\"failed\"",
+                "cat > \"/Volumes/My Shared Files/artifacts/result.json\" <<EOF",
+                &format!("\"schema_version\": {LIFECYCLE_SCHEMA_VERSION}"),
+                "\"status\": \"$status\"",
+                "\"exit_code\": $code",
+                "\"finished_at\": \"$(date -u +\"%Y-%m-%dT%H:%M:%SZ\")\"",
+                "\"message\": \"$message\"",
+            ],
+        );
+        assert!(!script.contains("status=\"passed\""));
+        assert!(!script.contains("\"status\": \"passed\""));

The existing tart_guest_script_writes_shared_terminal_result_vocabulary test now uses the assert_contains_all helper to verify all expected JSON fields (schema_version, status, exit_code, finished_at, message) plus the heredoc target path. The schema version needle now interpolates LIFECYCLE_SCHEMA_VERSION so the test breaks automatically if the constant changes but the script template is not updated.

Two negative assertions (!contains("passed")) ensure the scripts never emit the legacy "passed" status value, which was previously replaced by "completed".

Add a contract-pinning test for the local Linux guest module

Intent: Guarantee that the Nix-defined local Linux guest writes a result.json whose structure matches the shared terminal-result contract, catching any accidental divergence at compile time.

Affected files: crates/pikaci/src/executor.rs

Evidence
@@ -2479,6 +2480,10 @@
+    #[test]
+    fn local_linux_guest_module_pins_shared_terminal_result_contract() {
+        let source = local_linux_guest_module_source();
+        assert_contains_all(
+            source,
+            &[
+                "status=\"completed\"",
+                "status=\"failed\"",
+                "cat > /artifacts/result.json <<EOF",
+                "\"schema_version\": 1",
+                "\"status\": \"$status\"",
+                "\"exit_code\": $code",
+                "\"finished_at\": \"$(date -Iseconds)\"",
+                "\"message\": \"$message\"",
+            ],
+        );
+        assert!(!source.contains("status=\"passed\""));
+        assert!(!source.contains("\"status\": \"passed\""));

A brand-new test, local_linux_guest_module_pins_shared_terminal_result_contract, reads the embedded Nix source and asserts the same contract fields that the Tart test checks. Note that the Linux guest currently hard-codes "schema_version": 1 and uses date -Iseconds (ISO-8601) instead of the date -u format used by the Tart script — both differences are intentional and captured faithfully in the needles.

The same negative assertions guard against the stale "passed" status value.

Tighten the assertion failure message

Intent: Make a pre-existing assertion message more generic so it applies to both Incus and local guest sources without misleading the reader.

Affected files: crates/pikaci/src/executor.rs

Evidence
@@ -2470,7 +2471,7 @@
-                "expected Incus guest image source to contain `{needle}`"
+                "expected source to contain `{needle}`"

The assert_contains_all helper's panic message previously referenced "Incus guest image source" specifically. Because the helper is now reused for multiple source kinds (Tart script, Linux Nix module), the message is shortened to the neutral "expected source to contain {needle}".

Diff