feat(bindings): AffineScript port of the Gossamer IPC binding (standards#252)#73
Merged
Merged
Conversation
…rds#252)
Migrate the frontend/consumer IPC binding from ReScript to AffineScript (the
estate-current successor language; ReScript is banned). Adds
bindings/affinescript/src/Gossamer.affine — a faithful 1:1 port of
bindings/rescript/src/Gossamer.res — which TYPE-CHECKS CLEAN against the
AffineScript compiler (`affinescript check`).
This is the frontend binding layer, NOT the Gossamer core: the core remains
Ephapax (ephapax-affine sublanguage, region-linear) + Zig + Idris2. AffineScript
is a distinct language from ephapax-affine (separate compiler/AST/checker/proof
story; they share only the typed-wasm target); the binding meets the core only
at the IPC boundary.
Two faithful adaptations, both documented in the file + README:
1. ReScript's polymorphic `invoke: (string,'a)=>promise<'b>` becomes
per-command typed externs — AffineScript's kind system admits no
fully-polymorphic boundary primitive (only prelude Option/Result are sound
generic carriers; cf. stdlib/future.affine), and typed externs match the
stdlib Http.get/post idiom.
2. ReScript nested `module Dialog = {…}` namespaces become flat prefixed names
(dialog_open, fs_read_text_file, …) — AffineScript is one module per file.
Effect rows `/ { IO, Async }` cross the bridge honestly; the Deno-ESM backend
lowers each extern to a window.__gossamer_invoke round-trip with native
async/await (same shape as stdlib Http over fetch).
Deliberately NOT bundled here (coordinated under standards#252, consumer-facing):
retiring the published `@gossamer/api` ReScript `.res` + re-pipelining its
build/publish onto the AffineScript Deno-ESM output. Tracked, not force-fit into
the Android PR.
https://claude.ai/code/session_01GsJX13UjwiBk9hkddqvYMh
🔍 Hypatia Security ScanFindings: 112 issues detected
View findings[
{
"reason": "Action perpolymath/standards/.github/workflows/governance-reusable.yml@main\n needs attention",
"type": "unpinned_action",
"file": "governance.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in abi-typecheck.yml",
"type": "missing_timeout_minutes",
"file": "abi-typecheck.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in boj-build.yml",
"type": "missing_timeout_minutes",
"file": "boj-build.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in codeql.yml",
"type": "missing_timeout_minutes",
"file": "codeql.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in dogfood-gate.yml",
"type": "missing_timeout_minutes",
"file": "dogfood-gate.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in governance.yml",
"type": "missing_timeout_minutes",
"file": "governance.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
hyperpolymath
pushed a commit
that referenced
this pull request
Jun 2, 2026
…73 Session checkpoint for the PR #70 follow-through (CLI link fix, e2e §5 %unsafe-awareness, jni-cast SAFETY notes + thread resolution) and the ReScript->AffineScript IPC-binding migration split out to PR #73. No code change beyond STATE; also re-triggers CI on the current tip. https://claude.ai/code/session_01GsJX13UjwiBk9hkddqvYMh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Migrates Gossamer's frontend/consumer IPC binding from ReScript to AffineScript — the estate-current successor language (ReScript is banned per the Hyperpolymath language policy). Tracked under standards#252.
Adds
bindings/affinescript/src/Gossamer.affine, a faithful 1:1 port ofbindings/rescript/src/Gossamer.res, that type-checks clean against the AffineScript compiler (affinescript check→ Type checking passed).Layer note (important)
This is the frontend binding layer, not the Gossamer core. The core shell stays Ephapax (the
ephapax-affinesublanguage — region-linear) with Zig FFI and Idris2 ABI proofs. AffineScript is a different language fromephapax-affine(separate compiler / AST / type-checker / proof story); they share only thetyped-wasmtarget. This binding meets the Ephapax core only at the IPC boundary (window.__gossamer_invoke).Two faithful adaptations from the ReScript original
invoke: (string, 'a) => promise<'b>becomes per-command typed externs (window_set_title,dialog_open, …). AffineScript's kind system admits no fully-polymorphic boundary primitive (only preludeOption/Resultare sound generic carriers — seestdlib/future.affine), and typed externs match the stdlibHttp.get/Http.postidiom (and are sounder).module Dialog = { … }namespaces become flat, prefixed names (dialog_open,fs_read_text_file, …): AffineScript is one module per file, so the prefix carries the namespace.Async + effects
Every bridge-crossing signature carries the effect row
/ { IO, Async }(IPC isIO; the host round-trip isAsync). The Deno-ESM backend (codegen_deno.ml) lowers eachextern fnto awindow.__gossamer_invoke(...)round-trip and compilesAsynccallers to nativeasync/await— the same shape stdlibHttp.http_requestuses overglobalThis.fetch. A ReScriptpromise<result<T,string>>maps to an AffineScript value in theAsynceffect, no promise-monad wrapper.Verification
affinescript check bindings/affinescript/src/Gossamer.affine→ Type checking passed (verified with the compiler resolvingpreludefrom the stdlib).Scope — what this PR does NOT do (by design)
The published
@gossamer/apipackage currently ships the ReScript.res.js. Retiringbindings/rescript/and re-pipelining the build/publish (and examples) onto the AffineScript Deno-ESM output is consumer-facing and stays coordinated under standards#252 — not bundled here. This PR adds the verified binding so downstream can begin targeting it.Follow-up enabled by AffineScript
The capability
Tokenis carried as a plain record (matching the.res). Because AffineScript is affine-typed, a follow-up can make it linear so "must be revoked / consumed once" is type-enforced rather than a doc-comment — extending Gossamer's linearity guarantee to the frontend edge.Generated by Claude Code