Skip to content

Commit 87f4adb

Browse files
committed
chore(packaging): INT-04 JSR packaging prep — runtime publish-ready, NOT published (Refs #181 #260)
Bounded packaging prep (owner-directed: prepare only, stop before publish). Nothing is published; the workflow is manual-only. - `packages/affine-js` + `affinescript-tea`: `deno publish --dry-run` green. Two real packaging defects fixed: * test files were being published → `publish.exclude` in both deno.json (`loader_test.js` / `mod_test.js`). * `affinescript-tea/mod.js` imported affine-js via a cross-package relative path (`../packages/affine-js/loader.js`) — broken for any JSR consumer. Rewired to the bare spec `@hyperpolymath/affine-js/loader` + an import map in affinescript-tea/deno.json (resolves in-repo and to the JSR package once affine-js is published). 9/9 tea tests still green. - `.github/workflows/publish-jsr.yml`: **manual `workflow_dispatch` only** (never on push/merge), JSR OIDC via `id-token: write` (no token secret), `dry_run` defaults true, per-package. Publish order is load-bearing: affine-js before affinescript-tea. - `docs/PACKAGING.adoc`: publish-readiness, order, slow-types note, npm tail, and the open compiler-distribution question. - Filed **#260**: the compiler is a native OCaml binary, NOT a JSR/npm package — its distribution is a one-way-door design fork (surfaced, not guessed; blocks INT-10 LSP distribution). Gate: `dune test --force` 278/278 (no compiler change; zero regression). NOT published — owner-gated (explicit go + JSR/npm auth). Refs #181 #260. Not Closes — owner closes per ISSUE-CLOSURE.
1 parent abf86e8 commit 87f4adb

7 files changed

Lines changed: 144 additions & 8 deletions

File tree

.github/workflows/publish-jsr.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# INT-04 (#181): publish the JS runtime packages to JSR (Deno/JSR-first
3+
# per CLAUDE.md). Scaffolded by packaging prep — it is **manual-only**
4+
# (`workflow_dispatch`) and does NOT run on push/merge. The owner
5+
# dispatches it deliberately, package-by-package, after reviewing the
6+
# `deno publish --dry-run` output. No secrets are required or committed:
7+
# JSR uses GitHub OIDC (the `id-token: write` permission below); npm is
8+
# a separate, later tail (NOT wired here — see docs/PACKAGING.adoc).
9+
#
10+
# Publish order is load-bearing: @hyperpolymath/affine-js MUST be
11+
# published before @hyperpolymath/affinescript-tea (the latter depends
12+
# on the former via an import map).
13+
14+
name: Publish to JSR (manual)
15+
16+
on:
17+
workflow_dispatch:
18+
inputs:
19+
package:
20+
description: "Which package to publish"
21+
required: true
22+
type: choice
23+
options:
24+
- affine-js
25+
- affinescript-tea
26+
dry_run:
27+
description: "Dry run only (no publish)"
28+
required: true
29+
type: boolean
30+
default: true
31+
32+
permissions:
33+
contents: read
34+
id-token: write # JSR OIDC; no token secret needed
35+
36+
jobs:
37+
publish:
38+
runs-on: ubuntu-latest
39+
steps:
40+
- uses: actions/checkout@v4
41+
- uses: denoland/setup-deno@v2
42+
with:
43+
deno-version: v2.x
44+
- name: Resolve package directory
45+
id: pkg
46+
run: |
47+
case "${{ inputs.package }}" in
48+
affine-js) echo "dir=packages/affine-js" >> "$GITHUB_OUTPUT" ;;
49+
affinescript-tea) echo "dir=affinescript-tea" >> "$GITHUB_OUTPUT" ;;
50+
esac
51+
- name: Dry run
52+
working-directory: ${{ steps.pkg.outputs.dir }}
53+
run: deno publish --dry-run
54+
- name: Publish
55+
if: ${{ inputs.dry_run == false }}
56+
working-directory: ${{ steps.pkg.outputs.dir }}
57+
run: deno publish

affinescript-tea/deno.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
"exports": {
55
".": "./mod.js"
66
},
7+
"imports": {
8+
"@hyperpolymath/affine-js/loader": "../packages/affine-js/loader.js"
9+
},
710
"license": "PMPL-1.0-or-later",
11+
"publish": {
12+
"exclude": ["mod_test.js"]
13+
},
814
"tasks": {
915
"test": "deno test --allow-read --allow-write --allow-run mod_test.js"
1016
}

affinescript-tea/mod.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import {
2626
parseOwnershipSection,
2727
readBytes,
28-
} from "../packages/affine-js/loader.js";
28+
} from "@hyperpolymath/affine-js/loader";
2929

3030
/**
3131
* One model field, decoded from the `affinescript.tea_layout` section.
@@ -94,14 +94,14 @@ export class TeaApp {
9494
/** @type {WebAssembly.Instance} */ #instance;
9595
/** @type {WebAssembly.Memory} */ #memory;
9696
/** @type {TeaLayout} */ #layout;
97-
/** @type {import("../packages/affine-js/loader.js").OwnershipEntry[]} */ #ownership;
97+
/** @type {import("@hyperpolymath/affine-js/loader").OwnershipEntry[]} */ #ownership;
9898
/** Re-entrancy guard enforcing the Linear-msg invariant. */
9999
#inCycle = false;
100100

101101
/**
102102
* @param {WebAssembly.Instance} instance
103103
* @param {TeaLayout} layout
104-
* @param {import("../packages/affine-js/loader.js").OwnershipEntry[]} ownership
104+
* @param {import("@hyperpolymath/affine-js/loader").OwnershipEntry[]} ownership
105105
*/
106106
constructor(instance, layout, ownership) {
107107
this.#instance = instance;
@@ -152,7 +152,7 @@ export class TeaApp {
152152
* The ownership annotations. `affinescript_update`'s `msg` parameter is
153153
* Linear (kind `"linear"`) — the host-visible proof that a message is
154154
* consumed exactly once per update cycle.
155-
* @type {import("../packages/affine-js/loader.js").OwnershipEntry[]}
155+
* @type {import("@hyperpolymath/affine-js/loader").OwnershipEntry[]}
156156
*/
157157
get ownership() {
158158
return this.#ownership;

docs/ECOSYSTEM.adoc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,11 @@ S1..S6; legacy preview1 stdout path is the default until S6
197197
(reversible-in-progress). S3+ HARD-GATED on S2 toolchain provisioning
198198
(`wasm-tools`/`wasm-component-ld`, absent). WIT world of record:
199199
`wit/affinescript.wit`
200-
|INT-04 |Publish compiler + runtime to JSR (then npm) |#181 |open, S2
201-
(blocked by INT-01)
200+
|INT-04 |Publish compiler + runtime to JSR (then npm) |#181 |runtime
201+
packaging READY (affine-js + affinescript-tea JSR dry-run green;
202+
manual-only `publish-jsr.yml`; docs/PACKAGING.adoc). INT-01 dep
203+
cleared. NOT published (owner-gated: needs explicit go + JSR/npm
204+
auth). Compiler-binary distribution = design fork #260
202205
|INT-05 |Loader-driven multi-module app bundling |ledger-only |planned
203206
(blocked by INT-02)
204207
|INT-06 |Server-side runtime profile (on INT-03 WASI p2) |ledger-only

docs/PACKAGING.adoc

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// SPDX-License-Identifier: PMPL-1.0-or-later
2+
// SPDX-FileCopyrightText: 2026 hyperpolymath
3+
= AffineScript Packaging & Distribution (INT-04)
4+
:toc: macro
5+
:icons: font
6+
7+
INT-04 (#181). This documents what is publish-ready, the order, and the
8+
one open design question. *Nothing here publishes anything*: the
9+
workflow is manual-only and the owner dispatches it after review.
10+
11+
toc::[]
12+
13+
== JSR-publishable units (Deno/JSR-first)
14+
15+
The JS runtime packages are JSR-publishable today. `deno publish
16+
--dry-run` succeeds for both (verified during INT-04 prep):
17+
18+
[cols="2,2,3"]
19+
|===
20+
|Package |Spec |Notes
21+
22+
|`packages/affine-js` |`@hyperpolymath/affine-js` |Loader + marshal +
23+
runtime + ownership accessor. Tests excluded via `publish.exclude`.
24+
|`affinescript-tea` |`@hyperpolymath/affinescript-tea` |TEA runtime.
25+
Depends on `@hyperpolymath/affine-js/loader` (import map) — see order.
26+
|===
27+
28+
*Publish order is load-bearing*: `affine-js` **must** publish before
29+
`affinescript-tea` (the latter resolves `@hyperpolymath/affine-js/loader`).
30+
31+
`affinescript-dom` is AffineScript source (`.affine`), not a JS package
32+
— it is consumed by the compiler, not JSR; out of scope for JSR.
33+
34+
=== Slow types
35+
36+
The JS entrypoints emit JSR's `unsupported-javascript-entrypoint`
37+
(slow-types) warning — expected for a JS-with-JSDoc package; it
38+
publishes, only `@hyperpolymath/affine-js`'s fast-check is skipped.
39+
`types.d.ts` already provides the consumer-facing contract. Converting
40+
entrypoints is out of scope for INT-04 (tracked separately if desired).
41+
42+
== How to publish (owner, manual)
43+
44+
. Review `deno publish --dry-run` (CI: `Publish to JSR (manual)` with
45+
`dry_run: true`, or locally `cd <pkg> && deno publish --dry-run`).
46+
. Dispatch `.github/workflows/publish-jsr.yml` for `affine-js` with
47+
`dry_run: false` (JSR OIDC via `id-token: write` — no token secret).
48+
. Then dispatch it for `affinescript-tea`.
49+
50+
== npm tail
51+
52+
"then npm" (#181) is a *separate, later* step and is **not** wired by
53+
this prep. If/when needed it follows the existing owner-sanctioned npm
54+
pattern (`.github/workflows/affine-vscode-publish.yml`, `NPM_TOKEN`
55+
scoped automation token) — a deliberate exception to Deno-first.
56+
57+
== Open design question — the compiler itself
58+
59+
#181 says "publish *compiler* + runtime". The runtime is the JS
60+
packages above. The **compiler is a native OCaml binary** — it is *not*
61+
a JSR or npm package. "Publishing the compiler" therefore needs a
62+
release-binary strategy decision (GitHub Releases artifacts, Guix/Nix
63+
channel, or a thin JSR/npm shim that fetches a pinned binary). This is
64+
a one-way-door design choice and is filed as a separate issue rather
65+
than guessed here. `affinescript-lsp` distribution (INT-10) depends on
66+
that decision.

docs/TECH-DEBT.adoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ follow-up
162162
|INT-03 |WASI preview2 / host I/O |S1 |#180 ADR-015 accepted (full
163163
Component-Model re-target, staged S1..S6); S3+ hard-gated on S2
164164
toolchain (`wasm-tools`/`wasm-component-ld`)
165-
|INT-04 |Publish to JSR/npm |S2 |open #181 (◄ INT-01)
165+
|INT-04 |Publish to JSR/npm |S2 |#181 packaging READY (dry-run green,
166+
manual workflow); owner-gated publish; compiler-binary = #260
166167
|INT-07 |`affinescript-tea` runtime |S2 |#182 runtime + run loop shipped
167168
(TeaApp/parseTeaLayout, Linear-msg enforced); INT-01 cleared (#253)
168169
|INT-08 |DOM reconciler |S2 |#183 implemented + compiles; `.as`→`.affine`

packages/affine-js/deno.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,8 @@
77
"./marshal": "./marshal.js",
88
"./runtime": "./runtime.js"
99
},
10-
"license": "PMPL-1.0-or-later"
10+
"license": "PMPL-1.0-or-later",
11+
"publish": {
12+
"exclude": ["loader_test.js"]
13+
}
1114
}

0 commit comments

Comments
 (0)