---
# SPDX-FileCopyrightText: 2026 CoreWeave, Inc.
# SPDX-License-Identifier: Apache-2.0
# SPDX-PackageName: senpai

name: senpai-gh
description: >
  GitHub CLI primitives for the senpai research workflow — label swaps,
  send-back, close, mark-review, issue checks, PR queries. Use this skill
  whenever you need to manipulate PR labels, send a PR back to a student,
  close a dead-end experiment, mark a PR for review, or query the current
  state of PRs and issues. Also triggers for: "swap labels", "send back to
  student", "close this PR", "mark for review", "check human issues",
  "list review-ready PRs", "idle students".
user-invocable: false
model: claude-opus-4-8
effort: high
---

# senpai-gh

A bash library of GitHub operations shared by both advisor and student agents. Source it once, then call the functions you need.

The library lives at `${CLAUDE_PLUGIN_ROOT}/scripts/senpai-gh.sh`. Source it before using any function:

```bash
source "${CLAUDE_PLUGIN_ROOT}/scripts/senpai-gh.sh"
```

## Available functions

### Label operations

| Function | What it does |
|---|---|
| `swap_gh_pr_label <pr#> <remove-label> <add-label>` | Atomically swap one label for another. Safe — won't error if the old label is already gone. |

#### The `gh pr edit` footgun

GitHub's `gh pr edit --remove-label X --add-label Y` silently strips **all other labels** from the PR. The only safe way to swap a single label is two REST API calls: DELETE the old one, POST the new one. This library wraps that pattern so you never have to remember it.

### Advisor actions

| Function | What it does |
|---|---|
| `comment_on_pr <pr#> <comment>` | Leave a PR comment via a temporary body file, avoiding giant shell command lines. |
| `send_pr_back_to_student_with_comment <pr#> <comment>` | Send a PR back to the student with feedback. Comment on the PR, convert back to draft, swap `status:review` → `status:wip`. |
| `senpai_merge_winner_preflight <pr#> [problem-dir]` | Refuse unsafe winner merges with a specific error if the PR lacks terminal `SENPAI-RESULT`, has a newer hold comment, is draft/WIP, has bad labels, or has merge conflicts. |
| `close_pr_with_comment <pr#> <reason>` | Close a dead-end PR with a comment explaining why. Keeps the remote branch so the PR can be reopened or recovered if needed. |
| `create_assignment_pr_from_file <student> <head-branch> <title> <body-file> [base-branch]` | Create a draft assignment PR, then fail if the student already has a `status:wip` PR or if required base/head, draft, or routing labels are missing. |

### Student actions

| Function | What it does |
|---|---|
| `mark_ready_for_review <pr#>` | Require a terminal `SENPAI-RESULT` marker, then mark the PR as ready + swap `status:wip` → `status:review`. |

### Queries (both roles)

The default repo for `gh` is set via the injected `GH_REPO` env var, so no `--repo` flag is needed.

| Function | What it does |
|---|---|
| `check_gh_issues <role_label>` | List open human issues for a role label + team issues, deduplicated. Returns JSON array. |
| `issue_body <issue#>` | Read one issue body through REST. Returns JSON. |
| `issue_comments <issue#>` | Read all issue comments through REST pagination. Returns JSON array. |
| `issue_with_comments <issue#>` | Read one issue and all comments through REST pagination. Returns JSON object. |
| `list_ready_for_review_prs <branch>` | List PRs with `status:review` on a branch. Returns JSON array. |
| `list_prs_requiring_advisor_action <branch> [stale_wip_seconds] [student_names_csv]` | List open branch PRs requiring advisor action, with `reasons` such as stale WIP, duplicate student WIP, missing, unknown, or unroutable student labels, or rebase conflicts. Returns JSON array. |
| `list_all_prs <branch>` | List all open PRs on a branch (any status). Returns JSON array. |
| `student_poll_for_work <student_name> [branch]` | List branch-scoped WIP PRs assigned to a student. Returns JSON array. |
| `list_idle_students <names_csv> <branch>` | Print names of students with no `status:wip` PR, one per line. |
| `pr_body <pr#>` | Read one PR body through REST. Returns JSON. |
| `pr_issue_comments <pr#>` | Read all PR conversation comments through REST pagination. Returns JSON array. |
| `pr_reviews <pr#>` | Read all PR review submissions through REST pagination. Returns JSON array. |
| `pr_review_comments <pr#>` | Read all inline PR review comments through REST pagination. Returns JSON array. |
| `pr_all_comments <pr#>` | Read all PR conversation, review, and inline comments through REST pagination. Returns JSON array. |
| `training_log_status <logfile> [more-logfiles...]` | Summarize recent training-log state after a sparse wakeup. Use this instead of `tail -f` or Monitor callbacks for epoch progress. |

## Usage examples

```bash
source "${CLAUDE_PLUGIN_ROOT}/scripts/senpai-gh.sh"

# Advisor sends a PR back for revision
send_pr_back_to_student_with_comment 1842 "ADVISOR: Promising direction but didn't beat baseline. Try lr=1e-3 with cosine annealing."

# Leave a plain comment
comment_on_pr 1842 "ADVISOR: Please stop the current run; the branch is no longer assigned."

# Student marks PR ready for review
mark_ready_for_review 1842

# Advisor closes a dead end
close_pr_with_comment 1850 "results 12% worse than baseline with no promising signal"

# Check who's idle
list_idle_students "frieren,fern,stark" "noam"

# List PRs awaiting review
list_ready_for_review_prs "noam"
```
