diff --git a/.github/workflows/REVIEW.md b/.github/workflows/REVIEW.md index 063fd62f51..3e55ae3e07 100644 --- a/.github/workflows/REVIEW.md +++ b/.github/workflows/REVIEW.md @@ -2,15 +2,16 @@ **Read `REVIEW_COMMON.md` (repo root) first - its contract binds this checklist.** Architecture doc: `skills/internal/preflight.md` (repo root). A per-PR check is a step, a -matrix cell, or a workflow trigger whose failure turns a branch or a published artifact red -before a human merges or ships it - a `pull_request` lane's step and a branch-push lane's -smoke alike. +matrix cell, or a workflow trigger whose failure means the tree or a published artifact is +wrong, and that turns the lane red before a human merges or ships it - a `pull_request` lane's +step and a branch-push lane's smoke alike. A provisioning step - a toolchain install, a version +pin - is not itself a per-PR check. -**A diff that weakens a per-PR check is a defect: deleting it while no per-PR lane still -runs its cases, stopping its failure from failing the lane (`continue-on-error`, a trailing -`|| true`, a swallowed exit code), shrinking what it checks, or narrowing its condition to -anything but a `matrix.role` condition that still runs it on every pull request or the -nightly cron.** +**A diff that weakens a per-PR check is a defect: deleting it, or a step it depends on, while +no per-PR lane still runs its cases, stopping its failure from failing the lane +(`continue-on-error`, a trailing `|| true`, a swallowed exit code), shrinking what it checks, or +narrowing its condition to anything but a `matrix.role` condition that still runs it on every +pull request.** **A per-PR check the diff adds fails the lane when it finds a defect.** @@ -29,10 +30,10 @@ preflight gate - a check `preflight` runs locally before a push - that keeps it (`skills/internal/preflight.md` sec."extended_checks.yml") or states the platform no per-PR cell has.** A per-PR job fits 35 minutes; what does not fit moves. -**A diff that adds or changes a per-PR check states a run of that check's command, on the -lane's platform, in its PR body or commit message; a green run of that lane on the PR's head -commit is that evidence.** A check that fails for a non-defect turns a green branch red for -everyone. +**A diff that adds or changes a per-PR check, or adds, changes, or removes a step a per-PR +check depends on, states a run of that check's command, on the lane's platform, in its PR body +or commit message; a green run of that lane on the PR's head commit is that evidence.** A check +that fails for a non-defect turns a green branch red for everyone. **A step in `pages.yml` that names more than one id under `examples/games/` spells them as a `for g in ; do` loop, never inline.** `examples/games/REVIEW.das` (repo root) reads the diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 669964d255..0da83354d0 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -39,14 +39,6 @@ jobs: - name: "Install CMake and Ninja" uses: lukka/get-cmake@latest - # The wasm64 (MEMORY64) modules emscripten emits refuse to load under a node older than 23 - # ("This emscripten-generated code requires node v23.0.0"); ubuntu-latest ships 22, and the - # DlimConfiguration probe below runs one of those modules under the runner's node. - - name: "Install node 24 (the wasm64 probe runs under it)" - uses: actions/setup-node@v4 - with: - node-version: 24 - # The host daslang now builds with dasGlfw/dasOpenGL ON so it can drive the # /examples game cross-compile (daspkg release wasm). dasGlfw's # find_package(OpenGL REQUIRED) needs the GL + X11 dev headers. @@ -213,9 +205,9 @@ jobs: # WASM build: the wasm32 interpreter playground (daslang_static) + the wasm64 # compiled path (runtime/module archives, compute samples, and the /examples # games). Skipped on a cache hit — the cached web/output + web/output64 are - # reused. wasm32 is the universal interpreter fallback; everything COMPILED - # is wasm64 (the cross-compile is layout-correct only when host ptr width == - # target ptr width). + # reused. Everything COMPILED is cross-compiled as wasm64 (layout-correct only + # when host ptr width == target ptr width) and lowered to a 32-bit memory at + # link (-sMEMORY64=2), so it runs on every engine, WebKit included. - name: "Build WASM (Emscripten): playground + wasm64 examples" if: steps.wasm-cache.outputs.cache-hit != 'true' run: | @@ -241,7 +233,7 @@ jobs: # 1. wasm32 interpreter playground (daslang_static) + vendored UI + the example .das # sources staged into site/playground. THREADED build (-pthread + the imgui family), # so new_thread / JobQue map to Web Workers and every playground sample runs - # cross-origin-isolated (coi-serviceworker drops the memory64 gate for /playground). + # cross-origin-isolated (coi-serviceworker). # stage_site_playground also generates the furier + path_tracer_lab samples from the # canonical examples/graphics sources. If the imgui-family build breaks (an external's # master regressed), degrade rather than blocking every deploy: drop the clones and @@ -298,8 +290,8 @@ jobs: # drives its .das_package release_wasm_build to produce the 3 wasm64 # archives on demand — no daspkg install step (the example declares # no deps). Non-fatal — a wasm-build hiccup must not red the whole - # deploy; the furier card is skipped at stage time below (examples.js - # shows a "needs memory64" note when the iframe is unavailable). + # deploy; the furier card is skipped at stage time below (a placeholder + # page stands in for the iframe). if ./bin/daslang utils/daspkg/main.das -- \ release wasm --root examples/graphics/furier --out "$REPO/web/output64/examples"; then echo "furier wasm build OK" @@ -545,9 +537,9 @@ jobs: fi # /examples/ runtime: the interpreted runner harness + per-game artifacts. - # Each game dir holds BOTH the compiled wasm64 build (loaded in an iframe on - # memory64 engines) AND the .das sources + HUD font the interpreted fallback - # (_interp.html) mounts on Safari/iOS. The page UI (examples.html, posters, + # Each game dir holds BOTH the compiled build (loaded in an iframe on every + # engine) AND the .das sources + HUD font the interpreted runner + # (_interp.html) mounts under ?force=interp. The page UI (examples.html, posters, # files/examples.js) was already staged above via cp site/examples.html + # cp -r site/files. mkdir -p _site/examples @@ -568,11 +560,11 @@ jobs: cp modules/dasStbImage/fonts/droidsansmono.ttf "_site/examples/$g/" done - # furier — the ImGui-in-wasm showcase. wasm64-only: it bundles the compiled + # furier — the ImGui-in-wasm showcase. Compiled-only: it bundles the compiled # dasImgui module, which the universal interpreter can't bind, so there is NO - # interpreted fallback (no .das sources to stage). The card is always listed + # interpreted form (no .das sources to stage). The card is always listed # in examples.js, so stage the compiled build only when ALL THREE outputs are - # present; otherwise stage a small placeholder furier.html so a memory64 engine + # present; otherwise stage a small placeholder furier.html so the player # loads a friendly "being rebuilt" note instead of 404-ing the iframe (and # flipping the player to a bogus "running" on the 404 page's load event). mkdir -p _site/examples/furier diff --git a/CHANGELIST.md b/CHANGELIST.md index 1a41a07bd4..681af21422 100644 --- a/CHANGELIST.md +++ b/CHANGELIST.md @@ -95,6 +95,7 @@ A public site and service for the `[tune]` ecosystem: upload a tuned box's sidec - **On-demand wasm compilation** (#3628, #3630, #3633) - a fresh pre-warmed throwaway runtime per run, a content-addressed build queue behind a rootless-podman network-none sandboxed builder (`dasweb-buildd`), and standalone graphics/audio pages served from `run.daslang.io` - **The sample verifiers** (#3645, #3649, #3679) - a tier-1 batch compile gate over all 39 curated samples per PR, and a nightly playwright leg that drives the live playground per sample per engine (first sweep 70/77, zero false positives) - **Stability round** (#3635, #3648, #3650, #3652, #3667, #3714) - canvas size reconciled to the CSS box every frame (retiring three workarounds), wasm memory growth to 2 GB with reported OOM, channel `gather` outside the lock (the "dead window" wedge), the runtime wasm compiled once per page (the browser-tab OOM cliff), and a scripted fail-closed toolchain-bump protocol +- **Every browser** (#4051) - the compiled web builds link `-sMEMORY64=2` (wasm64 pointers over a memory lowered to 32-bit) and drop `+relaxed-simd`, so the example cards, the playground's wasm engine and the dasllama.io examples run on Safari and iOS; the memory64 gates are gone from both sites, and dasllama.io serves its examples under COEP `require-corp` #### The Fast Dev Loop: Module Cache + Split JIT (#3683, #3687, #3692, #3693, #3701, #3707, #3936) diff --git a/doc/source/reference/utils/daspkg.rst b/doc/source/reference/utils/daspkg.rst index e8a53d61d5..9e1dfee9b4 100644 --- a/doc/source/reference/utils/daspkg.rst +++ b/doc/source/reference/utils/daspkg.rst @@ -133,7 +133,8 @@ Options: - ``--quick`` -- on ``release``, accept a complete existing ``[tune]`` sidecar instead of re-minting (``--paranoid`` is accepted for compatibility; the tuner runs one margin-decided protocol). -- ``--wasm`` -- on ``build``, target wasm64 (memory64). +- ``--wasm`` -- on ``build``, target wasm64 (memory64, lowered to a 32-bit + memory at link so every browser runs the artifact). - ``--wasm-lib-dir `` -- directory holding the wasm64 archives; default ``/web/output64/lib``. diff --git a/examples/REVIEW.md b/examples/REVIEW.md index bd2928dbd0..94ce6075d3 100644 --- a/examples/REVIEW.md +++ b/examples/REVIEW.md @@ -5,8 +5,8 @@ **A `.das` in this folder tree that a game's `main.das` requires, directly or through another required file, answers to `games/REVIEW.md` too - wherever the diff puts it.** -**A folder with a `web_shell.html`, and every `.das` and `models.json` in it, answers to -`dasLLAMA/REVIEW.md` too, wherever the diff puts it.** +**Every file in a folder that holds a `web_shell.html` answers to `dasLLAMA/REVIEW.md` (beside +this file) too - wherever in this tree that folder sits.** **A diff that drops `require live/audio_live` from a program states, in the PR body, why that program's audio is meant to die with a reload** - `audio_live` is what carries the audio diff --git a/examples/dasLLAMA/REVIEW.md b/examples/dasLLAMA/REVIEW.md index 21428448bd..6c9f08b3ae 100644 --- a/examples/dasLLAMA/REVIEW.md +++ b/examples/dasLLAMA/REVIEW.md @@ -7,20 +7,27 @@ A browser example is a subfolder here with a `web_shell.html` (`ARCHITECTURE.md` rules below bind browser examples; a rule naming `library/` binds that folder instead. **A browser example reads its input inside its own frame - a `glfwSet*Callback` written in -`.das` is a defect; an example that draws its own text polls each input every frame and -edge-detects it (`glfwGetKey`, `glfwGetMouseButton`), and one on the imgui harness reads ImGui's -state.** In the browser build a callback lambda fires outside any frame of the program and the -program traps (`ARCHITECTURE.md` sec. 3.3). - -**A browser example's `web_shell.html` gives the canvas element `max-width` / `max-height` so the -element's box is exactly the rendered image - never `object-fit` on a canvas stretched to fill the -page area around it.** A click maps through the element's box with one ratio per axis, so a -stretched box mis-maps every click (`ARCHITECTURE.md` sec. 3.3). +`.das` is a defect; an example that draws its own text polls each input every frame and acts +when it goes down, never on every frame it stays down - a repeat comes from the example's own +hold timer (`glfwGetKey`, `glfwGetMouseButton`) - and one on the imgui harness reads ImGui's +state.** In the browser build a callback lambda fires outside any frame +of the program and the program traps (`ARCHITECTURE.md` sec. 3.3). + +**A browser example whose `main.das` reads the mouse - `glfwGetMouseButton`, or ImGui's mouse +state through the imgui harness - gives the canvas element `max-width` / `max-height` in its +`web_shell.html` - never `object-fit` on a canvas stretched to fill the page area around it.** A +click maps through the element's box with one ratio per axis, so a stretched box mis-maps every +click (`ARCHITECTURE.md` sec. 3.3). **A browser example's `web_shell.html` must reload a page the browser restored from its back-forward cache - a `pageshow` handler that reloads when `persisted` is set.** Such a page comes back with its workers and audio output frozen out of step (`ARCHITECTURE.md` sec. 3.1). +**A browser example's `web_shell.html` never refuses a browser on a WebAssembly feature probe - +it gates on the page's cross-origin isolation (`crossOriginIsolated`, `SharedArrayBuffer`) +alone.** The build runs on every engine, so a feature gate only refuses browsers that would have +run it. + **A diff that plays a second sound creates a new status box (`set_status_update`) for it and releases the first when its sound ends - never reuse a box across sounds.** The mixer's last report for the first sound lands after the second attaches, and reads as the second's stop @@ -43,6 +50,6 @@ writes nothing (`ARCHITECTURE.md` sec. 3.8). **A diff that adds an entry point to `library/dasllama_lib.das` gives it `[export_c]` and a result `daslib/c_api_header.das` can spell in C - a scalar, a string, a pointer, an enum, a -vector or a POD struct, never an array, a fixed array, a table or a tuple.** An `[export_c]` +vector, a POD struct, or nothing at all, never an array, a fixed array, a table or a tuple.** An `[export_c]` whose signature that describer refuses is a hard emit error, not a skipped export (`ARCHITECTURE.md` sec. 3.8). diff --git a/examples/dasLLAMA/parrot/web_shell.html b/examples/dasLLAMA/parrot/web_shell.html index 3973e44e56..9bfc221f47 100644 --- a/examples/dasLLAMA/parrot/web_shell.html +++ b/examples/dasLLAMA/parrot/web_shell.html @@ -11,7 +11,7 @@ - +