--- name: comment-sweep argument-hint: "[--staged | --worktree | BASE_BRANCH]" description: "Reviews newly added code comments in a git diff against rules/code-comments.md. Detects identifier paraphrase, WHAT/HOW explanation of next code, comparison comments ('既存の X と異なり'), change history references (Copilot 指摘 / issue ID prefix / 'added for' / 'fixes URL'), 3+ line blocks compressible to a 1-line WHY, and duplicate sentences within a block. Default scans the diff between the PR base and HEAD for PR readiness. '--staged' scans the index, '--worktree' scans tracked uncommitted changes, BASE_BRANCH (any positional arg) overrides the base ref. Auto-skips when base..HEAD contains only revert commits (subjects all start with 'Revert \"'). Use BEFORE 'gh pr create', or when the user mentions コメントチェック / コメント sweep / comment review / 余計なコメント / コメント不適切." --- # comment-sweep PR / staged / worktree diff の **新規追加コメント行**を [rules/code-comments.md](../../../rules/code-comments.md) の規範に照らして判定し、違反箇所を報告して修正まで導く leaf skill ([rules/skills.md](../../../rules/skills.md))。`/pr-codex-ci` の前段として走らせると、codex review が低レベル指摘 (コメント余計) に時間を使わなくなる。 ## いつ使うか - **PR 作成前 (推奨)**: `gh pr create` の**前**。実装直後・テスト直後等、push 前に sweep を通す - **既存 PR への追加 push 前**: review 対応や bug fix の差分にも適用 (commit 後・push 前に default モードで) - **ユーザーから「コメント不適切」「余計なコメント」等の指摘を受けた直後**: 全変更ファイルに対し再 sweep - **PR を作らない一時的な変更でも**: commit 前に `--staged` または `--worktree` モードで動かしてよい ## 引数モード | 引数 | 対象 diff | 用途 | |------|----------|------| | (なし) | `git diff origin/...HEAD` (HEAD-branch は `origin/HEAD` の symbolic-ref から決定。後述) | PR 作成前の最終 sweep | | `BASE_BRANCH` (`--` で始まらない任意 1 引数) | `git diff origin/...HEAD` | base を明示する場合 (リモート tracking ref を使う) | | `--staged` | `git diff --cached` (index) | commit 前 sweep | | `--worktree` | `git diff HEAD` (tracked かつ uncommitted。**untracked は含まない**) | 未 commit の tracked 変更を全部含めたい時 | 複数指定不可。フラグでなく数字でもない任意の 1 引数は `BASE_BRANCH` として扱う。`--worktree` で untracked な新規ファイルも対象にしたい場合は事前に `git add -N ` で intent-to-add してから呼ぶ。 ## 手順 ```text Sweep Progress: - [ ] Step 1: モード判定と diff 取得 - [ ] Step 1.5: Lightweight-PR diff の検出 (default / BASE_BRANCH モードのみ) - [ ] Step 2: 追加コメント行の抽出とブロック化 - [ ] Step 3: 各ブロックを規範で判定 - [ ] Step 4: 違反テーブルをユーザーに提示 - [ ] Step 5: ユーザー承認後 Edit で修正 - [ ] Step 6: 再 sweep で残違反ゼロを確認 ``` ### Step 1: モード判定と diff 取得 引数を解釈してモードを決定。default モード (引数なし) の base は **`origin/HEAD` (デフォルトブランチ)** を使う。feature branch の upstream を base にすると `git diff origin/feat/x...HEAD` が空になり sweep が false-negative で通ってしまうため、必ず `origin/HEAD` 由来で決定する。 ```bash git symbolic-ref refs/remotes/origin/HEAD --short ``` これが `origin/main` 等を返したら、その branch を base として `...` (triple-dot) diff を取る: ```bash git diff origin/main...HEAD ``` `origin/HEAD` が未設定で symbolic-ref が失敗する場合は `BASE_BRANCH` 引数を要求してユーザーに案内する (`git remote set-head origin -a` で再設定可能)。`--staged` / `--worktree` / `BASE_BRANCH` の場合はこの計算をスキップして対応コマンドを直接実行する。`BASE_BRANCH` 引数モードでは `git diff origin/...HEAD` を実行する (ローカル branch 名でなくリモート tracking ref を使う)。 ### Step 1.5: Lightweight-PR diff の検出 (auto-skip) `default` / `BASE_BRANCH` モードのみ実行 (`--staged` / `--worktree` は HEAD に commit が無いケースがあるため対象外、通常通り Step 2 へ進む)。 新規追加コメントが構造的に存在しない diff は auto-skip する。判定は共有 helper に委譲する: ```bash python3 -I .claude/skills/_shared/pr-skip-policy.py --base --head HEAD --json ``` `` は **Step 1 で `git diff ...HEAD` に使った base ref そのもの** (default は `origin/main` 等、`BASE_BRANCH` モードは `origin/`)。**`origin/` は二重に付けない**。head は本 skill が未 push のローカル commit を含むため `HEAD`。 出力 JSON の `profile` で分岐する: - `pure-revert` → 以下を出力して終了 (revert diff の `+` 行は復元コメントのみで再 sweep 対象外): ```text ✅ Revert-only diff (skipped) ``` - `tiny-json-hotfix` → 以下を出力して終了 (`.claude/` 配下の単一 JSON scalar 値置換等で新規追加コメント行ゼロ): ```text ✅ Lightweight PR (tiny-json-hotfix, skipped) ``` - `none` → Step 2 へ進む helper が exit code 0 以外 (git 失敗等の判定不能) を返した場合も通常フローに倒し Step 2 へ進む。 ### Step 2: 追加コメント行の抽出とブロック化 **生成ファイルの除外(抽出前、bun があれば)**: 自動生成ファイルはコメントも生成物でレビュー対象にならないため、ファイルごと sweep から除外する。bun が PATH 上にあれば、呼び出しモードに対応する検出 CLI を実行し、出力 JSON の `generated[].path` を以降の抽出対象から外す: | モード | コマンド | |--------|---------| | default / `BASE_BRANCH` | `bun --config=/dev/null .claude/skills/_shared/detect-generated-local.ts --range ...HEAD` | | `--staged` | `bun --config=/dev/null .claude/skills/_shared/detect-generated-local.ts --staged` | | `--worktree` | `bun --config=/dev/null .claude/skills/_shared/detect-generated-local.ts --worktree` | bun が無ければこのステップを skip し、すべての変更ファイルを抽出対象に含める (生成ファイルがあっても false-positive で違反検出するだけで、ユーザー承認段階で除外できる)。除外したファイルは Step 4 で件数と一覧を注記する(黙って消さない)。 diff 出力から `^\+(?!\+\+)` で始まる行のうち、**変更ファイルの拡張子に応じた**コメント prefix にマッチするものを抽出する。拡張子ごとに有効な prefix は以下: | 拡張子 | 有効なコメント prefix | |--------|---------------------| | `.go` / `.rs` / `.ts` / `.tsx` / `.js` / `.jsx` / `.mjs` / `.cjs` / `.c` / `.h` / `.cpp` / `.hpp` / `.java` / `.swift` / `.kt` / `.scala` / `.dart` | `^\+\s*//` / `^\+\s*/\*` 〜 `\*/` / `^\+\s*\*` (block 継続) | | `.py` / `.rb` / `.sh` / `.bash` / `.zsh` / `.yml` / `.yaml` / `.toml` / `.nix` / `Makefile` / `.mk` / `Dockerfile` | `^\+\s*#` (line) | | `.md` / `.markdown` / `.html` / `.htm` / `.xml` / `.svg` / `.vue` | `^\+\s*` (block) のみ | | `.sql` | `^\+\s*--` (line) / `^\+\s*/\*` 〜 `\*/` (block) | | `.ex` / `.exs` | `^\+\s*#` (line) | | `.erl` | `^\+\s*%` (line) | **Markdown ファイル (`.md` / `.markdown`) では `^\+\s*#` を「コメント」として扱わない** — `#` は heading 構文のため `# Usage` / `## Test plan` 等を violation に誤検出するリスクがある。Markdown は `` のみ対象。 判定対象から除外: - shebang (`#!`) - linter / formatter / type-check directive (`// eslint-disable-line`, `# noqa: ...`, `// biome-ignore *`, `// @ts-ignore`, `// @ts-expect-error`, `# type: ignore`, `// nolint`, `# pylint:`) - license header / copyright block - generated file marker (`@generated`) - `rules/code-comments.md` 自身を編集中の場合、その規範記述内の例コメント (`// 悪い例` 等) は対象外 **ブロック化ルール**: 同一ファイル内で連続する追加コメント行 (空行を挟まない) を 1 ブロックとする。間に `+` 以外 (context 行や `-` 行) が挟まれたら別ブロック。 ### Step 3: 各ブロックを規範で判定 [rules/code-comments.md](../../../rules/code-comments.md) の以下カテゴリで判定。**コメント prefix (`//` / `#` / `--` / `