Skip to content

feat: support ephemeral job-style sandboxes #2879

Description

@krishicks

User Story

As an automation user, I want to create an ephemeral sandbox that runs one finite command, so that I can execute isolated jobs and determine their outcome from the command's exit status without managing a long-lived sandbox.

Problem Statement

OpenShell's canonical main-process lifecycle treats every main-process exit as a terminal sandbox error, including a successful exit with code 0. This is appropriate for persistent, deployment-style sandboxes whose canonical process is expected to remain running, but it prevents finite commands from completing successfully as part of sandbox creation.

OpenShell needs an explicit job-style lifecycle for finite workloads, distinct from the existing persistent lifecycle established by #2710.

Impact / Why This Matters

One-shot commands such as build steps, tests, batch processing, and automation tasks cannot use sandbox creation as a successful finite operation. A command that completes normally is reported as a runtime failure, so callers cannot distinguish successful job completion from provisioning or runtime failure.

The current workaround is to create a retained sandbox, run the command with sandbox exec, capture its result, and then delete the sandbox manually. That workflow is not atomic, requires extra lifecycle coordination, can leak resources when automation is interrupted, and does not provide a single job result.

Proposed Design

Allow users to explicitly create an ephemeral, job-style sandbox. The sandbox runs a finite command without requiring a long-lived, health-checked canonical process.

The user-visible lifecycle should behave as follows:

  • A command exit code of 0 completes the job successfully.
  • A nonzero command exit preserves and reports the command's failure status.
  • The command's stdout and stderr remain available to the caller.
  • The CLI and API status clearly distinguish successful command completion, command failure, and sandbox provisioning or runtime failure.
  • Resources are cleaned up according to the documented ephemeral lifecycle after command completion.
  • Docker, Podman, Kubernetes, and VM sandboxes expose consistent job semantics.

Persistent, deployment-style sandboxes retain their existing canonical-main-process behavior, including health checks and the expectation that the main process remains running.

Acceptance Criteria

  • A user can explicitly request an ephemeral/job-style sandbox through the supported CLI and API workflows.
  • The sandbox can run a finite command without requiring a long-lived, health-checked canonical process.
  • A command that exits with code 0 is reported as successful completion rather than a sandbox error.
  • A command that exits nonzero reports the command's failure status to the caller.
  • The caller can access the command's stdout and stderr.
  • CLI and API status distinguish successful completion, command failure, and provisioning or runtime failure.
  • Ephemeral sandbox resources are cleaned up according to the documented lifecycle, including when the command fails.
  • Persistent/deployment-style canonical-main-process behavior remains unchanged.
  • Job-style behavior is consistent across Docker, Podman, Kubernetes, and VM drivers.
  • User-facing lifecycle documentation explains how to choose between persistent and job-style sandboxes.

Alternatives Considered

Infer job semantics from any command supplied at creation

Treating every explicit command as a job would make finite commands convenient, but it would make long-running service commands ambiguous and could change the persistent canonical-main-process contract. An explicit lifecycle keeps intent clear.

Treat exit code 0 as success for every canonical main process

This would erase the distinction between a successfully completed job and a deployment-style sandbox whose required process unexpectedly stopped. The lifecycle mode should determine whether process exit represents completion or loss of service.

Create a retained sandbox, use sandbox exec, then delete it

This is the current workaround. It requires multiple non-atomic operations, burdens callers with cleanup, and can leak retained resources when automation is interrupted.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions