The step ran `cargo nextest` in `nix develop`, whose default shell exports
CARGO_BUILD_TARGET=x86_64-pc-windows-msvc for the Windows cross build. On the
macOS runner that made cargo build the recorder's test executables for Windows,
and nextest then failed to list them:
for `komorebi-recorder::assert`, command `.../target/x86_64-pc-windows-msvc/debug/deps/assert-ce31ab528bf795df.exe --list --format terse`
exited with exit code 126 ... cannot execute binary file
Use `nix develop .#native`, the shell without the cross environment that exists
for exactly these `cargo -p komorebi-<platform>` commands. The schemas step
keeps the default shell: `just jsonschema` runs cargo through `env -u
CARGO_BUILD_TARGET`. docs/dev/ci.md notes the shell.
macos-14 was retired on 2 November 2026 and the runner label was no longer
supported, so macos-hosted was cancelled and failed required.
Only Apple silicon and the latest macOS are supported, and a standard hosted
runner is free on a public repository, so:
- macos-hosted runs on macos-latest
- it runs on a pull request that touches the macOS paths, without the label
ci:macos
- it needs only changes and lint, like windows-native-test, and no longer
waits for the KDE VM suites
- macos-selfhosted.yaml, its install-nix input, its path filter, the label
ci:macos-self and the variable MACOS_SELF_HOSTED are removed
A hosted runner of the ubuntu-24.04 pool is not promised nested virtualization, and
3 of the 16 suites of run 42182554717 failed the check of /dev/kvm. rerun-no-kvm.yaml
could not help: a workflow_run workflow runs only from the default branch, where the
file is not, and a run cannot rerun its own failed jobs while it is in progress.
The step "Enable KVM" of the nix action is now the only one that enables KVM
(enable_kvm of install-nix-action is off), runs before the disk and the install,
waits for udev to settle and polls /dev/kvm for 30 seconds instead of testing it
once, 42 ms after an asynchronous udevadm trigger, and prints what tells a missing
device from a rule that was not applied yet. With defer-no-kvm a host without KVM
is an output, not a failure.
_vm.yaml calls _vm-attempt.yaml up to three times: the suites that found no KVM are
listed through the artifacts of the run and run again on new machines, and the last
attempt fails them. vm-fast and vm-slow are calls of it. rerun-no-kvm.yaml is
removed.
A NAR of 460 MB was cut by the edge of the cache ("Stream error in the HTTP/2 framing layer") and the
resumed request failed the same way, so the job kwin-events failed before its VM test started. With
fallback = true Nix builds the derivation from source when a substitute cannot be downloaded: one dropped
connection costs minutes of compiling in that job, not the job. HTTP/2 is left at its default: nothing
shows that turning it off prevents the error.
An unquoted ": " inside the description made action.yaml invalid YAML ("mapping values are not allowed in
this context"), so every job that uses the action would have failed at its first step.
The write token goes to cachix-action on a push (master and the temporary komomono
trigger, without naming either), a manual run and a schedule; a pull request, a fork
and the merge queue only read. The flake-lock update goes through the nix action too,
and the nixpkgs canary reads the cache but never pushes (push: "false" replaces
cache: "false").
docs(ci): the write rule, the read-only path and a checklist for the first push to
komomono.
The tools of stage 0 are the latest releases, taken from the flake, and the code is changed to satisfy
them, not the other way round: every run says which versions it had, and docs/dev/ci.md says how they
are kept current (the weekly lock update, and nix flake update rust-overlay or nixpkgs in between).
The first stage ran shellcheck, rustfmt, cargo-deny and actionlint as the runner image, the
rust-toolchain rustup and two actions shipped them, and the runner's older shellcheck reported
SC2317 on a trap handler that the flake's does not. hygiene, fmt and deny now run every step in
`nix develop .#hygiene`, so CI and a local run use the same versions.
1.7.7 does not know the hosted Arm Windows runner and reported windows-11-arm as an unknown label.
1.7.12 is the latest release and the version nixpkgs gives `just lint`, so the hygiene job and a
local run now agree.
bug_report.yml and feature_request.yml get a required platform dropdown (Windows,
Linux (KDE Plasma), macOS) first in the form; the bug report's Windows-only
wording (ghost tiles, systeminfo, whkdrc, komorebic check) is scoped to Windows or
made platform-neutral; the feature request text names all three platforms.
config.yml links the Windows docs site plus the Linux and macOS index pages on
master (repo-relative GitHub links). Existing fields and labels are kept.
Verified: yq parses the three files. Links not fetched (the docs/linux and
docs/macos index files exist in the tree; they resolve on GitHub once pushed).
feature-check.yaml: the comment says feature requests for Windows, Linux and macOS
are open to current $5/month sponsors, individual commercial use licence holders
and approved contributors, and links the README section. It no longer implies
anything about a private repository. The [FEAT]: prefix check and the close and
lock behaviour are unchanged.
Verified: yq parses the file, actionlint reports nothing.
Step 8 (Option A of docs/dev/unified-binaries.md). The main.rs of komorebi-windows, komorebi-linux and
komorebi-macos becomes daemon.rs of the library (pub fn run; komorebi:: paths are crate:: paths now, the
inner attributes and the unit tests move with it), and their [[bin]] is gone, so each is a library only.
The new package komorebi (komorebi-daemon/, version 0.1.42) is the one binary: its main calls
komorebi_windows::daemon::run, komorebi_linux::daemon::run or komorebi_macos::daemon::run by cfg_select! on
the target OS, through target-gated dependencies (one key per library, cargo allows one path per key),
and forwards the features deadlock_detection and schemars. The binary name komorebi now comes from exactly
one package. The four KDE integration tests that run the binary (no_kwin, socket, hot_reload, version)
move to komorebi-daemon/tests/linux_*.rs; the version test compares with the KDE version crate, since
the package version is now shared. Old names: komorebi-windows, komorebi-linux and komorebi-macos still
build, as libraries (no binary any more: use -p komorebi). The flakes build -p komorebi with the KDE and
macOS packages, the source filters take komorebi-daemon (manifest, main.rs, linux tests), the Windows
filter leaves its linux tests out, deny.toml clarify entries gain komorebi, the release workflow's cargo wix
and the justfile version lookup name komorebi, tools/fast-check checks -p komorebi on KDE and macOS.
Behaviour: the same code runs, the same binary name; the Windows executable is rebuilt from the library
(BEHAVIOUR for the e2e gate: the Windows e2e must run).
Gates run: Windows clippy --all-targets -D warnings PASS; KDE check; macOS fake-CC check of -p komorebi
-p komorebi-macos PASS (type check only); KDE cargo test -p komorebi -p komorebi-linux -p komorebic -p
komorebi-client -p komorebi-hotkeys -p komorebi-core: 903 passed, 0 failed (the four moved tests and the
unit test of daemon.rs included); CLI docs oracle identical x3; bar schema harness identical both bars;
kde-closure-check ok; nix evaluation of the root and both nested flakes PASS; by evaluation an edit of
komorebi/src/daemon.rs changes the Windows derivations only, of the KDE daemon.rs kfde only, of the macOS
one neither (the shared komorebi-daemon/src/main.rs changes all, as expected). Not run: nix builds, VM,
e2e, any Mac run.
The package name komorebi is needed for the single komorebi binary package (Option A of
docs/dev/unified-binaries.md). The daemon library becomes komorebi-windows with [lib] name and
[[bin]] name unchanged (komorebi); komorebi-client uses package = ...; the version lookup in the
justfile and cargo wix -p in the release workflow follow. Cargo.lock only renames one entry (checked).
Not behaviour: same sources, same binary name.
Gates run: fast-check --since base: Windows clippy PASS, KDE and macOS PASS, nix eval PASS.
tools/e2e-needed lists the e2e binaries as affected (the closure crate's manifest changed), so the
Windows e2e gate is OWED by the coordinator; the produced komorebi.exe should be unchanged code. Not
run: nix builds, e2e.
Everything but dependencies.json is stored with LF, which nothing said, so
a CRLF file could get in unnoticed (it did, for two files, in a round trip
that shows as a rewrite of every line of both).
* .gitattributes: normalize every text file to LF in the repository and
check it out with LF, whatever core.autocrlf is (the Windows runner
defaults it to true)
* rustfmt.toml: newline_style = "Unix", so cargo fmt --check fails on
a Rust file with CRLF
* CI: fail when a file is stored with CRLF
* dependencies.json: the one file that was stored with CRLF
An MSI for Windows built with WiX and `cargo wix`, for x86_64 and aarch64,
attached to every release and, on tags, offered to winget. It is its own
product: its upgrade code and the GUID of its PATH component are new, since
reusing komorebi's would make the two installers upgrade and uninstall each
other.
WiX only runs on Windows, so `tests/packaging.rs` checks what a Mac can: every
binary the crate builds is in the installer, and the installer is not
komorebi's.
One workflow builds both platforms and publishes what they built. macOS builds
and checks through nix on the self-hosted runner; Windows builds natively on
`windows-latest` for x86_64 and aarch64, with fmt, clippy and the tests on
x86_64. A publish job packages the executables and checksums and writes the
release notes with kokai: a `v*` tag makes a release, a scheduled or manual run
on master replaces the rolling nightly, and any other push to master makes a
draft.
There is no nix on the Windows runner, so it checks out the komorebi sources at
the revisions `flake.lock` pins.
This commit adds various transparency related global configuration
values to GlobalState, which is can be queried via the komorebic
global-state command.
resolve#1182