---
name: ship-pr
description: "Commit, push, open a pull request, repair CI within bounded attempts, then squash merge and verify post-merge workflows."
argument-hint: "[message hint]"
disable-model-invocation: true
compatibility: Requires git and an authenticated gh CLI.
license: MIT
---

Commit every change, push, open a pull request, and merge it once CI is green. Never commit onto the default branch. The arguments, if any, are a hint at what the change is about, not the message itself.

Keep a shipping record outside the worktree with the original and repair PRs, branches, checked commits, run IDs and attempts, logs, QA/review reports, and recovery counters. Preserve it across restarts and follow-up PRs.

Start from the session's working directory. When this session's work sits in another worktree (`git worktree list`), run every step there with `git -C <path>` and leave the working directory's changes untouched.

1. Run `git status --short --branch`, `git diff HEAD --stat`, `git log --oneline origin/HEAD..HEAD` (the branch commits), `git log --oneline -10`, and `gh api 'repos/{owner}/{repo}/actions/permissions' --jq .enabled` (whether Actions is enabled). Read the full diff (`git diff HEAD`), every untracked file `git status` lists, and, when there are branch commits, their diff (`git diff origin/HEAD...HEAD`) before writing anything. Read each issue the branch commits reference (`#N`) with the **Read an issue** operation in `docs/agents/issue-tracker.md`, since its comments hold the triage brief, or with `gh issue view N --json title,body,comments` when that file is missing.
2. Scan it for credentials, tokens, private keys, and any value that does not belong in this repository. If you find one, stop, commit nothing, and report what you found.
3. If the current branch is the repository's default branch, create and switch to a new one first: `type/kebab-description`, where `type` matches the Conventional Commit type you are about to use and the description comes from the change itself. Any branch commits move to the new branch with it: then run `git branch -f <default> origin/<default>` so the default branch matches its remote and the merge can fast-forward it.
4. Stage the changes. Prefer explicit paths over `git add -A`. An untracked directory that holds a local tool's state (an index, cache, or database, such as `.codegraph/`) belongs in the root `.gitignore`, even when it ships its own `.gitignore`: add its path there, stage that line with the rest, and say so in the report.
5. Write a Conventional Commit `type(scope): description`, matching the subject style already in `git log`. When the `oss-writing` skill is installed, call the Skill tool with it for the wording.
6. Commit, then `git push -u origin HEAD` with a 10-minute timeout: a pre-push hook can run the whole test suite. If the hooks must run against a scratch copy, complete the [scratch dependency preflight](../code-review/SCRATCH.md) in that exact copy before pushing. Use the normal unchanged hooks.
7. Create the PR with `gh pr create`, or update the existing PR for this branch after a repair. The squash merge makes the title the one commit on the default branch, so the title and body cover the whole branch: your commit's subject when it is the branch's only commit, otherwise one Conventional Commit subject spanning every commit. Use the repository's pull request template when it has one. Otherwise, call the Skill tool with "pr" for the body, and call it again with "oss-writing" for the wording when that skill is installed, even when no commit was written in step 5.
8. Inspect applicable PR checks and commit statuses at the exact head, including external CI, and use `gh pr checks --watch` until they settle. It exits non-zero on failure, so allow that and read the result. Actions enabled `false` means only that GitHub Actions is disabled; external checks and statuses may still apply. If no checks appear, wait 20 seconds and query again. Report no CI only when repository configuration and required-check settings establish that none applies. A missing expected check or unavailable configuration is blocked, not green.
9. Green: `gh pr merge <PR URL> --squash`, then confirm `gh pr view <PR URL> --json state,mergedAt` reports MERGED. Keep the branch and worktree while this worker is alive: shell `cd` does not move the harness or its hooks out of their working directory. The orchestrator removes its clean worktree after the worker exits; a standalone run leaves local cleanup to its caller. On a failed check, follow [CI recovery](CI.md), then return to the CI gate for the repaired head. Merge only with all required checks green on that exact head; use `--match-head-commit <checked-head>` and preserve branch protections. A recovery that stops leaves the PR unmerged with its evidence and remaining blocker.
10. Merged: close each issue the branch commits reference (`#N`, or a local issue path) that is still open, since the merge is what finishes it and a closed issue unblocks the tickets that wait on it. Use the **Close** operation in `docs/agents/issue-tracker.md` with the comment `Merged in <PR URL>.`, or `gh issue close N --comment` when that file is missing.
11. Verify the CI and deployment workflows triggered by this merge before reporting completion. Resolve the merge SHA and identify applicable workflows from repository configuration, including chained workflows; use `gh` to inspect runs for that exact commit. Wait for them to settle. If an expected run has not registered, wait 20 seconds and query again; a still-missing expected run is blocked, not success. Record intentionally filtered/skipped workflows or no configured post-merge workflow separately. A failed run follows [CI recovery](CI.md), including its post-merge branch procedure. A pending approval or unavailable external service stays blocked without bypass. Keep the caller's ship slot through this step and report a failed or blocked default-branch run immediately so it can hold further merges.
12. Report every original and repair PR URL and merge SHA, issues closed, CI outcomes and remaining coverage gaps, recovery counters, retained branches, and the shipping record path. Distinguish a successful original merge from blocked post-merge verification. Report the `.gitignore` line from step 4 if one was added.
