Skip to content

fix: prune maintenance — the pool HEAD's branch config is not an orphan - #36

Merged
zheng-weihao merged 2 commits into
orbcli:mainfrom
zheng-weihao:prune-empty-default-guard
Aug 14, 2026
Merged

fix: prune maintenance — the pool HEAD's branch config is not an orphan#36
zheng-weihao merged 2 commits into
orbcli:mainfrom
zheng-weihao:prune-empty-default-guard

Conversation

@zheng-weihao

Copy link
Copy Markdown
Member

Problem

Pool maintenance's orphan-config reap (orbit prune's closing sweep) judges a branch.<name>.* section purely by ref existence. For an empty repo, the clone-written default-branch section (e.g. branch.master.*) can never have a ref — the branch is unborn by definition — so every bare orbit prune reaps it, even though that section is the pool's live first-push routing (upstream wiring for the first git push), not residue.

The checked-out-branch guard from #33 deliberately left the pool's own checkout unprotected ("stays reapable"). That is fine for genuine residue but misfires on healthy empty repos: the default section is reaped while the repo sits there legitimately unborn.

Change

Exempt the branch named by the pool's HEAD symref (git symbolic-ref --short HEAD) from the orphan-config reap:

  • Tracks HEAD, so it cannot leak. The protection self-releases when HEAD moves (pool switches defaults) or when a ref materializes (first push) and the ordinary ref check takes over. The only case kept forever is a HEAD that stays on an unborn branch — which is exactly the live line being protected.
  • Invisible in non-empty repos — the ref check already keeps the checked-out default there.
  • Name-agnostic — the signal is the HEAD symref, not a hardcoded master/main.
  • Documented premise: no orbit command ever detaches the pool's HEAD (sync only fetches; add/switch only touch worktrees), so the symref read always names the default branch; on a detached HEAD the exemption silently no-ops.

Verification

  • tests/09_prune.bats 101/101 green:
    • the two empty-repo cases updated to the new criterion (while the worktree lives, both the scoped section and the clone-written default section survive; after the workspace is reclaimed, the scoped section is reaped and the pool default is kept);
    • new case pins the behavior with a non-main default branch (dev).
  • Sandbox: two empty remotes (HEAD master / dev) — default sections survive, an injected genuine-orphan section is still reaped, scoped worktree sections untouched.

Docs: docs/spec-warnings.md criterion row and docs/spec-lifecycle.md orphan-config bullet restated to the HEAD-target semantics.

The orphan-config reap judged sections purely by ref existence, so an empty repo's clone-written default section (its branch is unborn by definition) was reaped on every bare prune — yet that section is the pool's live first-push routing, not residue.

Exempt the branch named by the pool's HEAD symref (git symbolic-ref --short HEAD). The protection tracks HEAD: it self-releases when HEAD moves or when a ref materializes. In non-empty repos it is invisible, since the ref check already keeps such sections. Premise (documented in code): no orbit command ever detaches the pool HEAD, so the symref always names the default branch; on a detached HEAD the exemption silently no-ops.

bats: the two empty-repo cases updated to the new criterion (scoped + default sections survive while the worktree lives; after reclaim only the scoped section is reaped) and a new case pins the behavior with a non-main default (dev). tests/09_prune.bats 101/101 green. Docs: spec-warnings criterion and spec-lifecycle orphan-config bullet restated.
Signed-off-by: Zheng Weihao <zheng-weihao@outlook.com>
…li#36)

Signed-off-by: Zheng Weihao <zheng-weihao@outlook.com>
@zheng-weihao
zheng-weihao merged commit 68a4aa5 into orbcli:main Aug 14, 2026
2 checks passed
@zheng-weihao
zheng-weihao deleted the prune-empty-default-guard branch August 24, 2026 11:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant