test: permanent V2 checks for airplane (#104) and fastfetch logo (#122)
Some checks failed
Check / eval (push) Has been cancelled
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:
@@ -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
|
||||
- **Task:** NEXT #104 (Airplane) + #122 (crisper fastfetch logo).
|
||||
- **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.
|
||||
**V2** fastfetch: real kitty screenshots
|
||||
`/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).
|
||||
- **Next suggestion:** #111 Recovery menu, or #98 with screenshot.
|
||||
|
||||
|
||||
85
flake.nix
85
flake.nix
@@ -90,6 +90,7 @@
|
||||
nomarchy-first-boot = final.callPackage ./pkgs/nomarchy-first-boot { };
|
||||
nomarchy-what-changed = final.callPackage ./pkgs/nomarchy-what-changed { };
|
||||
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
|
||||
# switch can refresh a broken system-package nomarchy-pull.
|
||||
# Includes nomarchy-what-changed (generation readability, #82).
|
||||
@@ -521,6 +522,90 @@
|
||||
assert assertMsg ok ("keybinds-cheatsheet: " + msg);
|
||||
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)`
|
||||
# row is display-only. Exercise it through the real template
|
||||
# patcher, then build the exact us + empty-variant console keymap
|
||||
|
||||
@@ -1,129 +1,10 @@
|
||||
# Airplane mode — runtime kill-switch for Wi-Fi + Bluetooth together.
|
||||
# Remembers each radio's prior state so disengage restores what you had
|
||||
# (if Wi-Fi was already off, it stays off). Waybar shows a plane glyph
|
||||
# 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.
|
||||
# Implementation: pkgs/nomarchy-airplane. Session state under
|
||||
# $XDG_RUNTIME_DIR; Waybar plane glyph self-hides when off.
|
||||
{ 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 = {
|
||||
home.packages = [ nomarchy-airplane ];
|
||||
home.packages = [ pkgs.nomarchy-airplane ];
|
||||
};
|
||||
}
|
||||
|
||||
124
pkgs/nomarchy-airplane/default.nix
Normal file
124
pkgs/nomarchy-airplane/default.nix
Normal 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
|
||||
''
|
||||
Reference in New Issue
Block a user