|
| 1 | +# Release process |
| 2 | + |
| 3 | +bstack ships as a skill installed via `npx skills add broomva/bstack` (vendored) or `git clone` (git install). Every release must be reachable to both install types and properly tagged so `bin/bstack-update-check` and downstream tooling can discover it. |
| 4 | + |
| 5 | +## Versioning policy (Semantic Versioning) |
| 6 | + |
| 7 | +bstack follows [SemVer 2.0](https://semver.org/) with the **pre-1.0 convention** that minor versions may carry breaking behavior changes: |
| 8 | + |
| 9 | +| Pre-1.0 (`0.x.y`) | Meaning | |
| 10 | +|---|---| |
| 11 | +| `0.x.0` (minor) | New primitives, new hooks wired by default, behavior-changing default flips. **May break existing installs** — document the migration in CHANGELOG. | |
| 12 | +| `0.x.y` (patch) | Bug fixes, doc updates, additive non-default features, doctor lint additions. Safe to auto-upgrade. | |
| 13 | + |
| 14 | +Once 1.0.0 ships, the standard SemVer rules apply (major = breaking, minor = additive backwards-compatible, patch = fixes only). |
| 15 | + |
| 16 | +### Examples |
| 17 | + |
| 18 | +| Change | Bump | |
| 19 | +|---|---| |
| 20 | +| New primitive `P21` added to table + doctor lint | **Minor** — governance change | |
| 21 | +| New optional hook in `settings.json.snippet` | **Minor** — installs that re-run `bstack repair` pick it up | |
| 22 | +| `bstack-update-check` switches transport (raw VERSION → GitHub releases API) | **Patch** — internal mechanism, observable behavior unchanged | |
| 23 | +| Default flip (`auto_upgrade` defaults to true) | **Minor** — silently changes behavior for existing users | |
| 24 | +| Typo fix in CLAUDE.md.template | **Patch** | |
| 25 | +| Remove legacy fallback shim that 0.x.y added | **Minor** — breaks pinned-to-shim installs even if "internal" | |
| 26 | + |
| 27 | +## Release checklist |
| 28 | + |
| 29 | +Use this checklist for every release. The CI workflow `validate-release.yml` enforces the VERSION ↔ CHANGELOG alignment automatically; the rest is human discipline. |
| 30 | + |
| 31 | +1. **PR opens with**: |
| 32 | + - `VERSION` bumped to the new `X.Y.Z` |
| 33 | + - `CHANGELOG.md` prepended with `## X.Y.Z — YYYY-MM-DD` section |
| 34 | + - Any breaking changes documented under a `### Migration` subheading |
| 35 | +2. **Validate locally** — `bash scripts/doctor.sh --quiet`, `shellcheck scripts/*.sh bin/*`, `jq -e . assets/templates/*.snippet`. |
| 36 | +3. **CI passes** — `ci.yml` (lint) + `validate-release.yml` (version/changelog match). |
| 37 | +4. **Reviewer approves** — at least one human or `pr-review-toolkit:code-reviewer` agent verdict. |
| 38 | +5. **Merge to main** (squash). |
| 39 | +6. **Tag + GitHub Release** — `bstack release tag` (≥ 0.2.2) wraps the manual sequence: |
| 40 | + ```bash |
| 41 | + git fetch origin && git checkout main && git pull --ff-only |
| 42 | + bstack release tag # validates clean tree, on main, in sync; tags + pushes + creates Release |
| 43 | + ``` |
| 44 | + The dispatcher reads `VERSION`, picks the matching `## X.Y.Z` section out of `CHANGELOG.md` as the release notes, and uses the first `### ` heading inside that section as the release title. If `gh` is not installed the tag is still pushed and the command prints the manual `gh release create` invocation. |
| 45 | + |
| 46 | + Manual fallback (pre-0.2.2 installs, or if the dispatcher is unavailable): |
| 47 | + ```bash |
| 48 | + VERSION=$(cat VERSION) |
| 49 | + git tag -a "v${VERSION}" -m "v${VERSION} — <title from CHANGELOG>" |
| 50 | + git push origin "v${VERSION}" |
| 51 | + gh release create "v${VERSION}" --title "v${VERSION} — <title>" --notes-file <(awk "/^## ${VERSION}/{flag=1; next} /^## /{flag=0} flag" CHANGELOG.md) |
| 52 | + ``` |
| 53 | +7. **Downstream verification**: |
| 54 | + - `bin/bstack-update-check --force` from any install should now emit `UPGRADE_AVAILABLE <old> <new>` within the cache TTL window. |
| 55 | + - For git installs with `auto_upgrade=true`, the SessionStart hook (≥ 0.3.0) auto-pulls on next session. |
| 56 | + |
| 57 | +## Cadence |
| 58 | + |
| 59 | +bstack has no fixed release cadence. The triggers for a release are: |
| 60 | + |
| 61 | +- A new primitive earns its rule-of-three and gets promoted → **minor**. |
| 62 | +- A behavior-changing default flip (anything that affects installs without their action) → **minor**. |
| 63 | +- A bundle of fixes/docs is ready to ship → **patch**. |
| 64 | +- A critical bug or security issue → **patch**, immediately. |
| 65 | + |
| 66 | +Avoid letting `main` accumulate more than 2-3 unreleased PRs — each unreleased PR is invisible to downstream installs. |
| 67 | + |
| 68 | +## Backporting |
| 69 | + |
| 70 | +bstack does not maintain release branches. If a fix on `main` is needed urgently on a pinned install, the downstream user pins to a tag and applies the fix locally. There is no `0.2.x` branch to backport to. |
| 71 | + |
| 72 | +## Retroactive tagging (history) |
| 73 | + |
| 74 | +The repo's first tagged release was **v0.2.0** (2026-05-16, commit `322ba23`). Earlier versions (`0.1.0`, etc.) referenced in `CHANGELOG.md` predate the release-infrastructure formalization and are not tagged. |
| 75 | + |
| 76 | +Tags `v0.2.0` and `v0.2.1` were created retroactively on 2026-05-18 as part of the v0.2.2 release-infrastructure work to give `bin/bstack-update-check` a stable anchor to compare against. |
| 77 | + |
| 78 | +## Update check transport |
| 79 | + |
| 80 | +`bin/bstack-update-check` (≥ 0.2.2) compares the local `VERSION` against: |
| 81 | + |
| 82 | +1. **Primary**: GitHub Releases API — `GET /repos/broomva/bstack/releases/latest`, read `.tag_name`, strip leading `v`. |
| 83 | +2. **Fallback**: raw `VERSION` file on `main` (`https://raw.githubusercontent.com/broomva/bstack/main/VERSION`) — used when the API is unreachable or rate-limited. |
| 84 | + |
| 85 | +This separation means **development-branch VERSION bumps do not leak as available upgrades to downstream installs** — only tagged releases do. Bump `VERSION` freely on a feature branch; downstream sees nothing until the tag lands. |
| 86 | + |
| 87 | +## Disabling update checks |
| 88 | + |
| 89 | +Downstream users can disable update checks entirely: |
| 90 | + |
| 91 | +```bash |
| 92 | +bstack-config set update_check false |
| 93 | +``` |
| 94 | + |
| 95 | +Or snooze a specific version via the `/bstack-upgrade` interactive flow. |
| 96 | + |
| 97 | +## Questions |
| 98 | + |
| 99 | +See `CONTRIBUTING.md` for the contribution + PR shape. Cadence-or-policy questions belong in repo discussions; mechanical bugs in the release workflow are issues. |
0 commit comments