{"owner":"aio-libs","repo":"aiohttp","hasSkills":true,"totalSkillsCount":3,"totalTokensCount":3021,"categories":["claude-rule","root-instruction","anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md","AGENTS.md",".claude/skills/backport-failed/SKILL.md"],"skills":{"CLAUDE.md":"@~/.claude/aio-libs/context.md\n@~/.claude/aio-libs/aiohttp/context.md\n@AGENTS.md\n@CLAUDE.local.md\n","AGENTS.md":"# AGENTS.md\n\nThis file provides guidance to AI coding agents working with this repository.\n\n## Branching\n\n- All new features and bug fixes target `master`. A bot creates backports to the `x.y` release branches automatically.\n\n## Build\n\n- Full dev setup: `make install-dev` (installs deps, cythonizes, builds extensions)\n- Vendored llhttp: `git submodule update --init` + `make generate-llhttp` (requires Node.js)\n- Cython extensions: `make cythonize` (.pyx → .c), then `pip install -e .` to compile\n- Pure Python mode: `AIOHTTP_NO_EXTENSIONS=1 pip install -e .`\n- `AIOHTTP_CYTHON_TRACE=1` enables Cython trace macros (only useful with linetrace-enabled .c files)\n\n## Test\n\n- Run all: `PYTHONPATH='.' pytest --numprocesses=auto`\n- Single test: `PYTHONPATH='.' pytest tests/test_foo.py::test_name`\n- Pure Python only: `PYTHONPATH='.' AIOHTTP_NO_EXTENSIONS=1 pytest`\n\n## Lint & Format\n\n- `pre-commit run --all-files` runs all checks (black, isort, flake8, pyupgrade, codespell)\n- `black` for formatting only, `mypy` for type checking\n- black with 88-col line length, isort with trailing commas\n\n## Documentation & code style\n\n- User-visible API changes need a docs update under `docs/` (`docs/client_reference.rst` / `docs/web_reference.rst` plus any narrative pages).\n- Docstrings in code, prose in Sphinx; `make doc` builds locally.\n- No docstrings or comments that just restate the code.\n\n## Changelog\n\n- Fragments in `CHANGES/{pr_or_issue}.{type}.rst` (valid types are defined in `pyproject.toml` under `[tool.towncrier]`).\n- Sign with `` -- by :user:`github-handle` ``.\n- Both issue and PR number wanted: keep the issue-numbered file and symlink: `ln -s 1234.bugfix.rst CHANGES/1240.bugfix.rst`.\n- Multiple fragments same category: `1234.feature.rst`, `1234.feature.1.rst`.\n\n## PRs\n\n- **Prove it works before opening the PR**. This means:\n  - Relevant tests pass locally.\n  - New behaviour is covered by a test.\n  - Any parser/websocket related changes have been tested with Cython extensions installed.\n- Use the shipped template at [`.github/PULL_REQUEST_TEMPLATE.md`](.github/PULL_REQUEST_TEMPLATE.md).\n  - A couple of sentences per section is plenty.\n  - Tick checklist boxes that apply; write `N/A` next to ones that do not.\n  - First-time contributors add themselves to `CONTRIBUTORS.txt` (alphabetical by first name).\n- **Draft.** Use `gh pr create --draft`.\n  - Every submission must be reviewed by a human before going out of draft; that review is the operator's job, not the maintainers'.\n  - Do not mark ready or request reviewers yourself.\n- **Disclosure.** One plain line at the bottom: `Drafted with <agent name and version>; reviewed by <human handle>.`\n- **No `Co-Authored-By:`** LLM trailers in commits or PR body.\n- Agent run output (test logs) goes in a collapsed `<details>` block **below** the template summary.\n\n**Commits**: Don't use conventional commits; match recent imperative subjects.\n\n## Threat model\n\n`THREAT_MODEL.md` is a living document and should be revised when:\n\n- A CVE / GHSA is filed against aiohttp.\n- The parser configuration changes (llhttp lenient flags, size limits, version regex).\n- Any default referenced in the document changes (`client_max_size`, `client_max_fields`, `keepalive_timeout`, `max_redirects`, `limit`, `limit_per_host`, etc.).\n- The vendored llhttp version is bumped.\n- A public API surface is added or removed in `client.py` / `web_*.py` / `multipart.py`.\n\nWhen a chunk's content is materially affected, update both the chunk and the relevant entries in §6.1–§6.4. The \"Past advisories / hardening (recap)\" subsection of each chunk is the audit trail for what has been verified-in-place.\n",".claude/skills/backport-failed/SKILL.md":"---\nname: backport-failed\ndescription: Create a manual backport to recover from a Patchback auto-backport failure.\n---\n\n# /backport-failed — Manual recovery for failed patchback backports\n\nWhen patchback (the auto-backport bot used by aio-libs and similar orgs) fails to cherry-pick a merged PR onto a stable branch, it leaves a comment like:\n\n> ### Backport to 3.13: 💔 cherry-picking failed — conflicts found\n> ❌ Failed to cleanly apply `<sha>` on top of `patchback/backports/3.13/<sha>/pr-<num>`\n\nThis skill produces the manual backport PRs that should have been created, matching patchback's exact shape so the PR list stays uniform.\n\nArguments passed: `$ARGUMENTS` — usually a PR number (e.g. `12581`). If empty, ask the user for it via `AskUserQuestion`.\n\n## The exact patchback PR shape\n\nEvery backport PR this skill opens **must** match this shape (study PRs authored by `patchback[bot]` — e.g. aio-libs/aiohttp#12574 — for the canonical form):\n\n- **Title:** `[PR #<orig_num>/<short_sha> backport][<branch>] <original PR title>`\n  - `<short_sha>` is the first 8 chars of the merge commit on master\n  - `<branch>` is the target branch, e.g. `3.13`, `3.14`\n- **Body first line:** `**This is a backport of PR #<orig_num> as merged into master (<full_sha>).**`\n- **Body remainder:** the *original* PR body verbatim (including the HTML template comments and the unchecked checklist items as patchback preserves them — copy what's on the original PR)\n- **Base branch:** the stable branch (`3.13`, `3.14`, etc.)\n- **Head branch on fork:** `patchback/backports/<branch>/<full_sha>/pr-<orig_num>`\n\nDo **not** add a \"Drafted with Claude Code\" footer, do **not** add Co-Authored-By, do **not** edit or summarize the original body. The goal is byte-for-byte indistinguishability from a successful patchback PR.\n\n## Procedure\n\n### 1. Resolve the PR number and gather metadata\n\nIf `$ARGUMENTS` is empty, ask the user for the PR number with `AskUserQuestion`. Then in parallel:\n\n```bash\ngh pr view <num> --repo <owner/repo> --json number,title,body,mergeCommit,headRepositoryOwner,baseRefName,labels,url\ngh pr view <num> --repo <owner/repo> --comments\n```\n\nDetect the repo from the working directory's `upstream` remote (`git remote get-url upstream`). If there is no `upstream` remote, ask the user which remote points at the canonical repo.\n\nExtract:\n- `orig_num` — the PR number\n- `orig_title` — the PR title (use as-is, do not modify)\n- `orig_body` — the PR body (use as-is, do not modify, do not strip HTML comments)\n- `full_sha` — the merge commit SHA on master (from `mergeCommit.oid`)\n- `short_sha` — first 8 chars of `full_sha`\n\n### 2. Find the failed target branches\n\nFrom the comments output, find each patchback comment that says **\"💔 cherry-picking failed — conflicts found\"** and extract the target branch from the heading (`Backport to <branch>:`).\n\nSanity check against PR labels: patchback is driven by labels like `backport-3.13`, `backport-3.14`. The set of failed branches should be a subset of those labels. If a backport label has no patchback failure comment and no existing backport PR, that target probably succeeded automatically — skip it.\n\nTo confirm a branch genuinely needs a manual backport, check whether a successful backport PR already exists:\n\n```bash\ngh pr list --repo <owner/repo> --search \"[PR #<orig_num>/<short_sha> backport]\" --state all\n```\n\nIf a PR with the expected title already exists for that branch, skip it.\n\n### 3. Verify the working tree is clean enough to checkout branches\n\n```bash\ngit status --porcelain\n```\n\nIf there are staged/unstaged changes to tracked files, stop and tell the user. Untracked files are fine — patchback's workflow doesn't touch them.\n\nRemember the current branch so you can return to it at the end:\n\n```bash\ngit rev-parse --abbrev-ref HEAD\n```\n\n### 4. For each failed branch, create the backport\n\nRun these steps **sequentially per branch** — never parallelize across target branches (they share the working tree).\n\n```bash\ngit fetch upstream\ngit checkout -b patchback/backports/<branch>/<full_sha>/pr-<orig_num> upstream/<branch>\ngit cherry-pick -x <full_sha>\n```\n\nIf the commit is a merge commit (`git cat-file -p <full_sha> | grep -c '^parent '` returns > 1), use `git cherry-pick -m1 -x <full_sha>` instead. For squash-merged PRs (the common case on aio-libs) it's a single-parent commit, so plain `-x` works.\n\n#### Resolving conflicts\n\nIf cherry-pick reports conflicts:\n\n1. Run `git status` to list conflicted files.\n2. For each file, Read it, locate the `<<<<<<<`/`=======`/`>>>>>>>` markers, and resolve.\n3. **Conflict-resolution principles** (in order):\n   - Preserve the *intent* of the original PR — the change being backported is the source of truth for what should land.\n   - Adapt to the stable branch's existing context. The conflict usually means surrounding code differs (e.g. a function got renamed on master but not on 3.13). Apply the PR's logical change to the stable branch's version of the code.\n   - For news fragments (`CHANGES/*.rst`) the file usually doesn't exist on the stable branch yet — just take the master version.\n   - If you cannot confidently resolve a conflict, **stop and ask the user**. Do not guess. Show the conflict markers and your proposed resolution, and let them confirm.\n4. `git add <file>` for each resolved file.\n5. `git cherry-pick --continue` (use a non-interactive editor: `GIT_EDITOR=true git cherry-pick --continue` to keep the cherry-pick's default message which already contains the `(cherry picked from commit ...)` trailer from `-x`).\n\n#### Push to the user's fork\n\nThe user's fork remote is conventionally `origin` for aio-libs contributors (or named after their GitHub handle). Detect it:\n\n```bash\ngit remote -v | grep -E \"(fetch)\" | grep -v upstream\n```\n\nIf multiple non-upstream remotes exist, prefer one matching the GitHub user from `gh api user --jq .login`. Ask the user if ambiguous.\n\n```bash\ngit push <fork_remote> patchback/backports/<branch>/<full_sha>/pr-<orig_num>\n```\n\n#### Open the backport PR\n\nUse a HEREDOC so the body is preserved exactly. The body of the new PR is the **original PR's body**, prepended with the `**This is a backport...**` line and a blank line:\n\n```bash\ngh pr create \\\n  --repo <owner/repo> \\\n  --base <branch> \\\n  --head <fork_owner>:patchback/backports/<branch>/<full_sha>/pr-<orig_num> \\\n  --title \"[PR #<orig_num>/<short_sha> backport][<branch>] <orig_title>\" \\\n  --body \"$(cat <<'EOF'\n**This is a backport of PR #<orig_num> as merged into master (<full_sha>).**\n\n<orig_body verbatim>\nEOF\n)\"\n```\n\nIf `<orig_body>` contains an `EOF` marker itself (rare), pick a different HEREDOC delimiter (e.g. `PATCHBACK_BODY`).\n\nReport the new PR URL.\n\n### 5. Return to the original branch\n\nAfter all backports are done (or after stopping for user input):\n\n```bash\ngit checkout <original_branch>\n```\n\nLeave the patchback branches in place locally — the user may want to amend them.\n\n## Output to the user\n\nAt the end, print a short summary:\n\n- Which branches had failed backports\n- For each: the new PR URL, or `skipped (already exists)`, or `paused for user (conflict in <file>)`\n\nKeep it terse — one line per branch.\n\n## Edge cases\n\n- **No patchback failure comments found.** Tell the user the PR's auto-backports look healthy and ask if they want to force a manual backport anyway.\n- **Cherry-pick is clean (no conflicts).** Still legitimate — patchback may have failed for a transient reason. Proceed to push and PR creation as normal.\n- **PR was a merge commit, not a squash.** Use `-m1` as noted above.\n- **The fork already has the branch.** `git push --force-with-lease` only if the user confirms (`AskUserQuestion`). Never `--force` blindly.\n- **News fragment filename differs.** Patchback preserves whatever filename the original PR used; do not rename.\n- **Stable branch is end-of-life.** If `gh api repos/<owner>/<repo>/branches/<branch>` 404s, tell the user — the backport label may be stale.\n"},"files":{"CLAUDE.md":"@~/.claude/aio-libs/context.md\n@~/.claude/aio-libs/aiohttp/context.md\n@AGENTS.md\n@CLAUDE.local.md\n","AGENTS.md":"# AGENTS.md\n\nThis file provides guidance to AI coding agents working with this repository.\n\n## Branching\n\n- All new features and bug fixes target `master`. A bot creates backports to the `x.y` release branches automatically.\n\n## Build\n\n- Full dev setup: `make install-dev` (installs deps, cythonizes, builds extensions)\n- Vendored llhttp: `git submodule update --init` + `make generate-llhttp` (requires Node.js)\n- Cython extensions: `make cythonize` (.pyx → .c), then `pip install -e .` to compile\n- Pure Python mode: `AIOHTTP_NO_EXTENSIONS=1 pip install -e .`\n- `AIOHTTP_CYTHON_TRACE=1` enables Cython trace macros (only useful with linetrace-enabled .c files)\n\n## Test\n\n- Run all: `PYTHONPATH='.' pytest --numprocesses=auto`\n- Single test: `PYTHONPATH='.' pytest tests/test_foo.py::test_name`\n- Pure Python only: `PYTHONPATH='.' AIOHTTP_NO_EXTENSIONS=1 pytest`\n\n## Lint & Format\n\n- `pre-commit run --all-files` runs all checks (black, isort, flake8, pyupgrade, codespell)\n- `black` for formatting only, `mypy` for type checking\n- black with 88-col line length, isort with trailing commas\n\n## Documentation & code style\n\n- User-visible API changes need a docs update under `docs/` (`docs/client_reference.rst` / `docs/web_reference.rst` plus any narrative pages).\n- Docstrings in code, prose in Sphinx; `make doc` builds locally.\n- No docstrings or comments that just restate the code.\n\n## Changelog\n\n- Fragments in `CHANGES/{pr_or_issue}.{type}.rst` (valid types are defined in `pyproject.toml` under `[tool.towncrier]`).\n- Sign with `` -- by :user:`github-handle` ``.\n- Both issue and PR number wanted: keep the issue-numbered file and symlink: `ln -s 1234.bugfix.rst CHANGES/1240.bugfix.rst`.\n- Multiple fragments same category: `1234.feature.rst`, `1234.feature.1.rst`.\n\n## PRs\n\n- **Prove it works before opening the PR**. This means:\n  - Relevant tests pass locally.\n  - New behaviour is covered by a test.\n  - Any parser/websocket related changes have been tested with Cython extensions installed.\n- Use the shipped template at [`.github/PULL_REQUEST_TEMPLATE.md`](.github/PULL_REQUEST_TEMPLATE.md).\n  - A couple of sentences per section is plenty.\n  - Tick checklist boxes that apply; write `N/A` next to ones that do not.\n  - First-time contributors add themselves to `CONTRIBUTORS.txt` (alphabetical by first name).\n- **Draft.** Use `gh pr create --draft`.\n  - Every submission must be reviewed by a human before going out of draft; that review is the operator's job, not the maintainers'.\n  - Do not mark ready or request reviewers yourself.\n- **Disclosure.** One plain line at the bottom: `Drafted with <agent name and version>; reviewed by <human handle>.`\n- **No `Co-Authored-By:`** LLM trailers in commits or PR body.\n- Agent run output (test logs) goes in a collapsed `<details>` block **below** the template summary.\n\n**Commits**: Don't use conventional commits; match recent imperative subjects.\n\n## Threat model\n\n`THREAT_MODEL.md` is a living document and should be revised when:\n\n- A CVE / GHSA is filed against aiohttp.\n- The parser configuration changes (llhttp lenient flags, size limits, version regex).\n- Any default referenced in the document changes (`client_max_size`, `client_max_fields`, `keepalive_timeout`, `max_redirects`, `limit`, `limit_per_host`, etc.).\n- The vendored llhttp version is bumped.\n- A public API surface is added or removed in `client.py` / `web_*.py` / `multipart.py`.\n\nWhen a chunk's content is materially affected, update both the chunk and the relevant entries in §6.1–§6.4. The \"Past advisories / hardening (recap)\" subsection of each chunk is the audit trail for what has been verified-in-place.\n",".claude/skills/backport-failed/SKILL.md":"---\nname: backport-failed\ndescription: Create a manual backport to recover from a Patchback auto-backport failure.\n---\n\n# /backport-failed — Manual recovery for failed patchback backports\n\nWhen patchback (the auto-backport bot used by aio-libs and similar orgs) fails to cherry-pick a merged PR onto a stable branch, it leaves a comment like:\n\n> ### Backport to 3.13: 💔 cherry-picking failed — conflicts found\n> ❌ Failed to cleanly apply `<sha>` on top of `patchback/backports/3.13/<sha>/pr-<num>`\n\nThis skill produces the manual backport PRs that should have been created, matching patchback's exact shape so the PR list stays uniform.\n\nArguments passed: `$ARGUMENTS` — usually a PR number (e.g. `12581`). If empty, ask the user for it via `AskUserQuestion`.\n\n## The exact patchback PR shape\n\nEvery backport PR this skill opens **must** match this shape (study PRs authored by `patchback[bot]` — e.g. aio-libs/aiohttp#12574 — for the canonical form):\n\n- **Title:** `[PR #<orig_num>/<short_sha> backport][<branch>] <original PR title>`\n  - `<short_sha>` is the first 8 chars of the merge commit on master\n  - `<branch>` is the target branch, e.g. `3.13`, `3.14`\n- **Body first line:** `**This is a backport of PR #<orig_num> as merged into master (<full_sha>).**`\n- **Body remainder:** the *original* PR body verbatim (including the HTML template comments and the unchecked checklist items as patchback preserves them — copy what's on the original PR)\n- **Base branch:** the stable branch (`3.13`, `3.14`, etc.)\n- **Head branch on fork:** `patchback/backports/<branch>/<full_sha>/pr-<orig_num>`\n\nDo **not** add a \"Drafted with Claude Code\" footer, do **not** add Co-Authored-By, do **not** edit or summarize the original body. The goal is byte-for-byte indistinguishability from a successful patchback PR.\n\n## Procedure\n\n### 1. Resolve the PR number and gather metadata\n\nIf `$ARGUMENTS` is empty, ask the user for the PR number with `AskUserQuestion`. Then in parallel:\n\n```bash\ngh pr view <num> --repo <owner/repo> --json number,title,body,mergeCommit,headRepositoryOwner,baseRefName,labels,url\ngh pr view <num> --repo <owner/repo> --comments\n```\n\nDetect the repo from the working directory's `upstream` remote (`git remote get-url upstream`). If there is no `upstream` remote, ask the user which remote points at the canonical repo.\n\nExtract:\n- `orig_num` — the PR number\n- `orig_title` — the PR title (use as-is, do not modify)\n- `orig_body` — the PR body (use as-is, do not modify, do not strip HTML comments)\n- `full_sha` — the merge commit SHA on master (from `mergeCommit.oid`)\n- `short_sha` — first 8 chars of `full_sha`\n\n### 2. Find the failed target branches\n\nFrom the comments output, find each patchback comment that says **\"💔 cherry-picking failed — conflicts found\"** and extract the target branch from the heading (`Backport to <branch>:`).\n\nSanity check against PR labels: patchback is driven by labels like `backport-3.13`, `backport-3.14`. The set of failed branches should be a subset of those labels. If a backport label has no patchback failure comment and no existing backport PR, that target probably succeeded automatically — skip it.\n\nTo confirm a branch genuinely needs a manual backport, check whether a successful backport PR already exists:\n\n```bash\ngh pr list --repo <owner/repo> --search \"[PR #<orig_num>/<short_sha> backport]\" --state all\n```\n\nIf a PR with the expected title already exists for that branch, skip it.\n\n### 3. Verify the working tree is clean enough to checkout branches\n\n```bash\ngit status --porcelain\n```\n\nIf there are staged/unstaged changes to tracked files, stop and tell the user. Untracked files are fine — patchback's workflow doesn't touch them.\n\nRemember the current branch so you can return to it at the end:\n\n```bash\ngit rev-parse --abbrev-ref HEAD\n```\n\n### 4. For each failed branch, create the backport\n\nRun these steps **sequentially per branch** — never parallelize across target branches (they share the working tree).\n\n```bash\ngit fetch upstream\ngit checkout -b patchback/backports/<branch>/<full_sha>/pr-<orig_num> upstream/<branch>\ngit cherry-pick -x <full_sha>\n```\n\nIf the commit is a merge commit (`git cat-file -p <full_sha> | grep -c '^parent '` returns > 1), use `git cherry-pick -m1 -x <full_sha>` instead. For squash-merged PRs (the common case on aio-libs) it's a single-parent commit, so plain `-x` works.\n\n#### Resolving conflicts\n\nIf cherry-pick reports conflicts:\n\n1. Run `git status` to list conflicted files.\n2. For each file, Read it, locate the `<<<<<<<`/`=======`/`>>>>>>>` markers, and resolve.\n3. **Conflict-resolution principles** (in order):\n   - Preserve the *intent* of the original PR — the change being backported is the source of truth for what should land.\n   - Adapt to the stable branch's existing context. The conflict usually means surrounding code differs (e.g. a function got renamed on master but not on 3.13). Apply the PR's logical change to the stable branch's version of the code.\n   - For news fragments (`CHANGES/*.rst`) the file usually doesn't exist on the stable branch yet — just take the master version.\n   - If you cannot confidently resolve a conflict, **stop and ask the user**. Do not guess. Show the conflict markers and your proposed resolution, and let them confirm.\n4. `git add <file>` for each resolved file.\n5. `git cherry-pick --continue` (use a non-interactive editor: `GIT_EDITOR=true git cherry-pick --continue` to keep the cherry-pick's default message which already contains the `(cherry picked from commit ...)` trailer from `-x`).\n\n#### Push to the user's fork\n\nThe user's fork remote is conventionally `origin` for aio-libs contributors (or named after their GitHub handle). Detect it:\n\n```bash\ngit remote -v | grep -E \"(fetch)\" | grep -v upstream\n```\n\nIf multiple non-upstream remotes exist, prefer one matching the GitHub user from `gh api user --jq .login`. Ask the user if ambiguous.\n\n```bash\ngit push <fork_remote> patchback/backports/<branch>/<full_sha>/pr-<orig_num>\n```\n\n#### Open the backport PR\n\nUse a HEREDOC so the body is preserved exactly. The body of the new PR is the **original PR's body**, prepended with the `**This is a backport...**` line and a blank line:\n\n```bash\ngh pr create \\\n  --repo <owner/repo> \\\n  --base <branch> \\\n  --head <fork_owner>:patchback/backports/<branch>/<full_sha>/pr-<orig_num> \\\n  --title \"[PR #<orig_num>/<short_sha> backport][<branch>] <orig_title>\" \\\n  --body \"$(cat <<'EOF'\n**This is a backport of PR #<orig_num> as merged into master (<full_sha>).**\n\n<orig_body verbatim>\nEOF\n)\"\n```\n\nIf `<orig_body>` contains an `EOF` marker itself (rare), pick a different HEREDOC delimiter (e.g. `PATCHBACK_BODY`).\n\nReport the new PR URL.\n\n### 5. Return to the original branch\n\nAfter all backports are done (or after stopping for user input):\n\n```bash\ngit checkout <original_branch>\n```\n\nLeave the patchback branches in place locally — the user may want to amend them.\n\n## Output to the user\n\nAt the end, print a short summary:\n\n- Which branches had failed backports\n- For each: the new PR URL, or `skipped (already exists)`, or `paused for user (conflict in <file>)`\n\nKeep it terse — one line per branch.\n\n## Edge cases\n\n- **No patchback failure comments found.** Tell the user the PR's auto-backports look healthy and ask if they want to force a manual backport anyway.\n- **Cherry-pick is clean (no conflicts).** Still legitimate — patchback may have failed for a transient reason. Proceed to push and PR creation as normal.\n- **PR was a merge commit, not a squash.** Use `-m1` as noted above.\n- **The fork already has the branch.** `git push --force-with-lease` only if the user confirms (`AskUserQuestion`). Never `--force` blindly.\n- **News fragment filename differs.** Patchback preserves whatever filename the original PR used; do not rename.\n- **Stable branch is end-of-life.** If `gh api repos/<owner>/<repo>/branches/<branch>` 404s, tell the user — the backport label may be stale.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/aio-libs/aiohttp/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AGENTS.md\n\nThis file provides guidance to AI coding agents working with this repository.\n\n## Branching\n\n- All new features and bug fixes target `master`. A bot creates backports to the `x.y` release branches automatically.\n\n## Build\n\n- Full dev setup: `make install-dev` (installs deps, cythonizes, builds extensions)\n- Vendored llhttp: `git submodule update --init` + `make generate-llhttp` (requires Node.js)\n- Cython extensions: `make cythonize` (.pyx → .c), then `pip install -e .` to compile\n- Pure Python mode: `AIOHTTP_NO_EXTENSIONS=1 pip install -e .`\n- `AIOHTTP_CYTHON_TRACE=1` enables Cython trace macros (only useful with linetrace-enabled .c files)\n\n## Test\n\n- Run all: `PYTHONPATH='.' pytest --numprocesses=auto`\n- Single test: `PYTHONPATH='.' pytest tests/test_foo.py::test_name`\n- Pure Python only: `PYTHONPATH='.' AIOHTTP_NO_EXTENSIONS=1 pytest`\n\n## Lint & Format\n\n- `pre-commit run --all-files` runs all checks (black, isort, flake8, pyupgrade, codespell)\n- `black` for formatting only, `mypy` for type checking\n- black with 88-col line length, isort with trailing commas\n\n## Documentation & code style\n\n- User-visible API changes need a docs update under `docs/` (`docs/client_reference.rst` / `docs/web_reference.rst` plus any narrative pages).\n- Docstrings in code, prose in Sphinx; `make doc` builds locally.\n- No docstrings or comments that just restate the code.\n\n## Changelog\n\n- Fragments in `CHANGES/{pr_or_issue}.{type}.rst` (valid types are defined in `pyproject.toml` under `[tool.towncrier]`).\n- Sign with `` -- by :user:`github-handle` ``.\n- Both issue and PR number wanted: keep the issue-numbered file and symlink: `ln -s 1234.bugfix.rst CHANGES/1240.bugfix.rst`.\n- Multiple fragments same category: `1234.feature.rst`, `1234.feature.1.rst`.\n\n## PRs\n\n- **Prove it works before opening the PR**. This means:\n  - Relevant tests pass locally.\n  - New behaviour is covered by a test.\n  - Any parser/websocket related changes have been tested with Cython extensions installed.\n- Use the shipped template at [`.github/PULL_REQUEST_TEMPLATE.md`](.github/PULL_REQUEST_TEMPLATE.md).\n  - A couple of sentences per section is plenty.\n  - Tick checklist boxes that apply; write `N/A` next to ones that do not.\n  - First-time contributors add themselves to `CONTRIBUTORS.txt` (alphabetical by first name).\n- **Draft.** Use `gh pr create --draft`.\n  - Every submission must be reviewed by a human before going out of draft; that review is the operator's job, not the maintainers'.\n  - Do not mark ready or request reviewers yourself.\n- **Disclosure.** One plain line at the bottom: `Drafted with <agent name and version>; reviewed by <human handle>.`\n- **No `Co-Authored-By:`** LLM trailers in commits or PR body.\n- Agent run output (test logs) goes in a collapsed `<details>` block **below** the template summary.\n\n**Commits**: Don't use conventional commits; match recent imperative subjects.\n\n## Threat model\n\n`THREAT_MODEL.md` is a living document and should be revised when:\n\n- A CVE / GHSA is filed against aiohttp.\n- The parser configuration changes (llhttp lenient flags, size limits, version regex).\n- Any default referenced in the document changes (`client_max_size`, `client_max_fields`, `keepalive_timeout`, `max_redirects`, `limit`, `limit_per_host`, etc.).\n- The vendored llhttp version is bumped.\n- A public API surface is added or removed in `client.py` / `web_*.py` / `multipart.py`.\n\nWhen a chunk's content is materially affected, update both the chunk and the relevant entries in §6.1–§6.4. The \"Past advisories / hardening (recap)\" subsection of each chunk is the audit trail for what has been verified-in-place.\n","isInternal":false,"tokens":936,"sizeBytes":3659},{"name":"SKILL.md","path":".claude/skills/backport-failed/SKILL.md","rawUrl":"https://raw.githubusercontent.com/aio-libs/aiohttp/HEAD/.claude/skills/backport-failed/SKILL.md","title":"backport-failed","category":"anthropic-skill","format":"markdown","content":"---\nname: backport-failed\ndescription: Create a manual backport to recover from a Patchback auto-backport failure.\n---\n\n# /backport-failed — Manual recovery for failed patchback backports\n\nWhen patchback (the auto-backport bot used by aio-libs and similar orgs) fails to cherry-pick a merged PR onto a stable branch, it leaves a comment like:\n\n> ### Backport to 3.13: 💔 cherry-picking failed — conflicts found\n> ❌ Failed to cleanly apply `<sha>` on top of `patchback/backports/3.13/<sha>/pr-<num>`\n\nThis skill produces the manual backport PRs that should have been created, matching patchback's exact shape so the PR list stays uniform.\n\nArguments passed: `$ARGUMENTS` — usually a PR number (e.g. `12581`). If empty, ask the user for it via `AskUserQuestion`.\n\n## The exact patchback PR shape\n\nEvery backport PR this skill opens **must** match this shape (study PRs authored by `patchback[bot]` — e.g. aio-libs/aiohttp#12574 — for the canonical form):\n\n- **Title:** `[PR #<orig_num>/<short_sha> backport][<branch>] <original PR title>`\n  - `<short_sha>` is the first 8 chars of the merge commit on master\n  - `<branch>` is the target branch, e.g. `3.13`, `3.14`\n- **Body first line:** `**This is a backport of PR #<orig_num> as merged into master (<full_sha>).**`\n- **Body remainder:** the *original* PR body verbatim (including the HTML template comments and the unchecked checklist items as patchback preserves them — copy what's on the original PR)\n- **Base branch:** the stable branch (`3.13`, `3.14`, etc.)\n- **Head branch on fork:** `patchback/backports/<branch>/<full_sha>/pr-<orig_num>`\n\nDo **not** add a \"Drafted with Claude Code\" footer, do **not** add Co-Authored-By, do **not** edit or summarize the original body. The goal is byte-for-byte indistinguishability from a successful patchback PR.\n\n## Procedure\n\n### 1. Resolve the PR number and gather metadata\n\nIf `$ARGUMENTS` is empty, ask the user for the PR number with `AskUserQuestion`. Then in parallel:\n\n```bash\ngh pr view <num> --repo <owner/repo> --json number,title,body,mergeCommit,headRepositoryOwner,baseRefName,labels,url\ngh pr view <num> --repo <owner/repo> --comments\n```\n\nDetect the repo from the working directory's `upstream` remote (`git remote get-url upstream`). If there is no `upstream` remote, ask the user which remote points at the canonical repo.\n\nExtract:\n- `orig_num` — the PR number\n- `orig_title` — the PR title (use as-is, do not modify)\n- `orig_body` — the PR body (use as-is, do not modify, do not strip HTML comments)\n- `full_sha` — the merge commit SHA on master (from `mergeCommit.oid`)\n- `short_sha` — first 8 chars of `full_sha`\n\n### 2. Find the failed target branches\n\nFrom the comments output, find each patchback comment that says **\"💔 cherry-picking failed — conflicts found\"** and extract the target branch from the heading (`Backport to <branch>:`).\n\nSanity check against PR labels: patchback is driven by labels like `backport-3.13`, `backport-3.14`. The set of failed branches should be a subset of those labels. If a backport label has no patchback failure comment and no existing backport PR, that target probably succeeded automatically — skip it.\n\nTo confirm a branch genuinely needs a manual backport, check whether a successful backport PR already exists:\n\n```bash\ngh pr list --repo <owner/repo> --search \"[PR #<orig_num>/<short_sha> backport]\" --state all\n```\n\nIf a PR with the expected title already exists for that branch, skip it.\n\n### 3. Verify the working tree is clean enough to checkout branches\n\n```bash\ngit status --porcelain\n```\n\nIf there are staged/unstaged changes to tracked files, stop and tell the user. Untracked files are fine — patchback's workflow doesn't touch them.\n\nRemember the current branch so you can return to it at the end:\n\n```bash\ngit rev-parse --abbrev-ref HEAD\n```\n\n### 4. For each failed branch, create the backport\n\nRun these steps **sequentially per branch** — never parallelize across target branches (they share the working tree).\n\n```bash\ngit fetch upstream\ngit checkout -b patchback/backports/<branch>/<full_sha>/pr-<orig_num> upstream/<branch>\ngit cherry-pick -x <full_sha>\n```\n\nIf the commit is a merge commit (`git cat-file -p <full_sha> | grep -c '^parent '` returns > 1), use `git cherry-pick -m1 -x <full_sha>` instead. For squash-merged PRs (the common case on aio-libs) it's a single-parent commit, so plain `-x` works.\n\n#### Resolving conflicts\n\nIf cherry-pick reports conflicts:\n\n1. Run `git status` to list conflicted files.\n2. For each file, Read it, locate the `<<<<<<<`/`=======`/`>>>>>>>` markers, and resolve.\n3. **Conflict-resolution principles** (in order):\n   - Preserve the *intent* of the original PR — the change being backported is the source of truth for what should land.\n   - Adapt to the stable branch's existing context. The conflict usually means surrounding code differs (e.g. a function got renamed on master but not on 3.13). Apply the PR's logical change to the stable branch's version of the code.\n   - For news fragments (`CHANGES/*.rst`) the file usually doesn't exist on the stable branch yet — just take the master version.\n   - If you cannot confidently resolve a conflict, **stop and ask the user**. Do not guess. Show the conflict markers and your proposed resolution, and let them confirm.\n4. `git add <file>` for each resolved file.\n5. `git cherry-pick --continue` (use a non-interactive editor: `GIT_EDITOR=true git cherry-pick --continue` to keep the cherry-pick's default message which already contains the `(cherry picked from commit ...)` trailer from `-x`).\n\n#### Push to the user's fork\n\nThe user's fork remote is conventionally `origin` for aio-libs contributors (or named after their GitHub handle). Detect it:\n\n```bash\ngit remote -v | grep -E \"(fetch)\" | grep -v upstream\n```\n\nIf multiple non-upstream remotes exist, prefer one matching the GitHub user from `gh api user --jq .login`. Ask the user if ambiguous.\n\n```bash\ngit push <fork_remote> patchback/backports/<branch>/<full_sha>/pr-<orig_num>\n```\n\n#### Open the backport PR\n\nUse a HEREDOC so the body is preserved exactly. The body of the new PR is the **original PR's body**, prepended with the `**This is a backport...**` line and a blank line:\n\n```bash\ngh pr create \\\n  --repo <owner/repo> \\\n  --base <branch> \\\n  --head <fork_owner>:patchback/backports/<branch>/<full_sha>/pr-<orig_num> \\\n  --title \"[PR #<orig_num>/<short_sha> backport][<branch>] <orig_title>\" \\\n  --body \"$(cat <<'EOF'\n**This is a backport of PR #<orig_num> as merged into master (<full_sha>).**\n\n<orig_body verbatim>\nEOF\n)\"\n```\n\nIf `<orig_body>` contains an `EOF` marker itself (rare), pick a different HEREDOC delimiter (e.g. `PATCHBACK_BODY`).\n\nReport the new PR URL.\n\n### 5. Return to the original branch\n\nAfter all backports are done (or after stopping for user input):\n\n```bash\ngit checkout <original_branch>\n```\n\nLeave the patchback branches in place locally — the user may want to amend them.\n\n## Output to the user\n\nAt the end, print a short summary:\n\n- Which branches had failed backports\n- For each: the new PR URL, or `skipped (already exists)`, or `paused for user (conflict in <file>)`\n\nKeep it terse — one line per branch.\n\n## Edge cases\n\n- **No patchback failure comments found.** Tell the user the PR's auto-backports look healthy and ask if they want to force a manual backport anyway.\n- **Cherry-pick is clean (no conflicts).** Still legitimate — patchback may have failed for a transient reason. Proceed to push and PR creation as normal.\n- **PR was a merge commit, not a squash.** Use `-m1` as noted above.\n- **The fork already has the branch.** `git push --force-with-lease` only if the user confirms (`AskUserQuestion`). Never `--force` blindly.\n- **News fragment filename differs.** Patchback preserves whatever filename the original PR used; do not rename.\n- **Stable branch is end-of-life.** If `gh api repos/<owner>/<repo>/branches/<branch>` 404s, tell the user — the backport label may be stale.\n","frontmatter":{"name":"backport-failed","description":"Create a manual backport to recover from a Patchback auto-backport failure."},"isInternal":false,"tokens":2046,"sizeBytes":8009},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/aio-libs/aiohttp/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"@~/.claude/aio-libs/context.md\n@~/.claude/aio-libs/aiohttp/context.md\n@AGENTS.md\n@CLAUDE.local.md\n","isInternal":false,"tokens":39,"sizeBytes":98}],"systemPromptSnippet":"<yakaai_skills repo=\"aio-libs/aiohttp\">\n<!-- File: AGENTS.md (Tokens: ~936 | Category: root-instruction) -->\n# AGENTS.md\n\nThis file provides guidance to AI coding agents working with this repository.\n\n## Branching\n\n- All new features and bug fixes target `master`. A bot creates backports to the `x.y` release branches automatically.\n\n## Build\n\n- Full dev setup: `make install-dev` (installs deps, cythonizes, builds extensions)\n- Vendored llhttp: `git submodule update --init` + `make generate-llhttp` (requires Node.js)\n- Cython extensions: `make cythonize` (.pyx → .c), then `pip install -e .` to compile\n- Pure Python mode: `AIOHTTP_NO_EXTENSIONS=1 pip install -e .`\n- `AIOHTTP_CYTHON_TRACE=1` enables Cython trace macros (only useful with linetrace-enabled .c files)\n\n## Test\n\n- Run all: `PYTHONPATH='.' pytest --numprocesses=auto`\n- Single test: `PYTHONPATH='.' pytest tests/test_foo.py::test_name`\n- Pure Python only: `PYTHONPATH='.' AIOHTTP_NO_EXTENSIONS=1 pytest`\n\n## Lint & Format\n\n- `pre-commit run --all-files` runs all checks (black, isort, flake8, pyupgrade, codespell)\n- `black` for formatting only, `mypy` for type checking\n- black with 88-col line length, isort with trailing commas\n\n## Documentation & code style\n\n- User-visible API changes need a docs update under `docs/` (`docs/client_reference.rst` / `docs/web_reference.rst` plus any narrative pages).\n- Docstrings in code, prose in Sphinx; `make doc` builds locally.\n- No docstrings or comments that just restate the code.\n\n## Changelog\n\n- Fragments in `CHANGES/{pr_or_issue}.{type}.rst` (valid types are defined in `pyproject.toml` under `[tool.towncrier]`).\n- Sign with `` -- by :user:`github-handle` ``.\n- Both issue and PR number wanted: keep the issue-numbered file and symlink: `ln -s 1234.bugfix.rst CHANGES/1240.bugfix.rst`.\n- Multiple fragments same category: `1234.feature.rst`, `1234.feature.1.rst`.\n\n## PRs\n\n- **Prove it works before opening the PR**. This means:\n  - Relevant tests pass locally.\n  - New behaviour is covered by a test.\n  - Any parser/websocket related changes have been tested with Cython extensions installed.\n- Use the shipped template at [`.github/PULL_REQUEST_TEMPLATE.md`](.github/PULL_REQUEST_TEMPLATE.md).\n  - A couple of sentences per section is plenty.\n  - Tick checklist boxes that apply; write `N/A` next to ones that do not.\n  - First-time contributors add themselves to `CONTRIBUTORS.txt` (alphabetical by first name).\n- **Draft.** Use `gh pr create --draft`.\n  - Every submission must be reviewed by a human before going out of draft; that review is the operator's job, not the maintainers'.\n  - Do not mark ready or request reviewers yourself.\n- **Disclosure.** One plain line at the bottom: `Drafted with <agent name and version>; reviewed by <human handle>.`\n- **No `Co-Authored-By:`** LLM trailers in commits or PR body.\n- Agent run output (test logs) goes in a collapsed `<details>` block **below** the template summary.\n\n**Commits**: Don't use conventional commits; match recent imperative subjects.\n\n## Threat model\n\n`THREAT_MODEL.md` is a living document and should be revised when:\n\n- A CVE / GHSA is filed against aiohttp.\n- The parser configuration changes (llhttp lenient flags, size limits, version regex).\n- Any default referenced in the document changes (`client_max_size`, `client_max_fields`, `keepalive_timeout`, `max_redirects`, `limit`, `limit_per_host`, etc.).\n- The vendored llhttp version is bumped.\n- A public API surface is added or removed in `client.py` / `web_*.py` / `multipart.py`.\n\nWhen a chunk's content is materially affected, update both the chunk and the relevant entries in §6.1–§6.4. The \"Past advisories / hardening (recap)\" subsection of each chunk is the audit trail for what has been verified-in-place.\n\n<!-- File: .claude/skills/backport-failed/SKILL.md (Tokens: ~2046 | Category: anthropic-skill) -->\n---\nname: backport-failed\ndescription: Create a manual backport to recover from a Patchback auto-backport failure.\n---\n\n# /backport-failed — Manual recovery for failed patchback backports\n\nWhen patchback (the auto-backport bot used by aio-libs and similar orgs) fails to cherry-pick a merged PR onto a stable branch, it leaves a comment like:\n\n> ### Backport to 3.13: 💔 cherry-picking failed — conflicts found\n> ❌ Failed to cleanly apply `<sha>` on top of `patchback/backports/3.13/<sha>/pr-<num>`\n\nThis skill produces the manual backport PRs that should have been created, matching patchback's exact shape so the PR list stays uniform.\n\nArguments passed: `$ARGUMENTS` — usually a PR number (e.g. `12581`). If empty, ask the user for it via `AskUserQuestion`.\n\n## The exact patchback PR shape\n\nEvery backport PR this skill opens **must** match this shape (study PRs authored by `patchback[bot]` — e.g. aio-libs/aiohttp#12574 — for the canonical form):\n\n- **Title:** `[PR #<orig_num>/<short_sha> backport][<branch>] <original PR title>`\n  - `<short_sha>` is the first 8 chars of the merge commit on master\n  - `<branch>` is the target branch, e.g. `3.13`, `3.14`\n- **Body first line:** `**This is a backport of PR #<orig_num> as merged into master (<full_sha>).**`\n- **Body remainder:** the *original* PR body verbatim (including the HTML template comments and the unchecked checklist items as patchback preserves them — copy what's on the original PR)\n- **Base branch:** the stable branch (`3.13`, `3.14`, etc.)\n- **Head branch on fork:** `patchback/backports/<branch>/<full_sha>/pr-<orig_num>`\n\nDo **not** add a \"Drafted with Claude Code\" footer, do **not** add Co-Authored-By, do **not** edit or summarize the original body. The goal is byte-for-byte indistinguishability from a successful patchback PR.\n\n## Procedure\n\n### 1. Resolve the PR number and gather metadata\n\nIf `$ARGUMENTS` is empty, ask the user for the PR number with `AskUserQuestion`. Then in parallel:\n\n```bash\ngh pr view <num> --repo <owner/repo> --json number,title,body,mergeCommit,headRepositoryOwner,baseRefName,labels,url\ngh pr view <num> --repo <owner/repo> --comments\n```\n\nDetect the repo from the working directory's `upstream` remote (`git remote get-url upstream`). If there is no `upstream` remote, ask the user which remote points at the canonical repo.\n\nExtract:\n- `orig_num` — the PR number\n- `orig_title` — the PR title (use as-is, do not modify)\n- `orig_body` — the PR body (use as-is, do not modify, do not strip HTML comments)\n- `full_sha` — the merge commit SHA on master (from `mergeCommit.oid`)\n- `short_sha` — first 8 chars of `full_sha`\n\n### 2. Find the failed target branches\n\nFrom the comments output, find each patchback comment that says **\"💔 cherry-picking failed — conflicts found\"** and extract the target branch from the heading (`Backport to <branch>:`).\n\nSanity check against PR labels: patchback is driven by labels like `backport-3.13`, `backport-3.14`. The set of failed branches should be a subset of those labels. If a backport label has no patchback failure comment and no existing backport PR, that target probably succeeded automatically — skip it.\n\nTo confirm a branch genuinely needs a manual backport, check whether a successful backport PR already exists:\n\n```bash\ngh pr list --repo <owner/repo> --search \"[PR #<orig_num>/<short_sha> backport]\" --state all\n```\n\nIf a PR with the expected title already exists for that branch, skip it.\n\n### 3. Verify the working tree is clean enough to checkout branches\n\n```bash\ngit status --porcelain\n```\n\nIf there are staged/unstaged changes to tracked files, stop and tell the user. Untracked files are fine — patchback's workflow doesn't touch them.\n\nRemember the current branch so you can return to it at the end:\n\n```bash\ngit rev-parse --abbrev-ref HEAD\n```\n\n### 4. For each failed branch, create the backport\n\nRun these steps **sequentially per branch** — never parallelize across target branches (they share the working tree).\n\n```bash\ngit fetch upstream\ngit checkout -b patchback/backports/<branch>/<full_sha>/pr-<orig_num> upstream/<branch>\ngit cherry-pick -x <full_sha>\n```\n\nIf the commit is a merge commit (`git cat-file -p <full_sha> | grep -c '^parent '` returns > 1), use `git cherry-pick -m1 -x <full_sha>` instead. For squash-merged PRs (the common case on aio-libs) it's a single-parent commit, so plain `-x` works.\n\n#### Resolving conflicts\n\nIf cherry-pick reports conflicts:\n\n1. Run `git status` to list conflicted files.\n2. For each file, Read it, locate the `<<<<<<<`/`=======`/`>>>>>>>` markers, and resolve.\n3. **Conflict-resolution principles** (in order):\n   - Preserve the *intent* of the original PR — the change being backported is the source of truth for what should land.\n   - Adapt to the stable branch's existing context. The conflict usually means surrounding code differs (e.g. a function got renamed on master but not on 3.13). Apply the PR's logical change to the stable branch's version of the code.\n   - For news fragments (`CHANGES/*.rst`) the file usually doesn't exist on the stable branch yet — just take the master version.\n   - If you cannot confidently resolve a conflict, **stop and ask the user**. Do not guess. Show the conflict markers and your proposed resolution, and let them confirm.\n4. `git add <file>` for each resolved file.\n5. `git cherry-pick --continue` (use a non-interactive editor: `GIT_EDITOR=true git cherry-pick --continue` to keep the cherry-pick's default message which already contains the `(cherry picked from commit ...)` trailer from `-x`).\n\n#### Push to the user's fork\n\nThe user's fork remote is conventionally `origin` for aio-libs contributors (or named after their GitHub handle). Detect it:\n\n```bash\ngit remote -v | grep -E \"(fetch)\" | grep -v upstream\n```\n\nIf multiple non-upstream remotes exist, prefer one matching the GitHub user from `gh api user --jq .login`. Ask the user if ambiguous.\n\n```bash\ngit push <fork_remote> patchback/backports/<branch>/<full_sha>/pr-<orig_num>\n```\n\n#### Open the backport PR\n\nUse a HEREDOC so the body is preserved exactly. The body of the new PR is the **original PR's body**, prepended with the `**This is a backport...**` line and a blank line:\n\n```bash\ngh pr create \\\n  --repo <owner/repo> \\\n  --base <branch> \\\n  --head <fork_owner>:patchback/backports/<branch>/<full_sha>/pr-<orig_num> \\\n  --title \"[PR #<orig_num>/<short_sha> backport][<branch>] <orig_title>\" \\\n  --body \"$(cat <<'EOF'\n**This is a backport of PR #<orig_num> as merged into master (<full_sha>).**\n\n<orig_body verbatim>\nEOF\n)\"\n```\n\nIf `<orig_body>` contains an `EOF` marker itself (rare), pick a different HEREDOC delimiter (e.g. `PATCHBACK_BODY`).\n\nReport the new PR URL.\n\n### 5. Return to the original branch\n\nAfter all backports are done (or after stopping for user input):\n\n```bash\ngit checkout <original_branch>\n```\n\nLeave the patchback branches in place locally — the user may want to amend them.\n\n## Output to the user\n\nAt the end, print a short summary:\n\n- Which branches had failed backports\n- For each: the new PR URL, or `skipped (already exists)`, or `paused for user (conflict in <file>)`\n\nKeep it terse — one line per branch.\n\n## Edge cases\n\n- **No patchback failure comments found.** Tell the user the PR's auto-backports look healthy and ask if they want to force a manual backport anyway.\n- **Cherry-pick is clean (no conflicts).** Still legitimate — patchback may have failed for a transient reason. Proceed to push and PR creation as normal.\n- **PR was a merge commit, not a squash.** Use `-m1` as noted above.\n- **The fork already has the branch.** `git push --force-with-lease` only if the user confirms (`AskUserQuestion`). Never `--force` blindly.\n- **News fragment filename differs.** Patchback preserves whatever filename the original PR used; do not rename.\n- **Stable branch is end-of-life.** If `gh api repos/<owner>/<repo>/branches/<branch>` 404s, tell the user — the backport label may be stale.\n\n<!-- File: CLAUDE.md (Tokens: ~39 | Category: claude-rule) -->\n@~/.claude/aio-libs/context.md\n@~/.claude/aio-libs/aiohttp/context.md\n@AGENTS.md\n@CLAUDE.local.md\n</yakaai_skills>"}