Skip to main content

tk-merge

Open the merge stage -- per PR in dependency order, fast-forward master onto the reviewed green head, push it, retarget stacked children, delete the branch, close the issue and delete its plan. Invoked by the owner after reviewing the diffs; the invocation is the owner's yes on the code.

Source facts

Repository
solatis/trapperkeeper
Last source activity
October 31, 2026 at 11:25
Detected SKILL.md language
English
Stars
0
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
tk-merge
description
Open the merge stage -- per PR in dependency order, fast-forward master onto the reviewed green head, push it, retarget stacked children, delete the branch, close the issue and delete its plan. Invoked by the owner after reviewing the diffs; the invocation is the owner's yes on the code.
disable-model-invocation
true
argument-hint
[#n ... , issues or PRs to merge; empty means every PR of this session's unit]
# /tk-merge -- the merge stage Run `/tk-workflow` first. An argument, when the owner gave one, is: <issues> $ARGUMENTS </issues> The PRs to merge are those of the issues the argument names (an issue number or a PR number), else those the build-stage message of this session names. With neither, stop and ask. ## Entry check Current branch: !`git branch --show-current` Working tree (empty means clean): !`git status --short` Master vs origin, commits ahead / behind (0 0 means in sync): !`git fetch -q origin 2>/dev/null; git rev-list --left-right --count master...origin/master` Plans on this machine: !`grep -H -E -r --include='*-plan.md' '^(Issue|Branch|Base|Status):' .plans 2>/dev/null || echo none` Open pull requests, with the head SHA and the state of each check on it: !`gh pr list --state open --json number,headRefName,baseRefName,headRefOid,statusCheckRollup --jq '.[] | "#\(.number) \(.headRefName) -> \(.baseRefName) \(.headRefOid[0:12]) \([.statusCheckRollup[]? | "\(.name)=\(.conclusion // .status)"] | join(" "))"' 2>&1 || true` CI workflows in the tree (empty means no CI): !`ls .github/workflows/ 2>/dev/null || true` The tree is clean, master is in sync with origin, and for each PR to merge: it is open; its head SHA on GitHub is the local branch's head (`git rev-parse <slug>`); and with CI in the tree, every check on that head is `SUCCESS`, `SKIPPED` or `NEUTRAL`. The checks are read from the list above or from `gh-watch.sh <sha>` (exit 0), never from the conversation: a build-stage message that says green is a claim, and GitHub is the evidence. Anything else (a dirty tree, a head that differs, a check `IN_PROGRESS`, `QUEUED` or `FAILURE`, a PR whose base is a branch not being merged in this run) is a stop for that PR and for every PR stacked on it; say which, and the owner decides. The others proceed. ## Step by step For each PR, in landing order (a PR after the PR its base branch belongs to): 1. Make it a fast-forward. When master moved since the branch was cut (an independent PR merged before it), `git merge-base --is-ancestor master <slug>` fails: rebase it onto master (`git rebase master <slug>`), then `git range-diff master <old head> <slug>` must show every commit unchanged in content. A conflict, or a commit whose content changed, is a stop: the reviewed code is no longer the code that would merge. Otherwise `git push --force-with-lease`, and with CI wait for the new head with `gh-watch.sh` (exit 0; exit 3 means rerun with the same SHA) before going on. A stacked PR whose parent was fast-forwarded in this run is already a fast-forward. 2. Fast-forward and publish, with the github skill's "Fast-forward merge": ``` git checkout master git merge --ff-only <slug> git push origin master ``` No merge commit, ever. A rejected push (origin moved, a ruleset that wants checks this head lacks) is a stop: report it; never force. 3. Verify: `gh pr view <n> --json state -q .state` is `MERGED`. When it is not, report it and leave the PR, the branch and the issue as they are. 4. Retarget every open PR whose base is this branch, before the branch goes: `gh pr edit <child> --base master`. 5. Delete the branch locally and on origin: `git branch -d <slug> && git push origin --delete <slug>`. 6. Close the issue: `gh issue close <issue> -c "Landed in #<n>"`. 7. Delete the plan: `rm .plans/<slug>-plan.md`. Every reason it carried is in the code or the documents; the build stage's check made sure of that. Close with one line per PR: `<slug>: #<pr> merged, <n> commits, <first sha>..<last sha>, issue #<issue> closed`, plus "rebased first" when step 1 rebased, and one line per PR that stopped, with the reason. Correct: logging (#20) and metrics (#21, stacked on logging) are green and approved. You fast-forward master to logging's head, push, see #20 MERGED, retarget #21 to master, delete `server-logging`, close #12, delete its plan; metrics is now a fast-forward of master, so you merge it the same way. Incorrect: you delete `server-logging` before retargeting #21, and GitHub closes #21. Or: the build-stage message said green, the list shows a check `IN_PROGRESS`, and the merge runs on the message. Or: the push is rejected and you retry with `--force`.
View on GitHub