Throwaway prototypes for Sausage v3. Plan and decisions: ~/research/sausage-v3/PLAN.md. Results and evidence: the spike READMEs.
72 lines
4.7 KiB
Markdown
72 lines
4.7 KiB
Markdown
# S2 shell experiment
|
|
|
|
The target is a brush shell inside WASI with external uutils commands in separate Wasmtime stores.
|
|
All instances share one world root through `sausage-vfs`.
|
|
The process import must preserve streaming, EOF, broken pipes, and exit codes.
|
|
|
|
## Reproduction
|
|
|
|
The scratch checkout must use brush revision `943553433ae04f5b3bd55d2cf207e39eb9ef2af7`.
|
|
The toolchain comes from the repository devshell.
|
|
|
|
```sh
|
|
git clone --depth 1 https://github.com/reubeno/brush /tmp/s2-shell/brush
|
|
git -C /tmp/s2-shell/brush fetch --depth 1 origin 943553433ae04f5b3bd55d2cf207e39eb9ef2af7
|
|
git -C /tmp/s2-shell/brush checkout --detach 943553433ae04f5b3bd55d2cf207e39eb9ef2af7
|
|
nu --no-config-file /home/surma/src/gitea.surma.technology/surma/sausage/spikes/s2-shell/patch-brush.nu
|
|
nix develop -c cargo build --manifest-path /tmp/s2-shell/brush/Cargo.toml -p brush-shell --release --no-default-features --features minimal --target wasm32-wasip2 -j 2
|
|
nix develop -c wasm-tools strip /tmp/s2-shell/brush/target/wasm32-wasip2/release/brush.wasm -o /tmp/s2-shell/brush-release.wasm
|
|
nix develop -c cargo build --manifest-path spikes/s2-shell/userland/Cargo.toml --release --target wasm32-wasip2 -j 2
|
|
nix develop -c cargo build --manifest-path spikes/s2-shell/Cargo.toml -j 2
|
|
nu --no-config-file /home/surma/src/gitea.surma.technology/surma/sausage/spikes/s2-shell/compare.nu /home/surma/src/gitea.surma.technology/surma/sausage/spikes/s2-shell/target/debug/s2-shell /tmp/s2-shell/brush-release.wasm
|
|
# Run the same comparison again after the cache is warm.
|
|
nu --no-config-file /home/surma/src/gitea.surma.technology/surma/sausage/spikes/s2-shell/compare.nu /home/surma/src/gitea.surma.technology/surma/sausage/spikes/s2-shell/target/debug/s2-shell /tmp/s2-shell/brush-release.wasm
|
|
nu --no-config-file /home/surma/src/gitea.surma.technology/surma/sausage/spikes/s2-shell/timings.nu /home/surma/src/gitea.surma.technology/surma/sausage/spikes/s2-shell/target/debug/s2-shell /tmp/s2-shell/brush-release.wasm
|
|
```
|
|
|
|
`userland/` builds the six commands from the published uutils 0.12.0 crates.
|
|
Its entry point calls libc's `chdir` with the host-supplied `S2_CWD` before it dispatches the command.
|
|
The packaged uutils component does not import `initial-cwd` and otherwise starts every command at `/`.
|
|
`compare.nu` copies the rebuilt multicall component into each bin alias in the test worlds.
|
|
The host checks the bin alias and reuses one compiled uutils component for these identical files.
|
|
It does not implement arbitrary executable resolution.
|
|
|
|
`corpus.sh` covers the requested syntax and traversal into another top-level folder.
|
|
`compare.nu` creates separate native and guest fixtures under `/tmp/s2-shell/comparison`.
|
|
It compares stdout and exit codes, and preserves stderr separately.
|
|
It removes the native fixture prefix from stdout because the guest sees the fixture as `/`.
|
|
|
|
## Bridge
|
|
|
|
`patch-brush.nu` copies `guest-process.rs` into the wasm launcher seam of the scratch checkout.
|
|
It adds the WIT import and its dependencies to that checkout only.
|
|
The guest launcher transfers bounded chunks between brush's open files and host-backed pipes.
|
|
It starts an independent Tokio task for each child's IO pump.
|
|
Brush waits for child processes sequentially, so a pump cannot run only inside the child's wait future.
|
|
Each pump yields between exchanges so the downstream pipeline stage can execute.
|
|
It closes the host output pipe when brush reports a broken pipe.
|
|
|
|
The host starts each child component in a separate store.
|
|
Unix socket pairs provide bounded, streamed stdin, stdout, and stderr.
|
|
The host uses the default Cranelift optimization level.
|
|
The dev profile optimizes dependencies at level 2, so Cranelift itself does not run unoptimized.
|
|
Wasmtime stores compiled modules in `/tmp/s2-shell/cache` and reuses them across host invocations.
|
|
The first comparison warms this cache. Cold compilation can take minutes.
|
|
`timings.nu` compares and times each corpus construct after the cache is warm.
|
|
Every child receives the same VFS root, its environment, and its initial working directory.
|
|
The guest process exchanges do not buffer a whole command's output.
|
|
Brush's existing in-memory pipes still buffer between cooperative shell tasks.
|
|
|
|
## Scope
|
|
|
|
The experiment supports only the acceptance corpus and its six uutils aliases.
|
|
It does not implement exec, signals, process groups, or interactive stdin inheritance.
|
|
It treats the shell's original stdin as EOF for external commands.
|
|
It does forward redirected stdin and pipeline stdin.
|
|
The fixture uses an ordinary file at `/dev/null`, not a device implementation.
|
|
The process import is spike-specific, not a proposed stable ABI.
|
|
|
|
AgentOS supplies the prior art, not code in this implementation.
|
|
Its standard library patches target `host_process` imports in its V8 runtime.
|
|
This experiment does not patch Rust's standard library.
|