bump — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited bump (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are a release engineer. Your job is to increment the project version across all 6 version files, consume accumulated changelog.d/ fragments into the new ## [X.Y.Z] section of CHANGELOG.md, and delete the consumed fragments in the same commit-ready change set.
This skill edits repository files. Roslyn MCP `server_catalog` is unrelated unless you are validating the shipped tool surface after a release.
$ARGUMENTS is the bump type: patch, minor, or major. If not provided, ask the user which type of bump to perform with a brief explanation:
All 6 files must carry the same version string. See docs/release-policy.md § Where To Bump The Version String for the canonical reference.
| # | File | Field |
|---|---|---|
| 1 | Directory.Build.props | <Version>X.Y.Z</Version> |
| 2 | .claude-plugin/plugin.json | "version": "X.Y.Z" |
| 3 | .claude-plugin/marketplace.json | plugins[0].version (NOT metadata.version) |
| 4 | manifest.json | "version": "X.Y.Z" |
| 5 | .claude-plugin/server.json | Top-level "version": "X.Y.Z" AND packages[0].version (MCP Registry manifest — both fields) |
| 6 | CHANGELOG.md | New ## [X.Y.Z] - YYYY-MM-DD header populated from changelog.d/*.md fragments, grouped by category |
CHANGELOG.md's ## [Unreleased] section is a structural anchor and stays empty between releases. Per-PR changelog entries are written as fragment files at changelog.d/<row-id>.md with YAML frontmatter carrying the category (see changelog.d/README.md for the full pattern). At release-cut time this skill consumes those fragments.
Read Directory.Build.props and extract the current <Version> value. Display it to the user.
Parse the current version as major.minor.patch. Apply the bump type:
patch: increment patchminor: increment minor, reset patch to 0major: increment major, reset minor and patch to 0Display the new version and confirm with the user before proceeding.
Before making any edits, grep each target file for the OLD version string and emit a preflight table:
| File | Occurrences | Edit Strategy |
|---|---|---|
Directory.Build.props | N | single / replace_all / ABORT |
.claude-plugin/plugin.json | N | single / replace_all / ABORT |
.claude-plugin/marketplace.json | N | single / replace_all / ABORT |
manifest.json | N | single / replace_all / ABORT |
.claude-plugin/server.json | N | replace_all (expected: 2) |
Rules:
X.Y.Z not found in FILE — file may have already been bumped or is tracking a different version. Verify before proceeding."replace_all: true in the Edit call.Note: server.json is expected to have 2 occurrences (top-level "version" and packages[0].version); Step 3 already documents replace_all: true for it. The zero-occurrence guard is the critical new protection against partial-application re-runs.
First, create the release-managed-edit override sentinel so the PreToolUse guard (eng/guard-release-managed-files.ps1) allows the version-file edits:
touch .release-managed-edit-allowedThe sentinel is gitignored and has a 1800 s TTL. See ai_docs/workflow.md § Release-managed file guard.
Then edit each of the first five version files using the Edit tool, replacing the old version with the new version:
<Version>OLD</Version> with <Version>NEW</Version>"version": "OLD" with "version": "NEW" (the first occurrence)"version": "OLD" in the plugins[0] entry (NOT the metadata.version on line 9)"version": "OLD" with "version": "NEW""version": "OLD" — the top-level version AND packages[0].version. Use Edit with replace_all: true since both occurrences are textually identical.changelog.d/ fragments into CHANGELOG.mdScan changelog.d/*.md (exclude README.md — the directory explainer is NOT a fragment):
ls changelog.d/*.md | grep -v README.mdFor each fragment, parse YAML frontmatter and extract:
category — must be one of: Fixed, Changed, Changed — BREAKING, Added, Maintenance (em-dash is U+2014). Unknown values fail the bump loudly — see Refusal conditions below.---. Expected to be a single bullet in the shipping **<Category>:** prose style (one per fragment).Group the fragments by category in the canonical emit order: Fixed → Changed — BREAKING → Changed → Added → Maintenance.
Insert a new section into CHANGELOG.md immediately above the most recent ## [X.Y.Z] block:
## [NEW] - YYYY-MM-DD
### Fixed
<bullets from Fixed fragments in the order fragments were read>
### Changed — BREAKING
<bullets from Changed — BREAKING fragments>
### Changed
<bullets from Changed fragments>
### Added
<bullets from Added fragments>
### Maintenance
<bullets from Maintenance fragments>Omit any subsection that has zero fragments (do NOT emit an empty ### Fixed header if no Fixed fragments were present). Do NOT remove or edit ## [Unreleased] — it stays as a structural anchor with its empty subsection headers.
If no fragments were present at all, emit a ## [NEW] - YYYY-MM-DD section with a single _No user-visible changes in this release._ line and proceed — some patch bumps legitimately ship with no fragments (e.g. version-file drift repair).
Delete each consumed fragment from disk after the CHANGELOG.md edit lands:
rm changelog.d/<row-id>.mdThe intent is that git add -- CHANGELOG.md changelog.d/ then git status shows a single atomic change set: one CHANGELOG.md edit + N changelog.d/*.md deletions. This is what /ship (or a manual git commit) will commit.
Refuse loudly — abort the bump before any CHANGELOG.md write — if any of the following hold:
| Condition | Message |
|---|---|
| A fragment has missing or unparseable YAML frontmatter | "Refusing: changelog.d/<file> is missing its YAML frontmatter or the frontmatter did not parse. Fix the fragment and re-run." |
A fragment's category key is missing | "Refusing: changelog.d/<file> has no 'category' key in its frontmatter. Fix the fragment and re-run." |
A fragment's category value is not one of the five canonical values | "Refusing: changelog.d/<file> has category '<value>'; expected one of Fixed / Changed — BREAKING / Changed / Added / Maintenance. Fix the fragment and re-run." |
| A fragment has no body (frontmatter-only) | "Refusing: changelog.d/<file> has no bullet body. Fix the fragment and re-run." |
Do NOT silently skip malformed fragments — a silent skip would lose the release note.
Run eng/verify-version-drift.ps1 via Bash to confirm all 5 files agree on the new version. If it fails, fix the discrepancy and re-run.
Also confirm changelog.d/ now contains only README.md — every fragment that was present at Step 4 start should have been consumed and deleted.
Remove the override sentinel created in Step 3 so subsequent edits go through the normal guard:
rm -f .release-managed-edit-allowed(It is gitignored, so a leftover sentinel does not pollute the commit, but removing it keeps the override contract honest.)
Display a summary:
CHANGELOG.md)changelog.d/ filenames deleted)## [NEW] section in CHANGELOG.md — the grouped bullets came directly from the fragments. Edit the prose if a fragment was under-specified. Run /roslyn-mcp:publish-preflight when ready to validate the full release."~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.