diff --git a/docs/superpowers/evidence/pacman-tests-follow-split-2026-08-21.json b/docs/superpowers/evidence/pacman-tests-follow-split-2026-08-21.json new file mode 100644 index 00000000..1156eb76 --- /dev/null +++ b/docs/superpowers/evidence/pacman-tests-follow-split-2026-08-21.json @@ -0,0 +1,46 @@ +{ + "intent": "Repair the Shell tests workflow, red on main since fbe9134c: three assertions in two test files look for wrapper code in pacman_wrapper.sh that the 250-line-cap split moved into the flat pw_*.sh libs.", + "scope": [ + "linux_configuration/tests/test_hosts_guard_pacman_integration.sh: assert_contains now searches the wrapper plus its libs", + "linux_configuration/tests/lib/pacman_wrapper_syntax.sh: three definition greps widened to the libs", + "linux_configuration/tests/test_pacman_wrapper_security.sh: two sed extractions now read pw_policy.sh", + "Non-goal: any change to pacman_wrapper.sh or the pw_*.sh libs -- the wrapper is correct; only the tests' idea of where its functions live was stale" + ], + "changes": [ + "test_hosts_guard_pacman_integration.sh builds a WRAPPER_SOURCES array from the entry script plus every pw_*.sh and passes it to assert_contains, which checks pacman_hooks_manage_guard_lib() and should_use_wrapper_guard_lib_fallback() -- both now defined in pw_guard.sh.", + "The two assert_order assertions in that file were deliberately left pointing at the entry script alone. They assert the ORDER of two call sites, and both calls remain in the entry script; widening them would have weakened a positional check into a meaningless one.", + "pacman_wrapper_syntax.sh: the definition greps for verify_policy_integrity() (now pw_policy.sh), auto_remove_virtualbox_vms() (now pw_cleanup.sh) and VBoxManage (now pw_cleanup.sh) search the entry script and the libs together. The 'CRITICAL near verify_policy_integrity' check and the auto_remove_virtualbox_vms call-site check were left alone -- verified that both still match in the entry script, so widening them was unnecessary.", + "test_pacman_wrapper_security.sh extracts strip_pkgfile_suffix and is_blocked_package_name with sed to run them in isolation; both moved to pw_policy.sh, so the extraction reads that file now. The sed patterns themselves were unchanged, since both functions kept the `function name() {` spelling.", + "Every widened grep uses a pw_*.sh glob rather than a named lib, so a future re-partition of the wrapper does not break these assertions again." + ], + "verification": [ + { + "command": "bash linux_configuration/tests/test_pacman_wrapper_security.sh", + "result": "pass", + "evidence": "rc=0 with zero ✗ markers. Previously failed at '[TEST 4] Integrity verification function not found' and then, once that was fixed, at the strip_pkgfile_suffix/is_blocked_package_name extraction with 'command not found'." + }, + { + "command": "bash linux_configuration/tests/test_hosts_guard_pacman_integration.sh", + "result": "pass", + "evidence": "rc=0 with zero FAIL lines. Previously failed on \"wrapper detects when guard-lib's pacman hooks are installed\"." + }, + { + "command": "Full linux_configuration/tests/test_*.sh sweep, as the arch-tests CI job runs it", + "result": "pass", + "evidence": "Both repaired files pass. Two other files still fail locally and neither is caused by this commit or the wrapper split: test_security_hardening.sh fails only on 'Compulsive block wrappers installed', which is this machine's state (signal-desktop and discord installed but unwrapped) and passes in CI where neither app exists; test_shutdown_timer_monitor.sh fails on the uncommitted setup_midnight_shutdown.sh split present in the working tree, and belongs to that commit." + }, + { + "command": "Behavioural check that the widened greps still assert something", + "result": "pass", + "evidence": "Each moved function was located before widening: pacman_hooks_manage_guard_lib and should_use_wrapper_guard_lib_fallback in pw_guard.sh, verify_policy_integrity and the two -U helpers in pw_policy.sh, auto_remove_virtualbox_vms and VBoxManage in pw_cleanup.sh. The assertions now match in exactly one file each, so they still fail if the code is deleted." + } + ], + "risks": [ + "Globbing pw_*.sh makes the definition assertions insensitive to WHICH lib holds a function. That is intended -- they assert the feature exists -- but they would also pass if a definition were duplicated across libs.", + "test_security_hardening.sh remains red on this machine for an unrelated, pre-existing reason. It is green in CI, so it does not block the workflow." + ], + "rollback": [ + "git revert this commit; the greps return to searching pacman_wrapper.sh alone and Shell tests goes red again on three assertions.", + "Validate with: bash linux_configuration/tests/test_pacman_wrapper_security.sh and bash linux_configuration/tests/test_hosts_guard_pacman_integration.sh, both expected rc=0." + ] +} diff --git a/linux_configuration/tests/lib/pacman_wrapper_syntax.sh b/linux_configuration/tests/lib/pacman_wrapper_syntax.sh index f9a20a6f..4d3d139b 100755 --- a/linux_configuration/tests/lib/pacman_wrapper_syntax.sh +++ b/linux_configuration/tests/lib/pacman_wrapper_syntax.sh @@ -31,9 +31,12 @@ pac_tests_wrapper_and_vbox() { exit 1 fi + # The wrapper was split into flat pw_*.sh libs under the 250-line cap, so + # these definition checks search the entry script AND its libs: the + # functions moved one file over, they did not disappear. # Test 4: Verify integrity check function exists echo "[TEST 4] Verifying integrity check function exists in wrapper..." - if grep -q "verify_policy_integrity()" "$WRAPPER_DIR/pacman_wrapper.sh"; then + if grep -q "verify_policy_integrity()" "$WRAPPER_DIR/pacman_wrapper.sh" "$WRAPPER_DIR"/pw_*.sh; then echo "✓ Integrity verification function found" else echo "✗ Integrity verification function not found" @@ -42,7 +45,7 @@ pac_tests_wrapper_and_vbox() { # Test 5: Verify hardcoded VirtualBox cleanup function exists echo "[TEST 5] Verifying hardcoded VirtualBox cleanup function exists..." - if grep -q "auto_remove_virtualbox_vms()" "$WRAPPER_DIR/pacman_wrapper.sh"; then + if grep -q "auto_remove_virtualbox_vms()" "$WRAPPER_DIR/pacman_wrapper.sh" "$WRAPPER_DIR"/pw_*.sh; then echo "✓ Hardcoded VirtualBox cleanup function found" else echo "✗ Hardcoded VirtualBox cleanup function not found" @@ -51,7 +54,7 @@ pac_tests_wrapper_and_vbox() { # Test 6: Verify VirtualBox cleanup uses VBoxManage directly echo "[TEST 6] Verifying VirtualBox cleanup uses VBoxManage directly..." - if grep -q "VBoxManage" "$WRAPPER_DIR/pacman_wrapper.sh"; then + if grep -q "VBoxManage" "$WRAPPER_DIR/pacman_wrapper.sh" "$WRAPPER_DIR"/pw_*.sh; then echo "✓ VirtualBox cleanup logic found" else echo "✗ VirtualBox cleanup logic not found" diff --git a/linux_configuration/tests/test_hosts_guard_pacman_integration.sh b/linux_configuration/tests/test_hosts_guard_pacman_integration.sh index 1415eb82..bdf9be5e 100755 --- a/linux_configuration/tests/test_hosts_guard_pacman_integration.sh +++ b/linux_configuration/tests/test_hosts_guard_pacman_integration.sh @@ -13,13 +13,22 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_DIR="$(dirname "$SCRIPT_DIR")" WRAPPER_FILE="$REPO_DIR/scripts/periodic_background/digital_wellbeing/pacman/pacman_wrapper.sh" +# The wrapper was split into flat pw_*.sh libs under the 250-line cap, so a +# function-definition check has to search the entry script AND its libs. +# Grepping the entry script alone reports "not found" for code that simply +# moved one file over. The call-site ORDER assertions below still target the +# entry script, where the calls themselves remain. +WRAPPER_SOURCES=("$WRAPPER_FILE") +for _pw_lib in "$(dirname "$WRAPPER_FILE")"/pw_*.sh; do + [[ -f "$_pw_lib" ]] && WRAPPER_SOURCES+=("$_pw_lib") +done assert_contains() { local file_path="$1" local pattern="$2" local message="$3" - if grep -Fq "$pattern" "$file_path"; then + if grep -Fq "$pattern" "$file_path" "${WRAPPER_SOURCES[@]:1}"; then echo "PASS: $message" else echo "FAIL: $message" diff --git a/linux_configuration/tests/test_pacman_wrapper_security.sh b/linux_configuration/tests/test_pacman_wrapper_security.sh index 3559ff8b..13763109 100755 --- a/linux_configuration/tests/test_pacman_wrapper_security.sh +++ b/linux_configuration/tests/test_pacman_wrapper_security.sh @@ -79,13 +79,15 @@ printf 'ungoogled-chromium-bin\n' >"$FIXTURE_DIR/pacman_whitelist.txt" printf '\n' >"$FIXTURE_DIR/pacman_greylist.txt" { + # Both functions moved to pw_policy.sh when the wrapper was split under the + # 250-line cap; they are extracted from there now. cat <<'HEADER' #!/bin/bash set -u load_policy_lists() { :; } # is_blocked_package_name calls this; arrays are pre-seeded below instead HEADER - sed -n '/^function strip_pkgfile_suffix/,/^}/p' "$WRAPPER_DIR/pacman_wrapper.sh" - sed -n '/^function is_blocked_package_name/,/^}/p' "$WRAPPER_DIR/pacman_wrapper.sh" + sed -n '/^function strip_pkgfile_suffix/,/^}/p' "$WRAPPER_DIR/pw_policy.sh" + sed -n '/^function is_blocked_package_name/,/^}/p' "$WRAPPER_DIR/pw_policy.sh" printf 'BLOCKED_KEYWORDS_LIST=(%s)\n' "$(printf "'%s' " "$(cat "$FIXTURE_DIR/pacman_blocked_keywords.txt")")" printf 'WHITELISTED_NAMES_LIST=(%s)\n' "$(printf "'%s' " "$(cat "$FIXTURE_DIR/pacman_whitelist.txt")")" printf 'GREYLISTED_KEYWORDS_LIST=()\n'