VERSIONING.md
GSD follows Semantic Versioning 2.0.0 with three release tiers mapped to npm dist-tags.
| Tier | What ships | Version format | npm tag | Branch | Install |
|---|---|---|---|---|---|
| Patch | Bug fixes only | 1.27.1 | latest | hotfix/1.27.1 | npx get-shit-done-cc@latest |
| Minor | Fixes + enhancements | 1.28.0 | latest (after RC) | release/1.28.0 | npx get-shit-done-cc@next (RC) |
| Major | Fixes + enhancements + features | 2.0.0 | latest (after beta) | release/2.0.0 | npx get-shit-done-cc@next (beta) |
Only two tags, following Angular/Next.js convention:
| Tag | Meaning | Installed by |
|---|---|---|
latest | Stable production release | npm install get-shit-done-cc (default) |
next | Pre-release (RC or beta) | npm install get-shit-done-cc@next (opt-in) |
The version string (-rc.1 vs -beta.1) communicates stability level. Users never get pre-releases unless they explicitly opt in.
| Increment | When | Examples |
|---|---|---|
| PATCH (1.27.x) | Bug fixes, typo corrections, test additions | Hook filter fix, config corruption fix |
| MINOR (1.x.0) | Non-breaking enhancements, new commands, new runtime support | New workflow command, discuss-mode feature |
| MAJOR (x.0.0) | Breaking changes to config format, CLI flags, or runtime API; new features that alter existing behavior | Removing a command, changing config schema |
Major and minor releases use different pre-release types:
Minor: 1.28.0-rc.1 → 1.28.0-rc.2 → 1.28.0
Major: 2.0.0-beta.1 → 2.0.0-beta.2 → 2.0.0
rc action in the release workflow automatically selects the correct type based on the version.main ← stable, always deployable
│
├── hotfix/1.27.1 ← patch: cherry-pick fix from main, publish to latest
│
├── release/1.28.0 ← minor: accumulate fixes + enhancements, RC cycle
│ ├── v1.28.0-rc.1 ← tag: published to next
│ └── v1.28.0 ← tag: promoted to latest
│
├── release/2.0.0 ← major: features + breaking changes, beta cycle
│ ├── v2.0.0-beta.1 ← tag: published to next
│ ├── v2.0.0-beta.2 ← tag: published to next
│ └── v2.0.0 ← tag: promoted to latest
│
├── fix/1200-bug-description ← bug fix branch (merges to main)
├── feat/925-feature-name ← feature branch (merges to main)
└── chore/1206-maintenance ← maintenance branch (merges to main)
For fixes that need to ship without waiting for the next minor.
A hotfix vX.YY.Z cumulatively includes everything in vX.YY.{Z-1} plus every fix:/chore: commit landed on main since that base. The base tag is the anchor — git cherry $BASE_TAG main reveals exactly which commits are still unshipped, and the new vX.YY.Z tag becomes the next hotfix's base, so the cycle is self-documenting.
Path A — hotfix.yml (canonical, two-step):
hotfix.yml with action=create, version=1.27.1, auto_cherry_pick=true (default).
BASE_TAG = highest v1.27.* < v1.27.1 (so 1.27.1 branches from v1.27.0; 1.27.2 would branch from v1.27.1).hotfix/1.27.1 from BASE_TAG.fix:/chore: commit on origin/main not already in the base, oldest-first. Patch-equivalents are skipped via git cherry. feat:/refactor: are never auto-included.auto_cherry_pick=false.package.json (and sdk/package.json), pushes the branch, and lists every included SHA in the run summary.hotfix/1.27.1.hotfix.yml with action=finalize. The workflow:
install-smoke cross-platform gate.sdk-bundle/gsd-sdk.tgz inside the CC tarball (parity with release-sdk.yml).v1.27.1, publishes to @latest, re-points @next → v1.27.1.main.Path B — release-sdk.yml (stopgap, one-shot):
Active while the @gsd-build/sdk npm token is unavailable; bundles the SDK inside the CC tarball.
release-sdk.yml with action=hotfix, version=1.27.1, auto_cherry_pick=true.
prepare job creates the branch and cherry-picks (same logic as Path A).install-smoke runs against the new branch.release job tags, publishes to @latest, re-points @next, opens merge-back PR.hotfix/1.27.1 already exists (e.g. you ran hotfix.yml create first), the prepare job checks it out and re-runs cherry-pick as a no-op.dry_run=true exercises the full pipeline without pushing the branch or publishing.For accumulated fixes and enhancements.
release.yml with action create and version (e.g., 1.28.0)release/1.28.0 branch from main, bumps package.jsonrelease.yml with action rc to publish 1.28.0-rc.1 to nextnpx get-shit-done-cc@nextrc.2, rc.3, etc.release.yml with action finalize — publishes 1.28.0 to latestSame as minor but uses -beta.N instead of -rc.N, signaling a longer testing cycle.
release.yml with action create and version (e.g., 2.0.0)release.yml with action rc to publish 2.0.0-beta.1 to nextbeta.2, beta.3, etc.release.yml with action finalize -- publishes 2.0.0 to latestBranch names map to commit types:
| Branch prefix | Commit type | Version bump |
|---|---|---|
fix/ | fix: | PATCH |
feat/ | feat: | MINOR |
hotfix/ | fix: | PATCH (immediate) |
chore/ | chore: | none |
docs/ | docs: | none |
refactor/ | refactor: | none |
# Stable release (sets latest tag automatically)
npm publish
# Pre-release (must use --tag to avoid overwriting latest)
npm publish --tag next
# Verify what latest and next point to
npm dist-tag ls get-shit-done-cc