Bump Version

SkillDev tools

Bump a native addon package's version in package.json and write its CHANGELOG.md entry. Defaults to a minor bump. Use before /release.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Bump Version skill

What this skill tells your AI

The instructions your AI receives, as published by tetherto/qvac in packages/ocr-ggml/.agent/skills/bump-version/SKILL.md and read by ahel’s review.

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:

CaseUse 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

  1. 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.
  2. Version not higher than npm latest. Report both numbers and stop.
  3. Working branch is a release-* branch. That is /release-patch territory — a release branch must stay a byte-exact copy of its base. Stop.
  4. 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:

ChangeLevel
New public API, new config key, new supported model, changed defaultminor
Bug fix onlypatch
qvac-fabric dependency bumpminor for 0.x, major for >=1.0 — see /rollout-phase-b
Breaking changemajor — 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.19.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:

PackageTag
llm-llamacppllamacpp-llm-v<ver> (reversed)
embed-llamacppllamacpp-embed-v<ver> (reversed)
vla-ggmlvla-v<ver> (no -ggml)
translation-nmtcppbare v<ver>
ocr-ggmlocr-ggml-v<ver>
classification-ggmlclassification-ggml-v<ver>

Addons get a git tag only, no GitHub Releaseon-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:

  1. the branch matches release-<slug>-x.y.z;
  2. package.json version equals the version in the branch name;
  3. 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.

Signals

GitHub stars
601
Forks
111
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
bump-version-tetherto
Source
github.com/tetherto/qvac