docs/dev/flake-checks.md records why the evaluation of the checks needed more than the host has (about 0.55 GB per VM suite and 0.4 GB per NixOS system of the module check, nothing shared), the sets and what is in each, how they are exposed (checkSets, checkMembers, defaultCheckSets in nix/checks.nix), the alternatives rejected, what was measured with the sets (nix flake check --no-build 4.54 GB / 33 s on one system, 6.55 GB / 40 s --all-systems; each set alone from 0.2 GB for the cheap ones to 11.6 GB for linux-nixos-eval), and why windows-nextest and macos-nextest ran no test. build-and-test.md gets the commands for one set, the default and one member and loses windows-nextest; flake.md, docs/linux/CONTRIBUTING.md, docs/linux/dev/vm-tests.md, the comment of nix/linux/tests/vm/default.nix and the CI step of CUTOVER-PLAN.md name the new places (checkSets, checkMembers, legacyPackages.<system>.vm.NAME) instead of the placeholder heavyChecks and checks.<system>.vm-NAME. Not run: the docs build.
17 KiB
Build and test, per platform
Status: the nix commands name the outputs of the one root flake (flake.md has the
old-name to new-name table and the layout). Commands marked "ran" were run on the Linux host at the revision
that made the flake; the rest are documented from flake.nix, the justfile, the Cargo manifests or the e2e
README. macOS cannot be built or run on Linux; Linux can only type-check it.
The map of the repository is ARCHITECTURE-UNIFIED.md. Package names in this
repository (cargo metadata --no-deps, ran): komorebi (the daemon, komorebi-daemon/), komorebic,
komorebi-client, komorebi-bar, the libraries komorebi-windows, komorebi-linux, komorebi-macos, the
shims komorebic-linux, komorebic-macos, komorebi-client-linux, komorebi-client-macos,
komorebi-bar-macos, and komorebi-backend, -bar-core, komorebic-core, -collections, -config,
-core, -protocol, -settings, -transport.
0. General rules
- Platform is chosen by
cfg(target_os):cargo build -p komorebi -p komorebic -p komorebi-barbuilds the program of the OS you are on. The Windows daemon is only buildable for the Windows target (cross build in section 1); on Linux-p komorebiis the KDE daemon, on macOS the macOS one. - Never put
komorebicandkomorebic-linux/komorebic-macosin one command (same binary name). The shims stay until the cutover. - Without a
.git(a jj workspace) the build script of the macOS and Linux crates needsCOMMIT_HASH=dev. Do not run a plainnix flake checkon the root flake (it boots the VM suites); name the check, or runnix flake check --no-build --all-systemsfor the evaluation only. - Text edits under
komorebi-linux/,komorebi-hotkeys/orkomorebi-macos/change only that platform's nix derivations (each platform builds from its own filtered source,nix/workspace-src.nix); a docs-only edit elsewhere changes none, because the commit stamp is a constant in the checks (COMMIT_HASH=nix-check) and only the nativedefaultandwindows-defaultpackages carry the real commit. - Heavy builds and e2e should not run at the same time as a timing-sensitive e2e: the Windows
commandsscenario is the most sensitive (section 6).
Developer tools
tools/ (README: tools/README.md) holds the helper scripts, runnable from any jj
workspace of the repository; none of them writes to the source tree.
| Command | Use |
|---|---|
tools/fast-check [--list] [--range | --since REV] |
only the checks the touched paths need; warm in seconds (Windows clippy 8-9 s, KDE 1-3 s, macOS 2-3 s) |
tools/e2e-needed [--since REV] |
does this diff change the Windows e2e binaries (NO carries a previous passing e2e over) |
tools/kde-closure-check |
the Linux source filter list (nix/linux/root-crates.json) matches the Linux cargo closure |
tools/mac-check.sh |
macOS type-check on Linux (fake C compiler tools/cc-fake.sh) |
tools/trim-target, tools/gate-lock, tools/lite-env |
disk trimming, a heavy-gate lock, debug-info-off builds |
The persistent target directories are under $FAST_CHECK_SCRATCH (default ~/.cache/komorebi-fast-check).
1. Windows (cross build from Linux via nix)
Binaries (the flake cross-compiles to x86_64-pc-windows-msvc with an xwin SDK):
nix build .#windows-komorebi .#windows-komorebic .#windows-komorebi-bar # result*/bin/*.exe; also windows-komorebic-no-console, -komorebi-gui, -komorebi-shortcuts, -komorebi-testwin
nix build .#windows-default # windows-komorebi-full: everything, with the real commit stamp
Checks (crane; the clippy one is the pre-landing gate, about 3.5 min warm deps; the dependency derivation is shared by all of them):
nix build -L --no-link .#checks.x86_64-linux.windows-clippy
# (there is no windows-nextest: the Windows crates' tests run on Windows, `cargo test` of .github/workflows/windows.yaml)
nix build -L --no-link .#checks.x86_64-linux.windows-fmt .#checks.x86_64-linux.windows-toml-fmt .#checks.x86_64-linux.windows-deny
nix build -L --no-link .#checks.x86_64-linux.windows-e2e-tests # the Python of the e2e (pytest), no guest needed
The checks are in sets (docs/dev/flake-checks.md): one set alone builds without the others being evaluated.
nix build -L --no-link .#checkSets.fmt .#checkSets.deny # a set (a linkFarm of its members); also linux-lint, linux-test, windows-lint, ...
nix build -L --no-link .#checkSets.cheap # what `nix flake check` runs (defaultCheckSets in nix/checks.nix)
nix build -L --no-link .#checkSets.vm-fast # the heavy sets: vm-fast, vm-slow, linux-nixos-eval, linux-demo
nix build -L --no-link .#checkMembers.vm-fast.vm-kwin # one member of any set (what a heavy check is called)
nix flake check --no-build # evaluates the default sets and every other output
Quick loop without nix builds (what tools/fast-check runs; clippy of the Windows tree from the nix dev shell):
nix develop --command cargo clippy --locked --all-targets -- -D warnings
On a Windows machine itself: just build / just install (the root justfile, PowerShell), or
cargo build -p komorebi -p komorebic -p komorebi-bar --locked.
Platform-neutral crates test natively on Linux, with no cross toolchain: cargo test -p komorebi-protocol -p komorebi-config -p komorebi-collections -p komorebi-core -p komorebi-backend -p komorebi-settings -p komorebi-transport -p komorebic-core -p komorebi-bar-core -p komorebi-layouts -p komorebi-scrolling.
2. KDE Plasma (native Linux)
From the repository root (a C compiler is needed: nix shell nixpkgs#gcc -c, or nix develop .#native):
cargo check -p komorebi-linux -p komorebi -p komorebic # ran, 27 s with a warm target
cargo test -p komorebi-linux --lib # the daemon's unit tests (294 passed at the step-8 measurement)
cargo test -p komorebi-linux --test schemas -- --test-threads=1 # the schema oracle; shares a pid-only socket path, keep one thread
cargo test -p komorebi -p komorebic -p komorebi-client -p komorebi-hotkeys # daemon-binary, CLI and client tests (tests/linux_*.rs)
A single test file: cargo test -p komorebi-linux --test NAME (the files are in komorebi-linux/tests).
The -p komorebi --lib that older notes use is the thin binary package now: the unit tests are in
komorebi-linux.
Run tools/kde-closure-check (see tools/README.md) after any dependency change in the KDE crates or the crates they use: the Linux
source takes only the crates listed in nix/linux/root-crates.json.
KDE nix checks (no VM), prefixed linux-:
nix build -L --no-link .#checks.x86_64-linux.linux-clippy
nix build -L --no-link .#checks.x86_64-linux.linux-nextest
# also linux-{fmt,toml-fmt,deny,doc,bridge-js,schema-fresh,nix-options-validation,nixos-module-eval,
# keybindings-fixtures,plasma-guests-eval}
nix build -L .#komorebi .#komorebic # the native packages of the Linux system
just check runs cargo test --workspace, which would build the Windows crates on Linux. Use the commands
above; just vm NAME and just nixgen-linux are fine.
KDE VM suites
Each suite under nix/linux/tests/vm/suites/NAME boots NixOS with Plasma and KWin; they need KVM
(nested is enough under WSL2; nix run .#wsl2-probe measures it).
just vm NAME # = nix build -L .#legacyPackages.x86_64-linux.vm.NAME
just vm-all # every suite in the order of the flake
nix build -L .#legacyPackages.x86_64-linux.vm.NAME # the same suite as a test with a `driver`
# the names of each tier as JSON (ran; CI reads it)
nix eval --json .#legacyPackages.x86_64-linux.vmTiers
Tiers (the tier in each suite's default.nix; CI runs fast on every pull request, slow on master):
- fast:
check hotplug commands kwin-restart kwin-events scrolling workspace-rules core-e2e kwin-contract kwin workspace-switch stacks module placement user-maximize run-kde - slow:
client-geometry restart-survival keys-whkd core-lock keys-sxhkd render-smoke drag-resize rdp features focus-follows-mouse latency keys-engine live-resize lock-sleep look keys-skhd keys-static wallpaper vm-lib(a check, not a suite) runs the unit tests of the VM library; no VM boots.
To run only some steps of a suite: E2E_ONLY=stacks,monocle nix build --impure .#legacyPackages.x86_64-linux.vm.core-e2e -L
(a substring of the printed module.function; KFDE_ONLY is the old name).
To record a run: KOMOREBI_RECORDER=$(nix build ~/komorebi-recorder#komorebi-recorder --no-link --print-out-paths) nix build --impure .#legacyPackages.x86_64-linux.vm.core-lock -L (the recorder's repository is private; core-e2e and
core-lock keep recording-NAME.tar.gz). Details, the library and how to add a suite:
docs/linux/dev/vm-tests.md. The suites use a daemon
built once with the constant stamp, so a new commit does not rebuild it.
3. macOS
On a Mac (aarch64-darwin), from the repository root (a .git checkout, or COMMIT_HASH=dev in the
environment). These are the commands for the Mac Mini; none has been run on a Mac against wip-cand4 unless
macos-handcheck.md says so:
cargo build --locked -p komorebi -p komorebic -p komorebi-bar
cargo clippy --locked -p komorebi -p komorebi-macos -p komorebic -p komorebi-client -p komorebi-bar -p komorebi-bar-core --all-targets -- -D warnings
cargo test --locked -p komorebi-macos -p komorebic -p komorebi-client -p komorebi-bar-core -p komorebi-bar
cargo build --locked --features deadlock_detection -p komorebi # the feature is forwarded
target/debug/komorebi --version # komorebi 0.1.0 (the macOS version crate)
target/debug/komorebic --help; target/debug/komorebic docgen --output /tmp/docs-mac
target/debug/komorebi-bar --schema | cmp - schemas/macos/schema.bar.json
Never -p komorebic-macos together with -p komorebic (the shims komorebic-macos, komorebi-client-macos
and komorebi-bar-macos still build alone). Before any change that touches macOS code, run the unit tests on
the Mac first: nothing else can run them. After that walk macos-handcheck.md.
On Linux, macOS can only be type-checked, through a fake C compiler and the target
aarch64-apple-darwin: tools/mac-check.sh does it unconditionally, tools/fast-check when macOS files changed
(fake compiler: tools/cc-fake.sh); it cannot link or run:
tools/mac-check.sh # = COMMIT_HASH=dev cargo check --target aarch64-apple-darwin ... --all-targets, CC set to tools/cc-fake.sh
Nix, on a Mac: the macos-* checks (macos-{clippy,fmt,toml-fmt,deny,nextest},
macos-nix-options-validation, macos-darwin-module-validation) and the packages komorebi, komorebic,
komorebi-bar of aarch64-darwin. From Linux they can be evaluated only (nix flake check --no-build --all-systems, nix eval), which proves nothing builds.
4. Windows e2e (QEMU guest)
Full text: e2e/platforms/qemu_windows/README.md (building the golden image, every variable). Short form:
E2E_GOLDEN=golden nix run .#e2e-windows -- OUT SCENARIO... # e.g. OUT tiling focus commands
E2E_GOLDEN=golden KOMOREBI_E2E_SCALE=1.5 nix run .#e2e-windows -- OUT bar # the komorebi-bar scenario
The app uses this checkout's binaries, built with the constant stamp e2e (so a docs-only commit reuses them);
the commit under test is KOMOREBI_E2E_COMMIT (default: the flake revision). To test another commit:
build-ref.sh REF bins then KOMOREBI_E2E_BINS=bins ... (bins needs komorebi-bar.exe for bar).
| Variable | Effect |
|---|---|
E2E_ONLY=word,word |
run only the steps whose printed name contains a word (a rerun of one step) |
KOMOREBI_E2E_LOG_LEVEL=trace |
the daemon's log level (debug, trace) |
KOMOREBI_E2E_RECORDER=DIR |
record with komorebi-recorder (a folder with komorebi-recorder.exe); comes back as recording.zip |
KOMOREBI_E2E_KEEP_GUEST=1 |
keep the guest's run directory (overlay, TPM state) instead of deleting it |
KOMOREBI_E2E_SCALE=1.5 |
every wait is 1.5 times as long, for a busy host |
KOMOREBI_E2E_STATE=DIR |
restore guests from a saved state (3 s instead of 50-90 s start) |
KOMOREBI_E2E_CAPTURE=DIR |
save raw komorebic state fixtures |
SWEEP_TWO_DISPLAYS=1 |
commands adds a second display |
Keep output and run directories on a short path (unix socket paths are limited to about 108 bytes). Each
scenario gets its own guest (about 4 vCPU and 6 GB). Results are in OUT/<scenario>/result.json; trust it over
the printed line. docs/dev/bar-e2e.md describes the bar scenario.
A change to the Windows daemon or bar needs these before it is considered landed (commit types BEHAVIOUR):
commands, plus the scenario of the cluster named in the revision body (see backend-switch.md for the table).
5. What runs where (summary)
| Change touches | Run |
|---|---|
crates/* (not bar/komorebic) |
section 1 native crate tests, then Windows clippy (section 1), KDE (section 2) and macOS type-check (section 3) |
komorebi-windows/ (Windows daemon) |
Windows clippy and nextest, then e2e (section 4) |
komorebi-linux/, komorebi-hotkeys/ |
section 2 cargo, then KDE checks, VM fast tier |
komorebi-macos/ |
macOS type-check on Linux; build and tests on a Mac |
komorebi-bar/, komorebi-bar-core |
Windows clippy, cargo test -p komorebi-bar-core, macOS type-check, e2e bar |
komorebic*, komorebic-core |
cargo test -p komorebic-core (CLI doc oracle), all three platforms' checks |
flake.nix, nix/**, flake.lock |
nix flake check --no-build --all-systems, then the checks of the platform edited |
| docs only | nothing, unless under a platform tree (see section 0) |
6. Known flakes
Policy: on any e2e or VM failure, check this list by check name and by log signature first; do not soak to
re-prove a known flake. Write rates as failures/runs with the commit and host load. A known flake needs
baseline-seen evidence (it occurred before the consolidation) or at least 3 occurrences with the same
signature. A name-only match gets one rerun on a calm host at trace with logs kept; no match gets one calm
rerun, and a second failure is a regression candidate to bisect by revision. A soak is only for a candidate
that failed twice or a flake whose rate looks more than 2x higher with at least 3 failures. Passing under
load stays a pass; failing under high load is not evidence of a regression. A full commands sweep takes 4
to 6 minutes, so the E2E_ONLY runs come first.
| Check | Platform | What is seen | Rate (from a measured set) |
|---|---|---|---|
commands, daemon stops answering komorebic state |
Windows | the daemon logs nothing from any thread for 3 to 3.6 s after answering State; the reply write hits a closed socket (os error 10054); border manager: stuck for ~3000 ms in locking the window manager; could not acquire window manager lock. Cause not found (host I/O stalls are a candidate) |
1/10 sweeps before the consolidation, 1/12 after; probe 0.35% vs 0.39% of calls |
lifecycle_hidden (monocle after crash) |
Windows | no signature captured (capture at trace next time) |
1/10 before, 2/12 after |
resize (drag checks win2:bottomleft, win3:top) |
Windows | drag checks fail, pass on rerun; documented as flaky | 1 failure in the first run, passed twice |
daemon does not start (failed call to AllowSetForegroundWindow after 5 retries) |
Windows | the scenario prints "did not run, counted as 1 failed", no result.json; only seen at load 6.6-8 |
candidate, 4/~45 starts at that load vs 0/~150 at load 3-5 |
hotplug with the recorder on (AgentLost ... during exec tasklist) |
Windows | after the display unplug, in the recorder collection step; the rerun passed | candidate, 1 occurrence |
maximizing.user, placement (integer case), unknown_monitor (2) |
Windows | not flakes: the same 4 checks fail on every commit (stale known-failure markers) | fix or re-mark them |
focus_follows_mouse "did not run" |
Windows | reporting quirk of the runner, result.json says 15/0 |
ignore the line |
vm-commands, vm-core-e2e |
KDE | commands.py (guest D-Bus stops replying, BrokenPipe), handover.py ("win3 is inside the work area and not on a tile"), lifecycle_hidden.py, manage_rules.py (window never appeared, 30 s), core_e2e.py (KWin script never reported in) |
0 green in 6 runs before the consolidation at host load 25 to 190; load-dependent is plausible, not shown; no gate decision until one calm-host run exists |
golden test of komorebi-protocol |
native | "5 passed; 1 failed" once, six reruns passed, text not captured | 1 occurrence; keep the text if it recurs |
KDE tests/schemas.rs |
native | shares a pid-only socket path | keep --test-threads=1 |
Observed rates are consistent with a wide range: 1 failure in 10 runs fits anything from about 0.3% to 45% per run. Quote the counts, not "flaky". The source registry of the consolidation runs (with commits and logs) is kept by whoever runs the gates; add new occurrences there and update this table when a rate changes.