f309f92d30
The startup pruner is deliberately conservative (unattended, pre-banner), so real installs accumulate what it can never touch: trees preserved for untracked-only scratch, and orphaned local branches beyond the two auto-generated prefixes it deletes. A measured multi-agent box: 35 trees / 15GB / 244 local branches, 120 of them fully merged. New attended surface (hermes_cli/worktree_gc.py + worktree_cmd.py): - hermes worktree list — audit every tree: age, size, verdict, reason, plus deletable-branch count - hermes worktree prune [--dry-run|--trees-only|--branches-only] - /worktree prune [--dry-run] — same engine in-session; never touches the session's own active tree - startup escalation: one WARNING when .worktrees/ exceeds 10 trees or 5GB, naming the reclaim commands (silence is how boxes hit 15GB) Safety invariants (shared with the startup pruner via cli.py primitives): tracked modifications and unique unpushed commits never deleted at any age; live-locked trees untouched; branch deletion gated on worktree removal success; untracked-only scratch ARCHIVED to ~/.hermes/archive/worktree-prune/ before its tree is reaped. Branch GC is content-gated, not name-gated: any local branch fully merged or git-cherry patch-equivalent upstream is safe to delete (rebase merges rewrite SHAs, so --merged alone misses the dominant leak); unique-commit, checked-out, protected, and stale-base (>50 ahead) branches are kept. Classification is parallel (8 workers) — 244 branches audit in ~64s live. git timeouts degrade to keep (returncode 124) instead of crashing the audit — live-verified failure on a 746MB .git repo. 16 behavior-contract tests against real git fixtures; live dry-run on the production repo: 12 trees reclaimable, 120 branches deletable, 0 false positives among kept trees.