gabriel / muse public
feat patch feat/57-release-tag-crosslink #1 / 1
AI Agent gabriel · 7 hours ago · Oct 21, 2026 · Diff

feat: cross-link muse release add --tag and muse tag add --release (muse#57 item 2)

`muse release add <tag>` and `muse tag add <tag>` have always been two independent systems pointed at the same tag string -- creating one never touched the other, matching the ticket's background: "muse release add v1.0.0 currently creates a MuseHub release record independently of muse tag."

`muse release add v1.0.0 --tag`: after creating the release, also writes a local VersionTagRecord at the same commit (same semver, author from the commit, message from --title) if a version tag with that name doesn't already exist locally. If one already exists at a DIFFERENT commit, warns on stderr with the exact repoint command rather than silently overwriting it -- same non-clobbering stance as this codebase's merge-conflict conventions.

`muse tag add v1.0.0 --release`: after creating the version tag, also builds a changelog since the last non-draft release (reusing build_changelog -- the exact logic `release add` itself uses) and writes a local draft ReleaseRecord (is_draft=True) at the same commit, if a release for that tag doesn't already exist. Composes independently with --sign (both flags can be passed together).

Both directions add a boolean field to their JSON envelope (tag_created / release_created) so scripts/agents can tell whether the cross-link actually fired or the target already existed.

New tests/test_release_tag_crosslink.py (8): --tag creates a version tag and is idempotent against an existing one at the same commit, omitting --tag creates nothing, an existing version tag at a DIFFERENT commit is warned about and left untouched; --release creates a draft release, omitting --release creates nothing, an existing release is not duplicated, and --sign + --release compose correctly together. Confirmed genuine RED (7/8 failed -- unknown flags, missing tag_created/release_created keys) before GREEN with the fix restored.

Targeted regression suite -- the new file plus test_cmd_version_tags.py, test_cmd_tag_sign.py, test_release.py, test_cmd_release_hardening.py -- all pass (311 passed), zero regressions.

Co-Authored-By: Claude Sonnet 5 <[email protected]>

sha256:2837c666bf81eea8e28651b4303b6638407601d46ca28955a7158464e08b4c5e sha
+26 ~9 symbols
4 changed · 1221 in snapshot files
sha256:717509a9f4fdf0867f23229bfcfe9a00bd055e6ef0a352b370925525600c4c54 snapshot
+26
symbols added
~9
symbols modified
4
files changed
1221
files in snapshot
0
dead code introduced
Semantic Changes 35 symbols
~ tests/test_release_tag_crosslink.py .py 26 symbols added
+ TestReleaseAddTagFlag class class TestReleaseAddTagFlag L70–133
+ test_existing_version_tag_at_different_commit_warns_not_overwritten method method test_existing_version_tag_at_different_commit_warns_not_overwritten L110–133
+ test_existing_version_tag_at_same_commit_not_duplicated method method test_existing_version_tag_at_same_commit_not_duplicated L97–108
+ test_tag_flag_creates_local_version_tag method method test_tag_flag_creates_local_version_tag L71–83
+ test_without_tag_flag_no_version_tag_created method method test_without_tag_flag_no_version_tag_created L85–95
+ TestTagAddReleaseFlag class class TestTagAddReleaseFlag L136–184
+ test_combined_sign_and_release_flags method method test_combined_sign_and_release_flags L175–184
+ test_existing_release_not_duplicated method method test_existing_release_not_duplicated L164–173
+ test_release_flag_creates_draft_release method method test_release_flag_creates_draft_release L137–150
+ test_without_release_flag_no_release_created method method test_without_release_flag_no_release_created L152–162
+ _env function function _env L20–21
+ _init_repo function function _init_repo L28–41
+ _make_commit function function _make_commit L44–67
+ _run function function _run L24–25
+ cli variable variable cli L16–16
+ CliRunner import import CliRunner L11–11
+ Manifest import import Manifest L13–13
+ annotations import import annotations L4–4
+ datetime import import datetime L6–6
+ fake_id import import fake_id L13–13
+ json import import json L7–7
+ muse_dir import import muse_dir L14–14
+ pathlib import import pathlib L8–8
+ pytest import import pytest L10–10
+ ref_path import import ref_path L14–14
+ runner variable variable runner L17–17
~ muse/cli/commands/tag.py .py 3 symbols modified
Files Changed
+1 ~3
1221 in snapshot
← Older Oldest on feat/57-release-tag-crosslink
All commits
Newer → Latest on feat/57-release-tag-crosslink

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:2837c666bf81eea8e28651b4303b6638407601d46ca28955a7158464e08b4c5e --body "your comment"