Three self-contained apps move to their own public repos with full
history (8, 14 and 30 commits, each matching the monorepo count):
github.com/kuhyx/reverse-survivors
github.com/kuhyx/kcd2-dice-solver (cloned to ~/kcd2-dice-solver)
github.com/kuhyx/focus-owner
Each gained a CI workflow. Only reverse_survivors had one here; the other
two were never gated by anything, which is part of why they no longer
belong in a repo whose CI is shared.
What stayed: setup_kcd2_dice_solver.sh, which deploys the solver rather
than being part of it. It now builds from ~/kcd2-dice-solver, and the
post-commit hook it generates drops its `git diff -- kcd2_dice_solver/`
filter -- in a standalone repo every commit is solver code, so the old
filter could never match again.
focus_owner's two references to python_pkg.focus_policy now name the
phone-focus-mode repo, where that generator is headed.
Running the live kcd2 unit -- rather than reading it -- found three real
breakages that no amount of grepping would have: pnpm ignoring the
package.json "pnpm" field, pnpm refusing to purge node_modules without a
TTY, and the Docker container still bind-mounting the deleted monorepo
path. All three are fixed; the unit exits 0 and
https://dice.kuhy.duckdns.org/ serves the freshly built bundle.
Depth violations 417 -> 303.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJrqKERAo5QUeEHWS5Asgp
Reverts the temporary broken assertion used to prove the pre-push gate
refuses a red shell suite (it did: exit 1).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJrqKERAo5QUeEHWS5Asgp
Three changes, none of which touch what a single test asserts:
thorium_repairs.sh's `sleep 4` becomes `sleep ${THORIUM_STARTUP_WAIT:-4}`
and the harness sets 0.2s. Three cases were each paying four real
seconds to watch a stubbed browser stay up; the stub sleeps 30s, so the
`kill -0` check is unchanged. That file: 17.0s -> 5.6s.
_t_hide was the rest of it. It walks PATH and creates a symlink per
executable -- ~13.5k here, 4.6s a build -- and the suite has ~16
distinct tool sets. Now the full farm is built ONCE and `cp -al`
hard-links it per set, with only the hidden names deleted from the copy.
The cache also moved out of $TEST_TMPDIR, which is per-file, into a
run-scoped dir run_all.sh creates and removes, so it survives between
files.
110s -> 98s (sleep) -> 85s (shared cache) -> 37s (hard-linked farm).
645 OK, 0 FAIL throughout. The cases that only pass when a tool is
genuinely unfindable -- install_pyroveil's missing-dependency arms,
fix_aggressive without sqlite3 -- still pass, which is what proves the
farm is still hiding rather than quietly returning a full PATH.
lib_test_core.sh hit exactly 250 lines, so _t_hide and the farm move to
lib_test_path.sh (194 + 67).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The seams were applied, verified and measured, but never reached the
commit: cb1e8c53 shipped the file with its hardcoded /etc/X11,
/etc/profile and /home/$SUDO_USER paths. ci-mirror caught it by running
the suite from a clean checkout, where the tests read the REAL system
files -- the RenderAccel assertion failed against this machine's actual
xorg config, which says "disabled", and the pyroveil clone path came
back as /home/testuser rather than the tmpdir.
The local run passed only because a stale seamed copy was sitting in the
measurement worktree. Re-applied and grepped back immediately, which is
the documented rule for exactly this failure mode.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
76/76 lines through run_all.sh at --min 100, exit 0. 45 assertions over
15 cases across all four functions.
XORG_CONF and XORG_CONF_D are plain globals ASSIGNED inside
configure_xorg, so the default had to move to the assignment itself --
exporting a value from the harness alone would have been overwritten on
entry. PROFILE_FILE and USER_HOME take the ordinary `${VAR:-default}`
form. The real /etc/X11/xorg.conf.d/20-nvidia.conf keeps its Jun 2025
mtime and ~/pyroveil does not exist after the suite runs.
configure_xorg's RenderAccel value is asserted to be "true" AND asserted
never to be "false": the lib's own comment records that "false" forces
software rendering and pins Xorg above 30% CPU, so that is a regression
worth a dedicated negative assertion.
install_pyroveil's prompt could not be asserted on its text -- bash
writes a `read -p` prompt straight to the terminal, so it never reaches
captured output. The branches are distinguished by the non-interactive
arm's "Auto-installing" line instead, which is observable.
bt_audio.sh re-measured at 127/127 with the new files present.
That is all eight libs from the original handoff: arch_sysctl (banked as
unmeasurable and quarantined), arch_cpu, arch_hardware, thorium_repairs,
hosts_guard_migrate, hosts_guard_rollback, ubuntu_perf_fixes and
nvidia_config. Allowlist 91 -> 84.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
81/81 lines through run_all.sh at --min 100, exit 0, and
check_shell_coverage.sh passes with the allowlist line already deleted.
59 assertions over 14 cases across all four functions: the sysctl
drop-in with both the "already applied" skip and the documented-default
fallback for an unreadable sysctl; both NVIDIA branches, since the
helper-service path and the standalone fallback write different units
and different undo lines; earlyoom install / already-installed /
config-backup; and fix_failed_sssd for none, all five and exactly one
failed unit -- that last one matters because the detection loop breaks
at the first failure while the masking loop re-checks each unit, so a
naive implementation would mask all five.
The four write targets are now behind overrides defaulting to the real
paths. The add_undo lines deliberately KEEP their literal /etc paths and
are asserted to: the undo script runs on the real system, so seaming
those would have written an undo that removes nothing. Neither
/etc/sysctl.d/99-performance-tuning.conf nor /etc/default/earlyoom
exists after the suite runs.
bt_audio.sh re-measured at 127/127 with the new files present -- that
canary runs after every addition to this suite now, because a test file
silently broke it once already.
The handoff is rewritten for the one remaining lib.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
hosts_guard_migrate.sh 81/81 and hosts_guard_rollback.sh 65/65, both
100.00% through run_all.sh at --min 100, and check_shell_coverage.sh
passes with each allowlist line already deleted.
82 assertions over 36 cases in three files sharing one harness: all four
validate_requirements refusals, plugin installation, the mount-collapse
loop in every arm (clears, fails, hits its 20-iteration bound, dry-run),
per-instance migration for both the bind-mounted and the plugin flavour,
and do_migrate's refusal to retire the legacy pacman hooks when nothing
registered -- the arm that exists so a failed migration cannot leave the
files with no unlock hook at all.
INSTRUMENT FIX: rollback measured 97.01% with lines 69 and 108
uncovered, both `done <redirect>` closing a loop. Reproduced minimally:
in a three-iteration loop ending `done >"$1"`, the body reports hits=3
and the `done` line hits=0, because bash attributes the redirected
compound statement to the loop's OPENING line. That is the same defect
_CLOSING_BRACE_OP already handles for `} |`, so _LOOP_END_OP is its
twin. The redirect is required by the pattern: a bare `done` stays in
the denominator, so genuinely uncovered loops are still caught.
Audited as the instrument notes demand -- every newly excluded line
printed with its text -- and it is exactly those two lines across all of
fixes/lib. Acceptance pair unchanged and exact: dot_resolver_install.sh
39/39, rpi_nc_ca.sh 73/73.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
75/75 lines through run_all.sh at --min 100, exit 0, and
check_shell_coverage.sh passes with the allowlist line already deleted
so the pass cannot come from the exemption.
55 assertions over 23 cases: all five profile repairs plus test_thorium,
including every dry-run arm, the partial singleton-lock case, a corrupt
database and the sqlite3-absent path. The lib needed NO production
change -- it already takes every path from $THORIUM_CONFIG_DIR, so
pointing that one variable at the tmpdir confines it completely.
The gate's per-case timeout moves from the jail's 120s default to 600s.
That default is a hang-catcher, not a performance budget, and this suite
has outgrown it: 76s bare at 25 test files, 93s at 27, and kcov roughly
doubles it. The symptom was a lib FAILING the gate while measuring
perfectly -- bt_audio.sh printed "127/127 lines = 100.00%" and then
"warn: case timed out after 120s", which --fail-on-case-error turned
into a non-zero exit. bt_audio.sh and arch_cpu.sh both pass now.
The cost, recorded in the evidence: a genuine hang takes 10 minutes per
pass to surface instead of 2. test_thorium's `read -r -p` is exactly
that shape, so every case here feeds it stdin explicitly.
This also settles the quarantine in b2779059. Re-adding the arch_sysctl
cases still yields "kcov instrumented no lines" for bt_audio at a 600s
timeout with no timeout warning, so runtime was never that file's
problem and the quarantine stands for the reason its header gives.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
check_shell_coverage.sh was RED on main. bt_audio.sh is off the
allowlist at 127/127, and commit 7c14cfca -- which added
test_arch_sysctl.sh -- made kcov stop registering it entirely, so the
gate failed on a lib nothing had touched.
Bisected by measuring bt_audio.sh at three commits: a2b23521 127/127,
afe6ac3a 127/127, 7c14cfca "kcov instrumented no lines". Removing that
one test file restores 127/127 with every other new file still in the
suite (arch_cpu, arch_hardware x2, thorium x2), and arch_cpu.sh
re-measures at 57/57 alongside it.
Both plausible causes inside lib_test_core.sh were ruled out by
reverting each on its own in a throwaway worktree: `export out` and the
_t_hide farm cache each left bt_audio broken while the file was
present. Neutering the file's body while keeping the source line does
NOT reproduce it either, so the trigger is cumulative rather than one
construct, and it is not understood.
The file keeps all 23 assertions and still passes when run directly; it
just leaves the test_*.sh glob run_all.sh iterates. That costs nothing
measurable, because arch_sysctl.sh has never measured through the jail
in the first place -- it reports "instrumented no lines" on its own,
like nc_php.sh -- and it stays on the allowlist.
The header records the bisect and what to re-verify before anyone
un-quarantines it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
94/94 lines through run_all.sh at --min 100, exit 0. 42 assertions over
26 cases across all five functions, including both boot-loader flavours
and the no-boot-loader path.
PRODUCTION BUG, found by writing the tests and confirmed against this
host: tweak_journal's regex required a space before the unit, but
journalctl prints "305.5M in the file system" with no separator. The
size check never matched, so the vacuum was unreachable and a
multi-gigabyte journal would never have been trimmed. This is the third
instance of the same defect -- arch_perf_report.sh:36,65 carried it too
-- so the fix is identical: the separator is now optional. One case
asserts the spaced form still matches, making this a widening.
The mitigation tweak edits the boot loader, so /boot/loader/entries,
/etc/default/grub and grub.cfg are now behind overrides defaulting to
the real paths. This machine's boot configuration is never touched.
_t_hide gets a cache: it symlinks every executable on PATH (13.5k here)
and was rebuilding that farm on every call, which took the suite to 92s
and pushed a jail case past its 120s timeout. Now 77s, and arch_cpu.sh
re-measures at 57/57 so the shared change cost nothing.
The cases are split across two files because a single one was 307 lines
and file-length-cap rejected the first commit attempt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
57/57 lines, measured through run_all.sh and confirmed a second time at
--min 100 so a shortfall would exit non-zero. check_shell_coverage.sh
passes with the exemption removed.
28 assertions over 14 cases: no cpufreq at all, every core already
tuned, the mixed case where only some cores lag, cpupower absent /
unconfigured / already configured, and all three I/O scheduler targets
(none for NVMe, mq-deadline for SATA SSD, bfq for spinning disks).
The sysfs reads and the two /etc write targets are now behind overrides
defaulting to the real paths, so the tests can present hardware this
host does not have -- a rotational disk -- without touching anything.
One assertion initially passed for the wrong reason: _t_hide keeps
$FAKE_BIN on PATH by design, so the harness's own cpupower stub still
satisfied has_cmd and the "not installed" branch never ran. Unstubbing
before hiding is now explicit, and the case fails if that is lost.
This also settles arch_sysctl.sh's diagnosis: it uses this same
harness, so the harness is not why it cannot be measured.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
23 assertions over 8 cases covering both tweak_vm_sysctl and
tweak_network_sysctl: the skip path, the write-when-the-drop-in-is-
missing path that a naive "nothing to do" check gets wrong, the
value-differs path, an unreadable-sysctl path, and the tcp_bbr guard.
arch_desktop_harness.sh is the third family harness, supplying the
globals and apply_tweak that live in optimize_arch_desktop.sh rather
than in any lib. arch_cpu.sh and arch_hardware.sh will reuse it.
SYSCTL_DROPIN_DIR defaults to the real /etc/sysctl.d, matching the
seam ubuntu_perf_more.sh and arch_perf_fixes.sh already carry; the
suite runs un-jailed in ci_mirror.sh and CI, so a bind mount would
protect nothing. Both real drop-ins keep their Mar 2 mtimes.
_t_run lands in lib_test_core.sh because `out="$(func)"` forks a
subshell and kcov never registers a lib whose first execution happens
inside one -- measured as 0 lines via $( ) against 54 lines via a
direct call.
arch_sysctl.sh STAYS on the coverage allowlist: it still reports "kcov
instrumented no lines" through the jail, while ubuntu_perf_more.sh
measures 32/32 in the same worktree and the same invocation. The tests
are real and green; the coverage number is not yet obtainable, and the
exemption may only come off once it is.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
shfmt runs on every staged shell file and rewrites drifted libs, which
moves coverage denominators and invalidates measurements taken minutes
earlier. Landing the reformat first makes every number measured from
here the number that survives pre-commit.
thorium_repairs.sh converts from 2-space indent to tabs; the other two
only lose runs of blank lines. `git diff -w` shows no token changed,
shellcheck is clean, and the 20-file suite stays green.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Eighth of the 16 untested fixes/lib libs. 22 assertions; 43/46 = 93.48%. The
lib STAYS on the allowlist -- see the artifact below.
Third instance of the same dead branch. Line 16 matched on
`([0-9]+\.?[0-9]*)\ G`, a required space before the unit, while journalctl
prints "4.2G" with no separator, so the vacuum could never run. Fixed to an
optional space, as in arch_perf_report.sh.
This one differs from that earlier fix and the difference was confirmed with
the user before landing: arch_perf_report.sh's vacuum sits behind
--apply-safe-fixes, but THIS one runs whenever fix_arch_performance.sh runs.
So the fix makes an unflagged destructive action live -- the script will now
really vacuum the journal to 300M once it passes a gigabyte. That is the
function's evident intent, since its next act is to write a permanent 300M
cap, and the user approved it explicitly.
Three absolute paths moved behind overrides defaulting to the real ones:
JOURNALD_CONF_DIR, SYSTEMD_UNIT_DIR (fix_media_organizer writes
/etc/systemd/system/media-organizer.service) and ORGANIZE_SCRIPT_CANDIDATES.
Verified afterwards that the real unit file still carries its 2026-07-25
mtime and the journald drop-in its 2026-03-02 one, i.e. a bare un-jailed
run_all.sh touched neither.
The three uncovered lines (68-70) are the element lines of a multi-line array
literal. `PS4` + `set -x` on a minimal case shows bash reporting the whole
assignment at its OPENING line and never emitting the elements or the closing
paren, so they are data, not statements -- a fourth flavour of defect (a),
after multi-line quotes, `} |` and the backslash-continued assignment. The
array is provably used: the loop on the next line iterates it and the
media-organizer assertions pass.
Worth fixing, unlike the bt_adapter one-liner: the form appears in three of
the remaining untested libs (thorium_repairs.sh has four) and in nine
allowlisted libs repo-wide. That lands as its own commit next.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Seventh of the 16 untested fixes/lib libs and the first of the ubuntu-perf
pair, which gets its own harness here. 24 assertions; 32/32 = 100.00%
through run_all.sh on the first measurement, confirmed at --min 100 (exit 0),
then cleared with the real gate and no exemption.
Two absolute paths had to move behind env overrides, defaulting to the real
ones: fix_journal writes /etc/systemd/journald.conf.d/size-limit.conf and
run_undo globs /root for undo scripts. Binding those in the jail was rejected
for the same reason as bt_pairing.sh's udev rule -- run_all.sh runs UN-jailed
in ci_mirror.sh and in CI, so a bind mount protects the coverage run and
nothing else. JOURNALD_CONF_DIR and UNDO_DIR follow the UDEV_RULES_DIR
precedent.
Proof the suite is safe where it runs un-jailed: after a bare run_all.sh the
real /etc/systemd/journald.conf.d/size-limit.conf still carries its 2026-03-02
mtime, a genuine artifact of a past production run, and no
undo_ubuntu_performance_*.sh exists in /root.
Worth noting for the rest of the family: run_undo ends in `exit`, so its cases
run inside an explicit subshell. A command substitution already provides one,
so the exit ends only that subshell rather than the whole test file.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sixth of the 16 untested fixes/lib libs, and the first with no dead branch to
fix -- the whole job was test-writing. 43 assertions across two files;
93/93 = 100.00% through run_all.sh, twice, the second at --min 100 (exit 0),
then cleared with the real gate confirming and no exemption.
The one genuine gap was check_memory_pressure's high-swap branch (lines
158-159), which fires only when swap is heavily used WHILE RAM is still
available -- a state this host does not happen to be in. The lib reads the
absolute /proc/meminfo, but every read goes through `awk`, so stubbing awk
supplies controlled figures without touching /proc: the stub answers on the
pattern being matched and execs the real awk for anything else. Both
directions are covered, including RAM genuinely exhausted, which must NOT be
flagged because it is not the stutter signature.
Everything else here is branch coverage of probes whose inputs are external
commands: failed systemd units, ACPI error counts, a CPU-hungry Xorg,
governors all-performance vs one-powersave vs unsupported, thermal
throttling excerpts, the TLP/power-profiles-daemon conflict in all three
combinations, and storage health with and without fstrim/smartctl.
lib_test_core.sh gains _t_stub_cat. "Print this fixture file" is by far the
commonest stub shape, and writing it inline forces every call site to embed
a literal ${LIB_TEST_DEV} that must not expand at write time -- SC2016 on
every use. Passing the fixture NAME as data removes the class outright, and
two earlier bluetooth test files are simplified onto it. All 21 test files
and three harnesses now lint clean with no suppression anywhere.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fifth of the 16 untested fixes/lib libs and the first of the arch-performance
group, which gets its own harness here. 38 assertions across two files. The
lib STAYS on the allowlist at 59/60 = 98.33%, measured twice.
The second dead branch this campaign has found, fixed here. Lines 36 and 65
matched on:
([0-9]+\.?[0-9]*)\ (G|M)
a REQUIRED space before the unit. journalctl actually prints "Archived and
active journals take up 305.5M in the file system." with no separator --
verified against the real binary on this machine. So check_journal_size could
never report a large journal and apply_safe_fixes could never vacuum one:
both were unreachable. The space is now optional, and tests cover the spaced
and unspaced forms so neither can rot.
NOTE: this makes a previously-dead DESTRUCTIVE action live. With
--apply-safe-fixes and a journal over a gigabyte, the entry script will now
really run `journalctl --vacuum-size=300M`. That is the flag's documented
purpose and it stays behind the flag, but it has never actually executed
before today.
Line 20, the one uncovered line, is `} >>"$REPORT_FILE"` -- the closing brace
of a redirected group. A minimal probe writes both inner lines to the file
while bash attributes no statement to the brace, and the report assertions
independently prove the group runs, since they read the text it writes. Same
defect (a) class as bt_audio's `} |`.
That form now caps four libs: bt_audio.sh, arch_perf_report.sh, and
arch_perf_probes.sh and nvidia_config.sh which are still untested. So the
continuation_lines() fix is worth landing after all -- as its own commit,
next, so a denominator change can be reverted without taking these tests
with it.
_t_hide and _t_full_path move from bt_harness.sh into lib_test_core.sh: they
are generic PATH plumbing and the arch harness needs them for the
"nvidia-smi is not installed" branch. All twelve existing suites re-run green
after the move.
One trap worth recording: apply_safe_fixes appends to the ACTIONS array, so
it must be called directly rather than inside "$(...)" -- a command
substitution runs it in a subshell where the appends die with it, and the
assertions read an empty array.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fourth of the 16 untested fixes/lib libs, the largest at 214 lines, and the
last of the bluetooth family. 47 assertions across three files. The lib
STAYS on the allowlist: 128/132 = 96.97%, twice with the same line set.
The bug the tests found, fixed here. Line 21 read:
if timeout 3 _run_as_user wpctl status &>/dev/null; then
`timeout` is a binary and `_run_as_user` is a shell function that is never
exported, so this always failed with rc=127 -- "timeout: failed to run
command '_run_as_user'". check_pipewire_health therefore reported PipeWire
hung on EVERY run and restarted a healthy audio stack every time
fix_bluetooth.sh ran. The healthy branch was unreachable, which is why the
test for it could not be written without first noticing. Now
`_run_as_user timeout 3 wpctl status`: same bound, inside the sudo'd command.
Why 96.97% and not 100%. An earlier run of this suite read 99/99 = 100.00%,
and that number was wrong -- it measured the file before pre-commit's
`shfmt -w` reformatted it. shfmt rewrites the `{ ...; } \` + `| bluetoothctl`
one-liners into multi-line blocks ending in `} |`, which raises the
denominator 99 -> 132. Confirmed unavoidable by running shfmt against HEAD's
own copy: it rewrites there too, so reverting the reformat is not stable.
The four uncovered lines (90, 113, 137, 157) are each that `} |` -- the pipe
operator joining a block to bluetoothctl, not a statement. They do execute:
a `{ echo a; echo b; } | consumer` block writes every marker to a file even
though bash's xtrace never reports the left-hand side, because a pipe's LHS
runs in a subshell whose xtrace is not captured. kcov instruments them and
cannot attribute them; defect (a) in docs/kcov-under-report.md, third flavour.
Scope, measured: the continuation-pipe form appears ONLY in bt_adapter.sh
(pre-format) and bt_audio.sh (post-shfmt). None of the remaining twelve
untested libs carries either, so this does not block the campaign and the
detector fix stays off the critical path.
Also worth 90.91% -> 96.97% on its own: the bluetoothctl stubs now drain
stdin before exiting. Real bluetoothctl consumes its whole input; a stub
that read one line and exited closed the pipe early, so the writing block
took SIGPIPE partway through and its later lines never ran.
NOTE for whoever edits this file next: bt_audio.sh is now exactly 250 lines,
at the cap. The next change to it needs a split, not a comment trim.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Third of the 16 untested fixes/lib libs, and the first that does NOT come
off the allowlist. 68/69 = 98.55%, up from 45/69. The remaining line is
not a missing test:
PS4='+TRACE:${BASH_SOURCE##*/}:${LINENO} ' bash -x
shows bash attributing the whole multi-line dbus-send assignment in
_services_resolved to line 100, and never emitting line 97 at all. Line 97
is the OPENING line of a backslash-continued statement; kcov instruments
it, bash never attributes a statement to it. That is defect (a) in
docs/kcov-under-report.md -- a wrong denominator -- and no test can move it.
continuation_lines() in shell_coverage_lines.py already excludes such lines,
but only detects them by tracking QUOTE state, so a line ending in an
unquoted backslash slips through. Fixing that is deliberately left out of
this commit: it changes the denominator for every measured lib, and if it
regresses one of the libs now gated with no exemption, reverting a mixed
commit would throw away these tests too.
Scope of the problem, measured rather than guessed -- backslash
continuations are confined to the bluetooth family: bt_audio.sh 10,
bt_adapter.sh 7, bt_pairing.sh 3, pacman_hook_stall_summary.sh 2, and ZERO
in the other 12 remaining libs. So this caps bt_audio.sh next and then stops
mattering.
Also replaces the harness's _t_only_path with _t_hide. _t_only_path dropped
PATH to $FAKE_BIN alone, which hid grep, head and sort as well as the tool
under test -- so the "usbreset is not installed" case died in a cascade of
"command not found" and passed for the wrong reason instead of exercising
the fallback. _t_hide rebuilds PATH from symlinks to every real executable
except the named ones; verified directly that command -v usbreset is then
empty while grep and head still resolve.
bt_report.sh (37/37) and bt_pairing.sh (65/65) re-measured at --min 100,
both exit 0, so neither cleared lib regressed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Second of the 16 untested fixes/lib libs. 65/65 = 100.00% through
run_all.sh, twice, the second at --min 100 (exit 0), then cleared from the
allowlist and confirmed by the real gate with no exemption.
Two findings worth keeping:
- udevadm was NOT in the harness's stub list, so `udevadm control
--reload-rules` was reaching the REAL binary during the suite. A
prepended stub dir cannot hide a tool the host actually has. Caught by
asserting on the recorded call rather than by reading the code, which is
the argument for asserting on calls at all.
- _disable_usb_autosuspend writes /etc/udev/rules.d/50-bluetooth-no-
autosuspend.rules. Binding /etc in the jail would have covered it, and
was rejected: run_all.sh runs UN-jailed in ci_mirror.sh and in the
shell-tests workflow, as its own header says, so a bind mount protects
the coverage run and leaves every bare run writing to a real root-owned
file. Instead the lib gained a UDEV_RULES_DIR override, defaulting to the
real path -- the same env-override seam pacman_hook_stall_harness.sh uses
for PACMAN_LOG/CACHE_DIR/PACMAN_LOCK.
Proof the suite is safe where it runs un-jailed: after a bare run_all.sh,
the real rule file still has its 2026-02-21 mtime (it is a genuine artifact
of a production run six months ago) and the probed power/control values are
unchanged. The jail cannot give that check.
fix_usb_autosuspend globs the real /sys/bus/usb/devices/*/ with no override,
so its branches are driven through stubbed lsusb output: ffff:ffff matches
nothing on any machine and reaches the not-found arm, while 046d:c077
(control=on) and 046d:0825 (control=auto) are read-only probes, each guarded
so the case self-skips with a note if the host state changes rather than
silently asserting nothing.
Split across two test files to stay under the 250-line cap; run_all.sh globs
test_*.sh, so splitting costs nothing.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
First of the 16 untested fixes/lib libs. Measured 37/37 = 100.00% through
lib/tests/run_all.sh, twice, the second run at --min 100 (exit 0), then
removed from the allowlist and confirmed with the real gate and no
exemption.
Adds two reusable pieces rather than a per-family harness clone:
- lib_test_core.sh -- PASS/FAIL tally, _t_eq/_t_contains/_t_lacks, a
mktemp -d sandbox wiped on EXIT, a FAKE_BIN stub dir on PATH, and
_t_stub/_t_unstub. _t_unstub runs `hash -r`: deleting a stub file alone
does not drop bash's cached executable path, so the real binary would
never be reached again.
- bt_harness.sh -- sources the core, sources the real scripts/lib/common.sh
for the production log_*/has_cmd helpers (verified inert at source time),
and redefines _btctl and apply_fix verbatim from fix_bluetooth.sh, since
those live in the entry script rather than in any lib. Same trade-off
pacman_hook_stall_harness.sh already makes with log_size.
pacman_hook_stall_harness.sh is deliberately left alone: its six libs are
already off the allowlist, i.e. gated at 100% with no exemption, so
refactoring it onto the new core would risk banked work for no gain. jscpd
reads 1.6% against the hook's own flags, and **/lib/tests/** is excluded
from that scan anyway, so the duplication budget is not at stake.
_t_only_path exists because every tool these libs call (usbreset, pactl,
lsusb, ...) genuinely exists on an Arch desktop: a prepended stub dir
cannot exercise a "not installed" branch, so those cases drop PATH to
FAKE_BIN alone.
The three coverage runs were made in a detached worktree: a second session
was writing to this repo concurrently, and the jail aborts on any
working-tree delta during a run.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The handoff recorded fixes/lib as having "no harness at all". It already had
8 test files and 2 harnesses. What was missing is run_all.sh -- the subject
is_covered() actually builds, and the only thing the gate measures through.
All 8 test files pass through it.
No jail_args beside it, deliberately: the harness confines every write to its
own `mktemp -d` and intercepts external commands with a PATH stub dir, and
grep finds no absolute write to /etc, /var or /usr in any of the tests. So it
runs bare, like the transcribe suite.
First measurement through it: pacman_hook_stall_usage.sh is 1/1 = 100.00%.
That denominator is honest, not broken -- the lib is a single usage() whose
body is one `cat <<EOF` heredoc plus `exit 0`, and heredoc content is data
rather than statements.
16 of the 22 libs there still have no tests at all. That is now the largest
block of real test-writing work left in the campaign.
Also rewrites NEXT_SESSION_PROMPT.md, whose central claim ("the instrument is
the bottleneck, not the tests") stopped being true this session. The new one
leads with re-measuring the 103 allowlisted libs on the fixed instrument
before writing any new test.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two defects found in review, both of which made checks PASS more easily, so
neither ever went red.
GATE: is_covered() hardcoded its jail flags and never read the jail_args
marker that ci_mirror.sh and shell-tests.yml both consume. The features/lib
suite needs /usr/local/share and /etc/pki and aborts under set -e without
them -- but the coverage number still printed, because kcov had already
recorded whatever the dead run reached. The gate would have graded 44 libs on
a suite that never finished. It now reads the marker, keeps the historical
defaults for suites without one, fails closed on an empty marker, and passes
--fail-on-case-error.
Negative control: stripping the binds makes the gate exit 1 and restoring
them returns exit 0. Before this commit both cases exited 0 -- the gate could
not fail on an aborting suite.
HASH CACHE: the _t_unstub helper written earlier today for the transcribe
harness was needed in features_harness.sh too. Two assertions were vacuous --
test_dwm_config's "verify still reports when dwm is absent", and
test_rpi_nc_ca's uname removal, where a cached uname left every later branch
running under a faked Darwin. All four `rm -f "$TEST_TMPDIR/bin/` sites in
the repo were audited; the other two are sound (one probes with [[ -f ]], the
other runs in a subshell).
No measured figure moved: dot_resolver_install.sh still 39/39 = 100.00% with
real absence enforced, so its off-allowlist clearance holds.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016sxxsDHWgdRhmdmzNMA6XM
A 38-assertion suite for the last lib in the directory without one. Every
one of its five libs now has a suite; at the start of the session it had
none. 118 assertions across the directory, 0 failures.
build_filters is asserted on the EXACT filter string it emits, because that
string is the lib's entire product. An arnndn chain missing its mandatory
48 kHz resample, or a preset silently falling through to no dynamics, yields
worse audio and never an error -- nothing else would catch it.
Every exit code is pinned: 1 for a missing command, 11 for "RNNoise required
but unavailable" (refusing to quietly fall back to afftdn), 8 for an ffmpeg
whose afftdn lacks md=.
Measured 83/93 = 89.25%; it stays on the allowlist. All ten uncovered lines
are the documented under-report, not gaps: an `exit 66` sentinel proves
require_cmd's lines 37-38 execute, 52-58 are a multi-line array literal (the
confirmed continuation-line artifact), and 129 is an empty `*) ;;` arm whose
branch has a passing assertion. The gate uses the measured figure, so the
exemption stands regardless.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016sxxsDHWgdRhmdmzNMA6XM
A 29-assertion suite covering all six functions. transcribe_venv.sh measures
53/53 = 100.00% through the directory runner, and check_shell_coverage.sh
passes it with the exemption deleted.
Assertions are on recorded ARGV because which index a pip install points at
IS the behaviour: the OpenNMT cu12 wheel index on the NVIDIA path, the
CPU-only torch index for diarization (forced to avoid mismatched CUDA
builds). "pip was called" cannot see either.
generate_test_audio's four-deep fallback chain is covered by failing each
generator in turn. Every stub materialises the wav, because the chain
advances on `[[ ! -s $tmpwav ]]` -- a record-only stub would silently
exercise the branch after the one under test.
One assertion was wrong and got corrected rather than forced: I claimed a
wholly-failing pip still returns 0, but the final `python "$PY_HELPERS"
deps-installed` carries no `|| log`, so it does not. The suite now asserts
what the subject actually guarantees -- all four warnings emitted, no earlier
failure aborting the run.
SC2016 fixed at the source with a quoted heredoc, not suppressed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016sxxsDHWgdRhmdmzNMA6XM
The first allowlist removal of the campaign this session. unity_handler.sh
measures 32/32 = 100.00% through its directory's runner, and
check_shell_coverage.sh passes it with the exemption DELETED -- the real
gate, not just the measurement.
HARNESS BUG found getting there: bash caches executable locations in a hash
table, so `command -v foo` keeps succeeding after foo is removed from the
stub dir. Every "tool is missing" test was therefore running as a "tool is
present" test, asserting the opposite of its own name while looking
plausible. Reproduced minimally: after rm, STILL FOUND; after `hash -r`,
gone.
A _t_unstub helper now removes the stub and clears the table. The two suites
committed an hour ago had the same defect and are corrected here --
test_transcribe_pkgmgr.sh goes from 15 to 18 passing assertions, so three of
its checks had been vacuous. This is exactly the failure the campaign exists
to catch, found in its own test code.
`basename` joins the restricted PATH because the SUBJECT calls it; the suite
avoids needing `tail` via a parameter expansion instead, since every binary
in that PATH is one more thing a stub's shebang can trip over.
transcribe_deps.sh (92.31%) and transcribe_pkgmgr.sh (98.00%) re-measured
unchanged and stay on the allowlist.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016sxxsDHWgdRhmdmzNMA6XM
The directory held five allowlisted libs and no tests. It now has a harness,
a runner, and suites for two libs: transcribe_deps.sh (the fourth
hardest-first target, 48/52 = 92.31%) and transcribe_pkgmgr.sh (49/50 =
98.00%). Both stay on the allowlist. 15 + 18 assertions, 0 failures.
No jail is needed here and no jail_args marker is created: every branch turns
on `command -v <manager>` and every install goes through sudo, both
intercepted by a PATH stub dir. Verified the runner exits 0 when invoked
bare, which is how both gates call it.
The harness REPLACES PATH rather than prepending. This host really has
pacman, and a prepended stub dir cannot HIDE a binary, so every "manager not
installed" case would have asserted nothing. `bash` and `env` are in the
private coreutils dir for a non-obvious reason: every stub's
`#!/usr/bin/env bash` shebang resolves through that restricted PATH, and
without them each stub died with "env: 'bash': No such file or directory"
while looking exactly like a coverage gap.
Assertions are on recorded ARGV rather than on the call happening, because
which packages a branch installs is what differs between distros --
pacman gets python-virtualenv where apt gets python3-venv.
Three assertions aimed at the libsndfile branch were REMOVED rather than left
green-but-vacuous: /usr/lib/libsndfile.so exists on this host, so
need_libsndfile is legitimately 0 and lines 19/52/53/55 are unreachable
without a jail that hides the library. The limitation is written into the
suite instead of asserted around.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016sxxsDHWgdRhmdmzNMA6XM
A 26-assertion suite for rpi_nc_ca.sh, third in the hardest-first order. All
five OS branches are exercised by seeding the marker file each one tests for
inside the jailed /etc, plus a uname stub for Darwin; both NSS stores and all
three Firefox outcomes are covered.
SHARED-FILE BUG: the Debian branch does `mkdir -p
/usr/local/share/ca-certificates` and jail_args bound only /usr/local/bin, so
the suite aborted there under set -e. /usr/local/share and /etc/pki are now
bound. jail_args is shared by every suite in the directory, so all five libs
were re-measured: dot_resolver_install.sh still 39/39 = 100.00%, and
rpi_nc_install.sh, dwm_config.sh and aw_autostart.sh are unchanged. An
over-aggressive mount looks exactly like unreachable code, so this check is
not optional.
That bind also unblocked the runner for the whole directory: with the old
args the run exited 1 before nc_php.sh could be measured at all.
Measured 72/73 = 98.63% through run_all.sh, which is the exact subject
is_covered() builds -- the gate's own view -- so the lib STAYS on the
allowlist. The single test file alone reports 73/73 = 100.00%, both figures
reproduced twice. The one-line delta is line 141, the first line of
show_help's heredoc BODY: not a statement, so the denominator is wrong rather
than a test missing. Excluding heredoc bodies from the denominator is the
next piece of work; it is what stands between this suite and the bar.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016sxxsDHWgdRhmdmzNMA6XM
A 25-assertion suite for aw_autostart.sh, second in the hardest-first order.
The generated i3blocks status script is asserted by RUNNING it against
stubbed pacman/pgrep across all four of its branches -- uninstalled,
installed-but-stopped, running, installed-via-package -- rather than by
grepping the heredoc's text. A heredoc that emits syntactically broken bash
passes a text check and fails in front of the user.
One assertion was silently testing nothing at first: aw-qt is genuinely
installed at /usr/bin/aw-qt on this host, so the "not installed" case found
the real binary through the PREPENDED stub dir. PATH is now REPLACED for that
one case. The suite went 24-passed-1-failed -> 25-passed-0-failed, and the
gate caught it rather than the number.
Measured 68/82 = 82.93%; it STAYS on the allowlist. The residue is the
`[[ $EUID -eq 0 ]]` false branches, which are unreachable inside the jail
because the process is uid 0 there, plus the documented kcov under-report --
an `exit 44` sentinel proves create_i3blocks_status runs to completion while
its lines 145-162 report zero hits. Third lib to show it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016sxxsDHWgdRhmdmzNMA6XM
A 27-assertion suite for dwm_config.sh, the highest-scored remaining
allowlisted lib. It drives the lib for real inside the jail: rewriting dwm.c
with perl, appending to config.h, compiling with cc and installing into
/usr/local/bin. The generated content is asserted, not just the call.
LATENT BUG, found by writing the test: apply_fullscreen_confine_hook does
`on=$(grep -c 'pconfine-auto on' "$src")`, and grep -c exits 1 when the count
is zero. The caller runs `set -euo pipefail`, so the function aborted at that
line exactly when the count was zero -- which is precisely when the
"setfullscreen/unmanage were likely refactored upstream" warning three lines
below was the thing needed. The warn branch was dead code in the only
situation it exists for. Both call sites now use `|| true`, and the suite
asserts the warning fires.
Measured: dwm_config.sh 35/73 = 47.95%. It STAYS on the allowlist -- the bar
is 100% and it is measured, not asserted.
That number is an under-report. An `exit 43` sentinel proves build_install,
build_pointer_confine, write_session_files and verify all execute inside the
jail while kcov reports their bodies at zero hits. One kcov artifact is now
CONFIRMED against a minimal repro: continuation lines inside a multi-line
quoted argument (the `perl -0777 -pe '...'` blocks) are counted as
statements that never run, which is the wrong denominator. A sixth
hypothesis -- that the exec-ing sudo shim or a pipeline loses the trace --
was tested and disproven. The two-strike time-box on this hunt is spent;
docs/shell-split-verification.md records what is known, including the
exit-sentinel technique for telling a tracing failure from an aborted suite.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016sxxsDHWgdRhmdmzNMA6XM
ci_mirror.sh and shell-tests.yml discovered every */lib/tests/run_all.sh and
invoked it bare. The features/lib suite refuses to run bare -- that guard is
what stops it rewriting the real /etc -- so the pre-push gate blocked all six
pending commits, and CI would have gone red on the same suite the moment they
landed.
A suite now DECLARES its jail requirement with a jail_args file beside its
run_all.sh, holding the --bind/--seed-* flags it needs. Both consumers branch
on the marker. The 105 still-allowlisted libs were scored on root ops and
system writes, so most future suites will need the jail too; naming the path
in two runners would drift, which is the failure ci_mirror.sh's own comments
say it exists to prevent.
Both branches fail closed: a marker present but empty is an error, not a skip.
Verified the extracted flags reproduce the independently measured
dot_resolver_install.sh 39/39 = 100.00%, and that the other five suites still
pass bare.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016sxxsDHWgdRhmdmzNMA6XM
rpi_nc_install.sh is one 200-line function that apt-installs 24
packages, seeds MariaDB, rm -rf's /var/www/nextcloud, rewrites Apache
and PHP config and installs a www-data crontab. 29 assertions, run for
real inside the jail. The destructive step is the point: a bug in
`rm -rf /var/www/nextcloud` is invisible to any check that does not
actually run it.
Two latent bugs in the ALREADY-COMMITTED nc_php suite, both found by
finally reading its assertion results instead of only its coverage
percentage. It was failing 2 of 29 in isolation:
- the cron entry arrives on crontab's STDIN, not in argv, so asserting
on the call log could never have passed for the right reason. The
stub now records stdin.
- configure_mariadb's stdout is eaten by `db_password=$(...)`, so the
phase-order marker now goes to stderr and the capture reads both.
Suites now: 28 + 30 + 29 = 87 assertions, 0 failures.
KNOWN AND UNEXPLAINED: kcov mis-measures rpi_nc_install.sh at 10/88 =
11.36%, recording lines 13-54 and nothing after -- yet the code past
line 54 provably runs, since /root/.nextcloud_db_password and
/etc/apache2/sites-available/nextcloud.conf both exist afterwards. The
three obvious culprits were each tested against a minimal reproduction
and DISPROVEN: kcov traces fine past a heredoc, into a $( ) command
substitution, and past a heredoc-fed stub reading stdin via $(cat).
The file stays on the allowlist and the suite is kept for its
assertions, not its percentage. Do not 'fix' the number by weakening a
test.
dot_resolver_install.sh 39/39 = 100.00%; nc_php.sh 84/85 = 98.82%.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbD4nco3EgL1UFoZKmKsLE
nc_php.sh was the next-hardest library on the allowlist. It targets a
Debian Raspberry Pi -- it edits /etc/php/<ver>/apache2/php.ini, drives
occ as www-data and installs a crontab -- so none of its write targets
exist on this Arch host and the jail had nothing to mirror.
- --seed-dir / --seed-file create the paths a foreign-platform subject
expects. Verified with a probe: /etc/php/8.2/apache2 exists inside
the jail while /etc/php does not exist outside it.
- A failed bind is now FATAL, and missing mountpoints are created
first. A bind that fails silently is indistinguishable from
unreachable code in the report, which is the misdiagnosis this
runner exists to prevent.
- Mirroring skips unreadable targets (/root as a normal user) rather
than aborting under set -e.
nc_php.sh: 84/85 = 98.82%, 24 assertions. It STAYS on the allowlist,
because 98.82% is below the bar. Line 111 -- the crontab first-run
fallback -- hung the suite on both attempts to cover it, so it is left
uncovered and documented rather than tried a third time.
Two harness hazards found the hard way and written down: a top-level
stub function shadows the subject's own function for every later
assertion (this silently dropped coverage 83.53% -> 57.65% while the
tests still passed), and a stub for a piped-into command must drain
stdin or the writer takes SIGPIPE.
dot_resolver_install.sh still measures 39/39 = 100.00%.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbD4nco3EgL1UFoZKmKsLE
The gate was a presence check -- 'a run_all.sh exists beside this lib' --
which an empty suite that asserts nothing satisfies. It now measures.
100% is reachable with no suppressions and no production source changes:
run the suite inside a user+mount namespace and the sudo-writes, systemd
units and nftables rules execute for real against a throwaway /etc.
- meta/scripts/shell_coverage_jail.sh: the runner, promoted out of a
session scratchpad. Two fixes it needed on the way: bind targets mirror
the real directory tree (an empty bind makes writes fail with ENOENT,
which reads as unreachable code), and sudo gets a pass-through stub
because real sudo cannot setresuid inside a userns.
- It fingerprints git status before and after and fails the run if a
write escapes the jail. Verified with a deliberate escapee.
- dot_resolver_install.sh: 39/39 = 100.00%, 28 assertions. Picked by
scoring every allowlisted lib on root ops, system writes and
destructive calls -- it scored highest in the repo. Allowlist 106 -> 105.
- jscpd was already over its own threshold at 2.45% and would have
rejected every commit staging a .sh file. Excluding vendored .venv/
shell alone gives 1.67%; also excluding lib/tests/ gives 1.47%.
The gate is deliberately NOT wired into the hook chain yet.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbD4nco3EgL1UFoZKmKsLE
1017 lines down to 148. Six libs: the per-language doc-URL builders (split in
two only for the cap), the lookup/dispatch layer, and one per generation phase.
The hard part was not the ten functions but the 335-line top-level block,
which extract_shell_functions.py cannot move because it only relocates
functions. It is now generate_doc_links / generate_anki_cards /
generate_llm_prompt, wrapped WITHOUT re-indenting the bodies: five heredocs
use quoted terminators, which must stay at column 0.
Proof the split is behaviour-preserving: a golden fixture captured before any
edit, re-checked after every step. All three outputs -- anki_cards.txt,
documentation_links.md, llm_anki_prompt.md -- stay byte-identical by sha256sum,
and stdout matches too.
Four latent defects surfaced while writing the tests, all fixed:
python_doc_url required a $2 it never reads, and get_doc_url has always
called it with one argument. That only worked because the entry script runs
`set -e` without `-u`, so "$2" silently expanded to empty; any caller with
`set -u` aborted. Defaulted, along with three more positionals documented as
optional but declared required.
The two imports loops hardcoded `head -20` while the other seven honoured
TOP_N, so --top was silently ignored for imports.
Only one of nine term loops skipped comment lines, so a '#' line in an
analysis file became a flashcard whose front was a comment.
Introduced and fixed within this change: the comment filter has to run
BEFORE `head -n` or comment lines count against the limit, and it needs
`|| true`, since grep exits 1 when it filters every line and the callers run
under `set -e`.
The golden fixture cannot show the last three, because it has no comments and
fewer than 20 imports -- which is exactly why they survived. A second fixture
with 25 imports and comment lines, at --top 3, emitted 20 imports and two
comment cards before, and 3 imports with zero leakage after.
166 assertions across 4 test files. 100% line coverage on study_doc_urls.sh
(38/38), study_doc_urls_more.sh (30/30), study_doc_lookup.sh (49/49) and
study_gen_llm.sh (54/54). study_gen_docs.sh 93.10% and study_gen_anki.sh
96.15%, where every remaining line is a `} >>"$FILE"` closing a brace group
whose output a passing test asserts -- the same kcov attribution artifact
recorded for services_hosts.sh.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F3PzGc75gBcdxP3PkHXGcV
Confirmed live (not dead code) via the dead-code check-in before any code
was touched -- the last two candidates this pattern was tried on were both
archived instead. Kept run_one/cleanup/log_size/main together in the entry
script: a prior session (2527fb3) already proved splitting run_one out
produces a real SC2153/SC2034 pair since PACMAN_PID/LAST_ELAPSED cross the
EXIT trap, not a suppressible false positive.
Fixed a real bug found while writing tests: print_summary's inline awk had
a dead `NR == 0` guard (printf on an empty array still emits one blank
line), reachable via `-n 0`. Refactored mem_available_mb, descendant_pids/
kill_tree, capture_stall's two output blocks, and print_summary's median
calc after confirming empirically (bash -x tracing) that kcov's
xtrace-based coverage can never see a `done <redirect>`, `} >redirect`, or
inline-awk line -- user chose to fix the code over the coverage tool.
descendant_pids specifically needed an explicit-fd process substitution
(not a pipe) to keep its array mutation in the current shell.
Made PACMAN_BIN/PACMAN_LOG/CACHE_DIR/PACMAN_LOCK/LOAD_FLOOR_MB/
LOAD_MIN_FREE_MB env-overridable for testing. Caught and fixed, before it
ran unbounded, a --with-load test that would have dd'd 13-20+ GB into
/dev/shm using this box's real available memory.
56 lib-level + 13 entry-level PATH-shim/subprocess assertions, 0 failed.
The entry test itself grew past 250 lines while adding coverage and had to
be split into a shared harness plus two test files, mid-session.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
Full history preserved via git filter-repo, including both pre-reorg
root paths (libre_translate.sh and the subtree-imported
Bash/libre_translate.sh) since both were genuine ancestors of the
current file. Live at
github.com/kuhyx/testsAndMisc-archive/tree/main/linux_configuration/scripts/single_use/misc/testsAndMisc-bash.
Asked the dead-code check-in before any split work started this time,
per the lesson from the plagiarism-tools session. NEXT_SESSION_PROMPT.md
now points at diagnose_pacman_hook_stall.sh.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
Full history preserved via git filter-repo, including the pre-rename path
from before the single_use/periodic_background split. Live at
github.com/kuhyx/testsAndMisc-archive/tree/main/linux_configuration/scripts/single_use/utils.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
Wraps the four install stages into named functions, one per lib/plagiarism_*.sh
sibling (matching install_exercism.sh's convention), and extracts the two
embedded Python heredocs into real, lint-clean check_plagiarism.py/sherlock.py
files -- check_plagiarism.py needed a second split into plagiarism_similarity.py
to also clear the 250-line cap. Every function reaches 100% shell coverage via
a PATH-shim test harness (fake python3/pip/git/java/wine); the two Python CLIs
were separately verified against a real venv with actual nltk/scikit-learn.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
Grouped by the state each function touches rather than by size:
steam_requirements.sh 199 requirement parsing, scoring, and the hardware
detection that feeds it
steam_report.sh 156 the run loop and the cache it reads
steam_api.sh 124 library discovery, Steam and ProtonDB calls
steam_credentials.sh 103 credentials, usage text, presentation helpers
The grouping was forced by the SC2034 writer/reader rule, not chosen. Two
arrangements were discarded: detect_system alone in a lib writes the three
SYSTEM_* globals without reading them, and load_cache_map alone writes
CACHE_MAP without reading it. Both were fixed by putting the writer next to
its reader - detect_system beside score_game, load_cache_map beside main.
Verified: all 33 functions verbatim; every lib passes shellcheck standalone
with no suppression; and the script actually runs - `--help` prints the usage
block and exits 0, which is what proves the four source lines resolve and
main still dispatches.
Over-cap files 26 -> 25.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
clean_audio.sh 419 -> 230 + 204
enforce_vbox_hosts.sh 443 -> 220 + 236
migrate_hosts_guard.sh 444 -> 167 + 162 + 141
migrate_hosts_guard needed two libraries: with all ten work functions moved
the single lib was 295 lines, so migrate and rollback were separated.
The extractor's brace matcher required index > start and so silently skipped
one-line `warn() { ...; }` definitions. Fixed, and regression-checked against
the committed fresh-install/main.sh split byte-for-byte.
The harness earned its keep on a fourth file: adding `export` to libre_translate
to satisfy SC2034 changed two function bodies, and verify_shell_split.sh caught
what lint had accepted. Those exports were reverted, and libre_translate.sh is
parked - what remains after its clean seams both assigns and reads the same
globals, so getting it under the cap needs parse_args restructured rather than
relocated, which is a refactor rather than a verbatim move.
That cost is now written down: a lib must contain the readers of every global
it assigns. The precedent at install_pacman_wrapper.sh:29 is about
definitions-only libs, not about assignments as such, and the pre-commit hook
runs shellcheck with no -x, so a source= directive will not make it follow the
link. This is the shell analogue of the monkeypatch-target trap.
Verified: all 8, 13 and 19 functions verbatim; all four libraries source with
no side effects; shellcheck passes standalone on every file with no
suppression; bash -n passes on all seven. None of the three was executed -
they drive ffmpeg over real media, mutate VirtualBox guest disks, and rewrite
systemd units.
Over-cap files 29 -> 26.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
Two single-use scripts with no deployed copy, so the entry+lib shape is
safe. Each keeps the ordering, the safety checks and the user-facing output;
the configuration writers move to a library beside it.
Both scripts write `set -e # Exit on any error`, so extract_shell_functions.py
now matches the directive rather than the whole line. Regression-checked by
re-deriving the committed fresh-install/main.sh split byte-for-byte.
Verified: all 6 and all 9 top-level functions verbatim via the shfmt
harness; both libraries source with no side effects and define every
function moved into them; bash -n passes on all four.
Neither script was run. nvidia_troubleshoot.sh writes /etc/X11 config and
installs pyroveil; setup_passwordless_system.sh writes sudoers and lightdm
autologin, which is what this machine's login depends on.
Over-cap files 31 -> 29.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
The five package-installation functions move to lib/packages.sh; main.sh
keeps the top-level flow and sources the library after `set -e`.
The first attempt sliced by line range and was thrown away. This file
interleaves top-level commands - sudo -v, git config, the cp of
makepkg.conf and pacman.conf - between its function definitions, so a range
slice swept them into the library, where they would have run at source time
and in the wrong order. Sourcing that version blocked on a sudo password
prompt, which is how it was caught. The rebuild extracts function blocks by
brace counting and leaves every other line exactly where it was.
Verified with the new shfmt harness (all 5 functions verbatim), by a
structural comparison of the top-level flow showing exactly one line added
and none missing, and by sourcing the library to confirm it defines all five
functions with no side effects. The script itself was NOT run: it does
`sudo pacman -Sy`, overwrites /etc/makepkg.conf and /etc/pacman.conf, and
installs AUR packages.
Over-cap files 32 -> 31.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
The last Python file over the cap:
_transcribe_media.py 143 _try_import, both duration probes,
get_media_duration, ffmpeg transcode, cleanup
_transcribe_cluster.py 105 _resample_linear, _kmeans_cosine and its
iteration loop
_transcribe_diarize.py 164 the pipeline: audio loading, the classifier,
embedding extraction, diarize_segments
The graph is a tree: _transcribe_media imports nothing local, _cluster takes
only _try_import from it, _diarize imports from both. All 13 top-level
definitions verified AST-identical to HEAD, and an AST scan confirms the
three module constants travelled to the modules that use them.
transcribe_fw.py now imports get_media_duration from _transcribe_media
rather than through _transcribe_diarize. Ruff removed that re-export as
unused and broke the import; running the program is what caught it, and
naming the owning module is the correct fix under the no-barrels rule.
Verified: transcribe_fw.py /nonexistent.wav still exits 2 and --help exits
0; 63 tests pass at 100% line and branch on all three modules; 338 pass in
the directory. Over-cap files 33 -> 32, and no Python file is over the cap
any more - the remaining 32 are 29 shell, 2 kotlin, 1 dart.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
_transcribe_progress.py 91 _run_progress_loop, _format_progress_line,
and the two constants only they use
transcribe_fw.py 236 argument parsing, model loading, diarized
output writing, main
All 8 top-level definitions verified AST-identical to HEAD, and an AST scan
confirms neither module references a name it does not bind - which is what
caught that the two progress constants and the hhmmss import had to travel
with the loop. transcribe_fw.py no longer imports time.
The progress tests now patch _transcribe_progress, including its sys.stderr
and time references, since that is where the loop resolves them.
_resolve_device_and_compute stayed behind, so its test still points at
transcribe_fw.
Verified: --help prints the full usage and a missing input returns exit 2,
the code transcribe.sh branches on; 32 tests pass at 100% line and branch on
both modules; 275 pass in the directory. Over-cap files 34 -> 33.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
Split along the natural seam now that the file is fully covered:
_transcribe_probes.py 177 _try_import, the four dependency probes,
generate_sine_wav, prepare_model, test_cuda
transcribe_helpers.py 142 the eight _handle_* functions and main()
All 18 top-level definitions verified AST-identical to HEAD, and an AST
scan confirms neither module references a name it does not bind.
transcribe.sh is untouched - it invokes tools/transcribe_helpers.py by
path, and that path still exists with the same name and executable bit.
The CLI tests' patch targets did not move either, because main() dispatches
to names imported into its own namespace.
Verified by running every subcommand and reading the exit status directly,
since those codes are the contract transcribe.sh branches on:
python-version 0, check-faster-whisper 7, check-ctranslate2 1,
check-diarization 0, deps-installed 0; generate-wav writes the same
96044-byte WAV as before the split. 41 tests pass at 100% line and branch
on both modules; 243 pass in the directory. Over-cap files 35 -> 34.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
setup_thorium_startup.sh (443 lines) was queued for a split under the 250-line
cap. It turned out the feature it installs has been broken since Thorium was
removed in favour of chromium/librewolf.
/usr/local/bin/thorium-browser is now only a leftover symlink to
browser-preexec-wrapper, which routes by basename to /usr/bin/<name>. With no
/usr/bin/thorium-browser it falls into its testing branch and treats the URL as
the binary, so every boot logged:
thorium-browser: line 33: /https://www.fitatu.com/app/planner: No such file
while systemd reported status=0/SUCCESS and "Finished". The success status is
why this went unnoticed.
Splitting a 443-line script to keep a dead feature under a line cap is the
wrong work, so it is deleted instead, along with its checker.
Removing check_thorium_startup() from check_and_enable_services.sh is the part
that makes this stick: its report_and_fix RE-RAN the installer whenever the
service was not enabled, so deleting only the deployed units would have let
them come back. Verified afterwards that the hourly maintenance timer runs a
deployed script with no thorium reference, and that nothing on a timer invokes
the checker at all.
Also removed from fresh-install/main.sh so new machines skip it. Units disabled
and all four deployed files removed. The generic browser-candidate lists that
merely mention thorium are left alone.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY