Skip to content

feat(bindings): AffineScript port of the Gossamer IPC binding (standards#252)#73

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/gossamer-rescript-to-affinescript
Jun 2, 2026
Merged

feat(bindings): AffineScript port of the Gossamer IPC binding (standards#252)#73
hyperpolymath merged 1 commit into
mainfrom
claude/gossamer-rescript-to-affinescript

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

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 of bindings/rescript/src/Gossamer.res, that type-checks clean against the AffineScript compiler (affinescript checkType checking passed).

Layer note (important)

This is the frontend binding layer, not the Gossamer core. The core shell stays Ephapax (the ephapax-affine sublanguage — region-linear) with Zig FFI and Idris2 ABI proofs. AffineScript is a different language from ephapax-affine (separate compiler / AST / type-checker / proof story); they share only the typed-wasm target. This binding meets the Ephapax core only at the IPC boundary (window.__gossamer_invoke).

Two faithful adaptations from the ReScript original

  1. ReScript's single polymorphic 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 prelude Option/Result are sound generic carriers — see stdlib/future.affine), and typed externs match the stdlib Http.get/Http.post idiom (and are sounder).
  2. ReScript nested 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 is IO; the host round-trip is Async). The Deno-ESM backend (codegen_deno.ml) lowers each extern fn to a window.__gossamer_invoke(...) round-trip and compiles Async callers to native async/await — the same shape stdlib Http.http_request uses over globalThis.fetch. A ReScript promise<result<T,string>> maps to an AffineScript value in the Async effect, no promise-monad wrapper.

Verification

  • affinescript check bindings/affinescript/src/Gossamer.affineType checking passed (verified with the compiler resolving prelude from the stdlib).

Scope — what this PR does NOT do (by design)

The published @gossamer/api package currently ships the ReScript .res.js. Retiring bindings/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 Token is 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

…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
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

🔍 Hypatia Security Scan

Findings: 112 issues detected

Severity Count
🔴 Critical 3
🟠 High 36
🟡 Medium 73

⚠️ Action Required: Critical security issues found!

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
@hyperpolymath hyperpolymath marked this pull request as ready for review June 2, 2026 18:40
@hyperpolymath hyperpolymath merged commit 2e3ca1f into main Jun 2, 2026
20 of 23 checks passed
@hyperpolymath hyperpolymath deleted the claude/gossamer-rescript-to-affinescript branch June 2, 2026 18:41
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.

2 participants