Skip to content

BranchPruner

Defined in: src/branch-pruner.ts:25

Hourly janitor that deletes local shepherd/* branches whose PR has merged.

The merge train squash-merges (gh pr merge --squash --delete-branch), which deletes the remote branch but leaves the local branch’s tip a non-ancestor of main — so WorktreeMgr.pruneMergedBranch’s --is-ancestor check never fires and the branch lingers forever (worse: at merge time the session still holds the worktree, so nothing could delete it then anyway). This sweep is the deferred cleanup: it asks the forge whether each branch’s PR merged, which is authoritative regardless of merge method.

Orphan branches only — a branch checked out in any worktree, or owned by an active session, is never touched; nor is a branch whose PR isn’t merged (open/closed/none, or a forge/gh error, all mean “keep”).

new BranchPruner(store, resolveForge, extraRepos?, intervalMs?, maxChecksPerTick?): BranchPruner

Defined in: src/branch-pruner.ts:29

Pick<SessionStore, "list" | "getSetting">

(repoPath) => GitForge | null

() => string[]

Durable repo source unioned with the session-derived set. Session housekeeping prunes old archived rows, so a fully-idle repo can drop out of store.list() entirely — without this its leftover shepherd/* branches would never be swept again. Defaults to none (tests / callers that don’t wire it).

number = ...

number = 20

Max forge lookups per sweep. Each forge.prStatus is an async gh subprocess (non-blocking). This cap bounds the number of concurrent/ sequential gh calls per tick (and associated GitHub API load), not event-loop stall time. Raise to drain faster, lower to reduce API pressure; the backlog drains across subsequent hourly ticks regardless.

BranchPruner

start(): void

Defined in: src/branch-pruner.ts:180

void


stop(): void

Defined in: src/branch-pruner.ts:184

void


tick(): Promise<void>

Defined in: src/branch-pruner.ts:150

Promise<void>