Checkpoint before integration and package validation. Assisted-by: SurmAgent:unknown [read] [edit] [bash]
89 lines
4.3 KiB
Markdown
89 lines
4.3 KiB
Markdown
# Working on Sausage (v3)
|
|
|
|
Sausage is a world of WASI programs and durable agents. It is meant to be read and changed by agents,
|
|
including its own. Keep it that way.
|
|
|
|
This branch (`v3`) rebuilds Sausage. The plan and its decisions (D1, D2, …) are in
|
|
`~/research/sausage-v3/PLAN.md`. `README.md` describes the current build and layout.
|
|
|
|
## The boundary
|
|
|
|
- **The world is the sandbox.** Everything inside the world sees and changes the whole world. Do not add
|
|
inner boundaries, permissions or per-agent views. The VFS is a safety net against mistakes, not a wall
|
|
against attackers.
|
|
- **Host calls pierce the sandbox.** The only host import beyond standard WASI is the process interface
|
|
(spawn, wait, kill). Do not add another one. Everything else uses standard WASI 0.2 interfaces: files
|
|
through the VFS, `wasi:http` (the host API on its reserved host name, credential injection, signing),
|
|
and `wasi:sockets`.
|
|
- **The credentials manager in the host is the one real security boundary.** Its managed secrets never enter
|
|
the world. Approvals need a passkey. The one exception is the LLM proxy key in `/etc/sausage/config.yaml`.
|
|
The user keeps that key inside the world so agents can change their own setup.
|
|
- **Native code is the exception.** The only native work for the world is the Rust builder, and it runs in
|
|
user, mount and network namespaces.
|
|
|
|
## Priorities
|
|
|
|
1. **Correct.** Every behavior has a test.
|
|
2. **Simple and short.** Prefer the obvious code. No abstraction for one caller. No configuration that
|
|
nobody asked for.
|
|
3. **Readable.** A new reader must understand a file without the others. Each module starts with a doc
|
|
comment that says what it owns.
|
|
4. **Efficient** on the paths that run per command and per model turn.
|
|
|
|
## Layout
|
|
|
|
- `host/`: the host crate (package and binary `sausage`): the world, the process table, the harness.
|
|
`host/src/exec.rs` is the contract between the harness and the process table.
|
|
- `vfs/`: `sausage-vfs`, the virtual filesystem for WASI guests and for host code. It knows nothing
|
|
about Sausage. Host code reads and writes the world only through it.
|
|
- `userland/`: the default CLIs of a world, built for `wasm32-wasip2` in the root Cargo workspace.
|
|
The patched Brush crates live in `userland/brush/source/` and share the root lock file.
|
|
- `spikes/`: accepted prototypes. Read them for evidence, copy from them, do not build on them.
|
|
|
|
## Programs in the world
|
|
|
|
- Agents write CLIs and servers. That they are WASI binaries is a detail, not a concept to explain.
|
|
- The platform is WASI 0.2 components. Rust programs build for `wasm32-wasip2`. WASI 0.1 programs run
|
|
through an adapter.
|
|
|
|
## Checks
|
|
|
|
```sh
|
|
nix develop -c cargo test -p sausage -p sausage-vfs
|
|
nix develop -c cargo clippy -p sausage -p sausage-vfs --all-targets -- -D warnings
|
|
nix develop -c nu userland/bundle.nu
|
|
# For one tool, select its package and WASI target explicitly:
|
|
nix develop -c cargo build -p git --target wasm32-wasip2 --release
|
|
```
|
|
|
|
`nix build` uses separate Crane pipelines for the native host and WASI userland.
|
|
Go tools and QuickJS build separately. Nix assembles the bundle without `bundle.nu`.
|
|
Both Nix and the incremental development bundle read the command names from `userland/tools.json`.
|
|
Coreutils, diffutils, procps, and brush use relative symlinks to one binary each.
|
|
|
|
`nix flake check` checks the packaged host, its bundle, and the whole host/VFS test suite.
|
|
Sandbox-incompatible tests print an explicit skip reason instead of a flake-level filter.
|
|
|
|
## Tests
|
|
|
|
Host integration tests share one executable:
|
|
|
|
```sh
|
|
cargo test -p sausage --test it
|
|
cargo test -p sausage --test it -- chain::
|
|
```
|
|
|
|
Use the required Nix environment and build slot wrapper for these commands.
|
|
Add test modules under `host/tests/it/` and declare them in `it/main.rs`.
|
|
Use fully qualified child test filters with `--exact`.
|
|
See `host/tests/README.md` for fixture and isolation details.
|
|
|
|
Tests must stay fast:
|
|
|
|
- Only a few tests may wait for a timing (grace periods, deadlines).
|
|
- Poll for a condition with a deadline. Do not sleep.
|
|
- Do not test unrealistic load, such as many fast cycles.
|
|
- `#[ignore]` only disables a test for a short time, with the reason in the attribute.
|
|
- Tests that build or compile guests use a persistent cache (for example under
|
|
`env!("CARGO_TARGET_TMPDIR")`), so a warm run does not compile again.
|