Go to file T
Code
.github install: four releases of lag (lupin 0.1.50 and 0.1.51 kept 0.1.49's v0.2.24 pin and mirrored the newer surfaces instead; the widest gap the check has counted); the archive's folder holds std/ since v0.2.27, and the Windows job now asserts std/ and std/STD-REV with the rest of the folder; 0.2.27's and 0.2.28's additions print their headers or are declined for the tab's reasons (the file-changing calls, exec, jobs, the umask, a net read, tasks, module c's sibling), and under 0.1.49 the json rows answered first-wins, env_unset was declined and int_truth_wrap_mul_wide trapped; 0.2.26's additions become history; the parting sentence names chdir_relative as the one output parting; tap and AUR read live at 0.2.28 / 0.1.51; 0.1.49, 0.1.50, v0.2.26 and v0.2.27 listed
crates Retire the applied wasm portability patch
docs Record the plant's red runs in ww46's evidence
nginx build, nginx: say which book script stays unversioned and why
scripts Re-read book counts at 591cd5d
site Write eleven releases of lag
tests Add 'ten releases' to the lag guard's closed set
upstream Pin the book at 591cd5d for 0.2.35
.gitignore scaffold: submodules, deploy and build scripts, both nginx configs
.gitmodules scaffold: submodules, deploy and build scripts, both nginx configs
CHANGELOG.md Log ww46 in the site changelog
LICENSE scaffold: submodules, deploy and build scripts, both nginx configs
README.md readme: unslop — say what things are instead of what they are not, drop the aphorisms, cut the em dashes and the bold, and lose the house words (loudly, by name, honest) that carried no information

wolf-web

The site at lupp.us: the book, a live interpreter, the docs.

Everything the site serves is generated from pinned submodules, so a page cannot claim a version of wolf that does not exist. The interpreter in the playground is lupin, the reference interpreter, compiled to WebAssembly and run in the visitor's browser.

Layout

site/          the static source: pages, styles, the playground shell
crates/        lupin-wasm, the playground's bridge to the interpreter
scripts/       build and deploy
nginx/         the two configs, bootstrap and final
upstream/      pinned submodules (book, interpreter, compiler)
dist/          build output, not tracked

Build and deploy

git submodule update --init --recursive
./scripts/build.sh          # writes dist/
./scripts/deploy.sh         # builds, stages a release, flips current

deploy.sh needs sudo for the parts under /var/www and for the nginx reload, and asks for it.

The book ships twice from the one pinned checkout: the web edition under dist/book/, and the typst-set dist/book/wolf-book.pdf that the reading page offers for download with its measured size. The PDF needs typst on the machine (on PATH, at $TYPST, or in ~/.cargo/bin); CI installs a pinned release binary. Without it the build stops (ALLOW_NO_PDF=1 lets it continue), and the reading page then omits the download link.

Each step of build.sh degrades instead of aborting: a book that will not render leaves a page saying so, a wasm build that fails leaves a playground that says so, and the deploy still goes out. The exit code reports whether the build ran, and the pages report what it produced.

The playground

scripts/build-wasm.sh compiles the pinned interpreter for wasm32-unknown-unknown and publishes one file, dist/play/lupin.wasm. The module imports nothing; the script checks that and refuses to publish one that does. site/play/lupin.js is hand-written glue over a byte-buffer ABI documented in crates/lupin-wasm/src/lib.rs. There is no wasm-bindgen and no npm, so the toolchain is cargo alone and the nginx CSP needs only 'self' 'wasm-unsafe-eval'.

The build needs the wasm target. On a rustup machine the script adds it. On a distro rust without rustup, install the distribution's wasm std, or point WOLF_WASM_SYSROOT at a sysroot that has one.

The portability patch

The site once carried crates/lupin-wasm/wasm-portability.patch. The pinned interpreter ran the parser and the evaluator on threads it sized itself and read a monotonic clock at startup, none of which exists on wasm32-unknown-unknown, and the patch gated all three on the target. Upstream took the gates in wolf-interp c1ec02e and the patch was deleted; the interpreter has owned its wasm behaviour since. At the current pin that covers the interpreter's larger surface too: the net tier and the process functions decline on wasm the same way tasks, procs and the time functions do, so the build applies nothing and the module still imports nothing. build-wasm.sh keeps the staging-and-patch machinery. If a future pin regresses, a patch dropped into crates/lupin-wasm/ is picked up again, and one that does not apply fails the build.

The samples

scripts/collect-samples.py copies conformance-corpus programs into dist/play/samples/ verbatim, header comment included. The running order is a list in that script; the bytes are the corpus's. Programs whose tiers the browser build declines are left out, and the reasons are in the script's docstring.

Updating what the site serves

Move a submodule to the revision you want and commit the pin:

git -C upstream/wolf-book fetch origin && git -C upstream/wolf-book checkout <sha>
git add upstream/wolf-book && git commit -m "pins: book <sha>"
./scripts/deploy.sh

First-time nginx setup

See nginx/lupp.us.bootstrap.conf for the command sequence. In short: install the bootstrap config, run certbot, install the real config.