Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
# `wasi-stdio-validate`
|
||||
|
||||
## Purpose
|
||||
|
||||
ABI surface validator for the WASI-stdio variant. Inspects a
|
||||
`WebAssembly.Module`'s imports and exports BEFORE instantiation and
|
||||
raises `SAND_WASM_BRIDGE.INVALID_PLUGIN_SURFACE` if the module is
|
||||
missing any of the five required WASI imports
|
||||
(`wasi_snapshot_preview1.{fd_read, fd_write, environ_get,
|
||||
environ_sizes_get, proc_exit}`) OR the two required exports (`memory`,
|
||||
`_start`). The check is the WASI-stdio mirror of `validateWasmAbi`
|
||||
in `abi-direct/wasm-abi/`; it does NOT require the six
|
||||
`__suaveplan_*` direct-variant exports because Javy-compiled plugins
|
||||
cannot emit them.
|
||||
|
||||
## Features
|
||||
|
||||
- Module-level (pre-instantiation) check — operators see the failure
|
||||
before the host commits to instantiating the plugin.
|
||||
- Both required imports and required exports are validated in a single
|
||||
pass; `context.missing` carries the sorted union of absent symbols.
|
||||
- Namespace-qualified diagnostic for imports
|
||||
(`wasi_snapshot_preview1.fd_read`) vs bare for exports (`_start`)
|
||||
makes the absent surface obvious at a glance.
|
||||
- The required-symbol lists are sorted constants so a future addition
|
||||
surfaces as a typecheck divergence rather than a silent drift.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { validateWasiStdioAbi } from
|
||||
"@suaveplan/api-sandbox-wasm-host-bridge/abi-wasi-stdio";
|
||||
|
||||
declare const module: WebAssembly.Module;
|
||||
validateWasiStdioAbi(module, "example");
|
||||
// Throws SandboxWasmBridgeError on missing surface.
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import { validateWasiStdioAbi } from
|
||||
"@suaveplan/api-sandbox-wasm-host-bridge/abi-wasi-stdio";
|
||||
import {
|
||||
SAND_WASM_BRIDGE_CODES,
|
||||
SandboxWasmBridgeError,
|
||||
} from "@suaveplan/api-sandbox-wasm-host-bridge/error-codes";
|
||||
|
||||
declare const module: WebAssembly.Module;
|
||||
try {
|
||||
validateWasiStdioAbi(module, "billing");
|
||||
} catch (err) {
|
||||
if (
|
||||
err instanceof SandboxWasmBridgeError &&
|
||||
err.code === SAND_WASM_BRIDGE_CODES.INVALID_PLUGIN_SURFACE
|
||||
) {
|
||||
const missing = (err.context as { missing?: readonly string[] })
|
||||
.missing;
|
||||
// missing → ["_start"] OR ["wasi_snapshot_preview1.fd_read", ...]
|
||||
void missing;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `validateWasiStdioAbi(module, pluginName): void`
|
||||
|
||||
- `module: WebAssembly.Module` — pre-compiled module under inspection.
|
||||
- `pluginName: string` — error-context label.
|
||||
|
||||
Throws `SandboxWasmBridgeError` with code
|
||||
`SAND_WASM_BRIDGE.INVALID_PLUGIN_SURFACE` and
|
||||
`context.abiVariant = "wasi-stdio"` + sorted `context.missing`.
|
||||
|
||||
### `REQUIRED_WASI_STDIO_IMPORTS: readonly string[]`
|
||||
|
||||
Sorted list: `environ_get`, `environ_sizes_get`, `fd_read`, `fd_write`,
|
||||
`proc_exit`.
|
||||
|
||||
### `REQUIRED_WASI_STDIO_EXPORTS: readonly string[]`
|
||||
|
||||
Sorted list: `_start`, `memory`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The validator walks `WebAssembly.Module.imports(module)` and
|
||||
`WebAssembly.Module.exports(module)` once each — both are O(n) over
|
||||
the module's metadata and never touch the linear memory. Running
|
||||
them BEFORE instantiation costs effectively nothing.
|
||||
- The required-imports list is intentionally minimal: it captures the
|
||||
five hooks any WASI-stdio guest MUST call. A guest that uses
|
||||
additional WASI imports (e.g. `clock_time_get`, `random_get`) is
|
||||
fine — those are wired by the runner but their absence is not a
|
||||
surface error.
|
||||
- `context.abiVariant` carries the literal `"wasi-stdio"` string so
|
||||
operators reading a stack trace can tell which variant raised
|
||||
without inferring it from the plugin's manifest. The direct
|
||||
validator does not set this field for the inverse reason: the
|
||||
direct path is the default and the absence of the field implies
|
||||
it.
|
||||
Reference in New Issue
Block a user