From e455964d8fbfaf62de5345f1e2aa927d0f6a99b5 Mon Sep 17 00:00:00 2001 From: Lann Martin Date: Sun, 30 Aug 2026 20:40:00 -0400 Subject: [PATCH] =?UTF-8?q?contracts:=20A25=20=E2=80=94=20host=20modules?= =?UTF-8?q?=20get=20sync=20callbacks=20handed=20by=20the=20application,=20?= =?UTF-8?q?never=20by=20importing=20the=20runtime?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pins the A22 consequence explicitly: sync() is application machinery, and the host-module path to a synchronous guest callback is being handed the sync(exports.f) function by the deploying application — the StreamWriter handing pattern, verbatim. --- contracts/embedder-api.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/contracts/embedder-api.md b/contracts/embedder-api.md index f277cd8..638cc8b 100644 --- a/contracts/embedder-api.md +++ b/contracts/embedder-api.md @@ -500,7 +500,13 @@ class PeerTrappedError extends Error { // A7: a stream/future op whose peer ins exported from `@polyengine/runtime/embedder` — application machinery in A22's sense, like `createStream`: only an instantiating application holds export functions, so this is deliberately NOT host-module - vocabulary and does not touch `@polyengine/protocol`. Recognition is by + vocabulary and does not touch `@polyengine/protocol`. A host module + MUST NOT import the runtime to get it (A22's rule is unchanged): a host + module whose shape wants a synchronous guest callback is **handed one + by the application** — `sync(exports.f)` produces a plain function — + exactly as a host module wanting writer-driven push is handed a + `StreamWriter` (A22); placement stays with the deploying application. + Recognition is by brand (`polyengine.syncCallable/1`, a registry symbol per A9) so views work across mixed runtime copies. Dispatch by target shape: