### Vector graphics (Draft): the sink as a WebAssembly 1.0 module, in three browser engines

Additive. No payload, outline set, vector or digest changes.

- **The sink's exports.** `wai-vector/wasm` exports the sink of
  [graphics-vector](extensions/graphics-vector.md) behind a C ABI, with no bindings
  generator and no imports. `wv_add_set` holds an outline set a payload may name;
  `wv_open` loads a payload to a handle, or to its refusal's code; `wv_render` gives a
  frame's `RGBA8P` at a listed size and rate, or the request error's code; `wv_cost`
  gives a listed size's cost; `wv_transcript` gives the transcript, and `wv_projection`
  the projection at a frame of a listed rate, each as the JSON of §5.4, or the request
  error's code; `wv_sha256` gives a digest; `wv_close` releases a handle. A result is
  read at `wv_out_ptr`, `wv_out_len` bytes of it. No export takes or returns a 64-bit
  integer: a frame number goes in as two halves.
- **The package.** `wai-vector/wasm/build-pkg.sh` builds the module a site serves: the
  sink's exports alone, with no glue script. It is WebAssembly 1.0 and nothing later:
  no SIMD, no threads, no bulk memory, no sign-extension operators, no reference types.
  The target is `wasm32v1-none`, whose precompiled `core` and `alloc` are 1.0
  themselves, so the crate is now `no_std` and carries its own allocator. The build
  then reads the module back: `wasm/check-mvp.mjs` decodes every section, type, segment
  and instruction, and refuses anything later than 1.0, any import, any 64-bit integer
  at an exported function, any floating point, and any exported function the script
  does not list.
- **Three browser engines.** `wai-vector/browser/run.mjs` serves a page, the package and
  the corpus, and in each engine loads every payload of `vector-conformance` to its
  expected code, checks its SHA-256 and each listed size's cost, and renders its frames
  through the page's hook, `window.__wai_overlay.frame(size, rate, g)`, which returns
  the renderer's own buffer: every listed frame at sizes up to 1280 × 720, and sampled
  frames above. The page hashes each frame with the module's SHA-256 and with the
  platform's digest. The sampled frames are also sent to Node as bytes, and Node hashes
  them itself. Where a payload's expected file states a text record, the page's hook
  also gives the sink's transcript and its projection at every frame of every listed
  rate, `transcript()` and `projection(rate, g)`; written out as the record's lines,
  they must be the committed `<name>.a11y.jsonl` byte for byte. The recomputation
  module then recomputes every expected file and authoring form in each engine.
  Nothing is read from a canvas. A run passes only when all three engines ran: a
  missing engine is a failure.
- **CI.** `wai-vector.yml` gains the `browser` job: the package built and read back,
  then the three engines, in a container image pinned by digest.

