Skip to content

Commit 22fc2ed

Browse files
robertsLandoclaude
andauthored
docs: host documentation on GitHub Pages with VitePress (#234)
* docs: host documentation on GitHub Pages with VitePress Move README content into a proper documentation site built with VitePress and deployed to https://yao-pkg.github.io/pkg/ via GitHub Actions. - Landing page with pkg identity (amber/pink palette from logo) - Guide split into 21 focused pages (getting started, targets, config, bytecode, compression, SEA mode, snapshot FS, native addons, ESM, API, troubleshooting, advanced) - New SEA vs Standard page highlighting the stock-binary benefit and linking the pkg-fetch elimination roadmap (#231) - DEVELOPMENT.md and docs/ARCHITECTURE.md canonical sources moved into docs-site/, roots replaced with stub pointers to avoid drift - README trimmed to install + quick start + links to hosted docs - .github/workflows/docs.yml builds and deploys on push to main Manual follow-up: enable GitHub Pages with Source = GitHub Actions in repo settings. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * docs: update GitHub Actions to use latest versions of checkout, setup-node, and deploy-pages * docs: address self-review feedback on docs site PR - gate docs workflow on PRs (build-only) to catch VitePress breakage before merge - switch workflow to npm ci with cache-dependency-path for reproducible installs - read site version from package.json so nav dropdown no longer rots each release - reconcile SEA vs Standard messaging on the guide landing page - fix typos and stale DEVELOPMENT.md references in copilot-instructions - mark root DEVELOPMENT.md and docs/ARCHITECTURE.md stubs as non-canonical - replace non-standard -webkit-linear-gradient with standard linear-gradient Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * docs: major docs site overhaul — tutorials, recipes, mermaid, migration New pages: - guide/migration.md — drop-in migration from archived vercel/pkg fork - guide/recipes.md — copy-paste cookbook for common tasks - changelog.md — CHANGELOG.md mirrored into the docs site via include Rewritten pages: - guide/getting-started.md — first-binary tutorial with code groups + full CLI table; no more raw --help dump - guide/sea-mode.md — leads with a hello-world walkthrough - guide/configuration.md — full schema table + production example - guide/targets.md — code groups + tip callout + alpine/musl section - guide/environment.md — inlined pkg-fetch vars + PKG_EXECPATH clarification - guide/troubleshooting.md — NODE_OPTIONS dead end replaced with a full fix, check-this-first preface added - guide/bytecode|compression|options|build|output|snapshot-fs|native-addons| esm|api|packaged-app|custom-node|detecting-assets|advanced-debug-vfs| advanced-windows-metadata — expanded + frontmatter + next-step links VitePress config: - withMermaid for mermaid flowchart support - sitemap.hostname for SEO - outline level raised to [2, 4] - Collapsed singleton sidebar groups into a Cookbook section - Added Recipes to the top nav - Version dropdown links to migration + changelog Landing page: - vercel/pkg fork banner - Social badges (npm version, downloads, stars, CI, license) - Code groups for CLI vs package.json vs Node.js API - Standard vs SEA side-by-side Architecture: - Top-level mermaid overview comparing both build paths - Mermaid flowcharts for traditional + SEA build pipelines - Mermaid flow for VFS provider path resolution - ASCII diagrams kept for readers who prefer them Development page: - Full docs-site local dev workflow - Structure, mermaid how-to, new-page checklist - Canonical-source note for the root stubs Polish: - Responsive hero image on small viewports - Fork-banner CSS - .nvmrc pinning docs-site to Node 22 - Frontmatter (title + description) on every guide page for SEO - Twitter card meta Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * docs: add hero terminal GIF and fix badge stacking on landing page - Record a real 15s pkg session (mkdir → echo → pkg index.js → ls → run) with VHS as docs-site/public/hero.gif (98KB). Tape-based so it is reproducible in CI if we want to regenerate it later. - Embed the GIF in the landing page as a figure under the fork banner. - Replace the inline HTML badge anchors with Markdown image links on a single line so VitePress renders them inside a single <p>. The old setup put each anchor on its own line which the markdown processor wrapped in separate paragraphs, stacking the badges vertically. - Add .landing-badges / .landing-demo / .landing-body CSS: flex layout for the badge row, shadow + border-radius on the demo GIF, consistent max-width + padding on the content block. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * docs: re-record hero GIF with a working sandboxed pkg wrapper The previous recording ran VHS with a PATH that did not include the nvm node bin dir, so the /tmp/bin/pkg wrapper's `env ... node ...` invocation failed with "env: node: No such file or directory" and the session showed three cascading errors instead of a successful build. Fix: hardcode the absolute node path inside the wrapper so it works under any restricted PATH. Re-recorded — now shows the real pkg build producing three binaries and running the linux one. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * docs: update mermaid diagram styles for better readability and adjust SEA mode documentation * docs: enhance dark mode visibility for mermaid diagrams and update native addon notes * docs: trim docs-site verbosity and split architecture doc Audience split: keep the detailed pipelines, binary layouts, VFS provider, worker bootstrap and patch tables as docs/ARCHITECTURE.md (contributor / agent reference), and replace docs-site/architecture.md with a lean ~110 line user overview that links back to it. Also dedup SEA-vs-standard and walker explanations across index pages, collapse the pkg-fetch roadmap down to a pointer to #231, share the reference sidebar config, and add a jump TOC to the recipes page. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * docs: clarify cross-compile support and Node 22 regression Standard cross-compile is confirmed broken on Node 22 targets (builds succeed but linux-arm64 crashes with UNEXPECTED-20 and win-x64 exits silently, matching #87 and #181). Node 20 and Node 24 are fine in both Standard and Enhanced SEA modes. Rewrite the targets.md Cross-compilation section as a node-version-keyed support table with the regression called out, and reference it from the landing page, getting-started, and the sea-vs-standard feature matrix. Verified on a Linux x86_64 host against linux-x64, linux-arm64 (via docker + QEMU) and win-x64 (via docker + Wine) for each of Node 20, 22, and 24 using the pkg-xcompile-test harness. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * chore(skills): add pkg-xcompile-test skill Project-local skill (under .claude/skills/) that runs a full (mode × target) cross-compile matrix for pkg and reports which combinations work. Default modes are std, std-public (--public-packages "*" --public) and sea; targets cover linux-x64, linux-arm64 (via docker + QEMU), win-x64 (via docker + Wine), and macos-* (build only — runtime verification needs a real Mac). The run-matrix.sh script auto-switches nvm to match the target node major, resolves PKG_BIN from its own location (<repo>/lib-es5/bin.js), and writes binaries to $PKG_XCOMPILE_WORKDIR (default /tmp/pkg-xcompile) so the working tree stays clean. SKILL.md records the known results for node 20/22/24 as of 2026-04-15 and documents the wine-in-docker stdout gotcha. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * ci: add cross-compile matrix workflow Adds a GitHub Actions workflow that builds hello.js from every supported host runner (linux-x64, linux-arm64, macos-x64, macos-arm64, win-x64) for every target triple, in Standard / Standard+public / SEA modes on Node 22. Each produced binary is then executed on its target runner, and a per-mode matrix of the host-to-target results is posted as a sticky PR comment. Structured as three stages: 1. build — matrix of (host × mode × node); each job compiles all targets from that host and uploads the binaries. 2. run — one job per target runner; downloads all artifacts, filters by target, runs each binary, writes result JSON. 3. collate — renders the markdown matrix and upserts it as a PR comment using a <!-- xcompile-matrix --> marker so re-runs update instead of spamming. Build failures are emitted as ".failed" sentinel files so the run stage can distinguish BUILD_FAIL from RUN_FAIL. Uses yarn (the repo's package manager) and pins actions to the versions already used elsewhere in the repo (checkout@v6, setup-node@v6, upload/download- artifact@v4, github-script@v7). Triggers on PRs touching lib/, prelude/, dictionary/, scripts/, package.json, yarn.lock, or the workflow itself, and on workflow_dispatch for manual runs. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * fix: address deep-review findings on docs site branch - docs: fix broken cross-page anchors in bytecode, recipes, build and sea-mode guides; replace raw /pkg/ prefixed link in index.md with VitePress-managed markdown link. - ci(xcompile): switch cross-compile matrix to workflow_dispatch only (manual trigger is safer and avoids burning macOS/Windows minutes on every PR), wire the node-majors input via a setup job, add timeouts, upload per-cell build logs, short-circuit collate when no results, fix empty-array expansion under bash 3.2 / set -u on macOS runners, add spawnSync timeout, sanitise backticks in PR summary, and drop the dead PR-comment path. - ci(docs): split concurrency so PR builds no longer queue behind production deploys, scope pages/id-token permissions to the deploy job, add timeout-minutes, and add an offline lychee link-check step to catch dead anchors before they ship. - chore(skills): make run-matrix.sh fail fast (set -euo pipefail), write per-cell logs under $WORKDIR/logs so a failing cell is not overwritten, print log paths on stderr, add an unknown-target case, and document the debugging workflow in SKILL.md. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * chore: drop root package-lock.json and standardize on yarn for pkg package-lock.json was created by accident in #229 alongside the yarn lockfile. pkg's canonical package manager is yarn (see yarn.lock); the accidental npm lockfile drifts silently and confuses contributors. - Remove package-lock.json and gitignore it at the repo root so it cannot reappear. - Rewrite the dev-command references in CLAUDE.md, .claude/rules/*, .github/copilot-instructions.md and docs-site/development.md from "npm run <x>" to "yarn <x>", and spell out the split: pkg uses yarn, docs-site is the only place npm is used. User-facing install instructions (README, guide/getting-started, guide/ migration, guide/api) are unchanged — end users still "npm install -g @yao-pkg/pkg" and the CI recipe example still shows npm, since that reflects how consumers package their own projects. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * ci: fix xcompile matrix false failures on macos and build-fail reporting First run of the matrix on #234 surfaced three harness bugs (all cells that failed under Standard mode were already matching the known Node 22 regression — those were expected). The CI-side bugs were: 1. macos-arm64 std jobs died on the first target with `EXTRA[@]: unbound variable`. Bash 3.2 ships on GitHub's macOS runners, and `set -u` + `"${EMPTY_ARRAY[@]}"` is a nounset error there. std-public/sea worked only because EXTRA was non-empty. Expand it with `${EXTRA[@]+"${EXTRA[@]}"}` instead, which degrades gracefully on old bash. 2. All macos-x64 build and run jobs were cancelled by the runner pool — GitHub has retired the Intel macOS runner (macos-13). Drop macos-x64 as a build host entirely, and route the macos-x64 *target* runs to macos-14, which pre-installs Rosetta 2 and executes x86_64 Mach-O binaries transparently. 3. The run-stage reader iterated binaries and skipped .failed sidecars, so a pkg failure that left no output at all (vs. a 0-byte stub) dropped the combo out of the matrix as `:grey_question:` instead of showing `:x:&nbsp;build`. Also capture pkg's real exit code via `|| status=$?` so `set -e` doesn't eat it, always leave an empty binary on failure so the reader enumerates every combo, and pull the last 5 lines of the build log into the BUILD_FAIL detail so the collated summary surfaces the actual error without downloading artifacts. Verified by parsing the workflow YAML: 4 build hosts (linux-x64, linux-arm64, macos-arm64, win-x64), 5 run targets including macos-x64@macos-14. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * fix(ci): drop lychee link-checker from docs workflow The step was a belt-and-braces defence against dead anchors, but lychee fights VitePress's /pkg/ base-URL rewrite and extensionless URLs — it reports ~2000 false positives for resources that are served fine on the live site. Not worth the complexity; VitePress's own build-time dead-link check already catches markdown link typos, and the five broken anchors that motivated the step have been fixed and are verified against the rendered HTML. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * docs: proofread development.md Address Copilot review feedback on grammar in docs-site/development.md: fix "create release", "have build", "runned", "It install", and "Foreach" phrases flagged by the reviewer. * ci: skip heavy jobs on docs-only PRs Add a `changes` job that uses dorny/paths-filter to detect whether anything outside docs-site/ was touched. The build matrix and every test.yml call still run so their required status check contexts are reported, but their steps are gated on the flag — docs-only PRs get green checks in seconds instead of burning the full OS/node matrix. --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
1 parent 6b70b3b commit 22fc2ed

54 files changed

Lines changed: 7794 additions & 9088 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/rules/development.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,27 @@ description: Build, lint, formatting, and TypeScript rules
44

55
# Development
66

7+
## Package manager
8+
9+
`pkg` uses **yarn** (see `yarn.lock`). **Never run `npm install` / `npm ci` / `npm run X` at the repo root** — it will create a spurious `package-lock.json`. `npm` is used only inside `docs-site/` (the VitePress site has its own `package-lock.json`).
10+
711
## Build
812

913
```bash
10-
npm run build # Required before testing — compiles lib/ to lib-es5/
11-
npm run start # Watch mode with auto-rebuild
14+
yarn build # Required before testing — compiles lib/ to lib-es5/
15+
yarn start # Watch mode with auto-rebuild
1216
```
1317

1418
## Lint & Format
1519

1620
```bash
17-
npm run lint # Check both ESLint + Prettier
18-
npm run fix # Auto-fix all issues
19-
npm run lint:code # ESLint only
20-
npm run lint:style # Prettier only
21+
yarn lint # Check both ESLint + Prettier
22+
yarn fix # Auto-fix all issues
23+
yarn lint:code # ESLint only
24+
yarn lint:style # Prettier only
2125
```
2226

23-
- Always run `npm run lint` before committing. Fix all issues — never push dirty code.
27+
- Always run `yarn lint` before committing. Fix all issues — never push dirty code.
2428
- Console statements are disallowed in production code but allowed in test files.
2529

2630
## TypeScript

.claude/rules/git-and-pr.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ description: Git workflow, commit conventions, and PR rules
1818
## Before Committing
1919

2020
1. Clean test artifacts from test directories (`*.exe`, `*-linux`, `*-macos`, `*-win.exe`).
21-
2. Run `npm run lint` and fix all issues.
21+
2. Run `yarn lint` and fix all issues.
2222
3. Show `git status --short` and get user approval before committing.
2323

2424
## Release
2525

26-
Uses `release-it` with conventional commits (`npm run release`). This runs linting, generates changelog, creates a git tag, pushes to GitHub, and publishes to npm as `@yao-pkg/pkg`.
26+
Uses `release-it` with conventional commits (`yarn release`). This runs linting, generates changelog, creates a git tag, pushes to GitHub, and publishes to npm as `@yao-pkg/pkg`.

.claude/rules/project.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ This is `yao-pkg/pkg` — a maintained fork of the archived `vercel/pkg`.
1010

1111
## Repository Structure
1212

13-
- `lib/` — TypeScript source (compiled to `lib-es5/` via `npm run build`)
13+
- `lib/` — TypeScript source (compiled to `lib-es5/` via `yarn build`)
1414
- `prelude/` — Bootstrap code injected into packaged executables
1515
- `dictionary/` — Package-specific configs for known npm packages
1616
- `test/` — Numbered test directories (`test-XX-name/`)
@@ -22,3 +22,8 @@ This is `yao-pkg/pkg` — a maintained fork of the archived `vercel/pkg`.
2222
- `lib/bin.js` — CLI entry point
2323
- `prelude/bootstrap.js` — Injected into every packaged executable
2424
- `dictionary/*.js` — Special handling for specific npm packages
25+
26+
## Architecture Reference
27+
28+
- `docs/ARCHITECTURE.md`**detailed** contributor/agent reference. Full build pipelines, binary layout, VFS provider, worker-thread bootstrap, patch tables. Read this when working on `lib/` or `prelude/`.
29+
- `docs-site/architecture.md` — short user-facing overview (linked from the published docs site). Don't duplicate internals here; link back to `docs/ARCHITECTURE.md`.

.claude/rules/testing.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ paths:
99
## Commands
1010

1111
```bash
12-
npm run build # Always build first
13-
npm run test:22 # Test with Node.js 22
14-
npm run test:host # Test with host Node.js version
12+
yarn build # Always build first
13+
yarn test:22 # Test with Node.js 22
14+
yarn test:host # Test with host Node.js version
1515
node test/test.js node22 no-npm test-50-* # Run specific test pattern
1616
```
1717

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
---
2+
name: pkg-xcompile-test
3+
description: >
4+
Cross-compile test harness for @yao-pkg/pkg. Builds a tiny hello.js for
5+
every (mode × target) combination and runs what can be executed on a Linux
6+
host (native x64, arm64 via docker+qemu, win-x64 via docker-wine). Use
7+
when the user wants to verify pkg cross-compilation claims, reproduce
8+
issues #87/#181, sanity-check a pkg PR, or compare Standard vs Enhanced
9+
SEA across Node 20/22/24. Trigger: "test cross-compile", "run pkg
10+
matrix", "verify xcompile", or /pkg-xcompile-test.
11+
---
12+
13+
# pkg cross-compile test harness
14+
15+
Validates `pkg` cross-OS and cross-arch support across Node 20/22/24 and
16+
Standard vs Enhanced SEA modes. Produces a consistent result table so
17+
claims in docs and issues can be checked against reality.
18+
19+
## When to use
20+
21+
- User is about to edit docs about cross-compile support and needs ground truth.
22+
- User is looking at a cross-compile issue (e.g. [#87](https://github.com/yao-pkg/pkg/issues/87), [#181](https://github.com/yao-pkg/pkg/issues/181)) and wants to reproduce it.
23+
- User bumped `pkg-fetch` or touched bootstrap/prelude and wants a smoke test across targets.
24+
- User wants to know whether a regression is Node-version specific.
25+
26+
## Host requirements
27+
28+
This harness is designed for a **Linux x86_64** host with:
29+
30+
- `nvm` with node 20, 22, and 24 installed (`nvm install 20 22 24`).
31+
- `docker` daemon running.
32+
- `docker` image `scottyhardy/docker-wine` (pulled on first win-x64 run).
33+
- `tonistiigi/binfmt` installed for cross-arch containers — if you see
34+
`exec format error` on arm64 runs, install with:
35+
```bash
36+
docker run --privileged --rm tonistiigi/binfmt --install arm64
37+
```
38+
- `pkg` built from this repo (`yarn build`) so `lib-es5/bin.js` exists.
39+
The script resolves the pkg entry from its own location — it lives at
40+
`.claude/skills/pkg-xcompile-test/run-matrix.sh` and defaults
41+
`PKG_BIN` to `<repo-root>/lib-es5/bin.js`.
42+
43+
**Not supported:** macOS runtime verification. `docker-osx` needs `/dev/kvm`
44+
and darling is dead. macOS regressions have to be caught on a real Mac
45+
or on the GitHub Actions `macos-*` runners — note that in the final report.
46+
47+
## What it runs
48+
49+
For each Node major (20, 22, 24) the harness:
50+
51+
1. Uses `nvm use $major` so the pkg **host** node matches the **target**
52+
node major. This matters — SEA's blob generator uses host `execPath`
53+
when host-major == target-major, otherwise tries to run the downloaded
54+
target-arch node binary (which fails without cross-arch emulation).
55+
2. Loops over modes × targets:
56+
- **Modes**: `std`, `std-public` (`--public-packages "*" --public`), `sea`
57+
- **Targets**: `linux-x64`, `linux-arm64`, `win-x64`, `macos-x64`, `macos-arm64`
58+
3. Records **build result** (OK / FAIL), then tries to **run** the binary:
59+
- linux-x64 → native
60+
- linux-arm64 → `docker run --platform linux/arm64 ubuntu:latest`
61+
- win-x64 → `docker run scottyhardy/docker-wine` (see gotcha below)
62+
- macos-\* → skipped (`SKIP-no-mac`)
63+
4. Prints a summary table.
64+
65+
## Wine gotcha
66+
67+
`wine` inside a non-tty docker container produces invalid stdio file
68+
descriptors, causing Node to crash with `Error: open EBADF` before any
69+
user code runs. The workaround is to redirect wine's stdout/stderr to
70+
files **inside** the container, then `cat` them back:
71+
72+
```bash
73+
docker run --rm -v "$BINDIR:/mnt" scottyhardy/docker-wine \
74+
bash -c "wine '/mnt/app.exe' </dev/null >/tmp/out 2>/tmp/err; cat /tmp/out"
75+
```
76+
77+
Without this, every wine run will look like a pkg failure when it isn't.
78+
79+
## Usage
80+
81+
Run from the repo root (paths in the examples are relative to it).
82+
83+
### Quick run (single node version)
84+
85+
```bash
86+
# Runs the full matrix for node 22 targets with node 22 as host
87+
./.claude/skills/pkg-xcompile-test/run-matrix.sh 22
88+
```
89+
90+
### Full sweep (20 + 22 + 24)
91+
92+
```bash
93+
for V in 20 22 24; do
94+
./.claude/skills/pkg-xcompile-test/run-matrix.sh $V
95+
done
96+
```
97+
98+
### Custom pkg build
99+
100+
```bash
101+
./.claude/skills/pkg-xcompile-test/run-matrix.sh 22 /path/to/other/pkg/lib-es5/bin.js
102+
```
103+
104+
### Custom work directory
105+
106+
By default build outputs go to `/tmp/pkg-xcompile/bin-node<major>/`. Override with:
107+
108+
```bash
109+
PKG_XCOMPILE_WORKDIR=/somewhere/else ./.claude/skills/pkg-xcompile-test/run-matrix.sh 22
110+
```
111+
112+
### Reading the output
113+
114+
Each cell is `BUILD / RUN`:
115+
116+
- `OK / OK` — works
117+
- `OK / FAIL` — built, but runtime error on target
118+
- `FAIL / n/a` — build failed
119+
- `OK / SKIP-no-mac` — can't test macOS runtime on this host
120+
121+
## Known results (captured 2026-04-15)
122+
123+
Host: Ubuntu 24.04 x86_64, pkg HEAD of `docs/github-pages-site`. Tests run
124+
with matching host-node / target-node major.
125+
126+
### Node 20
127+
128+
| target | std | std-public | sea |
129+
| ----------- | -------- | ---------- | ------------------------------ |
130+
| linux-x64 | OK / OK | OK / OK | **FAIL** — SEA needs host ≥ 22 |
131+
| linux-arm64 | OK / OK | OK / OK | FAIL (same) |
132+
| win-x64 | OK / OK | OK / OK | FAIL (same) |
133+
| macos-x64 | OK / n/a | OK / n/a | FAIL (same) |
134+
| macos-arm64 | OK / n/a | OK / n/a | FAIL (same) |
135+
136+
Standard cross-compile on Node 20 **works without workarounds**.
137+
SEA mode is unavailable because pkg enforces `host node ≥ 22`.
138+
139+
### Node 22
140+
141+
| target | std | std-public | sea |
142+
| ----------- | ------------- | ---------- | -------- |
143+
| linux-x64 | OK / OK | OK / OK | OK / OK |
144+
| linux-arm64 | OK / **FAIL** | OK / OK | OK / OK |
145+
| win-x64 | OK / **FAIL** | OK / OK | OK / OK |
146+
| macos-x64 | OK / n/a | OK / n/a | OK / n/a |
147+
| macos-arm64 | OK / n/a | OK / n/a | OK / n/a |
148+
149+
Standard cross-compile on Node 22 is **broken**:
150+
151+
- `linux-arm64` crashes at runtime with `Error: UNEXPECTED-20` in
152+
`readFileFromSnapshot`. Matches the [#181](https://github.com/yao-pkg/pkg/issues/181)
153+
failure mode.
154+
- `win-x64` exits silently with EXIT=4 and no stdout. Matches the [#87](https://github.com/yao-pkg/pkg/issues/87)
155+
Windows silent-exit bug.
156+
157+
Both are fixed by adding `--public-packages "*" --public` (which skips the
158+
V8 bytecode step). Enhanced SEA avoids both out of the box.
159+
160+
### Node 24
161+
162+
| target | std | std-public | sea |
163+
| ----------- | -------- | ---------- | -------- |
164+
| linux-x64 | OK / OK | OK / OK | OK / OK |
165+
| linux-arm64 | OK / OK | OK / OK | OK / OK |
166+
| win-x64 | OK / OK | OK / OK | OK / OK |
167+
| macos-x64 | OK / n/a | OK / n/a | OK / n/a |
168+
| macos-arm64 | OK / n/a | OK / n/a | OK / n/a |
169+
170+
Node 24 **works out of the box** for Standard and SEA, same as Node 20.
171+
The Node 22 bug is a Node-22-specific `pkg-fetch` patch regression, not
172+
a permanent Standard-mode limitation.
173+
174+
### macOS runtime
175+
176+
Not verified — see "Host requirements" above. The regressions tracked
177+
in [#181](https://github.com/yao-pkg/pkg/issues/181) (macOS host, Node 22+) must be confirmed on a real Mac.
178+
GitHub Actions' `macos-13` / `macos-14` runners are the right place for
179+
that; a follow-up CI workflow that runs the hello.js matrix there would
180+
close the last hole.
181+
182+
## Debugging a failing run
183+
184+
Each cell writes its own log; paths are printed on stderr next to any
185+
`FAIL` and re-summarised at the end of the run.
186+
187+
- **Log location**`$PKG_XCOMPILE_WORKDIR/logs/node<major>/build-<mode>-<target>.log`
188+
(and `run-<mode>-<target>.log`). Default workdir is `/tmp/pkg-xcompile`.
189+
Logs are per-cell so a failing build is not overwritten by the next one.
190+
- **Re-run one cell** — the fastest way is still to invoke `pkg` directly
191+
against the same fixture:
192+
```bash
193+
cd /tmp/pkg-xcompile
194+
node /path/to/pkg/lib-es5/bin.js hello.js -t node22-linux-arm64 \
195+
-o /tmp/pkg-xcompile/bin-node22/std-linux-arm64
196+
```
197+
- **`exec format error` on arm64 runs** — binfmt is not registered. After
198+
a reboot `tonistiigi/binfmt` needs to be re-installed:
199+
```bash
200+
docker run --privileged --rm tonistiigi/binfmt --install arm64
201+
```
202+
- **Wine cell always FAIL** — pull the image manually once
203+
(`docker pull scottyhardy/docker-wine`) and inspect
204+
`logs/node<major>/run-sea-win-x64.log` for the actual crash. The
205+
EBADF-stdout gotcha is documented above.
206+
- **SEA FAIL on Node 20** — expected; pkg enforces `host node ≥ 22` for SEA.
207+
- **`Error: UNEXPECTED-20` / silent exit (EXIT=4)** — these are the
208+
tracked Node-22 Standard-mode regressions (issues #181 and #87). Not
209+
environment bugs — see [Node 22 results](#node-22) below.
210+
- **Stale binary hiding a regression** — pkg does not hash its own source
211+
into the output. After rebuilding pkg, delete `bin-node<major>/` before
212+
re-running the matrix.
213+
214+
## The script
215+
216+
The harness lives next to this `SKILL.md` as `run-matrix.sh`. Before
217+
first run, set `PKG_BIN` to your pkg build and ensure `nvm` is sourced.
218+
219+
## Quick reference of pkg flags touched
220+
221+
| Flag | Effect |
222+
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
223+
| `-t nodeNN-<os>-<arch>` | Target triple |
224+
| `--sea` | Enhanced SEA mode |
225+
| `--public-packages "*" --public` | Disable V8 bytecode, include sources in plaintext — the cross-compile escape hatch for Standard mode |
226+
| `--no-bytecode` | Same effect for bytecode, but does not imply `--public` — use with `--public-packages` if you want consistent behavior |
227+
| `--debug` | Inject diagnostic bootstrap; enables `DEBUG_PKG` at runtime |
228+
229+
## Notes for future maintainers
230+
231+
- Do **not** reuse cached binaries between matrix runs — delete
232+
`bin-node${major}/` first if you rebuilt pkg. pkg does not hash its
233+
own source into the output, so stale binaries silently hide regressions.
234+
- If you add a new target to the matrix, also add a runner branch in
235+
`run_one()`. Unknown targets fall through the `case` and count as pass.
236+
- If `scottyhardy/docker-wine` becomes unavailable, `tobix/wine` is a
237+
smaller drop-in replacement — it has the same EBADF stdout gotcha.
238+
- Don't confuse "builds with warning" with "builds clean". The matrix
239+
only records `OK` when the binary file exists on disk; a warning like
240+
`Failed to make bytecode node22-arm64` still produces a binary but it
241+
will crash at runtime. Runtime is the source of truth.

0 commit comments

Comments
 (0)