# Package versioning

Publishable workspace packages use **Semantic Versioning** and **Conventional Commits**. Version bumps are recorded with [Changesets](https://github.com/changesets/changesets); commit messages are linted in CI.

## Scope

| Surface | Versioning |
| --- | --- |
| `create-edgecms-app`, `@edgecms/plugin-sdk`, `@edgecms/runtime`, `@edgecms/client` | Changesets, lockstep (`fixed` group). SemVer bumps via `.changeset/*.md`. |
| Root, `apps/*`, `@edgecms/schemas` | Lockstep with root `package.json`, gated by `bun run check:release` / `check:release:library`. |

Packages stay private until an operator publishes with `NPM_TOKEN`. Local checks only qualify manifests (`bun run check:package`); they are not an npm publication proof.

## Conventional Commits

Commit messages follow [Conventional Commits](https://www.conventionalcommits.org/):

```text
feat(client): add locale-aware preview helper
fix(runtime): handle empty snapshot pointer
chore(ci): add commitlint gate
```

Allowed types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert`. Merge and Revert commits are ignored by commitlint.

PR CI (single job) runs `bun run check:commits --from <base> --to <head>` on pull requests.

## Changesets

When you change a publishable package:

```bash
bun run changeset
# pick packages (or the fixed group) and patch | minor | major
git add .changeset/*.md
git commit -m "feat(client): …"
```

PR CI runs `bun run check:changeset --base <base>` and fails if publishable package sources change without a new `.changeset/*.md`.

Release (operator):

```bash
bun run version-packages          # apply changesets → package.json + CHANGELOG fragments
bun run check:release:library
bun run publish:packages:dry-run  # or publish:packages with NPM_TOKEN
```

Or use `.github/workflows/publish-packages.yml`.

## Related commands

```bash
bun run check:commits --from origin/main
bun run check:changeset --base origin/main
bun run check:package
bun run publish:packages:dry-run
```
