Skip to content

Gossamer loader: finish IPC wiring + add smoke harness once ephapax#36 lands #218

@hyperpolymath

Description

@hyperpolymath

Tracking issue for the Gossamer loader / GUI bring-up items that remain after PR #212 (workflow + initial loader prep) and PR #217 (loader stub tightening). All items are scoped to src/ui/gossamer/ unless noted.

Upstream gate (blocks DoD item 1 of #196)

  • hyperpolymath/ephapax#36 — single .eph.wasm CLI subcommand. The build workflow already auto-promotes when just compile-affine, ephapax-cli compile-eph, or ephapax-cli compile-affine ships upstream; nothing hypatia-side is needed until it lands.

Loader runtime (src/ui/gossamer/loader.js)

  • Multi-channel IPC. makeGossamerHost holds a single global ws. A second ipc_open call clobbers the first without closing it (socket leak) and any prior recvQueue is lost. Replace with a Map<handle, { ws, recvQueue }> keyed by handle; allocate fresh handles per ipc_open, look them up in ipc_recv / ipc_send / ipc_close.
  • ipc_send reads no bytes. Currently a no-op even when the WS is open. Once the bytes ABI is pinned (likely "ptr + leading i32 len" mirroring strings, but unconfirmed), read [ptr+4, ptr+4+len) from memory.buffer and ws.send(bytes). Surface the assumption in the same comment as readEphapaxString.
  • ipc_recv real return path. Currently returns 0 (stubbed in refactor(gossamer): tighten loader stubs from PR #212 review #217). Real signature returns a bytes pointer into wasm memory; needs cooperation with a wasm-side allocator export (__alloc(len) -> ptr or equivalent). Spec out with bridge.eph maintainer before implementing.
  • ws.send race on open. WebSocket isn't OPEN immediately after new WebSocket(). If ipc_send is called before onopen fires, the message is silently dropped. Buffer pending sends in the per-handle state and flush on onopen.
  • DataView recreation per readEphapaxString call. Minor perf — cache and invalidate on memory.grow (buffer detaches on grow, so listen via a manual flag or rebuild on each byteLength mismatch).
  • ipc_send body ABI assumption. Once chore(deps): bump actions/checkout from 4.1.1 to 6.0.2 #36 lands and emits a real wasm artifact, confirm whether bytes are {ptr, len} vs {ptr-to-header, header=i32-len}. The latter is what strings use; bytes may differ.

Loader smoke harness (no upstream dep)

  • Add a Node-side test (Vitest or plain node --test) that builds a tiny fixture .wasm (or assembles WAT with wabt) declaring the gossamer imports + a no-op hypatia_init/_update/_view/_subs and instantiates it through loader.js. Locks the import-surface contract so a future bridge.eph rename breaks CI rather than the browser smoke test.
  • Once the harness exists, drop a CI job that runs it on PRs touching src/ui/gossamer/**. Lightweight — should run on the existing Elixir runner.

Docs

Cross-links


Filed by Claude Code from review of PR #212.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions