aboutsummaryrefslogtreecommitdiffstats
path: root/claude-code-prompt-sbo-batch-tester.txt
blob: 7a2d0e5ee0ff960f740d35489d0ca5cb2e555620 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
================================================================================
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:
      <category>_<prog>.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
================================================================================