From 0062ef6b5ffc3d57f3559118929ed9aed58b21ee Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Thu, 15 Oct 2026 12:03:51 +0200 Subject: docs(spec): an updates module that names the next step The conky updates card copies nvtable's table, where installed-behind and repo-behind share a row and are told apart by colour, and it measured "shipped" as the .info version: gamescope and kitty read as ready to install while the binary repo still held the old build. The drawer module sorts each tracked package into one action, from PACKAGES.TXT of the binary repo rather than the recipe: upgrade here, awaiting build, upstream newer, app updates. Slackware is compared mirror against installed, not against slackpkg's local ChangeLog, which `slackpkg update` replaces without installing anything; new and removed packages come from the mirror's ChangeLog. NFS reads go through a timed-out child because the mount is hard. Co-Authored-By: Claude Opus 5.5 --- .../superpowers/specs/2026-10-15-updates-design.md | 149 +++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 docs/superpowers/specs/2026-10-15-updates-design.md (limited to 'docs/superpowers/specs/2026-10-15-updates-design.md') diff --git a/docs/superpowers/specs/2026-10-15-updates-design.md b/docs/superpowers/specs/2026-10-15-updates-design.md new file mode 100644 index 0000000..e6a3458 --- /dev/null +++ b/docs/superpowers/specs/2026-10-15-updates-design.md @@ -0,0 +1,149 @@ +# Updates module + +A drawer tile and page that answer one question per row: what do I do next +to bring this machine up to date. It replaces two places that showed the same +facts less clearly: the conky updates card, a copy of `nvtable`'s table where +installed-behind and repo-behind share a row and are told apart by colour, +and the homepage ChangeLog widget, which shows the latest upstream -current +entry rather than what this machine is missing. + +## Sources and what they mean + +Four versions per tracked package: + +- **U, upstream**: `~/.config/nvchecker/new_ver.json`. +- **R, recipe**: `VERSION=` in `.info` under the three repos of + `~/Programming/GIT/slackbuilds-superrepo` (`sbo-slackbuilds`, + `my-slackbuilds`, `Slackware-Pentesting-Suite`), falling back to the + SlackBuilds.org clone at `/var/lib/sbopkg/SBo-git`. A recipe from that clone + is tagged `SBo`: it is not the user's SlackBuild, and a bump of it happens + through a slackrepo `.hint` file on the build VM, which is not visible from + here. +- **B, built**: `PACKAGES.TXT` of the user's binary repo, the directory named + by the `danix` entry of `MIRRORPLUS` in `/etc/slackpkg/slackpkgplus.conf`. +- **I, installed**: `/var/log/packages`, then appimage-updater's + `installed.json`, then `flatpak list --app`, in that order, as `nvtable` + does. + +nvtable's two alias tables (stanza name to installed name, stanza name to +SlackBuild directory) are ported into the script as dicts. + +For Slackware itself, the mirror is the `file://` line active in +`/etc/slackpkg/mirrors`. Its `PACKAGES.TXT` and `ChangeLog.txt` are compared +against `/var/log/packages`. `/var/lib/slackpkg/ChangeLog.txt` is not used: +`slackpkg update` replaces it without installing anything, so a diff against +it reads "nothing pending" after an update that was never applied. + +## Sections + +In page order. A package appears in exactly one section, the first that +matches, so a row shows the next step and nothing after it. + +1. **Slackware**, three groups, all from the mirror: + - *Upgrade*: an installed package whose name is on the mirror with a + different version or build. + - *New*: the ChangeLog's newest line for the package says `Added.`, it is + on the mirror, and it is not installed. These are slackpkg's + `install-new` semantics. + - *Removed*: the ChangeLog's newest line for the package says `Removed.`, + it is installed, and it is not on the mirror. The row carries the date of + that ChangeLog entry. + + Installed packages whose build tag matches a pattern in + `/etc/slackpkg/blacklist` (`_SBo`, `_danix`, `alien` and the rest) are + skipped in all three, as slackpkg skips them; so are blacklisted names. +2. **Upgrade here**: B newer than I. The package is built and sitting in the + repo. +3. **Awaiting build**: R is the user's (not `SBo`), R equals U, and B is older + than U. The SlackBuild is bumped and only needs building. +4. **Upstream newer**: U newer than both R and B. The SlackBuild or its hint + needs bumping, then a build. `SBo` rows land here until the build appears + in B. +5. **App updates**: I comes from AppImage or flatpak and is older than U. + +"Newer" and "older" are version order, never equality: an installed 2.1.278 +against an SBo recipe of 2.1.267 is not an upgrade. A tracked package that is +not installed and whose recipe is current is not shown. + +## `updatesctl` + +`desktop/modules/updates/updatesctl`, `/usr/bin/python3`, standard library +only. It prints one JSON document: + + { + "checked": , + "slackware": {"upgrade": [...], "new": [...], "removed": [...]}, + "upgrade": [...], "build": [...], "upstream": [...], "apps": [...], + "errors": {"mirror": "unreachable", ...} + } + +Rows are `{name, repo, from, to}`; Slackware rows are `{name, from, to}`, +`{name, version}` and `{name, date}`. `repo` is the label nvtable shows +(`personal`, `my-sbo`, `pentesting`, `SBo`, `AppImage`, `flatpak`). + +**Version order** is a small `vercmp`: split on non-alphanumerics, compare +numeric chunks as numbers and alphabetic chunks as strings, numbers before +letters. It replaces nvtable's normalised equality, including its rule that +an installed version extending upstream at a component boundary (a kernel +suffix, a git hash) counts as equal; that rule is kept as a prefix check +before ordering. + +**NFS reads** (`PACKAGES.TXT` of the repo and of the mirror, the mirror's +`ChangeLog.txt`) go through `subprocess.run(["cat", path], timeout=5)`. The +mount is `hard`, so a read during a NAS outage blocks; the timeout kills the +child, the script carries on, and that source is reported in `errors` while +the sections that do not need it still fill. + +**`--refresh`** runs `nvchecker -c ~/.config/nvchecker/nvchecker.toml` +synchronously first, then prints as above. That config already names the +GitHub keyfile. nvtake is not run: this model never reads `old_ver.json`. + +## Module + +`desktop/modules/updates/UpdatesModule.qml`, name `updates`. + +- **Icon**: ``, `linux-slackware`, present in Inconsolata Nerd Font. +- **Tile line**: `3 to install · 2 to build`, counting Slackware (all three + groups) plus Upgrade here as "to install", and Awaiting build as "to build". + `up to date` when both are zero. `checking…` before the first result. +- **Active** (accent) when there is anything to install. +- **Freshness**: when the tile is created, which is when the drawer opens, the + module runs `updatesctl`. If `checked` is more than 30 minutes old it then + runs `updatesctl --refresh` and the page shows `checking…` until it + returns. Nothing runs while the drawer is closed, the same gating as KDE + Connect. +- **Page**: the five sections in order, each with a heading and a count, each + hidden when empty. Rows read `name repo from → to`. A footer reads + `checked 12 min ago` and holds a refresh button that runs `--refresh`. + An entry in `errors` shows as one dim line under the section it empties, + e.g. `mirror unreachable`. Read-only: no install or build buttons. + +## Retiring conky's card + +Once the user trusts the tile, `bin/updates-sample.sh` and +`widgets/updates.lua` are deleted from `conky-theme-udt`, with the card's +slot, as a separate commit in that repo. `nvtable` stays in +`danix-nvchecker` for the shell; this repo does not depend on it. + +## Testing + +`desktop/modules/updates/test_updatesctl.py`, run with `/usr/bin/python3`: + +- `vercmp`: 1.14.10 > 1.14.9, 2.1.278 > 2.1.267, 2026_10_02 > 2026_09_12, + a kernel suffix equal to its base. +- Section assignment on fixture directories built in a temp dir, one row per + case: built and newer goes to Upgrade here, bumped and unbuilt to Awaiting + build, unbumped to Upstream newer, an SBo recipe behind upstream to + Upstream newer, an installed version ahead of SBo to nothing, an AppImage + behind to App updates. +- Slackware: a mirror with one changed build, one `Added.` package and one + `Removed.` package, plus a blacklisted `_SBo` build that must not appear. +- An NFS path that times out: a fifo with no writer, read with a short + timeout, must report `unreachable` without hanging the test. + +The tests must be shown to fail on a broken input before they are trusted. + +## Not in scope + +Installing, building, or bumping from the page. Showing upstream lag of the +NFS mirror itself. Reading slackrepo hint files from the build VM. -- cgit v1.2.3