Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/skills/land-pr/.pr-kit
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Installed by the PR kit (open-pr/kit.ts). Edit the kit at its source, not here.
version 67 sha256:d0:c2:68:8a:e0:a8:c2:fc:32:62:f5:ed:8c:5e:c5:74:4a:6e:c0:d7:a8:ca:42:6e:5b:40:6d:5f:26:50:07:f8
version 85 sha256:66:ab:65:d4:d7:dd:3a:24:86:65:02:cb:59:80:4e:1b:59:87:ad:10:6b:53:92:b6:38:2b:cf:4e:92:a1:81:2d
9 changes: 6 additions & 3 deletions .claude/skills/land-pr/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ The PR gate refuses a merge unless the PR body passes the contract and the revie
| Conflict fix | A conflict-resolution commit changes the head. Wait for a successful `pullfrog-approval` check-run on that exact head before merging. An exempt repo has no check-run to wait for. It needs green CI and a local review of the new head instead. |
| CI | Required checks pass on the same head. |
| Threads | Fix actionable findings. Resolve bot threads with evidence. Resolve or disposition every other thread. |
| Agent merge | The agent merges without asking when all of these hold on the exact head: the PR body's Merge danger shows a blast radius of `none`, `low`, or `medium`, required CI passes, the project's verify skills pass (step 6), and the pass signal passes. A repo with no review bot qualifies only when this kit's exemption list (`merge.ts`) names it, because that list is the owner's record that the repo has no bot on purpose. Never add a repo to that list to make a merge pass. The rating counts only as the local review left it. If the blast radius was lowered after that review, the agent does not merge on its own. The gate checks the body and the bot verdict, not the rating, so this rule is the agent's to keep. The owner set this rule on 2026-10-30. |
| Owner's word | Every other merge takes the owner's word: a `high` blast radius, a rating lowered after review, or a repo with no review bot and no exemption. The word is an explicit "merge", or a request whose wording implies it ("ship it", "get it merged", "merge when green"). For "merge when green", wait for required checks and exact-head approval, then use a merge pinned to that approved head. Without the word, stop at merge-ready and report the head SHA, CI, bot verdict, threads, spec fidelity, verify skills, and merge danger. A `high` PR also gets an explainer video first (see Explainer video for a high PR). |
| Agent merge | The agent merges without asking when all of these hold on the exact head: the merge danger that counts shows a blast radius of `none`, `low`, or `medium`, required CI passes, the project's verify skills pass (step 6), and the pass signal passes. A repo with no review bot qualifies only when this kit's exemption list (`merge.ts`) names it, because that list is the owner's record that the repo has no bot on purpose. Never add a repo to that list to make a merge pass. The rating counts only as the local review left it. If the blast radius was lowered after that review, the agent does not merge on its own. The gate checks the body and the bot verdict, not the rating, so this rule is the agent's to keep. The owner set this rule on 2026-10-30. |
| Merge danger that counts | The higher of two ratings: the PR body's Merge danger, and the `merge-danger` commit status that the kit's scorer posts on the exact head (open-pr step 5). `bun <this skill's dir>/danger.ts <owner/repo> <n>` reads both and decides. With no status and no scorer for the PR (no workflow on the default branch, or a fork or Dependabot PR it skips), the body's rating alone counts, as before. When the scorer runs for the PR, wait for its status like a CI check. A PR opened before the scorer was installed gets its status on its next push, or on a close and reopen. When no status comes 60 minutes after the last push, as when the scorer job died before posting, stop and report it under the convergence rule. That merge takes the owner's word. The newest status decides, so a rerun can replace an `error`. The PR body contract still requires a Door and a Blast radius line, so every PR, a cloud agent's included, carries a body rating. A body that breaks the contract takes the owner's word. When the scorer rated the head, its rating stands in for the local review of the body's rating, so a cloud PR with no local review merges on its own when the higher of the two is `medium` or lower. A newest status of `error` or `failure` takes the owner's word. Any workflow can post as `github-actions[bot]`, so a rating counts only when its status links a finished run of `merge-danger.yml` on the exact head. Any other `merge-danger` status takes the owner's word. The owner set this rule on 2026-11-05. |
| Owner's word | Every other merge takes the owner's word: a `high` blast radius, a rating lowered after review, a `merge-danger` status of `error` or `failure`, or a repo with no review bot and no exemption. The word is an explicit "merge", or a request whose wording implies it ("ship it", "get it merged", "merge when green"). For "merge when green", wait for required checks and exact-head approval, then use a merge pinned to that approved head. Without the word, stop at merge-ready and report the head SHA, CI, bot verdict, threads, spec fidelity, verify skills, and merge danger. A `high` PR also gets an explainer video first (see Explainer video for a high PR). |
| Always | Never pass `--admin` or `--auto`. The gate refuses both. Never merge when the repo's AGENTS.md forbids agent merges. |
| Other bots | Open Code Review, CodeRabbit, Greptile, and Codex are advisory unless branch rules require them. |

Expand Down Expand Up @@ -51,12 +52,14 @@ A stale PR costs more than one more round. Keep fixing while each round makes pr
```

4. **Wait on the real state change.** Watch the check-run, not a timer. Count the round and apply the convergence rule.
- A scorer status must match the PR's current head, base commit, and scored title and body. An edit requests a new score. If the base branch advances without a PR event, close and reopen the PR to request a score for the new comparison. Wait for that score before merging. Old scores without an input fingerprint need a fresh score too.
- The matching fingerprint and actual radius must also come from the linked scorer run's own job log, read through GitHub. Status URL text alone proves nothing. A log proof that contradicts its status takes the owner's word. A score whose proof is gone (expired logs, a deleted run, or an attempt that failed or was cancelled after it posted) can only raise the rating. With no verified score for the current inputs, the owner decides, so request a fresh score with a close and reopen. When no scorer applies and only stale statuses remain, the body-only rule applies.
Comment thread
AojdevStudio marked this conversation as resolved.
Resolved
- When a T3 watch is the wake source and Bash supports `run_in_background`, also arm one bounded `until` loop on the head's `pullfrog-approval` check-run as a backstop.
5. **Check spec fidelity before merge.** Diff the result against the issue, the plan, or the mock. Post every deviation, or "no deviations", as a PR comment.
6. **Run the project's verify skills on the head.** Run `git fetch origin <base>` and check out the exact head you will merge. Run `bun <this skill's dir>/../open-pr/verify.ts --base origin/<base>` in the repo, then read each listed `SKILL.md` in full and run it, in the listed order. The listed paths are relative to the repo root.
- When one fails, stop. Do not merge. Report the skill, the failing step, and its output on the PR. A skill that cannot start counts as a failure, and so does a non-zero exit from `verify.ts`. Never read a `verify.ts` error as nothing to run. A fix is a new head, so it goes through this skill again.
- When it prints `verify: none.`, note that line in the merge-ready report and go on.
7. **Merge under the merge policy.** Read the Merge danger section of the PR body as it is now, since a fix round can change it. If the policy leaves this merge to the owner and the owner has not given the word, stop here and report merge-ready. For a `high` blast radius, make the explainer video below before you report. Otherwise, first check allowed methods with `gh api repos/{owner}/{repo} --jq '{allow_squash_merge,allow_merge_commit,allow_rebase_merge}'`. Follow the repo's required method if allowed. Otherwise fetch main and run `git log origin/main --first-parent -10 --format='%h %p %s'`. Two parents show a merge commit. Squash and rebase history can look the same. Use an allowed method supported by policy or history, and prefer squash when neither names one. Stop if the evidence conflicts with the settings. Run `gh pr merge <n> <method flag> --match-head-commit <approved-head-sha>` alone in its call, with `-R <owner>/<repo>` when the current directory is not that repo's checkout or the repo is exempt. The gate checks a merge only when nothing runs before it but a literal `cd` or a `set` of `-e`, `-u`, `-x`, or `-o pipefail`, and nothing runs beside or after it, not even a pipe into a filter, since any other command can move the head. Nonexempt REST merges must also name that same head in the `sha` field. The asynchronous REST `merge-async` endpoint is refused. The merge is the only command in its call, so `git pull` or `git checkout main` runs in a later call. The gate checks the policy again.
7. **Merge under the merge policy.** Run `bun <this skill's dir>/danger.ts <owner/repo> <n>`. It reads the PR body's Merge danger as it is now, since a fix round can change it, and the scorer's status on the head. Exit 0 lets the agent merge, 1 takes the owner's word, and 3 means the scorer has not rated the head yet. Wait for it as step 4 says. If the policy leaves this merge to the owner and the owner has not given the word, stop here and report merge-ready. For a `high` blast radius, make the explainer video below before you report. Otherwise, first check allowed methods with `gh api repos/{owner}/{repo} --jq '{allow_squash_merge,allow_merge_commit,allow_rebase_merge}'`. Follow the repo's required method if allowed. Otherwise fetch main and run `git log origin/main --first-parent -10 --format='%h %p %s'`. Two parents show a merge commit. Squash and rebase history can look the same. Use an allowed method supported by policy or history, and prefer squash when neither names one. Stop if the evidence conflicts with the settings. Run `gh pr merge <n> <method flag> --match-head-commit <approved-head-sha>` alone in its call, with `-R <owner>/<repo>` when the current directory is not that repo's checkout or the repo is exempt. The gate checks a merge only when nothing runs before it but a literal `cd` or a `set` of `-e`, `-u`, `-x`, or `-o pipefail`, and nothing runs beside or after it, not even a pipe into a filter, since any other command can move the head. REST merges, exempt ones included, must also name that same head in the `sha` field. The asynchronous REST `merge-async` endpoint is refused. The merge is the only command in its call, so `git pull` or `git checkout main` runs in a later call. The gate checks the policy again.
8. **Prove the merge.** Only `gh api repos/{owner}/{repo}/pulls/<n> --jq .merged` returning `true` proves it. A tool's success message does not.

## Explainer video for a high PR
Expand Down
Loading
Loading