live: heartbeat sync 2026-10-30T15:20:04-07:00 (Refs #11)

This commit is contained in:
Frank committed 2026-10-30 15:20:04 -07:00
1 parent ad5903c294
commit 9f142b7eaf
14 files changed
+233 -33

No files matched your search

@@ -1,9 +1,9 @@
---
name: agenttrash-purger-invocation
description: "Invoke the .AGENTTRASH purger (scripts/purge-agenttrash.sh) to clear staged deletions, and diagnose its two refusal traps: a false stale-lock error on a full filesystem, and $HOME refused on dankserver by podman-storage permission denials."
description: "Invoke the .AGENTTRASH purger (scripts/purge-agenttrash.sh) — plus its two refusal traps: ENOSPC masquerading as a stale lock, and an unreadable container-storage directory poisoning the whole root scan."
---
# Purging .AGENTTRASH — invocation and two refusal traps
# Purging .AGENTTRASH — invocation, and the two traps that make it refuse
`scripts/purge-agenttrash.sh` (serverAppConfigs, merged in PR #79 `fad87aa`) is the tool form of the fleet's deletion policy: files land in `.AGENTTRASH`, and an approved purge runs this instead of being improvised per session.
@@ -15,25 +15,28 @@ sh scripts/purge-agenttrash.sh --execute # perform the plan
sh scripts/purge-agenttrash.sh --execute /some/root # scope to one root (default: $HOME)
```
- `--quiet` silences per-line output; errors and the summary still print. `--log PATH` overrides the default `~/.AGENTTRASH-cleanup.log` (one dated line per run — written even for a dry run, so pass a scratch `--log` when you only want to look).
- `--quiet` silences per-line output; errors and the summary still print. `--log PATH` overrides the default `~/.AGENTTRASH-cleanup.log` (one dated line per run — written even for a dry run).
- Every printable line is fixed at plan time in `$HOME/.agenttrash-purge.lock/plan`, so dry-run and `--execute` output cannot drift. Exit `0` ok · `1` any refusal or failure · `2` usage.
- Rule: a root's own `.AGENTTRASH` is *emptied* (the directory survives); deeper `.AGENTTRASH` trees are *removed*; symlinked or foreign-owned candidates are refused, never followed; `/` is refused outright.
- Deleting a big staged item by hand (e.g. `find <dir> -depth -delete`) is the fallback **only** when the tool cannot run at all — see trap 1 — and the operator's purge approval covers exactly that.
## Trap 1: a FULL filesystem makes it lie about a lock
## Trap 1: a full filesystem makes it lie about a lock (measured 2026-10-30)
The script acquires `~/.agenttrash-purge.lock` and writes a plan file **before** it scans. On a filesystem with 0 bytes free both writes fail `ENOSPC`, and the run dies with:
With **0 bytes free**, three invocations refused with
```
purge-agenttrash: /home/…/.agenttrash-purge.lock exists and is not ours to reclaim
purge-agenttrash: refused /home/<user>: exists and is not ours to reclaim
```
while **no lock exists** (`find <root> -maxdepth 2 -name '.agenttrash-purge.lock'` comes back empty, `pgrep -af purge-agenttrash` shows nothing). Do not hunt the phantom lock and do not delete anything to "reclaim" it: check `df -h` first. Free space by the purge's own intended action — delete the staged item the operator approved (a same-filesystem `mv` into `.AGENTTRASH` frees nothing; only deletion does) — then re-run the tool, which will clean the rest and log its summary.
and no lock directory existed anywhere. The script writes its lock *and* its plan file before scanning; both hit `ENOSPC`, and the failure surfaced as the lock-reclaim message. There is nothing to reclaim — **free space first** (delete the staged item, move it to another volume, `journalctl --vacuum-size=`), then run plan + `--execute`. Never hunt a phantom lock because the message says so; check `df` first.
## Trap 2: `$HOME` is always refused on dankserver
## Trap 2: an unreadable directory spoils the whole root
`sh scripts/purge-agenttrash.sh` on dankserver reports `refused /home/dank (find failed)` and exits 1 even though the plan is otherwise right, and `~/.AGENTTRASH-cleanup.log` records `refused=1` beside whatever it did manage.
`collect_root` turns any nonzero `find` status into a root refusal, so the plan is built from a partial scan and the root reports `refused=1` even though `find` printed every `.AGENTTRASH` it found.
- Cause: `find /home/dank -xdev -name .AGENTTRASH` exits 1 there because rootless podman storage contains UID-mismatched directories — `~/.local/share/containers/storage/overlay/*/diff/var/lib/mysql`, `…/etc/valkey`, `…/.config/calibre/plugins`, `…/var/cache/apt/archives/partial` — plus `~/Containers/romm/mariadb/*`. `collect_root` turns any nonzero find status into a root refusal, so a *partial* scan becomes no plan.
- Find still prints every real tree (14 on dankserver: `vLLM/`, `Containers/`, four under `serverAppConfigs`, the swift15 checkout), so the refusal is about the scan status, not the candidates.
- This is the same class as the uutils-find trap on the dev box, with a different cause (GNU find + foreign-owned overlay internals). Minimal fix, safe because a `.AGENTTRASH` never lives inside container storage: prune `-path "$HOME/.local/share/containers"` from the scan, or accept find's partial output and reserve the refusal for a hard find failure. Verify with `sh -n`/shellcheck, not `bash -n`.
- Do not run the purger with `sudo` to dodge this: candidates are judged by ownership, and a root-owned scan changes the refusal outcome rather than fixing it. Retire the blocker, then re-run as the deploy user.
- On the dev box the cause is uutils find (`find --version` → `find 0.8.0`), which exits 1 on `~/.local/share/containers/storage/**`. Proof: `find /home/blank -xdev -name .AGENTTRASH >/dev/null 2>&1; echo $?` → `1`, while a narrower root → `0`.
- On **dankserver** GNU find does the same, because rootless podman storage holds foreign-UID directories (`overlay/*/diff/var/lib/mysql`, `valkey`, `calibre/plugins`, `apt/.../partial`): `find /home/dank -xdev -name .AGENTTRASH 2>&1 >/dev/null | head` shows the denials.
- Fix to land in the script (not to improvise around): prune `~/.local/share/containers` from the scan — a `.AGENTTRASH` never lives inside container storage — or accept partial output and reserve refusal for a hard find failure. `sh -n` / shellcheck is the gate; `bash -n` is not.
## Verified good path (dankserver, 2026-10-30)
After freeing space by hand: `/tmp`-scoped plan → `--execute` deleted the staged item and reported `removed=1 deleted=1`; a second `--execute /mnt/entropy` cleaned that volume's root (`refused=0`). The cleanup log carries one dated line per run; read it instead of re-deriving what happened.