RELEASING.md
Rama main · réplica de lectura del repositorio original.
# Release process
Brokoli ships on a fixed **4-week cycle**, loosely modeled on the Linux
kernel's merge-window/rc/release rhythm, scaled down for a project this
size. The goal isn't process for its own sake — it's a predictable rhythm
so contributors know when a change needs to land, and so "what's in the
next release" is always answerable by looking at a milestone, not by
asking someone.
## The cycle
| Phase | Length | What happens |
|---|---|---|
| **Open development** | 2 weeks | PRs merge freely against issues carrying the current milestone. |
| **Scope lock** | instant, end of week 2 | The milestone's issue list freezes. "In scope" means actively in flight (an open PR, or clearly claimed with visible progress) — not necessarily merged yet. |
| **RC / stabilization** | 1 week | Tag `vX.Y.0-rc1`. Bugfixes only from here — no new features, no scope additions. |
| **Soak** | 1 week | Run the rc build, watch `/metrics` (leader status, execution-attempt counters) and `run_events` for anything the rc week didn't catch. This is intentionally lightweight for a small team — it'll get more formal as the project and the team grow. |
| **Release** | tag day | Tag `vX.Y.0`. `.github/workflows/release.yml` (GoReleaser) builds and publishes automatically. Move `CHANGELOG.md`'s `[Unreleased]` section under the new version heading. |
A cycle is 4 weeks end to end; the next one's open-development phase
starts the same day the previous release tags.
## If an issue doesn't make scope lock
It slips — quietly, not as a judgment on the work. The maintainer removes
the milestone label and leaves one comment:
> Moving this to `vX.(Y+1).0` — didn't make scope lock, no reflection on
> the work, just cadence.
It goes back on as soon as the next milestone exists. Nothing gets closed
for slipping.
## RC bugs
If stabilization week turns up a real bug, whether that costs a fresh
week of rc/soak or just a respin is a maintainer call, made per-bug based
on severity — not a fixed rule. For a team this size, a hard "any rc bug
restarts the whole clock" rule would grind releases to a halt over minor
issues.
## Per-repo version tracks
Each repo tags independently — there's no single "Brokoli vX.Y.0" that
spans all three:
- **`brokoli`** (this repo) tags real semver releases (`v0.10.7` as of
this writing) and is the only repo GoReleaser publishes automatically
for.
- **`brokoli-sdk`** has shipped zero tags so far. Its first tag happens
the cycle it needs one — most likely once the SDK/backend
capability-negotiation work lands.
- **`brokoli-ee`** keeps its own separate, currently-behind tag line and
its own `deploy.yml`.
Because of that, `brokoli-sdk` and `brokoli-ee` milestones are named by
cycle (e.g. `2026-08 cycle`) rather than a version number that would
misleadingly imply they track `brokoli`'s semver — the *cadence* is
shared across the three repos, the version number is not.
## Where to look
- [`CONTRIBUTING.md`](./CONTRIBUTING.md) — how to claim an issue, PR
conventions, what "done" means.
- [`docs/adr/README.md`](./docs/adr/README.md) — how architecture
decisions get made and how to weigh in on one.
- `CHANGELOG.md` — what's actually shipped, release by release.
## Release notes and changelog
GoReleaser publishes a raw commit list; that is a fallback, not the
release notes. After the workflow completes, edit the release
(`gh release edit vX.Y.Z --notes-file ...`) with curated notes:
- grouped by area, leading with why a change matters, not what the commit
subject said;
- **every entry names its owner** by GitHub handle;
- a "Behaviour changes to read before upgrading" section whenever any
exist — an empty section is a claim, so state it explicitly;
- a short orientation paragraph for new contributors when the release
warrants one.
Mirror a condensed entry into `CHANGELOG.md` in the same PR window, with
the same ownership attribution.