Skip to content

chore: release v2.6.0#135

Merged
cmeans-claude-dev[bot] merged 2 commits into
mainfrom
release/v2.5.2
May 7, 2026
Merged

chore: release v2.6.0#135
cmeans-claude-dev[bot] merged 2 commits into
mainfrom
release/v2.5.2

Conversation

@cmeans-claude-dev
Copy link
Copy Markdown
Contributor

@cmeans-claude-dev cmeans-claude-dev Bot commented May 7, 2026

Release PR for v2.6.0.

What's in this release

Type Summary Issue / PR
Fixed Windows UTF-8 stdin encoding so PowerShell write paths preserve non-ASCII characters (em dash, curly quotes, non-Latin scripts). Reproduced and verified on a QEMU Windows guest. Closes #129 / via #131
Added CLI flags --version, --help, --check on the mcp-clipboard binary so users can verify their install before any MCP-host wiring. --check exits 1 with a stderr diagnostic on failure so it doubles as a CI smoke check. Closes #130 / via #134
Added github-release job in publish.yml auto-creates the GitHub Release on tag push, with notes pulled from this CHANGELOG section. v2.6.0 is the first firing of this workflow on a real release. Closes #126 / via #127
Changed README ## Setup rewritten into a five-step quick-start. Step 1 acknowledges that mcp-clipboard is a regular PyPI package and links to the official pipx and uv install docs (the project advertises both runners in its install-counts badges). Steps 3, 4, 5 show both pipx run and uvx forms. Windows tip on Claude Desktop's environment caching is preserved and made runner-agnostic. Closes #130 / via #134
Changed Platform status corrected in three locations (README ## Setup callout, README ## Limitations bullet, CLAUDE.md Conventions). The previous "Windows untested on real hardware" boilerplate is no longer accurate; v2.5.x exercised the Windows code paths end-to-end on a QEMU Windows guest, surfacing #129. X11 and macOS still hold "complete with unit tests but unverified beyond that". via #134

Diff scope

Standard three-file release commit per repo convention:

uv.lock is intentionally not in the diff (gitignored on this repo per .gitignore:17; different from pypi-winnow-downloads which tracks it).

Tag-push effects

Once squash-merged and tagged v2.6.0:

This is the first release where the github-release job actually fires on a tag push (the prior backfilled releases were created manually with gh release create). If anything goes wrong with the github-release job, the PyPI publish is unaffected — the job is idempotent and gated needs: publish-pypi, so a re-run after a fix will edit-in-place rather than failing on duplicate-tag-create.

Local verification at this commit

  • uv run pytest -q: 610 passed, 19 deselected (integration-marked, run in integration-x11 CI), 5 xfailed.
  • uv run ruff check src tests: All checks passed.
  • uv run ruff format --check src tests: 10 files already formatted.
  • uv run mypy src: no issues, 4 source files.
  • python scripts/sync-server-json.py --check: in sync at 2.6.0.
  • uv build --wheel: dist/mcp_clipboard-2.6.0-py3-none-any.whl builds cleanly.
  • American-English sweep on the new ## [2.6.0] section: clean.
  • Em-dash / en-dash sweep on the new ## [2.6.0] section: clean.

Test plan

  • CI passes on this PR (lint, typecheck, test ×3, integration-x11, codecov, version-sync, validate-server-json).
  • After squash-merge and tag push, publish.yml runs all four jobs green: publish-pypi, validate-server-json, publish-registry, github-release.
  • PyPI shows mcp-clipboard==2.6.0 as the latest release (https://pypi.org/project/mcp-clipboard/).
  • GitHub Releases shows a new v2.6.0 release with notes drawn from this CHANGELOG section (https://github.com/cmeans/mcp-clipboard/releases).
  • MCP Server registry shows io.github.cmeans/mcp-clipboard at version 2.6.0, isLatest=true.

Aggregates the changes that have landed on `main` since v2.5.1:

- fix(windows): UTF-8 stdin encoding on PowerShell write paths so non-ASCII characters (em dash, curly quotes, non-Latin scripts) are no longer corrupted by `clipboard_copy` / `clipboard_copy_markdown`. Found and fixed via a QEMU Windows guest reproduction (#129, #131).
- feat(cli): `--version`, `--help`, `--check` flags on the `mcp-clipboard` binary so users can verify their install before any MCP-host wiring (#130, #134).
- ci: `github-release` job in `publish.yml` auto-creates the GitHub Release on tag push, with notes pulled from this CHANGELOG section. First firing of this workflow lands with v2.5.2 (#127).
- docs: README `## Setup` rewritten into a five-step quick-start that acknowledges both `pipx` and `uv` as install runners; platform status corrected to reflect that Windows has been exercised on a QEMU guest as of v2.5.x (#130, #134).

Three-file release commit per repo convention: `pyproject.toml` (version bump), `CHANGELOG.md` (date stamp + new `## [Unreleased]` shell), and `server.json` (synced via `scripts/sync-server-json.py`).

Local verification: 610 tests pass, ruff clean, mypy clean, server.json in sync, wheel builds cleanly to `dist/mcp_clipboard-2.5.2-py3-none-any.whl`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added Awaiting CI Dev complete, waiting for CI/Codecov to pass before QA and removed Awaiting CI Dev complete, waiting for CI/Codecov to pass before QA labels May 7, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions github-actions Bot added the Ready for QA Dev work complete — QA can begin review label May 7, 2026
Copy link
Copy Markdown
Owner

@cmeans cmeans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@cmeans cmeans added the QA Active QA is actively reviewing; Dev should not push changes label May 7, 2026
@github-actions github-actions Bot removed the Ready for QA Dev work complete — QA can begin review label May 7, 2026
Copy link
Copy Markdown
Owner

@cmeans cmeans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA review — release PR #135 (round 1)

Verdict: QA Failed for one substantive finding on the bump level. The diff itself is clean and the CHANGELOG content is accurate; the issue is that the version label doesn't match the content per semver and project precedent.

F1 (substantive) — version bump should be 2.6.0 (minor), not 2.5.2 (patch)

The Unreleased CHANGELOG content being stamped under this release contains two ### Added entries:

  • Added — CLI flags --version, --help, --check on the mcp-clipboard binary (#134, closes #130). User-visible new functionality on the binary's interface; mcp-clipboard --check is a brand-new invocable command.
  • Addedgithub-release job in publish.yml auto-creates the GitHub Release on tag push (#127, closes #126). Internal CI infra, but conventionally CHANGELOGd as ### Added per Keep a Changelog.

Per semver §6: "MINOR version when you add functionality in a backwards-compatible manner". The Added entries here are by definition backwards-compatible feature additions, which is exactly what triggers a MINOR bump.

Project precedent (this repo's own pattern):

Release Bump What landed Convention
v2.5.0 (2026-05-05) minor (2.4.0 → 2.5.0) 3 PRs aggregating ### Added + ### Changed (registry registration, clipboard_copy_markdown, PRIMARY selection) minor for any Added
v2.5.1 (2026-05-05) patch (2.5.0 → 2.5.1) Pure README mcp-name token fix; only ### Fixed patch for fix-only
v2.5.2 (this PR, proposed) patch (2.5.1 → 2.5.2) Fixed + 2× Added + 2× Changed mismatched — should be minor

The v2.5.0 release is the direct precedent: same shape (Added + Changed + Fixed entries aggregated into one release) → minor bump. Following that pattern, this release should be v2.6.0.

Why this matters concretely:

  • A consumer pinning mcp-clipboard~=2.5.0 would silently auto-upgrade across this release because ~=2.5.0 covers 2.5.x. They'd get --check as a new invocable surface they didn't ask for and didn't see in their dependency declaration. With 2.6.0, that pin would correctly not match — they'd opt in via ~=2.6.0 once they're ready for the new surface.
  • The MCP Server registry's version: "2.5.2" would tell registry consumers "patch-level only; no behavior change." That's wrong.
  • The PyPI release page would communicate the same wrong signal.

The cost of getting this right now is small (rename branch + update 3 files + update PR body); the cost of getting it wrong is a permanent versioning lie that future consumers can't unscrew without us cutting a follow-up 2.6.0 that adds nothing new.

Suggested fix (mechanical):

  1. Branch rename: release/v2.5.2release/v2.6.0 (git branch -m release/v2.5.2 release/v2.6.0, push the new branch, delete the old remote ref). Or just open a fresh release PR if the rename is fiddly.
  2. pyproject.toml line 7: version = "2.5.2"version = "2.6.0".
  3. server.json lines 6 and 15: both "version": "2.5.2""version": "2.6.0". (Keep them in lockstep — scripts/sync-server-json.py will catch drift.)
  4. CHANGELOG.md: change the new heading from ## [2.5.2] - 2026-05-07 to ## [2.6.0] - 2026-05-07.
  5. PR title: chore: release v2.5.2chore: release v2.6.0.
  6. PR body: replace v2.5.2 / 2.5.2 with v2.6.0 / 2.6.0 in the title, "What's in this release" header context, and all four post-merge test-plan checkboxes (lines 46-50).
  7. Re-run python scripts/sync-server-json.py --check locally to confirm the three files agree at 2.6.0.

What's clean

  • Diff scope is exactly 5 added / 3 deleted across the three expected files (pyproject.toml, server.json, CHANGELOG.md). No drift.
  • CHANGELOG content accurately mirrors the Unreleased section. Each entry traces back to a merged PR (#131 / #134 / #127). The ## [Unreleased] shell is correctly preserved at the top per Keep a Changelog convention.
  • server.json sync is consistent: top-level and packages[0] versions both updated together.
  • CI is fully green on this commit: all 11 actual checks pass (lint, typecheck, test ×3, integration-x11, codecov/patch, on-push, qa-approved, version-sync, validate-server-json).
  • Local verification numbers in the PR body are consistent with what I observed on the post-#134 main: pytest 610 / 19 deselected / 5 xfailed, ruff/format/mypy/sync clean.
  • uv.lock exclusion rationale is correct — .gitignore:17 does list it (verified) and that matches this repo's convention even though sibling projects (e.g. pypi-winnow-downloads) track it.
  • American-English / em-dash sweep on the new section is clean (verified via git diff origin/main..HEAD -- CHANGELOG.md | grep "—" — only matches are pre-existing prose dashes preserved from the Unreleased entries).

Test-plan checkboxes

Leaving all five unticked. Three of them embed 2.5.2 / v2.5.2 in their text; if the version moves to v2.6.0 per F1, those bullets need to be re-typed and re-verified, so ticking them now would add work for Dev to un-tick. Once the new release branch is pushed, I'll re-verify on the new head.

Round 1 → Round 2

Single mechanical fix in three files plus the branch/PR-body rename. After Dev pushes the new release branch, Round 2 will: re-confirm version-sync and validate-server-json CI gates pass at 2.6.0, re-run pytest/ruff/mypy locally on the new head, confirm the CHANGELOG heading matches the version, sweep the PR body for residual 2.5.2 references, and tick the (re-typed) test-plan checkboxes that are pre-tag.

Applying QA Failed.

@cmeans cmeans added the QA Failed QA found issues — needs dev attention label May 7, 2026
@github-actions github-actions Bot removed the QA Active QA is actively reviewing; Dev should not push changes label May 7, 2026
QA reviewer flagged the bump level: this release contains two `### Added` entries (CLI flags --version/--help/--check via #134, and the github-release job via #127), both of which are backwards-compatible feature additions. Per semver §6, that's a MINOR bump trigger, not patch.

This repo's own precedent confirms the convention:

- v2.5.0 (2026-05-05): minor bump for the same release shape (Added + Changed + Fixed aggregated). Direct precedent.
- v2.5.1 (2026-05-05): patch bump for fix-only release.
- v2.5.2 (proposed): mismatched -- patch bump for an Added-bearing release.

Concrete consumer impact of getting it wrong: a `~=2.5.0` pin would silently auto-upgrade across this release and pull in the new --check surface unannounced. With 2.6.0, that pin correctly does not match.

Mechanical fix:
- pyproject.toml: version "2.5.2" -> "2.6.0"
- server.json: top-level + packages[0] versions synced to 2.6.0 via scripts/sync-server-json.py
- CHANGELOG.md: heading "## [2.5.2] - 2026-05-07" -> "## [2.6.0] - 2026-05-07"

Branch name `release/v2.5.2` is now a cosmetic mismatch -- preserved to keep PR #135's QA review history intact rather than re-opening a fresh PR. The squash-merge will collapse this commit into the release commit and the branch will be deleted.

Local verification at this commit:
- python scripts/sync-server-json.py --check: in sync at 2.6.0
- uv run pytest -q: 610 passed, 19 deselected, 5 xfailed
- uv run ruff check src tests: clean
- uv run mypy src: clean
- uv build --wheel: dist/mcp_clipboard-2.6.0-py3-none-any.whl built cleanly
- grep "2.5.2" across pyproject.toml + server.json + CHANGELOG.md: zero hits

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cmeans-claude-dev cmeans-claude-dev Bot changed the title chore: release v2.5.2 chore: release v2.6.0 May 7, 2026
@github-actions github-actions Bot removed the QA Failed QA found issues — needs dev attention label May 7, 2026
@cmeans-claude-dev cmeans-claude-dev Bot added the Ready for QA Dev work complete — QA can begin review label May 7, 2026
@github-actions github-actions Bot added Awaiting CI Dev complete, waiting for CI/Codecov to pass before QA and removed Awaiting CI Dev complete, waiting for CI/Codecov to pass before QA labels May 7, 2026
@cmeans-claude-dev
Copy link
Copy Markdown
Contributor Author

QA Round 1 → Round 2 response

F1 (semver bump level) — addressed at e9d7553. Bumped 2.5.2 → 2.6.0.

You're right on both the semver argument and the project precedent. Two ### Added entries (CLI flags via #134, github-release job via #127) are backwards-compatible feature additions, which is the textbook minor-bump trigger; v2.5.0's minor bump for the same release shape is the direct precedent.

Mechanical changes on this commit:

File Change
pyproject.toml version = "2.5.2"version = "2.6.0"
server.json Top-level and packages[0] versions synced to 2.6.0 via scripts/sync-server-json.py
CHANGELOG.md Heading ## [2.5.2] - 2026-05-07## [2.6.0] - 2026-05-07

PR title and body updated to v2.6.0 throughout (the four post-merge test-plan checkboxes were re-typed).

Branch name is now a cosmetic mismatch (release/v2.5.2 while the content says 2.6.0). I kept it that way deliberately so PR #135's QA review history stays intact; the squash-merge will collapse the two commits into one and delete the branch, so it's a 30-minute cosmetic mismatch rather than a permanent record.

Local verification at e9d7553:

  • python scripts/sync-server-json.py --check: in sync at 2.6.0.
  • uv run pytest -q: 610 passed, 19 deselected, 5 xfailed.
  • uv run ruff check src tests: clean.
  • uv run mypy src: clean.
  • uv build --wheel: dist/mcp_clipboard-2.6.0-py3-none-any.whl built cleanly.
  • grep -n "2.5.2" pyproject.toml server.json CHANGELOG.md: zero hits.

Label reset to Ready for QA.

@cmeans cmeans added the QA Active QA is actively reviewing; Dev should not push changes label May 7, 2026
@github-actions github-actions Bot removed the Ready for QA Dev work complete — QA can begin review label May 7, 2026
Copy link
Copy Markdown
Owner

@cmeans cmeans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA review — release PR #135 (round 2)

Verdict: Zero new findings. Recommending Ready for QA Signoff.

Round 1 F1 — fixed at e9d7553

Single commit chore(release): bump 2.5.2 -> 2.6.0 per QA Round 1 F1 (semver minor). The diff is exactly the requested version swap in all four required surfaces (3 files + PR title/body):

Surface Before After
pyproject.toml:7 version = "2.5.1" version = "2.6.0"
server.json:6 (top-level) "version": "2.5.1" "version": "2.6.0"
server.json:15 (packages[0].version) "version": "2.5.1" "version": "2.6.0"
CHANGELOG.md:7 (new section heading) ## [2.5.2] - 2026-05-07 ## [2.6.0] - 2026-05-07
PR title chore: release v2.5.2 chore: release v2.6.0
PR body (10 occurrences across summary, diff scope, tag-push effects, local verification, test plan) mix of 2.5.2 / v2.5.2 all 2.6.0 / v2.6.0

grep -nE "2\.5\.2|v2\.5\.2" against the current PR body returns zero hits. The remaining 2.5.1 references in the body (e.g., pyproject.toml: "version = "2.5.1" → "2.6.0") are intentional — they describe the pre-release version being bumped FROM, which is correct.

Verification on e9d7553

Check Result
pyproject.toml version 2.6.0
server.json top-level + packages[0] both 2.6.0
CHANGELOG.md heading position ## [Unreleased] shell preserved at line 5; ## [2.6.0] - 2026-05-07 at line 7 (Keep a Changelog convention) ✓
uv run pytest -q 610 passed, 19 deselected, 5 xfailed
uv run ruff check src tests scripts All checks passed
uv run ruff format --check src tests scripts 11 files already formatted
uv run mypy src clean (4 source files)
uv run python scripts/sync-server-json.py --check in sync at 2.6.0
uv build --wheel dist/mcp_clipboard-2.6.0-py3-none-any.whl builds cleanly
CI on e9d7553 11 actual checks all green (lint, typecheck, test ×3, integration-x11, codecov/patch, on-label, qa-approved, version-sync, validate-server-json)

Diff scope

Still exactly 5 added / 3 deleted across the same three files (pyproject.toml, server.json, CHANGELOG.md). uv.lock correctly absent from the diff per .gitignore:17. No drift outside the release-bump triad.

Test-plan checkboxes

  • CI passes on this PR — all 11 actual checks green on e9d7553. Ticked.
  • Post-merge publish.yml jobs all green — gated on tag push, not verifiable pre-merge. Leaving unticked.
  • PyPI shows mcp-clipboard==2.6.0 — gated on publish-pypi running. Leaving unticked.
  • GitHub Releases shows v2.6.0 — gated on github-release running (this is the first real firing of the job ported in #127, so it's the most worth-watching of the four post-tag verifications). Leaving unticked.
  • MCP Server registry shows 2.6.0 — gated on publish-registry running. Leaving unticked.

Note on the leftover branch name

The branch name is still release/v2.5.2 (Dev kept the existing branch and updated its content rather than renaming). I'm not flagging this as a finding — branch names are developer-side artifacts that don't surface anywhere consumers see (tag, PyPI, registry, GitHub Release page, squash-merge commit message will all carry 2.6.0), and head branches typically get deleted post-merge. Mentioning here only so the trail is documented.

Round 2 verdict

This is a clean version-bump fix. The release content (CHANGELOG entries, server.json sync, pyproject.toml version) was already correct in Round 1 — only the version label needed correcting, which is exactly what e9d7553 did. The four post-tag-push verifications remain Dev's job to confirm green after the squash-merge and git tag v2.6.0 push.

Applying Ready for QA Signoff.

@cmeans cmeans added the Ready for QA Signoff QA passed — ready for maintainer final review and merge label May 7, 2026
@github-actions github-actions Bot removed the QA Active QA is actively reviewing; Dev should not push changes label May 7, 2026
Copy link
Copy Markdown
Owner

@cmeans cmeans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@cmeans cmeans added QA Approved Manual QA testing completed and passed and removed Ready for QA Signoff QA passed — ready for maintainer final review and merge labels May 7, 2026
@cmeans-claude-dev cmeans-claude-dev Bot merged commit 169e3d0 into main May 7, 2026
35 checks passed
@cmeans-claude-dev cmeans-claude-dev Bot deleted the release/v2.5.2 branch May 7, 2026 20:24
@cmeans cmeans mentioned this pull request May 8, 2026
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

QA Approved Manual QA testing completed and passed

Projects

None yet

1 participant