Skip to main content
Version: Next (unreleased)

Note on this document: this is the branching and release policy the jira-sdlc skills (in ../skills/) were written against — it's what "the default base branch," the feature//hotfix/ split, and the squash-merge-into-parent-then-manual-release logic all assume. It's already generic (no project names, no company specifics — reviewed before publishing this repo). If your process differs, adapt this document to match yours, then update <DEFAULT_BASE_BRANCH> in .jst/jira-sdlc-tools.env in the project root (see ../skills/_shared/project-config.md) and the branch-prefix rules in jira-task-assigner and jira-api-reference.md §12 to match.

Software Development Life Cycle (SDLC) & Branching Strategy

1. Overview and Purpose

This document defines the standard operating procedures for the Software Development Life Cycle (SDLC), Git branching strategy, and release management for this repository.

Audience: Human developers, DevOps engineers, and Autonomous AI/LLM coding assistants.

Core Philosophy:

  • Continuous Integration / Batched Deployment: We merge code continuously to staging but release to production in scheduled two-week sprint batches.
  • Decoupled Deployments: Deployment does not equal release. We rely heavily on Feature Flags to merge incomplete or untested features safely into production without exposing them to end-users.

2. Branch Architecture

Branch Name PatternProtected?SourceMerges ToPurpose
main✅ Yesrelease/*, hotfix/*developmentRepresents the current production state. Strictly tagged with Semantic Versioning (e.g., v1.2.3).
development✅ Yesmainrelease/*The default working branch. Represents Staging/Integration. Code here is continuously deployed to the staging environment.
feature/ISSUE-KEY-slug❌ NodevelopmentdevelopmentUsed for new features and non-critical bug fixes.
hotfix/ISSUE-KEY-slug❌ Nomainmain & developmentUsed only for critical production bugs that cannot wait for the next sprint release.
release/sprint-<X.Y.Z>❌ NodevelopmentmainTemporary branch created at the end of a sprint for QA hardening and final bug fixes before production release. Named after the intended release version (computed from latest v* tag + chosen bump level, default minor — see §5).

3. The 2-Week Sprint Lifecycle

Our development cycles run in 14-day sprints. The Git workflow strictly follows this cadence.

Phase 1: Active Development (Days 1 to 11)

  • Developers branch off development to create feature/* branches.
  • Pull Requests (PRs) are opened against development.
  • Once approved, PRs are merged immediately.
  • Rule: If a feature is incomplete, it MUST be wrapped in a Feature Flag before merging into development.

Phase 2: Feature Freeze & Release Cut (Day 12)

  • A new release branch is cut from development (e.g., release/sprint-0.3.0). The branch name embeds the intended SemVer version — cut-release.yml computes it from the latest v* tag + the chosen bump level (patch/minor/major, default minor per §5). The version lives in the branch name from this point on; release.yml reads it back out at merge time (§5), so the way to change a release's version is to rename or re-cut the branch, not to relabel a PR.
  • No new features are allowed into this release branch.
  • development remains open for developers to start merging features for the next sprint.

Phase 3: QA & Hardening (Days 12 to 14)

  • QA tests the release/* branch in the staging environment.
  • If bugs are found, developers branch directly off the release/* branch, fix the bug, and open a PR back into the release/* branch.

Phase 4: Production Deployment (Day 14)

  • The release/* branch is merged into main via a PR.
  • A snapshot of the documentation is cut for that version (docusaurus docs:version) and committed on main, so the tagged commit carries the docs as that release published them.
  • A Semantic Version Tag (e.g., v0.95.4) is applied to that commit on main.
  • The CI/CD pipeline deploys main to Production.
  • The documentation site is republished so the new version appears on it.
  • main is merged back into development to ensure all QA bug fixes are synced.
  • The release/* branch is deleted.

All of the above is automated by release.yml (see CI.md). The one exception is below.

Cutting the docs version by hand

release.yml runs from the version of itself that already exists on main, so the release that first introduces the docs-versioning step cannot run it — and the same applies to any release merged before that change reaches main. That release ships without a docs snapshot unless somebody cuts one. Do it from main immediately after the release, substituting the version that was just tagged (no leading v):

git checkout main
git pull origin main

cd website
npm ci
npm run docusaurus -- docs:version 0.95.4
npm run build # snapshot-only breakage fails HERE, not in review

cd ..
git add website/versioned_docs website/versioned_sidebars website/versions.json
git commit -m "docs: version snapshot v0.95.4"
git push origin main

Two things to know while doing it:

  • All three paths are committed. An ignored snapshot is a released version that silently is not on the site; website/.gitignore covers build products only.
  • That push will not republish the site on its own if it is made with a CI token — a GITHUB_TOKEN push creates no workflow runs. Pushing it yourself from a laptop does trigger docs.yml. If in doubt, dispatch it explicitly: gh workflow run "Docs site" --ref main.

4. Emergency Production Bug Flow (Hotfixes)

When a critical bug is discovered in production that cannot wait for the end of the 2-week sprint cycle, the Hotfix Flow is triggered. This process completely bypasses the development branch to ensure we do not accidentally deploy unreleased sprint features prematurely.


[main (v1.0.0)] ────► [hotfix/ISSUE-123] ────► [QA/Verification]
│ │
▼ ▼
[main (v1.0.1)] ◄─────────────────────────────────────┘ (Merge & Tag)


[development] (Sync back immediately)

Step 1: Isolate and Branch

  • Do NOT branch from development.
  • Pull the latest code from main and create a hotfix branch:
git checkout main
git pull origin main
git checkout -b hotfix/ISSUE-KEY-short-description

Step 2: Fix and Validate

  • Implement the fix locally.
  • Deploy the hotfix branch to an isolated staging/preview environment for immediate QA validation.

Step 3: Production Merge and Patch Tagging

  • Open a Pull Request targeting main.
  • Once approved, merge the PR into main.
  • Increment the PATCH version of your semantic tag (e.g., v1.2.4 becomes v1.2.5).
  • The CI/CD pipeline triggers an automatic immediate deployment to Production.

Step 4: Downstream Synchronization (Crucial)

  • To prevent the bug from being reintroduced during the next sprint release, main must be merged back into development immediately following the production deployment.
git checkout development
git pull origin development
git merge main
git push origin development


5. Versioning Strategy (SemVer)

We strictly adhere to Semantic Versioning (vMAJOR.MINOR.PATCH) on the main branch.

The version for each release is taken from the branch name — no PR label is read:

  • A release/sprint-<X.Y.Z> branch carries its SemVer version in the name (set at cut time by cut-release.yml). release.yml parses that version back out at merge time; a malformed name (anything other than release/sprint-<X.Y.Z>, including a leading v) fails the release. To ship a different version, rename or re-cut the branch.
  • A hotfix/* branch always takes a patch bump on the latest v* tag. A hotfix is by §4's definition an emergency fix for a critical production bug — that IS a patch; work needing a minor or major bump belongs in a release/* branch, where the version is explicit.

Commit-message conventions play no part in version resolution.

  • MAJOR (v2.0.0): Breaking changes, massive UI overhauls, or major architectural shifts.
  • MINOR (v1.5.0): New sprint releases containing backward-compatible features (the standard increment for Day 14 releases — the cut-release.yml default).
  • PATCH (v1.5.1): Emergency hotfix/* branches merged directly to main mid-sprint.

Note: Version tags must contain ONLY the semantic version number (e.g., v1.5.0), never sprint identifiers (e.g., v1.5.0-sprint24), to ensure compatibility with standard package managers and CI tools.


6. Feature Flags

Scope note: Feature flags are a project practice the jira-sdlc skills do not automate — they never create, wrap, or toggle a flag on their own (see §7 #3). The guidance below applies where a project adopts flags; adopting, wiring, or dropping them is a human/product decision.

To prevent merge conflicts and "branch rot", long-running feature branches are discouraged.

  • All code should ideally be merged into development within 3-4 days.
  • If a feature spans multiple sprints, it MUST be protected by a feature flag.
  • The feature is deployed to production silently. The product team toggles the flag to true when the feature is ready for public consumption.

7. 🤖 LLM System Directives

Instructions for AI coding assistants (Copilot, Cursor, Gemini, etc.) reading this document:

  1. Branch Naming: Work branched off development is always named feature/<ISSUE-KEY>-<kebab-case-description> (e.g. git checkout -b feature/PROJ-123-add-user-auth) — feature/ is the only branch type cut from development, and it covers all planned work, features and bug fixes alike. The one exception is an emergency hotfix/ off main (see #2); never create a hotfix/ branch from development.
  2. Target Branches: Always default PR creation scripts or git merge targets to development, unless explicitly told it is a production hotfix — those (and only those) branch from main, are named hotfix/<ISSUE-KEY>-<kebab-case-description>, and target main.
  3. Feature Flags: Do not add feature-flag wrapping on your own initiative. Whether incomplete work ships behind a flag (§6) is a deliberate human/product decision — wrap an entry point in a flag only when the issue or the user explicitly asks for it, and then follow the codebase's existing flag pattern rather than inventing one.
  4. Commit Messages & Versioning: SemVer bumps are driven by the branch name (release/sprint-<X.Y.Z> carries the version; hotfix/* is always a patch), not by PR labels or commit-message parsing — so Conventional Commits are not required. Prefix each commit with its Jira issue key (<ISSUE-KEY> <short imperative summary>, e.g. PROJ-123 add user auth) so history stays traceable to the issue; release.yml resolves the version from the head ref on the merge (see §5).