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
37 changes: 16 additions & 21 deletions product/skills/admin-bypass-sweep/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,32 +193,27 @@ human:

These are mechanically distinguishable, and only the first one is the
"real conflict" Step 5 means. Before recording a `CONFLICTING` PR as
blocked, check which case it is, in a disposable worktree outside the
human's main checkout — never touch their primary working tree's branch or
uncommitted state to do this:
blocked, run the rebase probe outside the human's main checkout — never
touch their primary working tree's branch or uncommitted state to do this:

```bash
git fetch origin master
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
scripts/probe_branch_rebase.sh origin/<pr-head-branch> origin/master
```

- **Rebase applies clean** (no conflict markers, `git status` clean) — this
was stale mergeability, not a real conflict. Force-push the rebased
branch back to the PR's head with `--force-with-lease` pinned to the
known old SHA, wait for GitHub to recompute (`sleep 5`), confirm
`mergeable` now reads `MERGEABLE`, then continue this PR (and its
children) through Step 4 as normal.
- **Rebase stops with conflict markers** — this is Step 5's real-conflict
case. Run `git rebase --abort`, remove the scratch worktree, and follow
Step 5 as written: stop the chain, record as blocked, move on. Do not
attempt to resolve the markers by picking a side — that part of Step 5
still applies.

Remove the scratch worktree (`git worktree remove --force`) once the PR's
fate — merged or genuinely blocked — is decided.
- **Exit 0, `OK`** — the PR rebases cleanly onto current master, so this was
stale mergeability rather than Step 5's real-conflict case. Wait for
GitHub to recompute (`sleep 5`), confirm `mergeable` now reads
`MERGEABLE`, then continue this PR (and its children) through Step 4 as
normal.
- **Exit 1, `FAIL`** — the probe ran and found a real content conflict.
Follow Step 5 as written: stop the chain, record as blocked, and move on.
Do not attempt to resolve the markers by picking a side — that part of
Step 5 still applies.
- **Exit 3, `UNCHECKED`** — the probe could not run, so nothing is proven.
Do not treat this as stale mergeability and do not treat it as Step 5's
real-conflict case; report the unchecked PR separately for manual retry
or setup repair.

## Step 6: Prove the final state

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Fixture assertion: the Step 5a passage in
`product/skills/admin-bypass-sweep/SKILL.md` must name
`scripts/probe_branch_rebase.sh`, must name all three probe outcomes
`OK`, `FAIL`, and `UNCHECKED`, and must not contain `rm -rf`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env python3
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")
FIXTURE = (SKILL_DIR / "tests" / "fires_step5a_names_probe.md").read_text(encoding="utf-8")


def step5a_passage() -> str:
match = re.search(r"## Step 5a:.*?(?=\n## Step 6:)", SKILL, re.S)
if not match:
raise AssertionError("Step 5a passage not found")
return match.group(0)


class TestStep5aProbePassage(unittest.TestCase):
def test_fixture_names_the_assertions(self):
self.assertIn("scripts/probe_branch_rebase.sh", FIXTURE)
for outcome in ("OK", "FAIL", "UNCHECKED"):
self.assertIn(outcome, FIXTURE)
self.assertIn("rm -rf", FIXTURE)

def test_step5a_names_probe_and_all_three_outcomes(self):
passage = step5a_passage()
self.assertIn("scripts/probe_branch_rebase.sh", passage)
for outcome in ("OK", "FAIL", "UNCHECKED"):
self.assertRegex(passage, rf"`{outcome}`")

def test_step5a_no_longer_contains_improvised_removal(self):
self.assertNotIn("rm -rf", step5a_passage())


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