================================================================================ PROMPT FOR CLAUDE CODE Build a batch SlackBuild testing tool for Slackware 15.0 stable ================================================================================ CONTEXT ------- I am an SBo (SlackBuilds.org) package maintainer. My daily-driver machine runs Slackware64-current, but SBo targets Slackware 15.0 stable. I need to test my SlackBuilds against a clean 15.0 environment WITHOUT booting a VM, because a build that works on -current can fail on 15.0 (different toolchain, library sonames, Python version, etc.). There is an existing reference script by Jeremy Hansen (bassmadrigal) called overlay-chroot.sh that solves the isolation problem using an overlayfs-backed chroot: it keeps a read-only 15.0 base tree as the overlay lowerdir, layers a disposable writable upper dir on top, binds the needed system dirs (dev, proc, sys, /dev/pts, resolv.conf, dbus machine-id), drops the user into an interactive chroot, and on exit unmounts everything and discards the upper layer. I want to REUSE that proven mounting/teardown machinery but build a NEW, purpose-built tool around it. Treat overlay-chroot.sh as a reference for the mechanics, not as a base to lightly patch. The new tool's job is different: non-interactive, automated, batch testing with dependency resolution, persistent logs, and a color summary. NOTE ON ISOLATION SCOPE (so expectations are correct): the chroot shares the host kernel, which here is the -current VM's kernel, not a 15.0 kernel. This is acceptable and expected: the tool verifies that SlackBuilds BUILD and install cleanly against the 15.0 userland/toolchain/libraries, which is where -current vs 15.0 drift actually bites. It does NOT claim to test kernel-module packages or anything depending on the running kernel version; those few cases still want a real 15.0 VM and are out of scope for this tool. I will provide overlay-chroot.sh alongside this prompt (or you can ask me to paste it). Study its overlay setup, bind mounts, X-access handling, and its robust cleanup/unmount ordering and reuse those patterns faithfully. Its cleanup ordering in particular is correct and worth preserving (pts before dev, overlay last, etc.). ================================================================================ GOAL ================================================================================ A single root-run bash script that takes either ONE package name or a CATEGORY FOLDER, resolves and builds the full SBo dependency tree in correct order inside a clean, disposable Slackware 15.0 overlay chroot, installs each resulting package, captures persistent per-package logs, and prints a color-coded summary at the end recapping exactly what happened. ================================================================================ INVOCATION / ARGUMENTS ================================================================================ The script must accept: 1. A single program name, e.g.: sbo-batch-test playwright-cli -> Resolve its full SBo dependency tree, topologically sort it, build and install every dependency first (in order), then build/install the target. Test as a unit; if a dependency fails, the target is reported as blocked/failed and the reason is the failed dep. 2. A category folder from my LOCAL SBo repository, e.g.: sbo-batch-test ./network sbo-batch-test /path/to/SBo-danix/pentesting -> Treat every SlackBuild directory inside that folder as a target. For EACH target, resolve+build its dep tree (deps may live in OTHER categories) then build the target. Each target is an independent test unit; one target failing must not abort the whole run. Design the argument parsing so additional modes can be added later (e.g. "all", a queue/list file). Do not implement those now, but leave a clean extension point and mention it in --help. Standard niceties: --help / -h usage text --keep do not destroy the overlay on completion (for inspection) --no-color disable ANSI color in summary (auto-disable if stdout is not a TTY) --jobs / -j N reserved/optional; if non-trivial, stub it and note it A dry-run flag that resolves and PRINTS the build order without building. ================================================================================ DEPENDENCY RESOLUTION (this is the hard part — get it right) ================================================================================ - Parse REQUIRES from each package's .info file. - Resolve TRANSITIVELY: a dep's deps must also be built first. - TOPOLOGICALLY SORT the resulting graph so every package is built only after all its dependencies. Detect and clearly report dependency CYCLES instead of looping forever. - The "%README%" token in REQUIRES is NOT a package. It is a marker meaning the user must read the README for manual configuration/optional deps. Skip it for build ordering but RECORD that the package carries a %README% so it shows in the summary (maintainers should be reminded). - A dependency may already be satisfied by the base Slackware install (i.e. it is part of stock 15.0, not an SBo package). Such deps will NOT be found in the SBo tree. Do NOT treat "not in SBo tree" as a hard failure by default; check whether it is already installed in the chroot (look in /var/log/packages). If it is neither in the SBo tree nor installed, THAT is a real unmet-dependency error — report it. - SOURCE OF TRUTH for resolution: my LOCAL on-disk SBo tree (my SBo-danix checkout and/or a local SBo 15.0 clone), NOT the network. The script should take the SBo tree root as a configurable variable at the top. If a needed SlackBuild directory cannot be located in the configured tree(s), report it as a resolution failure with the missing package name — do not silently skip. This is settled: resolution is LOCAL-tree-only (the SBO_TREE_ROOTS in the VM). Do NOT add network/sbopkg resolution. My SBo-danix tree contains unpublished personal and pentesting packages that do not exist upstream, so the local tree is the only correct source of truth. ================================================================================ BUILD + INSTALL FLOW (per package, inside the chroot) ================================================================================ For each package in sorted order: 1. Copy its SlackBuild directory into a working location inside the overlay. 2. Source the .info; download the source(s) to the build dir. 3. Verify the MD5SUM from the .info. A mismatch is a hard failure for that package (and blocks anything depending on it). 4. Run the .SlackBuild non-interactively. Capture full stdout+stderr to that package's log file. 5. installpkg the resulting package from /tmp (or $OUTPUT). 6. Record: SUCCESS / BUILD-FAILED / DOWNLOAD-FAILED / MD5-MISMATCH / INSTALL-FAILED / BLOCKED-BY-DEP / UNMET-DEP, plus elapsed build time. 7. If a package fails, mark every not-yet-built package that depends on it as BLOCKED-BY-DEP (do not attempt them) and continue with independent targets. The chroot must run the build NON-INTERACTIVELY (no dropping into a shell). Reuse the reference script's chroot/env/PS1 mounting approach but execute a command string instead of an interactive login shell. Preserve and propagate exit codes correctly. OVERLAY LIFECYCLE — THIS IS THE INTENDED DESIGN, NOT A QUESTION: The purpose of this tool is purely to verify that SlackBuilds BUILD cleanly against stable 15.0. I do NOT keep or redistribute the resulting packages for stable, so installed packages are throwaway. Therefore: - Use a FRESH, disposable overlay PER TARGET, destroyed after that target's build chain completes (success or failure). - Single-package mode: one overlay covers the whole dependency-tree-plus-target chain, then is torn down. - Category-folder mode: EACH target package gets its OWN fresh overlay against a pristine 15.0 base. A previous target's built/installed deps must NOT leak into the next target. This guarantees every target is tested against clean stable, which is the whole point. - --keep should suppress teardown ONLY for the final/most-recent overlay (or make its exact behavior clear in --help); by default everything is destroyed. Accepted tradeoff (document it, do not optimize it away now): shared dependencies will be rebuilt for every target that requires them, since each target starts from a clean base. This is correct for isolation. Leave a TODO marker for a future optional package-output cache (keep built .tgz outside the overlay, installpkg a cached dep when its SlackBuild + version are unchanged) so this optimization is on record but NOT implemented now. ================================================================================ ENVIRONMENT / BASE TREE (my actual setup — wire these as config vars) ================================================================================ DEPLOYMENT CONTEXT — read this carefully, it constrains the design: This tool runs INSIDE my Slackware64-CURRENT VM, the same VM where my SBo-danix SlackBuild repo lives and where I use slackrepo to build my redistributable -current packages. The SBo tree is therefore a LOCAL path in the VM and is the single source of truth. There is NO second copy of the repo and the tool must NOT clone, sync, or duplicate it. It reads the local tree in place. The Slackware 15.0 STABLE material (mirror) is provided over NFS, mounted into the VM. This keeps the big generic distro bits out of the VM's own storage. CRITICAL OVERLAYFS CONSTRAINT — do not get this wrong: The overlay LOWERDIR (SLACKWARE_BASE) must be a LOCAL filesystem path in the VM (ext4/xfs/etc), NOT the NFS mount. overlayfs over an NFS lowerdir is fragile and a known source of intermittent, hard-to-debug failures. Therefore: - NFS provides the 15.0 MIRROR only (a read-only package SOURCE). - SLACKWARE_BASE is a LOCAL directory in the VM, populated FROM that mirror with `installpkg -root`. The overlay lowerdir points at this local tree. Make this separation explicit in the config comments so the lowerdir is never accidentally pointed at the NFS path. Expose clear, well-commented config variables at the top: SLACKWARE_BASE -> LOCAL (non-NFS) read-only 15.0 base install tree; this is the overlay lowerdir. MUST be local. LOCAL_MIRROR_15 -> the NFS-mounted 15.0 mirror (package source for populating/patching the base). Read-only is fine. SBO_TREE_ROOTS -> one or more LOCAL SBo tree roots in the VM to resolve from (my SBo-danix checkout, plus optionally a local SBo 15.0 clone for upstream deps). In-place, never copied or synced. CHROOT_LOCATION -> where overlays are created (default /tmp), LOCAL. LOG_ROOT -> where persistent logs are written (see below). - Keep the base patched: reuse the reference script's logic that upgrades the base from the mirror's patches/ when the ChangeLog head differs. Point it at LOCAL_MIRROR_15 (the NFS mirror). The base tree it WRITES to is the local SLACKWARE_BASE. - STARTUP VALIDATION (fail fast, clear messages): * Verify SLACKWARE_BASE is a LOCAL path and looks like a real Slackware install (/var/log/packages present, key dirs exist). If it does not exist or is incomplete, FAIL with a precise, copy-pasteable hint for populating it from LOCAL_MIRROR_15 via `installpkg -root` (full package set, not minimal — a minimal base yields false "missing dependency" results that would not occur on a normal user's full Slackware install). * Verify LOCAL_MIRROR_15 is actually mounted/reachable (it is NFS); if the mount is absent, fail with a clear message rather than proceeding against an empty path. * Verify each SBO_TREE_ROOTS path exists locally. Do NOT attempt to auto-bootstrap the base unattended. DO NOT integrate with, wrap, or drive slackrepo. slackrepo is my separate release pipeline (clean reproducible builds, upstream revision tracking, slackpkg+ output for redistribution). THIS tool is only a disposable pre-flight "does it build on clean 15.0 stable" check. Keep them fully independent. ================================================================================ LOGGING (non-volatile — must survive overlay teardown) ================================================================================ - Logs MUST be written OUTSIDE the overlay so they persist after cleanup. - Per RUN: create a timestamped directory under LOG_ROOT, e.g. $LOG_ROOT/2026-06-22_14-30-05/ - Inside it: _.log per-package full build/install log summary.log plain-text recap of the whole run build-order.txt the resolved topological order actually used - The plain-text summary.log must be greppable and contain the same facts as the on-screen color summary (no color codes in the file). ================================================================================ END-OF-RUN COLOR SUMMARY (on screen) ================================================================================ Print a clear, color-coded recap to the terminal: - GREEN = success - RED = failed (with the failure category) - YELLOW = blocked-by-dep, unmet-dep, or skipped - Note packages carrying a %README% (so I remember to check manual steps). Include, per package: status, failure reason if any, and build time. End with totals: X succeeded, Y failed, Z blocked, total wall time, and the path to the run's log directory. Auto-disable color when stdout is not a TTY or when --no-color is passed. ================================================================================ SAFETY, CORRECTNESS, ROBUSTNESS ================================================================================ - Must run as root (overlay + chroot). Check EUID and exit cleanly if not. - Use `set -euo pipefail` thoughtfully, but DO NOT let one package's build failure kill the whole batch — isolate per-package execution so the run continues. A failed build is an expected, handled outcome, not a script crash. - Cleanup must be bulletproof and idempotent: trap EXIT/INT/TERM and unmount in the correct reverse order (pts, dev/proc/sys, resolv.conf, dbus machine-id, overlay last), exactly as the reference script does, even if the run aborts mid-way. Never leave dangling mounts or overlay dirs (unless --keep). Because overlays are created and destroyed PER TARGET, the teardown routine must be a reusable function called after each target, AND registered in the trap so an abort mid-target still unmounts cleanly. Track all active overlay mounts so the trap can unwind whichever one is live when an interrupt hits. - Be aware overlayfs has occasional sharp edges with some builds; if a build fails ONLY in the overlay, that is worth a comment in the code near the build step, but do not try to work around it speculatively. - X server access: default to NO X (these are headless batch builds). Only wire optional X passthrough behind a flag, and comment the xhost security caveat. - Quote variables, handle paths with spaces, use mktemp for temp dirs. - Comment generously. Put all user-tunable config in one clearly marked block at the top. ================================================================================ DELIVERABLES ================================================================================ 1. The new script (suggest name: sbo-batch-test). Single self-contained bash file, heavily commented. 2. A short README section (can be a comment block or separate .md) covering: prerequisites (the 15.0 base tree, the mirror, the SBo tree roots), how to populate SLACKWARE_BASE, and usage examples for both the single-package and category-folder modes, plus the dry-run. 3. Inline TODO markers for the deferred features (e.g. "all" mode, queue-file mode, -j parallelism) at the extension points. ================================================================================ WORKING STYLE I WANT FROM YOU ================================================================================ - ASK ME QUESTIONS before coding if anything is ambiguous — especially the dependency-resolution source-of-truth assumption above, the exact layout of my SBo tree, and whether my SlackBuilds follow stock SBo conventions. - Do NOT default to agreement. If any choice in this prompt is wrong, suboptimal, or fragile (e.g. overlay quirks, dep-resolution edge cases, the build-then-install-then-leave-installed question), tell me and propose a better alternative with reasoning. - Build incrementally: I'd rather review the dependency resolver and the mount/teardown core first, confirm they're solid, then layer on logging and the summary. A note on my conventions: when writing any prose, comments, README text, or commit messages, do NOT use the em dash character. Use commas or periods. ================================================================================ END OF PROMPT ================================================================================