Quickshell on Kandelo — Qt 6.10 on wasm32: QtCore, QtGui, QML, and a QtQuick bar on the desktop - #1354
Draft
mho22 wants to merge 13 commits into
Draft
Quickshell on Kandelo — Qt 6.10 on wasm32: QtCore, QtGui, QML, and a QtQuick bar on the desktop#1354mho22 wants to merge 13 commits into
mho22 wants to merge 13 commits into
Conversation
…e scanner nixpkgs declines to build Qt cross-builds run host generators (moc, rcc, uic, qmltyperegistrar, qmlcachegen) and resolve them through QT_HOST_PATH, refusing a host/target version mismatch, so the flake's pinned Qt 6.10.2 fixes the version the recipes may declare. symlinkJoin folds qtbase, qtdeclarative and qtshadertools into the one prefix Qt's CMake requires; ninja and spirv-opt join the dev shell because Qt configures against them. qtbase builds its qtwaylandscanner only if(LINUX), so nixpkgs' darwin qtbase ships neither the generator nor its Qt6WaylandScannerTools CMake package — a Qt Wayland cross-build on a Mac stops at the missing host tool. The flake builds the generator from qtbase's own src and version, joined into the host tree only where qtbase declines wayland, so Linux keeps its own copy. host/test/qtwaylandscanner-host-tool.test.ts gates both the tool and the generated xdg-shell glue.
…tform plugin Qt is the first dependency that cannot use the meson bypass — moc/rcc/uic codegen is woven through qtbase — so the recipe drives Qt's own CMake against the flake's host tools. Three target adaptations, each stated in the script: -D__linux__=1 (qsystemdetection.h has no wasm branch), QT_LINUXBASE plus the qmutex patch (Qt honours the switch in qfutex_p.h but not qmutex.h), and an empty <linux/fs.h>. The baked qt_prfxpath is relocated to the guest prefix at install. Qt 6.10 moved the Wayland client platform plugin into qtbase, so this one package delivers libQt6WaylandClient.a, the wayland QPA plugin and the xdg-shell integration on wl_shm. wayland-shm-gbm-pool.patch backs QWaylandShmBuffer with a renderD128 gbm bo, the pool contract the browser compositor's GL importer requires. forkfd-generic-on-wasm.patch keeps QProcess on forkfd's generic fork() fallback — the __linux__ define would otherwise route it to clone(2), which this kernel does not have, and musl's _Fork.o would duplicate the glue's _Fork at link. The markdown reader pins Qt's bundled md4c so configure cannot link the build machine's dylib. QtWidgets and QtNetwork build too (Quickshell's QuickControls2 styles and src/ipc link them); brotli is forced off because configure detected the nix host copy with no wasm32 bytes behind it. qt_gui_smoke.cpp gates the stage on the kernel: plugin registry, raster fill, fontconfig/FreeType/HarfBuzz typesetting, and a QProcess re-exec child. The build script rejects any env. import outside the runtime's three. tests/package-system/qtbase-package.test.ts pins the recipe contract; docs/porting-guide.md records the host-generator technique.
…face CMake consumers resolve libdrm installs a relocatable libdrm.pc plus the linux/asm UAPI shims a __linux__-defining consumer needs, so Qt clients that include drm.h down its Linux branch compile against the installed headers alone. wayland-protocols stages its vendored XML a second time at upstream 1.45's share/wayland-protocols layout and announces it through wayland-protocols.pc, the shape CMake's pkg_get_variable resolves; ext-background-effect, ext-idle-notify and ext-workspace join the vendored set for Quickshell's wlr modules. Both revisions bump.
The MAP_FIXED branch of mmap dropped every mapping that overlapped the requested range, including the parts outside it, so a fixed map placed inside a larger mapping erased the whole mapping from the manager's records and a later first-fit search could hand out addresses the program still used. QtQml hit exactly this: its guard-page mprotect path re-maps a page inside the QML stack area, and the stack got reallocated under the running interpreter. The branch now routes through munmap, which already splits a mapping and keeps the remainder recorded. test_map_fixed_inside_mapping_splits_it pins the carve.
…gate qtshadertools cross-builds first because qtdeclarative's CMake hard-requires it, even though the software adaptation never compiles a shader at runtime. qtdeclarative builds QtQml, QtQmlModels and QtQuick with the software scenegraph; qml-network and qml-debug stay on because Quickshell's launcher links QtNetwork unconditionally and calls QQmlDebuggingEnabler unguarded. qv4-stack-bounds-on-wasm.patch bounds the QV4 engine's stack probes: the engine derives its native stack base from platform heuristics that do not hold on wasm32, and unpatched it walks past the linear-memory stack into the heap. The qt-qml-smoke gate loads a QML scene on the offscreen platform and asserts rendered non-background pixels through QQuickWindow::grabWindow.
…licy Two source-only gaps. `build-deps path` computed its cache key and cache root under the default policy regardless of the active one, so the printed path pointed at a tier the source-only engine never fills. And the local-build engine did not hand its output root to recipe children: a recipe that boots the kernel host (coreutils-docs runs the real coreutils.wasm) needs WASM_POSIX_SOURCE_ONLY_BINARY_ROOT under the env-scrubbed dev-shell entry, or the resolver refuses the policy env. The engine now exports the root to source-build children; standalone resolve callers keep exporting it themselves. source_only_recipe_receives_engine_binary_root pins the passthrough.
… exactly once Every SYS_SPAWN preflight compiled its program twice. The resolver (handlePosixSpawnResolve on both hosts) compiled a module that resolveSpawnProgram in the shared worker always discarded, then compileSpawnCandidateSnapshot compiled the same bytes again from its isolated copy. The snapshot compile already carries every check the resolver compile provided. On Firefox the duplicate is what broke the omarchy desktop: SpiderMonkey reserves one fixed 2 GiB executable-code region per content process for all workers, compiled wasm code is several times the module size (the 93 MB quickshell.wasm costs ~620 MB), and with the desktop's live code at ~1.2 GB the second quickshell compile could not get code memory — InternalError: out of memory, mapped to EIO, surfaced as posix_spawnp: I/O error. The resolver contract narrows to ResolvedSpawnCandidate — programBytes and argv, no module — on both hosts, so the duplicate cannot come back. The candidate-binding tests now assert byte-identical commits reuse the snapshot module and diverging commits recompile from the committed bytes.
programs/qtdemo/qtdemo.cpp draws an animated wave field, gradient-filled type and a live clock through QtGui's raster engine, the wayland QPA plugin and xdg-shell onto wl_shm — antialiasing the C clients' wpkdraw does not have. Qt's wayland plugin resolves the socket through XDG_RUNTIME_DIR and refuses to start without it. host/test/qtdemo-smoke.test.ts boots wlcompositor and qtdemo under one NodeKernelHost and reads the program's markers — QTDEMO_PLATFORM=wayland, the first paint, QTDEMO_FRAME at 30 and 60, a non-black composite sample — then a host-injected Escape closes the window through Qt's xkb state and both processes exit 0.
Quickshell is the QtQuick shell toolkit Omarchy v4 writes its bar and launcher in. The build keeps WAYLAND with WLR_LAYERSHELL and turns off every feature whose dependency this kernel does not carry (DBus, PipeWire, PAM, greetd, X11, Hyprland, screencopy, session-lock, toplevel-management, jemalloc, the crash handler). cli11 2.5.0 ships as a header-only package for the launcher's CLI parsing. no-wl-proxy-interpose-on-wasm.patch removes upstream's wl_proxy_get_listener interposition — a dynamic-linking mechanism (dlsym RTLD_NEXT plus --export-dynamic-symbol, which wasm-ld lacks) that collides with libwayland-client.a's definition in a static link. The executable link closes over libffi, libxml2, libiconv, libcharset and the sysroot gbm — the recipe had declared them without linking them, and the resulting env.ffi_prep_cif trap killed quickshell inside libwayland's closure marshalling before the QML engine started. After the fix the only env imports are the three the platform owns. The quickshell-smoke gate boots the binary on the kernel and asserts --version.
The launcher gains two entries. Qt Demo runs qtdemo — the seventh tile, fontconfig's new sans-serif alias resolving Qt's default family. Quickshell runs the staged /usr/share/kandelo/quickshell/shell.qml; the compositor's environment carries QT_QUICK_BACKEND=software for every client it spawns, and the PanelWindow maps as a wlr-layer-shell clock bar along the bottom edge, where Waybar does not own the exclusive zone. The rootfs superblock capacity doubles to 512 MiB (the demo stages ~200 MB of desktop binaries; the 256 MiB cap died with ENOSPC at exec-time materialization of /usr/bin/dash) and the source-only Vite asset ceiling rises to 1 GiB so the 93 MB quickshell module fits the retained snapshot set. wlcompositor prints a one-shot GLDRAW app_id= the first time the GL renderer draws a window's own texture, and the spec polls it for foot and qtdemo: every protocol marker (map, focus, tile, frame callback) still fires for a window whose wl_shm pool the GPU cannot import, which is exactly how an invisible qtdemo first shipped. Gate 5e launches Quickshell through the launcher and takes the LAYER ns=quickshell line as the mapping proof — layer surfaces never emit GLDRAW. Firefox is excluded with a pointer to the new browser-support section: the running desktop's compiled wasm plus Quickshell's main and thread-patched modules exceeds SpiderMonkey's fixed 2 GiB per-process executable-code arena, so its first QThread::start fails. The section records the measured numbers.
perl is a multi-output package, so its binary lands at programs/perl/perl.wasm; run-example.ts still probed the flat programs/perl.wasm and silently skipped the perl examples.
Upstream libdrm's drmHandleEvent does a single read and assumes Linux's blocking read on /dev/dri/cardN parks the caller until the vblank pump delivers an event. This kernel returns 0 immediately on an empty event ring, so a bare drmHandleEvent races the vblank tick: it returns without dispatching, the queued flip stays pending, and the next drmModePageFlip hits EBUSY. Real consumers (SDL2 KMSDRM, weston, mutter) poll first; the fixture now does the same.
… runtime file The shell package's build.toml moved to revision 32 and shell-lazy-archives grew NCURSES_TERMINFO_RUNTIME_FILE, but the bridge test still asserted revision 30 and staged no terminfo member, so it failed against the tree it verifies. The fixture now writes the terminfo archive the resolver contract names and the revision assertion follows the manifest.
mho22
force-pushed
the
explore-dri-quattro
branch
from
September 1, 2026 14:27
36d9da7 to
076a470
Compare
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.
Why
Omarchy v4 folds Waybar, Walker, Mako, SwayOSD, hyprlock, hypridle, swaybg and polkit-gnome into a single Quickshell QML process, and Quickshell is a QtQuick client. Nothing Qt existed in the registry, so this PR is the floor of that stack: Qt 6.10.2 QtCore, QtConcurrent, QtXml, QtGui and the Wayland platform plugin, static on wasm32, running on the kernel.
It stacks on
explore-dri-omarchy(#1241), extending the DRI stack (#698 → #709 → #948 → #976 → #1318 → #1241 → this). The staging plan lands whole: stage 0 is the Qt6 host toolchain, stage 1 is QtCore, stage 2 is QtGui plus the Wayland plugin, stage 3 is QtDeclarative running QML on the kernel, stage 4 is Quickshell 0.3.1, and stage 5 puts Quickshell on the Omarchy desktop as a launcher entry.What changed
QtCore on wasm32 (stage 1). Qt is the first dependency that cannot use the meson bypass — moc, rcc and uic codegen is woven through qtbase, so it drives its own CMake with host generators from the flake's pinned Qt through
QT_HOST_PATH. Three target adaptations, each for a reason the port exposed:-D__linux__=1becauseqsystemdetection.hhas no wasm branch and reads preprocessor macros, notCMAKE_SYSTEM_NAME;QT_LINUXBASEplusqmutex-honour-qt-linuxbase.patchbecause Qt 6.10.2 honours that switch inqfutex_p.hbut ignores it inqmutex.h, so the configuration static-asserts without the patch; and an empty<linux/fs.h>because Qt defines the one symbol it wants (FICLONE) when the header does not.QProcessstarts off at this stage: its forkfd references_Fork, and musl's_Fork.oalso carries__post_Fork, whichchannel_syscall.cdoes not override, so linking duplicates_Fork. The QProcess paragraph below settles this before stage 4. Qt also baked its configure-time prefix intolibQt6Core.aasqt_prfxpath, writing the builder's PID into every downstream program; the recipe now configures against the guest path, relocates at install time, and fails if the staging path survives.The host qtwaylandscanner (stage 2's build prerequisite). Every Qt Wayland cross-build runs a host
qtwaylandscanner. qtbase builds it onlyif(LINUX), so nixpkgs' darwin qtbase ships neither the generator nor itsQt6WaylandScannerToolsCMake package — stage 2 would build on Linux CI and fail on every Mac.flake.nixnow builds the generator from qtbase's ownsrcandversion, joined intoQT_HOST_PATHonly where nixpkgs' qtbase declines wayland, so Linux keeps qtbase's own copy and receives no duplicate. The binary stays out of every package recipe on purpose: a package archive is content-hashed and published, so a Mach-O binary inside one makes an arm64 Mac and an x86_64 runner produce different wasm32 archives for the same source.QtGui and the Wayland platform plugin (stage 2). Qt 6.10 moved the Wayland client platform plugin out of qtwayland and into qtbase, at
src/plugins/platforms/wayland. No qtwayland package is needed — the one qtbase recipe now produceslibQt6WaylandClient.a, thewaylandQPA plugin and the xdg-shell integration, driven by the host scanner above. QtGui's dependencies come from the registry: freetype, fontconfig, harfbuzz, libpng and libxkbcommon. OpenGL stays off, so the client runs onwl_shm— QtQuick will need a graphics API; that is stage 3. One cross-build trap fixed on the way:write_basic_package_version_filebakes the pointer width of the machine that built the host tool into a bitness check, so the wasm32 consumer found the package and refused it ("version: 6.10.2 (64bit)"); clearingCMAKE_SIZEOF_VOID_Pomits the check, as Qt's own tools packages do.The gate is a program, not a recipe assertion.
qt_gui_smoke.cppimports the offscreen, wayland and xdg-shell plugins, asserts both Wayland keys reach the static plugin registry, fills a rect through the raster engine and typesets a string through fontconfig, FreeType and HarfBuzz, on the kernel:The build script also rejects any
env.import outside the runtime's own three — the SDK link does not fail on an undefined symbol, it leaves a host import that traps only if that path runs, which is how a missing libxml2 surfaced asUnimplemented import: env.xmlCreatePushParserCtxtat runtime rather than at link. Every archive on the link line was then removed in turn: what remains is what the check or the run demands.Font enumeration is not claimed. fontconfig matches the staged font and FreeType rasterises it (
GLYPH_PIXELS=228), butQFontDatabasereports only Qt's three generic families, never the staged name, so the gate asserts ink and says so in its comment.qtdemo — the first Qt window on the desktop. The stack above proves itself only offscreen;
programs/qtdemo.cppputs its pixels on the Omarchy desktop. AQRasterWindowdraws an animated wave field, gradient-filled type and a live clock through QtGui's raster engine, the wayland QPA plugin and xdg-shell ontowl_shm— antialiasing the C clients' wpkdraw does not have. The desktop wires it in as a launcher entry ("Qt Demo"), and the omarchyfonts.confgains asans-serifalias to the staged Inconsolata, because Qt asks for sans-serif where the wpkdraw clients ask for monospace. Two findings from the first run: Qt's wayland plugin resolves the socket throughXDG_RUNTIME_DIRand refuses to start without it, and the compositor'sCOMPOSITE_SAMPLEis one-shot — it fires on the first composite with a mapped surface.Both hosts gate it.
host/test/qtdemo-smoke.test.tsboots wlcompositor and qtdemo under oneNodeKernelHostand reads the program's markers —QTDEMO_PLATFORM=wayland, the first paint,QTDEMO_FRAMEat 30 and 60 (the frame-callback loop keeps granting frames), a non-black composite sample — then a host-injected Escape closes the window through Qt's xkb state and both processes exit 0. The browser spec (kandelo-omarchy.spec.ts) launches it the way a user does — Ctrl+Space, "qt", Enter — and asserts the same markers plus the seventh tile; the launcher-count gate moves from eight entries to nine.Qt paints through gbm pools — the invisible-window bug and its gate. The first browser run of qtdemo passed every one of those markers and drew nothing: pure wallpaper where the seventh tile focused. On this kernel a
wl_shmpool fd must be a DRI prime fd — the browser compositor composites with its GL renderer, which imports client pools withgbm_bo_import(GBM_BO_IMPORT_FD); Qt's stock backing store allocates a memfd, the import failsEINVAL, andrepaint_glskips the surface while map, focus, tile and the frame-callback loop all keep reporting success. The Node smoke never sees it because the Node compositor is on the CPU renderer, which reads any fd.wayland-shm-gbm-pool.patchbacksQWaylandShmBufferwith a renderD128 gbm bo — allocate,gbm_bo_mappersistently into the QImage at bo stride, handgbm_bo_get_fd()towl_shm_create_pool— the same adaptation foot and GTK already carry.The class now has its own gate, because every existing one is protocol, not pixels. wlcompositor prints a one-shot
GLDRAW app_id=the first time the GL renderer draws a window's own texture, and the browser spec polls it for foot and qtdemo: a window that maps, focuses, tiles and pumps frames but never draws now fails the spec, and the fix was verified by screenshot — the animated Qt card on the canvas, not wallpaper.QML runs on the kernel (stage 3). qtshadertools cross-builds first — qtdeclarative's CMake hard-requires it even though the software adaptation never compiles a shader at runtime — and qtdeclarative builds QtQml, QtQmlModels and QtQuick with the software scenegraph selected via
QT_QUICK_BACKEND=software. One patch carries the stage:qv4-stack-bounds-on-wasm.patchbounds the QV4 engine's stack probes, because the engine derives its native stack base from platform heuristics that do not hold on wasm32 and unpatched it walks past the linear-memory stack into the heap. Theqt-qml-smokegate loads a QML scene on the offscreen platform and asserts rendered non-background pixels throughQQuickWindow::grabWindow. Quickshell later widened the stage: qtbase adds QtWidgets (QuickControls2 styles link it) and QtNetwork (src/ipclinksQt::Networkunconditionally), and qtdeclarative re-enablesqml-networkandqml-debugbecause Quickshell's launcher callsQQmlDebuggingEnablerunguarded. QtNetwork builds with brotli forced off — qtbase's configure auto-detected brotli from the nix host closure and emitted-lbrotlidecwith no wasm32 bytes behind it, the host-leak class PR #406 diagnosed.A MAP_FIXED map inside a mapping carves, not evicts — a kernel fix QML forced. The
MAP_FIXEDbranch of mmap dropped every mapping that overlapped the requested range, including the parts outside it, so a fixed map placed inside a larger mapping erased the whole mapping from the manager's records and a later first-fit search could hand out addresses the program still used. QtQml hit exactly this: its guard-page mprotect path re-maps a page inside the QML stack area, and the stack then got reallocated under the running interpreter. The branch now routes through munmap, which already splits a mapping and keeps the remainder recorded;test_map_fixed_inside_mapping_splits_itpins the carve.QProcess through forkfd's generic fork fallback. Quickshell needs QProcess, and stage 1 had switched it off. Qt is compiled with
__linux__defined, which routes its bundled forkfd toforkfd_linux.c, whoseclone(2)calls cannot exist on this kernel — and whose libcclone()reference pulls musl's_Fork.othrough__post_Fork, duplicating the glue's_Forkat link.forkfd-generic-on-wasm.patchkeeps wasm off that path with one condition (__linux__ && !__wasm__); forkfd then takes its genericfork()fallback — the same instrumented fork every shell pipeline uses — and reaps throughwaitid(WNOWAIT)and SIGCHLD, both of which the kernel carries.libc/gluestays untouched. The gui smoke gains a QProcess pass: the program re-execs itself with--childthroughQProcess::startand asserts the child's exit code and marker.Quickshell 0.3.1 on wasm32 (stage 4). Quickshell is the QtQuick shell toolkit Omarchy v4 writes its bar and launcher in. The build keeps WAYLAND with WLR_LAYERSHELL and turns off every feature whose dependency this kernel does not carry (DBus, PipeWire, PAM, greetd, X11, Hyprland, screencopy, session-lock, toplevel-management, jemalloc, the crash handler). cli11 2.5.0 ships as a new header-only package for the launcher's CLI parsing.
no-wl-proxy-interpose-on-wasm.patchremoves upstream'swl_proxy_get_listenerinterposition — a dynamic-linking mechanism (dlsymRTLD_NEXTplus--export-dynamic-symbol, which wasm-ld lacks) that collides withlibwayland-client.a's definition in a static link. Support commits carry the surrounding surface: libdrm installs a relocatable.pcand the linux/asm UAPI shims a__linux__-defining consumer needs, wayland-protocols stages upstream 1.45's canonicalshare/wayland-protocols/layout for CMake'spkg_get_variable, and the executable link closes over libffi, libxml2, libiconv, libcharset and the sysroot gbm — the recipe had declared them without linking them, and the resultingenv.ffi_prep_ciftrap killed quickshell inside libwayland's closure marshalling before the QML engine started. After the fix the onlyenvimports are the three the platform owns.Every spawn compiled its program twice — the fix that let Quickshell start on Firefox. The SYS_SPAWN preflight resolver (
handlePosixSpawnResolve, both hosts) compiled a module that the shared worker'sresolveSpawnProgramalways discarded, thencompileSpawnCandidateSnapshotcompiled the same bytes again. The snapshot compile already carries every check the resolver compile provided. On Firefox the duplicate is what broke the desktop: SpiderMonkey reserves one fixed 2 GiB executable-code region per content process for all workers (verified withvmmap— a single 2.0G rwxVM_ALLOCATEregion), compiled wasm code is several times the module size (the 93 MB quickshell.wasm costs ~620 MB of arena, measured), and with the desktop's live code at ~1.2 GB the second quickshell compile could not get code memory —InternalError: out of memory, mapped to EIO, surfaced asposix_spawnp: I/O error. The resolver contract narrows toResolvedSpawnCandidate— bytes and argv, no module — so the duplicate cannot come back. Both host entries drop theirWebAssembly.compile; the candidate-binding tests assert byte-identical commits reuse the snapshot module and diverging commits recompile from the committed bytes.Quickshell joins the desktop (stage 5). The launcher gains a Quickshell entry: Quickshell runs the staged
/usr/share/kandelo/quickshell/shell.qml, the compositor's environment carriesQT_QUICK_BACKEND=softwarefor every client it spawns, and thePanelWindowmaps as a wlr-layer-shell clock bar along the bottom edge, where Waybar does not own the exclusive zone. Two infrastructure fixes made the boot survive: the rootfs superblock capacity doubles to 512 MiB (the omarchy demo stages ~200 MB of desktop binaries; the 256 MiB cap died with ENOSPC at exec-time materialization of/usr/bin/dash), and the local-build engine now exportsWASM_POSIX_SOURCE_ONLY_BINARY_ROOTto recipes, so a recipe that boots the kernel host — coreutils-docs runs the real coreutils.wasm — resolves under the source-only policy;./run.sh local-buildcompletes 150/150 nodes from cold.The spec grows Gate 5e: launch Quickshell through the launcher and take the
LAYER ns=quickshellline as the mapping proof — layer surfaces never emit GLDRAW. The gate runs on Chromium and WebKit. Firefox is excluded with a pointer to the newdocs/browser-support.mdsection: after the double-compile fix Quickshell spawns and runs QML on Firefox, but its firstpthread_createneeds the thread-patched module — a second legitimate full compile — and ~1.9 GB of live desktop code plus another ~620 MB cannot fit the 2 GiB arena, soQThread::startfails. Disabling the optimizing JIT does not reduce the arena below the cap. That is an engine limit, not host waste — every byte of that code belongs to a running desktop program — so the section records the measured numbers and the spec gates on it.Verification
At the branch head, inside
scripts/dev-shell.shwith the source-only resolution env:apps/browser-demos/test/kandelo-omarchy.spec.ts→ 3 passed on chromium, firefox and webkit, with the Qt gate, bothGLDRAWgates, and Gate 5e (Quickshell; documented firefox exclusion)gbm_bo_importerrorcargo test --workspace --target aarch64-apple-darwin --lib→ 1784 passed, 0 failed (includestest_map_fixed_inside_mapping_splits_it)host/test/posix-spawn.test.ts,spawn-blob-transport.test.ts,spawn-pid-authority.test.ts→ passed on the narrowed resolver contractbash scripts/check-abi-version.sh→ exit 0, snapshot in sync. The one kernel change (the MAP_FIXED carve) fixes mapping bookkeeping; it moves no ABI surface.cd host && npx vitest run→ 383 files passed, 14 failed. 13 of the 14 fail only because the source-only env changes fixture and package-system expectations; each passes under the default env. The 14th is one test infork-from-thread.test.ts(see the known defect below).bash scripts/run-libc-tests.sh→ 605 PASS, 20 XFAIL, 1 FAIL:regression/raise-race(known defect below).bash scripts/run-posix-tests.sh→ 174 PASS, 3 XFAIL, 2 SKIP, 0 FAIL.Known defect, inherited from the base branch: raise-race.
regression/raise-race— fork from a caught signal handler on a thread; 100 children, ~14 lost,waitreturns ECHILD — fails deterministically on this stack and passes on the pre-rebase line. The cause sits below this PR: the rebased stack's commit9b79d73b4redesigned signal/park handling (kandelo_caught_handler_depthplus host-owned SA_RESTART records) and dropped the original line'sCH_SIG_RESTARTchannel-word protocol (ea97a4261). Both runtime commits of this PR (1c1db5e20,e40269649) were revert-tested; the failure persists without them. The failing concurrentfork-from-threadtest (errno 12) plausibly shares the same machinery. The fix belongs to the stack stage that ownslibc/glueand the host signal records, not to this PR.Per-stage gates, each verified green at its commit:
host/test/qt-gui-smoke.test.ts→ 1 passed (QT_GUI_SMOKE_OKon the kernel, plus the QProcess child pass; the undefined-import check stays green)host/test/qt-qml-smoke.test.ts→ passed (a QML scene renders non-background pixels through the software scenegraph)host/test/qtdemo-smoke.test.ts→ 1 passed (Qt maps on wlcompositor, animates, composites, closes on Escape)host/test/quickshell-smoke.test.ts→ 1 passed (quickshell.wasm boots, CLI11 parses argv,--versionprints build metadata)host/test/qtwaylandscanner-host-tool.test.ts→ 2 passed;host/test/wayland-protocols-scanner.test.ts→ 1 passed;tests/package-system/qtbase-package.test.ts→ 9 passed./run.sh local-build→ 150/150 nodes, 7/7 products with quickshell and cli11 in the registry roots