From dab262ac239f07a460f2a3432e5116e17a484fc0 Mon Sep 17 00:00:00 2001 From: Steve Beaulac Date: Tue, 22 Sep 2026 17:52:48 -0400 Subject: [PATCH] feat: add arch-maintenance and arch-troubleshooting skills --- README.md | 5 ++ skills/personal/README.md | 8 ++ skills/personal/arch-maintenance/SKILL.md | 50 ++++++++++++ skills/personal/arch-troubleshooting/SKILL.md | 41 ++++++++++ skills/personal/arch/references/mise.md | 35 ++++++++ skills/personal/arch/references/safety.md | 53 +++++++++++++ skills/personal/arch/scripts/check-system.sh | 66 ++++++++++++++++ .../personal/arch/scripts/inspect-system.sh | 79 +++++++++++++++++++ 8 files changed, 337 insertions(+) create mode 100644 skills/personal/README.md create mode 100644 skills/personal/arch-maintenance/SKILL.md create mode 100644 skills/personal/arch-troubleshooting/SKILL.md create mode 100644 skills/personal/arch/references/mise.md create mode 100644 skills/personal/arch/references/safety.md create mode 100755 skills/personal/arch/scripts/check-system.sh create mode 100755 skills/personal/arch/scripts/inspect-system.sh diff --git a/README.md b/README.md index 640b91c..aeacfbb 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,11 @@ Skills are grouped by invocation type. [User-invoked](docs/invocation.md) skills - [tmux-launch-agent](skills/misc/tmux-launch-agent/SKILL.md) — Fork a new agent CLI session into a new tmux window. - [visual-verification](skills/misc/visual-verification/SKILL.md) — Verify running desktop UI changes with screenshots and recordings. +### Personal + +- [arch-maintenance](skills/personal/arch-maintenance/SKILL.md) — Keep an Arch/CachyOS system updated and healthy with status, check, and update workflows. +- [arch-troubleshooting](skills/personal/arch-troubleshooting/SKILL.md) — Diagnose and repair Arch/CachyOS system problems. + ### PKM - [conversation-summary](skills/pkm/conversation-summary/SKILL.md) — Save the current conversation as a report note in an Obsidian vault. diff --git a/skills/personal/README.md b/skills/personal/README.md new file mode 100644 index 0000000..1a3e8e8 --- /dev/null +++ b/skills/personal/README.md @@ -0,0 +1,8 @@ +# Personal Skills + +Skills tied to the user's own setup and not promoted as general-purpose workflows. + +## User-invoked + +- [arch-maintenance](arch-maintenance/SKILL.md) — Keep an Arch/CachyOS system updated and healthy with status, check, and update workflows. +- [arch-troubleshooting](arch-troubleshooting/SKILL.md) — Diagnose and repair Arch/CachyOS system problems. diff --git a/skills/personal/arch-maintenance/SKILL.md b/skills/personal/arch-maintenance/SKILL.md new file mode 100644 index 0000000..7bf1c37 --- /dev/null +++ b/skills/personal/arch-maintenance/SKILL.md @@ -0,0 +1,50 @@ +--- +name: arch-maintenance +description: Keep an Arch or CachyOS system updated and healthy with status, check, and update workflows. +disable-model-invocation: true +--- + +# Arch Maintenance + +User-invoked only. Local machine. For diagnosing and fixing a broken system, use the `arch-troubleshooting` skill instead. + +## First move + +1. Read `../arch/references/safety.md` for distro detection, the safety contract, and redaction rules. +2. Resolve `DOTFILES_ROOT` as described there. +3. Run `bash ../arch/scripts/inspect-system.sh "$DOTFILES_ROOT"` for the read-only baseline. + +## Modes + +- `status` — baseline health report. +- `check` — run `bash ../arch/scripts/check-system.sh "$DOTFILES_ROOT"`; report available updates, cache size, orphans, reboot need, and `.pacnew` files. No mutation. +- `update` — full official update, then separately approved AUR and mise reconciliation. +- `report` — save a redacted detailed report. Create `$HOME/.local/state/arch-system-management/reports/` and write `$(date +%Y-%m-%dT%H%M%S).md`. + +If the request is ambiguous, run `status` and ask which mode is wanted. + +## Update workflow + +1. Run the baseline, `check-system.sh`, and the pacman-lock checks from `../arch/references/safety.md`. +2. Present the official update plan — exact command `sudo pacman -Syu`, affected scope, rollback, post-check — and obtain approval. +3. Run `sudo pacman -Syu`; require exit 0. +4. Verify: `pacman -Qkk` and a `find /etc -name '*.pacnew' -o -name '*.pacsave'` scan. Report `.pacnew` files for manual merge; never merge them automatically. +5. Separately present AUR changes (`paru -Qua`); if approved, run `paru -Sua` (AUR only — the official update already ran) and verify. +6. Separately present mise reconciliation; if approved, run `mise install` from `$DOTFILES_ROOT` and verify. +7. Offer approved mise tasks individually; never run all tasks as a bundle. +8. Check reboot need and failed units with `check-system.sh`. +9. Append `timestamp, command, result, verification` to `$HOME/.local/state/arch-system-management/mutations.log` (no secrets). + +Declare success only after the post-checks pass. A reboot is a recommendation, never an implicit action. + +## Mise and dotfiles + +Read `../arch/references/mise.md` when the request concerns mise, dotfiles, or development tools. + +## Output + +1. detected system +2. findings +3. proposed next action +4. approval needed, if any +5. verification result diff --git a/skills/personal/arch-troubleshooting/SKILL.md b/skills/personal/arch-troubleshooting/SKILL.md new file mode 100644 index 0000000..c5e850a --- /dev/null +++ b/skills/personal/arch-troubleshooting/SKILL.md @@ -0,0 +1,41 @@ +--- +name: arch-troubleshooting +description: Diagnose and repair Arch or CachyOS system problems. +disable-model-invocation: true +--- + +# Arch Troubleshooting + +User-invoked only. Local machine. For routine maintenance and updates, use the `arch-maintenance` skill instead. + +## First move + +1. Read `../arch/references/safety.md` for distro detection, the safety contract, and redaction rules. +2. Resolve `DOTFILES_ROOT` as described there. +3. Run `bash ../arch/scripts/inspect-system.sh "$DOTFILES_ROOT"` for the read-only baseline before investigating. + +## Discipline + +Observe → rank causes → gather targeted evidence → propose → verify. Show ranked causes before testing any of them; proceed with the ranking if the user is away. + +- `diagnose ` — baseline plus targeted checks for `boot`, `packages`, `kernel`, `graphics`, `audio`, `network`, `storage`, or `services`. +- `repair ` — propose a repair for package recovery, failed systemd units, initramfs regeneration, boot configuration, or network restart; apply only after approval and the safety contract. + +## Targeted evidence + +- boot/service: `journalctl -b` and `journalctl -b -1` for the relevant unit; `systemctl status `. +- packages: transaction errors, lock ownership, sync state; never partial upgrades. +- kernel: running vs installed kernel, initramfs presence, bootloader config. +- graphics/audio/network: identify the active device, driver, service, and recent relevant journal entries before suggesting any change. + +## Repairs + +Each repair must state: observation, ranked cause, evidence, proposed change, reversibility, verification. Repairs are limited to reversible, scoped actions. After each approved repair, run its targeted verification and stop if it fails. + +## Output + +1. observation +2. ranked causes with evidence +3. proposed change +4. approval needed +5. verification result diff --git a/skills/personal/arch/references/mise.md b/skills/personal/arch/references/mise.md new file mode 100644 index 0000000..666c899 --- /dev/null +++ b/skills/personal/arch/references/mise.md @@ -0,0 +1,35 @@ +# Mise integration + +This machine uses mise for dotfile management and development tools. + +## Sources of truth + +- `$DOTFILES_ROOT/mise.toml` — dotfiles, bootstrap packages, setup tasks. +- `$DOTFILES_ROOT/config/mise/config.toml` — mise tools and tasks. +- `$DOTFILES_ROOT/packages/sjb-dev.packages` — pacman development packages. + +Prefer the configured owner: a tool in mise `[tools]` is reconciled with `mise install`; a package in `sjb-dev.packages` is checked with pacman. Duplicate installations are reported, never removed. + +## Read-only commands + +Run from the dotfiles root after verifying it contains `mise.toml`: + +```bash +mise ls # installed tools +mise outdated # tools behind their declared version +mise tasks # list tasks +``` + +## Mutations (approval required) + +```bash +mise install # reconcile declared tools — network + installs +mise run # runs project tasks — may install plugins, edit config, enable services +mise trust # approve a config's executable settings — approve once, explicitly +``` + +Never run all tasks as a bundle; each needs its own approval. Never trust an arbitrary discovered project automatically. + +## Shell activation + +Bash and Fish configuration activate mise. When a mise-managed command is missing, check shell activation and `mise ls` before installing another copy. diff --git a/skills/personal/arch/references/safety.md b/skills/personal/arch/references/safety.md new file mode 100644 index 0000000..314ecbe --- /dev/null +++ b/skills/personal/arch/references/safety.md @@ -0,0 +1,53 @@ +# Safety contract + +Shared by the arch-maintenance and arch-troubleshooting skills. + +## Distro detection + +Read `/etc/os-release`; use `ID` and `ID_LIKE`. Support Arch and CachyOS. On any other distro, stay read-only. Confirm `pacman` is available before any package operation. + +## DOTFILES_ROOT + +Set `DOTFILES_ROOT` to `$DOTFILES_ROOT` when it points to a directory containing `mise.toml`; otherwise `$HOME/.local/share/dotfiles` when it contains `mise.toml`. If neither, report it and treat mise checks as unavailable. + +## Read first, mutate second + +Before every mutation show: the exact command, affected scope, risk, rollback/recovery option, and the post-check. Wait for explicit approval. + +## Privilege + +Run as the normal user; use `sudo` only for the individual privileged command. Never store passwords or edit sudo policy. + +## Forbidden + +- `pacman -Sy` standalone (partial upgrade) — full updates are `sudo pacman -Syu` only +- `--noconfirm`, `--force`, `--overwrite`, `-Rdd` +- deleting `/var/lib/pacman/db.lck` without diagnosing +- disk formatting, partitioning, filesystem repair, kernel removal, firewall/security disablement, destructive deletion + +## Pacman lock + +If `/var/lib/pacman/db.lck` exists or `pacman` errors with "unable to lock database": + +1. `pgrep -a pacman` and `pgrep -a paru` — is a package process active? If yes, wait for it; never kill it or delete the lock. +2. If no process is active, the lock is stale. Report it and ask before removing it. + +## Config edits + +Create a backup, show a diff, get approval, then verify the result. + +## Backups + +Before risky work, detect snapshots/backups and warn when none exist. Do not create backup infrastructure automatically. + +## Failure + +If a mutation fails, stop mutations, preserve evidence, run only independent read-only checks, and report the exact failed command. + +## Verification + +Every mutation ends with the smallest check that fails if the change broke: exit code, then `pacman -Qkk` for package integrity, and a `find /etc -name '*.pacnew' -o -name '*.pacsave'` scan after upgrades. Report `.pacnew`/`.pacsave` files for manual merge; never merge them automatically. + +## Redaction + +Redact identity (usernames, hostnames), network identifiers (IP/MAC), storage serials/UUIDs, credentials, and environment values. Device paths and package/service names stay — they are diagnostic evidence. diff --git a/skills/personal/arch/scripts/check-system.sh b/skills/personal/arch/scripts/check-system.sh new file mode 100755 index 0000000..8fd1bf8 --- /dev/null +++ b/skills/personal/arch/scripts/check-system.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +set -u + +section() { + printf '\n[%s]\n' "$1" +} + +section "updates" +if command -v checkupdates >/dev/null 2>&1; then + printf 'official_updates=%s\n' "$(checkupdates 2>/dev/null | wc -l)" +else + printf 'checkupdates=unavailable (do not substitute pacman -Sy)\n' +fi +if command -v paru >/dev/null 2>&1; then + printf 'aur_updates=%s\n' "$(paru -Qua 2>/dev/null | wc -l)" +else + printf 'paru=unavailable\n' +fi + +section "cache" +if [[ -d /var/cache/pacman/pkg ]]; then + du -sh /var/cache/pacman/pkg 2>/dev/null +else + printf 'cache=unavailable\n' +fi + +section "reboot-needed" +# Compare the running kernel against its own installed package, not the newest +# kernel in /usr/lib/modules (a fallback kernel can be newer without being booted). +running="$(uname -r)" +pkg="" +for p in linux-cachyos linux-lts linux-zen linux; do + if pacman -Q "$p" >/dev/null 2>&1; then + pkg="$p" + break + fi +done +if [[ -n "$pkg" ]]; then + installed="$(pacman -Q "$pkg" | awk '{print $2}')" + # cachyos/lts/zen place the flavor after pkgrel: "7.2.5-1-cachyos" vs "7.2.5-1" + if [[ "$running" == "$installed"* ]]; then + printf 'reboot=not-needed (running=%s, %s=%s)\n' "$running" "$pkg" "$installed" + else + printf 'reboot=recommended (running=%s, %s=%s)\n' "$running" "$pkg" "$installed" + fi +else + printf 'reboot=unknown\n' +fi + +section "pacnew" +found="$(find /etc -name '*.pacnew' -o -name '*.pacsave' 2>/dev/null || true)" +if [[ -n "$found" ]]; then + printf '%s\n' "$found" +else + printf 'pacnew=none\n' +fi + +section "orphans" +if command -v pacman >/dev/null 2>&1; then + printf 'orphan_candidates=%s\n' "$(pacman -Qdtq 2>/dev/null | wc -l)" +fi + +section "failed-units" +if command -v systemctl >/dev/null 2>&1; then + systemctl --failed --no-legend --plain 2>/dev/null || true +fi diff --git a/skills/personal/arch/scripts/inspect-system.sh b/skills/personal/arch/scripts/inspect-system.sh new file mode 100755 index 0000000..14ca03b --- /dev/null +++ b/skills/personal/arch/scripts/inspect-system.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash +set -u + +DOTFILES_ROOT="${1:-${DOTFILES_ROOT:-$HOME/.local/share/dotfiles}}" + +section() { + printf '\n[%s]\n' "$1" +} + +section "system" +if [[ -r /etc/os-release ]]; then + # shellcheck disable=SC1091 + . /etc/os-release + printf 'name=%s\nid=%s\nid_like=%s\n' "${NAME:-unknown}" "${ID:-unknown}" "${ID_LIKE:-unknown}" +else + printf 'os_release=unavailable\n' +fi +printf 'kernel=%s\narch=%s\n' "$(uname -r)" "$(uname -m)" + +section "package-manager" +if command -v pacman >/dev/null 2>&1; then + printf 'pacman=%s\ninstalled_packages=%s\n' "$(command -v pacman)" "$(pacman -Qq 2>/dev/null | wc -l)" + orphans="$(pacman -Qdtq 2>/dev/null || true)" + if [[ -n "$orphans" ]]; then + printf 'orphan_candidates=%s\n' "$(printf '%s\n' "$orphans" | wc -l)" + else + printf 'orphan_candidates=0\n' + fi +else + printf 'pacman=unavailable\n' +fi + +section "services" +if command -v systemctl >/dev/null 2>&1; then + failed="$(systemctl --failed --no-legend --plain 2>/dev/null || true)" + if [[ -n "$failed" ]]; then + printf '%s\n' "$failed" + else + printf 'failed_units=none\n' + fi +else + printf 'systemctl=unavailable\n' +fi + +section "storage" +if command -v df >/dev/null 2>&1; then + df -hP / 2>/dev/null | tail -n 1 +else + printf 'df=unavailable\n' +fi + +section "dotfiles-and-mise" +if [[ -d "$DOTFILES_ROOT" && -f "$DOTFILES_ROOT/mise.toml" ]]; then + printf 'dotfiles_root=%s\n' "$DOTFILES_ROOT" + [[ -f "$DOTFILES_ROOT/config/mise/config.toml" ]] && printf 'mise_config=present\n' || printf 'mise_config=missing\n' + [[ -f "$DOTFILES_ROOT/packages/sjb-dev.packages" ]] && printf 'dev_packages=present\n' || printf 'dev_packages=missing\n' + if command -v mise >/dev/null 2>&1; then + printf 'mise=%s\n' "$(command -v mise)" + tools="$(cd "$DOTFILES_ROOT" && mise ls 2>/dev/null || true)" + if [[ -n "$tools" ]]; then + printf 'mise_installed_tools=%s\n' "$(printf '%s\n' "$tools" | grep -c .)" + else + printf 'mise_ls=failed\n' + fi + else + printf 'mise=unavailable\n' + fi +else + printf 'dotfiles_root=not-found\n' +fi + +section "optional-tools" +for tool in paru checkupdates smartctl lsblk; do + if command -v "$tool" >/dev/null 2>&1; then + printf '%s=present\n' "$tool" + else + printf '%s=missing\n' "$tool" + fi +done