Go to file
Krzysztof Rudnicki 8e24ff093f Add boot-repair: offline recovery for a stale EFI System Partition
On 2026-07-30 a kernel upgrade left the machine in systemd emergency mode
on three consecutive boots. The upgrade replaced /usr/lib/modules/<old>
with <new>, but the new kernel never reached the ESP, so the firmware kept
booting the OLD vmlinuz whose module tree had just been deleted. Nothing
modular could load after pivot-root — including vfat, which meant /boot
itself could not be mounted, local-fs.target failed, and systemd dropped to
an emergency shell. pacman reported the transaction as successful.

Root cause: pacman-git with ParallelDownloads > 1 segfaults every forked
alpm hook child, silently skipping 90-mkinitcpio-install and depmod.

boot-repair is self-contained (no repo libs — it must run in the emergency
shell) and fully offline (missing modules are recovered from
/var/cache/pacman/pkg). It repairs by default; --dry-run inspects.

It detects and fixes: read-only root, noauto/nofail fstab drift, orphaned
kernel files shadowing an unmounted ESP, unloadable vfat, unmounted ESP,
missing modules.dep, ESP kernel != installed tree, stale initramfs, and
ParallelDownloads > 1.

Two pacman hooks make the failure impossible rather than merely
recoverable: 05-boot-mounted-guard aborts a kernel transaction when the
ESP is unmounted (AbortOnFail), and 99-boot-autorepair fixes ESP drift
after the transaction, before the machine is ever rebooted.

Safety: a module tree counts as usable only if it has BOTH vmlinuz and
kernel/, so the metadata-only wreckage this bug leaves — which sorts
newer — is never chosen as the target. Files under /boot are deleted only
while it is not a mountpoint AND contains no EFI/ or loader/; deleting
after mounting would destroy the real kernel.

Verified:
- 31/31 fixture tests (--root against throwaway trees, no privileges)
- 11/11 reversible live tests on the real machine: unmounted the real ESP,
  planted shadow files, confirmed they were deleted and the ESP then
  mounted with EFI/, loader/ and kernel 7.1.5-arch1-2 intact
- Gate proven against a real transaction with the ESP unmounted:
  "failed to commit transaction", no packages upgraded, nothing written
- shellcheck + shfmt clean, pre-commit passing

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 12:48:56 +02:00
.github Run all 14 shell tests in CI 2026-07-19 19:39:28 +02:00
.hippo style: prettier format .hippo memory files 2026-05-28 07:05:24 +02:00
.vscode chore: archive 41 unmaintained directories to testsAndMisc-archive 2026-05-14 20:21:05 +02:00
bucket_catch bucket_catch: introduce a real design-token system, fix reversed gradients 2026-07-22 19:18:12 +02:00
docs Add boot-repair: offline recovery for a stale EFI System Partition 2026-07-30 12:48:56 +02:00
kcd2_dice_solver kcd2 dice solver: lock deploy_build.sh so two runs cannot publish half a bundle 2026-07-26 20:33:38 +02:00
linux_configuration Add boot-repair: offline recovery for a stale EFI System Partition 2026-07-30 12:48:56 +02:00
meta Make the hook tests' non-vacuity re-verifiable, and gate it 2026-07-25 17:37:34 +02:00
phone_focus_mode app_icons: add home_inventory storage-box glyph; whitelist it on the phone 2026-07-27 07:35:55 +02:00
python_pkg wsg_grabber: scrape /wsg/, download every new video, triage with keep/pass 2026-07-27 14:55:30 +02:00
third_party/agent-skills style(prettier): apply markdown/json formatting updates 2026-05-07 22:08:00 +02:00
.copilotignore chore: archive 41 unmaintained directories to testsAndMisc-archive 2026-05-14 20:21:05 +02:00
.fvmrc chore: consolidate root configs into meta/, drop unused C dir + split/pdfCentered/geo_data 2026-05-14 20:40:12 +02:00
.gitignore linux_configuration: self-hosted dufs cloud storage + KeePass WebDAV auto-sync 2026-07-12 03:40:54 +02:00
.pre-commit-config.yaml Make the hook tests' non-vacuity re-verifiable, and gate it 2026-07-25 17:37:34 +02:00
.prettierignore cloud_gallery: React media-gallery SPA served by dufs (Phase 3) 2026-07-12 06:05:52 +02:00
CLAUDE.md remove(digital-wellbeing): delete unusable focus-mode daemon entirely 2026-07-19 13:15:04 +02:00
DESIGN_AUDIT_TODO.md Format the design-audit report with prettier 2026-07-21 15:38:08 +02:00
lint_python.sh chore: consolidate root configs into meta/, drop unused C dir + split/pdfCentered/geo_data 2026-05-14 20:40:12 +02:00
pyproject.toml chore: consolidate root configs into meta/, drop unused C dir + split/pdfCentered/geo_data 2026-05-14 20:40:12 +02:00
README.md chore: consolidate root configs into meta/, drop unused C dir + split/pdfCentered/geo_data 2026-05-14 20:40:12 +02:00
requirements.txt chore: consolidate root configs into meta/, drop unused C dir + split/pdfCentered/geo_data 2026-05-14 20:40:12 +02:00
run.sh chore: consolidate root configs into meta/, drop unused C dir + split/pdfCentered/geo_data 2026-05-14 20:40:12 +02:00

testsAndMisc

A collection of personal projects, scripts, and experiments — from a GPS-based phone focus tool to Linux/Arch automation, with CI, linting, and pre-commit hooks across the board.

Highlights

Phone Focus Mode

Location-based app restriction for rooted Android. Automatically disables non-whitelisted apps within 500 m of home using ADB + Magisk. Features Haversine distance calculation, hysteresis to prevent toggling, fail-safe unlock, and state persistence. Bash, Android ADB.

Linux Configuration

Automated Arch Linux setup: fresh-install scripts, i3 window manager config, LaTeX environment, and system tests. Includes documentation and test result logging.

Scripts

Utility scripts for development workflows — build file validation, secret detection, and custom makepkg helpers.

Repository Layout

Path Description
python_pkg/ Python packages (each maintained subpackage lives here)
linux_configuration/ Arch Linux setup, i3 config, system maintenance scripts
phone_focus_mode/ GPS-based Android focus enforcer
scripts/ Workspace-level helper scripts and pre-commit hooks
docs/ Reference docs and historical reports
third_party/ Vendored upstream skills/agents
meta/ Repo-wide tooling: pyproject.toml, requirements.txt, .pre-commit-config.yaml, run.sh, lint_python.sh, .fvmrc. Symlinked into the repo root so tools that auto-discover from root keep working.

Archived / unmaintained projects live in the sibling repository testsAndMisc-archive.

Tooling

  • Python linting: Ruff with all rules enabled (see meta/pyproject.toml)
  • Dependencies: pip install -r meta/requirements.txt (combined runtime + dev)
  • CI: GitHub Actions — lint, build, and test on push
  • Testing: pytest (Python), custom shell-based test harness for scripts