fix(branch ensure-feature): treat sibling-worktree checkout as success (#211) - #479
Merged
PolyphonyRequiem merged 1 commit intoMay 19, 2026
Merged
Conversation
#211) Under the parallel-fleet apex convention a feature branch may be checked out in a sibling worktree (e.g. polyphony-item-3043) when `branch ensure-feature` is invoked from another worktree. The verb then ran `git checkout <branch>` unconditionally, which git refuses with exit 128 and stderr `fatal: '<branch>' is already used by worktree at '<path>'`. `CheckoutAsync` threw `ExternalToolException`, the outer catch wrapped it as `CacheError`, and the workflow exploded even though the only thing the verb cares about — the branch's existence — was already satisfied. This commit narrows the catch around the `CheckoutAsync` call and recognises that specific stderr via a partial regex. On match we treat the branch as present (existence satisfied), surface the sibling worktree path on a new `WorktreePath` envelope field, set `Action=exists_in_other_worktree`, and keep the existing push step intact for the `!remoteExisted` case (push works regardless of which worktree owns the checkout). Unrelated checkout failures still propagate to the outer catch and emit `CacheError` unchanged. The new field is additive — `WorktreePath` is nullable, only set on the new action — so consumers that ignore it keep working. Tests cover all four state combinations plus the three AB#211 paths (sibling-worktree happy path, sibling-worktree + remote-absent push, generic checkout failure still errors). Closes #211 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PolyphonyRequiem
deleted the
fix/issue-211-ensure-feature-sibling-worktree
branch
May 19, 2026 21:00
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Under the parallel-fleet apex convention the apex spawns sibling
worktrees per item (
polyphony-item-3043,polyphony-item-9001,…) all backed by the same shared bare repo. When
polyphony branch ensure-featureruns from one worktree and the target feature branchis already checked out in a sibling,
git checkout <branch>refuseswith exit 128:
GitClient.CheckoutAsyncthrowsExternalToolException, theouter
catchinEnsureFeaturewraps it asCacheError, andthe workflow tips over — even though the verb's sole job (make sure
the branch exists) is already satisfied.
Fix
Per #211 Option 1 (idempotent success):
try/catcharound theCheckoutAsynccall inside thelocalExistedbranch.ExternalToolException.Stderragainstis already used by worktree at '<path>'via a partial regex.path on a new
WorktreePathenvelope field, setAction = "exists_in_other_worktree", and keep the existing pushstep intact for
!remoteExisted(git pushoperates on refsand is unaffected by which worktree owns the checkout).
exit
CacheErrorunchanged.Envelope shape
BranchEnsureFeatureResult.Actionnow includesexists_in_other_worktree.WorktreePathis the new nullablefield, populated only on that path. Consumers that ignore it keep
working — fully additive.
Tests
New
BranchCommandsEnsureFeatureTests(7 tests, all green):checked_out, no pushexists_in_other_worktree+WorktreePath, no pushCacheError(regression guard)--branch→RoutingFailureValidation
dotnet test tests/Polyphony.Tests— 3836 passed, 0 failedInvoke-Pester tests/lint-jinja-resolver.Tests.ps1— 30 passedtests/lint/fixtures/verb-output-schemas.json— surgical insertof the new
worktree_pathfield per thehand-curated-fixture convention
Closes #211