I3832 — majordomus worktree sweep removes merged, clean, idle worktrees, never with force, and announces each on the mesh
Add a typed capability worktree.sweep (CLI `majordomus worktree sweep`, --check and --apply) that lists, and with --apply removes through `git worktree remove` without --force, every linked worktree whose head is an ancestor of origin/master but not its tip, whose status is empty, with no file modified within the idle window, no process cwd or open file inside it, not named in the derive lock's owner, a mesh claim or a CARGO_*_DIR of a running process; branches are kept, and each removal is announced on the mesh.
READY wave 0 · p2 · implementation profile · parallel safe
Ready. Every dependency is done, so majordomus plan start I3832 will be accepted.
Objective
Add a typed capability worktree.sweep (CLI `majordomus worktree sweep`, --check and --apply) that lists, and with --apply removes through `git worktree remove` without --force, every linked worktree whose head is an ancestor of origin/master but not its tip, whose status is empty, with no file modified within the idle window, no process cwd or open file inside it, not named in the derive lock's owner, a mesh claim or a CARGO_*_DIR of a running process; branches are kept, and each removal is announced on the mesh.
Why
The owner's relaxation of 2026-10-21 (I3824 clause 8): cleanup runs without asking. On 2026-10-20 the machine went from 32 GiB to 115 GiB free by hand, and 106 such worktrees of this repository (18 GiB) were left because the removal had no named capability the owner could allow.
Current state
scripts/reap-orphans reclaims build output only; removing a worktree is a hand-written loop.
Desired state
One capability, the same on every machine, that the owner can allow by name; --check is read-only.
Scope
- apps/majordomus-cli/src/capability/builtin/worktree.rs
- apps/majordomus-cli/src/worktree
- share/commands.yaml
- docs/WORKTREES.md
Out of scope
- Changing which checks CI requires
- Claude Code permission settings, which are the owner's to paste
Dependencies
None. This issue is a root of the graph.
Acceptance criteria
- --check lists each candidate with the guard that admitted it and each excluded worktree with the guard that kept it, and writes nothing
- --apply removes exactly the listed candidates with git worktree remove without --force and keeps their branches
- A worktree that is dirty, at master's tip, unmerged, recently modified, occupied by a process, named in the derive lock or a mesh claim is never removed
- Each removal is one mesh announcement naming the path and branch
- A removal holds the directory's cargo lock, or an flock over it, for the whole rm: a build started on the directory mid-sweep either completes or finds the directory intact (a3 and 0c, 2026-10-21; the same criterion as I2881)
- A worktree or build directory named by a live cargo or rustc, on its command line or in its CARGO_BUILD_BUILD_DIR or CARGO_TARGET_DIR (ps -Eww), or holding a cargo lock file is never removed, even when its mtime and lsof pass: a cargo between start-up and its first write is invisible to both (a3, 2026-10-21, a private build dir deleted under 9c's starting build)
Validation
- bash test/run.sh 3832_merged_idle_worktrees_are_swept
- bin/majordomus plan validate
Evidence required
- merged_idle_worktrees_are_swept_test
Evidence
None recorded. Every token above needs a command or an artifact behind it before this issue can be completed; narrative is refused.
Timeline
- started
- —
- verified
- —
- completed
- —
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I3832.yaml. Read it back with majordomus plan show I3832.