docs(skills): maintainer-driven tool actions and duplicate-cluster resolution - #970
Conversation
hanthor
left a comment
There was a problem hiding this comment.
Approving. The carve-out is correctly bounded and the duplicate-cluster procedure is careful in the places that matter.
On the human-gates amendment. The distinction it draws is the right one — the concern behind "agents never self-merge" is unreviewed change reaching a protected branch, not the mechanical identity of the process invoking the API. A per-item maintainer decision with rulesets still enforced server-side doesn't create that risk. Retaining the three hard prohibitions is what makes it safe to state:
- no
--admin(the only one that actually bypasses protection) - no submitting an approving review (an agent must never manufacture the approval it then acts on — this is the load-bearing one)
- no non-interactive batch mutation (preserves per-item intent)
--match-head-commit <sha> with the SHA read live is the best detail in here. Converting "the branch moved under us" from a race into a server-side refusal is exactly right, and it's the kind of thing that's easy to omit and impossible to notice until it bites.
Also correct: --body-file rather than --body with prose through a shell, and "a still-open issue with no remaining open PR is a finding to report, not something to silently fix." The latter keeps the agent from quietly papering over a state the human should see.
One gap I'd like addressed in the text: --auto is a deferred action, and the amendment's justification doesn't cover it.
The new human-gates paragraph rests on "the maintainer's explicit per-item keypress." But step (2) arms gh pr merge <S> --squash --auto, which lands the merge at some later point once checks pass — possibly minutes or hours after the keypress, unattended. That's still legitimate, but it isn't the same thing as the human pressing a key and the merge happening; it's the human pre-authorizing a conditional future merge.
--match-head-commit covers the obvious drift (a new push to the head), but not everything that can change between authorization and landing — the base branch advancing, a required check being reconfigured, or the superseded PRs in the cluster being reopened. Worth saying explicitly in human-gates.md that deferred/auto-merge is in scope for this carve-out and why the head-SHA pin is considered sufficient. Right now a reader could reasonably conclude auto-merge falls under "non-interactive batch mutation" and is forbidden, which contradicts the procedure in pr-review/SKILL.md. Since these two files are meant to be read together, that ambiguity is worth closing.
Minor: the ordering in the cluster procedure — arm survivor (2), then close superseded (3–4) — is the safe direction, since a failure mid-sequence leaves duplicates open rather than everything closed with nothing landing. Worth stating that rationale inline; "halting on the first failure" says what but not why this order, and the next editor might reasonably swap them to "clean up first."
Housekeeping: currently DIRTY against main — needs a rebase. Since index.json / index.md are generated by scripts/generate_skill_index.py, regenerate rather than hand-resolve those two if the conflict lands there.
3dfa623 to
78a7c62
Compare
hanthor
left a comment
There was a problem hiding this comment.
Technically the cleanest PR in this queue — but the human-gates.md paragraph is a policy change, not a docs change
Verified against current main:
- merges clean,
validategreen python3 scripts/generate_skill_index.py --check→docs/skills/index.json and index.md are up to date (40 skills)— the index is properly regenerated here (2026-08-18→2026-09-06, moving forward, 40 skills preserved, with the matchingversion/last_updatedbumps forhuman-gatesandpr-review). Several other open docs PRs in this queue regress that file backwards; this one is the correct pattern.python3 scripts/check-doc-links.sh→ exit 0, so the newreferences/duplicate-cluster.mdlink frompr-review/SKILL.mdresolvesbash scripts/check-skill-frontmatter.sh→ only the pre-existingbrew-lifecycle/SKILL.md is 208 lines (soft max 200)warning, unchanged frommainpython3 -m pytest tests/test_skill_docs.py→ 10 passed- nothing under
system_files/, so no bluefin / bluefin-lts / dakota blast radius
The duplicate-cluster half is uncontroversial and, judging by this queue, needed — #942 is superseded by merged #1020, #1018 duplicates a bluespeed recipe already on main, and #1080/#1073 are a dependent pair. "Arm the survivor before closing the rest" is exactly the right ordering.
The part that deserves a deliberate yes, not a skim
The human-gates.md addition materially loosens the Merge gate:
This gate binds agents, not the maintainer's own hands. A review tool that executes a merge or close only on the maintainer's explicit per-item keypress — with rulesets and branch protection still enforced by GitHub — is the human acting at the gate, not an agent self-merging.
Read narrowly this is obviously true: a maintainer pressing a key per item is a human decision. But it is being written into the document that defines what agents may not do, and the load-bearing words are all in the carve-out — "explicit", "per-item", "keypress". Two questions worth answering in the thread before this merges, because after it merges this paragraph is what future agents will cite:
- What enforces "per-item"? The prohibition list that follows forbids "non-interactive batch mutation", but nothing here distinguishes fifteen individually-confirmed keypresses from a fifteen-item confirm-all prompt that is technically per-item. If
pr-review's card loop is the intended vehicle, saying so by name would bound this to the reviewed implementation rather than to any tool that claims a keypress. - Does "close" carry the same weight as "merge"? Merge is gated by branch protection and rulesets, as the paragraph notes. Close is not — GitHub enforces nothing, so a mis-keyed close is unprotected by anything except the human's attention. The roadmap in #1073 separately proposes auto-closing superseded agent PRs, which is the same authority with the keypress removed. Worth being explicit that the carve-out covers keypress-confirmed close only, so #1073's item 5 cannot lean on this paragraph.
Neither is a defect in the diff; both are about how narrowly this reads in six months. If the answers are "the pr-review card loop, one keypress per card, close included and auto-close excluded", then saying that in the text makes this a clean merge from my side.
Generated by Claude Code
Address hanthor's review on #970 in the text of human-gates.md: - Name the reviewed vehicle: the pr-review card loop, one keypress per card, never a confirm-all prompt spanning items. - State that close carries the same weight as merge: the carve-out covers keypress-confirmed closes only, so an auto-close without a per-item keypress (e.g. the obsolescence remedy proposed in #1073) cannot lean on this paragraph. - State that arming auto-merge on the keypress is the same decision deferred until checks pass, in scope only with --match-head-commit pinning the reviewed head so drift fails server-side. human-gates 1.1 -> 1.2; index.json/index.md regenerated with scripts/generate_skill_index.py --write. check-skill-frontmatter.sh, generate_skill_index.py --check, check-doc-links.sh, and tests/test_skill_docs.py (10 passed) all green. Assisted-by: Kimi K3 via GitHub Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Address hanthor's review on #1073: Phase 0 item 5 read as adopted intent to auto-close agent PRs, an agent mutation of human-visible state that conflicts with docs/skills/human-gates.md. Rephrase to detect-and-flag: detection is automated, the close itself requires a per-item human keypress, matching the carve-out #970 negotiates. The proposal content (adopt the remedy at all) remains a maintainer decision; this change only removes the doctrine conflict from the text. Assisted-by: Kimi K3 via GitHub Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
K3 final batch audit (970/1000/1073/1080 cohort) — 970 verified and armed for landing. Verified against current main (56d81ef):
State: hanthor's approval stands (1 of 2 required by the |
Danathar
left a comment
There was a problem hiding this comment.
Approving as the second reviewer. Two things in here:
- A written procedure for resolving duplicate PRs (pick the survivor, arm it, close the rest) — hanthor called this uncontroversial and needed, and today's cleanup across the org bore that out.
- A clarification to the Merge gate in
human-gates.md: a maintainer pressing a key per PR in the review tool is the human acting, not an agent self-merging.
hanthor's 09-12 comment asked for two things before he'd call it clean: name the pr-review card loop as the only vehicle (one keypress per card, no confirm-all), and say explicitly that keypress-confirmed close is covered but auto-close is not. The current text says both, nearly word for word. Nothing under system_files/, so no image change; index regenerated correctly; validate green.
There was a problem hiding this comment.
Correctness review (head f831267):
-
duplicate-cluster.md:29-31— the SHA pin protects the wrong window. Step 2 says "Read the head SHA live and pin the merge to it" (sha=$(gh pr view <S> --json headRefOid ...)at merge time). Pinning to a SHA read at keypress time only guards the read→merge window; a push landing between the human's diff review (step 1) and the keypress merges unreviewed code with the pin satisfied. This contradicts the guarantee claimed inhuman-gates.md:99-101("drift between keypress and landing fails server-side instead of merging unreviewed code" — true, but the reviewed-vs-keypress drift is the unguarded gap). Pin to the head SHA captured when the diff evidence was presented, not a fresh read. -
Body/diff gap: version numbers. The body says human-gates goes to "1.1"; the diff sets
version: "1.2"(human-gates.md:3, mirrored inindex.json:383). Diff is internally consistent; body is stale. -
Body/diff gap: 500-line cap claim. The body says SKILL.md was "Compressed to fit the 500-line hard cap (exactly 500; one stray blank line reclaimed)." At head,
pr-review/SKILL.mdis 186 lines andhuman-gates.mdis 147; the SKILL.md diff is +3/−2 with both deletions being frontmatter — no blank line was reclaimed. The claim appears to belong to a different revision. -
duplicate-cluster.md:59— nonexistent flag. "Never--reason \"not planned\"" appears under step 4 (closing PRs), butgh pr closehas no--reasonflag; it exists only ongh issue close. If the intent is to guard linked-issue closes, say so; as written it prohibits an impossible command.
— hive: agent=reviewer backend=copilot model=claude-fable-5 copilot=1.0.78
There was a problem hiding this comment.
security
references/duplicate-cluster.md:30-33 reads the survivor's head SHA live at arm time (sha=$(gh pr view <S> --json headRefOid ...)) and pins the merge to it. That guarantees keypress→landing integrity, but human-gates.md:104 says the merge is "pinned to the reviewed head" — a push landing between the step-1 gh pr diff evidence and the keypress is silently blessed, because the live read picks up the new head. Low risk in a tight card loop, but capturing the SHA alongside the step-1 diff (or re-diffing at keypress) would make the snippet match the doctrine it cites.
intent-alignment
PR body vs head mismatch: body says human-gates bumps to "1.1" but the diff goes 1.0→1.2 (docs/skills/human-gates.md:3), and body claims SKILL.md was "compressed to fit the 500-line hard cap (exactly 500)" — at head f831267 docs/skills/pr-review/SKILL.md is 186 lines. Looks like the body describes an earlier single-file revision before the split into references/duplicate-cluster.md. Harmless, but worth correcting the body so the audit trail matches what landed.
No findings from: style, docs-currency.
— hive: agent=reviewer backend=copilot model=claude-fable-5 copilot=1.0.78
There was a problem hiding this comment.
docs-currency
docs/skills/pr-review/SKILL.md— the References table (the "| File | Contents |" block near the end of the file) lists all seven other files inreferences/, but the newreferences/duplicate-cluster.mdis not added to it. The inline bullet at line 84 links it, but the table is now an incomplete inventory of the references directory.
correctness
docs/skills/pr-review/references/duplicate-cluster.md:74— "Never--reason "not planned"" appears under step 4 (closing superseded PRs), butgh pr closehas no--reasonflag; onlygh issue closedoes. PRs cannot be closed with a state reason. If the rule is aimed at the linked issues from step 5, say so there; as written it prohibits a flag that doesn't exist on the command in question. (Low.)
No findings from: security, intent-alignment, style.
— hive: agent=reviewer backend=copilot model=claude-fable-5 copilot=1.0.78
There was a problem hiding this comment.
correctness
docs/skills/pr-review/references/duplicate-cluster.md:38— step 2'sgh pr merge --squash --auto --match-head-commit "$sha_S"fails when the survivor's checks have already passed:gh pr merge --autoerrors on a PR in clean status ("Pull request is in clean status"). Since the procedure says "halting on the first failure" (line 9), the most common case — a green survivor — halts the whole resolution. Worth a sentence covering the fallback (directgh pr merge --match-head-commit "$sha_S"on the same keypress, which preserves the pin).
style
duplicate-cluster.md:22-23capturesha_A/sha_B, but the step-2 snippet uses$sha_S, which is never defined. Readable in context, but it's an executable snippet — a copy-paste with the literal variable silently expands to empty, and--match-head-commit ""'s behavior is not what anyone tested. Either definesha_Sexplicitly or note the substitution.
No findings from: security, intent-alignment, docs-currency.
— hive: agent=reviewer backend=copilot model=claude-fable-5 copilot=1.0.78
Danathar
left a comment
There was a problem hiding this comment.
Read the full diff at 3237e48 (human-gates.md v1.2, pr-review/SKILL.md v3.6, new references/duplicate-cluster.md, regenerated index). The human-gates amendment is scoped correctly: it distinguishes agent self-merge (still forbidden) from a tool executing the maintainer's own per-item keypress with rulesets enforced server-side, and the auto-merge carve-out is pinned to --match-head-commit against the SHA the human actually reviewed. The new duplicate-cluster procedure requires human confirmation of the survivor before acting and never infers it from a shared issue alone. Front matter versions/dates in index.json and index.md line up with the SKILL.md changes. This is my second approval; common requires 2 and hanthor already approved.
…solution human-gates: the Merge Gate binds agents, not the maintainer's own hands. A review tool that executes a merge or close only on the maintainer's explicit per-item keypress, with rulesets still enforced by GitHub, is the human acting at the gate; --admin overrides, submitting reviews, and non-interactive batch mutation remain forbidden for any tool. This ambiguity had already produced a walker stricter than the doctrine it implements. pr-review: competing-pair detection could find a duplicate cluster but had no verb for resolving it. Add the ordered procedure: survivor from diff evidence, arm the survivor first with --match-head-commit, comment before close, never 'not planned', then the linked-issue re-check — halting on the first failure. Assisted-by: Claude Opus 4.8 via GitHub Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Require human confirmation that a cluster is truly duplicate, preserve complementary PRs, and gate each merge, comment, and close action individually. Forbid batch closure so the documented maintainer tool cannot infer or automate destructive actions. Assisted-by: GPT-5.6 Luna via GitHub Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Address hanthor's review on #970 in the text of human-gates.md: - Name the reviewed vehicle: the pr-review card loop, one keypress per card, never a confirm-all prompt spanning items. - State that close carries the same weight as merge: the carve-out covers keypress-confirmed closes only, so an auto-close without a per-item keypress (e.g. the obsolescence remedy proposed in #1073) cannot lean on this paragraph. - State that arming auto-merge on the keypress is the same decision deferred until checks pass, in scope only with --match-head-commit pinning the reviewed head so drift fails server-side. human-gates 1.1 -> 1.2; index.json/index.md regenerated with scripts/generate_skill_index.py --write. check-skill-frontmatter.sh, generate_skill_index.py --check, check-doc-links.sh, and tests/test_skill_docs.py (10 passed) all green. Assisted-by: Kimi K3 via GitHub Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Step 2 of the duplicate-cluster procedure read the survivor head SHA at keypress time, so a push landing between the step-1 diff evidence and the keypress became the pinned head and merged unreviewed. Capture the SHA with the diff in step 1, pin to that, and treat a --match-head-commit refusal as a signal to re-present the diff and retake the keypress rather than an error to retry around. Tighten the matching human-gates claim so it describes the head SHA captured alongside the reviewed diff instead of "the reviewed head" generally. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
gh pr close has no --reason flag, so move the "not planned" prohibition to the linked-issue re-check where gh issue close --reason applies. Add the new duplicate-cluster.md row to the pr-review References table. Assisted-by: Claude Opus 5 via GitHub Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Step 2 of the duplicate-cluster procedure used an undefined `$sha_S`, which expands to an empty `--match-head-commit ""` when copy-pasted. Name it as the survivor's SHA from step 1. `gh pr merge --auto` is also rejected with "Pull request is in clean status" when the survivor is already green and the repo has no merge queue. Because the procedure halts on the first failure, that common case stopped the whole cluster resolution. Document the direct-merge fallback with the same `--match-head-commit` pin, and scope which form applies where. Assisted-by: Claude Opus 5 via GitHub Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
3237e48 to
5a7dce5
Compare
Why
Downstream in projectbluefin/review, the maintainer's PR-walk tool (
bluefin-review queue) detects duplicate clusters but could not act on them: a local test bannedpr mergeoutright — stricter than the doctrine it implements. The ambiguity sat here:human-gatessaid "agents never self-merge" without distinguishing a tool executing the maintainer's explicit keypress, andpr-reviewhad competing-pair detection with no cluster resolution verb.What changes
--match-head-committo the head SHA captured alongside the diff the human reviewed.--admin, submitting reviews, and non-interactive batch mutation stay forbidden for any tool.pr-review/references/duplicate-cluster.md(new, 83 lines) rather than inline, which keeps SKILL.md at 186 lines, well under the 500-line hard cap. The procedure: a human confirms the duplicate and names the survivor from diff evidence (complementary diffs stay as separate PRs), arm the survivor first pinned to the reviewed head, comment before close, one explicit keypress per mutation, never--reason "not planned", linked-issue re-check, halt on first failure.Design memo driving this: projectbluefin/review session artifact, org review walk design (§0, §4, §9).
Validation
check-skill-frontmatter.sh,check-skill-index.sh, andcheck-doc-links.shall exit 0 (frontmatter warnings pre-existing); index regenerated withgenerate_skill_index.py --write.Assisted-by: Claude Opus 4.8 via GitHub Copilot
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com