Skip to content

Execute the first v2/main → main milestone merge and cut the release #1876

Description

@cliffhall

Execute the first v2/main → main milestone merge and cut the v2.1.0 release.

Everything is built and staged in PR #1903 — merge resolved, version bumped, npm run ci green. Only the steps below remain.

Runbook

  1. Approve chore: merge v2/main for the v2.1.0 milestone release #1903 — 1 review required, from someone other than the author (Copilot's doesn't count). Wait for build.
  2. Merge it with the button, using Create a merge commit. A local merge + git push origin main is rejected — main is ruleset-protected (two rulesets on ~DEFAULT_BRANCH; one grants bypass to nobody, admins included). Same reason nothing can be pushed to main directly, including a version bump — which is why the bump already rides chore: merge v2/main for the v2.1.0 milestone release #1903 as dedee5af.
  3. Cut the release in the GitHub UI — Releases → Draft a new release → Choose a tag → type 2.1.0 → Create new tag on publish, Target = main → Publish.
    Publishing is what publishes to npm: the publish job is gated on github.event_name == 'release', runs pack:verify, asserts the tag matches package.json, and pushes the latest dist-tag. (A tag push alone runs build but never publishes.)
  4. Release notes — the Node engine floor >=22.7.5 → >=22.19.0, fix(core): mirror SEP-2243 x-mcp-header args to Mcp-Param-* on tools/call #1847 (tools/call now sends the SEP-2243 Mcp-Param-* headers), and 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). Those are the only user-visible changes; the rest is repo infrastructure. Full payload: milestone overview.
  5. Close this issue manually — chore: merge v2/main for the v2.1.0 milestone release #1903 says References, not Closes.

Then verify

Two things not to undo

Never back-merge main into v2/main. Built and rejected — #1868 (closed). It would pull 224 commits, 212 of them pre-swap v1-tree commits, permanently into the develop branch's ancestry. This is also why #1903's conflicts were resolved on a branch cut from main: GitHub's web conflict editor commits to the head branch, which would have done exactly that.

Never --allow-unrelated-histories. The branches share merge base 4d30d1cd, established by the go-live merge (#1830).

After this, it's self-sustaining

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. This one was the exception: the branches had only just acquired a shared history, two PRs (#1880, #1881) existed purely to shrink the conflict set, and #1904 closed the last file where main held content v2/main lacked. A normal milestone needs none of that.

Activity

  1. added this to the v2.1.0 milestone on Jul 31, 2026
  2. self-assigned this
    on Jul 31, 2026
  3. cliffhall commented on Aug 1, 2026

    @cliffhall
    MemberAuthor

    Triage record: Priority High — scored 11/16 (severity 4, urgency 5, +2 for milestone and assignee) with the rubric added in #1891. Retained as an audit trail of the rubric; nothing here is needed to execute the merge.

    Superseded detail: this was written while the card was in Todo and #1826 was an open flake risk. Both have since moved — the card is In Progress and #1826 shipped in this milestone.

  4. cliffhall commented on Aug 1, 2026

    @cliffhall
    MemberAuthor

    Milestone overview — what v2.1.0 actually contains

    Status 2026-08-02 — merged and built. All 14 PRs below are on v2/main and carried by PR #1903, which is open, MERGEABLE, and green on npm run ci. Their issues are closed and their board cards are Done.

    v2/main is now 15 commits ahead of main, not 14: #1904 (the .github/workflows/main.yml sync, Closes #1902) landed after #1903's branch was cut, so it is not in this release. That's harmless — it only repairs v2/main's copy of a file main already has correct, and workflows aren't in the published tarball.

    Scope measured against origin/main, not against the milestone label — 14 PRs, the payload #1903 carries (git rev-list --count origin/main..834fd2d7 → 14).

    The shape of it is unusual and worth stating plainly: this milestone is mostly repo infrastructure, not product work. Exactly one PR changes runtime behavior. The rest exists because the 2.0.0 tree swap replaced main's tree wholesale and took a set of repo-level files with it, or because the contribution model changed underneath us in the same week.


    1. Security & dependency hardening (2 PRs, both ✅ merged)

    Both are dev-scope — neither ships in the tarball — and both were deferred out of the pre-2.0.0 sweep (#1837) precisely so a major upgrade wouldn't land immediately before an irreversible publish.

    PR Issue What it does
    ✅ #1899 #1839 vitest / @vitest/browser / @vitest/browser-playwright / @vitest/coverage-v8 → 4.1.10, clearing GHSA-p63j-vcc4-9vmv (critical) plus two more. Storybook 10.2.19 → 10.5.5 to satisfy the exact peer pins. clients/web audit 19 → 1.
    ✅ #1900 #1838 eslint 10, clearing the brace-expansion DoS from all five lockfiles. Dropping @eslint/eslintrc took js-yaml with it, clearing a second high advisory for free.

    Two things worth carrying into the release notes: #1900 is larger than a version bump because eslint 10 surfaced 21 genuine violations — 15 preserve-caught-error sites, 2 dead initializers, and 8 react-hooks/set-state-in-effect sites — all fixed in code, with no rule disabled or scoped away. And the issue's predicted fix for #1839 does not work: even naming every vitest and Storybook package in one npm i -D still ERESOLVEs, because npm resolves against the existing lock tree. Regenerating clients/web/package-lock.json is the only mechanism, which is why that lock diff is large — it is the fix, not churn.

    ✅ The merge-order hazard — resolved as specified. #1899 pinned eslint-plugin-react-hooks to ~7.0.1 (tracked as #1897) as a deliberate hold; #1900 required 7.1.1, since 7.0.1's peer range stops at ^9.0.0 and ERESOLVEs against eslint 10. Merging them in the wrong order would have dropped the version back and broken lint.

    #1899 was merged first (23e0c39d), then #1900 (834fd2d7). As expected, #1900 went CONFLICTING the moment #1899 landed; it was brought up to date with a merge from v2/main, the ~7.0.1 hold removed, all five lockfiles regenerated from a clean root npm install rather than hand-merged, and npm run ci re-run green end to end (coverage gate, build gate, all smokes, 462 Storybook tests) before merging.

    Verified on v2/main after the merge — clients/web/package.json now declares "eslint-plugin-react-hooks": "^7.1.1" with no hold remaining, while #1899's other holds survived intact (zod: "~4.3.6", vitest 4.1.10, Storybook 10.5.5 — those stay held; see v2.2.0 below). #1897 is closed, resolved by #1900 rather than worked separately.

    2. Tree-swap recovery — files main had that v2/main didn't (3 PRs, all ✅ merged)

    The swap (#1830) replaced main's tree with v2's, so anything living only in the old tree vanished from the released branch. Each of these is a restoration, and each is written so the next swap-like event can't repeat it.

    3. Contribution model & branch policy (4 PRs, all ✅ merged)

    The repo moved to Collaborators-only in the go-live, making issues the single intake channel for everyone outside the org. These make that legible.

    4. Board & triage process (1 PR ✅ merged, plus board-only work)

    5. Protocol correctness — the only runtime change in the milestone (1 PR, ✅ merged)

    6. Merge convergence — work whose only purpose was making this merge possible (2 PRs, ✅ merged)

    #1868 — the rejected alternative. A back-merge of main into v2/main would have made this merge conflict-free, but only by pulling 224 commits, 212 of them pre-swap v1-tree commits, permanently into the develop branch's ancestry. Closed unmerged. The three-line conflict is cheaper than that lineage, and it does not recur.

    7. Tooling reliability (1 PR, ✅ merged)


    Not in this milestone's payload

    Spun out of #1839 into v2.2.0 — not part of this release

    Untangling the vitest peer knot floated two in-range dependencies that broke the gate for reasons unrelated to the security fix. Both were held rather than silently pinned, and both holds ship as-is in v2.1.0; the follow-up work is milestoned v2.2.0 and is not a candidate for this merge:

    A third, #1897 (react-hooks 7.1), was also filed against v2.2.0 but got resolved early — #1900 was forced to take 7.1.1 regardless, so it closed with this milestone rather than waiting.

    Release-note candidates

    Only three items are user-visible; everything else is repo hygiene a consumer never sees:

    1. tools/call now sends Mcp-Param-* headers (fix(core): mirror SEP-2243 x-mcp-header args to Mcp-Param-* on tools/call #1847) — fixes rejection by strict modern servers.
    2. Node engine floor >=22.7.5 → >=22.19.0 (already called out in the pre-flight below).
    3. Issue forms + 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) — changes how people report things.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

v2Issues and PRs for v2

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions