bfd9cef389
The installer clones with --depth 1, so every default install is shallow. In a shallow repo, an older worktree HEAD (a past snapshot of main) is disconnected from current origin/main by the shallow boundary, so 'git log HEAD --not --remotes' misreports thousands of already-public commits as unpushed. The fail-safe unpushed guard then preserves every aged 'hermes -w' worktree forever, and the git-cherry squash-merge escape hatch never rescues them (22k 'ahead' >> max_ahead=20). Real incident: 21 of 25 hermes-* worktrees stuck on one install. Fix at the root, one owner: - _deepen_shallow_repo(): one-time blobless unshallow (fetch --unshallow --filter=blob:none; plain --unshallow fallback) run from the background startup pruner thread before classification, so history verdicts become correct and the backlog self-clears on the next 'hermes -w' startup. Fail-soft offline: keep preserving. - _cleanup_worktree(): when the unpushed verdict comes from a shallow clone, say 'Shallow clone — cannot verify push state' instead of the misleading 'has unpushed commits' message. - Document the shallow caveat on _worktree_has_unpushed_commits (the primitive stays conservative on purpose). Tests: real shallow clone over file:// reproducing the disconnect shape, covering detection, deepen+verdict flip, pruner E2E reap, offline fail-soft preserve, full-clone noop, and genuine-unpushed-work survival. Sabotage-verified: the E2E test fails with the deepen call disabled.