Skip to main content

max / mountaineer

todo: reconcile against the May 19 background batch Mark complete the items that landed in 54b1f0f..652cd72: - sysop info version field + server/sysadmin profile filter - sysop net default-route + resolver liveness - sysop wifi auto-iface, pre-scan, rescan, disconnect - sysop storage detail view + dataset view - /etc/issue spec form - /etc/profile.d/sysop-motd.sh shim - flatwhite themes for foot/helix/zellij/fuzzel/fnott/swaylock - yambar config + svc/zfs/net feed scripts New open items surfaced by that work: - Fill version_cmd for remaining roles - Activate the `sysadmin` manifest profile so the overlay ships - Add conditional yambar segments (vpn, dnd) - Version-pump discipline for /etc/issue Reproducibility item updated with pointer to the static audit in build_notes.md and the next concrete step (apkovl-only diff).
Author: Max J. <87768334+MaxJMath@users.noreply.github.com> · 2026-05-19 21:59 UTC
Commit: 83f1de28c4e37a501572979b486b301a6702f0b0
Parent: 652cd72
1 file changed, +24 insertions, -20 deletions
M docs/todo.md +24 -20
@@ -89,7 +89,7 @@ Lives in `../build/`. **Full installer runs end-to-end in QEMU as of build 16**;
89 89 - [ ] **Framework 13 hardware test**: `dd` `out/mountaineer-server-v3.23-x86_64.iso` to USB, boot F13 in UEFI mode, run installer against `/dev/nvme0n1` (triggers the `p1`/`p2` partition-naming branch in `installer/install.sh`). If F13 needs wifi setup before install: `iwctl` in the live env.
90 90 - [ ] Re-verify the install → reboot → ssh-in cycle in QEMU with build 16 (the new ISO carries the kcl-property + pubkey fixes that haven't yet been exercised end-to-end together).
91 91 - [ ] First-boot route walk-through: ROUTES.md "first boot" beyond hostname (network up, operator key works, services up under s6-rc) — verify each.
92 - - [ ] Reproducible builds: build 16 from a clean checkout twice, compare sha256 of the ISO.
92 + - [ ] Reproducible builds: static audit landed in `../build/build_notes.md` (apkovl half looks reproducible by construction; ISO half has 8 candidate non-determinism sources). Next concrete step is the apkovl-only diff (`build-apkovl.sh` twice, compare sha) before spinning the VM. Requires GNU tar on the build host.
93 93
94 94 ### Build history — fixes burned through (institutional memory)
95 95
@@ -186,7 +186,7 @@ Builds 11–16 (ISO-boots-and-installs era — full session details in `../build
186 186
187 187 ### Per-subcommand implementation
188 188
189 - Status: MVP slice complete. `sysop info`, `sysop motd`, `sysop services`, `sysop storage`, `sysop wifi`, `sysop net` all run on host via mock-or-real backend auto-detection. Yambar producers ready for `svc`, `zfs`, `net`. `sysop wifi` is the first interactive subcommand (masked password input). Active: TBD — natural next is `sysop id` (large) or overlay/installer work in `../build/`.
189 + Status: MVP slice complete plus the follow-ups previously deferred. `sysop info` now ships version display + server/sysadmin profile filter. `sysop net` shows default-route + resolver liveness. `sysop wifi` auto-detects the interface, pre-scans, rescans on `r`, and has a `disconnect` verb. `sysop storage` has a pool detail screen (`zpool status -P` parsing) and a dataset view (`d`). All `--summary` outputs unchanged. Active: TBD — natural next is `sysop id` (large) or live-system verification on a Mountaineer install.
190 190
191 191 **sysop-tui primitives**
192 192
@@ -196,13 +196,15 @@ Status: MVP slice complete. `sysop info`, `sysop motd`, `sysop services`, `sysop
196 196
197 197 **sysop info**
198 198
199 - - [ ] Version field on the detail screen (requires per-tool version queries — shell out to `<tool> --version`, parse, cache; defer until subprocess plumbing is settled)
199 + - [x] Version field on the detail screen — lazy per-tool `<bin> --version` lookup with per-session cache; populated for 18 of 30 roles via `version_cmd` in roles.toml
200 + - [x] Server vs Sysadmin profile filter — `--server` / `--sysadmin` flags filter via the `profile` field on Role (12 graphical roles tagged `sysadmin`)
200 201 - [ ] Runtime override: layer `/etc/mountaineer/roles.toml` on top of the compiled-in defaults (principle 2 — operator can see/edit). Currently only `include_str!` source
201 - - [ ] Server vs Sysadmin profile filter — graphical-layer roles should be hidden in `--server` mode
202 + - [ ] Fill `version_cmd` for the remaining roles (busybox, s6, ifupdown-ng, iwd, cliphist, swaybg, swappy, seatd, tlp) — most need a tool-specific incantation
203 + - [ ] Replace synchronous Command::output with a bounded-timeout variant if any version_cmd is found to hang on a real Mountaineer system
202 204
203 205 **sysop motd**
204 206
205 - - [ ] `/etc/profile.d/sysop-motd.sh` glue script — calls `sysop motd print` on login. Lives in `../build/apkovl-src/`
207 + - [x] `/etc/profile.d/sysop-motd.sh` glue script — calls `sysop motd print` on login (silent no-op if sysop missing). Lives in `../build/apkovl-src/common/`
206 208 - [ ] Tip set worth revisiting once more `sysop` verbs exist — currently 6, drawn from AESTHETICS
207 209 - [ ] Decide whether `sysop motd print` should respect a "first-login-of-the-day" suppression to avoid tip spam in tmux-heavy sessions
208 210
@@ -215,26 +217,25 @@ Status: MVP slice complete. `sysop info`, `sysop motd`, `sysop services`, `sysop
215 217
216 218 **sysop storage**
217 219
218 - - [ ] Detail view: vdev tree, error counters (read/write/cksum), scrub progress. Needs `zpool status -P <name>` parsing
219 - - [ ] Dataset view: `zfs list` — separate verb (`sysop storage datasets`?) or filtered detail screen
220 + - [x] Detail view: vdev tree, error counters (read/write/cksum), scrub progress — `zpool status -P <name>` parsing with indent-preserving vdev tree, scan/errors lines, per-row red error counts
221 + - [x] Dataset view: `zfs list -H -o name,used,avail,mountpoint` — `d` key from pool list opens it; `Esc` returns
220 222 - [ ] Snapshot management — read-only first (list), write later
221 223 - [ ] Scrub trigger verb. Same caveat as services enable/disable — gate on live system
222 224
223 225 **sysop wifi**
224 226
225 - - [ ] Pre-scan: `iwctl station wlan0 scan` + brief wait before `get-networks`, so the cache is fresh on first invocation
226 - - [ ] `r` to rescan from the list view (calls iwctl scan, waits, refreshes)
227 - - [ ] Auto-detect interface name (currently hardcoded `wlan0`); `iwctl device list` is the source
227 + - [x] Pre-scan: `iwctl station <dev> scan` + 1.5s settle before `get-networks`; `r` rescans from the list view with "scanning…" indicator
228 + - [x] Auto-detect interface name from `iwctl device list` (mode=station), fall back to `wlan0`
229 + - [x] Disconnect verb — `sysop wifi disconnect`
228 230 - [ ] Enterprise (8021x) flow — out of scope for MVP, currently a no-op on Enter; needs identity + cert/PEAP plumbing
229 231 - [ ] iwctl `get-networks` text parsing is fragile; verify on a real Mountaineer install and adjust. D-Bus interface is the upgrade path if the text format proves too noisy
230 - - [ ] Disconnect verb (`sysop wifi disconnect`)
231 232 - [ ] Promote the password input to a `sysop-tui` primitive once a second consumer exists (probably `sysop id` for passphrase entry)
232 233
233 234 **sysop net**
234 235
236 + - [x] Default route / gateway display — `ip -json route show default` parsing, rendered as a header row above the interface list
237 + - [x] Resolver liveness check — 200 ms TCP probe to 127.0.0.1:53 (`reachable` / `unreachable`), rendered alongside default-route
235 238 - [ ] SSID enrichment for wireless: read `/var/lib/iwd/` or `iwctl station <iface> show` to populate `ssid` on the real backend (mock already returns it)
236 - - [ ] Default route / gateway display (`ip -json route show default` parsing)
237 - - [ ] Resolver liveness check — show whether unbound is reachable on 127.0.0.1:53 (would also feed a future `sysop info resolver` detail screen)
238 239 - [ ] Yambar `net` segment should reflect the active default-route interface, not just wired-first. Currently wired-first heuristic
239 240 - [ ] Detail view: per-interface MAC, MTU, link speed (ethtool for wired)
240 241
@@ -284,16 +285,19 @@ Status: MVP slice complete. `sysop info`, `sysop motd`, `sysop services`, `sysop
284 285 - [x] `sysop info <role>` — first subcommand, role→tool registry shipped (33 roles in `../sysop/crates/sysop/data/roles.toml`)
285 286 - [x] `sysop motd on/off/print` — opt-out tip rotation, time-bucketed; config at `/etc/mountaineer/sysop.toml` (`$SYSOP_CONFIG` override for host dev)
286 287 - [x] `sysop services` (read-only) — s6-rc backend with mock fallback for host dev; `--summary` emits `ok`/`N down` for the yambar `svc` segment to consume. Enable/disable verbs deferred to live-system phase
287 - - [x] `sysop storage` (read-only) — zfs backend (zpool list) with mock fallback; `--summary` emits `ok`/`degraded` for the yambar `zfs` segment. Detail view, scrub trigger, snapshot ops deferred
288 - - [x] `sysop wifi` — iwctl backend with mock fallback. Selection + password prompt + connect attempt; first interactive subcommand (masked input). Enterprise (8021x), pre-scan, rescan, disconnect, auto-iface deferred
289 - - [x] `sysop net` — iproute2 backend (`ip -json addr show`) with mock fallback. Interface list with state + addresses + SSID; `--summary` for the yambar `net` segment (`eth0 ↑` / `wlan0 <ssid>` / `net ↓`). Default-route awareness, gateway display, resolver liveness check deferred
290 - - [ ] Overlay configs in flatwhite + Iosevka: foot, helix, zellij, fuzzel, fnott, swaylock, yambar — apkovl-src work
288 + - [x] `sysop storage` — zfs backend with mock fallback; pool list + detail (vdev tree, error counters, scrub line) + dataset view (`d` from pool list). `--summary` emits `ok`/`degraded` for the yambar `zfs` segment. Scrub trigger and snapshot ops deferred
289 + - [x] `sysop wifi` — iwctl backend with mock fallback. Auto-iface, pre-scan, rescan, disconnect, selection + masked password + connect. Enterprise (8021x) deferred
290 + - [x] `sysop net` — iproute2 backend with mock fallback. Default-route + resolver liveness header rows; interface list with state + addresses + SSID; `--summary` for the yambar `net` segment. SSID enrichment, detail view deferred
291 + - [x] Overlay configs in flatwhite + Iosevka: foot, helix (theme), zellij (theme), fuzzel, fnott, swaylock — `../build/apkovl-src/sysadmin/`
292 + - [x] yambar config: tag + clock + bat + net + vol + svc + zfs segments; svc/zfs/net feed scripts at `usr/local/libexec/yambar/{svc,zfs,net}.sh` calling `sysop <subcmd> --summary`. Conditional `vpn`/`dnd` still to add
293 + - [x] `/etc/issue` content set to spec form (`Mountaineer 3.23 (Dull Edge) · \n · \l`); version literal needs a bump when Alpine base moves
294 + - [x] `/etc/profile.d/sysop-motd.sh` — shim calling `sysop motd print`; silent no-op if sysop missing
291 295 - [ ] river init: minimal active bind set + commented-available blocks from upstream example — apkovl-src path TBD
292 - - [ ] yambar config: tag + date/time/bat/net/vol/svc/zfs segments, conditional `vpn`/`dnd`; Mountaineer-specific `svc` (s6-rc) and `zfs` data sources need scripts
293 - - [ ] `/etc/issue` content (`Mountaineer 3.21.0 (Dull Edge) · \n · \l`) — apkovl-src work
294 - - [ ] `/etc/profile.d/sysop-motd.sh` — one-line shim that calls `sysop motd print` on login (apkovl-src)
296 + - [ ] Activate the `sysadmin` manifest profile (`sources = ["common", "live", "sysadmin"]`, separate `world` file) so the new overlay tree actually ships
295 297 - [ ] `/etc/mountaineer/sysop.toml` seed with `[motd] enabled = true|false` written by installer based on Y/n prompt
296 298 - [ ] Installer prompt: "Show a `sysop` tip on each login? [Y/n]" → writes motd-enable choice into the seed file above
299 + - [ ] Conditional yambar segments: `vpn wg0` and `dnd` (notifications muted) — need state probes
300 + - [ ] Version-pump discipline for `/etc/issue` — emit from build.sh into apkovl-src as a generated file, or accept hand-bump per Alpine release
297 301
298 302 ## Project / community
299 303