Skip to content

feat(wasm): compile the kernel cube to graff-kernel.wasm - #591

Draft
justrach wants to merge 2 commits into
mainfrom
cursor/wasm-kernel-1a17
Draft

feat(wasm): compile the kernel cube to graff-kernel.wasm#591
justrach wants to merge 2 commits into
mainfrom
cursor/wasm-kernel-1a17

Conversation

@justrach

@justrach justrach commented Aug 20, 2026

Copy link
Copy Markdown
Owner

fx compiles to WASM as fx-core.wasm / fx-term.wasm behind a JS host (JSPI fetch, no bash). graff cannot do that for the live agent yet — std.http.Client, jobs, MCP stdio, and TTY restore do not compile to wasm32-freestanding.

What does compile is the maths: the ToolCatalog cube ({0,1}^6 → 64 name lists) and the lexical path jail. This PR ships that as the first artifact.

What you get

zig build wasm
# zig-out/bin/graff-kernel.wasm  (~2.8 KB, ReleaseSmall)
import { loadGraffKernel } from "./sdk/wasm/graff-kernel.js";
const k = await loadGraffKernel("./graff-kernel.wasm");
k.catalog({ lean: true });          // 8 names
k.advertised("subagent", { isSub: true }); // false
k.confined("/etc/passwd");          // false

No JSPI. No WASI. Not the agent.

Guardrails

  • Native tests replay the same fixtures Lean exports (spec/kernels/tool_catalog.json, path_confine.json).
  • scripts/eval-tier1.sh --only wasm is compile-only so the target cannot rot.
  • CI runs zig build wasm on Linux and Windows.
  • ADR 0012: a later graff-core.wasm / graff-term.wasm needs an explicit host capability table (fetch, workspace, no implicit bash), the same way fx does. Do not compile src/main.zig and hope.

Until that host layer exists, embed the live harness with graff serve + the remote SDK.

Demo after zig build wasm: python3 -m http.server 8080/sdk/wasm/demo.html.

CI

sdk typecheck failed on process.off("unhandledRejection") — bun-types only overloads Process.off for memoryPressure. Fixed by casting through EventEmitter in remote.test.ts (also on #593).

Open in Web Open in Cursor 

fx ships fx-core.wasm / fx-term.wasm behind a JS host. graff cannot
compile the live agent that way yet (HTTP, bash, TTY). The kernels
already are total functions over finite cubes, so zig build wasm emits
those: catalog({0,1}^6) and confined(path), with a JS loader and a
compile-only tier-1 check. Not JSPI, not WASI, not the agent (ADR 0012).
CI tsc failed on remote.test.ts: process.off("unhandledRejection") is
not in bun-types' Process overloads. Cast through EventEmitter so the
test still asserts create-rejection is observed, not unhandled.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants