| name | bump-version |
| description | Bump a native addon package's version in package.json and write its CHANGELOG.md entry. Defaults to a minor bump. Use before /release. |
| argument-hint | <package-name> [major|minor|patch] |
| disable-model-invocation | true |
Bump Version
Bump a native addon package's version in package.json and write the matching CHANGELOG.md entry,
so /release can publish it. Defaults to a minor bump.
$ARGUMENTS is <package-name> [major|minor|patch] — the package directory name under packages/,
plus an optional explicit bump level.
Usage
/bump-version llm-llamacpp # minor (default): 0.39.0 -> 0.40.0
/bump-version llm-llamacpp patch # 0.39.0 -> 0.39.1
/bump-version ocr-ggml minor
/bump-version translation-nmtcpp major # never chosen automatically — must be explicit
When to use this skill
Use it when work has merged to main for an addon package and the package still carries the previous
version — i.e. the feature is on main but unreleasable because nothing bumped it. This is the routine
gap that /addon-changelog and /release both refuse to fill:
/addon-changelog writes the changelog but refuses to bump — it stops with a
VERSION BUMP REQUIRED banner if package.json is unchanged vs main.
/release validates the bump then stops and tells you to bump first.
Do not use it for:
| Case | Use instead |
|---|
SDK/TS pods: sdk, cli, rag, logging, error, ai-sdk-provider | /sdk-changelog |
Back-porting a fix onto a shipped release-* line | /release-patch |
A qvac-fabric bump across all 7 consumers | /rollout-phase-b |
| Publishing an existing bump | /release |
Refusals — stop, do not edit anything
- SDK pods. Their root
CHANGELOG.md is machine-generated by
scripts/sdk/generate-changelog-sdk-pod.cjs (rebuildRootChangelog()); a hand-edit is destroyed on
the next generator run. Tell the user to run /sdk-changelog and stop.
- Version not higher than npm
latest. Report both numbers and stop.
- Working branch is a
release-* branch. That is /release-patch territory — a release branch
must stay a byte-exact copy of its base. Stop.
- Package has no
CHANGELOG.md. Ask the user before creating one.
fabric is NOT a refusal. An earlier version of this skill refused it, claiming its release read
packages/fabric/release-notes/v<ver>.md via create-github-release-fabric.yml. That workflow does
not exist and is referenced nowhere; on-merge-fabric.yml passes
changelog-path: packages/fabric/CHANGELOG.md, and that file is current and correctly bracketed.
packages/fabric/release-notes/ holds only a v0.1.0.md leftover and is not the release source.
Treat fabric like any other addon.
Step 1 — Read the real current version
Never trust the local checkout; it is routinely days or thousands of commits behind.
git -C <repo> fetch origin main
git -C <repo> show origin/main:packages/<pkg>/package.json
Read version from that output. Cross-check the published version:
npm view @qvac/<pkg> dist-tags.latest
Expect npm to equal or trail origin/main. If origin/main is already ahead of npm, a bump is
already pending — say so and confirm with the user before adding another.
Step 2 — Find what changed since the last bump
Resolve the previous release tag (see Step 6 — do not guess it from the directory name), then:
git -C <repo> log <prev-tag>..origin/main --oneline -- packages/<pkg>/
If the tag is missing, fall back to the last commit that touched
packages/<pkg>/package.json and diff from there. Harvest PR numbers from the commit subjects
((#1234)) for the ### Pull Requests list, and read the PR titles:
gh pr view <number> --repo tetherto/qvac --json title,body
Drop any PR whose diff does not touch packages/<pkg>/. Read the actual source diff for the
user-visible behaviour — do not paraphrase commit messages, which go stale. (A real example: a merged
commit advertised an opt-in env var that did not exist in the merged code.)
Step 3 — Choose the bump level
Honour an explicit major|minor|patch argument. Otherwise default to minor, and state the
reasoning before editing. The de-facto rule from this repo's history:
| Change | Level |
|---|
| New public API, new config key, new supported model, changed default | minor |
| Bug fix only | patch |
qvac-fabric dependency bump | minor for 0.x, major for >=1.0 — see /rollout-phase-b |
| Breaking change | major — never selected automatically |
Never auto-select major. For a package already at major ≥ 1 still default to minor here; a major
bump must be an explicit user decision, passed as the major argument.
translation-nmtcpp is the only current post-1.0 addon (9.0.0). Its history used to be
inconsistent — the same rollout landed as both minor and major — but 8.3.1 → 9.0.0 (#3567), a
dependency-floor alignment with no breaking API change, settled it: post-1.0 packages take the major
on a fabric rollout. /rollout-phase-b codifies that and passes major explicitly, which satisfies
the never-auto-select rule.
Note that for a 0.x package a minor bump is technically the SemVer breaking-change signal; this repo
leans on that deliberately, so a minor default is correct rather than conservative.
Print the decision before touching files:
llm-llamacpp: 0.39.0 -> 0.40.0 (minor)
reason: adds new supported finetuning architectures (new accepted config values)
Step 4 — Bump package.json
Edit packages/<pkg>/package.json with the Edit tool, changing only the version field. Nothing
else in that file, and no other file — in particular never vcpkg.json (that is a dependency floor,
not the package version) and never vcpkg-configuration.json's default-registry.baseline.
Step 5 — Write the CHANGELOG entry
Insert at the top of packages/<pkg>/CHANGELOG.md, directly below the preamble and above the previous
version heading. The dominant addon shape:
## [<version>] - <YYYY-MM-DD>
<optional 1-3 sentence intro — worth it for a feature release, skip for a one-line fix>
### Added
- <bullet; backtick identifiers; use -> for transitions; explain why it matters, not just what changed>
### Pull Requests
- [#3509](https://github.com/tetherto/qvac/pull/3509) - <PR title>
Rules:
- The heading must be bracketed — literally
## [0.40.0]. ## 0.40.0, ##[0.40.0] and
### [0.40.0] all fail the extractor at .github/actions/verify-changelog-notes/action.yml, whose
awk is $0 ~ "^## \\[" version "\\]". This is the single most common way this task goes wrong.
- Use the date the bump lands,
YYYY-MM-DD.
- Section headings are level-3:
### Added, ### Changed, ### Fixed. Pick by intent — new
capability is Added, altered behaviour or a dependency bump is Changed, a defect fix is Fixed.
Do not use the level-2 ## Features / ## Bug Fixes style; /addon-changelog's own documentation
still shows it, but that documentation is stale and no current addon entry uses it.
- The body must be non-empty until the next
^## [, or the extractor errors with
Changelog section for version X is empty.
## [Unreleased] blocks exist in ocr-ggml, tts-ggml and decoder-audio. Insert the new
dated entry below the Unreleased block. Do not fold Unreleased content into your version, and do
not insert above it — that makes the extractor slice your body off at ## [Unreleased]. Precedent:
commit dfd1fd7eb on ocr-ggml.
- Match the file's existing preamble. Some packages have a Keep-a-Changelog + SemVer preamble, some
just
# Changelog. Do not add one that was not there.
- If the version documents work someone else merged, describe the merged code, and say so if a
commit message contradicts it.
Step 6 — Report what happens next
Look up the git tag by reading repo_name: from .github/workflows/on-merge-<pkg>.yml. Never derive
the tag from the directory name — several are counter-intuitive:
| Package | Tag |
|---|
llm-llamacpp | llamacpp-llm-v<ver> (reversed) |
embed-llamacpp | llamacpp-embed-v<ver> (reversed) |
vla-ggml | vla-v<ver> (no -ggml) |
translation-nmtcpp | bare v<ver> |
ocr-ggml | ocr-ggml-v<ver> |
classification-ggml | classification-ggml-v<ver> |
Addons get a git tag only, no GitHub Release — on-merge-<pkg>.yml calls create-release-tag.yml
since #2602. Do not promise a Releases-page entry; only the SDK publishes one.
Then tell the user the next step is /release <pkg>, which cuts release-<pkg>-<version>, dispatches
on-merge-<pkg>.yml, and pauses at the human-only npm approval gate.
Step 7 — Verify before committing
grep -nE "^## \[<version>\]" packages/<pkg>/CHANGELOG.md
git -C <repo> diff --stat origin/main
- The
grep must match. This is the extractor's own regex — if it does not match, the release fails
later, not now.
package.json version must equal the heading version exactly.
- The diff must show exactly two files:
package.json and CHANGELOG.md. Anything else means
something was swept in.
Then commit on a branch off origin/main — never on main, never on a release-* branch:
git -C <repo> worktree add -b <TICKET>/bump-<pkg>-<version> <path> origin/main
Commit title follows the repo convention TICKET prefix[tags]: subject, with chore as the prefix
(precedent: chore: bump llm-llamacpp to 0.38.1):
QVAC-12345 chore: bump <pkg> to <version> for <reason>
Add no [api] tag unless the public API or config surface actually changed — widening the set of
accepted values is not an API change. Add no AI signature or Co-Authored-By trailer.
PR body uses the repo's four-section format: problem / how / tested / breaking changes.
What CI actually enforces
Be accurate about this; two in-repo docs are wrong.
For addons, release-merge-guard (.github/actions/release-merge-guard/) asserts exactly three
things:
- the branch matches
release-<slug>-x.y.z;
package.json version equals the version in the branch name;
CHANGELOG.md was modified (skipped on initial branch push and on workflow_dispatch).
It does not validate the heading text for addons, and no CI check anywhere compares the new
version against the previous one. So a malformed heading will not fail the guard — it fails /release
Step 1, and would fail the release-body extractor for the SDK and the two lib packages that still use
it.
Write the bracketed heading regardless: /release, /addon-changelog, /release-patch and
/release-fabric-consumers all assume it.
Do not copy from ci-validation.mdc:234 (claims the guard checks the heading, and shows an unbracketed
## x.y.z) or from /addon-changelog's level-2 section example. Both are stale.
Bash discipline
Per repo CLAUDE.md: no heredocs, no $() command substitution, no &&/||/; chaining, no pipes or
redirects. Use Read / Write / Edit / Grep / Glob instead of cat / sed / grep / find, and
git -C <path> instead of cd. Put anything longer than a single command in a script file and run
bash <file>.
Error handling
release-merge-guard fails on merge — version not bumped, the branch name does not match the
version, or CHANGELOG.md was not modified.
/release Step 1 fails — the changelog heading is missing or unbracketed. Fix the heading.
- npm publish rejects the version — it already exists. Check
npm view @qvac/<pkg> versions and
pick the next free one.
- Never weaken, skip, or delete a test to get a bump through.