# Orb Runtime

One logical execution workspace for one ProjectIssue run. An Orb bundles an AgentOS actor, an OpenCode harness session, a Docker sandbox, a mounted repository workspace, project context, model-gateway configuration, process/log handling, normalized execution events, and a cleanup lifecycle.

## Architecture

```
┌──────────────────────────────────────────────────┐
│ OrbRuntime                                       │
│   creates OrbHandle instances                    │
├──────────────────────────────────────────────────┤
│ OrbHandle                                        │
│   ┌─────────────┐    ┌────────────────────────┐  │
│   │ AgentOS VM  │    │ Docker Sandbox         │  │
│   │ (OpenCode   │◄──►│ (bun, tests, builds,   │  │
│   │  ACP agent) │    │  repo checkout)        │  │
│   └─────────────┘    └────────────────────────┘  │
│        │                        │                │
│   session events           runProcess /          │
│   → normalized              createProcess        │
│     OrbEvent                                     │
└──────────────────────────────────────────────────┘
```

The AgentOS VM runs the OpenCode ACP adapter (lightweight agent loop, session management, durable identity). Heavy execution — package installs, test suites, builds — runs inside the Docker sandbox via `runProcess`. The sandbox filesystem is mounted into the VM at `/mnt/sandbox`.

## Domain model

| Type | Description |
| --- | --- |
| `OrbId` | Branded identifier for one Orb |
| `OrbRunId` | Branded identifier for one run attempt |
| `OrbSessionId` | Branded identifier for one OpenCode session |
| `OrbIdentity` | `{ projectId, runId, workUnitId }` — derives the actor key |
| `OrbState` | `creating → prepared → running → needs-input → completed/failed/cancelled → disposed` |
| `RunState` | `queued → provisioning → preparing → running → verifying → succeeded/failed/cancelled` |
| `OrbEvent` | Normalized, secret-free execution event |

Orb state and run state are separate state machines. The VM/sandbox lease state is never conflated with the product work-unit state.

## Tagged errors

| Error | Reasons |
| --- | --- |
| `OrbStateError` | `InvalidTransition`, `AlreadyDisposed`, `NotRunning` |
| `OrbSandboxError` | `DockerUnavailable`, `ContainerStart`, `CommandFailed`, `ContainerCleanup` |
| `OrbSessionError` | `OpenSession`, `PromptFailed`, `AgentNotInstalled`, `SessionNotFound` |
| `OrbConfigurationError` | `MissingGateway`, `MissingIdentity`, `InvalidModelConfig` |

## Environment variables

| Variable | Required | Description |
| --- | --- | --- |
| `ORB_PROOF` | Proof only | Set to `1` to run the proof fixture |
| `ORB_GATEWAY_API_KEY` | Proof only | Model gateway API key |
| `ORB_GATEWAY_BASE_URL` | Proof only | Model gateway base URL (OpenAI-compatible `/v1`) |
| `ORB_GATEWAY_MODEL` | Proof only | Model name |
| `ORB_GATEWAY_PROVIDER` | Proof only | Provider identifier |
| `ORB_DOCKER_IMAGE` | Optional | Docker image (default: `oven/bun:1.3-debian`) |
| `ORB_DOCKER_WORKSPACE` | Optional | Host workspace root (default: `/tmp/orb-workspaces`) |
| `RIVET_ENDPOINT` | Optional | AgentOS/RivetKit sidecar endpoint |

No permanent provider credentials are stored in project files. API keys are injected at runtime via the OpenCode config written to the VM filesystem, and all event output is passed through `redactSecrets`.

## Docker requirements

- Docker daemon running and accessible via `docker` CLI
- The proof fixture uses `oven/bun:1.3-debian` by default
- Containers run with `--cap-drop=ALL --security-opt=no-new-privileges`
- Memory limited to 2g, CPUs to 2
- Writable mount is the project workspace only

## Local startup

```bash
# Run the proof fixture
ORB_PROOF=1 \
ORB_GATEWAY_API_KEY=your-key \
ORB_GATEWAY_BASE_URL=https://ai.example.com/v1 \
ORB_GATEWAY_MODEL=glm-5.2 \
ORB_GATEWAY_PROVIDER=cheaptricks \
bun run scripts/orb-proof.ts
```

Stable markers: `ORB_PROOF_PASSED` (exit 0), `ORB_PROOF_BLOCKED` (exit 2), `ORB_PROOF_FAILED` (exit 1).

## Filesystem layout

```
Container (/workspace = host bind mount)
  /workspace/repository/     — project checkout
  /workspace/control/        — issue + context files
  /tmp/orb-pids/             — process PID tracking

AgentOS VM
  /mnt/sandbox/              — sandbox mount point
  /mnt/sandbox/repository/   — repo (via sandbox)
  /root/.config/opencode/    — OpenCode config
```

## Current limitations

- AgentOS VM creation requires the sidecar binary; the proof fixture exercises the Docker sandbox path and skips the OpenCode session when no sidecar is available.
- `sendProcessInput` is not supported by the Docker sandbox.
- No automatic merge or production deployment capability.
- No multi-region support.
- Interactive PTY sessions are not wired through the Docker sandbox.
