Document and standardize the release process (semver, GitLab Release, CONTRIBUTING)
## Context
The current `CONTRIBUTING.md` describes a partial release flow (tag → CI builds gem + Docker) but is missing:
- Semantic versioning rules
- GitLab Release creation (currently done manually)
- Asset links (Docker image, RubyGems)
- A step-by-step checklist usable by Claude Code and Claude Desktop
The release process follows **Option C**: CI handles the build (gem + Docker image), but the GitLab Release itself is created separately — either via the GitLab UI or via `gitlab:create_release` MCP call — with a hand-crafted description and the two standard asset links.
This keeps the CI simple (no `release-cli`, no extra stage) while producing clean, readable release notes.
## Work to do
### 1. Add semantic versioning rules to `CONTRIBUTING.md`
Add a **Versioning** section:
```markdown
## Versioning
Faure follows [Semantic Versioning](https://semver.org/):
| Increment | When |
|---|---|
| `MAJOR` (x.0.0) | Breaking change to the public API or CI template variables |
| `MINOR` (0.x.0) | New feature, backward-compatible |
| `PATCH` (0.0.x) | Bug fix, backward-compatible |
Pre-releases use the `-beta.N` suffix: `1.0.0-beta.1`.
```
### 2. Update the release process section in `CONTRIBUTING.md`
Replace the current "Release process" section with:
```markdown
## Release process
**Never bump `version.rb` manually in a feature branch.**
### Step-by-step
1. Ensure all target issues are closed and merged to `main`
2. Determine the next version number following semver (see above)
3. Create the GitLab Release from the UI or via MCP:
- Go to `Deploy → Releases → New release` (UI), OR
- Use `gitlab:create_release` (Claude Desktop MCP)
- Set the tag name (e.g. `v1.2.3`) — GitLab creates the tag from `main`
- Write the release description in Markdown (bug fixes, features, breaking changes)
- Add the two standard asset links:
- **Docker image**: `https://gitlab.com/rol-public/faure/container_registry/11018860?orderBy=PUBLISHED_AT&sort=desc&search[]=v1.2.3`
- **RubyGems**: `https://rubygems.org/gems/faure/versions/1.2.3`
4. Publishing the tag triggers the CI pipeline, which:
- Patches `version.rb` to the tag version before building
- Publishes the gem to RubyGems
- Builds and pushes the Docker release image
- Commits the version bump back to `main` (`[skip ci]`)
### Asset link URL patterns
| Asset | URL pattern |
|---|---|
| Docker image | `https://gitlab.com/rol-public/faure/container_registry/11018860?orderBy=PUBLISHED_AT&sort=desc&search[]=${TAG}` |
| RubyGems | `https://rubygems.org/gems/faure/versions/${TAG#v}` |
The `GITLAB_PUSH_TOKEN` CI variable (project access token, `write_repository` scope) is required for the auto-commit step.
```
### 3. Language conventions (see also #15)
Add a **Language** section:
```markdown
## Language conventions
- Code, comments, commit messages, branch names → English
- MR titles and descriptions → English
- Bot messages and prompts → configurable via `FAURE_LANG` (default: `en`)
- `.faure/AGENTS.md` should enforce English for generated MR descriptions
```
## Expected result
- Any Claude instance (Code or Desktop) can execute a full release given "release vX.Y.Z" with no ambiguity
- CONTRIBUTING.md is the single source of truth for the release process
- #15 (language conventions) can be closed as part of this issue
issue