Release process

vibe-sketch is independently versioned. Changes land on main through the process in AGENTS.md. Released tags are immutable: do not rewrite published history or move a release tag to repair documentation or packaging metadata.

Contributor evidence

A change needs the relevant tests, with the commands named in the commit message. Record a user-visible change as a changelog fragment, one file per change: changelog.d/<slug>.<type>.md, where <type> is added, changed, deprecated, removed, fixed or security and the text is one paragraph in the user’s words. Fragments never conflict between parallel changes, which a shared [Unreleased] section did. They are folded into CHANGELOG.md when a release is cut (step 3 below).

Release checklist

The maintainer chooses the version. The approved first minor name is Couper’s Coati; later names come from the approved pool after another sibling collision check. The version and catalogue changes below land in one commit on a release-candidate/vX.Y.Z branch taken from main. tests/test_version.py and tests/test_codenames.py fail if any two of these sites disagree.

  1. Version. Set X.Y.Z in each of these files:

    • pyproject.toml: version.

    • src/vibesketch/__init__.py: __version__, and the codename in its trailing comment.

    • web/package.json: version.

    • web/package-lock.json: both version entries, the top-level one and the one under packages[""].

    • electron/package.json: version.

    • electron/package-lock.json: both version entries, the top-level one and the one under packages[""].

  2. Codename. For a new minor release, add the X.Y.0 entry to RELEASE_CODENAMES in src/vibesketch/codenames.py with its rationale comment, set FALLBACK_CODENAME in electron/main.js, and add the row to the catalogue table in the codename catalogue. A patch release inherits its minor’s name, so this step is skipped.

  3. Changelog fragments. Run python scripts/fold_changelog.py. It moves every changelog.d/ fragment into ## [Unreleased] under its ### heading and deletes the fragment files. Edit the folded entries into release notes if they need it.

  4. Changelog heading. Rename ## [Unreleased] to ## [vX.Y.Z] - YYYY-MM-DD - *Codename* and add a new empty ## [Unreleased] above it.

  5. Local proof. Run ruff check ., ruff format --check ., mypy, the test suite, npm ci && npm run check && npm run build in web/, and make strict in docs/. Use CI’s pinned QVF corpus and require the browser tests. Complete the real-program and packaged-desktop acceptance checks for the candidate.

  6. Candidate pipeline. Push the release-candidate/vX.Y.Z branch. Its pipeline runs every gate job, builds the docs strictly, and retains reproducible wheel/source artifacts with checksums. Plain topic branches have no pipeline until a merge request exists; merge requests and main run the same gate.

  7. Tag and publish. When the candidate pipeline is green, tag vX.Y.Z at the candidate commit and fast-forward release onto it. The release pipeline builds the documentation for publication without repeating the gate. Site-specific publication steps live in the private operations repository, never here.

Build and validate distributions

From a clean candidate checkout with its development environment active:

python -m pip install -e '.[release]'
(cd web && npm ci && npm run check && npm run build)
python scripts/build_release_artifacts.py --output-dir dist/release

The web build records hashes of its inputs and complete output tree. The release builder refuses stale or missing assets, notices, the reviewed WASM or its corresponding source. Wheels include the browser and document schema; source archives include the built browser and the files needed to rebuild it. No Node.js or checkout is needed to serve an installed wheel.

The builder uses the candidate commit time as SOURCE_DATE_EPOCH (an explicit environment value overrides it). It builds a wheel and source archive twice, normalises source-archive owner/time metadata, and compares their bytes. Metadata, payloads, wheel RECORD hashes and twine check must pass. It then installs the wheel into a fresh virtual environment outside the checkout, checks the CLI, serves its packaged UI/WASM/notices/schema, and imports and exports a molecule through REST. Only then are the artifacts and SHA256SUMS written to the requested output directory. Build and validation failures leave existing outputs untouched; operators must treat a nonzero exit as a failed candidate.

scripts/make_wheel.sh runs those checks and also stages the wheel in docs/_static/downloads/. Select its interpreter with VIBESKETCH_RELEASE_PYTHON if necessary. It refuses changed bytes at an already-staged version and retains older versioned wheels. Generated artifacts are ignored by Git; transfer the qualified candidate artifacts through the operator publication process. Never replace a published wheel or installer with different bytes under the same version.

Desktop and hosting

Build native desktop artifacts with electron/build-desktop.sh; use --dir for an unpacked test. macOS packages use ad-hoc signing without notarization or an Apple developer account. The desktop bundles Electron and the complete notices/source collection, and uses an external Python environment. It does not bundle Python or RDKit. The onboarding command installs the wheel matching the desktop version.

The approved public locations are:

  • Documentation: https://vibe-qc.com/vibe-sketch/docs/.

  • Wheels: https://vibe-qc.com/vibe-sketch/docs/_static/downloads/vibesketch-X.Y.Z-py3-none-any.whl.

  • Desktop update feed: https://vibe-qc.com/updates/vibe-sketch/.

Before publishing the desktop update manifest, publish and verify the matching wheel and installers with their checksums. Keep previous wheel URLs available for older desktop bootstrap and repair commands. Test a downloaded installer, first-run Python setup, file open/save, notices and server shutdown using the packaged-app acceptance procedure. Desktop delivery issues #9 and #11–#14 must be complete before the first release. Current sketch and compute features plus desktop delivery are the approved release scope; future roadmap features are not prerequisites.

Building and staging do not upload anything. Credentials, deployment targets and operational evidence remain in private operator tooling. The release version and actual publication remain explicit maintainer decisions.