Versioning and releases
Two things carry a version, and they are kept apart on purpose.
The app
The number lives in soldermask/version.py (__version__), follows semantic versioning, and must agree with a section in CHANGELOG.md and a git tag. soldermask release keeps the three in step so they cannot drift:
soldermask release note "Added a diff between versions" --kind Added # as you go
soldermask release show # what is waiting
soldermask release bump minor # 0.1.0 -> 0.2.0bump rewrites version.py, moves everything under Unreleased into a dated ## 0.2.0 — 2026-09-02 section, commits the two files and tags v0.2.0. It refuses to release with nothing under Unreleased unless --allow-empty; --no-git edits the files only; --dry-run shows what would happen.
soldermask version prints what is running, including the commit and whether the tree is dirty: 0.1.0+g0851531.dirty. /about and /api/app show the same.
The project format
FORMAT in version.py is the on-disk layout number of a project directory. It changes only when project.json or the version folders change shape, and it changes rarely. Every project records the format it was written in; the app migrates older ones on read (keeping a backup) and refuses newer ones. Bump it, add a migration step in soldermask/projects.py, and describe the change in Projects on disk.
Each project's versions
v001, v002, … under projects/<slug>/ — immutable directories, one per build, each recording the app version that made it. See Versions and history.
What goes where
| Change | Bump | Also |
|---|---|---|
| a fix, no format change | patch | changelog note |
| a feature, an endpoint, a flag | minor | changelog note, docs page |
a change to project.json or the version directory | minor or major | FORMAT + migration + docs |
| removing a command, endpoint or field | major | changelog under Removed |