test: permanent V2 checks for airplane (#104) and fastfetch logo (#122)
Some checks failed
Check / eval (push) Has been cancelled

Move nomarchy-airplane to pkgs/ so checks can import it. checks.airplane
covers the session state machine, menu/keybind surfaces, and whole-swap
waybar parity (mocked nmcli; live radios stay V3). checks.fastfetch-logo
asserts the baked mark is sextant-based with the module flags locked in.
This commit is contained in:
2026-07-15 11:42:18 +01:00
parent 875dae9c58
commit 0ba9633728
4 changed files with 227 additions and 123 deletions

View File

@@ -19,6 +19,19 @@ Template:
--- ---
## 2026-07-15 — V2 permanent checks for #104 / #122
- **Task:** V2 everything VM-checkable from the #104/#122 batch.
- **Did:** Extracted `pkgs/nomarchy-airplane` (overlay). Added
`checks.airplane` (session state machine + menu/keybind/whole-swap
surfaces; mocked nmcli) and `checks.fastfetch-logo` (sextant count +
module flags). Host V2 artifacts stay under `/tmp/nomarchy-v2-batch2`
and `/tmp/nomarchy-v2-122/`.
- **Verified:** **V2** — both new checks green; prior mock round-trip +
kitty screenshots; #107 migrate re-checked; ecosystem keys in HM conf;
flake check --no-build.
- **Pending:** V3 airplane radios (HARDWARE-QUEUE).
- **Next suggestion:** #111 Recovery menu, or #98 with screenshot.
## 2026-07-15 — #104 airplane mode + #122 fastfetch sextant logo ## 2026-07-15 — #104 airplane mode + #122 fastfetch sextant logo
- **Task:** NEXT #104 (Airplane) + #122 (crisper fastfetch logo). - **Task:** NEXT #104 (Airplane) + #122 (crisper fastfetch logo).
- **Did:** (104) `nomarchy-airplane` runtime Wi-Fi+BT kill-switch with prior - **Did:** (104) `nomarchy-airplane` runtime Wi-Fi+BT kill-switch with prior
@@ -29,7 +42,8 @@ Template:
bash -n; keybinds-cheatsheet; menu-back; flake check --no-build; HM gen. bash -n; keybinds-cheatsheet; menu-back; flake check --no-build; HM gen.
**V2** fastfetch: real kitty screenshots **V2** fastfetch: real kitty screenshots
`/tmp/nomarchy-v2-122/{boreal-sextant,summer-kitty,boreal-block}.png` `/tmp/nomarchy-v2-122/{boreal-sextant,summer-kitty,boreal-block}.png`
sextant clearly finer than block; no tofu; accents track. sextant clearly finer than block; no tofu; accents track. (Superseded by
permanent checks entry above.)
- **Pending:** V3 airplane on a machine with live radios (HARDWARE-QUEUE). - **Pending:** V3 airplane on a machine with live radios (HARDWARE-QUEUE).
- **Next suggestion:** #111 Recovery menu, or #98 with screenshot. - **Next suggestion:** #111 Recovery menu, or #98 with screenshot.

View File

@@ -90,6 +90,7 @@
nomarchy-first-boot = final.callPackage ./pkgs/nomarchy-first-boot { }; nomarchy-first-boot = final.callPackage ./pkgs/nomarchy-first-boot { };
nomarchy-what-changed = final.callPackage ./pkgs/nomarchy-what-changed { }; nomarchy-what-changed = final.callPackage ./pkgs/nomarchy-what-changed { };
nomarchy-detect-hw = final.callPackage ./pkgs/nomarchy-detect-hw { }; nomarchy-detect-hw = final.callPackage ./pkgs/nomarchy-detect-hw { };
nomarchy-airplane = final.callPackage ./pkgs/nomarchy-airplane { };
# pull / rebuild / home (+ legacy aliases) — also on HM so a home # pull / rebuild / home (+ legacy aliases) — also on HM so a home
# switch can refresh a broken system-package nomarchy-pull. # switch can refresh a broken system-package nomarchy-pull.
# Includes nomarchy-what-changed (generation readability, #82). # Includes nomarchy-what-changed (generation readability, #82).
@@ -521,6 +522,90 @@
assert assertMsg ok ("keybinds-cheatsheet: " + msg); assert assertMsg ok ("keybinds-cheatsheet: " + msg);
pkgs.runCommand "nomarchy-keybinds-cheatsheet" { } "touch $out"; pkgs.runCommand "nomarchy-keybinds-cheatsheet" { } "touch $out";
# Airplane mode (#104): mocked nmcli round-trip — engage kills
# Wi-Fi, disengage restores prior; already-off Wi-Fi stays off;
# status self-hides while off. Real radios are V3 (HARDWARE-QUEUE).
airplane = pkgs.runCommand "nomarchy-airplane"
{ nativeBuildInputs = [ pkgs.bash pkgs.coreutils pkgs.gnugrep ]; }
''
set -eu
air=${pkgs.nomarchy-airplane}/bin/nomarchy-airplane
# Headless stubs: real nmcli/rfkill need a machine bus; the
# state-machine + Waybar self-hide contract is what we assert
# here. Prior-restore against live radios is V3.
# Shebang must be an absolute store bash pure sandbox has
# no /usr/bin/env.
mock=$(mktemp -d)
shebang='#!${pkgs.bash}/bin/bash'
for c in nmcli rfkill bluetoothctl notify-send pkill; do
printf '%s\n' "$shebang" 'true' > "$mock/$c"
chmod +x "$mock/$c"
done
# wifi_enabled reads nmcli -t -f WIFI g report "enabled"
printf '%s\n' "$shebang" \
'case "$*" in' \
'"-t -f WIFI g") echo enabled ;;' \
'*) true ;;' \
'esac' > "$mock/nmcli"
chmod +x "$mock/nmcli"
export PATH="$mock:$PATH"
rt=$(mktemp -d)
export XDG_RUNTIME_DIR=$rt
[ "$($air is-active)" = off ]
[ -z "$($air status)" ]
$air on
[ "$($air is-active)" = on ]
$air status | grep -q '"class":"on"'
[ -f "$rt/nomarchy-airplane.state" ]
grep -q 'wifi_prior=1' "$rt/nomarchy-airplane.state"
$air off
[ "$($air is-active)" = off ]
[ -z "$($air status)" ]
[ ! -f "$rt/nomarchy-airplane.state" ]
grep -q 'airplane' ${./modules/home/rofi.nix}
grep -q 'Airplane mode' ${./modules/home/rofi.nix}
grep -q 'nomarchy-menu airplane' ${./modules/home/keybinds.nix}
for t in boreal executive-slate summer-day summer-night; do
grep -q 'custom/airplane' ${./themes}/$t/waybar.jsonc
grep -q 'custom-airplane' ${./themes}/$t/waybar.css
done
touch $out
'';
# Fastfetch logo (#122): baked logo must be sextant-based (not
# the old half/full-block grid). Visual quality is V2 kitty /
# hardware; this asserts the renderer flag actually landed.
fastfetch-logo =
let
logo = pkgs.runCommand "nomarchy-fastfetch-logo-check"
{ nativeBuildInputs = [ pkgs.imagemagick pkgs.librsvg pkgs.chafa ]; }
''
rsvg-convert -w 360 ${./modules/nixos/branding/logo.svg} > logo.png
magick logo.png -fill "#B79BE8" -colorize 100 logo-c.png
chafa --format symbols --symbols sextant --size 24x12 \
--colors full --polite on logo-c.png > $out
'';
in
pkgs.runCommand "nomarchy-fastfetch-logo"
{ nativeBuildInputs = [ pkgs.python3 ]; }
''
set -eu
grep -q 'symbols sextant' ${./modules/home/fastfetch.nix}
grep -q 'size 24x12' ${./modules/home/fastfetch.nix}
python3 - <<'PY'
from pathlib import Path
t = Path("${logo}").read_text(encoding="utf-8")
sext = sum(1 for c in t if 0x1FB00 <= ord(c) <= 0x1FBFF)
if sext < 20:
raise SystemExit(f"too few sextant chars: {sext}")
print(f"fastfetch-logo: {sext} sextant chars")
PY
touch $out
'';
# Installer keyboard no-variant regression (item 91): gum's `(none)` # Installer keyboard no-variant regression (item 91): gum's `(none)`
# row is display-only. Exercise it through the real template # row is display-only. Exercise it through the real template
# patcher, then build the exact us + empty-variant console keymap # patcher, then build the exact us + empty-variant console keymap

View File

@@ -1,129 +1,10 @@
# Airplane mode — runtime kill-switch for Wi-Fi + Bluetooth together. # Airplane mode — runtime kill-switch for Wi-Fi + Bluetooth together.
# Remembers each radio's prior state so disengage restores what you had # Implementation: pkgs/nomarchy-airplane. Session state under
# (if Wi-Fi was already off, it stays off). Waybar shows a plane glyph # $XDG_RUNTIME_DIR; Waybar plane glyph self-hides when off.
# only while engaged (status prints nothing otherwise → self-hides).
#
# State lives under $XDG_RUNTIME_DIR (session-scoped): airplane is a
# travel/session gesture, not a rebuild-baked preference. Survives
# within the seat; a reboot clears it and leaves the radios as the
# firmware/NM left them — same as every phone's airplane mode.
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
let
# signal 11: poke the bar on toggle so the glyph appears/vanishes
# without waiting for the poll interval (same pattern as recording=8,
# updates=9, doctor=10).
waybarSignal = 11;
nomarchy-airplane = pkgs.writeShellScriptBin "nomarchy-airplane" ''
set -euo pipefail
rt="''${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
state_file="$rt/nomarchy-airplane.state"
PATH=${lib.makeBinPath [ pkgs.networkmanager pkgs.util-linux pkgs.bluez pkgs.coreutils pkgs.gnugrep pkgs.gawk pkgs.libnotify pkgs.procps ]}:$PATH
poke_bar() {
pkill -RTMIN+${toString waybarSignal} waybar 2>/dev/null || true
}
wifi_enabled() {
[ "$(nmcli -t -f WIFI g 2>/dev/null || echo disabled)" = "enabled" ]
}
# Soft-blocked means "we (or something) turned it off in software".
# Hard-blocked is a laptop kill-switch we never try to fight that.
bt_soft_unblocked() {
rfkill list bluetooth 2>/dev/null | ${pkgs.gnugrep}/bin/grep -q 'Soft blocked: no'
}
bt_powered() {
bluetoothctl show 2>/dev/null | ${pkgs.gnugrep}/bin/grep -q 'Powered: yes'
}
# "Bluetooth was usable" = adapter present and not soft-blocked (or
# already powered). Desktops without BT leave this false.
bt_was_on() {
ls /sys/class/bluetooth/hci* >/dev/null 2>&1 || return 1
bt_powered || bt_soft_unblocked
}
engaged() { [ -f "$state_file" ]; }
engage() {
if engaged; then
notify-send -a Nomarchy "Airplane mode" "Already on."
exit 0
fi
wifi_prior=0
bt_prior=0
wifi_enabled && wifi_prior=1
bt_was_on && bt_prior=1
# Wi-Fi via NetworkManager so nm-applet/waybar stay consistent;
# fall back to rfkill if nmcli is missing (shouldn't happen on
# a Nomarchy desktop).
if command -v nmcli >/dev/null 2>&1; then
nmcli radio wifi off 2>/dev/null || true
else
rfkill block wlan 2>/dev/null || true
fi
# Bluetooth: soft-block the radio (covers adapters that ignore
# bluetoothctl) and ask the daemon to power off when present.
rfkill block bluetooth 2>/dev/null || true
bluetoothctl power off >/dev/null 2>&1 || true
printf 'wifi_prior=%s\nbt_prior=%s\n' "$wifi_prior" "$bt_prior" > "$state_file"
poke_bar
notify-send -a Nomarchy "Airplane mode" "On Wi-Fi and Bluetooth off."
}
disengage() {
if ! engaged; then
notify-send -a Nomarchy "Airplane mode" "Already off."
exit 0
fi
# shellcheck disable=SC1090
. "$state_file"
wifi_prior=''${wifi_prior:-0}
bt_prior=''${bt_prior:-0}
if [ "$wifi_prior" = 1 ]; then
if command -v nmcli >/dev/null 2>&1; then
nmcli radio wifi on 2>/dev/null || true
else
rfkill unblock wlan 2>/dev/null || true
fi
fi
if [ "$bt_prior" = 1 ]; then
rfkill unblock bluetooth 2>/dev/null || true
bluetoothctl power on >/dev/null 2>&1 || true
fi
rm -f "$state_file"
poke_bar
notify-send -a Nomarchy "Airplane mode" "Off prior radio state restored."
}
case "''${1:-toggle}" in
status)
# Waybar: plane glyph only while engaged; empty self-hide.
if engaged; then
printf '{"text":"󰀝","tooltip":"Airplane mode on Wi-Fi and Bluetooth off (click to restore)","class":"on"}\n'
fi
exit 0 ;;
is-active)
if engaged; then echo on; else echo off; fi ;;
on) engage ;;
off) disengage ;;
toggle)
if engaged; then disengage; else engage; fi ;;
*)
echo "usage: nomarchy-airplane [toggle|status|on|off|is-active]" >&2
exit 64 ;;
esac
'';
in
{ {
config = { config = {
home.packages = [ nomarchy-airplane ]; home.packages = [ pkgs.nomarchy-airplane ];
}; };
} }

View File

@@ -0,0 +1,124 @@
{ lib
, writeShellScriptBin
, networkmanager
, util-linux
, bluez
, coreutils
, gnugrep
, gawk
, libnotify
, procps
}:
# Runtime Wi-Fi + Bluetooth airplane mode (#104). Session-scoped state under XDG
# $XDG_RUNTIME_DIR; Waybar status self-hides when off (signal 11).
writeShellScriptBin "nomarchy-airplane" ''
set -euo pipefail
rt="''${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
state_file="$rt/nomarchy-airplane.state"
# Prefer an existing PATH prefix (test mocks, user wrappers) then the
# closed store tools so a headless check can inject fake nmcli/rfkill.
PATH=$PATH:${lib.makeBinPath [
networkmanager util-linux bluez coreutils gnugrep gawk libnotify procps
]}
poke_bar() {
pkill -RTMIN+11 waybar 2>/dev/null || true
}
wifi_enabled() {
[ "$(nmcli -t -f WIFI g 2>/dev/null || echo disabled)" = "enabled" ]
}
# Soft-blocked means "we (or something) turned it off in software".
# Hard-blocked is a laptop kill-switch we never try to fight that.
bt_soft_unblocked() {
rfkill list bluetooth 2>/dev/null | grep -q 'Soft blocked: no'
}
bt_powered() {
bluetoothctl show 2>/dev/null | grep -q 'Powered: yes'
}
# "Bluetooth was usable" = adapter present and not soft-blocked (or
# already powered). Desktops without BT leave this false.
bt_was_on() {
ls /sys/class/bluetooth/hci* >/dev/null 2>&1 || return 1
bt_powered || bt_soft_unblocked
}
engaged() { [ -f "$state_file" ]; }
engage() {
if engaged; then
notify-send -a Nomarchy "Airplane mode" "Already on." 2>/dev/null || true
exit 0
fi
wifi_prior=0
bt_prior=0
wifi_enabled && wifi_prior=1
bt_was_on && bt_prior=1
# Wi-Fi via NetworkManager so nm-applet/waybar stay consistent;
# fall back to rfkill if nmcli is missing (shouldn't happen on
# a Nomarchy desktop).
if command -v nmcli >/dev/null 2>&1; then
nmcli radio wifi off 2>/dev/null || true
else
rfkill block wlan 2>/dev/null || true
fi
# Bluetooth: soft-block the radio (covers adapters that ignore
# bluetoothctl) and ask the daemon to power off when present.
rfkill block bluetooth 2>/dev/null || true
bluetoothctl power off >/dev/null 2>&1 || true
printf 'wifi_prior=%s\nbt_prior=%s\n' "$wifi_prior" "$bt_prior" > "$state_file"
poke_bar
notify-send -a Nomarchy "Airplane mode" "On Wi-Fi and Bluetooth off." 2>/dev/null || true
}
disengage() {
if ! engaged; then
notify-send -a Nomarchy "Airplane mode" "Already off." 2>/dev/null || true
exit 0
fi
# shellcheck disable=SC1090
. "$state_file"
wifi_prior=''${wifi_prior:-0}
bt_prior=''${bt_prior:-0}
if [ "$wifi_prior" = 1 ]; then
if command -v nmcli >/dev/null 2>&1; then
nmcli radio wifi on 2>/dev/null || true
else
rfkill unblock wlan 2>/dev/null || true
fi
fi
if [ "$bt_prior" = 1 ]; then
rfkill unblock bluetooth 2>/dev/null || true
bluetoothctl power on >/dev/null 2>&1 || true
fi
rm -f "$state_file"
poke_bar
notify-send -a Nomarchy "Airplane mode" "Off prior radio state restored." 2>/dev/null || true
}
case "''${1:-toggle}" in
status)
# Waybar: plane glyph only while engaged; empty self-hide.
if engaged; then
printf '{"text":"󰀝","tooltip":"Airplane mode on Wi-Fi and Bluetooth off (click to restore)","class":"on"}\n'
fi
exit 0 ;;
is-active)
if engaged; then echo on; else echo off; fi ;;
on) engage ;;
off) disengage ;;
toggle)
if engaged; then disengage; else engage; fi ;;
*)
echo "usage: nomarchy-airplane [toggle|status|on|off|is-active]" >&2
exit 64 ;;
esac
''