Files
suaveplan/openspec/changes/api-sandbox-wasm-stdio-abi/tasks.md
2026-05-27 23:29:53 +01:00

3.8 KiB

Tasks — WASI-stdio ABI variant for the WASM host bridge

0. Pre-flight (non-negotiable)

  • 0.1 Clean working tree; account for every .claude/worktrees/agent-* (active, work-pending-merge, stale-and-prune)
  • 0.2 MANIFEST.md package count matches find packages -maxdepth 3 -name package.json
  • 0.3 §0a Sync: worktree-isolated agents fast-forward to orchestrator-supplied SHA before any work

1. Shared protocol contract in @suaveplan/api-types/sandbox-bridge

  • 1.1 Add wasi-stdio-protocol.types.ts exporting PluginEnvelopeIn and PluginEnvelopeOut discriminated unions + WASI_STDIO_PROTOCOL_VERSION: 1 constant
  • 1.2 Paired .md documenting wire format ([u32 BE length][JSON]) + frame ordering invariants
  • 1.3 Paired .test.ts proving the types-only invariant (byte-size guard already enforces)
  • 1.4 Re-export from packages/api-stack/api/api-types/src/sandbox-bridge/index.ts + root src/index.ts
  • 1.5 bunx --bun turbo lint typecheck test:coverage --filter=@suaveplan/api-types green

2. Bridge runtime — WASI-stdio variant

  • 2.1 src/wasi-stdio/wasi-stdio-frame.ts — Zod-validated length-prefix encoder/decoder
  • 2.2 src/wasi-stdio/wasi-stdio-runner.ts — drives the sandbox via fd 0 / fd 1; surfaces stderr to logger
  • 2.3 src/wasi-stdio/wasi-stdio-routes.ts — issues {kind:"routes"} at bridge-init, captures the response into the BridgedPlugin
  • 2.4 src/abi-wasi-stdio/wasi-stdio-validate.ts — variant-specific ABI validator (memory + _start + WASI imports allowlist)
  • 2.5 src/abi-direct/ (existing direct-i32-i64 path) — moved existing src/wasm-abi/ + src/memory/ + src/marshal/ modules under this folder so the variant split is structural, not parameterised
  • 2.6 src/bridge/bridge.ts — switch (abiVariant) dispatch; default remains "direct-i32-i64"
  • 2.7 New error codes appended: SAND_WASM_BRIDGE.FRAME_OVERSIZE, SAND_WASM_BRIDGE.PROTOCOL_MISMATCH, SAND_WASM_BRIDGE.STDIO_TIMEOUT (10 codes total)
  • 2.8 Lifecycle (start/dispose) routes through stdio envelopes when abiVariant === "wasi-stdio"
  • 2.9 Trap classification preserved across both variants
  • 2.10 OTel instruments labelled with abi_variant attribute on every counter and histogram

3. Conformance harness

  • 3.1 runWasmHostBridgeConformance({ buildBridge, abiVariant }) gains the new parameter; both variants run all five invariants
  • 3.2 New WASI-stdio fixture WASM under tests/fixtures/wasi-stdio/build-wasm.ts — hand-encoded, no wabt
  • 3.3 Fixture exercises route-discovery, request round-trip, lifecycle, trap (unreachable mid-frame), capability-gate

4. Integration test

  • 4.1 tests/integration/wasi-stdio-flow.test.ts — full round-trip + assertBridgeThrowsOnTrap for both variants
  • 4.2 tests/integration/full-flow.test.ts (existing direct variant) — left untouched; proves the split didn't regress
  • 4.3 100% istanbul coverage on every touched module
  • 4.4 No // biome-ignore; every test file imports from @suaveplan/testing/runner; public-constructor preserved

5. Gate

  • 5.1 bunx --bun turbo lint typecheck test:coverage --filter=@suaveplan/api-types --filter=@suaveplan/api-sandbox-wasm --filter=@suaveplan/api-sandbox-wasm-host-bridge --filter=@suaveplan/api-sandbox-vm-host-bridge --concurrency=4 green (vm-bridge included to prove the api-types additive change doesn't regress it)

6. Archive (orchestrator step)

  • 6.1 Fold delta into openspec/specs/api-sandbox-wasm-host-bridge/spec.md (creating the spec if it doesn't exist yet — the original wasm host-bridge proposal still awaits its first archive)
  • 6.2 Fold delta into openspec/specs/api-types/spec.md for the additive protocol types
  • 6.3 Move folder → openspec/archive/2026-05-27-api-sandbox-wasm-stdio-abi/
  • 6.4 Refresh MANIFEST.md