---
name: update-issue-index
description: Use this skill whenever the user wants to refresh or regenerate `docs/issues/INDEX.md` from the current state of GitHub Issues, Pull Requests, and local/remote git branches. Triggers include Japanese phrases like "INDEX を更新して", "INDEX.md 再生成", "issue 一覧を最新にして", "インデックス更新", or English equivalents like "update issue index", "refresh INDEX.md", "regenerate issues index". This skill is **manual-fire only** — it is never wired into hooks. It runs `scripts/generate-index.sh`, which rewrites the table between `<!-- BEGIN_ISSUE_TABLE -->` / `<!-- END_ISSUE_TABLE -->` markers. The skill shows the diff to the user and only commits when the user explicitly asks for it. Trigger this even if the user doesn't explicitly say "skill" — any request to update / refresh / regenerate the issues index in this project should invoke it.
---

# Update Issues INDEX.md

`docs/issues/INDEX.md` の「一覧」テーブルを、`gh` / `git` の現在状態から再生成する手動発火スキル。

SDD 運用で issue / PR が増えるほど INDEX.md は実態と乖離しがちなので、任意のタイミングで一発更新できるようにしたもの。発火は**手動のみ**で、hook 登録は行わない。

---

## 付属スクリプト

プラグインとしてインストールされると、スクリプトは `${CLAUDE_PLUGIN_ROOT%/}/skills/update-issue-index/scripts/` 配下に展開される。呼び出し時は bash の parameter expansion `${VAR%/}` で末尾スラッシュを剥がす形で統一する(`CLAUDE_PLUGIN_ROOT` は末尾スラッシュ付きで展開されるため、そのまま連結すると `//` が混入する)。作業ディレクトリ(cwd)はユーザーのプロジェクトのままで OK。

| スクリプト | 役割 | 使い方 |
| --- | --- | --- |
| `generate-index.sh` | INDEX.md のテーブルをマーカー間で再生成 | `bash "${CLAUDE_PLUGIN_ROOT%/}/skills/update-issue-index/scripts/generate-index.sh" [INDEX_FILE]` |

`INDEX_FILE` 省略時は `docs/issues/INDEX.md` を対象にする。スクリプトは INDEX.md を in-place で書き換える。差分の提示とコミット判断は Claude(このスキル)側の責務。

---

## マーカーの前提

`docs/issues/INDEX.md` には以下のマーカーが必要。スクリプトはこの 2 行の間をテーブルで置き換える。

```markdown
<!-- BEGIN_ISSUE_TABLE -->
| # | タイトル | status | ブランチ | PR |
| --- | --- | --- | --- | --- |
| ... |
<!-- END_ISSUE_TABLE -->
```

マーカーが無い INDEX.md に対してはスクリプトがエラーで終了する。初回導入時はマーカーを手動で追加する。

---

## ワークフロー

### ステップ 1: スクリプトを実行

```bash
bash "${CLAUDE_PLUGIN_ROOT%/}/skills/update-issue-index/scripts/generate-index.sh"
```

エラー終了したら内容をユーザーに報告して中断する。よくある原因:
- `gh auth login` されていない
- 現在地が git リポジトリの外
- INDEX.md にマーカーが無い

### ステップ 2: 差分を確認

```bash
git diff -- docs/issues/INDEX.md
```

差分の有無で分岐する。

- **差分なし**: 「INDEX.md は既に最新です」とユーザーに報告して終了する。**コミットしない**。
- **差分あり**: diff の内容(追加/変更/削除された行)をユーザーに提示する。長い場合は「追加 N 行 / 変更 N 行 / 削除 N 行」のサマリと、特徴的な変化(新規 issue が追加された、status が `open` → `pr-open` に変わった 等)を抜粋する。

### ステップ 3: コミット判断【チェックポイント】

ユーザーに「コミットしますか?」と明示的に確認する。**自動でコミットしない**。

ユーザーが「コミットして」等の明示指示をしたら、次のコマンドでコミットする:

```bash
git add docs/issues/INDEX.md
git commit -m "docs: refresh issues INDEX.md"
```

コミットメッセージの書式はこの形式で固定(SDD 運用上、INDEX.md の更新はメタ作業なので Conventional Commits の `docs:` 固定でよい)。

ユーザーが「コミットしない」「確認だけ」等と言った場合は、書き換え済みの INDEX.md をワーキングツリーに残したまま終了する(ユーザーが手動で編集・コミット・捨てられる)。

### ステップ 4: 結果を報告

- 差分の有無
- コミットしたならコミットハッシュ、していないなら「ワーキングツリーに変更を残しています」
- 次にユーザーがやるべきこと(push、別ブランチへの持ち込み等、該当すれば)

---

## status 判定ロジック

スクリプトは各 issue に対して以下の順で status を判定する:

1. マージ済 PR が紐付いている → `merged`
2. OPEN な PR が紐付いている → `pr-open`
3. 実装ブランチ(`issue-<N>` をパス要素として含む)が存在 & PR 無し → `in-progress`
4. Issue が OPEN & 上記いずれも該当せず → `open`
5. Issue が CLOSED & マージ済 PR も無し → `closed`

PR と issue の紐付けは以下のどちらかで判定する:
- PR のブランチ名に `issue-<N>` をトークンとして含む(例: `feature/issue-7-foo`, `fix/issue-2`)
- PR 本文に `Closes #<N>` / `Fixes #<N>` / `Resolves #<N>` を含む(大文字小文字問わず)

複数候補がある場合: PR は OPEN > MERGED > CLOSED、ブランチはローカル優先(アルファベット順先頭)。

---

## 例

### 例 1: 更新不要のケース

ユーザー: 「INDEX を更新して」

動き:
1. `generate-index.sh` を実行
2. `git diff` → 差分なし
3. 「INDEX.md は既に最新です」と報告して終了

### 例 2: 新規 issue と PR 状態変化が反映されるケース

ユーザー: 「INDEX 最新にして」

動き:
1. `generate-index.sh` を実行
2. `git diff` → issue #8 の行が追加、issue #2 が `open` → `pr-open` に変化
3. 差分要約をユーザーに提示:
   - `+ | 8 | ... | open | - | - |`
   - `- | 2 | ... | open | - | - |` → `+ | 2 | ... | pr-open | fix/issue-2-... | #6 |`
4. ユーザー: 「コミットして」
5. `git add` + `git commit -m "docs: refresh issues INDEX.md"`
6. コミットハッシュを報告

---

## 注意点

- **手動発火のみ**: このスキルは hook に登録しない設計。PR / issue の自動操作フックで動かすと、想定外のタイミングで差分が発生し rebase や CI を混乱させる可能性がある。
- **マーカー必須**: INDEX.md に `<!-- BEGIN_ISSUE_TABLE -->` / `<!-- END_ISSUE_TABLE -->` が無いとスクリプトはエラー終了する。初回導入時はユーザーに相談の上、マーカーを追加する(冒頭説明と「status の語彙」セクションはマーカー外なので保持される)。
- **自動 commit しない**: 差分が出ても、ユーザーの明示指示があるまで絶対にコミットしない。INDEX.md が意図しないコミットに混入すると厄介なので、ここは守る。
- **push はしない**: コミットしても push は別行動。ユーザーの指示時のみ `git push` する。
- **ブランチ**: このスキルは現在のブランチに対して INDEX.md をコミットする。通常はデフォルトブランチでの運用を想定するが、他ブランチで作業中に更新したい場合もあるので、ブランチチェックは強制しない(必要ならユーザーに一言確認する程度)。
- **大量 issue のリポでの性能**: `gh issue list --limit 1000` と `gh pr list --limit 1000` を呼ぶ。1000 を超えるリポでは取りこぼしが起きる可能性あり(その時は `--limit` の調整が必要)。
- **タイトルのエスケープ**: タイトルに `|` が含まれるとテーブルが崩れるので、スクリプト側で `\|` にエスケープする。改行もスペースに変換する。
- **status 判定の限界**: 「ブランチ有り & PR 無し」を `in-progress` と判定するが、実装を放棄したまま残っているブランチも `in-progress` になる。気になるときはユーザーが手動で該当ブランチを削除すれば次回の生成で正しい status に落ち着く。
