Skip to content

Execution Backends

coo1white edited this page Jun 8, 2026 · 2 revisions

Execution Backends (v0.1.29)

How CW lifts execution out of the kernel into a pluggable driver layer — node, bun, shell, container, remote, ci — without the kernel ever learning which driver ran a task.

The design mantra for this layer:

One narrow interface.
Many interchangeable drivers.
The kernel never knows which one ran.
Same evidence, any backend.
Fail closed, never downgrade.

The Borrowed Idea: A BSD Device-Driver / VFS Layer

CW models execution exactly like a BSD VFS / device-driver layer. There is ONE narrow ExecutionBackend interface (the mechanism) and many interchangeable drivers (the policy of how and where). The kernel — orchestrator, dispatch, pipeline-runner — issues the same call regardless of driver, the same way a filesystem issues read()/write() without knowing if the device is a disk, an SSD, or a network share.

selected backend -> sandbox attestation -> execution/delegation -> canonical envelope

1. Mechanism vs Policy

  • Kernel (mechanism, policy of intent): WHAT to run, and WHICH evidence to record.
  • Driver (policy of execution): HOW and WHERE it runs.

The kernel must contain no backend-specific branching. WHAT/WHERE is pushed to the edge, behind a three-member interface:

descriptor   which sandbox dimensions it enforces vs attests; local/remote; readiness
probe(ctx)   live, deterministic readiness check
run(request) execute or delegate under a sandbox profile; return a canonical envelope

2. The Sandbox Profile Is the Contract

Every driver MUST account for all five sandbox dimensions — read, write, command, network, env — declaring each as enforce, attest, or unsupported. This is the same enforce/attest split CW already used between itself and the host; backends just make it explicit and per-driver.

A driver may not pretend. What it cannot enforce, it must honestly attest (a verifiable claim the host/runner upholds) or mark unsupported.

3. Identical Envelopes, Any Backend

The result envelope, evidence refs, and provenance are schema-identical no matter which driver ran the task. The backend id and its sandbox attestation are recorded as provenance, not in the result.

This is the load-bearing invariant: because evidence is backend-independent, eval/replay, the verifier gates, and the v0.1.28 run registry stay completely agnostic to who executed a run. Running CW's own self-verify through node, shell, and bun yields byte-identical result and evidence; only provenance.backendId differs.

command:<command + args>
exitCode:<code>
stdoutSha256:sha256:<hex>

4. Fail Closed, Never Downgrade

If a required sandbox dimension is unsupported, the backend is not ready, the command is denied by the profile, or a delegating driver has no target, then run returns status: "refused" with attestation.status: "refused".

CW never silently runs a task unsandboxed when the requested profile cannot be honored, and never substitutes a different backend behind your back. Ambiguity is a refusal, not a guess.

5. CW Delegates; It Does Not Become the Executor

Consistent with CW's standing model (CW records evidence; the host runs workers), the container/remote/ci drivers delegate and record a handle + attestation + result. CW drives docker/podman, a remote runner, or a CI job through a thin adapter and captures verifiable evidence — it never reimplements a container runtime or a CI system.

6. Node by Default, Bun-Friendly — Not Bun-Only

The node driver is the default and reproduces pre-v0.1.29 behavior exactly. bun is a driver, not a kernel runtime: it executes via the Node-compatible runtime so evidence stays byte-stable, and attests Bun availability in provenance.

This keeps the standing distribution stance intact:

Node-compatible by default.
Bun-friendly where useful.
Bun-only only if the ecosystem standard changes.

Bun lives at the execution edge as an optional, fail-closed driver — never as a dependency of the kernel that every agent host would have to satisfy.

7. One Selection, Two Surfaces

Selection parallels --sandbox:

--backend <id>   (flag)   >   CW_BACKEND   (env)   >   node   (default)

backend list|show|probe and the --backend flag are declared once in src/capability-registry.ts, so the CLI and MCP render one data source and pass the v0.1.27 CLI ↔ MCP parity gate automatically. Selection is recorded in run state and surfaced in the v0.1.28 registry's backends field.

8. Backward Compatible by Construction

The backend fields are additive and optional. Old run state loads unchanged, runs with no backend selected behave exactly as before, and the ResultEnvelope schema (summary, findings, evidence) is untouched — backend id and attestation live in provenance and run state, never in the result.

How It Was Built

v0.1.29 was developed in dev-mode bootstrap (claude --plugin-dir): the live local plugin built its own next version, and the acceptance bar was self-referential — CW had to run its own build/verify across more than one backend with byte-identical evidence before the feature was considered done.

See Also

Clone this wiki locally