Automate the documented release-tag checklist (#48) without bypassing safety
gates.
scripts/release-tag:
- Requires a SemVer tag (vMAJOR.MINOR.PATCH); validates before any git/network.
- Fetch/prune first, then refuses: dirty worktree, non-master branch, local
master != remote master, HEAD not on remote master, and an existing local or
remote tag of the same name.
- Runs the full suite by default; --skip-tests is an explicit opt-out that warns.
- Creates an ANNOTATED tag (git tag -a), never lightweight.
- Safe by default: no push unless --push; --dry-run prints planned actions and
changes nothing. Supports --notes-file <path> for the annotation message.
- Prints: commit, tag, tests_run, tag_created, tag_pushed.
- Env injection points for testing/CI: RELEASE_TAG_REMOTE, RELEASE_TAG_TEST_CMD.
tests/test_release_tag.py (14 cases): valid SemVer dry-run; invalid version;
dirty worktree; non-master; master/remote mismatch; existing tag; missing
notes-file; annotated-not-lightweight; no-push-without-flag; push-only-with-flag;
notes-file message; --skip-tests warns; default runs tests (fail blocks tag,
pass tags). Each test builds a throwaway repo with a LOCAL bare remote (cloned,
not pushed) and stubs the test command — no network, no real tags, no pushing
from the project repo.
Docs: reference scripts/release-tag from the runbook, SKILL, and the release-tag
template (script preferred; manual steps are the fallback).
Full suite 305 passed / 0 failures; bash -n clean; git diff --check clean; no
secrets.
Closes#50. Refs #48.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Formalize the branch↔issue relationship and add a release/version-tagging policy.
Branch/issue linkage:
- scripts/worktree-start now validates branch names: implementation branches
must match (fix|feat|docs|chore)/issue-<number>-<slug>; review branches
review/pr-<number>-<slug>. Untraceable names are rejected with a clear error
(exit 2). New --allow-unlinked override for genuine exceptions. --dry-run
preserved.
- Documented issue → branch → worktree → PR → cleanup traceability in the
runbook and the portable SKILL, including the claim-comment convention and
Closes #n / Refs #n PR-body usage.
- Noted that Gitea exposes no native issue→branch API field (only a PR head
branch), so linkage is enforced via branch name + claim comment + PR body +
cleanup.
Versioning / tagging policy (docs only; no release automation yet):
- SemVer vMAJOR.MINOR.PATCH (v0.x.y while unstable) with PATCH/MINOR/MAJOR bump
rules.
- Annotated tags only, from the exact commit on remote master, only after the
full suite passes, with release notes referencing merged PRs/issues. Never tag
feature branches, dirty worktrees, unreviewed/self-authored work, or commits
not on remote master.
- Release runbook in the runbook + SKILL, plus a new
skills/llm-project-workflow/templates/release-tag.md prompt template.
Tests: worktree-start branch validation — accepts fix/feat/docs/chore/issue-*
and review/pr-*, rejects fix/random-name / my-branch / non-numeric issue,
honors --allow-unlinked, preserves --dry-run. Full suite 291 passed / 0 failures;
bash -n clean; git diff --check clean; no secrets.
Release-tag automation (a scripts/release-tag helper) intentionally deferred to a
later issue to keep this diff narrow and testable.
Closes#48. Refs #38, #39, #46.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Finishes the isolated-worktree standard begun in #38 (which merged the
branches/ gitignore, runbook, and scripts/worktree-start). Adds the two
remaining helpers and their tests.
- scripts/worktree-review: isolated DETACHED review worktree under
branches/review-<branch> (fetch/prune first, refuse to overwrite, print path,
--dry-run). Detached so a reviewer cannot accidentally commit and review work
never blocks the author's implementation folder.
- scripts/worktree-clean: the only deleting helper — removes a branches/
worktree after merge/close, refuses a dirty worktree (no --force), optionally
safe-deletes a merged branch (git branch -d), fetch/prune first, --dry-run.
Deletes nothing unless explicitly invoked.
- tests/test_worktrees.py: path generation + refuse-to-overwrite for all three
helpers via --dry-run (no real worktrees/branches/network/deletions).
- runbook: reference worktree-review / worktree-clean and the --dry-run flag.
Checks: bash -n clean on all three scripts; git diff --check clean; full suite
286 passed, 0 failures.
Closes#39. Follow-up to #38.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>