# CTMS Git Branch Governance ## 1. Purpose This document defines the long-term Git branch governance model for the CTMS repository. The goals are: - keep daily development efficient on `dev` - keep `main` readable as the next major version baseline - keep `release` stable and suitable for production maintenance - make release, hotfix, and back-merge behavior explicit This document is the default branch management policy unless a later written rule supersedes it. ## 2. Branch Roles ### `dev` `dev` is the daily development and integration branch. Use cases: - feature development - exploratory changes - internal integration and verification - non-release refactors Characteristics: - accepts frequent commits - may contain incomplete but merge-approved work - history can be relatively dense ### `main` `main` is the candidate primary version branch. Use cases: - preparing the next formal release - staging a version for full regression, acceptance, or external integration - holding a clean version-level history of what is intended to go to production next Characteristics: - must remain deployable in principle - should only receive changes that are judged release-candidate quality - should be cleaner than `dev` in both content and history ### `release` `release` is the long-lived production stability branch. Use cases: - current production version - urgent production hotfixes - maintenance of already released code Characteristics: - strongest stability requirement - no routine feature development - every production release should be identifiable by tag ## 3. Promotion Path The default code promotion path is: `feature/*` -> `dev` -> `main` -> `release` Meaning: - daily work enters `dev` - stable milestone scope is promoted from `dev` to `main` - approved release scope is promoted from `main` to `release` Direct promotion that skips stages is discouraged and must be justified in writing. ## 3.1 Unified Web and Desktop Mainline CTMS Web and Desktop are two delivery targets of the same product version. They share the Vue application, API contract, and product branches. Rules: - Do not create long-lived `web-dev`, `desktop-dev`, `web-release`, or `desktop-release` branches. - Web and Desktop changes both follow `feature/*` -> `dev` -> `main` -> `release`. - A platform-specific feature or agent task branch is allowed while work is in progress, for example `feature/desktop-file-picker` or `codex/desktop-menu-polish`, but it must merge back into `dev`. - `codex/ctms-desktop` was the temporary desktop integration branch for the Tauri baseline. It is no longer a current desktop mainline. Do not commit, rebase, or push new desktop work to it unless explicitly cleaning up the historical branch after its accepted changes are present on `dev`. - Platform differences belong behind `frontend/src/runtime/`. Shared business modules must not import Tauri APIs directly. - A release tag identifies one product source state. Web and Desktop artifacts for that release must be built from the same tag and Git commit. ## 4. Branch Entry Rules ### Changes allowed into `dev` Allowed: - feature branches - refactors - test improvements - integration work - exploratory work that has passed review Requirements: - code review completed - no known blocking regression introduced intentionally without team alignment - relevant tests pass at the feature or module level ### Changes allowed into `main` Allowed: - version-ready content promoted from `dev` - tightly scoped fixes required to stabilize the next version Requirements: - scope is explicitly selected for the next release candidate - regression testing has been run for the affected area - release-risking incomplete work must be excluded - merge should represent a coherent version increment, not random unfinished work ### Changes allowed into `release` Allowed: - approved production releases from `main` - hotfixes for production incidents Requirements: - release checklist completed - production-facing validation completed - change is either a formal release or a critical maintenance fix Routine feature work must not be merged directly into `release`. ## 5. Merge Strategy ### `feature/*` -> `dev` Preferred strategy: - pull request merge or rebase merge Rules: - branch should be reasonably scoped - commit history can be preserved - reviewer may require cleanup for obviously noisy commits ### `dev` -> `main` Preferred strategy: - squash merge Rationale: - preserve detailed development history on `dev` - keep `main` at a version or milestone granularity - avoid making `main` a duplicate of `dev` commit-for-commit Rules: - each merge to `main` should correspond to a named milestone, candidate, or release scope - squash commit message should describe the version or milestone clearly Recommended commit format: - `release(main): prepare v1.2.0 candidate` - `release(main): integrate Q2 CTMS milestone` ### `main` -> `release` Preferred strategy: - normal merge commit Rationale: - preserve the relationship between the released state and the accepted candidate branch - make production promotion traceable Rules: - merge only after acceptance and release checks - create a version tag immediately after the release merge ### `hotfix/*` -> `release` Preferred strategy: - normal merge commit Rules: - branch must be narrowly scoped to the production issue - branch name should identify the production problem clearly Examples: - `hotfix/login-timeout-loop` - `hotfix/admin-init-guard` ## 6. Tag Rules Every formal production release on `release` must be tagged. Recommended format: - `v1.0.0` - `v1.1.0` - `v1.1.1` Tag semantics: - major: incompatible or structurally significant release - minor: backward-compatible feature release - patch: backward-compatible hotfix release Rules: - tags are created on `release`, not on `dev` - a tag must point to the exact production release commit - patch hotfixes on `release` should increment the patch version - Web and Desktop use the same semantic version. Do not add a separate Desktop product version. - Desktop packaging-only rebuilds may add build metadata to the artifact name, but must retain the product version and record the source commit. - Before creating a tag, run `cd frontend && npm run version:check`. - Change the shared client version with `cd frontend && npm run version:set -- `. ## 7. Hotfix Back-Merge Rules Every hotfix merged into `release` must be merged back into both `main` and `dev`. Required follow-up path: `hotfix/*` -> `release` -> `main` -> `dev` Rules: - do not assume the fix already exists elsewhere - perform the back-merge as soon as the production fix is verified - if conflicts occur, resolve them immediately and document the resolution in the pull request or release record This rule prevents production fixes from being lost in later development cycles. ## 8. Branch Protection Recommendations ### Protect `release` Recommended controls: - no direct push - pull request required - at least one reviewer required - status checks required - tag creation restricted to release maintainers if platform settings allow ### Protect `main` Recommended controls: - no direct push - pull request required - at least one reviewer required - regression or build checks required before merge ### Manage `dev` Recommended controls: - direct push discouraged - pull request preferred - team may allow limited direct push for maintainers during active integration windows If direct push is temporarily allowed on `dev`, it should remain an exception rather than the default workflow. ## 9. Release Readiness Criteria Before promoting `dev` to `main`, confirm: - selected feature scope is complete - known blockers are resolved or explicitly deferred - affected tests pass - acceptance scope is defined Before promoting `main` to `release`, confirm: - release checklist is complete - production initialization, build, and smoke verification are complete - Desktop updater signatures are present and verified - platform signing is either complete or the exact version has an approved, checked-in exception in `frontend/desktop-release-policy.json`; the current v0.1.0 exception requires macOS ad-hoc signing, unsigned Windows artifacts, controlled distribution, and explicit trust warnings - rollback or remediation path is clear - release tag has been prepared Platform signing remains the default for versions without an exact approved exception. An exception never permits disabling Tauri updater signatures or building Web, macOS, and Windows from different tags or commits. For v0.1.0 only, the release owner also approved a staged contingency while hosted Actions capacity is unavailable: macOS may be built on a controlled local macOS host from the immutable final `v0.1.0` tag and published first. Windows remains pending and must later be built from that same tag and SHA. The macOS-only release must carry checksums, provenance, updater signature, platform-trust warnings, and an explicit Windows-pending notice. It must not publish or replace production `latest.json`; updater feed activation waits for combined macOS and Windows verification. Reference: - [docs/guides/release-checklist.md](guides/release-checklist.md) ## 10. Standard Workflow Examples ### New feature 1. create `feature/` from `dev` 2. develop and review against `dev` 3. merge into `dev` 4. when milestone scope is stable, squash merge selected scope from `dev` to `main` 5. run candidate validation on `main` 6. merge `main` into `release` 7. create production tag on `release` ### Production hotfix 1. create `hotfix/` from `release` 2. fix and validate only the production issue 3. merge into `release` 4. tag patch version on `release` 5. back-merge the same fix into `main` 6. back-merge the same fix into `dev` ## 11. Current Repository Mapping For the current CTMS repository, the intended meaning is: - `dev`: ongoing development branch - `main`: next candidate major version branch - `release`: long-lived stable production branch Current local workspace layout: - primary repository: `/Users/zcc/MyCTMS/ctms-dev` on `dev` - `main` worktree: `/Users/zcc/MyCTMS/ctms-dev/.worktrees/main` - `release` worktree: `/Users/zcc/MyCTMS/ctms-dev/.worktrees/release` Current remote default branch: - `origin/HEAD` points to `origin/main` If `dev` and `main` temporarily point to the same commit, that is acceptable as a transition state. The governance target is not to keep them permanently identical. The target is: - `dev` keeps detailed development history - `main` keeps milestone-level release-candidate history - `release` keeps production-approved history with tags ## 12. Non-Goals This policy does not require: - rewriting branch history to a single commit - forcing `main` to always differ from `dev` - maintaining a separate release branch per version unless future scale requires it The policy prioritizes traceability, stable promotion, and predictable maintenance over artificially minimal history.