fix(spidermonkey-node): show npm install spinner#596
Open
brandonpayton wants to merge 871 commits into
Open
Conversation
…244) ## Summary - Rewrote `sys_select` to use stack-allocated arrays instead of `Vec` allocations that leak with the kernel's bump allocator - Vim (and any program using `select()` in a retry loop) would exhaust the 1GB kernel memory limit and crash with `RuntimeError: unreachable` - Zero heap allocations in the select hot path: fd_set copies use `[0u8; 128]` stack buffers, readiness checks use a single stack `WasmPollFd` ## Root Cause The kernel's wasm bump allocator has a no-op `dealloc`. `sys_select` created `Vec<WasmPollFd>` and `Vec<(usize, bool, bool, bool)>` on every call. In centralized mode, `pselect6` retries via `setImmediate` in a tight loop — each retry leaked ~64KB (one wasm page), reaching the 16384-page (1GB) limit and crashing. ## Test plan - [x] `cargo test` — 700 passed - [x] `vitest` — 266 passed (1 pre-existing unrelated failure) - [x] `libc-test` — 0 FAIL, 22 XFAIL - [x] `posix-tests` — 0 FAIL, 9 XFAIL - [x] Browser shell demo: `vim /etc/gitconfig` opens, accepts input (`:q` works), exits cleanly
## Summary
- esbuild's minifier drops `let` declarations from TypeScript `const
enum` IIFEs in `@xterm/xterm`'s pre-built ESM bundle
- Produces `(void 0||(i={}))` where `i` has no declaration — throws
`ReferenceError: assignment to undeclared variable i` in Firefox (ESM
strict mode)
- Crashes xterm's terminal parser when vim sends DECRQM (request mode)
escape sequences, hanging the session
- Switch to terser which correctly preserves variable declarations
## Test plan
- [x] `vite build` succeeds
- [x] Verified `requestMode` in terser output has proper `let i;`
declaration
- [ ] Vim in browser shell demo works on Firefox after deploy
## Summary - Include vim doc/*.txt and doc/tags in the runtime bundle so `:help` works in the browser shell demo - Excludes version history files (version4-9.txt, ~4.7MB) to keep bundle size reasonable - Bundle: 1.2MB → 8.4MB raw (357KB → 2.8MB gzip) - 147 help files + tags file added (was 55 runtime files, now 203) ## Test plan - [ ] Run `vim` in browser shell, type `:help` — should open help.txt - [ ] `:help motion` — should navigate to motion.txt - [ ] `:help :quit` — should navigate to relevant help topic
## Summary - Move cross-origin fetch proxying to the service worker for production deployments (GitHub Pages). The SW detects cross-origin requests and routes them through a configurable CORS proxy, adding CORP headers for COEP compliance. - CORS proxy URL is injected at build time via `VITE_CORS_PROXY_URL` env var. Deploy script defaults to `https://wordpress-playground-cors-proxy.com/?`. - In dev mode, the kernel worker uses vite's `/cors-proxy?url=` middleware directly (SW isn't active in dev). - Removes `corsProxyUrl` from `BrowserKernelOptions` — no longer a user-facing option. ## How it works - **Production**: Service worker intercepts cross-origin fetches -> routes through CORS proxy -> adds CORP headers -> COEP satisfied - **Dev**: Kernel worker catches fetch failures -> retries through vite middleware at `/cors-proxy?url=` -> same-origin response ## Usage ```bash # Deploy with default proxy bash scripts/deploy-gh-pages.sh # Deploy with custom proxy VITE_CORS_PROXY_URL="https://my-proxy.example.com/?" bash scripts/deploy-gh-pages.sh ``` ## Test plan - [x] Dev mode: curl https://example.com works via vite CORS proxy middleware - [x] Production build: CORS_PROXY_URL correctly injected into service-worker.js - [x] Build without env var: CORS_PROXY_URL is empty string (proxy disabled) - [x] Cargo tests: 700 passed - [x] Vitest: 267 passed - [x] libc-test: 0 FAIL - [x] POSIX: 0 FAIL
## Summary
- `resolve_path(".", "/dev")` returned `"/dev/."` which didn't match
devfs patterns like `b"/dev"`, causing `ls` to fail with "No such file
or directory" when CWD is `/dev` (while `ls /dev` worked fine)
- Root cause: `resolve_path` concatenated CWD + relative path without
normalizing `.`/`..` components
- Fix: call `normalize_path` on the result in `resolve_path` so all
callers benefit
- Also fixes the same issue for `/proc`, `/dev/pts`, `/dev/shm`, etc.
## Test plan
- [x] Cargo tests pass (703/703, 3 new path tests)
- [x] Vitest pass (267/267)
- [x] libc-test: 0 FAIL, 22 XFAIL
- [x] POSIX: 0 FAIL, 9 XFAIL
- [ ] Shell demo: `cd /dev && ls` works
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The WordPress Playground CORS proxy is at .net not .com, and it expects raw URLs after the ? delimiter — encodeURIComponent produces percent-encoded URLs that return HTTP 400.
## Summary - `/proc` wasn't visible in `ls /` or tab completion because root directory listings came purely from the host VFS, which has no `/proc` entry - Direct access (`ls /proc`, `cat /proc/self/stat`) always worked since the kernel intercepts all `/proc` paths in stat/open/read - Fix: `sys_getdents64` now injects a synthetic `proc` entry when listing `/` after host entries are exhausted - Handles buffer-full edge case with `-3` dir_handle state for resumption ## Test plan - [x] Cargo tests pass (703/703) - [x] Vitest pass (267/267) - [x] libc-test: 0 FAIL - [x] POSIX: 0 FAIL - [ ] Shell demo: `ls /` shows `proc`, `ls /proc` works, `cd /proc && ls` works 🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary - `cd /proc` failed with "can't cd to /proc" because `sys_chdir` validated paths only via `host.host_stat()`, which has no `/proc` entry - Now checks procfs and devfs virtual filesystems before falling through to the host VFS - Combined with PR #249 (path normalization) and #250 (/proc in root listing), `/proc` is now fully navigable in the shell demo ## Test plan - [x] Cargo tests pass (703/703) - [x] Vitest pass (267/267) - [x] libc-test: 0 FAIL - [x] POSIX: 0 FAIL - [ ] Shell demo: `cd /proc && ls` works 🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary - In dev mode, the `__CORS_PROXY_URL__` placeholder in `service-worker.js` is served as-is (the vite build-time replacement only runs during `vite build`). The SW was treating this literal string as a proxy URL, causing broken cross-origin fetch attempts. - Added a guard that detects the unreplaced placeholder and treats it as empty, so the SW correctly falls back to no-proxy behavior in dev mode. ## Test plan - [x] Verified `wget https://automattic.com/...` works on deployed GitHub Pages shell demo (496KB JPEG downloaded successfully over HTTPS via CORS proxy) - [x] Dev mode unaffected (TLS backend's own vite middleware proxy handles cross-origin fetches)
## Summary - Build `mysqltest` (mariadb-test) binary for wasm32 — extends the existing MariaDB cross-compilation pipeline to produce a 3.8MB mysqltest.wasm plus all 1,184 upstream mysql-test suite test files - TypeScript test harness (`examples/mariadb-test/run-tests.ts`) manages the full lifecycle: bootstrap system tables, start mariadbd in server mode, run individual mysqltest processes per-test, handle timeouts with automatic server restart - Shell wrapper (`scripts/run-mariadb-tests.sh`) with a curated set of **89 passing tests** and comprehensive XFAIL categorization covering ~600 known-failing tests ### Infrastructure fixes discovered during triage - **Root TCP grants**: `FLUSH PRIVILEGES` re-enables grant checking; setup SQL inserts `root@127.0.0.1` and `root@%` with full passwordless access - **Stored procedure definer**: `CREATE DEFINER='root'@'localhost'` prevents "definer does not exist" errors after `FLUSH PRIVILEGES` - **Aria crash recovery**: server restart cleans `aria_log_control` to avoid checksum mismatch - **`--protocol=tcp`**: forces TCP connections to avoid unix socket attempts ### Failure categories (XFAIL) | Category | Count | Reason | |----------|-------|--------| | Multi-connection | ~111 | `connect` command deadlocks with `--thread-handling=no-threads` | | InnoDB | ~228 | Storage engine not available (Aria only) | | exec/system | ~109 | Shell commands not supported in wasm | | Debug | ~78 | Requires debug build (`debug_dbug`, `debug_sync`) | | Timeout | ~27 | Tests too slow for 60s on wasm | | Grants/SSL/binlog/plugins | ~50+ | Various unsupported features | ## Test plan - [ ] `scripts/run-mariadb-tests.sh` runs 89 curated tests with 0 unexpected failures - [ ] `scripts/run-mariadb-tests.sh --all` runs all 1,184 tests (slow; failures are XFAIL) - [ ] Existing test suites unaffected (cargo, vitest, libc-test, POSIX, sortix) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary - Add `mariadb` test suite to `run.sh` dispatcher — run via `./run.sh test mariadb` - Register `mysqltest.wasm` in `builtinPrograms` map in `run-example.ts` for exec resolution Follow-up to #253 (MariaDB mysql-test suite infrastructure). ## Test plan - [ ] `./run.sh test mariadb` runs the curated 89-test suite - [ ] No impact on existing test suites 🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary
- Port Erlang/OTP 28.2 BEAM emulator to wasm-posix-kernel
- BEAM boots with single scheduler + dirty schedulers (8 threads total),
loads kernel/stdlib applications, and executes Erlang code
- Full support for process spawning, message passing, ETS, list
comprehensions, maps, binaries, pattern matching
## Platform fixes
- **musl qsort replacement**: Heapsort replaces smoothsort which has
shift-by-32 UB on wasm32
- **handleReadv chunked reads**: Large readv calls (up to 253KB .beam
files) now chunk data to avoid 64KB scratch buffer overflow
- **Driver signature fix**: Added 3rd parameter to inet/ram_file driver
start functions for wasm indirect call table type checking
- **ESTACK → local stack**: `db_is_fully_bound` uses fixed local stack
to avoid allocator corruption during ETS operations
- **BEAM loader insertion sort**: Replaced qsort in select_val/map_key
sorting to fix non-deterministic loader corruption
- **THE_NON_VALUE hash guard**: `erts_internal_hash(0x0)` returns 0
instead of crashing
- **Code path fix**: Add kernel/stdlib ebin directories to `-pa` for
dynamic module loading after boot
## Build & Run
```bash
# Build (requires host Erlang OTP 28)
bash examples/libs/erlang/build-erlang.sh
# Run
npx tsx examples/erlang/serve.ts -eval 'io:format("Hello from BEAM!~n"), halt().'
```
## Output
```
=== Erlang/OTP on wasm-posix-kernel ===
OTP release: 28
ERTS version: 16.1.2
Word size: 4
Schedulers: 1
Atoms: 10164
Processes: 43
ETS tables: 19
List comprehension: [1,4,9,16,25,36,49,64,81,100]
Map: #{hello => world,beam => wasm}
Binary: <<1,2,3,4,5>>
```
## Test plan
- [x] Cargo tests: 703 passed, 0 failed
- [x] Vitest: 199 passed, 0 failed
- [x] libc-test: 0 FAIL, 14 XFAIL
- [x] POSIX tests: 0 FAIL, 9 XFAIL
- [x] BEAM boots and prints "Hello from BEAM!"
- [x] Erlang process spawning and message passing works
- [x] System info queries (OTP release, ERTS version, word size) return
correct values
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary - Adds browser variant of MariaDB mysql-test infrastructure - Full triage of all 1184 upstream tests in headless Chromium - **185 tests pass** in the browser (up from 88 Node.js-derived curated set) - Auto-reload on server hang for robust large-scale triage runs ## Files - `scripts/build-mariadb-test-bundle.sh` — packages test files as JSON bundle for browser VFS (`--all` for full triage) - `examples/browser/pages/mariadb-test/` — boots MariaDB via SystemInit, exposes `window.__runMariadbTest()` - `scripts/browser-mariadb-test-runner.ts` — Playwright runner with batch support and hang recovery - `scripts/run-browser-mariadb-tests.sh` — shell wrapper with 185 curated tests - `run.sh` — integrated as `browser-mariadb` test suite ## Full triage results (1184 tests) | Status | Count | |--------|-------| | PASS | 185 | | SKIP | 143 | | TIMEOUT | 339 | | CONNECT-DEADLOCK | 230 | | OTHER FAIL | 287 | ## Test plan - [x] Full triage of all 1184 tests in browser - [x] Verification pass: 185/185 curated tests pass on fresh boot - [x] `./run.sh test browser-mariadb` runs successfully 🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary - **nginx test suite**: Drop-in nginx wrapper for the upstream Test::Nginx Perl framework. Runs nginx.wasm in CentralizedKernelWorker with fork support. Full triage of 484 tests: 32 pass, 410 skip (missing modules like rewrite/gzip/SSL/stream), 40 expected failures (proxy backends, timing), 2 timeouts. - **SQLite test suite**: Builds sqlite3 CLI (1.4MB) with FTS5, JSON1, and math functions. 17 comprehensive SQL test scripts covering all major SQLite features (CRUD, types, expressions, aggregates, joins, indexes, transactions, constraints, views, CTEs, window functions, triggers, subqueries, date/time, JSON, FTS, schema DDL, complex analytics). - **stdin piping fix**: `run-example.ts` now reads piped stdin data and forwards to wasm processes (previously set empty stdin, breaking `sqlite3 < test.sql` pattern). - **run.sh integration**: Added `nginx` and `sqlite` test suite targets. ## Test plan - [x] `./run.sh test nginx` — 32/32 pass - [x] `./run.sh test sqlite` — 17/17 pass - [x] `scripts/run-nginx-tests.sh --all` — 32 PASS, 410 SKIP, 40 XFAIL, 2 TIME (0 unexpected)
- Rewrite ring.erl with correct ring topology (self as counter,
spawned processes as forwarders). Old version had a deadlock bug
where set_next broke the chain.
- Work around BEAM wasm32 ~f format bug: float_to_list/1 uses broken
ryu/snprintf path, use float_to_list/2 with {decimals,N} instead.
- Track thread workers in serve.ts for proper cleanup on exit. BEAM's
halt(0) hangs in pthread_join because threads are blocked on futex
waits. Add halt detection: if stdout goes idle for 2s after output,
force clean exit.
- Remove unused threadChannelOffsets array and keepalive timer.
Ring benchmark results: 1000 processes, 100 rounds = 100K messages
in ~54ms (~1.85M messages/sec).
## Summary
- Port Erlang/OTP 28.2 BEAM emulator to wasm-posix-kernel with threading
support (dirty schedulers via clone/futex)
- Fix musl's qsort (smoothsort shift-by-32 UB on wasm32), handleReadv
for large reads, driver signature mismatches, ETS ESTACK crash
- Add ring benchmark (1000 processes x 100 rounds, ~54ms for 100K
messages) with halt detection workaround for BEAM's pthread_join hang
## Test plan
- [x] cargo tests: 703 passed
- [x] vitest: 199 passed
- [x] libc-test: 0 FAIL / 22 XFAIL
- [x] POSIX tests: 0 FAIL / 9 XFAIL
- [x] BEAM boots and runs `io:format("Hello from BEAM!~n"), halt().`
- [x] Ring benchmark completes: 1000 processes, 100 rounds, 100K
messages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
LLVM's wasm32 backend miscompiles aggregate initialization of structs containing pointers to shadow-stack local arrays at -O2. This causes BEAM's ESTACK macros and iodata traversal in erl_unicode.c to produce garbage, breaking unicode:characters_to_binary/2 and filename conversion. Two fixes: - global.h: explicit field-by-field ESTACK/WSTACK init on wasm32 - Makefile: compile erl_unicode.c at -O1 to avoid the codegen bug Both patches are applied automatically by build-erlang.sh.
## Summary
- Fix LLVM wasm32 backend miscompiling aggregate struct initialization
with shadow-stack pointers at -O2
- Add `global.h` patch: explicit field-by-field ESTACK/WSTACK init under
`#ifdef __wasm32__`
- Add Makefile patch: compile `erl_unicode.c` at `-O1` to avoid iodata
traversal codegen bug
- Both patches applied automatically by `build-erlang.sh`
## Details
BEAM's `unicode:characters_to_binary/2` BIF and
`erts_native_filename_need` traverse iodata using ESTACK macros
(stack-based term traversal). At `-O2`, LLVM's wasm32 backend
miscompiles the aggregate initialization of `ErtsEStack`/`ErtsWStack`
structs that contain pointers to shadow-stack local arrays. This
manifests as:
- `{error, <<>>, {}}` from `unicode:characters_to_binary([[]])`
- EISDIR error opening `start_clean.boot` (filename conversion fails)
The bug is a classic heisenbug — adding `fprintf(stderr, ...)` debug
calls changes code layout enough to prevent miscompilation.
**Root cause**: LLVM optimization passes at `-O2` incorrectly handle
struct fields pointing to `__stack_pointer`-relative local arrays on
wasm32.
**Fix**: Two-pronged approach:
1. `global.h`: Replace aggregate initialization with explicit
field-by-field assignment under `#ifdef __wasm32__` (defensive)
2. `Makefile`: Compile `erl_unicode.c` at `-O1` (fixes the actual
codegen bug)
## Test plan
- [x] BEAM boots and runs: `io:format("Hello from BEAM!~n"), halt().`
- [x] Arithmetic, string, list comprehension, map, binary, atom
operations work
- [x] Cargo tests: 703 passed
- [x] Vitest: 199 passed
- [x] musl libc-test: 0 FAIL (19 XFAIL)
- [x] POSIX test suite: 0 FAIL (1 XFAIL)
- Add build/run/clean/list targets for Erlang in run.sh - ./run.sh build erlang — builds BEAM via build-erlang.sh - ./run.sh run erlang — starts BEAM emulator - Add 5 vitest integration tests: hello world, arithmetic, lists, process spawning, and ring benchmark message passing
## Summary
- Add `erlang` build/run/clean/list targets to `run.sh`
- `./run.sh build erlang` builds BEAM VM via build-erlang.sh
- `./run.sh run erlang -eval 'Expr'` starts the BEAM emulator
- Add 5 vitest integration tests covering hello world, arithmetic, list
operations, lightweight process spawning, and ring benchmark message
passing
## Test plan
- [x] `./run.sh list` shows Erlang with status indicator
- [x] `./run.sh run erlang -eval 'io:format("Hello!~n"), halt().'` works
- [x] Vitest: 204 passed (5 new Erlang tests), 0 failures
- [x] Cargo: 703 passed
- [x] libc-test: 0 FAIL
- [x] POSIX: 0 FAIL
Remove unconditional console.error for signal delivery in kernel-worker.ts that polluted stderr, causing 15 sortix test failures (signal output comparison mismatch). Also clean up verbose patchWasmForThread and Erlang serve.ts debug logging.
aio_read requires pthreads (musl's AIO uses helper threads) which are not supported for guest-initiated pthread_create. Same reason as aio_error and aio_fsync.
## Summary - Remove unconditional `console.error` for signal delivery in `kernel-worker.ts` that polluted stderr output - Clean up verbose `patchWasmForThread` debug logging in `worker-main.ts` - Remove noisy clone/fork/thread/exit debug logs from Erlang `serve.ts` ## Details The Erlang/OTP PR (#255) introduced an unconditional `console.error` log line in `kernel-worker.ts` that fired on every signal delivery. Since sortix signal tests capture stderr+stdout (`2>&1`) and do exact string comparison against expected output, the extra `[signal] pid=100 signum=10 handler=3 flags=0x...` line caused all 15 signal-related tests to fail. ## Test plan - [x] Vitest: 204 passed, 0 failures - [x] Sortix signal tests: 32/32 PASS (was 15 FAIL) - [x] Erlang BEAM still works with cleaned-up output - [ ] Full sortix suite running (waiting for confirmation of 0 FAIL)
- Remove unused imports (S_IFCHR, S_IFLNK) from devfs.rs - Prefix unused test variables with underscore in memory.rs - Remove unused any_interested variable in select() syscall - Suppress dead_code warnings on POSIX constants kept for reference (FUTEX_FD, CLONE_CHILD_SETTID, EPOLLRDHUP, MqQueue fields)
## Summary - Remove unused imports (`S_IFCHR`, `S_IFLNK`) from devfs.rs - Prefix unused test variables with underscore in memory.rs - Remove unused `any_interested` variable in select() syscall - Suppress dead_code warnings on POSIX constants kept for API reference Eliminates all 10 compiler warnings from `cargo test`. ## Test plan - [x] Cargo: 703 passed, 0 warnings - [x] Zero warnings in build output (excluding expected unstable feature note)
Added a warning about .wasm binary builds in the repository history and future history rewrite.
## Summary - add missing browser deploy path filters for rootfs, benchmark, example, and mkrootfs inputs - include host package metadata and rootfs/overlay helper scripts that can affect prepare-browser - bump checkout, setup-node, and gh-pages deploy actions to tagged Node 24-compatible releases ## Validation - clean checkout simulation: fetched musl submodule, installed npm deps, ran `bash scripts/dev-shell.sh ./run.sh prepare-browser --allow-stale` - clean checkout simulation: ran `VITE_BASE=/kandelo/ npm run build` in `apps/browser-demos` - main deploy after #541 passed: https://github.com/brandonpayton/kandelo/actions/runs/26261916751 - `ruby -e 'require \"yaml\"; YAML.load_file(\".github/workflows/browser-demos-pages.yml\")'` - `git diff --check origin/main..HEAD`
Summary - Inject the configured CORS proxy URL into production service-worker.js by default. - Pass VITE_CORS_PROXY_URL in the GitHub Pages deployment workflow. - Add a deploy-script verification that fails if the proxy URL is not injected. - Harden the service worker cross-origin proxy path so the page sees a synthetic CORS/CORP/COEP-compatible response; the external CORS proxy only needs to provide ordinary CORS for the service worker fetch. - Add a Kandelo startup gate so live boot, web bridge setup, and software-gallery fetches wait until the unified service worker is installed, active, controlling the app, and the page is cross-origin isolated. - Make the isolation gate visible: the boot log reports the activation reload, and a failed post-reload isolation check becomes a normal Kandelo boot error instead of hanging quietly. Verification - git diff --check - bash -n scripts/deploy-gh-pages.sh - node --check apps/browser-demos/public/service-worker.js - Focused Vite plugin check emitted `var CORS_PROXY_URL = "https://wordpress-playground-cors-proxy.net/?";` - Confirmed the proxy returns CORS headers for the Doom WAD from `https://brandonpayton.github.io` - Synthetic service-worker/proxy smoke test passed in Playwright Chromium, Firefox, and WebKit with `crossOriginIsolated: true` and controlled cross-origin fetches Note - Full `npm run build` could not complete in this worktree because generated kernel artifacts are missing (`local-binaries/kernel.wasm` and `binaries/kernel.wasm`). CI prepares these before building. - Full `tsc -p apps/browser-demos/tsconfig.json --noEmit` currently reports existing project-wide type errors outside this change set.
Summary - Add forwarded host/proto/prefix headers when the service worker sends app requests through the HTTP bridge. - Rewrite same-host absolute `http://...` URLs in bridged text responses to the browser-visible app URL, preserving `/kandelo/app` and avoiding HTTPS mixed-content blocks. - Handle both plain URLs and escaped URL strings emitted in HTML/JS/JSON/CSS-like text responses. Verification - node --check apps/browser-demos/public/service-worker.js - git diff --check origin/main..HEAD - Focused rewrite check covers WordPress-style `http://brandonpayton.github.io/wp-includes/...`, escaped `http:\/\/...`, and already-prefixed `http://brandonpayton.github.io/kandelo/app/...` URLs.
Summary: - Adds a generic Kandelo demo guide pane driven by /etc/kandelo/demo.json metadata from the VFS image. - Supports approved terminal actions, raw REPL input, editable scripts, and sandboxed companion HTML action requests. - Moves built-in guide metadata into VFS builders for shell, Node, nginx, and nginx+PHP; Doom and WordPress omit guides. - Documents the metadata format for kandelo-software REPL demos. Verification: - npm --prefix apps/browser-demos run build - npx vitest run web-libs/kandelo-session/test/kandelo-session.test.ts - host/node_modules/.bin/tsc --noEmit ... images/vfs/scripts/*kandelo* and VFS builders - Playwright smoke: shell guide/action ok, Doom no guide, WordPress SQLite no guide
## Summary - patch WordPress runtime config before boot in Kandelo, WordPress SQLite, and LAMP demos so WordPress generates `https://.../kandelo/app` URLs and forces `home`/`siteurl` through an MU plugin - route `vim.zip` and `nethack.zip` lazy archives through Vite-emitted asset URLs instead of assuming root-level `/kandelo/*.zip` files exist - make lazy binary size probing fall back from `HEAD` to a one-byte range request, so shell utilities are not silently skipped when `Content-Length` is unavailable - expand service-worker rewriting for same-host `http://` URLs in bridged text, JSON/XML-ish responses, encoded URL values, and `Link` headers ## Verification - `node --check apps/browser-demos/public/service-worker.js` - `git diff --check origin/main..HEAD` - `npx --prefix apps/browser-demos tsc apps/browser-demos/lib/init/fetch-size.ts apps/browser-demos/lib/init/lazy-archives.ts apps/browser-demos/lib/init/wordpress-runtime-config.ts --noEmit --target ES2022 --module ESNext --moduleResolution bundler --lib ES2022,DOM --types vite/client --skipLibCheck` - `npm --prefix apps/browser-demos run build` still cannot complete in this worktree because `kernel.wasm` is not present at `local-binaries/kernel.wasm` or `binaries/kernel.wasm`
## Summary - add agent-facing guidance that Kandelo demo presentation metadata belongs in VFS images - document that missing demo.json should use generic defaults, not demo-specific app fallbacks - point agents to the existing human-facing browser support docs ## Testing - git diff --check origin/main...HEAD
## Summary
- initialize a temporary git repository before cleanup jobs delete
remote PR branches
- document that PRs merged by GITHUB_TOKEN-backed workflows may miss the
close-event cleanup path
## Why
The scheduled/manual staging cleanup sweep was finding stale merged
ready-to-ship PR branches, but remote deletion failed with `fatal: not a
git repository` because the job never checked out or initialized a repo
before `git push <remote> :refs/heads/<branch>`.
## Validation
- `ruby -e 'require "yaml";
YAML.load_file(".github/workflows/staging-cleanup.yml")'`\n- `git diff
--check -- .github/workflows/staging-cleanup.yml`
## Summary - Add `skip-staging-tests` handling to staging-build, including `labeled`/`unlabeled` triggers so label changes refresh checks and cancel older runs. - Keep staging preflight, toolchain cache, package matrix builds, and binary materialization intact while skipping only the expensive post-materialization test suites. - Prevent staging from posting merge-gate success when staging tests are skipped; `prepare-merge.yml` is unchanged. ## Validation - `ruby -e 'require "yaml"; YAML.load_file(ARGV.fetch(0)); puts "YAML parsed"' .github/workflows/staging-build.yml`\n- `git diff --check -- .github/workflows/staging-build.yml`\n- Confirmed workflow-only changes do not match the package staging path filter (`package_staging_required=false`).\n- `actionlint` is not installed locally.
## Summary
- capture one current base SHA at the start of prepare-merge
- synthesize and share a PR-head-into-base merge commit through
downstream jobs
- switch package preflight/build/promote/test-gate paths off GitHub's
refs/pull/*/merge
- keep final base-drift checks before posting merge-gate
## Validation
- ruby -e 'require "yaml";
YAML.load_file(".github/workflows/prepare-merge.yml")'\n- git diff
--check -- .github/workflows/prepare-merge.yml\n- rg scan for stale
github.ref/github.sha/PR merge-ref usage in prepare-merge.yml\n\nNote:
actionlint was not installed locally, and npx actionlint did not expose
an executable.
## Summary - Keep staging-build label refreshes scoped to the `skip-staging-tests` label. - Put unrelated label events, including `ready-to-ship`, in an isolated concurrency group so they cannot cancel active staging runs. - Skip the staging job graph for unrelated label/unlabel events. ## Validation - `ruby -e 'require "yaml"; YAML.load_file(ARGV.fetch(0)); puts "YAML parsed"' .github/workflows/staging-build.yml`\n- `git diff --check -- .github/workflows/staging-build.yml`\n- `actionlint` skipped: not installed locally, and `go` is not installed to run it via `go run`.\n\n## Note\nThe broad label trigger was introduced by `f05c61cf` / #556 when `skip-staging-tests` support was added.
## Summary - Adds `kernel.fetchInKernel(port, request)` on both `NodeKernelHost` and `BrowserKernel` for sending HTTP requests directly to in-kernel servers, bypassing real TCP. - Consolidates the existing browser SW-bridge connection pump into one public method `CentralizedKernelWorker.sendHttpRequest`, deleting ~165 lines of duplicate inline pump/parse code from `kernel-worker-entry.ts`. - Migrates the WordPress + LAMP browser demos to the new API via a `setupServiceWorkerFetchBridge` helper. End-to-end verified in a browser — the WordPress install page renders. - Migrates `examples/wordpress/test/wordpress-server.test.ts` from manual kernel boilerplate + real-port allocation to `NodeKernelHost.fetchInKernel`. Test runs in <1s vs ~30s. See [docs/plans/2026-04-30-external-kernel-http-request-interface.md](docs/plans/2026-04-30-external-kernel-http-request-interface.md) for the full design and migration findings. ## What's new - `host/src/networking/in-kernel-http.ts` — shared `HttpRequest`/`HttpResponse` types, raw HTTP/1.1 framing helpers (request build + response parse with chunked decoding + multi-Set-Cookie merging). - `CentralizedKernelWorker.sendHttpRequest` — picks listener target, calls `kernel_inject_connection`, writes the request, pumps the response, parses it. Configurable timeout; returns 504 on expiry. `pickListenerTarget` is now public. - `NodeKernelHost.fetchInKernel` + `BrowserKernel.fetchInKernel` — thin host-side proxies plumbed through a new `http_request` worker-protocol message. - `examples/browser/lib/init/sw-bridge-fetch.ts` — `setupServiceWorkerFetchBridge` helper that wires a service-worker `HttpBridgeHost` to `fetchInKernel` and reinstalls itself when the SW restarts. - `programs/tiny-http-server.c` — minimal single-shot HTTP/1.1 server used as a test fixture. - `examples/run-fetch-in-kernel.ts` — small CLI demo script. ## Tests - `host/test/in-kernel-http.test.ts` — 5 tests: 1 integration round-trip through `NodeKernelHost.fetchInKernel`, 1 no-listener-error, 3 codec unit tests. - `host/test/browser-kernel.test.ts` — 7 tests: mocks `globalThis.Worker` to verify BrowserKernel's message-protocol contract (boot, fetchInKernel emission/timeout/error/concurrent IDs, destroy). Required a small Vite-URL stub plugin in `host/vitest.config.ts` to make `BrowserKernel` loadable in vitest. - `examples/wordpress/test/wordpress-server.test.ts` — rewritten to use `fetchInKernel`; ~80 lines vs ~240, runs in <1s. - All 351 host vitest tests pass (only the pre-existing `wasm64.test.ts` skip remains, unrelated to this work). ## Out of scope (intentional) - The `serve.ts` / `serve-nginx.ts` Node scripts don't migrate — they expose a real localhost port for outside clients, which is the opposite contract from `fetchInKernel`. The design doc explains. - Streaming bodies, HTTPS, HTTP/2, WebSocket upgrade, HTTP/1.1 pipelining — prototype scope. - The `nginx` / `nginx-php` browser demos still use the old `sendBridgePort` path. Consolidating them onto the new helper is a straightforward follow-up. ## Test plan - [x] `cd host && npx vitest run --exclude '**/wasm64.test.ts'` — 351 passed - [x] `npx vitest run test/in-kernel-http.test.ts` — 5 passed - [x] `npx vitest run test/browser-kernel.test.ts` — 7 passed - [x] `npx vitest run ../examples/wordpress/test/wordpress-server.test.ts` — passes - [x] `npx tsx examples/run-fetch-in-kernel.ts` — round-trips a request to the in-kernel C server - [x] `npx vitest run test/nginx.test.ts` — pre-existing real-TCP path still works - [x] Browser end-to-end — booted the WordPress demo via `vite`, clicked Start, watched the WordPress install page render inside the iframe via the new `fetchInKernel` bridge 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## Summary
- move the host syscall pointer-marshalling descriptor table into
`wasm_posix_shared::host_abi`
- generate `SYSCALL_ARGS` TypeScript bindings and
`syscall_arg_descriptors` ABI snapshot coverage from Rust metadata
- migrate `kernel-worker.ts` to consume generated descriptors and remove
TS-owned syscall size switches for poll/ppoll, SysV msg prefix handling,
semop sizing, and msgrcv copy-back adjustment
- keep platform-bound memory copies, Atomics scheduling, Worker/Wasmtime
boot, scatter/gather nested-pointer handling, epoll interception, and
host I/O in TypeScript
## ABI notes
- no `ABI_VERSION` bump: the ABI checker classifies the new snapshot
section as additive-compatible coverage
- changes to existing syscall arg descriptors are now classified as
breaking/incompatible
## Tests
- `nix develop -c cargo test -p wasm-posix-shared --target
aarch64-apple-darwin --lib host_abi`
- `nix develop -c bash -lc 'HOST_TARGET=$(rustc -vV | awk "/host:/
{print \\$2}"); cargo test -p xtask --target "$HOST_TARGET"
dump_abi'`\n- `nix develop -c bash scripts/check-abi-version.sh`\n-
focused generated ABI vitest: `cd host && npx vitest run --config <temp
generated-abi config>`\n- `nix develop -c npm --prefix host run
build`\n- `nix develop -c cargo test -p wasm-posix-kernel --target
aarch64-apple-darwin --lib`\n- `git diff --check`\n\n## Blocked check\n-
`nix develop -c npm --prefix host test -- --run` is blocked in this
worktree before test collection because `test/global-setup.ts` tries to
compile `examples/putenv_test.c`, but `sysroot` is missing and asks to
run `scripts/build-musl.sh`.\n
Summary: - add versioned image-level metadata to VFS images with optional kernelAbi declarations - expose metadata read/write and ABI assertion helpers on MemoryFileSystem - stamp mkrootfs/rootfs builds with ABI metadata and add inspect --metadata output Verification: - cd host && npx vitest run test/vfs-image.test.ts --config /dev/null - cd tools/mkrootfs && npm test -- test/builder.test.ts test/cli.test.ts - cd host && npm run build - git diff --check
## Summary - add package-system browser bundle entries for `vim.zip` and `nethack.zip`, so publishing can produce resolver-visible bare zip outputs - route `run.sh` Vim zip generation through the shared helper and add `nethack-zip` to browser asset prep - make Vite's `@binaries/` resolver apply the same implicit `programs/wasm32/` arch rule as the shell/host resolver - fix the zip helpers to write generated bundles to `apps/browser-demos/public/` before installing them into `local-binaries/` ## Verification - `bash -n run.sh packages/registry/vim-browser-bundle/build-vim-browser-bundle.sh packages/registry/nethack-browser-bundle/build-nethack-browser-bundle.sh` - `bash scripts/dev-shell.sh cargo run -p xtask --target "$HOST_TARGET" --quiet -- build-deps output-path vim-browser-bundle vim.zip` - `bash scripts/dev-shell.sh cargo run -p xtask --target "$HOST_TARGET" --quiet -- build-deps output-path nethack-browser-bundle nethack.zip` - `bash scripts/dev-shell.sh cargo run -p xtask --target "$HOST_TARGET" --quiet -- compute-cache-key-sha --package packages/registry/vim-browser-bundle --arch wasm32` - `bash scripts/dev-shell.sh cargo run -p xtask --target "$HOST_TARGET" --quiet -- compute-cache-key-sha --package packages/registry/nethack-browser-bundle --arch wasm32` - `bash scripts/dev-shell.sh ./run.sh build vim-zip nethack-zip` - `bash scripts/dev-shell.sh cargo run -p xtask --target "$HOST_TARGET" --quiet -- archive-stage --package packages/registry/vim-browser-bundle --arch wasm32 --out /tmp/kandelo-vim-browser-bundle-stage --build-timestamp 2026-05-22T00:00:00Z --build-host local-test` - `bash scripts/dev-shell.sh cargo run -p xtask --target "$HOST_TARGET" --quiet -- archive-stage --package packages/registry/nethack-browser-bundle --arch wasm32 --out /tmp/kandelo-nethack-browser-bundle-stage --build-timestamp 2026-05-22T00:00:00Z --build-host local-test` - `bash scripts/dev-shell.sh ./run.sh prepare-browser --allow-stale` - `VITE_BASE=/kandelo/ VITE_CORS_PROXY_URL=https://wordpress-playground-cors-proxy.net/? npm run build`
## Summary - Bake shell utility lazy-file stubs, placeholder URLs, and actual wasm sizes into the shell and node VFS images. - Rewrite those placeholders to Vite asset URLs at browser startup and forward baked lazy-file metadata from `BrowserKernel.init()`. - Remove shell/Kandelo boot-time utility `HEAD` size probes; update shell/node-vfs package deps and revisions so stale VFS images are not reused. ## Verification - `npx vitest --run --config host/.vitest-lazy-temp.mjs` with `lazy-vfs.test.ts` and `vfs-image.test.ts`: 40 tests passed. - `nix develop -c bash packages/registry/shell/build-shell.sh`: passed; inspected shell VFS image has 21 lazy entries with real target wasm sizes. - `nix develop -c bash packages/registry/node-vfs/build-node-vfs.sh`: passed; inspected node VFS image has `/usr/bin/node` lazy entry with real target wasm size. - `npm --prefix apps/browser-demos run build`: still blocked in this worktree by missing unrelated artifact `programs/wasm32/nginx-php-vfs.vfs.zst`.
## Summary - add a core `kandelo-sdk` package that builds the in-session SDK VFS image - add guest SDK wrappers under `sdk/kandelo/bin` for `wasm32posix-cc`, `wasm32posix-c++`, binutils wrappers, configure, and pkg-config - add the SDK VFS image builder under `images/vfs/scripts`, including sysroot, C/C++ libraries, syscall glue, precompiled glue objects, clang resource headers, and license notices ## Package Boundary This keeps the SDK/sysroot image in the core Kandelo repo. The larger Clang toolchain payload is maintained separately in `brandonpayton/kandelo-software`, where it can be staged lazily or as a lazy archive-backed payload. ## Validation - `bash -n packages/registry/kandelo-sdk/build-kandelo-sdk.sh images/vfs/scripts/build-kandelo-sdk-vfs-image.sh sdk/kandelo/bin/wasm32posix-*` - `git diff --check` - `cargo run --target <host> -p xtask -- build-deps parse packages/registry/kandelo-sdk/package.toml` - `cargo run --target <host> -p xtask -- build-deps check` - `cargo run --target <host> -p xtask -- compute-cache-key-sha --package packages/registry/kandelo-sdk --arch wasm32` - direct SDK VFS build using a temporary sysroot copied from the existing local sysroot; output was 256.0 MB raw and 3.3 MB zstd The direct build installed only ignored local artifacts in this isolated worktree (`local-binaries/`, `packages/registry/kandelo-sdk/kandelo-sdk.vfs.zst`, and glue object output).
## Summary - Add a `spidermonkey` registry package pinned to Firefox ESR `140.11.0esr`, producing the standalone SpiderMonkey shell as `js.wasm`. - Add the Kandelo/wasm32 integration patches needed for the Mozilla JS shell build, including wasm target mapping, randomness, stack/crash handling, and wasm-compatible configure/runtime paths. - Fix supporting platform issues uncovered by the port: SDK linker/configure flag handling, cbindgen in the dev shell, ABI parsing without invoking wasm constructors, fork-instrumented constructor/thread startup handling, and musl overlay fixes. - Update the SpiderMonkey Node runtime design doc to mark the standalone engine shell gate green and leave the Node-compatible SpiderMonkey embedding for the follow-up PR. ## Validation - `cargo run -p xtask --target "$HOST_TRIPLE" -- build-deps resolve spidermonkey` - Direct kernel run of `js -e "print(1 + 1)"`: stdout `2`, exit `0`, empty stderr - `npx vitest run packages/registry/spidermonkey/test/spidermonkey.test.ts host/test/wasm-binary-parse.test.ts host/test/exec.test.ts host/test/wasm-trap.test.ts host/test/thread-allocator.test.ts` - `cd sdk && npm test` - `cd host && npm run build` - Fresh Firefox ESR source patch-application check for `packages/registry/spidermonkey/patches/*.patch` ## Follow-up The Node.js-compatible environment using SpiderMonkey is intentionally out of scope here. This PR lands the engine shell package and the platform fixes needed to run JavaScript on SpiderMonkey under Kandelo. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## Summary - remove the Kandelo MockKernelHost runtime, `?mock=1` entry path, and mock-only fixture data - keep live gallery presets in a dedicated `presets.ts` module used by the real boot path - update Kandelo/session tests, comments, docs, and the COI spec to reflect live-only UI behavior ## Testing - `./host/node_modules/.bin/vitest run web-libs/kandelo-session/test/kandelo-session.test.ts` - `git diff --check` - `npm --prefix apps/browser-demos run build` *(blocked: missing `kernel.wasm` in `local-binaries/` or `binaries/` in this worktree)* Note: `tests/sortix/os-test` was dirty before the commit and is not included.
## Summary - preserve Kandelo gallery-selected VFS image URLs in browser state - fix WordPress + MariaDB Kandelo boot settings to match the working LAMP profile - prevent service worker app-readiness probes from capturing the Kandelo shell page and redirecting later gallery launches under /app/ ## Verification - `KANDELO_TEST_BASE_URL=http://127.0.0.1:5328 npm test -- --project=chromium test/kandelo-url.spec.ts` - manually booted WordPress MariaDB in Kandelo to HTTP preview ready with nginx, php-fpm, and mariadb listening ## Note - `npm run build` still fails before Kandelo on missing `examples/gencat.wasm` from `pages/test-runner/main.ts`.
## Summary - forward focused framebuffer keydown/keyup events as Linux MEDIUMRAW input, with Ctrl+Shift+Esc as the host escape - update Doom and Kandelo framebuffer panes to use the shared keyboard helper - fix Doom saves by using the user HOME directory, with a compatibility alias for older fbDOOM builds - add a Doom-only Vite config for focused demo builds ## Testing - npx vitest run test/framebuffer-browser-controls.test.ts --config /dev/null --root . - npm run build - npm run build -- --config vite.doom.config.ts - Playwright smoke test for Doom save name `wasd` with no save errors - git diff --check
## Summary
- classify `staging-build` runs before prepare-merge decides whether to
wait, block, or continue
- allow prepare-merge to continue to its own synthetic-merge package
validation when the only staging run is the intentionally skipped
label-event run
- keep real failed/in-progress/successful staging runs authoritative
when they exist
- add a small jq selector fixture test for the run-state cases
## Verification
- `.github/scripts/test-select-staging-build-run.sh`
- `ruby -e 'require "yaml"; ARGV.each { |f| YAML.load_file(f); puts "ok
#{f}" }' .github/workflows/prepare-merge.yml
.github/workflows/staging-build.yml`
- `git diff --check`
- confirmed PR #564 and #566 staging-build run lists classify as
`only_skipped`
## Summary - start demo/user processes with explicit uid/gid, `/home/user`, and root processes with `/root` - enforce kernel DAC checks for host-backed filesystem syscalls, including create/open, unlink/rename/link/symlink, readlink/realpath, exec, chmod/chown, access, sticky-directory deletion, and Unix socket bind - set created file/dir/socket ownership from the creator's effective uid/gid - tighten privilege-sensitive user syscalls (`setresuid`, `setresgid`, `setgroups`, hard rlimit raises, nice priority raises) and SysV IPC permissions - make default `/home/user` scratch mounts owned by uid/gid 1000 ## Verification - `cargo fmt -p wasm-posix-kernel` - `cargo check -Zbuild-std=core,alloc -p wasm-posix-kernel` - `cargo build --release -p wasm-posix-kernel -Zbuild-std=core,alloc` - `npx vitest run test/vfs/default-mounts.test.ts test/vfs/browser-mount-layering.test.ts --config /dev/null` - `git diff --check` - Browser shell demo at `http://127.0.0.1:5175/pages/shell/` confirms uid 1000 cannot create in `/`, can create under `/home/user`, and cannot `cd /root`. Note: the normal host Vitest config still requires `wasm32posix-cc` for global setup; I used `--config /dev/null` for the VFS-only tests to avoid unrelated SDK setup.
## Summary
- Make fork-path discovery table-aware for indirect calls, including
active/passive/declared element handling and conservative dynamic table
writes.
- Bound transitive indirect-call closure to two dispatch hops while
still propagating direct callers, preventing dynamic-runtime cascades
from instrumenting unrelated callbacks.
- Add WAT regressions for wrong-table, declared/passive element,
table.init, and over-cascading indirect-call cases; document the
remaining static-analysis limit.
## Root Cause
The QuickJS/Node-shaped build uses one large LLVM function table. The
previous analyzer treated indirect targets too broadly and let
same-table/same-signature indirect closure recurse without a resource
boundary, so generic interpreter dispatchers pulled in unrelated
QuickJS/OpenSSL callbacks. This was an over-broad call-graph discovery
issue, not an npm/demo workaround or a transform correctness change.
## Verification
- `scripts/dev-shell.sh bash -lc 'HOST_TARGET=$(rustc -vV | awk "/^host/
{print \\$2}"); cargo test -p fork-instrument --target "$HOST_TARGET"'`
- Fork-capable QuickJS/Node-shaped discover-only: optimized temp binary
reduced `5516 -> 876`; unoptimized temp binary reduced `7269 -> 978`.
- Unoptimized discover-only no longer pulls OpenSSL-family names: `SSL=0
EVP=0 CRYPTO=0 ossl=0`; still includes `JS_CallInternal`,
`js_call_c_function`, and `js_os_exec`.
- Rebuilt kernel/rootfs/tooling with `bash build.sh` and rebuilt
QuickJS/Node with the final instrumenter; `node.wasm` is `5,387,796`
bytes.
- Host runtime checks using `NodePlatformIO`: `node npm-cli.js
--version` prints `10.9.2`; `require(.../npm/lib/npm.js)` prints
`{"ctor":"function"}`.
- `scripts/dev-shell.sh bash -lc 'cd host && npx vitest run
../tests/package-system/fetch-binaries-allow-stale.test.ts'`
## Notes
- `scripts/test-allow-stale.sh` is stale in this checkout: it expects
`revision = ...` in `packages/registry/bzip2/package.toml`, but that
manifest no longer has the field. It restored the file before exiting;
the maintained package-system artifact policy Vitest above passes.
- The targeted npm Vitest file is not runnable as-is against absolute
host-side npm paths under the default rootfs-backed worker harness in
this checkout; the same npm/module-loading checks pass via the host
filesystem harness.
## Summary - restore Kandelo live demo panes from VFS demo guide metadata and keep demo pane state across tab switches - rebuild demo/runtime config paths for WordPress, MariaDB/LAMP, Node, and related VFS images - add generalized fork-instrumentation artifact guards, cargo-backed instrumenter wrapper, and reject stale Asyncify artifacts - fix Node/npm browser startup by removing fork-only qjs:os.exec from node.wasm while keeping standalone qjs fork-capable ## Verification - `git diff --check` - `scripts/dev-shell.sh bash -lc 'npx vitest run host/test/wasm-binary-parse.test.ts -t "built node.wasm artifact policy"'`\n- `scripts/dev-shell.sh bash -lc 'npx vitest run packages/registry/quickjs/test/quickjs-node-npm.test.ts -t "require|process.emit|console|fs/promises|module cache|prints 10.9.2"'`\n- `cd apps/browser-demos && npx playwright test test/kandelo-node.spec.ts --project=chromium`\n- `scripts/dev-shell.sh bash -lc 'npm --prefix apps/browser-demos run build'`\n\n## Notes\n- Follow-up investigation is still needed for the fork-instrumentation resource-safety issue with broad indirect-call closure in dynamic runtimes. This PR keeps node.wasm on the no-fork runtime path and documents the instrumentation policy.
## Summary - keep web demo presentation on syslog while the HTTP preview is still starting - migrate built-in nginx/WordPress demo metadata at runtime so older VFS images do not briefly focus Terminal - mark unexpected init exits as errors so the focused surface remains syslog instead of a stale preview ## Testing - `git diff --check origin/main..HEAD` - transpiled changed TS/TSX files with TypeScript (`transpileModule`)
## Summary - make the canonical `node` package resolve to the SpiderMonkey-backed Node-compatible runtime while keeping `spidermonkey-node` as an explicit alias - route the Kandelo Node.js demo through the SpiderMonkey Node host with npm, Intl, SharedArrayBuffer, and worker_threads demo actions - remove the QuickJS registry package/build/tests now that Node compatibility is backed by SpiderMonkey - move the shared Node compatibility bootstrap to `packages/registry/node-compat/` and have SpiderMonkey consume it from there - add SpiderMonkey Node compatibility/parity tests, including npm cowsay install and EMFILE errno coverage ## Testing - `bash scripts/dev-shell.sh npm --prefix host test -- packages/registry/spidermonkey/test/spidermonkey-node-compat.test.ts packages/registry/spidermonkey/test/spidermonkey-node-parity.test.ts packages/registry/spidermonkey/test/spidermonkey.test.ts` - `bash -n packages/registry/spidermonkey/build-spidermonkey.sh packages/registry/spidermonkey-node/build-spidermonkey-node.sh run.sh packages/registry/npm/fetch-npm.sh` - verified active source has no `quickjs` / `packages/registry/quickjs` references outside historical docs and ABI metadata - `build-deps parse node`, `build-deps parse spidermonkey`, `build-deps parse spidermonkey-node`, and confirmed `build-deps parse quickjs` fails because the package is gone - Playwright smoke against `http://127.0.0.1:5199/pages/kandelo/?demo=node`: demo pane loads; prior smoke also verified `Install cowsay` installs and runs cowsay ## Notes - `npm --prefix apps/browser-demos run build` is still blocked locally by a missing unrelated `nginx-vfs.vfs.zst` binary artifact; Vite dev compiled and ran the Node demo path successfully.
## Summary Batch PR collecting the committed changes currently on `emdash/try-batch-pr-5eqga`. ## Included PRs - #579 - #576 - #570 - #568 - #560 - #522 - #567 ## Changes - #579: Restore Open POSIX test discovery against the checked-in `tests/posix/open-posix-testsuite` tree, split shared CI setup into `test-gate-prepare`, and fan out cargo, fork-instrument, vitest, libc-test, Open POSIX, and Sortix suites into concurrent test-suite jobs across staging, prepare-merge, and force-rebuild. - #576: Fix the host declaration-file typecheck failure by keeping the wasm ABI parser cursor typed as a concrete number, add a host `typecheck` script, and run host type checking in the browser demo, docs, staging, prepare-merge, and force-rebuild workflows. - #570: Preserve process-group leaders after `waitpid` reaping by keeping resource-free limbo records until their process groups empty, and add focused Sortix expectation overrides plus process lifecycle coverage. - #568: Fix browser demo deploy fallback paths for LAMP/MariaDB assets, align MariaDB resolver metadata and diagnostics, and move the deploy workflow to GitHub's Node 24 action runtime. - #560: Add SMTP capture support for WordPress/LAMP demos with a new `msmtpd` package, VFS/dinit wiring, WordPress mail configuration, and Playwright coverage for captured `.eml` output. - #522: Add the lazy POSIX utility rootfs package plan and implementation path: `images/rootfs/PACKAGES.toml`, generated mkrootfs manifest fragments, lazy URL metadata, rootfs package build support, resolver fallback handling, shell VFS composition, and lazy exec materialization in browser/Node hosts. - #567: Add the Rust-owned host adapter manifest with ABI and host adapter metadata, generated TypeScript bindings/snapshot data, kernel wasm manifest exports, worker-side manifest validation, tests, and ABI documentation updates. ## Testing Not rerun as a single batch after creating this PR. The individual commits and linked PRs include their focused validation commands and notes.
## Summary
- add a prepare-merge merge-mode selector based on the `batched-changes`
label
- use rebase auto-merge for labeled PRs while preserving squash
auto-merge by default
- include the selected merge method in prepare-merge log/comment text
## Tests
- `ruby -e 'require "yaml";
YAML.load_file(".github/workflows/prepare-merge.yml"); puts "yaml
ok"'`\n- `git diff --check -- .github/workflows/prepare-merge.yml`
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.
Summary
Verification
Notes