# Adopt Pr

> Bootstrap branch-context on an existing PR. Writes issue-brief.md from the linked issue(s) + current PR state, and backfills pr-decisions.md with decision-bearing entries from already-resolved review threads. Use when picking up a PR mid-flight (yours or someone else's) without prior local context.

- Skill: `pydantic/adopt-pr` (Agent Skill)
- Install (CLI): `npx skillmds@latest add pydantic/adopt-pr`
- Raw SKILL.md: https://api.skillmd.com/api/skills/pydantic/adopt-pr/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: pydantic (https://skillmd.com/u/pydantic)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/pydantic/adopt-pr

---


# Adopt PR -- bootstrap branch-context on an existing PR

Populate `issue-brief.md` and `pr-decisions.md` for a worktree whose PR already
exists and has history.

## When to use

- You checked out an existing PR and the branch-context files are empty
  templates (or absent).
- You are picking up someone else's PR.
- Your own PR predates the branch-context setup and you want to backfill.

Do not use this for fresh work with no PR yet -- write the brief from the linked
issue directly.

## Startup

Bootstrapping presumes the linked issue describes a real problem. If you have
not confirmed that, skim the issue before adopting -- authorship (a bot,
contributor, or automated sweep) is not proof the problem is real.

1. Read `CLAUDE.md` for project context.
2. Instantiate the branch-context instances if they do not exist:
   ```bash
   cd "$(git rev-parse --show-toplevel)"
   D=.claude/skills/branch-context
   [ -f "$D/issue-brief.md" ]   || cp "$D/issue-brief.template.md" "$D/issue-brief.md"
   [ -f "$D/pr-decisions.md" ]  || cp "$D/pr-decisions.template.md" "$D/pr-decisions.md"
   ```
   If `issue-brief.md` already has populated `issues:` frontmatter, ask via
   `AskUserQuestion` whether to overwrite the brief, re-seed decisions, both, or
   neither, before proceeding.

## Step 1 -- Resolve the PR

Parse `$ARGUMENTS`:
- **PR number/URL** -> use it directly.
- **Empty** -> detect from the current branch:
  ```bash
  PR_NUMBER=$(gh pr view --json number -q .number 2>/dev/null)
  ```
  If detection fails, ask via `AskUserQuestion`.

Fetch PR metadata:
```bash
gh pr view "$PR_NUMBER" --json number,title,url,state,headRefName,body,closingIssuesReferences,createdAt,author
```

## Step 2 -- Resolve linked issues

Two sources, in order:
1. `closingIssuesReferences` from the PR metadata (canonical -- set via the PR
   sidebar or `Fixes #N` keywords).
2. Fallback: grep the PR body for `(?:Fixes|Closes|Resolves|Relates to) #\d+` if
   (1) is empty.

For each linked issue:
```bash
gh issue view "<N>" --json number,url,title,state,body,labels,comments
```

If there is no linked issue and the body has no problem description worth
linking, proceed with `issues: []` (free-text problem) -- ask the user whether to
continue or abort.

## Step 3 -- Study the existing diff

Understand the code before synthesizing the brief:
```bash
git fetch origin main 2>/dev/null || git fetch origin master
MERGE_BASE=$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD origin/master)
git diff --stat "$MERGE_BASE"..HEAD
git log --oneline "$MERGE_BASE"..HEAD
```

Map the changes: which files/modules are touched, which tests exist on the
branch (existing tests are implied success criteria), which public symbols
changed, any notable new abstractions.

## Step 4 -- Write `issue-brief.md`

Use the schema in `issue-brief.template.md`. Adaptations for adoption:

- `related_pr`: the PR URL (not `TBD` -- the PR already exists).
- `branch`: `git rev-parse --abbrev-ref HEAD`.
- **Success criteria** -- derive from the issue text and from tests already on
  the branch (each existing test is a de facto criterion; cross-reference them
  in the table).
- **Affected surface** -- extract from the diff, not from a planning pass.
- **Constraints** -- include anything reviewers have already emphasized in
  comments (e.g. "must preserve backwards-compat" from a maintainer reply).

Write to `.claude/skills/branch-context/issue-brief.md`, overwriting the
template.

## Step 5 -- Backfill `pr-decisions.md` from resolved threads

Fetch resolved review threads via the GraphQL API:
```bash
read -r OWNER REPO < <(gh repo view --json owner,name -q '.owner.login + " " + .name')
gh api graphql -f query='
query($owner:String!,$repo:String!,$pr:Int!){
  repository(owner:$owner,name:$repo){
    pullRequest(number:$pr){
      reviewThreads(first:100){ nodes{
        isResolved
        comments(first:50){ nodes{ author{login} bodyText url path } }
      }}
    }
  }
}' -F owner="$OWNER" -F repo="$REPO" -F pr="$PR_NUMBER" \
  --jq '.data.repository.pullRequest.reviewThreads.nodes | map(select(.isResolved))'
```

For each resolved thread, read the full conversation, then classify:

- **Decision-bearing** -- the thread debated two or more options, or a reviewer
  flagged a concern and the author adjusted the code (e.g. "use kwargs over
  positional", "renamed the public method", "moved the helper to a different
  module").
- **Noise** -- typo fixes, "nit: missing docstring", "good catch thanks",
  resolved without a code change. Skip these.

For each decision-bearing thread, append an entry (Source is the root comment's
`url`):
```bash
.claude/skills/branch-context/append-pr-decision.sh \
  --title "thread: <short title>" \
  --decision "<one-line summary of what was decided>" \
  --why "<one-line reason, quoting reviewer or author if concise>" \
  --source "<thread URL>" \
  --iter "-"
```

Decision budget: aim for <=10 entries. If more resolved threads than that seem
worth logging, you are probably over-including noise -- re-apply the filter.

## Step 6 -- Seed an "adoption" meta-entry

Append one final entry marking the boundary between backfilled decisions
(everything above) and live-logged ones (everything below):
```bash
.claude/skills/branch-context/append-pr-decision.sh \
  --title "adopted PR #<N> at <DATE>" \
  --decision "Branch-context bootstrapped from existing PR + issue(s). Decisions above are backfilled from resolved threads." \
  --why "PR predates the branch-context setup" \
  --source "<PR URL>" \
  --iter "-"
```

## Step 7 -- Report

Print a concise summary:
```
Adopted PR #<N> -- "<title>"
  Issues linked: #<A>, #<B>
  Resolved threads seeded: <count> decisions
  Unresolved threads (for later triage): <count>
```

## Rules

- Do not open a new PR (it already exists). Do not commit anything to the branch
  during adoption -- only read, classify, and write the two branch-context files.
- Do not re-classify unresolved threads during adoption -- just report the count.
- Do not log every resolved thread -- only decision-bearing ones. The decisions
  log is meant to reward reading; diluting it with noise defeats the point.
- Every backfilled entry must have a thread URL in `Source:`. If you cannot find
  one, you are over-inferring -- skip it.
- If the existing brief/decisions files are already populated (not templates),
  the user's Startup confirmation governs whether to overwrite.

