# Plan: WASI Host Adapter

## Overview

Implementation track for the WASI host adapter sketched in
`docs/proposals/wasi-host-adapter-proposal.md`. The proposal's Phase W.0
through W.8 decomposition is the source of truth; each task below maps to
one phase. This plan is ad-hoc until selected, and the v0 phases (W.1 and
W.2) are parallel-safe with the kernel-core selected milestone because
they touch only new userspace crates, demos, manifests, and Makefile
targets. Preview 2 / Component Model phases (W.7 onward) will touch
`schema/capos.capnp` and must serialise with other schema-touching plans
per `docs/plans/README.md` Concurrency Notes.

## Conflict Surface

Owned by this plan:

- `capos-wasm/` (NEW crate, standalone like `init/` and `capos-rt/`,
  built for the `targets/x86_64-unknown-capos.json` userspace target).
- `vendor/wasmi-no_std/` (NEW vendored runtime if upstream `no_std`
  flag is insufficient; otherwise a `cargo-vendor`-style mirror).
- `demos/wasi-hello-rust/`, `demos/wasi-hello-c/`,
  `demos/wasi-cli-args/`, `demos/wasi-random/`, `demos/wasi-fs/`,
  `demos/wasi-net/`, `demos/wasi-component-bridge/`,
  `demos/wasi-cue-evaluator/` (NEW per-phase smoke binaries).
- `Makefile` (new `wasm-host-build`, `run-wasm-host`,
  `wasm-hello-rust-build`, `wasm-hello-c-build`, `run-wasi-hello-rust`,
  `run-wasi-hello-c`, and successor `run-wasi-*` targets).
- Repo-root `system-wasm-host.cue` and per-phase
  `system-wasi-*.cue` focused-proof manifests.
- `docs/proposals/wasi-host-adapter-proposal.md` (status updates,
  closeout stamps, phase progress).
- `docs/plans/wasi-host-adapter.md` (this file).
- `docs/programming-languages.md` WASI row updates as phases land.
- `docs/proposals/userspace-binaries-proposal.md` Part 5 status note
  (cross-link only; the full proposal lives elsewhere).
- `docs/proposals/index.md` Future Architecture row for the new
  proposal.
- `WORKPLAN.md` ad-hoc track bullet update.
- `docs/plans/README.md` Track Map row update.

Do not touch from this plan:

- Kernel-core cap tables, scheduler, device manager, or the existing
  userspace runtime (`capos-rt/`).
- `tools/remote-session-client/` (owned by remote-session plan).
- Any other proposal/plan file that does not directly cross-reference
  this track.
- `docs/topics.md` (auto-regenerated; never edit manually).
- `schema/capos.capnp` until Phase W.7. When that phase begins, queue
  on the shared serial surface per `docs/plans/README.md` Concurrency
  Notes.

## Validation Commands

- `make fmt-check`
- `make generated-code-check`
- `cargo build --features qemu`
- `cargo test-config`
- `cargo test-lib`
- `cargo build-demos-capos`
- `make capos-rt-check`
- `make run-smoke`
- Per-phase smoke targets (added as the matching task lands):
  - W.1: `make run-wasm-host`
  - W.2: `make run-wasi-hello-rust`, `make run-wasi-hello-c`
  - W.3: `make run-wasi-cli-args`
  - W.4: `make run-wasi-random`
  - W.5: `make run-wasi-fs`
  - W.6: `make run-wasi-net`
  - W.7: `make run-wasi-component-bridge`
  - W.8: `make run-wasi-cue-evaluator`

Treat the matching `make run-wasi-*` target for the most recent phase
as required for any iteration that touches this plan's owned files.

## Success Criteria

Each landed phase must keep its `make run-wasi-*` target green, leave
unrelated `make run-*` targets unaffected, and stamp the phase closeout
in `docs/proposals/wasi-host-adapter-proposal.md` with commit hash and
minute-precision timestamp. The track is recorded done when Phase W.6 is
green (Preview 1 surface complete against the available cap surfaces);
W.7 and W.8 are layered milestones that close independently when their
dependencies land.

### Task 1: Phase W.0 — Decision and host runtime selection (planning)

- [x] Decide runtime: wasmi for v0; WAMR / wasmtime as W.7+ migration
      targets. Captured in
      `docs/proposals/wasi-host-adapter-proposal.md` Runtime Selection.
- [x] Land `docs/proposals/wasi-host-adapter-proposal.md` with the
      capability-mapping surface, phase decomposition, runtime survey,
      and open questions.
- [x] Land this plan file as the ralphex-shaped task list.
- [ ] Resolve the cross-cutting open questions §1 (per-instance vs
      per-process), §3 (`poll_oneoff` semantics), §6 (`environ_get`
      source), §7 (`args_get` source), and §8 (vendoring posture for
      wasmi) before W.1 starts. The vendoring decision in §8 gates the
      W.1 scaffold because Task 2 vendors wasmi and the fork-vs-mirror
      shape determines the directory layout. Working answers are
      captured in the proposal; promote each to a final decision when
      W.1 begins.

### Task 2: Phase W.1 — `capos-wasm` host process scaffold

- [ ] Create the `capos-wasm/` standalone userspace crate built on
      `capos-rt`.
- [ ] Vendor wasmi at a pinned tag with `default-features = false`. If
      upstream `no_std` is insufficient, fork into `vendor/wasmi-no_std/`
      with the dependency-trim patches noted in the proposal.
- [ ] Embed one hand-written empty `.wasm` blob in `.rodata` and
      compile/instantiate it with no imports; run `_start`; exit cleanly.
- [ ] Add `system-wasm-host.cue` (its own distinct CUE package; imports
      the shared `capos.local/cue/defaults` package per the slice-3
      defaults pattern).
- [ ] Add `make run-wasm-host` target. Smoke must print
      `[wasm-host] empty module instantiated and exited` and exit cleanly
      under QEMU.
- [ ] Update `docs/programming-languages.md` WASI row to note Phase W.1
      landed.
- [ ] Stamp the phase closeout in
      `docs/proposals/wasi-host-adapter-proposal.md` with commit hash
      and minute-precision timestamp.

### Task 3: Phase W.2 — WASI Preview 1 stdout-only

- [ ] Add `capos-wasm/src/wasi/` (Preview 1 import resolver).
- [ ] Implement `args_get`, `args_sizes_get`, `environ_get`,
      `environ_sizes_get` (all return empty), `clock_time_get(MONOTONIC)`
      via `Timer.now()`, `proc_exit`, `random_get` (gated on the
      in-tree `EntropySource` cap; refuse with `ERRNO_NOSYS` if absent),
      `fd_write(1, …)` via host's `Console.write_line`, `fd_write(2, …)`
      via the same or a separate log cap.
- [ ] Stub everything else as `ERRNO_NOSYS`. Verify a probe module
      receives `ERRNO_NOSYS` for each unimplemented import.
- [ ] Add `demos/wasi-hello-rust/` built for `wasm32-wasip1` and
      `demos/wasi-hello-c/` built with `clang --target=wasm32-wasi` (or
      wasi-sdk if available). Both must print `Hello from WASI on capOS`
      and exit cleanly.
- [ ] Add `system-wasi-hello-rust.cue` and `system-wasi-hello-c.cue`
      manifests; embed the produced `.wasm` blob bytes inline (no capnp
      schema change).
- [ ] Add `make run-wasi-hello-rust` and `make run-wasi-hello-c`
      targets.
- [ ] Update `docs/programming-languages.md` WASI row to note Phase W.2
      landed: C runs on capOS without any `libcapos`/POSIX work in tree.
- [ ] Stamp the phase closeout in the proposal.

### Task 4: Phase W.3 — Per-instance CapSet plumbing + LaunchParameters

- [ ] Define how the host adapter receives per-instance grants from the
      manifest. Extend the wasm-host CUE shape so each entry lists
      `{ binary, args, caps: { console, timer, random, preopens } }`.
- [ ] Cross-cutting: until a capOS `LaunchParameters` surface exists,
      ship a bounded text grant in the host adapter manifest as the v0
      argv source. Document the migration path so the future
      `LaunchParameters` surface replaces the bounded text grant when
      it lands.
- [ ] Add `demos/wasi-cli-args/` smoke that reads `argv[1]` and prints
      it back; assert the printed value matches the manifest grant.
- [ ] Add `system-wasi-cli-args.cue` and `make run-wasi-cli-args`
      target.
- [ ] Update the proposal Open Question §5 / §6 / §7 status as each is
      decided.
- [ ] Stamp the phase closeout in the proposal.

### Task 5: Phase W.4 — WASI Preview 1 random + clocks production-ready

- [ ] Wire the in-tree kernel `EntropySource` cap through the host
      adapter so `random_get` returns cryptographically-sourced bytes
      when the instance was granted entropy authority.
- [ ] Document wall-clock support as deferred until capOS has a
      wall-clock cap; `clock_time_get(REALTIME)` returns the documented
      sentinel error.
- [ ] Add `demos/wasi-random/` smoke that reads N random bytes through
      the host's granted `EntropySource` cap and asserts entropy bounds;
      ungranted manifest variant proves refusal.
- [ ] Add `system-wasi-random.cue` and `make run-wasi-random` target.
- [ ] Stamp the phase closeout in the proposal.

### Task 6: Phase W.5 — WASI Preview 1 filesystem (gated on Namespace/File caps)

- [ ] Map preopened-dir fds to `Namespace` caps from the manifest.
      Implement `path_open`, `fd_read`, `fd_write`, `fd_seek`,
      `fd_close`, `fd_filestat_get`, `fd_prestat_get`,
      `fd_prestat_dir_name` against the available
      `Namespace`/`File`/`Store` cap surface.
- [ ] Add `demos/wasi-fs/` smoke that reads and writes a file inside a
      preopened capOS namespace; assert ungranted-namespace path-open
      attempts return `ERRNO_BADF` / `ERRNO_ACCES`.
- [ ] Add `system-wasi-fs.cue` and `make run-wasi-fs` target.
- [ ] **Blocked** until the Namespace/File cap surface exists. Note the
      block in the proposal status header until storage proposals land.
- [ ] Stamp the phase closeout in the proposal once unblocked.

### Task 7: Phase W.6 — WASI Preview 1 sockets (gated on userspace network stack)

- [ ] Implement `sock_send`, `sock_recv`, `sock_shutdown` against
      `TcpSocket` / `UdpSocket` caps once the userspace network stack
      lands. Until then, ship an HTTP client over `Fetch`/`HttpEndpoint`
      as the v0 networking shim and document the migration path.
- [ ] Add `demos/wasi-net/` smoke that serves an HTTP response or
      drives an HTTP request inside a capOS process; assert
      ungranted-socket attempts fail closed.
- [ ] Add `system-wasi-net.cue` and `make run-wasi-net` target.
- [ ] **Blocked** until the userspace network stack (or the
      `Fetch`/`HttpEndpoint` v0 shim) lands.
- [ ] Stamp the phase closeout in the proposal once unblocked.

### Task 8: Phase W.7 — Move to wasmtime or migrate to WASI Preview 2 / Component Model

- [ ] Decide between (a) swapping wasmi for wasmtime once capOS
      userspace gains `std` and a futures executor, or (b) promoting
      wasmi to wasip2 / Component Model support once that maturity
      arrives. Capture the decision in the proposal.
- [ ] Map WIT resources to typed `OwnedCapability<T>` slots in the
      host adapter. Capability transfer between wasm components becomes
      a host-mediated resource handoff.
- [ ] Add `schema/capos.capnp` variants needed for Component Model
      resource bridging. **Schema serial-surface coordination required**:
      queue on the shared `schema/capos.capnp` serial surface per
      `docs/plans/README.md` Concurrency Notes; only one plan at a time
      may add or change interfaces in `schema/capos.capnp`. Run
      `make generated-code-check` before downstream Cargo builds.
- [ ] Add `demos/wasi-component-bridge/` smoke proving a wasm component
      exports a typed interface that a native capOS process invokes.
- [ ] Add `system-wasi-component-bridge.cue` and
      `make run-wasi-component-bridge` target.
- [ ] **Blocked** on the std-userspace decision (same blocker as the
      capnp-rpc rewrite in the remote-session plan).
- [ ] Stamp the phase closeout in the proposal once unblocked.

### Task 9: Phase W.8 — TinyGo / Go-on-WASI integration for CUE

- [ ] Build a CUE evaluator binary against TinyGo or upstream Go's
      `GOOS=wasip1`. Run it in the host adapter against a CUE source
      blob granted as a future `ScriptPackage` cap (same shape as the
      planned `LaunchParameters` work).
- [ ] Add `demos/wasi-cue-evaluator/` smoke that evaluates a small CUE
      expression and prints the canonicalised result.
- [ ] Add `system-wasi-cue-evaluator.cue` and
      `make run-wasi-cue-evaluator` target.
- [ ] Cross-link the bridge to native `GOOS=capos` planning in
      `docs/proposals/go-runtime-proposal.md`: WASI is the v0 path for
      CUE evaluation; native Go remains the path for full Go runtime
      semantics.
- [ ] Stamp the phase closeout in the proposal.
