| name | mpi-version-bump |
| description | The file-edit MECHANIC for a Cubric Vision version bump — bump app version (appVersion.js + package.json + package-lock.json), update operation registry, update model mappings, sync operation_registry.json, generate release notes, run release:check, and offer pre-release tests. Use when the user says "bump the version", "/mpi-version-bump", or when the release skill (mpi-release) needs the version stamped. For the full ship flow (builds, GitHub release) use mpi-release — this skill only does the in-repo file edits. |
| user-invocable | true |
/mpi-version-bump — version-bump file mechanic
This skill is the file-edit mechanic for a version bump: bumping the app
version, updating engine versions, registering new operations, updating all
related files, generating release notes, running npm run release:check, and
optionally running pre-release tests.
It does NOT run builds, push tags, or publish to GitHub. That is the single
release skill that calls this one as its bump step:
mpi-release — the one GitHub-only release flow: pick the digit (3rd = fix,
2nd = feature, 1st = breaking), stamp the version here, build the portable in
CI, and publish a GitHub Release with the full builds + update bundles.
Run this skill directly only for the in-repo file edits, or when mpi-release
tells you to. The build/tag/publish decisions live in mpi-release — don't
improvise them here.
Use this skill whenever you're ready to stamp a new version of Cubric Vision.
Quick path: patch-only release (most common)
If the release is a pure patch — bug fixes and/or small UI changes, with
no new operations, no ComfyUI engine change, and no project-schema change —
you only need to edit five files. Skip every operation/engine/schema step.
js/core/appVersion.js — bump APP_VERSION (e.g. a patch 1.0.1 → 1.0.2). Leave SCHEMA_VERSION untouched.
package.json — bump the top-level "version" to the same value. The portable build reads this; it must match APP_VERSION.
package-lock.json — bump the root "version" and packages[""].version to the same value.
js/data/releaseNotes.js — add a new RELEASE_NOTES['<newVersion>'] entry (runtime changelog overlay source).
docs/releases/YYYY-MM-DD-vX.Y.Z.md — archival, user-facing markdown notes.
Then review/approve the notes (required before any build — see Step 5.5) and run
the release gate:
npm run release:approve
npm run release:check
APP_VERSION, package.json version, and root package-lock.json version
metadata MUST be identical. Optionally run the pre-release tests (Step 6) — for
a pure patch with no operation changes the test output hash is unaffected, but
running it confirms nothing else drifted.
For anything beyond a pure patch (new ops, engine bump, schema change), use the
full flow below.
Step 1: Read Current State
I will read the following files to understand the current state:
js/core/appVersion.js — current APP_VERSION, SCHEMA_VERSION
package.json — current version (must track APP_VERSION)
package-lock.json — root version metadata (must track APP_VERSION)
dev_configs/system_dependencies.json — current COMFY_VERSION
js/core/operationRegistry.js — all registered operations
js/data/commandRegistry.js — UI metadata for all operations
js/data/modelConstants/models.js — model/operation/workflow mappings
js/data/modelConstants/universal_workflows.js — universal operation definitions
operation_registry.json — JSON mirror (should match operationRegistry.js)
Change Impact Matrix
Before asking bump questions, classify the change:
Change Impact Matrix: read docs/versioning.md § Change Impact Matrix (authoritative) before classifying.
Always run npm run release:check after edits and before builds, tags, pushes,
pre-release generation tests, or publication.
Step 2: Ask Questions Interactively
I will ask you the following questions:
Q1: Bump Type?
Choose: patch / minor / major
- patch (e.g., 1.0.1 → 1.0.2): Bug fixes, no new features, no schema change. Stage stays/derives alpha (Z>0).
- minor (e.g., 1.0.2 → 1.1.0): New operations added OR ComfyUI engine updated. Stage derives beta (X.Y.0, Y>0).
- major (e.g., 1.1.0 → 2.0.0): Breaking changes (schema change, significant architecture change). Stage derives release (X.0.0).
All three are shipped by the same skill, mpi-release — the digit is the only difference.
Derived stage: js/core/appStage.js derives alpha/beta/release from the
version — you don't set it. X.0.0→release, X.Y.0(Y>0)→beta, X.Y.Z(Z>0)→alpha,
0.x.x→alpha. It drives the About panel + bug-report stage:<x> label, so a
patch labeled itself "alpha" is correct, not a mistake.
Q2: ComfyUI Engine Version Changing?
Current ComfyUI version: X.Y.Z (read from dev_configs/system_dependencies.json)
If yes, provide new version (e.g., 0.19.0). If no, press Enter to keep current.
Q3: New Operations Being Added?
List each new operation. For each:
- Key: snake_case identifier (e.g.,
my_new_op)
- Label: Display name (e.g.,
My New Operation)
- Media Type:
image or video
- Requires Images: Number (0, 1, 2, ...) — does it need input images?
- Requires Mask:
y or n
- Prompt Required:
y or n
- Universal:
y or n — is it model-agnostic, or model-tied?
- If universal: none of the fields below
- If model-tied:
- Supporting Models: comma-separated model IDs (e.g.,
sdxl-realistic,ill-anime-beauty)
- Workflow Filenames: one per model (e.g.,
my_new_op_sdxl_realistic.json, my_new_op_ill_anime_beauty.json)
Example:
New operation key: segment
Label: Image Segmentation
Media type: image
Requires images: 1
Requires mask: n
Prompt required: n
Universal: y
Or:
New operation key: upscale_2x
Label: 2x Upscale
Media type: image
Requires images: 1
Requires mask: n
Prompt required: n
Universal: n
Supporting models: sdxl-realistic,ill-anime-beauty
Workflow filenames: upscale_2x_sdxl_realistic.json, upscale_2x_ill_anime_beauty.json
Q4: Operations Being Deprecated?
List operation keys to mark as deprecated (e.g., old_op_v1, legacy_filter), or press Enter for none.
Important: Deprecation does NOT remove operations — it marks them so the UI hides them but projects using them can still load.
Q5: Project Schema Version Changing?
y or n
If yes, the app's SCHEMA_VERSION will increment (from 1 to 2, etc.) and you'll need to implement a migration in js/migrations/projectMigrations.js. I will create a stub for you.
Q6: Notable Changelog Items?
Free-text description of what changed. Examples:
- "Added image segmentation operation"
- "Upgraded ComfyUI to support new video models"
- "Bug fixes in the gallery grid rendering"
- "Performance improvements in project load"
Press Enter to skip if no additional notes.
Step 3: Compute and Confirm New Version
I will calculate the new version based on your bump type and confirm it with you:
Current version: 1.0.2
Bump type: minor
New version: 1.1.0
Is this correct? [y/n]
Answer n to re-do the questions, y to continue.
Step 4: Make Targeted Edits
In this exact order (so if anything fails, state is consistent):
4a. Edit js/core/appVersion.js
- Bump
APP_VERSION to the new version
- If schema version changing, increment
SCHEMA_VERSION
- Do NOT edit engine versions — those are in
system_dependencies.json
4b. Edit package.json
- Bump the top-level
"version" field to the same new version as APP_VERSION.
- This is what the portable build (
scripts/build-portable.mjs) and Electron read. If it drifts from APP_VERSION, the build artifact and in-app version disagree.
- Do not run
npm install or touch other fields.
4c. Edit package-lock.json
- Bump the root
"version" field and packages[""].version to the same new version as APP_VERSION.
- Do not run
npm install solely for this metadata change.
4d. Edit dev_configs/system_dependencies.json
If ComfyUI version changed:
- Update
engine.version to the new ComfyUI version
This is the single source of truth for the engine version. routes/platformEngine.js reads from this file.
4e. Edit js/core/operationRegistry.js
For each new operation:
- Add entry:
opKey: { latestVersion: '1.0', appVersionIntroduced: '<newVersion>' }
For each deprecated operation:
- Add field:
deprecated: true (do NOT remove the entry)
4f. Edit js/data/commandRegistry.js
For each new operation, add a CommandDef:
myNewOp: {
label: 'My New Operation',
mediaType: 'image',
requiresImages: 1,
requiresMask: false,
promptRequired: false,
universal: true,
components: [],
},
4g. Edit js/data/modelConstants/models.js
For each model that supports a new operation:
- Add the operation key to the model's
supportedOps[] array
- Add the operation key and workflow filename to the model's
workflows{} object
Example:
supportedOps: ['t2i', 'upscale', 'myNewOp'],
workflows: {
t2i: 't2i_sdxl_realistic.json',
upscale: 'upscaler_sdxl_realistic.json',
myNewOp: 'my_new_op_sdxl_realistic.json',
},
4h. Edit js/data/modelConstants/universal_workflows.js
For each new universal operation, add entry:
myNewOp: {
workflow: 'my_new_op.json',
dependencies: ['dep1', 'dep2'],
},
4i. Edit operation_registry.json
Add/update entries to match operationRegistry.js exactly. Add universal: true for universal ops. Mark deprecated ops with deprecated: true.
4j. If Schema Changed: Edit js/migrations/projectMigrations.js
I will add a migration stub:
function migrateVXtoVY(projectJson) {
return projectJson;
}
export const MIGRATIONS = {
Y: migrateVXtoVY,
};
You fill in the actual migration logic. Remember SCHEMA_VERSION must match in
both appVersion.js and projectMigrations.js.
Step 5: Generate Release Notes
Release notes live in two places that must stay aligned:
-
Runtime source — js/data/releaseNotes.js (consumed by the in-app changelog
overlay, MpiChangelogDialog, shown once per APP_VERSION at startup). Add an
entry to RELEASE_NOTES keyed by the new APP_VERSION:
'<newVersion>': {
version: '<newVersion>',
whatIsNew: [ ],
fixes: [ ],
breakingChanges: [ ],
importantChanges: [ ],
engineNotes: [ ],
},
Keep sections as empty arrays when not relevant — the overlay hides empty
sections. Do NOT add any network/update-check behavior here (that is MPI-8 /
portable-distribution scope; the changelog overlay only describes the already-
running version).
The overlay renders each string as plain text (li.textContent) — markdown
like **bold**, links, and parentheticals ship verbatim. Strip author asides
("add notes when X ships", "Also shipping as a 1.0.1 hotfix") and editorial
instructions; ship only the user-facing sentence. Fold docs/releases/UNRELEASED.md
scratchpad items into these arrays and clear it back to its header.
Every "used to / previously / no longer" claim must be checked against the
PREVIOUS RELEASED TAG before you write it — git show v<prev>:<path> | grep,
per bullet, not per release. Code that changed two or three times inside this
unreleased version reads like user-visible history but never shipped, and the
entry is then simply false. The full gate, the two commands and the measured
1.3.1 case are in .claude/skills/mpi-release/references/copy-review.md § Gate 0
— read it before drafting either changelog surface.
Section order shown to the user is fixed by the overlay (MpiChangelogDialog),
not by your array order: Breaking changes → Important → What's new → Fixes →
Engine. A "Breaking — …" item parked in the scratchpad's
belongs in here.
I will create docs/releases/YYYY-MM-DD-vX.Y.Z.md with:
# Cubric Vision vX.Y.Z — YYYY-MM-DD
## Changelog
<summary from Q6>
### Changes
- <changelog items>
### New Operations
- **op_key** (Op Label): media type, input requirements
(or "None")
### Breaking Changes
<list from Q5 if schema changed, otherwise "None">
### ComfyUI Engine
ComfyUI version unchanged (X.Y.Z) | Updated to X.Y.Z
---
## Platform Update Checklist
After publishing this release, update all parallel platforms:
- [ ] **Landing Page**: Update version badge, feature list if new ops added
- [ ] **Documentation Website**: Update operation list, changelog page
- [ ] **GitHub Releases**: Create release with tag vX.Y.Z, attach portable artifacts (gated per repo-distribution rules), write release notes
- [ ] **Patreon**: Post update announcement with changelog highlights
- [ ] **Discord**: Post in #updates channel with release highlights and download link
Step 5.5: Review and approve release notes (enforced build gate)
The build cannot run until you have reviewed and approved the exact release
notes that will ship in the in-app changelog overlay (MpiChangelogDialog). This
is not a soft instruction — scripts/build-portable.mjs calls assertApproved()
before any staging and aborts a real build if the notes are unapproved or have
changed since approval.
After writing the notes (Step 5), run:
npm run release:approve
This prints the notes exactly as the overlay renders them — kicker
<Stage> · v<newVersion>, sections in the overlay's fixed order skipping empties
(Breaking changes → Important → What's new → Fixes → Engine), each item as a
plain-text bullet (no markdown processing). What you see is byte-for-byte what
ships, so any stray **bold**, link syntax, or author aside is a copy bug to fix
now. It then asks for a y/n.
- y → writes an approval token
docs/releases/.approved-<newVersion>.json
(a SHA256 of the rendered notes). Commit this file with the version bump —
CI reads it to unlock the headless build.
- n → nothing is written. Go back to Step 5, fix the
releaseNotes.js entry
(and the archival markdown to match), and re-run npm run release:approve.
If you edit the notes after approving, the token's hash no longer matches and
the build re-blocks until you re-run release:approve. To re-review the rendered
notes without approving, run npm run release:notes.
This is the last checkpoint before the build (build is a separate step — CI
dispatch / scripts/build-portable.mjs — outside this skill), so the notes you
approve here are the ones that go out.
Step 6: Run Release Gate, Then Offer Pre-Release Tests
I will print a summary of all changes made:
- Files edited
- New version
- New operations added
- Release notes written to
docs/releases/
Then I run:
npm run release:check
If it fails, I stop and fix the release drift before building, tagging, pushing,
or running pre-release generation tests.
Then I run the automated suites — both must exit 0 before anything is built,
tagged or approved:
npm test
npm run test:desktop
npm run release:deps
release:deps is the only check that touches the outside world: it HEADs all 215
download URLs (215/119 deps as of 1.3.1) and fails on any that moved, were deleted, or
404. Nothing else catches that class — the unit tests prove the download LOGIC offline,
and a dead R2 key or a removed HF re-host stays invisible until a user hits it. It is
NOT in CI on purpose (network-bound, would flake). A dead MIRROR fails the run too: it
silently drops that dep to a single route, which is the regression MPI-429 exists to
prevent. It also prints the weights that have no second origin at all — expect 9 today
(the four MiniMax H3 deps and controlnet-union-flux are HF-only;
krea2-raw-transformer-nsfw is R2-only until 2026-08-10, plus the three TAESD decoders).
release:check only compares files to each other; it never runs the app. These
two are the only gate that executes real code, and the desktop suite is what
covers the class of bug that shipped in 1.3.0 — the LoRA and upscale pickers
opening into hidden DOM, invisible to every static check (MPI-443).
If either suite fails, STOP. A red test at this point means a regression landed
since the last green commit — fix it, re-run npm run release:check (a code fix
can drift the registry), and only continue once both suites are green again.
test:desktop no longer needs the app closed (MPI-448)
Do not ask the user to close Cubric Vision, and do not check port 3000. That
instruction lived here until 2026-08-05 and is now wrong: tests/desktop/globalSetup.js
hands each run its own free CUBRIC_PORT, which server.js and main.js both read,
so the suite launches beside a live instance and leaves it alone (verified 17/17 green
with the dev app on 3000).
The old silent-attach failure is dead in both directions too — server.js exits 1 on
EADDRINUSE and main.js turns that into a fatal — so a port collision can no longer
fake a pass. Just run the suite.
Then ask:
Release gate passed. Would you like to run scripts/pre_release_test.py now? [y/n]
If yes, I run the test suite and surface the results. If tests FAIL, you can re-run them or skip.
If no, testing is skipped.
Step 7: Print Final Summary
After all edits and tests:
=== Release vX.Y.Z Complete ===
Files edited:
- js/core/appVersion.js
- package.json
- package-lock.json
- dev_configs/system_dependencies.json
- js/core/operationRegistry.js
- js/data/commandRegistry.js
- js/data/modelConstants/models.js
- operation_registry.json
- js/data/releaseNotes.js
- docs/releases/YYYY-MM-DD-vX.Y.Z.md
- docs/releases/.approved-X.Y.Z.json (release-notes approval token — commit it)
New operations: 2 (myNewOp, anotherOp)
Deprecated: 0
Release notes: docs/releases/2026-04-17-v0.1.0.md
Test result: PASS (17 tests)
What Happens Next
⚠️ Do NOT tag + push from here. This skill only stamps the version files.
Pushing the v* tag fires the private CI build (push: tags: v*) — that is
mpi-release's step, not this one.
- Commit the version files by explicit pathspec (shared tree —
git commit --only <paths>, never git add -A).
- Hand back to
mpi-release, which owns the build, tag, and publish:
push master, push the v<ver> tag to trigger the CI build, download the 6
artifacts, then gh release create with the full builds + update bundles.
The digit you bumped (patch / minor / major) is the only thing that varies —
the ship steps are identical.
- Comms (Discord / YouTube / Gumroad) are owned by the MadPony-Identity
launch-comms workflow — a separate manual step, never automated from here.
See mpi-release for the build/tag/publish flow.
Troubleshooting
Q: I made a mistake during the bump. Can I undo it?
A: Yes, the skill edits files atomically in order. If something fails, check the error message and re-run the skill. You can also manually edit the files and re-run /mpi-version-bump with the correct values.
Q: The pre-release tests failed. Should I still release?
A: No, FAIL means the test output hash changed unexpectedly. Investigate why, fix the issue, update the baselines if the change is intentional, then re-run.
Q: APP_VERSION, package.json, and package-lock.json disagree after a bump — which wins?
A: None wins automatically. They must be identical. package.json drives the portable build artifact name/Electron version; APP_VERSION drives in-app version, release-note lookup, and derived stage; root package-lock.json metadata tracks package identity. Fix all three to the same value, then run npm run release:check before building.
Q: How do I add a new model?
A: Add the model to js/data/modelConstants/models.js with its id, supportedOps, and workflow filenames. The version-bump skill doesn't touch models — that's a separate step. Rerun /mpi-version-bump if model additions happen in the same release.
Q: I added a universal operation but forgot to add workflows. What do I do?
A: Add the workflow filename to js/data/modelConstants/universal_workflows.js and re-run the pre-release test. The test will fail if the workflow file is missing.
Q: Where does engine version get read?
A: dev_configs/system_dependencies.json is the single source of truth for the engine version. routes/platformEngine.js reads this file at startup and exports COMFY_VERSION for use by the rest of the app.
See Also
docs/versioning.md — versioning system explained
dev_configs/system_dependencies.json — engine version (single source of truth)
routes/platformEngine.js — reads system_dependencies.json and exports version constants
docs/releases/ — all past release notes
scripts/pre_release_test.py — pre-release test suite
operation_registry.json — JSON mirror of operation registry
js/core/operationRegistry.js — source of truth for operations
js/migrations/projectMigrations.js — schema migration functions