release について
Worktrunk のメンテナー向けリリースワークフローのスキルです。バージョン更新、検証、変更履歴の確認、マージ、タグ付けを案内し、公開前のデータ損失リスクとドキュメントの確認を重視します。
主な機能
- 01リリースブランチを main と同期
- 02ローカルおよびクロスプラットフォームテスト
- 03変更とライブラリ互換性の確認
- 04バージョンと変更履歴の準備
- 05データ損失とドキュメントのリスク監査
- 06マージ、タグ付け、リリース監視
活用シーン
- 01Worktrunk のリリース準備
- 02累積変更に潜むデータ損失リスクの確認
- 03タグ付け前の変更履歴の網羅性確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ max-sixty/ worktrunk --skill releaseインストール後、Claude Code で/releaseを入力して読み込まれたか確認します。
詳細
Release Workflow
Steps
-
リリースブランチを
mainと同期する:リリース用ワークツリーのブランチは、リリースの合間にmainより遅れています。リリースがマージされた後にのみmainへリセットされるためです。古いブランチからリリースを切ると、それ以降にマージされたすべての変更が気づかないうちに抜け落ちます。まず、ほかの作業を始める前にmainの先端までファストフォワードします:git fetch origin git merge --ff-only origin/main--ff-onlyは、ブランチがorigin/mainの厳密な祖先であればブランチを進めます。分岐している場合は、マージコミットを作成したり作業を破棄したりせずに失敗するため、続行する前に手動で調整してください。これはリリースブランチに対するwt upに相当します。upエイリアスは各ブランチをそれぞれの上流ブランチ(origin/release)にリベースし、mainにはリベースしないため、ここでは明示的に記述しています。結果のコミットSHAを記録してください。これは変更履歴が対象とする先端であり、手順12ではタグ付け前にmainへ到達したすべての変更を変更履歴と照合します。 -
テストを実行する:ローカルのテストスイートと、全プラットフォームを対象とするテストスイートの2つのゲートがあります。
- ローカル:
cargo run -- hook pre-merge --yes。 - クロスプラットフォーム:切り出し元の先端で
nightlyワークフローをディスパッチし、成功するまで待ちます。リリースに必要なlinux/macos/windows全体の検証はここで行います。PRのパス(ci.yaml)はcargo-affectedによる選択方式に移行中で、testマトリックス全体は実行されなくなります。一方、nightlyでは全OSを対象とするfull-testsに加え、feature-powerset、release-target、nix-flake、minimal-versionsが実行されます。ベンチマークはnightlyには含まれません。専用のbenchmarks.yamlで実行され、ゲートにはなりません。
ci-reporterを起動して、gh workflow run nightly.yaml --ref main # 登録はディスパッチより遅れるうえ、前回のリリースで古い # workflow_dispatchの完了済み実行が残っている場合もあるため、実行中のものに絞ります。 sleep 5 RUN=$(gh run list --workflow=nightly.yaml --event=workflow_dispatch --branch=main --limit 5 --json databaseId,status --jq 'map(select(.status != "completed")) | .[0].databaseId')$RUNの完了まで監視します(ハングすることがあるため、gh run watchは使わないでください)。失敗があれば、続行する前に修正します。
- ローカル:
-
現在のバージョンを確認する:
Cargo.tomlのversionを読みます。 -
コミットを確認する:前回のリリース以降のコミットを確認し、変更の範囲を把握します。累積差分について、データ損失に関わる範囲(データ損失に関わる範囲のレビューを参照)とドキュメント(ドキュメントのレビューを参照)を監査します。
-
ライブラリAPIの互換性を確認する(参考):バージョンの引き上げレベルを判断するための情報として、
cargo semver-checks check-release -p worktrunkを実行します(見つからない場合はcargo install cargo-semver-checks --lockedでインストールします)。これは互換性のゲートではありません。worktrunkでは、破壊的なライブラリ変更を自由にリリースしています。破壊的変更が報告されても問題ありません。semverに従い、バージョンの引き上げは引き続き、1.0未満ならminor、1.0以降ならmajorである必要があります。下記の「ライブラリAPIの互換性」を参照してください。 -
貢献者に謝意を示す:外部のPR作成者とissue報告者を確認します(下記の「外部の貢献者への謝意」と「issue報告者への謝意」を参照)。
-
リリースの種類を決める:変更内容(semver-checksの結果を含む)に基づいて、バージョンの引き上げを選びます。選択が本当に曖昧な場合に限り、ユーザーに確認してください(下記を参照)。
-
バージョンを引き上げる(クリーンなツリーで実行する必要があります。CHANGELOGを編集する前に実行してください):
cargo release X.Y.Z -p worktrunk -x --no-publish --no-push --no-tag --no-verify --no-confirm && cargo checkこれにより
Cargo.tomlとCargo.lockのバージョンが引き上げられ、自動的にコミットされます。手順10でこのコミットをリセットし、CHANGELOGの変更をまとめます。 -
CHANGELOGを更新する:最上部のセクションに、このリリースの変更を記載します(下記の必須確認を参照)。見出しが
## Unreleasedの場合は、その見出しを## X.Y.Zに変更し、残りの項目をその中にまとめます。この見出しの上に新しい見出しを挿入すると、リリースノートに古い## Unreleasedが残ります。それ以外の場合、最上部のセクションは最後にリリースされたバージョンです。その上に## X.Y.Zセクションを追加し、既存のセクションには決して追記しないでください。 -
コミットする:手順8で作成された自動コミットをリセットし、すべてをステージングして、最終的なリリースコミットを作成します:
git reset --soft HEAD~1 && git add -A && git commit -m "Release vX.Y.Z" -
mainにマージする:最終候補のドキュメントレビューを完了してから、リリースブランチをプッシュし、PRを作成して、CIの完了を待ってマージします。ワークツリーはそのままにしてください。残りの手順はそこから実行します。その後、ブランチをマージ済みの先端に移動します:git fetch origin && git reset --keep origin/mainPRはスカッシュマージされるため、ブランチは
mainの祖先ではなくなり、手順1の--ff-onlyでは進められません。--keepならブランチを移動でき、未コミットの変更がある場合は引き続き失敗します。CIの完了を待つ間にmainが進むこともあります。手順12では、タグ付け前に到達した変更を確認します。 -
変更履歴が
mainを網羅していることを確認し、タグを付けてプッシュする:リリース内容はタグによって決まります。release.yamlはタグ時点のツリーからバイナリとGitHubのリリースノートをビルドするため、そのタグから到達可能なものはすべてリリースに含まれます。マージ時点のmainの先端にスカッシュマージされるため、PRのCI待ち中に到達したコミットはすでにリリースコミットの祖先となっており、変更履歴に記載されているかどうかに関係なくリリースされます(見落としやすいのは、今回のリリースですでに記載した機能を作り直すフォローアップです)。切り出し元の先端(手順1)以降にmainへ到達した変更を一覧表示します:git fetch origin git log --oneline <cut-from-commit>..origin/main変更履歴がクリーンな状態とは、
origin/mainの変更履歴に、一覧にあるユーザー向けの変更がすべて記載されていることです。差分がなければ、一覧にはRelease vX.Y.Z (#NNNN)というスカッシュコミットが1行だけ表示されます。その間に到達したほかの変更を確認し、ユーザー向けのものがあれば変更履歴に取り込み、フォローアップのスカッシュPRを作成してから、再取得してもう一度確認します。一覧は確認のたびに増えるだけです。間に到達したコミットは残り、フォローアップのスカッシュコミットが加わるため、確認を重ねるたびに、より長い一覧を対象として網羅性を再確認します。 ドキュメントレビューを、レビュー済み SHA 以降の変更にも拡大します。修正や CI の実行中に到着したコミットも対象にします。最終的にレビューした SHA を記録し、タグ付け前に指摘事項を解決します。問題がなくなったら、
origin/mainにタグを付けます。チェック対象とタグが同じ ref を指し、それが main の先端なので、タグはmainから到達可能です。git tag vX.Y.Z origin/main && git push origin vX.Y.Z -
リリースワークフローの完了を待つ:タグのプッシュによって
release.yamlが起動します。ci-reporter エージェントを起動して、実行が完了するまで監視します(gh run watchは停止することがあるため、使用しないでください)。実行 ID は次のコマンドで取得できます。gh run list --workflow=release.yaml --event=push --branch=vX.Y.Z --limit 1 --json databaseId --jq '.[0].databaseId'
release.yaml はバイナリをビルドし、crates.io、Homebrew、winget に自動で公開します。
データ損失リスクのレビュー
Worktrunk で最悪の障害は、ユーザーの作業を気付かれないまま破壊してしまうことです。PR ごとのレビュー(running-tend、「データ損失リスク」)が最初のゲートであり、リリースが2つ目のゲートです。リリースでは、前回のリリース以降の差分全体を一度に確認できます。
このレビューでは再現率を優先します。削除に関わる可能性のある変更をすべて見つけ、誤検出を許容したうえで、候補を一つずつ判定します。実際の損失につながる経路を一つ見逃すコストは、誤検出をレビューするコストをはるかに上回ります。
キーワードの grep だけでは不十分です。grep で見つかるのは、誰かがパターンとして想定したものだけです。エージェントに grep の手掛かりを与えると、それに依存して盲点を引き継いでしまいます。そのため、独立した検出役を複数用意し、その大半には grep を使わせず、見つかった候補をすべて分析します。
検出:独立した検出役を用意し、適合率より再現率を優先する
累積差分(git log v<last-version>..HEAD -p)と、その変更が触れるコードを対象に、検出役のサブエージェントを3~5個並行して起動します。変更コードを呼び出すコードと、変更コードから呼び出されるコードも含めます。各エージェントは独立して作業します。この段階では見つけた内容を共有させず、全員に同じ手法を取らせないでください。各エージェントは候補の場所と簡潔な理由を1行で報告し、見逃しを避けるため広めに報告します。
各エージェントには異なる役割を割り当てます。少なくとも2つには grep もキーワード一覧も与えず、パターン照合ではなくコードから推論させます。
- 動作の分析(grep なし): 変更箇所を一つずつ読み、それによって何が破壊される可能性があるかを考えます。ファイル、ブランチ、ワークツリー、未コミットまたは未追跡の作業、コミット済みだが未プッシュのコミットなどを確認します。最悪の場合にユーザーデータが失われる変更には、すべてフラグを立てます。
- 影響範囲の分析(grep なし): 差分が触れるすべての関数とファイルについて、呼び出し元と呼び出し先をたどります。破壊的なプリミティブ(ブランチの削除、ワークツリーの削除、ファイルシステム上の削除、履歴の書き換え)に到達し得る経路には、呼び出しが差分の外にある場合でもフラグを立てます。
- 自動化の差分(grep なし): リリース済みの自動化を変更前後で比較します。対象は
plugins/*/hooks/hooks.json、hooks/hooks.json、hooks/wt.sh、およびユーザーがコピーするスキルやエイリアスの例です。何かを削除したり、強制的に上書きしたりする新規または変更後の呼び出しにはフラグを立てます。 - キーワードスキャン(grep): 1つの検出役が、照合用として差分全体にパターンフィルターを実行します。主な手法としては使用しません。パス指定は行いません。パスの許可リストを設けると、grep を使わない検出役で避けるべき盲点を再び生み出すことになります(最も破壊的なコードが集中する
src/remove_dir.rsのツリー走査は、src/git/の外にあります)。git log v<last-version>..HEAD -p \ | grep -nE -- '--force-delete|--force| -D| -f |branch -[dD]|worktree remove|reset --hard|checkout -f|clean -[fdx]|remove_dir_all|remove_file|unlinkat|rm -rf'
分析:候補を一つずつ判定する
候補を集めて重複を取り除き、それぞれを AGENTS.md のデータ安全性に関する不変条件と、FAQ の「What can Worktrunk delete?」の一覧に照らして分析します。失敗時にデータが保護されるか、破壊的な操作に明示的な同意が必要か、意図しない副作用による削除が起きないかを確認します。理由とともに、それぞれを「実際のリスク」「許容可能」「要変更」のいずれかに分類します。
判定済みの候補一覧をすべて提示し、タグ付け前に明示的な承認を得ます。許容可能に見える候補であっても、削除リスクに関する候補が未解決のままリリースにタグを付けてはいけません。
ドキュメントレビュー
リリースレビューでは、前回のリリース以降に行われたすべてのドキュメント変更を確認します。main にすでに反映された変更と、リリース準備中に行われた編集も対象です。公開ドキュメントは、読者が Worktrunk を理解または使用するのに役立つ製品ガイダンスです。各記述の詳しさは、その情報を必要とする読者の数に応じたものにします。
まず、リリース差分全体から、ドキュメントがどこにあるかを漏れなく洗い出します。
git diff --name-status v<last-version> HEAD
git diff v<last-version> HEAD
前回のタグ、候補 SHA、完全な一覧を独立したレビュアーに渡します。サイトのページ、README ファイル、CLI のヘルプ、設定とコマンドの例、同梱されるスキル、リリースノートを対象にします。正本は一度レビューし、生成されたコピーに内容の相違がないことを確認します。所有権と同期については docs/AGENTS.md で定義されています。
レビュアーは、変更された箇所をすべて周辺のセクションとあわせて読み、次の点を確認します。
- 目的と分量: 読者の理解や行動にどのような変化をもたらしますか。重複する説明や、テストや PR に記載すべき実装・リグレッションの詳細は削除します。正確性の修正については、使用方法が変わる場合、または既存の記述が誤りになる場合にのみ、説明文を追加します。
- 明確さと簡潔さ: 具体的で一貫性のある用語を使い、概念を参照する前に導入します。注意事項を重ねるのではなく、定義をその場で書き直します。短くする場合も、必要な手順や条件は残します。
- 正確性と使いやすさ: 記述が実際の動作と一致し、例が対応するコマンドで正しく動くことを確認します。リンクを確認し、読者が目にする順序で、影響を受ける箇所をレンダリングして読みます。
指摘ごとに、該当箇所、読者への影響、具体的な置き換え案または削除案を示します。正本に修正を適用し、ミラーを再生成して、docs/AGENTS.md に記載されたチェックを実行します。指摘をクローズする前に、修正箇所をレビュアーに確認してもらいます。レビューした範囲と SHA、確認範囲、指摘、およびその対応状況をリリースレビューに記録します。未解決の指摘がある場合、タグ付けはできません。変更履歴の記載内容とクレジットについても、以下の確認を行います。
変更履歴の確認
前回のリリース以降のコミットから作成したエントリー案:
git log v<last-version>..HEAD --oneline
重要:コミットメッセージを鵜呑みにしないでください。 コミットメッセージは、変更を控えめに表現したり、誤って説明したりすることがよくあります。ユーザーに影響する可能性のあるコミットについては、次の手順を実行してください。
git show <commit> --statを実行して、変更されたファイルを確認します- ユーザー向けのコード(コマンド、CLI、出力)が変更されている場合は、実際の差分を読みます
- まとめて行われた変更を探します。「フラグ名の変更」というコミットに、新機能が追加されている場合もあります
コミットメッセージが誤解を招くよくあるパターン:
- 動作も変更する「X のリファクタリング」コミット
- 新機能を追加する「フラグ名の変更」コミット
- エラーメッセージの改善やヒントの追加も行う「Y の修正」コミット
- 製品コードの修正も含む CI/テストのコミット
記載すべき注目の変更:
- 新機能や新しいコマンド
- ユーザーから見える動作の変更
- ユーザーが遭遇する可能性のあるバグ修正
セクションの順序: 改善、修正、ドキュメント、内部。ドキュメントにはヘルプテキスト、ウェブドキュメント、用語の改善を記載します。内部には、選別した注目すべき内部変更を記載します(すべてではありません)。
各セクション内では、読者の関心が高い順に並べます。 並べ替えの第一基準はセクションで、順序は固定です。第二基準は読者の関心であり、セクション内の順位を決めます。変更の分類は関係ありません。誰も求めていない動作変更は、要望の多かった機能より下に、すべてのユーザーが遭遇する修正は、特定のプラットフォームだけに関係する修正より上に記載します。関心度は、その変更がどれだけ多くの読者に届くかと、それぞれの読者にどれほどの対応を求めるかを組み合わせて考えます。変更を実装するための労力は含めません。労力と関心度が最もかけ離れるのは、書き上げたばかりの変更です。つまり、いま記載している変更です。したがって、破壊的変更は対象となる読者が少なくても、その全員が対応を求められるため、セクションの上位に置きます。(/writing-prose では、これを「読者層の割合に合わせて目立たせ方を調整する」と表現しています。このスキルは個人設定であり、このリポジトリには含まれていないため、ここに再掲しています。)
破壊的変更: 独立したセクションにはせず、エントリー内に記載します。
- **Feature name**: Description. (Breaking: old behavior no longer supported)
対象外:内部リファクタリング、テストの追加(シェル補完テストのようにユーザー向けのものを除く)。
長さとトーン
関連する箇条書きは統合してください。 同じテーマを共有する複数の PR — たとえば、合わせて 1 つのユーザーから見える高速化につながる 3 つのパフォーマンス変更 — は、3 つではなく 1 つの箇条書きに入れるべきです。読者が気にするのは PR の区切りではなく正味の変化です。末尾の ([#a](...), [#b](...), [#c](...)) リストにすべての PR を記載してください。
簡潔に — 上限は文ではなく語数です。 箇条書きは 35 語を目標にし、密度の高いものでも 60 語まで、見出しになる 2、3 項目は 80 語に達してもかまいません。内部向けセクションの箇条書きは 1 文にします。「なぜこうしたか」という詳細は、ユーザーの変更に対する見方が変わらない限り省き、コード例や Cmd::stream / OnceCell / DashMap のような内部実装は、その理由が属する PR の説明に残してください。
文は言いたいことに合わせていくらでも伸びますが、語は伸びません。ですから判断するのではなく計測してください:
awk '/^## /{if (f) exit; f=1} f' CHANGELOG.md \
| awk '/^- \*\*/ {n=split($0,_," "); t+=n; c++; if (n>60) o++; printf "%4d %.58s\n", n, $0} END {printf "\n%d entries, %d avg, %d over 60\n", c, c?t/c:0, o}'
前回のリリースではなく、上限を基準に調整してください。 長さはラチェット式に増えていきます。各リリースは前のセクションの隣で起草され、抽象的なルールは具体的な隣の見本に必ず負けます。このスキルがずっと「簡潔に」と言い続けている間に、項目は 5 回のリリースで平均 49 語から 101 語へと膨らみました。前のセクションを読んでどこまでずれたかを確認し、それからそれは無視して上限に向けて書いてください。
項目は記述します。 項目は、以前の動作がどうだったか、今どうなっているかを記録します。指示的なガイダンスを書くのは、かなりの割合のユーザーに影響する重大な問題の場合だけであり、それはまれです。それ以外の対処法は PR の説明に属します。
編集的な色付けはしないでください。 何が変わったかを記述し、以前の決定が主観的にどうおかしかったかは書きません。過去のコードに対して「sledgehammer」「ugly」「noisy」「wrong」といった言葉を使うのは避けてください。以前の動作は中立に、新しい動作は率直に述べてください。
良い例: 「デフォルトの除外リストから .pi/ を削除しました。必要なユーザーは [step.copy-ignored] で追加できます。」
悪い例: 「.pi/ を削除 — 無関係なデバッグ作業で使われた sledgehammer 的な修正で、プロジェクトに依存しないデフォルトとして置くべきものではありません。」
修正の目立ち具合はその影響範囲に合わせてください。 読者は太字の見出しをざっと読みます。ですから、見出しと、その修正に独立した箇条書きがあるかどうかで、本文を読む前にそれがどれほど大きいかを知ります。正確性やデータ損失の修正は通常、狭い条件を必要とします — デフォルトではない git 設定、特定の場所から実行したコマンド、特定の形の変更などです。条件は見出しに、結果は本文に置いてください。結果を述べた見出しは、すべての読者に自分にも起こりえたと伝え、その後に続く条件がそれを打ち消すことはありません。条件は「and」でつないでください。「X が設定され、かつ Y から実行された」はレアケースですが、「X または Y」はよくある 2 つのきっかけとして読まれます。各条件は、差分から読み取るのではなく、前回のリリースのバイナリに対して再現して確認してください。想定した条件は、その項目が過大に述べている条件であり、データ損失バグを過大に述べることはそれ自体が一種の不正確さです。
良い例: 「ignore 設定のあるサブモジュール: submodule.<name>.ignore がサブモジュール内の未コミットの変更を隠していたとき、wt remove はワークツリーをクリーンとみなし、その変更ごと削除しました。」
悪い例: 「wt remove は設定で隠されたサブモジュールの変更を削除しなくなりました: submodule.<name>.ignore が設定され、かつ サブモジュール内に未コミットの変更がある場合、…」 — 条件はすべてそろっていますが、見出しがすでにすべての読者にデータ損失バグを告げてしまっています。
読者の関心がほぼゼロの修正 (上記の順序ルールを参照) — - で始まる名前、非 UTF-8 のパス、特殊な環境の 1 プラットフォームなど — には独立した箇条書きを付けません。これらは「特殊なセットアップ向けの修正」のような締めの箇条書きにまとめ、各ケースを一節で挙げてください。独立した太字の修正が並ぶセクションは、本文が何と言おうと、ツールがそれだけ多くの壊れ方をしたように読まれます。
外部コントリビューターをクレジットする
外部コントリビューター(リポジトリのオーナーではない人)がコミットを作成したチェンジログのエントリには、その GitHub ユーザー名を添えてクレジットを追加します:
- **Feature name**: Description. ([#123](https://github.com/user/repo/pull/123), thanks @contributor)
外部コントリビューターを見つけます:
git log v<last-version>..HEAD --format="%an <%ae>" | sort -u
次に、各外部コントリビューターのコミットについて、そのコミットから GitHub ユーザー名を特定します(通常はメールアドレスまたは PR に記載されています)。
イシュー報告者をクレジットする
修正や機能がこのリポジトリでユーザーが報告したイシューに対応するものである場合、PR の作成者だけでなく、報告者にも感謝します。バグを報告したり、機能をリクエストしたり、再現手順を提供したりするために時間を割いてくれたユーザーは、評価されるに値します。(上流/外部リポジトリの報告者をクレジットしないでください — ここで起票されたイシューのみです。)
- **Feature name**: Description. ([#456](https://github.com/user/repo/pull/456), thanks @reporter for reporting)
イシューを参照する修正の場合:
- **Bug fix**: Description. Fixes [#123](https://github.com/user/repo/issues/123). (thanks @reporter)
報告者を見つける — 3 つの手順をすべて実行します:
イシューは修正のはるか数月前に起票されていることがあります。バグ報告はイシューだけでなく、PR のコメントとして現れることもあります。これらの手順は補完的であり、それぞれが他が見逃すものを捉えます。
-
すべてのコミットからすべてのイシュー/PR 参照を抽出します(主要):
git log v<last-version>..HEAD --format="%B" | grep -oE '#[0-9]+' | sort -t'#' -k2 -n -u参照されている各番号について、
gh issue view N --json title,author,stateを実行します。これにより、数月前に起票されたイシュー — 最も見落とされやすいクレジット — を捉えられます。 -
バグ報告がないか PR コメントを確認します(イシューにならなかった報告を捉えます): コミットで参照されている機能 PR について、問題を報告しているユーザーのコメントスレッドを確認します:
gh pr view NNN --json comments --jq '.comments[] | "\(.author.login): \(.body[:150])"' -
前回のリリース以降に起票またはクローズされたすべてのイシューを調査します(参照されていない一致を捉えます):
git log -1 --format=%cs v<last-version> gh issue list --state all --search "created:>=<date>" --json number,title,author --limit 100 gh issue list --state closed --search "closed:>=<date>" --json number,title,author --limit 100すべてのタイトルを、このリリースの変更と照合します。
クレジットする場合:
- 明確な再現手順を伴うバグ報告(イシューまたは PR コメント内)
- 実装を形作った機能リクエスト
- 測定値を伴うパフォーマンス報告(「15 秒かかる」など)
- 議論を通じてイシューの診断を手助けしたユーザー
クレジットを省略する場合:リポジトリのオーナーが起票したイシュー、些細な報告、または実装された内容と実質的に異なるイシュー。
重要な機能をドキュメントにリンクする
専用のドキュメントがある主要な機能には、ドキュメントへのリンクを含めます。GitHub リリースからリンクが機能するように、完全な URL を使用します:
- **Hook system**: Shell commands that run at key points in worktree lifecycle. [Docs](https://worktrunk.dev/hook/) ([#234](https://github.com/user/repo/pull/234), thanks @contributor for the suggestion)
ユーザーが読むと有益な相当な量のドキュメントがある場合にリンクします — 新しいコマンド、機能ページ、Tips & Patterns のセクションなど。軽微な改善では省略します。
必須:各チェンジログエントリを検証する
チェンジログのエントリを起草した後、各箇条書きが正確であることを検証するためにサブエージェントを起動しなければなりません。 タグはこのテキストを GitHub リリース本文として公開するため、後から訂正するには CHANGELOG.md への追加 PR とリリースページの手作業での編集が必要になり、その頃には人々が間違った行を読んでしまっています。このパスには、それにかかる時間だけの価値があります。
このゲートは両刃です。 正確性だけを確認すると、すべてのエントリが長くなります。「過小評価している」「カバーされていない」には釣り合う重みがなく、各パスは追加ばかりで削除はありません。この非対称性が、前述のラチェットを招いたのです。長すぎる、内部向けすぎる、あるいはより多くの読者が気づくものより上位にランクされたエントリは、間違っているエントリと同じ立場で報告されます。
サブエージェントのプロンプトテンプレート:
Verify these changelog entries for version X.Y.Z are accurate. They publish with
the tag, and by the time anyone corrects a wrong line, readers have acted on it.
Spend the time to read a source for each one: reading the entry and finding it
plausible is not a check, because the entry was written from the same commits you
are about to read.
Previous version: [e.g., v0.1.9]
Commits to check: git log v<previous>..HEAD
Entries to verify: the top section of CHANGELOG.md as it stands on disk. Read it
there rather than from a paste:
awk '/^## /{if (f) exit; f=1} f' CHANGELOG.md
Verify claim by claim, not entry by entry: an entry carries several independent
claims, and one verdict over the whole entry waves through every claim that is not
its headline.
1. Find the relevant commit(s) using git log and git show
2. Read the diff, not the commit message. The diff settles what changed, and
nothing else: not what the behavior was before, not what the user sees, not
what a file it doesn't touch does. Settle a "previously" / "no longer" / "so X
broke" claim by reading the old file (`git show <sha>^:<path>`) and confirming
the old behavior there. The new code's handling of the old case is not that
confirmation: a case added together with a comment about why it produces
nothing reads in a diff exactly like a case that used to produce something.
Some claims have no source in the commit at all — a version floor, what a
rendered page shows, how another component behaves. Read that source: the
rendered output, the other component's own file, the upstream project's own
releases
3. Flag any claim its source does not support, whether it overstates,
understates, or misdescribes
4. Flag if the entry runs over 60 words (80 for one of the two or three headline
entries), restates the PR description, or explains mechanism the reader cannot
act on — report these as seriously as an inaccuracy, and quote a shorter
rewrite that keeps every user-facing claim
Also check:
- Are there user-facing changes NOT covered by these entries?
- Verify each "thanks @..." attribution (right person, right role — author vs reporter)
- Within each section, is any entry ranked above one that more readers will notice?
- Read each headline alone, as a skimming reader does. Flag one that states the
consequence (what was lost or broken) rather than the situation it needed, and a
fix almost no reader will notice that has its own bullet rather than a clause in
a closing roll-up.
Report format:
- Entry: [entry text]
Status: ✅ Accurate / ⚠️ Needs revision / ❌ Incorrect
Length: [word count] — ✅ / ⚠️ over ceiling
Evidence: [for each claim, the source you read and what it said]
Suggested fix: [if needed]
このパスは、最初の実行の検証結果ではなく、クリーンな実行で終わります。 検証者が提案した書き直しは、あなた自身が書いたものと同じ以上の根拠を持ちませんし、パスの実行中に編集したエントリも同じ状態です — どちらもそのエントリを未検証のままにします。現在の状態のセクションに対して再実行し、実行がクリーンに返ってきたときに初めて確定します。
このスキルの隣にある evals/README.md には、出荷済みリリースからの 4 つのエントリ(うち 3 つは誤り)が収められており、このテンプレートへの変更を、前回の文言が見逃したものに対してスコアリングするため、および prominence ルールの起草ケースのために使用します。
検証で問題が見つかった場合: ユーザーにエスカレーションします。サブエージェントの検証結果を提示し、どう進めるかを尋ねます。曖昧なチェンジログエントリを自律的に解決しようとしないでください — ユーザーはあなたよりも自分の変更の意図をよく知っています。
リリースの種類を判断する
変更内容に応じてバージョンを上げます。妥当な選択肢が1つしかない場合は質問を省略し、本当に判断が分かれる場合にのみ質問してください。
答えが明らかな場合は、質問せずに進めてください。
cargo semver-checksが破壊的変更を報告した場合 → minor(1.0未満では patch は不可で、成熟段階にあるプロジェクトでは major にする根拠もありません)。ユーザーに伝えて続行します:「minor にバージョンを上げます — semver-checks が N 件の破壊的変更を報告しました。1.0未満では patch は不可です。」- 前回のリリース以降、バグ修正と内部コミットのみで、新機能も semver 上の破壊的変更もない場合 → patch。同じ形式でユーザーに伝えます。
本当に判断が分かれる場合にのみ質問してください — たとえば、semver 上の破壊的変更がない状態で新機能が追加された場合(patch か minor かは判断次第)、または変更内容に対するユーザーの見解が異なる可能性がある境界的なケースです。実際の選択肢(patch か minor)を使って AskUserQuestion を使用し、バージョン番号を飛ばすといった余計な選択肢は追加しないでください。
質問する際は、次の内容を提示してください。
- 現在のバージョン(例:
0.2.0) - 変更内容の簡潔な概要(新機能、バグ修正、破壊的変更)
- 推奨案とその理由
例:
Current version: 0.2.0
Changes since v0.2.0:
- Added `state clear` command (new feature)
- Added `previous-branch` state key (new feature)
- No breaking changes
Recommendation: Minor release (0.3.0) — new features, no breaking changes
バージョンのガイドライン
- 2桁目(0.1.0 → 0.2.0):後方互換性のない変更
- 3桁目(0.1.0 → 0.1.1):その他すべて
現在のプロジェクト状況:成熟段階(AGENTS.md › プロジェクト状況 を参照)。外部インターフェースである設定ファイル形式(wt.toml、ユーザー設定)と CLI フラグ/引数には互換性が求められるため、これらを変更するには正当な理由(単なる整理ではなく、実質的な改善)が必要です。また、予告なく変更するより、非推奨の警告を優先してください。それ以外は、内部 API とライブラリ API を含め、柔軟に変更できます。worktrunk は破壊的なライブラリ変更を自由にリリースし、その都度バージョンを上げます。既存の内部 API に互換性上の重みはありません。
ライブラリ API の互換性
Worktrunk は CLI ツールです。Cargo.toml の [lib] クレートは公開 API を提供していますが、互換性を保証する対象ではありません — AGENTS.md › プロジェクト状況 にあるとおり、Rust ライブラリの互換性に関する懸念はなく、プロジェクトはライブラリに対する破壊的変更を自由にリリースし、その都度バージョンを上げています(CHANGELOG.md の「Breaking library API」の項目を参照)。下流のクレートではバージョンを固定することが想定されています。
したがって、cargo-semver-checks はバージョンの引き上げ幅を決める際の参考情報であり、下流のクレートに対して API の安定性を維持すると約束するためのゲートではありません。現在の公開 API と crates.io に公開された最新バージョンを比較し、semver 上重要な変更を報告するため、バージョンの引き上げ幅を決める有用な判断材料になります。
cargo semver-checks check-release -p worktrunk
結果の解釈:
- 問題が報告されない場合:ライブラリレベルでは、バージョンの引き上げ幅を判断する材料はありません。CLI の変更内容と新機能に基づいて決めてください。
- 破壊的変更が報告された場合:想定内であり、問題ありません。ここではライブラリ API の破壊的変更を避ける必要はありません。ただし semver に従うと、1.0未満では破壊的変更に対して少なくとも minor の引き上げが必要です(例:0.37.0 → 0.38.0)。それに応じてバージョンを上げてください。これはバージョンのルール上の対応であり、古い API を維持するための判断材料ではありません。
- ツールを実行できない場合(例:ベースラインがない):クレートがまだ公開されていないか、レジストリのキャッシュが古い可能性があります。
cargo semver-checks check-release -p worktrunk --baseline-version <last-published>を試してください。
このチェックで検証できるのは、選択したバージョンの引き上げ幅が妥当かどうかです。破壊的変更がない場合に patch と minor のどちらを選ぶべきかは判断できません。patch(修正のみ)と minor(新機能)のどちらにするかは、引き続きコミットを確認して決めてください。