with one click
issue-close
イシュー完了時に使用。PRマージ・worktree削除・ブランチ安全削除を一括実行
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
イシュー完了時に使用。PRマージ・worktree削除・ブランチ安全削除を一括実行
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
dev workflow 向けの最終チェック。PR 前に品質ゲート、docs 整合、設計書昇格、Issue 更新をまとめて確認する。
docs-only workflow 向けの最終チェック。docs 整合と Issue 状態を確認し、PR に進めるか判定する。
docs review の指摘に対応し、ドキュメントのみを修正する。コードやテストは変更しない。
docs-only の変更をレビューし、事実整合性・実装整合性・運用整合性の観点から判定する。
docs-only の更新を行う。コードやテストは変更せず、現行実装・CLI・運用方針との整合を確認しながら docs を修正する。
docs review の指摘が適切に修正されたかを確認する。新規指摘は行わない。
| description | イシュー完了時に使用。PRマージ・worktree削除・ブランチ安全削除を一括実行 |
| name | issue-close |
イシュー対応完了後のクリーンアップを実行します。 PR マージ、worktree 削除、ブランチ削除、Issue クローズを一括実行します。
| タイミング | このスキルを使用 |
|---|---|
| PRがApproveされマージ可能 | ✅ 使用 |
| PRレビュー待ち | ❌ 待機 |
| 作業途中 | ❌ 不要 |
ワークフロー内の位置: implement → review-code → i-dev-final-check → i-pr → close
常に注入される変数:
| 変数 | 型 | 説明 |
|---|---|---|
issue_id | str | 正規化済み Issue ID(GitHub 数値または local ID) |
issue_ref | str | 人間可読の Issue 参照(GitHub では #<issue_id>、local では bare ID) |
step_id | str | 現在のステップ ID |
provider 解決時に追加で注入される変数:
| 変数 | 型 | 説明 |
|---|---|---|
provider_type | str | github / local のいずれか。本 Skill の経路分岐に使用 |
default_branch | str | ベースブランチ名(main 等)。local 経路で merge / push の引数に使用 |
branch_name | str | フィーチャーブランチ名(feat/<id> 等) |
worktree_dir | str | worktree 絶対パス |
$ARGUMENTS = <issue_id>
コンテキスト変数 issue_id が存在すればそちらを使用。
なければ $ARGUMENTS の第1引数を issue_id として使用。
issue_ref はハーネス経由ではプロンプトに自動注入される(provider 別に整形済み)。手動実行時は issue_id から導出する: GitHub 数値 ID なら #<issue_id>、local-* 形式なら bare ID(# を付けない)。
/i-pr でPRが作成済みであること[provider_type] に応じて手順が分岐する。
[provider_type] が github(または未注入の legacy 環境)→ 既存の
Step 1〜6 を順に実行する(uv run kaji pr merge / worktree 削除 / branch 削除 /
git pull / uv run kaji issue close / 報告)。[provider_type] が local → 後述の provider=local の場合 セクションへ
ジャンプし、local 用の手順 (6 step) を実行する。
github 用の Step 1〜6 は実行しない(PR 概念が無いため)。Issue本文からWorktree情報を取得します:
uv run kaji issue view [issue_id] --json body -q '.body'
以下の情報を抽出:
> **Worktree**: \../[worktree_dirname]` → worktree パス(/issue-start` が記録した値)> **Branch**: \[prefix]/[issue_id]`` → ブランチ名git worktree list の最初の行が常に main worktree(bare repository のルート)を示す:
MAIN_REPO=$(git worktree list | head -1 | awk '{print $1}')
注意:
git rev-parse --show-toplevelは現在の worktree のルートを返すため、 worktree 内から実行すると main repo を取得できない。必ずgit worktree listを使うこと。
worktree 内にいる場合は main repo に移動:
cd "$MAIN_REPO"
uv run kaji pr merge [branch_name]
マージコミットを作成してブランチ履歴を保持する。ブランチ削除は worktree 削除後に Step 4.5 で行う。
結果を記録:
pr_merge_result= 「マージ済み」。この値は Step 6 で使用する。
git worktree remove "$MAIN_REPO/../[worktree_dirname]"
$MAIN_REPOは Step 2 で取得済み。
結果を記録:
worktree_result= 「削除済み」。この値は Step 6 で使用する。
worktree 削除後にローカル・リモートブランチを削除する。
git fetch [git_remote] で [git_remote]/[default_branch] を最新化してから、merge-base --is-ancestor でマージ済み判定を行い、安全に削除する。
ローカル削除とリモート削除は独立して実行し、片方の失敗がもう片方をブロックしない。
ブランチが既に存在しない場合はスキップする。
# 1. fetch して [git_remote]/[default_branch] を更新
git fetch [git_remote]
# 2. ローカルブランチ削除: 存在確認 → マージ済み判定 → 安全な -D
if git show-ref --verify --quiet refs/heads/[branch_name]; then
if git merge-base --is-ancestor [branch_name] [git_remote]/[default_branch]; then
git branch -D [branch_name]
else
echo "WARNING: branch not merged into [git_remote]/[default_branch], skipping local delete"
fi
fi
# 3. リモートブランチ削除(ローカル削除の成否に依存しない)
git ls-remote --exit-code --heads [git_remote] [branch_name] >/dev/null 2>&1
LS_EXIT=$?
if [ "$LS_EXIT" -eq 0 ]; then
if ! git push [git_remote] --delete [branch_name]; then
echo "ERROR: git push [git_remote] --delete failed"
exit 1
fi
elif [ "$LS_EXIT" -eq 2 ]; then
echo "INFO: remote branch already deleted"
else
echo "ERROR: git ls-remote failed (exit $LS_EXIT)"
exit 1
fi
# 4. stale remote-tracking ref を掃除
git fetch --prune [git_remote]
結果を記録:
local_branch_result= 「削除済み」/「未存在を確認」/「未マージのためスキップ」remote_branch_result= 「削除済み」/「未存在を確認」/「削除失敗(要手動対応)」これらの値は Step 6 で使用する。
git pull [git_remote] [default_branch]
結果を記録:
pull_result= 「最新化済み」。この値は Step 6 で使用する。
uv run kaji issue close [issue_id] --reason completed
結果を記録:
close_result= 「クローズ済み」/「クローズ失敗(要手動対応)」。この値は Step 6 で使用する。重要:
uv run kaji issue closeが失敗した場合は verdict を ABORT にすること。Issue が未クローズのまま残ることは許容しない。
Step 3〜5.5 の結果を使って、stdout への報告と Issue タイムラインへのコメント投稿の両方を行う。
各ステップで記録した結果変数を使い、コメント内容を動的に組み立てて投稿する:
uv run kaji issue comment [issue_id] --commit --body-file - <<'COMMENT_EOF'
## Issue クローズ完了
| 項目 | 状態 |
|------|------|
| PR | [pr_merge_result] |
| worktree | [worktree_result] |
| ローカルブランチ | [local_branch_result] |
| リモートブランチ | [remote_branch_result] |
| main | [pull_result] |
| Issue | [close_result] |
COMMENT_EOF
[pr_merge_result]等のプレースホルダーは、実際の実行結果に置き換えること。ハードコードしない。
以下の形式で報告してください:
## Issue クローズ完了
| 項目 | 状態 |
|------|------|
| Issue | [issue_ref] |
| PR | [pr_merge_result] |
| worktree | [worktree_result] |
| ローカルブランチ | [local_branch_result] |
| リモートブランチ | [remote_branch_result] |
| main | [pull_result] |
| Issue 状態 | [close_result] |
[provider_type] が local のとき、PR 概念が無いため
以下の local 用手順 (6 step) を実行する。
重要 (worktree 運用): bare repository + worktree パターンでは
[default_branch]は feature worktree とは別の worktree(通常 main repo 側) で checkout されている。そのため merge / close commit は base worktree 側 で実行し、feature worktree ([worktree_dir]) はその後で削除する。 feature worktree 内でgit switch [default_branch]を実行しても、別 worktree がそのブランチを保持しているため Git に拒否される。
cd [worktree_dir]
test -z "$(git status --porcelain)" || { echo "ABORT: uncommitted changes in [worktree_dir]"; exit 1; }
git rev-parse --abbrev-ref HEAD | grep -qE "^[a-z]+/local-[a-z0-9]+-[0-9]+(-[a-z0-9-]+)?$" || { echo "ABORT: not on feature branch"; exit 1; }
未コミット変更 / feature ブランチ外なら ABORT。
git worktree list --porcelain から [default_branch] を checkout している
worktree を抽出する。見つからなければ user が手動で base 側を準備する必要が
あるため ABORT。
# [default_branch] を checkout している worktree を取得
BASE_WT=$(git worktree list --porcelain | awk -v b="[default_branch]" '
/^worktree / { wt=$2 }
$0 == "branch refs/heads/" b { print wt; exit }
')
test -n "$BASE_WT" || { echo "ABORT: no worktree has [default_branch] checked out. Run 'git worktree add <path> [default_branch]' or 'git switch [default_branch]' in your main checkout first."; exit 1; }
cd "$BASE_WT"
# Step 2.1: 3 段ガードによる救済 commit 判定
#
# 標準動線(各 skill での `uv run kaji issue {comment,edit} --commit`)が機能していれば
# base worktree は clean。蓄積が残っている場合は LocalProvider 永続化由来の path
# のみ救済し、それ以外は ABORT する。
#
# 救済対象 (LocalProvider 命名規則):
# - .kaji/issues/<issue_id>-<slug>/issue.md
# - .kaji/issues/<issue_id>-<slug>/comments/<4桁seq>-<machine_id>.md
DIRTY=$(git status --porcelain)
if [ -n "$DIRTY" ]; then
# 条件 1: dirty path がすべて [issue_id] の永続化 whitelist に一致するか検査
ISSUE_DIR_RE='^\.kaji/issues/[issue_id]-[a-z0-9-]+/(issue\.md|comments/[0-9]{4}-[a-z0-9]{1,16}\.md)$'
UNRELATED=$(printf '%s\n' "$DIRTY" | awk -v re="$ISSUE_DIR_RE" '
{
# rename / copy ("R old -> new") は救済対象外として ABORT に倒す
if (match($0, /->/)) { print; next }
# 先頭 3 文字 (status + space) を除いた残りを path として扱う
path = substr($0, 4)
# quoted path (path に空白等あり) は対応外として ABORT
if (substr(path, 1, 1) == "\"") { print; next }
if (path !~ re) { print }
}
')
if [ -n "$UNRELATED" ]; then
echo "ABORT: dirty files outside LocalProvider persistence whitelist in base worktree $BASE_WT:"
printf '%s\n' "$UNRELATED"
echo " Allowed pattern: $ISSUE_DIR_RE"
exit 1
fi
# 条件 2: whitelist 命名規則の glob で限定 add + atomic commit
# - `comments/` ディレクトリ全体を add してはならない (note.txt 等を巻き込む)
# - `git commit --only` で他の staged change を HEAD に混入させない
git add \
".kaji/issues/[issue_id]-"*"/issue.md" \
".kaji/issues/[issue_id]-"*"/comments/"[0-9][0-9][0-9][0-9]-*.md \
2>/dev/null || true
git commit --only \
-m "chore(local): salvage uncommitted issue files for [issue_ref]" \
-- \
".kaji/issues/[issue_id]-"*"/issue.md" \
".kaji/issues/[issue_id]-"*"/comments/"[0-9][0-9][0-9][0-9]-*.md \
|| { echo "ABORT: salvage commit failed"; exit 1; }
# 条件 3: 救済後の残差を再検証 (rename/copy/rm 等の取りこぼしを検出)
test -z "$(git status --porcelain)" || {
echo "ABORT: residual dirty files after salvage commit in base worktree $BASE_WT:"
git status --porcelain
exit 1
}
fi
# remote 設定がある場合のみ fetch + ff-only merge。
# fetch 失敗 (network 断 / 認証エラー / suspended account 等) は WARNING で skip し、
# local-only で close を完結させる (Step 6 の push も同様に warning で続行する設計と整合)。
# `uv run kaji run` 非対話モードでは AskUserQuestion 経由のリカバリ不可のため、
# deterministic に local fallback すること。手動 push は remote 復旧後に実施。
if git remote get-url [git_remote] >/dev/null 2>&1; then
if git fetch [git_remote] [default_branch] 2>&1; then
git merge --ff-only "[git_remote]/[default_branch]" || { echo "ABORT: ff-only merge failed in base worktree"; exit 1; }
else
echo "WARNING: git fetch [git_remote] [default_branch] failed; proceeding with local-only close (manual push needed after remote recovery)"
fi
fi
ABORT 条件:
WARNING 継続条件:
git fetch 失敗 (remote 到達不可 / 認証失敗) → local merge は実行、push は Step 6 で warning skip標準動線で各 skill が uv run kaji issue {comment,edit} --commit を使っていれば、ここまで到達した時点で
base worktree は clean のはず。救済 commit は標準動線が機能しなかった場合の安全装置として残す。
git merge --no-ff --no-edit [branch_name] || { echo "ABORT: merge conflict, resolve manually in $BASE_WT then retry"; exit 1; }
衝突したら ABORT。Issue は open のまま、user が手動 resolve した後で再実行する。
uv run kaji issue close [issue_id] --reason completed
git add .kaji/issues/[issue_id]-*/issue.md
git commit -m "chore(issue): close [issue_ref]" || { echo "ABORT: commit failed"; exit 1; }
--reason completed は明示で書く(kaji 側の default も
completed だが、Skill markdown 上で明示することで読み手の予期外を減らす)。
Step 4 完了で Issue close は確定。以降の失敗は警告のみ。
base worktree に居る状態で feature worktree を削除する。cwd == 削除対象 を
回避するため、Step 2 の cd "$BASE_WT" は維持したまま実行する。
git worktree remove [worktree_dir] || echo "WARNING: worktree remove failed for [worktree_dir]; manual cleanup needed"
git branch -d [branch_name] || echo "WARNING: branch delete failed for [branch_name]; manual cleanup needed"
if git remote get-url [git_remote] >/dev/null 2>&1; then
git push [git_remote] [default_branch] || echo "WARNING: push failed; manual push needed"
fi
実行完了後、以下の形式で verdict を出力すること:
---VERDICT---
status: PASS
reason: |
クローズ完了
evidence: |
PR マージ・worktree 削除・main 最新化・Issue クローズ済み
suggestion: |
---END_VERDICT---
重要: verdict は stdout にそのまま出力 すること。Issue コメントや Issue 本文更新とは別に、最終的な verdict ブロックは stdout に残す。
| status | 条件 |
|---|---|
| PASS | クローズ完了 |
| ABORT | クローズ失敗(uv run kaji issue close 失敗を含む / local merge 衝突) |