From 22b8cc7a92a8dbee0ce2cfc563fc2d03d9a0b406 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 21 Jul 2026 16:17:47 +0200 Subject: [PATCH 01/18] feat(skills): Add backport-pr skill Adds a skill that backports a merged PR to a maintenance major branch (v10 by default, with a target-major parameter for older majors like v9). It cherry-picks the PR's squash-merge commit, namespaces the commit/PR title scope (e.g. fix(core) -> fix(v10/core)), and opens a draft backport PR following the convention used for the v9 backports. Co-Authored-By: Opus 4.8 --- .agents/skills/backport-pr/SKILL.md | 151 ++++++++++++++++++++++++++++ agents.toml | 28 +++++- 2 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 .agents/skills/backport-pr/SKILL.md diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md new file mode 100644 index 000000000000..a51adfdf59e8 --- /dev/null +++ b/.agents/skills/backport-pr/SKILL.md @@ -0,0 +1,151 @@ +--- +name: backport-pr +description: Backport a merged PR to a maintenance major branch (v10 by default) in getsentry/sentry-javascript. Cherry-picks the PR's squash-merge commit onto the target branch, namespaces the commit/PR title scope (e.g. fix(core) -> fix(v10/core)), and opens a draft backport PR. Use when asked to backport a PR, port a fix to v10 (or an older major like v9), or cut a maintenance release change. Trigger phrases include "backport", "port to v10", "cherry-pick to the maintenance branch", "release this on v10". +argument-hint: ' [target-major] # e.g. 18211 v10; target defaults to v10' +--- + +# Backport a PR to a maintenance major branch + +`develop` is the current major (v11). Released changes now go onto the previous major's +maintenance branch (`v10` by default). This skill cherry-picks a merged PR's changes onto +that branch and opens a draft backport PR, following the same convention used for the v9 +backports. + +## Inputs + +- **PR number** (required): the already-merged PR on `develop` to backport. +- **Target major** (optional, default `v10`): the maintenance branch to backport onto. + Accept `v10`, `10`, `v9`, etc. Normalize to a branch name like `v10`. + +If the PR number is missing, ask for it. Do not guess. + +## Convention (learned from the v9 backports) + +- **Base branch** = the target major branch (`v10`), which must already exist on `origin`. +- **Commit + PR title**: keep the original conventional-commit prefix but namespace the + scope with the major, e.g. + - `fix(core): Fix logs flush starvation` -> `fix(v10/core): Fix logs flush starvation` + - `feat(node): Add X` -> `feat(v10/node): Add X` + - If the original has no scope (e.g. `fix: ...`), use `fix(v10): ...`. + - For a multi-scope title, prefix the whole group once, not each scope: + `fix(cloudflare,deno,node): ...` -> `fix(v10/cloudflare,deno,node): ...`. +- **PR body** is a single line: `Backport of: #`. +- **PR is opened as a draft.** +- **Branch name**: `ab/-` (personal rule is the `ab/` prefix). Derive + `` from the original PR title, e.g. `ab/v10-fix-log-flush-starvation`. +- The changes come from the PR's **squash-merge commit** on `develop` (one commit per PR), + so a single `git cherry-pick` normally covers the whole PR. + +## Steps + +### 1. Resolve the PR and target branch + +```bash +# Fetch PR metadata (title, merge commit, base branch) +gh pr view --json number,title,baseRefName,mergeCommit,state,url +``` + +Verify: +- The PR is **merged** (`state == "MERGED"`). If not, stop and tell the user. +- Its `baseRefName` is `develop` (or the expected parent major). If it targeted something + else, confirm with the user before continuing. + +Grab `mergeCommit.oid` — this is the squash commit to cherry-pick. + +Make sure the target branch exists and is up to date: + +```bash +git fetch origin develop +git rev-parse --verify origin/ # errors if the branch doesn't exist +``` + +If `origin/` doesn't exist, stop: the maintenance branch hasn't been created yet. + +Then check the change isn't already on the target. A freshly cut major often still shares +history with `develop`, so a recent PR may already be present: + +```bash +git merge-base --is-ancestor origin/ && echo "ALREADY ON " +``` + +If it prints `ALREADY ON`, there's nothing to backport — stop and tell the user rather than +producing an empty commit. + +### 2. Create the backport branch off the target major + +```bash +git checkout -b ab/- origin/ +``` + +### 3. Cherry-pick the merge commit + +```bash +git cherry-pick +``` + +- If git reports the pick is **empty** ("nothing to commit" / "the previous cherry-pick is + now empty"), the change is already on the target. Run `git cherry-pick --abort` and stop — + do not force it through with `--allow-empty`. This is the same situation the ancestor check + in step 1 guards against, caught here for changes that landed via a different commit. +- On **conflicts**: resolve them by consulting the original diff (`git show `). + The target major may lack refactors that landed on `develop`, so adapt the change to the + older code rather than force-porting it. After resolving: `git add -A && git cherry-pick --continue`. + If the change can't be cleanly adapted, stop and surface the conflict to the user instead + of guessing. +- If the PR was **not** squash-merged (multiple commits, e.g. a merge commit), cherry-pick + each relevant commit in order, or use `git cherry-pick -m 1 ` for a merge commit. + +### 4. Reword the commit to namespace the scope + +Rewrite only the subject line's scope to include the major; keep the body. Do **not** add a +`Co-Authored-By` line or conventional prefix beyond what's described here — the backport +branch's first commit mirrors an existing commit rather than being new authored work. + +```bash +git commit --amend -m "(/): " -m "Backport of: #" +``` + +Example: `fix(v10/core): Fix logs flush timeout starvation with continuous logging` + +### 5. Build and verify before pushing + +Run the repo's pre-commit checks so the backport branch is green: + +```bash +yarn format +yarn lint +yarn build:dev +``` + +Run tests scoped to the touched packages when possible (full `yarn test` if unsure). If the +target major's toolchain differs and a check fails for reasons unrelated to the change, note +it for the user rather than silently skipping. + +### 6. Push and open the draft PR + +```bash +git push -u origin ab/- + +gh pr create \ + --draft \ + --base \ + --title "(/): " \ + --body "Backport of: #" +``` + +### 7. Cross-link on the original PR + +Add a note to the original PR pointing at the backport (mirrors `v9 backport: #NNNN`): + +```bash +gh pr comment --body " backport: #" +``` + +## Notes + +- Never push directly to `develop`, `master`, or the major branch. Work only on the + `ab/-...` branch and open a PR. +- One PR per backport. If asked to backport several PRs, repeat the whole flow per PR (each + gets its own branch and draft PR). +- If asked to backport to multiple majors at once (e.g. v10 and v9), do them as separate + branches/PRs, each based off its own `origin/`. diff --git a/agents.toml b/agents.toml index ebb2beb3ad83..17780c1bb893 100644 --- a/agents.toml +++ b/agents.toml @@ -51,8 +51,8 @@ name = "bump-size-limit" source = "path:.agents/skills/bump-size-limit" [[skills]] -name = "upgrade-otel" -source = "path:.agents/skills/upgrade-otel" +name = "vendor-otel" +source = "path:.agents/skills/vendor-otel" [[skills]] name = "skill-scanner" @@ -61,3 +61,27 @@ source = "getsentry/skills" [[skills]] name = "skill-creator" source = "anthropics/skills" + +[[skills]] +name = "backport-pr" +source = "path:.agents/skills/backport-pr" + +[[skills]] +name = "bump-conventions" +source = "path:.agents/skills/bump-conventions" + +[[skills]] +name = "linear-project-status" +source = "path:.agents/skills/linear-project-status" + +[[skills]] +name = "linear-project-update" +source = "path:.agents/skills/linear-project-update" + +[[skills]] +name = "track-framework-updates" +source = "path:.agents/skills/track-framework-updates" + +[[skills]] +name = "write-tests" +source = "path:.agents/skills/write-tests" From 0995b49931cd266dbacff7d02a555edfd23c30c2 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 21 Jul 2026 16:37:36 +0200 Subject: [PATCH 02/18] Fix verify/commit ordering and genericize branch prefix Run verification before finalizing the commit so yarn format changes are folded into the pushed commit instead of left uncommitted. Replace the personal ab/ branch prefix with a neutral backport/ default. --- .agents/skills/backport-pr/SKILL.md | 51 ++++++++++++++++++----------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index a51adfdf59e8..9ced45f01266 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -31,8 +31,10 @@ If the PR number is missing, ask for it. Do not guess. `fix(cloudflare,deno,node): ...` -> `fix(v10/cloudflare,deno,node): ...`. - **PR body** is a single line: `Backport of: #`. - **PR is opened as a draft.** -- **Branch name**: `ab/-` (personal rule is the `ab/` prefix). Derive - `` from the original PR title, e.g. `ab/v10-fix-log-flush-starvation`. +- **Branch name**: `backport/-`, where `` comes from the + original PR title, e.g. `backport/v10-fix-log-flush-starvation`. If you already use a + personal branch prefix (some contributors do, e.g. `/...`), keep using it — only + the base branch and commit/PR title conventions below are load-bearing. - The changes come from the PR's **squash-merge commit** on `develop` (one commit per PR), so a single `git cherry-pick` normally covers the whole PR. @@ -74,7 +76,7 @@ producing an empty commit. ### 2. Create the backport branch off the target major ```bash -git checkout -b ab/- origin/ +git checkout -b backport/- origin/ ``` ### 3. Cherry-pick the merge commit @@ -95,21 +97,12 @@ git cherry-pick - If the PR was **not** squash-merged (multiple commits, e.g. a merge commit), cherry-pick each relevant commit in order, or use `git cherry-pick -m 1 ` for a merge commit. -### 4. Reword the commit to namespace the scope +### 4. Build and verify -Rewrite only the subject line's scope to include the major; keep the body. Do **not** add a -`Co-Authored-By` line or conventional prefix beyond what's described here — the backport -branch's first commit mirrors an existing commit rather than being new authored work. - -```bash -git commit --amend -m "(/): " -m "Backport of: #" -``` - -Example: `fix(v10/core): Fix logs flush timeout starvation with continuous logging` - -### 5. Build and verify before pushing - -Run the repo's pre-commit checks so the backport branch is green: +Run the repo's pre-commit checks. Do this **before** finalizing the commit in step 5, because +`yarn format` writes changes to the working tree — those fixes must end up inside the backport +commit, not left dangling after it (otherwise you'd push an unformatted tree and CI would fail +on a commit that doesn't match your local state). ```bash yarn format @@ -121,10 +114,30 @@ Run tests scoped to the touched packages when possible (full `yarn test` if unsu target major's toolchain differs and a check fails for reasons unrelated to the change, note it for the user rather than silently skipping. +### 5. Finalize the commit (reword scope + fold in verification changes) + +Stage anything `yarn format`/`yarn lint` changed, then amend in one step: this both namespaces +the subject scope with the major and captures the formatting fixes. Rewrite only the subject's +scope; keep the body. Do **not** add a `Co-Authored-By` line — the backport commit mirrors an +existing commit rather than being new authored work. + +```bash +git add -A +git commit --amend -m "(/): " -m "Backport of: #" +``` + +Example subject: `fix(v10/core): Fix logs flush timeout starvation with continuous logging` + +Confirm the tree is clean so nothing is left uncommitted before you push: + +```bash +git status --porcelain # expect no output +``` + ### 6. Push and open the draft PR ```bash -git push -u origin ab/- +git push -u origin backport/- gh pr create \ --draft \ @@ -144,7 +157,7 @@ gh pr comment --body " backport: #" ## Notes - Never push directly to `develop`, `master`, or the major branch. Work only on the - `ab/-...` branch and open a PR. + `backport/-...` branch and open a PR. - One PR per backport. If asked to backport several PRs, repeat the whole flow per PR (each gets its own branch and draft PR). - If asked to backport to multiple majors at once (e.g. v10 and v9), do them as separate From cc2b92760c9f1ef2f9f038f8528b1299546e6320 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 21 Jul 2026 16:38:17 +0200 Subject: [PATCH 03/18] Stop prescribing a branch name The branch name isn't load-bearing; only the base branch and commit/PR title conventions matter. --- .agents/skills/backport-pr/SKILL.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index 9ced45f01266..21eca0bb3331 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -31,10 +31,9 @@ If the PR number is missing, ask for it. Do not guess. `fix(cloudflare,deno,node): ...` -> `fix(v10/cloudflare,deno,node): ...`. - **PR body** is a single line: `Backport of: #`. - **PR is opened as a draft.** -- **Branch name**: `backport/-`, where `` comes from the - original PR title, e.g. `backport/v10-fix-log-flush-starvation`. If you already use a - personal branch prefix (some contributors do, e.g. `/...`), keep using it — only - the base branch and commit/PR title conventions below are load-bearing. +- **Working branch**: any local branch off the target major works — the name isn't + load-bearing (GitHub ignores it and contributors use varied prefixes). Just pick something + descriptive. What matters is the base branch and the commit/PR title conventions. - The changes come from the PR's **squash-merge commit** on `develop` (one commit per PR), so a single `git cherry-pick` normally covers the whole PR. @@ -76,7 +75,7 @@ producing an empty commit. ### 2. Create the backport branch off the target major ```bash -git checkout -b backport/- origin/ +git checkout -b origin/ ``` ### 3. Cherry-pick the merge commit @@ -137,7 +136,7 @@ git status --porcelain # expect no output ### 6. Push and open the draft PR ```bash -git push -u origin backport/- +git push -u origin gh pr create \ --draft \ @@ -156,8 +155,8 @@ gh pr comment --body " backport: #" ## Notes -- Never push directly to `develop`, `master`, or the major branch. Work only on the - `backport/-...` branch and open a PR. +- Never push directly to `develop`, `master`, or the major branch. Work only on your + backport branch and open a PR. - One PR per backport. If asked to backport several PRs, repeat the whole flow per PR (each gets its own branch and draft PR). - If asked to backport to multiple majors at once (e.g. v10 and v9), do them as separate From bba78ba7ceb2b8f3cc373d17d6b1067c7ff01b82 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 21 Jul 2026 16:47:11 +0200 Subject: [PATCH 04/18] Fix commit body instruction and scope-less title template The amend replaces the body with the one-line Backport of: note, so drop the contradictory keep-the-body wording. Use a prebuilt namespaced title placeholder so a scope-less source PR yields fix(v10): not fix(v10/):. --- .agents/skills/backport-pr/SKILL.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index 21eca0bb3331..5cf1e355286a 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -116,13 +116,17 @@ it for the user rather than silently skipping. ### 5. Finalize the commit (reword scope + fold in verification changes) Stage anything `yarn format`/`yarn lint` changed, then amend in one step: this both namespaces -the subject scope with the major and captures the formatting fixes. Rewrite only the subject's -scope; keep the body. Do **not** add a `Co-Authored-By` line — the backport commit mirrors an -existing commit rather than being new authored work. +the subject scope with the major and captures the formatting fixes. The final message is the +namespaced subject plus the one-line `Backport of:` body (this replaces the squash-merge body, +matching the convention above). Do **not** add a `Co-Authored-By` line — the backport commit +mirrors an existing commit rather than being new authored work. + +Build the namespaced title as in the convention above: `(/):` when the +original had a scope, or `():` when it didn't (never emit an empty `/`). ```bash git add -A -git commit --amend -m "(/): " -m "Backport of: #" +git commit --amend -m "" -m "Backport of: #" ``` Example subject: `fix(v10/core): Fix logs flush timeout starvation with continuous logging` @@ -141,7 +145,7 @@ git push -u origin gh pr create \ --draft \ --base \ - --title "(/): " \ + --title "" \ --body "Backport of: #" ``` From 8ed66cb9e25cb8253f9e72be98ab2815d98c8eec Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 21 Jul 2026 16:53:10 +0200 Subject: [PATCH 05/18] Trim vague clause from skill description --- .agents/skills/backport-pr/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index 5cf1e355286a..b635a43065c5 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -1,6 +1,6 @@ --- name: backport-pr -description: Backport a merged PR to a maintenance major branch (v10 by default) in getsentry/sentry-javascript. Cherry-picks the PR's squash-merge commit onto the target branch, namespaces the commit/PR title scope (e.g. fix(core) -> fix(v10/core)), and opens a draft backport PR. Use when asked to backport a PR, port a fix to v10 (or an older major like v9), or cut a maintenance release change. Trigger phrases include "backport", "port to v10", "cherry-pick to the maintenance branch", "release this on v10". +description: Backport a merged PR to a maintenance major branch (v10 by default) in getsentry/sentry-javascript. Cherry-picks the PR's squash-merge commit onto the target branch, namespaces the commit/PR title scope (e.g. fix(core) -> fix(v10/core)), and opens a draft backport PR. Use when asked to backport a PR, or port a fix to v10 (or an older major like v9). Trigger phrases include "backport", "port to v10", "cherry-pick to the maintenance branch", "release this on v10". argument-hint: ' [target-major] # e.g. 18211 v10; target defaults to v10' --- From ffdf207fa8985b7553c27a852348b1f16cd02ab7 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 21 Jul 2026 16:53:25 +0200 Subject: [PATCH 06/18] Drop cherry-pick trigger phrase from description --- .agents/skills/backport-pr/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index b635a43065c5..01454305a0c6 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -1,6 +1,6 @@ --- name: backport-pr -description: Backport a merged PR to a maintenance major branch (v10 by default) in getsentry/sentry-javascript. Cherry-picks the PR's squash-merge commit onto the target branch, namespaces the commit/PR title scope (e.g. fix(core) -> fix(v10/core)), and opens a draft backport PR. Use when asked to backport a PR, or port a fix to v10 (or an older major like v9). Trigger phrases include "backport", "port to v10", "cherry-pick to the maintenance branch", "release this on v10". +description: Backport a merged PR to a maintenance major branch (v10 by default) in getsentry/sentry-javascript. Cherry-picks the PR's squash-merge commit onto the target branch, namespaces the commit/PR title scope (e.g. fix(core) -> fix(v10/core)), and opens a draft backport PR. Use when asked to backport a PR, or port a fix to v10 (or an older major like v9). Trigger phrases include "backport", "port to v10", "release this on v10". argument-hint: ' [target-major] # e.g. 18211 v10; target defaults to v10' --- From 335dcd4dd826245c5b4508462b88d2d812938573 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 21 Jul 2026 16:57:38 +0200 Subject: [PATCH 07/18] Accept a PR URL or number as input gh pr view takes either, so pass the input through unchanged and use the resolved number for the Backport of: reference so URLs render correctly. --- .agents/skills/backport-pr/SKILL.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index 01454305a0c6..19959c7c48f4 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -1,7 +1,7 @@ --- name: backport-pr description: Backport a merged PR to a maintenance major branch (v10 by default) in getsentry/sentry-javascript. Cherry-picks the PR's squash-merge commit onto the target branch, namespaces the commit/PR title scope (e.g. fix(core) -> fix(v10/core)), and opens a draft backport PR. Use when asked to backport a PR, or port a fix to v10 (or an older major like v9). Trigger phrases include "backport", "port to v10", "release this on v10". -argument-hint: ' [target-major] # e.g. 18211 v10; target defaults to v10' +argument-hint: ' [target-major] # e.g. https://github.com/getsentry/sentry-javascript/pull/18211 v10; target defaults to v10' --- # Backport a PR to a maintenance major branch @@ -13,11 +13,13 @@ backports. ## Inputs -- **PR number** (required): the already-merged PR on `develop` to backport. +- **PR** (required): the already-merged PR on `develop` to backport, given as either a full + GitHub URL or a bare number. `gh pr view` accepts both, so pass whichever the user gave + through unchanged; `` in the commands below is that value. - **Target major** (optional, default `v10`): the maintenance branch to backport onto. Accept `v10`, `10`, `v9`, etc. Normalize to a branch name like `v10`. -If the PR number is missing, ask for it. Do not guess. +If no PR is given, ask for it. Do not guess. ## Convention (learned from the v9 backports) @@ -51,7 +53,9 @@ Verify: - Its `baseRefName` is `develop` (or the expected parent major). If it targeted something else, confirm with the user before continuing. -Grab `mergeCommit.oid` — this is the squash commit to cherry-pick. +Grab `mergeCommit.oid` — this is the squash commit to cherry-pick. Also grab `number`: use +that bare number (not the raw input) wherever `#` appears below, so `Backport of:` reads +`Backport of: #18211` even when the user passed a URL. Make sure the target branch exists and is up to date: From d98e6d2ff9ba33f9a7d827e696d9f9d4002ea81c Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 21 Jul 2026 17:02:03 +0200 Subject: [PATCH 08/18] Align PR arg hint with repo convention (number-or-url) --- .agents/skills/backport-pr/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index 19959c7c48f4..b121e2debf4a 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -1,7 +1,7 @@ --- name: backport-pr description: Backport a merged PR to a maintenance major branch (v10 by default) in getsentry/sentry-javascript. Cherry-picks the PR's squash-merge commit onto the target branch, namespaces the commit/PR title scope (e.g. fix(core) -> fix(v10/core)), and opens a draft backport PR. Use when asked to backport a PR, or port a fix to v10 (or an older major like v9). Trigger phrases include "backport", "port to v10", "release this on v10". -argument-hint: ' [target-major] # e.g. https://github.com/getsentry/sentry-javascript/pull/18211 v10; target defaults to v10' +argument-hint: ' [target-major] # e.g. 18211 v10; target defaults to v10' --- # Backport a PR to a maintenance major branch From 12ab735579ebd99e77ee2b5f1a704da5c84bcd98 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 21 Jul 2026 17:14:32 +0200 Subject: [PATCH 09/18] Reword intro for clarity --- .agents/skills/backport-pr/SKILL.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index b121e2debf4a..d457d9cce6b7 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -6,10 +6,10 @@ argument-hint: ' [target-major] # e.g. 18211 v10; target defa # Backport a PR to a maintenance major branch -`develop` is the current major (v11). Released changes now go onto the previous major's -maintenance branch (`v10` by default). This skill cherry-picks a merged PR's changes onto -that branch and opens a draft backport PR, following the same convention used for the v9 -backports. +`develop` is the current major (v11). A change that also needs to ship on a still-maintained +older major has to land on that major's branch too (`v10` by default). This skill cherry-picks +a merged `develop` PR onto that branch and opens a draft backport PR, following the same +convention used for the v9 backports. ## Inputs From 2730e9d64fcfb86dfc84b5e12791fab151ae35dc Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 21 Jul 2026 17:15:18 +0200 Subject: [PATCH 10/18] Drop references to unwritten v9 convention --- .agents/skills/backport-pr/SKILL.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index d457d9cce6b7..7c2d4251b28a 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -8,8 +8,7 @@ argument-hint: ' [target-major] # e.g. 18211 v10; target defa `develop` is the current major (v11). A change that also needs to ship on a still-maintained older major has to land on that major's branch too (`v10` by default). This skill cherry-picks -a merged `develop` PR onto that branch and opens a draft backport PR, following the same -convention used for the v9 backports. +a merged `develop` PR onto that branch and opens a draft backport PR. ## Inputs @@ -21,7 +20,7 @@ convention used for the v9 backports. If no PR is given, ask for it. Do not guess. -## Convention (learned from the v9 backports) +## Convention - **Base branch** = the target major branch (`v10`), which must already exist on `origin`. - **Commit + PR title**: keep the original conventional-commit prefix but namespace the From dcc0800fd12d5996aab357c80df0a5a2de184ddc Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 21 Jul 2026 17:18:50 +0200 Subject: [PATCH 11/18] Simplify working-branch note --- .agents/skills/backport-pr/SKILL.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index 7c2d4251b28a..64dacfe4e59c 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -32,9 +32,7 @@ If no PR is given, ask for it. Do not guess. `fix(cloudflare,deno,node): ...` -> `fix(v10/cloudflare,deno,node): ...`. - **PR body** is a single line: `Backport of: #`. - **PR is opened as a draft.** -- **Working branch**: any local branch off the target major works — the name isn't - load-bearing (GitHub ignores it and contributors use varied prefixes). Just pick something - descriptive. What matters is the base branch and the commit/PR title conventions. +- **Working branch**: branch off the target major and give it a descriptive name. - The changes come from the PR's **squash-merge commit** on `develop` (one commit per PR), so a single `git cherry-pick` normally covers the whole PR. From 582c9eaefa37e3435654bdd553bae049b9c41249 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 21 Jul 2026 17:25:06 +0200 Subject: [PATCH 12/18] Fix lint/staging steps and capture backport PR URL Use lint:fix so auto-fixable issues are applied, git add -u so a repo-wide format doesn't stage unrelated edits, and capture the gh pr create URL for the cross-link comment. --- .agents/skills/backport-pr/SKILL.md | 34 +++++++++++++++++++---------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index 64dacfe4e59c..0b91ddd3addc 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -106,27 +106,34 @@ on a commit that doesn't match your local state). ```bash yarn format -yarn lint +yarn lint:fix yarn build:dev ``` +Use `lint:fix`, not `lint` — plain `yarn lint` only reports, so auto-fixable issues would +otherwise survive to fail CI. + Run tests scoped to the touched packages when possible (full `yarn test` if unsure). If the target major's toolchain differs and a check fails for reasons unrelated to the change, note it for the user rather than silently skipping. ### 5. Finalize the commit (reword scope + fold in verification changes) -Stage anything `yarn format`/`yarn lint` changed, then amend in one step: this both namespaces -the subject scope with the major and captures the formatting fixes. The final message is the -namespaced subject plus the one-line `Backport of:` body (this replaces the squash-merge body, -matching the convention above). Do **not** add a `Co-Authored-By` line — the backport commit -mirrors an existing commit rather than being new authored work. +Stage the format/lint fixes, then amend in one step: this both namespaces the subject scope +with the major and captures those fixes. The final message is the namespaced subject plus the +one-line `Backport of:` body (this replaces the squash-merge body, matching the convention +above). Do **not** add a `Co-Authored-By` line — the backport commit mirrors an existing commit +rather than being new authored work. Build the namespaced title as in the convention above: `(/):` when the original had a scope, or `():` when it didn't (never emit an empty `/`). +Stage only the files the cherry-pick and verification touched — `git add -u` restages tracked +files without sweeping in unrelated local edits. Sanity-check the staged set with +`git status` first if `yarn format` may have reformatted files outside the backport. + ```bash -git add -A +git add -u git commit --amend -m "" -m "Backport of: #" ``` @@ -140,22 +147,27 @@ git status --porcelain # expect no output ### 6. Push and open the draft PR +`gh pr create` prints the new PR's URL — capture it, since step 7 needs its number. + ```bash git push -u origin -gh pr create \ +backport_url=$(gh pr create \ --draft \ --base \ --title "" \ - --body "Backport of: #" + --body "Backport of: #") +echo "$backport_url" ``` ### 7. Cross-link on the original PR -Add a note to the original PR pointing at the backport (mirrors `v9 backport: #NNNN`): +Comment on the original PR with a link to the backport (e.g. `v10 backport: #NNNN`). Pass the +URL captured above — `gh pr comment` accepts it directly, so you don't have to parse the number +out: ```bash -gh pr comment --body " backport: #" +gh pr comment --body " backport: $backport_url" ``` ## Notes From 4774fa7939fab5754c704d312b420b58c56dfbfa Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 22 Jul 2026 10:32:57 +0200 Subject: [PATCH 13/18] Drop manual cross-link step; GitHub links via the Backport of: reference --- .agents/skills/backport-pr/SKILL.md | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index 0b91ddd3addc..66b10e07a56f 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -147,27 +147,17 @@ git status --porcelain # expect no output ### 6. Push and open the draft PR -`gh pr create` prints the new PR's URL — capture it, since step 7 needs its number. +The `Backport of: #` body references the original PR, so GitHub cross-links the two +automatically — no separate comment needed. ```bash git push -u origin -backport_url=$(gh pr create \ +gh pr create \ --draft \ --base \ --title "" \ - --body "Backport of: #") -echo "$backport_url" -``` - -### 7. Cross-link on the original PR - -Comment on the original PR with a link to the backport (e.g. `v10 backport: #NNNN`). Pass the -URL captured above — `gh pr comment` accepts it directly, so you don't have to parse the number -out: - -```bash -gh pr comment --body " backport: $backport_url" + --body "Backport of: #" ``` ## Notes From b22be60e6564b0647fd8f162cdadb10e325e23be Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 22 Jul 2026 10:35:49 +0200 Subject: [PATCH 14/18] Clarify amend behavior for multi-commit backports --- .agents/skills/backport-pr/SKILL.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index 66b10e07a56f..169a71dcb93a 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -128,6 +128,10 @@ rather than being new authored work. Build the namespaced title as in the convention above: `(/):` when the original had a scope, or `():` when it didn't (never emit an empty `/`). +`--amend` only rewrites HEAD, which is exactly right for the usual single squash commit. If +step 3 cherry-picked multiple commits, leave their individual messages as-is — the namespaced +title lives on the PR (step 6), not on each commit. + Stage only the files the cherry-pick and verification touched — `git add -u` restages tracked files without sweeping in unrelated local edits. Sanity-check the staged set with `git status` first if `yarn format` may have reformatted files outside the backport. From b0214ea66fc02f3fe64001dca467ef80c50423cd Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 22 Jul 2026 10:39:25 +0200 Subject: [PATCH 15/18] Split finalize step into single- and multi-commit cases The commands now match the prose: amend with the namespaced title for a single squash commit, or fold fixes with --no-edit for multi-commit backports where the title lives on the PR. --- .agents/skills/backport-pr/SKILL.md | 38 +++++++++++++++++------------ 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index 169a71dcb93a..a5785c94af0e 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -117,32 +117,40 @@ Run tests scoped to the touched packages when possible (full `yarn test` if unsu target major's toolchain differs and a check fails for reasons unrelated to the change, note it for the user rather than silently skipping. -### 5. Finalize the commit (reword scope + fold in verification changes) +### 5. Finalize the commit (fold in verification changes) -Stage the format/lint fixes, then amend in one step: this both namespaces the subject scope -with the major and captures those fixes. The final message is the namespaced subject plus the -one-line `Backport of:` body (this replaces the squash-merge body, matching the convention -above). Do **not** add a `Co-Authored-By` line — the backport commit mirrors an existing commit -rather than being new authored work. +First stage the format/lint fixes. Use `git add -u` so only tracked files the cherry-pick and +verification touched are staged, not unrelated local edits — sanity-check with `git status` +first if `yarn format` may have reformatted files outside the backport. -Build the namespaced title as in the convention above: `(/):` when the -original had a scope, or `():` when it didn't (never emit an empty `/`). +```bash +git add -u +``` -`--amend` only rewrites HEAD, which is exactly right for the usual single squash commit. If -step 3 cherry-picked multiple commits, leave their individual messages as-is — the namespaced -title lives on the PR (step 6), not on each commit. +Then finalize, depending on how step 3 went: -Stage only the files the cherry-pick and verification touched — `git add -u` restages tracked -files without sweeping in unrelated local edits. Sanity-check the staged set with -`git status` first if `yarn format` may have reformatted files outside the backport. +**Single squash commit (the usual case)** — amend HEAD to both namespace the subject scope and +fold in the staged fixes. The message is the namespaced title plus the one-line `Backport of:` +body (this replaces the squash-merge body, matching the convention above). Do **not** add a +`Co-Authored-By` line — the backport commit mirrors an existing commit, not new authored work. + +Build the title as in the convention: `(/):` when the original had a +scope, or `():` when it didn't (never emit an empty `/`). ```bash -git add -u git commit --amend -m "" -m "Backport of: #" ``` Example subject: `fix(v10/core): Fix logs flush timeout starvation with continuous logging` +**Multiple commits (non-squash merge)** — leave the individual commit messages as-is; the +namespaced title lives on the PR (step 6), not on each commit. Just fold the staged fixes into +HEAD without rewording: + +```bash +git commit --amend --no-edit +``` + Confirm the tree is clean so nothing is left uncommitted before you push: ```bash From 6ddfee2c18d43a0edee5f03639cdde958d2b47a2 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 22 Jul 2026 10:42:26 +0200 Subject: [PATCH 16/18] Note ancestor check is not conclusive if commit was reverted --- .agents/skills/backport-pr/SKILL.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index a5785c94af0e..a3bc8b45b0f2 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -63,15 +63,20 @@ git rev-parse --verify origin/ # errors if the branch doesn't exist If `origin/` doesn't exist, stop: the maintenance branch hasn't been created yet. -Then check the change isn't already on the target. A freshly cut major often still shares +Then check whether the change is already on the target. A freshly cut major often still shares history with `develop`, so a recent PR may already be present: ```bash git merge-base --is-ancestor origin/ && echo "ALREADY ON " ``` -If it prints `ALREADY ON`, there's nothing to backport — stop and tell the user rather than -producing an empty commit. +If it prints `ALREADY ON`, the commit is in the target's history — usually meaning nothing to +backport. It's not conclusive on its own, though: a commit that was later reverted on the +maintenance branch still shows as an ancestor. So treat this as a strong signal to stop and +tell the user, but if you have reason to think the change was reverted, confirm the fix is +actually present (e.g. `git log origin/ -- `, or grep for the change) +before deciding. The cherry-pick in step 3 is the real backstop — it comes up empty only when +the change is genuinely still applied. ### 2. Create the backport branch off the target major From 4f530d3e2593d0a5c130031807f7de76d2d233b3 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 22 Jul 2026 10:47:15 +0200 Subject: [PATCH 17/18] Apply oxfmt formatting --- .agents/skills/backport-pr/SKILL.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index a3bc8b45b0f2..5754d3ac46f3 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -46,6 +46,7 @@ gh pr view --json number,title,baseRefName,mergeCommit,state,url ``` Verify: + - The PR is **merged** (`state == "MERGED"`). If not, stop and tell the user. - Its `baseRefName` is `develop` (or the expected parent major). If it targeted something else, confirm with the user before continuing. From 3516b72be33040f9a3e15b0242c71c939c88543c Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 22 Jul 2026 10:49:15 +0200 Subject: [PATCH 18/18] Use git add -u during conflict resolution too --- .agents/skills/backport-pr/SKILL.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.agents/skills/backport-pr/SKILL.md b/.agents/skills/backport-pr/SKILL.md index 5754d3ac46f3..24558a34f353 100644 --- a/.agents/skills/backport-pr/SKILL.md +++ b/.agents/skills/backport-pr/SKILL.md @@ -97,9 +97,10 @@ git cherry-pick in step 1 guards against, caught here for changes that landed via a different commit. - On **conflicts**: resolve them by consulting the original diff (`git show `). The target major may lack refactors that landed on `develop`, so adapt the change to the - older code rather than force-porting it. After resolving: `git add -A && git cherry-pick --continue`. - If the change can't be cleanly adapted, stop and surface the conflict to the user instead - of guessing. + older code rather than force-porting it. Stage the resolved files with `git add -u` (tracked + files only, so stray untracked workspace files don't get baked in), then + `git cherry-pick --continue`. If the change can't be cleanly adapted, stop and surface the + conflict to the user instead of guessing. - If the PR was **not** squash-merged (multiple commits, e.g. a merge commit), cherry-pick each relevant commit in order, or use `git cherry-pick -m 1 ` for a merge commit.