aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers/specs/2026-10-20-sb-builder-phase4-design.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/superpowers/specs/2026-10-20-sb-builder-phase4-design.md')
-rw-r--r--docs/superpowers/specs/2026-10-20-sb-builder-phase4-design.md266
1 files changed, 0 insertions, 266 deletions
diff --git a/docs/superpowers/specs/2026-10-20-sb-builder-phase4-design.md b/docs/superpowers/specs/2026-10-20-sb-builder-phase4-design.md
deleted file mode 100644
index b746044..0000000
--- a/docs/superpowers/specs/2026-10-20-sb-builder-phase4-design.md
+++ /dev/null
@@ -1,266 +0,0 @@
-# sb-builder phase 4: hints
-
-Date: 2026-10-20
-Status: approved
-Builds on: `2026-10-19-sb-builder-phase1-design.md` (helper, job model, GUI shell),
-`2026-10-19-sb-builder-phase2-design.md` (inventory, hint view, slackrepo jobs)
-
-## Goal
-
-Manage slackrepo hint files from sb-builder: check upstream versions, update
-version hints, create and delete hints, and see a diff of every change
-with a way to revert it.
-
-Direction set by the user: the repo is run from the desktop, the VM shell is
-for upgrading Slackware only. The VM-side tools were built for a terminal; a
-tool may lose its in-VM usability if that makes sb-builder simpler. So the
-hint logic of mkhint moves into `sbb-remote` (Python, JSON answers) and the
-upstream check moves to the desktop. mkhint is not extended.
-
-## Facts this design rests on
-
-Verified on the VM, in the mkhint source (`~/Programming/GIT/mkhintfile/mkhint`,
-1.4.0, 2291 lines) and in slackrepo (`../GITHUB/slackrepo`):
-
-- The VM has 607 hints, all in `hintdir`, none in subdirectories and none in
- the SBo tree. 594 carry only `DELREQUIRES`, 13 carry
- `VERSION` + `ARCH` + `DOWNLOAD` + `MD5SUM`, one carries `OPTIONS`. No hint
- carries `NODOWNLOAD`. Pinned hints carry `DOWNLOAD_x86_64`/`MD5SUM_x86_64`
- lines, mostly empty (`claude-code`: `DOWNLOAD="UNSUPPORTED"` with the URL in
- `DOWNLOAD_x86_64`), and `ARCH="x86_64"`.
-- slackrepo reads `DOWNLOAD="no"` as "no download" and ignores `NODOWNLOAD`.
- `DOWNLOAD_$ARCH` replaces `DOWNLOAD` when set
- (`libexec/functions.d/parsefunctions.sh:457`), so `DOWNLOAD="no"` next to a
- `DOWNLOAD_x86_64` line has no effect.
-- mkhint's version update: back up to `.bak`, replace the old version by the
- new one everywhere in the file, also the `_` -> `-` form when either version
- contains `_`, also the dotless form of a dotted version inside URLs as a
- whole number (`_swap_dotless_url_version`), then for `DOWNLOAD`/`MD5SUM` and
- `DOWNLOAD_x86_64`/`MD5SUM_x86_64`: download the first URL and recompute its
- md5, keep the md5 of continuation URLs unless the user typed a new URL.
- `UNSUPPORTED`/`UNTESTED` values are skipped.
-- mkhint's new hint from `.info`: copy the `.info`, drop `PRGNAM`, `HOMEPAGE`,
- `MAINTAINER`, `EMAIL`, comment out `REQUIRES`, set `ARCH="x86_64"`, append
- `DELREQUIRES` for phantom deps in `REQUIRES`, then apply a version as above
- when one is given.
-- mkhint's `-F`: for every `.info` in the repo whose `REQUIRES` contains a
- phantom dep, merge those deps into the hint's `DELREQUIRES` (union, first
- seen order, `.bak` only when something changes, minimal hint created when
- absent). It edits only the `DELREQUIRES` line. sbshadow
- (slackrepo_setup) runs it after every sync: that is where the 594
- DELREQUIRES-only hints come from, and why they exist (slackrepo must not
- build deps -current does not need). Until now sbshadow ran it on `--no`
- previews too.
-- The VM's nvchecker config has 64 stanzas named after the packages, plus a
- `[__config__]` with oldver, newver and keyfile. nvchecker v2.22 is
- installed on the desktop, with a GitHub token in
- `~/.config/nvchecker/keys.toml`. With `--logger json` it prints one JSON
- object per line on stdout: `{"name", "version", "event": "updated"}` per
- result, `{"name", "error", "level": "error"}` per failure; it exits 0 when
- entries fail and needs no oldver or newver to run.
-- A DELREQUIRES-only hint has no `VERSION`; mkhint's update cannot bump it.
- Updating one pins it from the `.info` first; the next `mkhint -F` keeps the
- pin. A package with a phantom dep always has such a hint, so `hint-new`
- never sees one.
-- slackrepo `update <item>` builds an item that exists, built or not
- (`update_command` calls `build_command`).
-- The phantom deps list on the VM (`/root/.config/mkhint/phantom-deps`) has
- 18 entries.
-- Two packages use bundled-dep manifests: neovim (url mode) and openvino
- (sha mode, GitHub submodules). That code is about 470 lines of mkhint.
-
-## Scope
-
-In: upstream check, version update, new hint, delete hint,
-`--no-dl` as `DOWNLOAD="no"`, diff and revert.
-
-Out, for good (the Hints screen covers them): mkhint `--list`, `--versions`,
-`--review`, `--strip-version`, `--info`, `--clean`.
-
-Out, later (phase 4b, which then removes mkhint and nvchecker from the VM):
-bundled-dep reconcile for neovim and openvino, and a helper `fix-current`
-that sbshadow calls in place of `mkhint -F`, with the phantom deps list
-moved into the helper config as its single source. Also out: generating nvchecker stanzas
-for new packages (add them to `nvchecker.toml` by hand), free text hint
-editing, migration of `NODOWNLOAD=yes` lines (none exist).
-
-## Part 1: upstream check, on the desktop
-
-- `nvchecker.toml` in the repo root: the VM's 64 stanzas, without
- `[__config__]`. Stanza name = package name. Git-tracked, edited by hand.
-- `sb_builder/upstream.py` runs nvchecker through `QProcess` (as `remote.py`
- runs `virsh`) with a fixed argv: `nvchecker -c <tmp>/nvchecker.toml
- --logger json`. The temp dir holds a generated config: a `[__config__]`
- with `keyfile` (from the GUI config, when the file exists), followed by the
- repo file's text. No oldver, newver or `nvtake`: the comparison is against
- the hints.
-- Result: `{pkg: version}` and `{pkg: error}` from the JSON log. A package
- without a result, or a failed run (exit status, stderr), shows as
- `nvchecker error` with the reason in the tooltip.
-- Upstream versions are stored with `-` as `_` (mkhint's `_normalize_version`):
- `-` is illegal in a SlackBuild version, so upstream `2026-10-14` is
- packaged `2026_10_14`. The comparison and `hint-update` use that form.
-- A package is outdated when its upstream version differs from the hint
- `VERSION`, or from the `.info` `VERSION` when the hint has none. Versions
- are compared as strings; no ordering is attempted.
-
-GUI config gains `[hints] nvchecker_keyfile`, default
-`~/.config/nvchecker/keys.toml` (expanded). A missing keyfile is not an
-error: nvchecker runs without a token.
-
-## Part 2: helper (`sbb-remote` 0.5.0)
-
-### Config
-
-New key `manifest_packages` (below). `remote/config.example.toml` shows it.
-
-### Arguments
-
-- package: `PKGNAME` and present in the repo (as for slackrepo jobs).
-- version: `^[A-Za-z0-9._+-]+$`, at most 64 characters.
-- hint path: always `<hintdir>/<pkg>.hint`. If `find_hint` returns a
- different file for the package (a hint earlier in slackrepo's search
- order), every hint command refuses: "hint lives at <path>, not managed".
-- packages with a bundled-dep manifest are named in config key
- `manifest_packages`, default `["neovim", "openvino"]`. `hint-update` and
- `hint-new` with a version refuse them: "bundled deps: use mkhint until
- phase 4b".
-
-### Job kinds
-
-- `hint-update <pkg>=<ver>... [--no-dl]`: per package, in order: compute the
- new text (apply the version, below), then back the hint up to `.bak` and
- write atomically. A failure (download, missing `.info` VERSION) leaves the
- hint and its old `.bak` untouched, logs `<pkg>: failed: <why>` and
- continues with the next package. A package without a hint gets a new one
- built as `hint-new` does. The last log line is
- `SBB-RESULT {"ok": [pkg...], "failed": [[pkg, why]...]}`. Exit status 1
- when any package failed.
-- `hint-new <pkg> [<ver>] [--no-dl]` (since 0.6.0 `hint-new <pkg>... [--no-dl]`,
- no version, see the UI design): refuses when the hint exists. Builds
- the hint from the `.info` as mkhint does, without phantom deps (see the
- facts), then applies the version when given. No `.bak` (a stale
- one is removed); revert means delete.
-
-These jobs never sign, so they do not check the signing key. Their argv is
-the helper itself: `python3 sbb-remote _hint <kind> <args>`, validated again
-there. Job ids now allow a hyphenated kind (`...-hint-update`).
-
-`job-result <id>`: the last `SBB-RESULT` object of a job's log.
-
-### Applying a version
-
-1. A hint without `VERSION` is first pinned from the `.info`: its
- `VERSION`, `DOWNLOAD*` and `MD5SUM*` lines, plus `ARCH="x86_64"` when the
- hint has no `ARCH`, are put in front of the hint's text. Old version = the
- hint's `VERSION`. With no version given (`hint-new <pkg>`), steps 2 and 3
- are skipped.
-2. Replace old by new everywhere in the file except inside `MD5SUM*`
- values. When either contains `_`, also the `-` forms. When old contains
- `.`, also its dotless form inside URLs, as a whole number (no digit before
- or after).
-3. Without `--no-dl`: for `DOWNLOAD`/`MD5SUM` and
- `DOWNLOAD_x86_64`/`MD5SUM_x86_64`, split the values on whitespace (hint
- values may continue over lines with `\`). Skip a pair whose value is empty,
- `UNSUPPORTED` or `UNTESTED`. Download the first URL with `urllib`
- (timeout 60 s, streamed into `hashlib.md5`, nothing kept on disk) and
- replace its md5; keep the md5s of the other URLs. Write values back one
- URL per line with ` \` continuation, as mkhint does.
-4. With `--no-dl`: nothing is downloaded. Every `DOWNLOAD*` and `MD5SUM*`
- assignment is removed (whole multi-line values) and `DOWNLOAD="no"` is
- written, because `DOWNLOAD_$ARCH` would override it.
-
-Hint text is edited as text, not regenerated, so comments, order and other
-keys stay as they are. An assignment is `KEY="..."` (the value may span
-lines inside the quotes) or `KEY=word`, at line start.
-
-### Commands (answer at once, not jobs)
-
-- `hint-diff <pkg>`: `{"bak": text|null, "current": text|null}`. Both null
- is an error ("no backup").
-- `hint-revert <pkg>`: when a `.bak` exists, move it over the hint (also
- recreating a deleted hint); when there is no `.bak` and the hint exists,
- delete the hint (reverting a `hint-new`). Returns `{"ok": true}`.
-- `hint-delete <pkg>`: move the hint to `.bak`. Errors when there is no hint.
-
-`.bak` is one level deep and overwritten by each change, the mkhint
-convention.
-
-### Version
-
-`VERSION` 0.5.0 in `remote/sbb-remote` and `sb_builder/__init__.py`.
-
-## Part 3: GUI
-
-### Hints screen (`sb_builder/hints_tab.py`, ribbon entry and `Open > Hints`)
-
-- Rows: every package with a stanza in `nvchecker.toml` or a hint in
- `hintdir`. Columns: checkbox, package, hint version, `.info` version,
- upstream, state. Versions come from the existing `inventory` call.
-- States: `outdated`, `current`, `no stanza`, `not checked`,
- `nvchecker error` (stderr in the tooltip). Filter chips per state and a
- text filter on the name, as in the Packages tab.
-- Buttons:
- - **Check upstream**: runs Part 1 over the whole file, fills the upstream
- column, checks the outdated rows. Results live for the session.
- - **Update selected**: starts `hint-update pkg=ver ...` for the checked
- rows that have an upstream version; a **No download** checkbox adds
- `--no-dl`.
- - **Delete hint**: confirm dialog, then `hint-delete` for the current row.
-- Jobs go through the Jobs tab like every other job.
-
-### After a hint job
-
-When a `hint-update` or `hint-new` job ends, the GUI reads
-its `SBB-RESULT` line and opens a dialog with one entry per changed package:
-a unified diff (`difflib`) of `hint-diff`, and a **Revert** button per
-package. Failed packages are listed with their reason. The dialog ends with
-**Build these**, which starts `slackrepo update --preview` for the changed
-packages that were not reverted (update builds unbuilt items too), and
-**Close**. Revert is offered once per package: a second one would delete
-the restored hint. After Revert or Delete the inventory is reloaded.
-
-Each diff is fetched when its package is selected.
-
-### Packages detail pane
-
-- No hint: **New hint**, with an optional version field and a **No
- download** checkbox, starts `hint-new`.
-- Hint present: **Open in Hints** selects the package in the Hints screen.
-
-## Error handling
-
-- Bad arguments, unmanaged hint paths and manifest packages are refused by
- the helper before a job starts; the GUI shows the message.
-- A download failure (HTTP status, timeout, DNS) fails that package only and
- leaves its hint as it was.
-- Writes are atomic (temp file in the same directory, `os.replace`).
-- nvchecker missing or failing on the desktop affects only the upstream
- column; the rest of the screen works.
-- A job without an `SBB-RESULT` line (killed, lost) opens no dialog; the
- log shows what happened and `hint-diff` still works per package.
-
-## Testing
-
-- `test_remote.py`: an `http.server` thread serves fixture files for md5.
- Version swap forms (plain, `_`/`-`, dotless in URL only, md5 hex not
- touched), multi-line `DOWNLOAD`/`MD5SUM` with continuation md5s kept,
- `UNSUPPORTED` skipped, `--no-dl` removing `DOWNLOAD_x86_64` and writing
- `DOWNLOAD="no"`, a download failure restoring the hint while the next
- package still updates, `SBB-RESULT` contents, `hint-new` from `.info`,
- a DELREQUIRES-only hint pinned from the `.info`, new -> revert, update -> diff ->
- revert, delete -> revert, manifest package refusal, unmanaged hint path
- refusal, bad version and package rejection.
-- `test_upstream.py`: generated config, JSON log parsing, states (hint
- version, `.info` fallback), the repo file has no `[__config__]`, `Checker`
- against a fake `nvchecker` on `PATH` and a missing one. No network.
-- `test_gui.py`: Hints screen with a fake remote and injected upstream
- results (states, checked rows, Update selected argv), diff dialog Revert
- call.
-
-## Deploy (asks first)
-
-1. `./install.sh --remote` with helper 0.5.0.
-2. slackrepo_setup's sbshadow, which no longer runs `mkhint -F` on `--no`.
-3. mkhint, nvchecker and `/root/.config/{mkhint,nvchecker}` stay on the VM
- until phase 4b.