You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@polymorph/iroh is the appliance: the package instantiates its own packaged component. host-polyengine/src/harness.ts imports instantiate from @polyengine/runtime/embedder, and the published deno.json maps that bare specifier to jsr:@polyengine/runtime@^0.5.1/embedder. That was the explicit packaging ruling of #81 — "the endpoint component + the harness, consumable out of the box (newEndpointInstance() → bindEndpoint())" — and #90 reaffirmed it post-A22 ("host-polyengine stays an instantiating application by design").
What A22 says, and where the tension is
polyengine A22 (contracts/embedder-api.md, "The host-ABI surface and its version"):
Host modules MUST NOT import @polyengine/runtime; the embedder surface was stripped to machinery "only an instantiating application uses".
Placement of runtime concerns — "like runtime selection itself — [stays] with the deploying application."
@polymorph/iroh is not a host module (it provides no import fragments to someone else's instantiation), so the MUST NOT does not bind it by letter. But it is a published package whose manifest names a runtime specifier, which pre-empts exactly the selection A22 assigns to the deploying application.
Consumer evidence
polyvisor's demo/deno.json records the failure mode concretely: at webrtc-datachannels 0.4.0, that sibling's polyengine-impl/deno.json named @polyengine/runtime@^0.4.0; Deno consulted the package's own config for the bare specifier and the app graph carried a second runtime@0.4.0 beside the app's exact-pinned 0.5.1 — "the exact duplication this block exists to prevent." The sibling going A22-clean at its 0.5.0 was the fix. A published @polymorph/iroh JS surface in an embedding app's graph is the same hazard, latent: caret-vs-exact-pin skew duplicates rather than unifies.
The one real external consumer (polyvisor) does not use the appliance at all. It consumes the component bytes (engine/tools/fetch-endpoint-wasm.ts calls loadArtifacts() and discards the translation — paying a translator run and pulling the whole dependency graph because the package has no bytes-only door) and embeds its own composite under its own runtime pin. release-assets: attach iroh_endpoint.wasm + SHA256SUMS to releases #94's release assets (iroh_endpoint.wasm + SHA256SUMS) now serve that consumer properly.
So today nobody is bitten: the appliance's known consumers are leaf applications (this repo's exam), and the composer takes wasm, not JS. The question is what the package should promise before a consumer that embeds its own components alongside the appliance appears.
Options
a. Status quo, documented: the appliance is for leaf applications; a graph that loads its own embedder next to @polymorph/iroh owns the version-intersection problem. Cheapest; keeps the ^0.5.1 runtime floor (A23: the endpoint's dial timeouts drop in-flight import futures; polyengine#239) enforced by constraint.
b. Application-supplied embedder — A22's own placement pattern (the same move it makes for stream writers): the package goes protocol-only; newEndpointInstance() takes the embedder (or an instantiate capability) from the caller. Runtime selection returns to the deploying application; the A23 floor demotes from constraint to documentation plus a runtime check (the copy registry carries runtimeVersion). Breaking → minor bump under the caret-honest regime.
c. Split: a protocol-only parts surface (component bytes + import-fragment assembly) beside the appliance, in one package or two. The bytes-only door also fixes the loadArtifacts() extraction wart independently of the embedder question (though release assets may have mooted that consumer).
Whichever way this lands, it decides what the next minor release claims — recording it here per the divergence-with-no-artifact rule.
The shape today
@polymorph/irohis the appliance: the package instantiates its own packaged component.host-polyengine/src/harness.tsimportsinstantiatefrom@polyengine/runtime/embedder, and the publisheddeno.jsonmaps that bare specifier tojsr:@polyengine/runtime@^0.5.1/embedder. That was the explicit packaging ruling of #81 — "the endpoint component + the harness, consumable out of the box (newEndpointInstance()→bindEndpoint())" — and #90 reaffirmed it post-A22 ("host-polyengine stays an instantiating application by design").What A22 says, and where the tension is
polyengine A22 (contracts/embedder-api.md, "The host-ABI surface and its version"):
@polyengine/runtime; the embedder surface was stripped to machinery "only an instantiating application uses".@polymorph/irohis not a host module (it provides no import fragments to someone else's instantiation), so the MUST NOT does not bind it by letter. But it is a published package whose manifest names a runtime specifier, which pre-empts exactly the selection A22 assigns to the deploying application.Consumer evidence
demo/deno.jsonrecords the failure mode concretely: at webrtc-datachannels 0.4.0, that sibling'spolyengine-impl/deno.jsonnamed@polyengine/runtime@^0.4.0; Deno consulted the package's own config for the bare specifier and the app graph carried a secondruntime@0.4.0beside the app's exact-pinned 0.5.1 — "the exact duplication this block exists to prevent." The sibling going A22-clean at its 0.5.0 was the fix. A published@polymorph/irohJS surface in an embedding app's graph is the same hazard, latent: caret-vs-exact-pin skew duplicates rather than unifies.engine/tools/fetch-endpoint-wasm.tscallsloadArtifacts()and discards the translation — paying a translator run and pulling the whole dependency graph because the package has no bytes-only door) and embeds its own composite under its own runtime pin. release-assets: attach iroh_endpoint.wasm + SHA256SUMS to releases #94's release assets (iroh_endpoint.wasm+SHA256SUMS) now serve that consumer properly.So today nobody is bitten: the appliance's known consumers are leaf applications (this repo's exam), and the composer takes wasm, not JS. The question is what the package should promise before a consumer that embeds its own components alongside the appliance appears.
Options
a. Status quo, documented: the appliance is for leaf applications; a graph that loads its own embedder next to
@polymorph/irohowns the version-intersection problem. Cheapest; keeps the^0.5.1runtime floor (A23: the endpoint's dial timeouts drop in-flight import futures; polyengine#239) enforced by constraint.b. Application-supplied embedder — A22's own placement pattern (the same move it makes for stream writers): the package goes protocol-only;
newEndpointInstance()takes the embedder (or aninstantiatecapability) from the caller. Runtime selection returns to the deploying application; the A23 floor demotes from constraint to documentation plus a runtime check (the copy registry carriesruntimeVersion). Breaking → minor bump under the caret-honest regime.c. Split: a protocol-only parts surface (component bytes + import-fragment assembly) beside the appliance, in one package or two. The bytes-only door also fixes the
loadArtifacts()extraction wart independently of the embedder question (though release assets may have mooted that consumer).Whichever way this lands, it decides what the next minor release claims — recording it here per the divergence-with-no-artifact rule.