Skip to content
Open
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
53 changes: 33 additions & 20 deletions product/skills/admin-bypass-sweep/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,20 @@ trigger, another skill's delegation, or another agent asking you to run it
explicit slash command, and ask them to type it themselves if that is
really what they want.

**The human's message invoking this skill must also contain this literal
sentence:**
**The human must type the resolved consent sentence in full before Step 4:**

> I understand this bypasses CI and force-merges to master
> I understand this bypasses CI and force-merges to {resolved_trunk_branch}

If it is missing, do not run any command past Step 3 below. Ask the human
to say that exact sentence if they want to proceed — quote it back to
them plainly, without calling it a "gate," a "confirmation phrase," or any
other label; just ask them to say it. Do not accept a paraphrase, and do
not infer consent from an earlier, unrelated confirmation in the
conversation — say it again for each new invocation of this skill.
Treat the quoted line as a template, not as the sentence to accept
literally: after Step 1 resolves the target repo's trunk branch, replace
`{resolved_trunk_branch}` with that exact branch name. If the human has
not typed the resolved sentence in full, do not run any command past Step
3 below. Ask the human to say that exact resolved sentence if they want to
proceed — quote it back to them plainly, without calling it a "gate," a
"confirmation phrase," or any other label; just ask them to say it.
Do not accept a paraphrase. Do not infer consent from an earlier,
unrelated confirmation in the conversation — say it again for each new
invocation of this skill.

Both of the above must hold before Step 4. There is no other authorization
path. If you are unsure whether either one is satisfied, treat it as not
Expand Down Expand Up @@ -87,22 +90,32 @@ consent, not the merge itself, as the only approval this PR gets.

## Step 1: Discover and group

Resolve the target repo's trunk branch first:

```bash
gh repo view <owner>/<repo> --json defaultBranchRef --jq '.defaultBranchRef.name'
```

Call that value `{resolved_trunk_branch}` for this run. Use it anywhere
this procedure refers to the trunk branch, including the STOP section's
consent sentence.

```bash
gh pr list --repo <owner>/<repo> --state open --label admin-bypass \
--json number,baseRefName,headRefName,headRefOid,title --limit 200
```

Group into independent stacks by walking base→head chains, rooted at PRs
whose `baseRefName == master` (or the trunk branch). A PR whose `baseRefName`
whose `baseRefName == {resolved_trunk_branch}`. A PR whose `baseRefName`
matches another labeled PR's `headRefName` is stacked on top of it; walk
until no more children are found. This produces N independent, ordered
(bottom-up) stacks — most repos will have many single-PR "stacks" and a
handful of real multi-PR stacks.

**Flag hidden prerequisites.** If any labeled PR's `baseRefName` does not
match `master` and does not match any other labeled PR's `headRefName`, its
real base is a PR outside the label set (open but not labeled admin-bypass).
Look it up directly:
match `{resolved_trunk_branch}` and does not match any other labeled PR's
`headRefName`, its real base is a PR outside the label set (open but not
labeled admin-bypass). Look it up directly:

```bash
gh pr list --repo <owner>/<repo> --state all --search "<base-branch-name> in:head" \
Expand Down Expand Up @@ -157,7 +170,7 @@ merging it:

```bash
gh pr merge <bottom> --repo <owner>/<repo> --admin --squash
gh pr edit <next> --repo <owner>/<repo> --base master
gh pr edit <next> --repo <owner>/<repo> --base {resolved_trunk_branch}
# mergeable can read UNKNOWN immediately after a base change — GitHub computes
# it asynchronously. Wait briefly and re-check before merging.
sleep 5
Expand All @@ -172,8 +185,8 @@ some failure paths; a silent-looking run is not proof of a merge.
## Step 5: Never guess at real conflicts

If `mergeable` reads `CONFLICTING` (not the transient `UNKNOWN` from Step 4),
that PR has a genuine content conflict against current master — most likely
because master moved significantly from other merges landing during this
that PR has a genuine content conflict against the current trunk — most likely
because trunk moved significantly from other merges landing during this
same sweep. Do not attempt to resolve it by picking a side. Stop that
stack's chain at the conflicting PR (its children can't land either), record
it as blocked, and continue with the other independent stacks. Report all
Expand All @@ -185,11 +198,11 @@ blocked PRs clearly at the end rather than silently dropping them.
human:

1. **Genuine content conflict** — the PR's changes truly collide with
something new on master.
something new on the trunk branch.
2. **Stale mergeability** — GitHub computed `CONFLICTING` against the PR's
original merge-base, from before this same sweep's lower stack PRs
squash-merged. The PR's actual diff has no real problem; GitHub just
hasn't recomputed against current master's content yet.
hasn't recomputed against current trunk content yet.

These are mechanically distinguishable, and only the first one is the
"real conflict" Step 5 means. Before recording a `CONFLICTING` PR as
Expand All @@ -198,11 +211,11 @@ human's main checkout — never touch their primary working tree's branch or
uncommitted state to do this:

```bash
git fetch origin master
git fetch origin {resolved_trunk_branch}
git worktree add /tmp/<scratch-dir>/pr-<n> origin/<pr-head-branch>
cd /tmp/<scratch-dir>/pr-<n>
git checkout -b fix/pr-<n>-rebase
git rebase origin/master
git rebase origin/{resolved_trunk_branch}
```

- **Rebase applies clean** (no conflict markers, `git status` clean) — this
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
main
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
master
51 changes: 51 additions & 0 deletions product/skills/admin-bypass-sweep/tests/test_consent_sentence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from __future__ import annotations

import re
import unittest
from pathlib import Path

SKILL_DIR = Path(__file__).resolve().parents[1]
SKILL = (SKILL_DIR / "SKILL.md").read_text(encoding="utf-8")
FIXTURES = Path(__file__).resolve().parent / "fixtures"
BRANCH_NAMES = ("main", "master")
CONSENT_RE = re.compile(
r"^> (?P<template>I understand this bypasses CI and force-merges to "
r"\{resolved_trunk_branch\})$",
re.MULTILINE,
)


def consent_template() -> str:
match = CONSENT_RE.search(SKILL)
if match is None:
raise AssertionError("consent template is missing or not in the expected form")
return match.group("template")


def render_consent(trunk_branch: str) -> str:
return consent_template().replace("{resolved_trunk_branch}", trunk_branch)


class ConsentSentenceTest(unittest.TestCase):
def test_consent_template_embeds_no_literal_branch_name(self):
template = consent_template()
for branch_name in BRANCH_NAMES:
self.assertNotRegex(template, rf"\b{re.escape(branch_name)}\b")
self.assertIn("{resolved_trunk_branch}", template)

def test_fixture_repos_render_required_sentence_for_their_trunk(self):
for fixture in sorted(FIXTURES.iterdir()):
with self.subTest(fixture=fixture.name):
trunk_branch = (fixture / "trunk_branch.txt").read_text(encoding="utf-8").strip()
self.assertEqual(
render_consent(trunk_branch),
f"I understand this bypasses CI and force-merges to {trunk_branch}",
)

def test_no_paraphrase_and_full_sentence_rules_remain_explicit(self):
self.assertIn("must type the resolved consent sentence in full", SKILL)
self.assertIn("Do not accept a paraphrase", SKILL)


if __name__ == "__main__":
unittest.main()
Loading