ship について
shipは、リポジトリの種類に応じた条件を確認してから、変更のプッシュや受信したPR・MRの処理を行うリリースワークフロースキルです。チェックリストを提示し、リモート操作の前に明示的な承認を待ちます。
主な機能
- 01リポジトリの役割に応じたゲート確認
- 02push・release・PR・MR・mergeに対応
- 03ヘルスチェックと該当するリモートUATを実行
- 04リリースノートやPR・MR文面を作成
- 05リモート操作前に承認を待機
活用シーン
- 01変更をpushする前の準備状況確認
- 02releaseやPR・MRの準備
- 03受信したリクエストをマージ前にテスト
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ rheinmir/ setup --skill shipインストール後、Claude Code で/shipを入力して読み込まれたか確認します。
詳細
スキル:ship
リモートを中心としたワークフローです。条件チェックリストを実行し、副作用を伴うすべての手順(push/tag/PR/MR/merge)の前に停止して承認を待ちます。5つのレベル — 4つの外向きレベルと1つの取り込みレベル:push(tagなしで全手順を実行) · release(push + tag
vX.Y.Z+ リリースノート) · pr(ブランチをpush +gh経由でGitHub Pull Requestを作成) · mr(ブランチをpush +glab経由でGitLab Merge Requestを作成) · merge(到着したPR/MRを一覧表示 → ブランチを取り込む → gate+テスト → 問題がなければmerge)。
内容
目的とコンテキスト
- 目的: 条件チェックリストがすべて問題ない場合に限り、変更をリモートに反映(push/release/PR/MR)するか、到着したPR/MRを取り込み(merge)ます。副作用を伴うすべての手順の前に停止して承認を待ちます。
- 使用するタイミング:
- ユーザーが「release」/「push」/「ship」/「リリースして」/「pushの準備をして」/「pushできる状態?」/「PRを開いて」/「MRを作って」と言ったとき。
- コードをリモートにpushする前、リリースを作成する前、またはレビュー後のmergeに向けてPR/MRを開く前。
- リポジトリのオープン中のPR/MRを承認してmergeしたいとき:「PRを取り込んでmerge」/「テストが問題なければPRをmerge」/「ship merge」。
- 対象外: gateの不具合を自動で修正しない(
/medicと修正スキルの担当です)。issueを自動でクローズしない。gh/glabを自動でインストール/認証しない。
メンタルモデル
repo_role(framework · module · downstream · foreign)→ 正しい種類のリポジトリに対応するgate表 → の後に、共通の流れに進みます:
レベル(push · release · pr · mr · merge)→ 健全性gate(medic --ci + ci-local)→ リモートUAT(release/pr/mrのうち、対応能力があるもののみ)→ gitがクリーン→ selftest → [version + patch note] → チェックリスト → 承認待ちで停止 → 副作用 → [UATフェーズ2]。各レベルの違いは最後の手順であり、チェックリストではありません。
入力と出力の契約
| Field | 必須? | 意味 | |
|---|---|---|---|
| In | repo_role | 自動読み取り | python3 harness/scripts/repo_role.py . --json(クライアントマシンでは:~/.claude/harness/harness/scripts/repo_role.py)— .overstack.yaml で宣言されたラベルです。存在しない場合は、根拠を添えて推定し、ユーザーに一度だけ確認してから --set を実行します。今回だけ手動で指定する場合:ship <mức> --as <role> |
| In | レベル | いいえ(デフォルト = push) | push · release · pr · mr · merge — ユーザーは範囲を説明すればよく、フラグを覚える必要はありません |
| In | ユーザーの承認 | はい、副作用を伴う操作の前 | push/tag/release/PR/MR/merge/canaryに対する明示的な「yes」 |
| Out | チェックリスト + 推奨コマンド | はい | 各gateの結果、UATフェーズ1またはスキップする理由、commit msg、最後のコマンド |
| Out | 文書 | レベルによる | release → RELEASE-vX.Y.Z.md;pr/mr → PR/MR本文;push → commit msgのみ;merge → テスト報告 + 判断 |
| Out | 副作用 | 承認後のみ | 実行済みのpush / tag / release / PR / MR / merge |
ルールと機能
- RULE-01 (MUST):
medic --ciが失敗した状態でプッシュしない — ユーザーが明示的にオーバーライドした場合を除きます。オーバーライドする場合も、理由をパッチノートに記載してください。 - RULE-02 (MUST): パッチノートを誇張しない — 未完了の箇所がある場合は、既知の制限事項を必ず記載してください。
- RULE-03 (MUST): レベルの違いは最終ステップにあり、チェックリストにはありません: すべてのレベルでヘルスゲートを通過します。違うのは最終成果物(タグ/リリース/PR/MR/マージ)だけです。ユーザーが「pr」/「mr」と言った場合はタグを付けないでください。ユーザーが「push」とだけ言った場合はPRを作成しないでください。
- RULE-04 (MUST):
medic --ciが成功しても、リモート環境で動作する証明にはなりません。それを確認するのが/fdk-uatです。 新しい機能を含むrelease/pr/mrは、ステップ7を提案する前に必ずUATフェーズ1(カナリア)を通過してください。diffでユーザーに見える機能が何も追加されていないと確認できる場合に限り省略でき、その理由を記載する必要があります。実際に失敗した判断の記録:2026-09-17、それまでのすべてのプッシュ(6c839d8を含む)はmedic --ci/ci-localのみ通過し、実際のリモートUATは一度も通過していません。 - RULE-05 (MUST):
mergeレベルでは、TESTはマージの条件であり、形式ではありません: ブランチを更新し、medic --ciと実際のテストを実行してからマージしてください。失敗したら絶対にマージせず、作成者にそのまま戻してください。個別に処理し、複数のPRを一度にまとめて無確認でマージしないでください。 - RULE-06 (MUST): PR/MRの本文にもパッチノートと同じルールを適用: ユーザー向けの口調にし、未完成の箇所がある場合は既知の制限事項を必ず記載してください。SHAや内部関数名は記載しないでください。
Closes #Nを自動で付けないでください。 - RULE-07 (MUST): 副作用を伴う操作には「yes」が必要: push/tag/release/PR/MRは取り消しにくい外部向けの操作です。必ず一度停止してコマンドを表示し、承認を待ってください。fdkに従い、コミットやPR本文にAIによる作成の attribution を記載しないでください。
- RULE-08 (MUST):
gh/glabを自動でインストール/認証しない: ツールがない場合は停止してユーザーに知らせてください。ホストを推測しないでください。 - RULE-10 (MUST): いずれかのゲートを実行する前に、対象のリポジトリ種別を把握してください。 チェックリストの最初の行は常に
🏷 repo_role=<role> (khai báo | sổ máy | suy luận | ép tay)とします。ソースがsuy luậnの場合は、ユーザーに確認してからラベルを記録してください(repo_role.py . --set <role>。foreignの場合はマシン台帳に記録し、他人のリポジトリには触れないでください)。あるリポジトリ種別のゲートは、別の種別には適用されません。ci-local/capability-stamp/UATが意味を持つのはframeworkのみです。これらをmodule/downstreamで実行するのは誤った採点であり、frameworkで省略すると見落としにつながります。2026-09-20の教訓:/shipの単一フローでは、エンジンリポジトリの出荷にまったく異なる手順が必要なことを、自分で覚えておかなければなりませんでした。 - RULE-11 (MUST): プッシュ前にゲートの終了コードを確認してください。 push/tagコマンドは、
rc=を出力して読み取った後の独立したステップにしてください。ゲートとpushを;でつないだり、終了コードを捨てる| tailを使ったりすることは禁止です。2026-09-20、同日に2件の失敗が発生しました。medicが失敗している状態でc83b065をプッシュし、install-testがFAILを報告した状態でタグv3.0.1を付けました。どちらもコマンドを連結したことが原因です。frameworkで未コミットの不明なファイルが作業ツリーにある場合(例:別のツールによって上書きされたファイル)は、ワークフローを誤って採点しないよう、コミットのクリーンなチェックアウトでゲートを実行してください(git worktree add --detach <tmp> HEAD)。 - RULE-12 (MUST):
foreignは他人の家にいるお客さんです。pr/mrレベルのみを使用し、デフォルトブランチへ直接pushしないでください。相手のコミット/CIルールに従ってください(CONTRIBUTINGを読み、R15やoverstackのルールを適用しないでください)。インストールしないでください。.overstack.yamlを書き込まず、自分たちの設定ファイルをリポジトリに追加しないでください。 - RULE-09 (MUST): Composeして作り直さない:ヘルスチェックには
medic、バージョン管理にはgit tag、PR/MRにはgh/glabを使い、このスキルはチェックリストの調整のみを行います。 - Capabilities: リポジトリの読み取りとローカルゲートの実行。リモートへの書き込み(push/tag/PR/MR/merge)は、認証済みのツールを使い、承認を得た後に限ります。
失敗時の境界
- ゲート失敗(
medic --ci/ci-local/freshinstall)→ blocked。問題箇所と修正コマンドを出力し、pushしないでください。 - UATのいずれかのフェーズでFAIL → failed。出荷を停止し、カナリアを削除してください。フェーズ2でFAILした場合は、
/fdk-uatのステップ5に従ってリモートからコミットを取り除いてください。 - diffに「新しい機能」が含まれるか、バージョンの段階がどれに当たるか不明 → clarify(ユーザーに質問)とし、自分で判断しないでください。
gh/glabがない、または未認証 → blocked。ユーザーにインストールとログインを依頼してください。mergeレベル:PRが失敗した場合、そのPRはマージしないでください(ロット全体を partial とし)、理由をユーザーに伝えてください。
HOW
メインワークフロー
| ステップ | 種別 | 入力 | アクション | 出力/終了 | 失敗時/次の処理 |
|---|---|---|---|---|---|
| W00 | 決定的 | リポジトリ | repo_role.py . --json → 🏷 repo_role=… に記録します。ソースが inferred の場合はユーザーに確認してから --set を指定し、「Luồng theo repo_role」表のゲート列を選択します | ロール + ゲート表 | ロールが無効 → ブロック |
| W01 | 決定的 | リポジトリ | ヘルスゲート medic --ci を実行し、続けて python3 fdk/tools/ci-local.py を実行します(freshinstall プローブを含みます) | rc 0 | 赤 → ブロック |
| W02 | 副作用あり | 差分、レベル | UAT /fdk-uat のフェーズ1 — 新しい機能がある場合に限り release/pr/mr で実行します(B02) | PASS またはスキップの理由 | FAIL → 失敗 |
| W03 | 決定的 | ワークツリー | Git がクリーンであることを確認します:git status --short。追跡されていない一時ファイルは除外します | クリーン | 汚れている → クリーンアップして W03 を繰り返します |
| W04 | 決定的 | 差分 | 変更対象のエンジンをセルフテスト/簡易チェックします | rc 0 | 赤 → ブロック |
| W05 | 判断 | 最新タグ | バージョン vX.Y.(Z+1) — release のみ(B01) | 推奨タグ | バージョンの桁が不明 → 確認 |
| W06 | 判断 | git log、スクラッチログ | パッチノート/PR・MR の本文を事実に即して作成します。中途半端な部分がある場合は Known-limitations を必ず記載します | テキスト | — |
| W07 | 決定的 | W01~W06 の結果 | チェックリストとコマンド案を表示し、承認を待って停止します | "yes" | 承認されない → キャンセル |
| W08 | 副作用あり | 承認 | レベルに応じて実行します。W02 を実行済みの場合は、その直後に UAT フェーズ2を実行します | 副作用 + 実行記録 | フェーズ2 FAIL → コミットを取り消します |
各ステップの詳細(W01~W08 の正確な情報源):
フラグを覚えるのではなく、範囲を指定します:「push」(プッシュのみ)・「release」(プッシュ + タグ + ノート)・「pr」(ブランチをプッシュ + GitHub Pull Request)・「mr」(ブランチをプッシュ + GitLab Merge Request)・「merge」(PR/MR を取り込み → テスト → マージ)。デフォルトは push です。
push/release/pr/mr レベル(外部へのプッシュ)では、以下のステップ1~8を実行します。merge レベル(取り込み)では、ステップ8の専用分岐を実行します(「merge レベル」を参照)。
ステップ1、3~4はすべてのレベルに適用されます。ステップ2(UAT)は release/pr/mr のみです。ステップ5(バージョンタグ)は release レベルのみです。ステップ6で「作成する成果物」の名前を変更します:release → RELEASE-vX.Y.Z.md、pr/mr → PR/MR の本文(ユーザー向けの同じトーンで、Known-limitations のルールも同じです)。push ではテキストは不要で、コミットメッセージのみです。merge レベルではノートを作成せず、テスト結果とマージするかどうかの判断のみを報告します。
- ヘルスゲート —
medic --ci(またはpython3 fdk/tools/medic.py --ci)。FAIL → 停止し、問題箇所と修正コマンドを出力します。赤信号のまま push してはいけません。Warn(既知の負債)→ 続行できますが、パッチノートに必ず記載してください。- 続けて
python3 fdk/tools/ci-local.py(framework リポジトリ)を実行します — すべての GitHub ワークフローにあるrun:ステップをすべてローカルで実行します(L4)。medic は L2 です。CI にしかないゲート(search-index、skill-provenance、retrieval-eval など)があります — 080926 に失敗した事例があります。medic は成功して push したものの、CI では 2 つのジョブが失敗しました。失敗したら push してはいけません。 freshinstallプローブ(E2E)も含みます。隔離された空のプロジェクト(リポジトリ外の mktemp)に、working-tree 経由で overstack を curl インストールし、3 つの柱 + harness の動作 + オーケストレーション対応を検証します。失敗 = 新規ユーザー向けのインストール経路が壊れています → push してはいけません。完全版の curl-github + ライブ受け入れテストはbash harness/scripts/fresh-install-smoke.sh --remoteです。
- 続けて
- UAT ゲート —
/fdk-uat(release/pr/mrの場合のみ。通常のpushでは実施しない): ステップ 1 のmedic --ci/ci-localがインストールするのはfile://の working-tree 経由です — これは「ローカルのコードが正常」であることを証明するだけで、「初めてのユーザーがリモートからcurlして実行できる」ことは証明しません(GH#77 のエラー層:「ドキュメントで約束されているのに、ユーザーが受け取れない」。2026-09-17 に push6c839d8で UAT を一切実施せず、実際に確認されました)。- 差分に新機能がある場合(新しい skill/新しいルールが動作する/新しい engine-tool)→ ステップ 7 に進む前に、最低でもフェーズ 1(カナリア:一時ブランチを push し、そのブランチの raw から curl インストールして、新機能が利用可能であることを確認)を必ず実施してください。フェーズ 2(メイン URL のスモークテスト、CDN 待ち)は、ステップ 8 でユーザーが実際の merge/tag を承認した直後に実施します — 提案時ではありません。
- 差分が純粋なバグ修正/内部リファクタリングのみで、ユーザーが認識できる新機能を追加しない場合 → このステップを省略し、ステップ 7 のチェックリストに理由を明記します(「新機能なし — UAT をスキップ」)。
- 差分が「新機能」に該当するか確信がない場合 → ユーザーに確認し、自己判断で省略してはいけません。
- カナリアの push は実際の副作用(リモートへの一時ブランチの push)です → 実行前に停止してユーザーに確認します。この skill の副作用に関するルールも適用されます。どのフェーズでも失敗したらリリースを止め、具体的なエラーを報告し、カナリアを削除します(「後で」ではありません)。
- Git の状態確認:
git status --shortを実行します。一時的なゴミ(scratchpad/…)が.gitignoreに追加されていることを確認し、誤って追跡した場合はgit rm -r --cachedを実行します。秘密情報や一時ファイルが紛れ込んでいないか確認します。 - Selftest/簡易テスト:変更した engine をテストします(例:
council.py selftest、差分に関連するテスト)。 - バージョン:
git tag --sort=-v:refname | head -1→ 最新の tagvX.Y.Z→vX.Y.(Z+1)(patch)、または差分に応じて minor/major を提案します。桁に確信がない場合はユーザーに確認します。 - 誠実なパッチノート(ユーザー向けのリリースノート調 — Claude Code 風):
RELEASE-vX.Y.Z.mdを作成します。- 形式:
Version X.Y.Z:ヘッダーの後に、各行 1 項目のフラットな箇条書きを記載します。 - 文体: ユーザーが実際に目にする変更を動詞から始めて説明し、コミットや内部情報を羅列しません。
Fixed <症状> — <現在の状態>·Added <機能> — <用途>·Removed/Changed …。読者の視点(「あなた/あなたの」)で書き、SHA や、ユーザーが直接入力しない限り関数名は記載しません。 - 動詞による暗黙の分類: Added/Changed を先に、Fixed を後にします(Claude のリリースノートと同様)。箇条書きが短い場合、グループ見出しは不要です。
- 情報源:
git log <tag-cũ>..HEADとセッションの scratch-log を読み、技術的なコミットをユーザーにわかる表現に変換します(ユーザーが実感する価値に応じて、1 つのコミットを複数の箇条書きに分けたり、複数のコミットをまとめたりできます。1 対 1 にする必要はありません)。 - 既知の制限事項(中途半端な部分がある場合は必須 — Claude より優れた点): proposal のドラフトで未実装、部分的な coverage、既知の medic 警告などを、「作業中/既知」と明示します。記載しないのは誇張になります(council での 2026-07-03 の教訓)。
- 形式:
- チェックリストと提案するコマンドをユーザーに提示します(コミットメッセージ、push、tag/PR/MR、UAT フェーズ 1 の結果またはスキップ理由)。承認を待って停止します。
- ユーザーの承認後、該当する操作を実行します。明示的な「yes」がない限り、副作用を伴うステップを実行してはいけません。ステップ 2 で UAT フェーズ 1(PASS)を実施済みの場合は、merge/tag/push の完了後、ユーザーに「完了」と報告する前に UAT フェーズ 2(メイン URL のスモークテスト、CDN sentinel 待ち)を直ちに実施します。失敗した場合は
/fdk-uatのステップ 5 に従ってリモートからコミットを取り消します。- push: コミットして
git push。 - release: コミットして push し、
git tag vX.Y.Zを実行してリリースを作成します(notes = パッチノート)。 - pr(GitHub): コミットして
git push -u origin <ブランチ>を実行し、gh pr create --base <base> --head <ブランチ> --title "…" --body-file <PR-body>を実行します。Base の既定値はリポジトリのメインブランチ(例:orca)です。確信がない場合は確認します。 - mr(GitLab): コミットして
git push -u origin <ブランチ>を実行し、glab mr create --source-branch <ブランチ> --target-branch <base> --title "…" --description "…"(または-F <ファイル>)を実行します。 - remote に応じてツールを選択:
git remote get-url originにgithub.comが含まれる場合はgh、gitlabが含まれる場合はglabを使用します。ship pr/ship mrは使用ツールを明示します。ツールがインストールされていない、または認証されていない場合(gh auth status/glab auth status)は停止し、ユーザーにインストールとログインを依頼します(こちらで勝手に実行しません)。 - ユーザーが明示的に依頼しない限り、PR/MR の本文に
Closes #N/Fixes #Nを自動で追加してはいけません — issue を手動で閉じる権限はユーザーに残します。
- push: コミットして
repo_role ごとのフロー(W00 で列を 1 つ選択。W01~W08 では上記の framework 列について説明)
| ステップ | framework(Rheinmir/setup) | module(orca-graph、uiux-asset…) | downstream(.llmwiki/ があるプロジェクト) | foreign(他者のリポジトリ) |
|---|---|---|---|---|
| ゲート | medic --ci → ci-local(作業ツリーに見慣れないファイルがある場合は、クリーンなチェックアウトで実行) | 先にコミット → 自身のテスト + eval + install-test(各 rc を確認。install-test は HEAD からクローンするため、未コミットの変更はテストされません) | プロジェクトのテスト + llmwiki-validate + medic(downstream モード) | Git がクリーン + 相手側のテスト/CI |
| リモート UAT | diff に新しい機能がある場合(B02) | push 後、リモートからインストールしてスモークテスト(モジュールの install.sh を一時的な HOME にインストール) | なし | なし |
| バージョン | クライアントのマシンに届くもの(hook、shim、installer、global tool)が変わる場合は capability-stamp.py --update を実行 — 表面上の sha が変わらなくても bump が必要です。そうしないと、すでに現行バージョンのマシンで更新されません | VERSION + コード内の定数 + CHANGELOG を bump | プロジェクトに従う | 相手側に従う |
| 最終ステップ | push(・レベルに応じて tag/PR) | push → CI がグリーンになるまで待機 → tag + release → framework で再 pin(.overstack.yaml の upstream_pin:変更があれば SKILL をコピー → sync-skills.py → fdk/skills.provenance.json に commit/version を記録 → framework を ship) | push / pr | PR / MR のみ |
| 禁止事項 | このリポジトリへの installer による書き込み(rc 3 で自動拒否) | ci-local、capability-stamp | framework のファイルの push、UAT、stamp | インストール、overstack の設定書き込み、相手側の規則に反する AI attribution |
ブランチ
| ID | 種別 | 条件 | 動作 | スキップ / 失敗 | 合流先 |
|---|---|---|---|---|---|
| B01 | conditional_required | レベル = release | W05 version + tag vX.Y.Z + リリースノート | それ以外のレベル → スキップ | W06 |
| B02 | conditional_required | レベル ∈ {release, pr, mr} かつ diff に新しい機能がある | W07 の前にフェーズ 1、W08 の後にフェーズ 2 の UAT | 内部の bugfix/refactor → スキップし、チェックリストに理由を記録。不明確な場合 → 確認 | W03 |
| B03 | user_optional | レベル = merge | 個別の GOM VỀ ループ(下記)、W02、W05~W06 を省略 | PR が赤 → その PR はマージしない | 全体レポート |
merge レベル(GOM VỀ — 到着した PR/MR を確認してからマージ)
ノート/tag は作成しません。ステップ 2、5~6 を省略し、代わりにリクエストごとにテストするループを実行します。
- リモートに応じてツールを選択(上記のとおり):
github.com→gh、gitlab→glab。認証されていない場合は停止してユーザーに知らせます。 - リポジトリでオープン中の PR/MR を一覧表示します:
- GitHub:
gh pr list --json number,title,headRefName,mergeable,isDraft - GitLab:
glab mr list(または、対応バージョンでは--output json)。 一覧をユーザーに表示します。ユーザーが番号を指定した場合は絞り込み、指定がなければすべて処理するか選択するか確認します。
- GitHub:
- 各 PR/MR を個別に処理します(まとめて無条件に処理しない):
a. ブランチをクリーンな LOCAL に取得します:GitHub
gh pr checkout <n>、GitLabgit fetch origin merge-requests/<n>/head:mr-<n> && git checkout mr-<n>(またはglab mr checkout <n>)。 b. そのブランチで GATE + TEST を実行します:medic --ci+ PR の diff に関連する selftest/test。これはマージ条件です — 実行せずにマージしてはなりません。 c. グリーン → マージコマンドを提案し、承認を待って停止してからマージします:GitHubgh pr merge <n> --squash(またはリポジトリに応じて --merge/--rebase)、GitLabglab mr merge <n>。赤 → マージしてはなりません。問題箇所を報告し、作成者が修正できるよう PR はそのままにします。 d. マージ後:元のブランチに戻り(git checkout <nhánh-cũ>)、一時ブランチを削除します。 - 全体レポート: 各 PR/MR について、マージ済み / 赤のためスキップ(理由を記載)/ ユーザー指示によりスキップ。
検証と停止
続行の条件はツール(medic、ci-local、fdk-uat、test)の rc であり、モデル自身の評価ではありません。すべての副作用を W07 で停止し、「yes」を待ちます。merge レベルでは、PR ごとに承認を待って停止します。ネットワークエラー時に push/tag を自動で再試行してはなりません — ユーザーに報告します。
例
- 成功例(モジュール):
orca-graphリポジトリで「ship release」と入力 → W00 が🏷 repo_role=module (宣言)を出力 → コミット →pytest testsの終了コード 0 →evals/run.pyの終了コード 0 →tests/install-test.shの終了コード 0 →VERSIONを更新 → 承認待ちで停止 → プッシュ → CI が成功 → タグ付け+リリース →upstream_pinに従ってRheinmir/setupで再ピン留めする手順を案内。 - 境界例(外部): スタンプもラベルもないリポジトリで、W00 が
🏷 repo_role=foreign (推論:fdk/wiki がなく、.harness-stamp もない)を出力 → ユーザーに確認を求める →ship prのみを提案し、そのリポジトリの CONTRIBUTING を読み、overstack のファイルは一切書き込まない。 - 成功例: ドキュメントを修正した後に「ship push」→ W01 は成功、B02 はスキップ(新しい機能はなく、理由を記録)、W03~W04 は成功 → チェックリスト+
git push→ ユーザーが「yes」→ プッシュ。 - 境界例/失敗例: 新しいスキルを含む「ship pr」で
ci-localの 1 つのジョブが失敗 → W01 でブロックし、失敗したジョブと修正コマンドを出力。ブランチはプッシュせず、PR も作成しない。 - 境界例: 2 件の PR を含む「ship merge」で、PR #2 のテストが失敗 → 承認後に #1 をマージし、理由を添えて #2 は見送る(一部のみ実施)。