You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Status 2026-08-02 — the merge is built and waiting on one approval.
PR #1903 is open, MERGEABLE, with npm run ci green on the merged tree. Everything below that was a question has been answered; the original plan needed three corrections, all applied. The only thing left is a maintainer approval (olaservo / BobDickinson) — then merge, then cut the release.
Why this merge is different from every one that follows
This is the first v2/main → main milestone merge, and the only one that will look like this. Read the sequence below as a one-off, not as the template.
The branches only just acquired a shared history. They had unrelated histories until the go-live merge (chore: replace main's tree with v2 #1830) established merge base 4d30d1cd. That makes this an ordinary merge — but it is the first time that has been true, which is why the "never use --allow-unrelated-histories" warning needs saying at all.
The payload is repo infrastructure, not product work. The tree swap dropped files that lived only in the old tree, so most of this milestone restores them. Exactly one PR (fix(core): mirror SEP-2243 x-mcp-header args to Mcp-Param-* on tools/call #1847) changes runtime behavior. A normal milestone will invert that ratio.
Do not "fix" the divergence with a back-merge of main into v2/main. Built and rejected — see #1868 (closed). It would make the merge conflict-free, but only by pulling 224 commits, 212 of them pre-swap v1-tree commits, permanently into the develop branch's ancestry. git log, bisect, and every GitHub compare on v2/main would carry the v1 lineage from then on.
# 1. DONE — the merge, resolved on a branch cut from main so v2/main# stays untouched (see "the eight conflicts" below).# git checkout -b v2/chore/milestone-merge-v2.1.0 origin/main# git merge --no-ff origin/v2/main# → merge commit 6233d8bb, parents fb1b0cb4 (main) + 834fd2d7 (v2/main)# → npm run ci green on the merged tree# → opened as PR #1903# 2. Get ONE approving review on #1903, then merge it with the button# (or `gh pr merge 1903 --merge`). A local merge + `git push origin main`# is REJECTED — see "main is ruleset-protected" below.# 3. Cut the release. The version bump is ALREADY on #1903's branch# (dedee5af, root package.json 2.0.0 -> 2.1.0), so there is no# second bump PR. Two equivalent ways to do this after #1903 merges:## (a) ENTIRELY IN THE GITHUB UI — no local git needed. Releases > Draft# a new release > "Choose a tag" > type 2.1.0 > "Create new tag on# publish", with Target = main. Publishing creates the tag AND the# release in one step.## (b) Or from the CLI, if you prefer the tag to exist first:# git fetch origin && git checkout main && git pull# git tag 2.1.0 && git push origin 2.1.0 # tags are NOT ruleset-protected# then draft & publish the release for that tag (UI, or# `gh release create 2.1.0 --title 2.1.0 --notes "..."`).## Either way, publishing the RELEASE is what publishes to npm. Both# publish jobs are gated on `github.event_name == 'release'`, so a tag# push alone runs the `build` job (the workflow's `on: push:` is# unqualified) but will NOT publish. The `publish` job runs pack:verify,# asserts the tag matches package.json's version, and pushes the# `latest` dist-tag.
Why the tag comes after the merge, not with the bump.#1903 merges as a merge commit, so dedee5af lands on main intact — but only once it merges. A tag created now would point at a commit that isn't on the release branch yet, which is why the bump used npm version --no-git-tag-version. With option (a) the tag is never pushed by hand at all; GitHub creates it against main when you publish.
The eight conflicts — resolved, and the prediction that was wrong
This issue originally predicted zero conflicts once #1880 landed. That went stale: main subsequently took 8 post-swap commits v2/main never did (#1843, #1842, #1841, #1837, #1836, #1835, #1834, #1832, #1831), and #1899/#1900 regenerated every lockfile. A direct v2/main → main PR (#1901, closed) came up CONFLICTING in 8 files.
All eight took v2/main's side in #1903, each verified rather than assumed:
File
Conflict
Why v2/main wins
README.md
content
main's Mcp-Param-* callout is stale; v2/main's is corrected by #1847
SECURITY.md
add/add
restored independently (#1843 / #1867); differ by one line — the CONTRIBUTORS.md → CONTRIBUTING.md rename (#1884)
took v2/main's, then regenerated from a clean npm install — zero drift
⚠️Never resolve these with GitHub's web "Resolve conflicts" button. It commits to the head branch — merging main into v2/main, i.e. exactly the #1868 back-merge. Resolving on a branch cut from main avoids that, and the merge commit still carries v2/main's tip as its second parent, so the self-sustaining property below still holds.
main is ruleset-protected
Classic branch protections are not configured (GET /branches/main/protection → 404), which is misleading — protection comes from rulesets. Two target ~DEFAULT_BRANCH, and 2749948 grants bypass to nobody, repo admins included.
A PR is mandatory.git push origin main is rejected. Applies to npm version too.
1 approving review, from someone other than the author. A Copilot approval does not count.
The build check must pass.
allowed_merge_methods includes merge, so the --no-ff merge commit is permitted — merge via the button, not a local merge + push.
Not blockers, verified: require_code_owner_review is inert (no CODEOWNERS anywhere), and the release tag is unrestricted (the only tag ruleset matches refs/tags/1.*).
Pre-flight
Branch protection on main permits a maintainer merge commit — it does, but only via a PR.
Decide PR vs. direct maintainer merge — not a choice; a PR is mandatory.
Cut the release — push the 2.1.0 tag, then draft & publish the GitHub Release (step 3 above). The version bump is already on the branch, so no second PR.
Once v2/main's tip is an ancestor of main, and main makes no content changes of its own, every subsequent milestone merge is conflict-free with no back-merge needed. This one-time conflict is the whole cost.
The last thing standing in the way of that was .github/workflows/main.yml — the only file where main still had content v2/main lacked (#1831 least-privilege token, #1834 dist-tag derivation, #1836 OIDC trusted publishing). Fixed by #1904 (Closes #1902, merged 07a2b4bd): since v2/main had nothingmain lacked except the superseded publish step, it took main's file verbatim. git diff origin/main origin/v2/main -- .github/workflows/main.yml is now empty.
Why this merge is different from every one that follows
This is the first
v2/main→mainmilestone merge, and the only one that will look like this. Read the sequence below as a one-off, not as the template.4d30d1cd. That makes this an ordinary merge — but it is the first time that has been true, which is why the "never use--allow-unrelated-histories" warning needs saying at all.main's rc-series deps) existed purely to shrink this merge. Nothing analogous will be needed again.The sequence
Step 1 is done. #1903 carries it.
The eight conflicts — resolved, and the prediction that was wrong
This issue originally predicted zero conflicts once #1880 landed. That went stale:
mainsubsequently took 8 post-swap commitsv2/mainnever did (#1843, #1842, #1841, #1837, #1836, #1835, #1834, #1832, #1831), and #1899/#1900 regenerated every lockfile. A directv2/main→mainPR (#1901, closed) came up CONFLICTING in 8 files.All eight took
v2/main's side in #1903, each verified rather than assumed:README.mdMcp-Param-*callout is stale; v2/main's is corrected by #1847SECURITY.mdCONTRIBUTORS.md→CONTRIBUTING.mdrename (#1884)clients/web/package.jsonvitest^4.1.0→^4.1.10, the #1899 security fixpackage-lock.jsonnpm install— zero driftmainis ruleset-protectedClassic branch protections are not configured (
GET /branches/main/protection→404), which is misleading — protection comes from rulesets. Two target~DEFAULT_BRANCH, and2749948grants bypass to nobody, repo admins included.git push origin mainis rejected. Applies tonpm versiontoo.buildcheck must pass.allowed_merge_methodsincludesmerge, so the--no-ffmerge commit is permitted — merge via the button, not a local merge + push.require_code_owner_reviewis inert (noCODEOWNERSanywhere), and the release tag is unrestricted (the only tag ruleset matchesrefs/tags/1.*).Pre-flight
Branch protection on— it does, but only via a PR.mainpermits a maintainer merge commitDecide PR vs. direct maintainer merge— not a choice; a PR is mandatory.Conflict expectations— 8 conflicts, all resolved in chore: merge v2/main for the v2.1.0 milestone release #1903,npm run cigreen.Approving reviewer available— olaservo and BobDickinson.2.1.0tag, then draft & publish the GitHub Release (step 3 above). The version bump is already on the branch, so no second PR.After it lands
@claudeshould work again — comment@claude reviewon any open PR (claude[bot]replied in ~19s on docs: refresh V2 board Status option IDs in AGENTS.md (#1823) #1825). Workflows forissue_commentevents run from the default branch, so ci: restore the Claude Code workflow and .mcp.json, lost in the v2 tree swap #1869 is inert until now.v2/main, and security updates should still appear (they ran whiledependabot.ymlwas missing entirely — build(deps): bump the npm_and_yarn group across 5 directories with 12 updates #1833, build(deps): bump the npm_and_yarn group across 5 directories with 2 updates #1840 — buttarget-branchis documented as affecting security-update behavior, so confirm).tools/callnow sends the SEP-2243Mcp-Param-*headers) — the only two user-visible changes, plus the issues-only contribution model (docs: replace the markdown bug template with GitHub issue forms #1894, docs: rename CONTRIBUTORS.md to CONTRIBUTING.md so GitHub surfaces the policy #1884).References #1876, notCloses, so it will not auto-close on merge — deliberate, since merging is only step 2 of 3.Then it's self-sustaining
Once
v2/main's tip is an ancestor ofmain, andmainmakes no content changes of its own, every subsequent milestone merge is conflict-free with no back-merge needed. This one-time conflict is the whole cost.The last thing standing in the way of that was
.github/workflows/main.yml— the only file wheremainstill had contentv2/mainlacked (#1831 least-privilege token, #1834 dist-tag derivation, #1836 OIDC trusted publishing). Fixed by #1904 (Closes #1902, merged07a2b4bd): sincev2/mainhad nothingmainlacked except the superseded publish step, it tookmain's file verbatim.git diff origin/main origin/v2/main -- .github/workflows/main.ymlis now empty.