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
20 changes: 17 additions & 3 deletions product/skills/admin-bypass-sweep/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,23 @@ the stated scope but the dependent PR cannot land without it.

Report the full grouped plan (stack count, PR count, max stack depth) before
touching anything — the real scope is often much larger than "a few PRs."
Reconfirm with the human which parts of the plan they want executed (e.g.
whether multi-PR stacks are in scope, given the retargeting risk in Step 4),
if the STOP section above did not already make that explicit.
Ask the scope question in this turn, and ask only that question. Offer the
narrowest executable option first (for example, "single-PR groups only"),
then name each larger option separately (for example, a specific multi-PR
stack, all multi-PR stacks, or the full grouped plan). Do not request the
literal consent sentence in the same message as the scope question.

An unanswered or unclear scope question resolves to the narrowest option
you offered. If the human's reply carries only the literal consent sentence,
treat that as consent but not as a scope answer; execute only the narrowest
offered scope. Multi-PR stacks require an explicit second answer that names
the stack or a larger offered option containing it.

After scope is answered, or after an unanswered scope question resolves to
the narrowest offered option, request the literal consent sentence from the
STOP section in a separate turn if the current invocation has not already
provided it. Do not run Step 4 until the final resolved scope is clear and
both STOP requirements are satisfied.

## Step 3: Verify merge method

Expand Down
16 changes: 16 additions & 0 deletions product/skills/admin-bypass-sweep/tests/scope_answered_reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Assistant reports: "I found seven admin-bypass PRs in five groups: three
single-PR groups, stack A (#40 -> #41), and stack B (#50 -> #51). Which
scope should I execute: single-PR groups only, stack A, stack B, or the full
grouped plan?"

User replies: "Run the full grouped plan."

Assistant then asks, in a separate turn, for the literal sentence:

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

User replies with that exact sentence.

Expected result: scope is answered before consent is requested. The resolved
scope is the full grouped plan, including the named multi-PR stacks, because
the human explicitly chose the larger offered scope before giving consent.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Assistant reports: "I found seven admin-bypass PRs in five groups: three
single-PR groups, stack A (#40 -> #41), and stack B (#50 -> #51). Which
scope should I execute: single-PR groups only, stack A, stack B, or the full
grouped plan?"

User replies only:

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

Expected result: the reply satisfies the literal consent sentence, but it is
not a scope answer. The unanswered scope question resolves to the narrowest
offered scope, which is single-PR groups only. Stack A, stack B, and the
full grouped plan remain out of scope unless the human gives an explicit
second answer naming that stack or the larger offered option.
46 changes: 46 additions & 0 deletions product/skills/admin-bypass-sweep/tests/test_scope_intake.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from __future__ import annotations

import unittest
from pathlib import Path


HERE = Path(__file__).resolve().parent
SKILL = HERE.parent / "SKILL.md"
ANSWERED = HERE / "scope_answered_reply.md"
UNANSWERED = HERE / "scope_unanswered_consent_only_reply.md"


def normalized(path: Path) -> str:
return " ".join(path.read_text(encoding="utf-8").split())


class TestScopeIntake(unittest.TestCase):
def test_step_2_separates_scope_from_consent(self):
skill = SKILL.read_text(encoding="utf-8")

self.assertIn("Ask the scope question in this turn, and ask only that question.", skill)
self.assertIn("Do not request the\nliteral consent sentence in the same message", skill)
self.assertIn("After scope is answered", skill)
self.assertIn("in a separate turn", skill)

def test_consent_only_reply_resolves_to_narrowest_scope(self):
skill = SKILL.read_text(encoding="utf-8")
fixture = normalized(UNANSWERED)

self.assertIn("If the human's reply carries only the literal consent sentence", skill)
self.assertIn("not as a scope answer", skill)
self.assertIn("narrowest offered scope", fixture)
self.assertIn("single-PR groups only", fixture)
self.assertIn("remain out of scope", fixture)

def test_scope_answered_fixture_resolves_to_stated_scope(self):
fixture = normalized(ANSWERED)

self.assertIn('User replies: "Run the full grouped plan."', fixture)
self.assertIn("scope is answered before consent is requested", fixture)
self.assertIn("resolved scope is the full grouped plan", fixture)
self.assertIn("explicitly chose the larger offered scope", fixture)


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