Skip to content

Upstream-iroh experiments rebuilt on main, migrated from jco to deltic - #41

Merged
lann merged 7 commits into
mainfrom
upstream-iroh-deltic
Aug 10, 2026
Merged

Upstream-iroh experiments rebuilt on main, migrated from jco to deltic#41
lann merged 7 commits into
mainfrom
upstream-iroh-deltic

Conversation

@lann

@lann lann commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

The upstream-iroh experiment series (the iroh-relay-ws spike, the stock iroh-blobs spike, and the ping demo — issues #14, #25, #26) rebuilt onto current main, with the JS host migrated from the pinned jco fork to deltic, following the conventions host-deltic/ established in #36. The original jco history is preserved at the archive/iroh-experiments-jco tag; its final jco-pin bump (91ebda1) is deliberately dropped — the experiments no longer consume jco at all, and main's jco legs are untouched.

Co-dependence, per the sizing rule: the deltic pin bump (first commit) and the experiments land together because the guests are sync wasip2 commands — tokio parks in sync-lowered wasi:io/poll#poll thousands of times per run — a shape the old pin explicitly refused (NeedsJspi; the embedder contract's tier (c) was paper-only). The new pin carries the A-series that unblocks them (polymorph-components/polyengine#51/#53: suspending()-marked sync lowers park the frame on JSPI; #59: build-time translation for the demo's deploy path). The pin bump's own gate (just exam-deltic) passes at the new tag: EXAM PASS (5 pass, 0 blocked, 0 fail).

What the guests run on now

  • Stock Deno, flagless (no Node 24 + --experimental-wasm-jspi lane), runtime-linked — no transpile step, no generated trees, no jco fork pin in setup.sh's experiment path.
  • One shared host layer under experiments/iroh-relay-ws/host/: a synthetic WASI network in deltic's embedder conventions (sockets.ts, with real tier-(c) poll/clock parking — deltic's own wasi-shims stop at always-ready stubs by design), the relay-websocket bridge and issue-Consider splitting the synthetic-address overlay approach into a generic project (polymorph-overlay) #26 overlay over the siblings' deltic modules, and an A3/A4 harness. One deno.json pins deltic for all three experiments; fetch-translator.ts's pin gate now checks every pinned file (last commit).
  • The ping demo site is assembled by build-time translation (A4 envelope) + one deno bundle --platform browser pass: no vendored module copies, no sed rewrites, no translator wasm on the page.

Gates (all green on this branch)

  • ./experiments/iroh-relay-ws/run.sh: relay echo p50 27.6 ms → migration 51 ms after overlay addrs → phase 2 over the data channel p50 763 µs; browser-test.mjs PASS in real Chromium (flagless JSPI).
  • ./experiments/iroh-blobs/run.sh: both bao-verified fetch phases, phase 2 at 4.6 MiB/s over path=direct; browser leg PASS.
  • experiments/ping-demo: build.sh + full Playwright suite PASS (QR bootstrap, migration to direct on both sides, pings both ways, 2 MiB transfers both directions, third-participant refusal, rejoin with identity preserved, re-migration).
  • just check (fmt, clippy, validate-wit, test) and just exam-deltic green; no jco-lane surface touched.

lann added 5 commits August 10, 2026 18:55
…path translation

The upstream-iroh experiments this branch rebuilds are sync wasip2
commands: tokio's reactor parks thousands of times per run inside
sync-lowered WASI imports (wasi:io/poll#poll), the one shape the
previous pin refused (NeedsJspi — the embedder contract's tier (c) was
paper-only). The new pin carries the A-series amendments that unblock
them, plus deploy conveniences the demo build uses:

- A1/A2: suspending()-marked sync lowers park the calling wasm frame on
  JSPI, per-declaration (polymorph-components/polyengine#51, #53);
- A3: instantiate accepts untranslated { componentBytes, translator }
  (polymorph-components/polyengine#55-era surface);
- A4: build-time translation — the translate CLI and
  artifactsFromEnvelope, shipping component + envelope with no
  translator wasm on the page (polymorph-components/polyengine#59);
- Translator.fromExports (polymorph-components/polyengine#60).

The translator release asset is byte-identical to the old pin's
(same sha256), so only the tag moves; deno.lock re-resolved.

Gate: just exam-deltic — EXAM PASS (5 pass, 0 blocked, 0 fail).
Rebuild of the iroh-relay-ws spike (issue #14) on the deltic host: the
unmodified iroh crate (upstream main plus the wasi-enablement branches —
lann/iroh and lann/net-tools 'polymorph-iroh', the noq family at the rev
carrying noq#773) runs as a wasip2 command component, runtime-linked on
stock Deno. No transpile step, no generated tree, no engine flag, no jco
pin: the guest translates through the sha256-pinned translator shim
(host-deltic/fetch-translator.ts) and instantiates directly.

The host layer replaces the jco spike's 503-line shim.mjs:

- sockets.ts — the synthetic WASI network in deltic's embedder
  conventions: guest datagrams route to host bridges by well-known port
  or full synthetic address; wasi:io/poll and the monotonic clock are
  real tier-(c) implementations (suspending()-marked, embedder-api A1),
  since deltic's wasi-shims stop at always-ready stubs by design. Every
  own<pollable> handed to the guest is a fresh instance: two own handles
  sharing one host instance alias one registry rep, and the first drop
  would kill both.
- bridge.ts / webrtc-bridge.ts — the relay-websocket bridge and the
  issue #26 synthetic-address overlay, ported onto the siblings' deltic
  host modules (.deps/websocket/js/deltic, .deps/webrtc/deltic-impl)
  with WitError-branded error handling.
- harness.ts / run.ts — instantiate-from-bytes (A3), wasi:cli/run
  invocation, line-buffered guest stdio, watchdog and counters.
- browser-entry.ts + browser-test.mjs — the same flow in a real
  Chromium (deno bundle --platform browser; flagless JSPI), asserting
  the migration and phase-2-over-ip lines.

One deno.json serves all three experiments in this series (the deltic
tag matches host-deltic's pin); Playwright is the only npm dev
dependency left.

Gates: ./experiments/iroh-relay-ws/run.sh — relay echo p50 27.6ms,
migration 51ms after overlay addrs, phase 2 over the data channel p50
763us, clean exit (706 polls, 388 suspensions); browser-test.mjs — PASS
(migration 54ms, phase 2 p50 940us).
…tion

Rebuild of the ecosystem-compatibility spike (issues #14, #25) on the
deltic host: the unmodified iroh-blobs crate as a wasip2 command, one
component running provider and fetcher endpoints, bao-verified blob
fetches over a connection that live-migrates from the relay onto a
WebRTC data channel between the two fetch phases.

The host is the iroh-relay-ws spike's, shared the same way the jco
version shared its shim: sockets/bridge/webrtc-bridge re-export the
sibling modules, the driver and browser harness follow its pattern, and
every deno invocation points at that spike's deno.json (one deltic pin
across the experiment series).

Gates: ./experiments/iroh-blobs/run.sh — both fetch phases green, phase
2 over path=direct at 4.6 MiB/s after the migration; browser-test.mjs —
PASS (same assertions in a real Chromium, flagless JSPI).
…for Pages

Rebuild of the ping demo (issue #26 overlay, spike attachment) on the
deltic host: two browsers, one iroh endpoint per page, QR-code join,
canvas ripples mirrored over the session, file drop over stock
iroh-blobs, live migration onto a WebRTC data channel with real
page-ferried signaling — the demo semantics, the guest event ferry
(synthetic port 3), the 0x01/0x02 file chunk framing, rejoin, the debug
panel, and the __demo harness contract are unchanged from the jco
build.

What changes is the pipeline. build.sh now assembles a lean static
site with no vendored host-module copies and no sed rewrites:

- build-time translation (deltic embedder-api A4): the translate CLI
  produces ping-demo.plan.json next to the component, and the page
  reconstitutes artifacts with artifactsFromEnvelope — no translator
  wasm ships;
- one deno bundle --platform browser pass inlines the demo, the shared
  host layer (sockets/harness/bridge from the iroh-relay-ws spike), the
  overlay (now over .deps/webrtc's deltic module), and the vendored
  qrcode; node-datachannel/werift stay external — a browser resolves
  the RTCPeerConnection global and never imports them;
- guest env (role, secret, peer, relay) passes through the harness's
  cli options instead of a globalThis.GUEST_ENV hook.

Site: index.html + demo.js (450 KB) + component wasm + envelope +
.nojekyll, 8.4 MB total.

Gate: web/test.mjs (Playwright, host + joiner + third page against a
local relay) — bootstrap via the QR URL, relay connect, migration to
path=direct on both sides, pings both ways, 2 MiB file transfer both
directions, third-participant refusal, host reload/rejoin with identity
preserved, re-migration, post-rejoin ping: PASS.
The upstream-iroh experiments ride the same deltic release as
host-deltic: their shared import map (experiments/iroh-relay-ws/host/
deno.json) and the ping demo's build-time translate step name the tag
in raw URLs. fetch-translator.ts's pin-consistency gate now checks
those files too, so a partial bump fails at the first translator fetch
instead of surfacing as a plan-format mismatch (or silent skew) deep in
an experiment run. host-deltic/README.md's pin section documents the
full pinned set and the bump procedure.
@lann

lann commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator Author

The dom-lib type-check gap that keeps the experiments' browser entries outside the deno check gate (see the experiments/iroh-relay-ws/host/deno.json comment) is now filed as polymorph-components/polymorph-websocket#43 — one cast at websocket.ts:460 (WebSocket.send vs Uint8Array<ArrayBufferLike> under TS generic typed arrays). When that lands and the websocket pin bumps, the shared config can add dom to compilerOptions.lib and pull browser-entry.ts/demo.ts/overlay.ts into the check gate.

lann added 2 commits August 10, 2026 19:27
…e-deltic

# Conflicts:
#	.gitignore
#	justfile
…ck gate

polymorph-websocket#44 narrows the deltic module's WebSocket.send cast
to Uint8Array<ArrayBuffer> (sound: guest-lifted list<u8> is always a
fresh copy) and adds the dom libs to its own check config — the fix for
the dom-lib type-check gap this branch had to route around
(polymorph-websocket#43, found porting these experiments).

With the pinned checkout past it, the experiments' shared config
restores dom to compilerOptions.lib, and the browser entry modules
(browser-entry.ts in both spikes, the ping demo's demo.ts/overlay.ts)
type-check in the same graph as the Deno drivers instead of leaning on
bundling plus the Playwright suites alone.

Gates: deno check green across all three experiments including the
browser entries; just exam-deltic — EXAM PASS (5 pass, 0 blocked,
0 fail); iroh-relay-ws run.sh, iroh-blobs browser-test, ping-demo
build + Playwright suite all green at the new checkout.
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.

1 participant