| name | rdm-land |
| description | Land a reviewed rdm item to `main` with linear history (rebase + merge --ff-only), re-running CI-equivalent checks first, then clean up its worktree — aborting and escalating on conflict or failure instead of force-merging |
| allowed-tools | ["Read","Bash","Glob","Grep","Agent"] |
Land one reviewed rdm item onto main with linear history and then clean up after it. This is the landing tail of autonomous execution: rdm-dispatch-phase / rdm-autopilot drive an item to reviewed on its roadmap/<slug> (or task/<slug>) branch but deliberately never touch main. This skill performs that final, consequential integration — rebasing the branch onto main and fast-forwarding — so the existing Done:-line post-commit hook flips the item reviewed → done.
IMPORTANT: This is the rdm source repo. Always run cargo build first, then use ./target/debug/rdm — never bare rdm. If you modify any rdm source, cargo build again before running it.
Contract
Input ($ARGUMENTS): an item ref — <roadmap>/<phase>, task/<slug>, or a bare <roadmap> (lands the whole roadmap's shared branch). This names the single item to land.
This skill is non-interactive. Launch unattended runs with --permission-mode auto (or bypassPermissions in a sandbox) so the git commands don't block on permission prompts.
Safety posture
Landing is the one step that writes to main. It runs only on explicit invocation — when you run /rdm-land, or when rdm-autopilot is given its opt-in --land flag. It never auto-lands: nothing in the normal review flow reaches main on its own. The fast-forward is exactly what triggers rdm hook post-commit on the default branch to mark the item done, so the Done: line the branch already carries keeps working unchanged.
The history guarantee is linear: rebase onto main, then git merge --ff-only. A fast-forward merge creates no merge commit. If a fast-forward is not possible, that is a signal to abort — never fall back to a merge commit and never force.
Preconditions (abort, do not force, if any fail)
Before touching main, confirm all of:
- The item is
reviewed. Read it: ./target/debug/rdm phase show <phase> --roadmap <slug> --project rdm (or ./target/debug/rdm task show <slug> --project rdm). If it is not reviewed — e.g. still needs-review, blocked, or already done — stop: only reviewed work lands.
- The branch carries the
Done: line. The reviewed commit must include Done: <roadmap>/<phase> (or Done: task/<slug>); that line is what the post-commit hook reads. Inspect with git log.
- The worktree is clean. No uncommitted changes (
git status --porcelain is empty).
- The CI-equivalent checks pass on the rebased branch — see step 4 below. This is checked after rebasing, not before.
Steps
Worktree topology. rdm uses one worktree per roadmap: the item's branch (roadmap/<slug>, task/<slug>, or the phase's branch) is checked out in a linked worktree, while main stays checked out in the primary worktree. git refuses to git checkout a branch that is already checked out in another worktree, so never git checkout main from inside the item worktree — operate on each branch in the worktree that already holds it. Find the primary worktree with git worktree list (it is the first entry); call it <primary> below.
- Read item status and verify it is
reviewed (precondition 1). Determine its branch: roadmap/<slug>, task/<slug>, or the phase's branch.
- Update
main (in the primary worktree, only if it tracks an upstream): if git -C <primary> rev-parse --abbrev-ref main@{u} succeeds, refresh it with git -C <primary> pull --ff-only. In a local-only repo with no upstream, skip this — main is already the rebase base, and git pull would error with "no tracking information."
- Rebase the item's branch onto
main: from inside the item's worktree, git rebase main (main is a ref readable from any worktree — no checkout needed). On conflict → abort (see below).
- Re-run the CI-equivalent checks on the rebased branch:
cargo fmt --check
cargo clippy -- -D warnings
cargo nextest run
These mirror the project's CI gate. If any fail → abort (see below): the rebase may have surfaced a semantic conflict the checks catch.
- Fast-forward
main: advance main from the primary worktree where it is checked out — git -C <primary> merge --ff-only <branch> (do not git checkout main inside the item worktree). Assert this produces no merge commit (a true fast-forward). If --ff-only is refused, abort — do not retry without it.
- Confirm the item flipped
reviewed → done. The fast-forward onto the default branch fires rdm hook post-commit, which reads the Done: line and marks the item done. Verify with ./target/debug/rdm phase show <phase> --roadmap <slug> --project rdm. If the hook did not run (e.g. hooks not installed), apply the idempotent fallback:
./target/debug/rdm phase update <phase> --status done --commit <sha> --no-edit --roadmap <slug> --project rdm
./target/debug/rdm task update <slug> --status done --commit <sha> --no-edit --project rdm
- Clean up the worktree:
./target/debug/rdm worktree remove <item> --delete-branch --project rdm removes this item's worktree and its now-merged branch. For batch end-of-run cleanup of all already-done items at once, use ./target/debug/rdm worktree prune --project rdm (add --delete-branch to also drop the merged branches).
Abort / escalation
On rebase conflict or failing checks:
git rebase --abort (or git merge --abort if a merge was in flight) to return the branch to its pre-landing state.
- Leave the worktree intact — never
git reset --hard, force-push, force-merge, or discard the work.
- Surface an actionable escalation per
docs/escalation-protocol.md: state which precondition or step failed, the conflicting files or failing check, and that main was left untouched. The item stays reviewed, ready for a human to resolve the conflict and re-run landing.
main is only ever advanced by a clean fast-forward of fully-checked, reviewed work. Anything less aborts.