mcpField
S
swain-release

swain-release

github.com/cristoslc開発2126 回インストール26 週間前に更新
リポジトリ

swain-release について

swain-releaseは、ソフトウェアリポジトリ向けのリリース支援スキルです。既存の規約から計画を提案し、変更履歴やバージョンの更新、安全チェック、タグ作成を案内します。

主な機能

  1. 01リポジトリからリリース規約を検出
  2. 02コミットに基づくバージョン更新の提案
  3. 03分類した変更履歴の作成
  4. 04バージョンファイルの更新とタグ作成
  5. 05タグ作成前のセキュリティチェック

活用シーン

  1. 01既存のGitタグに沿ったリリース準備
  2. 02バージョンと変更履歴の案の確認
  3. 03タグ作成前のプロジェクトバージョン更新

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/cristoslc/swain --skill swain-release

インストール後、Claude Code で/swain-releaseを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

.gitkeep
changelog-contract.yaml
scripts/
render_changelog.py
templates/
changelog.md.j2
tests/
test_render_changelog.py

詳細

リリース

状態を変更する操作を行う前に、アクティブなセッションがあるか確認してください:

REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
bash "$REPO_ROOT/.agents/bin/swain-session-check.sh" 2>/dev/null

JSON 出力の "status" が "active" 以外の場合は、オペレーターに「アクティブなセッションがありません。/swain-init で開始しますか?」と伝えてください。オペレーターが却下した場合は続行します。

プロジェクトのバージョン管理の状況を検出し、変更履歴を生成して、バージョンを更新し、タグを付けてリリースを作成します。前提をハードコードせず、git の履歴とプロジェクト構成から状況を読み取るため、あらゆるリポジトリで動作します。

オーバーライドファイル

開始する前に、.agents/release.override.skill.md が存在する場合は読み込んでください。これはプロジェクトオーナーが作成した自由形式の Markdown ファイルで、このスキルの指示に追加されます。内容が競合する場合は、こちらが優先されます。既定値の適用範囲を絞る、バージョンファイルの場所を指定する、タグの形式を定める、リリース前後の手順を追加するなど、自由に指定できます。

オーバーライドがない場合は、状況の検出のみを行ってください。

ワークフロー

1. 状況を確認する

既存の情報から、プロジェクトのリリース規約を推測します。ユーザーに何か提案する前に、これらの確認をすべて済ませてください。

タグの履歴:

git tag --sort=-v:refname | head -20

既存のタグから、次の項目を推測します:

  • タグの形式 — v1.2.3、1.2.3、name-v1.2.3 など
  • バージョン管理方式 — セマンティックバージョニング、カレンダーバージョニング、またはカスタム方式
  • 現在のバージョン — 検出したパターンに一致する最新のタグ

タグが一つもない場合は、初回リリースであることを伝え、希望する形式をユーザーに尋ねてください。

直近のリリース以降のコミット:

git log <last-tag>..HEAD --oneline --no-decorate

タグがない場合は、すべてのコミットを対象にします(または妥当な範囲を指定します。数百件ある場合はユーザーに確認してください)。

バージョンファイル — バージョン番号が記載されていることの多いファイルを検索します:

# Look for common version carriers
grep -rl 'version' --include='*.json' --include='*.toml' --include='*.yaml' --include='*.yml' -l . 2>/dev/null | head -20

VERSION ファイル、SKILL.md のフロントマターにある version:、package.json、pyproject.toml、Cargo.toml などの version フィールドも確認してください。まだ何も変更せず、存在するファイルを一覧にするだけにしてください。

2. 更新幅を決める

直近のタグ以降のコミットを Conventional Commits のプレフィックスに基づいて解析し、推奨する更新幅を決めます:

コミットのプレフィックス推奨内容
featマイナーバージョン更新
fixパッチバージョン更新
docs、chore、refactor、test、ciパッチバージョン更新
本文に BREAKING CHANGE がある、またはタイプの後に ! があるメジャーバージョン更新

最も大きい更新幅の根拠を採用します(破壊的変更が一つでもあればメジャー、feat が一つでもあれば少なくともマイナー、それ以外はパッチ)。

コミットが Conventional Commits 形式に従っていない場合は、一覧を提示し、適切な更新幅をユーザーに尋ねてください。

3. リリースを提案する

実行する前に、リリース計画をユーザーに提示してください。次の項目を含めます:

  • 現在のバージョン(最新のタグに基づく、または「初回リリース」)
  • 提案するバージョン(検出した更新幅を適用)
  • 変更履歴のプレビュー(テーマに沿った文章。手順 4 を参照)
  • 更新するファイル(手順 1 で見つかったバージョンファイルがあれば記載)
  • 作成するタグ(検出した形式を使用)

ユーザーが確認、バージョンの調整、または中止を選ぶまで待ってください。ユーザーが提案とは異なるバージョンを希望する場合は、そのバージョンを使用してください。提案はあくまで出発点であり、必須ではありません。

4. 変更履歴を生成する

書き写すのではなく、要約してまとめます。 変更履歴は、git log --oneline にひと手間加えたものではなく、リリースノートを読む人のためのものです。数十件のコミットも、まとまりのある数件の説明にまとめてください。

書き始める前に、既存の CHANGELOG.md(存在する場合)を読み、プロジェクトで使われている文体、情報密度、構成に合わせてください。各項目が同じ人によって書かれたような変更履歴にしてください。

テンプレートに基づく変更履歴

変更履歴は、JSON データファイルを入力とする Jinja2 テンプレート(templates/changelog.md.j2)から生成されます。これにより、変更をどのセクションに分類するかという判断と、Markdown をどのように表示するかという処理を分離できます。

ステップ 4a — コミットを5つの分類に振り分けます。 各コミットは必ず一つだけに分類します。

分類ここに含めるものここに含めないもの
features現在、オペレーターが操作できるようリリースされた機能:新しいスキル、新しい CLI コマンド、オペレーターが実行する新しいスクリプト、オペレーター向けワークフローのバグ修正。判断基準は、「これによってオペレーターが新しいことや、これまでと違うことをできるようになるか?」です。成果物は Complete である必要があります(または、追跡用の成果物なしで作業がデプロイされている必要があります)。計画に関する成果物、内部品質の改善、内部ツールのしきい値調整、内部テストスイート、オペレーターが直接実行しないスクリプトのバグ修正、Active のままの未完了作業。
in_progress一部がリリースされた作業。コードは trunk にあり、オペレーターはその一部を利用できますが、追跡用の成果物はまだ Active(Complete ではない)です。「Y に Z がまだ必要なため、X が初期段階の形で利用可能になりました」のように記述します。不足がある場合は正直に伝えます。完全にリリースされた作業(これは features です)。trunk にコードがなく、計画のみの作業(これは roadmap です)。
roadmap今後の作業に関するプレビュー。計画中の内容と、それがユーザーにとって重要な理由を記載します。「SPEC-NNN が作成されました」ではなく、「Y のため、X を計画・設計しています」のように記述します。読者が検索する必要がない限り、成果物 ID は省略します。内部の事務処理だけに関する項目は省略します。成果物の状態遷移(「EPIC を有効化」「SPEC を作成」)、リリース済みのもの(これは features です)、trunk にコードがあるもの(これは in_progress です)。
researchTrove コレクション、スパイクの完了、調査成果物、収集したエビデンス。調査から生まれた仕様(これは roadmap または in_progress です)。
supporting内部品質の改善、内部テストスイート、内部ツールのしきい値変更、内部スクリプトのバグ修正、依存関係の更新、相互参照の拡充、小規模なリファクタリング、CI の変更。オペレーターが直接操作するもの(これは features です)。

エージェントが間違えやすい重要な区別:SPEC または EPIC の作成は roadmap の変更であり、機能ではありません。 機能とは、このリリースで提供され、オペレーターが今日利用できるものです。SPEC は、将来リリースされるものの計画です。

エージェントが間違えやすい2つ目の区別:Active の成果物に対応するコードが trunk にある場合、それは機能ではなく進行中の作業です。 追跡対象の仕様のフェーズが Active であれば、その作業は一部しか利用できません。in_progress 分類を使ってください。成果物が Complete になった場合(または成果物がなく、作業がデプロイされて利用可能な場合)にのみ、features に移します。

エージェントが間違えやすい3つ目の区別:内部の改善は features ではなく supporting です。 内部しきい値の引き上げ、内部スクリプトのアンチパターンの修正、swain 自体のコードのテストスイート追加は、品質を向上させますが、オペレーターに新しい機能を提供するものではありません。「オペレーターは日々のワークフローでこの変更に気づくか?」と考えてください。答えが「以前に何かが壊れていた場合に限る」なら、supporting です。

Roadmap のアンチパターン:「子 SPEC 3件(SPEC-118、SPEC-119、SPEC-120)を伴う EPIC-029 が有効化されました」はノイズです。プロジェクトのメンテナーにしか関係のない成果物の状態遷移を説明しているからです。代わりに、「swain が設定なしで任意のブランチ名を使えるよう、trunk の検出方法を汎用化しています」と記述してください。読者には、内部の追跡用成果物の状態ではなく、何が実現する予定で、それを気にする理由は何かが伝わるようにします。

Supporting のアンチパターン — supporting に含めないもの:

  • 開発プロセスの変更(「close handler の順序を変更」「session-state の許容範囲を拡大」など)。これらは実装の詳細であり、完全に省略します。
  • 成果物の状態遷移(「EPIC-053 が承認され有効化」「SPEC-220 を作成」など)。これらはリリース済みの作業ではなく計画活動を説明するものなので、省略するか roadmap に含めます。
  • リリース期間より前から存在する未追跡ファイル。差分で変更されたファイルのみを含めます。
  • オペレーター向けワークフローのバグ修正。これらは supporting ではなく features です。 **Supporting に含めるもの:**依存関係の更新、CI/設定の変更、内部リファクタリング、使用されていないコードの削除、可読性の改善、内部テストスイート、内部ツールのしきい値変更、内部スクリプト(オペレーターが直接実行しないスクリプト)のバグ修正。

機械的なコミットはすべて省略します。マージコミット、ライフサイクルのハッシュスタンプ、インデックスの更新、ブックマークの前進が該当します。

**分類先は相互排他的です。**features に含まれるものは、in_progress、roadmap、supporting には含めません。in_progress に含まれるものは、features や roadmap には含めません。roadmap に含まれるものは、supporting には含めません。各コミットは、必ず1つの分類先に含めるか、省略します。

ステップ4b — 変更履歴の Markdown を直接作成します。templates/changelog.md.j2 のテンプレートは、レンダリング対象ではなく構成のガイドとして使用します。次の形式に従って、Markdown を自分で作成します。

## [0.10.0-alpha] - 2026-03-21

### Features

#### CLI Roadmap Renderer

chart.sh roadmap --cli produces deterministic, terminal-friendly
output grouped by Eisenhower quadrant with all first-degree children
nested under their parent initiative. New swain-roadmap skill wraps
it as the user-facing entry point: regenerate, open, display.

### In Progress

- CHORE artifact type — ADR-045 and script support are in
  trunk, but skill docs and Python tooling (SPEC-312/313) are still
  Active.

### Planned

- Session facilitation rebuild — rethinking how swain helps the operator maintain focus, make decisions, and recover context across sessions.

### Research

- Google Stitch SDK trove — 7 sources collected.

### Supporting Changes

- Dependency graph rendering switched to flowchart TD for clearer layout.
- Cross-reference enrichment across ~100 doc files.

書式ルール:

  • Features セクションは見出しのみを使用します。各機能には、説明文を添えた #### 見出し を付けます。Features には、単独の箇条書きを置きません。変更が小さすぎて独自の見出しを設けられない場合は、関連する見出しの説明文に含めるか、Supporting に移します。
  • In Progress では、見出しと箇条書きを組み合わせてもかまいません。部分的な状態や残りの作業を最もよく伝えられる形式を使用します。
  • Planned セクションと Roadmap セクションでは、見出しと箇条書きを組み合わせてもかまいません。十分な内容があり、段落で説明する主要な予定作業には見出しを、1行で説明できる項目には箇条書きを使います。
  • Research セクションと Supporting セクションは、常にフラットな箇条書きにします。
  • 空のセクションは省略します。
省略するもの

マージコミット、ライフサイクルのハッシュスタンプ、インデックスの更新、ブックマークの前進など、その他の機械的なコミットは、情報を加えずノイズになるため、すべて省略します。変更履歴に記載するテキストから、コミット種別の接頭辞(feat:、fix:)を取り除きます。

バージョン更新の判定にはコミット接頭辞を使い、変更履歴の構成には使わない

Conventional Commit の種別は、メジャー/マイナー/パッチのいずれを更新するかの判定に使います(ステップ2)。判定後は接頭辞を意識する必要はありません。変更履歴の読者にとって、変更が feat か docs かは重要ではありません。

変更履歴の配置先:

  • CHANGELOG.md が存在する場合は、先頭(ヘッダーがある場合はその下)に新しいセクションを追加します。
  • 変更履歴が存在しない場合は、新しく作成するか、作成する場合はどこに配置するかをユーザーに尋ねます。
  • ファイルを作成しない場合は、会話に出力します。
5. バージョンを更新する

ステップ1で特定したファイル内のバージョン文字列を更新します。周囲の内容には触れず、バージョン値だけを変更してください。ファイル形式ごとの対応は次のとおりです。

  • package.json / composer.json:"version" フィールドを更新します
  • pyproject.toml / Cargo.toml:version = "..." を更新します
  • SKILL.md frontmatter:YAML ヘッダーの version: を更新します
  • VERSION ファイル:内容を置き換えます

ファイル内にバージョンらしき文字列が複数あり、どれを更新すべきか判断できない場合は、推測せずユーザーに尋ねます。

5.5. セキュリティゲート

タグ付けの前に、セキュリティスキャナーを実行し、シークレット、依存関係の脆弱性、静的解析の問題を検出します。swain-security-check スキルを呼び出します(スキルが利用できない場合は、スキャナースクリプトを直接実行します)。

REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
SCANNER="$REPO_ROOT/.agents/bin/security-scan.sh"
if [[ -n "$SCANNER" ]]; then
  bash "$SCANNER"
fi

重大または高の重大度の検出結果が報告された場合は、リリースを中止し、ユーザーに提示します。ユーザーは次のいずれかを選択できます。

  • 問題を修正して再開する
  • 検出結果を認識したうえで、そのまま進める(判断はユーザーに委ねます)

中程度以下の検出結果は報告しますが、リリースはブロックしません。

セキュリティスキャナーがインストールされていない場合は、その不足を伝えて作業を続けます。ツールがないことを理由にブロックしてはいけません。

5.7. README ゲート(SPEC-211)

README の整合性と、README に記載された内容を保証するテストカバレッジを検証する、2段階の必須ゲートです。タグ付けの前に、両方を通過するか、明示的に例外扱いにする必要があります。

**スキップ条件:**README.md が存在しない場合は、このゲートをスキップします。README がないことは、すでに swain-doctor が警告しています。作成されていないファイルを理由にリリースをブロックしてはいけません。

Part 1: 整合性チェック

README.md を読み、プロジェクトが何をするのか、誰を対象としているのか、どのように動作するのか、何をサポートするのかについての主張をすべて抽出します。現在の Active アーティファクトツリー(Visions、Designs、Journeys、Specs)と照合します。

不一致をすべて明らかにします。

  • 古くなった約束 — README が、アーティファクトで明示的に取り下げられた、または置き換えられた機能や動作を主張しています。
  • 記載漏れ — アーティファクトには提供済みの機能が記載されていますが、README には記載されていません。
  • 矛盾 — README とアーティファクトで、動作、対象ユーザー、または範囲について見解が異なっています。

未解決の乖離があるとリリースを進められません。各指摘について、担当者は次のいずれかを行う必要があります。

  1. 実態に合わせて README を更新する、または
  2. README に合わせてアーティファクトを更新する、または
  3. 乖離を許容できる理由を明示して、例外として承認する。承認内容はリリースノートに記録されます。
Part 2: 検証チェック

テスト可能な動作を示唆する README の主張を特定します。

  • インストール/セットアップに関する主張 — 「npm install && npm start を実行する」とあれば、インストール手順が機能することを確認するスモークテストが必要です。
  • CLI の動作 — 「foo init がプロジェクトを作成する」とあれば、統合テストが必要です。
  • API サーフェス — 「createWidget 関数をエクスポートする」とあれば、エクスポートの存在を確認するテストが必要です。
  • 動作に関する約束 — 「失敗時に自動で再試行する」とあれば、再試行動作のテストが必要です。
  • 統合に関する主張 — 「PostgreSQL 15 以降で動作する」とあれば、バージョン固有の統合テストが必要です。

テストされていない約束ごとに、担当者は次のいずれかを選びます。

  1. テストを追加する — リリースを一時停止してテストを作成し、その後チェックを再実行します。
  2. 約束を削除する — README を更新し、チェックを再実行します。
  3. ギャップを許容する — ギャップをリリースノートに記録します。
例外承認

担当者は、明示的な理由を記載して README ゲート全体を例外承認できます。例外承認とその理由は、リリースメタデータ(changelog またはタグ注釈)に記録されます。無言での回避は禁止です。例外承認を行う場合は、その理由を明示する必要があります。

6. コミットとタグ付け

変更したファイル(changelog とバージョン番号の更新)をステージングして、コミットします。

git add <changed-files>
git commit -m "release: v1.5.0

Co-Authored-By: <model-name-from-system-prompt> <noreply@unknown>"

システムプロンプトからモデル名を解決します。サブエージェントが別のモデルで実行されていた場合は、モデルごとに Co-Authored-By トレーラーを 1 つ追加します(AGENTS.md の Model attribution を参照)。

次に、注釈付きタグを作成します。

git tag -a <tag> -m "Release <tag>"

ステップ 1 で検出したタグ形式(またはユーザーが指定した形式)を使用します。

6.5. リリースブランチへのスカッシュマージ

release ブランチが存在する場合(git rev-parse --verify release 2>/dev/null で確認)、現在のブランチ(trunk)をスカッシュマージして、release ブランチに統合します。

# Detect trunk branch dynamically (EPIC-029)
REPO_ROOT=$(git rev-parse --show-toplevel)
TRUNK=$(bash "$REPO_ROOT/.agents/bin/swain-trunk.sh")
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)

# Ensure we're on the trunk (development) branch
if [ "$CURRENT_BRANCH" != "$TRUNK" ]; then
  echo "Warning: not on $TRUNK ($CURRENT_BRANCH). Skipping release branch update."
else
  # Tag trunk first (lifecycle hashes must be reachable from trunk per ADR-012)
  # Tag was already created in step 6

  # Squash-merge trunk into release
  git checkout release
  git merge --squash "$TRUNK"
  git commit -m "release: <tag>

Co-Authored-By: <model-name-from-system-prompt> <noreply@unknown>"

  # Return to trunk
  git checkout "$TRUNK"
fi

release ブランチが存在しない場合は、このステップを何も通知せずにスキップします。プロジェクトではまだ trunk+release モデルを採用していません。

7. プッシュするか確認する

プッシュするかどうかをユーザーに尋ねます。プッシュ前には、プッシュ拒否を防ぐため、必ず fetch して上流の変更を統合します。

# Fetch upstream to detect divergence before pushing
git fetch origin

# Rebase trunk onto upstream to incorporate any changes that landed since the release was prepared
TRUNK_UPSTREAM="origin/$TRUNK"
if ! git merge-base --is-ancestor "$TRUNK_UPSTREAM" HEAD; then
  echo "Trunk has diverged from upstream. Rebasing..."
  git rebase "$TRUNK_UPSTREAM" || {
    echo "Rebase conflict — resolve before pushing."
    git rebase --abort
    exit 1
  }
fi

# If release branch was updated, rebase it too
if git rev-parse --verify release >/dev/null 2>&1; then
  RELEASE_UPSTREAM="origin/release"
  if git rev-parse --verify "$RELEASE_UPSTREAM" >/dev/null 2>&1; then
    if ! git merge-base --is-ancestor "$RELEASE_UPSTREAM" release; then
      echo "Release branch has diverged from upstream. Rebasing..."
      git checkout release
      git rebase "$RELEASE_UPSTREAM" || {
        echo "Rebase conflict on release — resolve before pushing."
        git rebase --abort
        git checkout "$TRUNK"
        exit 1
      }
      git checkout "$TRUNK"
    fi
  fi
fi

ステップ 6.5 でリリースブランチを更新した場合:

git push origin "$TRUNK" && git push origin release && git push origin <tag>

リリースブランチが存在しない場合は、これまでどおりプッシュします。

git push && git push origin <tag>

特定のタグだけをプッシュします。git push --tags を実行すると、ローカルにあるすべてのタグをプッシュしようとし、リモートにすでに存在するタグについて不要な拒否メッセージが表示されます。

ユーザーに確認せずにプッシュしてはいけません。ユーザーは先に確認したい場合や、タグをトリガーに CI パイプラインを実行している場合があります。

エッジケース

複数のバージョン系列があるモノレポ: タグ履歴からパッケージごとのタグ(例:frontend-v1.2.0、api-v3.1.0)が示唆される場合は、どのパッケージをリリースするのかをユーザーに尋ね、決めつけないでください。

プレリリースバージョン: ユーザーがプレリリース(alpha、beta、rc)を求めた場合は、バージョンにプレリリースサフィックスを付けます。1.5.0-alpha.1。過去にプレリリースタグがある場合は、既存の規則に従います。

Conventional Commits を使用していない場合: コミット履歴で conventional prefix が使われていない場合は、無理に分類しないでください。フラットな一覧を提示し、変更点を箇条書きにしたシンプルな changelog にします。

作業ツリーに未コミットの変更がある場合: /swain-release の実行時に未コミットの変更がある場合は、ユーザーに警告し、続行するか(変更はリリースに含まれません)、先にコミットできるよう中止するかを尋ねてください。

セッションのブックマーク

リリースが成功したら、ブックマークを更新します:bash "$REPO_ROOT/.agents/bin/swain-bookmark.sh" "Released v{version}"

コメント