| name | mpi-release |
| description | Cut a Cubric Vision release — the single GitHub-only release flow. Bump the right version digit (2nd = new features/ops/engine, 3rd = bug fixes, 1st = breaking), stamp the files via mpi-version-bump, build the portable artifacts in CI, and publish a GitHub Release with the full builds + update bundles. Use when the user says "cut a release", "ship a release", "make a release", "publish the release", "release to GitHub", "ship this version", "release the fixes", or indicates master is ready to go public. There is ONE release flow now — no pre-release tiers, no branch merging. |
| user-invocable | true |
mpi-release — the one GitHub-only release flow
Cubric Vision ships from master to a public GitHub Release. That's it —
one branch, one channel. Every release is the same mechanical operation; only
the version digit differs:
| Digit | When | Example |
|---|
| 3rd (patch) | Bug fixes only, no new ops/engine/schema | 1.1.0 → 1.1.1 |
| 2nd (minor) | New operations, new model support, or a ComfyUI engine bump | 1.1.1 → 1.2.0 |
| 1st (major) | Breaking change (schema bump, incompatible op change) | 1.2.0 → 2.0.0 |
Pick the digit, then run the exact same steps below. There is no separate
"promote", "patch", or "publish" skill — this is all of them.
Read the two references in this skill's references/ before running:
build-dispatch.md (CI build + artifact download) and copy-review.md (the two
mandatory user-facing copy gates). The version file edits belong to
mpi-version-bump — this skill calls it, it does not re-implement it.
Invariants (do not skip)
- Prep all, then STOP before each live op. Version edits, notes, and the copy
drafts are fine to do autonomously. PAUSE and wait for the user before:
git push, pushing the v* tag (fires the CI build), and gh release create (the
public moment). These are irreversible / public-facing.
- Two copy-review gates are mandatory — the in-app changelog and the GitHub
release body. The user rewrites dev-speak into user-speak before it ships. See
references/copy-review.md.
- Shared git tree. Commit by explicit pathspec (
git commit --only <paths>),
never git add -A (see .claude/rules/git.md).
Preconditions
Steps
1. Stamp the version — via mpi-version-bump
Run mpi-version-bump for the chosen digit. It bumps appVersion.js +
package.json + package-lock.json, updates the operation/model registries and
operation_registry.json if ops changed, folds every docs/releases/UNRELEASED.md
item into the js/data/releaseNotes.js block + a new archival
docs/releases/YYYY-MM-DD-v<ver>.md, then clears UNRELEASED back to its header.
Hold release:approve/check until after Gate 1.
Derived stage (js/core/appStage.js) is automatic: X.Y.Z (Z>0) = alpha,
X.Y.0 (Y>0) = beta, X.0.0 = release. You don't set it.
2. 🛑 Gate 1 — user reviews the in-app changelog
Present the releaseNotes.js block rendered the way MpiChangelogDialog shows it
(kicker <Stage> · v<ver>; fixed section order Breaking → Important → What's new →
Fixes → Engine; each item plain text). Apply the user's edits to releaseNotes.js
AND the archival md so they stay aligned (references/copy-review.md Gate 1). Then
npm run release:approve + npm run release:check.
Do not approve on a red suite. mpi-version-bump step 6 runs npm test +
npm run test:desktop; confirm both came back green before approving. Good copy
on a broken build is still a broken build — 1.3.0 shipped with the LoRA and
upscale pickers dead and every static check passed (MPI-443).
⚠️ release:approve must be the LAST thing you touch before building. The
build step hashes releaseNotes.js against the committed approval stamp
(.approved-<ver>.json); ANY edit after approving (even a one-word copy fix)
re-drifts the hash and the CI build FAILS with "Release notes … changed after
approval". release:check does NOT catch this — a green check is not proof the
build will pass. If you touch the notes after approving, re-run
release:approve, re-commit the stamp, THEN build. release:approve prompts
y/N — the USER runs it; agents are classifier-blocked.
3. Commit master (explicit pathspec) — then 🛑 STOP for push
Commit only your files (shared tree — never git add -A). Pushing master is a
live op: stop, let the user push (or run it once authorized). CI builds the
pushed ref, so master must be pushed before the build.
4. 🛑 Build — push the v<ver> tag, then download artifacts
Per references/build-dispatch.md: the v<ver> tag push is the build trigger
(push: tags: v* → private mpi-ci build). Pushing the tag is user-authorized —
stop first. When CI finishes, download the 6 artifacts (3 full builds + 3
update bundles) to D:\CubricStudio\Vision\Builds\v<ver>\, verify they landed,
then delete the CI run's artifacts (storage hygiene).
The tag publishes nothing on its own — it only fires the private artifact
build. The public moment is gh release create in Step 6.
Rebuilt via workflow_dispatch? The tag no longer matches the artifacts.
Any rebuild round dispatched by ref leaves the tag behind, and the release
would then claim provenance on code that was never built. Before Step 6, check
git rev-parse 'v<ver>^{}' against the SHA CI actually built, and move it if
they differ (git tag -f -a v<ver> <build-sha> + force-push — user-authorized;
agents are classifier-blocked on push --force). Measured 2026-08-01: five
rebuild rounds left v1.3.0's tag 63 commits stale.
5. 🛑 Gate 2 — user reviews the GitHub release body
The release body is user-facing → present it for review/rewrite
(references/copy-review.md Gate 2). The body bundles the accumulated changelog
blocks since the last release (each version added its own block; a release that
skips versions lists all of them). Keep within the claim boundary in
docs/releases/github-release-checklist.md (image + video gen allowed; no
unshipped-roadmap claims; Vision is local image/video, not an assistant) and
include the platform-disclosure block from that checklist.
6. 🛑 Publish — create the GitHub Release
With the user's authorization, create the release on the existing tag and attach
all 6 artifacts (full builds and update bundles — the update bundles are how
existing users patch in place via the online update.* script; without them
every update is a full re-download):
gh release create v<ver> --repo MadPonyInteractive/Cubric-Vision \
--title "v<ver>" --notes-file <body.md> --latest \
D:/CubricStudio/Vision/Builds/v<ver>/CubricVision-*-v<ver>.zip \
D:/CubricStudio/Vision/Builds/v<ver>/CubricVision-*-v<ver>.tar.gz \
D:/CubricStudio/Vision/Builds/v<ver>/CubricVision-*-update-v<ver>.zip
Use the canonical asset names from docs/releases/github-release-checklist.md
(no legacy CubricStudio names).
Title = the bare tag. Every published release is named v1.2.0 / v1.1.0 /
v1.0.1 — name equals tag. Corrected 2026-08-01 (this step used to say
Cubric Vision v<ver>, which no release has ever used). Check
gh release list before inventing a title.
7. Verify the release is REACHABLE — do not skip
Publishing is not proof users can see it. check-for-update (main.js)
reads releases/latest, which excludes drafts and prereleases — a slip there leaves
every installed app silently seeing the old version, with no error surfaced anywhere.
curl -s https://api.github.com/repos/MadPonyInteractive/Cubric-Vision/releases/latest \
| grep -E '"tag_name"|"prerelease"|"draft"'
Wants "tag_name": "v<ver>", "prerelease": false, "draft": false. Anything else →
fix on GitHub before announcing.
Then prove the prompt fires: launch a portable build of the previous version and
confirm the "Update available" dialog appears. MPI-334 shipped code-verified only and
could not be tested before 1.3.0 (a 1.2.0 install correctly saw 1.2.0 as latest), so
treat the first real observation as the validation. Windows builds older than 1.3.0
cannot be reached this way at all — Smart App Control blocks the update scripts; the
release body must tell those users to download the full zip
(docs/releases/github-release-checklist.md).
8. Summary
Report the published tag, release URL, and attached assets. Comms are out of
scope — announcement copy (Patreon / Discord / YouTube / Gumroad) is owned by
the MadPony-Identity launch-comms workflow, a separate manual step the user
drives. (Patreon is a comms/support channel only — it no longer gates release
downloads.)
9. Post-publish — restamp the baselines, then cut the maintenance branch
Both are post-publish by definition. Doing either early is exactly what
MPI-409 was.
Restamp release-baselines/*.json to the just-shipped FULL manifests so the
NEXT release deltas against this one. Extract them verbatim from the published
artifacts — never re-serialise — then assert toVersion: <ver>,
fromVersion: null, kind: portable-stage, and a file count in the thousands on
all three before committing. Recipe and the timing rule live in
release-baselines/README.md. Windows uses a different member path
(resources/cubric/update-manifest.json, no top-level folder since the MPI-387
layout move); the wrapped path that works for linux/macOS fails there in a way
that truncates the baseline to 0 bytes before erroring.
Cut the maintenance branch:
git branch <ver> v<ver> && git push -u origin <ver>
Master then moves on toward the next minor, while a bug report against the
shipped version is fixed on this branch and released as the next patch digit —
without dragging master's unfinished work into it. Building from the branch needs
nothing new: mpi-ci's workflow_dispatch takes ref: Branch, tag, or SHA.
Cherry-pick the baseline restamp onto the branch too, or its update bundles
delta against the previous release — correct, but needlessly fat.
Established 2026-08-01. 1.2.0 could not be hotfixed because master held
half-finished features, which forced a week of unplanned work finishing them
just to get fixes out — and that shipped as 1.3.0 with the rest of the
in-flight work pushed to 1.4.0. The branch exists so that never repeats.