mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 21:27:02 +01:00
Record the /usr/bin bind limit; retarget the brief at the pacman wrapper
`--bind-abs /usr/bin` overlays the directory bwrap needs to exec anything, so the run dies with `execvp bash: No such file or directory` before the script starts. A target whose last act replaces a binary there traces fine with every other path bound and stops at that line with exit 1 on EPERM — usable as a baseline (it is deterministic across runs), but blind to statements at or after the failure, which is a constraint on where the seams can go. Also noted: the absolute-path scanner misses a literal `ln -sf` target, because it follows variables into `cat >`/`cp`. The brief now targets install_pacman_wrapper.sh (316) with its baseline already captured: 16 file hashes, one stubbed call, exit 1 at line 304. Checked ahead of time that its source.sha256 drift manifest hashes only the seven copied source files, not the installer, so a split leaves it stable. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
This commit is contained in:
parent
26965bad32
commit
32a4d9c70c
@ -1,4 +1,4 @@
|
||||
# Next session: split `install_usage_monitoring.sh`
|
||||
# Next session: split `install_pacman_wrapper.sh`
|
||||
|
||||
> **Paste this whole file into a fresh Claude session opened in `~/testsAndMisc`.**
|
||||
> It is self-contained. Do not go looking for the previous session's context.
|
||||
@ -6,237 +6,174 @@
|
||||
## The one job
|
||||
|
||||
Split
|
||||
`linux_configuration/scripts/periodic_background/system-maintenance/bin/install_usage_monitoring.sh`
|
||||
(290 lines, over the 250-line cap by 40) into files that are each under the
|
||||
`linux_configuration/scripts/periodic_background/digital_wellbeing/pacman/install_pacman_wrapper.sh`
|
||||
(316 lines, over the 250-line cap by 66) into files that are each under the
|
||||
cap, and **prove by execution** that it still does exactly the same thing.
|
||||
|
||||
This is a split, not a tooling task. The harness you need already exists and is
|
||||
already proven against this exact file — use it, don't rebuild it.
|
||||
The harness already exists and has already been run against this exact file —
|
||||
its baseline is captured and its one blind spot is mapped below. Use it, don't
|
||||
rebuild it.
|
||||
|
||||
Then, if there is room left in the session, take the next target using the same
|
||||
method (see "If there is time" at the end).
|
||||
## What landed last session (do not redo)
|
||||
|
||||
## Why this file, and why now
|
||||
`install_usage_monitoring.sh` (290 lines) is done, committed and pushed as
|
||||
`26965ba`: a 53-line entry plus five libs in a sibling `lib/`, with an empty
|
||||
before/after trace diff including all five generated-file hashes. That split is
|
||||
the worked example — read it before starting this one, the shape transfers.
|
||||
|
||||
57 files remain over the cap. Until last session, six installer scripts could
|
||||
not be executed at all to verify a split: shell redirections (`cat > …`) are
|
||||
bash builtins, so no `PATH` stub can intercept them — stub `cp`/`chmod` and the
|
||||
trace comes back nearly empty, don't and the run rewrites the live system.
|
||||
Two things it discovered that this file inherits:
|
||||
|
||||
`meta/scripts/trace_shell_split.sh --prefix` fixed that. This file is the
|
||||
smallest of the newly-unblocked set (over by only 40) and its trace is
|
||||
**deterministic across runs**, so a before/after diff is a real proof rather
|
||||
than a judgement call. It is the cheapest genuine win available.
|
||||
- The pre-commit hook runs **`shfmt -w` on every staged shell file** and
|
||||
re-stages it. It rewrites `cat > "x" << 'EOF'` to `cat >"x" <<'EOF'`. If any
|
||||
test greps a script's source text for a redirection, that rewrite silently
|
||||
breaks extraction. Run `shfmt -w` on your files yourself, then re-verify, so
|
||||
the state you tested is the state that gets committed.
|
||||
- Repo-wide `jscpd` currently reports **2.51% (over the 2% gate)** from the
|
||||
working tree, but every clone above the HEAD baseline is vendored
|
||||
`.venv`/`.ci-mirror-venv` site-packages (`tqdm/completion.sh`,
|
||||
`virtualenv/activate.sh`). Measured at HEAD in a clean worktree it is 1.47%
|
||||
with 27 clones, and the committed hook run passed. Don't chase it, and don't
|
||||
"fix" it by touching vendored files.
|
||||
|
||||
## The baseline you must reproduce, byte for byte
|
||||
## The baseline you must reproduce
|
||||
|
||||
Captured on 2026-08-16 at commit `19e652d`. Re-capture it yourself with the
|
||||
procedure below rather than trusting this paste — but if your post-split trace
|
||||
differs from this in any line, you have broken something:
|
||||
|
||||
```
|
||||
=== exit status: 0
|
||||
=== mutating calls (stubbed)
|
||||
sudo pacman -S --needed --noconfirm atop nvtop netdata xclip
|
||||
systemctl list-unit-files atop.service
|
||||
sudo systemctl enable --now atop.service
|
||||
systemctl list-unit-files atop-rotate.timer
|
||||
sudo systemctl enable --now atop-rotate.timer
|
||||
systemctl list-unit-files netdata.service
|
||||
sudo systemctl enable --now netdata.service
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable --now nvidia-pmon.service
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable --now usage-report-catchup.timer
|
||||
=== files written (prefix)
|
||||
.config/systemd/user/nvidia-pmon.service size=199 sha=af8da89074b49c3f
|
||||
.config/systemd/user/usage-report-catchup.service size=159 sha=bd685190626f72cb
|
||||
.config/systemd/user/usage-report-catchup.timer size=206 sha=020effbe805f4ee3
|
||||
.local/bin/nvidia-pmon-logger.sh size=972 sha=f307d0d3fe5f5e7f
|
||||
.local/bin/usage-report-catchup.sh size=757 sha=9f4803ab157c5527
|
||||
=== stdout
|
||||
=== stderr
|
||||
[install-usage] detected distro family: arch (Arch Linux)
|
||||
[install-usage] installing: atop nvtop netdata xclip
|
||||
[install-usage] enabling atop.service
|
||||
[install-usage] enabling atop-rotate.timer
|
||||
[install-usage] enabling netdata.service
|
||||
[install-usage] setting up nvidia-pmon user service
|
||||
[install-usage] usage reports will be generated hourly in @PREFIX@/.local/share/usage-reports/
|
||||
[install-usage] done. Wait for the first atop sample (default 10 min), then run:
|
||||
[install-usage] python /home/kuhy/testsAndMisc/linux_configuration/scripts/periodic_background/system-maintenance/bin/usage_report.py
|
||||
```
|
||||
|
||||
**The five content hashes are the real assertion.** The stubbed-call list only
|
||||
proves the same binaries were invoked; the hashes prove every generated file
|
||||
came out identical. A split that drops a heredoc shows up here and nowhere
|
||||
else.
|
||||
|
||||
### How to capture and compare — capture the baseline IN PLACE
|
||||
|
||||
**Do not trace the baseline from a detached worktree.** The obvious workflow is
|
||||
wrong for this file and it was measured: tracing
|
||||
`/tmp/basewt/…/install_usage_monitoring.sh` makes `REPO_DIR` resolve to
|
||||
`/tmp/basewt`, that path is interpolated into the generated
|
||||
`usage-report-catchup.sh`, and you get a 2-line diff (`size=745 sha=d15c970e…`
|
||||
instead of `size=757 sha=9f4803ab…`, plus the final stdout line) that looks
|
||||
exactly like a broken split but is pure harness artefact. Normalising the trace
|
||||
text does **not** fix it — the repo path is inside the hashed file content, not
|
||||
just the trace.
|
||||
|
||||
Capture the baseline at the real repo path instead, by restoring `HEAD`'s
|
||||
version in place for one run:
|
||||
Captured at commit `26965ba`. **Verified deterministic**: two consecutive runs
|
||||
at HEAD produced byte-identical traces, so a before/after diff is real proof.
|
||||
|
||||
```bash
|
||||
F=linux_configuration/scripts/periodic_background/system-maintenance/bin/install_usage_monitoring.sh
|
||||
F=linux_configuration/scripts/periodic_background/digital_wellbeing/pacman/install_pacman_wrapper.sh
|
||||
|
||||
cp "$F" /tmp/split_version.sh # keep your split work
|
||||
git show HEAD:"$F" > "$F" # restore the pre-split file in place
|
||||
meta/scripts/trace_shell_split.sh "$F" --prefix /tmp/pfx-before --out /tmp/before.txt
|
||||
|
||||
cp /tmp/split_version.sh "$F" # put your split back
|
||||
meta/scripts/trace_shell_split.sh "$F" --prefix /tmp/pfx-after --out /tmp/after.txt
|
||||
|
||||
diff /tmp/before.txt /tmp/after.txt # must be empty
|
||||
git status --porcelain "$F" # sanity: your split is back in place
|
||||
rm -rf /tmp/pfx-before # fresh, NOT emptied — the harness refuses a non-empty prefix
|
||||
meta/scripts/trace_shell_split.sh "$F" --prefix /tmp/pfx-before \
|
||||
--bind-abs /usr/local/bin \
|
||||
--bind-abs /usr/local/share/digital_wellbeing \
|
||||
--bind-abs /usr/local/share/digital_wellbeing/virtualbox \
|
||||
--bind-abs /var/lib/pacman-wrapper \
|
||||
--out /tmp/before.txt
|
||||
```
|
||||
|
||||
Verified pre-split: this produces an empty diff, so any diff you see after
|
||||
splitting is real signal. If your split moved code into new lib files, restore
|
||||
those too (or `git stash` is blocked — use `git show HEAD:<path>` per file).
|
||||
|
||||
**Each run needs its own EMPTY prefix.** Reusing one leaves the first run's
|
||||
files behind, so the second manifest reports writes that never happened and a
|
||||
dropped write stops showing up at all. The harness refuses a non-empty prefix,
|
||||
so you will get an error rather than a false pass — don't work around it by
|
||||
deleting the directory contents and reusing the path out of habit.
|
||||
|
||||
## Four hazards specific to THIS file
|
||||
|
||||
Each of these was measured. Do not rediscover them.
|
||||
|
||||
### 1. An existing test greps the installer's SOURCE TEXT
|
||||
|
||||
`linux_configuration/tests/test_usage_monitoring_installer_efficiency.sh`
|
||||
extracts the pmon-logger heredoc out of the installer with an awk pattern
|
||||
anchored on this exact line:
|
||||
Expect **exit status 1** (see the blind spot below — this is correct, not a
|
||||
failure), one stubbed call (`npm install --prefix …`), and 16 files written:
|
||||
|
||||
```
|
||||
cat > "$HOME/.local/bin/nvidia-pmon-logger.sh" << 'SCRIPT'
|
||||
abs/usr/local/bin/heavy_job_lock.sh size=7221 sha=3961b14e6a6a8b86
|
||||
abs/usr/local/bin/makepkg_capped size=2037 sha=3acf1189e93e5771
|
||||
abs/usr/local/bin/mkpkg size=178 sha=da4a2fa3e8f5b6ab
|
||||
abs/usr/local/bin/pacman_blocked_keywords.txt size=1042 sha=7bd951741c649b60
|
||||
abs/usr/local/bin/pacman_greylist.txt size=174 sha=2dc47dd4a25d6aca
|
||||
abs/usr/local/bin/pacman_lock_lib.sh size=6581 sha=147ea7a163000f82
|
||||
abs/usr/local/bin/pacman_whitelist.txt size=6079 sha=cfec8efc4a2330c1
|
||||
abs/usr/local/bin/pacman_wrapper size=29410 sha=548fc2b53ee4cea6
|
||||
abs/usr/local/bin/words.txt size=1375483 sha=f5c9d52b244f9973
|
||||
abs/usr/local/share/digital_wellbeing/install_leechblock.sh size=15965 sha=e4ec4b37fd9113a3
|
||||
abs/usr/local/share/digital_wellbeing/leechblock_defaults.json size=51084 sha=ca068b74282921c6
|
||||
abs/usr/local/share/digital_wellbeing/package.json size=258 sha=618fa688d2edfa4f
|
||||
abs/usr/local/share/digital_wellbeing/seed_leechblock_storage.js size=4176 sha=1611cb17124fd388
|
||||
abs/usr/local/share/digital_wellbeing/virtualbox/enforce_vbox_hosts.sh size=12601 sha=ab039aedc3cd84cd
|
||||
abs/var/lib/pacman-wrapper/policy.sha256 size=412 sha=0aa8d95524660324
|
||||
abs/var/lib/pacman-wrapper/source.sha256 size=1374 sha=4c928a499d437070
|
||||
```
|
||||
|
||||
It then asserts five properties of the extracted template (no `read -t`
|
||||
busy-loop, sleeps to the day boundary, blocks on `wait`, uses the `printf`
|
||||
date builtin, no external `date`). **If you move that heredoc into a lib file,
|
||||
this test fails with `could not extract nvidia-pmon-logger template`** — and
|
||||
it is not in the pre-commit set, so nothing will tell you.
|
||||
The last stderr line is
|
||||
`ln: failed to create symbolic link '/usr/bin/pacman': Permission denied`.
|
||||
|
||||
Run it before and after, every time:
|
||||
Capture the baseline at HEAD **before editing anything**, then diff your split
|
||||
against it. Unlike last file, a detached worktree is fine here — nothing
|
||||
interpolates the repo path into a generated artifact (verified: the drift
|
||||
manifest hashes source files by `readlink -f`, and those hashes are of file
|
||||
_contents_, not paths).
|
||||
|
||||
## The one blind spot — this is the whole design constraint
|
||||
|
||||
`--bind-abs /usr/bin` **cannot be used**: it mounts an empty overlay over the
|
||||
directory the sandbox needs to exec anything, and the run dies with
|
||||
`bwrap: execvp bash: No such file or directory` before reaching the script.
|
||||
Measured last session; it is a hard limit of the harness.
|
||||
|
||||
So the trace reaches **line 304** (`ln -sf "$WRAPPER_DEST" /usr/bin/pacman`),
|
||||
hits EPERM, and exits 1. Lines 304 and 306 (the final `echo`) are the only
|
||||
statements that never execute — everything before them is covered, 16 files
|
||||
written and 19 stdout lines deep.
|
||||
|
||||
**Therefore: keep lines 304–316 in the entry script.** Anything you move into a
|
||||
lib gets proven by the trace; anything at or after 304 does not, and a broken
|
||||
split there would diff clean. This is a constraint on where the seams go, not a
|
||||
reason to skip the file.
|
||||
|
||||
Note the absolute-path scanner does **not** list `/usr/bin` when it refuses to
|
||||
run — it follows variables into `cat >`/`cp` and misses the literal `ln -sf`
|
||||
target. Don't read its list as complete.
|
||||
|
||||
## Hazards specific to THIS file
|
||||
|
||||
### 1. It self-sudos at line 9
|
||||
|
||||
```bash
|
||||
bash linux_configuration/tests/test_usage_monitoring_installer_efficiency.sh
|
||||
# expect: "Usage monitoring installer efficiency tests passed."
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
sudo "$0" "$@"
|
||||
exit $?
|
||||
fi
|
||||
```
|
||||
|
||||
Either keep that heredoc in a file the test still reads, or update the test's
|
||||
`INSTALLER` path in the same commit. Deciding which is part of the job; don't
|
||||
leave it broken and don't weaken the assertions.
|
||||
Under `--bind-abs` the run is already uid 0 (bwrap `--unshare-user --uid 0`),
|
||||
so this branch is skipped and the script proceeds for real — that is why the
|
||||
trace is 16 files deep rather than the three-line `require_root` truncation.
|
||||
If you move this block, `$0` must still be the entry point.
|
||||
|
||||
### 2. `REPO_DIR` is computed by walking up five levels from `$0`
|
||||
### 2. `source.sha256` is a drift manifest — but a split does not disturb it
|
||||
|
||||
```bash
|
||||
REPO_DIR="$(dirname "$(readlink -f "$0")")/../../../../.."
|
||||
```
|
||||
Line ~247 hashes seven **source** files (`WRAPPER_SOURCE`, `LOCK_LIB_SOURCE`,
|
||||
`BLOCKED_SOURCE`, `GREYLIST_SOURCE`, `MAKEPKG_CAPPED_SOURCE`, `MKPKG_SOURCE`,
|
||||
`WHITELIST_SOURCE`) plus the installed lock lib. Checked: it does **not** hash
|
||||
the installer itself, and there is no glob that would pick up a new `lib/`.
|
||||
So `sha=4c928a499d437070` should stay put across a split — if it moves, you
|
||||
changed one of those seven copied files, which is a real regression.
|
||||
|
||||
From `…/system-maintenance/bin/` that resolves to `/home/kuhy/testsAndMisc`.
|
||||
This value is **interpolated into the generated catch-up script**, so if a lib
|
||||
at a different directory depth recomputes it, the generated file silently
|
||||
points at the wrong repo — and the trace still exits 0. If the code that uses
|
||||
`REPO_DIR` moves, pass the value in rather than recomputing it, and check the
|
||||
`usage-report-catchup.sh` hash (`9f4803ab157c5527`) is unchanged.
|
||||
`check_and_enable_services.sh` replays this manifest with `sha256sum -c` from
|
||||
systemd with `cwd=/`, which is why the entries must be absolute
|
||||
(`readlink -f`). Don't make those paths relative while tidying.
|
||||
|
||||
Note `$0` in a sourced lib is the _entry point_, not the lib — which is what
|
||||
makes this survivable if you pass the value, and silently wrong if you don't.
|
||||
### 3. `chattr +i` / immutability
|
||||
|
||||
This is not theoretical: it already broke the _verification procedure_ for this
|
||||
file (see "capture the baseline IN PLACE" above), producing a convincing
|
||||
2-line diff out of nothing but a changed repo root. Treat any diff in
|
||||
`usage-report-catchup.sh`'s hash as a `REPO_DIR` question first.
|
||||
The script makes policy files immutable and has unlock/relock helpers
|
||||
(`is_immutable_file`, `unlock_immutable_file_if_needed`,
|
||||
`relock_files_on_exit`, lines 58–84) wired to a trap. Inside the sandbox these
|
||||
warn ("Could not make integrity file immutable") and continue — that warning is
|
||||
in the baseline and is expected. If you move the trap or the helpers, check the
|
||||
trap still fires from the entry script.
|
||||
|
||||
### 3. The final stdout line contains the script's own absolute path
|
||||
### 4. It writes a _live_ system when run for real
|
||||
|
||||
```
|
||||
[install-usage] python /home/kuhy/…/bin/usage_report.py
|
||||
```
|
||||
|
||||
It is built from `REPO_DIR`/`$0`. It is in the trace, so a change here fails
|
||||
the diff loudly — good. Just don't "fix" it into a relative path while
|
||||
splitting; that is a behaviour change disguised as tidying.
|
||||
|
||||
### 4. Line 222 is an UNQUOTED heredoc
|
||||
|
||||
`cat > "$HOME/.local/bin/usage-report-catchup.sh" << SCRIPT` — no quotes on
|
||||
`SCRIPT`, so `$HOME` and `$REPO_DIR` interpolate at write time, while `\$REPO`
|
||||
and `\$OUT_DIR` stay literal. The escaping inside it is load-bearing. If you
|
||||
move this block, move it verbatim; a single unescaped `$` changes the
|
||||
generated file and the hash will catch you.
|
||||
|
||||
## The seams (already mapped — verify, don't re-derive)
|
||||
|
||||
The file is banner-sectioned, so the seams are pre-marked:
|
||||
|
||||
| Lines | Section | Notes |
|
||||
| ------- | ---------------------------------------------------------- | ---------------------------------- |
|
||||
| 1–24 | preamble, `log()`, `die()` | shared by everything |
|
||||
| 25–55 | distro detection → `FAMILY` | `FAMILY` crosses into packages |
|
||||
| 56–120 | package names, `pkg_name`, `clipboard_pkg`, resolve `pkgs` | `FAMILY` in, `pkgs` out |
|
||||
| 121–136 | `enable_unit`, system services | uses `pkgs` |
|
||||
| 137–214 | NVIDIA pmon logger (guarded) | **holds the heredoc test 1 greps** |
|
||||
| 216–290 | usage-report catch-up timer | `REPO_DIR`, unquoted heredoc |
|
||||
|
||||
State crossing any seam: `FAMILY`, `pkgs`, `clip`, `unit_dir`, `REPO_DIR`.
|
||||
Five globals — few enough that this is a genuinely tractable split, unlike the
|
||||
named blockers in `refactor_claude_todo_resume.md`.
|
||||
|
||||
`nvidia-smi` IS present on this machine, so the 137–214 branch really executes
|
||||
in the trace. That is why the baseline has `nvidia-pmon.service` in it. Don't
|
||||
assume the guarded block is untested — it is the opposite.
|
||||
|
||||
There is **no `lib/` directory** in `…/system-maintenance/bin/` yet. Elsewhere
|
||||
in the repo the convention is a sibling `lib/` holding sourced `.sh` files with
|
||||
a shebang and the executable bit (see `meta/scripts/lib/`). Follow it.
|
||||
`/usr/bin/pacman` is currently a symlink to `/usr/local/bin/pacman_wrapper`.
|
||||
The sandbox protects this (the `ln` is denied — that denial is the positive
|
||||
proof the bind worked), but **never run this script outside the harness** to
|
||||
"check something".
|
||||
|
||||
## Rules that will bite you
|
||||
|
||||
- **`SCRIPT_DIR` must resolve symlinks**:
|
||||
`SCRIPT_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"`. Plain
|
||||
`dirname` is string manipulation; adding a `source` line to a script reached
|
||||
through a symlink turns a latent wrong value into an instant `set -e` exit.
|
||||
This has already broken `lint_python.sh` once.
|
||||
`SCRIPT_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"`. The
|
||||
`SOURCE_*` vars are built from `dirname "$0"` and the code comments say so
|
||||
explicitly — if you move that computation into a lib, pass the value in
|
||||
rather than recomputing it at a different directory depth.
|
||||
- **Wrapping top-level code in a function changes what `set -e` sees.** A bare
|
||||
`((x > 0)) && FLAG=true` as the last statement of a function becomes its
|
||||
return value; if false, the script dies. Check the last statement of every
|
||||
function you create; append `|| true` if it is a bare conditional.
|
||||
- **Don't make a clean file `shfmt`-dirty.** This file is _already_
|
||||
`shfmt -d` dirty, so don't let that mislead you: the rule is not to make it
|
||||
**worse**, and any NEW lib file you create must be clean. `shellcheck` on the
|
||||
original is currently CLEAN — keep it that way.
|
||||
- **No suppressions.** No `# shellcheck disable`, no per-file ignores. Fix the
|
||||
finding or restructure. If a lint fix seems to require touching behaviour,
|
||||
stop and re-read — last session a lint fix silently neutered a regression
|
||||
fixture by making an added `echo` the function's last statement, turning
|
||||
exit 1 into exit 0 while still "passing".
|
||||
`((x > 0)) && FLAG=true` as a function's last statement becomes its return
|
||||
value; if false, the script dies. Check the last statement of every function
|
||||
you create; append `|| true` if it is a bare conditional.
|
||||
- **No suppressions.** No `# shellcheck disable`, no per-file ignores.
|
||||
- New `.sh` files need the executable bit, a `#!/bin/bash` shebang, and **no
|
||||
`set -euo pipefail`** (a sourced lib inherits the caller's strict mode).
|
||||
Convention: a sibling `lib/` directory; see the `bin/lib/` that landed in
|
||||
`26965ba`.
|
||||
- Every commit touching code needs an evidence JSON in
|
||||
`docs/superpowers/evidence/`; **≥4 staged code files** additionally needs a
|
||||
fresh `docs/superpowers/contracts/*.json`
|
||||
(`python3 meta/scripts/validate_contract.py <file>`).
|
||||
- New `.sh` files need the executable bit or the commit hook rejects them.
|
||||
fresh `docs/superpowers/contracts/*.json`. Validate both with
|
||||
`python3 meta/scripts/validate_contract.py` /
|
||||
`meta/scripts/validate_evidence.py` before committing.
|
||||
- Markdown needs `npx prettier --write` — prettier is pre-push only, so a file
|
||||
that passes every per-commit gate can still fail the push.
|
||||
- Work directly on `main`; commit and push. `git stash` and branch creation are
|
||||
blocked by hooks. `git worktree add --detach` is the usual way to get a clean
|
||||
baseline — but **not for this file's trace**; see "capture the baseline IN
|
||||
PLACE" above for why, and use `git show HEAD:<path>` instead.
|
||||
blocked by hooks.
|
||||
- `git push` runs `ci-mirror` (clean-venv install + `pre-commit --all-files` +
|
||||
pytest) and takes minutes. Never edit files while a push is running.
|
||||
- **Do not wire the file-length pre-commit hook.** It must land last, only once
|
||||
@ -246,26 +183,23 @@ a shebang and the executable bit (see `meta/scripts/lib/`). Follow it.
|
||||
## Read these first
|
||||
|
||||
1. `docs/shell-split-verification.md` — how a green split is still broken. The
|
||||
`--prefix` section covers the manifest, the empty-prefix rule, and the
|
||||
`require_root` truncation trap.
|
||||
`--prefix` section covers the manifest, the empty-prefix rule, the
|
||||
`require_root` truncation trap, and the `/usr/bin` limit above.
|
||||
2. `docs/shell-split-recipes.md` — how to actually make a split.
|
||||
3. `meta/scripts/trace_shell_split.sh --help` — the harness.
|
||||
3. The `26965ba` diff — the worked example of the entry+lib shape.
|
||||
|
||||
## Definition of done
|
||||
|
||||
- `install_usage_monitoring.sh` and every file split out of it are **under 250
|
||||
- `install_pacman_wrapper.sh` and every file split out of it are **under 250
|
||||
lines** (`bash ~/utils/scripts/check_file_length.sh --all` no longer lists
|
||||
any of them).
|
||||
- `diff /tmp/before.txt /tmp/after.txt` is **empty** — same exit status, same
|
||||
stubbed calls in the same order, and all five content hashes identical.
|
||||
- `bash linux_configuration/tests/test_usage_monitoring_installer_efficiency.sh`
|
||||
still prints "Usage monitoring installer efficiency tests passed."
|
||||
- `shellcheck` clean on every touched file; no new `shfmt` damage; zero
|
||||
- `diff /tmp/before.txt /tmp/after.txt` is **empty** — same exit status (1),
|
||||
same stubbed call, and all 16 content hashes identical.
|
||||
- Nothing you moved into a lib sits at or after line 304.
|
||||
- `shellcheck` clean and `shfmt` clean on every touched file; zero
|
||||
suppressions.
|
||||
- `~/.config/systemd/user/` and `~/.local/bin/` untouched by the verification
|
||||
runs — confirm by `ls -la` before and after, and check the mtimes of
|
||||
`nvidia-pmon-logger.sh` and `usage-report-catchup.sh` still read **May 2026**.
|
||||
If either shows today's date, a run escaped the prefix; stop and say so.
|
||||
- `/usr/bin/pacman` still symlinks to `/usr/local/bin/pacman_wrapper` and
|
||||
`pacman --version` still works, after every verification run.
|
||||
- Committed and pushed, with evidence (and a contract if ≥4 code files).
|
||||
|
||||
## If there is time
|
||||
@ -277,12 +211,12 @@ count — a big file you can run beats a small one you cannot:
|
||||
bash ~/utils/scripts/check_file_length.sh --all
|
||||
```
|
||||
|
||||
Newly unblocked by `--prefix`, in ascending difficulty:
|
||||
`install_pacman_wrapper.sh` (316), `nvidia_troubleshoot.sh` (336, needs
|
||||
`--bind-abs /etc/modprobe.d --bind-abs /etc/X11 --bind-abs /etc/profile`),
|
||||
`setup_thorium_startup.sh` (443), `install_leechblock.sh` (485 — confirm where
|
||||
`INSTALL_ROOT`/`VERSION_DIR` point BEFORE the first run, it uses
|
||||
`rsync -a --delete`).
|
||||
Remaining newly-unblocked targets, ascending difficulty: `nvidia_troubleshoot.sh`
|
||||
(336, needs `--bind-abs /etc/modprobe.d --bind-abs /etc/X11 --bind-abs
|
||||
/etc/profile`; it embeds `$(date)` in its config so that one hash varies every
|
||||
run — compare file list and sizes instead), `setup_thorium_startup.sh` (443),
|
||||
`install_leechblock.sh` (485 — confirm where `INSTALL_ROOT`/`VERSION_DIR` point
|
||||
BEFORE the first run, it uses `rsync -a --delete`).
|
||||
|
||||
**Still out of scope:** `block_compulsive_opening.sh` (705) — `install_all`
|
||||
copies the running script into `/usr/local/bin`, and an entry+lib shape ships
|
||||
|
||||
@ -128,8 +128,17 @@ the `dropped_write_{before,after}.sh` fixture pair: with the manifest the lost
|
||||
`.timer` is a one-line diff; with the section stripped the two traces are
|
||||
byte-identical, i.e. the pre-`--prefix` harness passed that broken split.
|
||||
|
||||
Four traps, each of which cost a debugging round:
|
||||
Five traps, each of which cost a debugging round:
|
||||
|
||||
- **`/usr/bin` cannot be bound at all.** `--bind-abs /usr/bin` overlays the
|
||||
directory the sandbox needs to exec anything; the run dies with
|
||||
`bwrap: execvp bash: No such file or directory`. So a script whose last act
|
||||
replaces a binary there (`install_pacman_wrapper.sh:304`,
|
||||
`ln -sf … /usr/bin/pacman`) traces with everything else bound and **stops at
|
||||
that line with exit 1** on EPERM. That baseline is stable across runs, but
|
||||
proves nothing at or after the failing line — keep those statements in the
|
||||
entry script. The scanner does not list `/usr/bin`: it follows variables into
|
||||
`cat >`/`cp` and misses a literal `ln -sf` target.
|
||||
- **Bind leaf directories, never `/etc`.** Binding `/etc` wholesale shadows
|
||||
`/etc/passwd` and `/etc/os-release`. Measured: `$SUDO_USER` lookup collapsed
|
||||
to `/home//pyroveil`, `/etc/profile` became "No such file or directory", and
|
||||
|
||||
Loading…
Reference in New Issue
Block a user