Skip to content

Latest commit

 

History

History
136 lines (107 loc) · 6.12 KB

File metadata and controls

136 lines (107 loc) · 6.12 KB

ADR-019: Compiler distribution — GitHub Releases binaries + thin Deno/JSR shim

Status

Accepted

Date

2026-05-19 (accepted); implementation S1–S4 landed 2026-05-20

Issue

INT-04 #260 (split from #181)

Series

Settled-decisions ledger; companion entry in .machine_readable/6a2/META.a2ml id="ADR-019"; narrative in docs/specs/SETTLED-DECISIONS.adoc §"Compiler Distribution".

Context

INT-04 (#181) is "publish compiler + runtime". The two halves have very different shapes:

  • The runtime JS packages (@hyperpolymath/affine-js, @hyperpolymath/affinescript-tea) are ordinary JSR/npm packages — their publish path is bounded packaging-prep (docs/PACKAGING.adoc) and was already ready/independent of this decision.

  • The compiler is a native OCaml binary. It is not a JSR/npm package, so "publish the compiler" has no off-the-shelf answer. How consumers — and in particular affinescript-lsp (INT-10) — install it is a one-way-door contract: it sets the install surface, the checksum/trust story, and the LSP’s compiler-resolution path.

This was escalated as a design fork (issue #260, AskUserQuestion 2026-05-19) rather than guessed, because it is irreversible-ish and outside the packaging-prep scope.

Decision

Option survey

The fork presented four options:

(1) GitHub Releases binaries. Per-platform artifacts via the existing release.yml (v* tags) + an install script / fetch-pin.

(2) Guix/Nix channel. Aligns with the repo’s primary packaging (guix.scm / flake.nix); reproducible, but a narrower audience and no deno/npm ergonomics for the LSP-installer consumers.

(3) Thin JSR/npm shim. A small package that, on first run, downloads a pinned, checksummed prebuilt binary and execs it — deno/npm ergonomics without shipping OCaml source.

(4) Combination of the above.

Chosen: (4) — Releases-canonical, dual-channel

The owner chose the combination, with GitHub Releases as the single canonical artifact source and a thin Deno/JSR shim as the ergonomic front door:

  • Canonical artifact. .github/workflows/release.yml, on a v* tag, builds per-platform compiler binaries and a SHA256SUMS manifest, both attached to the GitHub Release. The Release is the one source of truth; Guix/Nix and any later npm tail are additive fetch-derivations over it, not separate producers.

  • Ergonomic front door. A thin Deno/JSR package @hyperpolymath/affinescript downloads the host-platform binary from the pinned Release, verifies it against the SHA256SUMS checksum embedded in that shim version, then caches and execs it. HTTPS-only, no secrets, one version+checksum pinned per shim release (no floating fetch).

  • LSP path. affinescript-lsp (INT-10) resolves the compiler via AFFINESCRIPT_COMPILERaffinescript on PATH → the @hyperpolymath/affinescript shim. Consuming the shim is what unblocks INT-10; the LSP does no bespoke bundling.

  • npm tail deferred. An npm publish is added only if an npm-native consumer needs it, mirroring the affine-vscode runtime exception. It is not wired by this ADR.

Staging

Tracked in docs/TECH-DEBT.adoc (INT-04 / INT-10); all four stages have landed:

Stage Content Status

S1

This ADR + plan; file INT-10. No code.

DONE

S2

release.yml per-platform binary build + SHA256SUMS matrix

DONE (#283/#284/#285)

S3

The shim package — download + checksum-verify + cache + exec + tests; publish owner-gated via the existing manual JSR workflow

DONE

S4

Wire INT-10 affinescript-lsp onto the shim

DONE (#282)

First JSR publish landed 2026-05-20: @hyperpolymath/affinescript@0.1.2 LIVE (cross-runtime Deno + Bun + Node, MPL-2.0, sibling .d.ts for JSR fast-check). The shim pins all three v0.1.1 binaries by SHA256, so the resolution path executes end-to-end. Compiler version-string drift was fixed in lock-step via lib/version.ml (single source of truth) + a release.yml tag-time bake step (#297/#300).

Consequences

  • The install contract is Releases-first. Renaming the SHA256SUMS manifest or the per-platform asset names is an ABI change for every shim version and for Guix/Nix derivations downstream — do not rename without amending this ADR and the shim’s pinned spec.

  • Browsers and Cloudflare Workers are out of scope for the shim by construction (fetch → save to disk → exec a native binary cannot run in a sandboxed JS runtime). The shim’s runtime-compatibility matrix is therefore Deno ✅ / Bun ✅ / Node ✅ / Workers ❌ / Browsers ❌ (see .claude/CLAUDE.md Runtime Exemptions).

  • Reproducible-build consumers are served by the additive Guix/Nix derivations layered over the same Release artifact, not by a competing artifact source.

References

  • Issue: #260 (INT-04 compiler distribution), split from #181.

  • Unblocks: INT-10 #282 (affinescript-lsp distribution).

  • docs/specs/SETTLED-DECISIONS.adoc §"Compiler Distribution: GitHub Releases Binaries + Thin Deno/JSR Shim (ADR-019)" — the narrative twin of this record.

  • docs/PACKAGING.adoc §"The compiler itself — decided (ADR-019 / #260)".

  • docs/TECH-DEBT.adoc INT-04 / INT-10 rows.

  • .machine_readable/6a2/META.a2ml id="ADR-019" — the machine record.

  • .github/workflows/release.yml (S2 producer), .github/workflows/publish-jsr.yml (owner-gated shim publish), packages/affinescript-cli/ (the shim).

Standing rule

This decision is settled and implemented. Do not reopen without amending this ADR. The companion SETTLED-DECISIONS.adoc section and the META.a2ml ADR-019 record must move in lock-step with any amendment.