diff --git a/INSTALLER_FIX_TASK.md b/INSTALLER_FIX_TASK.md new file mode 100644 index 00000000..79498349 --- /dev/null +++ b/INSTALLER_FIX_TASK.md @@ -0,0 +1,151 @@ +# Next session: make `install_core_system.sh` actually work on a fresh machine + +Paste everything below into a **fresh** Claude session (`/clear` first). + +--- + +`~/testsAndMisc/linux_configuration/install_core_system.sh` is the documented +way to set this machine up from scratch. It does not work. Three defects were +found on 2026-08-22 by running the real installer in a disposable Arch VM +(`~/utils/vmbox`) rather than by reading it — 2 of its 7 modules cannot install +at all, and a third installs something that silently does nothing. + +**Do not trust this file's line numbers without re-checking them.** They were +correct on 2026-08-22; the repo moves. + +## The evidence + +The sandbox progression, measured with the repo's own hardening checks: + +| State | Result | +|---|---| +| Bare guest, nothing installed | 0 passed / 17 skipped | +| After `install_core_system.sh --all` | 10 passed / 14 skipped | +| After manually installing guard-lib + the shutdown timer | 14 passed / 10 skipped | +| After manually running the hosts migration | **18 passed, 6 skipped, 0 failed** | + +The remaining 6 skips are legitimately screen_locker's. The gap between row 2 +and row 4 is entirely defects 2 and 3 below: everything needed to reach a green +machine already exists in the repos, but the documented install path never runs it. + +## Defect 1 — two module paths no longer exist + +`install_core_system.sh` invokes: + +- line 129: `bash "$REPO_ROOT/python_pkg/screen_locker/install_systemd.sh"` — **gone** +- line 143: `sudo bash "$REPO_ROOT/python_pkg/steam_backlog_enforcer/install.sh"` — **gone** + +Both packages were extracted into their own repos. Verified on disk 2026-08-22: + +- `~/screen-locker/install_systemd.sh` (5637 b, executable) +- `~/steam-backlog-enforcer/install.sh` (3248 b, executable) + +"Workout screen locker" is a **CORE** module, so a fresh machine fails on the +first thing the installer does. + +Note this makes the installer **cross-repo**: `~/testsAndMisc` no longer owns +that code. That is design question (b) below — do not just hardcode `~/screen-locker` +and call it done without putting the question to kuhy. + +## Defect 2 — guard-lib is required but never installed + +`scripts/periodic_background/digital_wellbeing/setup_midnight_shutdown.sh` +depends on `guardctl` and dies with `guardctl not found on PATH`. Nothing in +`install_core_system.sh` installs guard-lib, which lives at +`~/utils/guard-lib/install.sh` — a **third** sibling repo. + +So the CORE module "Midnight shutdown timer" always fails on a fresh machine. + +## Defect 3 — the hosts file-guards are installed only by a one-shot script + +`scripts/periodic_background/hosts/install.sh` (130 lines) never installs the +hosts/nsswitch/resolved file-guards. Its own comment block around **line 109** +claims otherwise: + +> Enforcement does not depend on these sources being immutable: /etc/hosts +> itself is chattr +i, guard-lib's "hosts" file-guard instance (`guardctl +> file-guard status hosts`) watches and re-enforces it against its canonical +> snapshot, and the same instance's bind mount pins it. + +That is only true after running +`scripts/single_use/fixes/migrate_hosts_guard_to_guard_lib.sh` (169 lines), +which is filed under `single_use/fixes/` and is not part of any install path. + +A fresh machine following the documented path therefore gets `chattr +i` and +**no watcher, no canonical copy, no bind mount** — immutability with nothing +re-enforcing it. Verified both ways in the sandbox: 5 hardening checks stayed +skipped until the migration was run, then passed. + +## Two design questions — ask kuhy, do not guess + +Run these as a `grilling` round before writing any code. + +**(a) Where should defect 3's fix live?** Either `hosts/install.sh` calls the +migration script, or the migration's logic moves into `install.sh` and the +one-shot script is deleted (or becomes a thin wrapper). The first is a smaller +diff; the second stops `single_use/fixes/` from being load-bearing, which is +arguably what "single use" is supposed to mean. + +**(b) How should a testsAndMisc installer reach code in sibling repos?** +`~/screen-locker`, `~/steam-backlog-enforcer` and `~/utils/guard-lib` are +separate repos now. Options, none obviously right: + +1. **Expect-adjacent** — check for `~/screen-locker` etc., fail with a clear + message naming the repo to clone. Simple; the installer stops being + self-contained. +2. **Clone if missing** — the installer clones the siblings it needs. Works on + a truly bare machine; puts network access and repo URLs into an installer + that currently has neither. +3. **Drop those modules** — `install_core_system.sh` installs only what + testsAndMisc owns, and each sibling repo installs itself. Cleanest ownership; + means there is no longer one command that sets up the machine. +4. **Invert entirely** — a top-level bootstrap outside all four repos. + +Do not assume `~/` layout is stable; whatever is chosen must fail loudly with +an actionable message rather than silently skipping a module. + +## Done — checkable in a sandbox, not a sentence + +The fix is done when, in a **fresh** vmbox guest: + +```bash +vm share ~/testsAndMisc && vm share ~/utils +vm new inst +vm run inst 'git clone --no-hardlinks -q /mnt/hostrepo/testsAndMisc ~/tam' +# plus whatever cloning question (b)'s answer implies for the sibling repos +vm run inst 'cd ~/tam && echo y | bash linux_configuration/install_core_system.sh --all' +``` + +1. Every module reports installed or **explicitly** skipped with a reason — + zero entries in the installer's own `Failed (...)` summary section. +2. The hardening checks reach **18 passed, 6 skipped, 0 failed**, matching the + row-4 measurement above, with **no manual steps after the installer**. + The 6 skips must be the screen_locker ones; if a different 6 skip, that is + a regression, not a pass. +3. `guardctl file-guard status hosts` in the guest shows a live watcher with a + canonical copy and a bind mount — not just `chattr +i` on `/etc/hosts`. +4. Re-running the installer a second time is a no-op that still exits 0 + (it must be idempotent; the sandbox makes this cheap to check). + +## How to work on this + +- **Sandbox first, always.** This is a root installer that writes `/etc`, + systemd units, pacman hooks and `chattr +i`. Never run it on the host to + test it. `~/utils/vmbox`: `vm new` / `vm run` / `vm reset`. A sandbox pass + does **not** prove the host is fine — report it that way. +- Installers prompt; `vm run` closes stdin, so pipe `echo y |`. +- vmbox is fast: `vm run` ~14s cold / ~3s warm, `vm reset` ~2s. Reuse one + sandbox, do not rebuild per command. +- `~/utils/vmbox/SESSION_RESULTS.md` has the full 2026-08-22 measurements. +- The 250-line file cap applies (`~/utils/file_length`). `install.sh` is at + 130 lines and the migration at 169 — merging them wholesale will breach it, + which is worth weighing in design question (a). +- `~/testsAndMisc` requires a `docs/superpowers/evidence/*.json` artifact for + any code change (pre-commit gate `ai-evidence-contract`); copy + `docs/superpowers/evidence/template.json`. + +## Out of scope + +Do not fix `boot-repair` — its BIOS/GRUB guard landed 2026-08-22 in commit +`aec2b275`. Do not refactor the installer's module-runner machinery +(`run_installer` / `ask_install`); the defects are all in what it points at. diff --git a/NEXT_SESSION_PROMPT.md b/NEXT_SESSION_PROMPT.md deleted file mode 100644 index 89de5785..00000000 --- a/NEXT_SESSION_PROMPT.md +++ /dev/null @@ -1,82 +0,0 @@ -# Next session prompt — testsAndMisc restructure, final units - -Paste everything below into a fresh session. - ---- - -Extract `linux_configuration/periodic_background/hosts/` into its own repo, -then `digital_wellbeing/`. Read `NEXT_SESSION_RESTRUCTURE.md` first — its -"Traps already paid for" section is the expensive part and every line in it -cost a real failure. - -## Start here - -```bash -cd ~/testsAndMisc -./meta/scripts/check_directory_depth.sh --all | head -1 # expect 46 -./meta/scripts/check_repo_size.sh # expect 1051/1200 -git status -sb # expect clean -``` - -If those three numbers do not match, something moved since 2026-08-23 — -find out what before extracting anything. - -## What to do - -**1. `hosts` first** (5 depth violations). It is unblocked: the guard repoint -landed on 2026-08-23, so no guard names a repo path any more -(`sudo guardctl file-guard status resolved` should print -`/usr/local/share/guard-lib-plugins/...`). Its installer was already proven in -vmbox to run from an extracted layout. - -**2. `digital_wellbeing` last** (41 violations). The hard one. It owns the -pacman wrapper, `chattr +i`, `heavy_job_lock.sh`, and 12 orchestrator paths in -`check_and_enable_services.sh` / `setup_periodic_system.sh` that the flatten -already rewrote once. `setup_midnight_shutdown.sh` is `chattr +i` and is -excluded from two pre-commit fixer hooks **by path** — that exclude must move -with it, or the next commit fails on a file nothing can write. - -**3. Then close the loop:** delete `--warn` from the `directory-depth-cap` hook -entry in `.pre-commit-config.yaml`. That is the whole point of the campaign — -the cap only enforces once both units are gone. Verify with -`./meta/scripts/check_directory_depth.sh --all` exiting 0. - -## Constraints - -- Use the `extract-to-own-repo` skill; do not hand-roll the mechanics. -- **Sandbox-first**: both units are root/`/etc`/systemd/pacman territory, so - vmbox before the host (`vmbox-testing` skill). A vmbox pass never proves the - host is fine — report it as "passed in vmbox, not verified on the host". -- Never `--no-verify`. Every commit in this campaign has been green. -- `sudo -n` works and `guardctl` is at `/usr/local/bin/guardctl` — do not - hand me commands you can run yourself. -- Run `./meta/scripts/report_live_state.sh --check` **before and after** each - move. It scans `/usr/local/bin` too, where installed copies name repo paths - invisibly to a repo grep. There are already 8 known-stale references from the - earlier flatten; do not add more. -- Each commit needs an evidence artifact; 4+ staged code files (`.sh` counts, - `.json`/`.yaml` do not) also needs a contract. - -## Ask before doing (do not decide these yourself) - -- deleting `.hippo/` (161 tracked files; dead since 2026-05-28, but it is a - deletion) -- `rm -rf` on the 3.7 GB of untracked extraction residue (`focus_owner/`, - `bucket_catch/`, `kcd2_dice_solver/`, `billsplit/`) - -## Do NOT - -- attempt the Nextcloud dedup — measured and recommended against; it needs a - Raspberry Pi that cannot be reached from here, and only 3 of 15 libs have - tests. See item 3 of the status doc for the numbers. -- raise the 2G pytest cap if the push fails with "tests passed, then Killed". - That is the ci-mirror concurrency issue, already fixed; measure what runs - alongside instead. -- "sync" `.pre-commit-config.yaml` with `meta/.pre-commit-config.yaml`. They - are deliberately different files. - -## Done means - -`./meta/scripts/check_directory_depth.sh --all` exits **0** with `--warn` -removed from the hook, both units are their own repos with CI, the live-state -check adds no new stale references, and `main` is pushed clean. diff --git a/NEXT_SESSION_RESTRUCTURE.md b/RESTRUCTURE_HANDOFF.md similarity index 62% rename from NEXT_SESSION_RESTRUCTURE.md rename to RESTRUCTURE_HANDOFF.md index 80b3e4c3..a1126f86 100644 --- a/NEXT_SESSION_RESTRUCTURE.md +++ b/RESTRUCTURE_HANDOFF.md @@ -1,4 +1,99 @@ -# testsAndMisc restructure — where it stands +# testsAndMisc restructure — the only handoff file + +**This is the whole handoff. There is no second file to find.** + +- **To start work:** `/clear`, then paste from the line `## Prompt — paste +from here` down to `## Reference`. Or just paste the whole file — that works + too, and is the safer default. +- **Superseded:** the old `NEXT_SESSION_PROMPT.md` and + `NEXT_SESSION_RESTRUCTURE.md` were merged into this file on 2026-08-23. +- **Unrelated task:** `INSTALLER_FIX_TASK.md` is a different job + (`install_core_system.sh` on a fresh machine). Not part of the restructure. + +--- + +## Prompt — paste from here + +Extract `linux_configuration/periodic_background/hosts/` into its own repo, +then `digital_wellbeing/`. Everything you need is in this file — the +reference sections below the prompt are part of it. Read "Traps already paid +for" before touching anything; every line in it cost a real failure. + +## Start here + +```bash +cd ~/testsAndMisc +./meta/scripts/check_directory_depth.sh --all | head -1 # expect 46 +./meta/scripts/check_repo_size.sh # expect 1051/1200 +git status -sb # expect clean +``` + +If those three numbers do not match, something moved since 2026-08-23 — +find out what before extracting anything. + +## What to do + +**1. `hosts` first** (5 depth violations). It is unblocked: the guard repoint +landed on 2026-08-23, so no guard names a repo path any more +(`sudo guardctl file-guard status resolved` should print +`/usr/local/share/guard-lib-plugins/...`). Its installer was already proven in +vmbox to run from an extracted layout. + +**2. `digital_wellbeing` last** (41 violations). The hard one. It owns the +pacman wrapper, `chattr +i`, `heavy_job_lock.sh`, and 12 orchestrator paths in +`check_and_enable_services.sh` / `setup_periodic_system.sh` that the flatten +already rewrote once. `setup_midnight_shutdown.sh` is `chattr +i` and is +excluded from two pre-commit fixer hooks **by path** — that exclude must move +with it, or the next commit fails on a file nothing can write. + +**3. Then close the loop:** delete `--warn` from the `directory-depth-cap` hook +entry in `.pre-commit-config.yaml`. That is the whole point of the campaign — +the cap only enforces once both units are gone. Verify with +`./meta/scripts/check_directory_depth.sh --all` exiting 0. + +## Constraints + +- Use the `extract-to-own-repo` skill; do not hand-roll the mechanics. +- **Sandbox-first**: both units are root/`/etc`/systemd/pacman territory, so + vmbox before the host (`vmbox-testing` skill). A vmbox pass never proves the + host is fine — report it as "passed in vmbox, not verified on the host". +- Never `--no-verify`. Every commit in this campaign has been green. +- `sudo -n` works and `guardctl` is at `/usr/local/bin/guardctl` — do not + hand me commands you can run yourself. +- Run `./meta/scripts/report_live_state.sh --check` **before and after** each + move. It scans `/usr/local/bin` too, where installed copies name repo paths + invisibly to a repo grep. There are already 8 known-stale references from the + earlier flatten; do not add more. +- Each commit needs an evidence artifact; 4+ staged code files (`.sh` counts, + `.json`/`.yaml` do not) also needs a contract. + +## Ask before doing (do not decide these yourself) + +- deleting `.hippo/` (161 tracked files; dead since 2026-05-28, but it is a + deletion) +- `rm -rf` on the 3.7 GB of untracked extraction residue (`focus_owner/`, + `bucket_catch/`, `kcd2_dice_solver/`, `billsplit/`) + +## Do NOT + +- attempt the Nextcloud dedup — measured and recommended against; it needs a + Raspberry Pi that cannot be reached from here, and only 3 of 15 libs have + tests. See item 3 of the status doc for the numbers. +- raise the 2G pytest cap if the push fails with "tests passed, then Killed". + That is the ci-mirror concurrency issue, already fixed; measure what runs + alongside instead. +- "sync" `.pre-commit-config.yaml` with `meta/.pre-commit-config.yaml`. They + are deliberately different files. + +## Done means + +`./meta/scripts/check_directory_depth.sh --all` exits **0** with `--warn` +removed from the hook, both units are their own repos with CI, the live-state +check adds no new stale references, and `main` is pushed clean. + +--- + +## Reference — stop pasting here (the agent reads the rest itself) Plan: `~/.claude/plans/after-refactor-of-testsandmisc-modular-wigderson.md` Live-state checklist: `docs/restructure-live-state.md`