fix(kvb-cleanup): hand sandbox worktree removal to the operator
An agent sandbox mounts every .git/worktrees/<id> read-only, so git worktree remove unregisters the worktree and then fails with EBUSY; container-owned files fail with EACCES. The worktree rules now forbid removal inside the sandbox and hand the operator the ownership count, chown and removal command in one message. A dirty worktree is a candidate only when all its changed and untracked content is preserved at a branch tip, and an untagged image with RepoDigests counts as a medium-risk digest pull. Both files were trimmed so the skill text does not grow. 🎯 Fix: 92 % 💥 Break: 2 % 💸 Cost: 100 % ⏱️ Time: 100 % 🛡️ Security: 100 % 🏆 Score: 90 🚦 Gate: ✅ 90/5, cost and time <= 100, security 100 % Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
db3c5264f2
commit
fea80f40f7
2 files changed
+32
-33
No files matched your search
@@ -2,31 +2,25 @@
|
|||||||
|
|
||||||
## Inventory
|
## Inventory
|
||||||
|
|
||||||
`docker system df -v`; containers with state and compose project label,
|
`docker system df -v`: containers with state and compose project, volumes
|
||||||
volumes with the containers using them (`docker ps -a --filter
|
with their users (`docker ps -a --filter volume=<name>`), dangling and unused
|
||||||
volume=<name>`), dangling and unused images, build cache, unused networks.
|
images, build cache, unused networks. An untagged image with `RepoDigests`
|
||||||
For every stopped container (`exited`, `created`) record its volumes
|
is a digest-pinned pull: medium. Per stopped container its volumes
|
||||||
(`{{.Mounts}}`); for every volume no running container uses, record size,
|
(`{{.Mounts}}`); per volume without a running user its size, `CreatedAt` and
|
||||||
`CreatedAt` (`docker volume inspect`) and compose project label, anonymous
|
compose project, anonymous ones included.
|
||||||
ones included.
|
|
||||||
|
|
||||||
## Volumes checklist
|
## Volumes checklist
|
||||||
|
|
||||||
Stopped containers and volumes always get their own checklist
|
Stopped containers and volumes get their own checklist (`multiSelect: true`,
|
||||||
(`multiSelect: true`, header `⚠ Volumes`, in a further call when call 1 is
|
header `⚠ Volumes`, a further call when call 1 is full), each one unless a
|
||||||
full). Every stopped container and every volume without a running container
|
peer claimed it, `unknown` and anonymous ones included. Question text:
|
||||||
appears there unless a peer claimed it; none is dropped as "not proposed",
|
|
||||||
`unknown` and anonymous ones included. The question text carries the warning:
|
|
||||||
`Deleting a volume is irreversible; its data does not come back unless the
|
`Deleting a volume is irreversible; its data does not come back unless the
|
||||||
description says how.` One option per stopped container together with its
|
description says how.` One option per stopped container with its volumes,
|
||||||
volumes (removing the container alone frees nothing of them), one per
|
one per unattached volume, anonymous ones grouped; each names size,
|
||||||
unattached volume, anonymous ones grouped. Each description gives size,
|
`CreatedAt`, owner or project, and what is lost.
|
||||||
`CreatedAt`, owner or compose project, and what is lost.
|
|
||||||
|
|
||||||
## After removing images
|
## After removing images
|
||||||
|
|
||||||
Locally built images free little on their own: their layers stay behind as
|
Built images leave their layers as build cache: re-measure `docker system
|
||||||
build cache. Re-measure `docker system df`; the layers show up as reclaimable
|
df`, then offer `docker builder prune --filter until=24h`, after asking the
|
||||||
build cache. Offer `docker builder prune --filter until=24h` as a follow-up
|
peers that claimed build cache, outside their builds.
|
||||||
candidate, ask the peers that claimed build cache first, and run it outside
|
|
||||||
their running builds.
|
|
||||||
@@ -2,20 +2,25 @@
|
|||||||
|
|
||||||
## Inventory
|
## Inventory
|
||||||
|
|
||||||
Per worktree: size (`du -sh`), dirty state (`git status --short`), whether
|
Per worktree: size (`du -sh`), dirty state, whether its branch is pushed and
|
||||||
its branch is pushed, and whether its HEAD is already contained in an
|
whether its HEAD is in an integration line (the default branch and every
|
||||||
integration line: the default branch and every branch the project merges
|
branch the project merges features into; ask the operator or the project's
|
||||||
features into (ask the operator or the project's memory which ones). With
|
memory). With `pkgmgr`, `pkgmgr branch gc --json --sizes --merged-into
|
||||||
`pkgmgr` installed, `pkgmgr branch gc --json --sizes --merged-into <line>`
|
<line>` (one per line) measures it all; merged-clean items go to the
|
||||||
(one per line) measures all of it; its merged-clean items go to the
|
|
||||||
`kvb-git-branch-gc` skill.
|
`kvb-git-branch-gc` skill.
|
||||||
|
|
||||||
A clean worktree whose HEAD is in an integration line is medium risk: its
|
Clean and in a line: medium, its ignored files (`node_modules`, build output,
|
||||||
ignored files (`node_modules`, build output, evidence) are lost, no commit.
|
evidence) are lost. Dirty: a candidate only when every changed, staged and
|
||||||
|
untracked file is a blob at some branch tip and a detached HEAD is reachable
|
||||||
|
from another ref; else it is unique work and stays.
|
||||||
|
|
||||||
## Removal
|
## Removal
|
||||||
|
|
||||||
Remove a worktree the way it was made: a slot worktree through the project's
|
The way it was made: a slot worktree through the project's teardown target
|
||||||
teardown target (e.g. `make worktree-down`), run outside the sandbox; a plain
|
(e.g. `make worktree-down`), a sidetree through `git worktree remove`,
|
||||||
sidetree through `git worktree remove` without `--force`, which refuses a
|
`--force` only for a dirty one cleared above. Never in an agent sandbox: its
|
||||||
dirty tree.
|
read-only `.git/worktrees/<id>` mounts make git unregister and then fail with
|
||||||
|
`Device or resource busy`, container-owned files with `Permission denied`.
|
||||||
|
Hand the operator in one message, per worktree, its count of `find <wt> -not
|
||||||
|
-user "$USER" -prune | wc -l`, `sudo chown -R "$USER": <wt>` where it is not
|
||||||
|
0, then the removal command.
|
||||||
Reference in new issue
Block a user