Skip to content

fix: make land-* post-merge cleanup worktree-aware#206

Merged
aagnone3 merged 4 commits into
mainfrom
claude/workflows-work-9d13fe
Jul 19, 2026
Merged

fix: make land-* post-merge cleanup worktree-aware#206
aagnone3 merged 4 commits into
mainfrom
claude/workflows-work-9d13fe

Conversation

@aagnone3

Copy link
Copy Markdown
Collaborator

Closes #182

Summary

  • Reworks the merge-verification and post-merge cleanup of the three land-* skills (land-pr, land-docs, land-plan-docs) so they branch on worktree context instead of assuming the default branch can be checked out in the current tree. In the worktree-first workflow this plugin promotes, the default branch is held by the primary tree, so git checkout <default> from a linked worktree fails and the documented success criteria were unreachable — the git-worktree and land-pr skills contradicted each other on every merge.
  • land-pr (fix(land-pr): worktree-safe merge-verify + post-merge cleanup #183): step 5 now verifies the merge from server state (gh pr view --json state,mergedAt), documenting that fatal: '<base>' is already used by worktree after a merge means local cleanup failed, not the merge — do not retry. Step 6 is a context-aware three-leaf decision tree (classic single-tree / current linked worktree / feature-branch-held-elsewhere) built on a canonical is_linked_worktree predicate, resolves the base from the PR (baseRefName, not repo default / origin/HEAD), and points local teardown at gc_worktrees with both coverage caveats documented. Success criteria and the report step are forked by mode.
  • git-worktree (docs(git-worktree): companion note on land-* teardown deferral to gc #184): a companion note near the gc docs cross-references that the land-* skills defer teardown to gc, spelling out gc's two coverage limits (can't self-reap the active worktree; only reaps $GIT_ROOT/.worktrees/).
  • land-docs + land-plan-docs (fix(land-docs,land-plan-docs): extend worktree-safe cleanup pattern #185): the same worktree-safe treatment in setup and cleanup, reusing the byte-identical is_linked_worktree predicate (verified by hash across all three skills), and repairs land-plan-docs's half-converted BASE handling.

Key decisions (from the plan)

  • Merge signal is state-based, never stderr/exit-code matching (locale/version fragile).
  • Base resolved from the PR, not the repo default.
  • Teardown is legitimately deferred under worktrees, not done — reported explicitly, never silently claimed. .claude/worktrees/ (harness worktrees, including this run) is outside gc's scope and needs a manual git worktree remove.
  • allowed-tools unchanged; gc is referenced in prose only. Classic single-tree behavior is preserved verbatim.

Testing

Post-Deploy Monitoring & Validation

This is a docs-only change to skill markdown (prose + bash recipes) — no product code, no runtime service, no deploy surface.

  • What to monitor/search: N/A at the service level. The observable behavioral signal is in future land-* runs from linked worktrees.
  • Expected healthy behavior: an agent following git-worktree + land-pr together lands a PR from a linked worktree with no false-failure retry and no unreachable success criterion; worktree-mode runs report deferred teardown (naming the worktree + branch left for gc / manual removal).
  • Failure signal / rollback trigger: any land-* run still recommending git checkout <default> from a context where the default is held elsewhere, or reporting cleanup "done" while a worktree/branch remains. Trigger → git revert the docs commits (pure markdown, no state to unwind).
  • Validation window & owner: first land from a worktree after merge; owner: skill maintainers.
  • No additional operational monitoring required: docs-only change with no production/runtime impact.

Before / After Screenshots

N/A — no UI changes (skill markdown only).


Compound Engineered 🤖 Generated with Claude Code

aagnone3 added 4 commits July 18, 2026 12:30
Rework land-pr steps 5-6 and Success criteria to branch on worktree
context: state-based merge verification, canonical is_linked_worktree
predicate, base resolved from the PR, a three-leaf cleanup tree, and
teardown deferred to gc_worktrees with both coverage caveats. Classic
single-tree path is unchanged. Also materializes the join-keyed plan doc
for #182.

Closes #183
…worktree gc note

Reuse the canonical is_linked_worktree predicate (byte-identical to
land-pr) in land-docs and land-plan-docs: make setup and cleanup
context-aware (no checkout of a held default from a linked worktree;
git fetch + defer teardown to gc), and repair land-plan-docs's
half-converted BASE handling. Add a companion note to git-worktree
cross-referencing the land-* teardown deferral and gc's coverage limits.

Closes #184
Closes #185
Clarify that the held-in-another-worktree guard runs before any
git branch -d, including Leaf A's, per the AC pre-check note.
… cleanup recipes

Address /workflows-review findings on PR #206:
- P1: land-docs/land-plan-docs green-path cleanup called is_linked_worktree
  from a separate Bash invocation (function out of scope -> exit 127 ->
  wrong else-branch checkout that fails in a worktree) and led with 'if'
  (breaks the unattended allowed-tools first-token contract, gotcha #3).
  Replace with land-pr-style separate git-leading leaves, predicate
  evaluated in prose.
- P2: reframe land-pr step 6 as two paths + a shared pre-delete guard
  (Leaf C was a cross-cutting guard, not a mutually-exclusive leaf).
- P3: land-pr Leaf C guard uses whole-line grep -qxF.

Findings recorded in todos/005-008.
@aagnone3
aagnone3 merged commit 81fd876 into main Jul 19, 2026
7 checks passed
@aagnone3
aagnone3 deleted the claude/workflows-work-9d13fe branch July 19, 2026 00:47
@github-actions github-actions Bot mentioned this pull request Jul 18, 2026
aagnone3 added a commit that referenced this pull request Jul 19, 2026
…#3) (#208)

The "detect an existing PR before branching" section led its decision with
a standalone `if [ -n "$EXISTING" ] ...` block. Claude Code matches a skill's
`allowed-tools` (Bash(gh *), Bash(git *), Read) by the pipeline's FIRST token,
and `if` is not allow-listed — so an unattended run could stall on a permission
prompt (the same class fixed for the cleanup recipes in PR #206 / issue #182,
which predated this block).

Fold the null-check into the `gh pr list --jq` with `// empty` so the recipe
leads with `gh` (covered by Bash(gh *)), and evaluate the existence decision in
prose — mirroring how PR #206 resolved the cleanup recipes (command-leading
leaves, predicate evaluated in prose). allowed-tools unchanged.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
aagnone3 added a commit that referenced this pull request Jul 19, 2026
Captures two learnings from PR #206: the worktree-aware merge-verify +
cleanup pattern for land-* skills, and the shell-function-scope trap where
a predicate defined in one fenced recipe block does not survive into
another (each block is its own shell). Markdown only — no code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
aagnone3 added a commit that referenced this pull request Jul 19, 2026
…ly, not --repo (#210)

`gh repo view --repo "$ORIGIN"` fails with "unknown flag: --repo" (gh has no
-R/--repo on `repo view`; the repo is a positional arg — unlike gh pr/issue/api).
It empties BASE and breaks BASE resolution in both land-docs and land-plan-docs.

The wrong form originated in the land-plan-docs-gh-git-boundary-gotchas solution
doc's own §2 "fix" recipe and was copied into both skills (land-docs in #206,
land-plan-docs in #173). Correct all three to the positional form and teach the
distinction in the gotchas doc.

Discovered while running the compound data lane for #182.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
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.

land-pr post-merge cleanup breaks under the worktree-first workflow (checkout of held default branch)

1 participant