aboutsummaryrefslogtreecommitdiffstats
path: root/CLAUDE.md
blob: 1254ab1b00370ec30423e2f7b0cf5ca8994f38a6 (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
# CLAUDE.md

Working notes for Claude Code on this project. Read before editing.

## What this is

`sbo-batch-test`: a single self-contained bash script that batch-tests
SlackBuilds against a clean Slackware 15.0 overlay chroot. The user is an SBo
(SlackBuilds.org) maintainer on Slackware64-current who needs to verify builds
against 15.0 stable without booting a VM.

Full spec lives in `claude-code-prompt-sbo-batch-tester.txt`. Reference mount
machinery in `overlay-chroot.sh` (Jeremy Hansen / bassmadrigal). User-facing
docs in `README.md`.

## Conventions (the user cares about these)

- **No em dash character** in any prose, comments, README, or commit messages.
  Use commas or periods. This is a hard rule.
- This session runs with ponytail (laziest working solution) and caveman
  (terse replies) modes. Code stays normal; chat is terse.
- Build incrementally. The user wants to review the dep resolver and the
  mount/teardown core before trusting the rest. Do not balloon scope.
- Do NOT default to agreement. If a choice is fragile or wrong, say so and
  propose better with reasoning.

## Hard constraints (do not violate)

- **Resolution is LOCAL-tree-only.** Never add network/sbopkg resolution. The
  local SBo tree is the single source of truth (contains unpublished
  personal/pentesting packages). Settled, not open for revisiting.
- **overlay lowerdir must be LOCAL.** `SLACKWARE_BASE` is a local fs path.
  `LOCAL_MIRROR_15` is the NFS mountpoint, a package SOURCE only (content read
  via the derived `MIRROR_TREE`). overlayfs over NFS lowerdir is fragile. The
  script guards against pointing base under the mirror. The mirror fstab entry
  is `noauto`; the script checks `mountpoint -q` and auto-mounts (`mount
  $LOCAL_MIRROR_15`) if absent, left mounted after the run.
- **Do not wrap/drive slackrepo.** Separate pipeline, keep independent.
- **Shares host kernel.** No kernel-module testing claims.
- Runs as root only (overlay + chroot).
- Per-target disposable overlay: each category target tests against pristine
  15.0. Built packages are throwaway.

## Architecture (single file: sbo-batch-test)

Top-to-bottom layout:

1. **CONFIG block** - empty defaults plus a `source` of the external config
   file. Real values live OUTSIDE the script in `$SBO_BATCH_CONFIG` (default
   `~/.config/sbo-batch-tester/config`, i.e. `/root/.config/...` since it runs
   as root); `config.example` in the repo is the template. The block sets empty
   defaults (`SLACKWARE_BASE LOCAL_MIRROR_15 SBO_TREE_ROOTS`) plus
   `CHROOT_LOCATION=/tmp LOG_ROOT VERSION=15.0`, sources the config if present
   (NOT an error if missing, so the script stays sourceable by `test-logic.sh`),
   then derives `MIRROR_TREE`. `require_config` (called by `validate_env` and
   `init_base`) is what hard-fails a real run when the config is absent or has
   not set the required paths. `LOCAL_MIRROR_15` is the NFS mountpoint; the tree
   is one level down, `MIRROR_TREE="$LOCAL_MIRROR_15/slackware64-$VERSION"`
   (holds ChangeLog.txt, slackware64/, patches/). All mirror content reads use
   `MIRROR_TREE`; the mountpoint check, auto-mount, and the under-mirror guard
   use `LOCAL_MIRROR_15`.
2. **Globals / flags** - `USE_COLOR DRY_RUN WITH_X JOBS`, status maps
   (`ST_STATUS ST_REASON ST_TIME ST_README`), `ACTIVE_MOUNTS[]`.
3. **usage / init_color / parse_args / validate_env** - fail-fast startup
   checks with copy-pasteable hints.
4. **init_base** - `--init-base` mode only. First-time populate: `installpkg
   --root` the full `slackware64/*/*.t?z` set into `SLACKWARE_BASE`, seed the
   `last-base-update` marker, exit. Runs its own checks (root, mirror mounted
   /auto-mount, ChangeLog.txt present, not under mirror) since the base does not
   exist yet; refuses to clobber a populated base. Wired in `main` before
   `validate_env`, exits 0. installpkg/upgradepkg run with `--terse`.
   **update_base** - patches local base from mirror's `patches/packages/` when
   ChangeLog head differs (reused from reference script).
5. **SBo tree lookup** - `find_slackbuild_dir`, `category_of`, `pkg_key`,
   `read_requires`.
6. **Dependency resolution** - `resolve_target` -> `_resolve_visit` (DFS topo
   sort + cycle detection). Outputs `RESOLVED_ORDER[]`, records `UNMET[]`,
   `CYCLES[]`, `HAS_README[]`. `installed_in_base` checks base package db.
7. **Overlay lifecycle** - `setup_overlay` (echoes tmpdir, mounts overlay +
   binds), `teardown_overlay` (idempotent, correct reverse order), `cleanup_trap`
   (EXIT/INT/TERM, unwinds all live overlays).
8. **build_one** - copies SlackBuild into overlay, runs download/md5/build/
   installpkg INSIDE the chroot non-interactively via heredoc, reads back a
   status token file, sets status maps. Logs resolved .info env up front and
   the installed file list (from /var/log/packages) after installpkg, so the
   overlay is fully disposable.
9. **run_target** - fresh overlay per target, builds resolved chain in order,
   marks `BLOCKED-BY-DEP` on dependents of failures, tears down.
10. **print_summary** - color screen recap + plain `summary.log`.
11. **main** - parse, validate, make `RUN_DIR`, update base, collect targets
    (single-package or category-folder), run each.

## Teardown order (do not reorder)

pts -> dev/proc/sys -> resolv.conf -> dbus machine-id -> overlay last.
Matches the reference script. Idempotent (mountpoint-guarded), trap-registered
so a mid-target abort still unwinds. `ACTIVE_MOUNTS[]` tracks live overlays.

## Status values

`SUCCESS DOWNLOAD-FAILED MD5-MISMATCH BUILD-FAILED INSTALL-FAILED
BLOCKED-BY-DEP UNMET-DEP`. `%README%` recorded separately as a reminder flag,
not a status.

## What is verified vs not

- **Verified by self-check** (`test-logic.sh` in repo, `bash test-logic.sh`, no
  VM needed): topo order, `%README%` recording, unmet-dep, cycle detection, and
  BLOCKED-BY-DEP propagation (`depends_on_failed`, including the transitive
  one-hop cascade). The check builds a fake SBo tree and sources the script with
  config overridden AFTER sourcing (sourcing re-runs the CONFIG block, which
  resets the vars to empty defaults and may source the external config, so test
  vars must be set after the `source`). The test runs as a normal user, so
  `~/.config/sbo-batch-tester/config` usually does not exist and is not sourced;
  even if it did, the post-source overrides win. Gotchas baked in: do not name the dead
  list `failed` (collides with `depends_on_failed`'s `local -n failed`), and
  `ok`/`bad` must `return 0` (`((x++))` returns nonzero when x was 0).
- **Verified on the build system**: `--init-base` populate ran clean against
  the real mirror (mountpoint check, auto-mount of the noauto NFS entry,
  `MIRROR_TREE` derivation, external config sourcing, full installpkg --terse
  set). The external-config split (`require_config`, missing/incomplete errors)
  was checked in isolation too.
- **NOT runnable-tested** (needs a real build run): overlay mounts, chroot
  build flow, base patching (update_base), per-package installpkg. Logic mirrors
  the reference script.

## Known shortcuts (ponytail: comments in source)

- `depends_on_failed`: direct-REQUIRES check only. Transitive blocking still
  works because the loop runs in topo order, so a failure propagates one hop per
  package.

## Open items / TODO

- **`--keep` removed (resolved).** No keep-overlay option. Overlay is always
  torn down. Rationale: per-package logs now capture full build/install output,
  resolved `.info` env, and the installed file list, so the overlay holds
  nothing worth retaining. Do not re-add `--keep` without a reason logs cannot
  cover.
- **Package-output cache** (deferred, user wants it next): keep built `.tgz`
  outside the overlay, `installpkg` a cached dep instead of rebuilding. Fixes
  the "shared deps rebuilt per target" cost in category mode. Likely shape: a
  per-run stash in `$RUN_DIR/pkgcache` keyed `prog-version`, reused across
  targets within one run. NOT implemented yet.
- **"all" mode**: build every package across all SBo roots. Extension point in
  `main` where `targets` is populated. TODO marker in source.
- **queue/list-file mode**: build a named list. Same extension point.
- **`-j` parallelism**: flag parsed, currently no-op. TODO marker in source.

## How to run the self-check

```sh
bash test-logic.sh
```

Covers resolution + BLOCKED-BY-DEP. Extend it (not /tmp scratch files) when
adding logic. Anything VM-dependent (overlay, chroot, installpkg) is out of its
reach by design.