diff options
Diffstat (limited to 'docs/superpowers/specs')
| -rw-r--r-- | docs/superpowers/specs/2026-10-19-sb-builder-phase1-design.md | 54 |
1 files changed, 33 insertions, 21 deletions
diff --git a/docs/superpowers/specs/2026-10-19-sb-builder-phase1-design.md b/docs/superpowers/specs/2026-10-19-sb-builder-phase1-design.md index cf13c8c..2364269 100644 --- a/docs/superpowers/specs/2026-10-19-sb-builder-phase1-design.md +++ b/docs/superpowers/specs/2026-10-19-sb-builder-phase1-design.md @@ -1,7 +1,7 @@ # sb-builder phase 1: core design Date: 2026-10-19 -Status: approved in brainstorming, pending spec review +Status: approved ## Goal @@ -64,12 +64,14 @@ sb_builder/remote.py the only code that runs ssh; also virsh sb_builder/mainwindow.py tabs, menu, status bar, notifications sb_builder/dashboard.py Dashboard tab sb_builder/jobs.py Jobs tab +sb_builder/fmt.py text formatting shared by the tabs +sb-builder launcher (python3 -m sb_builder) remote/sbb-remote VM helper, single file config.example.toml GUI config example remote/config.example.toml helper config example install.sh local install; --remote deploys helper to VM tests/test_remote.py -tests/test_gui_smoke.py +tests/test_gui.py ``` ### Transport @@ -97,7 +99,8 @@ No shell strings and no paths cross ssh. Validation rules: ### Version check -On connect the GUI runs `sbb-remote version`. A mismatch with the GUI's own +On connect the GUI runs `sbb-remote version`, which also returns the +configured `overlays` (the GUI builds its sbpull menu from them). A mismatch with the GUI's own version shows a banner telling the user to run `./install.sh --remote`. ## Helper: `sbb-remote` @@ -122,7 +125,7 @@ All print one JSON object on stdout, except `job-follow`. | command | behaviour | |---|---| -| `version` | `{"version": "..."}` | +| `version` | `{"version": "...", "overlays": [...]}` | | `stats` | Dashboard data: load, uptime, disk free for repo and state dirs, package counts (total, personal, pentesting, shadowed = overlay packages also present in the pristine `current` branch, as sbshadow computes it), last sync per overlay (time of the newest commit touching `<overlay>/` in `repo_dir`), slackrepo summary from its sqlite DB (built, failed, never built). Any missing source yields `null` for that field, never an error | | `jobs` | list of all jobs' meta. A job whose meta says `running` but whose pid is gone (`os.kill(pid, 0)` fails) is reported and rewritten as `lost` | | `job-start <kind> [args]` | validate; spawn `sbb-remote _run <id>` with `start_new_session=True`, `stdin=/dev/null`, stdout/stderr to `/dev/null`; wait up to 3s for `_run` to write status; return `{"id": ...}`, or `{"busy": "<running id>"}` after deleting the refused job's dir | @@ -155,11 +158,12 @@ The flag is required in both kinds (a job has no stdin). ### Helper config: `/etc/sb-builder/config.toml` ```toml -state_dir = "/var/lib/sb-builder" -repo_dir = "/var/lib/sbopkg/SBo-danix" -slackrepo_db = "/var/lib/slackrepo/SBo-danix/database_SBo-danix_x86_64.sqlite3" -sbpull_script = "/usr/local/share/slackrepo_setup/sbpull.bash" -overlays = ["personal", "pentesting"] +state_dir = "/var/lib/sb-builder" +repo_dir = "/var/lib/sbopkg/SBo-danix" +upstream_branch = "current" +slackrepo_db = "/var/lib/slackrepo/SBo-danix/database_SBo-danix_x86_64.sqlite3" +sbpull_script = "/usr/local/share/slackrepo_setup/sbpull.bash" +overlays = ["personal", "pentesting"] ``` Missing file: these defaults. Unknown key or wrong type: every command @@ -178,7 +182,11 @@ Done in that repo, its own commit, redeployed to the VM. `--yes` applies without asking. `--no` prints the plan and leaves the tree unchanged (preview). `mkhint -F` runs in all cases, as it does today on abort. -- `sbpull <target> [--yes|--no]`: passes the flag to `sbshadow`. +- `sbshadow` honours `SBO_REPO` to override the repo path, so it can be + tested against a throwaway repo. +- `sbpull <target> [--yes|--no]`: passes the flag to `sbshadow`, and returns + `sbshadow`'s exit status (today it returns `popd`'s, so a failure would + show as a successful job). GUI flow: `sbpull personal --no` pulls and shows the shadow plan in the log; the Jobs tab offers "Apply shadowing", which starts `sbshadow --yes`. @@ -220,9 +228,10 @@ values stay, greyed, with "stale since HH:MM". `sbshadow --no`, `sbshadow --yes` (confirm dialog). - After a `--no` run whose log lists `shadow:` or `unshadow:` lines, an "Apply shadowing" button starts `sbshadow --yes`. -- Selecting a running job starts `job-follow` from the stored offset. On - stream drop: reconnect with backoff (2s doubling, max 30s) from the last - offset. +- Selecting a job starts `job-follow` from offset 0. If the stream drops + while the job is still running, the next successful `jobs` poll restarts + it from the last received offset (the poll itself backs off while the VM + is down, see Error handling). - `job-start` returning busy: dialog "busy: <id>" with [Show job]. ### Notifications @@ -276,7 +285,7 @@ settings dialog yet. | case | behaviour | |---|---| -| ssh down | status bar, VM check, stale tiles, retry with backoff | +| ssh down | status bar, VM check, stale tiles; the `jobs` poll interval doubles from `refresh.jobs` up to 30s, and resets once ssh answers | | helper missing or version mismatch | banner with `./install.sh --remote` | | busy | dialog with [Show job] | | follow drop | reconnect from offset, job unaffected | @@ -293,18 +302,21 @@ stdlib `unittest`, no frameworks. config, unknown flag), lock busy, `lost` detection, `job-follow` from an offset, and a full `_run` of a fake kind patched into the kind table (ok, failed, killed). -- `tests/test_gui_smoke.py`: `QT_QPA_PLATFORM=offscreen`, MainWindow with a - fake Remote; asserts tabs exist and the Dashboard renders a canned `stats` - dict, including `null` fields. +- `tests/test_gui.py`: config load and validation, `remote.parse`, GUI and + helper versions equal, both example configs equal the defaults. Smoke tests + under `QT_QPA_PLATFORM=offscreen` with a fake Remote: tabs, Dashboard from + a canned `stats` dict with `null` fields, job-end notification sent once, + VM-off offer, carriage-return handling in the log view. - slackrepo_setup: sbshadow `--yes` and `--no` verified in a throwaway git repo, the same way the current behaviour was tested. - First run against the real VM: manual, with the user. ## Install -- `install.sh`: installs the GUI locally (to `~/.local`, or system-wide as - root), copies `config.example.toml` to the config path only if no config - exists. -- `install.sh --remote`: scp `remote/sbb-remote` to `<target>:/usr/local/bin/`, +- `install.sh`: symlinks the `sb-builder` launcher into `~/bin` (`BINDIR` + overrides), so repo edits are live; copies `config.example.toml` to the + config path only if no config exists. +- `install.sh --remote`: scp `remote/sbb-remote` to `<target>:/usr/local/bin/` + (`SBB_TARGET`, default `buildsystem`), create `/etc/sb-builder/config.toml` from the example only if missing. Asks before deploying. A SlackBuild comes later. |
