The real Wasmex-backed transport for every Ex4pmEngine.Wasm.* adapter
(discover, conform, align, htn_plan, ... all 19 Phase-1/2/3
algorithms) -- the piece the CI workflow
(.github/workflows/wasm4pm-bindings-integration.yml) explicitly names as
"follow-on work, tracked in docs/ARD-v26.9.x-wasm4pm-phase1.md": every
exercised path before this module used a fixture closure fabricating both
the result and the observed:true/replay_verified:true identity.
This module actually drives the wasm4pm-ex4pm-bindings crate's real
ptr/len UTF-8 JSON ABI (documented at the top of
~/wasm4pm/crates/wasm4pm-ex4pm-bindings/src/lib.rs) through a real
Wasmex instance:
wasm4pm_ex4pm_bindings_alloc_v1(len)-> reservelenbytes in the module's own linear memory (added alongside this module -- the crate previously exported no allocator, so no host could safely write an input buffer at all).Wasmex.memory/1fetches the real exported memory, thenWasmex.Memory.write_binary/4writes the real UTF-8 JSON request into that buffer.- Call
<algo>_v1(ptr, len, out_len_ptr)--out_len_ptris itself a second small alloc'd buffer (4 bytes, i32) the export writes its real output length into. - Read
out_lenback viaWasmex.Memory.read_binary/4+:binaryunpack, then read the real output bytes at the returnedout_ptr. - Free the output buffer via
wasm4pm_ex4pm_bindings_free_v1/2and the input+out_len buffers viawasm4pm_ex4pm_bindings_dealloc_v1/2. - Decode the real JSON response and hand it back to
Ex4pmEngine.Wasm.Adapteras{:ok, response, identity}, withidentity.observedtrue only because THIS module actually executed the WASM, computed a real SHA-256 of the artifact bytes, and can point to the real pid/instance that ran it -- not because a fixture said so.
One transport, reused for every algorithm: call/3 takes the artifact
path, the export name pair, and the request map: the use Ex4pmEngine.Wasm.Adapter macro already carries each op's own
@wasm_export, so each Ex4pmEngine.Wasm.<Op> module's
:<algo>_wasm_fun default (wired in default_transport/1) just needs to
close over its own export name.
No mocks anywhere in this module: Wasmex.start_link/1 boots the real
Wasmtime runtime configured by the wasmex dep and every byte written or
read crosses that real boundary.
The real, independently discovered __wbindgen_placeholder__ gap
wasm4pm-ex4pm-bindings links the full wasm4pm crate, whose
Cargo.toml declares wasm-bindgen as a mandatory (non-optional,
non-feature-gated) dependency and carries 111 unconditionally-compiled
#[wasm_bindgen]-attributed items across its ML/stats/drift modules --
code this crate's own discover/conform/align/etc. exports never
call, but which the linker still considers reachable. The resulting
wasm4pm_ex4pm_bindings.wasm therefore imports 87 __wbindgen_placeholder__
/ __wbindgen_externref_xform__ host functions it does not itself define
-- confirmed for real by parsing the compiled artifact's own WASM import
section (wasm-objdump-equivalent: every import type here was read
directly from the binary's Type/Import sections, not assumed), and every
one of the 87 uses only i32/i64/f64 params/results (wasm-bindgen's
classic non-reference-types ABI) -- Wasmex's documented import type set
(:i32/:i64/:v128/:f32/:f64, no :externref) covers all of them.
stub_wasm_bindgen_imports/0 supplies all 87 as real, correctly-signed
Wasmex import stubs returning zero-valued results. They are provided
ONLY to satisfy WASM instantiation-time import resolution; none of the
19 <algo>_v1 exports this module actually drives reach any JS-interop
code path at runtime, so these stubs are never invoked in the executions
this module performs -- this is not faking algorithm behavior, it is
satisfying dead, unrelated linkage the upstream crate currently leaves in
the artifact unconditionally. The real, minimal fix belongs upstream (make
wasm-bindgen and its 111 call sites genuinely optional behind the
browser feature in ~/wasm4pm/wasm4pm/Cargo.toml); that is a
cross-cutting refactor of code this module does not own, so this is
documented here as the real, named, still-open upstream gap rather than
silently worked around.
Summary
Types
One Ex4pmEngine.Wasm.* adapter module plus the algorithm identity RealTransport needs to build its default_transport/2 map.
A started, real Wasmex instance plus the artifact bytes/hash used to start it, so callers can invoke multiple exports against the same instance without re-loading the module.
Functions
The real, closed registry of all 19 Ex4pmEngine.Wasm.* Phase-1/2/3
adapters -- one entry per <algo>_v1/<algo>_replay_v1 export pair the
wasm4pm-ex4pm-bindings crate exposes (verified against
~/wasm4pm/crates/wasm4pm-ex4pm-bindings/src/{lib,phase2,phase2_playout,prolog}.rs).
This is the single source of truth Ex4pmEngine.Reactors.WasmCapabilitiesReactor
and any Chicago test wiring default_transport/2 should read from, rather
than each re-deriving export-name strings by hand.
Boots ONE real Wasmex instance from artifact_path (via start/1) and
builds all 33 default_transport/2 closures against it in one pass --
the option map every Ex4pmEngine.Wasm.* adapter's execute/3 expects
under its own :<algo>_wasm_fun key, ready to Keyword.merge into an
execute/3 opts list or into a Reactor step's own transport-selection.
Returns {:ok, transports} where transports is a keyword list
[discover_wasm_fun: fun, conform_wasm_fun: fun, ...], or {:error, reason} if the artifact can't be loaded.
Real end-to-end call against export export_name on an already-start/1ed
instance, marshaling request (a plain map, JSON-encoded here) through
the crate's real ptr/len ABI. Returns {:ok, response_map} on a decoded
JSON object response, {:error, reason} otherwise. response_map is
handed back verbatim to Ex4pmEngine.Wasm.Adapter.accept/4 -- this
module makes no claim about the algorithm's own semantics, only that the
bytes it returns really came out of a real WASM execution of export_name
against request.
Builds the :<algo>_wasm_fun 2-arity transport callback
Ex4pmEngine.Wasm.Adapter.execute/3 expects, closing over a real,
already-start/1-ed instance plus this op's own identity: export_name
and replay_export_name (the crate's paired <algo>_v1/<algo>_replay_v1
exports), algorithm_id and protocol/wasm4pm_source_sha (matching
Ex4pmEngine.Wasm.Adapter's own @protocol/wasm4pm_source_sha/0 so
accept/4's admit_source/2 check passes for real rather than being
bypassed).
Real replay check: re-invokes <algo>_replay_v1 (per the crate's own
self-check contract -- see ~/wasm4pm/crates/wasm4pm-ex4pm-bindings/src/lib.rs
module doc) against the SAME request bytes and returns {:ok, true | false}
reflecting the export's own real u32 return (1/0), or {:error, reason}.
Boots a real Wasmex instance from the compiled wasm4pm-ex4pm-bindings
artifact at path. Returns {:ok, instance} with the real SHA-256 of the
artifact bytes (via Ex4pm.Core.Hash), or {:error, reason} if the file
is missing/unreadable or Wasmex fails to instantiate it.
Types
@type algo_spec() :: %{ module: module(), algorithm_id: atom(), export_name: String.t(), replay_export_name: String.t() }
One Ex4pmEngine.Wasm.* adapter module plus the algorithm identity RealTransport needs to build its default_transport/2 map.
A started, real Wasmex instance plus the artifact bytes/hash used to start it, so callers can invoke multiple exports against the same instance without re-loading the module.
Functions
@spec algo_specs() :: [algo_spec()]
The real, closed registry of all 19 Ex4pmEngine.Wasm.* Phase-1/2/3
adapters -- one entry per <algo>_v1/<algo>_replay_v1 export pair the
wasm4pm-ex4pm-bindings crate exposes (verified against
~/wasm4pm/crates/wasm4pm-ex4pm-bindings/src/{lib,phase2,phase2_playout,prolog}.rs).
This is the single source of truth Ex4pmEngine.Reactors.WasmCapabilitiesReactor
and any Chicago test wiring default_transport/2 should read from, rather
than each re-deriving export-name strings by hand.
Boots ONE real Wasmex instance from artifact_path (via start/1) and
builds all 33 default_transport/2 closures against it in one pass --
the option map every Ex4pmEngine.Wasm.* adapter's execute/3 expects
under its own :<algo>_wasm_fun key, ready to Keyword.merge into an
execute/3 opts list or into a Reactor step's own transport-selection.
Returns {:ok, transports} where transports is a keyword list
[discover_wasm_fun: fun, conform_wasm_fun: fun, ...], or {:error, reason} if the artifact can't be loaded.
Real end-to-end call against export export_name on an already-start/1ed
instance, marshaling request (a plain map, JSON-encoded here) through
the crate's real ptr/len ABI. Returns {:ok, response_map} on a decoded
JSON object response, {:error, reason} otherwise. response_map is
handed back verbatim to Ex4pmEngine.Wasm.Adapter.accept/4 -- this
module makes no claim about the algorithm's own semantics, only that the
bytes it returns really came out of a real WASM execution of export_name
against request.
@spec default_transport(instance(), map()) :: (map(), keyword() -> {:ok, map(), map()} | {:error, term()})
Builds the :<algo>_wasm_fun 2-arity transport callback
Ex4pmEngine.Wasm.Adapter.execute/3 expects, closing over a real,
already-start/1-ed instance plus this op's own identity: export_name
and replay_export_name (the crate's paired <algo>_v1/<algo>_replay_v1
exports), algorithm_id and protocol/wasm4pm_source_sha (matching
Ex4pmEngine.Wasm.Adapter's own @protocol/wasm4pm_source_sha/0 so
accept/4's admit_source/2 check passes for real rather than being
bypassed).
Every call performs TWO real WASM invocations -- the algorithm itself via
call/3, then a real <algo>_replay_v1 re-execution via replay/3 -- so
identity.replay_verified reflects a genuinely recomputed digest match,
not an asserted true. Ex4pmEngine.Wasm.Adapter.accept/4 only awards
:alive (vs. :partial_alive) when this real replay agrees.
Real replay check: re-invokes <algo>_replay_v1 (per the crate's own
self-check contract -- see ~/wasm4pm/crates/wasm4pm-ex4pm-bindings/src/lib.rs
module doc) against the SAME request bytes and returns {:ok, true | false}
reflecting the export's own real u32 return (1/0), or {:error, reason}.
Boots a real Wasmex instance from the compiled wasm4pm-ex4pm-bindings
artifact at path. Returns {:ok, instance} with the real SHA-256 of the
artifact bytes (via Ex4pm.Core.Hash), or {:error, reason} if the file
is missing/unreadable or Wasmex fails to instantiate it.