docs(git-commit): document the release tagging step (T-393)
The "Cutting a release" ritual moved the changelog and bumped pubspec but never mentioned tagging — which is how tags silently lapsed from v2.2.0 through v2.8.0. Add step 6: run `make release` (verify + gate + annotated tag), then push with --follow-tags, and state the rule that every released version must have a matching git tag. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -99,6 +99,7 @@ Cutting a release is its own commit. In a single commit:
|
||||
3. Bump `pubspec.yaml` `version:` to `X.Y.Z` (drop the `-dev` suffix for the tag; re-add it on the next development commit if desired).
|
||||
4. Run `make gen-build-info` so `assets/licenses.yaml` `self.version:` re-syncs from pubspec (it's auto-rewritten by every build but commit the fresh state). Stage the resulting diff alongside step 3.
|
||||
5. Commit subject: `release vX.Y.Z`.
|
||||
6. **Tag it.** After the commit lands, run `make release` — it verifies the version/changelog/clean-tree invariants, runs the full gate, and creates the annotated `vX.Y.Z` tag. Then `git push origin main --follow-tags` to publish the commit and the tag together. **Every released version must have a matching `git tag`** — a CHANGELOG heading without a tag is an incomplete release (T-393: tagging had silently lapsed from v2.2.0 through v2.8.0). Don't hand-roll the tag; `make release` keeps the tag, gate, and version in lockstep. If you tag by hand, use an annotated tag (`git tag -a vX.Y.Z -m "clide vX.Y.Z"`); never push a release commit without its tag.
|
||||
|
||||
`pubspec.yaml` is the single source of truth for the version. Every `make` build/run/test target regenerates `lib/src/build_info.g.dart` (gitignored) and rewrites `assets/licenses.yaml` `self.version:` from it — so the Flutter app sees the current version everywhere without manual sync. Bumping `pubspec.yaml` and the changelog out of sync is the mistake this rule prevents.
|
||||
|
||||
|
||||
@@ -5955,3 +5955,4 @@ INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, chang
|
||||
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBHC46SEHH8NQY481VMGK66R', 'status', 'backlog', 'in_progress', NULL, '2026-06-23 19:50:10', '2026-06-23 19:50:10.066', '2026-06-23 19:50:10.066', NULL, 'a03e02614d5e3c2c7ffc795d84487a9e', 2) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBHC46SEHH8NQY481VMGK66R', 'status', 'in_progress', 'done', NULL, '2026-06-24 13:28:43', '2026-06-24 13:28:43.038', '2026-06-24 13:28:43.038', NULL, '53c03d3229add40fdbcb41eed62cb42b', 2) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FFKFYBZFKBX0WV574QJEH2BC', 'status', 'backlog', 'done', NULL, '2026-06-24 13:28:43', '2026-06-24 13:28:43.041', '2026-06-24 13:28:43.041', NULL, '016e6d0c845e076bb60fe3cb0c34b4c9', 2) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBHDE5A3965GNRFS5WPZW878', 'status', 'in_progress', 'done', NULL, '2026-06-24 21:26:58', '2026-06-24 21:26:58.043', '2026-06-24 21:26:58.043', NULL, '8781bb622159f6670c45ae3685b0e496', 2) ON CONFLICT(hash) DO NOTHING;
|
||||
|
||||
@@ -7478,3 +7478,12 @@ Fix (pattern: hand-enumerated lists drift; export the truth): make lib/ export o
|
||||
|
||||
Acceptance: gates fail if a newly added theme/namespace is not covered; catppuccin contrast-checked; all 8 i18n namespaces checked; testmode harness consumes the same exported theme list.', 'done', 'high', NULL, NULL, NULL, '2026-06-11 21:57:17', '2026-06-24 13:28:43.038', NULL, '034c9261ad30a2da8b2e2144aa0a763a', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FFKFYBZFKBX0WV574QJEH2BC', 'story', '06FB0TNQM5TWC00GW0P3X02HZW', 'Ship Summer Night theme + high-contrast sibling', NULL, 'done', 'medium', NULL, NULL, NULL, '2026-06-24 13:09:16.923', '2026-06-24 13:28:43.041', NULL, '74542be3691f98a24e00961136927873', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBHDE5A3965GNRFS5WPZW878', 'story', '06FBHBGHNEQTAEPGNJKN42C1E8', 'Close the release loop: back-tag 2.2.0–2.3.3, fix ci/release.sh, add tagging to the release ritual, widen the fast-path regex', 'No git tag since v2.1.0 despite five CHANGELOG releases; ci/release.sh exits 64 and still references the dissolved sidecar; the pre-push fast path''s safety argument cites "release CI on tagged versions" that does not exist; and the fast-path regex skips ALL tests for pushes touching test/, ci/, or the hook itself.
|
||||
|
||||
Work items (separable commits):
|
||||
1. Back-tag v2.2.0 through v2.3.3 at the release-cut commits (find them via the CHANGELOG version-bump commits).
|
||||
2. Rewrite ci/release.sh for the single-process architecture or delete it and fold release steps into the Makefile — either way, no stub that exits 64.
|
||||
3. Add tagging to the release ritual in .claude/skills/git-commit/SKILL.md (version bump + changelog move + tag in one documented step).
|
||||
4. Widen the pre-push fast-path regex so changes under test/, ci/, and the hook itself run the full gate.
|
||||
|
||||
This is also the blocking prerequisite the T-47 (self-update) refinement identified. Acceptance: git tag lists every released version; release.sh (or its replacement) runs end-to-end; fast-path regex covered by a hook test if feasible.', 'done', 'high', NULL, NULL, NULL, '2026-06-11 22:03:00', '2026-06-24 21:26:58.043', NULL, 'f1cce1ec70abb6f1408e317c358d3342', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
|
||||
Reference in New Issue
Block a user